OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 InvokeFlag flag, | 841 InvokeFlag flag, |
842 const CallWrapper& call_wrapper) { | 842 const CallWrapper& call_wrapper) { |
843 // You can't call a builtin without a valid frame. | 843 // You can't call a builtin without a valid frame. |
844 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 844 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
845 | 845 |
846 // Rely on the assertion to check that the number of provided | 846 // Rely on the assertion to check that the number of provided |
847 // arguments match the expected number of arguments. Fake a | 847 // arguments match the expected number of arguments. Fake a |
848 // parameter count to avoid emitting code to do the check. | 848 // parameter count to avoid emitting code to do the check. |
849 ParameterCount expected(0); | 849 ParameterCount expected(0); |
850 GetBuiltinEntry(rdx, id); | 850 GetBuiltinEntry(rdx, id); |
851 InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD); | 851 InvokeCode(rdx, expected, expected, flag, call_wrapper); |
852 } | 852 } |
853 | 853 |
854 | 854 |
855 void MacroAssembler::GetBuiltinFunction(Register target, | 855 void MacroAssembler::GetBuiltinFunction(Register target, |
856 Builtins::JavaScript id) { | 856 Builtins::JavaScript id) { |
857 // Load the builtins object into target register. | 857 // Load the builtins object into target register. |
858 movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 858 movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
859 movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); | 859 movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); |
860 movq(target, FieldOperand(target, | 860 movq(target, FieldOperand(target, |
861 JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 861 JSBuiltinsObject::OffsetOfFunctionWithId(id))); |
(...skipping 2603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3465 void MacroAssembler::DebugBreak() { | 3465 void MacroAssembler::DebugBreak() { |
3466 Set(rax, 0); // No arguments. | 3466 Set(rax, 0); // No arguments. |
3467 LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate())); | 3467 LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak, isolate())); |
3468 CEntryStub ces(1); | 3468 CEntryStub ces(1); |
3469 ASSERT(AllowThisStubCall(&ces)); | 3469 ASSERT(AllowThisStubCall(&ces)); |
3470 Call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK); | 3470 Call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK); |
3471 } | 3471 } |
3472 #endif // ENABLE_DEBUGGER_SUPPORT | 3472 #endif // ENABLE_DEBUGGER_SUPPORT |
3473 | 3473 |
3474 | 3474 |
3475 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { | |
3476 // This macro takes the dst register to make the code more readable | |
3477 // at the call sites. However, the dst register has to be rcx to | |
3478 // follow the calling convention which requires the call type to be | |
3479 // in rcx. | |
3480 ASSERT(dst.is(rcx)); | |
3481 if (call_kind == CALL_AS_FUNCTION) { | |
3482 LoadSmiConstant(dst, Smi::FromInt(1)); | |
3483 } else { | |
3484 LoadSmiConstant(dst, Smi::FromInt(0)); | |
3485 } | |
3486 } | |
3487 | |
3488 | |
3489 void MacroAssembler::InvokeCode(Register code, | 3475 void MacroAssembler::InvokeCode(Register code, |
3490 const ParameterCount& expected, | 3476 const ParameterCount& expected, |
3491 const ParameterCount& actual, | 3477 const ParameterCount& actual, |
3492 InvokeFlag flag, | 3478 InvokeFlag flag, |
3493 const CallWrapper& call_wrapper, | 3479 const CallWrapper& call_wrapper) { |
3494 CallKind call_kind) { | |
3495 // You can't call a function without a valid frame. | 3480 // You can't call a function without a valid frame. |
3496 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3481 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
3497 | 3482 |
3498 Label done; | 3483 Label done; |
3499 bool definitely_mismatches = false; | 3484 bool definitely_mismatches = false; |
3500 InvokePrologue(expected, | 3485 InvokePrologue(expected, |
3501 actual, | 3486 actual, |
3502 Handle<Code>::null(), | 3487 Handle<Code>::null(), |
3503 code, | 3488 code, |
3504 &done, | 3489 &done, |
3505 &definitely_mismatches, | 3490 &definitely_mismatches, |
3506 flag, | 3491 flag, |
3507 Label::kNear, | 3492 Label::kNear, |
3508 call_wrapper, | 3493 call_wrapper); |
3509 call_kind); | |
3510 if (!definitely_mismatches) { | 3494 if (!definitely_mismatches) { |
3511 if (flag == CALL_FUNCTION) { | 3495 if (flag == CALL_FUNCTION) { |
3512 call_wrapper.BeforeCall(CallSize(code)); | 3496 call_wrapper.BeforeCall(CallSize(code)); |
3513 SetCallKind(rcx, call_kind); | |
3514 call(code); | 3497 call(code); |
3515 call_wrapper.AfterCall(); | 3498 call_wrapper.AfterCall(); |
3516 } else { | 3499 } else { |
3517 ASSERT(flag == JUMP_FUNCTION); | 3500 ASSERT(flag == JUMP_FUNCTION); |
3518 SetCallKind(rcx, call_kind); | |
3519 jmp(code); | 3501 jmp(code); |
3520 } | 3502 } |
3521 bind(&done); | 3503 bind(&done); |
3522 } | 3504 } |
3523 } | 3505 } |
3524 | 3506 |
3525 | 3507 |
3526 void MacroAssembler::InvokeCode(Handle<Code> code, | 3508 void MacroAssembler::InvokeCode(Handle<Code> code, |
3527 const ParameterCount& expected, | 3509 const ParameterCount& expected, |
3528 const ParameterCount& actual, | 3510 const ParameterCount& actual, |
3529 RelocInfo::Mode rmode, | 3511 RelocInfo::Mode rmode, |
3530 InvokeFlag flag, | 3512 InvokeFlag flag, |
3531 const CallWrapper& call_wrapper, | 3513 const CallWrapper& call_wrapper) { |
3532 CallKind call_kind) { | |
3533 // You can't call a function without a valid frame. | 3514 // You can't call a function without a valid frame. |
3534 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3515 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
3535 | 3516 |
3536 Label done; | 3517 Label done; |
3537 bool definitely_mismatches = false; | 3518 bool definitely_mismatches = false; |
3538 Register dummy = rax; | 3519 Register dummy = rax; |
3539 InvokePrologue(expected, | 3520 InvokePrologue(expected, |
3540 actual, | 3521 actual, |
3541 code, | 3522 code, |
3542 dummy, | 3523 dummy, |
3543 &done, | 3524 &done, |
3544 &definitely_mismatches, | 3525 &definitely_mismatches, |
3545 flag, | 3526 flag, |
3546 Label::kNear, | 3527 Label::kNear, |
3547 call_wrapper, | 3528 call_wrapper); |
3548 call_kind); | |
3549 if (!definitely_mismatches) { | 3529 if (!definitely_mismatches) { |
3550 if (flag == CALL_FUNCTION) { | 3530 if (flag == CALL_FUNCTION) { |
3551 call_wrapper.BeforeCall(CallSize(code)); | 3531 call_wrapper.BeforeCall(CallSize(code)); |
3552 SetCallKind(rcx, call_kind); | |
3553 Call(code, rmode); | 3532 Call(code, rmode); |
3554 call_wrapper.AfterCall(); | 3533 call_wrapper.AfterCall(); |
3555 } else { | 3534 } else { |
3556 ASSERT(flag == JUMP_FUNCTION); | 3535 ASSERT(flag == JUMP_FUNCTION); |
3557 SetCallKind(rcx, call_kind); | |
3558 Jump(code, rmode); | 3536 Jump(code, rmode); |
3559 } | 3537 } |
3560 bind(&done); | 3538 bind(&done); |
3561 } | 3539 } |
3562 } | 3540 } |
3563 | 3541 |
3564 | 3542 |
3565 void MacroAssembler::InvokeFunction(Register function, | 3543 void MacroAssembler::InvokeFunction(Register function, |
3566 const ParameterCount& actual, | 3544 const ParameterCount& actual, |
3567 InvokeFlag flag, | 3545 InvokeFlag flag, |
3568 const CallWrapper& call_wrapper, | 3546 const CallWrapper& call_wrapper) { |
3569 CallKind call_kind) { | |
3570 // You can't call a function without a valid frame. | 3547 // You can't call a function without a valid frame. |
3571 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3548 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
3572 | 3549 |
3573 ASSERT(function.is(rdi)); | 3550 ASSERT(function.is(rdi)); |
3574 movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3551 movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
3575 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); | 3552 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); |
3576 movsxlq(rbx, | 3553 movsxlq(rbx, |
3577 FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); | 3554 FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); |
3578 // Advances rdx to the end of the Code object header, to the start of | 3555 // Advances rdx to the end of the Code object header, to the start of |
3579 // the executable code. | 3556 // the executable code. |
3580 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 3557 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
3581 | 3558 |
3582 ParameterCount expected(rbx); | 3559 ParameterCount expected(rbx); |
3583 InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); | 3560 InvokeCode(rdx, expected, actual, flag, call_wrapper); |
3584 } | 3561 } |
3585 | 3562 |
3586 | 3563 |
3587 void MacroAssembler::InvokeFunction(Register function, | 3564 void MacroAssembler::InvokeFunction(Register function, |
3588 const ParameterCount& expected, | 3565 const ParameterCount& expected, |
3589 const ParameterCount& actual, | 3566 const ParameterCount& actual, |
3590 InvokeFlag flag, | 3567 InvokeFlag flag, |
3591 const CallWrapper& call_wrapper, | 3568 const CallWrapper& call_wrapper) { |
3592 CallKind call_kind) { | |
3593 // You can't call a function without a valid frame. | 3569 // You can't call a function without a valid frame. |
3594 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3570 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
3595 | 3571 |
3596 ASSERT(function.is(rdi)); | 3572 ASSERT(function.is(rdi)); |
3597 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); | 3573 movq(rsi, FieldOperand(function, JSFunction::kContextOffset)); |
3598 // Advances rdx to the end of the Code object header, to the start of | 3574 // Advances rdx to the end of the Code object header, to the start of |
3599 // the executable code. | 3575 // the executable code. |
3600 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 3576 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
3601 | 3577 |
3602 InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); | 3578 InvokeCode(rdx, expected, actual, flag, call_wrapper); |
3603 } | 3579 } |
3604 | 3580 |
3605 | 3581 |
3606 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 3582 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
3607 const ParameterCount& expected, | 3583 const ParameterCount& expected, |
3608 const ParameterCount& actual, | 3584 const ParameterCount& actual, |
3609 InvokeFlag flag, | 3585 InvokeFlag flag, |
3610 const CallWrapper& call_wrapper, | 3586 const CallWrapper& call_wrapper) { |
3611 CallKind call_kind) { | |
3612 Move(rdi, function); | 3587 Move(rdi, function); |
3613 InvokeFunction(rdi, expected, actual, flag, call_wrapper, call_kind); | 3588 InvokeFunction(rdi, expected, actual, flag, call_wrapper); |
3614 } | 3589 } |
3615 | 3590 |
3616 | 3591 |
3617 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 3592 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
3618 const ParameterCount& actual, | 3593 const ParameterCount& actual, |
3619 Handle<Code> code_constant, | 3594 Handle<Code> code_constant, |
3620 Register code_register, | 3595 Register code_register, |
3621 Label* done, | 3596 Label* done, |
3622 bool* definitely_mismatches, | 3597 bool* definitely_mismatches, |
3623 InvokeFlag flag, | 3598 InvokeFlag flag, |
3624 Label::Distance near_jump, | 3599 Label::Distance near_jump, |
3625 const CallWrapper& call_wrapper, | 3600 const CallWrapper& call_wrapper) { |
3626 CallKind call_kind) { | |
3627 bool definitely_matches = false; | 3601 bool definitely_matches = false; |
3628 *definitely_mismatches = false; | 3602 *definitely_mismatches = false; |
3629 Label invoke; | 3603 Label invoke; |
3630 if (expected.is_immediate()) { | 3604 if (expected.is_immediate()) { |
3631 ASSERT(actual.is_immediate()); | 3605 ASSERT(actual.is_immediate()); |
3632 if (expected.immediate() == actual.immediate()) { | 3606 if (expected.immediate() == actual.immediate()) { |
3633 definitely_matches = true; | 3607 definitely_matches = true; |
3634 } else { | 3608 } else { |
3635 Set(rax, actual.immediate()); | 3609 Set(rax, actual.immediate()); |
3636 if (expected.immediate() == | 3610 if (expected.immediate() == |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3668 Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 3642 Handle<Code> adaptor = isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
3669 if (!code_constant.is_null()) { | 3643 if (!code_constant.is_null()) { |
3670 Move(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); | 3644 Move(rdx, code_constant, RelocInfo::EMBEDDED_OBJECT); |
3671 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3645 addq(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
3672 } else if (!code_register.is(rdx)) { | 3646 } else if (!code_register.is(rdx)) { |
3673 movq(rdx, code_register); | 3647 movq(rdx, code_register); |
3674 } | 3648 } |
3675 | 3649 |
3676 if (flag == CALL_FUNCTION) { | 3650 if (flag == CALL_FUNCTION) { |
3677 call_wrapper.BeforeCall(CallSize(adaptor)); | 3651 call_wrapper.BeforeCall(CallSize(adaptor)); |
3678 SetCallKind(rcx, call_kind); | |
3679 Call(adaptor, RelocInfo::CODE_TARGET); | 3652 Call(adaptor, RelocInfo::CODE_TARGET); |
3680 call_wrapper.AfterCall(); | 3653 call_wrapper.AfterCall(); |
3681 if (!*definitely_mismatches) { | 3654 if (!*definitely_mismatches) { |
3682 jmp(done, near_jump); | 3655 jmp(done, near_jump); |
3683 } | 3656 } |
3684 } else { | 3657 } else { |
3685 SetCallKind(rcx, call_kind); | |
3686 Jump(adaptor, RelocInfo::CODE_TARGET); | 3658 Jump(adaptor, RelocInfo::CODE_TARGET); |
3687 } | 3659 } |
3688 bind(&invoke); | 3660 bind(&invoke); |
3689 } | 3661 } |
3690 } | 3662 } |
3691 | 3663 |
3692 | 3664 |
3693 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { | 3665 void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { |
3694 if (frame_mode == BUILD_STUB_FRAME) { | 3666 if (frame_mode == BUILD_STUB_FRAME) { |
3695 push(rbp); // Caller's frame pointer. | 3667 push(rbp); // Caller's frame pointer. |
(...skipping 1351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5047 j(equal, found); | 5019 j(equal, found); |
5048 movq(current, FieldOperand(current, Map::kPrototypeOffset)); | 5020 movq(current, FieldOperand(current, Map::kPrototypeOffset)); |
5049 CompareRoot(current, Heap::kNullValueRootIndex); | 5021 CompareRoot(current, Heap::kNullValueRootIndex); |
5050 j(not_equal, &loop_again); | 5022 j(not_equal, &loop_again); |
5051 } | 5023 } |
5052 | 5024 |
5053 | 5025 |
5054 } } // namespace v8::internal | 5026 } } // namespace v8::internal |
5055 | 5027 |
5056 #endif // V8_TARGET_ARCH_X64 | 5028 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |