OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/js-type-feedback.h" | 5 #include "src/compiler/js-type-feedback.h" |
6 | 6 |
7 #include "src/property-details.h" | 7 #include "src/property-details.h" |
8 | 8 |
9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
10 #include "src/ast.h" | 10 #include "src/ast.h" |
11 #include "src/compiler.h" | 11 #include "src/compiler.h" |
12 #include "src/type-info.h" | 12 #include "src/type-info.h" |
13 | 13 |
14 #include "src/compiler/access-builder.h" | 14 #include "src/compiler/access-builder.h" |
15 #include "src/compiler/common-operator.h" | 15 #include "src/compiler/common-operator.h" |
| 16 #include "src/compiler/frame-states.h" |
16 #include "src/compiler/node-aux-data.h" | 17 #include "src/compiler/node-aux-data.h" |
17 #include "src/compiler/node-matchers.h" | 18 #include "src/compiler/node-matchers.h" |
18 #include "src/compiler/operator-properties.h" | 19 #include "src/compiler/operator-properties.h" |
19 #include "src/compiler/simplified-operator.h" | 20 #include "src/compiler/simplified-operator.h" |
20 | 21 |
21 namespace v8 { | 22 namespace v8 { |
22 namespace internal { | 23 namespace internal { |
23 namespace compiler { | 24 namespace compiler { |
24 | 25 |
25 enum LoadOrStore { LOAD, STORE }; | 26 enum LoadOrStore { LOAD, STORE }; |
26 | 27 |
27 #define EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT false | |
28 | |
29 JSTypeFeedbackTable::JSTypeFeedbackTable(Zone* zone) | 28 JSTypeFeedbackTable::JSTypeFeedbackTable(Zone* zone) |
30 : map_(TypeFeedbackIdMap::key_compare(), | 29 : map_(TypeFeedbackIdMap::key_compare(), |
31 TypeFeedbackIdMap::allocator_type(zone)) {} | 30 TypeFeedbackIdMap::allocator_type(zone)) {} |
32 | 31 |
33 | 32 |
34 void JSTypeFeedbackTable::Record(Node* node, TypeFeedbackId id) { | 33 void JSTypeFeedbackTable::Record(Node* node, TypeFeedbackId id) { |
35 map_.insert(std::make_pair(node->id(), id)); | 34 map_.insert(std::make_pair(node->id(), id)); |
36 } | 35 } |
37 | 36 |
38 | 37 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 | 155 |
157 | 156 |
158 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { | 157 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamed(Node* node) { |
159 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed); | 158 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed); |
160 Node* receiver = node->InputAt(0); | 159 Node* receiver = node->InputAt(0); |
161 if (IsGlobalObject(receiver)) { | 160 if (IsGlobalObject(receiver)) { |
162 return ReduceJSLoadNamedForGlobalVariable(node); | 161 return ReduceJSLoadNamedForGlobalVariable(node); |
163 } | 162 } |
164 | 163 |
165 if (!FLAG_turbo_deoptimization) return NoChange(); | 164 if (!FLAG_turbo_deoptimization) return NoChange(); |
166 // TODO(titzer): deopt locations are wrong for property accesses | 165 Node* frame_state_before = GetFrameStateBefore(node); |
167 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange(); | 166 if (frame_state_before == nullptr) return NoChange(); |
168 | 167 |
169 // TODO(turbofan): handle vector-based type feedback. | 168 // TODO(turbofan): handle vector-based type feedback. |
170 TypeFeedbackId id = js_type_feedback_->find(node); | 169 TypeFeedbackId id = js_type_feedback_->find(node); |
171 if (id.IsNone() || oracle()->LoadInlineCacheState(id) == UNINITIALIZED) { | 170 if (id.IsNone() || oracle()->LoadInlineCacheState(id) == UNINITIALIZED) { |
172 return NoChange(); | 171 return NoChange(); |
173 } | 172 } |
174 | 173 |
175 const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); | 174 const LoadNamedParameters& p = LoadNamedParametersOf(node->op()); |
176 SmallMapList maps; | 175 SmallMapList maps; |
177 Handle<Name> name = p.name().handle(); | 176 Handle<Name> name = p.name().handle(); |
(...skipping 12 matching lines...) Expand all Loading... |
190 Node* check_success; | 189 Node* check_success; |
191 Node* check_failed; | 190 Node* check_failed; |
192 BuildMapCheck(receiver, map, true, effect, control, &check_success, | 191 BuildMapCheck(receiver, map, true, effect, control, &check_success, |
193 &check_failed); | 192 &check_failed); |
194 | 193 |
195 // Build the actual load. | 194 // Build the actual load. |
196 Node* load = graph()->NewNode(simplified()->LoadField(field_access), receiver, | 195 Node* load = graph()->NewNode(simplified()->LoadField(field_access), receiver, |
197 effect, check_success); | 196 effect, check_success); |
198 | 197 |
199 // TODO(turbofan): handle slow case instead of deoptimizing. | 198 // TODO(turbofan): handle slow case instead of deoptimizing. |
200 // TODO(titzer): frame state should be from before the load. | 199 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state_before, |
201 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 200 effect, check_failed); |
202 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state, effect, | |
203 check_failed); | |
204 NodeProperties::MergeControlToEnd(graph(), common(), deopt); | 201 NodeProperties::MergeControlToEnd(graph(), common(), deopt); |
205 NodeProperties::ReplaceWithValue(node, load, load, check_success); | 202 NodeProperties::ReplaceWithValue(node, load, load, check_success); |
206 return Replace(load); | 203 return Replace(load); |
207 } | 204 } |
208 | 205 |
209 | 206 |
210 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable( | 207 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadNamedForGlobalVariable( |
211 Node* node) { | 208 Node* node) { |
212 Handle<String> name = | 209 Handle<String> name = |
213 Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle()); | 210 Handle<String>::cast(LoadNamedParametersOf(node->op()).name().handle()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 } | 272 } |
276 | 273 |
277 | 274 |
278 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) { | 275 Reduction JSTypeFeedbackSpecializer::ReduceJSLoadProperty(Node* node) { |
279 return NoChange(); | 276 return NoChange(); |
280 } | 277 } |
281 | 278 |
282 | 279 |
283 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreNamed(Node* node) { | 280 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreNamed(Node* node) { |
284 DCHECK(node->opcode() == IrOpcode::kJSStoreNamed); | 281 DCHECK(node->opcode() == IrOpcode::kJSStoreNamed); |
285 // TODO(titzer): deopt locations are wrong for property accesses | 282 Node* frame_state_before = GetFrameStateBefore(node); |
286 if (!EAGER_DEOPT_LOCATIONS_FOR_PROPERTY_ACCESS_ARE_CORRECT) return NoChange(); | 283 if (frame_state_before == nullptr) return NoChange(); |
287 | 284 |
288 TypeFeedbackId id = js_type_feedback_->find(node); | 285 TypeFeedbackId id = js_type_feedback_->find(node); |
289 if (id.IsNone() || oracle()->StoreIsUninitialized(id)) return NoChange(); | 286 if (id.IsNone() || oracle()->StoreIsUninitialized(id)) return NoChange(); |
290 | 287 |
291 const StoreNamedParameters& p = StoreNamedParametersOf(node->op()); | 288 const StoreNamedParameters& p = StoreNamedParametersOf(node->op()); |
292 SmallMapList maps; | 289 SmallMapList maps; |
293 Handle<Name> name = p.name().handle(); | 290 Handle<Name> name = p.name().handle(); |
294 Node* receiver = node->InputAt(0); | 291 Node* receiver = node->InputAt(0); |
295 Node* effect = NodeProperties::GetEffectInput(node); | 292 Node* effect = NodeProperties::GetEffectInput(node); |
296 GatherReceiverTypes(receiver, effect, id, name, &maps); | 293 GatherReceiverTypes(receiver, effect, id, name, &maps); |
(...skipping 11 matching lines...) Expand all Loading... |
308 Node* check_failed; | 305 Node* check_failed; |
309 BuildMapCheck(receiver, map, true, effect, control, &check_success, | 306 BuildMapCheck(receiver, map, true, effect, control, &check_success, |
310 &check_failed); | 307 &check_failed); |
311 | 308 |
312 // Build the actual load. | 309 // Build the actual load. |
313 Node* value = node->InputAt(1); | 310 Node* value = node->InputAt(1); |
314 Node* store = graph()->NewNode(simplified()->StoreField(field_access), | 311 Node* store = graph()->NewNode(simplified()->StoreField(field_access), |
315 receiver, value, effect, check_success); | 312 receiver, value, effect, check_success); |
316 | 313 |
317 // TODO(turbofan): handle slow case instead of deoptimizing. | 314 // TODO(turbofan): handle slow case instead of deoptimizing. |
318 // TODO(titzer): frame state should be from before the store. | 315 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state_before, |
319 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0); | 316 effect, check_failed); |
320 Node* deopt = graph()->NewNode(common()->Deoptimize(), frame_state, effect, | |
321 check_failed); | |
322 NodeProperties::MergeControlToEnd(graph(), common(), deopt); | 317 NodeProperties::MergeControlToEnd(graph(), common(), deopt); |
323 NodeProperties::ReplaceWithValue(node, store, store, check_success); | 318 NodeProperties::ReplaceWithValue(node, store, store, check_success); |
324 return Replace(store); | 319 return Replace(store); |
325 } | 320 } |
326 | 321 |
327 | 322 |
328 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreProperty(Node* node) { | 323 Reduction JSTypeFeedbackSpecializer::ReduceJSStoreProperty(Node* node) { |
329 return NoChange(); | 324 return NoChange(); |
330 } | 325 } |
331 | 326 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 TypeFeedbackId id, | 360 TypeFeedbackId id, |
366 Handle<Name> name, | 361 Handle<Name> name, |
367 SmallMapList* maps) { | 362 SmallMapList* maps) { |
368 // TODO(turbofan): filter maps by initial receiver map if known | 363 // TODO(turbofan): filter maps by initial receiver map if known |
369 // TODO(turbofan): filter maps by native context (if specializing) | 364 // TODO(turbofan): filter maps by native context (if specializing) |
370 // TODO(turbofan): filter maps by effect chain | 365 // TODO(turbofan): filter maps by effect chain |
371 oracle()->PropertyReceiverTypes(id, name, maps); | 366 oracle()->PropertyReceiverTypes(id, name, maps); |
372 } | 367 } |
373 | 368 |
374 | 369 |
| 370 // Get the frame state before an operation if it exists and has a valid |
| 371 // bailout id. |
| 372 Node* JSTypeFeedbackSpecializer::GetFrameStateBefore(Node* node) { |
| 373 int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
| 374 DCHECK_LE(count, 2); |
| 375 if (count == 2) { |
| 376 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 377 if (frame_state->opcode() == IrOpcode::kFrameState) { |
| 378 BailoutId id = OpParameter<FrameStateCallInfo>(node).bailout_id(); |
| 379 if (id != BailoutId::None()) return frame_state; |
| 380 } |
| 381 } |
| 382 return nullptr; |
| 383 } |
| 384 |
375 } // namespace compiler | 385 } // namespace compiler |
376 } // namespace internal | 386 } // namespace internal |
377 } // namespace v8 | 387 } // namespace v8 |
OLD | NEW |