| 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);
 | 
| 
 |