OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 static const int kPreviousIndexOffset = 2 * kPointerSize; | 2437 static const int kPreviousIndexOffset = 2 * kPointerSize; |
2438 static const int kSubjectOffset = 3 * kPointerSize; | 2438 static const int kSubjectOffset = 3 * kPointerSize; |
2439 static const int kJSRegExpOffset = 4 * kPointerSize; | 2439 static const int kJSRegExpOffset = 4 * kPointerSize; |
2440 | 2440 |
2441 Label runtime; | 2441 Label runtime; |
2442 // Ensure that a RegExp stack is allocated. | 2442 // Ensure that a RegExp stack is allocated. |
2443 ExternalReference address_of_regexp_stack_memory_address = | 2443 ExternalReference address_of_regexp_stack_memory_address = |
2444 ExternalReference::address_of_regexp_stack_memory_address(); | 2444 ExternalReference::address_of_regexp_stack_memory_address(); |
2445 ExternalReference address_of_regexp_stack_memory_size = | 2445 ExternalReference address_of_regexp_stack_memory_size = |
2446 ExternalReference::address_of_regexp_stack_memory_size(); | 2446 ExternalReference::address_of_regexp_stack_memory_size(); |
2447 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | 2447 __ Load(kScratchRegister, address_of_regexp_stack_memory_size); |
2448 __ movq(kScratchRegister, Operand(kScratchRegister, 0)); | |
2449 __ testq(kScratchRegister, kScratchRegister); | 2448 __ testq(kScratchRegister, kScratchRegister); |
2450 __ j(zero, &runtime); | 2449 __ j(zero, &runtime); |
2451 | 2450 |
2452 | 2451 |
2453 // Check that the first argument is a JSRegExp object. | 2452 // Check that the first argument is a JSRegExp object. |
2454 __ movq(rax, Operand(rsp, kJSRegExpOffset)); | 2453 __ movq(rax, Operand(rsp, kJSRegExpOffset)); |
2455 __ JumpIfSmi(rax, &runtime); | 2454 __ JumpIfSmi(rax, &runtime); |
2456 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); | 2455 __ CmpObjectType(rax, JS_REGEXP_TYPE, kScratchRegister); |
2457 __ j(not_equal, &runtime); | 2456 __ j(not_equal, &runtime); |
2458 // Check that the RegExp has been compiled (data contains a fixed array). | 2457 // Check that the RegExp has been compiled (data contains a fixed array). |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2599 | 2598 |
2600 // Isolates: note we add an additional parameter here (isolate pointer). | 2599 // Isolates: note we add an additional parameter here (isolate pointer). |
2601 static const int kRegExpExecuteArguments = 8; | 2600 static const int kRegExpExecuteArguments = 8; |
2602 int argument_slots_on_stack = | 2601 int argument_slots_on_stack = |
2603 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); | 2602 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); |
2604 __ EnterApiExitFrame(argument_slots_on_stack); | 2603 __ EnterApiExitFrame(argument_slots_on_stack); |
2605 | 2604 |
2606 // Argument 8: Pass current isolate address. | 2605 // Argument 8: Pass current isolate address. |
2607 // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | 2606 // __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
2608 // Immediate(ExternalReference::isolate_address())); | 2607 // Immediate(ExternalReference::isolate_address())); |
2609 __ movq(kScratchRegister, ExternalReference::isolate_address()); | 2608 __ LoadAddress(kScratchRegister, ExternalReference::isolate_address()); |
2610 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), | 2609 __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kPointerSize), |
2611 kScratchRegister); | 2610 kScratchRegister); |
2612 | 2611 |
2613 // Argument 7: Indicate that this is a direct call from JavaScript. | 2612 // Argument 7: Indicate that this is a direct call from JavaScript. |
2614 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), | 2613 __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kPointerSize), |
2615 Immediate(1)); | 2614 Immediate(1)); |
2616 | 2615 |
2617 // Argument 6: Start (high end) of backtracking stack memory area. | 2616 // Argument 6: Start (high end) of backtracking stack memory area. |
2618 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); | 2617 __ movq(kScratchRegister, address_of_regexp_stack_memory_address); |
2619 __ movq(r9, Operand(kScratchRegister, 0)); | 2618 __ movq(r9, Operand(kScratchRegister, 0)); |
2620 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); | 2619 __ movq(kScratchRegister, address_of_regexp_stack_memory_size); |
2621 __ addq(r9, Operand(kScratchRegister, 0)); | 2620 __ addq(r9, Operand(kScratchRegister, 0)); |
2622 // Argument 6 passed in r9 on Linux and on the stack on Windows. | 2621 // Argument 6 passed in r9 on Linux and on the stack on Windows. |
2623 #ifdef _WIN64 | 2622 #ifdef _WIN64 |
2624 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9); | 2623 __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kPointerSize), r9); |
2625 #endif | 2624 #endif |
2626 | 2625 |
2627 // Argument 5: static offsets vector buffer. | 2626 // Argument 5: static offsets vector buffer. |
2628 __ movq(r8, ExternalReference::address_of_static_offsets_vector()); | 2627 __ LoadAddress(r8, ExternalReference::address_of_static_offsets_vector()); |
2629 // Argument 5 passed in r8 on Linux and on the stack on Windows. | 2628 // Argument 5 passed in r8 on Linux and on the stack on Windows. |
2630 #ifdef _WIN64 | 2629 #ifdef _WIN64 |
2631 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), r8); | 2630 __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kPointerSize), r8); |
2632 #endif | 2631 #endif |
2633 | 2632 |
2634 // First four arguments are passed in registers on both Linux and Windows. | 2633 // First four arguments are passed in registers on both Linux and Windows. |
2635 #ifdef _WIN64 | 2634 #ifdef _WIN64 |
2636 Register arg4 = r9; | 2635 Register arg4 = r9; |
2637 Register arg3 = r8; | 2636 Register arg3 = r8; |
2638 Register arg2 = rdx; | 2637 Register arg2 = rdx; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2722 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2721 __ movq(rax, Operand(rsp, kSubjectOffset)); |
2723 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); | 2722 __ movq(FieldOperand(rbx, RegExpImpl::kLastSubjectOffset), rax); |
2724 __ movq(rcx, rbx); | 2723 __ movq(rcx, rbx); |
2725 __ RecordWrite(rcx, RegExpImpl::kLastSubjectOffset, rax, rdi); | 2724 __ RecordWrite(rcx, RegExpImpl::kLastSubjectOffset, rax, rdi); |
2726 __ movq(rax, Operand(rsp, kSubjectOffset)); | 2725 __ movq(rax, Operand(rsp, kSubjectOffset)); |
2727 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); | 2726 __ movq(FieldOperand(rbx, RegExpImpl::kLastInputOffset), rax); |
2728 __ movq(rcx, rbx); | 2727 __ movq(rcx, rbx); |
2729 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi); | 2728 __ RecordWrite(rcx, RegExpImpl::kLastInputOffset, rax, rdi); |
2730 | 2729 |
2731 // Get the static offsets vector filled by the native regexp code. | 2730 // Get the static offsets vector filled by the native regexp code. |
2732 __ movq(rcx, ExternalReference::address_of_static_offsets_vector()); | 2731 __ LoadAddress(rcx, ExternalReference::address_of_static_offsets_vector()); |
2733 | 2732 |
2734 // rbx: last_match_info backing store (FixedArray) | 2733 // rbx: last_match_info backing store (FixedArray) |
2735 // rcx: offsets vector | 2734 // rcx: offsets vector |
2736 // rdx: number of capture registers | 2735 // rdx: number of capture registers |
2737 NearLabel next_capture, done; | 2736 NearLabel next_capture, done; |
2738 // Capture register counter starts from number of capture registers and | 2737 // Capture register counter starts from number of capture registers and |
2739 // counts down until wraping after zero. | 2738 // counts down until wraping after zero. |
2740 __ bind(&next_capture); | 2739 __ bind(&next_capture); |
2741 __ subq(rdx, Immediate(1)); | 2740 __ subq(rdx, Immediate(1)); |
2742 __ j(negative, &done); | 2741 __ j(negative, &done); |
(...skipping 13 matching lines...) Expand all Loading... |
2756 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); | 2755 __ movq(rax, Operand(rsp, kLastMatchInfoOffset)); |
2757 __ ret(4 * kPointerSize); | 2756 __ ret(4 * kPointerSize); |
2758 | 2757 |
2759 __ bind(&exception); | 2758 __ bind(&exception); |
2760 // Result must now be exception. If there is no pending exception already a | 2759 // Result must now be exception. If there is no pending exception already a |
2761 // stack overflow (on the backtrack stack) was detected in RegExp code but | 2760 // stack overflow (on the backtrack stack) was detected in RegExp code but |
2762 // haven't created the exception yet. Handle that in the runtime system. | 2761 // haven't created the exception yet. Handle that in the runtime system. |
2763 // TODO(592): Rerunning the RegExp to get the stack overflow exception. | 2762 // TODO(592): Rerunning the RegExp to get the stack overflow exception. |
2764 ExternalReference pending_exception_address( | 2763 ExternalReference pending_exception_address( |
2765 Isolate::k_pending_exception_address); | 2764 Isolate::k_pending_exception_address); |
2766 __ movq(rbx, pending_exception_address); | 2765 Operand pending_exception_operand = |
2767 __ movq(rax, Operand(rbx, 0)); | 2766 masm->ExternalOperand(pending_exception_address, rbx); |
| 2767 __ movq(rax, pending_exception_operand); |
2768 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); | 2768 __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
2769 __ cmpq(rax, rdx); | 2769 __ cmpq(rax, rdx); |
2770 __ j(equal, &runtime); | 2770 __ j(equal, &runtime); |
2771 __ movq(Operand(rbx, 0), rdx); | 2771 __ movq(pending_exception_operand, rdx); |
2772 | 2772 |
2773 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 2773 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
2774 NearLabel termination_exception; | 2774 NearLabel termination_exception; |
2775 __ j(equal, &termination_exception); | 2775 __ j(equal, &termination_exception); |
2776 __ Throw(rax); | 2776 __ Throw(rax); |
2777 | 2777 |
2778 __ bind(&termination_exception); | 2778 __ bind(&termination_exception); |
2779 __ ThrowUncatchable(TERMINATION, rax); | 2779 __ ThrowUncatchable(TERMINATION, rax); |
2780 | 2780 |
2781 // Do the runtime call to execute the regexp. | 2781 // Do the runtime call to execute the regexp. |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3373 #endif | 3373 #endif |
3374 __ movq(kScratchRegister, | 3374 __ movq(kScratchRegister, |
3375 FUNCTION_ADDR(Runtime::PerformGC), | 3375 FUNCTION_ADDR(Runtime::PerformGC), |
3376 RelocInfo::RUNTIME_ENTRY); | 3376 RelocInfo::RUNTIME_ENTRY); |
3377 __ call(kScratchRegister); | 3377 __ call(kScratchRegister); |
3378 } | 3378 } |
3379 | 3379 |
3380 ExternalReference scope_depth = | 3380 ExternalReference scope_depth = |
3381 ExternalReference::heap_always_allocate_scope_depth(); | 3381 ExternalReference::heap_always_allocate_scope_depth(); |
3382 if (always_allocate_scope) { | 3382 if (always_allocate_scope) { |
3383 __ movq(kScratchRegister, scope_depth); | 3383 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); |
3384 __ incl(Operand(kScratchRegister, 0)); | 3384 __ incl(scope_depth_operand); |
3385 } | 3385 } |
3386 | 3386 |
3387 // Call C function. | 3387 // Call C function. |
3388 #ifdef _WIN64 | 3388 #ifdef _WIN64 |
3389 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 | 3389 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 |
3390 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. | 3390 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. |
3391 __ movq(StackSpaceOperand(0), r14); // argc. | 3391 __ movq(StackSpaceOperand(0), r14); // argc. |
3392 __ movq(StackSpaceOperand(1), r15); // argv. | 3392 __ movq(StackSpaceOperand(1), r15); // argv. |
3393 if (result_size_ < 2) { | 3393 if (result_size_ < 2) { |
3394 // Pass a pointer to the Arguments object as the first argument. | 3394 // Pass a pointer to the Arguments object as the first argument. |
3395 // Return result in single register (rax). | 3395 // Return result in single register (rax). |
3396 __ lea(rcx, StackSpaceOperand(0)); | 3396 __ lea(rcx, StackSpaceOperand(0)); |
3397 __ movq(rdx, ExternalReference::isolate_address()); | 3397 __ LoadAddress(rdx, ExternalReference::isolate_address()); |
3398 } else { | 3398 } else { |
3399 ASSERT_EQ(2, result_size_); | 3399 ASSERT_EQ(2, result_size_); |
3400 // Pass a pointer to the result location as the first argument. | 3400 // Pass a pointer to the result location as the first argument. |
3401 __ lea(rcx, StackSpaceOperand(2)); | 3401 __ lea(rcx, StackSpaceOperand(2)); |
3402 // Pass a pointer to the Arguments object as the second argument. | 3402 // Pass a pointer to the Arguments object as the second argument. |
3403 __ lea(rdx, StackSpaceOperand(0)); | 3403 __ lea(rdx, StackSpaceOperand(0)); |
3404 __ movq(r8, ExternalReference::isolate_address()); | 3404 __ LoadAddress(r8, ExternalReference::isolate_address()); |
3405 } | 3405 } |
3406 | 3406 |
3407 #else // _WIN64 | 3407 #else // _WIN64 |
3408 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. | 3408 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. |
3409 __ movq(rdi, r14); // argc. | 3409 __ movq(rdi, r14); // argc. |
3410 __ movq(rsi, r15); // argv. | 3410 __ movq(rsi, r15); // argv. |
3411 __ movq(rdx, ExternalReference::isolate_address()); | 3411 __ movq(rdx, ExternalReference::isolate_address()); |
3412 #endif | 3412 #endif |
3413 __ call(rbx); | 3413 __ call(rbx); |
3414 // Result is in rax - do not destroy this register! | 3414 // Result is in rax - do not destroy this register! |
3415 | 3415 |
3416 if (always_allocate_scope) { | 3416 if (always_allocate_scope) { |
3417 __ movq(kScratchRegister, scope_depth); | 3417 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); |
3418 __ decl(Operand(kScratchRegister, 0)); | 3418 __ decl(scope_depth_operand); |
3419 } | 3419 } |
3420 | 3420 |
3421 // Check for failure result. | 3421 // Check for failure result. |
3422 Label failure_returned; | 3422 Label failure_returned; |
3423 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 3423 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
3424 #ifdef _WIN64 | 3424 #ifdef _WIN64 |
3425 // If return value is on the stack, pop it to registers. | 3425 // If return value is on the stack, pop it to registers. |
3426 if (result_size_ > 1) { | 3426 if (result_size_ > 1) { |
3427 ASSERT_EQ(2, result_size_); | 3427 ASSERT_EQ(2, result_size_); |
3428 // Read result values stored on stack. Result is stored | 3428 // Read result values stored on stack. Result is stored |
(...skipping 22 matching lines...) Expand all Loading... |
3451 __ j(zero, &retry); | 3451 __ j(zero, &retry); |
3452 | 3452 |
3453 // Special handling of out of memory exceptions. | 3453 // Special handling of out of memory exceptions. |
3454 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); | 3454 __ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE); |
3455 __ cmpq(rax, kScratchRegister); | 3455 __ cmpq(rax, kScratchRegister); |
3456 __ j(equal, throw_out_of_memory_exception); | 3456 __ j(equal, throw_out_of_memory_exception); |
3457 | 3457 |
3458 // Retrieve the pending exception and clear the variable. | 3458 // Retrieve the pending exception and clear the variable. |
3459 ExternalReference pending_exception_address( | 3459 ExternalReference pending_exception_address( |
3460 Isolate::k_pending_exception_address); | 3460 Isolate::k_pending_exception_address); |
3461 __ movq(kScratchRegister, pending_exception_address); | 3461 Operand pending_exception_operand = |
3462 __ movq(rax, Operand(kScratchRegister, 0)); | 3462 masm->ExternalOperand(pending_exception_address); |
| 3463 __ movq(rax, pending_exception_operand); |
3463 __ movq(rdx, ExternalReference::the_hole_value_location()); | 3464 __ movq(rdx, ExternalReference::the_hole_value_location()); |
3464 __ movq(rdx, Operand(rdx, 0)); | 3465 __ movq(rdx, Operand(rdx, 0)); |
3465 __ movq(Operand(kScratchRegister, 0), rdx); | 3466 __ movq(pending_exception_operand, rdx); |
3466 | 3467 |
3467 // Special handling of termination exceptions which are uncatchable | 3468 // Special handling of termination exceptions which are uncatchable |
3468 // by javascript code. | 3469 // by javascript code. |
3469 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); | 3470 __ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
3470 __ j(equal, throw_termination_exception); | 3471 __ j(equal, throw_termination_exception); |
3471 | 3472 |
3472 // Handle normal exception. | 3473 // Handle normal exception. |
3473 __ jmp(throw_normal_exception); | 3474 __ jmp(throw_normal_exception); |
3474 | 3475 |
3475 // Retry. | 3476 // Retry. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3554 __ bind(&throw_normal_exception); | 3555 __ bind(&throw_normal_exception); |
3555 GenerateThrowTOS(masm); | 3556 GenerateThrowTOS(masm); |
3556 } | 3557 } |
3557 | 3558 |
3558 | 3559 |
3559 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 3560 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
3560 Label invoke, exit; | 3561 Label invoke, exit; |
3561 #ifdef ENABLE_LOGGING_AND_PROFILING | 3562 #ifdef ENABLE_LOGGING_AND_PROFILING |
3562 Label not_outermost_js, not_outermost_js_2; | 3563 Label not_outermost_js, not_outermost_js_2; |
3563 #endif | 3564 #endif |
| 3565 { // NOLINT. Scope block confuses linter. |
| 3566 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); |
| 3567 // Setup frame. |
| 3568 __ push(rbp); |
| 3569 __ movq(rbp, rsp); |
3564 | 3570 |
3565 // Setup frame. | 3571 // Push the stack frame type marker twice. |
3566 __ push(rbp); | 3572 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
3567 __ movq(rbp, rsp); | 3573 // Scratch register is neither callee-save, nor an argument register on any |
| 3574 // platform. It's free to use at this point. |
| 3575 // Cannot use smi-register for loading yet. |
| 3576 __ movq(kScratchRegister, |
| 3577 reinterpret_cast<uint64_t>(Smi::FromInt(marker)), |
| 3578 RelocInfo::NONE); |
| 3579 __ push(kScratchRegister); // context slot |
| 3580 __ push(kScratchRegister); // function slot |
| 3581 // Save callee-saved registers (X64/Win64 calling conventions). |
| 3582 __ push(r12); |
| 3583 __ push(r13); |
| 3584 __ push(r14); |
| 3585 __ push(r15); |
| 3586 #ifdef _WIN64 |
| 3587 __ push(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. |
| 3588 __ push(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. |
| 3589 #endif |
| 3590 __ push(rbx); |
| 3591 // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are |
| 3592 // callee save as well. |
3568 | 3593 |
3569 // Push the stack frame type marker twice. | 3594 // Set up the roots and smi constant registers. |
3570 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 3595 // Needs to be done before any further smi loads. |
3571 // Scratch register is neither callee-save, nor an argument register on any | 3596 __ InitializeSmiConstantRegister(); |
3572 // platform. It's free to use at this point. | 3597 __ InitializeRootRegister(); |
3573 // Cannot use smi-register for loading yet. | 3598 } |
3574 __ movq(kScratchRegister, | |
3575 reinterpret_cast<uint64_t>(Smi::FromInt(marker)), | |
3576 RelocInfo::NONE); | |
3577 __ push(kScratchRegister); // context slot | |
3578 __ push(kScratchRegister); // function slot | |
3579 // Save callee-saved registers (X64/Win64 calling conventions). | |
3580 __ push(r12); | |
3581 __ push(r13); | |
3582 __ push(r14); | |
3583 __ push(r15); | |
3584 #ifdef _WIN64 | |
3585 __ push(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI. | |
3586 __ push(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI. | |
3587 #endif | |
3588 __ push(rbx); | |
3589 // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are | |
3590 // callee save as well. | |
3591 | 3599 |
3592 // Save copies of the top frame descriptor on the stack. | 3600 // Save copies of the top frame descriptor on the stack. |
3593 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address); | 3601 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address); |
3594 __ load_rax(c_entry_fp); | 3602 { |
3595 __ push(rax); | 3603 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); |
3596 | 3604 __ push(c_entry_fp_operand); |
3597 // Set up the roots and smi constant registers. | 3605 } |
3598 // Needs to be done before any further smi loads. | |
3599 __ InitializeRootRegister(); | |
3600 __ InitializeSmiConstantRegister(); | |
3601 | 3606 |
3602 #ifdef ENABLE_LOGGING_AND_PROFILING | 3607 #ifdef ENABLE_LOGGING_AND_PROFILING |
3603 // If this is the outermost JS call, set js_entry_sp value. | 3608 // If this is the outermost JS call, set js_entry_sp value. |
3604 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address); | 3609 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address); |
3605 __ load_rax(js_entry_sp); | 3610 __ Load(rax, js_entry_sp); |
3606 __ testq(rax, rax); | 3611 __ testq(rax, rax); |
3607 __ j(not_zero, ¬_outermost_js); | 3612 __ j(not_zero, ¬_outermost_js); |
3608 __ movq(rax, rbp); | 3613 __ movq(rax, rbp); |
3609 __ store_rax(js_entry_sp); | 3614 __ Store(js_entry_sp, rax); |
3610 __ bind(¬_outermost_js); | 3615 __ bind(¬_outermost_js); |
3611 #endif | 3616 #endif |
3612 | 3617 |
3613 // Call a faked try-block that does the invoke. | 3618 // Call a faked try-block that does the invoke. |
3614 __ call(&invoke); | 3619 __ call(&invoke); |
3615 | 3620 |
3616 // Caught exception: Store result (exception) in the pending | 3621 // Caught exception: Store result (exception) in the pending |
3617 // exception field in the JSEnv and return a failure sentinel. | 3622 // exception field in the JSEnv and return a failure sentinel. |
3618 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 3623 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
3619 __ store_rax(pending_exception); | 3624 __ Store(pending_exception, rax); |
3620 __ movq(rax, Failure::Exception(), RelocInfo::NONE); | 3625 __ movq(rax, Failure::Exception(), RelocInfo::NONE); |
3621 __ jmp(&exit); | 3626 __ jmp(&exit); |
3622 | 3627 |
3623 // Invoke: Link this frame into the handler chain. | 3628 // Invoke: Link this frame into the handler chain. |
3624 __ bind(&invoke); | 3629 __ bind(&invoke); |
3625 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); | 3630 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); |
3626 | 3631 |
3627 // Clear any pending exceptions. | 3632 // Clear any pending exceptions. |
3628 __ load_rax(ExternalReference::the_hole_value_location()); | 3633 __ LoadRoot(rax, Heap::kTheHoleValueRootIndex); |
3629 __ store_rax(pending_exception); | 3634 __ Store(pending_exception, rax); |
3630 | 3635 |
3631 // Fake a receiver (NULL). | 3636 // Fake a receiver (NULL). |
3632 __ push(Immediate(0)); // receiver | 3637 __ push(Immediate(0)); // receiver |
3633 | 3638 |
3634 // Invoke the function by calling through JS entry trampoline | 3639 // Invoke the function by calling through JS entry trampoline |
3635 // builtin and pop the faked function when we return. We load the address | 3640 // builtin and pop the faked function when we return. We load the address |
3636 // from an external reference instead of inlining the call target address | 3641 // from an external reference instead of inlining the call target address |
3637 // directly in the code, because the builtin stubs may not have been | 3642 // directly in the code, because the builtin stubs may not have been |
3638 // generated yet at the time this code is generated. | 3643 // generated yet at the time this code is generated. |
3639 if (is_construct) { | 3644 if (is_construct) { |
3640 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); | 3645 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); |
3641 __ load_rax(construct_entry); | 3646 __ Load(rax, construct_entry); |
3642 } else { | 3647 } else { |
3643 ExternalReference entry(Builtins::JSEntryTrampoline); | 3648 ExternalReference entry(Builtins::JSEntryTrampoline); |
3644 __ load_rax(entry); | 3649 __ Load(rax, entry); |
3645 } | 3650 } |
3646 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); | 3651 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); |
3647 __ call(kScratchRegister); | 3652 __ call(kScratchRegister); |
3648 | 3653 |
3649 // Unlink this frame from the handler chain. | 3654 // Unlink this frame from the handler chain. |
3650 __ movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); | 3655 Operand handler_operand = |
3651 __ pop(Operand(kScratchRegister, 0)); | 3656 masm->ExternalOperand(ExternalReference(Isolate::k_handler_address)); |
| 3657 __ pop(handler_operand); |
3652 // Pop next_sp. | 3658 // Pop next_sp. |
3653 __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 3659 __ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
3654 | 3660 |
3655 #ifdef ENABLE_LOGGING_AND_PROFILING | 3661 #ifdef ENABLE_LOGGING_AND_PROFILING |
3656 // If current RBP value is the same as js_entry_sp value, it means that | 3662 // If current RBP value is the same as js_entry_sp value, it means that |
3657 // the current function is the outermost. | 3663 // the current function is the outermost. |
3658 __ movq(kScratchRegister, js_entry_sp); | 3664 __ movq(kScratchRegister, js_entry_sp); |
3659 __ cmpq(rbp, Operand(kScratchRegister, 0)); | 3665 __ cmpq(rbp, Operand(kScratchRegister, 0)); |
3660 __ j(not_equal, ¬_outermost_js_2); | 3666 __ j(not_equal, ¬_outermost_js_2); |
3661 __ movq(Operand(kScratchRegister, 0), Immediate(0)); | 3667 __ movq(Operand(kScratchRegister, 0), Immediate(0)); |
3662 __ bind(¬_outermost_js_2); | 3668 __ bind(¬_outermost_js_2); |
3663 #endif | 3669 #endif |
3664 | 3670 |
3665 // Restore the top frame descriptor from the stack. | 3671 // Restore the top frame descriptor from the stack. |
3666 __ bind(&exit); | 3672 __ bind(&exit); |
3667 __ movq(kScratchRegister, ExternalReference(Isolate::k_c_entry_fp_address)); | 3673 { |
3668 __ pop(Operand(kScratchRegister, 0)); | 3674 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); |
| 3675 __ pop(c_entry_fp_operand); |
| 3676 } |
3669 | 3677 |
3670 // Restore callee-saved registers (X64 conventions). | 3678 // Restore callee-saved registers (X64 conventions). |
3671 __ pop(rbx); | 3679 __ pop(rbx); |
3672 #ifdef _WIN64 | 3680 #ifdef _WIN64 |
3673 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. | 3681 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. |
3674 __ pop(rsi); | 3682 __ pop(rsi); |
3675 __ pop(rdi); | 3683 __ pop(rdi); |
3676 #endif | 3684 #endif |
3677 __ pop(r15); | 3685 __ pop(r15); |
3678 __ pop(r14); | 3686 __ pop(r14); |
(...skipping 1382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5061 // Do a tail call to the rewritten stub. | 5069 // Do a tail call to the rewritten stub. |
5062 __ jmp(rdi); | 5070 __ jmp(rdi); |
5063 } | 5071 } |
5064 | 5072 |
5065 | 5073 |
5066 #undef __ | 5074 #undef __ |
5067 | 5075 |
5068 } } // namespace v8::internal | 5076 } } // namespace v8::internal |
5069 | 5077 |
5070 #endif // V8_TARGET_ARCH_X64 | 5078 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |