Home | History | Annotate | Download | only in src
      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   }
     52 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 
     70 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 
     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 
     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 
    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 
    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 
    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 
    119 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    215 void Range::Verify() const {
    216   ASSERT(lower_ <= upper_);
    217 }
    218 #endif
    219 
    220 
    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 
    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 
    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 
    274 bool HValue::IsDefinedAfter(HBasicBlock* other) const {
    275   return block()->block_id() > other->block_id();
    276 }
    277 
    278 
    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 
    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 
    296 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
    297   Advance();
    298 }
    299 
    300 
    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 
    311 int HValue::UseCount() const {
    312   int count = 0;
    313   for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count;
    314   return count;
    315 }
    316 
    317 
    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 
    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 
    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 
    373 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 
    384 void HValue::SetOperandAt(int index, HValue* value) {
    385   RegisterUse(index, value);
    386   InternalSetOperandAt(index, value);
    387 }
    388 
    389 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    472 void HValue::PrintNameTo(StringStream* stream) {
    473   stream->Add("%s%d", representation_.Mnemonic(), id());
    474 }
    475 
    476 
    477 bool HValue::UpdateInferredType() {
    478   HType type = CalculateInferredType();
    479   bool result = (!type.Equals(type_));
    480   type_ = type;
    481   return result;
    482 }
    483 
    484 
    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 
    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 
    515 void HValue::RemoveLastAddedRange() {
    516   ASSERT(HasRange());
    517   ASSERT(range_->next() != NULL);
    518   range_ = range_->next();
    519 }
    520 
    521 
    522 void HValue::ComputeInitialRange(Zone* zone) {
    523   ASSERT(!HasRange());
    524   range_ = InferRange(zone);
    525   ASSERT(HasRange());
    526 }
    527 
    528 
    529 void HInstruction::PrintTo(StringStream* stream) {
    530   PrintMnemonicTo(stream);
    531   PrintDataTo(stream);
    532   PrintRangeTo(stream);
    533   PrintChangesTo(stream);
    534   PrintTypeTo(stream);
    535 }
    536 
    537 
    538 void HInstruction::PrintMnemonicTo(StringStream* stream) {
    539   stream->Add("%s ", Mnemonic());
    540 }
    541 
    542 
    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 
    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 
    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
    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 
    643 void HUnaryCall::PrintDataTo(StringStream* stream) {
    644   value()->PrintNameTo(stream);
    645   stream->Add(" ");
    646   stream->Add("#%d", argument_count());
    647 }
    648 
    649 
    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 
    659 void HBoundsCheck::PrintDataTo(StringStream* stream) {
    660   index()->PrintNameTo(stream);
    661   stream->Add(" ");
    662   length()->PrintNameTo(stream);
    663 }
    664 
    665 
    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 
    676 void HCallNamed::PrintDataTo(StringStream* stream) {
    677   stream->Add("%o ", *name());
    678   HUnaryCall::PrintDataTo(stream);
    679 }
    680 
    681 
    682 void HCallGlobal::PrintDataTo(StringStream* stream) {
    683   stream->Add("%o ", *name());
    684   HUnaryCall::PrintDataTo(stream);
    685 }
    686 
    687 
    688 void HCallKnownGlobal::PrintDataTo(StringStream* stream) {
    689   stream->Add("o ", target()->shared()->DebugName());
    690   stream->Add("#%d", argument_count());
    691 }
    692 
    693 
    694 void HCallRuntime::PrintDataTo(StringStream* stream) {
    695   stream->Add("%o ", *name());
    696   stream->Add("#%d", argument_count());
    697 }
    698 
    699 
    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 
    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 
    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 
    727 void HUnaryControlInstruction::PrintDataTo(StringStream* stream) {
    728   value()->PrintNameTo(stream);
    729   HControlInstruction::PrintDataTo(stream);
    730 }
    731 
    732 
    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 
    741 void HReturn::PrintDataTo(StringStream* stream) {
    742   value()->PrintNameTo(stream);
    743 }
    744 
    745 
    746 void HCompareMap::PrintDataTo(StringStream* stream) {
    747   value()->PrintNameTo(stream);
    748   stream->Add(" (%p)", *map());
    749   HControlInstruction::PrintDataTo(stream);
    750 }
    751 
    752 
    753 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 
    774 void HUnaryMathOperation::PrintDataTo(StringStream* stream) {
    775   const char* name = OpName();
    776   stream->Add("%s ", name);
    777   value()->PrintNameTo(stream);
    778 }
    779 
    780 
    781 void HUnaryOperation::PrintDataTo(StringStream* stream) {
    782   value()->PrintNameTo(stream);
    783 }
    784 
    785 
    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 
    807 void HTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
    808   value()->PrintNameTo(stream);
    809   stream->Add(" == %o", *type_literal_);
    810   HControlInstruction::PrintDataTo(stream);
    811 }
    812 
    813 
    814 void HCheckMapValue::PrintDataTo(StringStream* stream) {
    815   value()->PrintNameTo(stream);
    816   stream->Add(" ");
    817   map()->PrintNameTo(stream);
    818 }
    819 
    820 
    821 void HForInPrepareMap::PrintDataTo(StringStream* stream) {
    822   enumerable()->PrintNameTo(stream);
    823 }
    824 
    825 
    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 
    834 void HLoadFieldByIndex::PrintDataTo(StringStream* stream) {
    835   object()->PrintNameTo(stream);
    836   stream->Add(" ");
    837   index()->PrintNameTo(stream);
    838 }
    839 
    840 
    841 HValue* HConstant::Canonicalize() {
    842   return HasNoUses() ? NULL : this;
    843 }
    844 
    845 
    846 HValue* HTypeof::Canonicalize() {
    847   return HasNoUses() ? NULL : this;
    848 }
    849 
    850 
    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 
    869 HValue* HAdd::Canonicalize() {
    870   if (!representation().IsInteger32()) return this;
    871   if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
    872   return this;
    873 }
    874 
    875 
    876 HValue* HSub::Canonicalize() {
    877   if (!representation().IsInteger32()) return this;
    878   if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
    879   return this;
    880 }
    881 
    882 
    883 HValue* HChange::Canonicalize() {
    884   return (from().Equals(to())) ? value() : this;
    885 }
    886 
    887 
    888 HValue* HWrapReceiver::Canonicalize() {
    889   if (HasNoUses()) return NULL;
    890   if (receiver()->type().IsJSObject()) {
    891     return receiver();
    892   }
    893   return this;
    894 }
    895 
    896 
    897 void HTypeof::PrintDataTo(StringStream* stream) {
    898   value()->PrintNameTo(stream);
    899 }
    900 
    901 
    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 
    912 void HJSArrayLength::PrintDataTo(StringStream* stream) {
    913   value()->PrintNameTo(stream);
    914   stream->Add(" ");
    915   typecheck()->PrintNameTo(stream);
    916 }
    917 
    918 
    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 
    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 
    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 
    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 
    981 void HCheckFunction::PrintDataTo(StringStream* stream) {
    982   value()->PrintNameTo(stream);
    983   stream->Add(" %p", *target());
    984 }
    985 
    986 
    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 
    998 void HCheckInstanceType::PrintDataTo(StringStream* stream) {
    999   stream->Add("%s ", GetCheckName());
   1000   HUnaryOperation::PrintDataTo(stream);
   1001 }
   1002 
   1003 
   1004 void HCallStub::PrintDataTo(StringStream* stream) {
   1005   stream->Add("%s ",
   1006               CodeStub::MajorName(major_key_, false));
   1007   HUnaryCall::PrintDataTo(stream);
   1008 }
   1009 
   1010 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1218 void HPhi::DeleteFromGraph() {
   1219   ASSERT(block() != NULL);
   1220   block()->RemovePhi(this);
   1221   ASSERT(block() == NULL);
   1222 }
   1223 
   1224 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1305 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 
   1312 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 
   1320 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 
   1337 void HConstant::PrintDataTo(StringStream* stream) {
   1338   handle()->ShortPrint(stream);
   1339 }
   1340 
   1341 
   1342 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 
   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 
   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 
   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 
   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 
   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 
   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 
   1452 void HCompareGeneric::PrintDataTo(StringStream* stream) {
   1453   stream->Add(Token::Name(token()));
   1454   stream->Add(" ");
   1455   HBinaryOperation::PrintDataTo(stream);
   1456 }
   1457 
   1458 
   1459 void HStringCompareAndBranch::PrintDataTo(StringStream* stream) {
   1460   stream->Add(Token::Name(token()));
   1461   stream->Add(" ");
   1462   HControlInstruction::PrintDataTo(stream);
   1463 }
   1464 
   1465 
   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 
   1476 void HCompareObjectEqAndBranch::PrintDataTo(StringStream* stream) {
   1477   left()->PrintNameTo(stream);
   1478   stream->Add(" ");
   1479   right()->PrintNameTo(stream);
   1480   HControlInstruction::PrintDataTo(stream);
   1481 }
   1482 
   1483 
   1484 void HGoto::PrintDataTo(StringStream* stream) {
   1485   stream->Add("B%d", SuccessorAt(0)->block_id());
   1486 }
   1487 
   1488 
   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 
   1514 void HParameter::PrintDataTo(StringStream* stream) {
   1515   stream->Add("%u", index());
   1516 }
   1517 
   1518 
   1519 void HLoadNamedField::PrintDataTo(StringStream* stream) {
   1520   object()->PrintNameTo(stream);
   1521   stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
   1522 }
   1523 
   1524 
   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 
   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 
   1591 void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) {
   1592   object()->PrintNameTo(stream);
   1593   stream->Add(".");
   1594   stream->Add(*String::cast(*name())->ToCString());
   1595 }
   1596 
   1597 
   1598 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
   1599   object()->PrintNameTo(stream);
   1600   stream->Add(".");
   1601   stream->Add(*String::cast(*name())->ToCString());
   1602 }
   1603 
   1604 
   1605 void HLoadKeyedFastElement::PrintDataTo(StringStream* stream) {
   1606   object()->PrintNameTo(stream);
   1607   stream->Add("[");
   1608   key()->PrintNameTo(stream);
   1609   stream->Add("]");
   1610 }
   1611 
   1612 
   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 
   1627 void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
   1628   elements()->PrintNameTo(stream);
   1629   stream->Add("[");
   1630   key()->PrintNameTo(stream);
   1631   stream->Add("]");
   1632 }
   1633 
   1634 
   1635 void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
   1636   object()->PrintNameTo(stream);
   1637   stream->Add("[");
   1638   key()->PrintNameTo(stream);
   1639   stream->Add("]");
   1640 }
   1641 
   1642 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   1819 void HTransitionElementsKind::PrintDataTo(StringStream* stream) {
   1820   object()->PrintNameTo(stream);
   1821   stream->Add(" %p -> %p", *original_map(), *transitioned_map());
   1822 }
   1823 
   1824 
   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 
   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 
   1842 void HLoadGlobalGeneric::PrintDataTo(StringStream* stream) {
   1843   stream->Add("%o ", *name());
   1844 }
   1845 
   1846 
   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 
   1855 void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
   1856   stream->Add("%o = ", *name());
   1857   value()->PrintNameTo(stream);
   1858 }
   1859 
   1860 
   1861 void HLoadContextSlot::PrintDataTo(StringStream* stream) {
   1862   value()->PrintNameTo(stream);
   1863   stream->Add("[%d]", slot_index());
   1864 }
   1865 
   1866 
   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 
   1877 HType HValue::CalculateInferredType() {
   1878   return type_;
   1879 }
   1880 
   1881 
   1882 HType HCheckMap::CalculateInferredType() {
   1883   return value()->type();
   1884 }
   1885 
   1886 
   1887 HType HCheckFunction::CalculateInferredType() {
   1888   return value()->type();
   1889 }
   1890 
   1891 
   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 
   1898 HType HCheckSmi::CalculateInferredType() {
   1899   return HType::Smi();
   1900 }
   1901 
   1902 
   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 
   1913 HType HConstant::CalculateInferredType() {
   1914   return HType::TypeFromValue(handle_);
   1915 }
   1916 
   1917 
   1918 HType HCompareGeneric::CalculateInferredType() {
   1919   return HType::Boolean();
   1920 }
   1921 
   1922 
   1923 HType HInstanceOf::CalculateInferredType() {
   1924   return HType::Boolean();
   1925 }
   1926 
   1927 
   1928 HType HDeleteProperty::CalculateInferredType() {
   1929   return HType::Boolean();
   1930 }
   1931 
   1932 
   1933 HType HInstanceOfKnownGlobal::CalculateInferredType() {
   1934   return HType::Boolean();
   1935 }
   1936 
   1937 
   1938 HType HChange::CalculateInferredType() {
   1939   if (from().IsDouble() && to().IsTagged()) return HType::HeapNumber();
   1940   return type();
   1941 }
   1942 
   1943 
   1944 HType HBitwiseBinaryOperation::CalculateInferredType() {
   1945   return HType::TaggedNumber();
   1946 }
   1947 
   1948 
   1949 HType HArithmeticBinaryOperation::CalculateInferredType() {
   1950   return HType::TaggedNumber();
   1951 }
   1952 
   1953 
   1954 HType HAdd::CalculateInferredType() {
   1955   return HType::Tagged();
   1956 }
   1957 
   1958 
   1959 HType HBitNot::CalculateInferredType() {
   1960   return HType::TaggedNumber();
   1961 }
   1962 
   1963 
   1964 HType HUnaryMathOperation::CalculateInferredType() {
   1965   return HType::TaggedNumber();
   1966 }
   1967 
   1968 
   1969 HType HStringCharFromCode::CalculateInferredType() {
   1970   return HType::String();
   1971 }
   1972 
   1973 
   1974 HType HAllocateObject::CalculateInferredType() {
   1975   return HType::JSObject();
   1976 }
   1977 
   1978 
   1979 HType HFastLiteral::CalculateInferredType() {
   1980   // TODO(mstarzinger): Be smarter, could also be JSArray here.
   1981   return HType::JSObject();
   1982 }
   1983 
   1984 
   1985 HType HArrayLiteral::CalculateInferredType() {
   1986   return HType::JSArray();
   1987 }
   1988 
   1989 
   1990 HType HObjectLiteral::CalculateInferredType() {
   1991   return HType::JSObject();
   1992 }
   1993 
   1994 
   1995 HType HRegExpLiteral::CalculateInferredType() {
   1996   return HType::JSObject();
   1997 }
   1998 
   1999 
   2000 HType HFunctionLiteral::CalculateInferredType() {
   2001   return HType::JSObject();
   2002 }
   2003 
   2004 
   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 
   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 
   2035 HValue* HForceRepresentation::EnsureAndPropagateNotMinusZero(
   2036     BitVector* visited) {
   2037   visited->Add(id());
   2038   return value();
   2039 }
   2040 
   2041 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   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 
   2253 void HIn::PrintDataTo(StringStream* stream) {
   2254   key()->PrintNameTo(stream);
   2255   stream->Add(" ");
   2256   object()->PrintNameTo(stream);
   2257 }
   2258 
   2259 
   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 
   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 
   2315 void HSimulate::Verify() {
   2316   HInstruction::Verify();
   2317   ASSERT(HasAstId());
   2318 }
   2319 
   2320 
   2321 void HCheckSmi::Verify() {
   2322   HInstruction::Verify();
   2323   ASSERT(HasNoUses());
   2324 }
   2325 
   2326 
   2327 void HCheckNonSmi::Verify() {
   2328   HInstruction::Verify();
   2329   ASSERT(HasNoUses());
   2330 }
   2331 
   2332 
   2333 void HCheckFunction::Verify() {
   2334   HInstruction::Verify();
   2335   ASSERT(HasNoUses());
   2336 }
   2337 
   2338 
   2339 void HCheckPrototypeMaps::Verify() {
   2340   HInstruction::Verify();
   2341   ASSERT(HasNoUses());
   2342 }
   2343 
   2344 #endif
   2345 
   2346 } }  // namespace v8::internal
   2347