| Index: src/arm/code-stubs-arm.cc
|
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
|
| index 5525ec12a0bd4ecd242009002605c7b5dd5d65fb..be876b6eee89c27378fcd2f79826bd0ad364a75a 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -1502,38 +1502,36 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
|
| }
|
|
|
|
|
| -void CEntryStub::GenerateCore(MacroAssembler* masm,
|
| - Label* throw_normal_exception,
|
| - Label* throw_termination_exception,
|
| - bool do_gc,
|
| - bool always_allocate) {
|
| - // r0: result parameter for PerformGC, if any
|
| - // r4: number of arguments including receiver (C callee-saved)
|
| - // r5: pointer to builtin function (C callee-saved)
|
| - // r6: pointer to the first argument (C callee-saved)
|
| - Isolate* isolate = masm->isolate();
|
| +void CEntryStub::Generate(MacroAssembler* masm) {
|
| + // Called from JavaScript; parameters are on stack as if calling JS function.
|
| + // r0: number of arguments including receiver
|
| + // r1: 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)
|
|
|
| - if (do_gc) {
|
| - // Passing r0.
|
| - __ PrepareCallCFunction(2, 0, r1);
|
| - __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
|
| - __ CallCFunction(ExternalReference::perform_gc_function(isolate),
|
| - 2, 0);
|
| - }
|
| + ProfileEntryHookStub::MaybeCallEntryHook(masm);
|
|
|
| - ExternalReference scope_depth =
|
| - ExternalReference::heap_always_allocate_scope_depth(isolate);
|
| - if (always_allocate) {
|
| - __ mov(r0, Operand(scope_depth));
|
| - __ ldr(r1, MemOperand(r0));
|
| - __ add(r1, r1, Operand(1));
|
| - __ str(r1, MemOperand(r0));
|
| - }
|
| + __ mov(r5, Operand(r1));
|
|
|
| - // Call C built-in.
|
| - // r0 = argc, r1 = argv
|
| - __ mov(r0, Operand(r4));
|
| - __ mov(r1, Operand(r6));
|
| + // Compute the argv pointer in a callee-saved register.
|
| + __ add(r1, sp, Operand(r0, LSL, kPointerSizeLog2));
|
| + __ sub(r1, r1, Operand(kPointerSize));
|
| +
|
| + // Enter the exit frame that transitions from JavaScript to C++.
|
| + FrameScope scope(masm, StackFrame::MANUAL);
|
| + __ EnterExitFrame(save_doubles_);
|
| +
|
| + // Store a copy of argc in callee-saved registers for later.
|
| + __ mov(r4, Operand(r0));
|
| +
|
| + // r0, r4: number of arguments including receiver (C callee-saved)
|
| + // r1: pointer to the first argument (C callee-saved)
|
| + // r5: pointer to builtin function (C callee-saved)
|
| +
|
| + // Result returned in r0 or r0+r1 by default.
|
| +
|
| + Isolate* isolate = masm->isolate();
|
|
|
| #if V8_HOST_ARCH_ARM
|
| int frame_alignment = MacroAssembler::ActivationFrameAlignment();
|
| @@ -1551,6 +1549,8 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
| }
|
| #endif
|
|
|
| + // Call C built-in.
|
| + // r0 = argc, r1 = argv
|
| __ mov(r2, Operand(ExternalReference::isolate_address(isolate)));
|
|
|
| // To let the GC traverse the return address of the exit frames, we need to
|
| @@ -1570,132 +1570,67 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
|
|
| __ VFPEnsureFPSCRState(r2);
|
|
|
| - if (always_allocate) {
|
| - // It's okay to clobber r2 and r3 here. Don't mess with r0 and r1
|
| - // though (contain the result).
|
| - __ mov(r2, Operand(scope_depth));
|
| - __ ldr(r3, MemOperand(r2));
|
| - __ sub(r3, r3, Operand(1));
|
| - __ str(r3, MemOperand(r2));
|
| + // 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(r0, Heap::kTheHoleValueRootIndex);
|
| + __ b(ne, &okay);
|
| + __ stop("The hole escaped");
|
| + __ bind(&okay);
|
| }
|
|
|
| - // check for failure result
|
| - Label failure_returned;
|
| - STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
|
| - // Lower 2 bits of r2 are 0 iff r0 has failure tag.
|
| - __ add(r2, r0, Operand(1));
|
| - __ tst(r2, Operand(kFailureTagMask));
|
| - __ b(eq, &failure_returned);
|
| + // Check result for exception sentinel.
|
| + Label exception_returned;
|
| + __ CompareRoot(r0, Heap::kExceptionRootIndex);
|
| + __ b(eq, &exception_returned);
|
| +
|
| + 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;
|
| + __ mov(r2, Operand(pending_exception_address));
|
| + __ ldr(r2, MemOperand(r2));
|
| + __ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
|
| + // Cannot use check here as it attempts to generate call into runtime.
|
| + __ b(eq, &okay);
|
| + __ stop("Unexpected pending exception");
|
| + __ bind(&okay);
|
| + }
|
|
|
| // Exit C frame and return.
|
| // r0:r1: result
|
| // sp: stack pointer
|
| // fp: frame pointer
|
| - // Callee-saved register r4 still holds argc.
|
| + // Callee-saved register r4 still holds argc.
|
| __ LeaveExitFrame(save_doubles_, r4, true);
|
| __ mov(pc, lr);
|
|
|
| - // check if we should retry or throw exception
|
| - Label retry;
|
| - __ bind(&failure_returned);
|
| - STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
|
| - __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
|
| - __ b(eq, &retry);
|
| + // Handling of exception.
|
| + __ bind(&exception_returned);
|
|
|
| // Retrieve the pending exception.
|
| - __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
|
| - isolate)));
|
| - __ ldr(r0, MemOperand(ip));
|
| + __ mov(r2, Operand(pending_exception_address));
|
| + __ ldr(r0, MemOperand(r2));
|
|
|
| // Clear the pending exception.
|
| __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
|
| - __ mov(ip, Operand(ExternalReference(Isolate::kPendingExceptionAddress,
|
| - isolate)));
|
| - __ str(r3, MemOperand(ip));
|
| + __ str(r3, MemOperand(r2));
|
|
|
| // Special handling of termination exceptions which are uncatchable
|
| // by javascript code.
|
| - __ LoadRoot(r3, Heap::kTerminationExceptionRootIndex);
|
| - __ cmp(r0, r3);
|
| - __ b(eq, throw_termination_exception);
|
| -
|
| - // Handle normal exception.
|
| - __ jmp(throw_normal_exception);
|
| -
|
| - __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying
|
| -}
|
| -
|
| -
|
| -void CEntryStub::Generate(MacroAssembler* masm) {
|
| - // Called from JavaScript; parameters are on stack as if calling JS function
|
| - // r0: number of arguments including receiver
|
| - // r1: 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);
|
| -
|
| - // Result returned in r0 or r0+r1 by default.
|
| -
|
| - // 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.
|
| -
|
| - // Compute the argv pointer in a callee-saved register.
|
| - __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
|
| - __ sub(r6, r6, Operand(kPointerSize));
|
| -
|
| - // Enter the exit frame that transitions from JavaScript to C++.
|
| - FrameScope scope(masm, StackFrame::MANUAL);
|
| - __ EnterExitFrame(save_doubles_);
|
| -
|
| - // Set up argc and the builtin function in callee-saved registers.
|
| - __ mov(r4, Operand(r0));
|
| - __ mov(r5, Operand(r1));
|
| -
|
| - // r4: number of arguments (C callee-saved)
|
| - // r5: pointer to builtin function (C callee-saved)
|
| - // r6: pointer to first argument (C callee-saved)
|
| -
|
| - Label throw_normal_exception;
|
| Label throw_termination_exception;
|
| + __ CompareRoot(r0, Heap::kTerminationExceptionRootIndex);
|
| + __ b(eq, &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();
|
| - __ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
|
| - GenerateCore(masm,
|
| - &throw_normal_exception,
|
| - &throw_termination_exception,
|
| - true,
|
| - true);
|
| -
|
| - { FrameScope scope(masm, StackFrame::MANUAL);
|
| - __ PrepareCallCFunction(0, r0);
|
| - __ CallCFunction(
|
| - ExternalReference::out_of_memory_function(masm->isolate()), 0, 0);
|
| - }
|
| + // Handle normal exception.
|
| + __ Throw(r0);
|
|
|
| __ bind(&throw_termination_exception);
|
| __ ThrowUncatchable(r0);
|
| -
|
| - __ bind(&throw_normal_exception);
|
| - __ Throw(r0);
|
| }
|
|
|
|
|
| @@ -1791,7 +1726,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
|
| isolate)));
|
| }
|
| __ str(r0, MemOperand(ip));
|
| - __ mov(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
|
| + __ LoadRoot(r0, Heap::kExceptionRootIndex);
|
| __ b(&exit);
|
|
|
| // Invoke: Link this frame into the handler chain. There's only one
|
|
|