Commit 0ef08848 authored by Victor Gomes's avatar Victor Gomes Committed by Commit Bot

[deoptimizer] Adapt BuiltinContinuation frame for V8_REVERSE_JSARGS

This adapts the deoptimizer to create a correct stack frame when the JS arguments are reversed.

Change-Id: Ifc216116ce1e5e469316a22deb8679347e847f4f
Bug: v8:10201
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2297382
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68940}
parent c512d617
......@@ -1572,13 +1572,29 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
bool with_result) {
const RegisterConfiguration* config(RegisterConfiguration::Default());
int allocatable_register_count = config->num_allocatable_general_registers();
UseScratchRegisterScope temps(masm);
Register scratch = temps.Acquire(); // Temp register is not allocatable.
if (with_result) {
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin) {
__ mov(scratch, r0);
} else {
// Overwrite the hole inserted by the deoptimizer with the return value
// from the LAZY deopt point.
__ str(
r0,
MemOperand(
sp, config->num_allocatable_general_registers() * kPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize));
}
#else
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point.
__ str(r0,
MemOperand(
sp, config->num_allocatable_general_registers() * kPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize));
#endif
}
for (int i = allocatable_register_count - 1; i >= 0; --i) {
int code = config->GetAllocatableGeneralCode(i);
......@@ -1587,13 +1603,22 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
__ SmiUntag(Register::from_code(code));
}
}
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin && with_result) {
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point. r0 contains the arguments count, the return value
// from LAZY is always the last argument.
__ add(r0, r0, Operand(BuiltinContinuationFrameConstants::kFixedSlotCount));
__ str(scratch, MemOperand(sp, r0, LSL, kPointerSizeLog2));
// Recover arguments count.
__ sub(r0, r0, Operand(BuiltinContinuationFrameConstants::kFixedSlotCount));
}
#endif
__ ldr(fp, MemOperand(
sp, BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
// Load builtin index (stored as a Smi) and use it to get the builtin start
// address from the builtins table.
UseScratchRegisterScope temps(masm);
Register builtin = temps.Acquire();
Register builtin = scratch;
__ Pop(builtin);
__ add(sp, sp,
Operand(BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
......
......@@ -1746,14 +1746,28 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
allocatable_register_count)) *
kSystemPointerSize;
UseScratchRegisterScope temps(masm);
Register scratch = temps.AcquireX(); // Temp register is not allocatable.
// Set up frame pointer.
__ Add(fp, sp, frame_size);
if (with_result) {
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin) {
__ mov(scratch, x0);
} else {
// Overwrite the hole inserted by the deoptimizer with the return value
// from the LAZY deopt point.
__ Str(x0, MemOperand(
fp, BuiltinContinuationFrameConstants::kCallerSPOffset));
}
#else
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point.
__ Str(x0,
MemOperand(fp, BuiltinContinuationFrameConstants::kCallerSPOffset));
#endif
}
// Restore registers in pairs.
......@@ -1776,10 +1790,25 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
if (java_script_builtin) __ SmiUntag(kJavaScriptCallArgCountRegister);
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin && with_result) {
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point. r0 contains the arguments count, the return value
// from LAZY is always the last argument.
__ add(x0, x0,
BuiltinContinuationFrameConstants::kCallerSPOffset /
kSystemPointerSize);
__ Str(scratch, MemOperand(fp, x0, LSL, kSystemPointerSizeLog2));
// Recover argument count.
__ sub(x0, x0,
BuiltinContinuationFrameConstants::kCallerSPOffset /
kSystemPointerSize);
}
#endif
// Load builtin index (stored as a Smi) and use it to get the builtin start
// address from the builtins table.
UseScratchRegisterScope temps(masm);
Register builtin = temps.AcquireX();
Register builtin = scratch;
__ Ldr(
builtin,
MemOperand(fp, BuiltinContinuationFrameConstants::kBuiltinIndexOffset));
......
......@@ -1664,12 +1664,27 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
const RegisterConfiguration* config(RegisterConfiguration::Default());
int allocatable_register_count = config->num_allocatable_general_registers();
if (with_result) {
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin) {
// xmm0 is not included in the allocateable registers.
__ movd(xmm0, eax);
} else {
// Overwrite the hole inserted by the deoptimizer with the return value
// from the LAZY deopt point.
__ mov(
Operand(esp, config->num_allocatable_general_registers() *
kSystemPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize),
eax);
}
#else
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point.
__ mov(Operand(esp, config->num_allocatable_general_registers() *
kSystemPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize),
eax);
#endif
}
// Replace the builtin index Smi on the stack with the start address of the
......@@ -1687,6 +1702,16 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
__ SmiUntag(Register::from_code(code));
}
}
#ifdef V8_REVERSE_JSARGS
if (with_result && java_script_builtin) {
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point. eax contains the arguments count, the return value
// from LAZY is always the last argument.
__ movd(Operand(esp, eax, times_system_pointer_size,
BuiltinContinuationFrameConstants::kFixedFrameSize),
xmm0);
}
#endif
__ mov(
ebp,
Operand(esp, BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
......
......@@ -1634,6 +1634,20 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
const RegisterConfiguration* config(RegisterConfiguration::Default());
int allocatable_register_count = config->num_allocatable_general_registers();
if (with_result) {
#ifdef V8_REVERSE_JSARGS
if (java_script_builtin) {
// kScratchRegister is not included in the allocateable registers.
__ movq(kScratchRegister, rax);
} else {
// Overwrite the hole inserted by the deoptimizer with the return value
// from the LAZY deopt point.
__ movq(
Operand(rsp, config->num_allocatable_general_registers() *
kSystemPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize),
rax);
}
#else
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point.
__ movq(
......@@ -1641,6 +1655,7 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
kSystemPointerSize +
BuiltinContinuationFrameConstants::kFixedFrameSize),
rax);
#endif
}
for (int i = allocatable_register_count - 1; i >= 0; --i) {
int code = config->GetAllocatableGeneralCode(i);
......@@ -1649,6 +1664,16 @@ void Generate_ContinueToBuiltinHelper(MacroAssembler* masm,
__ SmiUntag(Register::from_code(code));
}
}
#ifdef V8_REVERSE_JSARGS
if (with_result && java_script_builtin) {
// Overwrite the hole inserted by the deoptimizer with the return value from
// the LAZY deopt point. rax contains the arguments count, the return value
// from LAZY is always the last argument.
__ movq(Operand(rsp, rax, times_system_pointer_size,
BuiltinContinuationFrameConstants::kFixedFrameSize),
kScratchRegister);
}
#endif
__ movq(
rbp,
Operand(rsp, BuiltinContinuationFrameConstants::kFixedFrameSizeFromFp));
......
......@@ -91,6 +91,24 @@ class FrameWriter {
iterator);
}
void PushStackJSArguments(TranslatedFrame::iterator& iterator,
int parameters_count) {
#ifdef V8_REVERSE_JSARGS
std::vector<TranslatedFrame::iterator> parameters;
parameters.reserve(parameters_count);
for (int i = 0; i < parameters_count; ++i, ++iterator) {
parameters.push_back(iterator);
}
for (auto& parameter : base::Reversed(parameters)) {
PushTranslatedValue(parameter, "stack parameter");
}
#else
for (int i = 0; i < parameters_count; ++i, ++iterator) {
PushTranslatedValue(iterator, "stack parameter");
}
#endif
}
unsigned top_offset() const { return top_offset_; }
private:
......@@ -930,25 +948,11 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
ReadOnlyRoots roots(isolate());
if (ShouldPadArguments(parameters_count)) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
#ifdef V8_REVERSE_JSARGS
std::vector<TranslatedFrame::iterator> parameters;
for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
parameters.push_back(value_iterator);
}
for (auto& parameter : base::Reversed(parameters)) {
frame_writer.PushTranslatedValue(parameter, "stack parameter");
}
#else
for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
#endif
frame_writer.PushStackJSArguments(value_iterator, parameters_count);
DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
frame_writer.top_offset());
......@@ -1303,9 +1307,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
TranslatedFrame::iterator receiver_iterator = value_iterator;
// Compute the incoming parameter translation.
for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
frame_writer.PushStackJSArguments(value_iterator, parameters_count);
DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
frame_writer.top_offset());
......@@ -1595,6 +1597,47 @@ void Deoptimizer::DoComputeBuiltinContinuation(
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
#ifdef V8_REVERSE_JSARGS
if (mode == BuiltinContinuationMode::STUB) {
DCHECK_EQ(Builtins::CallInterfaceDescriptorFor(builtin_name)
.GetStackArgumentOrder(),
StackArgumentOrder::kDefault);
for (uint32_t i = 0; i < frame_info.translated_stack_parameter_count();
++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
if (frame_info.frame_has_result_stack_slot()) {
frame_writer.PushRawObject(
roots.the_hole_value(),
"placeholder for return result on lazy deopt\n");
}
} else {
// JavaScript builtin.
if (frame_info.frame_has_result_stack_slot()) {
frame_writer.PushRawObject(
roots.the_hole_value(),
"placeholder for return result on lazy deopt\n");
}
switch (mode) {
case BuiltinContinuationMode::STUB:
UNREACHABLE();
case BuiltinContinuationMode::JAVASCRIPT:
break;
case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH: {
frame_writer.PushRawObject(roots.the_hole_value(),
"placeholder for exception on lazy deopt\n");
} break;
case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION: {
intptr_t accumulator_value =
input_->GetRegister(kInterpreterAccumulatorRegister.code());
frame_writer.PushRawObject(Object(accumulator_value),
"exception (from accumulator)\n");
} break;
}
frame_writer.PushStackJSArguments(
value_iterator, frame_info.translated_stack_parameter_count());
}
#else
for (uint32_t i = 0; i < frame_info.translated_stack_parameter_count();
++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
......@@ -1621,6 +1664,7 @@ void Deoptimizer::DoComputeBuiltinContinuation(
frame_writer.PushRawObject(roots.the_hole_value(),
"placeholder for return result on lazy deopt\n");
}
#endif
DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
frame_writer.top_offset());
......@@ -2959,10 +3003,23 @@ void TranslatedState::CreateArgumentsElementsTranslatedValues(
for (int i = 0; i < number_of_holes; ++i) {
frame.Add(TranslatedValue::NewTagged(this, roots.the_hole_value()));
}
for (int i = length - number_of_holes - 1; i >= 0; --i) {
int argc = length - number_of_holes;
#ifdef V8_REVERSE_JSARGS
int start_index = number_of_holes;
if (type == CreateArgumentsType::kRestParameter) {
start_index = std::max(0, formal_parameter_count_);
}
#endif
for (int i = 0; i < argc; i++) {
// Skip the receiver.
#ifdef V8_REVERSE_JSARGS
int offset = i + start_index + 1;
#else
int offset = argc - i - 1;
#endif
Address argument_slot = arguments_frame +
CommonFrameConstants::kFixedFrameSizeAboveFp +
i * kSystemPointerSize;
offset * kSystemPointerSize;
frame.Add(TranslatedValue::NewTagged(this, *FullObjectSlot(argument_slot)));
}
}
......
......@@ -1319,9 +1319,16 @@ Object JavaScriptBuiltinContinuationFrame::context() const {
void JavaScriptBuiltinContinuationWithCatchFrame::SetException(
Object exception) {
#ifdef V8_REVERSE_JSARGS
int argc = ComputeParametersCount();
Address exception_argument_slot =
fp() + BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp +
(argc - 1) * kSystemPointerSize;
#else
Address exception_argument_slot =
fp() + BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp +
kSystemPointerSize; // Skip over return value slot.
#endif
// Only allow setting exception if previous value was the hole.
CHECK_EQ(ReadOnlyRoots(isolate()).the_hole_value(),
......
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