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-call-reducer.h" | 5 #include "src/compiler/js-call-reducer.h" |
6 | 6 |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/simplified-operator.h" |
9 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
10 #include "src/type-feedback-vector-inl.h" | 11 #include "src/type-feedback-vector-inl.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace compiler { | 15 namespace compiler { |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 VectorSlotPair CallCountFeedback(VectorSlotPair p) { | 19 VectorSlotPair CallCountFeedback(VectorSlotPair p) { |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 } | 214 } |
214 | 215 |
215 | 216 |
216 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { | 217 Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { |
217 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 218 DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); |
218 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 219 CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); |
219 Node* target = NodeProperties::GetValueInput(node, 0); | 220 Node* target = NodeProperties::GetValueInput(node, 0); |
220 Node* context = NodeProperties::GetContextInput(node); | 221 Node* context = NodeProperties::GetContextInput(node); |
221 Node* control = NodeProperties::GetControlInput(node); | 222 Node* control = NodeProperties::GetControlInput(node); |
222 Node* effect = NodeProperties::GetEffectInput(node); | 223 Node* effect = NodeProperties::GetEffectInput(node); |
223 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | |
224 | 224 |
225 // Try to specialize JSCallFunction {node}s with constant {target}s. | 225 // Try to specialize JSCallFunction {node}s with constant {target}s. |
226 HeapObjectMatcher m(target); | 226 HeapObjectMatcher m(target); |
227 if (m.HasValue()) { | 227 if (m.HasValue()) { |
228 if (m.Value()->IsJSFunction()) { | 228 if (m.Value()->IsJSFunction()) { |
229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 229 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
230 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 230 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
231 | 231 |
232 // Raise a TypeError if the {target} is a "classConstructor". | 232 // Raise a TypeError if the {target} is a "classConstructor". |
233 if (IsClassConstructor(shared->kind())) { | 233 if (IsClassConstructor(shared->kind())) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 } else { | 316 } else { |
317 Node* native_context = effect = graph()->NewNode( | 317 Node* native_context = effect = graph()->NewNode( |
318 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | 318 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
319 context, context, effect); | 319 context, context, effect); |
320 array_function = effect = graph()->NewNode( | 320 array_function = effect = graph()->NewNode( |
321 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | 321 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), |
322 native_context, native_context, effect); | 322 native_context, native_context, effect); |
323 } | 323 } |
324 | 324 |
325 // Check that the {target} is still the {array_function}. | 325 // Check that the {target} is still the {array_function}. |
326 Node* check = graph()->NewNode( | 326 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
327 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 327 target, array_function); |
328 array_function, context); | 328 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
329 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | |
330 frame_state, effect, control); | |
331 | 329 |
332 // Turn the {node} into a {JSCreateArray} call. | 330 // Turn the {node} into a {JSCreateArray} call. |
333 NodeProperties::ReplaceValueInput(node, array_function, 0); | 331 NodeProperties::ReplaceValueInput(node, array_function, 0); |
334 NodeProperties::ReplaceEffectInput(node, effect); | 332 NodeProperties::ReplaceEffectInput(node, effect); |
335 NodeProperties::ReplaceControlInput(node, control); | |
336 return ReduceArrayConstructor(node); | 333 return ReduceArrayConstructor(node); |
337 } else if (feedback->IsWeakCell()) { | 334 } else if (feedback->IsWeakCell()) { |
338 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 335 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
339 if (cell->value()->IsJSFunction()) { | 336 if (cell->value()->IsJSFunction()) { |
340 Node* target_function = | 337 Node* target_function = |
341 jsgraph()->Constant(handle(cell->value(), isolate())); | 338 jsgraph()->Constant(handle(cell->value(), isolate())); |
342 | 339 |
343 // Check that the {target} is still the {target_function}. | 340 // Check that the {target} is still the {target_function}. |
344 Node* check = graph()->NewNode( | 341 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
345 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 342 target, target_function); |
346 target_function, context); | 343 effect = |
347 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | 344 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
348 frame_state, effect, control); | |
349 | 345 |
350 // Specialize the JSCallFunction node to the {target_function}. | 346 // Specialize the JSCallFunction node to the {target_function}. |
351 NodeProperties::ReplaceValueInput(node, target_function, 0); | 347 NodeProperties::ReplaceValueInput(node, target_function, 0); |
352 NodeProperties::ReplaceEffectInput(node, effect); | 348 NodeProperties::ReplaceEffectInput(node, effect); |
353 NodeProperties::ReplaceControlInput(node, control); | |
354 | 349 |
355 // Try to further reduce the JSCallFunction {node}. | 350 // Try to further reduce the JSCallFunction {node}. |
356 Reduction const reduction = ReduceJSCallFunction(node); | 351 Reduction const reduction = ReduceJSCallFunction(node); |
357 return reduction.Changed() ? reduction : Changed(node); | 352 return reduction.Changed() ? reduction : Changed(node); |
358 } | 353 } |
359 } | 354 } |
360 return NoChange(); | 355 return NoChange(); |
361 } | 356 } |
362 | 357 |
363 | 358 |
364 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { | 359 Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) { |
365 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 360 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
366 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 361 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
367 DCHECK_LE(2u, p.arity()); | 362 DCHECK_LE(2u, p.arity()); |
368 int const arity = static_cast<int>(p.arity() - 2); | 363 int const arity = static_cast<int>(p.arity() - 2); |
369 Node* target = NodeProperties::GetValueInput(node, 0); | 364 Node* target = NodeProperties::GetValueInput(node, 0); |
370 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 365 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
371 Node* context = NodeProperties::GetContextInput(node); | 366 Node* context = NodeProperties::GetContextInput(node); |
372 Node* effect = NodeProperties::GetEffectInput(node); | 367 Node* effect = NodeProperties::GetEffectInput(node); |
373 Node* control = NodeProperties::GetControlInput(node); | 368 Node* control = NodeProperties::GetControlInput(node); |
374 Node* frame_state = NodeProperties::FindFrameStateBefore(node); | |
375 | 369 |
376 // Try to specialize JSCallConstruct {node}s with constant {target}s. | 370 // Try to specialize JSCallConstruct {node}s with constant {target}s. |
377 HeapObjectMatcher m(target); | 371 HeapObjectMatcher m(target); |
378 if (m.HasValue()) { | 372 if (m.HasValue()) { |
379 if (m.Value()->IsJSFunction()) { | 373 if (m.Value()->IsJSFunction()) { |
380 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); | 374 Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value()); |
381 | 375 |
382 // Raise a TypeError if the {target} is not a constructor. | 376 // Raise a TypeError if the {target} is not a constructor. |
383 if (!function->IsConstructor()) { | 377 if (!function->IsConstructor()) { |
384 NodeProperties::ReplaceValueInputs(node, target); | 378 NodeProperties::ReplaceValueInputs(node, target); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 } else { | 432 } else { |
439 Node* native_context = effect = graph()->NewNode( | 433 Node* native_context = effect = graph()->NewNode( |
440 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | 434 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), |
441 context, context, effect); | 435 context, context, effect); |
442 array_function = effect = graph()->NewNode( | 436 array_function = effect = graph()->NewNode( |
443 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), | 437 javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true), |
444 native_context, native_context, effect); | 438 native_context, native_context, effect); |
445 } | 439 } |
446 | 440 |
447 // Check that the {target} is still the {array_function}. | 441 // Check that the {target} is still the {array_function}. |
448 Node* check = graph()->NewNode( | 442 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
449 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 443 target, array_function); |
450 array_function, context); | 444 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
451 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | |
452 frame_state, effect, control); | |
453 | 445 |
454 // Turn the {node} into a {JSCreateArray} call. | 446 // Turn the {node} into a {JSCreateArray} call. |
455 NodeProperties::ReplaceEffectInput(node, effect); | 447 NodeProperties::ReplaceEffectInput(node, effect); |
456 NodeProperties::ReplaceControlInput(node, control); | |
457 for (int i = arity; i > 0; --i) { | 448 for (int i = arity; i > 0; --i) { |
458 NodeProperties::ReplaceValueInput( | 449 NodeProperties::ReplaceValueInput( |
459 node, NodeProperties::GetValueInput(node, i), i + 1); | 450 node, NodeProperties::GetValueInput(node, i), i + 1); |
460 } | 451 } |
461 NodeProperties::ReplaceValueInput(node, new_target, 1); | 452 NodeProperties::ReplaceValueInput(node, new_target, 1); |
462 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); | 453 NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site)); |
463 return Changed(node); | 454 return Changed(node); |
464 } else if (feedback->IsWeakCell()) { | 455 } else if (feedback->IsWeakCell()) { |
465 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 456 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
466 if (cell->value()->IsJSFunction()) { | 457 if (cell->value()->IsJSFunction()) { |
467 Node* target_function = | 458 Node* target_function = |
468 jsgraph()->Constant(handle(cell->value(), isolate())); | 459 jsgraph()->Constant(handle(cell->value(), isolate())); |
469 | 460 |
470 // Check that the {target} is still the {target_function}. | 461 // Check that the {target} is still the {target_function}. |
471 Node* check = graph()->NewNode( | 462 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
472 javascript()->StrictEqual(CompareOperationHints::Any()), target, | 463 target, target_function); |
473 target_function, context); | 464 effect = |
474 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check, | 465 graph()->NewNode(simplified()->CheckIf(), check, effect, control); |
475 frame_state, effect, control); | |
476 | 466 |
477 // Specialize the JSCallConstruct node to the {target_function}. | 467 // Specialize the JSCallConstruct node to the {target_function}. |
478 NodeProperties::ReplaceValueInput(node, target_function, 0); | 468 NodeProperties::ReplaceValueInput(node, target_function, 0); |
479 NodeProperties::ReplaceEffectInput(node, effect); | 469 NodeProperties::ReplaceEffectInput(node, effect); |
480 NodeProperties::ReplaceControlInput(node, control); | |
481 if (target == new_target) { | 470 if (target == new_target) { |
482 NodeProperties::ReplaceValueInput(node, target_function, arity + 1); | 471 NodeProperties::ReplaceValueInput(node, target_function, arity + 1); |
483 } | 472 } |
484 | 473 |
485 // Try to further reduce the JSCallConstruct {node}. | 474 // Try to further reduce the JSCallConstruct {node}. |
486 Reduction const reduction = ReduceJSCallConstruct(node); | 475 Reduction const reduction = ReduceJSCallConstruct(node); |
487 return reduction.Changed() ? reduction : Changed(node); | 476 return reduction.Changed() ? reduction : Changed(node); |
488 } | 477 } |
489 } | 478 } |
490 | 479 |
(...skipping 16 matching lines...) Expand all Loading... |
507 | 496 |
508 CommonOperatorBuilder* JSCallReducer::common() const { | 497 CommonOperatorBuilder* JSCallReducer::common() const { |
509 return jsgraph()->common(); | 498 return jsgraph()->common(); |
510 } | 499 } |
511 | 500 |
512 | 501 |
513 JSOperatorBuilder* JSCallReducer::javascript() const { | 502 JSOperatorBuilder* JSCallReducer::javascript() const { |
514 return jsgraph()->javascript(); | 503 return jsgraph()->javascript(); |
515 } | 504 } |
516 | 505 |
| 506 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
| 507 return jsgraph()->simplified(); |
| 508 } |
| 509 |
517 } // namespace compiler | 510 } // namespace compiler |
518 } // namespace internal | 511 } // namespace internal |
519 } // namespace v8 | 512 } // namespace v8 |
OLD | NEW |