Commit 51b685f5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Basic refcounting in the interpreter

parent e3dcb351
......@@ -53,6 +53,8 @@
namespace pyston {
static int calculateNumVRegs(FunctionMetadata* md);
namespace {
class ASTInterpreter;
......@@ -76,8 +78,8 @@ public:
private:
Value createFunction(AST* node, AST_arguments* args, const std::vector<AST_stmt*>& body);
Value doBinOp(AST_expr* node, Value left, Value right, int op, BinExpType exp_type);
void doStore(AST_expr* node, Value value);
void doStore(AST_Name* name, Value value);
void doStore(AST_expr* node, STOLEN(Value) value);
void doStore(AST_Name* name, STOLEN(Value) value);
Box* doOSR(AST_Jump* node);
Value getNone();
......@@ -157,6 +159,18 @@ private:
bool should_jit;
public:
~ASTInterpreter() {
Py_XDECREF(frame_info.boxedLocals);
int nvregs = calculateNumVRegs(md);
for (int i = 0; i < nvregs; i++) {
Py_XDECREF(vregs[i]);
}
Py_DECREF(this->globals);
}
llvm::DenseMap<InternedString, int>& getSymVRegMap() {
assert(source_info->cfg);
return source_info->cfg->sym_vreg_map;
......@@ -224,6 +238,7 @@ void ASTInterpreter::setFrameInfo(const FrameInfo* frame_info) {
void ASTInterpreter::setGlobals(Box* globals) {
this->globals = globals;
Py_INCREF(globals);
}
ASTInterpreter::ASTInterpreter(FunctionMetadata* md, Box** vregs)
......@@ -285,6 +300,8 @@ void ASTInterpreter::startJITing(CFGBlock* block, int exit_offset) {
assert(ENABLE_BASELINEJIT);
assert(!jit);
assert(0 && "refcounting not set up");
auto& code_blocks = md->code_blocks;
JitCodeBlock* code_block = NULL;
if (!code_blocks.empty())
......@@ -340,7 +357,7 @@ Box* ASTInterpreter::execJITedBlock(CFGBlock* b) {
}
Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_block, AST_stmt* start_at) {
Value v;
Value v(nullptr, nullptr);
bool from_start = start_block == NULL && start_at == NULL;
......@@ -366,6 +383,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
}
interpreter.current_inst = s;
Py_XDECREF(v.o);
v = interpreter.visit_stmt(s);
}
} else {
......@@ -398,6 +416,7 @@ Box* ASTInterpreter::executeInner(ASTInterpreter& interpreter, CFGBlock* start_b
interpreter.current_inst = s;
if (interpreter.jit)
interpreter.jit->emitSetCurrentInst(s);
Py_XDECREF(v.o);
v = interpreter.visit_stmt(s);
}
}
......@@ -434,17 +453,19 @@ Value ASTInterpreter::doBinOp(AST_expr* node, Value left, Value right, int op, B
return Value();
}
void ASTInterpreter::doStore(AST_Name* node, Value value) {
void ASTInterpreter::doStore(AST_Name* node, STOLEN(Value) value) {
if (node->lookup_type == ScopeInfo::VarScopeType::UNKNOWN)
node->lookup_type = scope_info->getScopeTypeOfName(node->id);
InternedString name = node->id;
ScopeInfo::VarScopeType vst = node->lookup_type;
if (vst == ScopeInfo::VarScopeType::GLOBAL) {
assert(0 && "check refcounting");
if (jit)
jit->emitSetGlobal(globals, name.getBox(), value);
setGlobal(globals, name.getBox(), value.o);
} else if (vst == ScopeInfo::VarScopeType::NAME) {
assert(0 && "check refcounting");
if (jit)
jit->emitSetItemName(name.getBox(), value);
assert(frame_info.boxedLocals != NULL);
......@@ -453,6 +474,7 @@ void ASTInterpreter::doStore(AST_Name* node, Value value) {
} else {
bool closure = vst == ScopeInfo::VarScopeType::CLOSURE;
if (jit) {
assert(0 && "check refcounting");
if (!closure) {
bool is_live = source_info->getLiveness()->isLiveAtEnd(name, current_block);
if (is_live)
......@@ -465,9 +487,12 @@ void ASTInterpreter::doStore(AST_Name* node, Value value) {
assert(getSymVRegMap().count(name));
assert(getSymVRegMap()[name] == node->vreg);
Box* prev = vregs[node->vreg];
vregs[node->vreg] = value.o;
Py_XDECREF(prev);
if (closure) {
assert(0 && "check refcounting");
created_closure->elts[scope_info->getClosureOffset(name)] = value.o;
}
}
......@@ -524,7 +549,7 @@ void ASTInterpreter::doStore(AST_expr* node, Value value) {
}
Value ASTInterpreter::getNone() {
return Value(None, jit ? jit->imm(None) : NULL);
return Value(incref(None), jit ? jit->imm(None) : NULL);
}
Value ASTInterpreter::visit_unaryop(AST_UnaryOp* node) {
......@@ -538,7 +563,10 @@ Value ASTInterpreter::visit_unaryop(AST_UnaryOp* node) {
Value ASTInterpreter::visit_binop(AST_BinOp* node) {
Value left = visit_expr(node->left);
Value right = visit_expr(node->right);
return doBinOp(node, left, right, node->op_type, BinExpType::BinOp);
Value r = doBinOp(node, left, right, node->op_type, BinExpType::BinOp);
Py_DECREF(left.o);
Py_DECREF(right.o);
return r;
}
Value ASTInterpreter::visit_slice(AST_slice* node) {
......@@ -599,6 +627,8 @@ Value ASTInterpreter::visit_branch(AST_Branch* node) {
next_block = node->iftrue;
else
next_block = node->iffalse;
// TODO could potentially avoid doing this if we skip the incref in NONZERO
Py_DECREF(v.o);
if (jit) {
jit->emitJump(next_block);
......@@ -812,7 +842,10 @@ Value ASTInterpreter::visit_augBinOp(AST_AugBinOp* node) {
Value left = visit_expr(node->left);
Value right = visit_expr(node->right);
return doBinOp(node, left, right, node->op_type, BinExpType::AugBinOp);
Value r = doBinOp(node, left, right, node->op_type, BinExpType::AugBinOp);
Py_DECREF(left.o);
Py_DECREF(right.o);
return r;
}
Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
......@@ -879,6 +912,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
assert(node->args.size() == 1);
Value obj = visit_expr(node->args[0]);
v = Value(boxBool(nonzero(obj.o)), jit ? jit->emitNonzero(obj) : NULL);
Py_DECREF(obj.o);
} else if (node->opcode == AST_LangPrimitive::SET_EXC_INFO) {
assert(node->args.size() == 3);
......@@ -1235,8 +1269,7 @@ Value ASTInterpreter::visit_assign(AST_Assign* node) {
assert(node->targets.size() == 1 && "cfg should have lowered it to a single target");
Value v = visit_expr(node->value);
for (AST_expr* e : node->targets)
doStore(e, v);
doStore(node->targets[0], v);
return Value();
}
......@@ -1249,9 +1282,9 @@ Value ASTInterpreter::visit_print(AST_Print* node) {
jit->emitPrint(dest, var, node->nl);
if (node->dest)
printHelper(dest.o, var.o, node->nl);
printHelper(autoDecref(dest.o), autoXDecref(var.o), node->nl);
else
printHelper(getSysStdout(), var.o, node->nl);
printHelper(getSysStdout(), autoXDecref(var.o), node->nl);
return Value();
}
......@@ -1273,7 +1306,10 @@ Value ASTInterpreter::visit_compare(AST_Compare* node) {
RELEASE_ASSERT(node->comparators.size() == 1, "not implemented");
Value left = visit_expr(node->left);
Value right = visit_expr(node->comparators[0]);
return doBinOp(node, left, right, node->ops[0], BinExpType::Compare);
Value r = doBinOp(node, left, right, node->ops[0], BinExpType::Compare);
Py_DECREF(left.o);
Py_DECREF(right.o);
return r;
}
Value ASTInterpreter::visit_expr(AST_expr* node) {
......@@ -1424,6 +1460,7 @@ Value ASTInterpreter::visit_num(AST_Num* node) {
o = parent_module->getPureImaginaryConstant(node->n_float);
} else
RELEASE_ASSERT(0, "not implemented");
Py_INCREF(o);
return Value(o, jit ? jit->imm(o) : NULL);
}
......@@ -1499,10 +1536,12 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
if (jit)
v.var = jit->emitGetGlobal(globals, node->id.getBox());
assert(0 && "check refcounting");
v.o = getGlobal(globals, node->id.getBox());
return v;
}
case ScopeInfo::VarScopeType::DEREF: {
assert(0 && "check refcounting");
return Value(ASTInterpreterJitInterface::derefHelper(this, node->id),
jit ? jit->emitDeref(node->id) : NULL);
}
......@@ -1510,6 +1549,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
case ScopeInfo::VarScopeType::CLOSURE: {
Value v;
if (jit) {
assert(0 && "check refcounting");
bool is_live = false;
if (node->lookup_type == ScopeInfo::VarScopeType::FAST)
is_live = source_info->getLiveness()->isLiveAtEnd(node->id, current_block);
......@@ -1525,6 +1565,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
assert(getSymVRegMap()[node->id] == node->vreg);
Box* val = vregs[node->vreg];
if (val) {
Py_INCREF(val);
v.o = val;
return v;
}
......@@ -1533,6 +1574,7 @@ Value ASTInterpreter::visit_name(AST_Name* node) {
RELEASE_ASSERT(0, "should be unreachable");
}
case ScopeInfo::VarScopeType::NAME: {
assert(0 && "check refcounting");
Value v;
if (jit)
v.var = jit->emitGetBoxedLocal(node->id.getBox());
......@@ -1566,6 +1608,7 @@ Value ASTInterpreter::visit_list(AST_List* node) {
}
Value ASTInterpreter::visit_tuple(AST_Tuple* node) {
return getNone();
llvm::SmallVector<RewriterVar*, 8> items;
BoxedTuple* rtn = BoxedTuple::create(node->elts.size());
......@@ -1804,7 +1847,7 @@ Box* astInterpretFunction(FunctionMetadata* md, Box* closure, Box* generator, Bo
interpreter.initArguments((BoxedClosure*)closure, (BoxedGenerator*)generator, arg1, arg2, arg3, args);
Box* v = ASTInterpreter::execute(interpreter);
return v ? v : None;
return v ? v : incref(None);
}
Box* astInterpretFunctionEval(FunctionMetadata* md, Box* globals, Box* boxedLocals) {
......
......@@ -323,10 +323,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
FutureFlags future_flags = getFutureFlags(m->body, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, m->body, boxString(fn)));
auto fn_str = getStaticString(fn); // XXX this is not a static string
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, m->body, fn_str));
static BoxedString* doc_str = getStaticString("__doc__");
bm->setattr(doc_str, si->getDocString(), NULL);
bm->setattr(doc_str, autoDecref(si->getDocString()), NULL);
static BoxedString* builtins_str = getStaticString("__builtins__");
if (!bm->hasattr(builtins_str))
......@@ -338,6 +339,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_interpreted_module_toplevel");
Box* r = astInterpretFunction(md, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
assert(r == None);
Py_DECREF(r);
}
Box* evalOrExec(FunctionMetadata* md, Box* globals, Box* boxedLocals) {
......
......@@ -20,7 +20,8 @@ namespace pyston {
InternedString InternedStringPool::get(llvm::StringRef arg) {
// HACK: should properly track this liveness:
BoxedString* s = internStringImmortal(arg);
// XXX it's not a static string
BoxedString* s = getStaticString(arg);
#ifndef NDEBUG
return InternedString(s, this);
......
......@@ -164,13 +164,14 @@ extern "C" bool softspace(Box* b, bool newval) {
r = 0;
} else {
r = nonzero(gotten);
Py_DECREF(gotten);
}
} catch (ExcInfo e) {
r = 0;
}
try {
setattr(b, softspace_str, boxInt(newval));
setattr(b, softspace_str, autoDecref(boxInt(newval)));
} catch (ExcInfo e) {
r = 0;
}
......@@ -193,11 +194,12 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
callattrInternal<CXX, NOT_REWRITABLE>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1), space_str, 0, 0, 0,
0);
Box* str_or_unicode_var = (var->cls == unicode_cls) ? var : str(var);
Box* str_or_unicode_var = (var->cls == unicode_cls) ? incref(var) : str(var);
Box* write_rtn = callattrInternal<CXX, NOT_REWRITABLE>(dest, write_str, CLASS_OR_INST, 0, ArgPassSpec(1),
str_or_unicode_var, 0, 0, 0, 0);
autoDecref(str_or_unicode_var), 0, 0, 0, 0);
if (!write_rtn)
raiseAttributeError(dest, write_str->s());
Py_DECREF(write_rtn);
}
if (nl) {
......@@ -205,6 +207,8 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
newline_str, 0, 0, 0, 0);
if (!write_rtn)
raiseAttributeError(dest, write_str->s());
Py_DECREF(write_rtn);
if (!var)
softspace(dest, false);
}
......
......@@ -3427,21 +3427,24 @@ int BoxedModule::traverse(Box* _m, visitproc visit, void* arg) noexcept {
return 0;
}
template <typename CM>
void clearContiguousMap(CM& cm) {
for (auto&& p : cm) {
Py_DECREF(cm.getMapped(p.second));
}
cm.~ContiguousMap();
}
int BoxedModule::clear(Box* b) noexcept {
BoxedModule* self = static_cast<BoxedModule*>(b);
self->clearAttrs();
assert(!self->str_constants.size());
assert(!self->unicode_constants.size());
for (auto p : self->int_constants) {
Py_DECREF(self->int_constants.getMapped(p.second));
}
self->int_constants.~ContiguousMap();
assert(!self->float_constants.size());
assert(!self->imaginary_constants.size());
assert(!self->long_constants.size());
clearContiguousMap(self->str_constants);
clearContiguousMap(self->unicode_constants);
clearContiguousMap(self->int_constants);
clearContiguousMap(self->float_constants);
clearContiguousMap(self->imaginary_constants);
clearContiguousMap(self->long_constants);
assert(!self->keep_alive.size());
return 0;
......
......@@ -70,7 +70,7 @@ void setupSysEnd();
BORROWED(BoxedDict*) getSysModulesDict();
BORROWED(BoxedList*) getSysPath();
extern "C" Box* getSysStdout();
extern "C" BORROWED(Box*) getSysStdout();
extern "C" BoxedTuple* EmptyTuple;
extern "C" BoxedString* EmptyString;
......@@ -389,6 +389,9 @@ public:
template <typename B, bool Nullable = false> DecrefHandle<B, Nullable> autoDecref(B* b) {
return DecrefHandle<B, Nullable>(b);
}
template <typename B> DecrefHandle<B, true> autoXDecref(B* b) {
return DecrefHandle<B, true>(b);
}
template <typename B> B* incref(B* b) {
Py_INCREF(b);
......@@ -946,12 +949,12 @@ public:
BoxedModule() {} // noop constructor to disable zero-initialization of cls
std::string name();
BoxedString* getStringConstant(llvm::StringRef ast_str, bool intern = false);
Box* getUnicodeConstant(llvm::StringRef ast_str);
BoxedInt* getIntConstant(int64_t n);
BoxedFloat* getFloatConstant(double d);
Box* getPureImaginaryConstant(double d);
Box* getLongConstant(llvm::StringRef s);
BORROWED(BoxedString*) getStringConstant(llvm::StringRef ast_str, bool intern = false);
BORROWED(Box*) getUnicodeConstant(llvm::StringRef ast_str);
BORROWED(BoxedInt*) getIntConstant(int64_t n);
BORROWED(BoxedFloat*) getFloatConstant(double d);
BORROWED(Box*) getPureImaginaryConstant(double d);
BORROWED(Box*) getLongConstant(llvm::StringRef s);
static void dealloc(Box* b) noexcept;
static int traverse(Box* self, visitproc visit, void *arg) noexcept;
......
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