1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
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"
39 #elif V8_TARGET_ARCH_MIPS
40 #include "mips/lithium-mips.h"
41 #else
42 #error Unsupported target architecture.
43 #endif
44
45 namespace v8 {
46 namespace internal {
47
48 #define DEFINE_COMPILE(type) \
49 LInstruction* H##type::CompileToLithium(LChunkBuilder* builder) { \
50 return builder->Do##type(this); \
51 }
HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) const52 HYDROGEN_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
53 #undef DEFINE_COMPILE
54
55
56 const 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";
62 case kExternal: return "x";
63 case kNumRepresentations:
64 UNREACHABLE();
65 return NULL;
66 }
67 UNREACHABLE();
68 return NULL;
69 }
70
71
ConvertAndSetOverflow(int64_t result,bool * overflow)72 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
73 if (result > kMaxInt) {
74 *overflow = true;
75 return kMaxInt;
76 }
77 if (result < kMinInt) {
78 *overflow = true;
79 return kMinInt;
80 }
81 return static_cast<int32_t>(result);
82 }
83
84
AddWithoutOverflow(int32_t a,int32_t b,bool * overflow)85 static int32_t AddWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
86 int64_t result = static_cast<int64_t>(a) + static_cast<int64_t>(b);
87 return ConvertAndSetOverflow(result, overflow);
88 }
89
90
SubWithoutOverflow(int32_t a,int32_t b,bool * overflow)91 static int32_t SubWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
92 int64_t result = static_cast<int64_t>(a) - static_cast<int64_t>(b);
93 return ConvertAndSetOverflow(result, overflow);
94 }
95
96
MulWithoutOverflow(int32_t a,int32_t b,bool * overflow)97 static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
98 int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
99 return ConvertAndSetOverflow(result, overflow);
100 }
101
102
Mask() const103 int32_t Range::Mask() const {
104 if (lower_ == upper_) return lower_;
105 if (lower_ >= 0) {
106 int32_t res = 1;
107 while (res < upper_) {
108 res = (res << 1) | 1;
109 }
110 return res;
111 }
112 return 0xffffffff;
113 }
114
115
AddConstant(int32_t value)116 void Range::AddConstant(int32_t value) {
117 if (value == 0) return;
118 bool may_overflow = false; // Overflow is ignored here.
119 lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
120 upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
121 Verify();
122 }
123
124
Intersect(Range * other)125 void Range::Intersect(Range* other) {
126 upper_ = Min(upper_, other->upper_);
127 lower_ = Max(lower_, other->lower_);
128 bool b = CanBeMinusZero() && other->CanBeMinusZero();
129 set_can_be_minus_zero(b);
130 }
131
132
Union(Range * other)133 void Range::Union(Range* other) {
134 upper_ = Max(upper_, other->upper_);
135 lower_ = Min(lower_, other->lower_);
136 bool b = CanBeMinusZero() || other->CanBeMinusZero();
137 set_can_be_minus_zero(b);
138 }
139
140
Sar(int32_t value)141 void Range::Sar(int32_t value) {
142 int32_t bits = value & 0x1F;
143 lower_ = lower_ >> bits;
144 upper_ = upper_ >> bits;
145 set_can_be_minus_zero(false);
146 }
147
148
Shl(int32_t value)149 void Range::Shl(int32_t value) {
150 int32_t bits = value & 0x1F;
151 int old_lower = lower_;
152 int old_upper = upper_;
153 lower_ = lower_ << bits;
154 upper_ = upper_ << bits;
155 if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
156 upper_ = kMaxInt;
157 lower_ = kMinInt;
158 }
159 set_can_be_minus_zero(false);
160 }
161
162
AddAndCheckOverflow(Range * other)163 bool Range::AddAndCheckOverflow(Range* other) {
164 bool may_overflow = false;
165 lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
166 upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
167 KeepOrder();
168 Verify();
169 return may_overflow;
170 }
171
172
SubAndCheckOverflow(Range * other)173 bool Range::SubAndCheckOverflow(Range* other) {
174 bool may_overflow = false;
175 lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
176 upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
177 KeepOrder();
178 Verify();
179 return may_overflow;
180 }
181
182
KeepOrder()183 void Range::KeepOrder() {
184 if (lower_ > upper_) {
185 int32_t tmp = lower_;
186 lower_ = upper_;
187 upper_ = tmp;
188 }
189 }
190
191
Verify() const192 void Range::Verify() const {
193 ASSERT(lower_ <= upper_);
194 }
195
196
MulAndCheckOverflow(Range * other)197 bool Range::MulAndCheckOverflow(Range* other) {
198 bool may_overflow = false;
199 int v1 = MulWithoutOverflow(lower_, other->lower(), &may_overflow);
200 int v2 = MulWithoutOverflow(lower_, other->upper(), &may_overflow);
201 int v3 = MulWithoutOverflow(upper_, other->lower(), &may_overflow);
202 int v4 = MulWithoutOverflow(upper_, other->upper(), &may_overflow);
203 lower_ = Min(Min(v1, v2), Min(v3, v4));
204 upper_ = Max(Max(v1, v2), Max(v3, v4));
205 Verify();
206 return may_overflow;
207 }
208
209
ToString()210 const char* HType::ToString() {
211 switch (type_) {
212 case kTagged: return "tagged";
213 case kTaggedPrimitive: return "primitive";
214 case kTaggedNumber: return "number";
215 case kSmi: return "smi";
216 case kHeapNumber: return "heap-number";
217 case kString: return "string";
218 case kBoolean: return "boolean";
219 case kNonPrimitive: return "non-primitive";
220 case kJSArray: return "array";
221 case kJSObject: return "object";
222 case kUninitialized: return "uninitialized";
223 }
224 UNREACHABLE();
225 return "Unreachable code";
226 }
227
228
ToShortString()229 const char* HType::ToShortString() {
230 switch (type_) {
231 case kTagged: return "t";
232 case kTaggedPrimitive: return "p";
233 case kTaggedNumber: return "n";
234 case kSmi: return "m";
235 case kHeapNumber: return "h";
236 case kString: return "s";
237 case kBoolean: return "b";
238 case kNonPrimitive: return "r";
239 case kJSArray: return "a";
240 case kJSObject: return "o";
241 case kUninitialized: return "z";
242 }
243 UNREACHABLE();
244 return "Unreachable code";
245 }
246
247
TypeFromValue(Handle<Object> value)248 HType HType::TypeFromValue(Handle<Object> value) {
249 HType result = HType::Tagged();
250 if (value->IsSmi()) {
251 result = HType::Smi();
252 } else if (value->IsHeapNumber()) {
253 result = HType::HeapNumber();
254 } else if (value->IsString()) {
255 result = HType::String();
256 } else if (value->IsBoolean()) {
257 result = HType::Boolean();
258 } else if (value->IsJSObject()) {
259 result = HType::JSObject();
260 } else if (value->IsJSArray()) {
261 result = HType::JSArray();
262 }
263 return result;
264 }
265
266
LookupOperandIndex(int occurrence_index,HValue * op)267 int HValue::LookupOperandIndex(int occurrence_index, HValue* op) {
268 for (int i = 0; i < OperandCount(); ++i) {
269 if (OperandAt(i) == op) {
270 if (occurrence_index == 0) return i;
271 --occurrence_index;
272 }
273 }
274 return -1;
275 }
276
277
IsDefinedAfter(HBasicBlock * other) const278 bool HValue::IsDefinedAfter(HBasicBlock* other) const {
279 return block()->block_id() > other->block_id();
280 }
281
282
UsesMultipleTimes(HValue * op)283 bool HValue::UsesMultipleTimes(HValue* op) {
284 bool seen = false;
285 for (int i = 0; i < OperandCount(); ++i) {
286 if (OperandAt(i) == op) {
287 if (seen) return true;
288 seen = true;
289 }
290 }
291 return false;
292 }
293
294
Equals(HValue * other)295 bool HValue::Equals(HValue* other) {
296 if (other->opcode() != opcode()) return false;
297 if (!other->representation().Equals(representation())) return false;
298 if (!other->type_.Equals(type_)) return false;
299 if (other->flags() != flags()) return false;
300 if (OperandCount() != other->OperandCount()) return false;
301 for (int i = 0; i < OperandCount(); ++i) {
302 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
303 }
304 bool result = DataEquals(other);
305 ASSERT(!result || Hashcode() == other->Hashcode());
306 return result;
307 }
308
309
Hashcode()310 intptr_t HValue::Hashcode() {
311 intptr_t result = opcode();
312 int count = OperandCount();
313 for (int i = 0; i < count; ++i) {
314 result = result * 19 + OperandAt(i)->id() + (result >> 7);
315 }
316 return result;
317 }
318
319
SetOperandAt(int index,HValue * value)320 void HValue::SetOperandAt(int index, HValue* value) {
321 ASSERT(value == NULL || !value->representation().IsNone());
322 RegisterUse(index, value);
323 InternalSetOperandAt(index, value);
324 }
325
326
ReplaceAndDelete(HValue * other)327 void HValue::ReplaceAndDelete(HValue* other) {
328 if (other != NULL) ReplaceValue(other);
329 Delete();
330 }
331
332
ReplaceValue(HValue * other)333 void HValue::ReplaceValue(HValue* other) {
334 for (int i = 0; i < uses_.length(); ++i) {
335 HValue* use = uses_[i];
336 ASSERT(!use->block()->IsStartBlock());
337 InternalReplaceAtUse(use, other);
338 other->uses_.Add(use);
339 }
340 uses_.Rewind(0);
341 }
342
343
ClearOperands()344 void HValue::ClearOperands() {
345 for (int i = 0; i < OperandCount(); ++i) {
346 SetOperandAt(i, NULL);
347 }
348 }
349
350
Delete()351 void HValue::Delete() {
352 ASSERT(HasNoUses());
353 ClearOperands();
354 DeleteFromGraph();
355 }
356
357
ReplaceAtUse(HValue * use,HValue * other)358 void HValue::ReplaceAtUse(HValue* use, HValue* other) {
359 for (int i = 0; i < use->OperandCount(); ++i) {
360 if (use->OperandAt(i) == this) {
361 use->SetOperandAt(i, other);
362 }
363 }
364 }
365
366
ReplaceFirstAtUse(HValue * use,HValue * other,Representation r)367 void HValue::ReplaceFirstAtUse(HValue* use, HValue* other, Representation r) {
368 for (int i = 0; i < use->OperandCount(); ++i) {
369 if (use->RequiredInputRepresentation(i).Equals(r) &&
370 use->OperandAt(i) == this) {
371 use->SetOperandAt(i, other);
372 return;
373 }
374 }
375 }
376
377
InternalReplaceAtUse(HValue * use,HValue * other)378 void HValue::InternalReplaceAtUse(HValue* use, HValue* other) {
379 for (int i = 0; i < use->OperandCount(); ++i) {
380 if (use->OperandAt(i) == this) {
381 // Call internal method that does not update use lists. The caller is
382 // responsible for doing so.
383 use->InternalSetOperandAt(i, other);
384 }
385 }
386 }
387
388
SetBlock(HBasicBlock * block)389 void HValue::SetBlock(HBasicBlock* block) {
390 ASSERT(block_ == NULL || block == NULL);
391 block_ = block;
392 if (id_ == kNoNumber && block != NULL) {
393 id_ = block->graph()->GetNextValueID(this);
394 }
395 }
396
397
PrintTypeTo(HType type,StringStream * stream)398 void HValue::PrintTypeTo(HType type, StringStream* stream) {
399 stream->Add(type.ToShortString());
400 }
401
402
PrintNameTo(StringStream * stream)403 void HValue::PrintNameTo(StringStream* stream) {
404 stream->Add("%s%d", representation_.Mnemonic(), id());
405 }
406
407
UpdateInferredType()408 bool HValue::UpdateInferredType() {
409 HType type = CalculateInferredType();
410 bool result = (!type.Equals(type_));
411 type_ = type;
412 return result;
413 }
414
415
RegisterUse(int index,HValue * new_value)416 void HValue::RegisterUse(int index, HValue* new_value) {
417 HValue* old_value = OperandAt(index);
418 if (old_value == new_value) return;
419 if (old_value != NULL) old_value->uses_.RemoveElement(this);
420 if (new_value != NULL) {
421 new_value->uses_.Add(this);
422 }
423 }
424
425
AddNewRange(Range * r)426 void HValue::AddNewRange(Range* r) {
427 if (!HasRange()) ComputeInitialRange();
428 if (!HasRange()) range_ = new Range();
429 ASSERT(HasRange());
430 r->StackUpon(range_);
431 range_ = r;
432 }
433
434
RemoveLastAddedRange()435 void HValue::RemoveLastAddedRange() {
436 ASSERT(HasRange());
437 ASSERT(range_->next() != NULL);
438 range_ = range_->next();
439 }
440
441
ComputeInitialRange()442 void HValue::ComputeInitialRange() {
443 ASSERT(!HasRange());
444 range_ = InferRange();
445 ASSERT(HasRange());
446 }
447
448
PrintTo(StringStream * stream)449 void HInstruction::PrintTo(StringStream* stream) {
450 stream->Add("%s", Mnemonic());
451 if (HasSideEffects()) stream->Add("*");
452 stream->Add(" ");
453 PrintDataTo(stream);
454
455 if (range() != NULL &&
456 !range()->IsMostGeneric() &&
457 !range()->CanBeMinusZero()) {
458 stream->Add(" range[%d,%d,m0=%d]",
459 range()->lower(),
460 range()->upper(),
461 static_cast<int>(range()->CanBeMinusZero()));
462 }
463
464 int changes_flags = (flags() & HValue::ChangesFlagsMask());
465 if (changes_flags != 0) {
466 stream->Add(" changes[0x%x]", changes_flags);
467 }
468
469 if (representation().IsTagged() && !type().Equals(HType::Tagged())) {
470 stream->Add(" type[%s]", type().ToString());
471 }
472 }
473
474
Unlink()475 void HInstruction::Unlink() {
476 ASSERT(IsLinked());
477 ASSERT(!IsControlInstruction()); // Must never move control instructions.
478 ASSERT(!IsBlockEntry()); // Doesn't make sense to delete these.
479 ASSERT(previous_ != NULL);
480 previous_->next_ = next_;
481 if (next_ == NULL) {
482 ASSERT(block()->last() == this);
483 block()->set_last(previous_);
484 } else {
485 next_->previous_ = previous_;
486 }
487 clear_block();
488 }
489
490
InsertBefore(HInstruction * next)491 void HInstruction::InsertBefore(HInstruction* next) {
492 ASSERT(!IsLinked());
493 ASSERT(!next->IsBlockEntry());
494 ASSERT(!IsControlInstruction());
495 ASSERT(!next->block()->IsStartBlock());
496 ASSERT(next->previous_ != NULL);
497 HInstruction* prev = next->previous();
498 prev->next_ = this;
499 next->previous_ = this;
500 next_ = next;
501 previous_ = prev;
502 SetBlock(next->block());
503 }
504
505
InsertAfter(HInstruction * previous)506 void HInstruction::InsertAfter(HInstruction* previous) {
507 ASSERT(!IsLinked());
508 ASSERT(!previous->IsControlInstruction());
509 ASSERT(!IsControlInstruction() || previous->next_ == NULL);
510 HBasicBlock* block = previous->block();
511 // Never insert anything except constants into the start block after finishing
512 // it.
513 if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
514 ASSERT(block->end()->SecondSuccessor() == NULL);
515 InsertAfter(block->end()->FirstSuccessor()->first());
516 return;
517 }
518
519 // If we're inserting after an instruction with side-effects that is
520 // followed by a simulate instruction, we need to insert after the
521 // simulate instruction instead.
522 HInstruction* next = previous->next_;
523 if (previous->HasSideEffects() && next != NULL) {
524 ASSERT(next->IsSimulate());
525 previous = next;
526 next = previous->next_;
527 }
528
529 previous_ = previous;
530 next_ = next;
531 SetBlock(block);
532 previous->next_ = this;
533 if (next != NULL) next->previous_ = this;
534 }
535
536
537 #ifdef DEBUG
Verify()538 void HInstruction::Verify() {
539 // Verify that input operands are defined before use.
540 HBasicBlock* cur_block = block();
541 for (int i = 0; i < OperandCount(); ++i) {
542 HValue* other_operand = OperandAt(i);
543 HBasicBlock* other_block = other_operand->block();
544 if (cur_block == other_block) {
545 if (!other_operand->IsPhi()) {
546 HInstruction* cur = cur_block->first();
547 while (cur != NULL) {
548 ASSERT(cur != this); // We should reach other_operand before!
549 if (cur == other_operand) break;
550 cur = cur->next();
551 }
552 // Must reach other operand in the same block!
553 ASSERT(cur == other_operand);
554 }
555 } else {
556 ASSERT(other_block->Dominates(cur_block));
557 }
558 }
559
560 // Verify that instructions that may have side-effects are followed
561 // by a simulate instruction.
562 if (HasSideEffects() && !IsOsrEntry()) {
563 ASSERT(next()->IsSimulate());
564 }
565
566 // Verify that instructions that can be eliminated by GVN have overridden
567 // HValue::DataEquals. The default implementation is UNREACHABLE. We
568 // don't actually care whether DataEquals returns true or false here.
569 if (CheckFlag(kUseGVN)) DataEquals(this);
570 }
571 #endif
572
573
PrintDataTo(StringStream * stream)574 void HUnaryCall::PrintDataTo(StringStream* stream) {
575 value()->PrintNameTo(stream);
576 stream->Add(" ");
577 stream->Add("#%d", argument_count());
578 }
579
580
PrintDataTo(StringStream * stream)581 void HBinaryCall::PrintDataTo(StringStream* stream) {
582 first()->PrintNameTo(stream);
583 stream->Add(" ");
584 second()->PrintNameTo(stream);
585 stream->Add(" ");
586 stream->Add("#%d", argument_count());
587 }
588
589
PrintDataTo(StringStream * stream)590 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
591 if (IsApplyFunction()) {
592 stream->Add("optimized apply ");
593 } else {
594 stream->Add("%o ", function()->shared()->DebugName());
595 }
596 stream->Add("#%d", argument_count());
597 }
598
599
PrintDataTo(StringStream * stream)600 void HCallNamed::PrintDataTo(StringStream* stream) {
601 stream->Add("%o ", *name());
602 HUnaryCall::PrintDataTo(stream);
603 }
604
605
PrintDataTo(StringStream * stream)606 void HCallGlobal::PrintDataTo(StringStream* stream) {
607 stream->Add("%o ", *name());
608 HUnaryCall::PrintDataTo(stream);
609 }
610
611
PrintDataTo(StringStream * stream)612 void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
613 stream->Add("o ", target()->shared()->DebugName());
614 stream->Add("#%d", argument_count());
615 }
616
617
PrintDataTo(StringStream * stream)618 void HCallRuntime::PrintDataTo(StringStream* stream) {
619 stream->Add("%o ", *name());
620 stream->Add("#%d", argument_count());
621 }
622
623
PrintDataTo(StringStream * stream)624 void HClassOfTest::PrintDataTo(StringStream* stream) {
625 stream->Add("class_of_test(");
626 value()->PrintNameTo(stream);
627 stream->Add(", \"%o\")", *class_name());
628 }
629
630
PrintDataTo(StringStream * stream)631 void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
632 arguments()->PrintNameTo(stream);
633 stream->Add("[");
634 index()->PrintNameTo(stream);
635 stream->Add("], length ");
636 length()->PrintNameTo(stream);
637 }
638
639
PrintDataTo(StringStream * stream)640 void HControlInstruction::PrintDataTo(StringStream* stream) {
641 if (FirstSuccessor() != NULL) {
642 int first_id = FirstSuccessor()->block_id();
643 if (SecondSuccessor() == NULL) {
644 stream->Add(" B%d", first_id);
645 } else {
646 int second_id = SecondSuccessor()->block_id();
647 stream->Add(" goto (B%d, B%d)", first_id, second_id);
648 }
649 }
650 }
651
652
PrintDataTo(StringStream * stream)653 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
654 value()->PrintNameTo(stream);
655 HControlInstruction::PrintDataTo(stream);
656 }
657
658
PrintDataTo(StringStream * stream)659 void HCompareMap::PrintDataTo(StringStream* stream) {
660 value()->PrintNameTo(stream);
661 stream->Add(" (%p)", *map());
662 HControlInstruction::PrintDataTo(stream);
663 }
664
665
OpName() const666 const char* HUnaryMathOperation::OpName() const {
667 switch (op()) {
668 case kMathFloor: return "floor";
669 case kMathRound: return "round";
670 case kMathCeil: return "ceil";
671 case kMathAbs: return "abs";
672 case kMathLog: return "log";
673 case kMathSin: return "sin";
674 case kMathCos: return "cos";
675 case kMathTan: return "tan";
676 case kMathASin: return "asin";
677 case kMathACos: return "acos";
678 case kMathATan: return "atan";
679 case kMathExp: return "exp";
680 case kMathSqrt: return "sqrt";
681 default: break;
682 }
683 return "(unknown operation)";
684 }
685
686
PrintDataTo(StringStream * stream)687 void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
688 const char* name = OpName();
689 stream->Add("%s ", name);
690 value()->PrintNameTo(stream);
691 }
692
693
PrintDataTo(StringStream * stream)694 void HUnaryOperation::PrintDataTo(StringStream* stream) {
695 value()->PrintNameTo(stream);
696 }
697
698
PrintDataTo(StringStream * stream)699 void HHasInstanceType::PrintDataTo(StringStream* stream) {
700 value()->PrintNameTo(stream);
701 switch (from_) {
702 case FIRST_JS_OBJECT_TYPE:
703 if (to_ == LAST_TYPE) stream->Add(" spec_object");
704 break;
705 case JS_REGEXP_TYPE:
706 if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
707 break;
708 case JS_ARRAY_TYPE:
709 if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
710 break;
711 case JS_FUNCTION_TYPE:
712 if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
713 break;
714 default:
715 break;
716 }
717 }
718
719
PrintDataTo(StringStream * stream)720 void HTypeofIs::PrintDataTo(StringStream* stream) {
721 value()->PrintNameTo(stream);
722 stream->Add(" == ");
723 stream->Add(type_literal_->ToAsciiVector());
724 }
725
726
PrintDataTo(StringStream * stream)727 void HChange::PrintDataTo(StringStream* stream) {
728 HUnaryOperation::PrintDataTo(stream);
729 stream->Add(" %s to %s", from_.Mnemonic(), to().Mnemonic());
730
731 if (CanTruncateToInt32()) stream->Add(" truncating-int32");
732 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
733 }
734
735
NewIsJSObjectOrJSFunction(HValue * value)736 HCheckInstanceType* HCheckInstanceType::NewIsJSObjectOrJSFunction(
737 HValue* value) {
738 STATIC_ASSERT((LAST_JS_OBJECT_TYPE + 1) == JS_FUNCTION_TYPE);
739 return new HCheckInstanceType(value, FIRST_JS_OBJECT_TYPE, JS_FUNCTION_TYPE);
740 }
741
742
PrintDataTo(StringStream * stream)743 void HCheckMap::PrintDataTo(StringStream* stream) {
744 value()->PrintNameTo(stream);
745 stream->Add(" %p", *map());
746 }
747
748
PrintDataTo(StringStream * stream)749 void HCheckFunction::PrintDataTo(StringStream* stream) {
750 value()->PrintNameTo(stream);
751 stream->Add(" %p", *target());
752 }
753
754
PrintDataTo(StringStream * stream)755 void HCallStub::PrintDataTo(StringStream* stream) {
756 stream->Add("%s ",
757 CodeStub::MajorName(major_key_, false));
758 HUnaryCall::PrintDataTo(stream);
759 }
760
761
PrintDataTo(StringStream * stream)762 void HInstanceOf::PrintDataTo(StringStream* stream) {
763 left()->PrintNameTo(stream);
764 stream->Add(" ");
765 right()->PrintNameTo(stream);
766 stream->Add(" ");
767 context()->PrintNameTo(stream);
768 }
769
770
InferRange()771 Range* HValue::InferRange() {
772 if (representation().IsTagged()) {
773 // Tagged values are always in int32 range when converted to integer,
774 // but they can contain -0.
775 Range* result = new Range();
776 result->set_can_be_minus_zero(true);
777 return result;
778 } else if (representation().IsNone()) {
779 return NULL;
780 } else {
781 // Untagged integer32 cannot be -0 and we don't compute ranges for
782 // untagged doubles.
783 return new Range();
784 }
785 }
786
787
InferRange()788 Range* HConstant::InferRange() {
789 if (has_int32_value_) {
790 Range* result = new Range(int32_value_, int32_value_);
791 result->set_can_be_minus_zero(false);
792 return result;
793 }
794 return HValue::InferRange();
795 }
796
797
InferRange()798 Range* HPhi::InferRange() {
799 if (representation().IsInteger32()) {
800 if (block()->IsLoopHeader()) {
801 Range* range = new Range(kMinInt, kMaxInt);
802 return range;
803 } else {
804 Range* range = OperandAt(0)->range()->Copy();
805 for (int i = 1; i < OperandCount(); ++i) {
806 range->Union(OperandAt(i)->range());
807 }
808 return range;
809 }
810 } else {
811 return HValue::InferRange();
812 }
813 }
814
815
InferRange()816 Range* HAdd::InferRange() {
817 if (representation().IsInteger32()) {
818 Range* a = left()->range();
819 Range* b = right()->range();
820 Range* res = a->Copy();
821 if (!res->AddAndCheckOverflow(b)) {
822 ClearFlag(kCanOverflow);
823 }
824 bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
825 res->set_can_be_minus_zero(m0);
826 return res;
827 } else {
828 return HValue::InferRange();
829 }
830 }
831
832
InferRange()833 Range* HSub::InferRange() {
834 if (representation().IsInteger32()) {
835 Range* a = left()->range();
836 Range* b = right()->range();
837 Range* res = a->Copy();
838 if (!res->SubAndCheckOverflow(b)) {
839 ClearFlag(kCanOverflow);
840 }
841 res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
842 return res;
843 } else {
844 return HValue::InferRange();
845 }
846 }
847
848
InferRange()849 Range* HMul::InferRange() {
850 if (representation().IsInteger32()) {
851 Range* a = left()->range();
852 Range* b = right()->range();
853 Range* res = a->Copy();
854 if (!res->MulAndCheckOverflow(b)) {
855 ClearFlag(kCanOverflow);
856 }
857 bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
858 (a->CanBeNegative() && b->CanBeZero());
859 res->set_can_be_minus_zero(m0);
860 return res;
861 } else {
862 return HValue::InferRange();
863 }
864 }
865
866
InferRange()867 Range* HDiv::InferRange() {
868 if (representation().IsInteger32()) {
869 Range* result = new Range();
870 if (left()->range()->CanBeMinusZero()) {
871 result->set_can_be_minus_zero(true);
872 }
873
874 if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
875 result->set_can_be_minus_zero(true);
876 }
877
878 if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
879 SetFlag(HValue::kCanOverflow);
880 }
881
882 if (!right()->range()->CanBeZero()) {
883 ClearFlag(HValue::kCanBeDivByZero);
884 }
885 return result;
886 } else {
887 return HValue::InferRange();
888 }
889 }
890
891
InferRange()892 Range* HMod::InferRange() {
893 if (representation().IsInteger32()) {
894 Range* a = left()->range();
895 Range* result = new Range();
896 if (a->CanBeMinusZero() || a->CanBeNegative()) {
897 result->set_can_be_minus_zero(true);
898 }
899 if (!right()->range()->CanBeZero()) {
900 ClearFlag(HValue::kCanBeDivByZero);
901 }
902 return result;
903 } else {
904 return HValue::InferRange();
905 }
906 }
907
908
PrintTo(StringStream * stream)909 void HPhi::PrintTo(StringStream* stream) {
910 stream->Add("[");
911 for (int i = 0; i < OperandCount(); ++i) {
912 HValue* value = OperandAt(i);
913 stream->Add(" ");
914 value->PrintNameTo(stream);
915 stream->Add(" ");
916 }
917 stream->Add(" uses%d_%di_%dd_%dt]",
918 uses()->length(),
919 int32_non_phi_uses() + int32_indirect_uses(),
920 double_non_phi_uses() + double_indirect_uses(),
921 tagged_non_phi_uses() + tagged_indirect_uses());
922 }
923
924
AddInput(HValue * value)925 void HPhi::AddInput(HValue* value) {
926 inputs_.Add(NULL);
927 SetOperandAt(OperandCount() - 1, value);
928 // Mark phis that may have 'arguments' directly or indirectly as an operand.
929 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
930 SetFlag(kIsArguments);
931 }
932 }
933
934
HasRealUses()935 bool HPhi::HasRealUses() {
936 for (int i = 0; i < uses()->length(); i++) {
937 if (!uses()->at(i)->IsPhi()) return true;
938 }
939 return false;
940 }
941
942
GetRedundantReplacement()943 HValue* HPhi::GetRedundantReplacement() {
944 HValue* candidate = NULL;
945 int count = OperandCount();
946 int position = 0;
947 while (position < count && candidate == NULL) {
948 HValue* current = OperandAt(position++);
949 if (current != this) candidate = current;
950 }
951 while (position < count) {
952 HValue* current = OperandAt(position++);
953 if (current != this && current != candidate) return NULL;
954 }
955 ASSERT(candidate != this);
956 return candidate;
957 }
958
959
DeleteFromGraph()960 void HPhi::DeleteFromGraph() {
961 ASSERT(block() != NULL);
962 block()->RemovePhi(this);
963 ASSERT(block() == NULL);
964 }
965
966
InitRealUses(int phi_id)967 void HPhi::InitRealUses(int phi_id) {
968 // Initialize real uses.
969 phi_id_ = phi_id;
970 for (int j = 0; j < uses()->length(); j++) {
971 HValue* use = uses()->at(j);
972 if (!use->IsPhi()) {
973 int index = use->LookupOperandIndex(0, this);
974 Representation req_rep = use->RequiredInputRepresentation(index);
975 non_phi_uses_[req_rep.kind()]++;
976 }
977 }
978 }
979
980
AddNonPhiUsesFrom(HPhi * other)981 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
982 for (int i = 0; i < Representation::kNumRepresentations; i++) {
983 indirect_uses_[i] += other->non_phi_uses_[i];
984 }
985 }
986
987
AddIndirectUsesTo(int * dest)988 void HPhi::AddIndirectUsesTo(int* dest) {
989 for (int i = 0; i < Representation::kNumRepresentations; i++) {
990 dest[i] += indirect_uses_[i];
991 }
992 }
993
994
PrintDataTo(StringStream * stream)995 void HSimulate::PrintDataTo(StringStream* stream) {
996 stream->Add("id=%d ", ast_id());
997 if (pop_count_ > 0) stream->Add("pop %d", pop_count_);
998 if (values_.length() > 0) {
999 if (pop_count_ > 0) stream->Add(" /");
1000 for (int i = 0; i < values_.length(); ++i) {
1001 if (!HasAssignedIndexAt(i)) {
1002 stream->Add(" push ");
1003 } else {
1004 stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1005 }
1006 values_[i]->PrintNameTo(stream);
1007 }
1008 }
1009 }
1010
1011
PrintDataTo(StringStream * stream)1012 void HEnterInlined::PrintDataTo(StringStream* stream) {
1013 SmartPointer<char> name = function()->debug_name()->ToCString();
1014 stream->Add("%s, id=%d", *name, function()->id());
1015 }
1016
1017
HConstant(Handle<Object> handle,Representation r)1018 HConstant::HConstant(Handle<Object> handle, Representation r)
1019 : handle_(handle),
1020 constant_type_(HType::TypeFromValue(handle)),
1021 has_int32_value_(false),
1022 int32_value_(0),
1023 has_double_value_(false),
1024 double_value_(0) {
1025 set_representation(r);
1026 SetFlag(kUseGVN);
1027 if (handle_->IsNumber()) {
1028 double n = handle_->Number();
1029 double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1030 has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
1031 if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1032 double_value_ = n;
1033 has_double_value_ = true;
1034 }
1035 }
1036
1037
CopyToRepresentation(Representation r) const1038 HConstant* HConstant::CopyToRepresentation(Representation r) const {
1039 if (r.IsInteger32() && !has_int32_value_) return NULL;
1040 if (r.IsDouble() && !has_double_value_) return NULL;
1041 return new HConstant(handle_, r);
1042 }
1043
1044
CopyToTruncatedInt32() const1045 HConstant* HConstant::CopyToTruncatedInt32() const {
1046 if (!has_double_value_) return NULL;
1047 int32_t truncated = NumberToInt32(*handle_);
1048 return new HConstant(FACTORY->NewNumberFromInt(truncated),
1049 Representation::Integer32());
1050 }
1051
1052
ToBoolean() const1053 bool HConstant::ToBoolean() const {
1054 // Converts the constant's boolean value according to
1055 // ECMAScript section 9.2 ToBoolean conversion.
1056 if (HasInteger32Value()) return Integer32Value() != 0;
1057 if (HasDoubleValue()) {
1058 double v = DoubleValue();
1059 return v != 0 && !isnan(v);
1060 }
1061 if (handle()->IsTrue()) return true;
1062 if (handle()->IsFalse()) return false;
1063 if (handle()->IsUndefined()) return false;
1064 if (handle()->IsNull()) return false;
1065 if (handle()->IsString() &&
1066 String::cast(*handle())->length() == 0) return false;
1067 return true;
1068 }
1069
PrintDataTo(StringStream * stream)1070 void HConstant::PrintDataTo(StringStream* stream) {
1071 handle()->ShortPrint(stream);
1072 }
1073
1074
IsCopyOnWrite() const1075 bool HArrayLiteral::IsCopyOnWrite() const {
1076 return constant_elements()->map() == HEAP->fixed_cow_array_map();
1077 }
1078
1079
PrintDataTo(StringStream * stream)1080 void HBinaryOperation::PrintDataTo(StringStream* stream) {
1081 left()->PrintNameTo(stream);
1082 stream->Add(" ");
1083 right()->PrintNameTo(stream);
1084 if (CheckFlag(kCanOverflow)) stream->Add(" !");
1085 if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1086 }
1087
1088
InferRange()1089 Range* HBitAnd::InferRange() {
1090 int32_t left_mask = (left()->range() != NULL)
1091 ? left()->range()->Mask()
1092 : 0xffffffff;
1093 int32_t right_mask = (right()->range() != NULL)
1094 ? right()->range()->Mask()
1095 : 0xffffffff;
1096 int32_t result_mask = left_mask & right_mask;
1097 return (result_mask >= 0)
1098 ? new Range(0, result_mask)
1099 : HValue::InferRange();
1100 }
1101
1102
InferRange()1103 Range* HBitOr::InferRange() {
1104 int32_t left_mask = (left()->range() != NULL)
1105 ? left()->range()->Mask()
1106 : 0xffffffff;
1107 int32_t right_mask = (right()->range() != NULL)
1108 ? right()->range()->Mask()
1109 : 0xffffffff;
1110 int32_t result_mask = left_mask | right_mask;
1111 return (result_mask >= 0)
1112 ? new Range(0, result_mask)
1113 : HValue::InferRange();
1114 }
1115
1116
InferRange()1117 Range* HSar::InferRange() {
1118 if (right()->IsConstant()) {
1119 HConstant* c = HConstant::cast(right());
1120 if (c->HasInteger32Value()) {
1121 Range* result = (left()->range() != NULL)
1122 ? left()->range()->Copy()
1123 : new Range();
1124 result->Sar(c->Integer32Value());
1125 return result;
1126 }
1127 }
1128 return HValue::InferRange();
1129 }
1130
1131
InferRange()1132 Range* HShl::InferRange() {
1133 if (right()->IsConstant()) {
1134 HConstant* c = HConstant::cast(right());
1135 if (c->HasInteger32Value()) {
1136 Range* result = (left()->range() != NULL)
1137 ? left()->range()->Copy()
1138 : new Range();
1139 result->Shl(c->Integer32Value());
1140 return result;
1141 }
1142 }
1143 return HValue::InferRange();
1144 }
1145
1146
1147
PrintDataTo(StringStream * stream)1148 void HCompare::PrintDataTo(StringStream* stream) {
1149 stream->Add(Token::Name(token()));
1150 stream->Add(" ");
1151 HBinaryOperation::PrintDataTo(stream);
1152 }
1153
1154
SetInputRepresentation(Representation r)1155 void HCompare::SetInputRepresentation(Representation r) {
1156 input_representation_ = r;
1157 if (r.IsTagged()) {
1158 SetAllSideEffects();
1159 ClearFlag(kUseGVN);
1160 } else if (r.IsDouble()) {
1161 SetFlag(kDeoptimizeOnUndefined);
1162 ClearAllSideEffects();
1163 SetFlag(kUseGVN);
1164 } else {
1165 ClearAllSideEffects();
1166 SetFlag(kUseGVN);
1167 }
1168 }
1169
1170
PrintDataTo(StringStream * stream)1171 void HParameter::PrintDataTo(StringStream* stream) {
1172 stream->Add("%u", index());
1173 }
1174
1175
PrintDataTo(StringStream * stream)1176 void HLoadNamedField::PrintDataTo(StringStream* stream) {
1177 object()->PrintNameTo(stream);
1178 stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1179 }
1180
1181
HLoadNamedFieldPolymorphic(HValue * object,ZoneMapList * types,Handle<String> name)1182 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* object,
1183 ZoneMapList* types,
1184 Handle<String> name)
1185 : HUnaryOperation(object),
1186 types_(Min(types->length(), kMaxLoadPolymorphism)),
1187 name_(name),
1188 need_generic_(false) {
1189 set_representation(Representation::Tagged());
1190 SetFlag(kDependsOnMaps);
1191 for (int i = 0;
1192 i < types->length() && types_.length() < kMaxLoadPolymorphism;
1193 ++i) {
1194 Handle<Map> map = types->at(i);
1195 LookupResult lookup;
1196 map->LookupInDescriptors(NULL, *name, &lookup);
1197 if (lookup.IsProperty() && lookup.type() == FIELD) {
1198 types_.Add(types->at(i));
1199 int index = lookup.GetLocalFieldIndexFromMap(*map);
1200 if (index < 0) {
1201 SetFlag(kDependsOnInobjectFields);
1202 } else {
1203 SetFlag(kDependsOnBackingStoreFields);
1204 }
1205 }
1206 }
1207
1208 if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1209 SetFlag(kUseGVN);
1210 } else {
1211 SetAllSideEffects();
1212 need_generic_ = true;
1213 }
1214 }
1215
1216
DataEquals(HValue * value)1217 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1218 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1219 if (types_.length() != other->types()->length()) return false;
1220 if (!name_.is_identical_to(other->name())) return false;
1221 if (need_generic_ != other->need_generic_) return false;
1222 for (int i = 0; i < types_.length(); i++) {
1223 bool found = false;
1224 for (int j = 0; j < types_.length(); j++) {
1225 if (types_.at(j).is_identical_to(other->types()->at(i))) {
1226 found = true;
1227 break;
1228 }
1229 }
1230 if (!found) return false;
1231 }
1232 return true;
1233 }
1234
1235
PrintDataTo(StringStream * stream)1236 void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
1237 object()->PrintNameTo(stream);
1238 stream->Add("[");
1239 key()->PrintNameTo(stream);
1240 stream->Add("]");
1241 }
1242
1243
PrintDataTo(StringStream * stream)1244 void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1245 object()->PrintNameTo(stream);
1246 stream->Add("[");
1247 key()->PrintNameTo(stream);
1248 stream->Add("]");
1249 }
1250
1251
PrintDataTo(StringStream * stream)1252 void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1253 StringStream* stream) {
1254 external_pointer()->PrintNameTo(stream);
1255 stream->Add(".");
1256 switch (array_type()) {
1257 case kExternalByteArray:
1258 stream->Add("byte");
1259 break;
1260 case kExternalUnsignedByteArray:
1261 stream->Add("u_byte");
1262 break;
1263 case kExternalShortArray:
1264 stream->Add("short");
1265 break;
1266 case kExternalUnsignedShortArray:
1267 stream->Add("u_short");
1268 break;
1269 case kExternalIntArray:
1270 stream->Add("int");
1271 break;
1272 case kExternalUnsignedIntArray:
1273 stream->Add("u_int");
1274 break;
1275 case kExternalFloatArray:
1276 stream->Add("float");
1277 break;
1278 case kExternalPixelArray:
1279 stream->Add("pixel");
1280 break;
1281 }
1282 stream->Add("[");
1283 key()->PrintNameTo(stream);
1284 stream->Add("]");
1285 }
1286
1287
PrintDataTo(StringStream * stream)1288 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
1289 object()->PrintNameTo(stream);
1290 stream->Add(".");
1291 ASSERT(name()->IsString());
1292 stream->Add(*String::cast(*name())->ToCString());
1293 stream->Add(" = ");
1294 value()->PrintNameTo(stream);
1295 }
1296
1297
PrintDataTo(StringStream * stream)1298 void HStoreNamedField::PrintDataTo(StringStream* stream) {
1299 object()->PrintNameTo(stream);
1300 stream->Add(".");
1301 ASSERT(name()->IsString());
1302 stream->Add(*String::cast(*name())->ToCString());
1303 stream->Add(" = ");
1304 value()->PrintNameTo(stream);
1305 if (!transition().is_null()) {
1306 stream->Add(" (transition map %p)", *transition());
1307 }
1308 }
1309
1310
PrintDataTo(StringStream * stream)1311 void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
1312 object()->PrintNameTo(stream);
1313 stream->Add("[");
1314 key()->PrintNameTo(stream);
1315 stream->Add("] = ");
1316 value()->PrintNameTo(stream);
1317 }
1318
1319
PrintDataTo(StringStream * stream)1320 void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1321 object()->PrintNameTo(stream);
1322 stream->Add("[");
1323 key()->PrintNameTo(stream);
1324 stream->Add("] = ");
1325 value()->PrintNameTo(stream);
1326 }
1327
1328
PrintDataTo(StringStream * stream)1329 void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1330 StringStream* stream) {
1331 external_pointer()->PrintNameTo(stream);
1332 stream->Add(".");
1333 switch (array_type()) {
1334 case kExternalByteArray:
1335 stream->Add("byte");
1336 break;
1337 case kExternalUnsignedByteArray:
1338 stream->Add("u_byte");
1339 break;
1340 case kExternalShortArray:
1341 stream->Add("short");
1342 break;
1343 case kExternalUnsignedShortArray:
1344 stream->Add("u_short");
1345 break;
1346 case kExternalIntArray:
1347 stream->Add("int");
1348 break;
1349 case kExternalUnsignedIntArray:
1350 stream->Add("u_int");
1351 break;
1352 case kExternalFloatArray:
1353 stream->Add("float");
1354 break;
1355 case kExternalPixelArray:
1356 stream->Add("pixel");
1357 break;
1358 }
1359 stream->Add("[");
1360 key()->PrintNameTo(stream);
1361 stream->Add("] = ");
1362 value()->PrintNameTo(stream);
1363 }
1364
1365
PrintDataTo(StringStream * stream)1366 void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
1367 stream->Add("[%p]", *cell());
1368 if (check_hole_value()) stream->Add(" (deleteable/read-only)");
1369 }
1370
1371
PrintDataTo(StringStream * stream)1372 void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1373 stream->Add("%o ", *name());
1374 }
1375
1376
PrintDataTo(StringStream * stream)1377 void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
1378 stream->Add("[%p] = ", *cell());
1379 value()->PrintNameTo(stream);
1380 }
1381
1382
PrintDataTo(StringStream * stream)1383 void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1384 stream->Add("%o = ", *name());
1385 value()->PrintNameTo(stream);
1386 }
1387
1388
PrintDataTo(StringStream * stream)1389 void HLoadContextSlot::PrintDataTo(StringStream* stream) {
1390 value()->PrintNameTo(stream);
1391 stream->Add("[%d]", slot_index());
1392 }
1393
1394
PrintDataTo(StringStream * stream)1395 void HStoreContextSlot::PrintDataTo(StringStream* stream) {
1396 context()->PrintNameTo(stream);
1397 stream->Add("[%d] = ", slot_index());
1398 value()->PrintNameTo(stream);
1399 }
1400
1401
1402 // Implementation of type inference and type conversions. Calculates
1403 // the inferred type of this instruction based on the input operands.
1404
CalculateInferredType()1405 HType HValue::CalculateInferredType() {
1406 return type_;
1407 }
1408
1409
CalculateInferredType()1410 HType HCheckMap::CalculateInferredType() {
1411 return value()->type();
1412 }
1413
1414
CalculateInferredType()1415 HType HCheckFunction::CalculateInferredType() {
1416 return value()->type();
1417 }
1418
1419
CalculateInferredType()1420 HType HCheckNonSmi::CalculateInferredType() {
1421 // TODO(kasperl): Is there any way to signal that this isn't a smi?
1422 return HType::Tagged();
1423 }
1424
1425
CalculateInferredType()1426 HType HCheckSmi::CalculateInferredType() {
1427 return HType::Smi();
1428 }
1429
1430
CalculateInferredType()1431 HType HPhi::CalculateInferredType() {
1432 HType result = HType::Uninitialized();
1433 for (int i = 0; i < OperandCount(); ++i) {
1434 HType current = OperandAt(i)->type();
1435 result = result.Combine(current);
1436 }
1437 return result;
1438 }
1439
1440
CalculateInferredType()1441 HType HConstant::CalculateInferredType() {
1442 return constant_type_;
1443 }
1444
1445
CalculateInferredType()1446 HType HCompare::CalculateInferredType() {
1447 return HType::Boolean();
1448 }
1449
1450
CalculateInferredType()1451 HType HCompareJSObjectEq::CalculateInferredType() {
1452 return HType::Boolean();
1453 }
1454
1455
CalculateInferredType()1456 HType HUnaryPredicate::CalculateInferredType() {
1457 return HType::Boolean();
1458 }
1459
1460
CalculateInferredType()1461 HType HBitwiseBinaryOperation::CalculateInferredType() {
1462 return HType::TaggedNumber();
1463 }
1464
1465
CalculateInferredType()1466 HType HArithmeticBinaryOperation::CalculateInferredType() {
1467 return HType::TaggedNumber();
1468 }
1469
1470
CalculateInferredType()1471 HType HAdd::CalculateInferredType() {
1472 return HType::Tagged();
1473 }
1474
1475
CalculateInferredType()1476 HType HBitAnd::CalculateInferredType() {
1477 return HType::TaggedNumber();
1478 }
1479
1480
CalculateInferredType()1481 HType HBitXor::CalculateInferredType() {
1482 return HType::TaggedNumber();
1483 }
1484
1485
CalculateInferredType()1486 HType HBitOr::CalculateInferredType() {
1487 return HType::TaggedNumber();
1488 }
1489
1490
CalculateInferredType()1491 HType HBitNot::CalculateInferredType() {
1492 return HType::TaggedNumber();
1493 }
1494
1495
CalculateInferredType()1496 HType HUnaryMathOperation::CalculateInferredType() {
1497 return HType::TaggedNumber();
1498 }
1499
1500
CalculateInferredType()1501 HType HShl::CalculateInferredType() {
1502 return HType::TaggedNumber();
1503 }
1504
1505
CalculateInferredType()1506 HType HShr::CalculateInferredType() {
1507 return HType::TaggedNumber();
1508 }
1509
1510
CalculateInferredType()1511 HType HSar::CalculateInferredType() {
1512 return HType::TaggedNumber();
1513 }
1514
1515
EnsureAndPropagateNotMinusZero(BitVector * visited)1516 HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
1517 BitVector* visited) {
1518 visited->Add(id());
1519 if (representation().IsInteger32() &&
1520 !value()->representation().IsInteger32()) {
1521 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1522 SetFlag(kBailoutOnMinusZero);
1523 }
1524 }
1525 if (RequiredInputRepresentation(0).IsInteger32() &&
1526 representation().IsInteger32()) {
1527 return value();
1528 }
1529 return NULL;
1530 }
1531
1532
1533
EnsureAndPropagateNotMinusZero(BitVector * visited)1534 HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1535 visited->Add(id());
1536 if (from().IsInteger32()) return NULL;
1537 if (CanTruncateToInt32()) return NULL;
1538 if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
1539 SetFlag(kBailoutOnMinusZero);
1540 }
1541 ASSERT(!from().IsInteger32() || !to().IsInteger32());
1542 return NULL;
1543 }
1544
1545
EnsureAndPropagateNotMinusZero(BitVector * visited)1546 HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1547 visited->Add(id());
1548 if (range() == NULL || range()->CanBeMinusZero()) {
1549 SetFlag(kBailoutOnMinusZero);
1550 return left();
1551 }
1552 return NULL;
1553 }
1554
1555
EnsureAndPropagateNotMinusZero(BitVector * visited)1556 HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1557 visited->Add(id());
1558 if (range() == NULL || range()->CanBeMinusZero()) {
1559 SetFlag(kBailoutOnMinusZero);
1560 }
1561 return NULL;
1562 }
1563
1564
EnsureAndPropagateNotMinusZero(BitVector * visited)1565 HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1566 visited->Add(id());
1567 if (range() == NULL || range()->CanBeMinusZero()) {
1568 SetFlag(kBailoutOnMinusZero);
1569 }
1570 return NULL;
1571 }
1572
1573
EnsureAndPropagateNotMinusZero(BitVector * visited)1574 HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1575 visited->Add(id());
1576 // Propagate to the left argument. If the left argument cannot be -0, then
1577 // the result of the add operation cannot be either.
1578 if (range() == NULL || range()->CanBeMinusZero()) {
1579 return left();
1580 }
1581 return NULL;
1582 }
1583
1584
EnsureAndPropagateNotMinusZero(BitVector * visited)1585 HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
1586 visited->Add(id());
1587 // Propagate to the left argument. If the left argument cannot be -0, then
1588 // the result of the sub operation cannot be either.
1589 if (range() == NULL || range()->CanBeMinusZero()) {
1590 return left();
1591 }
1592 return NULL;
1593 }
1594
1595
1596 // Node-specific verification code is only included in debug mode.
1597 #ifdef DEBUG
1598
Verify()1599 void HPhi::Verify() {
1600 ASSERT(OperandCount() == block()->predecessors()->length());
1601 for (int i = 0; i < OperandCount(); ++i) {
1602 HValue* value = OperandAt(i);
1603 HBasicBlock* defining_block = value->block();
1604 HBasicBlock* predecessor_block = block()->predecessors()->at(i);
1605 ASSERT(defining_block == predecessor_block ||
1606 defining_block->Dominates(predecessor_block));
1607 }
1608 }
1609
1610
Verify()1611 void HSimulate::Verify() {
1612 HInstruction::Verify();
1613 ASSERT(HasAstId());
1614 }
1615
1616
Verify()1617 void HBoundsCheck::Verify() {
1618 HInstruction::Verify();
1619 }
1620
1621
Verify()1622 void HCheckSmi::Verify() {
1623 HInstruction::Verify();
1624 ASSERT(HasNoUses());
1625 }
1626
1627
Verify()1628 void HCheckNonSmi::Verify() {
1629 HInstruction::Verify();
1630 ASSERT(HasNoUses());
1631 }
1632
1633
Verify()1634 void HCheckInstanceType::Verify() {
1635 HInstruction::Verify();
1636 ASSERT(HasNoUses());
1637 }
1638
1639
Verify()1640 void HCheckMap::Verify() {
1641 HInstruction::Verify();
1642 ASSERT(HasNoUses());
1643 }
1644
1645
Verify()1646 void HCheckFunction::Verify() {
1647 HInstruction::Verify();
1648 ASSERT(HasNoUses());
1649 }
1650
1651
Verify()1652 void HCheckPrototypeMaps::Verify() {
1653 HInstruction::Verify();
1654 ASSERT(HasNoUses());
1655 }
1656
1657 #endif
1658
1659 } } // namespace v8::internal
1660