blob: e0caba1665071c4031eb9f984cb4c6b5a6a1c4db [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002// 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
30#include "factory.h"
31#include "hydrogen.h"
32
33#if V8_TARGET_ARCH_IA32
34#include "ia32/lithium-ia32.h"
35#elif V8_TARGET_ARCH_X64
36#include "x64/lithium-x64.h"
37#elif V8_TARGET_ARCH_ARM
38#include "arm/lithium-arm.h"
lrn@chromium.org7516f052011-03-30 08:52:27 +000039#elif V8_TARGET_ARCH_MIPS
40#include "mips/lithium-mips.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041#else
42#error Unsupported target architecture.
43#endif
44
45namespace v8 {
46namespace internal {
47
48#define DEFINE_COMPILE(type) \
49 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
50 return builder->Do##type(this); \
51 }
52HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
53#undef DEFINE_COMPILE
54
55
56const char* Representation::Mnemonic() const {
57 switch (kind_) {
58 case kNone: return "v";
59 case kTagged: return "t";
60 case kDouble: return "d";
61 case kInteger32: return "i";
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000062 case kExternal: return "x";
karlklose@chromium.org83a47282011-05-11 11:54:09 +000063 default:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000064 UNREACHABLE();
65 return NULL;
66 }
67}
68
69
danno@chromium.orgfa458e42012-02-01 10:48:36 +000070int HValue::LoopWeight() const {
71 const int w = FLAG_loop_weight;
72 static const int weights[] = { 1, w, w*w, w*w*w, w*w*w*w };
73 return weights[Min(block()->LoopNestingDepth(),
74 static_cast<int>(ARRAY_SIZE(weights)-1))];
75}
76
77
vegorov@chromium.org7304bca2011-05-16 12:14:13 +000078void HValue::AssumeRepresentation(Representation r) {
79 if (CheckFlag(kFlexibleRepresentation)) {
80 ChangeRepresentation(r);
81 // The representation of the value is dictated by type feedback and
82 // will not be changed later.
83 ClearFlag(kFlexibleRepresentation);
84 }
85}
86
87
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000088static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
89 if (result > kMaxInt) {
90 *overflow = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000091 return kMaxInt;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000092 }
93 if (result < kMinInt) {
94 *overflow = true;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000095 return kMinInt;
96 }
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000097 return static_cast<int32_t>(result);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000098}
99
100
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000101static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
102 int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
103 return ConvertAndSetOverflow(result, overflow);
104}
105
106
107static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
108 int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
109 return ConvertAndSetOverflow(result, overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000110}
111
112
113static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000114 int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
115 return ConvertAndSetOverflow(result, overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116}
117
118
119int32_t Range::Mask() const {
120 if (lower_ == upper_) return lower_;
121 if (lower_ >= 0) {
122 int32_t res = 1;
123 while (res < upper_) {
124 res = (res << 1) | 1;
125 }
126 return res;
127 }
128 return 0xffffffff;
129}
130
131
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000132void Range::AddConstant(int32_t value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000133 if (value == 0) return;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000134 bool may_overflow = false; // Overflow is ignored here.
135 lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
136 upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000137#ifdef DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000138 Verify();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000139#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140}
141
142
karlklose@chromium.org8f806e82011-03-07 14:06:08 +0000143void Range::Intersect(Range* other) {
144 upper_ = Min(upper_, other->upper_);
145 lower_ = Max(lower_, other->lower_);
146 bool b = CanBeMinusZero() && other->CanBeMinusZero();
147 set_can_be_minus_zero(b);
148}
149
150
151void Range::Union(Range* other) {
152 upper_ = Max(upper_, other->upper_);
153 lower_ = Min(lower_, other->lower_);
154 bool b = CanBeMinusZero() || other->CanBeMinusZero();
155 set_can_be_minus_zero(b);
156}
157
158
159void Range::Sar(int32_t value) {
160 int32_t bits = value & 0x1F;
161 lower_ = lower_ >> bits;
162 upper_ = upper_ >> bits;
163 set_can_be_minus_zero(false);
164}
165
166
167void Range::Shl(int32_t value) {
168 int32_t bits = value & 0x1F;
169 int old_lower = lower_;
170 int old_upper = upper_;
171 lower_ = lower_ << bits;
172 upper_ = upper_ << bits;
173 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
174 upper_ = kMaxInt;
175 lower_ = kMinInt;
176 }
177 set_can_be_minus_zero(false);
178}
179
180
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181bool Range::AddAndCheckOverflow(Range* other) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000182 bool may_overflow = false;
183 lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
184 upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 KeepOrder();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000186#ifdef DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000187 Verify();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000188#endif
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000189 return may_overflow;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000190}
191
192
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000193bool Range::SubAndCheckOverflow(Range* other) {
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000194 bool may_overflow = false;
195 lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
196 upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000197 KeepOrder();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000198#ifdef DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000199 Verify();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000200#endif
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000201 return may_overflow;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000202}
203
204
205void Range::KeepOrder() {
206 if (lower_ > upper_) {
207 int32_t tmp = lower_;
208 lower_ = upper_;
209 upper_ = tmp;
210 }
211}
212
213
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000214#ifdef DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215void Range::Verify() const {
216 ASSERT(lower_ <= upper_);
217}
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000218#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219
220
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000221bool Range::MulAndCheckOverflow(Range* other) {
222 bool may_overflow = false;
223 int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
224 int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
225 int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
226 int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
227 lower_ = Min(Min(v1, v2), Min(v3, v4));
228 upper_ = Max(Max(v1, v2), Max(v3, v4));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000229#ifdef DEBUG
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000230 Verify();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000231#endif
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000232 return may_overflow;
233}
234
235
236const char* HType::ToString() {
237 switch (type_) {
238 case kTagged: return "tagged";
239 case kTaggedPrimitive: return "primitive";
240 case kTaggedNumber: return "number";
241 case kSmi: return "smi";
242 case kHeapNumber: return "heap-number";
243 case kString: return "string";
244 case kBoolean: return "boolean";
245 case kNonPrimitive: return "non-primitive";
246 case kJSArray: return "array";
247 case kJSObject: return "object";
248 case kUninitialized: return "uninitialized";
249 }
250 UNREACHABLE();
251 return "Unreachable code";
252}
253
254
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000255HType HType::TypeFromValue(Handle<Object> value) {
256 HType result = HType::Tagged();
257 if (value->IsSmi()) {
258 result = HType::Smi();
259 } else if (value->IsHeapNumber()) {
260 result = HType::HeapNumber();
261 } else if (value->IsString()) {
262 result = HType::String();
263 } else if (value->IsBoolean()) {
264 result = HType::Boolean();
265 } else if (value->IsJSObject()) {
266 result = HType::JSObject();
267 } else if (value->IsJSArray()) {
268 result = HType::JSArray();
269 }
270 return result;
271}
272
273
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000274bool HValue::IsDefinedAfter(HBasicBlock* other) const {
275 return block()->block_id() > other->block_id();
276}
277
278
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000279HUseListNode* HUseListNode::tail() {
280 // Skip and remove dead items in the use list.
281 while (tail_ != NULL && tail_->value()->CheckFlag(HValue::kIsDead)) {
282 tail_ = tail_->tail_;
283 }
284 return tail_;
285}
286
287
ulan@chromium.org812308e2012-02-29 15:58:45 +0000288bool HValue::CheckUsesForFlag(Flag f) {
289 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
290 if (!it.value()->CheckFlag(f)) return false;
291 }
292 return true;
293}
294
295
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000296HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
297 Advance();
298}
299
300
301void HUseIterator::Advance() {
302 current_ = next_;
303 if (current_ != NULL) {
304 next_ = current_->tail();
305 value_ = current_->value();
306 index_ = current_->index();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000307 }
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000308}
309
310
311int HValue::UseCount() const {
312 int count = 0;
313 for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
314 return count;
315}
316
317
318HUseListNode* HValue::RemoveUse(HValue* value, int index) {
319 HUseListNode* previous = NULL;
320 HUseListNode* current = use_list_;
321 while (current != NULL) {
322 if (current->value() == value && current->index() == index) {
323 if (previous == NULL) {
324 use_list_ = current->tail();
325 } else {
326 previous->set_tail(current->tail());
327 }
328 break;
329 }
330
331 previous = current;
332 current = current->tail();
333 }
334
335#ifdef DEBUG
336 // Do not reuse use list nodes in debug mode, zap them.
337 if (current != NULL) {
338 HUseListNode* temp =
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000339 new(block()->zone())
340 HUseListNode(current->value(), current->index(), NULL);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000341 current->Zap();
342 current = temp;
343 }
344#endif
345 return current;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000346}
347
348
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000349bool HValue::Equals(HValue* other) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000350 if (other->opcode() != opcode()) return false;
351 if (!other->representation().Equals(representation())) return false;
352 if (!other->type_.Equals(type_)) return false;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000353 if (other->flags() != flags()) return false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000354 if (OperandCount() != other->OperandCount()) return false;
355 for (int i = 0; i < OperandCount(); ++i) {
356 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
357 }
358 bool result = DataEquals(other);
359 ASSERT(!result || Hashcode() == other->Hashcode());
360 return result;
361}
362
363
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000364intptr_t HValue::Hashcode() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000365 intptr_t result = opcode();
366 int count = OperandCount();
367 for (int i = 0; i < count; ++i) {
368 result = result * 19 + OperandAt(i)->id() + (result >> 7);
369 }
370 return result;
371}
372
373
ricow@chromium.orgdcebac02011-04-20 09:44:50 +0000374const char* HValue::Mnemonic() const {
375 switch (opcode()) {
376#define MAKE_CASE(type) case k##type: return #type;
377 HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
378#undef MAKE_CASE
379 case kPhi: return "Phi";
380 default: return "";
381 }
382}
383
384
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000385void HValue::SetOperandAt(int index, HValue* value) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000386 RegisterUse(index, value);
387 InternalSetOperandAt(index, value);
388}
389
390
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000391void HValue::DeleteAndReplaceWith(HValue* other) {
392 // We replace all uses first, so Delete can assert that there are none.
393 if (other != NULL) ReplaceAllUsesWith(other);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000394 ASSERT(HasNoUses());
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000395 Kill();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000396 DeleteFromGraph();
397}
398
399
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000400void HValue::ReplaceAllUsesWith(HValue* other) {
401 while (use_list_ != NULL) {
402 HUseListNode* list_node = use_list_;
403 HValue* value = list_node->value();
404 ASSERT(!value->block()->IsStartBlock());
405 value->InternalSetOperandAt(list_node->index(), other);
406 use_list_ = list_node->tail();
407 list_node->set_tail(other->use_list_);
408 other->use_list_ = list_node;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000409 }
410}
411
412
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000413void HValue::Kill() {
414 // Instead of going through the entire use list of each operand, we only
415 // check the first item in each use list and rely on the tail() method to
416 // skip dead items, removing them lazily next time we traverse the list.
417 SetFlag(kIsDead);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000418 for (int i = 0; i < OperandCount(); ++i) {
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000419 HValue* operand = OperandAt(i);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000420 if (operand == NULL) continue;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +0000421 HUseListNode* first = operand->use_list_;
422 if (first != NULL && first->value() == this && first->index() == i) {
423 operand->use_list_ = first->tail();
424 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000425 }
426}
427
428
429void HValue::SetBlock(HBasicBlock* block) {
430 ASSERT(block_ == NULL || block == NULL);
431 block_ = block;
432 if (id_ == kNoNumber && block != NULL) {
433 id_ = block->graph()->GetNextValueID(this);
434 }
435}
436
437
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000438void HValue::PrintTypeTo(StringStream* stream) {
439 if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
440 stream->Add(" type[%s]", type().ToString());
441}
442
443
444void HValue::PrintRangeTo(StringStream* stream) {
445 if (range() == NULL || range()->IsMostGeneric()) return;
446 stream->Add(" range[%d,%d,m0=%d]",
447 range()->lower(),
448 range()->upper(),
449 static_cast<int>(range()->CanBeMinusZero()));
450}
451
452
453void HValue::PrintChangesTo(StringStream* stream) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000454 GVNFlagSet changes_flags = ChangesFlags();
455 if (changes_flags.IsEmpty()) return;
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000456 stream->Add(" changes[");
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000457 if (changes_flags == AllSideEffectsFlagSet()) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000458 stream->Add("*");
459 } else {
460 bool add_comma = false;
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +0000461#define PRINT_DO(type) \
462 if (changes_flags.Contains(kChanges##type)) { \
463 if (add_comma) stream->Add(","); \
464 add_comma = true; \
465 stream->Add(#type); \
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000466 }
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000467 GVN_TRACKED_FLAG_LIST(PRINT_DO);
468 GVN_UNTRACKED_FLAG_LIST(PRINT_DO);
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000469#undef PRINT_DO
470 }
471 stream->Add("]");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000472}
473
474
475void HValue::PrintNameTo(StringStream* stream) {
476 stream->Add("%s%d", representation_.Mnemonic(), id());
477}
478
479
480bool HValue::UpdateInferredType() {
481 HType type = CalculateInferredType();
482 bool result = (!type.Equals(type_));
483 type_ = type;
484 return result;
485}
486
487
488void HValue::RegisterUse(int index, HValue* new_value) {
489 HValue* old_value = OperandAt(index);
490 if (old_value == new_value) return;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000491
492 HUseListNode* removed = NULL;
493 if (old_value != NULL) {
494 removed = old_value->RemoveUse(this, index);
495 }
496
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000497 if (new_value != NULL) {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000498 if (removed == NULL) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000499 new_value->use_list_ = new(new_value->block()->zone()) HUseListNode(
500 this, index, new_value->use_list_);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000501 } else {
502 removed->set_tail(new_value->use_list_);
503 new_value->use_list_ = removed;
504 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000505 }
506}
507
508
ulan@chromium.org812308e2012-02-29 15:58:45 +0000509void HValue::AddNewRange(Range* r, Zone* zone) {
510 if (!HasRange()) ComputeInitialRange(zone);
511 if (!HasRange()) range_ = new(zone) Range();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000512 ASSERT(HasRange());
513 r->StackUpon(range_);
514 range_ = r;
515}
516
517
518void HValue::RemoveLastAddedRange() {
519 ASSERT(HasRange());
520 ASSERT(range_->next() != NULL);
521 range_ = range_->next();
522}
523
524
ulan@chromium.org812308e2012-02-29 15:58:45 +0000525void HValue::ComputeInitialRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000526 ASSERT(!HasRange());
ulan@chromium.org812308e2012-02-29 15:58:45 +0000527 range_ = InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000528 ASSERT(HasRange());
529}
530
531
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000532void HInstruction::PrintTo(StringStream* stream) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000533 PrintMnemonicTo(stream);
534 PrintDataTo(stream);
535 PrintRangeTo(stream);
536 PrintChangesTo(stream);
537 PrintTypeTo(stream);
538}
539
540
541void HInstruction::PrintMnemonicTo(StringStream* stream) {
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000542 stream->Add("%s ", Mnemonic());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000543}
544
545
546void HInstruction::Unlink() {
547 ASSERT(IsLinked());
548 ASSERT(!IsControlInstruction()); // Must never move control instructions.
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000549 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these.
550 ASSERT(previous_ != NULL);
551 previous_->next_ = next_;
552 if (next_ == NULL) {
553 ASSERT(block()->last() == this);
554 block()->set_last(previous_);
555 } else {
556 next_->previous_ = previous_;
557 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000558 clear_block();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000559}
560
561
562void HInstruction::InsertBefore(HInstruction* next) {
563 ASSERT(!IsLinked());
564 ASSERT(!next->IsBlockEntry());
565 ASSERT(!IsControlInstruction());
566 ASSERT(!next->block()->IsStartBlock());
567 ASSERT(next->previous_ != NULL);
568 HInstruction* prev = next->previous();
569 prev->next_ = this;
570 next->previous_ = this;
571 next_ = next;
572 previous_ = prev;
573 SetBlock(next->block());
574}
575
576
577void HInstruction::InsertAfter(HInstruction* previous) {
578 ASSERT(!IsLinked());
579 ASSERT(!previous->IsControlInstruction());
580 ASSERT(!IsControlInstruction() || previous->next_ == NULL);
581 HBasicBlock* block = previous->block();
582 // Never insert anything except constants into the start block after finishing
583 // it.
584 if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
585 ASSERT(block->end()->SecondSuccessor() == NULL);
586 InsertAfter(block->end()->FirstSuccessor()->first());
587 return;
588 }
589
590 // If we're inserting after an instruction with side-effects that is
591 // followed by a simulate instruction, we need to insert after the
592 // simulate instruction instead.
593 HInstruction* next = previous->next_;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000594 if (previous->HasObservableSideEffects() && next != NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000595 ASSERT(next->IsSimulate());
596 previous = next;
597 next = previous->next_;
598 }
599
600 previous_ = previous;
601 next_ = next;
602 SetBlock(block);
603 previous->next_ = this;
604 if (next != NULL) next->previous_ = this;
jkummerow@chromium.org28faa982012-04-13 09:58:30 +0000605 if (block->last() == previous) {
606 block->set_last(this);
607 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000608}
609
610
611#ifdef DEBUG
ager@chromium.org378b34e2011-01-28 08:04:38 +0000612void HInstruction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000613 // Verify that input operands are defined before use.
614 HBasicBlock* cur_block = block();
615 for (int i = 0; i < OperandCount(); ++i) {
616 HValue* other_operand = OperandAt(i);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000617 if (other_operand == NULL) continue;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000618 HBasicBlock* other_block = other_operand->block();
619 if (cur_block == other_block) {
620 if (!other_operand->IsPhi()) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000621 HInstruction* cur = this->previous();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000622 while (cur != NULL) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000623 if (cur == other_operand) break;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000624 cur = cur->previous();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000625 }
626 // Must reach other operand in the same block!
627 ASSERT(cur == other_operand);
628 }
629 } else {
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000630 // If the following assert fires, you may have forgotten an
631 // AddInstruction.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000632 ASSERT(other_block->Dominates(cur_block));
633 }
634 }
635
636 // Verify that instructions that may have side-effects are followed
637 // by a simulate instruction.
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000638 if (HasObservableSideEffects() && !IsOsrEntry()) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000639 ASSERT(next()->IsSimulate());
640 }
ager@chromium.org378b34e2011-01-28 08:04:38 +0000641
642 // Verify that instructions that can be eliminated by GVN have overridden
643 // HValue::DataEquals. The default implementation is UNREACHABLE. We
644 // don't actually care whether DataEquals returns true or false here.
645 if (CheckFlag(kUseGVN)) DataEquals(this);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000646}
647#endif
648
649
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000650void HUnaryCall::PrintDataTo(StringStream* stream) {
651 value()->PrintNameTo(stream);
652 stream->Add(" ");
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000653 stream->Add("#%d", argument_count());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000654}
655
656
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000657void HBinaryCall::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000658 first()->PrintNameTo(stream);
659 stream->Add(" ");
660 second()->PrintNameTo(stream);
661 stream->Add(" ");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000662 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000663}
664
665
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000666void HBoundsCheck::PrintDataTo(StringStream* stream) {
667 index()->PrintNameTo(stream);
668 stream->Add(" ");
669 length()->PrintNameTo(stream);
670}
671
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000672
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000673void HCallConstantFunction::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000674 if (IsApplyFunction()) {
675 stream->Add("optimized apply ");
676 } else {
677 stream->Add("%o ", function()->shared()->DebugName());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000678 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000679 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000680}
681
682
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000683void HCallNamed::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000684 stream->Add("%o ", *name());
685 HUnaryCall::PrintDataTo(stream);
686}
687
688
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000689void HCallGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000690 stream->Add("%o ", *name());
691 HUnaryCall::PrintDataTo(stream);
692}
693
694
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000695void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000696 stream->Add("o ", target()->shared()->DebugName());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000697 stream->Add("#%d", argument_count());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000698}
699
700
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000701void HCallRuntime::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000702 stream->Add("%o ", *name());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000703 stream->Add("#%d", argument_count());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000704}
705
706
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000707void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000708 stream->Add("class_of_test(");
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000709 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000710 stream->Add(", \"%o\")", *class_name());
711}
712
713
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000714void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000715 arguments()->PrintNameTo(stream);
716 stream->Add("[");
717 index()->PrintNameTo(stream);
718 stream->Add("], length ");
719 length()->PrintNameTo(stream);
720}
721
722
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000723void HControlInstruction::PrintDataTo(StringStream* stream) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000724 stream->Add(" goto (");
725 bool first_block = true;
726 for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
727 stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
728 first_block = false;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000729 }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000730 stream->Add(")");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000731}
732
733
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000734void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000735 value()->PrintNameTo(stream);
736 HControlInstruction::PrintDataTo(stream);
737}
738
739
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000740void HIsNilAndBranch::PrintDataTo(StringStream* stream) {
741 value()->PrintNameTo(stream);
742 stream->Add(kind() == kStrictEquality ? " === " : " == ");
743 stream->Add(nil() == kNullValue ? "null" : "undefined");
744 HControlInstruction::PrintDataTo(stream);
745}
746
747
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000748void HReturn::PrintDataTo(StringStream* stream) {
749 value()->PrintNameTo(stream);
750}
751
752
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000753void HCompareMap::PrintDataTo(StringStream* stream) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000754 value()->PrintNameTo(stream);
755 stream->Add(" (%p)", *map());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000756 HControlInstruction::PrintDataTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000757}
758
759
760const char* HUnaryMathOperation::OpName() const {
761 switch (op()) {
762 case kMathFloor: return "floor";
763 case kMathRound: return "round";
764 case kMathCeil: return "ceil";
765 case kMathAbs: return "abs";
766 case kMathLog: return "log";
767 case kMathSin: return "sin";
768 case kMathCos: return "cos";
769 case kMathTan: return "tan";
770 case kMathASin: return "asin";
771 case kMathACos: return "acos";
772 case kMathATan: return "atan";
773 case kMathExp: return "exp";
774 case kMathSqrt: return "sqrt";
775 default: break;
776 }
777 return "(unknown operation)";
778}
779
780
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000781void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000782 const char* name = OpName();
783 stream->Add("%s ", name);
784 value()->PrintNameTo(stream);
785}
786
787
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000788void HUnaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000789 value()->PrintNameTo(stream);
790}
791
792
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000793void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000794 value()->PrintNameTo(stream);
795 switch (from_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000796 case FIRST_JS_RECEIVER_TYPE:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000797 if (to_ == LAST_TYPE) stream->Add(" spec_object");
798 break;
799 case JS_REGEXP_TYPE:
800 if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
801 break;
802 case JS_ARRAY_TYPE:
803 if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
804 break;
805 case JS_FUNCTION_TYPE:
806 if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
807 break;
808 default:
809 break;
810 }
811}
812
813
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000814void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000815 value()->PrintNameTo(stream);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000816 stream->Add(" == %o", *type_literal_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000817 HControlInstruction::PrintDataTo(stream);
818}
819
820
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000821void HCheckMapValue::PrintDataTo(StringStream* stream) {
822 value()->PrintNameTo(stream);
823 stream->Add(" ");
824 map()->PrintNameTo(stream);
825}
826
827
828void HForInPrepareMap::PrintDataTo(StringStream* stream) {
829 enumerable()->PrintNameTo(stream);
830}
831
832
833void HForInCacheArray::PrintDataTo(StringStream* stream) {
834 enumerable()->PrintNameTo(stream);
835 stream->Add(" ");
836 map()->PrintNameTo(stream);
837 stream->Add("[%d]", idx_);
838}
839
840
841void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
842 object()->PrintNameTo(stream);
843 stream->Add(" ");
844 index()->PrintNameTo(stream);
845}
846
847
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000848HValue* HConstant::Canonicalize() {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000849 return HasNoUses() ? NULL : this;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000850}
851
852
853HValue* HTypeof::Canonicalize() {
ulan@chromium.org812308e2012-02-29 15:58:45 +0000854 return HasNoUses() ? NULL : this;
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000855}
856
857
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000858HValue* HBitwise::Canonicalize() {
859 if (!representation().IsInteger32()) return this;
860 // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
861 int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
862 if (left()->IsConstant() &&
863 HConstant::cast(left())->HasInteger32Value() &&
864 HConstant::cast(left())->Integer32Value() == nop_constant) {
865 return right();
866 }
867 if (right()->IsConstant() &&
868 HConstant::cast(right())->HasInteger32Value() &&
869 HConstant::cast(right())->Integer32Value() == nop_constant) {
870 return left();
871 }
872 return this;
873}
874
875
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +0000876HValue* HBitNot::Canonicalize() {
877 // Optimize ~~x, a common pattern used for ToInt32(x).
878 if (value()->IsBitNot()) {
879 HValue* result = HBitNot::cast(value())->value();
880 ASSERT(result->representation().IsInteger32());
881 return result;
882 }
883 return this;
884}
885
886
ulan@chromium.org812308e2012-02-29 15:58:45 +0000887HValue* HAdd::Canonicalize() {
888 if (!representation().IsInteger32()) return this;
889 if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
890 return this;
891}
892
893
894HValue* HSub::Canonicalize() {
895 if (!representation().IsInteger32()) return this;
896 if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
897 return this;
898}
899
900
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000901HValue* HChange::Canonicalize() {
902 return (from().Equals(to())) ? value() : this;
903}
904
905
yangguo@chromium.org154ff992012-03-13 08:09:54 +0000906HValue* HWrapReceiver::Canonicalize() {
907 if (HasNoUses()) return NULL;
908 if (receiver()->type().IsJSObject()) {
909 return receiver();
910 }
911 return this;
912}
913
914
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000915void HTypeof::PrintDataTo(StringStream* stream) {
916 value()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000917}
918
919
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000920void HChange::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000921 HUnaryOperation::PrintDataTo(stream);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000922 stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000923
924 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
925 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000926 if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000927}
928
929
jkummerow@chromium.org486075a2011-09-07 12:44:28 +0000930void HJSArrayLength::PrintDataTo(StringStream* stream) {
931 value()->PrintNameTo(stream);
932 stream->Add(" ");
933 typecheck()->PrintNameTo(stream);
934}
935
936
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000937HValue* HUnaryMathOperation::Canonicalize() {
938 if (op() == kMathFloor) {
939 // If the input is integer32 then we replace the floor instruction
940 // with its input. This happens before the representation changes are
941 // introduced.
942 if (value()->representation().IsInteger32()) return value();
943
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +0000944#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_IA32) || \
945 defined(V8_TARGET_ARCH_X64)
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000946 if (value()->IsDiv() && (value()->UseCount() == 1)) {
947 // TODO(2038): Implement this optimization for non ARM architectures.
948 HDiv* hdiv = HDiv::cast(value());
949 HValue* left = hdiv->left();
950 HValue* right = hdiv->right();
951 // Try to simplify left and right values of the division.
952 HValue* new_left =
953 LChunkBuilder::SimplifiedDividendForMathFloorOfDiv(left);
954 HValue* new_right =
955 LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
956
957 // Return if left or right are not optimizable.
958 if ((new_left == NULL) || (new_right == NULL)) return this;
959
960 // Insert the new values in the graph.
961 if (new_left->IsInstruction() &&
962 !HInstruction::cast(new_left)->IsLinked()) {
963 HInstruction::cast(new_left)->InsertBefore(this);
964 }
965 if (new_right->IsInstruction() &&
966 !HInstruction::cast(new_right)->IsLinked()) {
967 HInstruction::cast(new_right)->InsertBefore(this);
968 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000969 HMathFloorOfDiv* instr = new(block()->zone()) HMathFloorOfDiv(context(),
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +0000970 new_left,
971 new_right);
972 // Replace this HMathFloor instruction by the new HMathFloorOfDiv.
973 instr->InsertBefore(this);
974 ReplaceAllUsesWith(instr);
975 Kill();
976 // We know the division had no other uses than this HMathFloor. Delete it.
977 // Also delete the arguments of the division if they are not used any
978 // more.
979 hdiv->DeleteAndReplaceWith(NULL);
980 ASSERT(left->IsChange() || left->IsConstant());
981 ASSERT(right->IsChange() || right->IsConstant());
982 if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL);
983 if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL);
984
985 // Return NULL to remove this instruction from the graph.
986 return NULL;
987 }
988#endif // V8_TARGET_ARCH_ARM
989 }
990 return this;
991}
992
993
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000994HValue* HCheckInstanceType::Canonicalize() {
995 if (check_ == IS_STRING &&
996 !value()->type().IsUninitialized() &&
997 value()->type().IsString()) {
998 return NULL;
999 }
1000 if (check_ == IS_SYMBOL &&
1001 value()->IsConstant() &&
1002 HConstant::cast(value())->handle()->IsSymbol()) {
1003 return NULL;
1004 }
1005 return this;
1006}
1007
1008
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001009void HCheckInstanceType::GetCheckInterval(InstanceType* first,
1010 InstanceType* last) {
1011 ASSERT(is_interval_check());
1012 switch (check_) {
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00001013 case IS_SPEC_OBJECT:
1014 *first = FIRST_SPEC_OBJECT_TYPE;
1015 *last = LAST_SPEC_OBJECT_TYPE;
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001016 return;
1017 case IS_JS_ARRAY:
1018 *first = *last = JS_ARRAY_TYPE;
1019 return;
1020 default:
1021 UNREACHABLE();
1022 }
1023}
1024
1025
1026void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
1027 ASSERT(!is_interval_check());
1028 switch (check_) {
1029 case IS_STRING:
1030 *mask = kIsNotStringMask;
1031 *tag = kStringTag;
1032 return;
1033 case IS_SYMBOL:
1034 *mask = kIsSymbolMask;
1035 *tag = kSymbolTag;
1036 return;
1037 default:
1038 UNREACHABLE();
1039 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001040}
1041
1042
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001043void HCheckMaps::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001044 value()->PrintNameTo(stream);
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001045 stream->Add(" [%p", *map_set()->first());
1046 for (int i = 1; i < map_set()->length(); ++i) {
1047 stream->Add(",%p", *map_set()->at(i));
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001048 }
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001049 stream->Add("]");
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001050}
1051
1052
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001053void HCheckFunction::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001054 value()->PrintNameTo(stream);
1055 stream->Add(" %p", *target());
1056}
1057
1058
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001059const char* HCheckInstanceType::GetCheckName() {
1060 switch (check_) {
1061 case IS_SPEC_OBJECT: return "object";
1062 case IS_JS_ARRAY: return "array";
1063 case IS_STRING: return "string";
1064 case IS_SYMBOL: return "symbol";
1065 }
1066 UNREACHABLE();
1067 return "";
1068}
1069
1070void HCheckInstanceType::PrintDataTo(StringStream* stream) {
1071 stream->Add("%s ", GetCheckName());
1072 HUnaryOperation::PrintDataTo(stream);
1073}
1074
1075
danno@chromium.org81cac2b2012-07-10 11:28:27 +00001076void HCheckPrototypeMaps::PrintDataTo(StringStream* stream) {
1077 stream->Add("[receiver_prototype=%p,holder=%p]", *prototype(), *holder());
1078}
1079
1080
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001081void HCallStub::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001082 stream->Add("%s ",
1083 CodeStub::MajorName(major_key_, false));
1084 HUnaryCall::PrintDataTo(stream);
1085}
1086
1087
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001088void HInstanceOf::PrintDataTo(StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001089 left()->PrintNameTo(stream);
1090 stream->Add(" ");
1091 right()->PrintNameTo(stream);
1092 stream->Add(" ");
1093 context()->PrintNameTo(stream);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001094}
1095
1096
ulan@chromium.org812308e2012-02-29 15:58:45 +00001097Range* HValue::InferRange(Zone* zone) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001098 // Untagged integer32 cannot be -0, all other representations can.
ulan@chromium.org812308e2012-02-29 15:58:45 +00001099 Range* result = new(zone) Range();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001100 result->set_can_be_minus_zero(!representation().IsInteger32());
1101 return result;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001102}
1103
1104
ulan@chromium.org812308e2012-02-29 15:58:45 +00001105Range* HChange::InferRange(Zone* zone) {
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001106 Range* input_range = value()->range();
1107 if (from().IsInteger32() &&
1108 to().IsTagged() &&
1109 input_range != NULL && input_range->IsInSmiRange()) {
1110 set_type(HType::Smi());
1111 }
1112 Range* result = (input_range != NULL)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001113 ? input_range->Copy(zone)
1114 : HValue::InferRange(zone);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001115 if (to().IsInteger32()) result->set_can_be_minus_zero(false);
1116 return result;
1117}
1118
1119
ulan@chromium.org812308e2012-02-29 15:58:45 +00001120Range* HConstant::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001121 if (has_int32_value_) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001122 Range* result = new(zone) Range(int32_value_, int32_value_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001123 result->set_can_be_minus_zero(false);
1124 return result;
1125 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001126 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001127}
1128
1129
ulan@chromium.org812308e2012-02-29 15:58:45 +00001130Range* HPhi::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001131 if (representation().IsInteger32()) {
1132 if (block()->IsLoopHeader()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001133 Range* range = new(zone) Range(kMinInt, kMaxInt);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001134 return range;
1135 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001136 Range* range = OperandAt(0)->range()->Copy(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001137 for (int i = 1; i < OperandCount(); ++i) {
1138 range->Union(OperandAt(i)->range());
1139 }
1140 return range;
1141 }
1142 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001143 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001144 }
1145}
1146
1147
ulan@chromium.org812308e2012-02-29 15:58:45 +00001148Range* HAdd::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001149 if (representation().IsInteger32()) {
1150 Range* a = left()->range();
1151 Range* b = right()->range();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001152 Range* res = a->Copy(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001153 if (!res->AddAndCheckOverflow(b)) {
1154 ClearFlag(kCanOverflow);
1155 }
1156 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
1157 res->set_can_be_minus_zero(m0);
1158 return res;
1159 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001160 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001161 }
1162}
1163
1164
ulan@chromium.org812308e2012-02-29 15:58:45 +00001165Range* HSub::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001166 if (representation().IsInteger32()) {
1167 Range* a = left()->range();
1168 Range* b = right()->range();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001169 Range* res = a->Copy(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001170 if (!res->SubAndCheckOverflow(b)) {
1171 ClearFlag(kCanOverflow);
1172 }
1173 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
1174 return res;
1175 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001176 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001177 }
1178}
1179
1180
ulan@chromium.org812308e2012-02-29 15:58:45 +00001181Range* HMul::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001182 if (representation().IsInteger32()) {
1183 Range* a = left()->range();
1184 Range* b = right()->range();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001185 Range* res = a->Copy(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001186 if (!res->MulAndCheckOverflow(b)) {
1187 ClearFlag(kCanOverflow);
1188 }
1189 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
1190 (a->CanBeNegative() && b->CanBeZero());
1191 res->set_can_be_minus_zero(m0);
1192 return res;
1193 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001194 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001195 }
1196}
1197
1198
ulan@chromium.org812308e2012-02-29 15:58:45 +00001199Range* HDiv::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001200 if (representation().IsInteger32()) {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001201 Range* result = new(zone) Range();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001202 if (left()->range()->CanBeMinusZero()) {
1203 result->set_can_be_minus_zero(true);
1204 }
1205
1206 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1207 result->set_can_be_minus_zero(true);
1208 }
1209
1210 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1211 SetFlag(HValue::kCanOverflow);
1212 }
1213
1214 if (!right()->range()->CanBeZero()) {
1215 ClearFlag(HValue::kCanBeDivByZero);
1216 }
1217 return result;
1218 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001219 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001220 }
1221}
1222
1223
ulan@chromium.org812308e2012-02-29 15:58:45 +00001224Range* HMod::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001225 if (representation().IsInteger32()) {
1226 Range* a = left()->range();
ulan@chromium.org812308e2012-02-29 15:58:45 +00001227 Range* result = new(zone) Range();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001228 if (a->CanBeMinusZero() || a->CanBeNegative()) {
1229 result->set_can_be_minus_zero(true);
1230 }
1231 if (!right()->range()->CanBeZero()) {
1232 ClearFlag(HValue::kCanBeDivByZero);
1233 }
1234 return result;
1235 } else {
ulan@chromium.org812308e2012-02-29 15:58:45 +00001236 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001237 }
1238}
1239
1240
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001241void HPhi::PrintTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001242 stream->Add("[");
1243 for (int i = 0; i < OperandCount(); ++i) {
1244 HValue* value = OperandAt(i);
1245 stream->Add(" ");
1246 value->PrintNameTo(stream);
1247 stream->Add(" ");
1248 }
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001249 stream->Add(" uses%d_%di_%dd_%dt",
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001250 UseCount(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001251 int32_non_phi_uses() + int32_indirect_uses(),
1252 double_non_phi_uses() + double_indirect_uses(),
1253 tagged_non_phi_uses() + tagged_indirect_uses());
fschneider@chromium.org1805e212011-09-05 10:49:12 +00001254 stream->Add("%s%s]",
1255 is_live() ? "_live" : "",
1256 IsConvertibleToInteger() ? "" : "_ncti");
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001257}
1258
1259
1260void HPhi::AddInput(HValue* value) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001261 inputs_.Add(NULL, value->block()->zone());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001262 SetOperandAt(OperandCount() - 1, value);
1263 // Mark phis that may have 'arguments' directly or indirectly as an operand.
1264 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1265 SetFlag(kIsArguments);
1266 }
1267}
1268
1269
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001270bool HPhi::HasRealUses() {
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001271 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1272 if (!it.value()->IsPhi()) return true;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +00001273 }
1274 return false;
1275}
1276
1277
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001278HValue* HPhi::GetRedundantReplacement() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001279 HValue* candidate = NULL;
1280 int count = OperandCount();
1281 int position = 0;
1282 while (position < count && candidate == NULL) {
1283 HValue* current = OperandAt(position++);
1284 if (current != this) candidate = current;
1285 }
1286 while (position < count) {
1287 HValue* current = OperandAt(position++);
1288 if (current != this && current != candidate) return NULL;
1289 }
1290 ASSERT(candidate != this);
1291 return candidate;
1292}
1293
1294
1295void HPhi::DeleteFromGraph() {
1296 ASSERT(block() != NULL);
1297 block()->RemovePhi(this);
1298 ASSERT(block() == NULL);
1299}
1300
1301
1302void HPhi::InitRealUses(int phi_id) {
1303 // Initialize real uses.
1304 phi_id_ = phi_id;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001305 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1306 HValue* value = it.value();
1307 if (!value->IsPhi()) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001308 Representation rep = value->ObservedInputRepresentation(it.index());
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001309 non_phi_uses_[rep.kind()] += value->LoopWeight();
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001310 if (FLAG_trace_representation) {
1311 PrintF("%d %s is used by %d %s as %s\n",
1312 this->id(),
1313 this->Mnemonic(),
1314 value->id(),
1315 value->Mnemonic(),
1316 rep.Mnemonic());
1317 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001318 }
1319 }
1320}
1321
1322
1323void HPhi::AddNonPhiUsesFrom(HPhi* other) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001324 if (FLAG_trace_representation) {
1325 PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n",
1326 this->id(),
1327 this->Mnemonic(),
1328 other->id(),
1329 other->Mnemonic(),
1330 other->non_phi_uses_[Representation::kInteger32],
1331 other->non_phi_uses_[Representation::kDouble],
1332 other->non_phi_uses_[Representation::kTagged]);
1333 }
1334
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001335 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1336 indirect_uses_[i] += other->non_phi_uses_[i];
1337 }
1338}
1339
1340
1341void HPhi::AddIndirectUsesTo(int* dest) {
1342 for (int i = 0; i < Representation::kNumRepresentations; i++) {
1343 dest[i] += indirect_uses_[i];
1344 }
1345}
1346
1347
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001348void HPhi::ResetInteger32Uses() {
1349 non_phi_uses_[Representation::kInteger32] = 0;
1350 indirect_uses_[Representation::kInteger32] = 0;
1351}
1352
1353
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001354void HSimulate::PrintDataTo(StringStream* stream) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001355 stream->Add("id=%d", ast_id());
1356 if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001357 if (values_.length() > 0) {
1358 if (pop_count_ > 0) stream->Add(" /");
1359 for (int i = 0; i < values_.length(); ++i) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001360 if (i > 0) stream->Add(",");
1361 if (HasAssignedIndexAt(i)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001362 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001363 } else {
1364 stream->Add(" push ");
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001365 }
1366 values_[i]->PrintNameTo(stream);
1367 }
1368 }
1369}
1370
1371
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001372void HDeoptimize::PrintDataTo(StringStream* stream) {
1373 if (OperandCount() == 0) return;
1374 OperandAt(0)->PrintNameTo(stream);
1375 for (int i = 1; i < OperandCount(); ++i) {
1376 stream->Add(" ");
1377 OperandAt(i)->PrintNameTo(stream);
1378 }
1379}
1380
1381
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001382void HEnterInlined::PrintDataTo(StringStream* stream) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001383 SmartArrayPointer<char> name = function()->debug_name()->ToCString();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001384 stream->Add("%s, id=%d", *name, function()->id());
1385}
1386
1387
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001388static bool IsInteger32(double value) {
1389 double roundtrip_value = static_cast<double>(static_cast<int32_t>(value));
1390 return BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(value);
1391}
1392
1393
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001394HConstant::HConstant(Handle<Object> handle, Representation r)
1395 : handle_(handle),
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001396 has_int32_value_(false),
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001397 has_double_value_(false) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001398 set_representation(r);
1399 SetFlag(kUseGVN);
1400 if (handle_->IsNumber()) {
1401 double n = handle_->Number();
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001402 has_int32_value_ = IsInteger32(n);
1403 int32_value_ = DoubleToInt32(n);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001404 double_value_ = n;
1405 has_double_value_ = true;
1406 }
1407}
1408
1409
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001410HConstant::HConstant(int32_t integer_value, Representation r)
1411 : has_int32_value_(true),
1412 has_double_value_(true),
1413 int32_value_(integer_value),
1414 double_value_(FastI2D(integer_value)) {
1415 set_representation(r);
1416 SetFlag(kUseGVN);
1417}
1418
1419
1420HConstant::HConstant(double double_value, Representation r)
1421 : has_int32_value_(IsInteger32(double_value)),
1422 has_double_value_(true),
1423 int32_value_(DoubleToInt32(double_value)),
1424 double_value_(double_value) {
1425 set_representation(r);
1426 SetFlag(kUseGVN);
1427}
1428
1429
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001430HConstant* HConstant::CopyToRepresentation(Representation r, Zone* zone) const {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001431 if (r.IsInteger32() && !has_int32_value_) return NULL;
1432 if (r.IsDouble() && !has_double_value_) return NULL;
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001433 if (handle_.is_null()) {
1434 ASSERT(has_int32_value_ || has_double_value_);
1435 if (has_int32_value_) return new(zone) HConstant(int32_value_, r);
1436 return new(zone) HConstant(double_value_, r);
1437 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001438 return new(zone) HConstant(handle_, r);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001439}
1440
1441
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001442HConstant* HConstant::CopyToTruncatedInt32(Zone* zone) const {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001443 if (has_int32_value_) {
1444 if (handle_.is_null()) {
1445 return new(zone) HConstant(int32_value_, Representation::Integer32());
1446 } else {
1447 // Re-use the existing Handle if possible.
1448 return new(zone) HConstant(handle_, Representation::Integer32());
1449 }
1450 } else if (has_double_value_) {
1451 return new(zone) HConstant(DoubleToInt32(double_value_),
1452 Representation::Integer32());
1453 } else {
1454 return NULL;
1455 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001456}
1457
1458
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001459bool HConstant::ToBoolean() {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001460 // Converts the constant's boolean value according to
1461 // ECMAScript section 9.2 ToBoolean conversion.
1462 if (HasInteger32Value()) return Integer32Value() != 0;
1463 if (HasDoubleValue()) {
1464 double v = DoubleValue();
1465 return v != 0 && !isnan(v);
1466 }
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001467 Handle<Object> literal = handle();
1468 if (literal->IsTrue()) return true;
1469 if (literal->IsFalse()) return false;
1470 if (literal->IsUndefined()) return false;
1471 if (literal->IsNull()) return false;
1472 if (literal->IsString() && String::cast(*literal)->length() == 0) {
1473 return false;
1474 }
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001475 return true;
1476}
1477
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001478void HConstant::PrintDataTo(StringStream* stream) {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00001479 if (has_int32_value_) {
1480 stream->Add("%d ", int32_value_);
1481 } else if (has_double_value_) {
1482 stream->Add("%lf ", FmtElm(double_value_));
1483 } else {
1484 handle()->ShortPrint(stream);
1485 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001486}
1487
1488
1489bool HArrayLiteral::IsCopyOnWrite() const {
ricow@chromium.org7ad65222011-12-19 12:13:11 +00001490 if (!boilerplate_object_->IsJSObject()) return false;
1491 return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
1492 HEAP->fixed_cow_array_map();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001493}
1494
1495
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001496void HBinaryOperation::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001497 left()->PrintNameTo(stream);
1498 stream->Add(" ");
1499 right()->PrintNameTo(stream);
1500 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1501 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1502}
1503
1504
ulan@chromium.org812308e2012-02-29 15:58:45 +00001505Range* HBitwise::InferRange(Zone* zone) {
1506 if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001507 const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001508 int32_t left_mask = (left()->range() != NULL)
1509 ? left()->range()->Mask()
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001510 : kDefaultMask;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001511 int32_t right_mask = (right()->range() != NULL)
1512 ? right()->range()->Mask()
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00001513 : kDefaultMask;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001514 int32_t result_mask = (op() == Token::BIT_AND)
1515 ? left_mask & right_mask
1516 : left_mask | right_mask;
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001517 return (result_mask >= 0)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001518 ? new(zone) Range(0, result_mask)
1519 : HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001520}
1521
1522
ulan@chromium.org812308e2012-02-29 15:58:45 +00001523Range* HSar::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001524 if (right()->IsConstant()) {
1525 HConstant* c = HConstant::cast(right());
1526 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001527 Range* result = (left()->range() != NULL)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001528 ? left()->range()->Copy(zone)
1529 : new(zone) Range();
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001530 result->Sar(c->Integer32Value());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001531 result->set_can_be_minus_zero(false);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001532 return result;
1533 }
1534 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001535 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001536}
1537
1538
ulan@chromium.org812308e2012-02-29 15:58:45 +00001539Range* HShr::InferRange(Zone* zone) {
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001540 if (right()->IsConstant()) {
1541 HConstant* c = HConstant::cast(right());
1542 if (c->HasInteger32Value()) {
1543 int shift_count = c->Integer32Value() & 0x1f;
1544 if (left()->range()->CanBeNegative()) {
1545 // Only compute bounds if the result always fits into an int32.
1546 return (shift_count >= 1)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001547 ? new(zone) Range(0,
1548 static_cast<uint32_t>(0xffffffff) >> shift_count)
1549 : new(zone) Range();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001550 } else {
1551 // For positive inputs we can use the >> operator.
1552 Range* result = (left()->range() != NULL)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001553 ? left()->range()->Copy(zone)
1554 : new(zone) Range();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001555 result->Sar(c->Integer32Value());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001556 result->set_can_be_minus_zero(false);
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001557 return result;
1558 }
1559 }
1560 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001561 return HValue::InferRange(zone);
ricow@chromium.org2c99e282011-07-28 09:15:17 +00001562}
1563
1564
ulan@chromium.org812308e2012-02-29 15:58:45 +00001565Range* HShl::InferRange(Zone* zone) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001566 if (right()->IsConstant()) {
1567 HConstant* c = HConstant::cast(right());
1568 if (c->HasInteger32Value()) {
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001569 Range* result = (left()->range() != NULL)
ulan@chromium.org812308e2012-02-29 15:58:45 +00001570 ? left()->range()->Copy(zone)
1571 : new(zone) Range();
karlklose@chromium.org8f806e82011-03-07 14:06:08 +00001572 result->Shl(c->Integer32Value());
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001573 result->set_can_be_minus_zero(false);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001574 return result;
1575 }
1576 }
ulan@chromium.org812308e2012-02-29 15:58:45 +00001577 return HValue::InferRange(zone);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001578}
1579
1580
ulan@chromium.org812308e2012-02-29 15:58:45 +00001581Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001582 switch (elements_kind()) {
1583 case EXTERNAL_PIXEL_ELEMENTS:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001584 return new(zone) Range(0, 255);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001585 case EXTERNAL_BYTE_ELEMENTS:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001586 return new(zone) Range(-128, 127);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001587 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001588 return new(zone) Range(0, 255);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001589 case EXTERNAL_SHORT_ELEMENTS:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001590 return new(zone) Range(-32768, 32767);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001591 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001592 return new(zone) Range(0, 65535);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001593 default:
ulan@chromium.org812308e2012-02-29 15:58:45 +00001594 return HValue::InferRange(zone);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001595 }
1596}
1597
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001598
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001599void HCompareGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001600 stream->Add(Token::Name(token()));
1601 stream->Add(" ");
1602 HBinaryOperation::PrintDataTo(stream);
1603}
1604
1605
erikcorry0ad885c2011-11-21 13:51:57 +00001606void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
1607 stream->Add(Token::Name(token()));
1608 stream->Add(" ");
1609 HControlInstruction::PrintDataTo(stream);
1610}
1611
1612
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001613void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
1614 stream->Add(Token::Name(token()));
1615 stream->Add(" ");
1616 left()->PrintNameTo(stream);
1617 stream->Add(" ");
1618 right()->PrintNameTo(stream);
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001619 HControlInstruction::PrintDataTo(stream);
1620}
1621
1622
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001623void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
1624 left()->PrintNameTo(stream);
1625 stream->Add(" ");
1626 right()->PrintNameTo(stream);
1627 HControlInstruction::PrintDataTo(stream);
1628}
1629
1630
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001631void HGoto::PrintDataTo(StringStream* stream) {
1632 stream->Add("B%d", SuccessorAt(0)->block_id());
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001633}
1634
1635
1636void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001637 input_representation_ = r;
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001638 if (r.IsDouble()) {
ulan@chromium.org9a21ec42012-03-06 08:42:24 +00001639 // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
1640 // and !=) have special handling of undefined, e.g. undefined == undefined
1641 // is 'true'. Relational comparisons have a different semantic, first
1642 // calling ToPrimitive() on their arguments. The standard Crankshaft
1643 // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
1644 // are doubles caused 'undefined' to be converted to NaN. That's compatible
1645 // out-of-the box with ordered relational comparisons (<, >, <=,
1646 // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
1647 // it is not consistent with the spec. For example, it would cause undefined
1648 // == undefined (should be true) to be evaluated as NaN == NaN
1649 // (false). Therefore, any comparisons other than ordered relational
1650 // comparisons must cause a deopt when one of their arguments is undefined.
1651 // See also v8:1434
1652 if (!Token::IsOrderedRelationalCompareOp(token_)) {
1653 SetFlag(kDeoptimizeOnUndefined);
1654 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001655 } else {
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001656 ASSERT(r.IsInteger32());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001657 }
1658}
1659
1660
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001661void HParameter::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001662 stream->Add("%u", index());
1663}
1664
1665
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001666void HLoadNamedField::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001667 object()->PrintNameTo(stream);
1668 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1669}
1670
1671
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001672// Returns true if an instance of this map can never find a property with this
1673// name in its prototype chain. This means all prototypes up to the top are
1674// fast and don't have the name in them. It would be good if we could optimize
1675// polymorphic loads where the property is sometimes found in the prototype
1676// chain.
1677static bool PrototypeChainCanNeverResolve(
1678 Handle<Map> map, Handle<String> name) {
1679 Isolate* isolate = map->GetIsolate();
1680 Object* current = map->prototype();
1681 while (current != isolate->heap()->null_value()) {
1682 if (current->IsJSGlobalProxy() ||
1683 current->IsGlobalObject() ||
1684 !current->IsJSObject() ||
1685 JSObject::cast(current)->IsAccessCheckNeeded() ||
1686 !JSObject::cast(current)->HasFastProperties()) {
1687 return false;
1688 }
1689
1690 LookupResult lookup(isolate);
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001691 Map* map = JSObject::cast(current)->map();
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001692 map->LookupDescriptor(NULL, *name, &lookup);
1693 if (lookup.IsFound()) return false;
1694 if (!lookup.IsCacheable()) return false;
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001695 current = JSObject::cast(current)->GetPrototype();
1696 }
1697 return true;
1698}
1699
1700
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001701HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1702 HValue* object,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00001703 SmallMapList* types,
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001704 Handle<String> name,
1705 Zone* zone)
1706 : types_(Min(types->length(), kMaxLoadPolymorphism), zone),
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001707 name_(name),
1708 need_generic_(false) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +00001709 SetOperandAt(0, context);
1710 SetOperandAt(1, object);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001711 set_representation(Representation::Tagged());
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001712 SetGVNFlag(kDependsOnMaps);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001713 SmallMapList negative_lookups;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001714 for (int i = 0;
1715 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1716 ++i) {
1717 Handle<Map> map = types->at(i);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001718 LookupResult lookup(map->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001719 map->LookupDescriptor(NULL, *name, &lookup);
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001720 if (lookup.IsFound()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00001721 switch (lookup.type()) {
1722 case FIELD: {
1723 int index = lookup.GetLocalFieldIndexFromMap(*map);
1724 if (index < 0) {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001725 SetGVNFlag(kDependsOnInobjectFields);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001726 } else {
jkummerow@chromium.org05ed9dd2012-01-23 14:42:48 +00001727 SetGVNFlag(kDependsOnBackingStoreFields);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001728 }
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001729 types_.Add(types->at(i), zone);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001730 break;
1731 }
1732 case CONSTANT_FUNCTION:
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001733 types_.Add(types->at(i), zone);
lrn@chromium.org1c092762011-05-09 09:42:16 +00001734 break;
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001735 case CALLBACKS:
1736 break;
1737 case TRANSITION:
yangguo@chromium.org99aa4902012-07-06 16:21:55 +00001738 case INTERCEPTOR:
1739 case NONEXISTENT:
1740 case NORMAL:
1741 case HANDLER:
1742 UNREACHABLE();
lrn@chromium.org1c092762011-05-09 09:42:16 +00001743 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001744 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +00001745 } else if (lookup.IsCacheable() &&
1746 PrototypeChainCanNeverResolve(map, name)) {
1747 negative_lookups.Add(types->at(i), zone);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001748 }
1749 }
1750
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001751 bool need_generic =
1752 (types->length() != negative_lookups.length() + types_.length());
1753 if (!need_generic && FLAG_deoptimize_uncommon_cases) {
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001754 SetFlag(kUseGVN);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001755 for (int i = 0; i < negative_lookups.length(); i++) {
1756 types_.Add(negative_lookups.at(i), zone);
1757 }
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001758 } else {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001759 // We don't have an easy way to handle both a call (to the generic stub) and
1760 // a deopt in the same hydrogen instruction, so in this case we don't add
1761 // the negative lookups which can deopt - just let the generic stub handle
1762 // them.
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001763 SetAllSideEffects();
1764 need_generic_ = true;
1765 }
1766}
1767
1768
1769bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1770 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1771 if (types_.length() != other->types()->length()) return false;
1772 if (!name_.is_identical_to(other->name())) return false;
1773 if (need_generic_ != other->need_generic_) return false;
1774 for (int i = 0; i < types_.length(); i++) {
1775 bool found = false;
1776 for (int j = 0; j < types_.length(); j++) {
1777 if (types_.at(j).is_identical_to(other->types()->at(i))) {
1778 found = true;
1779 break;
1780 }
1781 }
1782 if (!found) return false;
1783 }
1784 return true;
1785}
1786
1787
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001788void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
1789 object()->PrintNameTo(stream);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001790 stream->Add(".");
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001791 stream->Add(*String::cast(*name())->ToCString());
1792}
1793
1794
1795void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
1796 object()->PrintNameTo(stream);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001797 stream->Add(".");
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001798 stream->Add(*String::cast(*name())->ToCString());
1799}
1800
1801
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001802void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001803 object()->PrintNameTo(stream);
1804 stream->Add("[");
1805 key()->PrintNameTo(stream);
1806 stream->Add("]");
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001807 if (RequiresHoleCheck()) {
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001808 stream->Add(" check_hole");
1809 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001810}
1811
1812
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001813bool HLoadKeyedFastElement::RequiresHoleCheck() {
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001814 if (IsFastPackedElementsKind(elements_kind())) {
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001815 return false;
1816 }
1817
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001818 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1819 HValue* use = it.value();
1820 if (!use->IsChange()) return true;
1821 }
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001822
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001823 return false;
1824}
1825
1826
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001827void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1828 elements()->PrintNameTo(stream);
1829 stream->Add("[");
1830 key()->PrintNameTo(stream);
1831 stream->Add("]");
1832}
1833
1834
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001835void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1836 object()->PrintNameTo(stream);
1837 stream->Add("[");
1838 key()->PrintNameTo(stream);
1839 stream->Add("]");
1840}
1841
1842
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001843HValue* HLoadKeyedGeneric::Canonicalize() {
1844 // Recognize generic keyed loads that use property name generated
1845 // by for-in statement as a key and rewrite them into fast property load
1846 // by index.
1847 if (key()->IsLoadKeyedFastElement()) {
1848 HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
1849 if (key_load->object()->IsForInCacheArray()) {
1850 HForInCacheArray* names_cache =
1851 HForInCacheArray::cast(key_load->object());
1852
1853 if (names_cache->enumerable() == object()) {
1854 HForInCacheArray* index_cache =
1855 names_cache->index_cache();
1856 HCheckMapValue* map_check =
1857 new(block()->zone()) HCheckMapValue(object(), names_cache->map());
1858 HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
1859 index_cache,
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001860 key_load->key());
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001861 map_check->InsertBefore(this);
1862 index->InsertBefore(this);
mmassi@chromium.org7028c052012-06-13 11:51:58 +00001863 HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
1864 object(), index);
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +00001865 load->InsertBefore(this);
1866 return load;
1867 }
1868 }
1869 }
1870
1871 return this;
1872}
1873
1874
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001875void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1876 StringStream* stream) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001877 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001878 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001879 switch (elements_kind()) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001880 case EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001881 stream->Add("byte");
1882 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001883 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001884 stream->Add("u_byte");
1885 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001886 case EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001887 stream->Add("short");
1888 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001889 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001890 stream->Add("u_short");
1891 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001892 case EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001893 stream->Add("int");
1894 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001895 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001896 stream->Add("u_int");
1897 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001898 case EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001899 stream->Add("float");
1900 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001901 case EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00001902 stream->Add("double");
1903 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001904 case EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001905 stream->Add("pixel");
1906 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001907 case FAST_ELEMENTS:
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001908 case FAST_SMI_ELEMENTS:
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001909 case FAST_DOUBLE_ELEMENTS:
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001910 case FAST_HOLEY_ELEMENTS:
1911 case FAST_HOLEY_SMI_ELEMENTS:
1912 case FAST_HOLEY_DOUBLE_ELEMENTS:
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001913 case DICTIONARY_ELEMENTS:
1914 case NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001915 UNREACHABLE();
1916 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001917 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001918 stream->Add("[");
1919 key()->PrintNameTo(stream);
1920 stream->Add("]");
1921}
1922
1923
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001924void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001925 object()->PrintNameTo(stream);
1926 stream->Add(".");
1927 ASSERT(name()->IsString());
1928 stream->Add(*String::cast(*name())->ToCString());
1929 stream->Add(" = ");
1930 value()->PrintNameTo(stream);
1931}
1932
1933
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001934void HStoreNamedField::PrintDataTo(StringStream* stream) {
1935 object()->PrintNameTo(stream);
1936 stream->Add(".");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001937 stream->Add(*String::cast(*name())->ToCString());
1938 stream->Add(" = ");
1939 value()->PrintNameTo(stream);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00001940 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00001941 if (NeedsWriteBarrier()) {
1942 stream->Add(" (write-barrier)");
1943 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001944 if (!transition().is_null()) {
1945 stream->Add(" (transition map %p)", *transition());
1946 }
1947}
1948
1949
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001950void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001951 object()->PrintNameTo(stream);
1952 stream->Add("[");
1953 key()->PrintNameTo(stream);
1954 stream->Add("] = ");
1955 value()->PrintNameTo(stream);
1956}
1957
1958
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001959void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1960 elements()->PrintNameTo(stream);
1961 stream->Add("[");
1962 key()->PrintNameTo(stream);
1963 stream->Add("] = ");
1964 value()->PrintNameTo(stream);
1965}
1966
1967
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001968void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1969 object()->PrintNameTo(stream);
1970 stream->Add("[");
1971 key()->PrintNameTo(stream);
1972 stream->Add("] = ");
1973 value()->PrintNameTo(stream);
1974}
1975
1976
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001977void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1978 StringStream* stream) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001979 external_pointer()->PrintNameTo(stream);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001980 stream->Add(".");
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00001981 switch (elements_kind()) {
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001982 case EXTERNAL_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001983 stream->Add("byte");
1984 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001985 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001986 stream->Add("u_byte");
1987 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001988 case EXTERNAL_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001989 stream->Add("short");
1990 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001991 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001992 stream->Add("u_short");
1993 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001994 case EXTERNAL_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001995 stream->Add("int");
1996 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001997 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001998 stream->Add("u_int");
1999 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002000 case EXTERNAL_FLOAT_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002001 stream->Add("float");
2002 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002003 case EXTERNAL_DOUBLE_ELEMENTS:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002004 stream->Add("double");
2005 break;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002006 case EXTERNAL_PIXEL_ELEMENTS:
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002007 stream->Add("pixel");
2008 break;
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002009 case FAST_SMI_ELEMENTS:
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002010 case FAST_ELEMENTS:
2011 case FAST_DOUBLE_ELEMENTS:
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002012 case FAST_HOLEY_SMI_ELEMENTS:
2013 case FAST_HOLEY_ELEMENTS:
2014 case FAST_HOLEY_DOUBLE_ELEMENTS:
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00002015 case DICTIONARY_ELEMENTS:
2016 case NON_STRICT_ARGUMENTS_ELEMENTS:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002017 UNREACHABLE();
2018 break;
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00002019 }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002020 stream->Add("[");
2021 key()->PrintNameTo(stream);
2022 stream->Add("] = ");
2023 value()->PrintNameTo(stream);
2024}
2025
2026
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002027void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
2028 object()->PrintNameTo(stream);
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00002029 ElementsKind from_kind = original_map()->elements_kind();
2030 ElementsKind to_kind = transitioned_map()->elements_kind();
2031 stream->Add(" %p [%s] -> %p [%s]",
2032 *original_map(),
2033 ElementsAccessor::ForKind(from_kind)->name(),
2034 *transitioned_map(),
2035 ElementsAccessor::ForKind(to_kind)->name());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002036}
2037
2038
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002039void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002040 stream->Add("[%p]", *cell());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002041 if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
2042 if (details_.IsReadOnly()) stream->Add(" (read-only)");
2043}
2044
2045
2046bool HLoadGlobalCell::RequiresHoleCheck() {
2047 if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
2048 for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
2049 HValue* use = it.value();
2050 if (!use->IsChange()) return true;
2051 }
2052 return false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002053}
2054
2055
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002056void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
2057 stream->Add("%o ", *name());
2058}
2059
2060
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002061void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002062 stream->Add("[%p] = ", *cell());
2063 value()->PrintNameTo(stream);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002064 if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
2065 if (details_.IsReadOnly()) stream->Add(" (read-only)");
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002066}
2067
2068
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00002069void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
2070 stream->Add("%o = ", *name());
2071 value()->PrintNameTo(stream);
2072}
2073
2074
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002075void HLoadContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002076 value()->PrintNameTo(stream);
2077 stream->Add("[%d]", slot_index());
2078}
2079
2080
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002081void HStoreContextSlot::PrintDataTo(StringStream* stream) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00002082 context()->PrintNameTo(stream);
2083 stream->Add("[%d] = ", slot_index());
2084 value()->PrintNameTo(stream);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00002085}
2086
2087
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002088// Implementation of type inference and type conversions. Calculates
2089// the inferred type of this instruction based on the input operands.
2090
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002091HType HValue::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002092 return type_;
2093}
2094
2095
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00002096HType HCheckMaps::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002097 return value()->type();
2098}
2099
2100
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002101HType HCheckFunction::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002102 return value()->type();
2103}
2104
2105
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002106HType HCheckNonSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002107 // TODO(kasperl): Is there any way to signal that this isn't a smi?
2108 return HType::Tagged();
2109}
2110
2111
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002112HType HCheckSmi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002113 return HType::Smi();
2114}
2115
2116
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002117HType HPhi::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002118 HType result = HType::Uninitialized();
2119 for (int i = 0; i < OperandCount(); ++i) {
2120 HType current = OperandAt(i)->type();
2121 result = result.Combine(current);
2122 }
2123 return result;
2124}
2125
2126
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002127HType HConstant::CalculateInferredType() {
rossberg@chromium.org657d53b2012-07-12 11:06:03 +00002128 if (has_int32_value_) {
2129 return Smi::IsValid(int32_value_) ? HType::Smi() : HType::HeapNumber();
2130 }
2131 if (has_double_value_) return HType::HeapNumber();
danno@chromium.org160a7b02011-04-18 15:51:38 +00002132 return HType::TypeFromValue(handle_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002133}
2134
2135
ricow@chromium.org4f693d62011-07-04 14:01:31 +00002136HType HCompareGeneric::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002137 return HType::Boolean();
2138}
2139
2140
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00002141HType HInstanceOf::CalculateInferredType() {
2142 return HType::Boolean();
2143}
2144
2145
2146HType HDeleteProperty::CalculateInferredType() {
2147 return HType::Boolean();
2148}
2149
2150
2151HType HInstanceOfKnownGlobal::CalculateInferredType() {
2152 return HType::Boolean();
2153}
2154
2155
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002156HType HChange::CalculateInferredType() {
2157 if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
2158 return type();
2159}
2160
2161
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002162HType HBitwiseBinaryOperation::CalculateInferredType() {
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00002163 return HType::TaggedNumber();
2164}
2165
2166
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002167HType HArithmeticBinaryOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002168 return HType::TaggedNumber();
2169}
2170
2171
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002172HType HAdd::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002173 return HType::Tagged();
2174}
2175
2176
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002177HType HBitNot::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002178 return HType::TaggedNumber();
2179}
2180
2181
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00002182HType HUnaryMathOperation::CalculateInferredType() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002183 return HType::TaggedNumber();
2184}
2185
2186
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002187HType HStringCharFromCode::CalculateInferredType() {
2188 return HType::String();
2189}
2190
2191
ulan@chromium.org967e2702012-02-28 09:49:15 +00002192HType HAllocateObject::CalculateInferredType() {
2193 return HType::JSObject();
2194}
2195
2196
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00002197HType HFastLiteral::CalculateInferredType() {
2198 // TODO(mstarzinger): Be smarter, could also be JSArray here.
2199 return HType::JSObject();
2200}
2201
2202
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002203HType HArrayLiteral::CalculateInferredType() {
2204 return HType::JSArray();
2205}
2206
2207
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +00002208HType HObjectLiteral::CalculateInferredType() {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00002209 return HType::JSObject();
2210}
2211
2212
2213HType HRegExpLiteral::CalculateInferredType() {
2214 return HType::JSObject();
2215}
2216
2217
2218HType HFunctionLiteral::CalculateInferredType() {
2219 return HType::JSObject();
2220}
2221
2222
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002223HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
2224 BitVector* visited) {
2225 visited->Add(id());
2226 if (representation().IsInteger32() &&
2227 !value()->representation().IsInteger32()) {
2228 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2229 SetFlag(kBailoutOnMinusZero);
2230 }
2231 }
2232 if (RequiredInputRepresentation(0).IsInteger32() &&
2233 representation().IsInteger32()) {
2234 return value();
2235 }
2236 return NULL;
2237}
2238
2239
2240
2241HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2242 visited->Add(id());
2243 if (from().IsInteger32()) return NULL;
2244 if (CanTruncateToInt32()) return NULL;
2245 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2246 SetFlag(kBailoutOnMinusZero);
2247 }
2248 ASSERT(!from().IsInteger32() || !to().IsInteger32());
2249 return NULL;
2250}
2251
2252
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00002253HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
2254 BitVector* visited) {
2255 visited->Add(id());
2256 return value();
2257}
2258
2259
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002260HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2261 visited->Add(id());
2262 if (range() == NULL || range()->CanBeMinusZero()) {
2263 SetFlag(kBailoutOnMinusZero);
2264 return left();
2265 }
2266 return NULL;
2267}
2268
2269
2270HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2271 visited->Add(id());
2272 if (range() == NULL || range()->CanBeMinusZero()) {
2273 SetFlag(kBailoutOnMinusZero);
2274 }
2275 return NULL;
2276}
2277
2278
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00002279HValue* HMathFloorOfDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2280 visited->Add(id());
2281 SetFlag(kBailoutOnMinusZero);
2282 return NULL;
2283}
2284
2285
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002286HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2287 visited->Add(id());
2288 if (range() == NULL || range()->CanBeMinusZero()) {
2289 SetFlag(kBailoutOnMinusZero);
2290 }
2291 return NULL;
2292}
2293
2294
2295HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2296 visited->Add(id());
2297 // Propagate to the left argument. If the left argument cannot be -0, then
2298 // the result of the add operation cannot be either.
2299 if (range() == NULL || range()->CanBeMinusZero()) {
2300 return left();
2301 }
2302 return NULL;
2303}
2304
2305
2306HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2307 visited->Add(id());
2308 // Propagate to the left argument. If the left argument cannot be -0, then
2309 // the result of the sub operation cannot be either.
2310 if (range() == NULL || range()->CanBeMinusZero()) {
2311 return left();
2312 }
2313 return NULL;
2314}
2315
2316
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00002317bool HStoreKeyedFastDoubleElement::NeedsCanonicalization() {
2318 // If value was loaded from unboxed double backing store or
2319 // converted from an integer then we don't have to canonicalize it.
2320 if (value()->IsLoadKeyedFastDoubleElement() ||
2321 (value()->IsChange() && HChange::cast(value())->from().IsInteger32())) {
2322 return false;
2323 }
2324 return true;
2325}
2326
2327
erikcorry0ad885c2011-11-21 13:51:57 +00002328#define H_CONSTANT_INT32(val) \
2329new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED), \
2330 Representation::Integer32())
2331#define H_CONSTANT_DOUBLE(val) \
2332new(zone) HConstant(FACTORY->NewNumber(val, TENURED), \
2333 Representation::Double())
2334
2335#define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op) \
2336HInstruction* HInstr::New##HInstr(Zone* zone, \
2337 HValue* context, \
2338 HValue* left, \
2339 HValue* right) { \
2340 if (left->IsConstant() && right->IsConstant()) { \
2341 HConstant* c_left = HConstant::cast(left); \
2342 HConstant* c_right = HConstant::cast(right); \
2343 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
2344 double double_res = c_left->DoubleValue() op c_right->DoubleValue(); \
2345 if (TypeInfo::IsInt32Double(double_res)) { \
2346 return H_CONSTANT_INT32(static_cast<int32_t>(double_res)); \
2347 } \
2348 return H_CONSTANT_DOUBLE(double_res); \
2349 } \
2350 } \
2351 return new(zone) HInstr(context, left, right); \
2352}
2353
2354
2355DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
2356DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
2357DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
2358
2359#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
2360
2361
2362HInstruction* HMod::NewHMod(Zone* zone,
2363 HValue* context,
2364 HValue* left,
2365 HValue* right) {
2366 if (left->IsConstant() && right->IsConstant()) {
2367 HConstant* c_left = HConstant::cast(left);
2368 HConstant* c_right = HConstant::cast(right);
2369 if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
2370 int32_t dividend = c_left->Integer32Value();
2371 int32_t divisor = c_right->Integer32Value();
2372 if (divisor != 0) {
2373 int32_t res = dividend % divisor;
2374 if ((res == 0) && (dividend < 0)) {
2375 return H_CONSTANT_DOUBLE(-0.0);
2376 }
2377 return H_CONSTANT_INT32(res);
2378 }
2379 }
2380 }
2381 return new(zone) HMod(context, left, right);
2382}
2383
2384
2385HInstruction* HDiv::NewHDiv(Zone* zone,
2386 HValue* context,
2387 HValue* left,
2388 HValue* right) {
2389 // If left and right are constant values, try to return a constant value.
2390 if (left->IsConstant() && right->IsConstant()) {
2391 HConstant* c_left = HConstant::cast(left);
2392 HConstant* c_right = HConstant::cast(right);
2393 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2394 if (c_right->DoubleValue() != 0) {
2395 double double_res = c_left->DoubleValue() / c_right->DoubleValue();
2396 if (TypeInfo::IsInt32Double(double_res)) {
2397 return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
2398 }
2399 return H_CONSTANT_DOUBLE(double_res);
2400 }
2401 }
2402 }
2403 return new(zone) HDiv(context, left, right);
2404}
2405
2406
2407HInstruction* HBitwise::NewHBitwise(Zone* zone,
2408 Token::Value op,
2409 HValue* context,
2410 HValue* left,
2411 HValue* right) {
2412 if (left->IsConstant() && right->IsConstant()) {
2413 HConstant* c_left = HConstant::cast(left);
2414 HConstant* c_right = HConstant::cast(right);
2415 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2416 int32_t result;
2417 int32_t v_left = c_left->NumberValueAsInteger32();
2418 int32_t v_right = c_right->NumberValueAsInteger32();
2419 switch (op) {
2420 case Token::BIT_XOR:
2421 result = v_left ^ v_right;
2422 break;
2423 case Token::BIT_AND:
2424 result = v_left & v_right;
2425 break;
2426 case Token::BIT_OR:
2427 result = v_left | v_right;
2428 break;
2429 default:
2430 result = 0; // Please the compiler.
2431 UNREACHABLE();
2432 }
2433 return H_CONSTANT_INT32(result);
2434 }
2435 }
2436 return new(zone) HBitwise(op, context, left, right);
2437}
2438
2439
2440#define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result) \
2441HInstruction* HInstr::New##HInstr(Zone* zone, \
2442 HValue* context, \
2443 HValue* left, \
2444 HValue* right) { \
2445 if (left->IsConstant() && right->IsConstant()) { \
2446 HConstant* c_left = HConstant::cast(left); \
2447 HConstant* c_right = HConstant::cast(right); \
2448 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
2449 return H_CONSTANT_INT32(result); \
2450 } \
2451 } \
2452 return new(zone) HInstr(context, left, right); \
2453}
2454
2455
2456DEFINE_NEW_H_BITWISE_INSTR(HSar,
2457c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
2458DEFINE_NEW_H_BITWISE_INSTR(HShl,
2459c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
2460
2461#undef DEFINE_NEW_H_BITWISE_INSTR
2462
2463
2464HInstruction* HShr::NewHShr(Zone* zone,
2465 HValue* context,
2466 HValue* left,
2467 HValue* right) {
2468 if (left->IsConstant() && right->IsConstant()) {
2469 HConstant* c_left = HConstant::cast(left);
2470 HConstant* c_right = HConstant::cast(right);
2471 if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2472 int32_t left_val = c_left->NumberValueAsInteger32();
2473 int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
2474 if ((right_val == 0) && (left_val < 0)) {
2475 return H_CONSTANT_DOUBLE(
2476 static_cast<double>(static_cast<uint32_t>(left_val)));
2477 }
2478 return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
2479 }
2480 }
2481 return new(zone) HShr(context, left, right);
2482}
2483
2484
2485#undef H_CONSTANT_INT32
2486#undef H_CONSTANT_DOUBLE
2487
2488
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +00002489void HIn::PrintDataTo(StringStream* stream) {
2490 key()->PrintNameTo(stream);
2491 stream->Add(" ");
2492 object()->PrintNameTo(stream);
2493}
2494
2495
erik.corry@gmail.comed49e962012-04-17 11:57:53 +00002496void HBitwise::PrintDataTo(StringStream* stream) {
2497 stream->Add(Token::Name(op_));
2498 stream->Add(" ");
2499 HBitwiseBinaryOperation::PrintDataTo(stream);
2500}
2501
2502
rossberg@chromium.org2c067b12012-03-19 11:01:52 +00002503Representation HPhi::InferredRepresentation() {
2504 bool double_occurred = false;
2505 bool int32_occurred = false;
2506 for (int i = 0; i < OperandCount(); ++i) {
2507 HValue* value = OperandAt(i);
2508 if (value->IsUnknownOSRValue()) {
2509 HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
2510 if (hint_value != NULL) {
2511 Representation hint = hint_value->representation();
2512 if (hint.IsDouble()) double_occurred = true;
2513 if (hint.IsInteger32()) int32_occurred = true;
2514 }
2515 continue;
2516 }
2517 if (value->representation().IsDouble()) double_occurred = true;
2518 if (value->representation().IsInteger32()) int32_occurred = true;
2519 if (value->representation().IsTagged()) {
2520 if (value->IsConstant()) {
2521 HConstant* constant = HConstant::cast(value);
2522 if (constant->IsConvertibleToInteger()) {
2523 int32_occurred = true;
2524 } else if (constant->HasNumberValue()) {
2525 double_occurred = true;
2526 } else {
2527 return Representation::Tagged();
2528 }
2529 } else {
2530 return Representation::Tagged();
2531 }
2532 }
2533 }
2534
2535 if (double_occurred) return Representation::Double();
2536
2537 if (int32_occurred) return Representation::Integer32();
2538
2539 return Representation::None();
2540}
2541
2542
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002543// Node-specific verification code is only included in debug mode.
2544#ifdef DEBUG
2545
ager@chromium.org378b34e2011-01-28 08:04:38 +00002546void HPhi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002547 ASSERT(OperandCount() == block()->predecessors()->length());
2548 for (int i = 0; i < OperandCount(); ++i) {
2549 HValue* value = OperandAt(i);
2550 HBasicBlock* defining_block = value->block();
2551 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
2552 ASSERT(defining_block == predecessor_block ||
2553 defining_block->Dominates(predecessor_block));
2554 }
2555}
2556
2557
ager@chromium.org378b34e2011-01-28 08:04:38 +00002558void HSimulate::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002559 HInstruction::Verify();
2560 ASSERT(HasAstId());
2561}
2562
2563
ager@chromium.org378b34e2011-01-28 08:04:38 +00002564void HCheckSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002565 HInstruction::Verify();
2566 ASSERT(HasNoUses());
2567}
2568
2569
ager@chromium.org378b34e2011-01-28 08:04:38 +00002570void HCheckNonSmi::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002571 HInstruction::Verify();
2572 ASSERT(HasNoUses());
2573}
2574
2575
ager@chromium.org378b34e2011-01-28 08:04:38 +00002576void HCheckFunction::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002577 HInstruction::Verify();
2578 ASSERT(HasNoUses());
2579}
2580
2581
ager@chromium.org378b34e2011-01-28 08:04:38 +00002582void HCheckPrototypeMaps::Verify() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +00002583 HInstruction::Verify();
2584 ASSERT(HasNoUses());
2585}
2586
2587#endif
2588
2589} } // namespace v8::internal