Chromium Code Reviews| 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) |
| 2596 // edi: number of arguments including receiver (C callee-saved) | 2592 // edi: number of arguments including receiver (C callee-saved) |
| 2597 // esi: pointer to the first argument (C callee-saved) | 2593 // esi: pointer to the first argument (C callee-saved) |
| 2594 ProfileEntryHookStub::MaybeCallEntryHook(masm); | |
| 2595 | |
| 2596 // NOTE: Invocations of builtins may return failure objects instead | |
|
Jakob Kummerow
2014/04/17 14:20:12
I think this is outdated ;-)
| |
| 2597 // of a proper result. The builtin entry handles this by performing | |
| 2598 // a garbage collection and retrying the builtin (twice). | |
| 2599 | |
| 2600 // Enter the exit frame that transitions from JavaScript to C++. | |
| 2601 __ EnterExitFrame(save_doubles_ == kSaveFPRegs); | |
| 2598 | 2602 |
| 2599 // Result returned in eax, or eax+edx if result_size_ is 2. | 2603 // Result returned in eax, or eax+edx if result_size_ is 2. |
| 2604 // Call into the runtime system. | |
| 2600 | 2605 |
| 2601 // Check stack alignment. | 2606 // Check stack alignment. |
| 2602 if (FLAG_debug_code) { | 2607 if (FLAG_debug_code) { |
| 2603 __ CheckStackAlignment(); | 2608 __ CheckStackAlignment(); |
| 2604 } | 2609 } |
| 2605 | 2610 |
| 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. | 2611 // Call C function. |
| 2625 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. | 2612 __ mov(Operand(esp, 0 * kPointerSize), edi); // argc. |
| 2626 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. | 2613 __ mov(Operand(esp, 1 * kPointerSize), esi); // argv. |
| 2627 __ mov(Operand(esp, 2 * kPointerSize), | 2614 __ mov(Operand(esp, 2 * kPointerSize), |
| 2628 Immediate(ExternalReference::isolate_address(masm->isolate()))); | 2615 Immediate(ExternalReference::isolate_address(masm->isolate()))); |
| 2629 __ call(ebx); | 2616 __ call(ebx); |
| 2630 // Result is in eax or edx:eax - do not destroy these registers! | 2617 // Result is in eax or edx:eax - do not destroy these registers! |
| 2631 | 2618 |
| 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 | 2619 // Runtime functions should not return 'the hole'. Allowing it to escape may |
| 2637 // lead to crashes in the IC code later. | 2620 // lead to crashes in the IC code later. |
| 2638 if (FLAG_debug_code) { | 2621 if (FLAG_debug_code) { |
| 2639 Label okay; | 2622 Label okay; |
| 2640 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); | 2623 __ cmp(eax, masm->isolate()->factory()->the_hole_value()); |
| 2641 __ j(not_equal, &okay, Label::kNear); | 2624 __ j(not_equal, &okay, Label::kNear); |
| 2642 __ int3(); | 2625 __ int3(); |
| 2643 __ bind(&okay); | 2626 __ bind(&okay); |
| 2644 } | 2627 } |
| 2645 | 2628 |
| 2646 // Check for failure result. | |
| 2647 Label failure_returned; | 2629 Label failure_returned; |
| 2648 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 2630 __ cmp(eax, masm->isolate()->factory()->exception()); |
| 2649 __ lea(ecx, Operand(eax, 1)); | 2631 __ j(equal, &failure_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 | 2632 |
| 2654 ExternalReference pending_exception_address( | 2633 ExternalReference pending_exception_address( |
| 2655 Isolate::kPendingExceptionAddress, masm->isolate()); | 2634 Isolate::kPendingExceptionAddress, masm->isolate()); |
| 2656 | 2635 |
| 2657 // Check that there is no pending exception, otherwise we | 2636 // Check that there is no pending exception, otherwise we |
| 2658 // should have returned some failure value. | 2637 // should have returned the exception sentinel. |
| 2659 if (FLAG_debug_code) { | 2638 if (FLAG_debug_code) { |
| 2660 __ push(edx); | 2639 __ push(edx); |
| 2661 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2640 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); |
| 2662 Label okay; | 2641 Label okay; |
| 2663 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); | 2642 __ cmp(edx, Operand::StaticVariable(pending_exception_address)); |
| 2664 // Cannot use check here as it attempts to generate call into runtime. | 2643 // Cannot use check here as it attempts to generate call into runtime. |
| 2665 __ j(equal, &okay, Label::kNear); | 2644 __ j(equal, &okay, Label::kNear); |
| 2666 __ int3(); | 2645 __ int3(); |
| 2667 __ bind(&okay); | 2646 __ bind(&okay); |
| 2668 __ pop(edx); | 2647 __ pop(edx); |
| 2669 } | 2648 } |
| 2670 | 2649 |
| 2671 // Exit the JavaScript to C++ exit frame. | 2650 // Exit the JavaScript to C++ exit frame. |
| 2672 __ LeaveExitFrame(save_doubles_ == kSaveFPRegs); | 2651 __ LeaveExitFrame(save_doubles_ == kSaveFPRegs); |
| 2673 __ ret(0); | 2652 __ ret(0); |
| 2674 | 2653 |
| 2675 // Handling of failure. | 2654 // Handling of failure. |
| 2676 __ bind(&failure_returned); | 2655 __ bind(&failure_returned); |
| 2677 | 2656 |
| 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 | |
| 2684 // Retrieve the pending exception. | 2657 // Retrieve the pending exception. |
| 2685 __ mov(eax, Operand::StaticVariable(pending_exception_address)); | 2658 __ mov(eax, Operand::StaticVariable(pending_exception_address)); |
| 2686 | 2659 |
| 2687 // Clear the pending exception. | 2660 // Clear the pending exception. |
| 2688 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2661 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); |
| 2689 __ mov(Operand::StaticVariable(pending_exception_address), edx); | 2662 __ mov(Operand::StaticVariable(pending_exception_address), edx); |
| 2690 | 2663 |
| 2691 // Special handling of termination exceptions which are uncatchable | 2664 // Special handling of termination exceptions which are uncatchable |
| 2692 // by javascript code. | 2665 // by javascript code. |
| 2666 Label throw_termination_exception; | |
| 2693 __ cmp(eax, masm->isolate()->factory()->termination_exception()); | 2667 __ cmp(eax, masm->isolate()->factory()->termination_exception()); |
| 2694 __ j(equal, throw_termination_exception); | 2668 __ j(equal, &throw_termination_exception); |
| 2695 | 2669 |
| 2696 // Handle normal exception. | 2670 // Handle normal exception. |
| 2697 __ jmp(throw_normal_exception); | 2671 __ Throw(eax); |
| 2698 | 2672 |
| 2699 // Retry. | 2673 __ bind(&throw_termination_exception); |
| 2700 __ bind(&retry); | 2674 __ ThrowUncatchable(eax); |
| 2701 } | 2675 } |
| 2702 | 2676 |
| 2703 | 2677 |
| 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) { | 2678 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
| 2769 Label invoke, handler_entry, exit; | 2679 Label invoke, handler_entry, exit; |
| 2770 Label not_outermost_js, not_outermost_js_2; | 2680 Label not_outermost_js, not_outermost_js_2; |
| 2771 | 2681 |
| 2772 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 2682 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 2773 | 2683 |
| 2774 // Set up frame. | 2684 // Set up frame. |
| 2775 __ push(ebp); | 2685 __ push(ebp); |
| 2776 __ mov(ebp, esp); | 2686 __ mov(ebp, esp); |
| 2777 | 2687 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2802 // Jump to a faked try block that does the invoke, with a faked catch | 2712 // Jump to a faked try block that does the invoke, with a faked catch |
| 2803 // block that sets the pending exception. | 2713 // block that sets the pending exception. |
| 2804 __ jmp(&invoke); | 2714 __ jmp(&invoke); |
| 2805 __ bind(&handler_entry); | 2715 __ bind(&handler_entry); |
| 2806 handler_offset_ = handler_entry.pos(); | 2716 handler_offset_ = handler_entry.pos(); |
| 2807 // Caught exception: Store result (exception) in the pending exception | 2717 // Caught exception: Store result (exception) in the pending exception |
| 2808 // field in the JSEnv and return a failure sentinel. | 2718 // field in the JSEnv and return a failure sentinel. |
| 2809 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, | 2719 ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
| 2810 masm->isolate()); | 2720 masm->isolate()); |
| 2811 __ mov(Operand::StaticVariable(pending_exception), eax); | 2721 __ mov(Operand::StaticVariable(pending_exception), eax); |
| 2812 __ mov(eax, reinterpret_cast<int32_t>(Failure::Exception())); | 2722 __ mov(eax, Immediate(masm->isolate()->factory()->exception())); |
| 2813 __ jmp(&exit); | 2723 __ jmp(&exit); |
| 2814 | 2724 |
| 2815 // Invoke: Link this frame into the handler chain. There's only one | 2725 // Invoke: Link this frame into the handler chain. There's only one |
| 2816 // handler block in this code object, so its index is 0. | 2726 // handler block in this code object, so its index is 0. |
| 2817 __ bind(&invoke); | 2727 __ bind(&invoke); |
| 2818 __ PushTryHandler(StackHandler::JS_ENTRY, 0); | 2728 __ PushTryHandler(StackHandler::JS_ENTRY, 0); |
| 2819 | 2729 |
| 2820 // Clear any pending exceptions. | 2730 // Clear any pending exceptions. |
| 2821 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); | 2731 __ mov(edx, Immediate(masm->isolate()->factory()->the_hole_value())); |
| 2822 __ mov(Operand::StaticVariable(pending_exception), edx); | 2732 __ mov(Operand::StaticVariable(pending_exception), edx); |
| (...skipping 2347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5170 Operand(ebp, 7 * kPointerSize), | 5080 Operand(ebp, 7 * kPointerSize), |
| 5171 NULL); | 5081 NULL); |
| 5172 } | 5082 } |
| 5173 | 5083 |
| 5174 | 5084 |
| 5175 #undef __ | 5085 #undef __ |
| 5176 | 5086 |
| 5177 } } // namespace v8::internal | 5087 } } // namespace v8::internal |
| 5178 | 5088 |
| 5179 #endif // V8_TARGET_ARCH_IA32 | 5089 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |