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