| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index db24da7ff638901c2d2c633de561171482d6d83f..e567e1cdb193bd7720bf8d6787e693ff9f53b89b 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -745,7 +745,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HCheckMaps* mapcheck,
|
| bool is_js_array,
|
| ElementsKind elements_kind,
|
| - bool is_store) {
|
| + bool is_store,
|
| + Representation checked_index_representation) {
|
| Zone* zone = this->zone();
|
| // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
|
| // on a HElementsTransition instruction. The flag can also be removed if the
|
| @@ -773,8 +774,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| HInstruction* checked_key = NULL;
|
| if (IsExternalArrayElementsKind(elements_kind)) {
|
| length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
|
| - checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
|
| - ALLOW_SMI_KEY));
|
| + checked_key = AddInstruction(new(zone) HBoundsCheck(
|
| + key, length, ALLOW_SMI_KEY, checked_index_representation));
|
| HLoadExternalArrayPointer* external_elements =
|
| new(zone) HLoadExternalArrayPointer(elements);
|
| AddInstruction(external_elements);
|
| @@ -791,8 +792,8 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
|
| } else {
|
| length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
|
| }
|
| - checked_key = AddInstruction(new(zone) HBoundsCheck(key, length,
|
| - ALLOW_SMI_KEY));
|
| + checked_key = AddInstruction(new(zone) HBoundsCheck(
|
| + key, length, ALLOW_SMI_KEY, checked_index_representation));
|
| return BuildFastElementAccess(elements, checked_key, val, mapcheck,
|
| elements_kind, is_store);
|
| }
|
| @@ -3586,10 +3587,12 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
|
| HStackCheckEliminator sce(this);
|
| sce.Process();
|
|
|
| - EliminateRedundantBoundsChecks();
|
| - DehoistSimpleArrayIndexComputations();
|
| + if (FLAG_array_bounds_checks_elimination) EliminateRedundantBoundsChecks();
|
| + if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations();
|
| if (FLAG_dead_code_elimination) DeadCodeElimination();
|
|
|
| + RestoreActualValues();
|
| +
|
| return true;
|
| }
|
|
|
| @@ -3727,6 +3730,7 @@ class BoundsCheckBbData: public ZoneObject {
|
| new_check->index()->representation(),
|
| new_offset);
|
| if (!result) return false;
|
| + upper_check_->ReplaceAllUsesWith(upper_check_->index());
|
| upper_check_->SetOperandAt(0, added_upper_index_);
|
| }
|
| } else if (new_offset < lower_offset_) {
|
| @@ -3742,6 +3746,7 @@ class BoundsCheckBbData: public ZoneObject {
|
| new_check->index()->representation(),
|
| new_offset);
|
| if (!result) return false;
|
| + lower_check_->ReplaceAllUsesWith(lower_check_->index());
|
| lower_check_->SetOperandAt(0, added_lower_index_);
|
| }
|
| } else {
|
| @@ -3749,7 +3754,7 @@ class BoundsCheckBbData: public ZoneObject {
|
| }
|
|
|
| if (!keep_new_check) {
|
| - new_check->DeleteAndReplaceWith(NULL);
|
| + new_check->DeleteAndReplaceWith(new_check->ActualValue());
|
| }
|
|
|
| return true;
|
| @@ -3885,10 +3890,6 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
|
| if (!i->IsBoundsCheck()) continue;
|
|
|
| HBoundsCheck* check = HBoundsCheck::cast(i);
|
| - check->ReplaceAllUsesWith(check->index());
|
| -
|
| - if (!FLAG_array_bounds_checks_elimination) continue;
|
| -
|
| int32_t offset;
|
| BoundsCheckKey* key =
|
| BoundsCheckKey::Create(zone(), check, &offset);
|
| @@ -3906,7 +3907,7 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
|
| NULL);
|
| *data_p = bb_data_list;
|
| } else if (data->OffsetIsCovered(offset)) {
|
| - check->DeleteAndReplaceWith(NULL);
|
| + check->DeleteAndReplaceWith(check->ActualValue());
|
| } else if (data->BasicBlock() != bb ||
|
| !data->CoverCheck(check, offset)) {
|
| // If the check is in the current BB we try to modify it by calling
|
| @@ -3955,7 +3956,7 @@ void HGraph::EliminateRedundantBoundsChecks() {
|
|
|
|
|
| static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
|
| - HValue* index = array_operation->GetKey();
|
| + HValue* index = array_operation->GetKey()->ActualValue();
|
| if (!index->representation().IsInteger32()) return;
|
|
|
| HConstant* constant;
|
| @@ -4003,8 +4004,6 @@ static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
|
|
|
|
|
| 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();
|
| @@ -4056,6 +4055,30 @@ void HGraph::DeadCodeElimination() {
|
| }
|
|
|
|
|
| +void HGraph::RestoreActualValues() {
|
| + HPhase phase("H_Restore actual values", this);
|
| +
|
| + for (int block_index = 0; block_index < blocks()->length(); block_index++) {
|
| + HBasicBlock* block = blocks()->at(block_index);
|
| +
|
| +#ifdef DEBUG
|
| + for (int i = 0; i < block->phis()->length(); i++) {
|
| + HPhi* phi = block->phis()->at(i);
|
| + ASSERT(phi->ActualValue() == phi);
|
| + }
|
| +#endif
|
| +
|
| + for (HInstruction* instruction = block->first();
|
| + instruction != NULL;
|
| + instruction = instruction->next()) {
|
| + if (instruction->ActualValue() != instruction) {
|
| + instruction->ReplaceAllUsesWith(instruction->ActualValue());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void HOptimizedGraphBuilder::AddPhi(HPhi* instr) {
|
| ASSERT(current_block() != NULL);
|
| current_block()->AddPhi(instr);
|
|
|