• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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     default:
64       UNREACHABLE();
65       return NULL;
66   }
67 }
68 
69 
LoopWeight() const70 int 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 
AssumeRepresentation(Representation r)78 void 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 
ConvertAndSetOverflow(int64_t result,bool * overflow)88 static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
89   if (result > kMaxInt) {
90     *overflow = true;
91     return kMaxInt;
92   }
93   if (result < kMinInt) {
94     *overflow = true;
95     return kMinInt;
96   }
97   return static_cast<int32_t>(result);
98 }
99 
100 
AddWithoutOverflow(int32_t a,int32_t b,bool * overflow)101 static 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 
SubWithoutOverflow(int32_t a,int32_t b,bool * overflow)107 static 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);
110 }
111 
112 
MulWithoutOverflow(int32_t a,int32_t b,bool * overflow)113 static int32_t MulWithoutOverflow(int32_t a, int32_t b, bool* overflow) {
114   int64_t result = static_cast<int64_t>(a) * static_cast<int64_t>(b);
115   return ConvertAndSetOverflow(result, overflow);
116 }
117 
118 
Mask() const119 int32_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 
AddConstant(int32_t value)132 void Range::AddConstant(int32_t value) {
133   if (value == 0) return;
134   bool may_overflow = false;  // Overflow is ignored here.
135   lower_ = AddWithoutOverflow(lower_, value, &may_overflow);
136   upper_ = AddWithoutOverflow(upper_, value, &may_overflow);
137 #ifdef DEBUG
138   Verify();
139 #endif
140 }
141 
142 
Intersect(Range * other)143 void 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 
Union(Range * other)151 void 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 
Sar(int32_t value)159 void 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 
Shl(int32_t value)167 void 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 
AddAndCheckOverflow(Range * other)181 bool Range::AddAndCheckOverflow(Range* other) {
182   bool may_overflow = false;
183   lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
184   upper_ = AddWithoutOverflow(upper_, other->upper(), &may_overflow);
185   KeepOrder();
186 #ifdef DEBUG
187   Verify();
188 #endif
189   return may_overflow;
190 }
191 
192 
SubAndCheckOverflow(Range * other)193 bool Range::SubAndCheckOverflow(Range* other) {
194   bool may_overflow = false;
195   lower_ = SubWithoutOverflow(lower_, other->upper(), &may_overflow);
196   upper_ = SubWithoutOverflow(upper_, other->lower(), &may_overflow);
197   KeepOrder();
198 #ifdef DEBUG
199   Verify();
200 #endif
201   return may_overflow;
202 }
203 
204 
KeepOrder()205 void Range::KeepOrder() {
206   if (lower_ > upper_) {
207     int32_t tmp = lower_;
208     lower_ = upper_;
209     upper_ = tmp;
210   }
211 }
212 
213 
214 #ifdef DEBUG
Verify() const215 void Range::Verify() const {
216   ASSERT(lower_ <= upper_);
217 }
218 #endif
219 
220 
MulAndCheckOverflow(Range * other)221 bool 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));
229 #ifdef DEBUG
230   Verify();
231 #endif
232   return may_overflow;
233 }
234 
235 
ToString()236 const 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 
TypeFromValue(Handle<Object> value)255 HType 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 
IsDefinedAfter(HBasicBlock * other) const274 bool HValue::IsDefinedAfter(HBasicBlock* other) const {
275   return block()->block_id() > other->block_id();
276 }
277 
278 
tail()279 HUseListNode* 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 
CheckUsesForFlag(Flag f)288 bool 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 
HUseIterator(HUseListNode * head)296 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
297   Advance();
298 }
299 
300 
Advance()301 void HUseIterator::Advance() {
302   current_ = next_;
303   if (current_ != NULL) {
304     next_ = current_->tail();
305     value_ = current_->value();
306     index_ = current_->index();
307   }
308 }
309 
310 
UseCount() const311 int HValue::UseCount() const {
312   int count = 0;
313   for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
314   return count;
315 }
316 
317 
RemoveUse(HValue * value,int index)318 HUseListNode* 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 =
339         new HUseListNode(current->value(), current->index(), NULL);
340     current->Zap();
341     current = temp;
342   }
343 #endif
344   return current;
345 }
346 
347 
Equals(HValue * other)348 bool HValue::Equals(HValue* other) {
349   if (other->opcode() != opcode()) return false;
350   if (!other->representation().Equals(representation())) return false;
351   if (!other->type_.Equals(type_)) return false;
352   if (other->flags() != flags()) return false;
353   if (OperandCount() != other->OperandCount()) return false;
354   for (int i = 0; i < OperandCount(); ++i) {
355     if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false;
356   }
357   bool result = DataEquals(other);
358   ASSERT(!result || Hashcode() == other->Hashcode());
359   return result;
360 }
361 
362 
Hashcode()363 intptr_t HValue::Hashcode() {
364   intptr_t result = opcode();
365   int count = OperandCount();
366   for (int i = 0; i < count; ++i) {
367     result = result * 19 + OperandAt(i)->id() + (result >> 7);
368   }
369   return result;
370 }
371 
372 
Mnemonic() const373 const char* HValue::Mnemonic() const {
374   switch (opcode()) {
375 #define MAKE_CASE(type) case k##type: return #type;
376     HYDROGEN_CONCRETE_INSTRUCTION_LIST(MAKE_CASE)
377 #undef MAKE_CASE
378     case kPhi: return "Phi";
379     default: return "";
380   }
381 }
382 
383 
SetOperandAt(int index,HValue * value)384 void HValue::SetOperandAt(int index, HValue* value) {
385   RegisterUse(index, value);
386   InternalSetOperandAt(index, value);
387 }
388 
389 
DeleteAndReplaceWith(HValue * other)390 void HValue::DeleteAndReplaceWith(HValue* other) {
391   // We replace all uses first, so Delete can assert that there are none.
392   if (other != NULL) ReplaceAllUsesWith(other);
393   ASSERT(HasNoUses());
394   Kill();
395   DeleteFromGraph();
396 }
397 
398 
ReplaceAllUsesWith(HValue * other)399 void HValue::ReplaceAllUsesWith(HValue* other) {
400   while (use_list_ != NULL) {
401     HUseListNode* list_node = use_list_;
402     HValue* value = list_node->value();
403     ASSERT(!value->block()->IsStartBlock());
404     value->InternalSetOperandAt(list_node->index(), other);
405     use_list_ = list_node->tail();
406     list_node->set_tail(other->use_list_);
407     other->use_list_ = list_node;
408   }
409 }
410 
411 
Kill()412 void HValue::Kill() {
413   // Instead of going through the entire use list of each operand, we only
414   // check the first item in each use list and rely on the tail() method to
415   // skip dead items, removing them lazily next time we traverse the list.
416   SetFlag(kIsDead);
417   for (int i = 0; i < OperandCount(); ++i) {
418     HValue* operand = OperandAt(i);
419     HUseListNode* first = operand->use_list_;
420     if (first != NULL && first->value() == this && first->index() == i) {
421       operand->use_list_ = first->tail();
422     }
423   }
424 }
425 
426 
SetBlock(HBasicBlock * block)427 void HValue::SetBlock(HBasicBlock* block) {
428   ASSERT(block_ == NULL || block == NULL);
429   block_ = block;
430   if (id_ == kNoNumber && block != NULL) {
431     id_ = block->graph()->GetNextValueID(this);
432   }
433 }
434 
435 
PrintTypeTo(StringStream * stream)436 void HValue::PrintTypeTo(StringStream* stream) {
437   if (!representation().IsTagged() || type().Equals(HType::Tagged())) return;
438   stream->Add(" type[%s]", type().ToString());
439 }
440 
441 
PrintRangeTo(StringStream * stream)442 void HValue::PrintRangeTo(StringStream* stream) {
443   if (range() == NULL || range()->IsMostGeneric()) return;
444   stream->Add(" range[%d,%d,m0=%d]",
445               range()->lower(),
446               range()->upper(),
447               static_cast<int>(range()->CanBeMinusZero()));
448 }
449 
450 
PrintChangesTo(StringStream * stream)451 void HValue::PrintChangesTo(StringStream* stream) {
452   GVNFlagSet changes_flags = ChangesFlags();
453   if (changes_flags.IsEmpty()) return;
454   stream->Add(" changes[");
455   if (changes_flags == AllSideEffectsFlagSet()) {
456     stream->Add("*");
457   } else {
458     bool add_comma = false;
459 #define PRINT_DO(type)                            \
460     if (changes_flags.Contains(kChanges##type)) { \
461       if (add_comma) stream->Add(",");            \
462       add_comma = true;                           \
463       stream->Add(#type);                         \
464     }
465     GVN_FLAG_LIST(PRINT_DO);
466 #undef PRINT_DO
467   }
468   stream->Add("]");
469 }
470 
471 
PrintNameTo(StringStream * stream)472 void HValue::PrintNameTo(StringStream* stream) {
473   stream->Add("%s%d", representation_.Mnemonic(), id());
474 }
475 
476 
UpdateInferredType()477 bool HValue::UpdateInferredType() {
478   HType type = CalculateInferredType();
479   bool result = (!type.Equals(type_));
480   type_ = type;
481   return result;
482 }
483 
484 
RegisterUse(int index,HValue * new_value)485 void HValue::RegisterUse(int index, HValue* new_value) {
486   HValue* old_value = OperandAt(index);
487   if (old_value == new_value) return;
488 
489   HUseListNode* removed = NULL;
490   if (old_value != NULL) {
491     removed = old_value->RemoveUse(this, index);
492   }
493 
494   if (new_value != NULL) {
495     if (removed == NULL) {
496       new_value->use_list_ =
497           new HUseListNode(this, index, new_value->use_list_);
498     } else {
499       removed->set_tail(new_value->use_list_);
500       new_value->use_list_ = removed;
501     }
502   }
503 }
504 
505 
AddNewRange(Range * r,Zone * zone)506 void HValue::AddNewRange(Range* r, Zone* zone) {
507   if (!HasRange()) ComputeInitialRange(zone);
508   if (!HasRange()) range_ = new(zone) Range();
509   ASSERT(HasRange());
510   r->StackUpon(range_);
511   range_ = r;
512 }
513 
514 
RemoveLastAddedRange()515 void HValue::RemoveLastAddedRange() {
516   ASSERT(HasRange());
517   ASSERT(range_->next() != NULL);
518   range_ = range_->next();
519 }
520 
521 
ComputeInitialRange(Zone * zone)522 void HValue::ComputeInitialRange(Zone* zone) {
523   ASSERT(!HasRange());
524   range_ = InferRange(zone);
525   ASSERT(HasRange());
526 }
527 
528 
PrintTo(StringStream * stream)529 void HInstruction::PrintTo(StringStream* stream) {
530   PrintMnemonicTo(stream);
531   PrintDataTo(stream);
532   PrintRangeTo(stream);
533   PrintChangesTo(stream);
534   PrintTypeTo(stream);
535 }
536 
537 
PrintMnemonicTo(StringStream * stream)538 void HInstruction::PrintMnemonicTo(StringStream* stream) {
539   stream->Add("%s ", Mnemonic());
540 }
541 
542 
Unlink()543 void HInstruction::Unlink() {
544   ASSERT(IsLinked());
545   ASSERT(!IsControlInstruction());  // Must never move control instructions.
546   ASSERT(!IsBlockEntry());  // Doesn't make sense to delete these.
547   ASSERT(previous_ != NULL);
548   previous_->next_ = next_;
549   if (next_ == NULL) {
550     ASSERT(block()->last() == this);
551     block()->set_last(previous_);
552   } else {
553     next_->previous_ = previous_;
554   }
555   clear_block();
556 }
557 
558 
InsertBefore(HInstruction * next)559 void HInstruction::InsertBefore(HInstruction* next) {
560   ASSERT(!IsLinked());
561   ASSERT(!next->IsBlockEntry());
562   ASSERT(!IsControlInstruction());
563   ASSERT(!next->block()->IsStartBlock());
564   ASSERT(next->previous_ != NULL);
565   HInstruction* prev = next->previous();
566   prev->next_ = this;
567   next->previous_ = this;
568   next_ = next;
569   previous_ = prev;
570   SetBlock(next->block());
571 }
572 
573 
InsertAfter(HInstruction * previous)574 void HInstruction::InsertAfter(HInstruction* previous) {
575   ASSERT(!IsLinked());
576   ASSERT(!previous->IsControlInstruction());
577   ASSERT(!IsControlInstruction() || previous->next_ == NULL);
578   HBasicBlock* block = previous->block();
579   // Never insert anything except constants into the start block after finishing
580   // it.
581   if (block->IsStartBlock() && block->IsFinished() && !IsConstant()) {
582     ASSERT(block->end()->SecondSuccessor() == NULL);
583     InsertAfter(block->end()->FirstSuccessor()->first());
584     return;
585   }
586 
587   // If we're inserting after an instruction with side-effects that is
588   // followed by a simulate instruction, we need to insert after the
589   // simulate instruction instead.
590   HInstruction* next = previous->next_;
591   if (previous->HasObservableSideEffects() && next != NULL) {
592     ASSERT(next->IsSimulate());
593     previous = next;
594     next = previous->next_;
595   }
596 
597   previous_ = previous;
598   next_ = next;
599   SetBlock(block);
600   previous->next_ = this;
601   if (next != NULL) next->previous_ = this;
602 }
603 
604 
605 #ifdef DEBUG
Verify()606 void HInstruction::Verify() {
607   // Verify that input operands are defined before use.
608   HBasicBlock* cur_block = block();
609   for (int i = 0; i < OperandCount(); ++i) {
610     HValue* other_operand = OperandAt(i);
611     HBasicBlock* other_block = other_operand->block();
612     if (cur_block == other_block) {
613       if (!other_operand->IsPhi()) {
614         HInstruction* cur = this->previous();
615         while (cur != NULL) {
616           if (cur == other_operand) break;
617           cur = cur->previous();
618         }
619         // Must reach other operand in the same block!
620         ASSERT(cur == other_operand);
621       }
622     } else {
623       // If the following assert fires, you may have forgotten an
624       // AddInstruction.
625       ASSERT(other_block->Dominates(cur_block));
626     }
627   }
628 
629   // Verify that instructions that may have side-effects are followed
630   // by a simulate instruction.
631   if (HasObservableSideEffects() && !IsOsrEntry()) {
632     ASSERT(next()->IsSimulate());
633   }
634 
635   // Verify that instructions that can be eliminated by GVN have overridden
636   // HValue::DataEquals.  The default implementation is UNREACHABLE.  We
637   // don't actually care whether DataEquals returns true or false here.
638   if (CheckFlag(kUseGVN)) DataEquals(this);
639 }
640 #endif
641 
642 
PrintDataTo(StringStream * stream)643 void HUnaryCall::PrintDataTo(StringStream* stream) {
644   value()->PrintNameTo(stream);
645   stream->Add(" ");
646   stream->Add("#%d", argument_count());
647 }
648 
649 
PrintDataTo(StringStream * stream)650 void HBinaryCall::PrintDataTo(StringStream* stream) {
651   first()->PrintNameTo(stream);
652   stream->Add(" ");
653   second()->PrintNameTo(stream);
654   stream->Add(" ");
655   stream->Add("#%d", argument_count());
656 }
657 
658 
PrintDataTo(StringStream * stream)659 void HBoundsCheck::PrintDataTo(StringStream* stream) {
660   index()->PrintNameTo(stream);
661   stream->Add(" ");
662   length()->PrintNameTo(stream);
663 }
664 
665 
PrintDataTo(StringStream * stream)666 void HCallConstantFunction::PrintDataTo(StringStream* stream) {
667   if (IsApplyFunction()) {
668     stream->Add("optimized apply ");
669   } else {
670     stream->Add("%o ", function()->shared()->DebugName());
671   }
672   stream->Add("#%d", argument_count());
673 }
674 
675 
PrintDataTo(StringStream * stream)676 void HCallNamed::PrintDataTo(StringStream* stream) {
677   stream->Add("%o ", *name());
678   HUnaryCall::PrintDataTo(stream);
679 }
680 
681 
PrintDataTo(StringStream * stream)682 void HCallGlobal::PrintDataTo(StringStream* stream) {
683   stream->Add("%o ", *name());
684   HUnaryCall::PrintDataTo(stream);
685 }
686 
687 
PrintDataTo(StringStream * stream)688 void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
689   stream->Add("o ", target()->shared()->DebugName());
690   stream->Add("#%d", argument_count());
691 }
692 
693 
PrintDataTo(StringStream * stream)694 void HCallRuntime::PrintDataTo(StringStream* stream) {
695   stream->Add("%o ", *name());
696   stream->Add("#%d", argument_count());
697 }
698 
699 
PrintDataTo(StringStream * stream)700 void HClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
701   stream->Add("class_of_test(");
702   value()->PrintNameTo(stream);
703   stream->Add(", \"%o\")", *class_name());
704 }
705 
706 
PrintDataTo(StringStream * stream)707 void HAccessArgumentsAt::PrintDataTo(StringStream* stream) {
708   arguments()->PrintNameTo(stream);
709   stream->Add("[");
710   index()->PrintNameTo(stream);
711   stream->Add("], length ");
712   length()->PrintNameTo(stream);
713 }
714 
715 
PrintDataTo(StringStream * stream)716 void HControlInstruction::PrintDataTo(StringStream* stream) {
717   stream->Add(" goto (");
718   bool first_block = true;
719   for (HSuccessorIterator it(this); !it.Done(); it.Advance()) {
720     stream->Add(first_block ? "B%d" : ", B%d", it.Current()->block_id());
721     first_block = false;
722   }
723   stream->Add(")");
724 }
725 
726 
PrintDataTo(StringStream * stream)727 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
728   value()->PrintNameTo(stream);
729   HControlInstruction::PrintDataTo(stream);
730 }
731 
732 
PrintDataTo(StringStream * stream)733 void HIsNilAndBranch::PrintDataTo(StringStream* stream) {
734   value()->PrintNameTo(stream);
735   stream->Add(kind() == kStrictEquality ? " === " : " == ");
736   stream->Add(nil() == kNullValue ? "null" : "undefined");
737   HControlInstruction::PrintDataTo(stream);
738 }
739 
740 
PrintDataTo(StringStream * stream)741 void HReturn::PrintDataTo(StringStream* stream) {
742   value()->PrintNameTo(stream);
743 }
744 
745 
PrintDataTo(StringStream * stream)746 void HCompareMap::PrintDataTo(StringStream* stream) {
747   value()->PrintNameTo(stream);
748   stream->Add(" (%p)", *map());
749   HControlInstruction::PrintDataTo(stream);
750 }
751 
752 
OpName() const753 const char* HUnaryMathOperation::OpName() const {
754   switch (op()) {
755     case kMathFloor: return "floor";
756     case kMathRound: return "round";
757     case kMathCeil: return "ceil";
758     case kMathAbs: return "abs";
759     case kMathLog: return "log";
760     case kMathSin: return "sin";
761     case kMathCos: return "cos";
762     case kMathTan: return "tan";
763     case kMathASin: return "asin";
764     case kMathACos: return "acos";
765     case kMathATan: return "atan";
766     case kMathExp: return "exp";
767     case kMathSqrt: return "sqrt";
768     default: break;
769   }
770   return "(unknown operation)";
771 }
772 
773 
PrintDataTo(StringStream * stream)774 void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
775   const char* name = OpName();
776   stream->Add("%s ", name);
777   value()->PrintNameTo(stream);
778 }
779 
780 
PrintDataTo(StringStream * stream)781 void HUnaryOperation::PrintDataTo(StringStream* stream) {
782   value()->PrintNameTo(stream);
783 }
784 
785 
PrintDataTo(StringStream * stream)786 void HHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
787   value()->PrintNameTo(stream);
788   switch (from_) {
789     case FIRST_JS_RECEIVER_TYPE:
790       if (to_ == LAST_TYPE) stream->Add(" spec_object");
791       break;
792     case JS_REGEXP_TYPE:
793       if (to_ == JS_REGEXP_TYPE) stream->Add(" reg_exp");
794       break;
795     case JS_ARRAY_TYPE:
796       if (to_ == JS_ARRAY_TYPE) stream->Add(" array");
797       break;
798     case JS_FUNCTION_TYPE:
799       if (to_ == JS_FUNCTION_TYPE) stream->Add(" function");
800       break;
801     default:
802       break;
803   }
804 }
805 
806 
PrintDataTo(StringStream * stream)807 void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
808   value()->PrintNameTo(stream);
809   stream->Add(" == %o", *type_literal_);
810   HControlInstruction::PrintDataTo(stream);
811 }
812 
813 
PrintDataTo(StringStream * stream)814 void HCheckMapValue::PrintDataTo(StringStream* stream) {
815   value()->PrintNameTo(stream);
816   stream->Add(" ");
817   map()->PrintNameTo(stream);
818 }
819 
820 
PrintDataTo(StringStream * stream)821 void HForInPrepareMap::PrintDataTo(StringStream* stream) {
822   enumerable()->PrintNameTo(stream);
823 }
824 
825 
PrintDataTo(StringStream * stream)826 void HForInCacheArray::PrintDataTo(StringStream* stream) {
827   enumerable()->PrintNameTo(stream);
828   stream->Add(" ");
829   map()->PrintNameTo(stream);
830   stream->Add("[%d]", idx_);
831 }
832 
833 
PrintDataTo(StringStream * stream)834 void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
835   object()->PrintNameTo(stream);
836   stream->Add(" ");
837   index()->PrintNameTo(stream);
838 }
839 
840 
Canonicalize()841 HValue* HConstant::Canonicalize() {
842   return HasNoUses() ? NULL : this;
843 }
844 
845 
Canonicalize()846 HValue* HTypeof::Canonicalize() {
847   return HasNoUses() ? NULL : this;
848 }
849 
850 
Canonicalize()851 HValue* HBitwise::Canonicalize() {
852   if (!representation().IsInteger32()) return this;
853   // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
854   int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
855   if (left()->IsConstant() &&
856       HConstant::cast(left())->HasInteger32Value() &&
857       HConstant::cast(left())->Integer32Value() == nop_constant) {
858     return right();
859   }
860   if (right()->IsConstant() &&
861       HConstant::cast(right())->HasInteger32Value() &&
862       HConstant::cast(right())->Integer32Value() == nop_constant) {
863     return left();
864   }
865   return this;
866 }
867 
868 
Canonicalize()869 HValue* HAdd::Canonicalize() {
870   if (!representation().IsInteger32()) return this;
871   if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
872   return this;
873 }
874 
875 
Canonicalize()876 HValue* HSub::Canonicalize() {
877   if (!representation().IsInteger32()) return this;
878   if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
879   return this;
880 }
881 
882 
Canonicalize()883 HValue* HChange::Canonicalize() {
884   return (from().Equals(to())) ? value() : this;
885 }
886 
887 
Canonicalize()888 HValue* HWrapReceiver::Canonicalize() {
889   if (HasNoUses()) return NULL;
890   if (receiver()->type().IsJSObject()) {
891     return receiver();
892   }
893   return this;
894 }
895 
896 
PrintDataTo(StringStream * stream)897 void HTypeof::PrintDataTo(StringStream* stream) {
898   value()->PrintNameTo(stream);
899 }
900 
901 
PrintDataTo(StringStream * stream)902 void HChange::PrintDataTo(StringStream* stream) {
903   HUnaryOperation::PrintDataTo(stream);
904   stream->Add(" %s to %s", from().Mnemonic(), to().Mnemonic());
905 
906   if (CanTruncateToInt32()) stream->Add(" truncating-int32");
907   if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
908   if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
909 }
910 
911 
PrintDataTo(StringStream * stream)912 void HJSArrayLength::PrintDataTo(StringStream* stream) {
913   value()->PrintNameTo(stream);
914   stream->Add(" ");
915   typecheck()->PrintNameTo(stream);
916 }
917 
918 
Canonicalize()919 HValue* HCheckInstanceType::Canonicalize() {
920   if (check_ == IS_STRING &&
921       !value()->type().IsUninitialized() &&
922       value()->type().IsString()) {
923     return NULL;
924   }
925   if (check_ == IS_SYMBOL &&
926       value()->IsConstant() &&
927       HConstant::cast(value())->handle()->IsSymbol()) {
928     return NULL;
929   }
930   return this;
931 }
932 
933 
GetCheckInterval(InstanceType * first,InstanceType * last)934 void HCheckInstanceType::GetCheckInterval(InstanceType* first,
935                                           InstanceType* last) {
936   ASSERT(is_interval_check());
937   switch (check_) {
938     case IS_SPEC_OBJECT:
939       *first = FIRST_SPEC_OBJECT_TYPE;
940       *last = LAST_SPEC_OBJECT_TYPE;
941       return;
942     case IS_JS_ARRAY:
943       *first = *last = JS_ARRAY_TYPE;
944       return;
945     default:
946       UNREACHABLE();
947   }
948 }
949 
950 
GetCheckMaskAndTag(uint8_t * mask,uint8_t * tag)951 void HCheckInstanceType::GetCheckMaskAndTag(uint8_t* mask, uint8_t* tag) {
952   ASSERT(!is_interval_check());
953   switch (check_) {
954     case IS_STRING:
955       *mask = kIsNotStringMask;
956       *tag = kStringTag;
957       return;
958     case IS_SYMBOL:
959       *mask = kIsSymbolMask;
960       *tag = kSymbolTag;
961       return;
962     default:
963       UNREACHABLE();
964   }
965 }
966 
967 
PrintDataTo(StringStream * stream)968 void HCheckMap::PrintDataTo(StringStream* stream) {
969   value()->PrintNameTo(stream);
970   stream->Add(" %p", *map());
971   if (mode() == REQUIRE_EXACT_MAP) {
972     stream->Add(" [EXACT]");
973   } else if (!has_element_transitions_) {
974     stream->Add(" [EXACT*]");
975   } else {
976     stream->Add(" [MATCH ELEMENTS]");
977   }
978 }
979 
980 
PrintDataTo(StringStream * stream)981 void HCheckFunction::PrintDataTo(StringStream* stream) {
982   value()->PrintNameTo(stream);
983   stream->Add(" %p", *target());
984 }
985 
986 
GetCheckName()987 const char* HCheckInstanceType::GetCheckName() {
988   switch (check_) {
989     case IS_SPEC_OBJECT: return "object";
990     case IS_JS_ARRAY: return "array";
991     case IS_STRING: return "string";
992     case IS_SYMBOL: return "symbol";
993   }
994   UNREACHABLE();
995   return "";
996 }
997 
PrintDataTo(StringStream * stream)998 void HCheckInstanceType::PrintDataTo(StringStream* stream) {
999   stream->Add("%s ", GetCheckName());
1000   HUnaryOperation::PrintDataTo(stream);
1001 }
1002 
1003 
PrintDataTo(StringStream * stream)1004 void HCallStub::PrintDataTo(StringStream* stream) {
1005   stream->Add("%s ",
1006               CodeStub::MajorName(major_key_, false));
1007   HUnaryCall::PrintDataTo(stream);
1008 }
1009 
1010 
PrintDataTo(StringStream * stream)1011 void HInstanceOf::PrintDataTo(StringStream* stream) {
1012   left()->PrintNameTo(stream);
1013   stream->Add(" ");
1014   right()->PrintNameTo(stream);
1015   stream->Add(" ");
1016   context()->PrintNameTo(stream);
1017 }
1018 
1019 
InferRange(Zone * zone)1020 Range* HValue::InferRange(Zone* zone) {
1021   // Untagged integer32 cannot be -0, all other representations can.
1022   Range* result = new(zone) Range();
1023   result->set_can_be_minus_zero(!representation().IsInteger32());
1024   return result;
1025 }
1026 
1027 
InferRange(Zone * zone)1028 Range* HChange::InferRange(Zone* zone) {
1029   Range* input_range = value()->range();
1030   if (from().IsInteger32() &&
1031       to().IsTagged() &&
1032       input_range != NULL && input_range->IsInSmiRange()) {
1033     set_type(HType::Smi());
1034   }
1035   Range* result = (input_range != NULL)
1036       ? input_range->Copy(zone)
1037       : HValue::InferRange(zone);
1038   if (to().IsInteger32()) result->set_can_be_minus_zero(false);
1039   return result;
1040 }
1041 
1042 
InferRange(Zone * zone)1043 Range* HConstant::InferRange(Zone* zone) {
1044   if (has_int32_value_) {
1045     Range* result = new(zone) Range(int32_value_, int32_value_);
1046     result->set_can_be_minus_zero(false);
1047     return result;
1048   }
1049   return HValue::InferRange(zone);
1050 }
1051 
1052 
InferRange(Zone * zone)1053 Range* HPhi::InferRange(Zone* zone) {
1054   if (representation().IsInteger32()) {
1055     if (block()->IsLoopHeader()) {
1056       Range* range = new(zone) Range(kMinInt, kMaxInt);
1057       return range;
1058     } else {
1059       Range* range = OperandAt(0)->range()->Copy(zone);
1060       for (int i = 1; i < OperandCount(); ++i) {
1061         range->Union(OperandAt(i)->range());
1062       }
1063       return range;
1064     }
1065   } else {
1066     return HValue::InferRange(zone);
1067   }
1068 }
1069 
1070 
InferRange(Zone * zone)1071 Range* HAdd::InferRange(Zone* zone) {
1072   if (representation().IsInteger32()) {
1073     Range* a = left()->range();
1074     Range* b = right()->range();
1075     Range* res = a->Copy(zone);
1076     if (!res->AddAndCheckOverflow(b)) {
1077       ClearFlag(kCanOverflow);
1078     }
1079     bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
1080     res->set_can_be_minus_zero(m0);
1081     return res;
1082   } else {
1083     return HValue::InferRange(zone);
1084   }
1085 }
1086 
1087 
InferRange(Zone * zone)1088 Range* HSub::InferRange(Zone* zone) {
1089   if (representation().IsInteger32()) {
1090     Range* a = left()->range();
1091     Range* b = right()->range();
1092     Range* res = a->Copy(zone);
1093     if (!res->SubAndCheckOverflow(b)) {
1094       ClearFlag(kCanOverflow);
1095     }
1096     res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
1097     return res;
1098   } else {
1099     return HValue::InferRange(zone);
1100   }
1101 }
1102 
1103 
InferRange(Zone * zone)1104 Range* HMul::InferRange(Zone* zone) {
1105   if (representation().IsInteger32()) {
1106     Range* a = left()->range();
1107     Range* b = right()->range();
1108     Range* res = a->Copy(zone);
1109     if (!res->MulAndCheckOverflow(b)) {
1110       ClearFlag(kCanOverflow);
1111     }
1112     bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
1113         (a->CanBeNegative() && b->CanBeZero());
1114     res->set_can_be_minus_zero(m0);
1115     return res;
1116   } else {
1117     return HValue::InferRange(zone);
1118   }
1119 }
1120 
1121 
InferRange(Zone * zone)1122 Range* HDiv::InferRange(Zone* zone) {
1123   if (representation().IsInteger32()) {
1124     Range* result = new(zone) Range();
1125     if (left()->range()->CanBeMinusZero()) {
1126       result->set_can_be_minus_zero(true);
1127     }
1128 
1129     if (left()->range()->CanBeZero() && right()->range()->CanBeNegative()) {
1130       result->set_can_be_minus_zero(true);
1131     }
1132 
1133     if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
1134       SetFlag(HValue::kCanOverflow);
1135     }
1136 
1137     if (!right()->range()->CanBeZero()) {
1138       ClearFlag(HValue::kCanBeDivByZero);
1139     }
1140     return result;
1141   } else {
1142     return HValue::InferRange(zone);
1143   }
1144 }
1145 
1146 
InferRange(Zone * zone)1147 Range* HMod::InferRange(Zone* zone) {
1148   if (representation().IsInteger32()) {
1149     Range* a = left()->range();
1150     Range* result = new(zone) Range();
1151     if (a->CanBeMinusZero() || a->CanBeNegative()) {
1152       result->set_can_be_minus_zero(true);
1153     }
1154     if (!right()->range()->CanBeZero()) {
1155       ClearFlag(HValue::kCanBeDivByZero);
1156     }
1157     return result;
1158   } else {
1159     return HValue::InferRange(zone);
1160   }
1161 }
1162 
1163 
PrintTo(StringStream * stream)1164 void HPhi::PrintTo(StringStream* stream) {
1165   stream->Add("[");
1166   for (int i = 0; i < OperandCount(); ++i) {
1167     HValue* value = OperandAt(i);
1168     stream->Add(" ");
1169     value->PrintNameTo(stream);
1170     stream->Add(" ");
1171   }
1172   stream->Add(" uses%d_%di_%dd_%dt",
1173               UseCount(),
1174               int32_non_phi_uses() + int32_indirect_uses(),
1175               double_non_phi_uses() + double_indirect_uses(),
1176               tagged_non_phi_uses() + tagged_indirect_uses());
1177   stream->Add("%s%s]",
1178               is_live() ? "_live" : "",
1179               IsConvertibleToInteger() ? "" : "_ncti");
1180 }
1181 
1182 
AddInput(HValue * value)1183 void HPhi::AddInput(HValue* value) {
1184   inputs_.Add(NULL);
1185   SetOperandAt(OperandCount() - 1, value);
1186   // Mark phis that may have 'arguments' directly or indirectly as an operand.
1187   if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) {
1188     SetFlag(kIsArguments);
1189   }
1190 }
1191 
1192 
HasRealUses()1193 bool HPhi::HasRealUses() {
1194   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1195     if (!it.value()->IsPhi()) return true;
1196   }
1197   return false;
1198 }
1199 
1200 
GetRedundantReplacement()1201 HValue* HPhi::GetRedundantReplacement() {
1202   HValue* candidate = NULL;
1203   int count = OperandCount();
1204   int position = 0;
1205   while (position < count && candidate == NULL) {
1206     HValue* current = OperandAt(position++);
1207     if (current != this) candidate = current;
1208   }
1209   while (position < count) {
1210     HValue* current = OperandAt(position++);
1211     if (current != this && current != candidate) return NULL;
1212   }
1213   ASSERT(candidate != this);
1214   return candidate;
1215 }
1216 
1217 
DeleteFromGraph()1218 void HPhi::DeleteFromGraph() {
1219   ASSERT(block() != NULL);
1220   block()->RemovePhi(this);
1221   ASSERT(block() == NULL);
1222 }
1223 
1224 
InitRealUses(int phi_id)1225 void HPhi::InitRealUses(int phi_id) {
1226   // Initialize real uses.
1227   phi_id_ = phi_id;
1228   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1229     HValue* value = it.value();
1230     if (!value->IsPhi()) {
1231       Representation rep = value->RequiredInputRepresentation(it.index());
1232       non_phi_uses_[rep.kind()] += value->LoopWeight();
1233     }
1234   }
1235 }
1236 
1237 
AddNonPhiUsesFrom(HPhi * other)1238 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
1239   for (int i = 0; i < Representation::kNumRepresentations; i++) {
1240     indirect_uses_[i] += other->non_phi_uses_[i];
1241   }
1242 }
1243 
1244 
AddIndirectUsesTo(int * dest)1245 void HPhi::AddIndirectUsesTo(int* dest) {
1246   for (int i = 0; i < Representation::kNumRepresentations; i++) {
1247     dest[i] += indirect_uses_[i];
1248   }
1249 }
1250 
1251 
PrintDataTo(StringStream * stream)1252 void HSimulate::PrintDataTo(StringStream* stream) {
1253   stream->Add("id=%d", ast_id());
1254   if (pop_count_ > 0) stream->Add(" pop %d", pop_count_);
1255   if (values_.length() > 0) {
1256     if (pop_count_ > 0) stream->Add(" /");
1257     for (int i = 0; i < values_.length(); ++i) {
1258       if (i > 0) stream->Add(",");
1259       if (HasAssignedIndexAt(i)) {
1260         stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
1261       } else {
1262         stream->Add(" push ");
1263       }
1264       values_[i]->PrintNameTo(stream);
1265     }
1266   }
1267 }
1268 
1269 
PrintDataTo(StringStream * stream)1270 void HDeoptimize::PrintDataTo(StringStream* stream) {
1271   if (OperandCount() == 0) return;
1272   OperandAt(0)->PrintNameTo(stream);
1273   for (int i = 1; i < OperandCount(); ++i) {
1274     stream->Add(" ");
1275     OperandAt(i)->PrintNameTo(stream);
1276   }
1277 }
1278 
1279 
PrintDataTo(StringStream * stream)1280 void HEnterInlined::PrintDataTo(StringStream* stream) {
1281   SmartArrayPointer<char> name = function()->debug_name()->ToCString();
1282   stream->Add("%s, id=%d", *name, function()->id());
1283 }
1284 
1285 
HConstant(Handle<Object> handle,Representation r)1286 HConstant::HConstant(Handle<Object> handle, Representation r)
1287     : handle_(handle),
1288       has_int32_value_(false),
1289       has_double_value_(false),
1290       int32_value_(0),
1291       double_value_(0)  {
1292   set_representation(r);
1293   SetFlag(kUseGVN);
1294   if (handle_->IsNumber()) {
1295     double n = handle_->Number();
1296     double roundtrip_value = static_cast<double>(static_cast<int32_t>(n));
1297     has_int32_value_ = BitCast<int64_t>(roundtrip_value) == BitCast<int64_t>(n);
1298     if (has_int32_value_) int32_value_ = static_cast<int32_t>(n);
1299     double_value_ = n;
1300     has_double_value_ = true;
1301   }
1302 }
1303 
1304 
CopyToRepresentation(Representation r) const1305 HConstant* HConstant::CopyToRepresentation(Representation r) const {
1306   if (r.IsInteger32() && !has_int32_value_) return NULL;
1307   if (r.IsDouble() && !has_double_value_) return NULL;
1308   return new HConstant(handle_, r);
1309 }
1310 
1311 
CopyToTruncatedInt32() const1312 HConstant* HConstant::CopyToTruncatedInt32() const {
1313   if (!has_double_value_) return NULL;
1314   int32_t truncated = NumberToInt32(*handle_);
1315   return new HConstant(FACTORY->NewNumberFromInt(truncated),
1316                        Representation::Integer32());
1317 }
1318 
1319 
ToBoolean() const1320 bool HConstant::ToBoolean() const {
1321   // Converts the constant's boolean value according to
1322   // ECMAScript section 9.2 ToBoolean conversion.
1323   if (HasInteger32Value()) return Integer32Value() != 0;
1324   if (HasDoubleValue()) {
1325     double v = DoubleValue();
1326     return v != 0 && !isnan(v);
1327   }
1328   if (handle()->IsTrue()) return true;
1329   if (handle()->IsFalse()) return false;
1330   if (handle()->IsUndefined()) return false;
1331   if (handle()->IsNull()) return false;
1332   if (handle()->IsString() &&
1333       String::cast(*handle())->length() == 0) return false;
1334   return true;
1335 }
1336 
PrintDataTo(StringStream * stream)1337 void HConstant::PrintDataTo(StringStream* stream) {
1338   handle()->ShortPrint(stream);
1339 }
1340 
1341 
IsCopyOnWrite() const1342 bool HArrayLiteral::IsCopyOnWrite() const {
1343   if (!boilerplate_object_->IsJSObject()) return false;
1344   return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
1345       HEAP->fixed_cow_array_map();
1346 }
1347 
1348 
PrintDataTo(StringStream * stream)1349 void HBinaryOperation::PrintDataTo(StringStream* stream) {
1350   left()->PrintNameTo(stream);
1351   stream->Add(" ");
1352   right()->PrintNameTo(stream);
1353   if (CheckFlag(kCanOverflow)) stream->Add(" !");
1354   if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
1355 }
1356 
1357 
InferRange(Zone * zone)1358 Range* HBitwise::InferRange(Zone* zone) {
1359   if (op() == Token::BIT_XOR) return HValue::InferRange(zone);
1360   const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff);
1361   int32_t left_mask = (left()->range() != NULL)
1362       ? left()->range()->Mask()
1363       : kDefaultMask;
1364   int32_t right_mask = (right()->range() != NULL)
1365       ? right()->range()->Mask()
1366       : kDefaultMask;
1367   int32_t result_mask = (op() == Token::BIT_AND)
1368       ? left_mask & right_mask
1369       : left_mask | right_mask;
1370   return (result_mask >= 0)
1371       ? new(zone) Range(0, result_mask)
1372       : HValue::InferRange(zone);
1373 }
1374 
1375 
InferRange(Zone * zone)1376 Range* HSar::InferRange(Zone* zone) {
1377   if (right()->IsConstant()) {
1378     HConstant* c = HConstant::cast(right());
1379     if (c->HasInteger32Value()) {
1380       Range* result = (left()->range() != NULL)
1381           ? left()->range()->Copy(zone)
1382           : new(zone) Range();
1383       result->Sar(c->Integer32Value());
1384       result->set_can_be_minus_zero(false);
1385       return result;
1386     }
1387   }
1388   return HValue::InferRange(zone);
1389 }
1390 
1391 
InferRange(Zone * zone)1392 Range* HShr::InferRange(Zone* zone) {
1393   if (right()->IsConstant()) {
1394     HConstant* c = HConstant::cast(right());
1395     if (c->HasInteger32Value()) {
1396       int shift_count = c->Integer32Value() & 0x1f;
1397       if (left()->range()->CanBeNegative()) {
1398         // Only compute bounds if the result always fits into an int32.
1399         return (shift_count >= 1)
1400             ? new(zone) Range(0,
1401                               static_cast<uint32_t>(0xffffffff) >> shift_count)
1402             : new(zone) Range();
1403       } else {
1404         // For positive inputs we can use the >> operator.
1405         Range* result = (left()->range() != NULL)
1406             ? left()->range()->Copy(zone)
1407             : new(zone) Range();
1408         result->Sar(c->Integer32Value());
1409         result->set_can_be_minus_zero(false);
1410         return result;
1411       }
1412     }
1413   }
1414   return HValue::InferRange(zone);
1415 }
1416 
1417 
InferRange(Zone * zone)1418 Range* HShl::InferRange(Zone* zone) {
1419   if (right()->IsConstant()) {
1420     HConstant* c = HConstant::cast(right());
1421     if (c->HasInteger32Value()) {
1422       Range* result = (left()->range() != NULL)
1423           ? left()->range()->Copy(zone)
1424           : new(zone) Range();
1425       result->Shl(c->Integer32Value());
1426       result->set_can_be_minus_zero(false);
1427       return result;
1428     }
1429   }
1430   return HValue::InferRange(zone);
1431 }
1432 
1433 
InferRange(Zone * zone)1434 Range* HLoadKeyedSpecializedArrayElement::InferRange(Zone* zone) {
1435   switch (elements_kind()) {
1436     case EXTERNAL_PIXEL_ELEMENTS:
1437       return new(zone) Range(0, 255);
1438     case EXTERNAL_BYTE_ELEMENTS:
1439       return new(zone) Range(-128, 127);
1440     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1441       return new(zone) Range(0, 255);
1442     case EXTERNAL_SHORT_ELEMENTS:
1443       return new(zone) Range(-32768, 32767);
1444     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1445       return new(zone) Range(0, 65535);
1446     default:
1447       return HValue::InferRange(zone);
1448   }
1449 }
1450 
1451 
PrintDataTo(StringStream * stream)1452 void HCompareGeneric::PrintDataTo(StringStream* stream) {
1453   stream->Add(Token::Name(token()));
1454   stream->Add(" ");
1455   HBinaryOperation::PrintDataTo(stream);
1456 }
1457 
1458 
PrintDataTo(StringStream * stream)1459 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
1460   stream->Add(Token::Name(token()));
1461   stream->Add(" ");
1462   HControlInstruction::PrintDataTo(stream);
1463 }
1464 
1465 
PrintDataTo(StringStream * stream)1466 void HCompareIDAndBranch::PrintDataTo(StringStream* stream) {
1467   stream->Add(Token::Name(token()));
1468   stream->Add(" ");
1469   left()->PrintNameTo(stream);
1470   stream->Add(" ");
1471   right()->PrintNameTo(stream);
1472   HControlInstruction::PrintDataTo(stream);
1473 }
1474 
1475 
PrintDataTo(StringStream * stream)1476 void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
1477   left()->PrintNameTo(stream);
1478   stream->Add(" ");
1479   right()->PrintNameTo(stream);
1480   HControlInstruction::PrintDataTo(stream);
1481 }
1482 
1483 
PrintDataTo(StringStream * stream)1484 void HGoto::PrintDataTo(StringStream* stream) {
1485   stream->Add("B%d", SuccessorAt(0)->block_id());
1486 }
1487 
1488 
SetInputRepresentation(Representation r)1489 void HCompareIDAndBranch::SetInputRepresentation(Representation r) {
1490   input_representation_ = r;
1491   if (r.IsDouble()) {
1492     // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, ===
1493     // and !=) have special handling of undefined, e.g. undefined == undefined
1494     // is 'true'. Relational comparisons have a different semantic, first
1495     // calling ToPrimitive() on their arguments.  The standard Crankshaft
1496     // tagged-to-double conversion to ensure the HCompareIDAndBranch's inputs
1497     // are doubles caused 'undefined' to be converted to NaN. That's compatible
1498     // out-of-the box with ordered relational comparisons (<, >, <=,
1499     // >=). However, for equality comparisons (and for 'in' and 'instanceof'),
1500     // it is not consistent with the spec. For example, it would cause undefined
1501     // == undefined (should be true) to be evaluated as NaN == NaN
1502     // (false). Therefore, any comparisons other than ordered relational
1503     // comparisons must cause a deopt when one of their arguments is undefined.
1504     // See also v8:1434
1505     if (!Token::IsOrderedRelationalCompareOp(token_)) {
1506       SetFlag(kDeoptimizeOnUndefined);
1507     }
1508   } else {
1509     ASSERT(r.IsInteger32());
1510   }
1511 }
1512 
1513 
PrintDataTo(StringStream * stream)1514 void HParameter::PrintDataTo(StringStream* stream) {
1515   stream->Add("%u", index());
1516 }
1517 
1518 
PrintDataTo(StringStream * stream)1519 void HLoadNamedField::PrintDataTo(StringStream* stream) {
1520   object()->PrintNameTo(stream);
1521   stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1522 }
1523 
1524 
HLoadNamedFieldPolymorphic(HValue * context,HValue * object,SmallMapList * types,Handle<String> name)1525 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
1526                                                        HValue* object,
1527                                                        SmallMapList* types,
1528                                                        Handle<String> name)
1529     : types_(Min(types->length(), kMaxLoadPolymorphism)),
1530       name_(name),
1531       need_generic_(false) {
1532   SetOperandAt(0, context);
1533   SetOperandAt(1, object);
1534   set_representation(Representation::Tagged());
1535   SetGVNFlag(kDependsOnMaps);
1536   for (int i = 0;
1537        i < types->length() && types_.length() < kMaxLoadPolymorphism;
1538        ++i) {
1539     Handle<Map> map = types->at(i);
1540     LookupResult lookup(map->GetIsolate());
1541     map->LookupInDescriptors(NULL, *name, &lookup);
1542     if (lookup.IsFound()) {
1543       switch (lookup.type()) {
1544         case FIELD: {
1545           int index = lookup.GetLocalFieldIndexFromMap(*map);
1546           if (index < 0) {
1547             SetGVNFlag(kDependsOnInobjectFields);
1548           } else {
1549             SetGVNFlag(kDependsOnBackingStoreFields);
1550           }
1551           types_.Add(types->at(i));
1552           break;
1553         }
1554         case CONSTANT_FUNCTION:
1555           types_.Add(types->at(i));
1556           break;
1557         default:
1558           break;
1559       }
1560     }
1561   }
1562 
1563   if (types_.length() == types->length() && FLAG_deoptimize_uncommon_cases) {
1564     SetFlag(kUseGVN);
1565   } else {
1566     SetAllSideEffects();
1567     need_generic_ = true;
1568   }
1569 }
1570 
1571 
DataEquals(HValue * value)1572 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) {
1573   HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value);
1574   if (types_.length() != other->types()->length()) return false;
1575   if (!name_.is_identical_to(other->name())) return false;
1576   if (need_generic_ != other->need_generic_) return false;
1577   for (int i = 0; i < types_.length(); i++) {
1578     bool found = false;
1579     for (int j = 0; j < types_.length(); j++) {
1580       if (types_.at(j).is_identical_to(other->types()->at(i))) {
1581         found = true;
1582         break;
1583       }
1584     }
1585     if (!found) return false;
1586   }
1587   return true;
1588 }
1589 
1590 
PrintDataTo(StringStream * stream)1591 void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
1592   object()->PrintNameTo(stream);
1593   stream->Add(".");
1594   stream->Add(*String::cast(*name())->ToCString());
1595 }
1596 
1597 
PrintDataTo(StringStream * stream)1598 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
1599   object()->PrintNameTo(stream);
1600   stream->Add(".");
1601   stream->Add(*String::cast(*name())->ToCString());
1602 }
1603 
1604 
PrintDataTo(StringStream * stream)1605 void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
1606   object()->PrintNameTo(stream);
1607   stream->Add("[");
1608   key()->PrintNameTo(stream);
1609   stream->Add("]");
1610 }
1611 
1612 
RequiresHoleCheck()1613 bool HLoadKeyedFastElement::RequiresHoleCheck() {
1614   if (hole_check_mode_ == OMIT_HOLE_CHECK) {
1615     return false;
1616   }
1617 
1618   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1619     HValue* use = it.value();
1620     if (!use->IsChange()) return true;
1621   }
1622 
1623   return false;
1624 }
1625 
1626 
PrintDataTo(StringStream * stream)1627 void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1628   elements()->PrintNameTo(stream);
1629   stream->Add("[");
1630   key()->PrintNameTo(stream);
1631   stream->Add("]");
1632 }
1633 
1634 
PrintDataTo(StringStream * stream)1635 void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
1636   object()->PrintNameTo(stream);
1637   stream->Add("[");
1638   key()->PrintNameTo(stream);
1639   stream->Add("]");
1640 }
1641 
1642 
Canonicalize()1643 HValue* HLoadKeyedGeneric::Canonicalize() {
1644   // Recognize generic keyed loads that use property name generated
1645   // by for-in statement as a key and rewrite them into fast property load
1646   // by index.
1647   if (key()->IsLoadKeyedFastElement()) {
1648     HLoadKeyedFastElement* key_load = HLoadKeyedFastElement::cast(key());
1649     if (key_load->object()->IsForInCacheArray()) {
1650       HForInCacheArray* names_cache =
1651           HForInCacheArray::cast(key_load->object());
1652 
1653       if (names_cache->enumerable() == object()) {
1654         HForInCacheArray* index_cache =
1655             names_cache->index_cache();
1656         HCheckMapValue* map_check =
1657             new(block()->zone()) HCheckMapValue(object(), names_cache->map());
1658         HInstruction* index = new(block()->zone()) HLoadKeyedFastElement(
1659             index_cache,
1660             key_load->key(),
1661             HLoadKeyedFastElement::OMIT_HOLE_CHECK);
1662         HLoadFieldByIndex* load = new(block()->zone()) HLoadFieldByIndex(
1663             object(), index);
1664         map_check->InsertBefore(this);
1665         index->InsertBefore(this);
1666         load->InsertBefore(this);
1667         return load;
1668       }
1669     }
1670   }
1671 
1672   return this;
1673 }
1674 
1675 
PrintDataTo(StringStream * stream)1676 void HLoadKeyedSpecializedArrayElement::PrintDataTo(
1677     StringStream* stream) {
1678   external_pointer()->PrintNameTo(stream);
1679   stream->Add(".");
1680   switch (elements_kind()) {
1681     case EXTERNAL_BYTE_ELEMENTS:
1682       stream->Add("byte");
1683       break;
1684     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1685       stream->Add("u_byte");
1686       break;
1687     case EXTERNAL_SHORT_ELEMENTS:
1688       stream->Add("short");
1689       break;
1690     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1691       stream->Add("u_short");
1692       break;
1693     case EXTERNAL_INT_ELEMENTS:
1694       stream->Add("int");
1695       break;
1696     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
1697       stream->Add("u_int");
1698       break;
1699     case EXTERNAL_FLOAT_ELEMENTS:
1700       stream->Add("float");
1701       break;
1702     case EXTERNAL_DOUBLE_ELEMENTS:
1703       stream->Add("double");
1704       break;
1705     case EXTERNAL_PIXEL_ELEMENTS:
1706       stream->Add("pixel");
1707       break;
1708     case FAST_ELEMENTS:
1709     case FAST_SMI_ONLY_ELEMENTS:
1710     case FAST_DOUBLE_ELEMENTS:
1711     case DICTIONARY_ELEMENTS:
1712     case NON_STRICT_ARGUMENTS_ELEMENTS:
1713       UNREACHABLE();
1714       break;
1715   }
1716   stream->Add("[");
1717   key()->PrintNameTo(stream);
1718   stream->Add("]");
1719 }
1720 
1721 
PrintDataTo(StringStream * stream)1722 void HStoreNamedGeneric::PrintDataTo(StringStream* stream) {
1723   object()->PrintNameTo(stream);
1724   stream->Add(".");
1725   ASSERT(name()->IsString());
1726   stream->Add(*String::cast(*name())->ToCString());
1727   stream->Add(" = ");
1728   value()->PrintNameTo(stream);
1729 }
1730 
1731 
PrintDataTo(StringStream * stream)1732 void HStoreNamedField::PrintDataTo(StringStream* stream) {
1733   object()->PrintNameTo(stream);
1734   stream->Add(".");
1735   stream->Add(*String::cast(*name())->ToCString());
1736   stream->Add(" = ");
1737   value()->PrintNameTo(stream);
1738   stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
1739   if (!transition().is_null()) {
1740     stream->Add(" (transition map %p)", *transition());
1741   }
1742 }
1743 
1744 
PrintDataTo(StringStream * stream)1745 void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
1746   object()->PrintNameTo(stream);
1747   stream->Add("[");
1748   key()->PrintNameTo(stream);
1749   stream->Add("] = ");
1750   value()->PrintNameTo(stream);
1751 }
1752 
1753 
PrintDataTo(StringStream * stream)1754 void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
1755   elements()->PrintNameTo(stream);
1756   stream->Add("[");
1757   key()->PrintNameTo(stream);
1758   stream->Add("] = ");
1759   value()->PrintNameTo(stream);
1760 }
1761 
1762 
PrintDataTo(StringStream * stream)1763 void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
1764   object()->PrintNameTo(stream);
1765   stream->Add("[");
1766   key()->PrintNameTo(stream);
1767   stream->Add("] = ");
1768   value()->PrintNameTo(stream);
1769 }
1770 
1771 
PrintDataTo(StringStream * stream)1772 void HStoreKeyedSpecializedArrayElement::PrintDataTo(
1773     StringStream* stream) {
1774   external_pointer()->PrintNameTo(stream);
1775   stream->Add(".");
1776   switch (elements_kind()) {
1777     case EXTERNAL_BYTE_ELEMENTS:
1778       stream->Add("byte");
1779       break;
1780     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
1781       stream->Add("u_byte");
1782       break;
1783     case EXTERNAL_SHORT_ELEMENTS:
1784       stream->Add("short");
1785       break;
1786     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
1787       stream->Add("u_short");
1788       break;
1789     case EXTERNAL_INT_ELEMENTS:
1790       stream->Add("int");
1791       break;
1792     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
1793       stream->Add("u_int");
1794       break;
1795     case EXTERNAL_FLOAT_ELEMENTS:
1796       stream->Add("float");
1797       break;
1798     case EXTERNAL_DOUBLE_ELEMENTS:
1799       stream->Add("double");
1800       break;
1801     case EXTERNAL_PIXEL_ELEMENTS:
1802       stream->Add("pixel");
1803       break;
1804     case FAST_SMI_ONLY_ELEMENTS:
1805     case FAST_ELEMENTS:
1806     case FAST_DOUBLE_ELEMENTS:
1807     case DICTIONARY_ELEMENTS:
1808     case NON_STRICT_ARGUMENTS_ELEMENTS:
1809       UNREACHABLE();
1810       break;
1811   }
1812   stream->Add("[");
1813   key()->PrintNameTo(stream);
1814   stream->Add("] = ");
1815   value()->PrintNameTo(stream);
1816 }
1817 
1818 
PrintDataTo(StringStream * stream)1819 void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
1820   object()->PrintNameTo(stream);
1821   stream->Add(" %p -> %p", *original_map(), *transitioned_map());
1822 }
1823 
1824 
PrintDataTo(StringStream * stream)1825 void HLoadGlobalCell::PrintDataTo(StringStream* stream) {
1826   stream->Add("[%p]", *cell());
1827   if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
1828   if (details_.IsReadOnly()) stream->Add(" (read-only)");
1829 }
1830 
1831 
RequiresHoleCheck()1832 bool HLoadGlobalCell::RequiresHoleCheck() {
1833   if (details_.IsDontDelete() && !details_.IsReadOnly()) return false;
1834   for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
1835     HValue* use = it.value();
1836     if (!use->IsChange()) return true;
1837   }
1838   return false;
1839 }
1840 
1841 
PrintDataTo(StringStream * stream)1842 void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
1843   stream->Add("%o ", *name());
1844 }
1845 
1846 
PrintDataTo(StringStream * stream)1847 void HStoreGlobalCell::PrintDataTo(StringStream* stream) {
1848   stream->Add("[%p] = ", *cell());
1849   value()->PrintNameTo(stream);
1850   if (!details_.IsDontDelete()) stream->Add(" (deleteable)");
1851   if (details_.IsReadOnly()) stream->Add(" (read-only)");
1852 }
1853 
1854 
PrintDataTo(StringStream * stream)1855 void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
1856   stream->Add("%o = ", *name());
1857   value()->PrintNameTo(stream);
1858 }
1859 
1860 
PrintDataTo(StringStream * stream)1861 void HLoadContextSlot::PrintDataTo(StringStream* stream) {
1862   value()->PrintNameTo(stream);
1863   stream->Add("[%d]", slot_index());
1864 }
1865 
1866 
PrintDataTo(StringStream * stream)1867 void HStoreContextSlot::PrintDataTo(StringStream* stream) {
1868   context()->PrintNameTo(stream);
1869   stream->Add("[%d] = ", slot_index());
1870   value()->PrintNameTo(stream);
1871 }
1872 
1873 
1874 // Implementation of type inference and type conversions. Calculates
1875 // the inferred type of this instruction based on the input operands.
1876 
CalculateInferredType()1877 HType HValue::CalculateInferredType() {
1878   return type_;
1879 }
1880 
1881 
CalculateInferredType()1882 HType HCheckMap::CalculateInferredType() {
1883   return value()->type();
1884 }
1885 
1886 
CalculateInferredType()1887 HType HCheckFunction::CalculateInferredType() {
1888   return value()->type();
1889 }
1890 
1891 
CalculateInferredType()1892 HType HCheckNonSmi::CalculateInferredType() {
1893   // TODO(kasperl): Is there any way to signal that this isn't a smi?
1894   return HType::Tagged();
1895 }
1896 
1897 
CalculateInferredType()1898 HType HCheckSmi::CalculateInferredType() {
1899   return HType::Smi();
1900 }
1901 
1902 
CalculateInferredType()1903 HType HPhi::CalculateInferredType() {
1904   HType result = HType::Uninitialized();
1905   for (int i = 0; i < OperandCount(); ++i) {
1906     HType current = OperandAt(i)->type();
1907     result = result.Combine(current);
1908   }
1909   return result;
1910 }
1911 
1912 
CalculateInferredType()1913 HType HConstant::CalculateInferredType() {
1914   return HType::TypeFromValue(handle_);
1915 }
1916 
1917 
CalculateInferredType()1918 HType HCompareGeneric::CalculateInferredType() {
1919   return HType::Boolean();
1920 }
1921 
1922 
CalculateInferredType()1923 HType HInstanceOf::CalculateInferredType() {
1924   return HType::Boolean();
1925 }
1926 
1927 
CalculateInferredType()1928 HType HDeleteProperty::CalculateInferredType() {
1929   return HType::Boolean();
1930 }
1931 
1932 
CalculateInferredType()1933 HType HInstanceOfKnownGlobal::CalculateInferredType() {
1934   return HType::Boolean();
1935 }
1936 
1937 
CalculateInferredType()1938 HType HChange::CalculateInferredType() {
1939   if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
1940   return type();
1941 }
1942 
1943 
CalculateInferredType()1944 HType HBitwiseBinaryOperation::CalculateInferredType() {
1945   return HType::TaggedNumber();
1946 }
1947 
1948 
CalculateInferredType()1949 HType HArithmeticBinaryOperation::CalculateInferredType() {
1950   return HType::TaggedNumber();
1951 }
1952 
1953 
CalculateInferredType()1954 HType HAdd::CalculateInferredType() {
1955   return HType::Tagged();
1956 }
1957 
1958 
CalculateInferredType()1959 HType HBitNot::CalculateInferredType() {
1960   return HType::TaggedNumber();
1961 }
1962 
1963 
CalculateInferredType()1964 HType HUnaryMathOperation::CalculateInferredType() {
1965   return HType::TaggedNumber();
1966 }
1967 
1968 
CalculateInferredType()1969 HType HStringCharFromCode::CalculateInferredType() {
1970   return HType::String();
1971 }
1972 
1973 
CalculateInferredType()1974 HType HAllocateObject::CalculateInferredType() {
1975   return HType::JSObject();
1976 }
1977 
1978 
CalculateInferredType()1979 HType HFastLiteral::CalculateInferredType() {
1980   // TODO(mstarzinger): Be smarter, could also be JSArray here.
1981   return HType::JSObject();
1982 }
1983 
1984 
CalculateInferredType()1985 HType HArrayLiteral::CalculateInferredType() {
1986   return HType::JSArray();
1987 }
1988 
1989 
CalculateInferredType()1990 HType HObjectLiteral::CalculateInferredType() {
1991   return HType::JSObject();
1992 }
1993 
1994 
CalculateInferredType()1995 HType HRegExpLiteral::CalculateInferredType() {
1996   return HType::JSObject();
1997 }
1998 
1999 
CalculateInferredType()2000 HType HFunctionLiteral::CalculateInferredType() {
2001   return HType::JSObject();
2002 }
2003 
2004 
EnsureAndPropagateNotMinusZero(BitVector * visited)2005 HValue* HUnaryMathOperation::EnsureAndPropagateNotMinusZero(
2006     BitVector* visited) {
2007   visited->Add(id());
2008   if (representation().IsInteger32() &&
2009       !value()->representation().IsInteger32()) {
2010     if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2011       SetFlag(kBailoutOnMinusZero);
2012     }
2013   }
2014   if (RequiredInputRepresentation(0).IsInteger32() &&
2015       representation().IsInteger32()) {
2016     return value();
2017   }
2018   return NULL;
2019 }
2020 
2021 
2022 
EnsureAndPropagateNotMinusZero(BitVector * visited)2023 HValue* HChange::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2024   visited->Add(id());
2025   if (from().IsInteger32()) return NULL;
2026   if (CanTruncateToInt32()) return NULL;
2027   if (value()->range() == NULL || value()->range()->CanBeMinusZero()) {
2028     SetFlag(kBailoutOnMinusZero);
2029   }
2030   ASSERT(!from().IsInteger32() || !to().IsInteger32());
2031   return NULL;
2032 }
2033 
2034 
EnsureAndPropagateNotMinusZero(BitVector * visited)2035 HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
2036     BitVector* visited) {
2037   visited->Add(id());
2038   return value();
2039 }
2040 
2041 
EnsureAndPropagateNotMinusZero(BitVector * visited)2042 HValue* HMod::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2043   visited->Add(id());
2044   if (range() == NULL || range()->CanBeMinusZero()) {
2045     SetFlag(kBailoutOnMinusZero);
2046     return left();
2047   }
2048   return NULL;
2049 }
2050 
2051 
EnsureAndPropagateNotMinusZero(BitVector * visited)2052 HValue* HDiv::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2053   visited->Add(id());
2054   if (range() == NULL || range()->CanBeMinusZero()) {
2055     SetFlag(kBailoutOnMinusZero);
2056   }
2057   return NULL;
2058 }
2059 
2060 
EnsureAndPropagateNotMinusZero(BitVector * visited)2061 HValue* HMul::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2062   visited->Add(id());
2063   if (range() == NULL || range()->CanBeMinusZero()) {
2064     SetFlag(kBailoutOnMinusZero);
2065   }
2066   return NULL;
2067 }
2068 
2069 
EnsureAndPropagateNotMinusZero(BitVector * visited)2070 HValue* HSub::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2071   visited->Add(id());
2072   // Propagate to the left argument. If the left argument cannot be -0, then
2073   // the result of the add operation cannot be either.
2074   if (range() == NULL || range()->CanBeMinusZero()) {
2075     return left();
2076   }
2077   return NULL;
2078 }
2079 
2080 
EnsureAndPropagateNotMinusZero(BitVector * visited)2081 HValue* HAdd::EnsureAndPropagateNotMinusZero(BitVector* visited) {
2082   visited->Add(id());
2083   // Propagate to the left argument. If the left argument cannot be -0, then
2084   // the result of the sub operation cannot be either.
2085   if (range() == NULL || range()->CanBeMinusZero()) {
2086     return left();
2087   }
2088   return NULL;
2089 }
2090 
2091 
2092 #define H_CONSTANT_INT32(val)                                                  \
2093 new(zone) HConstant(FACTORY->NewNumberFromInt(val, TENURED),                   \
2094                     Representation::Integer32())
2095 #define H_CONSTANT_DOUBLE(val)                                                 \
2096 new(zone) HConstant(FACTORY->NewNumber(val, TENURED),                          \
2097                     Representation::Double())
2098 
2099 #define DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HInstr, op)                       \
2100 HInstruction* HInstr::New##HInstr(Zone* zone,                                  \
2101                                   HValue* context,                             \
2102                                   HValue* left,                                \
2103                                   HValue* right) {                             \
2104   if (left->IsConstant() && right->IsConstant()) {                             \
2105     HConstant* c_left = HConstant::cast(left);                                 \
2106     HConstant* c_right = HConstant::cast(right);                               \
2107     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
2108       double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
2109       if (TypeInfo::IsInt32Double(double_res)) {                               \
2110         return H_CONSTANT_INT32(static_cast<int32_t>(double_res));             \
2111       }                                                                        \
2112       return H_CONSTANT_DOUBLE(double_res);                                    \
2113     }                                                                          \
2114   }                                                                            \
2115   return new(zone) HInstr(context, left, right);                               \
2116 }
2117 
2118 
2119 DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HAdd, +)
2120 DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HMul, *)
2121 DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
2122 
2123 #undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
2124 
2125 
NewHMod(Zone * zone,HValue * context,HValue * left,HValue * right)2126 HInstruction* HMod::NewHMod(Zone* zone,
2127                             HValue* context,
2128                             HValue* left,
2129                             HValue* right) {
2130   if (left->IsConstant() && right->IsConstant()) {
2131     HConstant* c_left = HConstant::cast(left);
2132     HConstant* c_right = HConstant::cast(right);
2133     if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
2134       int32_t dividend = c_left->Integer32Value();
2135       int32_t divisor = c_right->Integer32Value();
2136       if (divisor != 0) {
2137         int32_t res = dividend % divisor;
2138         if ((res == 0) && (dividend < 0)) {
2139           return H_CONSTANT_DOUBLE(-0.0);
2140         }
2141         return H_CONSTANT_INT32(res);
2142       }
2143     }
2144   }
2145   return new(zone) HMod(context, left, right);
2146 }
2147 
2148 
NewHDiv(Zone * zone,HValue * context,HValue * left,HValue * right)2149 HInstruction* HDiv::NewHDiv(Zone* zone,
2150                             HValue* context,
2151                             HValue* left,
2152                             HValue* right) {
2153   // If left and right are constant values, try to return a constant value.
2154   if (left->IsConstant() && right->IsConstant()) {
2155     HConstant* c_left = HConstant::cast(left);
2156     HConstant* c_right = HConstant::cast(right);
2157     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2158       if (c_right->DoubleValue() != 0) {
2159         double double_res = c_left->DoubleValue() / c_right->DoubleValue();
2160         if (TypeInfo::IsInt32Double(double_res)) {
2161           return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
2162         }
2163         return H_CONSTANT_DOUBLE(double_res);
2164       }
2165     }
2166   }
2167   return new(zone) HDiv(context, left, right);
2168 }
2169 
2170 
NewHBitwise(Zone * zone,Token::Value op,HValue * context,HValue * left,HValue * right)2171 HInstruction* HBitwise::NewHBitwise(Zone* zone,
2172                                     Token::Value op,
2173                                     HValue* context,
2174                                     HValue* left,
2175                                     HValue* right) {
2176   if (left->IsConstant() && right->IsConstant()) {
2177     HConstant* c_left = HConstant::cast(left);
2178     HConstant* c_right = HConstant::cast(right);
2179     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2180       int32_t result;
2181       int32_t v_left = c_left->NumberValueAsInteger32();
2182       int32_t v_right = c_right->NumberValueAsInteger32();
2183       switch (op) {
2184         case Token::BIT_XOR:
2185           result = v_left ^ v_right;
2186           break;
2187         case Token::BIT_AND:
2188           result = v_left & v_right;
2189           break;
2190         case Token::BIT_OR:
2191           result = v_left | v_right;
2192           break;
2193         default:
2194           result = 0;  // Please the compiler.
2195           UNREACHABLE();
2196       }
2197       return H_CONSTANT_INT32(result);
2198     }
2199   }
2200   return new(zone) HBitwise(op, context, left, right);
2201 }
2202 
2203 
2204 #define DEFINE_NEW_H_BITWISE_INSTR(HInstr, result)                             \
2205 HInstruction* HInstr::New##HInstr(Zone* zone,                                  \
2206                                   HValue* context,                             \
2207                                   HValue* left,                                \
2208                                   HValue* right) {                             \
2209   if (left->IsConstant() && right->IsConstant()) {                             \
2210     HConstant* c_left = HConstant::cast(left);                                 \
2211     HConstant* c_right = HConstant::cast(right);                               \
2212     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
2213       return H_CONSTANT_INT32(result);                                         \
2214     }                                                                          \
2215   }                                                                            \
2216   return new(zone) HInstr(context, left, right);                               \
2217 }
2218 
2219 
2220 DEFINE_NEW_H_BITWISE_INSTR(HSar,
2221 c_left->NumberValueAsInteger32() >> (c_right->NumberValueAsInteger32() & 0x1f))
2222 DEFINE_NEW_H_BITWISE_INSTR(HShl,
2223 c_left->NumberValueAsInteger32() << (c_right->NumberValueAsInteger32() & 0x1f))
2224 
2225 #undef DEFINE_NEW_H_BITWISE_INSTR
2226 
2227 
NewHShr(Zone * zone,HValue * context,HValue * left,HValue * right)2228 HInstruction* HShr::NewHShr(Zone* zone,
2229                             HValue* context,
2230                             HValue* left,
2231                             HValue* right) {
2232   if (left->IsConstant() && right->IsConstant()) {
2233     HConstant* c_left = HConstant::cast(left);
2234     HConstant* c_right = HConstant::cast(right);
2235     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
2236       int32_t left_val = c_left->NumberValueAsInteger32();
2237       int32_t right_val = c_right->NumberValueAsInteger32() & 0x1f;
2238       if ((right_val == 0) && (left_val < 0)) {
2239         return H_CONSTANT_DOUBLE(
2240             static_cast<double>(static_cast<uint32_t>(left_val)));
2241       }
2242       return H_CONSTANT_INT32(static_cast<uint32_t>(left_val) >> right_val);
2243     }
2244   }
2245   return new(zone) HShr(context, left, right);
2246 }
2247 
2248 
2249 #undef H_CONSTANT_INT32
2250 #undef H_CONSTANT_DOUBLE
2251 
2252 
PrintDataTo(StringStream * stream)2253 void HIn::PrintDataTo(StringStream* stream) {
2254   key()->PrintNameTo(stream);
2255   stream->Add(" ");
2256   object()->PrintNameTo(stream);
2257 }
2258 
2259 
InferredRepresentation()2260 Representation HPhi::InferredRepresentation() {
2261   bool double_occurred = false;
2262   bool int32_occurred = false;
2263   for (int i = 0; i < OperandCount(); ++i) {
2264     HValue* value = OperandAt(i);
2265     if (value->IsUnknownOSRValue()) {
2266       HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value();
2267       if (hint_value != NULL) {
2268         Representation hint = hint_value->representation();
2269         if (hint.IsDouble()) double_occurred = true;
2270         if (hint.IsInteger32()) int32_occurred = true;
2271       }
2272       continue;
2273     }
2274     if (value->representation().IsDouble()) double_occurred = true;
2275     if (value->representation().IsInteger32()) int32_occurred = true;
2276     if (value->representation().IsTagged()) {
2277       if (value->IsConstant()) {
2278         HConstant* constant = HConstant::cast(value);
2279         if (constant->IsConvertibleToInteger()) {
2280           int32_occurred = true;
2281         } else if (constant->HasNumberValue()) {
2282           double_occurred = true;
2283         } else {
2284           return Representation::Tagged();
2285         }
2286       } else {
2287         return Representation::Tagged();
2288       }
2289     }
2290   }
2291 
2292   if (double_occurred) return Representation::Double();
2293 
2294   if (int32_occurred) return Representation::Integer32();
2295 
2296   return Representation::None();
2297 }
2298 
2299 
2300 // Node-specific verification code is only included in debug mode.
2301 #ifdef DEBUG
2302 
Verify()2303 void HPhi::Verify() {
2304   ASSERT(OperandCount() == block()->predecessors()->length());
2305   for (int i = 0; i < OperandCount(); ++i) {
2306     HValue* value = OperandAt(i);
2307     HBasicBlock* defining_block = value->block();
2308     HBasicBlock* predecessor_block = block()->predecessors()->at(i);
2309     ASSERT(defining_block == predecessor_block ||
2310            defining_block->Dominates(predecessor_block));
2311   }
2312 }
2313 
2314 
Verify()2315 void HSimulate::Verify() {
2316   HInstruction::Verify();
2317   ASSERT(HasAstId());
2318 }
2319 
2320 
Verify()2321 void HCheckSmi::Verify() {
2322   HInstruction::Verify();
2323   ASSERT(HasNoUses());
2324 }
2325 
2326 
Verify()2327 void HCheckNonSmi::Verify() {
2328   HInstruction::Verify();
2329   ASSERT(HasNoUses());
2330 }
2331 
2332 
Verify()2333 void HCheckFunction::Verify() {
2334   HInstruction::Verify();
2335   ASSERT(HasNoUses());
2336 }
2337 
2338 
Verify()2339 void HCheckPrototypeMaps::Verify() {
2340   HInstruction::Verify();
2341   ASSERT(HasNoUses());
2342 }
2343 
2344 #endif
2345 
2346 } }  // namespace v8::internal
2347