Commit e1430c45 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Lots of improvements

parent c6c87982
......@@ -513,6 +513,7 @@ void RewriterVar::xdecref() {
}
void Rewriter::_incref(RewriterVar* var) {
assert(!var->nullable);
//assembler->trap();
//auto reg = var->getInReg();
//assembler->incl(assembler::Indirect(reg, offsetof(Box, ob_refcnt)));
......@@ -533,6 +534,7 @@ void Rewriter::_incref(RewriterVar* var) {
}
void Rewriter::_decref(RewriterVar* var) {
assert(!var->nullable);
//assembler->trap();
//this->_call(NULL, true, (void*)Helper::decref, llvm::ArrayRef<RewriterVar*>(&var, 1),
......@@ -563,6 +565,7 @@ void Rewriter::_decref(RewriterVar* var) {
}
void Rewriter::_xdecref(RewriterVar* var) {
assert(var->nullable);
//assembler->trap();
this->_call(NULL, true, (void*)Helper::xdecref, llvm::ArrayRef<RewriterVar*>(&var, 1),
......@@ -1206,8 +1209,12 @@ RewriterVar* RewriterVar::setType(RefType type) {
}
void RewriterVar::_release() {
if (reftype == RefType::OWNED && !this->refHandedOff())
this->rewriter->_decref(this);
if (reftype == RefType::OWNED && !this->refHandedOff()) {
if (nullable)
this->rewriter->_xdecref(this);
else
this->rewriter->_decref(this);
}
for (Location loc : locations) {
rewriter->vars_by_location.erase(loc);
......@@ -1849,7 +1856,14 @@ assembler::Register Rewriter::allocReg(Location dest, Location otherThan) {
if (!done_guarding && var->is_arg && var->arg_loc == Location(reg)) {
continue;
}
if (var->uses[var->next_use] > best) {
if (var->next_use == var->uses.size()) {
// If we found a variable that is dead but somehow occupying a location,
// don't touch it.
// This could be something that we are actively working on decref'ing.
continue;
} else if (var->uses[var->next_use] > best) {
found = true;
best = var->uses[var->next_use];
best_reg = reg;
......
......@@ -208,6 +208,7 @@ class RewriterVar {
int num_refs_consumed = 0; // The number of "refConsumed()" calls on this RewriterVar
int last_refconsumed_numuses = 0; // The number of uses in the `uses` array when the last refConsumed() call was made.
RefType reftype = RefType::UNKNOWN;
bool nullable = false;
// Helper function: whether there is a ref that got consumed but came from the consumption of the
// initial (owned) reference.
bool refHandedOff();
......@@ -227,6 +228,10 @@ public:
RewriterVar* toBool(Location loc = Location::any());
RewriterVar* setType(RefType type);
RewriterVar* setNullable(bool nullable) {
this->nullable = nullable;
return this;
}
// Call this to let the automatic refcount machinery know that a refcount
// got "consumed", ie passed off. Such as to a function that steals a reference,
......
......@@ -406,15 +406,17 @@ public:
llvm::Value* uncasted = emitter.createIC(pp, (void*)pyston::createBoxedIterWrapperIfNeeded,
{ converted_iter_call->getValue() }, info.unw_info);
llvm::Value* value_has_iter = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
emitter.setType(value_has_iter, RefType::OWNED);
llvm::BasicBlock* value_has_iter_bb = emitter.currentBasicBlock();
emitter.getBuilder()->CreateBr(bb_join);
auto has_iter_terminator = emitter.getBuilder()->CreateBr(bb_join);
// var has no __iter__()
// TODO: we could create a patchpoint if this turns out to be hot
emitter.setCurrentBasicBlock(bb_no_iter);
llvm::Value* value_no_iter = emitter.createCall(info.unw_info, g.funcs.getiterHelper, var->getValue());
emitter.setType(value_no_iter, RefType::OWNED);
llvm::BasicBlock* value_no_iter_bb = emitter.currentBasicBlock();
emitter.getBuilder()->CreateBr(bb_join);
auto no_iter_terminator = emitter.getBuilder()->CreateBr(bb_join);
// join
emitter.setCurrentBasicBlock(bb_join);
......@@ -422,6 +424,10 @@ public:
phi->addIncoming(value_has_iter, value_has_iter_bb);
phi->addIncoming(value_no_iter, value_no_iter_bb);
emitter.refConsumed(value_has_iter, has_iter_terminator);
emitter.refConsumed(value_no_iter, no_iter_terminator);
emitter.setType(phi, RefType::OWNED);
return new ConcreteCompilerVariable(UNKNOWN, phi);
}
......@@ -505,6 +511,7 @@ ConcreteCompilerType* UNKNOWN = new UnknownType();
CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
BoxedString* attr, bool cls_only) {
llvm::Constant* ptr = embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr);
emitter.setType(ptr, RefType::BORROWED);
llvm::Value* rtn_val = NULL;
......@@ -539,6 +546,7 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
} else {
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr, target_exception_style);
}
emitter.setType(rtn_val, RefType::OWNED);
if (target_exception_style == CAPI)
emitter.checkAndPropagateCapiException(info.unw_info, rtn_val, getNullPtr(g.llvm_value_type_ptr));
......@@ -716,7 +724,7 @@ CompilerVariable* UnknownType::callattr(IREmitter& emitter, const OpInfo& info,
std::vector<llvm::Value*> other_args;
other_args.push_back(var->getValue());
other_args.push_back(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr));
other_args.push_back(emitter.setType(embedRelocatablePtr(attr, g.llvm_boxedstring_type_ptr), RefType::BORROWED));
other_args.push_back(getConstantInt(flags.asInt(), g.i64));
return _call(emitter, info, func, exception_style, func_ptr, other_args, flags.argspec, args, keyword_names,
UNKNOWN);
......@@ -1779,7 +1787,8 @@ public:
llvm::CallSite call = emitter.createCall3(
info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style);
emitter.setType(embedRelocatablePtr(attr->data(), g.i8_ptr), RefType::BORROWED),
getConstantInt(attr->size(), g.i64), exception_style);
if (exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
......
......@@ -1108,8 +1108,10 @@ private:
emitter.setType(r, RefType::OWNED);
return new ConcreteCompilerVariable(UNKNOWN, r);
} else {
llvm::Value* r = emitter.createCall2(unw_info, g.funcs.getGlobal, irstate->getGlobals(),
embedRelocatablePtr(node->id.getBox(), g.llvm_boxedstring_type_ptr));
llvm::Value* r = emitter.createCall2(
unw_info, g.funcs.getGlobal, irstate->getGlobals(),
emitter.setType(embedRelocatablePtr(node->id.getBox(), g.llvm_boxedstring_type_ptr),
RefType::BORROWED));
emitter.setType(r, RefType::OWNED);
return new ConcreteCompilerVariable(UNKNOWN, r);
}
......@@ -1685,9 +1687,10 @@ private:
module->setattr(emitter, getEmptyOpInfo(unw_info), name.getBox(), val);
} else {
auto converted = val->makeConverted(emitter, val->getBoxType());
emitter.createCall3(unw_info, g.funcs.setGlobal, irstate->getGlobals(),
embedRelocatablePtr(name.getBox(), g.llvm_boxedstring_type_ptr),
converted->getValue());
emitter.createCall3(
unw_info, g.funcs.setGlobal, irstate->getGlobals(),
emitter.setType(embedRelocatablePtr(name.getBox(), g.llvm_boxedstring_type_ptr), RefType::BORROWED),
converted->getValue());
}
} else if (vst == ScopeInfo::VarScopeType::NAME) {
// TODO inefficient
......@@ -1802,8 +1805,9 @@ private:
// We could patchpoint this or try to avoid the overhead, but this should only
// happen when the assertion is actually thrown so I don't think it will be necessary.
static BoxedString* AssertionError_str = getStaticString("AssertionError");
llvm_args.push_back(emitter.createCall2(unw_info, g.funcs.getGlobal, irstate->getGlobals(),
embedRelocatablePtr(AssertionError_str, g.llvm_boxedstring_type_ptr)));
llvm_args.push_back(emitter.createCall2(
unw_info, g.funcs.getGlobal, irstate->getGlobals(),
emitter.setType(embedRelocatablePtr(AssertionError_str, g.llvm_boxedstring_type_ptr), RefType::BORROWED)));
ConcreteCompilerVariable* converted_msg = NULL;
if (node->msg) {
......
......@@ -305,10 +305,12 @@ void RefcountTracker::addRefcounts(IRGenState* irstate) {
llvm::Function* f = irstate->getLLVMFunction();
RefcountTracker* rt = irstate->getRefcounts();
fprintf(stderr, "Before refcounts:\n");
fprintf(stderr, "\033[35m");
dumpPrettyIR(f);
fprintf(stderr, "\033[0m");
if (VERBOSITY()) {
fprintf(stderr, "Before refcounts:\n");
fprintf(stderr, "\033[35m");
dumpPrettyIR(f);
fprintf(stderr, "\033[0m");
}
#ifndef NDEBUG
int num_untracked = 0;
......@@ -361,7 +363,7 @@ void RefcountTracker::addRefcounts(IRGenState* irstate) {
printf("missed a refcounted object: ");
fflush(stdout);
v->dump();
//abort();
abort();
}
};
......@@ -625,11 +627,13 @@ void RefcountTracker::addRefcounts(IRGenState* irstate) {
addDecrefs(op.operand, op.num_refs, op.insertion_pt);
}
fprintf(stderr, "After refcounts:\n");
fprintf(stderr, "\033[35m");
f->dump();
//dumpPrettyIR(f);
fprintf(stderr, "\033[0m");
if (VERBOSITY()) {
fprintf(stderr, "After refcounts:\n");
fprintf(stderr, "\033[35m");
f->dump();
//dumpPrettyIR(f);
fprintf(stderr, "\033[0m");
}
}
} // namespace pyston
......@@ -1601,6 +1601,7 @@ Box* nondataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, Box
if (rewrite_args) {
RewriterVar* r_rtn
= rewrite_args->rewriter->call(false, (void*)boxInstanceMethod, r_im_self, r_im_func, r_im_class);
r_rtn->setType(RefType::OWNED);
rewrite_args->setReturn(r_rtn, ReturnConvention::HAS_RETURN);
}
return boxInstanceMethod(im_self, im_func, im_class);
......@@ -2568,6 +2569,9 @@ template <ExceptionStyle S> Box* _getattrEntry(Box* obj, BoxedString* attr, void
Box* val;
if (rewriter.get()) {
rewriter->getArg(0)->setType(RefType::BORROWED);
rewriter->getArg(1)->setType(RefType::BORROWED);
Location dest;
TypeRecorder* recorder = rewriter->getTypeRecorder();
if (recorder)
......@@ -2824,7 +2828,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, STOLEN(Box*) attr_val) {
if (rewriter.get()) {
rewriter->getArg(0)->setType(RefType::BORROWED);
rewriter->getArg(1)->setType(RefType::BORROWED);
rewriter->getArg(2)->setType(RefType::BORROWED);
rewriter->getArg(2)->setType(RefType::OWNED);
auto r_cls = rewriter->getArg(0)->getAttr(offsetof(Box, cls));
// rewriter->trap();
......@@ -3790,13 +3794,10 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
}
}
if (rewrite_args) {
// TODO should probably rethink the whole vrefcounting thing here.
// which ones actually need new vrefs?
if (num_output_args >= 3) {
RELEASE_ASSERT(0, "not sure what to do here\n");
//for (int i = 0; i < num_output_args - 3; i++) {
//rewrite_args->args->getAttr(i * sizeof(Box*))->incref();
//}
for (int i = 0; i < num_output_args - 3; i++) {
rewrite_args->args->getAttr(i * sizeof(Box*))->setType(RefType::BORROWED)->refConsumed();
}
}
}
};
......@@ -3884,7 +3885,6 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
// We might have trouble if we have more output args than input args,
// such as if we need more space to pass defaults.
if (num_output_args > 3 && num_output_args > num_passed_args) {
assert(!rewrite_args && "check refcounting");
int arg_bytes_required = (num_output_args - 3) * sizeof(Box*);
RewriterVar* new_args = NULL;
......@@ -4193,9 +4193,11 @@ void rearrangeArgumentsInternal(ParamReceiveSpec paramspec, const ParamNames* pa
rewrite_args->arg3
= rewrite_args->rewriter->loadConst((intptr_t)default_obj, Location::forArg(2))->setType(RefType::BORROWED);
else {
assert(0 && "check refcounting");
rewrite_args->args->setAttr((arg_idx - 3) * sizeof(Box*),
rewrite_args->rewriter->loadConst((intptr_t)default_obj));
auto rvar = rewrite_args->rewriter->loadConst((intptr_t)default_obj);
rvar->setType(RefType::BORROWED);
rewrite_args->args->setAttr((arg_idx - 3) * sizeof(Box*), rvar);
if (default_obj)
rvar->refConsumed();
}
}
......@@ -4367,6 +4369,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
res = createGenerator(func, arg1, arg2, arg3, oargs);
if (rewrite_args) {
assert(0 && "check refcounting");
RewriterVar* r_arg1 = num_output_args >= 1 ? rewrite_args->arg1 : rewrite_args->rewriter->loadConst(0);
RewriterVar* r_arg2 = num_output_args >= 2 ? rewrite_args->arg2 : rewrite_args->rewriter->loadConst(0);
RewriterVar* r_arg3 = num_output_args >= 3 ? rewrite_args->arg3 : rewrite_args->rewriter->loadConst(0);
......@@ -4380,8 +4383,11 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
res = callCLFunc<S, rewritable>(md, rewrite_args, num_output_args, closure, NULL, func->globals, arg1, arg2,
arg3, oargs);
}
if (rewrite_args) {
RELEASE_ASSERT(num_output_args <= 3, "figure out vrefs for arg array");
if (rewrite_args && num_output_args > 3) {
for (int i = 0; i < num_output_args - 3; i++) {
rewrite_args->args->getAttr(i * sizeof(Box*))->setType(RefType::OWNED)->setNullable(true);
}
}
return res;
......@@ -6145,7 +6151,7 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) {
static BoxedString* hasnext_str = getStaticString("__hasnext__");
if (rewriter.get()) {
RewriterVar* r_o = rewriter->getArg(0);
RewriterVar* r_o = rewriter->getArg(0)->setType(RefType::BORROWED);
RewriterVar* r_cls = r_o->getAttr(offsetof(Box, cls));
GetattrRewriteArgs rewrite_args(rewriter.get(), r_cls, rewriter->getReturnDestination());
Box* r = typeLookup(o->cls, hasnext_str, &rewrite_args);
......@@ -6155,10 +6161,11 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) {
RewriterVar* rtn = rewrite_args.getReturn(ReturnConvention::HAS_RETURN);
rtn->addGuard((uint64_t)r);
rewriter->commitReturning(r_o);
return o;
return incref(o);
} else /* if (!r) */ {
rewrite_args.assertReturnConvention(ReturnConvention::NO_RETURN);
RewriterVar* var = rewriter.get()->call(true, (void*)createBoxedIterWrapper, rewriter->getArg(0));
var->setType(RefType::OWNED);
rewriter->commitReturning(var);
return createBoxedIterWrapper(o);
}
......@@ -6167,7 +6174,7 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) {
// assert((typeLookup(o->cls, hasnext_str) == NULL) == (o->cls->tpp_hasnext == object_cls->tpp_hasnext));
if (o->cls->tpp_hasnext == object_cls->tpp_hasnext)
return new BoxedIterWrapper(o);
return o;
return incref(o);
}
extern "C" Box* getPystonIter(Box* o) {
......
......@@ -445,9 +445,9 @@ public:
#ifdef DISABLE_INT_FREELIST
return Box::operator new (size, int_cls);
#else
if (free_list == NULL) {
if (unlikely(free_list == NULL)) {
free_list = fill_free_list();
RELEASE_ASSERT(free_list, "");
assert(free_list);
}
PyIntObject* v = free_list;
......
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