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 |