OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3286 | 3286 |
3287 __ Push(function); | 3287 __ Push(function); |
3288 __ RecordWrite(feedback_vector, scratch1, function, kLRHasNotBeenSaved, | 3288 __ RecordWrite(feedback_vector, scratch1, function, kLRHasNotBeenSaved, |
3289 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 3289 kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
3290 __ Pop(function); | 3290 __ Pop(function); |
3291 | 3291 |
3292 __ Bind(&done); | 3292 __ Bind(&done); |
3293 } | 3293 } |
3294 | 3294 |
3295 | 3295 |
3296 static void GenericCallHelper(MacroAssembler* masm, | 3296 void CallFunctionStub::Generate(MacroAssembler* masm) { |
3297 const CallIC::State& state) { | 3297 ASM_LOCATION("CallFunctionStub::Generate"); |
3298 // x1 function the function to call | 3298 // x1 function the function to call |
| 3299 // x2 : feedback vector |
| 3300 // x3 : slot in feedback vector (smi) (if x2 is not the megamorphic symbol) |
3299 Register function = x1; | 3301 Register function = x1; |
| 3302 Register cache_cell = x2; |
| 3303 Register slot = x3; |
3300 Register type = x4; | 3304 Register type = x4; |
3301 Label slow, non_function, wrap, cont; | 3305 Label slow, non_function, wrap, cont; |
3302 | 3306 |
3303 // TODO(jbramley): This function has a lot of unnamed registers. Name them, | 3307 // TODO(jbramley): This function has a lot of unnamed registers. Name them, |
3304 // and tidy things up a bit. | 3308 // and tidy things up a bit. |
3305 | 3309 |
3306 if (state.IsGeneric()) { | 3310 if (NeedsChecks()) { |
3307 // Check that the function is really a JavaScript function. | 3311 // Check that the function is really a JavaScript function. |
3308 __ JumpIfSmi(function, &non_function); | 3312 __ JumpIfSmi(function, &non_function); |
3309 | 3313 |
3310 // Goto slow case if we do not have a function. | 3314 // Goto slow case if we do not have a function. |
3311 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); | 3315 __ JumpIfNotObjectType(function, x10, type, JS_FUNCTION_TYPE, &slow); |
| 3316 |
| 3317 if (RecordCallTarget()) { |
| 3318 GenerateRecordCallTarget(masm, x0, function, cache_cell, slot, x4, x5); |
| 3319 // Type information was updated. Because we may call Array, which |
| 3320 // expects either undefined or an AllocationSite in ebx we need |
| 3321 // to set ebx to undefined. |
| 3322 __ LoadRoot(cache_cell, Heap::kUndefinedValueRootIndex); |
| 3323 } |
3312 } | 3324 } |
3313 | 3325 |
3314 // Fast-case: Invoke the function now. | 3326 // Fast-case: Invoke the function now. |
3315 // x1 function pushed function | 3327 // x1 function pushed function |
3316 int argc = state.arg_count(); | 3328 ParameterCount actual(argc_); |
3317 ParameterCount actual(argc); | |
3318 | 3329 |
3319 if (state.CallAsMethod()) { | 3330 if (CallAsMethod()) { |
3320 if (state.IsGeneric()) { | 3331 if (NeedsChecks()) { |
3321 // Do not transform the receiver for strict mode functions. | 3332 // Do not transform the receiver for strict mode functions. |
3322 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | 3333 __ Ldr(x3, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
3323 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); | 3334 __ Ldr(w4, FieldMemOperand(x3, SharedFunctionInfo::kCompilerHintsOffset)); |
3324 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, &cont); | 3335 __ Tbnz(w4, SharedFunctionInfo::kStrictModeFunction, &cont); |
3325 | 3336 |
3326 // Do not transform the receiver for native (Compilerhints already in x3). | 3337 // Do not transform the receiver for native (Compilerhints already in x3). |
3327 __ Tbnz(w4, SharedFunctionInfo::kNative, &cont); | 3338 __ Tbnz(w4, SharedFunctionInfo::kNative, &cont); |
3328 } | 3339 } |
3329 | 3340 |
3330 if (state.IsSloppy()) { | 3341 // Compute the receiver in sloppy mode. |
3331 // Compute the receiver in sloppy mode. | 3342 __ Peek(x3, argc_ * kPointerSize); |
3332 __ Peek(x3, argc * kPointerSize); | |
3333 | 3343 |
| 3344 if (NeedsChecks()) { |
3334 __ JumpIfSmi(x3, &wrap); | 3345 __ JumpIfSmi(x3, &wrap); |
3335 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); | 3346 __ JumpIfObjectType(x3, x10, type, FIRST_SPEC_OBJECT_TYPE, &wrap, lt); |
| 3347 } else { |
| 3348 __ B(&wrap); |
3336 } | 3349 } |
3337 | 3350 |
3338 __ Bind(&cont); | 3351 __ Bind(&cont); |
3339 } | 3352 } |
| 3353 __ InvokeFunction(function, |
| 3354 actual, |
| 3355 JUMP_FUNCTION, |
| 3356 NullCallWrapper()); |
3340 | 3357 |
3341 if (state.ArgumentsMustMatch()) { | 3358 if (NeedsChecks()) { |
3342 __ InvokeFunction(function, | |
3343 actual, | |
3344 actual, | |
3345 JUMP_FUNCTION, | |
3346 NullCallWrapper()); | |
3347 } else { | |
3348 __ InvokeFunction(function, | |
3349 actual, | |
3350 JUMP_FUNCTION, | |
3351 NullCallWrapper()); | |
3352 } | |
3353 | |
3354 if (state.IsGeneric()) { | |
3355 // Slow-case: Non-function called. | 3359 // Slow-case: Non-function called. |
3356 __ Bind(&slow); | 3360 __ Bind(&slow); |
| 3361 if (RecordCallTarget()) { |
| 3362 // If there is a call target cache, mark it megamorphic in the |
| 3363 // non-function case. MegamorphicSentinel is an immortal immovable object |
| 3364 // (megamorphic symbol) so no write barrier is needed. |
| 3365 ASSERT_EQ(*TypeFeedbackInfo::MegamorphicSentinel(masm->isolate()), |
| 3366 masm->isolate()->heap()->megamorphic_symbol()); |
| 3367 __ Add(x12, cache_cell, Operand::UntagSmiAndScale(slot, |
| 3368 kPointerSizeLog2)); |
| 3369 __ LoadRoot(x11, Heap::kMegamorphicSymbolRootIndex); |
| 3370 __ Str(x11, FieldMemOperand(x12, FixedArray::kHeaderSize)); |
| 3371 } |
3357 // Check for function proxy. | 3372 // Check for function proxy. |
3358 // x10 : function type. | 3373 // x10 : function type. |
3359 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); | 3374 __ CompareAndBranch(type, JS_FUNCTION_PROXY_TYPE, ne, &non_function); |
3360 __ Push(function); // put proxy as additional argument | 3375 __ Push(function); // put proxy as additional argument |
3361 __ Mov(x0, argc + 1); | 3376 __ Mov(x0, argc_ + 1); |
3362 __ Mov(x2, 0); | 3377 __ Mov(x2, 0); |
3363 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); | 3378 __ GetBuiltinFunction(x1, Builtins::CALL_FUNCTION_PROXY); |
3364 { | 3379 { |
3365 Handle<Code> adaptor = | 3380 Handle<Code> adaptor = |
3366 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3381 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
3367 __ Jump(adaptor, RelocInfo::CODE_TARGET); | 3382 __ Jump(adaptor, RelocInfo::CODE_TARGET); |
3368 } | 3383 } |
3369 | 3384 |
3370 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead | 3385 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead |
3371 // of the original receiver from the call site). | 3386 // of the original receiver from the call site). |
3372 __ Bind(&non_function); | 3387 __ Bind(&non_function); |
3373 __ Poke(function, argc * kXRegSize); | 3388 __ Poke(function, argc_ * kXRegSize); |
3374 __ Mov(x0, argc); // Set up the number of arguments. | 3389 __ Mov(x0, argc_); // Set up the number of arguments. |
3375 __ Mov(x2, 0); | 3390 __ Mov(x2, 0); |
3376 __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION); | 3391 __ GetBuiltinFunction(function, Builtins::CALL_NON_FUNCTION); |
3377 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3392 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
3378 RelocInfo::CODE_TARGET); | 3393 RelocInfo::CODE_TARGET); |
3379 } | 3394 } |
3380 | 3395 |
3381 if (state.CallAsMethod() && state.IsSloppy()) { | 3396 if (CallAsMethod()) { |
3382 __ Bind(&wrap); | 3397 __ Bind(&wrap); |
3383 | |
3384 if (!state.IsGeneric()) { | |
3385 __ Ldr(x5, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); | |
3386 __ Ldr(w4, FieldMemOperand(x5, SharedFunctionInfo::kCompilerHintsOffset)); | |
3387 | |
3388 // Do not transform the receiver for native | |
3389 __ Tbnz(w4, SharedFunctionInfo::kNative, &cont); | |
3390 } | |
3391 | |
3392 // Wrap the receiver and patch it back onto the stack. | 3398 // Wrap the receiver and patch it back onto the stack. |
3393 { FrameScope frame_scope(masm, StackFrame::INTERNAL); | 3399 { FrameScope frame_scope(masm, StackFrame::INTERNAL); |
3394 __ Push(x1, x3); | 3400 __ Push(x1, x3); |
3395 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 3401 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
3396 __ Pop(x1); | 3402 __ Pop(x1); |
3397 } | 3403 } |
3398 __ Poke(x0, argc * kPointerSize); | 3404 __ Poke(x0, argc_ * kPointerSize); |
3399 __ B(&cont); | 3405 __ B(&cont); |
3400 } | 3406 } |
3401 } | 3407 } |
3402 | 3408 |
3403 | 3409 |
3404 void CallFunctionStub::Generate(MacroAssembler* masm) { | |
3405 ASM_LOCATION("CallFunctionStub::Generate"); | |
3406 // x1 function the function to call | |
3407 | |
3408 // GenericCallHelper expresses it's options in terms of CallIC::State. | |
3409 CallIC::CallType call_type = CallAsMethod() ? | |
3410 CallIC::METHOD : CallIC::FUNCTION; | |
3411 | |
3412 if (NeedsChecks()) { | |
3413 GenericCallHelper(masm, | |
3414 CallIC::State::SlowCallState( | |
3415 argc_, | |
3416 call_type)); | |
3417 } else { | |
3418 GenericCallHelper(masm, | |
3419 CallIC::State::MonomorphicCallState( | |
3420 argc_, | |
3421 call_type, | |
3422 CallIC::ARGUMENTS_COUNT_UNKNOWN, | |
3423 SLOPPY)); | |
3424 } | |
3425 } | |
3426 | |
3427 | |
3428 void CallConstructStub::Generate(MacroAssembler* masm) { | 3410 void CallConstructStub::Generate(MacroAssembler* masm) { |
3429 ASM_LOCATION("CallConstructStub::Generate"); | 3411 ASM_LOCATION("CallConstructStub::Generate"); |
3430 // x0 : number of arguments | 3412 // x0 : number of arguments |
3431 // x1 : the function to call | 3413 // x1 : the function to call |
3432 // x2 : feedback vector | 3414 // x2 : feedback vector |
3433 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) | 3415 // x3 : slot in feedback vector (smi) (if r2 is not the megamorphic symbol) |
3434 Register function = x1; | 3416 Register function = x1; |
3435 Label slow, non_function_call; | 3417 Label slow, non_function_call; |
3436 | 3418 |
3437 // Check that the function is not a smi. | 3419 // Check that the function is not a smi. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3488 __ GetBuiltinFunction(x1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | 3470 __ GetBuiltinFunction(x1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
3489 | 3471 |
3490 __ Bind(&do_call); | 3472 __ Bind(&do_call); |
3491 // Set expected number of arguments to zero (not changing x0). | 3473 // Set expected number of arguments to zero (not changing x0). |
3492 __ Mov(x2, 0); | 3474 __ Mov(x2, 0); |
3493 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 3475 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
3494 RelocInfo::CODE_TARGET); | 3476 RelocInfo::CODE_TARGET); |
3495 } | 3477 } |
3496 | 3478 |
3497 | 3479 |
3498 void CallICStub::GenerateMonomorphicCall(MacroAssembler* masm) { | |
3499 GenericCallHelper(masm, | |
3500 CallIC::State::MonomorphicCallState( | |
3501 state_.arg_count(), | |
3502 state_.call_type(), | |
3503 state_.argument_check(), | |
3504 state_.strict_mode())); | |
3505 } | |
3506 | |
3507 | |
3508 void CallICStub::GenerateSlowCall(MacroAssembler* masm) { | |
3509 GenericCallHelper(masm, | |
3510 CallIC::State::SlowCallState( | |
3511 state_.arg_count(), | |
3512 state_.call_type())); | |
3513 } | |
3514 | |
3515 | |
3516 void CallICStub::Generate(MacroAssembler* masm) { | |
3517 ASM_LOCATION("CallICStub"); | |
3518 | |
3519 // x1 - function | |
3520 // x2 - vector | |
3521 // x3 - slot id (Smi) | |
3522 Label extra_checks_or_miss, slow; | |
3523 Register function = x1; | |
3524 Register feedback_vector = x2; | |
3525 Register index = x3; | |
3526 | |
3527 // The checks. First, does x1 match the recorded monomorphic target? | |
3528 __ Add(x4, feedback_vector, | |
3529 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
3530 __ Ldr(x4, FieldMemOperand(x4, FixedArray::kHeaderSize)); | |
3531 | |
3532 __ Cmp(x4, function); | |
3533 __ B(ne, &extra_checks_or_miss); | |
3534 | |
3535 GenerateMonomorphicCall(masm); | |
3536 | |
3537 __ bind(&extra_checks_or_miss); | |
3538 if (IsGeneric()) { | |
3539 Label miss_uninit; | |
3540 | |
3541 __ JumpIfRoot(x4, Heap::kMegamorphicSymbolRootIndex, &slow); | |
3542 __ JumpIfRoot(x4, Heap::kUninitializedSymbolRootIndex, &miss_uninit); | |
3543 // If we get here, go from monomorphic to megamorphic, Don't bother missing, | |
3544 // just update. | |
3545 __ Add(x4, feedback_vector, | |
3546 Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | |
3547 __ LoadRoot(x5, Heap::kMegamorphicSymbolRootIndex); | |
3548 __ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize)); | |
3549 __ B(&slow); | |
3550 | |
3551 __ bind(&miss_uninit); | |
3552 } | |
3553 | |
3554 GenerateMiss(masm); | |
3555 | |
3556 // the slow case | |
3557 __ bind(&slow); | |
3558 GenerateSlowCall(masm); | |
3559 } | |
3560 | |
3561 | |
3562 void CallICStub::GenerateMiss(MacroAssembler* masm) { | |
3563 ASM_LOCATION("CallICStub[Miss]"); | |
3564 | |
3565 // Get the receiver of the function from the stack; 1 ~ return address. | |
3566 __ Peek(x4, (state_.arg_count() + 1) * kPointerSize); | |
3567 | |
3568 { | |
3569 FrameScope scope(masm, StackFrame::INTERNAL); | |
3570 | |
3571 // Push the receiver and the function and feedback info. | |
3572 __ Push(x4, x1, x2, x3); | |
3573 | |
3574 // Call the entry. | |
3575 ExternalReference miss = ExternalReference(IC_Utility(IC::kCallIC_Miss), | |
3576 masm->isolate()); | |
3577 __ CallExternalReference(miss, 4); | |
3578 | |
3579 // Move result to edi and exit the internal frame. | |
3580 __ Mov(x1, x0); | |
3581 } | |
3582 } | |
3583 | |
3584 | |
3585 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 3480 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
3586 // If the receiver is a smi trigger the non-string case. | 3481 // If the receiver is a smi trigger the non-string case. |
3587 __ JumpIfSmi(object_, receiver_not_string_); | 3482 __ JumpIfSmi(object_, receiver_not_string_); |
3588 | 3483 |
3589 // Fetch the instance type of the receiver into result register. | 3484 // Fetch the instance type of the receiver into result register. |
3590 __ Ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); | 3485 __ Ldr(result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
3591 __ Ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); | 3486 __ Ldrb(result_, FieldMemOperand(result_, Map::kInstanceTypeOffset)); |
3592 | 3487 |
3593 // If the receiver is not a string trigger the non-string case. | 3488 // If the receiver is not a string trigger the non-string case. |
3594 __ TestAndBranchIfAnySet(result_, kIsNotStringMask, receiver_not_string_); | 3489 __ TestAndBranchIfAnySet(result_, kIsNotStringMask, receiver_not_string_); |
(...skipping 2243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5838 MemOperand(fp, 6 * kPointerSize), | 5733 MemOperand(fp, 6 * kPointerSize), |
5839 NULL); | 5734 NULL); |
5840 } | 5735 } |
5841 | 5736 |
5842 | 5737 |
5843 #undef __ | 5738 #undef __ |
5844 | 5739 |
5845 } } // namespace v8::internal | 5740 } } // namespace v8::internal |
5846 | 5741 |
5847 #endif // V8_TARGET_ARCH_ARM64 | 5742 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |