1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29#include "lithium.h"
30
31namespace v8 {
32namespace internal {
33
34
35void LOperand::PrintTo(StringStream* stream) {
36  LUnallocated* unalloc = NULL;
37  switch (kind()) {
38    case INVALID:
39      stream->Add("(0)");
40      break;
41    case UNALLOCATED:
42      unalloc = LUnallocated::cast(this);
43      stream->Add("v%d", unalloc->virtual_register());
44      switch (unalloc->policy()) {
45        case LUnallocated::NONE:
46          break;
47        case LUnallocated::FIXED_REGISTER: {
48          const char* register_name =
49              Register::AllocationIndexToString(unalloc->fixed_index());
50          stream->Add("(=%s)", register_name);
51          break;
52        }
53        case LUnallocated::FIXED_DOUBLE_REGISTER: {
54          const char* double_register_name =
55              DoubleRegister::AllocationIndexToString(unalloc->fixed_index());
56          stream->Add("(=%s)", double_register_name);
57          break;
58        }
59        case LUnallocated::FIXED_SLOT:
60          stream->Add("(=%dS)", unalloc->fixed_index());
61          break;
62        case LUnallocated::MUST_HAVE_REGISTER:
63          stream->Add("(R)");
64          break;
65        case LUnallocated::WRITABLE_REGISTER:
66          stream->Add("(WR)");
67          break;
68        case LUnallocated::SAME_AS_FIRST_INPUT:
69          stream->Add("(1)");
70          break;
71        case LUnallocated::ANY:
72          stream->Add("(-)");
73          break;
74      }
75      break;
76    case CONSTANT_OPERAND:
77      stream->Add("[constant:%d]", index());
78      break;
79    case STACK_SLOT:
80      stream->Add("[stack:%d]", index());
81      break;
82    case DOUBLE_STACK_SLOT:
83      stream->Add("[double_stack:%d]", index());
84      break;
85    case REGISTER:
86      stream->Add("[%s|R]", Register::AllocationIndexToString(index()));
87      break;
88    case DOUBLE_REGISTER:
89      stream->Add("[%s|R]", DoubleRegister::AllocationIndexToString(index()));
90      break;
91    case ARGUMENT:
92      stream->Add("[arg:%d]", index());
93      break;
94  }
95}
96
97#define DEFINE_OPERAND_CACHE(name, type)                      \
98  name* name::cache = NULL;                                   \
99  void name::SetUpCache() {                                   \
100    if (cache) return;                                        \
101    cache = new name[kNumCachedOperands];                     \
102    for (int i = 0; i < kNumCachedOperands; i++) {            \
103      cache[i].ConvertTo(type, i);                            \
104    }                                                         \
105  }                                                           \
106
107DEFINE_OPERAND_CACHE(LConstantOperand, CONSTANT_OPERAND)
108DEFINE_OPERAND_CACHE(LStackSlot,       STACK_SLOT)
109DEFINE_OPERAND_CACHE(LDoubleStackSlot, DOUBLE_STACK_SLOT)
110DEFINE_OPERAND_CACHE(LRegister,        REGISTER)
111DEFINE_OPERAND_CACHE(LDoubleRegister,  DOUBLE_REGISTER)
112
113#undef DEFINE_OPERAND_CACHE
114
115void LOperand::SetUpCaches() {
116  LConstantOperand::SetUpCache();
117  LStackSlot::SetUpCache();
118  LDoubleStackSlot::SetUpCache();
119  LRegister::SetUpCache();
120  LDoubleRegister::SetUpCache();
121}
122
123bool LParallelMove::IsRedundant() const {
124  for (int i = 0; i < move_operands_.length(); ++i) {
125    if (!move_operands_[i].IsRedundant()) return false;
126  }
127  return true;
128}
129
130
131void LParallelMove::PrintDataTo(StringStream* stream) const {
132  bool first = true;
133  for (int i = 0; i < move_operands_.length(); ++i) {
134    if (!move_operands_[i].IsEliminated()) {
135      LOperand* source = move_operands_[i].source();
136      LOperand* destination = move_operands_[i].destination();
137      if (!first) stream->Add(" ");
138      first = false;
139      if (source->Equals(destination)) {
140        destination->PrintTo(stream);
141      } else {
142        destination->PrintTo(stream);
143        stream->Add(" = ");
144        source->PrintTo(stream);
145      }
146      stream->Add(";");
147    }
148  }
149}
150
151
152void LEnvironment::PrintTo(StringStream* stream) {
153  stream->Add("[id=%d|", ast_id());
154  stream->Add("[parameters=%d|", parameter_count());
155  stream->Add("[arguments_stack_height=%d|", arguments_stack_height());
156  for (int i = 0; i < values_.length(); ++i) {
157    if (i != 0) stream->Add(";");
158    if (values_[i] == NULL) {
159      stream->Add("[hole]");
160    } else {
161      values_[i]->PrintTo(stream);
162    }
163  }
164  stream->Add("]");
165}
166
167
168void LPointerMap::RecordPointer(LOperand* op) {
169  // Do not record arguments as pointers.
170  if (op->IsStackSlot() && op->index() < 0) return;
171  ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
172  pointer_operands_.Add(op);
173}
174
175
176void LPointerMap::RemovePointer(LOperand* op) {
177  // Do not record arguments as pointers.
178  if (op->IsStackSlot() && op->index() < 0) return;
179  ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
180  for (int i = 0; i < pointer_operands_.length(); ++i) {
181    if (pointer_operands_[i]->Equals(op)) {
182      pointer_operands_.Remove(i);
183      --i;
184    }
185  }
186}
187
188
189void LPointerMap::RecordUntagged(LOperand* op) {
190  // Do not record arguments as pointers.
191  if (op->IsStackSlot() && op->index() < 0) return;
192  ASSERT(!op->IsDoubleRegister() && !op->IsDoubleStackSlot());
193  untagged_operands_.Add(op);
194}
195
196
197void LPointerMap::PrintTo(StringStream* stream) {
198  stream->Add("{");
199  for (int i = 0; i < pointer_operands_.length(); ++i) {
200    if (i != 0) stream->Add(";");
201    pointer_operands_[i]->PrintTo(stream);
202  }
203  stream->Add("} @%d", position());
204}
205
206
207int ElementsKindToShiftSize(ElementsKind elements_kind) {
208  switch (elements_kind) {
209    case EXTERNAL_BYTE_ELEMENTS:
210    case EXTERNAL_PIXEL_ELEMENTS:
211    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
212      return 0;
213    case EXTERNAL_SHORT_ELEMENTS:
214    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
215      return 1;
216    case EXTERNAL_INT_ELEMENTS:
217    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
218    case EXTERNAL_FLOAT_ELEMENTS:
219      return 2;
220    case EXTERNAL_DOUBLE_ELEMENTS:
221    case FAST_DOUBLE_ELEMENTS:
222      return 3;
223    case FAST_SMI_ONLY_ELEMENTS:
224    case FAST_ELEMENTS:
225    case DICTIONARY_ELEMENTS:
226    case NON_STRICT_ARGUMENTS_ELEMENTS:
227      return kPointerSizeLog2;
228  }
229  UNREACHABLE();
230  return 0;
231}
232
233
234} }  // namespace v8::internal
235