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 |