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 2566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2577 } | 2577 } |
2578 } | 2578 } |
2579 | 2579 |
2580 | 2580 |
2581 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 2581 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
2582 CEntryStub stub(1, kDontSaveFPRegs); | 2582 CEntryStub stub(1, kDontSaveFPRegs); |
2583 stub.GetCode(isolate); | 2583 stub.GetCode(isolate); |
2584 } | 2584 } |
2585 | 2585 |
2586 | 2586 |
2587 void CEntryStub::GenerateCore(MacroAssembler* masm, | 2587 void CEntryStub::Generate(MacroAssembler* masm) { |
2588 Label* throw_normal_exception, | 2588 // eax: number of arguments including receiver |
2589 Label* throw_termination_exception, | |
2590 bool do_gc, | |
2591 bool always_allocate_scope) { | |
2592 // eax: result parameter for PerformGC, if any | |
2593 // ebx: pointer to C function (C callee-saved) | 2589 // ebx: pointer to C function (C callee-saved) |
2594 // ebp: frame pointer (restored after C call) | 2590 // ebp: frame pointer (restored after C call) |
2595 // esp: stack pointer (restored after C call) | 2591 // esp: stack pointer (restored after C call) |
| 2592 // esi: current context (C callee-saved) |
| 2593 // edi: JS function of the caller (C callee-saved) |
| 2594 |
| 2595 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 2596 |
| 2597 // Enter the exit frame that transitions from JavaScript to C++. |
| 2598 __ EnterExitFrame(save_doubles_ == kSaveFPRegs); |
| 2599 |
| 2600 // ebx: pointer to C function (C callee-saved) |
| 2601 // ebp: frame pointer (restored after C call) |
| 2602 // esp: stack pointer (restored after C call) |
2596 // edi: number of arguments including receiver (C callee-saved) | 2603 // edi: number of arguments including receiver (C callee-saved) |
2597 // esi: pointer to the first argument (C callee-saved) | 2604 // esi: pointer to the first argument (C callee-saved) |
2598 | 2605 |
2599 // Result returned in eax, or eax+edx if result_size_ is 2. | 2606 // Result returned in eax, or eax+edx if result_size_ is 2. |
2600 | 2607 |
| 2608 Isolate* isolate = masm->isolate(); |
| 2609 |
2601 // Check stack alignment. | 2610 // Check stack alignment. |
2602 if (FLAG_debug_code) { | 2611 if (FLAG_debug_code) { |
2603 __ CheckStackAlignment(); | 2612 __ CheckStackAlignment(); |
2604 } | 2613 } |
2605 | 2614 |
2606 if (do_gc) { | |
2607 // Pass failure code returned from last attempt as first argument to | |
2608 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | |
2609 // stack alignment is known to be correct. This function takes one argument | |
2610 // which is passed on the stack, and we know that the stack has been | |
2611 // prepared to pass at least one argument. | |
2612 __ mov(Operand(esp, 1 * kPointerSize), | |
2613 Immediate(ExternalReference::isolate_address(masm->isolate()))); | |
2614 __ mov(Operand(esp, 0 * kPointerSize), eax); // Result. | |
2615 __ call(FUNCTION_ADDR(Runtime::PerformGC), RelocInfo::RUNTIME_ENTRY); | |
2616 } | |
2617 | |
2618 ExternalReference scope_depth = | |
2619 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); | |
2620 if (always_allocate_scope) { | |
2621 __ inc(Operand::StaticVariable(scope_depth)); | |
2622 } | |
2623 | |
2624 // Call C function. | 2615 // Call C function. |
2625 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. | 2616 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. |
2626 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. | 2617 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. |
2627 __ mov(Operand(esp, 2 * kPointerSize), | 2618 __ mov(Operand(esp, 2 * kPointerSize), |
2628 Immediate(ExternalReference::isolate_address(masm->isolate()))); | 2619 Immediate(ExternalReference::isolate_address(isolate))); |
2629 __ call(ebx); | 2620 __ call(ebx); |
2630 // Result is in eax or edx:eax - do not destroy these registers! | 2621 // Result is in eax or edx:eax - do not destroy these registers! |
2631 | 2622 |
2632 if (always_allocate_scope) { | |
2633 __ dec(Operand::StaticVariable(scope_depth)); | |
2634 } | |
2635 | |
2636 // Runtime functions should not return 'the hole'. Allowing it to escape may | 2623 // Runtime functions should not return 'the hole'. Allowing it to escape may |
2637 // lead to crashes in the IC code later. | 2624 // lead to crashes in the IC code later. |
2638 if (FLAG_debug_code) { | 2625 if (FLAG_debug_code) { |
2639 Label okay; | 2626 Label okay; |
2640 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); | 2627 __ cmp(eax, isolate->factory()->the_hole_value()); |
2641 __ j(not_equal, &okay, Label::kNear); | 2628 __ j(not_equal, &okay, Label::kNear); |
2642 __ int3(); | 2629 __ int3(); |
2643 __ bind(&okay); | 2630 __ bind(&okay); |
2644 } | 2631 } |
2645 | 2632 |
2646 // Check for failure result. | 2633 // Check result for exception sentinel. |
2647 Label failure_returned; | 2634 Label exception_returned; |
2648 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 2635 __ cmp(eax, isolate->factory()->exception()); |
2649 __ lea(ecx, Operand(eax, 1)); | 2636 __ j(equal, &exception_returned); |
2650 // Lower 2 bits of ecx are 0 iff eax has failure tag. | |
2651 __ test(ecx, Immediate(kFailureTagMask)); | |
2652 __ j(zero, &failure_returned); | |
2653 | 2637 |
2654 ExternalReference pending_exception_address( | 2638 ExternalReference pending_exception_address( |
2655 Isolate::kPendingExceptionAddress, masm->isolate()); | 2639 Isolate::kPendingExceptionAddress, isolate); |
2656 | 2640 |
2657 // Check that there is no pending exception, otherwise we | 2641 // Check that there is no pending exception, otherwise we |
2658 // should have returned some failure value. | 2642 // should have returned the exception sentinel. |
2659 if (FLAG_debug_code) { | 2643 if (FLAG_debug_code) { |
2660 __ push(edx); | 2644 __ push(edx); |
2661 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2645 __ mov(edx, Immediate(isolate->factory()->the_hole_value())); |
2662 Label okay; | 2646 Label okay; |
2663 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); | 2647 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); |
2664 // Cannot use check here as it attempts to generate call into runtime. | 2648 // Cannot use check here as it attempts to generate call into runtime. |
2665 __ j(equal, &okay, Label::kNear); | 2649 __ j(equal, &okay, Label::kNear); |
2666 __ int3(); | 2650 __ int3(); |
2667 __ bind(&okay); | 2651 __ bind(&okay); |
2668 __ pop(edx); | 2652 __ pop(edx); |
2669 } | 2653 } |
2670 | 2654 |
2671 // Exit the JavaScript to C++ exit frame. | 2655 // Exit the JavaScript to C++ exit frame. |
2672 __ LeaveExitFrame(save_doubles_ == kSaveFPRegs); | 2656 __ LeaveExitFrame(save_doubles_ == kSaveFPRegs); |
2673 __ ret(0); | 2657 __ ret(0); |
2674 | 2658 |
2675 // Handling of failure. | 2659 // Handling of exception. |
2676 __ bind(&failure_returned); | 2660 __ bind(&exception_returned); |
2677 | |
2678 Label retry; | |
2679 // If the returned exception is RETRY_AFTER_GC continue at retry label | |
2680 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | |
2681 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); | |
2682 __ j(zero, &retry, Label::kNear); | |
2683 | 2661 |
2684 // Retrieve the pending exception. | 2662 // Retrieve the pending exception. |
2685 __ mov(eax, Operand::StaticVariable(pending_exception_address)); | 2663 __ mov(eax, Operand::StaticVariable(pending_exception_address)); |
2686 | 2664 |
2687 // Clear the pending exception. | 2665 // Clear the pending exception. |
2688 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2666 __ mov(edx, Immediate(isolate->factory()->the_hole_value())); |
2689 __ mov(Operand::StaticVariable(pending_exception_address), edx); | 2667 __ mov(Operand::StaticVariable(pending_exception_address), edx); |
2690 | 2668 |
2691 // Special handling of termination exceptions which are uncatchable | 2669 // Special handling of termination exceptions which are uncatchable |
2692 // by javascript code. | 2670 // by javascript code. |
2693 __ cmp(eax, masm->isolate()->factory()->termination_exception()); | 2671 Label throw_termination_exception; |
2694 __ j(equal, throw_termination_exception); | 2672 __ cmp(eax, isolate->factory()->termination_exception()); |
| 2673 __ j(equal, &throw_termination_exception); |
2695 | 2674 |
2696 // Handle normal exception. | 2675 // Handle normal exception. |
2697 __ jmp(throw_normal_exception); | 2676 __ Throw(eax); |
2698 | 2677 |
2699 // Retry. | 2678 __ bind(&throw_termination_exception); |
2700 __ bind(&retry); | 2679 __ ThrowUncatchable(eax); |
2701 } | 2680 } |
2702 | 2681 |
2703 | 2682 |
2704 void CEntryStub::Generate(MacroAssembler* masm) { | |
2705 // eax: number of arguments including receiver | |
2706 // ebx: pointer to C function (C callee-saved) | |
2707 // ebp: frame pointer (restored after C call) | |
2708 // esp: stack pointer (restored after C call) | |
2709 // esi: current context (C callee-saved) | |
2710 // edi: JS function of the caller (C callee-saved) | |
2711 | |
2712 ProfileEntryHookStub::MaybeCallEntryHook(masm); | |
2713 | |
2714 // NOTE: Invocations of builtins may return failure objects instead | |
2715 // of a proper result. The builtin entry handles this by performing | |
2716 // a garbage collection and retrying the builtin (twice). | |
2717 | |
2718 // Enter the exit frame that transitions from JavaScript to C++. | |
2719 __ EnterExitFrame(save_doubles_ == kSaveFPRegs); | |
2720 | |
2721 // eax: result parameter for PerformGC, if any (setup below) | |
2722 // ebx: pointer to builtin function (C callee-saved) | |
2723 // ebp: frame pointer (restored after C call) | |
2724 // esp: stack pointer (restored after C call) | |
2725 // edi: number of arguments including receiver (C callee-saved) | |
2726 // esi: argv pointer (C callee-saved) | |
2727 | |
2728 Label throw_normal_exception; | |
2729 Label throw_termination_exception; | |
2730 | |
2731 // Call into the runtime system. | |
2732 GenerateCore(masm, | |
2733 &throw_normal_exception, | |
2734 &throw_termination_exception, | |
2735 false, | |
2736 false); | |
2737 | |
2738 // Do space-specific GC and retry runtime call. | |
2739 GenerateCore(masm, | |
2740 &throw_normal_exception, | |
2741 &throw_termination_exception, | |
2742 true, | |
2743 false); | |
2744 | |
2745 // Do full GC and retry runtime call one final time. | |
2746 Failure* failure = Failure::InternalError(); | |
2747 __ mov(eax, Immediate(reinterpret_cast<int32_t>(failure))); | |
2748 GenerateCore(masm, | |
2749 &throw_normal_exception, | |
2750 &throw_termination_exception, | |
2751 true, | |
2752 true); | |
2753 | |
2754 { FrameScope scope(masm, StackFrame::MANUAL); | |
2755 __ PrepareCallCFunction(0, eax); | |
2756 __ CallCFunction( | |
2757 ExternalReference::out_of_memory_function(masm->isolate()), 0); | |
2758 } | |
2759 | |
2760 __ bind(&throw_termination_exception); | |
2761 __ ThrowUncatchable(eax); | |
2762 | |
2763 __ bind(&throw_normal_exception); | |
2764 __ Throw(eax); | |
2765 } | |
2766 | |
2767 | |
2768 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 2683 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
2769 Label invoke, handler_entry, exit; | 2684 Label invoke, handler_entry, exit; |
2770 Label not_outermost_js, not_outermost_js_2; | 2685 Label not_outermost_js, not_outermost_js_2; |
2771 | 2686 |
2772 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 2687 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
2773 | 2688 |
2774 // Set up frame. | 2689 // Set up frame. |
2775 __ push(ebp); | 2690 __ push(ebp); |
2776 __ mov(ebp, esp); | 2691 __ mov(ebp, esp); |
2777 | 2692 |
(...skipping 24 matching lines...) Expand all Loading... |
2802 // Jump to a faked try block that does the invoke, with a faked catch | 2717 // Jump to a faked try block that does the invoke, with a faked catch |
2803 // block that sets the pending exception. | 2718 // block that sets the pending exception. |
2804 __ jmp(&invoke); | 2719 __ jmp(&invoke); |
2805 __ bind(&handler_entry); | 2720 __ bind(&handler_entry); |
2806 handler_offset_ = handler_entry.pos(); | 2721 handler_offset_ = handler_entry.pos(); |
2807 // Caught exception: Store result (exception) in the pending exception | 2722 // Caught exception: Store result (exception) in the pending exception |
2808 // field in the JSEnv and return a failure sentinel. | 2723 // field in the JSEnv and return a failure sentinel. |
2809 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 2724 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
2810 masm->isolate()); | 2725 masm->isolate()); |
2811 __ mov(Operand::StaticVariable(pending_exception), eax); | 2726 __ mov(Operand::StaticVariable(pending_exception), eax); |
2812 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); | 2727 __ mov(eax, Immediate(masm->isolate()->factory()->exception())); |
2813 __ jmp(&exit); | 2728 __ jmp(&exit); |
2814 | 2729 |
2815 // Invoke: Link this frame into the handler chain. There's only one | 2730 // Invoke: Link this frame into the handler chain. There's only one |
2816 // handler block in this code object, so its index is 0. | 2731 // handler block in this code object, so its index is 0. |
2817 __ bind(&invoke); | 2732 __ bind(&invoke); |
2818 __ PushTryHandler(StackHandler::JS_ENTRY, 0); | 2733 __ PushTryHandler(StackHandler::JS_ENTRY, 0); |
2819 | 2734 |
2820 // Clear any pending exceptions. | 2735 // Clear any pending exceptions. |
2821 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2736 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); |
2822 __ mov(Operand::StaticVariable(pending_exception), edx); | 2737 __ mov(Operand::StaticVariable(pending_exception), edx); |
(...skipping 2347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5170 Operand(ebp, 7 * kPointerSize), | 5085 Operand(ebp, 7 * kPointerSize), |
5171 NULL); | 5086 NULL); |
5172 } | 5087 } |
5173 | 5088 |
5174 | 5089 |
5175 #undef __ | 5090 #undef __ |
5176 | 5091 |
5177 } } // namespace v8::internal | 5092 } } // namespace v8::internal |
5178 | 5093 |
5179 #endif // V8_TARGET_ARCH_IA32 | 5094 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |