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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 Zone* zone = graph()->zone(); | 117 Zone* zone = graph()->zone(); |
118 HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone); | 118 HPhi* phi = new(zone) HPhi(HPhi::kInvalidMergedIndex, zone); |
119 for (int i = 0; i < block->predecessors()->length(); i++) { | 119 for (int i = 0; i < block->predecessors()->length(); i++) { |
120 phi->AddInput(incoming_value); | 120 phi->AddInput(incoming_value); |
121 } | 121 } |
122 block->AddPhi(phi); | 122 block->AddPhi(phi); |
123 return phi; | 123 return phi; |
124 } | 124 } |
125 | 125 |
126 | 126 |
127 // Insert a newly created value check as a replacement for map checks. | |
128 HValue* HEscapeAnalysisPhase::NewMapCheckAndInsert( | |
129 HCapturedObject* state, HCheckMaps* mapcheck) { | |
Toon Verwaest
2013/08/28 13:29:30
Syntax nit: each argument on a single line.
Michael Starzinger
2013/08/28 13:53:15
Done. Also for the other methods above.
| |
130 Zone* zone = graph()->zone(); | |
131 HValue* value = state->values()->first(); | |
Toon Verwaest
2013/08/28 13:29:30
Can we have a helper method map_value() on HCaptur
Michael Starzinger
2013/08/28 13:53:15
Done.
| |
132 // TODO(mstarzinger): This will narrow a map check against a set of maps | |
133 // down to the first element in the set. Revisit and fix this. | |
134 Handle<Map> map_object = mapcheck->map_set()->first(); | |
135 UniqueValueId map_id = mapcheck->map_unique_ids()->first(); | |
136 HCheckValue* check = HCheckValue::New(zone, NULL, value, map_object, map_id); | |
137 check->InsertBefore(mapcheck); | |
138 return check; | |
139 } | |
140 | |
141 | |
127 // Performs a forward data-flow analysis of all loads and stores on the | 142 // Performs a forward data-flow analysis of all loads and stores on the |
128 // given captured allocation. This uses a reverse post-order iteration | 143 // given captured allocation. This uses a reverse post-order iteration |
129 // over affected basic blocks. All non-escaping instructions are handled | 144 // over affected basic blocks. All non-escaping instructions are handled |
130 // and replaced during the analysis. | 145 // and replaced during the analysis. |
131 void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) { | 146 void HEscapeAnalysisPhase::AnalyzeDataFlow(HInstruction* allocate) { |
132 HBasicBlock* allocate_block = allocate->block(); | 147 HBasicBlock* allocate_block = allocate->block(); |
133 block_states_.AddBlock(NULL, graph()->blocks()->length(), zone()); | 148 block_states_.AddBlock(NULL, graph()->blocks()->length(), zone()); |
134 | 149 |
135 // Iterate all blocks starting with the allocation block, since the | 150 // Iterate all blocks starting with the allocation block, since the |
136 // allocation cannot dominate blocks that come before. | 151 // allocation cannot dominate blocks that come before. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
170 case HValue::kStoreNamedField: { | 185 case HValue::kStoreNamedField: { |
171 HStoreNamedField* store = HStoreNamedField::cast(instr); | 186 HStoreNamedField* store = HStoreNamedField::cast(instr); |
172 int index = store->access().offset() / kPointerSize; | 187 int index = store->access().offset() / kPointerSize; |
173 if (store->object() != allocate) continue; | 188 if (store->object() != allocate) continue; |
174 ASSERT(store->access().IsInobject()); | 189 ASSERT(store->access().IsInobject()); |
175 state = NewStateCopy(store, state); | 190 state = NewStateCopy(store, state); |
176 state->SetOperandAt(index, store->value()); | 191 state->SetOperandAt(index, store->value()); |
177 if (store->has_transition()) { | 192 if (store->has_transition()) { |
178 state->SetOperandAt(0, store->transition()); | 193 state->SetOperandAt(0, store->transition()); |
179 } | 194 } |
180 store->DeleteAndReplaceWith(NULL); | 195 store->DeleteAndReplaceWith(store->ActualValue()); |
181 if (FLAG_trace_escape_analysis) { | 196 if (FLAG_trace_escape_analysis) { |
182 PrintF("Replacing store #%d%s\n", instr->id(), | 197 PrintF("Replacing store #%d%s\n", instr->id(), |
183 store->has_transition() ? " (with transition)" : ""); | 198 store->has_transition() ? " (with transition)" : ""); |
184 } | 199 } |
185 break; | 200 break; |
186 } | 201 } |
187 case HValue::kArgumentsObject: | 202 case HValue::kArgumentsObject: |
188 case HValue::kCapturedObject: | 203 case HValue::kCapturedObject: |
189 case HValue::kSimulate: { | 204 case HValue::kSimulate: { |
190 for (int i = 0; i < instr->OperandCount(); i++) { | 205 for (int i = 0; i < instr->OperandCount(); i++) { |
191 if (instr->OperandAt(i) != allocate) continue; | 206 if (instr->OperandAt(i) != allocate) continue; |
192 instr->SetOperandAt(i, state); | 207 instr->SetOperandAt(i, state); |
193 } | 208 } |
194 break; | 209 break; |
195 } | 210 } |
196 case HValue::kCheckHeapObject: { | 211 case HValue::kCheckHeapObject: { |
197 HCheckHeapObject* check = HCheckHeapObject::cast(instr); | 212 HCheckHeapObject* check = HCheckHeapObject::cast(instr); |
198 if (check->value() != allocate) continue; | 213 if (check->value() != allocate) continue; |
199 check->DeleteAndReplaceWith(NULL); | 214 check->DeleteAndReplaceWith(check->ActualValue()); |
200 break; | 215 break; |
201 } | 216 } |
202 case HValue::kCheckMaps: { | 217 case HValue::kCheckMaps: { |
203 HCheckMaps* mapcheck = HCheckMaps::cast(instr); | 218 HCheckMaps* mapcheck = HCheckMaps::cast(instr); |
204 if (mapcheck->value() != allocate) continue; | 219 if (mapcheck->value() != allocate) continue; |
205 // TODO(mstarzinger): This approach breaks if the tracked map value | 220 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()); | 221 mapcheck->DeleteAndReplaceWith(mapcheck->ActualValue()); |
209 break; | 222 break; |
210 } | 223 } |
211 default: | 224 default: |
212 // Nothing to see here, move along ... | 225 // Nothing to see here, move along ... |
213 break; | 226 break; |
214 } | 227 } |
215 } | 228 } |
216 | 229 |
217 // Propagate the block state forward to all successor blocks. | 230 // 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); | 286 AnalyzeDataFlow(allocate); |
274 | 287 |
275 cumulative_values_ += number_of_values_; | 288 cumulative_values_ += number_of_values_; |
276 ASSERT(allocate->HasNoUses()); | 289 ASSERT(allocate->HasNoUses()); |
277 ASSERT(!allocate->IsLinked()); | 290 ASSERT(!allocate->IsLinked()); |
278 } | 291 } |
279 } | 292 } |
280 | 293 |
281 | 294 |
282 } } // namespace v8::internal | 295 } } // namespace v8::internal |
OLD | NEW |