summaryrefslogtreecommitdiff
path: root/chromium/v8/src/deoptimizer/deoptimizer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/deoptimizer/deoptimizer.cc')
-rw-r--r--chromium/v8/src/deoptimizer/deoptimizer.cc417
1 files changed, 175 insertions, 242 deletions
diff --git a/chromium/v8/src/deoptimizer/deoptimizer.cc b/chromium/v8/src/deoptimizer/deoptimizer.cc
index 47c40d373eb..64551c68996 100644
--- a/chromium/v8/src/deoptimizer/deoptimizer.cc
+++ b/chromium/v8/src/deoptimizer/deoptimizer.cc
@@ -452,6 +452,15 @@ const char* Deoptimizer::MessageFor(DeoptimizeKind kind) {
return nullptr;
}
+namespace {
+
+uint16_t InternalFormalParameterCountWithReceiver(SharedFunctionInfo sfi) {
+ static constexpr int kTheReceiver = 1;
+ return sfi.internal_formal_parameter_count() + kTheReceiver;
+}
+
+} // namespace
+
Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction function,
DeoptimizeKind kind, unsigned bailout_id, Address from,
int fp_to_sp_delta)
@@ -503,8 +512,22 @@ Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction function,
CodeDeoptEvent(compiled_code_, kind, from_, fp_to_sp_delta_));
}
unsigned size = ComputeInputFrameSize();
- int parameter_count = function.shared().internal_formal_parameter_count() + 1;
+ const int parameter_count =
+ InternalFormalParameterCountWithReceiver(function.shared());
input_ = new (size) FrameDescription(size, parameter_count);
+
+ if (kSupportsFixedDeoptExitSize) {
+ DCHECK_EQ(bailout_id_, kMaxUInt32);
+ // Calculate bailout id from return address.
+ DCHECK_GT(kDeoptExitSize, 0);
+ DeoptimizationData deopt_data =
+ DeoptimizationData::cast(compiled_code_.deoptimization_data());
+ Address deopt_start = compiled_code_.raw_instruction_start() +
+ deopt_data.DeoptExitStart().value();
+ int offset = static_cast<int>(from_ - kDeoptExitSize - deopt_start);
+ DCHECK_EQ(0, offset % kDeoptExitSize);
+ bailout_id_ = offset / kDeoptExitSize;
+ }
}
Code Deoptimizer::FindOptimizedCode() {
@@ -624,10 +647,6 @@ int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
return -1;
}
-bool ShouldPadArguments(int arg_count) {
- return kPadArguments && (arg_count % 2 != 0);
-}
-
} // namespace
// We rely on this function not causing a GC. It is called from generated code
@@ -787,45 +806,33 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
SharedFunctionInfo shared = translated_frame->raw_shared_info();
TranslatedFrame::iterator value_iterator = translated_frame->begin();
- bool is_bottommost = (0 == frame_index);
- bool is_topmost = (output_count_ - 1 == frame_index);
+ const bool is_bottommost = (0 == frame_index);
+ const bool is_topmost = (output_count_ - 1 == frame_index);
- int bytecode_offset = translated_frame->node_id().ToInt();
- int height = translated_frame->height();
- int register_count = height - 1; // Exclude accumulator.
- int register_stack_slot_count =
- InterpreterFrameConstants::RegisterStackSlotCount(register_count);
- int height_in_bytes = register_stack_slot_count * kSystemPointerSize;
+ const int real_bytecode_offset = translated_frame->node_id().ToInt();
+ const int bytecode_offset =
+ goto_catch_handler ? catch_handler_pc_offset_ : real_bytecode_offset;
- // The topmost frame will contain the accumulator.
- if (is_topmost) {
- height_in_bytes += kSystemPointerSize;
- if (PadTopOfStackRegister()) height_in_bytes += kSystemPointerSize;
- }
+ const int parameters_count = InternalFormalParameterCountWithReceiver(shared);
+ const int locals_count = translated_frame->height();
+ InterpretedFrameInfo frame_info =
+ InterpretedFrameInfo::Precise(parameters_count, locals_count, is_topmost);
+ const uint32_t output_frame_size = frame_info.frame_size_in_bytes();
TranslatedFrame::iterator function_iterator = value_iterator++;
if (trace_scope_ != nullptr) {
PrintF(trace_scope_->file(), " translating interpreted frame ");
std::unique_ptr<char[]> name = shared.DebugName().ToCString();
PrintF(trace_scope_->file(), "%s", name.get());
- PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
- bytecode_offset, height_in_bytes,
- goto_catch_handler ? " (throw)" : "");
- }
- if (goto_catch_handler) {
- bytecode_offset = catch_handler_pc_offset_;
+ PrintF(trace_scope_->file(),
+ " => bytecode_offset=%d, variable_frame_size=%d, frame_size=%d%s\n",
+ real_bytecode_offset, frame_info.frame_size_in_bytes_without_fixed(),
+ output_frame_size, goto_catch_handler ? " (throw)" : "");
}
- // The 'fixed' part of the frame consists of the incoming parameters and
- // the part described by InterpreterFrameConstants. This will include
- // argument padding, when needed.
- unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
- unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
// Allocate and store the output frame description.
- int parameter_count = shared.internal_formal_parameter_count() + 1;
FrameDescription* output_frame = new (output_frame_size)
- FrameDescription(output_frame_size, parameter_count);
+ FrameDescription(output_frame_size, parameters_count);
FrameWriter frame_writer(this, output_frame, trace_scope_);
CHECK(frame_index >= 0 && frame_index < output_count_);
@@ -834,22 +841,19 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
// The top address of the frame is computed from the previous frame's top and
// this frame's size.
- intptr_t top_address;
- if (is_bottommost) {
- top_address = caller_frame_top_ - output_frame_size;
- } else {
- top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
- }
+ const intptr_t top_address =
+ is_bottommost ? caller_frame_top_ - output_frame_size
+ : output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
ReadOnlyRoots roots(isolate());
- if (ShouldPadArguments(parameter_count)) {
+ if (ShouldPadArguments(parameters_count)) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
- for (int i = 0; i < parameter_count; ++i, ++value_iterator) {
+ for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
@@ -880,7 +884,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
frame_writer.PushCallerFp(caller_fp);
- intptr_t fp_value = top_address + frame_writer.top_offset();
+ const intptr_t fp_value = top_address + frame_writer.top_offset();
output_frame->SetFp(fp_value);
if (is_topmost) {
Register fp_reg = InterpretedFrame::fp_register();
@@ -926,7 +930,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
frame_writer.PushRawObject(bytecode_array, "bytecode array\n");
// The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
- int raw_bytecode_offset =
+ const int raw_bytecode_offset =
BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
Smi smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
frame_writer.PushRawObject(smi_bytecode_offset, "bytecode offset\n");
@@ -938,16 +942,16 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
// Translate the rest of the interpreter registers in the frame.
// The return_value_offset is counted from the top. Here, we compute the
// register index (counted from the start).
- int return_value_first_reg =
- register_count - translated_frame->return_value_offset();
- int return_value_count = translated_frame->return_value_count();
- for (int i = 0; i < register_count; ++i, ++value_iterator) {
+ const int return_value_first_reg =
+ locals_count - translated_frame->return_value_offset();
+ const int return_value_count = translated_frame->return_value_count();
+ for (int i = 0; i < locals_count; ++i, ++value_iterator) {
// Ensure we write the return value if we have one and we are returning
// normally to a lazy deopt point.
if (is_topmost && !goto_catch_handler &&
deopt_kind_ == DeoptimizeKind::kLazy && i >= return_value_first_reg &&
i < return_value_first_reg + return_value_count) {
- int return_index = i - return_value_first_reg;
+ const int return_index = i - return_value_first_reg;
if (return_index == 0) {
frame_writer.PushRawValue(input_->GetRegister(kReturnRegister0.code()),
"return value 0\n");
@@ -955,7 +959,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
// the accumulator and another one into an ordinary register. Since
// the interpreter should never create such situation, just assert
// this does not happen.
- CHECK_LE(return_value_first_reg + return_value_count, register_count);
+ CHECK_LE(return_value_first_reg + return_value_count, locals_count);
} else {
CHECK_EQ(return_index, 1);
frame_writer.PushRawValue(input_->GetRegister(kReturnRegister1.code()),
@@ -967,18 +971,18 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
}
}
- int register_slots_written = register_count;
- DCHECK_LE(register_slots_written, register_stack_slot_count);
+ uint32_t register_slots_written = static_cast<uint32_t>(locals_count);
+ DCHECK_LE(register_slots_written, frame_info.register_stack_slot_count());
// Some architectures must pad the stack frame with extra stack slots
// to ensure the stack frame is aligned. Do this now.
- while (register_slots_written < register_stack_slot_count) {
+ while (register_slots_written < frame_info.register_stack_slot_count()) {
register_slots_written++;
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
// Translate the accumulator register (depending on frame position).
if (is_topmost) {
- if (PadTopOfStackRegister()) {
+ if (kPadArguments) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
// For topmost frame, put the accumulator on the stack. The
@@ -1054,26 +1058,24 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
void Deoptimizer::DoComputeArgumentsAdaptorFrame(
TranslatedFrame* translated_frame, int frame_index) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
- bool is_bottommost = (0 == frame_index);
+ const bool is_bottommost = (0 == frame_index);
- unsigned height = translated_frame->height();
- unsigned height_in_bytes = height * kSystemPointerSize;
- int parameter_count = height;
- if (ShouldPadArguments(parameter_count))
- height_in_bytes += kSystemPointerSize;
+ const int parameters_count = translated_frame->height();
+ ArgumentsAdaptorFrameInfo frame_info =
+ ArgumentsAdaptorFrameInfo::Precise(parameters_count);
+ const uint32_t output_frame_size = frame_info.frame_size_in_bytes();
TranslatedFrame::iterator function_iterator = value_iterator++;
if (trace_scope_ != nullptr) {
PrintF(trace_scope_->file(),
- " translating arguments adaptor => height=%d\n", height_in_bytes);
+ " translating arguments adaptor => variable_frame_size=%d, "
+ "frame_size=%d\n",
+ frame_info.frame_size_in_bytes_without_fixed(), output_frame_size);
}
- unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
- unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
// Allocate and store the output frame description.
FrameDescription* output_frame = new (output_frame_size)
- FrameDescription(output_frame_size, parameter_count);
+ FrameDescription(output_frame_size, parameters_count);
FrameWriter frame_writer(this, output_frame, trace_scope_);
// Arguments adaptor can not be topmost.
@@ -1083,21 +1085,18 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(
// The top address of the frame is computed from the previous frame's top and
// this frame's size.
- intptr_t top_address;
- if (is_bottommost) {
- top_address = caller_frame_top_ - output_frame_size;
- } else {
- top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
- }
+ const intptr_t top_address =
+ is_bottommost ? caller_frame_top_ - output_frame_size
+ : output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
ReadOnlyRoots roots(isolate());
- if (ShouldPadArguments(parameter_count)) {
+ if (ShouldPadArguments(parameters_count)) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
// Compute the incoming parameter translation.
- for (int i = 0; i < parameter_count; ++i, ++value_iterator) {
+ for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
@@ -1133,7 +1132,9 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(
frame_writer.PushTranslatedValue(function_iterator, "function\n");
// Number of incoming arguments.
- frame_writer.PushRawObject(Smi::FromInt(height - 1), "argc\n");
+ const uint32_t parameters_count_without_receiver = parameters_count - 1;
+ frame_writer.PushRawObject(Smi::FromInt(parameters_count_without_receiver),
+ "argc\n");
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
@@ -1157,7 +1158,7 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(
void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
int frame_index) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
- bool is_topmost = (output_count_ - 1 == frame_index);
+ const bool is_topmost = (output_count_ - 1 == frame_index);
// The construct frame could become topmost only if we inlined a constructor
// call which does a tail call (otherwise the tail callee's frame would be
// the topmost one). So it could only be the DeoptimizeKind::kLazy case.
@@ -1166,38 +1167,25 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
Builtins* builtins = isolate_->builtins();
Code construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
BailoutId bailout_id = translated_frame->node_id();
- unsigned height = translated_frame->height();
- unsigned parameter_count = height - 1; // Exclude the context.
- unsigned height_in_bytes = parameter_count * kSystemPointerSize;
-
- // If the construct frame appears to be topmost we should ensure that the
- // value of result register is preserved during continuation execution.
- // We do this here by "pushing" the result of the constructor function to the
- // top of the reconstructed stack and popping it in
- // {Builtins::kNotifyDeoptimized}.
- if (is_topmost) {
- height_in_bytes += kSystemPointerSize;
- if (PadTopOfStackRegister()) height_in_bytes += kSystemPointerSize;
- }
- if (ShouldPadArguments(parameter_count))
- height_in_bytes += kSystemPointerSize;
+ const int parameters_count = translated_frame->height();
+ ConstructStubFrameInfo frame_info =
+ ConstructStubFrameInfo::Precise(parameters_count, is_topmost);
+ const uint32_t output_frame_size = frame_info.frame_size_in_bytes();
TranslatedFrame::iterator function_iterator = value_iterator++;
if (trace_scope_ != nullptr) {
PrintF(trace_scope_->file(),
- " translating construct stub => bailout_id=%d (%s), height=%d\n",
+ " translating construct stub => bailout_id=%d (%s), "
+ "variable_frame_size=%d, frame_size=%d\n",
bailout_id.ToInt(),
bailout_id == BailoutId::ConstructStubCreate() ? "create" : "invoke",
- height_in_bytes);
+ frame_info.frame_size_in_bytes_without_fixed(), output_frame_size);
}
- unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
- unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
// Allocate and store the output frame description.
FrameDescription* output_frame = new (output_frame_size)
- FrameDescription(output_frame_size, parameter_count);
+ FrameDescription(output_frame_size, parameters_count);
FrameWriter frame_writer(this, output_frame, trace_scope_);
// Construct stub can not be topmost.
@@ -1207,12 +1195,12 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
// The top address of the frame is computed from the previous frame's top and
// this frame's size.
- intptr_t top_address;
- top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+ const intptr_t top_address =
+ output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
ReadOnlyRoots roots(isolate());
- if (ShouldPadArguments(parameter_count)) {
+ if (ShouldPadArguments(parameters_count)) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
@@ -1222,7 +1210,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
TranslatedFrame::iterator receiver_iterator = value_iterator;
// Compute the incoming parameter translation.
- for (unsigned i = 0; i < parameter_count; ++i, ++value_iterator) {
+ for (int i = 0; i < parameters_count; ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
@@ -1237,7 +1225,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
const intptr_t caller_fp = output_[frame_index - 1]->GetFp();
frame_writer.PushCallerFp(caller_fp);
- intptr_t fp_value = top_address + frame_writer.top_offset();
+ const intptr_t fp_value = top_address + frame_writer.top_offset();
output_frame->SetFp(fp_value);
if (is_topmost) {
Register fp_reg = JavaScriptFrame::fp_register();
@@ -1257,7 +1245,9 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
frame_writer.PushTranslatedValue(value_iterator++, "context");
// Number of incoming arguments.
- frame_writer.PushRawObject(Smi::FromInt(parameter_count - 1), "argc\n");
+ const uint32_t parameters_count_without_receiver = parameters_count - 1;
+ frame_writer.PushRawObject(Smi::FromInt(parameters_count_without_receiver),
+ "argc\n");
// The constructor function was mentioned explicitly in the
// CONSTRUCT_STUB_FRAME.
@@ -1277,7 +1267,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
frame_writer.PushTranslatedValue(receiver_iterator, debug_hint);
if (is_topmost) {
- if (PadTopOfStackRegister()) {
+ if (kPadArguments) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
// Ensure the result is restored back when we return to the stub.
@@ -1292,7 +1282,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
// Compute this frame's PC.
DCHECK(bailout_id.IsValidForConstructStub());
Address start = construct_stub.InstructionStart();
- int pc_offset =
+ const int pc_offset =
bailout_id == BailoutId::ConstructStubCreate()
? isolate_->heap()->construct_stub_create_deopt_pc_offset().value()
: isolate_->heap()->construct_stub_invoke_deopt_pc_offset().value();
@@ -1330,8 +1320,9 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
}
}
-bool Deoptimizer::BuiltinContinuationModeIsJavaScript(
- BuiltinContinuationMode mode) {
+namespace {
+
+bool BuiltinContinuationModeIsJavaScript(BuiltinContinuationMode mode) {
switch (mode) {
case BuiltinContinuationMode::STUB:
return false;
@@ -1343,31 +1334,16 @@ bool Deoptimizer::BuiltinContinuationModeIsJavaScript(
UNREACHABLE();
}
-bool Deoptimizer::BuiltinContinuationModeIsWithCatch(
+StackFrame::Type BuiltinContinuationModeToFrameType(
BuiltinContinuationMode mode) {
switch (mode) {
case BuiltinContinuationMode::STUB:
- case BuiltinContinuationMode::JAVASCRIPT:
- return false;
- case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
- case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
- return true;
- }
- UNREACHABLE();
-}
-
-namespace {
-
-StackFrame::Type BuiltinContinuationModeToFrameType(
- Deoptimizer::BuiltinContinuationMode mode) {
- switch (mode) {
- case Deoptimizer::BuiltinContinuationMode::STUB:
return StackFrame::BUILTIN_CONTINUATION;
- case Deoptimizer::BuiltinContinuationMode::JAVASCRIPT:
+ case BuiltinContinuationMode::JAVASCRIPT:
return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION;
- case Deoptimizer::BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
+ case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
- case Deoptimizer::BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
+ case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
}
UNREACHABLE();
@@ -1454,65 +1430,31 @@ void Deoptimizer::DoComputeBuiltinContinuation(
BuiltinContinuationMode mode) {
TranslatedFrame::iterator value_iterator = translated_frame->begin();
- // The output frame must have room for all of the parameters that need to be
- // passed to the builtin continuation.
- const int height_in_words = translated_frame->height();
-
- BailoutId bailout_id = translated_frame->node_id();
+ const BailoutId bailout_id = translated_frame->node_id();
Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
- Code builtin = isolate()->builtins()->builtin(builtin_name);
- Callable continuation_callable =
- Builtins::CallableFor(isolate(), builtin_name);
CallInterfaceDescriptor continuation_descriptor =
- continuation_callable.descriptor();
+ Builtins::CallInterfaceDescriptorFor(builtin_name);
+
+ const RegisterConfiguration* config = RegisterConfiguration::Default();
const bool is_bottommost = (0 == frame_index);
const bool is_topmost = (output_count_ - 1 == frame_index);
- const bool must_handle_result =
- !is_topmost || deopt_kind_ == DeoptimizeKind::kLazy;
- const RegisterConfiguration* config(RegisterConfiguration::Default());
- const int allocatable_register_count =
- config->num_allocatable_general_registers();
- const int padding_slot_count =
- BuiltinContinuationFrameConstants::PaddingSlotCount(
- allocatable_register_count);
-
- const int register_parameter_count =
- continuation_descriptor.GetRegisterParameterCount();
- // Make sure to account for the context by removing it from the register
- // parameter count.
- const int translated_stack_parameters =
- height_in_words - register_parameter_count - 1;
- const int stack_param_count =
- translated_stack_parameters + (must_handle_result ? 1 : 0) +
- (BuiltinContinuationModeIsWithCatch(mode) ? 1 : 0);
- const int stack_param_pad_count =
- ShouldPadArguments(stack_param_count) ? 1 : 0;
-
- // If the builtins frame appears to be topmost we should ensure that the
- // value of result register is preserved during continuation execution.
- // We do this here by "pushing" the result of callback function to the
- // top of the reconstructed stack and popping it in
- // {Builtins::kNotifyDeoptimized}.
- const int push_result_count =
- is_topmost ? (PadTopOfStackRegister() ? 2 : 1) : 0;
-
- const unsigned output_frame_size =
- kSystemPointerSize * (stack_param_count + stack_param_pad_count +
- allocatable_register_count + padding_slot_count +
- push_result_count) +
- BuiltinContinuationFrameConstants::kFixedFrameSize;
+ const int parameters_count = translated_frame->height();
+ BuiltinContinuationFrameInfo frame_info =
+ BuiltinContinuationFrameInfo::Precise(parameters_count,
+ continuation_descriptor, config,
+ is_topmost, deopt_kind_, mode);
+ const unsigned output_frame_size = frame_info.frame_size_in_bytes();
const unsigned output_frame_size_above_fp =
- kSystemPointerSize * (allocatable_register_count + padding_slot_count +
- push_result_count) +
- (BuiltinContinuationFrameConstants::kFixedFrameSize -
- BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp);
+ frame_info.frame_size_in_bytes_above_fp();
// Validate types of parameters. They must all be tagged except for argc for
// JS builtins.
bool has_argc = false;
+ const int register_parameter_count =
+ continuation_descriptor.GetRegisterParameterCount();
for (int i = 0; i < register_parameter_count; ++i) {
MachineType type = continuation_descriptor.GetParameterType(i);
int code = continuation_descriptor.GetRegisterParameter(i).code();
@@ -1531,25 +1473,22 @@ void Deoptimizer::DoComputeBuiltinContinuation(
if (trace_scope_ != nullptr) {
PrintF(trace_scope_->file(),
" translating BuiltinContinuation to %s,"
- " register param count %d,"
- " stack param count %d\n",
+ " => register_param_count=%d,"
+ " stack_param_count=%d, frame_size=%d\n",
Builtins::name(builtin_name), register_parameter_count,
- stack_param_count);
+ frame_info.stack_parameter_count(), output_frame_size);
}
FrameDescription* output_frame = new (output_frame_size)
- FrameDescription(output_frame_size, stack_param_count);
+ FrameDescription(output_frame_size, frame_info.stack_parameter_count());
output_[frame_index] = output_frame;
FrameWriter frame_writer(this, output_frame, trace_scope_);
// The top address of the frame is computed from the previous frame's top and
// this frame's size.
- intptr_t top_address;
- if (is_bottommost) {
- top_address = caller_frame_top_ - output_frame_size;
- } else {
- top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
- }
+ const intptr_t top_address =
+ is_bottommost ? caller_frame_top_ - output_frame_size
+ : output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Get the possible JSFunction for the case that this is a
@@ -1559,11 +1498,12 @@ void Deoptimizer::DoComputeBuiltinContinuation(
++value_iterator;
ReadOnlyRoots roots(isolate());
- if (ShouldPadArguments(stack_param_count)) {
+ if (ShouldPadArguments(frame_info.stack_parameter_count())) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
- for (int i = 0; i < translated_stack_parameters; ++i, ++value_iterator) {
+ for (uint32_t i = 0; i < frame_info.translated_stack_parameter_count();
+ ++i, ++value_iterator) {
frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
}
@@ -1584,7 +1524,7 @@ void Deoptimizer::DoComputeBuiltinContinuation(
} break;
}
- if (must_handle_result) {
+ if (frame_info.frame_has_result_stack_slot()) {
frame_writer.PushRawObject(roots.the_hole_value(),
"placeholder for return result on lazy deopt\n");
}
@@ -1659,9 +1599,10 @@ void Deoptimizer::DoComputeBuiltinContinuation(
"builtin JavaScript context\n");
// The builtin to continue to.
- frame_writer.PushRawObject(Smi::FromInt(builtin.builtin_index()),
- "builtin index\n");
+ frame_writer.PushRawObject(Smi::FromInt(builtin_name), "builtin index\n");
+ const int allocatable_register_count =
+ config->num_allocatable_general_registers();
for (int i = 0; i < allocatable_register_count; ++i) {
int code = config->GetAllocatableGeneralCode(i);
ScopedVector<char> str(128);
@@ -1683,17 +1624,20 @@ void Deoptimizer::DoComputeBuiltinContinuation(
// Some architectures must pad the stack frame with extra stack slots
// to ensure the stack frame is aligned.
+ const int padding_slot_count =
+ BuiltinContinuationFrameConstants::PaddingSlotCount(
+ allocatable_register_count);
for (int i = 0; i < padding_slot_count; ++i) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
if (is_topmost) {
- if (PadTopOfStackRegister()) {
+ if (kPadArguments) {
frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
}
- // Ensure the result is restored back when we return to the stub.
- if (must_handle_result) {
+ // Ensure the result is restored back when we return to the stub.
+ if (frame_info.frame_has_result_stack_slot()) {
Register result_reg = kReturnRegister0;
frame_writer.PushRawValue(input_->GetRegister(result_reg.code()),
"callback result\n");
@@ -1719,8 +1663,9 @@ void Deoptimizer::DoComputeBuiltinContinuation(
Register fp_reg = JavaScriptFrame::fp_register();
output_frame->SetRegister(fp_reg.code(), fp_value);
- Code continue_to_builtin = isolate()->builtins()->builtin(
- TrampolineForBuiltinContinuation(mode, must_handle_result));
+ Code continue_to_builtin =
+ isolate()->builtins()->builtin(TrampolineForBuiltinContinuation(
+ mode, frame_info.frame_has_result_stack_slot()));
output_frame->SetPc(
static_cast<intptr_t>(continue_to_builtin.InstructionStart()));
@@ -1801,17 +1746,9 @@ unsigned Deoptimizer::ComputeInputFrameSize() const {
}
// static
-unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo shared) {
- // The fixed part of the frame consists of the return address, frame
- // pointer, function, context, bytecode offset and all the incoming arguments.
- return ComputeIncomingArgumentSize(shared) +
- InterpreterFrameConstants::kFixedFrameSize;
-}
-
-// static
unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo shared) {
- int parameter_slots = shared.internal_formal_parameter_count() + 1;
- if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
+ int parameter_slots = InternalFormalParameterCountWithReceiver(shared);
+ if (ShouldPadArguments(parameter_slots)) parameter_slots++;
return parameter_slots * kSystemPointerSize;
}
@@ -2254,12 +2191,9 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
stack_it++;
// Get the expression stack.
- int stack_height = frame_it->height();
- if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
- // For interpreter frames, we should not count the accumulator.
- // TODO(jarin): Clean up the indexing in translated frames.
- stack_height--;
- }
+ DCHECK_EQ(TranslatedFrame::kInterpretedFunction, frame_it->kind());
+ const int stack_height = frame_it->height(); // Accumulator *not* included.
+
expression_stack_.resize(static_cast<size_t>(stack_height));
for (int i = 0; i < stack_height; i++) {
Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
@@ -2267,10 +2201,9 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
stack_it++;
}
- // For interpreter frame, skip the accumulator.
- if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
- stack_it++;
- }
+ DCHECK_EQ(TranslatedFrame::kInterpretedFunction, frame_it->kind());
+ stack_it++; // Skip the accumulator.
+
CHECK(stack_it == frame_it->end());
}
@@ -2688,20 +2621,30 @@ TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
}
int TranslatedFrame::GetValueCount() {
+ // The function is added to all frame state descriptors in
+ // InstructionSelector::AddInputsToFrameStateDescriptor.
+ static constexpr int kTheFunction = 1;
+
switch (kind()) {
case kInterpretedFunction: {
int parameter_count =
- raw_shared_info_.internal_formal_parameter_count() + 1;
- // + 2 for function and context.
- return height_ + parameter_count + 2;
+ InternalFormalParameterCountWithReceiver(raw_shared_info_);
+ static constexpr int kTheContext = 1;
+ static constexpr int kTheAccumulator = 1;
+ return height() + parameter_count + kTheContext + kTheFunction +
+ kTheAccumulator;
}
case kArgumentsAdaptor:
+ return height() + kTheFunction;
+
case kConstructStub:
case kBuiltinContinuation:
case kJavaScriptBuiltinContinuation:
- case kJavaScriptBuiltinContinuationWithCatch:
- return 1 + height_;
+ case kJavaScriptBuiltinContinuationWithCatch: {
+ static constexpr int kTheContext = 1;
+ return height() + kTheContext + kTheFunction;
+ }
case kInvalid:
UNREACHABLE();
@@ -2736,7 +2679,7 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
if (trace_file != nullptr) {
std::unique_ptr<char[]> name = shared_info.DebugName().ToCString();
PrintF(trace_file, " reading input frame %s", name.get());
- int arg_count = shared_info.internal_formal_parameter_count() + 1;
+ int arg_count = InternalFormalParameterCountWithReceiver(shared_info);
PrintF(trace_file,
" => bytecode_offset=%d, args=%d, height=%d, retval=%i(#%i); "
"inputs:\n",
@@ -2787,11 +2730,8 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
bailout_id.ToInt(), height);
}
- // Add one to the height to account for the context which was implicitly
- // added to the translation during code generation.
- int height_with_context = height + 1;
return TranslatedFrame::BuiltinContinuationFrame(bailout_id, shared_info,
- height_with_context);
+ height);
}
case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME: {
@@ -2806,11 +2746,8 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
bailout_id.ToInt(), height);
}
- // Add one to the height to account for the context which was implicitly
- // added to the translation during code generation.
- int height_with_context = height + 1;
return TranslatedFrame::JavaScriptBuiltinContinuationFrame(
- bailout_id, shared_info, height_with_context);
+ bailout_id, shared_info, height);
}
case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
BailoutId bailout_id = BailoutId(iterator->Next());
@@ -2825,11 +2762,8 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
bailout_id.ToInt(), height);
}
- // Add one to the height to account for the context which was implicitly
- // added to the translation during code generation.
- int height_with_context = height + 1;
return TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
- bailout_id, shared_info, height_with_context);
+ bailout_id, shared_info, height);
}
case Translation::UPDATE_FEEDBACK:
case Translation::BEGIN:
@@ -3450,7 +3384,7 @@ void TranslatedState::InitializeCapturedObjectAt(
// Handle the special cases.
switch (map->instance_type()) {
- case MUTABLE_HEAP_NUMBER_TYPE:
+ case HEAP_NUMBER_TYPE:
case FIXED_DOUBLE_ARRAY_TYPE:
return;
@@ -3528,15 +3462,14 @@ void TranslatedState::MaterializeFixedDoubleArray(TranslatedFrame* frame,
slot->set_storage(array);
}
-void TranslatedState::MaterializeMutableHeapNumber(TranslatedFrame* frame,
- int* value_index,
- TranslatedValue* slot) {
+void TranslatedState::MaterializeHeapNumber(TranslatedFrame* frame,
+ int* value_index,
+ TranslatedValue* slot) {
CHECK_NE(TranslatedValue::kCapturedObject,
frame->values_[*value_index].kind());
Handle<Object> value = frame->values_[*value_index].GetValue();
CHECK(value->IsNumber());
- Handle<MutableHeapNumber> box =
- isolate()->factory()->NewMutableHeapNumber(value->Number());
+ Handle<HeapNumber> box = isolate()->factory()->NewHeapNumber(value->Number());
(*value_index)++;
slot->set_storage(box);
}
@@ -3592,10 +3525,10 @@ void TranslatedState::EnsureCapturedObjectAllocatedAt(
// there is no need to process the children.
return MaterializeFixedDoubleArray(frame, &value_index, slot, map);
- case MUTABLE_HEAP_NUMBER_TYPE:
+ case HEAP_NUMBER_TYPE:
// Materialize (i.e. allocate&initialize) the heap number and return.
// There is no need to process the children.
- return MaterializeMutableHeapNumber(frame, &value_index, slot);
+ return MaterializeHeapNumber(frame, &value_index, slot);
case FIXED_ARRAY_TYPE:
case SCRIPT_CONTEXT_TABLE_TYPE:
@@ -3813,7 +3746,7 @@ void TranslatedState::InitializeJSObjectAt(
}
object_storage->WriteField<double>(offset, double_field_value);
} else if (marker == kStoreMutableHeapNumber) {
- CHECK(field_value->IsMutableHeapNumber());
+ CHECK(field_value->IsHeapNumber());
WRITE_FIELD(*object_storage, offset, *field_value);
WRITE_BARRIER(*object_storage, offset, *field_value);
} else {
@@ -3848,10 +3781,9 @@ void TranslatedState::InitializeObjectWithTaggedFieldsAt(
int offset = i * kTaggedSize;
uint8_t marker = object_storage->ReadField<uint8_t>(offset);
if (i > 1 && marker == kStoreMutableHeapNumber) {
- CHECK(field_value->IsMutableHeapNumber());
+ CHECK(field_value->IsHeapNumber());
} else {
CHECK(marker == kStoreTagged || i == 1);
- CHECK(!field_value->IsMutableHeapNumber());
}
WRITE_FIELD(*object_storage, offset, *field_value);
@@ -3918,15 +3850,16 @@ TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
// to last value in the TranslatedFrame. It should also always be
// {1}, as the GenericLazyDeoptContinuation builtin only has one
// argument (the receiver).
- const int height = frames_[i].height();
+ static constexpr int kTheContext = 1;
+ const int height = frames_[i].height() + kTheContext;
Object argc_object = frames_[i].ValueAt(height - 1)->GetRawValue();
CHECK(argc_object.IsSmi());
*args_count = Smi::ToInt(argc_object);
DCHECK_EQ(*args_count, 1);
} else {
- *args_count =
- frames_[i].shared_info()->internal_formal_parameter_count() + 1;
+ *args_count = InternalFormalParameterCountWithReceiver(
+ *frames_[i].shared_info());
}
return &(frames_[i]);
}