Commit b022674c authored by Marius Wachtler's avatar Marius Wachtler

bjit: reenable local block var optimization

parent a9a9c6c2
...@@ -1233,9 +1233,8 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr ...@@ -1233,9 +1233,8 @@ void Rewriter::_call(RewriterVar* result, bool has_side_effects, void* func_addr
std::vector<Location> Rewriter::getDecrefLocations() { std::vector<Location> Rewriter::getDecrefLocations() {
std::vector<Location> decref_infos; std::vector<Location> decref_infos;
for (RewriterVar& var : vars) { for (RewriterVar& var : vars) {
if (var.locations.size() && var.needsDecref()) { if (var.locations.size() && var.needsDecref(current_action_idx)) {
bool found_location = false; bool found_location = false;
for (Location l : var.locations) { for (Location l : var.locations) {
if (l.type == Location::Scratch) { if (l.type == Location::Scratch) {
// convert to stack based location because later on we may not know the offset of the scratch area // convert to stack based location because later on we may not know the offset of the scratch area
...@@ -1359,8 +1358,22 @@ void RewriterVar::refUsed() { ...@@ -1359,8 +1358,22 @@ void RewriterVar::refUsed() {
rewriter->addAction([=]() { this->bumpUse(); }, { this }, ActionType::NORMAL); rewriter->addAction([=]() { this->bumpUse(); }, { this }, ActionType::NORMAL);
} }
bool RewriterVar::needsDecref() { bool RewriterVar::needsDecref(int current_action_index) {
return reftype == RefType::OWNED && !this->refHandedOff(); rewriter->assertPhaseEmitting();
if (reftype != RefType::OWNED)
return false;
// if nothing consumes this reference we need to create a decref entry
if (num_refs_consumed == 0)
return true;
// don't create decref entry if the currenty action hands off the ownership
int reference_handed_off_action_index = uses[last_refconsumed_numuses - 1];
if (reference_handed_off_action_index == current_action_index)
return false;
return true;
} }
void RewriterVar::registerOwnedAttr(int byte_offset) { void RewriterVar::registerOwnedAttr(int byte_offset) {
...@@ -1513,6 +1526,7 @@ void Rewriter::commit() { ...@@ -1513,6 +1526,7 @@ void Rewriter::commit() {
_incref(var, 1); _incref(var, 1);
} }
current_action_idx = i;
actions[i].action(); actions[i].action();
if (failed) { if (failed) {
...@@ -2215,6 +2229,7 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L ...@@ -2215,6 +2229,7 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
return_location(this->rewrite->returnRegister()), return_location(this->rewrite->returnRegister()),
failed(false), failed(false),
needs_invalidation_support(needs_invalidation_support), needs_invalidation_support(needs_invalidation_support),
current_action_idx(-1),
added_changing_action(false), added_changing_action(false),
marked_inside_ic(false), marked_inside_ic(false),
done_guarding(false), done_guarding(false),
......
...@@ -254,7 +254,7 @@ private: ...@@ -254,7 +254,7 @@ private:
bool isDoneUsing() { return next_use == uses.size(); } bool isDoneUsing() { return next_use == uses.size(); }
bool hasScratchAllocation() const { return scratch_allocation.second > 0; } bool hasScratchAllocation() const { return scratch_allocation.second > 0; }
void resetHasScratchAllocation() { scratch_allocation = std::make_pair(0, 0); } void resetHasScratchAllocation() { scratch_allocation = std::make_pair(0, 0); }
bool needsDecref(); bool needsDecref(int current_action_index);
// Indicates if this variable is an arg, and if so, what location the arg is from. // Indicates if this variable is an arg, and if so, what location the arg is from.
bool is_arg; bool is_arg;
...@@ -432,6 +432,8 @@ protected: ...@@ -432,6 +432,8 @@ protected:
bool needs_invalidation_support = true); bool needs_invalidation_support = true);
std::deque<RewriterAction> actions; std::deque<RewriterAction> actions;
int current_action_idx; // in the emitting phase get's set to index of currently executed action
template <typename F> RewriterAction* addAction(F&& action, llvm::ArrayRef<RewriterVar*> vars, ActionType type) { template <typename F> RewriterAction* addAction(F&& action, llvm::ArrayRef<RewriterVar*> vars, ActionType type) {
assertPhaseCollecting(); assertPhaseCollecting();
for (RewriterVar* var : vars) { for (RewriterVar* var : vars) {
......
...@@ -471,13 +471,12 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) { ...@@ -471,13 +471,12 @@ void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
bool closure = vst == ScopeInfo::VarScopeType::CLOSURE; bool closure = vst == ScopeInfo::VarScopeType::CLOSURE;
if (jit) { if (jit) {
bool is_live = true; bool is_live = true;
// TODO: turn this optimization back on. if (!closure)
// if (!closure) is_live = source_info->getLiveness()->isLiveAtEnd(name, current_block);
// is_live = source_info->getLiveness()->isLiveAtEnd(name, current_block);
if (is_live) if (is_live)
jit->emitSetLocal(name, node->vreg, closure, value); jit->emitSetLocal(name, node->vreg, closure, value);
else else
jit->emitSetBlockLocal(name, value); jit->emitSetBlockLocal(name, node->vreg, value);
} }
if (closure) { if (closure) {
...@@ -1781,6 +1780,10 @@ int ASTInterpreterJitInterface::getBoxedLocalsOffset() { ...@@ -1781,6 +1780,10 @@ int ASTInterpreterJitInterface::getBoxedLocalsOffset() {
return offsetof(ASTInterpreter, frame_info.boxedLocals); return offsetof(ASTInterpreter, frame_info.boxedLocals);
} }
int ASTInterpreterJitInterface::getCreatedClosureOffset() {
return offsetof(ASTInterpreter, created_closure);
}
int ASTInterpreterJitInterface::getCurrentBlockOffset() { int ASTInterpreterJitInterface::getCurrentBlockOffset() {
return offsetof(ASTInterpreter, current_block); return offsetof(ASTInterpreter, current_block);
} }
......
...@@ -39,6 +39,7 @@ struct ASTInterpreterJitInterface { ...@@ -39,6 +39,7 @@ struct ASTInterpreterJitInterface {
static constexpr uint64_t osr_dummy_value = -1; static constexpr uint64_t osr_dummy_value = -1;
static int getBoxedLocalsOffset(); static int getBoxedLocalsOffset();
static int getCreatedClosureOffset();
static int getCurrentBlockOffset(); static int getCurrentBlockOffset();
static int getCurrentInstOffset(); static int getCurrentInstOffset();
static int getEdgeCountOffset(); static int getEdgeCountOffset();
......
...@@ -385,17 +385,16 @@ RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s, int vreg) { ...@@ -385,17 +385,16 @@ RewriterVar* JitFragmentWriter::emitGetBlockLocal(InternedString s, int vreg) {
auto it = local_syms.find(s); auto it = local_syms.find(s);
if (it == local_syms.end()) { if (it == local_syms.end()) {
auto r = emitGetLocal(s, vreg); auto r = emitGetLocal(s, vreg);
// TODO: clear out the vreg? assert(r->reftype == RefType::OWNED);
// assert(r->reftype == RefType::OWNED); emitSetBlockLocal(s, vreg, r);
// emitSetLocal(s, vreg, false, imm(nullptr));
// emitSetBlockLocal(s, r);
return r; return r;
} }
return it->second; return it->second;
} }
void JitFragmentWriter::emitKillTemporary(InternedString s, int vreg) { void JitFragmentWriter::emitKillTemporary(InternedString s, int vreg) {
emitSetLocal(s, vreg, false, imm(nullptr)); if (!local_syms.count(s))
emitSetLocal(s, vreg, false, imm(nullptr));
} }
RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) { RewriterVar* JitFragmentWriter::emitGetBoxedLocal(BoxedString* s) {
...@@ -549,8 +548,26 @@ std::vector<RewriterVar*> JitFragmentWriter::emitUnpackIntoArray(RewriterVar* v, ...@@ -549,8 +548,26 @@ std::vector<RewriterVar*> JitFragmentWriter::emitUnpackIntoArray(RewriterVar* v,
} }
RewriterVar* JitFragmentWriter::emitYield(RewriterVar* v) { RewriterVar* JitFragmentWriter::emitYield(RewriterVar* v) {
auto rtn = call(false, (void*)ASTInterpreterJitInterface::yieldHelper, getInterp(), v)->setType(RefType::OWNED); llvm::SmallVector<RewriterVar*, 16> local_args;
local_args.push_back(interp->getAttr(ASTInterpreterJitInterface::getCreatedClosureOffset()));
// we have to pass all owned references which are not stored in the vregs to yield() so that the GC can traverse it
for (auto&& sym : local_syms) {
if (sym.second == v)
continue;
if (sym.second->reftype == RefType::OWNED)
local_args.push_back(sym.second);
}
// erase duplicate entries
std::sort(local_args.begin(), local_args.end());
local_args.erase(std::unique(local_args.begin(), local_args.end()), local_args.end());
auto&& args = allocArgs(local_args, RewriterVar::SetattrType::REF_USED);
RewriterVar* generator = interp->getAttr(ASTInterpreterJitInterface::getGeneratorOffset());
auto rtn = call(false, (void*)yield, generator, v, args, imm(local_args.size()))->setType(RefType::OWNED);
v->refConsumed(); v->refConsumed();
for (auto&& var : local_args) {
var->refUsed();
}
return rtn; return rtn;
} }
...@@ -643,10 +660,12 @@ void JitFragmentWriter::emitSetAttr(AST_expr* node, RewriterVar* obj, BoxedStrin ...@@ -643,10 +660,12 @@ void JitFragmentWriter::emitSetAttr(AST_expr* node, RewriterVar* obj, BoxedStrin
attr->refConsumed(rtn.second); attr->refConsumed(rtn.second);
} }
void JitFragmentWriter::emitSetBlockLocal(InternedString s, STOLEN(RewriterVar*) v) { void JitFragmentWriter::emitSetBlockLocal(InternedString s, int vreg, STOLEN(RewriterVar*) v) {
if (LOG_BJIT_ASSEMBLY) if (LOG_BJIT_ASSEMBLY)
comment("BJIT: emitSetBlockLocal() start"); comment("BJIT: emitSetBlockLocal() start");
RewriterVar* prev = local_syms[s]; RewriterVar* prev = local_syms[s];
if (!prev)
emitSetLocal(s, vreg, false, imm(nullptr)); // clear out the vreg
local_syms[s] = v; local_syms[s] = v;
if (LOG_BJIT_ASSEMBLY) if (LOG_BJIT_ASSEMBLY)
comment("BJIT: emitSetBlockLocal() end"); comment("BJIT: emitSetBlockLocal() end");
......
...@@ -272,7 +272,7 @@ public: ...@@ -272,7 +272,7 @@ public:
void emitRaise3(RewriterVar* arg0, RewriterVar* arg1, RewriterVar* arg2); void emitRaise3(RewriterVar* arg0, RewriterVar* arg1, RewriterVar* arg2);
void emitReturn(RewriterVar* v); void emitReturn(RewriterVar* v);
void emitSetAttr(AST_expr* node, RewriterVar* obj, BoxedString* s, STOLEN(RewriterVar*) attr); void emitSetAttr(AST_expr* node, RewriterVar* obj, BoxedString* s, STOLEN(RewriterVar*) attr);
void emitSetBlockLocal(InternedString s, STOLEN(RewriterVar*) v); void emitSetBlockLocal(InternedString s, int vreg, STOLEN(RewriterVar*) v);
void emitSetCurrentInst(AST_stmt* node); void emitSetCurrentInst(AST_stmt* node);
void emitSetExcInfo(RewriterVar* type, RewriterVar* value, RewriterVar* traceback); void emitSetExcInfo(RewriterVar* type, RewriterVar* value, RewriterVar* traceback);
void emitSetGlobal(BoxedString* s, STOLEN(RewriterVar*) v, bool are_globals_from_module); void emitSetGlobal(BoxedString* s, STOLEN(RewriterVar*) v, bool are_globals_from_module);
......
# fail-if: '-n' in EXTRA_JIT_ARGS or '-O' in EXTRA_JIT_ARGS # expected: fail
# this only works in the interpreter and not in the bjit and llvm jit
class C(object): class C(object):
def next(self): def next(self):
......
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