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 "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 3199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3210 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 3210 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
3211 __ Push(x1, x3); | 3211 __ Push(x1, x3); |
3212 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 3212 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
3213 __ Pop(x1); | 3213 __ Pop(x1); |
3214 } | 3214 } |
3215 __ Poke(x0, argc * kPointerSize); | 3215 __ Poke(x0, argc * kPointerSize); |
3216 __ B(cont); | 3216 __ B(cont); |
3217 } | 3217 } |
3218 | 3218 |
3219 | 3219 |
3220 static void CallFunctionNoFeedback(MacroAssembler* masm, | 3220 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3221 int argc, bool needs_checks, | 3221 ASM_LOCATION("CallFunctionStub::Generate"); |
3222 bool call_as_method) { | |
3223 // x1 function the function to call | 3222 // x1 function the function to call |
| 3223 |
3224 Register function = x1; | 3224 Register function = x1; |
3225 Register type = x4; | 3225 Register type = x4; |
3226 Label slow, non_function, wrap, cont; | 3226 Label slow, non_function, wrap, cont; |
3227 | 3227 |
3228 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | 3228 // TODO(jbramley): This function has a lot of unnamed registers. Name them, |
3229 // and tidy things up a bit. | 3229 // and tidy things up a bit. |
3230 | 3230 |
3231 if (needs_checks) { | 3231 if (NeedsChecks()) { |
3232 // Check that the function is really a JavaScript function. | 3232 // Check that the function is really a JavaScript function. |
3233 __ JumpIfSmi(function, &non_function); | 3233 __ JumpIfSmi(function, &non_function); |
3234 | 3234 |
3235 // Goto slow case if we do not have a function. | 3235 // Goto slow case if we do not have a function. |
3236 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); | 3236 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); |
3237 } | 3237 } |
3238 | 3238 |
3239 // Fast-case: Invoke the function now. | 3239 // Fast-case: Invoke the function now. |
3240 // x1 function pushed function | 3240 // x1 function pushed function |
| 3241 int argc = argc_; |
3241 ParameterCount actual(argc); | 3242 ParameterCount actual(argc); |
3242 | 3243 |
3243 if (call_as_method) { | 3244 if (CallAsMethod()) { |
3244 if (needs_checks) { | 3245 if (NeedsChecks()) { |
3245 EmitContinueIfStrictOrNative(masm, &cont); | 3246 EmitContinueIfStrictOrNative(masm, &cont); |
3246 } | 3247 } |
3247 | 3248 |
3248 // Compute the receiver in sloppy mode. | 3249 // Compute the receiver in sloppy mode. |
3249 __ Peek(x3, argc * kPointerSize); | 3250 __ Peek(x3, argc * kPointerSize); |
3250 | 3251 |
3251 if (needs_checks) { | 3252 if (NeedsChecks()) { |
3252 __ JumpIfSmi(x3, &wrap); | 3253 __ JumpIfSmi(x3, &wrap); |
3253 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | 3254 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); |
3254 } else { | 3255 } else { |
3255 __ B(&wrap); | 3256 __ B(&wrap); |
3256 } | 3257 } |
3257 | 3258 |
3258 __ Bind(&cont); | 3259 __ Bind(&cont); |
3259 } | 3260 } |
3260 | 3261 |
3261 __ InvokeFunction(function, | 3262 __ InvokeFunction(function, |
3262 actual, | 3263 actual, |
3263 JUMP_FUNCTION, | 3264 JUMP_FUNCTION, |
3264 NullCallWrapper()); | 3265 NullCallWrapper()); |
3265 if (needs_checks) { | 3266 |
| 3267 if (NeedsChecks()) { |
3266 // Slow-case: Non-function called. | 3268 // Slow-case: Non-function called. |
3267 __ Bind(&slow); | 3269 __ Bind(&slow); |
3268 EmitSlowCase(masm, argc, function, type, &non_function); | 3270 EmitSlowCase(masm, argc, function, type, &non_function); |
3269 } | 3271 } |
3270 | 3272 |
3271 if (call_as_method) { | 3273 if (CallAsMethod()) { |
3272 __ Bind(&wrap); | 3274 __ Bind(&wrap); |
3273 EmitWrapCase(masm, argc, &cont); | 3275 EmitWrapCase(masm, argc, &cont); |
3274 } | 3276 } |
3275 } | 3277 } |
3276 | 3278 |
3277 | 3279 |
3278 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
3279 ASM_LOCATION("CallFunctionStub::Generate"); | |
3280 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); | |
3281 } | |
3282 | |
3283 | |
3284 void CallConstructStub::Generate(MacroAssembler* masm) { | 3280 void CallConstructStub::Generate(MacroAssembler* masm) { |
3285 ASM_LOCATION("CallConstructStub::Generate"); | 3281 ASM_LOCATION("CallConstructStub::Generate"); |
3286 // x0 : number of arguments | 3282 // x0 : number of arguments |
3287 // x1 : the function to call | 3283 // x1 : the function to call |
3288 // x2 : feedback vector | 3284 // x2 : feedback vector |
3289 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) | 3285 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) |
3290 Register function = x1; | 3286 Register function = x1; |
3291 Label slow, non_function_call; | 3287 Label slow, non_function_call; |
3292 | 3288 |
3293 // Check that the function is not a smi. | 3289 // Check that the function is not a smi. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3353 | 3349 |
3354 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { | 3350 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { |
3355 __ Ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3351 __ Ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
3356 __ Ldr(vector, FieldMemOperand(vector, | 3352 __ Ldr(vector, FieldMemOperand(vector, |
3357 JSFunction::kSharedFunctionInfoOffset)); | 3353 JSFunction::kSharedFunctionInfoOffset)); |
3358 __ Ldr(vector, FieldMemOperand(vector, | 3354 __ Ldr(vector, FieldMemOperand(vector, |
3359 SharedFunctionInfo::kFeedbackVectorOffset)); | 3355 SharedFunctionInfo::kFeedbackVectorOffset)); |
3360 } | 3356 } |
3361 | 3357 |
3362 | 3358 |
3363 void CallICStub::Generate_MonomorphicArray(MacroAssembler* masm, Label* miss) { | |
3364 // x1 - function | |
3365 // x2 - feedback vector | |
3366 // x3 - slot id | |
3367 Register function = x1; | |
3368 Register feedback_vector = x2; | |
3369 Register index = x3; | |
3370 Register scratch = x4; | |
3371 | |
3372 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, scratch); | |
3373 __ Cmp(function, scratch); | |
3374 __ B(ne, miss); | |
3375 | |
3376 Register allocation_site = feedback_vector; | |
3377 __ Mov(x0, Operand(arg_count())); | |
3378 | |
3379 __ Add(scratch, feedback_vector, | |
3380 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
3381 __ Ldr(allocation_site, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | |
3382 | |
3383 // Verify that x2 contains an AllocationSite | |
3384 __ AssertUndefinedOrAllocationSite(allocation_site, scratch); | |
3385 ArrayConstructorStub stub(masm->isolate(), arg_count()); | |
3386 __ TailCallStub(&stub); | |
3387 } | |
3388 | |
3389 | |
3390 void CallICStub::Generate_CustomFeedbackCall(MacroAssembler* masm) { | |
3391 // x1 - function | |
3392 // x2 - feedback vector | |
3393 // x3 - slot id | |
3394 Label miss; | |
3395 | |
3396 if (state_.stub_type() == CallIC::MONOMORPHIC_ARRAY) { | |
3397 Generate_MonomorphicArray(masm, &miss); | |
3398 } else { | |
3399 // So far there is only one customer for our custom feedback scheme. | |
3400 UNREACHABLE(); | |
3401 } | |
3402 | |
3403 __ bind(&miss); | |
3404 GenerateMiss(masm); | |
3405 | |
3406 // The slow case, we need this no matter what to complete a call after a miss. | |
3407 CallFunctionNoFeedback(masm, | |
3408 arg_count(), | |
3409 true, | |
3410 CallAsMethod()); | |
3411 | |
3412 __ Unreachable(); | |
3413 } | |
3414 | |
3415 | |
3416 void CallICStub::Generate(MacroAssembler* masm) { | 3359 void CallICStub::Generate(MacroAssembler* masm) { |
3417 ASM_LOCATION("CallICStub"); | 3360 ASM_LOCATION("CallICStub"); |
3418 | 3361 |
3419 // x1 - function | 3362 // x1 - function |
3420 // x3 - slot id (Smi) | 3363 // x3 - slot id (Smi) |
3421 Label extra_checks_or_miss, slow_start; | 3364 Label extra_checks_or_miss, slow_start; |
3422 Label slow, non_function, wrap, cont; | 3365 Label slow, non_function, wrap, cont; |
3423 Label have_js_function; | 3366 Label have_js_function; |
3424 int argc = state_.arg_count(); | 3367 int argc = state_.arg_count(); |
3425 ParameterCount actual(argc); | 3368 ParameterCount actual(argc); |
3426 | 3369 |
3427 Register function = x1; | 3370 Register function = x1; |
3428 Register feedback_vector = x2; | 3371 Register feedback_vector = x2; |
3429 Register index = x3; | 3372 Register index = x3; |
3430 Register type = x4; | 3373 Register type = x4; |
3431 | 3374 |
3432 EmitLoadTypeFeedbackVector(masm, feedback_vector); | 3375 EmitLoadTypeFeedbackVector(masm, feedback_vector); |
3433 | 3376 |
3434 if (state_.stub_type() != CallIC::DEFAULT) { | |
3435 Generate_CustomFeedbackCall(masm); | |
3436 return; | |
3437 } | |
3438 | |
3439 // The checks. First, does x1 match the recorded monomorphic target? | 3377 // The checks. First, does x1 match the recorded monomorphic target? |
3440 __ Add(x4, feedback_vector, | 3378 __ Add(x4, feedback_vector, |
3441 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 3379 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
3442 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3380 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
3443 | 3381 |
3444 __ Cmp(x4, function); | 3382 __ Cmp(x4, function); |
3445 __ B(ne, &extra_checks_or_miss); | 3383 __ B(ne, &extra_checks_or_miss); |
3446 | 3384 |
3447 __ bind(&have_js_function); | 3385 __ bind(&have_js_function); |
3448 if (state_.CallAsMethod()) { | 3386 if (state_.CallAsMethod()) { |
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5565 MemOperand(fp, 6 * kPointerSize), | 5503 MemOperand(fp, 6 * kPointerSize), |
5566 NULL); | 5504 NULL); |
5567 } | 5505 } |
5568 | 5506 |
5569 | 5507 |
5570 #undef __ | 5508 #undef __ |
5571 | 5509 |
5572 } } // namespace v8::internal | 5510 } } // namespace v8::internal |
5573 | 5511 |
5574 #endif // V8_TARGET_ARCH_ARM64 | 5512 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |