Home | History | Annotate | Download | only in src
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/hydrogen-dehoist.h"
      6 #include "src/base/safe_math.h"
      7 
      8 namespace v8 {
      9 namespace internal {
     10 
     11 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
     12   HValue* index = array_operation->GetKey()->ActualValue();
     13   if (!index->representation().IsSmiOrInteger32()) return;
     14   if (!index->IsAdd() && !index->IsSub()) return;
     15 
     16   HConstant* constant;
     17   HValue* subexpression;
     18   HBinaryOperation* binary_operation = HBinaryOperation::cast(index);
     19   if (binary_operation->left()->IsConstant() && index->IsAdd()) {
     20     subexpression = binary_operation->right();
     21     constant = HConstant::cast(binary_operation->left());
     22   } else if (binary_operation->right()->IsConstant()) {
     23     subexpression = binary_operation->left();
     24     constant = HConstant::cast(binary_operation->right());
     25   } else {
     26     return;
     27   }
     28 
     29   if (!constant->HasInteger32Value()) return;
     30   int32_t sign = binary_operation->IsSub() ? -1 : 1;
     31   int32_t value = constant->Integer32Value() * sign;
     32   if (value < 0) return;
     33 
     34   // Multiply value by elements size, bailing out on overflow.
     35   int32_t elements_kind_size =
     36       1 << ElementsKindToShiftSize(array_operation->elements_kind());
     37   v8::base::internal::CheckedNumeric<int32_t> multiply_result = value;
     38   multiply_result = multiply_result * elements_kind_size;
     39   if (!multiply_result.IsValid()) return;
     40   value = multiply_result.ValueOrDie();
     41 
     42   // Ensure that the array operation can add value to existing base offset
     43   // without overflowing.
     44   if (!array_operation->TryIncreaseBaseOffset(value)) return;
     45 
     46   array_operation->SetKey(subexpression);
     47   if (binary_operation->HasNoUses()) {
     48     binary_operation->DeleteAndReplaceWith(NULL);
     49   }
     50 
     51   array_operation->SetDehoisted(true);
     52 }
     53 
     54 
     55 void HDehoistIndexComputationsPhase::Run() {
     56   const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
     57   for (int i = 0; i < blocks->length(); ++i) {
     58     for (HInstructionIterator it(blocks->at(i)); !it.Done(); it.Advance()) {
     59       HInstruction* instr = it.Current();
     60       if (instr->IsLoadKeyed()) {
     61         DehoistArrayIndex(HLoadKeyed::cast(instr));
     62       } else if (instr->IsStoreKeyed()) {
     63         DehoistArrayIndex(HStoreKeyed::cast(instr));
     64       }
     65     }
     66   }
     67 }
     68 
     69 } }  // namespace v8::internal
     70