Commit d2bdbcf7 authored by Martyn Capewell's avatar Martyn Capewell Committed by Commit Bot

[arm64] Align CONSTRUCT frames in EnterFrame

Push cp in EnterFrame for CONSTRUCT type frames, in order to align the stack op,
and adapt the users (Generate_JSBuiltinConstructStub*) to account for it.
Then align the rest of the stack operations in
Generate_JSBuiltinConstructStubHelper.

Bug: v8:6644
Change-Id: I4ffca329d5838902f787a52ac0d362dfbf9174c6
Reviewed-on: https://chromium-review.googlesource.com/746923Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Martyn Capewell <martyn.capewell@arm.com>
Cr-Commit-Position: refs/heads/master@{#49063}
parent 6bb00184
...@@ -2479,13 +2479,21 @@ void TurboAssembler::EnterFrame(StackFrame::Type type) { ...@@ -2479,13 +2479,21 @@ void TurboAssembler::EnterFrame(StackFrame::Type type) {
// csp[1] : type // csp[1] : type
// csp[0] : for alignment // csp[0] : for alignment
} else { } else {
DCHECK_EQ(type, StackFrame::CONSTRUCT);
DCHECK(jssp.Is(StackPointer())); DCHECK(jssp.Is(StackPointer()));
Mov(type_reg, StackFrame::TypeToMarker(type)); Mov(type_reg, StackFrame::TypeToMarker(type));
Push(lr, fp, type_reg);
Add(fp, jssp, TypedFrameConstants::kFixedFrameSizeFromFp); // Users of this frame type push a context pointer after the type field,
// jssp[2] : lr // so do it here to keep the stack pointer aligned.
// jssp[1] : fp Push(lr, fp, type_reg, cp);
// jssp[0] : type
// The context pointer isn't part of the fixed frame, so add an extra slot
// to account for it.
Add(fp, jssp, TypedFrameConstants::kFixedFrameSizeFromFp + kPointerSize);
// jssp[3] : lr
// jssp[2] : fp
// jssp[1] : type
// jssp[0] : cp
} }
} }
......
...@@ -203,32 +203,49 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { ...@@ -203,32 +203,49 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// Enter a construct frame. // Enter a construct frame.
{ {
FrameScope scope(masm, StackFrame::CONSTRUCT); FrameScope scope(masm, StackFrame::CONSTRUCT);
Label already_aligned;
Register argc = x0;
if (__ emit_debug_code()) {
// Check that FrameScope pushed the context on to the stack already.
__ Peek(x2, 0);
__ Cmp(x2, cp);
__ Check(eq, kUnexpectedValue);
}
// Add slots for the context, tagged argc and receiver. // Add slots for the tagged argc and receiver, and round up to maintain
// alignment.
Register slot_count = x2; Register slot_count = x2;
__ Add(slot_count, x0, 3); Register slot_count_without_rounding = x12;
__ Add(slot_count_without_rounding, argc, 3);
__ Bic(slot_count, slot_count_without_rounding, 1);
__ Claim(slot_count); __ Claim(slot_count);
// Preserve the incoming parameters on the stack. // Preserve the incoming parameters on the stack.
__ LoadRoot(x10, Heap::kTheHoleValueRootIndex); __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
__ SmiTag(x11, x0); __ SmiTag(x11, argc);
// Compute a pointer to the slot immediately above the location on the
// stack to which arguments will be later copied.
__ SlotAddress(x2, argc);
// Compute a pointer to the slot immediately above the newly claimed area // Poke the hole (receiver) and number of arguments (tagged) into the
// of stack. // highest claimed slots, with padding between them if argc was odd.
__ SlotAddress(x2, slot_count); __ Stp(x10, x11, MemOperand(x2));
__ Tbnz(slot_count_without_rounding, 0, &already_aligned);
// Poke the the hole (receiver), number of arguments (tagged) and the // Overwrite the previously written argc with padding, and store argc at the
// context into the three highest slots. // next highest slot.
__ Stp(x11, cp, MemOperand(x2, -2 * kPointerSize)); __ Stp(padreg, x11, MemOperand(x2, 1 * kPointerSize));
__ Str(x10, MemOperand(x2, -3 * kPointerSize)); __ Bind(&already_aligned);
// Copy arguments to the expression stack. // Copy arguments to the expression stack.
{ {
Register count = x2; Register count = x2;
Register dst = x10; Register dst = x10;
Register src = x11; Register src = x11;
__ Mov(count, x0); __ Mov(count, argc);
__ Mov(dst, __ StackPointer()); __ SlotAddress(dst, 0);
__ Add(src, fp, StandardFrameConstants::kCallerSPOffset); __ Add(src, fp, StandardFrameConstants::kCallerSPOffset);
__ CopyDoubleWords(dst, src, count); __ CopyDoubleWords(dst, src, count);
} }
...@@ -241,23 +258,26 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { ...@@ -241,23 +258,26 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// -- ... // -- ...
// -- sp[(n-1)*kPointerSize]: argument 0 // -- sp[(n-1)*kPointerSize]: argument 0
// -- sp[(n+0)*kPointerSize]: the hole (receiver) // -- sp[(n+0)*kPointerSize]: the hole (receiver)
// -- sp[(n+1)*kPointerSize]: number of arguments (tagged) // -- sp[(n+1)*kPointerSize]: optional padding, depending on argc.
// -- sp[(n+2)*kPointerSize]: context // -- sp[(n+1+(argc&1))*kPointerSize]: number of arguments (tagged)
// -- sp[(n+2+(argc&1))*kPointerSize]: context (pushed by FrameScope)
// ----------------------------------- // -----------------------------------
// Call the function. // Call the function.
ParameterCount actual(x0); ParameterCount actual(argc);
__ InvokeFunction(x1, x3, actual, CALL_FUNCTION); __ InvokeFunction(x1, x3, actual, CALL_FUNCTION);
// Restore the context from the frame. // Restore the context from the frame.
__ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset)); __ Ldr(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
// Restore smi-tagged arguments count from the frame. // Restore smi-tagged arguments count from the frame. Use fp relative
__ Peek(x1, 0); // addressing to avoid the circular dependency between padding existence and
// argc parity.
__ Ldrsw(x1,
UntagSmiMemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame. // Leave construct frame.
} }
// Remove caller arguments from the stack and return. // Remove caller arguments from the stack and return.
__ SmiUntag(x1);
__ DropArguments(x1, TurboAssembler::kCountExcludesReceiver); __ DropArguments(x1, TurboAssembler::kCountExcludesReceiver);
__ Ret(); __ Ret();
} }
...@@ -274,22 +294,29 @@ void Generate_JSConstructStubGeneric(MacroAssembler* masm, ...@@ -274,22 +294,29 @@ void Generate_JSConstructStubGeneric(MacroAssembler* masm,
// -- sp[...]: constructor arguments // -- sp[...]: constructor arguments
// ----------------------------------- // -----------------------------------
ASM_LOCATION("Builtins::Generate_JSConstructStubHelper"); ASM_LOCATION("Builtins::Generate_JSConstructStubGeneric");
// Enter a construct frame. // Enter a construct frame.
{ {
FrameScope scope(masm, StackFrame::CONSTRUCT); FrameScope scope(masm, StackFrame::CONSTRUCT);
Label post_instantiation_deopt_entry, not_create_implicit_receiver; Label post_instantiation_deopt_entry, not_create_implicit_receiver;
if (__ emit_debug_code()) {
// Check that FrameScope pushed the context on to the stack already.
__ Peek(x2, 0);
__ Cmp(x2, cp);
__ Check(eq, kUnexpectedValue);
}
// Preserve the incoming parameters on the stack. // Preserve the incoming parameters on the stack.
__ SmiTag(x0); __ SmiTag(x0);
__ Push(cp, x0, x1, x3); __ Push(x0, x1, x3);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- sp[0*kPointerSize]: new target // -- sp[0*kPointerSize]: new target
// -- x1 and sp[1*kPointerSize]: constructor function // -- x1 and sp[1*kPointerSize]: constructor function
// -- sp[2*kPointerSize]: number of arguments (tagged) // -- sp[2*kPointerSize]: number of arguments (tagged)
// -- sp[3*kPointerSize]: context // -- sp[3*kPointerSize]: context (pushed by FrameScope)
// ----------------------------------- // -----------------------------------
__ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); __ Ldr(x4, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
...@@ -430,7 +457,8 @@ void Generate_JSConstructStubGeneric(MacroAssembler* masm, ...@@ -430,7 +457,8 @@ void Generate_JSConstructStubGeneric(MacroAssembler* masm,
__ Bind(&leave_frame); __ Bind(&leave_frame);
// Restore smi-tagged arguments count from the frame. // Restore smi-tagged arguments count from the frame.
__ Ldr(w1, UntagSmiMemOperand(fp, ConstructFrameConstants::kLengthOffset)); __ Ldrsw(x1,
UntagSmiMemOperand(fp, ConstructFrameConstants::kLengthOffset));
// Leave construct frame. // Leave construct frame.
} }
// Remove caller arguments from the stack and return. // Remove caller arguments from the stack and return.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment