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 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 Node* stack_pointer_after_call = LoadStackPointer(); | 485 Node* stack_pointer_after_call = LoadStackPointer(); |
486 Node* stack_pointer_before_call = stack_pointer_before_call_; | 486 Node* stack_pointer_before_call = stack_pointer_before_call_; |
487 stack_pointer_before_call_ = nullptr; | 487 stack_pointer_before_call_ = nullptr; |
488 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, | 488 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call, |
489 kUnexpectedStackPointer); | 489 kUnexpectedStackPointer); |
490 } | 490 } |
491 } | 491 } |
492 | 492 |
493 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, | 493 Node* InterpreterAssembler::IncrementCallCount(Node* type_feedback_vector, |
494 Node* slot_id) { | 494 Node* slot_id) { |
| 495 Comment("increment call count"); |
495 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); | 496 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); |
496 Node* call_count = | 497 Node* call_count = |
497 LoadFixedArrayElement(type_feedback_vector, call_count_slot); | 498 LoadFixedArrayElement(type_feedback_vector, call_count_slot); |
498 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); | 499 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); |
499 // Count is Smi, so we don't need a write barrier. | 500 // Count is Smi, so we don't need a write barrier. |
500 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, | 501 return StoreFixedArrayElement(type_feedback_vector, call_count_slot, |
501 new_count, SKIP_WRITE_BARRIER); | 502 new_count, SKIP_WRITE_BARRIER); |
502 } | 503 } |
503 | 504 |
504 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, | 505 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 Node* is_js_function = | 742 Node* is_js_function = |
742 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 743 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
743 BranchIf(is_js_function, &js_function, &call_construct); | 744 BranchIf(is_js_function, &js_function, &call_construct); |
744 | 745 |
745 Bind(&js_function); | 746 Bind(&js_function); |
746 { | 747 { |
747 // Cache the called function in a feedback vector slot. Cache states | 748 // Cache the called function in a feedback vector slot. Cache states |
748 // are uninitialized, monomorphic (indicated by a JSFunction), and | 749 // are uninitialized, monomorphic (indicated by a JSFunction), and |
749 // megamorphic. | 750 // megamorphic. |
750 // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a | 751 // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a |
751 // deferred block so that call_construct_function will be scheduled just | 752 // deferred block so that call_construct_function will be scheduled. |
752 // after increment_count and in the fast path we can reduce one branch in | 753 Label extra_checks(this), call_construct_function(this); |
753 // the | |
754 // fast path. | |
755 Label increment_count(this), extra_checks(this), | |
756 call_construct_function(this); | |
757 | 754 |
758 Node* feedback_element = | 755 Node* feedback_element = |
759 LoadFixedArrayElement(type_feedback_vector, slot_id); | 756 LoadFixedArrayElement(type_feedback_vector, slot_id); |
760 Node* feedback_value = LoadWeakCellValue(feedback_element); | 757 Node* feedback_value = LoadWeakCellValue(feedback_element); |
761 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 758 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
762 BranchIf(is_monomorphic, &increment_count, &extra_checks); | 759 BranchIf(is_monomorphic, &call_construct_function, &extra_checks); |
763 | 760 |
764 Bind(&extra_checks); | 761 Bind(&extra_checks); |
765 { | 762 { |
766 Label mark_megamorphic(this), initialize(this), | 763 Label mark_megamorphic(this), initialize(this), |
767 check_allocation_site(this), check_initialized(this), | 764 check_allocation_site(this), check_initialized(this), |
768 set_alloc_feedback_and_inc_count(this); | 765 set_alloc_feedback_and_call(this); |
769 { | 766 { |
770 // Check if it is a megamorphic target | 767 // Check if it is a megamorphic target |
771 Comment("check if megamorphic"); | 768 Comment("check if megamorphic"); |
772 Node* is_megamorphic = WordEqual( | 769 Node* is_megamorphic = WordEqual( |
773 feedback_element, | 770 feedback_element, |
774 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 771 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
775 GotoIf(is_megamorphic, &call_construct_function); | 772 GotoIf(is_megamorphic, &call_construct_function); |
776 | 773 |
777 Comment("check if weak cell"); | 774 Comment("check if weak cell"); |
778 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), | 775 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), |
(...skipping 12 matching lines...) Expand all Loading... |
791 Node* is_allocation_site = | 788 Node* is_allocation_site = |
792 WordEqual(LoadObjectField(feedback_element, 0), | 789 WordEqual(LoadObjectField(feedback_element, 0), |
793 LoadRoot(Heap::kAllocationSiteMapRootIndex)); | 790 LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
794 GotoUnless(is_allocation_site, &check_initialized); | 791 GotoUnless(is_allocation_site, &check_initialized); |
795 | 792 |
796 // Make sure the function is the Array() function | 793 // Make sure the function is the Array() function |
797 Node* context_slot = | 794 Node* context_slot = |
798 LoadFixedArrayElement(LoadNativeContext(context), | 795 LoadFixedArrayElement(LoadNativeContext(context), |
799 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 796 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
800 Node* is_array_function = WordEqual(context_slot, constructor); | 797 Node* is_array_function = WordEqual(context_slot, constructor); |
801 BranchIf(is_array_function, &set_alloc_feedback_and_inc_count, | 798 BranchIf(is_array_function, &set_alloc_feedback_and_call, |
802 &mark_megamorphic); | 799 &mark_megamorphic); |
803 } | 800 } |
804 | 801 |
805 Bind(&set_alloc_feedback_and_inc_count); | 802 Bind(&set_alloc_feedback_and_call); |
806 { | 803 { |
807 allocation_feedback.Bind(feedback_element); | 804 allocation_feedback.Bind(feedback_element); |
808 Goto(&increment_count); | 805 Goto(&call_construct_function); |
809 } | 806 } |
810 | 807 |
811 Bind(&check_initialized); | 808 Bind(&check_initialized); |
812 { | 809 { |
813 // Check if it is uninitialized. | 810 // Check if it is uninitialized. |
814 Comment("check if uninitialized"); | 811 Comment("check if uninitialized"); |
815 Node* is_uninitialized = WordEqual( | 812 Node* is_uninitialized = WordEqual( |
816 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); | 813 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); |
817 BranchIf(is_uninitialized, &initialize, &mark_megamorphic); | 814 BranchIf(is_uninitialized, &initialize, &mark_megamorphic); |
818 } | 815 } |
819 | 816 |
820 Bind(&initialize); | 817 Bind(&initialize); |
821 { | 818 { |
822 Label initialize_count(this), create_weak_cell(this), | 819 Label create_weak_cell(this), create_allocation_site(this); |
823 create_allocation_site(this); | |
824 Comment("initialize the feedback element"); | 820 Comment("initialize the feedback element"); |
825 // Check that it is the Array() function. | 821 // Check that it is the Array() function. |
826 Node* context_slot = | 822 Node* context_slot = |
827 LoadFixedArrayElement(LoadNativeContext(context), | 823 LoadFixedArrayElement(LoadNativeContext(context), |
828 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 824 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
829 Node* is_array_function = WordEqual(context_slot, constructor); | 825 Node* is_array_function = WordEqual(context_slot, constructor); |
830 BranchIf(is_array_function, &create_allocation_site, &create_weak_cell); | 826 BranchIf(is_array_function, &create_allocation_site, &create_weak_cell); |
831 | 827 |
832 Bind(&create_allocation_site); | 828 Bind(&create_allocation_site); |
833 { | 829 { |
834 // TODO(mythria): Inline the creation of allocation site. | 830 // TODO(mythria): Inline the creation of allocation site. |
835 CreateAllocationSiteStub create_stub(isolate()); | 831 CreateAllocationSiteStub create_stub(isolate()); |
836 CallStub(create_stub.GetCallInterfaceDescriptor(), | 832 CallStub(create_stub.GetCallInterfaceDescriptor(), |
837 HeapConstant(create_stub.GetCode()), context, | 833 HeapConstant(create_stub.GetCode()), context, |
838 type_feedback_vector, SmiTag(slot_id)); | 834 type_feedback_vector, SmiTag(slot_id)); |
839 Node* feedback_element = | 835 Node* feedback_element = |
840 LoadFixedArrayElement(type_feedback_vector, slot_id); | 836 LoadFixedArrayElement(type_feedback_vector, slot_id); |
841 allocation_feedback.Bind(feedback_element); | 837 allocation_feedback.Bind(feedback_element); |
842 Goto(&initialize_count); | 838 Goto(&call_construct_function); |
843 } | 839 } |
844 | 840 |
845 Bind(&create_weak_cell); | 841 Bind(&create_weak_cell); |
846 { | 842 { |
847 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), | 843 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), |
848 constructor); | 844 constructor); |
849 Goto(&initialize_count); | |
850 } | |
851 | |
852 Bind(&initialize_count); | |
853 { | |
854 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); | |
855 // Count is Smi, so we don't need a write barrier. | |
856 StoreFixedArrayElement(type_feedback_vector, call_count_slot, | |
857 SmiTag(Int32Constant(1)), SKIP_WRITE_BARRIER); | |
858 Goto(&call_construct_function); | 845 Goto(&call_construct_function); |
859 } | 846 } |
860 } | 847 } |
861 | 848 |
862 Bind(&mark_megamorphic); | 849 Bind(&mark_megamorphic); |
863 { | 850 { |
864 // MegamorphicSentinel is an immortal immovable object so | 851 // MegamorphicSentinel is an immortal immovable object so |
865 // write-barrier is not needed. | 852 // write-barrier is not needed. |
866 Comment("transition to megamorphic"); | 853 Comment("transition to megamorphic"); |
867 DCHECK( | 854 DCHECK( |
868 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 855 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
869 StoreFixedArrayElement( | 856 StoreFixedArrayElement( |
870 type_feedback_vector, slot_id, | 857 type_feedback_vector, slot_id, |
871 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 858 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
872 SKIP_WRITE_BARRIER); | 859 SKIP_WRITE_BARRIER); |
873 Goto(&call_construct_function); | 860 Goto(&call_construct_function); |
874 } | 861 } |
875 } | 862 } |
876 | 863 |
877 Bind(&increment_count); | |
878 { | |
879 // Increment the call count. | |
880 Comment("increment call count"); | |
881 Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1)); | |
882 Node* call_count = | |
883 LoadFixedArrayElement(type_feedback_vector, call_count_slot); | |
884 Node* new_count = SmiAdd(call_count, SmiTag(Int32Constant(1))); | |
885 // Count is Smi, so we don't need a write barrier. | |
886 StoreFixedArrayElement(type_feedback_vector, call_count_slot, new_count, | |
887 SKIP_WRITE_BARRIER); | |
888 Goto(&call_construct_function); | |
889 } | |
890 | |
891 Bind(&call_construct_function); | 864 Bind(&call_construct_function); |
892 { | 865 { |
893 Comment("call using callConstructFunction"); | 866 Comment("call using callConstructFunction"); |
| 867 IncrementCallCount(type_feedback_vector, slot_id); |
894 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( | 868 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
895 isolate(), CallableType::kJSFunction); | 869 isolate(), CallableType::kJSFunction); |
896 return_value.Bind(CallStub(callable_function.descriptor(), | 870 return_value.Bind(CallStub(callable_function.descriptor(), |
897 HeapConstant(callable_function.code()), | 871 HeapConstant(callable_function.code()), |
898 context, arg_count, new_target, constructor, | 872 context, arg_count, new_target, constructor, |
899 allocation_feedback.value(), first_arg)); | 873 allocation_feedback.value(), first_arg)); |
900 Goto(&end); | 874 Goto(&end); |
901 } | 875 } |
902 } | 876 } |
903 | 877 |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 Goto(&loop); | 1333 Goto(&loop); |
1360 } | 1334 } |
1361 Bind(&done_loop); | 1335 Bind(&done_loop); |
1362 | 1336 |
1363 return array; | 1337 return array; |
1364 } | 1338 } |
1365 | 1339 |
1366 } // namespace interpreter | 1340 } // namespace interpreter |
1367 } // namespace internal | 1341 } // namespace internal |
1368 } // namespace v8 | 1342 } // namespace v8 |
OLD | NEW |