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