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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not | 539 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not |
540 // computed, meaning that it can't appear to be a pointer. If the low bit is | 540 // computed, meaning that it can't appear to be a pointer. If the low bit is |
541 // 0, then hash is computed, but the 0 bit prevents the field from appearing | 541 // 0, then hash is computed, but the 0 bit prevents the field from appearing |
542 // to be a pointer. | 542 // to be a pointer. |
543 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); | 543 STATIC_ASSERT(WeakCell::kSize >= kPointerSize); |
544 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == | 544 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == |
545 WeakCell::kValueOffset && | 545 WeakCell::kValueOffset && |
546 WeakCell::kValueOffset == Symbol::kHashFieldSlot); | 546 WeakCell::kValueOffset == Symbol::kHashFieldSlot); |
547 | 547 |
548 Variable return_value(this, MachineRepresentation::kTagged); | 548 Variable return_value(this, MachineRepresentation::kTagged); |
549 Label handle_monomorphic(this), extra_checks(this), end(this), call(this), | 549 Label call_function(this), extra_checks(this, Label::kDeferred), call(this), |
550 call_function(this); | 550 end(this); |
551 | 551 |
552 // The checks. First, does function match the recorded monomorphic target? | 552 // The checks. First, does function match the recorded monomorphic target? |
553 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 553 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); |
554 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 554 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
555 Node* is_monomorphic = WordEqual(function, feedback_value); | 555 Node* is_monomorphic = WordEqual(function, feedback_value); |
556 Branch(is_monomorphic, &handle_monomorphic, &extra_checks); | 556 GotoUnless(is_monomorphic, &extra_checks); |
557 | 557 |
558 Bind(&handle_monomorphic); | 558 // The compare above could have been a SMI/SMI comparison. Guard against |
| 559 // this convincing us that we have a monomorphic JSFunction. |
| 560 Node* is_smi = TaggedIsSmi(function); |
| 561 Branch(is_smi, &extra_checks, &call_function); |
| 562 |
| 563 Bind(&call_function); |
559 { | 564 { |
560 // The compare above could have been a SMI/SMI comparison. Guard against | |
561 // this convincing us that we have a monomorphic JSFunction. | |
562 Node* is_smi = TaggedIsSmi(function); | |
563 GotoIf(is_smi, &extra_checks); | |
564 | |
565 // Increment the call count. | 565 // Increment the call count. |
566 IncrementCallCount(type_feedback_vector, slot_id); | 566 IncrementCallCount(type_feedback_vector, slot_id); |
567 | 567 |
568 // Call using call function builtin. | 568 // Call using call function builtin. |
569 Callable callable = CodeFactory::InterpreterPushArgsAndCall( | 569 Callable callable = CodeFactory::InterpreterPushArgsAndCall( |
570 isolate(), tail_call_mode, CallableType::kJSFunction); | 570 isolate(), tail_call_mode, CallableType::kJSFunction); |
571 Node* code_target = HeapConstant(callable.code()); | 571 Node* code_target = HeapConstant(callable.code()); |
572 Node* ret_value = CallStub(callable.descriptor(), code_target, context, | 572 Node* ret_value = CallStub(callable.descriptor(), code_target, context, |
573 arg_count, first_arg, function); | 573 arg_count, first_arg, function); |
574 return_value.Bind(ret_value); | 574 return_value.Bind(ret_value); |
575 Goto(&end); | 575 Goto(&end); |
576 } | 576 } |
577 | 577 |
578 Bind(&extra_checks); | 578 Bind(&extra_checks); |
579 { | 579 { |
580 Label check_initialized(this, Label::kDeferred), mark_megamorphic(this), | 580 Label check_initialized(this), mark_megamorphic(this), |
581 check_allocation_site(this), | 581 create_allocation_site(this); |
582 create_allocation_site(this, Label::kDeferred); | 582 |
583 // Check if it is a megamorphic target | 583 Comment("check if megamorphic"); |
| 584 // Check if it is a megamorphic target. |
584 Node* is_megamorphic = WordEqual( | 585 Node* is_megamorphic = WordEqual( |
585 feedback_element, | 586 feedback_element, |
586 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 587 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
587 Branch(is_megamorphic, &call, &check_allocation_site); | 588 GotoIf(is_megamorphic, &call); |
588 | 589 |
589 Bind(&check_allocation_site); | 590 Comment("check if it is an allocation site"); |
590 { | 591 Node* is_allocation_site = WordEqual( |
591 Node* is_allocation_site = | 592 LoadMap(feedback_element), LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
592 WordEqual(LoadMap(feedback_element), | 593 GotoUnless(is_allocation_site, &check_initialized); |
593 LoadRoot(Heap::kAllocationSiteMapRootIndex)); | |
594 GotoUnless(is_allocation_site, &check_initialized); | |
595 | 594 |
596 // If it is not the Array() function, mark megamorphic. | 595 // If it is not the Array() function, mark megamorphic. |
597 Node* context_slot = | 596 Node* context_slot = |
598 LoadFixedArrayElement(LoadNativeContext(context), | 597 LoadFixedArrayElement(LoadNativeContext(context), |
599 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 598 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
600 Node* is_array_function = WordEqual(context_slot, function); | 599 Node* is_array_function = WordEqual(context_slot, function); |
601 GotoUnless(is_array_function, &mark_megamorphic); | 600 GotoUnless(is_array_function, &mark_megamorphic); |
602 | 601 |
603 // It is a monomorphic Array function. Increment the call count. | 602 // It is a monomorphic Array function. Increment the call count. |
604 IncrementCallCount(type_feedback_vector, slot_id); | 603 IncrementCallCount(type_feedback_vector, slot_id); |
605 | 604 |
606 // Call ArrayConstructorStub. | 605 // Call ArrayConstructorStub. |
607 Callable callable_call = | 606 Callable callable_call = |
608 CodeFactory::InterpreterPushArgsAndConstructArray(isolate()); | 607 CodeFactory::InterpreterPushArgsAndConstructArray(isolate()); |
609 Node* code_target_call = HeapConstant(callable_call.code()); | 608 Node* code_target_call = HeapConstant(callable_call.code()); |
610 Node* ret_value = | 609 Node* ret_value = |
611 CallStub(callable_call.descriptor(), code_target_call, context, | 610 CallStub(callable_call.descriptor(), code_target_call, context, |
612 arg_count, function, feedback_element, first_arg); | 611 arg_count, function, feedback_element, first_arg); |
613 return_value.Bind(ret_value); | 612 return_value.Bind(ret_value); |
614 Goto(&end); | 613 Goto(&end); |
615 } | |
616 | 614 |
617 Bind(&check_initialized); | 615 Bind(&check_initialized); |
618 { | 616 { |
619 Label possibly_monomorphic(this); | 617 Comment("check if uninitialized"); |
620 // Check if it is uninitialized. | 618 // Check if it is uninitialized target first. |
621 Node* is_uninitialized = WordEqual( | 619 Node* is_uninitialized = WordEqual( |
622 feedback_element, | 620 feedback_element, |
623 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate()))); | 621 HeapConstant(TypeFeedbackVector::UninitializedSentinel(isolate()))); |
624 GotoUnless(is_uninitialized, &mark_megamorphic); | 622 GotoUnless(is_uninitialized, &mark_megamorphic); |
625 | 623 |
| 624 Comment("handle_unitinitialized"); |
| 625 // If it is not a JSFunction mark it as megamorphic. |
626 Node* is_smi = TaggedIsSmi(function); | 626 Node* is_smi = TaggedIsSmi(function); |
627 GotoIf(is_smi, &mark_megamorphic); | 627 GotoIf(is_smi, &mark_megamorphic); |
628 | 628 |
629 // Check if function is an object of JSFunction type | 629 // Check if function is an object of JSFunction type. |
630 Node* instance_type = LoadInstanceType(function); | 630 Node* instance_type = LoadInstanceType(function); |
631 Node* is_js_function = | 631 Node* is_js_function = |
632 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 632 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
633 GotoUnless(is_js_function, &mark_megamorphic); | 633 GotoUnless(is_js_function, &mark_megamorphic); |
634 | 634 |
635 // Check if it is the Array() function. | 635 // Check if it is the Array() function. |
636 Node* context_slot = | 636 Node* context_slot = |
637 LoadFixedArrayElement(LoadNativeContext(context), | 637 LoadFixedArrayElement(LoadNativeContext(context), |
638 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 638 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
639 Node* is_array_function = WordEqual(context_slot, function); | 639 Node* is_array_function = WordEqual(context_slot, function); |
640 GotoIf(is_array_function, &create_allocation_site); | 640 GotoIf(is_array_function, &create_allocation_site); |
641 | 641 |
642 // Check if the function belongs to the same native context | 642 // Check if the function belongs to the same native context. |
643 Node* native_context = LoadNativeContext( | 643 Node* native_context = LoadNativeContext( |
644 LoadObjectField(function, JSFunction::kContextOffset)); | 644 LoadObjectField(function, JSFunction::kContextOffset)); |
645 Node* is_same_native_context = | 645 Node* is_same_native_context = |
646 WordEqual(native_context, LoadNativeContext(context)); | 646 WordEqual(native_context, LoadNativeContext(context)); |
647 GotoUnless(is_same_native_context, &mark_megamorphic); | 647 GotoUnless(is_same_native_context, &mark_megamorphic); |
648 | 648 |
649 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), | 649 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), |
650 function); | 650 function); |
651 | 651 |
652 // Call using call function builtin. | 652 // Call using call function builtin. |
(...skipping 18 matching lines...) Expand all Loading... |
671 // and will not move during a GC. So it is safe to skip write barrier. | 671 // and will not move during a GC. So it is safe to skip write barrier. |
672 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | 672 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
673 StoreFixedArrayElement( | 673 StoreFixedArrayElement( |
674 type_feedback_vector, slot_id, | 674 type_feedback_vector, slot_id, |
675 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | 675 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
676 SKIP_WRITE_BARRIER); | 676 SKIP_WRITE_BARRIER); |
677 Goto(&call); | 677 Goto(&call); |
678 } | 678 } |
679 } | 679 } |
680 | 680 |
681 Bind(&call_function); | |
682 { | |
683 // Increment the call count. | |
684 IncrementCallCount(type_feedback_vector, slot_id); | |
685 | |
686 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( | |
687 isolate(), tail_call_mode, CallableType::kJSFunction); | |
688 Node* code_target_call = HeapConstant(callable_call.code()); | |
689 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, | |
690 context, arg_count, first_arg, function); | |
691 return_value.Bind(ret_value); | |
692 Goto(&end); | |
693 } | |
694 | |
695 Bind(&call); | 681 Bind(&call); |
696 { | 682 { |
| 683 Comment("Increment call count and call using Call builtin"); |
697 // Increment the call count. | 684 // Increment the call count. |
698 IncrementCallCount(type_feedback_vector, slot_id); | 685 IncrementCallCount(type_feedback_vector, slot_id); |
699 | 686 |
700 // Call using call builtin. | 687 // Call using call builtin. |
701 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( | 688 Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( |
702 isolate(), tail_call_mode, CallableType::kAny); | 689 isolate(), tail_call_mode, CallableType::kAny); |
703 Node* code_target_call = HeapConstant(callable_call.code()); | 690 Node* code_target_call = HeapConstant(callable_call.code()); |
704 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, | 691 Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, |
705 context, arg_count, first_arg, function); | 692 context, arg_count, first_arg, function); |
706 return_value.Bind(ret_value); | 693 return_value.Bind(ret_value); |
(...skipping 11 matching lines...) Expand all Loading... |
718 isolate(), tail_call_mode, CallableType::kAny); | 705 isolate(), tail_call_mode, CallableType::kAny); |
719 Node* code_target = HeapConstant(callable.code()); | 706 Node* code_target = HeapConstant(callable.code()); |
720 return CallStub(callable.descriptor(), code_target, context, arg_count, | 707 return CallStub(callable.descriptor(), code_target, context, arg_count, |
721 first_arg, function); | 708 first_arg, function); |
722 } | 709 } |
723 | 710 |
724 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, | 711 Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context, |
725 Node* new_target, Node* first_arg, | 712 Node* new_target, Node* first_arg, |
726 Node* arg_count, Node* slot_id, | 713 Node* arg_count, Node* slot_id, |
727 Node* type_feedback_vector) { | 714 Node* type_feedback_vector) { |
728 Label call_construct(this), js_function(this), end(this); | |
729 Variable return_value(this, MachineRepresentation::kTagged); | 715 Variable return_value(this, MachineRepresentation::kTagged); |
730 Variable allocation_feedback(this, MachineRepresentation::kTagged); | 716 Variable allocation_feedback(this, MachineRepresentation::kTagged); |
731 allocation_feedback.Bind(UndefinedConstant()); | 717 Label call_construct_function(this, &allocation_feedback), |
| 718 extra_checks(this, Label::kDeferred), call_construct(this), end(this); |
732 | 719 |
733 // Slot id of 0 is used to indicate no type feedback is available. | 720 // Slot id of 0 is used to indicate no type feedback is available. |
734 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 721 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
735 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); | 722 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); |
736 GotoIf(is_feedback_unavailable, &call_construct); | 723 GotoIf(is_feedback_unavailable, &call_construct); |
737 | 724 |
738 // Check that the constructor is not a smi. | 725 // Check that the constructor is not a smi. |
739 Node* is_smi = TaggedIsSmi(constructor); | 726 Node* is_smi = TaggedIsSmi(constructor); |
740 GotoIf(is_smi, &call_construct); | 727 GotoIf(is_smi, &call_construct); |
741 | 728 |
742 // Check that constructor is a JSFunction. | 729 // Check that constructor is a JSFunction. |
743 Node* instance_type = LoadInstanceType(constructor); | 730 Node* instance_type = LoadInstanceType(constructor); |
744 Node* is_js_function = | 731 Node* is_js_function = |
745 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 732 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
746 Branch(is_js_function, &js_function, &call_construct); | 733 GotoUnless(is_js_function, &call_construct); |
747 | 734 |
748 Bind(&js_function); | 735 // Check if it is a monomorphic constructor. |
| 736 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); |
| 737 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); |
| 738 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
| 739 allocation_feedback.Bind(UndefinedConstant()); |
| 740 Branch(is_monomorphic, &call_construct_function, &extra_checks); |
| 741 |
| 742 Bind(&call_construct_function); |
749 { | 743 { |
750 // Cache the called function in a feedback vector slot. Cache states | 744 Comment("call using callConstructFunction"); |
751 // are uninitialized, monomorphic (indicated by a JSFunction), and | 745 IncrementCallCount(type_feedback_vector, slot_id); |
752 // megamorphic. | 746 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( |
753 // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a | 747 isolate(), CallableType::kJSFunction); |
754 // deferred block so that call_construct_function will be scheduled. | 748 return_value.Bind(CallStub(callable_function.descriptor(), |
755 Label extra_checks(this), call_construct_function(this); | 749 HeapConstant(callable_function.code()), context, |
| 750 arg_count, new_target, constructor, |
| 751 allocation_feedback.value(), first_arg)); |
| 752 Goto(&end); |
| 753 } |
756 | 754 |
757 Node* feedback_element = | 755 Bind(&extra_checks); |
758 LoadFixedArrayElement(type_feedback_vector, slot_id); | 756 { |
759 Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element); | 757 Label check_allocation_site(this), check_initialized(this), |
760 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 758 initialize(this), mark_megamorphic(this); |
761 Branch(is_monomorphic, &call_construct_function, &extra_checks); | |
762 | 759 |
763 Bind(&extra_checks); | 760 // Check if it is a megamorphic target. |
| 761 Comment("check if megamorphic"); |
| 762 Node* is_megamorphic = WordEqual( |
| 763 feedback_element, |
| 764 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
| 765 GotoIf(is_megamorphic, &call_construct_function); |
| 766 |
| 767 Comment("check if weak cell"); |
| 768 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), |
| 769 LoadRoot(Heap::kWeakCellMapRootIndex)); |
| 770 GotoUnless(is_weak_cell, &check_allocation_site); |
| 771 |
| 772 // If the weak cell is cleared, we have a new chance to become |
| 773 // monomorphic. |
| 774 Comment("check if weak cell is cleared"); |
| 775 Node* is_smi = TaggedIsSmi(feedback_value); |
| 776 Branch(is_smi, &initialize, &mark_megamorphic); |
| 777 |
| 778 Bind(&check_allocation_site); |
764 { | 779 { |
765 Label mark_megamorphic(this), initialize(this), | 780 Comment("check if it is an allocation site"); |
766 check_allocation_site(this), check_initialized(this), | 781 Node* is_allocation_site = |
767 set_alloc_feedback_and_call(this); | 782 WordEqual(LoadObjectField(feedback_element, 0), |
| 783 LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
| 784 GotoUnless(is_allocation_site, &check_initialized); |
| 785 |
| 786 // Make sure the function is the Array() function. |
| 787 Node* context_slot = |
| 788 LoadFixedArrayElement(LoadNativeContext(context), |
| 789 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| 790 Node* is_array_function = WordEqual(context_slot, constructor); |
| 791 GotoUnless(is_array_function, &mark_megamorphic); |
| 792 |
| 793 allocation_feedback.Bind(feedback_element); |
| 794 Goto(&call_construct_function); |
| 795 } |
| 796 |
| 797 Bind(&check_initialized); |
| 798 { |
| 799 // Check if it is uninitialized. |
| 800 Comment("check if uninitialized"); |
| 801 Node* is_uninitialized = WordEqual( |
| 802 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); |
| 803 Branch(is_uninitialized, &initialize, &mark_megamorphic); |
| 804 } |
| 805 |
| 806 Bind(&initialize); |
| 807 { |
| 808 Label create_allocation_site(this), create_weak_cell(this); |
| 809 Comment("initialize the feedback element"); |
| 810 // Create an allocation site if the function is an array function, |
| 811 // otherwise create a weak cell. |
| 812 Node* context_slot = |
| 813 LoadFixedArrayElement(LoadNativeContext(context), |
| 814 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| 815 Node* is_array_function = WordEqual(context_slot, constructor); |
| 816 Branch(is_array_function, &create_allocation_site, &create_weak_cell); |
| 817 |
| 818 Bind(&create_allocation_site); |
768 { | 819 { |
769 // Check if it is a megamorphic target | 820 Node* site = CreateAllocationSiteInFeedbackVector(type_feedback_vector, |
770 Comment("check if megamorphic"); | 821 SmiTag(slot_id)); |
771 Node* is_megamorphic = WordEqual( | 822 allocation_feedback.Bind(site); |
772 feedback_element, | |
773 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | |
774 GotoIf(is_megamorphic, &call_construct_function); | |
775 | |
776 Comment("check if weak cell"); | |
777 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), | |
778 LoadRoot(Heap::kWeakCellMapRootIndex)); | |
779 GotoUnless(is_weak_cell, &check_allocation_site); | |
780 // If the weak cell is cleared, we have a new chance to become | |
781 // monomorphic. | |
782 Comment("check if weak cell is cleared"); | |
783 Node* is_smi = TaggedIsSmi(feedback_value); | |
784 Branch(is_smi, &initialize, &mark_megamorphic); | |
785 } | |
786 | |
787 Bind(&check_allocation_site); | |
788 { | |
789 Comment("check if it is an allocation site"); | |
790 Node* is_allocation_site = | |
791 WordEqual(LoadObjectField(feedback_element, 0), | |
792 LoadRoot(Heap::kAllocationSiteMapRootIndex)); | |
793 GotoUnless(is_allocation_site, &check_initialized); | |
794 | |
795 // Make sure the function is the Array() function | |
796 Node* context_slot = | |
797 LoadFixedArrayElement(LoadNativeContext(context), | |
798 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | |
799 Node* is_array_function = WordEqual(context_slot, constructor); | |
800 Branch(is_array_function, &set_alloc_feedback_and_call, | |
801 &mark_megamorphic); | |
802 } | |
803 | |
804 Bind(&set_alloc_feedback_and_call); | |
805 { | |
806 allocation_feedback.Bind(feedback_element); | |
807 Goto(&call_construct_function); | 823 Goto(&call_construct_function); |
808 } | 824 } |
809 | 825 |
810 Bind(&check_initialized); | 826 Bind(&create_weak_cell); |
811 { | 827 { |
812 // Check if it is uninitialized. | 828 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), |
813 Comment("check if uninitialized"); | 829 constructor); |
814 Node* is_uninitialized = WordEqual( | |
815 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); | |
816 Branch(is_uninitialized, &initialize, &mark_megamorphic); | |
817 } | |
818 | |
819 Bind(&initialize); | |
820 { | |
821 Label create_weak_cell(this), create_allocation_site(this); | |
822 Comment("initialize the feedback element"); | |
823 // Check that it is the Array() function. | |
824 Node* context_slot = | |
825 LoadFixedArrayElement(LoadNativeContext(context), | |
826 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | |
827 Node* is_array_function = WordEqual(context_slot, constructor); | |
828 Branch(is_array_function, &create_allocation_site, &create_weak_cell); | |
829 | |
830 Bind(&create_allocation_site); | |
831 { | |
832 Node* site = CreateAllocationSiteInFeedbackVector( | |
833 type_feedback_vector, SmiTag(slot_id)); | |
834 allocation_feedback.Bind(site); | |
835 Goto(&call_construct_function); | |
836 } | |
837 | |
838 Bind(&create_weak_cell); | |
839 { | |
840 CreateWeakCellInFeedbackVector(type_feedback_vector, SmiTag(slot_id), | |
841 constructor); | |
842 Goto(&call_construct_function); | |
843 } | |
844 } | |
845 | |
846 Bind(&mark_megamorphic); | |
847 { | |
848 // MegamorphicSentinel is an immortal immovable object so | |
849 // write-barrier is not needed. | |
850 Comment("transition to megamorphic"); | |
851 DCHECK( | |
852 Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); | |
853 StoreFixedArrayElement( | |
854 type_feedback_vector, slot_id, | |
855 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), | |
856 SKIP_WRITE_BARRIER); | |
857 Goto(&call_construct_function); | 830 Goto(&call_construct_function); |
858 } | 831 } |
859 } | 832 } |
860 | 833 |
861 Bind(&call_construct_function); | 834 Bind(&mark_megamorphic); |
862 { | 835 { |
863 Comment("call using callConstructFunction"); | 836 // MegamorphicSentinel is an immortal immovable object so |
864 IncrementCallCount(type_feedback_vector, slot_id); | 837 // write-barrier is not needed. |
865 Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( | 838 Comment("transition to megamorphic"); |
866 isolate(), CallableType::kJSFunction); | 839 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); |
867 return_value.Bind(CallStub(callable_function.descriptor(), | 840 StoreFixedArrayElement( |
868 HeapConstant(callable_function.code()), | 841 type_feedback_vector, slot_id, |
869 context, arg_count, new_target, constructor, | 842 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate())), |
870 allocation_feedback.value(), first_arg)); | 843 SKIP_WRITE_BARRIER); |
871 Goto(&end); | 844 Goto(&call_construct_function); |
872 } | 845 } |
873 } | 846 } |
874 | 847 |
875 Bind(&call_construct); | 848 Bind(&call_construct); |
876 { | 849 { |
877 Comment("call using callConstruct builtin"); | 850 Comment("call using callConstruct builtin"); |
878 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( | 851 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( |
879 isolate(), CallableType::kAny); | 852 isolate(), CallableType::kAny); |
880 Node* code_target = HeapConstant(callable.code()); | 853 Node* code_target = HeapConstant(callable.code()); |
881 return_value.Bind(CallStub(callable.descriptor(), code_target, context, | 854 return_value.Bind(CallStub(callable.descriptor(), code_target, context, |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 Goto(&loop); | 1331 Goto(&loop); |
1359 } | 1332 } |
1360 Bind(&done_loop); | 1333 Bind(&done_loop); |
1361 | 1334 |
1362 return array; | 1335 return array; |
1363 } | 1336 } |
1364 | 1337 |
1365 } // namespace interpreter | 1338 } // namespace interpreter |
1366 } // namespace internal | 1339 } // namespace internal |
1367 } // namespace v8 | 1340 } // namespace v8 |
OLD | NEW |