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