| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
| 10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
| (...skipping 2916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2927 { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); | 2927 { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); |
| 2928 __ Push(r1, r3); | 2928 __ Push(r1, r3); |
| 2929 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 2929 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
| 2930 __ pop(r1); | 2930 __ pop(r1); |
| 2931 } | 2931 } |
| 2932 __ str(r0, MemOperand(sp, argc * kPointerSize)); | 2932 __ str(r0, MemOperand(sp, argc * kPointerSize)); |
| 2933 __ jmp(cont); | 2933 __ jmp(cont); |
| 2934 } | 2934 } |
| 2935 | 2935 |
| 2936 | 2936 |
| 2937 static void CallFunctionNoFeedback(MacroAssembler* masm, | 2937 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 2938 int argc, bool needs_checks, | |
| 2939 bool call_as_method) { | |
| 2940 // r1 : the function to call | 2938 // r1 : the function to call |
| 2941 Label slow, non_function, wrap, cont; | 2939 Label slow, non_function, wrap, cont; |
| 2942 | 2940 |
| 2943 if (needs_checks) { | 2941 if (NeedsChecks()) { |
| 2944 // Check that the function is really a JavaScript function. | 2942 // Check that the function is really a JavaScript function. |
| 2945 // r1: pushed function (to be verified) | 2943 // r1: pushed function (to be verified) |
| 2946 __ JumpIfSmi(r1, &non_function); | 2944 __ JumpIfSmi(r1, &non_function); |
| 2947 | 2945 |
| 2948 // Goto slow case if we do not have a function. | 2946 // Goto slow case if we do not have a function. |
| 2949 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); | 2947 __ CompareObjectType(r1, r4, r4, JS_FUNCTION_TYPE); |
| 2950 __ b(ne, &slow); | 2948 __ b(ne, &slow); |
| 2951 } | 2949 } |
| 2952 | 2950 |
| 2953 // Fast-case: Invoke the function now. | 2951 // Fast-case: Invoke the function now. |
| 2954 // r1: pushed function | 2952 // r1: pushed function |
| 2953 int argc = argc_; |
| 2955 ParameterCount actual(argc); | 2954 ParameterCount actual(argc); |
| 2956 | 2955 |
| 2957 if (call_as_method) { | 2956 if (CallAsMethod()) { |
| 2958 if (needs_checks) { | 2957 if (NeedsChecks()) { |
| 2959 EmitContinueIfStrictOrNative(masm, &cont); | 2958 EmitContinueIfStrictOrNative(masm, &cont); |
| 2960 } | 2959 } |
| 2961 | 2960 |
| 2962 // Compute the receiver in sloppy mode. | 2961 // Compute the receiver in sloppy mode. |
| 2963 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); | 2962 __ ldr(r3, MemOperand(sp, argc * kPointerSize)); |
| 2964 | 2963 |
| 2965 if (needs_checks) { | 2964 if (NeedsChecks()) { |
| 2966 __ JumpIfSmi(r3, &wrap); | 2965 __ JumpIfSmi(r3, &wrap); |
| 2967 __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); | 2966 __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); |
| 2968 __ b(lt, &wrap); | 2967 __ b(lt, &wrap); |
| 2969 } else { | 2968 } else { |
| 2970 __ jmp(&wrap); | 2969 __ jmp(&wrap); |
| 2971 } | 2970 } |
| 2972 | 2971 |
| 2973 __ bind(&cont); | 2972 __ bind(&cont); |
| 2974 } | 2973 } |
| 2975 | 2974 |
| 2976 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); | 2975 __ InvokeFunction(r1, actual, JUMP_FUNCTION, NullCallWrapper()); |
| 2977 | 2976 |
| 2978 if (needs_checks) { | 2977 if (NeedsChecks()) { |
| 2979 // Slow-case: Non-function called. | 2978 // Slow-case: Non-function called. |
| 2980 __ bind(&slow); | 2979 __ bind(&slow); |
| 2981 EmitSlowCase(masm, argc, &non_function); | 2980 EmitSlowCase(masm, argc, &non_function); |
| 2982 } | 2981 } |
| 2983 | 2982 |
| 2984 if (call_as_method) { | 2983 if (CallAsMethod()) { |
| 2985 __ bind(&wrap); | 2984 __ bind(&wrap); |
| 2986 EmitWrapCase(masm, argc, &cont); | 2985 EmitWrapCase(masm, argc, &cont); |
| 2987 } | 2986 } |
| 2988 } | 2987 } |
| 2989 | 2988 |
| 2990 | 2989 |
| 2991 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
| 2992 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | |
| 2993 } | |
| 2994 | |
| 2995 | |
| 2996 void CallConstructStub::Generate(MacroAssembler* masm) { | 2990 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 2997 // r0 : number of arguments | 2991 // r0 : number of arguments |
| 2998 // r1 : the function to call | 2992 // r1 : the function to call |
| 2999 // r2 : feedback vector | 2993 // r2 : feedback vector |
| 3000 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback | 2994 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback |
| 3001 // vector (Smi) | 2995 // vector (Smi) |
| 3002 Label slow, non_function_call; | 2996 Label slow, non_function_call; |
| 3003 | 2997 |
| 3004 // Check that the function is not a smi. | 2998 // Check that the function is not a smi. |
| 3005 __ JumpIfSmi(r1, &non_function_call); | 2999 __ JumpIfSmi(r1, &non_function_call); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3045 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); | 3039 __ cmp(r4, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 3046 __ b(ne, &non_function_call); | 3040 __ b(ne, &non_function_call); |
| 3047 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); | 3041 __ GetBuiltinFunction(r1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 3048 __ jmp(&do_call); | 3042 __ jmp(&do_call); |
| 3049 | 3043 |
| 3050 __ bind(&non_function_call); | 3044 __ bind(&non_function_call); |
| 3051 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 3045 __ GetBuiltinFunction(r1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 3052 __ bind(&do_call); | 3046 __ bind(&do_call); |
| 3053 // Set expected number of arguments to zero (not changing r0). | 3047 // Set expected number of arguments to zero (not changing r0). |
| 3054 __ mov(r2, Operand::Zero()); | 3048 __ mov(r2, Operand::Zero()); |
| 3055 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3049 __ Jump(isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 3056 RelocInfo::CODE_TARGET); | 3050 RelocInfo::CODE_TARGET); |
| 3057 } | 3051 } |
| 3058 | 3052 |
| 3059 | 3053 |
| 3060 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { | 3054 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { |
| 3061 __ ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3055 __ ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3062 __ ldr(vector, FieldMemOperand(vector, | 3056 __ ldr(vector, FieldMemOperand(vector, |
| 3063 JSFunction::kSharedFunctionInfoOffset)); | 3057 JSFunction::kSharedFunctionInfoOffset)); |
| 3064 __ ldr(vector, FieldMemOperand(vector, | 3058 __ ldr(vector, FieldMemOperand(vector, |
| 3065 SharedFunctionInfo::kFeedbackVectorOffset)); | 3059 SharedFunctionInfo::kFeedbackVectorOffset)); |
| 3066 } | 3060 } |
| 3067 | 3061 |
| 3068 | 3062 |
| 3069 void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) { | |
| 3070 // r1 - function | |
| 3071 // r2 - feedback vector | |
| 3072 // r3 - slot id | |
| 3073 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r4); | |
| 3074 __ cmp(r1, r4); | |
| 3075 __ b(ne, miss); | |
| 3076 | |
| 3077 __ mov(r0, Operand(arg_count())); | |
| 3078 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | |
| 3079 __ ldr(r2, FieldMemOperand(r4, FixedArray::kHeaderSize)); | |
| 3080 // Verify that r2 contains an AllocationSite | |
| 3081 __ AssertUndefinedOrAllocationSite(r2, r4); | |
| 3082 ArrayConstructorStub stub(masm->isolate(), arg_count()); | |
| 3083 __ TailCallStub(&stub); | |
| 3084 } | |
| 3085 | |
| 3086 | |
| 3087 void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) { | |
| 3088 // r1 - function | |
| 3089 // r2 - feedback vector | |
| 3090 // r3 - slot id | |
| 3091 Label miss; | |
| 3092 | |
| 3093 if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) { | |
| 3094 Generate_MonomorphicArray(masm, &miss); | |
| 3095 } else { | |
| 3096 // So far there is only one customer for our custom feedback scheme. | |
| 3097 UNREACHABLE(); | |
| 3098 } | |
| 3099 | |
| 3100 __ bind(&miss); | |
| 3101 GenerateMiss(masm); | |
| 3102 | |
| 3103 // The slow case, we need this no matter what to complete a call after a miss. | |
| 3104 CallFunctionNoFeedback(masm, | |
| 3105 arg_count(), | |
| 3106 true, | |
| 3107 CallAsMethod()); | |
| 3108 | |
| 3109 // Unreachable. | |
| 3110 __ stop("Unexpected code address"); | |
| 3111 } | |
| 3112 | |
| 3113 | |
| 3114 void CallICStub::Generate(MacroAssembler* masm) { | 3063 void CallICStub::Generate(MacroAssembler* masm) { |
| 3115 // r1 - function | 3064 // r1 - function |
| 3116 // r3 - slot id (Smi) | 3065 // r3 - slot id (Smi) |
| 3117 Label extra_checks_or_miss, slow_start; | 3066 Label extra_checks_or_miss, slow_start; |
| 3118 Label slow, non_function, wrap, cont; | 3067 Label slow, non_function, wrap, cont; |
| 3119 Label have_js_function; | 3068 Label have_js_function; |
| 3120 int argc = state_.arg_count(); | 3069 int argc = state_.arg_count(); |
| 3121 ParameterCount actual(argc); | 3070 ParameterCount actual(argc); |
| 3122 | 3071 |
| 3123 EmitLoadTypeFeedbackVector(masm, r2); | 3072 EmitLoadTypeFeedbackVector(masm, r2); |
| 3124 | 3073 |
| 3125 if (state_.stub_type() != CallIC::DEFAULT) { | |
| 3126 Generate_CustomFeedbackCall(masm); | |
| 3127 return; | |
| 3128 } | |
| 3129 | |
| 3130 // The checks. First, does r1 match the recorded monomorphic target? | 3074 // The checks. First, does r1 match the recorded monomorphic target? |
| 3131 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); | 3075 __ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3)); |
| 3132 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); | 3076 __ ldr(r4, FieldMemOperand(r4, FixedArray::kHeaderSize)); |
| 3133 __ cmp(r1, r4); | 3077 __ cmp(r1, r4); |
| 3134 __ b(ne, &extra_checks_or_miss); | 3078 __ b(ne, &extra_checks_or_miss); |
| 3135 | 3079 |
| 3136 __ bind(&have_js_function); | 3080 __ bind(&have_js_function); |
| 3137 if (state_.CallAsMethod()) { | 3081 if (state_.CallAsMethod()) { |
| 3138 EmitContinueIfStrictOrNative(masm, &cont); | 3082 EmitContinueIfStrictOrNative(masm, &cont); |
| 3139 // Compute the receiver in sloppy mode. | 3083 // Compute the receiver in sloppy mode. |
| (...skipping 2159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5299 MemOperand(fp, 6 * kPointerSize), | 5243 MemOperand(fp, 6 * kPointerSize), |
| 5300 NULL); | 5244 NULL); |
| 5301 } | 5245 } |
| 5302 | 5246 |
| 5303 | 5247 |
| 5304 #undef __ | 5248 #undef __ |
| 5305 | 5249 |
| 5306 } } // namespace v8::internal | 5250 } } // namespace v8::internal |
| 5307 | 5251 |
| 5308 #endif // V8_TARGET_ARCH_ARM | 5252 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |