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 void CallFunctionStub::Generate(MacroAssembler* masm) { | 3220 static void CallFunctionNoFeedback(MacroAssembler* masm, |
3221 ASM_LOCATION("CallFunctionStub::Generate"); | 3221 int argc, bool needs_checks, |
| 3222 bool call_as_method) { |
3222 // x1 function the function to call | 3223 // 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 (NeedsChecks()) { | 3231 if (needs_checks) { |
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_; | |
3242 ParameterCount actual(argc); | 3241 ParameterCount actual(argc); |
3243 | 3242 |
3244 if (CallAsMethod()) { | 3243 if (call_as_method) { |
3245 if (NeedsChecks()) { | 3244 if (needs_checks) { |
3246 EmitContinueIfStrictOrNative(masm, &cont); | 3245 EmitContinueIfStrictOrNative(masm, &cont); |
3247 } | 3246 } |
3248 | 3247 |
3249 // Compute the receiver in sloppy mode. | 3248 // Compute the receiver in sloppy mode. |
3250 __ Peek(x3, argc * kPointerSize); | 3249 __ Peek(x3, argc * kPointerSize); |
3251 | 3250 |
3252 if (NeedsChecks()) { | 3251 if (needs_checks) { |
3253 __ JumpIfSmi(x3, &wrap); | 3252 __ JumpIfSmi(x3, &wrap); |
3254 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | 3253 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); |
3255 } else { | 3254 } else { |
3256 __ B(&wrap); | 3255 __ B(&wrap); |
3257 } | 3256 } |
3258 | 3257 |
3259 __ Bind(&cont); | 3258 __ Bind(&cont); |
3260 } | 3259 } |
3261 | 3260 |
3262 __ InvokeFunction(function, | 3261 __ InvokeFunction(function, |
3263 actual, | 3262 actual, |
3264 JUMP_FUNCTION, | 3263 JUMP_FUNCTION, |
3265 NullCallWrapper()); | 3264 NullCallWrapper()); |
3266 | 3265 if (needs_checks) { |
3267 if (NeedsChecks()) { | |
3268 // Slow-case: Non-function called. | 3266 // Slow-case: Non-function called. |
3269 __ Bind(&slow); | 3267 __ Bind(&slow); |
3270 EmitSlowCase(masm, argc, function, type, &non_function); | 3268 EmitSlowCase(masm, argc, function, type, &non_function); |
3271 } | 3269 } |
3272 | 3270 |
3273 if (CallAsMethod()) { | 3271 if (call_as_method) { |
3274 __ Bind(&wrap); | 3272 __ Bind(&wrap); |
3275 EmitWrapCase(masm, argc, &cont); | 3273 EmitWrapCase(masm, argc, &cont); |
3276 } | 3274 } |
3277 } | 3275 } |
3278 | 3276 |
3279 | 3277 |
| 3278 void CallFunctionStub::Generate(MacroAssembler* masm) { |
| 3279 ASM_LOCATION("CallFunctionStub::Generate"); |
| 3280 CallFunctionNoFeedback(masm, argc_, NeedsChecks(), CallAsMethod()); |
| 3281 } |
| 3282 |
| 3283 |
3280 void CallConstructStub::Generate(MacroAssembler* masm) { | 3284 void CallConstructStub::Generate(MacroAssembler* masm) { |
3281 ASM_LOCATION("CallConstructStub::Generate"); | 3285 ASM_LOCATION("CallConstructStub::Generate"); |
3282 // x0 : number of arguments | 3286 // x0 : number of arguments |
3283 // x1 : the function to call | 3287 // x1 : the function to call |
3284 // x2 : feedback vector | 3288 // x2 : feedback vector |
3285 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) | 3289 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) |
3286 Register function = x1; | 3290 Register function = x1; |
3287 Label slow, non_function_call; | 3291 Label slow, non_function_call; |
3288 | 3292 |
3289 // Check that the function is not a smi. | 3293 // Check that the function is not a smi. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3349 | 3353 |
3350 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { | 3354 static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) { |
3351 __ Ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3355 __ Ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
3352 __ Ldr(vector, FieldMemOperand(vector, | 3356 __ Ldr(vector, FieldMemOperand(vector, |
3353 JSFunction::kSharedFunctionInfoOffset)); | 3357 JSFunction::kSharedFunctionInfoOffset)); |
3354 __ Ldr(vector, FieldMemOperand(vector, | 3358 __ Ldr(vector, FieldMemOperand(vector, |
3355 SharedFunctionInfo::kFeedbackVectorOffset)); | 3359 SharedFunctionInfo::kFeedbackVectorOffset)); |
3356 } | 3360 } |
3357 | 3361 |
3358 | 3362 |
| 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 |
3359 void CallICStub::Generate(MacroAssembler* masm) { | 3416 void CallICStub::Generate(MacroAssembler* masm) { |
3360 ASM_LOCATION("CallICStub"); | 3417 ASM_LOCATION("CallICStub"); |
3361 | 3418 |
3362 // x1 - function | 3419 // x1 - function |
3363 // x3 - slot id (Smi) | 3420 // x3 - slot id (Smi) |
3364 Label extra_checks_or_miss, slow_start; | 3421 Label extra_checks_or_miss, slow_start; |
3365 Label slow, non_function, wrap, cont; | 3422 Label slow, non_function, wrap, cont; |
3366 Label have_js_function; | 3423 Label have_js_function; |
3367 int argc = state_.arg_count(); | 3424 int argc = state_.arg_count(); |
3368 ParameterCount actual(argc); | 3425 ParameterCount actual(argc); |
3369 | 3426 |
3370 Register function = x1; | 3427 Register function = x1; |
3371 Register feedback_vector = x2; | 3428 Register feedback_vector = x2; |
3372 Register index = x3; | 3429 Register index = x3; |
3373 Register type = x4; | 3430 Register type = x4; |
3374 | 3431 |
3375 EmitLoadTypeFeedbackVector(masm, feedback_vector); | 3432 EmitLoadTypeFeedbackVector(masm, feedback_vector); |
3376 | 3433 |
| 3434 if (state_.stub_type() != CallIC::DEFAULT) { |
| 3435 Generate_CustomFeedbackCall(masm); |
| 3436 return; |
| 3437 } |
| 3438 |
3377 // The checks. First, does x1 match the recorded monomorphic target? | 3439 // The checks. First, does x1 match the recorded monomorphic target? |
3378 __ Add(x4, feedback_vector, | 3440 __ Add(x4, feedback_vector, |
3379 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 3441 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
3380 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); | 3442 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); |
3381 | 3443 |
3382 __ Cmp(x4, function); | 3444 __ Cmp(x4, function); |
3383 __ B(ne, &extra_checks_or_miss); | 3445 __ B(ne, &extra_checks_or_miss); |
3384 | 3446 |
3385 __ bind(&have_js_function); | 3447 __ bind(&have_js_function); |
3386 if (state_.CallAsMethod()) { | 3448 if (state_.CallAsMethod()) { |
(...skipping 2116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5503 MemOperand(fp, 6 * kPointerSize), | 5565 MemOperand(fp, 6 * kPointerSize), |
5504 NULL); | 5566 NULL); |
5505 } | 5567 } |
5506 | 5568 |
5507 | 5569 |
5508 #undef __ | 5570 #undef __ |
5509 | 5571 |
5510 } } // namespace v8::internal | 5572 } } // namespace v8::internal |
5511 | 5573 |
5512 #endif // V8_TARGET_ARCH_ARM64 | 5574 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |