OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 2713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2724 | 2724 |
2725 // (9) Sliced string. Replace subject with parent. | 2725 // (9) Sliced string. Replace subject with parent. |
2726 __ Ldr(sliced_string_offset, | 2726 __ Ldr(sliced_string_offset, |
2727 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); | 2727 UntagSmiFieldMemOperand(subject, SlicedString::kOffsetOffset)); |
2728 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); | 2728 __ Ldr(subject, FieldMemOperand(subject, SlicedString::kParentOffset)); |
2729 __ B(&check_underlying); // Go to (4). | 2729 __ B(&check_underlying); // Go to (4). |
2730 #endif | 2730 #endif |
2731 } | 2731 } |
2732 | 2732 |
2733 | 2733 |
2734 static void GenerateRecordCallTarget(MacroAssembler* masm, | 2734 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub, |
2735 Register argc, | 2735 Register argc, Register function, |
| 2736 Register feedback_vector, |
| 2737 Register index) { |
| 2738 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2739 |
| 2740 // Arguments register must be smi-tagged to call out. |
| 2741 __ SmiTag(argc); |
| 2742 __ Push(argc, function, feedback_vector, index); |
| 2743 |
| 2744 DCHECK(feedback_vector.Is(x2) && index.Is(x3)); |
| 2745 __ CallStub(stub); |
| 2746 |
| 2747 __ Pop(index, feedback_vector, function, argc); |
| 2748 __ SmiUntag(argc); |
| 2749 } |
| 2750 |
| 2751 |
| 2752 static void GenerateRecordCallTarget(MacroAssembler* masm, Register argc, |
2736 Register function, | 2753 Register function, |
2737 Register feedback_vector, | 2754 Register feedback_vector, Register index, |
2738 Register index, | 2755 Register scratch1, Register scratch2, |
2739 Register scratch1, | 2756 Register scratch3) { |
2740 Register scratch2) { | |
2741 ASM_LOCATION("GenerateRecordCallTarget"); | 2757 ASM_LOCATION("GenerateRecordCallTarget"); |
2742 DCHECK(!AreAliased(scratch1, scratch2, | 2758 DCHECK(!AreAliased(scratch1, scratch2, scratch3, argc, function, |
2743 argc, function, feedback_vector, index)); | 2759 feedback_vector, index)); |
2744 // Cache the called function in a feedback vector slot. Cache states are | 2760 // Cache the called function in a feedback vector slot. Cache states are |
2745 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. | 2761 // uninitialized, monomorphic (indicated by a JSFunction), and megamorphic. |
2746 // argc : number of arguments to the construct function | 2762 // argc : number of arguments to the construct function |
2747 // function : the function to call | 2763 // function : the function to call |
2748 // feedback_vector : the feedback vector | 2764 // feedback_vector : the feedback vector |
2749 // index : slot in feedback vector (smi) | 2765 // index : slot in feedback vector (smi) |
2750 Label initialize, done, miss, megamorphic, not_array_function; | 2766 Label initialize, done, miss, megamorphic, not_array_function; |
2751 | 2767 |
2752 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), | 2768 DCHECK_EQ(*TypeFeedbackVector::MegamorphicSentinel(masm->isolate()), |
2753 masm->isolate()->heap()->megamorphic_symbol()); | 2769 masm->isolate()->heap()->megamorphic_symbol()); |
2754 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), | 2770 DCHECK_EQ(*TypeFeedbackVector::UninitializedSentinel(masm->isolate()), |
2755 masm->isolate()->heap()->uninitialized_symbol()); | 2771 masm->isolate()->heap()->uninitialized_symbol()); |
2756 | 2772 |
2757 // Load the cache state. | 2773 // Load the cache state. |
2758 __ Add(scratch1, feedback_vector, | 2774 Register feedback = scratch1; |
| 2775 Register feedback_map = scratch2; |
| 2776 Register feedback_value = scratch3; |
| 2777 __ Add(feedback, feedback_vector, |
2759 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 2778 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
2760 __ Ldr(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); | 2779 __ Ldr(feedback, FieldMemOperand(feedback, FixedArray::kHeaderSize)); |
2761 | 2780 |
2762 // A monomorphic cache hit or an already megamorphic state: invoke the | 2781 // A monomorphic cache hit or an already megamorphic state: invoke the |
2763 // function without changing the state. | 2782 // function without changing the state. |
2764 __ Cmp(scratch1, function); | 2783 Label check_megamorphic; |
| 2784 __ Ldr(feedback_value, FieldMemOperand(feedback, WeakCell::kValueOffset)); |
| 2785 __ Cmp(function, feedback_value); |
| 2786 __ B(eq, &done); |
| 2787 __ Ldr(feedback_map, FieldMemOperand(feedback, 0)); |
| 2788 __ CompareRoot(feedback_map, Heap::kWeakCellMapRootIndex); |
| 2789 __ B(ne, &check_megamorphic); |
| 2790 |
| 2791 // If function is not equal to the weak cell value, and the weak cell value is |
| 2792 // cleared, we have a new chance to become monomorphic. |
| 2793 __ JumpIfSmi(feedback_value, &initialize); |
| 2794 __ B(&megamorphic); |
| 2795 |
| 2796 __ bind(&check_megamorphic); |
| 2797 __ CompareRoot(feedback, Heap::kmegamorphic_symbolRootIndex); |
2765 __ B(eq, &done); | 2798 __ B(eq, &done); |
2766 | 2799 |
2767 if (!FLAG_pretenuring_call_new) { | 2800 if (!FLAG_pretenuring_call_new) { |
2768 // If we came here, we need to see if we are the array function. | 2801 // If we came here, we need to see if we are the array function. |
2769 // If we didn't have a matching function, and we didn't find the megamorph | 2802 // If we didn't have a matching function, and we didn't find the megamorph |
2770 // sentinel, then we have in the slot either some other function or an | 2803 // sentinel, then we have in the slot either some other function or an |
2771 // AllocationSite. Do a map check on the object in scratch1 register. | 2804 // AllocationSite. Do a map check on the object in scratch1 register. |
2772 __ Ldr(scratch2, FieldMemOperand(scratch1, AllocationSite::kMapOffset)); | 2805 __ JumpIfNotRoot(feedback_map, Heap::kAllocationSiteMapRootIndex, &miss); |
2773 __ JumpIfNotRoot(scratch2, Heap::kAllocationSiteMapRootIndex, &miss); | |
2774 | 2806 |
2775 // Make sure the function is the Array() function | 2807 // Make sure the function is the Array() function |
2776 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); | 2808 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); |
2777 __ Cmp(function, scratch1); | 2809 __ Cmp(function, scratch1); |
2778 __ B(ne, &megamorphic); | 2810 __ B(ne, &megamorphic); |
2779 __ B(&done); | 2811 __ B(&done); |
2780 } | 2812 } |
2781 | 2813 |
2782 __ Bind(&miss); | 2814 __ Bind(&miss); |
2783 | 2815 |
(...skipping 15 matching lines...) Expand all Loading... |
2799 | 2831 |
2800 if (!FLAG_pretenuring_call_new) { | 2832 if (!FLAG_pretenuring_call_new) { |
2801 // Make sure the function is the Array() function | 2833 // Make sure the function is the Array() function |
2802 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); | 2834 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch1); |
2803 __ Cmp(function, scratch1); | 2835 __ Cmp(function, scratch1); |
2804 __ B(ne, ¬_array_function); | 2836 __ B(ne, ¬_array_function); |
2805 | 2837 |
2806 // The target function is the Array constructor, | 2838 // The target function is the Array constructor, |
2807 // Create an AllocationSite if we don't already have it, store it in the | 2839 // Create an AllocationSite if we don't already have it, store it in the |
2808 // slot. | 2840 // slot. |
2809 { | 2841 CreateAllocationSiteStub create_stub(masm->isolate()); |
2810 FrameScope scope(masm, StackFrame::INTERNAL); | 2842 CallStubInRecordCallTarget(masm, &create_stub, argc, function, |
2811 CreateAllocationSiteStub create_stub(masm->isolate()); | 2843 feedback_vector, index); |
2812 | |
2813 // Arguments register must be smi-tagged to call out. | |
2814 __ SmiTag(argc); | |
2815 __ Push(argc, function, feedback_vector, index); | |
2816 | |
2817 // CreateAllocationSiteStub expect the feedback vector in x2 and the slot | |
2818 // index in x3. | |
2819 DCHECK(feedback_vector.Is(x2) && index.Is(x3)); | |
2820 __ CallStub(&create_stub); | |
2821 | |
2822 __ Pop(index, feedback_vector, function, argc); | |
2823 __ SmiUntag(argc); | |
2824 } | |
2825 __ B(&done); | 2844 __ B(&done); |
2826 | 2845 |
2827 __ Bind(¬_array_function); | 2846 __ Bind(¬_array_function); |
2828 } | 2847 } |
2829 | 2848 |
2830 // An uninitialized cache is patched with the function. | 2849 CreateWeakCellStub create_stub(masm->isolate()); |
2831 | 2850 CallStubInRecordCallTarget(masm, &create_stub, argc, function, |
2832 __ Add(scratch1, feedback_vector, | 2851 feedback_vector, index); |
2833 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
2834 __ Add(scratch1, scratch1, FixedArray::kHeaderSize - kHeapObjectTag); | |
2835 __ Str(function, MemOperand(scratch1, 0)); | |
2836 | |
2837 __ Push(function); | |
2838 __ RecordWrite(feedback_vector, scratch1, function, kLRHasNotBeenSaved, | |
2839 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
2840 __ Pop(function); | |
2841 | |
2842 __ Bind(&done); | 2852 __ Bind(&done); |
2843 } | 2853 } |
2844 | 2854 |
2845 | 2855 |
2846 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | 2856 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { |
2847 // Do not transform the receiver for strict mode functions. | 2857 // Do not transform the receiver for strict mode functions. |
2848 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | 2858 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
2849 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); | 2859 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); |
2850 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, cont); | 2860 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, cont); |
2851 | 2861 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2970 Label slow, non_function_call; | 2980 Label slow, non_function_call; |
2971 | 2981 |
2972 // Check that the function is not a smi. | 2982 // Check that the function is not a smi. |
2973 __ JumpIfSmi(function, &non_function_call); | 2983 __ JumpIfSmi(function, &non_function_call); |
2974 // Check that the function is a JSFunction. | 2984 // Check that the function is a JSFunction. |
2975 Register object_type = x10; | 2985 Register object_type = x10; |
2976 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, | 2986 __ JumpIfNotObjectType(function, object_type, object_type, JS_FUNCTION_TYPE, |
2977 &slow); | 2987 &slow); |
2978 | 2988 |
2979 if (RecordCallTarget()) { | 2989 if (RecordCallTarget()) { |
2980 GenerateRecordCallTarget(masm, x0, function, x2, x3, x4, x5); | 2990 GenerateRecordCallTarget(masm, x0, function, x2, x3, x4, x5, x11); |
2981 | 2991 |
2982 __ Add(x5, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); | 2992 __ Add(x5, x2, Operand::UntagSmiAndScale(x3, kPointerSizeLog2)); |
2983 if (FLAG_pretenuring_call_new) { | 2993 if (FLAG_pretenuring_call_new) { |
2984 // Put the AllocationSite from the feedback vector into x2. | 2994 // Put the AllocationSite from the feedback vector into x2. |
2985 // By adding kPointerSize we encode that we know the AllocationSite | 2995 // By adding kPointerSize we encode that we know the AllocationSite |
2986 // entry is at the feedback vector slot given by x3 + 1. | 2996 // entry is at the feedback vector slot given by x3 + 1. |
2987 __ Ldr(x2, FieldMemOperand(x5, FixedArray::kHeaderSize + kPointerSize)); | 2997 __ Ldr(x2, FieldMemOperand(x5, FixedArray::kHeaderSize + kPointerSize)); |
2988 } else { | 2998 } else { |
2989 Label feedback_register_initialized; | 2999 Label feedback_register_initialized; |
2990 // Put the AllocationSite from the feedback vector into x2, or undefined. | 3000 // Put the AllocationSite from the feedback vector into x2, or undefined. |
(...skipping 2754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5745 kStackUnwindSpace, NULL, spill_offset, | 5755 kStackUnwindSpace, NULL, spill_offset, |
5746 MemOperand(fp, 6 * kPointerSize), NULL); | 5756 MemOperand(fp, 6 * kPointerSize), NULL); |
5747 } | 5757 } |
5748 | 5758 |
5749 | 5759 |
5750 #undef __ | 5760 #undef __ |
5751 | 5761 |
5752 } } // namespace v8::internal | 5762 } } // namespace v8::internal |
5753 | 5763 |
5754 #endif // V8_TARGET_ARCH_ARM64 | 5764 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |