Index: src/x64/code-stubs-x64.cc |
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
index 541d1457856fc7a824c670ea16819ea372e7246c..2e2b975c79108b6d29705f6662072b2ef7185e1c 100644 |
--- a/src/x64/code-stubs-x64.cc |
+++ b/src/x64/code-stubs-x64.cc |
@@ -2408,19 +2408,28 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
} |
-void CEntryStub::GenerateCore(MacroAssembler* masm, |
- Label* throw_normal_exception, |
- Label* throw_termination_exception, |
- bool do_gc, |
- bool always_allocate_scope) { |
- // rax: result parameter for PerformGC, if any. |
- // rbx: pointer to C function (C callee-saved). |
- // rbp: frame pointer (restored after C call). |
- // rsp: stack pointer (restored after C call). |
+void CEntryStub::Generate(MacroAssembler* masm) { |
+ // rax: number of arguments including receiver |
+ // rbx: pointer to C function (C callee-saved) |
+ // rbp: frame pointer of calling JS frame (restored after C call) |
+ // rsp: stack pointer (restored after C call) |
+ // rsi: current context (restored) |
+ |
+ ProfileEntryHookStub::MaybeCallEntryHook(masm); |
+ |
+ // Enter the exit frame that transitions from JavaScript to C++. |
+#ifdef _WIN64 |
+ int arg_stack_space = (result_size_ < 2 ? 2 : 4); |
+#else |
+ int arg_stack_space = 0; |
+#endif |
+ __ EnterExitFrame(arg_stack_space, save_doubles_); |
+ |
+ // rbx: pointer to builtin function (C callee-saved). |
+ // rbp: frame pointer of exit frame (restored after C call). |
+ // rsp: stack pointer (restored after C call). |
// r14: number of arguments including receiver (C callee-saved). |
- // r15: pointer to the first argument (C callee-saved). |
- // This pointer is reused in LeaveExitFrame(), so it is stored in a |
- // callee-saved register. |
+ // r15: argv pointer (C callee-saved). |
// Simple results returned in rax (both AMD64 and Win64 calling conventions). |
// Complex results must be written to address passed as first argument. |
@@ -2431,25 +2440,6 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, |
__ CheckStackAlignment(); |
} |
- if (do_gc) { |
- // Pass failure code returned from last attempt as first argument to |
- // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the |
- // stack is known to be aligned. This function takes one argument which is |
- // passed in register. |
- __ Move(arg_reg_2, ExternalReference::isolate_address(masm->isolate())); |
- __ movp(arg_reg_1, rax); |
- __ Move(kScratchRegister, |
- ExternalReference::perform_gc_function(masm->isolate())); |
- __ call(kScratchRegister); |
- } |
- |
- ExternalReference scope_depth = |
- ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); |
- if (always_allocate_scope) { |
- Operand scope_depth_operand = masm->ExternalOperand(scope_depth); |
- __ incl(scope_depth_operand); |
- } |
- |
// Call C function. |
#ifdef _WIN64 |
// Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9. |
@@ -2480,14 +2470,6 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, |
__ call(rbx); |
// Result is in rax - do not destroy this register! |
- if (always_allocate_scope) { |
- Operand scope_depth_operand = masm->ExternalOperand(scope_depth); |
- __ decl(scope_depth_operand); |
- } |
- |
- // Check for failure result. |
- Label failure_returned; |
- STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
#ifdef _WIN64 |
// If return value is on the stack, pop it to registers. |
if (result_size_ > 1) { |
@@ -2499,121 +2481,65 @@ void CEntryStub::GenerateCore(MacroAssembler* masm, |
__ movq(rdx, Operand(rsp, 7 * kRegisterSize)); |
} |
#endif |
- __ leap(rcx, Operand(rax, 1)); |
- // Lower 2 bits of rcx are 0 iff rax has failure tag. |
- __ testl(rcx, Immediate(kFailureTagMask)); |
- __ j(zero, &failure_returned); |
+ |
+ // Runtime functions should not return 'the hole'. Allowing it to escape may |
+ // lead to crashes in the IC code later. |
+ if (FLAG_debug_code) { |
+ Label okay; |
+ __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); |
+ __ j(not_equal, &okay, Label::kNear); |
+ __ int3(); |
+ __ bind(&okay); |
+ } |
+ |
+ // Check result for exception sentinel. |
+ Label exception_returned; |
+ __ CompareRoot(rax, Heap::kExceptionRootIndex); |
+ __ j(equal, &exception_returned); |
+ |
+ ExternalReference pending_exception_address( |
+ Isolate::kPendingExceptionAddress, masm->isolate()); |
+ |
+ // Check that there is no pending exception, otherwise we |
+ // should have returned the exception sentinel. |
+ if (FLAG_debug_code) { |
+ Label okay; |
+ __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); |
+ Operand pending_exception_operand = |
+ masm->ExternalOperand(pending_exception_address); |
+ __ cmpp(r14, pending_exception_operand); |
+ __ j(equal, &okay, Label::kNear); |
+ __ int3(); |
+ __ bind(&okay); |
+ } |
// Exit the JavaScript to C++ exit frame. |
__ LeaveExitFrame(save_doubles_); |
__ ret(0); |
- // Handling of failure. |
- __ bind(&failure_returned); |
- |
- Label retry; |
- // If the returned exception is RETRY_AFTER_GC continue at retry label |
- STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); |
- __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); |
- __ j(zero, &retry, Label::kNear); |
+ // Handling of exception. |
+ __ bind(&exception_returned); |
// Retrieve the pending exception. |
- ExternalReference pending_exception_address( |
- Isolate::kPendingExceptionAddress, masm->isolate()); |
Operand pending_exception_operand = |
masm->ExternalOperand(pending_exception_address); |
__ movp(rax, pending_exception_operand); |
// Clear the pending exception. |
- pending_exception_operand = |
- masm->ExternalOperand(pending_exception_address); |
__ LoadRoot(rdx, Heap::kTheHoleValueRootIndex); |
__ movp(pending_exception_operand, rdx); |
// Special handling of termination exceptions which are uncatchable |
// by javascript code. |
+ Label throw_termination_exception; |
__ CompareRoot(rax, Heap::kTerminationExceptionRootIndex); |
- __ j(equal, throw_termination_exception); |
+ __ j(equal, &throw_termination_exception); |
// Handle normal exception. |
- __ jmp(throw_normal_exception); |
- |
- // Retry. |
- __ bind(&retry); |
-} |
- |
- |
-void CEntryStub::Generate(MacroAssembler* masm) { |
- // rax: number of arguments including receiver |
- // rbx: pointer to C function (C callee-saved) |
- // rbp: frame pointer of calling JS frame (restored after C call) |
- // rsp: stack pointer (restored after C call) |
- // rsi: current context (restored) |
- |
- // NOTE: Invocations of builtins may return failure objects |
- // instead of a proper result. The builtin entry handles |
- // this by performing a garbage collection and retrying the |
- // builtin once. |
- |
- ProfileEntryHookStub::MaybeCallEntryHook(masm); |
- |
- // Enter the exit frame that transitions from JavaScript to C++. |
-#ifdef _WIN64 |
- int arg_stack_space = (result_size_ < 2 ? 2 : 4); |
-#else |
- int arg_stack_space = 0; |
-#endif |
- __ EnterExitFrame(arg_stack_space, save_doubles_); |
- |
- // rax: Holds the context at this point, but should not be used. |
- // On entry to code generated by GenerateCore, it must hold |
- // a failure result if the collect_garbage argument to GenerateCore |
- // is true. This failure result can be the result of code |
- // generated by a previous call to GenerateCore. The value |
- // of rax is then passed to Runtime::PerformGC. |
- // rbx: pointer to builtin function (C callee-saved). |
- // rbp: frame pointer of exit frame (restored after C call). |
- // rsp: stack pointer (restored after C call). |
- // r14: number of arguments including receiver (C callee-saved). |
- // r15: argv pointer (C callee-saved). |
- |
- Label throw_normal_exception; |
- Label throw_termination_exception; |
- |
- // Call into the runtime system. |
- GenerateCore(masm, |
- &throw_normal_exception, |
- &throw_termination_exception, |
- false, |
- false); |
- |
- // Do space-specific GC and retry runtime call. |
- GenerateCore(masm, |
- &throw_normal_exception, |
- &throw_termination_exception, |
- true, |
- false); |
- |
- // Do full GC and retry runtime call one final time. |
- Failure* failure = Failure::InternalError(); |
- __ Move(rax, failure, Assembler::RelocInfoNone()); |
- GenerateCore(masm, |
- &throw_normal_exception, |
- &throw_termination_exception, |
- true, |
- true); |
- |
- { FrameScope scope(masm, StackFrame::MANUAL); |
- __ PrepareCallCFunction(0); |
- __ CallCFunction( |
- ExternalReference::out_of_memory_function(masm->isolate()), 0); |
- } |
+ __ Throw(rax); |
__ bind(&throw_termination_exception); |
__ ThrowUncatchable(rax); |
- |
- __ bind(&throw_normal_exception); |
- __ Throw(rax); |
} |
@@ -2702,7 +2628,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
ExternalReference pending_exception(Isolate::kPendingExceptionAddress, |
isolate); |
__ Store(pending_exception, rax); |
- __ Move(rax, Failure::Exception(), Assembler::RelocInfoNone()); |
+ __ LoadRoot(rax, Heap::kExceptionRootIndex); |
__ jmp(&exit); |
// Invoke: Link this frame into the handler chain. There's only one |