OLD | NEW |
| (Empty) |
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 v8::base::internal::CheckedNumeric<int32_t> checked_value = | |
31 constant->Integer32Value(); | |
32 int32_t sign = binary_operation->IsSub() ? -1 : 1; | |
33 checked_value = checked_value * sign; | |
34 | |
35 // Multiply value by elements size, bailing out on overflow. | |
36 int32_t elements_kind_size = | |
37 1 << ElementsKindToShiftSize(array_operation->elements_kind()); | |
38 checked_value = checked_value * elements_kind_size; | |
39 if (!checked_value.IsValid()) return; | |
40 int32_t value = checked_value.ValueOrDie(); | |
41 if (value < 0) return; | |
42 | |
43 // Ensure that the array operation can add value to existing base offset | |
44 // without overflowing. | |
45 if (!array_operation->TryIncreaseBaseOffset(value)) return; | |
46 | |
47 array_operation->SetKey(subexpression); | |
48 if (binary_operation->HasNoUses()) { | |
49 binary_operation->DeleteAndReplaceWith(NULL); | |
50 } | |
51 | |
52 array_operation->SetDehoisted(true); | |
53 } | |
54 | |
55 | |
56 void HDehoistIndexComputationsPhase::Run() { | |
57 const ZoneList<HBasicBlock*>* blocks(graph()->blocks()); | |
58 for (int i = 0; i < blocks->length(); ++i) { | |
59 for (HInstructionIterator it(blocks->at(i)); !it.Done(); it.Advance()) { | |
60 HInstruction* instr = it.Current(); | |
61 if (instr->IsLoadKeyed()) { | |
62 DehoistArrayIndex(HLoadKeyed::cast(instr)); | |
63 } else if (instr->IsStoreKeyed()) { | |
64 DehoistArrayIndex(HStoreKeyed::cast(instr)); | |
65 } | |
66 } | |
67 } | |
68 } | |
69 | |
70 } // namespace internal | |
71 } // namespace v8 | |
OLD | NEW |