Commit 7199f0e3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

proper dealloc (with free), and imports

parent 3a2c0407
......@@ -133,7 +133,7 @@ PyAPI_DATA(PyTypeObject*) dictvalues_cls;
(PyDictKeys_Check(op) || PyDictItems_Check(op))
PyAPI_FUNC(PyObject *) PyDict_New(void) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key) PYSTON_NOEXCEPT;
PyAPI_FUNC(BORROWED(PyObject *)) PyDict_GetItem(PyObject *mp, PyObject *key) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) PyDict_Clear(PyObject *mp) PYSTON_NOEXCEPT;
......@@ -172,7 +172,7 @@ PyAPI_FUNC(int) PyDict_MergeFromSeq2(PyObject *d,
PyObject *seq2,
int override) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyDict_GetItemString(PyObject *dp, const char *key) PYSTON_NOEXCEPT;
PyAPI_FUNC(BORROWED(PyObject *)) PyDict_GetItemString(PyObject *dp, const char *key) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyDict_SetItemString(PyObject *dp, const char *key, PyObject *item) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyDict_DelItemString(PyObject *dp, const char *key) PYSTON_NOEXCEPT;
......
......@@ -17,7 +17,7 @@ PyAPI_DATA(PyTypeObject*) module_cls;
#define PyModule_CheckExact(op) (Py_TYPE(op) == &PyModule_Type)
PyAPI_FUNC(PyObject *) PyModule_New(const char *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyModule_GetDict(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(BORROWED(PyObject *)) PyModule_GetDict(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(char *) PyModule_GetName(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(char *) PyModule_GetFilename(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(void) _PyModule_Clear(PyObject *) PYSTON_NOEXCEPT;
......
......@@ -42,8 +42,8 @@ PyAPI_DATA(PyTypeObject*) tuple_cls;
PyAPI_FUNC(PyObject *) PyTuple_New(Py_ssize_t size) PYSTON_NOEXCEPT;
PyAPI_FUNC(Py_ssize_t) PyTuple_Size(PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyTuple_GetItem(PyObject *, Py_ssize_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *) PYSTON_NOEXCEPT;
PyAPI_FUNC(BORROWED(PyObject *)) PyTuple_GetItem(PyObject *, Py_ssize_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) PyTuple_SetItem(PyObject *, Py_ssize_t, STOLEN(PyObject *)) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyTuple_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(int) _PyTuple_Resize(PyObject **, Py_ssize_t) PYSTON_NOEXCEPT;
PyAPI_FUNC(PyObject *) PyTuple_Pack(Py_ssize_t, ...) PYSTON_NOEXCEPT;
......
......@@ -2249,12 +2249,17 @@ _PyExc_Init(void)
PyExc_MemoryErrorInst = BaseException_new(&_PyExc_MemoryError, NULL, NULL);
if (!PyExc_MemoryErrorInst)
Py_FatalError("Cannot pre-allocate MemoryError instance");
// Pyston addition:
PyGC_RegisterStaticConstant(PyExc_MemoryErrorInst);
PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RuntimeError, NULL, NULL);
if (!PyExc_RecursionErrorInst)
Py_FatalError("Cannot pre-allocate RuntimeError instance for "
"recursion errors");
else {
// Pyston addition:
PyGC_RegisterStaticConstant(PyExc_RecursionErrorInst);
PyBaseExceptionObject *err_inst =
(PyBaseExceptionObject *)PyExc_RecursionErrorInst;
PyObject *args_tuple;
......
......@@ -2965,8 +2965,7 @@ static void inherit_slots(PyTypeObject* type, PyTypeObject* base) noexcept {
* didn't define tp_free, and the base uses the
* default non-gc tp_free.
*/
// Pyston change: don't do this:
// type->tp_free = PyObject_GC_Del;
type->tp_free = PyObject_GC_Del;
}
/* else they didn't agree about gc, and there isn't something
* obvious to be done -- the type is on its own.
......@@ -3379,7 +3378,7 @@ extern "C" void PyType_RequestHcAttrs(PyTypeObject* cls, int offset) noexcept {
extern "C" void PyType_GiveHcAttrsDictDescr(PyTypeObject* cls) noexcept {
static BoxedString* dict_str = getStaticString("__dict__");
assert(!cls->hasattr(dict_str));
cls->giveAttr(dict_str, dict_descr);
cls->giveAttr(incref(dict_str), incref(dict_descr));
}
extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
......@@ -3422,7 +3421,7 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
cls->giveAttrBorrowed("__base__", base);
assert(cls->tp_dict == NULL);
cls->tp_dict = cls->getAttrWrapper();
cls->tp_dict = incref(cls->getAttrWrapper());
assert(cls->tp_name);
......
......@@ -661,7 +661,7 @@ public:
void delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args);
// Only valid for hc-backed instances:
Box* getAttrWrapper();
BORROWED(Box*) getAttrWrapper();
Box* reprIC();
BoxedString* reprICAsString();
......
......@@ -712,8 +712,7 @@ void setupSys() {
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_module->giveAttr("maxsize", boxInt(PY_SSIZE_T_MAX));
sys_flags_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedSysFlags), false, "flags");
sys_flags_cls = BoxedClass::create(type_cls, object_cls, 0, 0, sizeof(BoxedSysFlags), false, "flags");
sys_flags_cls->giveAttr(
"__new__", new BoxedFunction(FunctionMetadata::create((void*)BoxedSysFlags::__new__, UNKNOWN, 1, true, true)));
sys_flags_cls->tp_dealloc = (destructor)BoxedSysFlags::dealloc;
......@@ -730,7 +729,6 @@ void setupSys() {
#ifdef Py_USING_UNICODE
SET_SYS_FROM_STRING("maxunicode", PyInt_FromLong(PyUnicode_GetMax()));
#endif
sys_flags_cls->tp_mro = BoxedTuple::create({ sys_flags_cls, object_cls });
sys_flags_cls->freeze();
for (auto& md : sys_methods) {
......
......@@ -313,7 +313,7 @@ extern "C" int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* ite
abort();
}
return PyDict_SetItem(mp, key_s, item);
return PyDict_SetItem(mp, autoDecref(key_s), item);
}
extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
......
......@@ -384,14 +384,14 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
static Box* importSub(const std::string& name, BoxedString* full_name, Box* parent_module) {
BoxedDict* sys_modules = getSysModulesDict();
if (sys_modules->d.find(full_name) != sys_modules->d.end()) {
return sys_modules->d[full_name];
return incref(sys_modules->d[full_name]);
}
BoxedList* path_list;
if (parent_module == NULL || parent_module == None) {
path_list = NULL;
} else {
static BoxedString* path_str = internStringImmortal("__path__");
static BoxedString* path_str = getStaticString("__path__");
path_list = static_cast<BoxedList*>(getattrInternal<ExceptionStyle::CXX>(parent_module, path_str));
if (path_list == NULL || path_list->cls != list_cls) {
return None;
......@@ -472,10 +472,10 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf,
std::string subname(local_name.substr(0, len));
buf += subname;
result = importSub(subname, boxString(buf), mod);
result = importSub(subname, autoDecref(boxString(buf)), mod);
if (result == None && altmod != mod) {
/* Here, altmod must be None and mod must not be None */
result = importSub(subname, boxString(subname), altmod);
result = importSub(subname, autoDecref(boxString(subname)), altmod);
if (result != NULL && result != None) {
markMiss(buf);
......@@ -566,7 +566,7 @@ extern "C" PyObject* PyImport_ImportModuleLevel(const char* name, PyObject* glob
}
static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive) {
static BoxedString* path_str = internStringImmortal("__path__");
static BoxedString* path_str = getStaticString("__path__");
Box* pathlist = NULL;
try {
pathlist = getattrInternal<ExceptionStyle::CXX>(module, path_str);
......@@ -579,6 +579,9 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
// If it's not a package, then there's no sub-importing to do
return;
}
Py_DECREF(pathlist);
RELEASE_ASSERT(0, "check the refcounting here");
for (Box* _s : fromlist->pyElements()) {
RELEASE_ASSERT(PyString_Check(_s), "");
......@@ -614,8 +617,8 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
try {
// TODO: check if this has the same behaviour as the cpython implementation
BoxedList* silly_list = new BoxedList();
listAppendInternal(silly_list, boxString("__doc__"));
return import(0, silly_list, ((BoxedString*)module_name)->s());
listAppendInternal(silly_list, autoDecref(boxString("__doc__")));
return import(0, autoDecref(silly_list), ((BoxedString*)module_name)->s());
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
......@@ -623,7 +626,7 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
}
extern "C" PyObject* PyImport_ImportModule(const char* name) noexcept {
return PyImport_Import(boxString(name));
return PyImport_Import(autoDecref(boxString(name)));
}
extern "C" PyObject* PyImport_GetModuleDict(void) noexcept {
......
......@@ -189,8 +189,7 @@ bool calliter_hasnext(Box* b) {
void setupIter() {
seqiter_cls = BoxedClass::create(type_cls, object_cls, 0, 0, sizeof(BoxedSeqIter), false,
"iterator");
seqiter_cls = BoxedClass::create(type_cls, object_cls, 0, 0, sizeof(BoxedSeqIter), false, "iterator");
seqiter_cls->giveAttr("next", new BoxedFunction(FunctionMetadata::create((void*)seqiterNext, UNKNOWN, 1)));
seqiter_cls->giveAttr("__hasnext__",
......
......@@ -154,7 +154,7 @@ extern "C" bool softspace(Box* b, bool newval) {
return (bool)r;
}
static BoxedString* softspace_str = internStringImmortal("softspace");
static BoxedString* softspace_str = getStaticString("softspace");
bool r;
Box* gotten = NULL;
......@@ -179,9 +179,9 @@ extern "C" bool softspace(Box* b, bool newval) {
}
extern "C" void printHelper(Box* dest, Box* var, bool nl) {
static BoxedString* write_str = internStringImmortal("write");
static BoxedString* newline_str = internStringImmortal("\n");
static BoxedString* space_str = internStringImmortal(" ");
static BoxedString* write_str = getStaticString("write");
static BoxedString* newline_str = getStaticString("\n");
static BoxedString* space_str = getStaticString(" ");
if (dest == None)
dest = getSysStdout();
......@@ -399,8 +399,8 @@ void BoxedClass::freeze() {
}
std::vector<BoxedClass*> classes;
BoxedClass::BoxedClass(BoxedClass* base, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, const char* name)
BoxedClass::BoxedClass(BoxedClass* base, int attrs_offset, int weaklist_offset, int instance_size, bool is_user_defined,
const char* name, destructor dealloc, freefunc free)
: attrs(HiddenClass::makeSingleton()),
attrs_offset(attrs_offset),
is_constant(false),
......@@ -452,21 +452,24 @@ BoxedClass::BoxedClass(BoxedClass* base, int attrs_offset, int weaklist_offset,
assert(cls == type_cls || PyType_Check(this));
}
if (is_user_defined) {
tp_dealloc = subtype_dealloc;
} else {
// We don't want default types like dict to have subtype_dealloc as a destructor.
// In CPython, they would have their custom tp_dealloc, except that we don't
// need them in Pyston due to GC.
//
// What's the problem with having subtype_dealloc? In some cases like defdict_dealloc,
// the destructor calls another destructor thinking it's the parent, but ends up in the
// same destructor again (since child destructors are found first by subtype_dealloc)
// causing an infinite recursion loop.
tp_dealloc = dealloc_null;
has_safe_tp_dealloc = true;
if (dealloc)
tp_dealloc = dealloc;
else {
assert(base && base->tp_dealloc);
tp_dealloc = base->tp_dealloc;
}
tp_free = default_free;
if (PyType_IS_GC(this))
assert(tp_free != PyObject_Del);
if (free)
tp_free = free;
else {
assert(base && base->tp_free);
tp_free = base->tp_free;
}
assert(tp_dealloc);
assert(tp_free);
if (!base) {
assert(this == object_cls);
......@@ -490,11 +493,12 @@ BoxedClass::BoxedClass(BoxedClass* base, int attrs_offset, int weaklist_offset,
}
}
BoxedClass* BoxedClass::create(BoxedClass* metaclass, BoxedClass* base, int attrs_offset,
int weaklist_offset, int instance_size, bool is_user_defined, const char* name) {
BoxedClass* BoxedClass::create(BoxedClass* metaclass, BoxedClass* base, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, const char* name, destructor dealloc,
freefunc free) {
assert(!is_user_defined);
BoxedClass* made = new (metaclass, 0)
BoxedClass(base, attrs_offset, weaklist_offset, instance_size, is_user_defined, name);
BoxedClass(base, attrs_offset, weaklist_offset, instance_size, is_user_defined, name, dealloc, free);
// While it might be ok if these were set, it'd indicate a difference in
// expectations as to who was going to calculate them:
......@@ -517,19 +521,101 @@ void BoxedClass::finishInitialization() {
}
assert(!this->tp_dict);
this->tp_dict = this->getAttrWrapper();
this->tp_dict = incref(this->getAttrWrapper());
commonClassSetup(this);
tp_flags |= Py_TPFLAGS_READY;
}
static int
subtype_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_FatalError("unimplemented");
#if 0
PyTypeObject *type, *base;
traverseproc basetraverse;
/* Find the nearest base with a different tp_traverse,
and traverse slots while we're at it */
type = Py_TYPE(self);
base = type;
while ((basetraverse = base->tp_traverse) == subtype_traverse) {
if (Py_SIZE(base)) {
int err = traverse_slots(base, self, visit, arg);
if (err)
return err;
}
base = base->tp_base;
assert(base);
}
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr)
Py_VISIT(*dictptr);
}
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
/* For a heaptype, the instances count as references
to the type. Traverse the type so the collector
can find cycles involving this link. */
Py_VISIT(type);
if (basetraverse)
return basetraverse(self, visit, arg);
return 0;
#endif
}
static int
subtype_clear(PyObject *self)
{
Py_FatalError("unimplemented");
#if 0
PyTypeObject *type, *base;
inquiry baseclear;
/* Find the nearest base with a different tp_clear
and clear slots while we're at it */
type = Py_TYPE(self);
base = type;
while ((baseclear = base->tp_clear) == subtype_clear) {
if (Py_SIZE(base))
clear_slots(base, self);
base = base->tp_base;
assert(base);
}
/* Clear the instance dict (if any), to break cycles involving only
__dict__ slots (as in the case 'self.__dict__ is self'). */
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr)
Py_CLEAR(*dictptr);
}
if (baseclear)
return baseclear(self);
return 0;
#endif
}
BoxedHeapClass::BoxedHeapClass(BoxedClass* base, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, BoxedString* name)
: BoxedClass(base, attrs_offset, weaklist_offset, instance_size, is_user_defined, name->data()),
: BoxedClass(base, attrs_offset, weaklist_offset, instance_size, is_user_defined, name->data(), subtype_dealloc, NULL),
ht_name(name),
ht_slots(NULL) {
assert(is_user_defined);
/* Always override allocation strategy to use regular heap */
this->tp_alloc = PyType_GenericAlloc;
if (this->tp_flags & Py_TPFLAGS_HAVE_GC) {
this->tp_free = PyObject_GC_Del;
this->tp_traverse = subtype_traverse;
this->tp_clear = subtype_clear;
} else
this->tp_free = PyObject_Del;
tp_as_number = &as_number;
tp_as_mapping = &as_mapping;
tp_as_sequence = &as_sequence;
......@@ -566,7 +652,7 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base,
}
std::string getFullNameOfClass(BoxedClass* cls) {
static BoxedString* module_str = internStringImmortal("__module__");
static BoxedString* module_str = getStaticString("__module__");
Box* b = cls->getattr(module_str);
if (!b)
return cls->tp_name;
......@@ -1733,7 +1819,7 @@ return gotten;
// came from the class or not.
Box* processDescriptorOrNull(Box* obj, Box* inst, Box* owner) {
if (DEBUG >= 2) {
static BoxedString* get_str = internStringImmortal("__get__");
static BoxedString* get_str = getStaticString("__get__");
assert((obj->cls->tp_descr_get == NULL) == (typeLookup(obj->cls, get_str) == NULL));
}
if (obj->cls->tp_descr_get) {
......@@ -1756,7 +1842,6 @@ Box* processDescriptor(Box* obj, Box* inst, Box* owner) {
template <bool IsType, Rewritable rewritable>
Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call,
Box** bind_obj_out, RewriterVar** r_bind_obj_out) {
RELEASE_ASSERT(0, "need to check the refcounting here\n");
if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
......@@ -1774,8 +1859,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
assert(obj->cls != closure_cls);
static BoxedString* get_str = internStringImmortal("__get__");
static BoxedString* set_str = internStringImmortal("__set__");
static BoxedString* get_str = getStaticString("__get__");
static BoxedString* set_str = getStaticString("__set__");
// Handle descriptor logic here.
// A descriptor is either a data descriptor or a non-data descriptor.
......@@ -1810,6 +1895,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
} else {
descr = typeLookup(obj->cls, attr);
}
RELEASE_ASSERT(!descr, "need to check the refcounting for this");
// Check if it's a data descriptor
descrgetfunc descr_get = NULL;
......@@ -1818,6 +1904,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
Box* _get_ = NULL;
RewriterVar* r_get = NULL;
if (descr) {
RELEASE_ASSERT(0, "need to check the refcounting for this");
descr_get = descr->cls->tp_descr_get;
if (rewrite_args)
......@@ -1928,6 +2015,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
if (unlikely(rewrite_args && !descr && obj->cls != instancemethod_cls
&& rewrite_args->rewriter->aggressiveness() < 40
&& attr->interned_state == SSTATE_INTERNED_IMMORTAL)) {
RELEASE_ASSERT(0, "need to check the refcounting for this");
class Helper {
public:
static Box* call(Box* obj, BoxedString* attr) { return obj->getattr(attr); }
......@@ -1942,6 +2030,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
Box* val;
if (rewrite_args) {
RELEASE_ASSERT(0, "need to check the refcounting for this");
GetattrRewriteArgs hrewrite_args(rewrite_args->rewriter, rewrite_args->obj, rewrite_args->destination);
val = obj->getattr(attr, &hrewrite_args);
......@@ -1956,9 +2045,12 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
val = obj->getattr(attr);
}
if (val)
if (val) {
Py_INCREF(val);
return val;
}
} else {
RELEASE_ASSERT(0, "need to check the refcounting for this");
// More complicated when obj is a type
// We have to look up the attr in the entire
// class hierarchy, and we also have to check if it is a descriptor,
......@@ -2022,6 +2114,7 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
// If descr and __get__ exist, then call __get__
if (descr) {
RELEASE_ASSERT(0, "need to check the refcounting for this");
// Special cases first
Box* res = nondataDescriptorInstanceSpecialCases<rewritable>(rewrite_args, obj, descr, r_descr, for_call,
bind_obj_out, r_bind_obj_out);
......@@ -2302,7 +2395,7 @@ void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* r
assert(val);
static BoxedString* set_str = internStringImmortal("__set__");
static BoxedString* set_str = getStaticString("__set__");
// TODO this should be in type_setattro
if (obj->cls == type_cls) {
......@@ -2389,7 +2482,7 @@ void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* r
if (PyType_Check(obj)) {
BoxedClass* self = static_cast<BoxedClass*>(obj);
static BoxedString* base_str = internStringImmortal("__base__");
static BoxedString* base_str = getStaticString("__base__");
if (attr->s() == "__base__" && self->getattr(base_str))
raiseExcHelper(TypeError, "readonly attribute");
......@@ -2456,7 +2549,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val) {
return;
} else if (tp_setattro != PyObject_GenericSetAttr) {
static BoxedString* setattr_str = internStringImmortal("__setattr__");
static BoxedString* setattr_str = getStaticString("__setattr__");
if (rewriter.get()) {
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0)->getAttr(offsetof(Box, cls)),
Location::any());
......@@ -2477,7 +2570,7 @@ extern "C" void setattr(Box* obj, BoxedString* attr, Box* attr_val) {
// We should probably add this as a GC root, but we can cheat a little bit since
// we know it's not going to get deallocated:
static Box* object_setattr = object_cls->getattr(internStringImmortal("__setattr__"));
static Box* object_setattr = object_cls->getattr(getStaticString("__setattr__"));
assert(object_setattr);
// I guess this check makes it ok for us to just rely on having guarded on the value of setattr without
......@@ -2623,8 +2716,8 @@ extern "C" bool nonzero(Box* obj) {
return r;
}
static BoxedString* nonzero_str = internStringImmortal("__nonzero__");
static BoxedString* len_str = internStringImmortal("__len__");
static BoxedString* nonzero_str = getStaticString("__nonzero__");
static BoxedString* len_str = getStaticString("__len__");
// try __nonzero__
CallattrRewriteArgs crewrite_args(rewriter.get(), r_obj,
......@@ -2752,7 +2845,7 @@ BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI
rewrite_args = NULL;
}
static BoxedString* len_str = internStringImmortal("__len__");
static BoxedString* len_str = getStaticString("__len__");
if (S == CAPI) {
assert(!rewrite_args && "implement me");
......@@ -4211,7 +4304,7 @@ Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec ar
Box* rtn;
static BoxedString* call_str = internStringImmortal("__call__");
static BoxedString* call_str = getStaticString("__call__");
if (DEBUG >= 2) {
assert((obj->cls->tp_call == NULL) == (typeLookup<rewritable>(obj->cls, call_str, NULL) == NULL));
......@@ -4732,7 +4825,7 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
}
if (op_type == AST_TYPE::In || op_type == AST_TYPE::NotIn) {
static BoxedString* contains_str = internStringImmortal("__contains__");
static BoxedString* contains_str = getStaticString("__contains__");
// The checks for this branch are taken from CPython's PySequence_Contains
if (PyType_HasFeature(rhs->cls, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
......@@ -4940,7 +5033,7 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
if (rrtn != NULL && rrtn != NotImplemented)
return rrtn;
static BoxedString* cmp_str = internStringImmortal("__cmp__");
static BoxedString* cmp_str = getStaticString("__cmp__");
lrtn = callattrInternal1<CXX, NOT_REWRITABLE>(lhs, cmp_str, CLASS_ONLY, NULL, ArgPassSpec(1), rhs);
if (lrtn && lrtn != NotImplemented) {
return boxBool(convert3wayCompareResultToBool(lrtn, op_type));
......@@ -5294,8 +5387,8 @@ Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args)
return r;
}
static BoxedString* getitem_str = internStringImmortal("__getitem__");
static BoxedString* getslice_str = internStringImmortal("__getslice__");
static BoxedString* getitem_str = getStaticString("__getitem__");
static BoxedString* getslice_str = getStaticString("__getslice__");
Box* rtn;
try {
......@@ -5438,8 +5531,8 @@ extern "C" void setitem(Box* target, Box* slice, Box* value) {
std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "setitem"));
static BoxedString* setitem_str = internStringImmortal("__setitem__");
static BoxedString* setslice_str = internStringImmortal("__setslice__");
static BoxedString* setitem_str = getStaticString("__setitem__");
static BoxedString* setslice_str = getStaticString("__setslice__");
auto&& m = target->cls->tp_as_mapping;
if (m && m->mp_ass_subscript && m->mp_ass_subscript != slot_mp_ass_subscript) {
......@@ -5491,8 +5584,8 @@ extern "C" void delitem(Box* target, Box* slice) {
std::unique_ptr<Rewriter> rewriter(
Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 2, "delitem"));
static BoxedString* delitem_str = internStringImmortal("__delitem__");
static BoxedString* delslice_str = internStringImmortal("__delslice__");
static BoxedString* delitem_str = getStaticString("__delitem__");
static BoxedString* delslice_str = getStaticString("__delslice__");
Box* rtn;
if (rewriter.get()) {
......@@ -5571,7 +5664,7 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs*
// first check whether the deleting attribute is a descriptor
Box* clsAttr = typeLookup(obj->cls, attr);
if (clsAttr != NULL) {
static BoxedString* delete_str = internStringImmortal("__delete__");
static BoxedString* delete_str = getStaticString("__delete__");
Box* delAttr = typeLookup(static_cast<BoxedClass*>(clsAttr->cls), delete_str);
if (delAttr != NULL) {
......@@ -5600,7 +5693,7 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs*
if (PyType_Check(obj)) {
BoxedClass* self = static_cast<BoxedClass*>(obj);
static BoxedString* base_str = internStringImmortal("__base__");
static BoxedString* base_str = getStaticString("__base__");
if (attr->s() == "__base__" && self->getattr(base_str))
raiseExcHelper(TypeError, "readonly attribute");
......@@ -5617,7 +5710,7 @@ extern "C" void delattrGeneric(Box* obj, BoxedString* attr, DelattrRewriteArgs*
}
extern "C" void delattrInternal(Box* obj, BoxedString* attr, DelattrRewriteArgs* rewrite_args) {
static BoxedString* delattr_str = internStringImmortal("__delattr__");
static BoxedString* delattr_str = getStaticString("__delattr__");
Box* delAttr = typeLookup(obj->cls, delattr_str);
if (delAttr != NULL) {
Box* rtn = runtimeCallInternal<CXX, NOT_REWRITABLE>(delAttr, NULL, ArgPassSpec(2), obj, attr, NULL, NULL, NULL);
......@@ -5655,7 +5748,7 @@ extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o) {
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(
__builtin_extract_return_addr(__builtin_return_address(0)), 1, "createBoxedIterWrapperIfNeeded"));
static BoxedString* hasnext_str = internStringImmortal("__hasnext__");
static BoxedString* hasnext_str = getStaticString("__hasnext__");
if (rewriter.get()) {
RewriterVar* r_o = rewriter->getArg(0);
......@@ -5768,7 +5861,7 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
"of the metaclasses of all its bases");
}
static BoxedString* new_box = internStringImmortal(new_str.c_str());
static BoxedString* new_box = getStaticString(new_str.c_str());
if (winner != metatype) {
if (getattr(winner, new_box) != getattr(type_cls, new_box)) {
CallattrFlags callattr_flags
......@@ -5787,7 +5880,7 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
assert(PyType_Check(base));
// Handle slots
static BoxedString* slots_str = internStringImmortal("__slots__");
static BoxedString* slots_str = getStaticString("__slots__");
Box* boxedSlots = PyDict_GetItem(attr_dict, slots_str);
int add_dict = 0;
int add_weak = 0;
......@@ -5961,7 +6054,7 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
}
if (made->instancesHaveHCAttrs() || made->instancesHaveDictAttrs()) {
static BoxedString* dict_str = internStringImmortal("__dict__");
static BoxedString* dict_str = getStaticString("__dict__");
made->setattr(dict_str, dict_descr, NULL);
}
......@@ -5974,16 +6067,16 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
made->setattr(s, p.second, NULL);
}
static BoxedString* module_str = internStringImmortal("__module__");
static BoxedString* module_str = getStaticString("__module__");
if (!made->hasattr(module_str)) {
Box* gl = getGlobalsDict();
static BoxedString* name_str = internStringImmortal("__name__");
static BoxedString* name_str = getStaticString("__name__");
Box* attr = PyDict_GetItem(gl, name_str);
if (attr)
made->giveAttr(module_str, attr);
}
static BoxedString* doc_str = internStringImmortal("__doc__");
static BoxedString* doc_str = getStaticString("__doc__");
if (!made->hasattr(doc_str))
made->giveAttr(doc_str, None);
......@@ -6273,11 +6366,11 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) {
RELEASE_ASSERT(PyModule_Check(_from_module), "%s", _from_module->cls->tp_name);
BoxedModule* from_module = static_cast<BoxedModule*>(_from_module);
static BoxedString* all_str = internStringImmortal("__all__");
static BoxedString* all_str = getStaticString("__all__");
Box* all = from_module->getattr(all_str);
if (all) {
static BoxedString* getitem_str = internStringImmortal("__getitem__");
static BoxedString* getitem_str = getStaticString("__getitem__");
Box* all_getitem = typeLookup(all->cls, getitem_str);
if (!all_getitem)
raiseExcHelper(TypeError, "'%s' object does not support indexing", getTypeName(all));
......
......@@ -382,7 +382,10 @@ extern "C" int PyTuple_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) no
BoxedTuple* t = static_cast<BoxedTuple*>(op);
RELEASE_ASSERT(i >= 0 && i < t->size(), "");
auto olditem = t->elts[i];
t->elts[i] = newitem;
Py_XDECREF(olditem);
return 0;
}
......@@ -399,6 +402,7 @@ extern "C" PyObject* PyTuple_Pack(Py_ssize_t n, ...) noexcept {
for (Py_ssize_t i = 0; i < n; i++) {
PyObject* o = va_arg(vargs, PyObject*);
Py_INCREF(o);
PyTuple_SetItem(result, i, o);
}
va_end(vargs);
......
......@@ -2498,11 +2498,13 @@ Box* Box::getAttrWrapper() {
auto new_hcls = hcls->getAttrwrapperChild();
appendNewHCAttr(aw, NULL);
attrs->hcls = new_hcls;
Py_DECREF(aw);
return aw;
} else {
assert(hcls->type == HiddenClass::SINGLETON);
appendNewHCAttr(aw, NULL);
hcls->appendAttrwrapper();
Py_DECREF(aw);
return aw;
}
}
......@@ -3223,12 +3225,6 @@ extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
return unicode;
}
// We don't need CPython's version of tp_free since we have GC.
// We still need to set tp_free to something and not a NULL pointer,
// because C extensions might still call tp_free from tp_dealloc.
void default_free(void*) {
}
void dealloc_null(Box* box) {
assert(box->cls->tp_del == NULL);
}
......@@ -3423,6 +3419,10 @@ void BoxedClass::dealloc(Box* b) noexcept {
#endif
}
static void object_dealloc(PyObject* self) {
Py_TYPE(self)->tp_free(self);
}
#ifndef Py_REF_DEBUG
#define PRINT_TOTAL_REFS()
......@@ -3448,15 +3448,14 @@ void setupRuntime() {
type_cls = static_cast<BoxedClass*>(PyObject_MALLOC(sizeof(BoxedClass)));
PyObject_INIT(object_cls, type_cls);
PyObject_INIT(type_cls, type_cls);
::new (object_cls) BoxedClass(NULL, 0, 0, sizeof(Box), false, "object");
::new (object_cls) BoxedClass(NULL, 0, 0, sizeof(Box), false, "object", object_dealloc, PyObject_Del);
object_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
::new (type_cls) BoxedClass(object_cls, offsetof(BoxedClass, attrs),
offsetof(BoxedClass, tp_weaklist), sizeof(BoxedHeapClass), false, "type");
::new (type_cls) BoxedClass(object_cls, offsetof(BoxedClass, attrs), offsetof(BoxedClass, tp_weaklist),
sizeof(BoxedHeapClass), false, "type", BoxedClass::dealloc, PyObject_GC_Del);
type_cls->has_safe_tp_dealloc = false;
type_cls->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
type_cls->tp_itemsize = sizeof(BoxedHeapClass::SlotOffset);
type_cls->tp_dealloc = BoxedClass::dealloc;
// XXX silly that we have to set this again
new (&object_cls->attrs) HCAttrs(HiddenClass::makeSingleton());
......@@ -3468,18 +3467,18 @@ void setupRuntime() {
object_cls->tp_new = object_new;
type_cls->tp_getattro = type_getattro;
none_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(Box), false, "NoneType");
none_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(Box), false, "NoneType", NULL, NULL);
None = new (none_cls) Box();
constants.push_back(None);
assert(None->cls);
// You can't actually have an instance of basestring
basestring_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(Box), false, "basestring");
basestring_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(Box), false, "basestring", NULL, NULL);
// We add 1 to the tp_basicsize of the BoxedString in order to hold the null byte at the end.
// We use offsetof(BoxedString, s_data) as opposed to sizeof(BoxedString) so that we can
// use the extra padding bytes at the end of the BoxedString.
str_cls = new (0) BoxedClass(basestring_cls, 0, 0, offsetof(BoxedString, s_data) + 1, false, "str");
str_cls = new (0) BoxedClass(basestring_cls, 0, 0, offsetof(BoxedString, s_data) + 1, false, "str", NULL, NULL);
str_cls->tp_flags |= Py_TPFLAGS_STRING_SUBCLASS;
str_cls->tp_itemsize = sizeof(char);
......@@ -3498,61 +3497,55 @@ void setupRuntime() {
// Not sure why CPython defines sizeof(PyTupleObject) to include one element,
// but we copy that, which means we have to subtract that extra pointer to get the tp_basicsize:
tuple_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedTuple) - sizeof(Box*), false, "tuple");
BoxedClass(object_cls, 0, 0, sizeof(BoxedTuple) - sizeof(Box*), false, "tuple", (destructor)tupledealloc, NULL);
tuple_cls->tp_dealloc = (destructor)tupledealloc;
tuple_cls->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
tuple_cls->tp_itemsize = sizeof(Box*);
tuple_cls->tp_mro = BoxedTuple::create({ tuple_cls, object_cls });
EmptyTuple = BoxedTuple::create({});
constants.push_back(EmptyTuple);
list_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedList), false, "list");
list_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedList), false, "list", BoxedList::dealloc, NULL);
list_cls->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
list_cls->tp_dealloc = BoxedList::dealloc;
pyston_getset_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedGetsetDescriptor), false, "getset_descriptor");
BoxedClass(object_cls, 0, 0, sizeof(BoxedGetsetDescriptor), false, "getset_descriptor", NULL, NULL);
attrwrapper_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(AttrWrapper), false, "attrwrapper");
dict_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedDict), false, "dict");
BoxedClass(object_cls, 0, 0, sizeof(AttrWrapper), false, "attrwrapper", NULL, NULL);
dict_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedDict), false, "dict", BoxedDict::dealloc, NULL);
dict_cls->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
dict_cls->tp_dealloc = BoxedDict::dealloc;
file_cls = new (0) BoxedClass(object_cls, 0, offsetof(BoxedFile, weakreflist),
sizeof(BoxedFile), false, "file");
file_cls->tp_dealloc = file_dealloc;
int_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedInt), false, "int");
sizeof(BoxedFile), false, "file", file_dealloc, NULL);
int_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedInt), false, "int", NULL, NULL);
int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
int_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
bool_cls = new (0) BoxedClass(int_cls, 0, 0, sizeof(BoxedBool), false, "bool");
bool_cls = new (0) BoxedClass(int_cls, 0, 0, sizeof(BoxedBool), false, "bool", NULL, NULL);
bool_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
complex_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedComplex), false, "complex");
complex_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedComplex), false, "complex", NULL, NULL);
complex_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
long_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedLong), false, "long");
long_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedLong), false, "long", NULL, NULL);
long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
long_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
float_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedFloat), false, "float");
float_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedFloat), false, "float", NULL, NULL);
float_cls->tp_flags &= ~Py_TPFLAGS_HAVE_GC;
function_cls = new (0)
BoxedClass(object_cls, offsetof(BoxedFunction, attrs),
offsetof(BoxedFunction, weakreflist), sizeof(BoxedFunction), false, "function");
offsetof(BoxedFunction, weakreflist), sizeof(BoxedFunction), false, "function", functionDtor, NULL);
builtin_function_or_method_cls = new (0)
BoxedClass(object_cls, 0, offsetof(BoxedBuiltinFunctionOrMethod, weakreflist),
sizeof(BoxedBuiltinFunctionOrMethod), false, "builtin_function_or_method");
function_cls->tp_dealloc = builtin_function_or_method_cls->tp_dealloc = functionDtor;
sizeof(BoxedBuiltinFunctionOrMethod), false, "builtin_function_or_method", functionDtor, NULL);
function_cls->has_safe_tp_dealloc = builtin_function_or_method_cls->has_safe_tp_dealloc = true;
module_cls = new (0) BoxedClass(object_cls, offsetof(BoxedModule, attrs), 0,
sizeof(BoxedModule), false, "module");
module_cls->tp_dealloc = BoxedModule::dealloc;
sizeof(BoxedModule), false, "module", BoxedModule::dealloc, NULL);
member_descriptor_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedMemberDescriptor), false, "member_descriptor");
BoxedClass(object_cls, 0, 0, sizeof(BoxedMemberDescriptor), false, "member_descriptor", NULL, NULL);
capifunc_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(BoxedCApiFunction), false, "capifunc");
BoxedClass(object_cls, 0, 0, sizeof(BoxedCApiFunction), false, "capifunc", NULL, NULL);
method_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedMethodDescriptor),
false, "method_descriptor");
false, "method_descriptor", NULL, NULL);
wrapperobject_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedWrapperObject),
false, "method-wrapper");
false, "method-wrapper", NULL, NULL);
wrapperdescr_cls = new (0) BoxedClass(object_cls, 0, 0,
sizeof(BoxedWrapperDescriptor), false, "wrapper_descriptor");
sizeof(BoxedWrapperDescriptor), false, "wrapper_descriptor", NULL, NULL);
EmptyString = new (0) BoxedString("");
constants.push_back(EmptyString);
......@@ -3660,8 +3653,7 @@ void setupRuntime() {
instancemethod_cls = BoxedClass::create(type_cls, object_cls, 0,
offsetof(BoxedInstanceMethod, im_weakreflist), sizeof(BoxedInstanceMethod),
false, "instancemethod");
instancemethod_cls->tp_dealloc = BoxedInstanceMethod::dealloc;
false, "instancemethod", BoxedInstanceMethod::dealloc);
slice_cls
= BoxedClass::create(type_cls, object_cls, 0, 0, sizeof(BoxedSlice), false, "slice");
......
......@@ -68,7 +68,7 @@ void setupImport();
void setupAST();
void setupSysEnd();
BoxedDict* getSysModulesDict();
BORROWED(BoxedDict*) getSysModulesDict();
BoxedList* getSysPath();
extern "C" Box* getSysStdout();
......@@ -173,7 +173,6 @@ struct ExcInfo;
void setCAPIException(const ExcInfo& e);
// Finalizer-related
void default_free(void*);
void dealloc_null(Box* box);
void file_dealloc(Box*) noexcept;
......@@ -276,11 +275,12 @@ public:
SlotOffset* slotOffsets() { return (BoxedClass::SlotOffset*)((char*)this + this->cls->tp_basicsize); }
// These should only be used for builtin types:
static BoxedClass* create(BoxedClass* metatype, BoxedClass* base, int attrs_offset,
int weaklist_offset, int instance_size, bool is_user_defined, const char* name);
static BoxedClass* create(BoxedClass* metatype, BoxedClass* base, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, const char* name, destructor dealloc = NULL,
freefunc free = NULL);
BoxedClass(BoxedClass* base, int attrs_offset, int weaklist_offset, int instance_size,
bool is_user_defined, const char* name);
bool is_user_defined, const char* name, destructor dealloc, freefunc free);
DEFAULT_CLASS_VAR(type_cls, sizeof(SlotOffset));
......
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