Index: src/arm/code-stubs-arm.cc |
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc |
index 21413335ea0764e443d50c9a02523a8755d0361b..0dd399ea2c6b6430b325f70e648c07cd5ae66aee 100644 |
--- a/src/arm/code-stubs-arm.cc |
+++ b/src/arm/code-stubs-arm.cc |
@@ -999,11 +999,9 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
// 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. |
- |
-#if V8_HOST_ARCH_ARM |
int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
int frame_alignment_mask = frame_alignment - 1; |
+#if V8_HOST_ARCH_ARM |
if (FLAG_debug_code) { |
if (frame_alignment > kPointerSize) { |
Label alignment_as_expected; |
@@ -1018,8 +1016,25 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
#endif |
// Call C built-in. |
- // r0 = argc, r1 = argv |
- __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); |
+ int result_stack_size; |
+ if (result_size() <= 2) { |
+ // r0 = argc, r1 = argv, r2 = isolate |
+ __ mov(r2, Operand(ExternalReference::isolate_address(isolate()))); |
+ result_stack_size = 0; |
+ } else { |
+ DCHECK_EQ(3, result_size()); |
+ // Allocate additional space for the result. |
+ result_stack_size = |
+ ((result_size() * kPointerSize) + frame_alignment_mask) & |
+ ~frame_alignment_mask; |
+ __ sub(sp, sp, Operand(result_stack_size)); |
+ |
+ // r0 = hidden result argument, r1 = argc, r2 = argv, r3 = isolate. |
+ __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); |
+ __ mov(r2, Operand(r1)); |
+ __ mov(r1, Operand(r0)); |
+ __ mov(r0, Operand(sp)); |
+ } |
// To let the GC traverse the return address of the exit frames, we need to |
// know where the return address is. The CEntryStub is unmovable, so |
@@ -1032,11 +1047,19 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
// Prevent literal pool emission before return address. |
Assembler::BlockConstPoolScope block_const_pool(masm); |
__ add(lr, pc, Operand(4)); |
- __ str(lr, MemOperand(sp, 0)); |
+ __ str(lr, MemOperand(sp, result_stack_size)); |
__ Call(r5); |
} |
+ if (result_size() > 2) { |
+ DCHECK_EQ(3, result_size()); |
+ // Read result values stored on stack. |
+ __ ldr(r2, MemOperand(r0, 2 * kPointerSize)); |
+ __ ldr(r1, MemOperand(r0, 1 * kPointerSize)); |
+ __ ldr(r0, MemOperand(r0, 0 * kPointerSize)); |
+ } |
+ // Result returned in r0, r1:r0 or r2:r1:r0 - do not destroy these registers! |
- __ VFPEnsureFPSCRState(r2); |
+ __ VFPEnsureFPSCRState(r3); |
// Check result for exception sentinel. |
Label exception_returned; |
@@ -1049,9 +1072,9 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
Label okay; |
ExternalReference pending_exception_address( |
Isolate::kPendingExceptionAddress, isolate()); |
- __ mov(r2, Operand(pending_exception_address)); |
- __ ldr(r2, MemOperand(r2)); |
- __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
+ __ mov(r3, Operand(pending_exception_address)); |
+ __ ldr(r3, MemOperand(r3)); |
+ __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
// Cannot use check here as it attempts to generate call into runtime. |
__ b(eq, &okay); |
__ stop("Unexpected pending exception"); |