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