Commit 051a4886 authored by Marius Wachtler's avatar Marius Wachtler

Emit trampoline jumps to the slowpath func

If a jump offset is larger then 0x80 the instruction encoding requires 6bytes instead of 2bytes.
This adds up quickly, thats why we will try to find another jump to the slowpath with the same condition with a
smaller offset and jump to it / use it as a trampoline.
The benchmark show that this increases the performance slightly even though it introduces additional jumps.
parent 15098268
...@@ -215,22 +215,6 @@ void Rewriter::ConstLoader::loadConstIntoReg(uint64_t val, assembler::Register d ...@@ -215,22 +215,6 @@ void Rewriter::ConstLoader::loadConstIntoReg(uint64_t val, assembler::Register d
moveImmediate(val, dst_reg); moveImmediate(val, dst_reg);
} }
assembler::Register Rewriter::ConstLoader::loadConst(uint64_t val, Location otherThan) {
assert(rewriter->phase_emitting);
bool found_value = false;
assembler::Register /*reg = findConst(val, found_value);
if (found_value)
return reg;*/
reg = rewriter->allocReg(Location::any(), otherThan);
if (tryLea(val, reg))
return reg;
moveImmediate(val, reg);
return reg;
}
void Rewriter::restoreArgs() { void Rewriter::restoreArgs() {
ASSERT(!done_guarding, "this will probably work but why are we calling this at this time"); ASSERT(!done_guarding, "this will probably work but why are we calling this at this time");
...@@ -284,6 +268,23 @@ void RewriterVar::addGuard(uint64_t val) { ...@@ -284,6 +268,23 @@ void RewriterVar::addGuard(uint64_t val) {
rewriter->addAction([=]() { rewriter->_addGuard(this, val_var); }, { this, val_var }, ActionType::GUARD); rewriter->addAction([=]() { rewriter->_addGuard(this, val_var); }, { this, val_var }, ActionType::GUARD);
} }
void Rewriter::_slowpathJump(bool condition_eq) {
// If a jump offset is larger then 0x80 the instruction encoding requires 6bytes instead of 2bytes.
// This adds up quickly, thats why we will try to find another jump to the slowpath with the same condition with a
// smaller offset and jump to it / use it as a trampoline.
// The benchmark show that this increases the performance slightly even though it introduces additional jumps.
int& last_jmp_offset = condition_eq ? offset_eq_jmp_slowpath : offset_ne_jmp_slowpath;
auto condition = condition_eq ? assembler::COND_EQUAL : assembler::COND_NOT_EQUAL;
assert(assembler->bytesWritten() + assembler->bytesLeft() == rewrite->getSlotSize());
if (last_jmp_offset != -1 && assembler->bytesLeft() >= 0x80 && assembler->bytesWritten() - last_jmp_offset < 0x80) {
assembler->jmp_cond(assembler::JumpDestination::fromStart(last_jmp_offset), condition);
} else {
last_jmp_offset = assembler->bytesWritten();
assembler->jmp_cond(assembler::JumpDestination::fromStart(rewrite->getSlotSize()), condition);
}
}
void Rewriter::_addGuard(RewriterVar* var, RewriterVar* val_constant) { void Rewriter::_addGuard(RewriterVar* var, RewriterVar* val_constant) {
assembler->comment("_addGuard"); assembler->comment("_addGuard");
...@@ -300,7 +301,7 @@ void Rewriter::_addGuard(RewriterVar* var, RewriterVar* val_constant) { ...@@ -300,7 +301,7 @@ void Rewriter::_addGuard(RewriterVar* var, RewriterVar* val_constant) {
restoreArgs(); // can only do movs, doesn't affect flags, so it's safe restoreArgs(); // can only do movs, doesn't affect flags, so it's safe
assertArgsInPlace(); assertArgsInPlace();
assembler->jne(assembler::JumpDestination::fromStart(rewrite->getSlotSize())); _slowpathJump(false /*= not equal jmp */);
var->bumpUse(); var->bumpUse();
val_constant->bumpUse(); val_constant->bumpUse();
...@@ -331,7 +332,7 @@ void Rewriter::_addGuardNotEq(RewriterVar* var, RewriterVar* val_constant) { ...@@ -331,7 +332,7 @@ void Rewriter::_addGuardNotEq(RewriterVar* var, RewriterVar* val_constant) {
restoreArgs(); // can only do movs, doesn't affect flags, so it's safe restoreArgs(); // can only do movs, doesn't affect flags, so it's safe
assertArgsInPlace(); assertArgsInPlace();
assembler->je(assembler::JumpDestination::fromStart(rewrite->getSlotSize())); _slowpathJump(true /*= equal jmp */);
var->bumpUse(); var->bumpUse();
val_constant->bumpUse(); val_constant->bumpUse();
...@@ -381,10 +382,7 @@ void Rewriter::_addAttrGuard(RewriterVar* var, int offset, RewriterVar* val_cons ...@@ -381,10 +382,7 @@ void Rewriter::_addAttrGuard(RewriterVar* var, int offset, RewriterVar* val_cons
restoreArgs(); // can only do movs, doesn't affect flags, so it's safe restoreArgs(); // can only do movs, doesn't affect flags, so it's safe
assertArgsInPlace(); assertArgsInPlace();
if (negate) _slowpathJump(negate);
assembler->je(assembler::JumpDestination::fromStart(rewrite->getSlotSize()));
else
assembler->jne(assembler::JumpDestination::fromStart(rewrite->getSlotSize()));
var->bumpUse(); var->bumpUse();
val_constant->bumpUse(); val_constant->bumpUse();
...@@ -1813,8 +1811,10 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L ...@@ -1813,8 +1811,10 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
failed(false), failed(false),
added_changing_action(false), added_changing_action(false),
marked_inside_ic(false), marked_inside_ic(false),
done_guarding(false),
last_guard_action(-1), last_guard_action(-1),
done_guarding(false) { offset_eq_jmp_slowpath(-1),
offset_ne_jmp_slowpath(-1) {
initPhaseCollecting(); initPhaseCollecting();
finished = false; finished = false;
......
...@@ -379,9 +379,6 @@ protected: ...@@ -379,9 +379,6 @@ protected:
// Loads the constant into the specified register // Loads the constant into the specified register
void loadConstIntoReg(uint64_t val, assembler::Register reg); void loadConstIntoReg(uint64_t val, assembler::Register reg);
// Loads the constant into any register or if already in a register just return it
assembler::Register loadConst(uint64_t val, Location otherThan = Location::any());
llvm::SmallVector<std::pair<uint64_t, RewriterVar*>, 16> consts; llvm::SmallVector<std::pair<uint64_t, RewriterVar*>, 16> consts;
}; };
...@@ -444,14 +441,16 @@ protected: ...@@ -444,14 +441,16 @@ protected:
bool added_changing_action; bool added_changing_action;
bool marked_inside_ic; bool marked_inside_ic;
int last_guard_action;
bool done_guarding; bool done_guarding;
bool isDoneGuarding() { bool isDoneGuarding() {
assertPhaseEmitting(); assertPhaseEmitting();
return done_guarding; return done_guarding;
} }
int last_guard_action;
int offset_eq_jmp_slowpath;
int offset_ne_jmp_slowpath;
// Move the original IC args back into their original registers: // Move the original IC args back into their original registers:
void restoreArgs(); void restoreArgs();
// Assert that our original args are correctly placed in case we need to // Assert that our original args are correctly placed in case we need to
...@@ -482,6 +481,7 @@ protected: ...@@ -482,6 +481,7 @@ protected:
bool finishAssembly(int continue_offset) override; bool finishAssembly(int continue_offset) override;
void _slowpathJump(bool condition_eq);
void _trap(); void _trap();
void _loadConst(RewriterVar* result, int64_t val); void _loadConst(RewriterVar* result, int64_t val);
void _setupCall(bool has_side_effects, llvm::ArrayRef<RewriterVar*> args, llvm::ArrayRef<RewriterVar*> args_xmm); void _setupCall(bool has_side_effects, llvm::ArrayRef<RewriterVar*> args, llvm::ArrayRef<RewriterVar*> args_xmm);
......
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