| Index: src/mips/code-stubs-mips.cc
|
| diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
|
| index 57f75bb968ed5656091eb4213a10009bcedf4d29..1d94e70b659ff147955fd17afcd2a6530c01025d 100644
|
| --- a/src/mips/code-stubs-mips.cc
|
| +++ b/src/mips/code-stubs-mips.cc
|
| @@ -1610,34 +1610,34 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
|
| }
|
|
|
|
|
| -void CEntryStub::GenerateCore(MacroAssembler* masm,
|
| - Label* throw_normal_exception,
|
| - Label* throw_termination_exception,
|
| - bool do_gc,
|
| - bool always_allocate) {
|
| - // v0: result parameter for PerformGC, if any
|
| - // s0: number of arguments including receiver (C callee-saved)
|
| - // s1: pointer to the first argument (C callee-saved)
|
| - // s2: pointer to builtin function (C callee-saved)
|
| +void CEntryStub::Generate(MacroAssembler* masm) {
|
| + // Called from JavaScript; parameters are on stack as if calling JS function
|
| + // s0: number of arguments including receiver
|
| + // s1: size of arguments excluding receiver
|
| + // s2: pointer to builtin function
|
| + // fp: frame pointer (restored after C call)
|
| + // sp: stack pointer (restored as callee's sp after C call)
|
| + // cp: current context (C callee-saved)
|
|
|
| - Isolate* isolate = masm->isolate();
|
| + ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
|
|
| - if (do_gc) {
|
| - // Move result passed in v0 into a0 to call PerformGC.
|
| - __ mov(a0, v0);
|
| - __ PrepareCallCFunction(2, 0, a1);
|
| - __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
|
| - __ CallCFunction(ExternalReference::perform_gc_function(isolate), 2, 0);
|
| - }
|
| + // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
|
| + // The reason for this is that these arguments would need to be saved anyway
|
| + // so it's faster to set them up directly.
|
| + // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
|
|
|
| - ExternalReference scope_depth =
|
| - ExternalReference::heap_always_allocate_scope_depth(isolate);
|
| - if (always_allocate) {
|
| - __ li(a0, Operand(scope_depth));
|
| - __ lw(a1, MemOperand(a0));
|
| - __ Addu(a1, a1, Operand(1));
|
| - __ sw(a1, MemOperand(a0));
|
| - }
|
| + // Compute the argv pointer in a callee-saved register.
|
| + __ Addu(s1, sp, s1);
|
| +
|
| + // Enter the exit frame that transitions from JavaScript to C++.
|
| + FrameScope scope(masm, StackFrame::MANUAL);
|
| + __ EnterExitFrame(save_doubles_);
|
| +
|
| + // s0: number of arguments including receiver (C callee-saved)
|
| + // s1: pointer to first argument (C callee-saved)
|
| + // s2: pointer to builtin function (C callee-saved)
|
| +
|
| + Isolate* isolate = masm->isolate();
|
|
|
| // Prepare arguments for C routine.
|
| // a0 = argc
|
| @@ -1684,130 +1684,67 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
| masm->InstructionsGeneratedSince(&find_ra));
|
| }
|
|
|
| - if (always_allocate) {
|
| - // It's okay to clobber a2 and a3 here. v0 & v1 contain result.
|
| - __ li(a2, Operand(scope_depth));
|
| - __ lw(a3, MemOperand(a2));
|
| - __ Subu(a3, a3, Operand(1));
|
| - __ sw(a3, MemOperand(a2));
|
| +
|
| + // 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;
|
| + __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
|
| + __ Branch(&okay, ne, v0, Operand(t0));
|
| + __ stop("The hole escaped");
|
| + __ bind(&okay);
|
| }
|
|
|
| - // Check for failure result.
|
| - Label failure_returned;
|
| - STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
|
| - __ addiu(a2, v0, 1);
|
| - __ andi(t0, a2, kFailureTagMask);
|
| - __ Branch(USE_DELAY_SLOT, &failure_returned, eq, t0, Operand(zero_reg));
|
| - // Restore stack (remove arg slots) in branch delay slot.
|
| - __ addiu(sp, sp, kCArgsSlotsSize);
|
| + // Check result for exception sentinel.
|
| + Label exception_returned;
|
| + __ LoadRoot(t0, Heap::kExceptionRootIndex);
|
| + __ Branch(&exception_returned, eq, t0, Operand(v0));
|
|
|
| + ExternalReference pending_exception_address(
|
| + Isolate::kPendingExceptionAddress, isolate);
|
| +
|
| + // Check that there is no pending exception, otherwise we
|
| + // should have returned the exception sentinel.
|
| + if (FLAG_debug_code) {
|
| + Label okay;
|
| + __ li(a2, Operand(pending_exception_address));
|
| + __ lw(a2, MemOperand(a2));
|
| + __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
|
| + // Cannot use check here as it attempts to generate call into runtime.
|
| + __ Branch(&okay, eq, t0, Operand(a2));
|
| + __ stop("Unexpected pending exception");
|
| + __ bind(&okay);
|
| + }
|
|
|
| // Exit C frame and return.
|
| // v0:v1: result
|
| // sp: stack pointer
|
| // fp: frame pointer
|
| + // s0: still holds argc (callee-saved).
|
| __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN);
|
|
|
| - // Check if we should retry or throw exception.
|
| - Label retry;
|
| - __ bind(&failure_returned);
|
| - STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
|
| - __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize);
|
| - __ Branch(&retry, eq, t0, Operand(zero_reg));
|
| + // Handling of exception.
|
| + __ bind(&exception_returned);
|
|
|
| // Retrieve the pending exception.
|
| - __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
|
| - isolate)));
|
| - __ lw(v0, MemOperand(t0));
|
| + __ li(a2, Operand(pending_exception_address));
|
| + __ lw(v0, MemOperand(a2));
|
|
|
| // Clear the pending exception.
|
| __ li(a3, Operand(isolate->factory()->the_hole_value()));
|
| - __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
|
| - isolate)));
|
| - __ sw(a3, MemOperand(t0));
|
| + __ sw(a3, MemOperand(a2));
|
|
|
| // Special handling of termination exceptions which are uncatchable
|
| // by javascript code.
|
| + Label throw_termination_exception;
|
| __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex);
|
| - __ Branch(throw_termination_exception, eq, v0, Operand(t0));
|
| + __ Branch(&throw_termination_exception, eq, v0, Operand(t0));
|
|
|
| // Handle normal exception.
|
| - __ jmp(throw_normal_exception);
|
| -
|
| - __ bind(&retry);
|
| - // Last failure (v0) will be moved to (a0) for parameter when retrying.
|
| -}
|
| -
|
| -
|
| -void CEntryStub::Generate(MacroAssembler* masm) {
|
| - // Called from JavaScript; parameters are on stack as if calling JS function
|
| - // s0: number of arguments including receiver
|
| - // s1: size of arguments excluding receiver
|
| - // s2: pointer to builtin function
|
| - // fp: frame pointer (restored after C call)
|
| - // sp: stack pointer (restored as callee's sp after C call)
|
| - // cp: current context (C callee-saved)
|
| -
|
| - ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
| -
|
| - // 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.
|
| -
|
| - // NOTE: s0-s2 hold the arguments of this function instead of a0-a2.
|
| - // The reason for this is that these arguments would need to be saved anyway
|
| - // so it's faster to set them up directly.
|
| - // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction.
|
| -
|
| - // Compute the argv pointer in a callee-saved register.
|
| - __ Addu(s1, sp, s1);
|
| -
|
| - // Enter the exit frame that transitions from JavaScript to C++.
|
| - FrameScope scope(masm, StackFrame::MANUAL);
|
| - __ EnterExitFrame(save_doubles_);
|
| -
|
| - // s0: number of arguments (C callee-saved)
|
| - // s1: pointer to first argument (C callee-saved)
|
| - // s2: pointer to builtin function (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();
|
| - __ li(v0, Operand(reinterpret_cast<int32_t>(failure)));
|
| - GenerateCore(masm,
|
| - &throw_normal_exception,
|
| - &throw_termination_exception,
|
| - true,
|
| - true);
|
| -
|
| - { FrameScope scope(masm, StackFrame::MANUAL);
|
| - __ PrepareCallCFunction(0, v0);
|
| - __ CallCFunction(
|
| - ExternalReference::out_of_memory_function(masm->isolate()), 0);
|
| - }
|
| + __ Throw(v0);
|
|
|
| __ bind(&throw_termination_exception);
|
| __ ThrowUncatchable(v0);
|
| -
|
| - __ bind(&throw_normal_exception);
|
| - __ Throw(v0);
|
| }
|
|
|
|
|
|
|