| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 HCapturedObject* state = NewState(previous); | 79 HCapturedObject* state = NewState(previous); |
| 80 for (int index = 0; index < number_of_values_; index++) { | 80 for (int index = 0; index < number_of_values_; index++) { |
| 81 state->SetOperandAt(index, undefined); | 81 state->SetOperandAt(index, undefined); |
| 82 } | 82 } |
| 83 return state; | 83 return state; |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 // Create a new state full of phis for loop header entries. | 87 // Create a new state full of phis for loop header entries. |
| 88 HCapturedObject* HEscapeAnalysisPhase::NewStateForLoopHeader( | 88 HCapturedObject* HEscapeAnalysisPhase::NewStateForLoopHeader( |
| 89 HInstruction* previous, HCapturedObject* old_state) { | 89 HInstruction* previous, |
| 90 HCapturedObject* old_state) { |
| 90 HBasicBlock* block = previous->block(); | 91 HBasicBlock* block = previous->block(); |
| 91 HCapturedObject* state = NewState(previous); | 92 HCapturedObject* state = NewState(previous); |
| 92 for (int index = 0; index < number_of_values_; index++) { | 93 for (int index = 0; index < number_of_values_; index++) { |
| 93 HValue* operand = old_state->OperandAt(index); | 94 HValue* operand = old_state->OperandAt(index); |
| 94 HPhi* phi = NewPhiAndInsert(block, operand, index); | 95 HPhi* phi = NewPhiAndInsert(block, operand, index); |
| 95 state->SetOperandAt(index, phi); | 96 state->SetOperandAt(index, phi); |
| 96 } | 97 } |
| 97 return state; | 98 return state; |
| 98 } | 99 } |
| 99 | 100 |
| 100 | 101 |
| 101 // Create a new state by copying an existing one. | 102 // Create a new state by copying an existing one. |
| 102 HCapturedObject* HEscapeAnalysisPhase::NewStateCopy( | 103 HCapturedObject* HEscapeAnalysisPhase::NewStateCopy( |
| 103 HInstruction* previous, HCapturedObject* old_state) { | 104 HInstruction* previous, |
| 105 HCapturedObject* old_state) { |
| 104 HCapturedObject* state = NewState(previous); | 106 HCapturedObject* state = NewState(previous); |
| 105 for (int index = 0; index < number_of_values_; index++) { | 107 for (int index = 0; index < number_of_values_; index++) { |
| 106 HValue* operand = old_state->OperandAt(index); | 108 HValue* operand = old_state->OperandAt(index); |
| 107 state->SetOperandAt(index, operand); | 109 state->SetOperandAt(index, operand); |
| 108 } | 110 } |
| 109 return state; | 111 return state; |
| 110 } | 112 } |
| 111 | 113 |
| 112 | 114 |
| 113 // Insert a newly created phi into the given block and fill all incoming | 115 // Insert a newly created phi into the given block and fill all incoming |
| 114 // edges with the given value. | 116 // edges with the given value. |
| 115 HPhi* HEscapeAnalysisPhase::NewPhiAndInsert( | 117 HPhi* HEscapeAnalysisPhase::NewPhiAndInsert(HBasicBlock* block, |
| 116 HBasicBlock* block, HValue* incoming_value, int index) { | 118 HValue* incoming_value, |
| 119 int index) { |
| 117 Zone* zone = graph()->zone(); | 120 Zone* zone = graph()->zone(); |
| 118 HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone); | 121 HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone); |
| 119 for (int i = 0; i < block->predecessors()->length(); i++) { | 122 for (int i = 0; i < block->predecessors()->length(); i++) { |
| 120 phi->AddInput(incoming_value); | 123 phi->AddInput(incoming_value); |
| 121 } | 124 } |
| 122 block->AddPhi(phi); | 125 block->AddPhi(phi); |
| 123 return phi; | 126 return phi; |
| 124 } | 127 } |
| 125 | 128 |
| 126 | 129 |
| 130 // Insert a newly created value check as a replacement for map checks. |
| 131 HValue* HEscapeAnalysisPhase::NewMapCheckAndInsert(HCapturedObject* state, |
| 132 HCheckMaps* mapcheck) { |
| 133 Zone* zone = graph()->zone(); |
| 134 HValue* value = state->map_value(); |
| 135 // TODO(mstarzinger): This will narrow a map check against a set of maps |
| 136 // down to the first element in the set. Revisit and fix this. |
| 137 Handle<Map> map_object = mapcheck->map_set()->first(); |
| 138 UniqueValueId map_id = mapcheck->map_unique_ids()->first(); |
| 139 HCheckValue* check = HCheckValue::New(zone, NULL, value, map_object, map_id); |
| 140 check->InsertBefore(mapcheck); |
| 141 return check; |
| 142 } |
| 143 |
| 144 |
| 127 // Performs a forward data-flow analysis of all loads and stores on the | 145 // Performs a forward data-flow analysis of all loads and stores on the |
| 128 // given captured allocation. This uses a reverse post-order iteration | 146 // given captured allocation. This uses a reverse post-order iteration |
| 129 // over affected basic blocks. All non-escaping instructions are handled | 147 // over affected basic blocks. All non-escaping instructions are handled |
| 130 // and replaced during the analysis. | 148 // and replaced during the analysis. |
| 131 void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) { | 149 void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) { |
| 132 HBasicBlock* allocate_block = allocate->block(); | 150 HBasicBlock* allocate_block = allocate->block(); |
| 133 block_states_.AddBlock(NULL, graph()->blocks()->length(), zone()); | 151 block_states_.AddBlock(NULL, graph()->blocks()->length(), zone()); |
| 134 | 152 |
| 135 // Iterate all blocks starting with the allocation block, since the | 153 // Iterate all blocks starting with the allocation block, since the |
| 136 // allocation cannot dominate blocks that come before. | 154 // allocation cannot dominate blocks that come before. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 case HValue::kStoreNamedField: { | 188 case HValue::kStoreNamedField: { |
| 171 HStoreNamedField* store = HStoreNamedField::cast(instr); | 189 HStoreNamedField* store = HStoreNamedField::cast(instr); |
| 172 int index = store->access().offset() / kPointerSize; | 190 int index = store->access().offset() / kPointerSize; |
| 173 if (store->object() != allocate) continue; | 191 if (store->object() != allocate) continue; |
| 174 ASSERT(store->access().IsInobject()); | 192 ASSERT(store->access().IsInobject()); |
| 175 state = NewStateCopy(store, state); | 193 state = NewStateCopy(store, state); |
| 176 state->SetOperandAt(index, store->value()); | 194 state->SetOperandAt(index, store->value()); |
| 177 if (store->has_transition()) { | 195 if (store->has_transition()) { |
| 178 state->SetOperandAt(0, store->transition()); | 196 state->SetOperandAt(0, store->transition()); |
| 179 } | 197 } |
| 180 store->DeleteAndReplaceWith(NULL); | 198 store->DeleteAndReplaceWith(store->ActualValue()); |
| 181 if (FLAG_trace_escape_analysis) { | 199 if (FLAG_trace_escape_analysis) { |
| 182 PrintF("Replacing store #%d%s\n", instr->id(), | 200 PrintF("Replacing store #%d%s\n", instr->id(), |
| 183 store->has_transition() ? " (with transition)" : ""); | 201 store->has_transition() ? " (with transition)" : ""); |
| 184 } | 202 } |
| 185 break; | 203 break; |
| 186 } | 204 } |
| 187 case HValue::kArgumentsObject: | 205 case HValue::kArgumentsObject: |
| 188 case HValue::kCapturedObject: | 206 case HValue::kCapturedObject: |
| 189 case HValue::kSimulate: { | 207 case HValue::kSimulate: { |
| 190 for (int i = 0; i < instr->OperandCount(); i++) { | 208 for (int i = 0; i < instr->OperandCount(); i++) { |
| 191 if (instr->OperandAt(i) != allocate) continue; | 209 if (instr->OperandAt(i) != allocate) continue; |
| 192 instr->SetOperandAt(i, state); | 210 instr->SetOperandAt(i, state); |
| 193 } | 211 } |
| 194 break; | 212 break; |
| 195 } | 213 } |
| 196 case HValue::kCheckHeapObject: { | 214 case HValue::kCheckHeapObject: { |
| 197 HCheckHeapObject* check = HCheckHeapObject::cast(instr); | 215 HCheckHeapObject* check = HCheckHeapObject::cast(instr); |
| 198 if (check->value() != allocate) continue; | 216 if (check->value() != allocate) continue; |
| 199 check->DeleteAndReplaceWith(NULL); | 217 check->DeleteAndReplaceWith(check->ActualValue()); |
| 200 break; | 218 break; |
| 201 } | 219 } |
| 202 case HValue::kCheckMaps: { | 220 case HValue::kCheckMaps: { |
| 203 HCheckMaps* mapcheck = HCheckMaps::cast(instr); | 221 HCheckMaps* mapcheck = HCheckMaps::cast(instr); |
| 204 if (mapcheck->value() != allocate) continue; | 222 if (mapcheck->value() != allocate) continue; |
| 205 // TODO(mstarzinger): This approach breaks if the tracked map value | 223 NewMapCheckAndInsert(state, mapcheck); |
| 206 // is not a HConstant. Find a repro test case and fix this. | |
| 207 ASSERT(mapcheck->ActualValue() == allocate); | |
| 208 mapcheck->DeleteAndReplaceWith(mapcheck->ActualValue()); | 224 mapcheck->DeleteAndReplaceWith(mapcheck->ActualValue()); |
| 209 break; | 225 break; |
| 210 } | 226 } |
| 211 default: | 227 default: |
| 212 // Nothing to see here, move along ... | 228 // Nothing to see here, move along ... |
| 213 break; | 229 break; |
| 214 } | 230 } |
| 215 } | 231 } |
| 216 | 232 |
| 217 // Propagate the block state forward to all successor blocks. | 233 // Propagate the block state forward to all successor blocks. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 AnalyzeDataFlow(allocate); | 289 AnalyzeDataFlow(allocate); |
| 274 | 290 |
| 275 cumulative_values_ += number_of_values_; | 291 cumulative_values_ += number_of_values_; |
| 276 ASSERT(allocate->HasNoUses()); | 292 ASSERT(allocate->HasNoUses()); |
| 277 ASSERT(!allocate->IsLinked()); | 293 ASSERT(!allocate->IsLinked()); |
| 278 } | 294 } |
| 279 } | 295 } |
| 280 | 296 |
| 281 | 297 |
| 282 } } // namespace v8::internal | 298 } } // namespace v8::internal |
| OLD | NEW |