Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: src/interpreter/interpreter-assembler.cc

Issue 2333243004: CallConstruct also gets call count information if megamorphic. (Closed)
Patch Set: Compile/runtime fixes. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698