Commit df01ab6e authored by Victor Gomes's avatar Victor Gomes Committed by Commit Bot

[arm] Remove arguments adaptor frame

Change-Id: I7df25ca2c7caabed429cfdc0b4aab0aeb5e03fcd
Bug: v8:10201
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2463222Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70926}
parent f4d5e8a3
......@@ -111,7 +111,8 @@ declare_args() {
# Disable arguments adaptor frame (sets -dV8_NO_ARGUMENTS_ADAPTOR).
v8_disable_arguments_adaptor =
v8_current_cpu == "x86" || v8_current_cpu == "x64"
v8_current_cpu == "x86" || v8_current_cpu == "x64" ||
v8_current_cpu == "arm"
# Sets -dOBJECT_PRINT.
v8_enable_object_print = ""
......
This diff is collapsed.
......@@ -1547,22 +1547,102 @@ void TurboAssembler::PrepareForTailCall(Register callee_args_count,
mov(sp, dst_reg);
}
void MacroAssembler::LoadStackLimit(Register destination, StackLimitKind kind) {
DCHECK(root_array_available());
Isolate* isolate = this->isolate();
ExternalReference limit =
kind == StackLimitKind::kRealStackLimit
? ExternalReference::address_of_real_jslimit(isolate)
: ExternalReference::address_of_jslimit(isolate);
DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit));
intptr_t offset =
TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit);
CHECK(is_int32(offset));
ldr(destination, MemOperand(kRootRegister, offset));
}
void MacroAssembler::StackOverflowCheck(Register num_args, Register scratch,
Label* stack_overflow) {
// Check the stack for overflow. We are not trying to catch
// interruptions (e.g. debug break and preemption) here, so the "real stack
// limit" is checked.
LoadStackLimit(scratch, StackLimitKind::kRealStackLimit);
// Make scratch the space we have left. The stack might already be overflowed
// here which will cause scratch to become negative.
sub(scratch, sp, scratch);
// Check if the arguments will overflow the stack.
cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2));
b(le, stack_overflow); // Signed comparison.
}
void MacroAssembler::InvokePrologue(Register expected_parameter_count,
Register actual_parameter_count,
Label* done, InvokeFlag flag) {
Label regular_invoke;
// Check whether the expected and actual arguments count match. If not,
// setup registers according to contract with ArgumentsAdaptorTrampoline:
// r0: actual arguments count
// r1: function (passed through to callee)
// r2: expected arguments count
// The code below is made a lot easier because the calling code already sets
// up actual and expected registers according to the contract.
DCHECK_EQ(actual_parameter_count, r0);
DCHECK_EQ(expected_parameter_count, r2);
#ifdef V8_NO_ARGUMENTS_ADAPTOR
// If the expected parameter count is equal to the adaptor sentinel, no need
// to push undefined value as arguments.
cmp(expected_parameter_count, Operand(kDontAdaptArgumentsSentinel));
b(eq, &regular_invoke);
// If overapplication or if the actual argument count is equal to the
// formal parameter count, no need to push extra undefined values.
sub(expected_parameter_count, expected_parameter_count,
actual_parameter_count, SetCC);
b(le, &regular_invoke);
Label stack_overflow;
Register scratch = r4;
StackOverflowCheck(expected_parameter_count, scratch, &stack_overflow);
// Underapplication. Move the arguments already in the stack, including the
// receiver and the return address.
{
Label copy, check;
Register num = r5, src = r6, dest = r9; // r7 and r8 are context and root.
mov(src, sp);
// Update stack pointer.
lsl(scratch, expected_parameter_count, Operand(kSystemPointerSizeLog2));
AllocateStackSpace(scratch);
mov(dest, sp);
mov(num, actual_parameter_count);
b(&check);
bind(&copy);
ldr(scratch, MemOperand(src, kSystemPointerSize, PostIndex));
str(scratch, MemOperand(dest, kSystemPointerSize, PostIndex));
sub(num, num, Operand(1), SetCC);
bind(&check);
b(ge, &copy);
}
// Fill remaining expected arguments with undefined values.
LoadRoot(scratch, RootIndex::kUndefinedValue);
{
Label loop;
bind(&loop);
str(scratch, MemOperand(r9, kSystemPointerSize, PostIndex));
sub(expected_parameter_count, expected_parameter_count, Operand(1), SetCC);
b(gt, &loop);
}
b(&regular_invoke);
bind(&stack_overflow);
{
FrameScope frame(this,
has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
CallRuntime(Runtime::kThrowStackOverflow);
bkpt(0);
}
#else
// Check whether the expected and actual arguments count match. If not,
// setup registers according to contract with ArgumentsAdaptorTrampoline.
cmp(expected_parameter_count, actual_parameter_count);
b(eq, &regular_invoke);
......@@ -1573,7 +1653,8 @@ void MacroAssembler::InvokePrologue(Register expected_parameter_count,
} else {
Jump(adaptor, RelocInfo::CODE_TARGET);
}
bind(&regular_invoke);
#endif
bind(&regular_invoke);
}
void MacroAssembler::CallDebugOnFunctionCall(Register fun, Register new_target,
......
......@@ -17,6 +17,10 @@
namespace v8 {
namespace internal {
// TODO(victorgomes): Move definition to macro-assembler.h, once all other
// platforms are updated.
enum class StackLimitKind { kInterruptStackLimit, kRealStackLimit };
// ----------------------------------------------------------------------------
// Static helper functions
......@@ -781,6 +785,12 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
Register scratch2);
// ---------------------------------------------------------------------------
// Stack limit utilities
void LoadStackLimit(Register destination, StackLimitKind kind);
void StackOverflowCheck(Register num_args, Register scratch,
Label* stack_overflow);
// ---------------------------------------------------------------------------
// Smi utilities
......
......@@ -3768,9 +3768,8 @@ void CodeGenerator::AssembleConstructFrame() {
}
}
void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
void CodeGenerator::AssembleReturn(InstructionOperand* additional_pop_count) {
auto call_descriptor = linkage()->GetIncomingDescriptor();
int pop_count = static_cast<int>(call_descriptor->StackParameterCount());
const int returns = frame()->GetReturnSlotCount();
if (returns != 0) {
......@@ -3796,32 +3795,76 @@ void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
unwinding_info_writer_.MarkBlockWillExit();
// We might need r3 for scratch.
DCHECK_EQ(0u, call_descriptor->CalleeSavedRegisters() & r3.bit());
ArmOperandConverter g(this, nullptr);
const int parameter_count =
static_cast<int>(call_descriptor->StackParameterCount());
// {additional_pop_count} is only greater than zero if {parameter_count = 0}.
// Check RawMachineAssembler::PopAndReturn.
if (parameter_count != 0) {
if (additional_pop_count->IsImmediate()) {
DCHECK_EQ(g.ToConstant(additional_pop_count).ToInt32(), 0);
} else if (__ emit_debug_code()) {
__ cmp(g.ToRegister(additional_pop_count), Operand(0));
__ Assert(eq, AbortReason::kUnexpectedAdditionalPopValue);
}
}
Register argc_reg = r3;
#ifdef V8_NO_ARGUMENTS_ADAPTOR
// Functions with JS linkage have at least one parameter (the receiver).
// If {parameter_count} == 0, it means it is a builtin with
// kDontAdaptArgumentsSentinel, which takes care of JS arguments popping
// itself.
const bool drop_jsargs = frame_access_state()->has_frame() &&
call_descriptor->IsJSFunctionCall() &&
parameter_count != 0;
#else
const bool drop_jsargs = false;
#endif
if (call_descriptor->IsCFunctionCall()) {
AssembleDeconstructFrame();
} else if (frame_access_state()->has_frame()) {
// Canonicalize JSFunction return sites for now unless they have an variable
// number of stack slot pops.
if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) {
if (additional_pop_count->IsImmediate() &&
g.ToConstant(additional_pop_count).ToInt32() == 0) {
if (return_label_.is_bound()) {
__ b(&return_label_);
return;
} else {
__ bind(&return_label_);
AssembleDeconstructFrame();
}
} else {
AssembleDeconstructFrame();
}
if (drop_jsargs) {
// Get the actual argument count.
__ ldr(argc_reg, MemOperand(fp, StandardFrameConstants::kArgCOffset));
}
AssembleDeconstructFrame();
}
if (pop->IsImmediate()) {
DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type());
pop_count += g.ToConstant(pop).ToInt32();
if (drop_jsargs) {
// We must pop all arguments from the stack (including the receiver). This
// number of arguments is given by max(1 + argc_reg, parameter_count).
__ add(argc_reg, argc_reg, Operand(1)); // Also pop the receiver.
if (parameter_count > 1) {
__ cmp(argc_reg, Operand(parameter_count));
__ mov(argc_reg, Operand(parameter_count), LeaveCC, lt);
}
__ Drop(argc_reg);
} else if (additional_pop_count->IsImmediate()) {
DCHECK_EQ(Constant::kInt32, g.ToConstant(additional_pop_count).type());
int additional_count = g.ToConstant(additional_pop_count).ToInt32();
__ Drop(parameter_count + additional_count);
} else if (parameter_count == 0) {
__ Drop(g.ToRegister(additional_pop_count));
} else {
__ Drop(g.ToRegister(pop));
// {additional_pop_count} is guaranteed to be zero if {parameter_count !=
// 0}. Check RawMachineAssembler::PopAndReturn.
__ Drop(parameter_count);
}
__ Drop(pop_count);
__ Ret();
}
......
......@@ -1894,9 +1894,8 @@ Object Isolate::UnwindAndFindHandler() {
case StackFrame::BUILTIN:
// For builtin frames we are guaranteed not to find a handler.
if (catchable_by_js) {
CHECK_EQ(-1,
JavaScriptFrame::cast(frame)->LookupExceptionHandlerInTable(
nullptr, nullptr));
CHECK_EQ(-1, BuiltinFrame::cast(frame)->LookupExceptionHandlerInTable(
nullptr, nullptr));
}
break;
......
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