| Index: src/arm/code-stubs-arm.cc
|
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
|
| index 1e7d55897ad3049bf9b903a687240de8fdc0133f..1150e82764975dc01df321e064b5af2eceff5adb 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -3299,105 +3299,13 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
|
|
|
|
|
| void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
|
| - // r0 holds the exception.
|
| -
|
| - // Adjust this code if not the case.
|
| - STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
|
| -
|
| - // Drop the sp to the top of the handler.
|
| - __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
|
| - __ ldr(sp, MemOperand(r3));
|
| -
|
| - // Restore the next handler and frame pointer, discard handler state.
|
| - STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
|
| - __ pop(r2);
|
| - __ str(r2, MemOperand(r3));
|
| - STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
|
| - __ ldm(ia_w, sp, r3.bit() | fp.bit()); // r3: discarded state.
|
| -
|
| - // Before returning we restore the context from the frame pointer if
|
| - // not NULL. The frame pointer is NULL in the exception handler of a
|
| - // JS entry frame.
|
| - __ cmp(fp, Operand(0, RelocInfo::NONE));
|
| - // Set cp to NULL if fp is NULL.
|
| - __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
|
| - // Restore cp otherwise.
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
|
| -#ifdef DEBUG
|
| - if (FLAG_debug_code) {
|
| - __ mov(lr, Operand(pc));
|
| - }
|
| -#endif
|
| - STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
|
| - __ pop(pc);
|
| + __ Throw(r0);
|
| }
|
|
|
|
|
| void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
|
| UncatchableExceptionType type) {
|
| - // Adjust this code if not the case.
|
| - STATIC_ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
|
| -
|
| - // Drop sp to the top stack handler.
|
| - __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
|
| - __ ldr(sp, MemOperand(r3));
|
| -
|
| - // Unwind the handlers until the ENTRY handler is found.
|
| - Label loop, done;
|
| - __ bind(&loop);
|
| - // Load the type of the current stack handler.
|
| - const int kStateOffset = StackHandlerConstants::kStateOffset;
|
| - __ ldr(r2, MemOperand(sp, kStateOffset));
|
| - __ cmp(r2, Operand(StackHandler::ENTRY));
|
| - __ b(eq, &done);
|
| - // Fetch the next handler in the list.
|
| - const int kNextOffset = StackHandlerConstants::kNextOffset;
|
| - __ ldr(sp, MemOperand(sp, kNextOffset));
|
| - __ jmp(&loop);
|
| - __ bind(&done);
|
| -
|
| - // Set the top handler address to next handler past the current ENTRY handler.
|
| - STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
|
| - __ pop(r2);
|
| - __ str(r2, MemOperand(r3));
|
| -
|
| - if (type == OUT_OF_MEMORY) {
|
| - // Set external caught exception to false.
|
| - ExternalReference external_caught(Top::k_external_caught_exception_address);
|
| - __ mov(r0, Operand(false, RelocInfo::NONE));
|
| - __ mov(r2, Operand(external_caught));
|
| - __ str(r0, MemOperand(r2));
|
| -
|
| - // Set pending exception and r0 to out of memory exception.
|
| - Failure* out_of_memory = Failure::OutOfMemoryException();
|
| - __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
|
| - __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
|
| - __ str(r0, MemOperand(r2));
|
| - }
|
| -
|
| - // Stack layout at this point. See also StackHandlerConstants.
|
| - // sp -> state (ENTRY)
|
| - // fp
|
| - // lr
|
| -
|
| - // Discard handler state (r2 is not used) and restore frame pointer.
|
| - STATIC_ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize);
|
| - __ ldm(ia_w, sp, r2.bit() | fp.bit()); // r2: discarded state.
|
| - // Before returning we restore the context from the frame pointer if
|
| - // not NULL. The frame pointer is NULL in the exception handler of a
|
| - // JS entry frame.
|
| - __ cmp(fp, Operand(0, RelocInfo::NONE));
|
| - // Set cp to NULL if fp is NULL.
|
| - __ mov(cp, Operand(0, RelocInfo::NONE), LeaveCC, eq);
|
| - // Restore cp otherwise.
|
| - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
|
| -#ifdef DEBUG
|
| - if (FLAG_debug_code) {
|
| - __ mov(lr, Operand(pc));
|
| - }
|
| -#endif
|
| - STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
|
| - __ pop(pc);
|
| + __ ThrowUncatchable(type, r0);
|
| }
|
|
|
|
|
| @@ -3484,7 +3392,9 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
|
| // r0:r1: result
|
| // sp: stack pointer
|
| // fp: frame pointer
|
| - __ LeaveExitFrame(save_doubles_);
|
| + // Callee-saved register r4 still holds argc.
|
| + __ LeaveExitFrame(save_doubles_, r4);
|
| + __ mov(pc, lr);
|
|
|
| // check if we should retry or throw exception
|
| Label retry;
|
| @@ -4263,24 +4173,27 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
| __ IncrementCounter(&Counters::regexp_entry_native, 1, r0, r2);
|
|
|
| static const int kRegExpExecuteArguments = 7;
|
| - __ push(lr);
|
| - __ PrepareCallCFunction(kRegExpExecuteArguments, r0);
|
| + static const int kParameterRegisters = 4;
|
| + __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
|
| +
|
| + // Stack pointer now points to cell where return address is to be written.
|
| + // Arguments are before that on the stack or in registers.
|
|
|
| - // Argument 7 (sp[8]): Indicate that this is a direct call from JavaScript.
|
| + // Argument 7 (sp[12]): Indicate that this is a direct call from JavaScript.
|
| __ mov(r0, Operand(1));
|
| - __ str(r0, MemOperand(sp, 2 * kPointerSize));
|
| + __ str(r0, MemOperand(sp, 3 * kPointerSize));
|
|
|
| - // Argument 6 (sp[4]): Start (high end) of backtracking stack memory area.
|
| + // Argument 6 (sp[8]): Start (high end) of backtracking stack memory area.
|
| __ mov(r0, Operand(address_of_regexp_stack_memory_address));
|
| __ ldr(r0, MemOperand(r0, 0));
|
| __ mov(r2, Operand(address_of_regexp_stack_memory_size));
|
| __ ldr(r2, MemOperand(r2, 0));
|
| __ add(r0, r0, Operand(r2));
|
| - __ str(r0, MemOperand(sp, 1 * kPointerSize));
|
| + __ str(r0, MemOperand(sp, 2 * kPointerSize));
|
|
|
| - // Argument 5 (sp[0]): static offsets vector buffer.
|
| + // Argument 5 (sp[4]): static offsets vector buffer.
|
| __ mov(r0, Operand(ExternalReference::address_of_static_offsets_vector()));
|
| - __ str(r0, MemOperand(sp, 0 * kPointerSize));
|
| + __ str(r0, MemOperand(sp, 1 * kPointerSize));
|
|
|
| // For arguments 4 and 3 get string length, calculate start of string data and
|
| // calculate the shift of the index (0 for ASCII and 1 for two byte).
|
| @@ -4302,8 +4215,10 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
|
| // Locate the code entry and call it.
|
| __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| - __ CallCFunction(r7, kRegExpExecuteArguments);
|
| - __ pop(lr);
|
| + DirectCEntryStub stub;
|
| + stub.GenerateCall(masm, r7);
|
| +
|
| + __ LeaveExitFrame(false, no_reg);
|
|
|
| // r0: result
|
| // subject: subject string (callee saved)
|
| @@ -4312,6 +4227,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
|
|
| // Check the result.
|
| Label success;
|
| +
|
| __ cmp(r0, Operand(NativeRegExpMacroAssembler::SUCCESS));
|
| __ b(eq, &success);
|
| Label failure;
|
| @@ -4324,12 +4240,26 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
|
| // stack overflow (on the backtrack stack) was detected in RegExp code but
|
| // haven't created the exception yet. Handle that in the runtime system.
|
| // TODO(592): Rerunning the RegExp to get the stack overflow exception.
|
| - __ mov(r0, Operand(ExternalReference::the_hole_value_location()));
|
| - __ ldr(r0, MemOperand(r0, 0));
|
| - __ mov(r1, Operand(ExternalReference(Top::k_pending_exception_address)));
|
| + __ mov(r1, Operand(ExternalReference::the_hole_value_location()));
|
| __ ldr(r1, MemOperand(r1, 0));
|
| + __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
|
| + __ ldr(r0, MemOperand(r2, 0));
|
| __ cmp(r0, r1);
|
| __ b(eq, &runtime);
|
| +
|
| + __ str(r1, MemOperand(r2, 0)); // Clear pending exception.
|
| +
|
| + // Check if the exception is a termination. If so, throw as uncatchable.
|
| + __ LoadRoot(ip, Heap::kTerminationExceptionRootIndex);
|
| + __ cmp(r0, ip);
|
| + Label termination_exception;
|
| + __ b(eq, &termination_exception);
|
| +
|
| + __ Throw(r0); // Expects thrown value in r0.
|
| +
|
| + __ bind(&termination_exception);
|
| + __ ThrowUncatchable(TERMINATION, r0); // Expects thrown value in r0.
|
| +
|
| __ bind(&failure);
|
| // For failure and exception return null.
|
| __ mov(r0, Operand(Factory::null_value()));
|
| @@ -5953,14 +5883,24 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
| ApiFunction *function) {
|
| __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
|
| RelocInfo::CODE_TARGET));
|
| - // Push return address (accessible to GC through exit frame pc).
|
| __ mov(r2,
|
| Operand(ExternalReference(function, ExternalReference::DIRECT_CALL)));
|
| + // Push return address (accessible to GC through exit frame pc).
|
| __ str(pc, MemOperand(sp, 0));
|
| __ Jump(r2); // Call the api function.
|
| }
|
|
|
|
|
| +void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
|
| + Register target) {
|
| + __ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
|
| + RelocInfo::CODE_TARGET));
|
| + // Push return address (accessible to GC through exit frame pc).
|
| + __ str(pc, MemOperand(sp, 0));
|
| + __ Jump(target); // Call the C++ function.
|
| +}
|
| +
|
| +
|
| void GenerateFastPixelArrayLoad(MacroAssembler* masm,
|
| Register receiver,
|
| Register key,
|
|
|