Commit 4dd4b5b3 authored by Marius Wachtler's avatar Marius Wachtler Committed by GitHub

Merge pull request #1255 from undingen/bjit_opt7

rewriter+bjit: remove duplicate getattrs, misc codegen improvements
parents 5edb8980 a93836fd
This diff is collapsed.
......@@ -202,7 +202,8 @@ public:
template <typename Src, typename Dst> inline RewriterVar* getAttrCast(int offset, Location loc = Location::any());
bool isConstant() { return is_constant; }
bool isConstant() const { return is_constant; }
bool isContantNull() const { return isConstant() && constant_value == 0; }
protected:
void incref();
......@@ -236,11 +237,11 @@ private:
// /* some code */
// bumpUseLateIfNecessary();
void bumpUseEarlyIfPossible() {
if (reftype != RefType::OWNED && !hasScratchAllocation())
if (reftype != RefType::OWNED && !isScratchAllocation())
bumpUse();
}
void bumpUseLateIfNecessary() {
if (reftype == RefType::OWNED || hasScratchAllocation())
if (reftype == RefType::OWNED || isScratchAllocation())
bumpUse();
}
......@@ -251,8 +252,9 @@ private:
// Don't call it directly: call bumpUse and releaseIfNoUses instead.
void _release();
bool isDoneUsing() { return next_use == uses.size(); }
bool hasScratchAllocation() const { return scratch_allocation.second > 0; }
void resetHasScratchAllocation() { scratch_allocation = std::make_pair(0, 0); }
bool isScratchAllocation() const { return scratch_allocation.second > 0; }
void resetIsScratchAllocation() { scratch_allocation = std::make_pair(0, 0); }
Location getScratchLocation(int additional_offset_in_bytes = 0);
bool needsDecref(int current_action_index);
// Indicates if this variable is an arg, and if so, what location the arg is from.
......@@ -263,7 +265,8 @@ private:
Location arg_loc;
std::pair<int /*offset*/, int /*size*/> scratch_allocation;
llvm::SmallSet<std::tuple<int, uint64_t, bool>, 4> attr_guards; // used to detect duplicate guards
llvm::SmallSet<std::tuple<int, uint64_t, bool>, 4> attr_guards; // used to detect duplicate guards
llvm::SmallDenseMap<std::pair<int, int>, RewriterVar*> getattrs; // used to detect duplicate getAttrs
// Gets a copy of this variable in a register, spilling/reloading if necessary.
// TODO have to be careful with the result since the interface doesn't guarantee
......@@ -565,8 +568,13 @@ protected:
// These do not call bumpUse on their arguments:
void _incref(RewriterVar* var, int num_refs = 1);
void _decref(RewriterVar* var);
void _xdecref(RewriterVar* var);
void _decref(RewriterVar* var, llvm::ArrayRef<RewriterVar*> vars_to_bump = {});
void _xdecref(RewriterVar* var, llvm::ArrayRef<RewriterVar*> vars_to_bump = {});
// emits a call instruction using the smallest encoding.
// either doing a relative call if or otherwise loading the address into the supplied register and calling it.
// the caller of this function must make sure that the supplied register can be safely overwriten.
void _callOptimalEncoding(assembler::Register tmp_reg, void* func_addr);
void assertConsistent() {
#ifndef NDEBUG
......
......@@ -177,6 +177,8 @@ JitFragmentWriter::JitFragmentWriter(CFGBlock* block, std::unique_ptr<ICInfo> ic
ic_info(std::move(ic_info)) {
allocatable_regs = bjit_allocatable_regs;
added_changing_action = true;
if (LOG_BJIT_ASSEMBLY)
comment("BJIT: JitFragmentWriter() start");
interp = createNewVar();
......@@ -410,8 +412,14 @@ RewriterVar* JitFragmentWriter::emitGetLocal(InternedString s, int vreg) {
assert(vreg >= 0);
// TODO Can we use BORROWED here? Not sure if there are cases when we can't rely on borrowing the ref
// from the vregs array. Safer like this.
RewriterVar* val_var = vregs_array->getAttr(vreg * 8)->setType(RefType::OWNED);
addAction([=]() { _emitGetLocal(val_var, s.c_str()); }, { val_var }, ActionType::NORMAL);
RewriterVar* val_var = vregs_array->getAttr(vreg * 8);
if (known_non_null_vregs.count(vreg) == 0) {
addAction([=]() { _emitGetLocal(val_var, s.c_str()); }, { val_var }, ActionType::NORMAL);
known_non_null_vregs.insert(vreg);
} else {
val_var->incref();
}
val_var->setType(RefType::OWNED);
if (LOG_BJIT_ASSEMBLY)
comment("BJIT: emitGetLocal end");
return val_var;
......@@ -694,10 +702,14 @@ void JitFragmentWriter::emitSetLocal(InternedString s, int vreg, bool set_closur
// The issue is that definedness analysis is somewhat expensive to compute, so we don't compute it
// for the bjit. We could try calculating it (which would require some re-plumbing), which might help
// but I suspect is not that big a deal as long as the llvm jit implements this kind of optimization.
bool prev_nullable = true;
bool prev_nullable = known_non_null_vregs.count(vreg) == 0;
assert(!block->cfg->getVRegInfo().isBlockLocalVReg(vreg));
vregs_array->replaceAttr(8 * vreg, v, prev_nullable);
if (v->isContantNull())
known_non_null_vregs.erase(vreg);
else
known_non_null_vregs.insert(vreg);
}
if (LOG_BJIT_ASSEMBLY)
comment("BJIT: emitSetLocal() end");
......@@ -999,9 +1011,8 @@ void JitFragmentWriter::_emitGetLocal(RewriterVar* val_var, const char* name) {
_setupCall(false, {});
{
assembler::ForwardJump jnz(*assembler, assembler::COND_NOT_ZERO);
assembler->mov(assembler::Immediate((uint64_t)name), assembler::RDI);
assembler->mov(assembler::Immediate((void*)assertNameDefinedHelper), assembler::R11);
assembler->callq(assembler::R11);
const_loader.loadConstIntoReg((uint64_t)name, assembler::RDI);
_callOptimalEncoding(assembler::R11, (void*)assertNameDefinedHelper);
registerDecrefInfoHere();
}
......
......@@ -207,6 +207,9 @@ private:
RewriterVar* interp;
RewriterVar* vregs_array;
llvm::DenseMap<InternedString, RewriterVar*> local_syms;
// keeps track which non block local vregs are known to have a non NULL value
// TODO: in the future we could reuse this information between different basic blocks
llvm::DenseSet<int> known_non_null_vregs;
std::unique_ptr<ICInfo> ic_info;
// Optional points to a CFGBlock and a patch location which should get patched to a direct jump if
......
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