| 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/interpreter/interpreter-assembler.h" | 5 #include "src/interpreter/interpreter-assembler.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <ostream> | 8 #include <ostream> |
| 9 | 9 |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 | 580 |
| 581 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); | 581 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |
| 582 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == | 582 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |
| 583 WeakCell::kValueOffset && | 583 WeakCell::kValueOffset && |
| 584 WeakCell::kValueOffset == Symbol::kHashFieldSlot); | 584 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
| 585 | 585 |
| 586 Variable return_value(this, MachineRepresentation::kTagged); | 586 Variable return_value(this, MachineRepresentation::kTagged); |
| 587 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), | 587 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), |
| 588 end(this); | 588 end(this); |
| 589 | 589 |
| 590 // Increment the call count. |
| 591 IncrementCallCount(feedback_vector, slot_id); |
| 592 |
| 590 // The checks. First, does function match the recorded monomorphic target? | 593 // The checks. First, does function match the recorded monomorphic target? |
| 591 Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id); | 594 Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id); |
| 592 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 595 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
| 593 Node* is_monomorphic = WordEqual(function, feedback_value); | 596 Node* is_monomorphic = WordEqual(function, feedback_value); |
| 594 GotoIfNot(is_monomorphic, &extra_checks); | 597 GotoIfNot(is_monomorphic, &extra_checks); |
| 595 | 598 |
| 596 // The compare above could have been a SMI/SMI comparison. Guard against | 599 // The compare above could have been a SMI/SMI comparison. Guard against |
| 597 // this convincing us that we have a monomorphic JSFunction. | 600 // this convincing us that we have a monomorphic JSFunction. |
| 598 Node* is_smi = TaggedIsSmi(function); | 601 Node* is_smi = TaggedIsSmi(function); |
| 599 Branch(is_smi, &extra_checks, &call_function); | 602 Branch(is_smi, &extra_checks, &call_function); |
| 600 | 603 |
| 601 BIND(&call_function); | 604 BIND(&call_function); |
| 602 { | 605 { |
| 603 // Increment the call count. | |
| 604 IncrementCallCount(feedback_vector, slot_id); | |
| 605 | |
| 606 // Call using call function builtin. | 606 // Call using call function builtin. |
| 607 Callable callable = CodeFactory::InterpreterPushArgsThenCall( | 607 Callable callable = CodeFactory::InterpreterPushArgsThenCall( |
| 608 isolate(), receiver_mode, tail_call_mode, | 608 isolate(), receiver_mode, tail_call_mode, |
| 609 InterpreterPushArgsMode::kJSFunction); | 609 InterpreterPushArgsMode::kJSFunction); |
| 610 Node* code_target = HeapConstant(callable.code()); | 610 Node* code_target = HeapConstant(callable.code()); |
| 611 Node* ret_value = CallStub(callable.descriptor(), code_target, context, | 611 Node* ret_value = CallStub(callable.descriptor(), code_target, context, |
| 612 arg_count, first_arg, function); | 612 arg_count, first_arg, function); |
| 613 return_value.Bind(ret_value); | 613 return_value.Bind(ret_value); |
| 614 Goto(&end); | 614 Goto(&end); |
| 615 } | 615 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 633 // For undefined receivers (mostly global calls), do an additional check | 633 // For undefined receivers (mostly global calls), do an additional check |
| 634 // for the monomorphic Array function, which would otherwise appear | 634 // for the monomorphic Array function, which would otherwise appear |
| 635 // megamorphic. | 635 // megamorphic. |
| 636 | 636 |
| 637 // If it is not the Array() function, mark megamorphic. | 637 // If it is not the Array() function, mark megamorphic. |
| 638 Node* context_slot = LoadContextElement(LoadNativeContext(context), | 638 Node* context_slot = LoadContextElement(LoadNativeContext(context), |
| 639 Context::ARRAY_FUNCTION_INDEX); | 639 Context::ARRAY_FUNCTION_INDEX); |
| 640 Node* is_array_function = WordEqual(context_slot, function); | 640 Node* is_array_function = WordEqual(context_slot, function); |
| 641 GotoIfNot(is_array_function, &mark_megamorphic); | 641 GotoIfNot(is_array_function, &mark_megamorphic); |
| 642 | 642 |
| 643 // It is a monomorphic Array function. Increment the call count. | |
| 644 IncrementCallCount(feedback_vector, slot_id); | |
| 645 | |
| 646 // Call ArrayConstructorStub. | 643 // Call ArrayConstructorStub. |
| 647 Callable callable_call = | 644 Callable callable_call = |
| 648 CodeFactory::InterpreterPushArgsThenConstructArray(isolate()); | 645 CodeFactory::InterpreterPushArgsThenConstructArray(isolate()); |
| 649 Node* code_target_call = HeapConstant(callable_call.code()); | 646 Node* code_target_call = HeapConstant(callable_call.code()); |
| 650 Node* ret_value = | 647 Node* ret_value = |
| 651 CallStub(callable_call.descriptor(), code_target_call, context, | 648 CallStub(callable_call.descriptor(), code_target_call, context, |
| 652 arg_count, function, feedback_element, first_arg); | 649 arg_count, function, feedback_element, first_arg); |
| 653 return_value.Bind(ret_value); | 650 return_value.Bind(ret_value); |
| 654 Goto(&end); | 651 Goto(&end); |
| 655 | 652 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 StoreFixedArrayElement( | 713 StoreFixedArrayElement( |
| 717 feedback_vector, slot_id, | 714 feedback_vector, slot_id, |
| 718 HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())), | 715 HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())), |
| 719 SKIP_WRITE_BARRIER); | 716 SKIP_WRITE_BARRIER); |
| 720 Goto(&call); | 717 Goto(&call); |
| 721 } | 718 } |
| 722 } | 719 } |
| 723 | 720 |
| 724 BIND(&call); | 721 BIND(&call); |
| 725 { | 722 { |
| 726 Comment("Increment call count and call using Call builtin"); | 723 Comment("invoke using Call builtin"); |
| 727 // Increment the call count. | |
| 728 IncrementCallCount(feedback_vector, slot_id); | |
| 729 | |
| 730 // Call using call builtin. | 724 // Call using call builtin. |
| 731 Callable callable_call = CodeFactory::InterpreterPushArgsThenCall( | 725 Callable callable_call = CodeFactory::InterpreterPushArgsThenCall( |
| 732 isolate(), receiver_mode, tail_call_mode, | 726 isolate(), receiver_mode, tail_call_mode, |
| 733 InterpreterPushArgsMode::kOther); | 727 InterpreterPushArgsMode::kOther); |
| 734 Node* code_target_call = HeapConstant(callable_call.code()); | 728 Node* code_target_call = HeapConstant(callable_call.code()); |
| 735 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, | 729 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, |
| 736 context, arg_count, first_arg, function); | 730 context, arg_count, first_arg, function); |
| 737 return_value.Bind(ret_value); | 731 return_value.Bind(ret_value); |
| 738 Goto(&end); | 732 Goto(&end); |
| 739 } | 733 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 Node* InterpreterAssembler::Construct(Node* constructor, Node* context, | 769 Node* InterpreterAssembler::Construct(Node* constructor, Node* context, |
| 776 Node* new_target, Node* first_arg, | 770 Node* new_target, Node* first_arg, |
| 777 Node* arg_count, Node* slot_id, | 771 Node* arg_count, Node* slot_id, |
| 778 Node* feedback_vector) { | 772 Node* feedback_vector) { |
| 779 DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); | 773 DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); |
| 780 Variable return_value(this, MachineRepresentation::kTagged); | 774 Variable return_value(this, MachineRepresentation::kTagged); |
| 781 Variable allocation_feedback(this, MachineRepresentation::kTagged); | 775 Variable allocation_feedback(this, MachineRepresentation::kTagged); |
| 782 Label call_construct_function(this, &allocation_feedback), | 776 Label call_construct_function(this, &allocation_feedback), |
| 783 extra_checks(this, Label::kDeferred), call_construct(this), end(this); | 777 extra_checks(this, Label::kDeferred), call_construct(this), end(this); |
| 784 | 778 |
| 785 // Slot id of 0 is used to indicate no type feedback is available. | 779 // Increment the call count. |
| 786 STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); | 780 IncrementCallCount(feedback_vector, slot_id); |
| 787 Node* is_feedback_unavailable = WordEqual(slot_id, IntPtrConstant(0)); | |
| 788 GotoIf(is_feedback_unavailable, &call_construct); | |
| 789 | 781 |
| 790 // Check that the constructor is not a smi. | 782 // Check that the constructor is not a smi. |
| 791 Node* is_smi = TaggedIsSmi(constructor); | 783 Node* is_smi = TaggedIsSmi(constructor); |
| 792 GotoIf(is_smi, &call_construct); | 784 GotoIf(is_smi, &call_construct); |
| 793 | 785 |
| 794 // Check that constructor is a JSFunction. | 786 // Check that constructor is a JSFunction. |
| 795 Node* instance_type = LoadInstanceType(constructor); | 787 Node* instance_type = LoadInstanceType(constructor); |
| 796 Node* is_js_function = | 788 Node* is_js_function = |
| 797 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 789 Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
| 798 GotoIfNot(is_js_function, &call_construct); | 790 GotoIfNot(is_js_function, &call_construct); |
| 799 | 791 |
| 800 // Check if it is a monomorphic constructor. | 792 // Check if it is a monomorphic constructor. |
| 801 Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id); | 793 Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id); |
| 802 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 794 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
| 803 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 795 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
| 804 allocation_feedback.Bind(UndefinedConstant()); | 796 allocation_feedback.Bind(UndefinedConstant()); |
| 805 Branch(is_monomorphic, &call_construct_function, &extra_checks); | 797 Branch(is_monomorphic, &call_construct_function, &extra_checks); |
| 806 | 798 |
| 807 BIND(&call_construct_function); | 799 BIND(&call_construct_function); |
| 808 { | 800 { |
| 809 Comment("call using ConstructFunction"); | 801 Comment("construct using ConstructFunction"); |
| 810 IncrementCallCount(feedback_vector, slot_id); | |
| 811 Callable callable_function = CodeFactory::InterpreterPushArgsThenConstruct( | 802 Callable callable_function = CodeFactory::InterpreterPushArgsThenConstruct( |
| 812 isolate(), InterpreterPushArgsMode::kJSFunction); | 803 isolate(), InterpreterPushArgsMode::kJSFunction); |
| 813 return_value.Bind(CallStub(callable_function.descriptor(), | 804 return_value.Bind(CallStub(callable_function.descriptor(), |
| 814 HeapConstant(callable_function.code()), context, | 805 HeapConstant(callable_function.code()), context, |
| 815 arg_count, new_target, constructor, | 806 arg_count, new_target, constructor, |
| 816 allocation_feedback.value(), first_arg)); | 807 allocation_feedback.value(), first_arg)); |
| 817 Goto(&end); | 808 Goto(&end); |
| 818 } | 809 } |
| 819 | 810 |
| 820 BIND(&extra_checks); | 811 BIND(&extra_checks); |
| (...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 return array; | 1459 return array; |
| 1469 } | 1460 } |
| 1470 | 1461 |
| 1471 int InterpreterAssembler::CurrentBytecodeSize() const { | 1462 int InterpreterAssembler::CurrentBytecodeSize() const { |
| 1472 return Bytecodes::Size(bytecode_, operand_scale_); | 1463 return Bytecodes::Size(bytecode_, operand_scale_); |
| 1473 } | 1464 } |
| 1474 | 1465 |
| 1475 } // namespace interpreter | 1466 } // namespace interpreter |
| 1476 } // namespace internal | 1467 } // namespace internal |
| 1477 } // namespace v8 | 1468 } // namespace v8 |
| OLD | NEW |