| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index a179e808a3f63a11b6ab784e02b6bce06e597670..d3b91184eca596bacc9f2ea42a8b79f23326c99c 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -2758,6 +2758,7 @@ HGraph* HGraphBuilder::CreateGraph() {
|
| sce.Process();
|
|
|
| graph()->EliminateRedundantBoundsChecks();
|
| + graph()->DehoistSimpleArrayIndexComputations();
|
|
|
| return graph();
|
| }
|
| @@ -3016,7 +3017,6 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
|
| HBoundsCheck* check = HBoundsCheck::cast(i);
|
| check->ReplaceAllUsesWith(check->index());
|
|
|
| - isolate()->counters()->array_bounds_checks_seen()->Increment();
|
| if (!FLAG_array_bounds_checks_elimination) continue;
|
|
|
| int32_t offset;
|
| @@ -3035,10 +3035,8 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
|
| *data_p = bb_data_list;
|
| } else if (data->OffsetIsCovered(offset)) {
|
| check->DeleteAndReplaceWith(NULL);
|
| - isolate()->counters()->array_bounds_checks_removed()->Increment();
|
| } else if (data->BasicBlock() == bb) {
|
| data->CoverCheck(check, offset);
|
| - isolate()->counters()->array_bounds_checks_removed()->Increment();
|
| } else {
|
| int32_t new_lower_offset = offset < data->LowerOffset()
|
| ? offset
|
| @@ -3082,6 +3080,93 @@ void HGraph::EliminateRedundantBoundsChecks() {
|
| }
|
|
|
|
|
| +static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
|
| + HValue* index = array_operation->GetKey();
|
| +
|
| + HConstant* constant;
|
| + HValue* subexpression;
|
| + int32_t sign;
|
| + if (index->IsAdd()) {
|
| + sign = 1;
|
| + HAdd* add = HAdd::cast(index);
|
| + if (add->left()->IsConstant()) {
|
| + subexpression = add->right();
|
| + constant = HConstant::cast(add->left());
|
| + } else if (add->right()->IsConstant()) {
|
| + subexpression = add->left();
|
| + constant = HConstant::cast(add->right());
|
| + } else {
|
| + return;
|
| + }
|
| + } else if (index->IsSub()) {
|
| + sign = -1;
|
| + HSub* sub = HSub::cast(index);
|
| + if (sub->left()->IsConstant()) {
|
| + subexpression = sub->right();
|
| + constant = HConstant::cast(sub->left());
|
| + } else if (sub->right()->IsConstant()) {
|
| + subexpression = sub->left();
|
| + constant = HConstant::cast(sub->right());
|
| + } return;
|
| + } else {
|
| + return;
|
| + }
|
| +
|
| + if (!constant->HasInteger32Value()) return;
|
| + int32_t value = constant->Integer32Value() * sign;
|
| + // We limit offset values to 30 bits because we want to avoid the risk of
|
| + // overflows when the offset is added to the object header size.
|
| + if (value >= 1 << 30 || value < 0) return;
|
| + array_operation->SetKey(subexpression);
|
| + if (index->HasNoUses()) {
|
| + index->DeleteAndReplaceWith(NULL);
|
| + }
|
| + ASSERT(value >= 0);
|
| + array_operation->SetIndexOffset(static_cast<uint32_t>(value));
|
| + array_operation->SetDehoisted(true);
|
| +}
|
| +
|
| +
|
| +void HGraph::DehoistSimpleArrayIndexComputations() {
|
| + if (!FLAG_array_index_dehoisting) return;
|
| +
|
| + HPhase phase("H_Dehoist index computations", this);
|
| + for (int i = 0; i < blocks()->length(); ++i) {
|
| + for (HInstruction* instr = blocks()->at(i)->first();
|
| + instr != NULL;
|
| + instr = instr->next()) {
|
| + ArrayInstructionInterface* array_instruction = NULL;
|
| + if (instr->IsLoadKeyedFastElement()) {
|
| + HLoadKeyedFastElement* op = HLoadKeyedFastElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else if (instr->IsLoadKeyedFastDoubleElement()) {
|
| + HLoadKeyedFastDoubleElement* op =
|
| + HLoadKeyedFastDoubleElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else if (instr->IsLoadKeyedSpecializedArrayElement()) {
|
| + HLoadKeyedSpecializedArrayElement* op =
|
| + HLoadKeyedSpecializedArrayElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else if (instr->IsStoreKeyedFastElement()) {
|
| + HStoreKeyedFastElement* op = HStoreKeyedFastElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else if (instr->IsStoreKeyedFastDoubleElement()) {
|
| + HStoreKeyedFastDoubleElement* op =
|
| + HStoreKeyedFastDoubleElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else if (instr->IsStoreKeyedSpecializedArrayElement()) {
|
| + HStoreKeyedSpecializedArrayElement* op =
|
| + HStoreKeyedSpecializedArrayElement::cast(instr);
|
| + array_instruction = static_cast<ArrayInstructionInterface*>(op);
|
| + } else {
|
| + continue;
|
| + }
|
| + DehoistArrayIndex(array_instruction);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
|
| ASSERT(current_block() != NULL);
|
| current_block()->AddInstruction(instr);
|
|
|