[arm64] Pad registers in interpreter frame.
Add padding for the interpreter registers when needed, to make the interpreter frame a multiple of 16 bytes. The padding needs to be added in the InterpreterEntryTrampoline and when generating an interpreter frame in the deoptimizer. It also needs to be considered when calculating the size of the interpreter frame during OSR and stack unwinding. Bug: v8:6644 Change-Id: Icfec94079cf0785fc8a2506ff555b5f9e89e3d13 Reviewed-on: https://chromium-review.googlesource.com/664563 Commit-Queue: Georgia Kouveli <georgia.kouveli@arm.com> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#48121}
This commit is contained in:
parent
2098e9c589
commit
9f01414923
@ -20,6 +20,10 @@ Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -19,6 +19,11 @@ Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
// Round up to a multiple of two, to make the frame a multiple of 16 bytes.
|
||||
return RoundUp(register_count, 2);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -981,9 +981,11 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
// register in the register file.
|
||||
Label loop_header;
|
||||
__ LoadRoot(x10, Heap::kUndefinedValueRootIndex);
|
||||
// TODO(rmcilroy): Ensure we always have an even number of registers to
|
||||
// allow stack to be 16 bit aligned (and remove need for jssp).
|
||||
__ Lsr(x11, x11, kPointerSizeLog2);
|
||||
// Round up the number of registers to a multiple of 2, to align the stack
|
||||
// to 16 bytes.
|
||||
__ Add(x11, x11, 1);
|
||||
__ Bic(x11, x11, 1);
|
||||
__ PushMultipleTimes(x10, x11);
|
||||
__ Bind(&loop_header);
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ OsrHelper::OsrHelper(CompilationInfo* info)
|
||||
: parameter_count_(
|
||||
info->shared_info()->bytecode_array()->parameter_count()),
|
||||
stack_slot_count_(
|
||||
info->shared_info()->bytecode_array()->register_count() +
|
||||
InterpreterFrameConstants::RegisterStackSlotCount(
|
||||
info->shared_info()->bytecode_array()->register_count()) +
|
||||
InterpreterFrameConstants::kExtraSlotCount) {}
|
||||
|
||||
void OsrHelper::SetupFrame(Frame* frame) {
|
||||
|
@ -736,14 +736,16 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
|
||||
int input_index = 0;
|
||||
|
||||
int bytecode_offset = translated_frame->node_id().ToInt();
|
||||
unsigned height = translated_frame->height();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
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 * kPointerSize;
|
||||
|
||||
// All tranlations for interpreted frames contain the accumulator and hence
|
||||
// are assumed to be in bailout state {BailoutState::TOS_REGISTER}. However
|
||||
// such a state is only supported for the topmost frame. We need to skip
|
||||
// pushing the accumulator for any non-topmost frame.
|
||||
if (!is_topmost) height_in_bytes -= kPointerSize;
|
||||
// The topmost frame is assumed to be in bailout state
|
||||
// {BailoutState::TOS_REGISTER} and will contain the accumulator, which we
|
||||
// add to the frame height here.
|
||||
if (is_topmost) height_in_bytes += kPointerSize;
|
||||
|
||||
JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
|
||||
value_iterator++;
|
||||
@ -912,12 +914,23 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
|
||||
}
|
||||
|
||||
// Translate the rest of the interpreter registers in the frame.
|
||||
for (unsigned i = 0; i < height - 1; ++i) {
|
||||
for (int i = 0; i < register_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
|
||||
output_offset);
|
||||
}
|
||||
|
||||
int register_slots_written = register_count;
|
||||
DCHECK_LE(register_slots_written, 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) {
|
||||
register_slots_written++;
|
||||
output_offset -= kPointerSize;
|
||||
WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
|
||||
output_offset, "padding ");
|
||||
}
|
||||
|
||||
// Translate the accumulator register (depending on frame position).
|
||||
if (is_topmost) {
|
||||
// For topmost frame, put the accumulator on the stack. The bailout state
|
||||
|
@ -300,6 +300,11 @@ class InterpreterFrameConstants : public AllStatic {
|
||||
static const int kBytecodeArrayExpressionIndex = -2;
|
||||
static const int kBytecodeOffsetExpressionIndex = -1;
|
||||
static const int kRegisterFileExpressionIndex = 0;
|
||||
|
||||
// Returns the number of stack slots needed for 'register_count' registers.
|
||||
// This is needed because some architectures must pad the stack frame with
|
||||
// additional stack slots to ensure the stack pointer is aligned.
|
||||
static int RegisterStackSlotCount(int register_count);
|
||||
};
|
||||
|
||||
inline static int FPOffsetToFrameSlot(int frame_offset) {
|
||||
|
@ -18,6 +18,10 @@ Register JavaScriptFrame::fp_register() { return ebp; }
|
||||
Register JavaScriptFrame::context_register() { return esi; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -1310,7 +1310,8 @@ Object* Isolate::UnwindAndFindHandler() {
|
||||
// For interpreted frame we perform a range lookup in the handler table.
|
||||
if (!catchable_by_js) break;
|
||||
InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame);
|
||||
int register_slots = js_frame->GetBytecodeArray()->register_count();
|
||||
int register_slots = InterpreterFrameConstants::RegisterStackSlotCount(
|
||||
js_frame->GetBytecodeArray()->register_count());
|
||||
int context_reg = 0; // Will contain register index holding context.
|
||||
int offset =
|
||||
js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr);
|
||||
|
@ -18,6 +18,10 @@ Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -18,6 +18,10 @@ Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -23,6 +23,10 @@ Register JavaScriptFrame::constant_pool_pointer_register() {
|
||||
return kConstantPoolRegister;
|
||||
}
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -20,6 +20,10 @@ Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -18,6 +18,10 @@ Register JavaScriptFrame::fp_register() { return rbp; }
|
||||
Register JavaScriptFrame::context_register() { return rsi; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() { UNREACHABLE(); }
|
||||
|
||||
int InterpreterFrameConstants::RegisterStackSlotCount(int register_count) {
|
||||
return register_count;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user