Commit f1e90870 authored by Kevin Modzelewski's avatar Kevin Modzelewski Committed by Kevin Modzelewski

Some basic compile()/exec refcounting

parent 5e13f1e3
...@@ -131,8 +131,11 @@ SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags fut ...@@ -131,8 +131,11 @@ SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, FutureFlags fut
cfg(NULL), cfg(NULL),
body(std::move(body)) { body(std::move(body)) {
assert(fn); assert(fn);
// TODO: we should track this reference correctly rather than making it a root
//gc::registerPermanentRoot(fn, true); // TODO: this is a very bad way of handling this:
incref(fn);
late_constants.push_back(fn);
this->fn = fn; this->fn = fn;
switch (ast->type) { switch (ast->type) {
......
...@@ -107,6 +107,11 @@ InternedStringPool& SourceInfo::getInternedStrings() { ...@@ -107,6 +107,11 @@ InternedStringPool& SourceInfo::getInternedStrings() {
return scoping->getInternedStrings(); return scoping->getInternedStrings();
} }
BORROWED(BoxedString*) SourceInfo::getFn() {
assert(fn->ob_refcnt >= 1);
return fn;
}
BORROWED(BoxedString*) SourceInfo::getName() { BORROWED(BoxedString*) SourceInfo::getName() {
assert(ast); assert(ast);
...@@ -323,7 +328,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -323,7 +328,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
FutureFlags future_flags = getFutureFlags(m->body, fn); FutureFlags future_flags = getFutureFlags(m->body, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m, true); ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
auto fn_str = getStaticString(fn); // XXX this is not a static string auto fn_str = boxString(fn);
AUTO_DECREF(fn_str);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, m->body, fn_str)); std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, future_flags, m, m->body, fn_str));
static BoxedString* doc_str = getStaticString("__doc__"); static BoxedString* doc_str = getStaticString("__doc__");
...@@ -525,7 +531,7 @@ extern "C" PyObject* PyEval_EvalCode(PyCodeObject* co, PyObject* globals, PyObje ...@@ -525,7 +531,7 @@ extern "C" PyObject* PyEval_EvalCode(PyCodeObject* co, PyObject* globals, PyObje
} }
} }
Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags) { void exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags) {
if (!globals) if (!globals)
globals = None; globals = None;
if (!locals) if (!locals)
...@@ -608,7 +614,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_f ...@@ -608,7 +614,7 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_f
} }
#endif #endif
if (PyString_AsStringAndSize(prog, &str, NULL)) if (PyString_AsStringAndSize(prog, &str, NULL))
return 0; throwCAPIException();
cf.cf_flags |= caller_future_flags & PyCF_MASK; cf.cf_flags |= caller_future_flags & PyCF_MASK;
if (cf.cf_flags) if (cf.cf_flags)
v = PyRun_StringFlags(str, Py_file_input, globals, locals, &cf); v = PyRun_StringFlags(str, Py_file_input, globals, locals, &cf);
...@@ -619,7 +625,9 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_f ...@@ -619,7 +625,9 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_f
if (!v) if (!v)
throwCAPIException(); throwCAPIException();
return v;
assert(v == None); // not really necessary but I think this should be true
Py_DECREF(v);
} }
// If a function version keeps failing its speculations, kill it (remove it // If a function version keeps failing its speculations, kill it (remove it
......
...@@ -39,7 +39,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm); ...@@ -39,7 +39,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm);
// will we always want to generate unique function names? (ie will this function always be reasonable?) // will we always want to generate unique function names? (ie will this function always be reasonable?)
CompiledFunction* cfForMachineFunctionName(const std::string&); CompiledFunction* cfForMachineFunctionName(const std::string&);
extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags); extern "C" void exec(Box* boxedCode, Box* globals, Box* locals, FutureFlags caller_future_flags);
} }
#endif #endif
...@@ -1394,6 +1394,7 @@ private: ...@@ -1394,6 +1394,7 @@ private:
std::vector<llvm::Value*> args{ cvar->getValue() }; std::vector<llvm::Value*> args{ cvar->getValue() };
llvm::Value* rtn = emitter.createCall(unw_info, g.funcs.repr, args); llvm::Value* rtn = emitter.createCall(unw_info, g.funcs.repr, args);
emitter.setType(rtn, RefType::BORROWED); // Well, really it's owned, and we handoff the ref to the bitcast
rtn = emitter.getBuilder()->CreateBitCast(rtn, g.llvm_value_type_ptr); rtn = emitter.getBuilder()->CreateBitCast(rtn, g.llvm_value_type_ptr);
emitter.setType(rtn, RefType::OWNED); emitter.setType(rtn, RefType::OWNED);
......
...@@ -409,7 +409,7 @@ public: ...@@ -409,7 +409,7 @@ public:
const std::vector<AST_stmt*> body; const std::vector<AST_stmt*> body;
BORROWED(BoxedString*) getName(); BORROWED(BoxedString*) getName();
BORROWED(BoxedString*) getFn() { return fn; } BORROWED(BoxedString*) getFn();
InternedString mangleName(InternedString id); InternedString mangleName(InternedString id);
......
...@@ -34,7 +34,7 @@ BORROWED(Box*) BoxedCode::name(Box* b, void*) { ...@@ -34,7 +34,7 @@ BORROWED(Box*) BoxedCode::name(Box* b, void*) {
return code->f->source->getName(); return code->f->source->getName();
} }
Box* BoxedCode::f_name(Box* b, void* arg) { Box* BoxedCode::co_name(Box* b, void* arg) {
return incref(name(b, arg)); return incref(name(b, arg));
} }
...@@ -46,7 +46,7 @@ BORROWED(Box*) BoxedCode::filename(Box* b, void*) { ...@@ -46,7 +46,7 @@ BORROWED(Box*) BoxedCode::filename(Box* b, void*) {
return code->f->source->getFn(); return code->f->source->getFn();
} }
Box* BoxedCode::f_filename(Box* b, void* arg) { Box* BoxedCode::co_filename(Box* b, void* arg) {
return incref(filename(b, arg)); return incref(filename(b, arg));
} }
...@@ -213,8 +213,8 @@ void setupCode() { ...@@ -213,8 +213,8 @@ void setupCode() {
code_cls->giveAttrBorrowed("__new__", None); // Hacky way of preventing users from instantiating this code_cls->giveAttrBorrowed("__new__", None); // Hacky way of preventing users from instantiating this
code_cls->giveAttrDescriptor("co_name", BoxedCode::f_name, NULL); code_cls->giveAttrDescriptor("co_name", BoxedCode::co_name, NULL);
code_cls->giveAttrDescriptor("co_filename", BoxedCode::f_filename, NULL); code_cls->giveAttrDescriptor("co_filename", BoxedCode::co_filename, NULL);
code_cls->giveAttrDescriptor("co_firstlineno", BoxedCode::firstlineno, NULL); code_cls->giveAttrDescriptor("co_firstlineno", BoxedCode::firstlineno, NULL);
code_cls->giveAttrDescriptor("co_argcount", BoxedCode::argcount, NULL); code_cls->giveAttrDescriptor("co_argcount", BoxedCode::argcount, NULL);
code_cls->giveAttrDescriptor("co_varnames", BoxedCode::varnames, NULL); code_cls->giveAttrDescriptor("co_varnames", BoxedCode::varnames, NULL);
......
...@@ -41,8 +41,8 @@ public: ...@@ -41,8 +41,8 @@ public:
// pointers could point to them. // pointers could point to them.
static BORROWED(Box*) name(Box* b, void*); static BORROWED(Box*) name(Box* b, void*);
static BORROWED(Box*) filename(Box* b, void*); static BORROWED(Box*) filename(Box* b, void*);
static Box* f_name(Box* b, void*); static Box* co_name(Box* b, void*);
static Box* f_filename(Box* b, void*); static Box* co_filename(Box* b, void*);
static Box* firstlineno(Box* b, void*); static Box* firstlineno(Box* b, void*);
static Box* argcount(Box* b, void*); static Box* argcount(Box* b, void*);
static Box* varnames(Box* b, void*); static Box* varnames(Box* b, void*);
......
# expected: reffail
import _ast import _ast
def ast_parse(source, filename='<unknown>', mode='exec'): def ast_parse(source, filename='<unknown>', mode='exec'):
......
# expected: reffail
print `42` print `42`
print `int` print `int`
print `2+3` print `2+3`
......
# expected: reffail
print compile print compile
c = compile("a", "test.py", "eval") c = compile("a", "test.py", "eval")
print type(c), c.co_filename, c.co_name print type(c), c.co_filename, c.co_name
......
# expected: reffail
from __future__ import division from __future__ import division
# compile() inherits the future flags of the parent module # compile() inherits the future flags of the parent module
......
# expected: reffail
try: try:
import __pyston__ import __pyston__
__pyston__.setOption("LAZY_SCOPING_ANALYSIS", 0) __pyston__.setOption("LAZY_SCOPING_ANALYSIS", 0)
......
# expected: reffail
# skip-if: '-O' in EXTRA_JIT_ARGS # skip-if: '-O' in EXTRA_JIT_ARGS
# statcheck: 4 <= noninit_count('num_deopt') < 50 # statcheck: 4 <= noninit_count('num_deopt') < 50
# statcheck: 1 <= stats["num_osr_exits"] <= 2 # statcheck: 1 <= stats["num_osr_exits"] <= 2
......
# expected: reffail
d = {} d = {}
exec "a = 5" in d exec "a = 5" in d
print d['a'] print d['a']
......
# expected: reffail
def f(): def f():
exec "a = 5" exec "a = 5"
print a print a
......
# expected: reffail
s = """ s = """
def f(): def f():
a = 1 a = 1
......
# expected: reffail
# fail-if: '-x' in EXTRA_JIT_ARGS # fail-if: '-x' in EXTRA_JIT_ARGS
# - we don't get syntax errors through the old parser correctly # - we don't get syntax errors through the old parser correctly
......
# expected: reffail
import test_package.import_target import test_package.import_target
import import_target import import_target
print print
......
# expected: reffail
# I really don't understand all the intricacies of unicode parsing, but apparently in addition to # I really don't understand all the intricacies of unicode parsing, but apparently in addition to
# Python-specific coding lines, you can put a unicode byte order mark to signify that the text # Python-specific coding lines, you can put a unicode byte order mark to signify that the text
# is encoded. # is encoded.
......
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