| Index: src/arm64/code-stubs-arm64.cc
|
| diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
|
| index a1e920755dd2ef913b76f04a1d04f968fbd34591..a9b647ca80095acce040ac6a3823dc16dae6ea48 100644
|
| --- a/src/arm64/code-stubs-arm64.cc
|
| +++ b/src/arm64/code-stubs-arm64.cc
|
| @@ -1104,10 +1104,13 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
| __ Sub(temp_argv, temp_argv, 1 * kPointerSize);
|
| }
|
|
|
| - // Enter the exit frame. Reserve three slots to preserve x21-x23 callee-saved
|
| - // registers.
|
| + // Reserve three slots to preserve x21-x23 callee-saved registers. If the
|
| + // result size is too large to be returned in registers then also reserve
|
| + // space for the return value.
|
| + int extra_stack_space = 3 + (result_size() <= 2 ? 0 : result_size());
|
| + // Enter the exit frame.
|
| FrameScope scope(masm, StackFrame::MANUAL);
|
| - __ EnterExitFrame(save_doubles(), x10, 3);
|
| + __ EnterExitFrame(save_doubles(), x10, extra_stack_space);
|
| DCHECK(csp.Is(__ StackPointer()));
|
|
|
| // Poke callee-saved registers into reserved space.
|
| @@ -1115,6 +1118,11 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
| __ Poke(argc, 2 * kPointerSize);
|
| __ Poke(target, 3 * kPointerSize);
|
|
|
| + if (result_size() > 2) {
|
| + // Save the location of the return value into x8 for call.
|
| + __ Add(x8, __ StackPointer(), Operand(4 * kPointerSize));
|
| + }
|
| +
|
| // We normally only keep tagged values in callee-saved registers, as they
|
| // could be pushed onto the stack by called stubs and functions, and on the
|
| // stack they can confuse the GC. However, we're only calling C functions
|
| @@ -1184,7 +1192,18 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
| __ Blr(target);
|
| __ Bind(&return_location);
|
|
|
| - // x0 result The return code from the call.
|
| + if (result_size() > 2) {
|
| + DCHECK_EQ(3, result_size());
|
| + // Read result values stored on stack.
|
| + __ Ldr(x0, MemOperand(__ StackPointer(), 4 * kPointerSize));
|
| + __ Ldr(x1, MemOperand(__ StackPointer(), 5 * kPointerSize));
|
| + __ Ldr(x2, MemOperand(__ StackPointer(), 6 * kPointerSize));
|
| + }
|
| + // Result returned in x0, x1:x0 or x2:x1:x0 - do not destroy these registers!
|
| +
|
| + // x0 result0 The return code from the call.
|
| + // x1 result1 For calls which return ObjectPair or ObjectTriple.
|
| + // x2 result2 For calls which return ObjectTriple.
|
| // x21 argv
|
| // x22 argc
|
| // x23 target
|
|
|