[deoptimizer] Change layout of builtin continuation frames
Builtin continuation frames know their height now. This is prework to allow UnwindAndFindHandler to reconstructor the stack pointer for the ContinueToBuiltin trampoline. Bug: v8:7584 Change-Id: If1361f5bbac130c284cd46c0d39cc81e2df613d3 Reviewed-on: https://chromium-review.googlesource.com/983633 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#52322}
This commit is contained in:
parent
4b09b0d557
commit
122ece2d70
@ -1370,16 +1370,20 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
|
|||||||
// | ... |
|
// | ... |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | builtin param m |<- FrameState input value n+m-1, or in
|
// | builtin param m |<- FrameState input value n+m-1, or in
|
||||||
// +-------------------------+ the LAZY case, return LAZY result value
|
// +-----needs-alignment-----+ the LAZY case, return LAZY result value
|
||||||
// | ContinueToBuiltin entry |
|
// | ContinueToBuiltin entry |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | | saved frame (FP) |
|
// | | saved frame (FP) |
|
||||||
// | +=========================+<- fpreg
|
// | +=====needs=alignment=====+<- fpreg
|
||||||
// | |constant pool (if ool_cp)|
|
// | |constant pool (if ool_cp)|
|
||||||
// v +-------------------------+
|
// v +-------------------------+
|
||||||
// |BUILTIN_CONTINUATION mark|
|
// |BUILTIN_CONTINUATION mark|
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | JS Builtin code object |
|
// | JSFunction (or zero) |<- only if JavaScript builtin
|
||||||
|
// +-------------------------+
|
||||||
|
// | frame height above FP |
|
||||||
|
// +-------------------------+
|
||||||
|
// | builtin address |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | builtin input GPR reg0 |<- populated from deopt FrameState using
|
// | builtin input GPR reg0 |<- populated from deopt FrameState using
|
||||||
// +-------------------------+ the builtin's CallInterfaceDescriptor
|
// +-------------------------+ the builtin's CallInterfaceDescriptor
|
||||||
@ -1388,11 +1392,11 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
|
|||||||
// | builtin input GPR regn |
|
// | builtin input GPR regn |
|
||||||
// +-------------------------+
|
// +-------------------------+
|
||||||
// | reg padding (arch dept) |
|
// | reg padding (arch dept) |
|
||||||
// +-------------------------+
|
// +-----needs--alignment----+
|
||||||
// | res padding (arch dept) |<- only if {is_topmost}; result is pop'd by
|
// | res padding (arch dept) |<- only if {is_topmost}; result is pop'd by
|
||||||
// +-------------------------+<- kNotifyDeopt ASM stub and moved to acc
|
// +-------------------------+<- kNotifyDeopt ASM stub and moved to acc
|
||||||
// | result value |<- reg, as ContinueToBuiltin stub expects.
|
// | result value |<- reg, as ContinueToBuiltin stub expects.
|
||||||
// +-------------------------+<- spreg
|
// +-----needs-alignment-----+<- spreg
|
||||||
//
|
//
|
||||||
void Deoptimizer::DoComputeBuiltinContinuation(
|
void Deoptimizer::DoComputeBuiltinContinuation(
|
||||||
TranslatedFrame* translated_frame, int frame_index,
|
TranslatedFrame* translated_frame, int frame_index,
|
||||||
@ -1402,7 +1406,7 @@ void Deoptimizer::DoComputeBuiltinContinuation(
|
|||||||
|
|
||||||
// The output frame must have room for all of the parameters that need to be
|
// The output frame must have room for all of the parameters that need to be
|
||||||
// passed to the builtin continuation.
|
// passed to the builtin continuation.
|
||||||
int height_in_words = translated_frame->height();
|
const int height_in_words = translated_frame->height();
|
||||||
|
|
||||||
BailoutId bailout_id = translated_frame->node_id();
|
BailoutId bailout_id = translated_frame->node_id();
|
||||||
Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
|
Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
|
||||||
@ -1413,35 +1417,47 @@ void Deoptimizer::DoComputeBuiltinContinuation(
|
|||||||
CallInterfaceDescriptor continuation_descriptor =
|
CallInterfaceDescriptor continuation_descriptor =
|
||||||
continuation_callable.descriptor();
|
continuation_callable.descriptor();
|
||||||
|
|
||||||
bool is_bottommost = (0 == frame_index);
|
const bool is_bottommost = (0 == frame_index);
|
||||||
bool is_topmost = (output_count_ - 1 == frame_index);
|
const bool is_topmost = (output_count_ - 1 == frame_index);
|
||||||
bool must_handle_result = !is_topmost || bailout_type_ == LAZY;
|
const bool must_handle_result = !is_topmost || bailout_type_ == LAZY;
|
||||||
|
|
||||||
const RegisterConfiguration* config(RegisterConfiguration::Default());
|
const RegisterConfiguration* config(RegisterConfiguration::Default());
|
||||||
int allocatable_register_count = config->num_allocatable_general_registers();
|
const int allocatable_register_count =
|
||||||
int padding_slot_count = BuiltinContinuationFrameConstants::PaddingSlotCount(
|
config->num_allocatable_general_registers();
|
||||||
allocatable_register_count);
|
const int padding_slot_count =
|
||||||
|
BuiltinContinuationFrameConstants::PaddingSlotCount(
|
||||||
|
allocatable_register_count);
|
||||||
|
|
||||||
int register_parameter_count =
|
const int register_parameter_count =
|
||||||
continuation_descriptor.GetRegisterParameterCount();
|
continuation_descriptor.GetRegisterParameterCount();
|
||||||
// Make sure to account for the context by removing it from the register
|
// Make sure to account for the context by removing it from the register
|
||||||
// parameter count.
|
// parameter count.
|
||||||
int stack_param_count = height_in_words - register_parameter_count - 1;
|
const int translated_stack_parameters =
|
||||||
if (must_handle_result) stack_param_count++;
|
height_in_words - register_parameter_count - 1;
|
||||||
unsigned output_frame_size =
|
const int stack_param_count =
|
||||||
kPointerSize * (stack_param_count + allocatable_register_count +
|
translated_stack_parameters + (must_handle_result ? 1 : 0);
|
||||||
padding_slot_count) +
|
const int stack_param_pad_count =
|
||||||
BuiltinContinuationFrameConstants::kFixedFrameSize;
|
ShouldPadArguments(stack_param_count) ? 1 : 0;
|
||||||
|
|
||||||
// If the builtins frame appears to be topmost we should ensure that the
|
// If the builtins frame appears to be topmost we should ensure that the
|
||||||
// value of result register is preserved during continuation execution.
|
// value of result register is preserved during continuation execution.
|
||||||
// We do this here by "pushing" the result of callback function to the
|
// We do this here by "pushing" the result of callback function to the
|
||||||
// top of the reconstructed stack and popping it in
|
// top of the reconstructed stack and popping it in
|
||||||
// {Builtins::kNotifyDeoptimized}.
|
// {Builtins::kNotifyDeoptimized}.
|
||||||
if (is_topmost) {
|
const int push_result_count =
|
||||||
output_frame_size += kPointerSize;
|
is_topmost ? (PadTopOfStackRegister() ? 2 : 1) : 0;
|
||||||
if (PadTopOfStackRegister()) output_frame_size += kPointerSize;
|
|
||||||
}
|
const unsigned output_frame_size =
|
||||||
|
kPointerSize * (stack_param_count + stack_param_pad_count +
|
||||||
|
allocatable_register_count + padding_slot_count +
|
||||||
|
push_result_count) +
|
||||||
|
BuiltinContinuationFrameConstants::kFixedFrameSize;
|
||||||
|
|
||||||
|
const unsigned output_frame_size_above_fp =
|
||||||
|
kPointerSize * (allocatable_register_count + padding_slot_count +
|
||||||
|
push_result_count) +
|
||||||
|
(BuiltinContinuationFrameConstants::kFixedFrameSize -
|
||||||
|
BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp);
|
||||||
|
|
||||||
// Validate types of parameters. They must all be tagged except for argc for
|
// Validate types of parameters. They must all be tagged except for argc for
|
||||||
// JS builtins.
|
// JS builtins.
|
||||||
@ -1470,10 +1486,6 @@ void Deoptimizer::DoComputeBuiltinContinuation(
|
|||||||
stack_param_count);
|
stack_param_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int translated_stack_parameters =
|
|
||||||
must_handle_result ? stack_param_count - 1 : stack_param_count;
|
|
||||||
|
|
||||||
if (ShouldPadArguments(stack_param_count)) output_frame_size += kPointerSize;
|
|
||||||
FrameDescription* output_frame = new (output_frame_size)
|
FrameDescription* output_frame = new (output_frame_size)
|
||||||
FrameDescription(output_frame_size, stack_param_count);
|
FrameDescription(output_frame_size, stack_param_count);
|
||||||
output_[frame_index] = output_frame;
|
output_[frame_index] = output_frame;
|
||||||
@ -1573,6 +1585,8 @@ void Deoptimizer::DoComputeBuiltinContinuation(
|
|||||||
DebugPrintOutputSlot(value, frame_index, output_frame_offset,
|
DebugPrintOutputSlot(value, frame_index, output_frame_offset,
|
||||||
"caller's fp\n");
|
"caller's fp\n");
|
||||||
|
|
||||||
|
DCHECK_EQ(output_frame_size_above_fp, output_frame_offset);
|
||||||
|
|
||||||
if (FLAG_enable_embedded_constant_pool) {
|
if (FLAG_enable_embedded_constant_pool) {
|
||||||
// Read the caller's constant pool from the previous frame.
|
// Read the caller's constant pool from the previous frame.
|
||||||
output_frame_offset -= kPointerSize;
|
output_frame_offset -= kPointerSize;
|
||||||
@ -1603,7 +1617,15 @@ void Deoptimizer::DoComputeBuiltinContinuation(
|
|||||||
DebugPrintOutputSlot(value, frame_index, output_frame_offset,
|
DebugPrintOutputSlot(value, frame_index, output_frame_offset,
|
||||||
java_script_builtin ? "JSFunction\n" : "unused\n");
|
java_script_builtin ? "JSFunction\n" : "unused\n");
|
||||||
|
|
||||||
// The builtin to continue to
|
// The delta from the SP to the FP; used to reconstruct SP in
|
||||||
|
// Isolate::UnwindAndFindHandler.
|
||||||
|
output_frame_offset -= kPointerSize;
|
||||||
|
value = static_cast<intptr_t>(output_frame_size_above_fp);
|
||||||
|
output_frame->SetFrameSlot(output_frame_offset, value);
|
||||||
|
DebugPrintOutputSlot(value, frame_index, output_frame_offset,
|
||||||
|
"frame height at deoptimization\n");
|
||||||
|
|
||||||
|
// The builtin to continue to.
|
||||||
output_frame_offset -= kPointerSize;
|
output_frame_offset -= kPointerSize;
|
||||||
value = reinterpret_cast<intptr_t>(builtin);
|
value = reinterpret_cast<intptr_t>(builtin);
|
||||||
output_frame->SetFrameSlot(output_frame_offset, value);
|
output_frame->SetFrameSlot(output_frame_offset, value);
|
||||||
|
@ -252,11 +252,14 @@ class BuiltinContinuationFrameConstants : public TypedFrameConstants {
|
|||||||
public:
|
public:
|
||||||
// FP-relative.
|
// FP-relative.
|
||||||
static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
|
static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
|
||||||
static const int kBuiltinOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
|
static const int kFrameSPtoFPDeltaAtDeoptimize =
|
||||||
|
TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
|
||||||
|
static const int kBuiltinOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
|
||||||
|
|
||||||
// The argument count is in the first allocatable register, stored below the
|
// The argument count is in the first allocatable register, stored below the
|
||||||
// fixed part of the frame and therefore is not part of the fixed frame size.
|
// fixed part of the frame and therefore is not part of the fixed frame size.
|
||||||
static const int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
|
static const int kArgCOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
|
||||||
DEFINE_TYPED_FRAME_SIZES(2);
|
DEFINE_TYPED_FRAME_SIZES(3);
|
||||||
|
|
||||||
// Returns the number of padding stack slots needed when we have
|
// Returns the number of padding stack slots needed when we have
|
||||||
// 'register_count' register slots.
|
// 'register_count' register slots.
|
||||||
|
Loading…
Reference in New Issue
Block a user