Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify inline exit frames. #345

Merged
merged 1 commit into from Jul 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions vm/jit.h
Expand Up @@ -130,6 +130,7 @@ class CompilerBase : public PcodeVisitor
Label throw_error_code_[SP_MAX_ERROR_CODES];
Label report_error_;
Label return_reported_error_;
Label unbound_native_error_;

// Debugging.
Label debug_break_;
Expand Down
6 changes: 6 additions & 0 deletions vm/runtime-helpers.cpp
Expand Up @@ -40,4 +40,10 @@ ReportOutOfBoundsError(cell_t index, cell_t bounds)
}
}

void
ReportUnboundNative()
{
Environment::get()->ReportError(SP_ERROR_INVALID_NATIVE);
}

} // namespace sp
1 change: 1 addition & 0 deletions vm/runtime-helpers.h
Expand Up @@ -22,6 +22,7 @@
namespace sp {

void ReportOutOfBoundsError(cell_t index, cell_t bounds);
void ReportUnboundNative();

} // namespace sp

Expand Down
11 changes: 0 additions & 11 deletions vm/x64/macro-assembler-x64.cpp
Expand Up @@ -35,17 +35,6 @@ MacroAssembler::leaveFrame()
leave();
}

void
MacroAssembler::enterInlineExitFrame(ExitFrameType type, uintptr_t payload, CodeLabel* return_address)
{
{
ReserveScratch scratch(this);
movq(scratch.reg(), return_address);
push(scratch.reg());
}
enterExitFrame(type, payload);
}

void
MacroAssembler::enterExitFrame(ExitFrameType type, uintptr_t payload)
{
Expand Down
4 changes: 0 additions & 4 deletions vm/x64/macro-assembler-x64.h
Expand Up @@ -35,10 +35,6 @@ class MacroAssembler : public Assembler
void enterFrame(JitFrameType type, uint32_t function_id);
void leaveFrame();

// Inline exit frames are not entered via a call; instead they simulate a
// call by pushing a return address.
void enterInlineExitFrame(ExitFrameType type, uintptr_t payload, CodeLabel* return_address);

void enterExitFrame(ExitFrameType type, uintptr_t payload);
void leaveExitFrame();

Expand Down
27 changes: 15 additions & 12 deletions vm/x86/jit_x86.cpp
Expand Up @@ -1344,13 +1344,7 @@ void
Compiler::emitLegacyNativeCall(uint32_t native_index, NativeEntry* native)
{
CodeLabel return_address;
__ enterInlineExitFrame(ExitFrameType::Native, native_index, &return_address);

// Align the stack.
static const uint32_t stack_use = 4 * sizeof(intptr_t);
static const uint32_t misalignment = Align(stack_use, sizeof(intptr_t)) - stack_use;
if (misalignment)
__ addl(esp, misalignment);
__ pushInlineExitFrame(ExitFrameType::Native, native_index, &return_address);

// Save registers.
__ push(edx);
Expand All @@ -1361,7 +1355,7 @@ Compiler::emitLegacyNativeCall(uint32_t native_index, NativeEntry* native)
if (!immutable) {
__ movl(edx, Operand(ExternalAddress(&native->legacy_fn)));
__ testl(edx, edx);
jumpOnError(zero, SP_ERROR_INVALID_NATIVE);
__ j(zero, &unbound_native_error_);
}

// Save the old heap pointer.
Expand Down Expand Up @@ -1397,8 +1391,8 @@ Compiler::emitLegacyNativeCall(uint32_t native_index, NativeEntry* native)
// Restore SP.
__ addl(stk, dat);

// Note: no ret, the frame is inline. We add 4 to esp isntead.
__ leaveInlineExitFrame();
// Remove the inline frame, + our four arguments.
__ popInlineExitFrame(4);

// Check for errors. Note we jump directly to the return stub since the
// error has already been reported.
Expand Down Expand Up @@ -1556,14 +1550,14 @@ Compiler::emitOutOfBoundsErrorPath(OutOfBoundsErrorPath* path)
{
CodeLabel return_address;
__ alignStack();
__ enterInlineExitFrame(ExitFrameType::Helper, 0, &return_address);
__ pushInlineExitFrame(ExitFrameType::Helper, 0, &return_address);
__ subl(esp, 8);
__ push(path->bounds);
__ push(eax);
__ callWithABI(ExternalAddress((void*)ReportOutOfBoundsError));
__ bind(&return_address);
emitCipMapping(path->cip);
__ leaveInlineExitFrame();
__ popInlineExitFrame(4);
__ jmp(&return_reported_error_);
}

Expand All @@ -1587,6 +1581,15 @@ Compiler::emitErrorHandlers()
__ jmp(&return_to_invoke);
}

// The unbound native path re-uses the native exit frame so the stack trace
// looks as if the native was bound.
if (unbound_native_error_.used()) {
__ bind(&unbound_native_error_);
__ alignStack();
__ callWithABI(ExternalAddress((void*)ReportUnboundNative));
__ jmp(&return_reported_error_);
}

// The timeout uses a special stub.
if (throw_timeout_.used()) {
__ bind(&throw_timeout_);
Expand Down
16 changes: 8 additions & 8 deletions vm/x86/macro-assembler-x86.h
Expand Up @@ -60,16 +60,16 @@ class MacroAssembler : public Assembler
leaveFrame();
}

// Inline exit frames are not entered via a call; instead they simulate a
// call by pushing a return address.
void enterInlineExitFrame(ExitFrameType type, uintptr_t payload, CodeLabel* return_address) {
void pushInlineExitFrame(ExitFrameType type, uintptr_t payload, CodeLabel* return_address) {
push(return_address);
enterExitFrame(type, payload);
push(ebp);
movl(Operand(ExternalAddress(Environment::get()->addressOfExit())), esp);
push(uint32_t(JitFrameType::Exit));
push(EncodeExitFrameId(type, payload));
}
void leaveInlineExitFrame() {
// Note: no ret, the frame is inline. We add 4 to esp isntead.
leaveExitFrame();
addl(esp, 4);

void popInlineExitFrame(uint32_t extra_argc) {
addl(esp, (4 + extra_argc) * sizeof(uintptr_t));
}

void alignStack() {
Expand Down