| 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
| (...skipping 2729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2740 __ B(&done); | 2740 __ B(&done); |
| 2741 | 2741 |
| 2742 __ Bind(¬_array_function); | 2742 __ Bind(¬_array_function); |
| 2743 CreateWeakCellStub weak_cell_stub(masm->isolate()); | 2743 CreateWeakCellStub weak_cell_stub(masm->isolate()); |
| 2744 CallStubInRecordCallTarget(masm, &weak_cell_stub, argc, function, | 2744 CallStubInRecordCallTarget(masm, &weak_cell_stub, argc, function, |
| 2745 feedback_vector, index, orig_construct, is_super); | 2745 feedback_vector, index, orig_construct, is_super); |
| 2746 __ Bind(&done); | 2746 __ Bind(&done); |
| 2747 } | 2747 } |
| 2748 | 2748 |
| 2749 | 2749 |
| 2750 static void LoadCompilerHints(MacroAssembler* masm) { | |
| 2751 // ----------- S t a t e ------------- | |
| 2752 // -- x1 : the function to call | |
| 2753 // ----------------------------------- | |
| 2754 // Do not transform the receiver for strict mode functions. | |
| 2755 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | |
| 2756 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); | |
| 2757 } | |
| 2758 | |
| 2759 | |
| 2760 static void EmitContinueIfStrictOrNative(MacroAssembler* masm, Label* cont) { | |
| 2761 // ----------- S t a t e ------------- | |
| 2762 // -- a1 : the function to call | |
| 2763 // -- x3 : the shared function info | |
| 2764 // -- w4 : the compiler info hints from the shared function info | |
| 2765 // ----------------------------------- | |
| 2766 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, cont); | |
| 2767 | |
| 2768 // Do not transform the receiver for native (Compilerhints already in x3). | |
| 2769 __ Tbnz(w4, SharedFunctionInfo::kNative, cont); | |
| 2770 } | |
| 2771 | |
| 2772 | |
| 2773 static void EmitSlowCase(MacroAssembler* masm, int argc) { | |
| 2774 __ Mov(x0, argc); | |
| 2775 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 2776 } | |
| 2777 | |
| 2778 | |
| 2779 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { | |
| 2780 // Wrap the receiver and patch it back onto the stack. | |
| 2781 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
| 2782 __ Push(x1); | |
| 2783 __ Mov(x0, x3); | |
| 2784 ToObjectStub stub(masm->isolate()); | |
| 2785 __ CallStub(&stub); | |
| 2786 __ Pop(x1); | |
| 2787 } | |
| 2788 __ Poke(x0, argc * kPointerSize); | |
| 2789 __ B(cont); | |
| 2790 } | |
| 2791 | |
| 2792 | |
| 2793 static void EmitClassConstructorCallCheck(MacroAssembler* masm) { | |
| 2794 // ----------- S t a t e ------------- | |
| 2795 // -- x1 : the function to call | |
| 2796 // -- x3 : the shared function info | |
| 2797 // -- w4 : the shared function's compiler hints | |
| 2798 // ----------------------------------- | |
| 2799 // ClassConstructor Check: ES6 section 9.2.1 [[Call]] | |
| 2800 Label non_class_constructor; | |
| 2801 __ TestAndBranchIfAllClear( | |
| 2802 w4, (1 << SharedFunctionInfo::kIsDefaultConstructor) | | |
| 2803 (1 << SharedFunctionInfo::kIsSubclassConstructor) | | |
| 2804 (1 << SharedFunctionInfo::kIsBaseConstructor), | |
| 2805 &non_class_constructor); | |
| 2806 // If we call a classConstructor Function throw a TypeError | |
| 2807 // indirectly via the CallFunction builtin. | |
| 2808 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | |
| 2809 __ bind(&non_class_constructor); | |
| 2810 } | |
| 2811 | |
| 2812 | |
| 2813 static void CallFunctionNoFeedback(MacroAssembler* masm, | |
| 2814 int argc, bool needs_checks, | |
| 2815 bool call_as_method) { | |
| 2816 // x1 function the function to call | |
| 2817 Register function = x1; | |
| 2818 Register type = x4; | |
| 2819 Label slow, wrap, cont; | |
| 2820 | |
| 2821 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | |
| 2822 // and tidy things up a bit. | |
| 2823 | |
| 2824 if (needs_checks) { | |
| 2825 // Check that the function is really a JavaScript function. | |
| 2826 __ JumpIfSmi(function, &slow); | |
| 2827 | |
| 2828 // Goto slow case if we do not have a function. | |
| 2829 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); | |
| 2830 } | |
| 2831 | |
| 2832 LoadCompilerHints(masm); | |
| 2833 EmitClassConstructorCallCheck(masm); | |
| 2834 | |
| 2835 // Fast-case: Invoke the function now. | |
| 2836 // x1 function pushed function | |
| 2837 ParameterCount actual(argc); | |
| 2838 | |
| 2839 if (call_as_method) { | |
| 2840 if (needs_checks) { | |
| 2841 EmitContinueIfStrictOrNative(masm, &cont); | |
| 2842 } | |
| 2843 | |
| 2844 // Compute the receiver in sloppy mode. | |
| 2845 __ Peek(x3, argc * kPointerSize); | |
| 2846 | |
| 2847 if (needs_checks) { | |
| 2848 __ JumpIfSmi(x3, &wrap); | |
| 2849 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | |
| 2850 } else { | |
| 2851 __ B(&wrap); | |
| 2852 } | |
| 2853 | |
| 2854 __ Bind(&cont); | |
| 2855 } | |
| 2856 | |
| 2857 __ InvokeFunction(function, | |
| 2858 actual, | |
| 2859 JUMP_FUNCTION, | |
| 2860 NullCallWrapper()); | |
| 2861 if (needs_checks) { | |
| 2862 // Slow-case: Non-function called. | |
| 2863 __ Bind(&slow); | |
| 2864 EmitSlowCase(masm, argc); | |
| 2865 } | |
| 2866 | |
| 2867 if (call_as_method) { | |
| 2868 __ Bind(&wrap); | |
| 2869 EmitWrapCase(masm, argc, &cont); | |
| 2870 } | |
| 2871 } | |
| 2872 | |
| 2873 | |
| 2874 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
| 2875 ASM_LOCATION("CallFunctionStub::Generate"); | |
| 2876 CallFunctionNoFeedback(masm, argc(), NeedsChecks(), CallAsMethod()); | |
| 2877 } | |
| 2878 | |
| 2879 | |
| 2880 void CallConstructStub::Generate(MacroAssembler* masm) { | 2750 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 2881 ASM_LOCATION("CallConstructStub::Generate"); | 2751 ASM_LOCATION("CallConstructStub::Generate"); |
| 2882 // x0 : number of arguments | 2752 // x0 : number of arguments |
| 2883 // x1 : the function to call | 2753 // x1 : the function to call |
| 2884 // x2 : feedback vector | 2754 // x2 : feedback vector |
| 2885 // x3 : slot in feedback vector (Smi, for RecordCallTarget) | 2755 // x3 : slot in feedback vector (Smi, for RecordCallTarget) |
| 2886 // x4 : original constructor (for IsSuperConstructorCall) | 2756 // x4 : original constructor (for IsSuperConstructorCall) |
| 2887 Register function = x1; | 2757 Register function = x1; |
| 2888 | 2758 |
| 2889 Label non_function; | 2759 Label non_function; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2969 void CallICStub::Generate(MacroAssembler* masm) { | 2839 void CallICStub::Generate(MacroAssembler* masm) { |
| 2970 ASM_LOCATION("CallICStub"); | 2840 ASM_LOCATION("CallICStub"); |
| 2971 | 2841 |
| 2972 // x1 - function | 2842 // x1 - function |
| 2973 // x3 - slot id (Smi) | 2843 // x3 - slot id (Smi) |
| 2974 // x2 - vector | 2844 // x2 - vector |
| 2975 const int with_types_offset = | 2845 const int with_types_offset = |
| 2976 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); | 2846 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex); |
| 2977 const int generic_offset = | 2847 const int generic_offset = |
| 2978 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); | 2848 FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex); |
| 2979 Label extra_checks_or_miss, slow_start; | 2849 Label extra_checks_or_miss, call; |
| 2980 Label slow, wrap, cont; | |
| 2981 Label have_js_function; | |
| 2982 int argc = arg_count(); | 2850 int argc = arg_count(); |
| 2983 ParameterCount actual(argc); | 2851 ParameterCount actual(argc); |
| 2984 | 2852 |
| 2985 Register function = x1; | 2853 Register function = x1; |
| 2986 Register feedback_vector = x2; | 2854 Register feedback_vector = x2; |
| 2987 Register index = x3; | 2855 Register index = x3; |
| 2988 Register type = x4; | 2856 Register type = x4; |
| 2989 | 2857 |
| 2990 // The checks. First, does x1 match the recorded monomorphic target? | 2858 // The checks. First, does x1 match the recorded monomorphic target? |
| 2991 __ Add(x4, feedback_vector, | 2859 __ Add(x4, feedback_vector, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3016 | 2884 |
| 3017 // Increment the call count for monomorphic function calls. | 2885 // Increment the call count for monomorphic function calls. |
| 3018 __ Add(feedback_vector, feedback_vector, | 2886 __ Add(feedback_vector, feedback_vector, |
| 3019 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 2887 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 3020 __ Add(feedback_vector, feedback_vector, | 2888 __ Add(feedback_vector, feedback_vector, |
| 3021 Operand(FixedArray::kHeaderSize + kPointerSize)); | 2889 Operand(FixedArray::kHeaderSize + kPointerSize)); |
| 3022 __ Ldr(index, FieldMemOperand(feedback_vector, 0)); | 2890 __ Ldr(index, FieldMemOperand(feedback_vector, 0)); |
| 3023 __ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); | 2891 __ Add(index, index, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement))); |
| 3024 __ Str(index, FieldMemOperand(feedback_vector, 0)); | 2892 __ Str(index, FieldMemOperand(feedback_vector, 0)); |
| 3025 | 2893 |
| 3026 __ bind(&have_js_function); | 2894 __ bind(&call); |
| 3027 | 2895 __ Mov(x0, argc); |
| 3028 LoadCompilerHints(masm); | 2896 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 3029 EmitClassConstructorCallCheck(masm); | |
| 3030 | |
| 3031 if (CallAsMethod()) { | |
| 3032 EmitContinueIfStrictOrNative(masm, &cont); | |
| 3033 | |
| 3034 // Compute the receiver in sloppy mode. | |
| 3035 __ Peek(x3, argc * kPointerSize); | |
| 3036 | |
| 3037 __ JumpIfSmi(x3, &wrap); | |
| 3038 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | |
| 3039 | |
| 3040 __ Bind(&cont); | |
| 3041 } | |
| 3042 | |
| 3043 __ InvokeFunction(function, | |
| 3044 actual, | |
| 3045 JUMP_FUNCTION, | |
| 3046 NullCallWrapper()); | |
| 3047 | |
| 3048 __ bind(&slow); | |
| 3049 EmitSlowCase(masm, argc); | |
| 3050 | |
| 3051 if (CallAsMethod()) { | |
| 3052 __ bind(&wrap); | |
| 3053 EmitWrapCase(masm, argc, &cont); | |
| 3054 } | |
| 3055 | 2897 |
| 3056 __ bind(&extra_checks_or_miss); | 2898 __ bind(&extra_checks_or_miss); |
| 3057 Label uninitialized, miss, not_allocation_site; | 2899 Label uninitialized, miss, not_allocation_site; |
| 3058 | 2900 |
| 3059 __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &slow_start); | 2901 __ JumpIfRoot(x4, Heap::kmegamorphic_symbolRootIndex, &call); |
| 3060 | 2902 |
| 3061 __ Ldr(x5, FieldMemOperand(x4, HeapObject::kMapOffset)); | 2903 __ Ldr(x5, FieldMemOperand(x4, HeapObject::kMapOffset)); |
| 3062 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, ¬_allocation_site); | 2904 __ JumpIfNotRoot(x5, Heap::kAllocationSiteMapRootIndex, ¬_allocation_site); |
| 3063 | 2905 |
| 3064 HandleArrayCase(masm, &miss); | 2906 HandleArrayCase(masm, &miss); |
| 3065 | 2907 |
| 3066 __ bind(¬_allocation_site); | 2908 __ bind(¬_allocation_site); |
| 3067 | 2909 |
| 3068 // The following cases attempt to handle MISS cases without going to the | 2910 // The following cases attempt to handle MISS cases without going to the |
| 3069 // runtime. | 2911 // runtime. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3081 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 2923 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
| 3082 __ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex); | 2924 __ LoadRoot(x5, Heap::kmegamorphic_symbolRootIndex); |
| 3083 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 2925 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
| 3084 // We have to update statistics for runtime profiling. | 2926 // We have to update statistics for runtime profiling. |
| 3085 __ Ldr(x4, FieldMemOperand(feedback_vector, with_types_offset)); | 2927 __ Ldr(x4, FieldMemOperand(feedback_vector, with_types_offset)); |
| 3086 __ Subs(x4, x4, Operand(Smi::FromInt(1))); | 2928 __ Subs(x4, x4, Operand(Smi::FromInt(1))); |
| 3087 __ Str(x4, FieldMemOperand(feedback_vector, with_types_offset)); | 2929 __ Str(x4, FieldMemOperand(feedback_vector, with_types_offset)); |
| 3088 __ Ldr(x4, FieldMemOperand(feedback_vector, generic_offset)); | 2930 __ Ldr(x4, FieldMemOperand(feedback_vector, generic_offset)); |
| 3089 __ Adds(x4, x4, Operand(Smi::FromInt(1))); | 2931 __ Adds(x4, x4, Operand(Smi::FromInt(1))); |
| 3090 __ Str(x4, FieldMemOperand(feedback_vector, generic_offset)); | 2932 __ Str(x4, FieldMemOperand(feedback_vector, generic_offset)); |
| 3091 __ B(&slow_start); | 2933 __ B(&call); |
| 3092 | 2934 |
| 3093 __ bind(&uninitialized); | 2935 __ bind(&uninitialized); |
| 3094 | 2936 |
| 3095 // We are going monomorphic, provided we actually have a JSFunction. | 2937 // We are going monomorphic, provided we actually have a JSFunction. |
| 3096 __ JumpIfSmi(function, &miss); | 2938 __ JumpIfSmi(function, &miss); |
| 3097 | 2939 |
| 3098 // Goto miss case if we do not have a function. | 2940 // Goto miss case if we do not have a function. |
| 3099 __ JumpIfNotObjectType(function, x5, x5, JS_FUNCTION_TYPE, &miss); | 2941 __ JumpIfNotObjectType(function, x5, x5, JS_FUNCTION_TYPE, &miss); |
| 3100 | 2942 |
| 3101 // Make sure the function is not the Array() function, which requires special | 2943 // Make sure the function is not the Array() function, which requires special |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3120 // x3 - slot | 2962 // x3 - slot |
| 3121 // x1 - function | 2963 // x1 - function |
| 3122 { | 2964 { |
| 3123 FrameScope scope(masm, StackFrame::INTERNAL); | 2965 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3124 CreateWeakCellStub create_stub(masm->isolate()); | 2966 CreateWeakCellStub create_stub(masm->isolate()); |
| 3125 __ Push(function); | 2967 __ Push(function); |
| 3126 __ CallStub(&create_stub); | 2968 __ CallStub(&create_stub); |
| 3127 __ Pop(function); | 2969 __ Pop(function); |
| 3128 } | 2970 } |
| 3129 | 2971 |
| 3130 __ B(&have_js_function); | 2972 __ B(&call); |
| 3131 | 2973 |
| 3132 // We are here because tracing is on or we encountered a MISS case we can't | 2974 // We are here because tracing is on or we encountered a MISS case we can't |
| 3133 // handle here. | 2975 // handle here. |
| 3134 __ bind(&miss); | 2976 __ bind(&miss); |
| 3135 GenerateMiss(masm); | 2977 GenerateMiss(masm); |
| 3136 | 2978 |
| 3137 // the slow case | 2979 __ B(&call); |
| 3138 __ bind(&slow_start); | |
| 3139 | |
| 3140 // Check that the function is really a JavaScript function. | |
| 3141 __ JumpIfSmi(function, &slow); | |
| 3142 | |
| 3143 // Goto slow case if we do not have a function. | |
| 3144 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); | |
| 3145 __ B(&have_js_function); | |
| 3146 } | 2980 } |
| 3147 | 2981 |
| 3148 | 2982 |
| 3149 void CallICStub::GenerateMiss(MacroAssembler* masm) { | 2983 void CallICStub::GenerateMiss(MacroAssembler* masm) { |
| 3150 ASM_LOCATION("CallICStub[Miss]"); | 2984 ASM_LOCATION("CallICStub[Miss]"); |
| 3151 | 2985 |
| 3152 FrameScope scope(masm, StackFrame::INTERNAL); | 2986 FrameScope scope(masm, StackFrame::INTERNAL); |
| 3153 | 2987 |
| 3154 // Push the receiver and the function and feedback info. | 2988 // Push the receiver and the function and feedback info. |
| 3155 __ Push(x1, x2, x3); | 2989 __ Push(x1, x2, x3); |
| (...skipping 2887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6043 MemOperand(fp, 6 * kPointerSize), NULL); | 5877 MemOperand(fp, 6 * kPointerSize), NULL); |
| 6044 } | 5878 } |
| 6045 | 5879 |
| 6046 | 5880 |
| 6047 #undef __ | 5881 #undef __ |
| 6048 | 5882 |
| 6049 } // namespace internal | 5883 } // namespace internal |
| 6050 } // namespace v8 | 5884 } // namespace v8 |
| 6051 | 5885 |
| 6052 #endif // V8_TARGET_ARCH_ARM64 | 5886 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |