| 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 |