Commit 790f24d2 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'tp_alloc'

parents 91321622 1ee311d6
...@@ -160,12 +160,17 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t) PYSTON_NO ...@@ -160,12 +160,17 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t) PYSTON_NO
#define PyObject_NewVar(type, typeobj, n) \ #define PyObject_NewVar(type, typeobj, n) \
( (type *) _PyObject_NewVar((typeobj), (n)) ) ( (type *) _PyObject_NewVar((typeobj), (n)) )
// Pyston change: these are function calls now
#if 0
/* Macros trading binary compatibility for speed. See also pymem.h. /* Macros trading binary compatibility for speed. See also pymem.h.
Note that these macros expect non-NULL object pointers.*/ Note that these macros expect non-NULL object pointers.*/
#define PyObject_INIT(op, typeobj) \ #define PyObject_INIT(op, typeobj) \
( Py_TYPE(op) = (typeobj), (op) ) ( Py_TYPE(op) = (typeobj), (op) )
#define PyObject_INIT_VAR(op, typeobj, size) \ #define PyObject_INIT_VAR(op, typeobj, size) \
( Py_SIZE(op) = (size), PyObject_INIT((op), (typeobj)) ) ( Py_SIZE(op) = (size), PyObject_INIT((op), (typeobj)) )
#endif
#define PyObject_INIT(op, typeobj) PyObject_Init((PyObject*)(op), (PyTypeObject*)(typeobj))
#define PyObject_INIT_VAR(op, typeobj, size) PyObject_InitVar((PyObject*)(op), (PyTypeObject*)(typeobj), size)
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize ) #define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
......
...@@ -44,7 +44,9 @@ private: ...@@ -44,7 +44,9 @@ private:
public: public:
BoxedCApiFunction(int ml_flags, Box* passthrough, const char* name, PyCFunction func) BoxedCApiFunction(int ml_flags, Box* passthrough, const char* name, PyCFunction func)
: Box(capifunc_cls), ml_flags(ml_flags), passthrough(passthrough), name(name), func(func) {} : ml_flags(ml_flags), passthrough(passthrough), name(name), func(func) {}
DEFAULT_CLASS(capifunc_cls);
static BoxedString* __repr__(BoxedCApiFunction* self) { static BoxedString* __repr__(BoxedCApiFunction* self) {
assert(self->cls == capifunc_cls); assert(self->cls == capifunc_cls);
...@@ -88,7 +90,9 @@ public: ...@@ -88,7 +90,9 @@ public:
BoxedClass* type; BoxedClass* type;
void* wrapped; void* wrapped;
BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type, void* wrapped) BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type, void* wrapped)
: Box(wrapperdescr_cls), wrapper(wrapper), type(type), wrapped(wrapped) {} : wrapper(wrapper), type(type), wrapped(wrapped) {}
DEFAULT_CLASS(wrapperdescr_cls);
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner); static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
}; };
...@@ -98,7 +102,9 @@ public: ...@@ -98,7 +102,9 @@ public:
BoxedWrapperDescriptor* descr; BoxedWrapperDescriptor* descr;
Box* obj; Box* obj;
BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : Box(wrapperobject_cls), descr(descr), obj(obj) {} BoxedWrapperObject(BoxedWrapperDescriptor* descr, Box* obj) : descr(descr), obj(obj) {}
DEFAULT_CLASS(wrapperobject_cls);
static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) { static Box* __call__(BoxedWrapperObject* self, Box* args, Box* kwds) {
assert(self->cls == wrapperobject_cls); assert(self->cls == wrapperobject_cls);
...@@ -128,7 +134,9 @@ public: ...@@ -128,7 +134,9 @@ public:
PyMethodDef* method; PyMethodDef* method;
BoxedClass* type; BoxedClass* type;
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : Box(method_cls), method(method), type(type) {} BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) {}
DEFAULT_CLASS(method_cls);
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner) { static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == method_cls, ""); RELEASE_ASSERT(self->cls == method_cls, "");
......
...@@ -986,7 +986,7 @@ Value ASTInterpreter::visit_set(AST_Set* node) { ...@@ -986,7 +986,7 @@ Value ASTInterpreter::visit_set(AST_Set* node) {
for (AST_expr* e : node->elts) for (AST_expr* e : node->elts)
set.insert(visit_expr(e).o); set.insert(visit_expr(e).o);
return new BoxedSet(std::move(set), set_cls); return new BoxedSet(std::move(set));
} }
Value ASTInterpreter::visit_str(AST_Str* node) { Value ASTInterpreter::visit_str(AST_Str* node) {
......
...@@ -354,14 +354,6 @@ enum class GCKind : uint8_t { ...@@ -354,14 +354,6 @@ enum class GCKind : uint8_t {
extern "C" void* gc_alloc(size_t nbytes, GCKind kind); extern "C" void* gc_alloc(size_t nbytes, GCKind kind);
} }
class PythonGCObject {
public:
void* operator new(size_t size) __attribute__((visibility("default"))) {
return gc_alloc(size, gc::GCKind::PYTHON);
}
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
};
class ConservativeGCObject { class ConservativeGCObject {
public: public:
void* operator new(size_t size) __attribute__((visibility("default"))) { void* operator new(size_t size) __attribute__((visibility("default"))) {
...@@ -370,14 +362,6 @@ public: ...@@ -370,14 +362,6 @@ public:
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); } void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
}; };
class UntrackedGCObject {
public:
void* operator new(size_t size) __attribute__((visibility("default"))) {
return gc_alloc(size, gc::GCKind::UNTRACKED);
}
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
};
class HiddenClass; class HiddenClass;
extern HiddenClass* root_hcls; extern HiddenClass* root_hcls;
...@@ -399,26 +383,19 @@ public: ...@@ -399,26 +383,19 @@ public:
class BoxedString; class BoxedString;
class Box : public PythonGCObject { class Box {
public: public:
// Add a no-op constructor to make sure that we don't zero-initialize cls
Box() {}
void* operator new(size_t size, BoxedClass* cls) __attribute__((visibility("default")));
void operator delete(void* ptr) __attribute__((visibility("default"))) { abort(); }
// Note: cls gets initialized in the new() function.
BoxedClass* cls; BoxedClass* cls;
llvm::iterator_range<BoxIterator> pyElements(); llvm::iterator_range<BoxIterator> pyElements();
Box(BoxedClass* cls) : cls(cls) {
// if (TRACK_ALLOCATIONS) {
// int id = Stats::getStatId("allocated_" + *getNameOfClass(c));
// Stats::log(id);
//}
// the only way cls should be NULL is if we're creating the type_cls
// object itself:
if (cls == NULL) {
ASSERT(type_cls == NULL, "should pass a non-null cls here");
} else {
}
}
HCAttrs* getAttrsPtr(); HCAttrs* getAttrsPtr();
void setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args); void setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args);
...@@ -439,12 +416,20 @@ public: ...@@ -439,12 +416,20 @@ public:
}; };
static_assert(offsetof(Box, cls) == offsetof(struct _object, ob_type), ""); static_assert(offsetof(Box, cls) == offsetof(struct _object, ob_type), "");
#define DEFAULT_CLASS(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
return Box::operator new(size, cls); \
} \
void* operator new(size_t size) __attribute__((visibility("default"))) { \
return Box::operator new(size, default_cls); \
}
// CPython C API compatibility class: // CPython C API compatibility class:
class BoxVar : public Box { class BoxVar : public Box {
public: public:
Py_ssize_t ob_size; Py_ssize_t ob_size;
BoxVar(BoxedClass* cls, Py_ssize_t ob_size) : Box(cls), ob_size(ob_size) {} BoxVar(Py_ssize_t ob_size) : ob_size(ob_size) {}
}; };
static_assert(offsetof(BoxVar, ob_size) == offsetof(struct _varobject, ob_size), ""); static_assert(offsetof(BoxVar, ob_size) == offsetof(struct _varobject, ob_size), "");
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "core/ast.h" #include "core/ast.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/capi.h"
#include "runtime/classobj.h" #include "runtime/classobj.h"
#include "runtime/ics.h" #include "runtime/ics.h"
#include "runtime/import.h" #include "runtime/import.h"
...@@ -262,8 +263,11 @@ Box* open(Box* arg1, Box* arg2) { ...@@ -262,8 +263,11 @@ Box* open(Box* arg1, Box* arg2) {
const std::string& mode = static_cast<BoxedString*>(arg2)->s; const std::string& mode = static_cast<BoxedString*>(arg2)->s;
FILE* f = fopen(fn.c_str(), mode.c_str()); FILE* f = fopen(fn.c_str(), mode.c_str());
if (!f) if (!f) {
raiseExcHelper(IOError, "[Errno %d] %s: '%s'", errno, strerror(errno), fn.c_str()); PyErr_SetFromErrnoWithFilename(IOError, fn.c_str());
checkAndThrowCAPIException();
abort(); // unreachable;
}
return new BoxedFile(f, fn, mode); return new BoxedFile(f, fn, mode);
} }
...@@ -533,7 +537,7 @@ Box* exceptionNew1(BoxedClass* cls) { ...@@ -533,7 +537,7 @@ Box* exceptionNew1(BoxedClass* cls) {
class BoxedException : public Box { class BoxedException : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
BoxedException(BoxedClass* cls) : Box(cls) {} BoxedException() {}
}; };
Box* exceptionNew2(BoxedClass* cls, Box* message) { Box* exceptionNew2(BoxedClass* cls, Box* message) {
...@@ -548,11 +552,7 @@ Box* exceptionNew(BoxedClass* cls, BoxedTuple* args) { ...@@ -548,11 +552,7 @@ Box* exceptionNew(BoxedClass* cls, BoxedTuple* args) {
raiseExcHelper(TypeError, "BaseException.__new__(%s): %s is not a subtype of BaseException", raiseExcHelper(TypeError, "BaseException.__new__(%s): %s is not a subtype of BaseException",
getNameOfClass(cls)->c_str(), getNameOfClass(cls)->c_str()); getNameOfClass(cls)->c_str(), getNameOfClass(cls)->c_str());
assert(cls->tp_basicsize >= sizeof(BoxedException)); BoxedException* rtn = new (cls) BoxedException();
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
memset((char*)mem + sizeof(BoxedException), 0, cls->tp_basicsize - sizeof(BoxedException));
BoxedException* rtn = ::new (mem) BoxedException(cls);
initUserAttrs(rtn, cls);
// TODO: this should be a MemberDescriptor and set during init // TODO: this should be a MemberDescriptor and set during init
if (args->elts.size() == 1) if (args->elts.size() == 1)
...@@ -587,7 +587,7 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int ...@@ -587,7 +587,7 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int
if (size == 0) if (size == 0)
size = base->tp_basicsize; size = base->tp_basicsize;
BoxedClass* cls = new BoxedHeapClass(type_cls, base, NULL, offsetof(BoxedException, attrs), size, false); BoxedClass* cls = new BoxedHeapClass(base, NULL, offsetof(BoxedException, attrs), size, false);
cls->giveAttr("__name__", boxStrConstant(name)); cls->giveAttr("__name__", boxStrConstant(name));
cls->giveAttr("__module__", boxStrConstant("exceptions")); cls->giveAttr("__module__", boxStrConstant("exceptions"));
...@@ -609,8 +609,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d ...@@ -609,8 +609,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
try { try {
BoxedClass* base = Exception; BoxedClass* base = Exception;
BoxedClass* cls BoxedClass* cls = new BoxedHeapClass(base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), true);
= new BoxedHeapClass(type_cls, base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), true);
char* dot_pos = strchr(name, '.'); char* dot_pos = strchr(name, '.');
RELEASE_ASSERT(dot_pos, ""); RELEASE_ASSERT(dot_pos, "");
...@@ -634,7 +633,9 @@ private: ...@@ -634,7 +633,9 @@ private:
public: public:
BoxedEnumerate(BoxIterator iterator_begin, BoxIterator iterator_end, int64_t idx) BoxedEnumerate(BoxIterator iterator_begin, BoxIterator iterator_end, int64_t idx)
: Box(enumerate_cls), iterator(iterator_begin), iterator_end(iterator_end), idx(idx) {} : iterator(iterator_begin), iterator_end(iterator_end), idx(idx) {}
DEFAULT_CLASS(enumerate_cls);
static Box* new_(Box* cls, Box* obj, Box* start) { static Box* new_(Box* cls, Box* obj, Box* start) {
RELEASE_ASSERT(cls == enumerate_cls, ""); RELEASE_ASSERT(cls == enumerate_cls, "");
...@@ -906,11 +907,11 @@ void setupBuiltins() { ...@@ -906,11 +907,11 @@ void setupBuiltins() {
builtins_module->giveAttr("print", new BoxedFunction(boxRTFunction((void*)print, NONE, 0, 0, true, true))); builtins_module->giveAttr("print", new BoxedFunction(boxRTFunction((void*)print, NONE, 0, 0, true, true)));
notimplemented_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false); notimplemented_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType")); notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1))); notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
notimplemented_cls->freeze(); notimplemented_cls->freeze();
NotImplemented = new Box(notimplemented_cls); NotImplemented = new (notimplemented_cls) Box();
gc::registerPermanentRoot(NotImplemented); gc::registerPermanentRoot(NotImplemented);
builtins_module->giveAttr("NotImplemented", NotImplemented); builtins_module->giveAttr("NotImplemented", NotImplemented);
...@@ -1015,8 +1016,7 @@ void setupBuiltins() { ...@@ -1015,8 +1016,7 @@ void setupBuiltins() {
builtins_module->giveAttr("__import__", new BoxedFunction(boxRTFunction((void*)bltinImport, UNKNOWN, 1))); builtins_module->giveAttr("__import__", new BoxedFunction(boxRTFunction((void*)bltinImport, UNKNOWN, 1)));
enumerate_cls enumerate_cls = new BoxedHeapClass(object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), false);
= new BoxedHeapClass(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), false);
enumerate_cls->giveAttr("__name__", boxStrConstant("enumerate")); enumerate_cls->giveAttr("__name__", boxStrConstant("enumerate"));
enumerate_cls->giveAttr( enumerate_cls->giveAttr(
"__new__", "__new__",
...@@ -1091,9 +1091,9 @@ void setupBuiltins() { ...@@ -1091,9 +1091,9 @@ void setupBuiltins() {
builtins_module->giveAttr("classmethod", classmethod_cls); builtins_module->giveAttr("classmethod", classmethod_cls);
PyExc_RecursionErrorInst = new BoxedException(RuntimeError); PyExc_RecursionErrorInst = new (RuntimeError) BoxedException();
gc::registerPermanentRoot(PyExc_RecursionErrorInst); gc::registerPermanentRoot(PyExc_RecursionErrorInst);
PyExc_MemoryErrorInst = new BoxedException(MemoryError); PyExc_MemoryErrorInst = new (MemoryError) BoxedException();
gc::registerPermanentRoot(PyExc_MemoryErrorInst); gc::registerPermanentRoot(PyExc_MemoryErrorInst);
} }
} }
...@@ -158,13 +158,15 @@ class BoxedSysFlags : public Box { ...@@ -158,13 +158,15 @@ class BoxedSysFlags : public Box {
public: public:
Box* division_warning, *bytes_warning, *no_user_site; Box* division_warning, *bytes_warning, *no_user_site;
BoxedSysFlags() : Box(sys_flags_cls) { BoxedSysFlags() {
auto zero = boxInt(0); auto zero = boxInt(0);
division_warning = zero; division_warning = zero;
bytes_warning = zero; bytes_warning = zero;
no_user_site = zero; no_user_site = zero;
} }
DEFAULT_CLASS(sys_flags_cls);
static void gcHandler(GCVisitor* v, Box* _b) { static void gcHandler(GCVisitor* v, Box* _b) {
assert(_b->cls == sys_flags_cls); assert(_b->cls == sys_flags_cls);
boxGCHandler(v, _b); boxGCHandler(v, _b);
...@@ -235,7 +237,7 @@ void setupSys() { ...@@ -235,7 +237,7 @@ void setupSys() {
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX)); sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_flags_cls = new BoxedHeapClass(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, sizeof(BoxedSysFlags), false); sys_flags_cls = new BoxedHeapClass(object_cls, BoxedSysFlags::gcHandler, 0, sizeof(BoxedSysFlags), false);
sys_flags_cls->giveAttr("__name__", boxStrConstant("flags")); sys_flags_cls->giveAttr("__name__", boxStrConstant("flags"));
sys_flags_cls->giveAttr("__new__", sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true))); new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
......
...@@ -63,17 +63,6 @@ int Py_Py3kWarningFlag; ...@@ -63,17 +63,6 @@ int Py_Py3kWarningFlag;
BoxedClass* capifunc_cls; BoxedClass* capifunc_cls;
extern "C" PyObject* PyType_GenericAlloc(PyTypeObject* cls, Py_ssize_t nitems) noexcept {
RELEASE_ASSERT(nitems == 0, "unimplemented");
RELEASE_ASSERT(cls->tp_itemsize == 0, "unimplemented");
auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
memset(rtn, 0, cls->tp_basicsize);
PyObject_Init(rtn, cls);
return rtn;
}
BoxedClass* wrapperdescr_cls, *wrapperobject_cls; BoxedClass* wrapperdescr_cls, *wrapperobject_cls;
Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner) { Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner) {
...@@ -142,26 +131,6 @@ extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) noexcep ...@@ -142,26 +131,6 @@ extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) noexcep
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
RELEASE_ASSERT(op, "");
RELEASE_ASSERT(tp, "");
assert(gc::isValidGCObject(op));
assert(gc::isValidGCObject(tp));
Py_TYPE(op) = tp;
// I think CPython defers the dict creation (equivalent of our initUserAttrs) to the
// first time that an attribute gets set.
// Our HCAttrs object already includes this optimization of no-allocation-if-empty,
// but it's nice to initialize the hcls here so we don't have to check it on every getattr/setattr.
// TODO It does mean that anything not defering to this function will have to call
// initUserAttrs themselves, though.
initUserAttrs(op, tp);
return op;
}
extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_ssize_t size) noexcept { extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_ssize_t size) noexcept {
assert(gc::isValidGCObject(op)); assert(gc::isValidGCObject(op));
assert(gc::isValidGCObject(tp)); assert(gc::isValidGCObject(tp));
...@@ -1342,7 +1311,7 @@ BoxedModule* importTestExtension(const std::string& name) { ...@@ -1342,7 +1311,7 @@ BoxedModule* importTestExtension(const std::string& name) {
} }
void setupCAPI() { void setupCAPI() {
capifunc_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedCApiFunction), false); capifunc_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedCApiFunction), false);
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc")); capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr("__repr__",
...@@ -1354,7 +1323,7 @@ void setupCAPI() { ...@@ -1354,7 +1323,7 @@ void setupCAPI() {
capifunc_cls->freeze(); capifunc_cls->freeze();
method_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false); method_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false);
method_cls->giveAttr("__name__", boxStrConstant("method")); method_cls->giveAttr("__name__", boxStrConstant("method"));
method_cls->giveAttr("__get__", method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
...@@ -1362,13 +1331,13 @@ void setupCAPI() { ...@@ -1362,13 +1331,13 @@ void setupCAPI() {
0, true, true))); 0, true, true)));
method_cls->freeze(); method_cls->freeze();
wrapperdescr_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperDescriptor), false); wrapperdescr_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedWrapperDescriptor), false);
wrapperdescr_cls->giveAttr("__name__", boxStrConstant("wrapper_descriptor")); wrapperdescr_cls->giveAttr("__name__", boxStrConstant("wrapper_descriptor"));
wrapperdescr_cls->giveAttr("__get__", wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->freeze(); wrapperdescr_cls->freeze();
wrapperobject_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperObject), false); wrapperobject_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedWrapperObject), false);
wrapperobject_cls->giveAttr("__name__", boxStrConstant("method-wrapper")); wrapperobject_cls->giveAttr("__name__", boxStrConstant("method-wrapper"));
wrapperobject_cls->giveAttr( wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
......
...@@ -83,7 +83,7 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) { ...@@ -83,7 +83,7 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
raiseExcHelper(TypeError, "PyClass_New: bases must be a tuple"); raiseExcHelper(TypeError, "PyClass_New: bases must be a tuple");
BoxedTuple* bases = static_cast<BoxedTuple*>(_bases); BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
BoxedClassobj* made = new BoxedClassobj(cls, name, bases); BoxedClassobj* made = new (cls) BoxedClassobj(name, bases);
made->giveAttr("__module__", boxString(getCurrentModule()->name())); made->giveAttr("__module__", boxString(getCurrentModule()->name()));
made->giveAttr("__doc__", None); made->giveAttr("__doc__", None);
...@@ -270,9 +270,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) { ...@@ -270,9 +270,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
} }
void setupClassobj() { void setupClassobj() {
classobj_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedClassobj::gcHandler, offsetof(BoxedClassobj, attrs), classobj_cls = new BoxedHeapClass(object_cls, &BoxedClassobj::gcHandler, offsetof(BoxedClassobj, attrs),
sizeof(BoxedClassobj), false); sizeof(BoxedClassobj), false);
instance_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedInstance::gcHandler, offsetof(BoxedInstance, attrs), instance_cls = new BoxedHeapClass(object_cls, &BoxedInstance::gcHandler, offsetof(BoxedInstance, attrs),
sizeof(BoxedInstance), false); sizeof(BoxedInstance), false);
classobj_cls->giveAttr("__name__", boxStrConstant("classobj")); classobj_cls->giveAttr("__name__", boxStrConstant("classobj"));
......
...@@ -38,8 +38,7 @@ public: ...@@ -38,8 +38,7 @@ public:
BoxedTuple* bases; BoxedTuple* bases;
BoxedString* name; BoxedString* name;
BoxedClassobj(BoxedClass* metaclass, BoxedString* name, BoxedTuple* bases) BoxedClassobj(BoxedString* name, BoxedTuple* bases) : bases(bases), name(name) {}
: Box(metaclass), bases(bases), name(name) {}
static void gcHandler(GCVisitor* v, Box* _o) { static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == classobj_cls); assert(_o->cls == classobj_cls);
...@@ -55,7 +54,9 @@ public: ...@@ -55,7 +54,9 @@ public:
BoxedClassobj* inst_cls; BoxedClassobj* inst_cls;
BoxedInstance(BoxedClassobj* inst_cls) : Box(instance_cls), inst_cls(inst_cls) {} BoxedInstance(BoxedClassobj* inst_cls) : inst_cls(inst_cls) {}
DEFAULT_CLASS(instance_cls);
static void gcHandler(GCVisitor* v, Box* _o) { static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == instance_cls); assert(_o->cls == instance_cls);
......
...@@ -95,7 +95,7 @@ Box* dictViewKeys(BoxedDict* self) { ...@@ -95,7 +95,7 @@ Box* dictViewKeys(BoxedDict* self) {
raiseExcHelper(TypeError, "descriptor 'viewkeys' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'viewkeys' requires a 'dict' object but received a '%s'",
getTypeName(self)->c_str()); getTypeName(self)->c_str());
} }
BoxedDictView* rtn = new BoxedDictView(self, dict_keys_cls); BoxedDictView* rtn = new (dict_keys_cls) BoxedDictView(self);
return rtn; return rtn;
} }
...@@ -104,7 +104,7 @@ Box* dictViewValues(BoxedDict* self) { ...@@ -104,7 +104,7 @@ Box* dictViewValues(BoxedDict* self) {
raiseExcHelper(TypeError, "descriptor 'viewvalues' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'viewvalues' requires a 'dict' object but received a '%s'",
getTypeName(self)->c_str()); getTypeName(self)->c_str());
} }
BoxedDictView* rtn = new BoxedDictView(self, dict_values_cls); BoxedDictView* rtn = new (dict_values_cls) BoxedDictView(self);
return rtn; return rtn;
} }
...@@ -113,7 +113,7 @@ Box* dictViewItems(BoxedDict* self) { ...@@ -113,7 +113,7 @@ Box* dictViewItems(BoxedDict* self) {
raiseExcHelper(TypeError, "descriptor 'viewitems' requires a 'dict' object but received a '%s'", raiseExcHelper(TypeError, "descriptor 'viewitems' requires a 'dict' object but received a '%s'",
getTypeName(self)->c_str()); getTypeName(self)->c_str());
} }
BoxedDictView* rtn = new BoxedDictView(self, dict_items_cls); BoxedDictView* rtn = new (dict_items_cls) BoxedDictView(self);
return rtn; return rtn;
} }
...@@ -465,11 +465,11 @@ extern "C" void dictViewGCHandler(GCVisitor* v, Box* b) { ...@@ -465,11 +465,11 @@ extern "C" void dictViewGCHandler(GCVisitor* v, Box* b) {
} }
void setupDict() { void setupDict() {
dict_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), false); dict_iterator_cls = new BoxedHeapClass(object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), false);
dict_keys_cls = new BoxedHeapClass(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false); dict_keys_cls = new BoxedHeapClass(object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false);
dict_values_cls = new BoxedHeapClass(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false); dict_values_cls = new BoxedHeapClass(object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false);
dict_items_cls = new BoxedHeapClass(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false); dict_items_cls = new BoxedHeapClass(object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false);
dict_cls->giveAttr("__name__", boxStrConstant("dict")); dict_cls->giveAttr("__name__", boxStrConstant("dict"));
dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, BOXED_INT, 1))); dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, BOXED_INT, 1)));
......
...@@ -34,6 +34,8 @@ public: ...@@ -34,6 +34,8 @@ public:
const IteratorType type; const IteratorType type;
BoxedDictIterator(BoxedDict* d, IteratorType type); BoxedDictIterator(BoxedDict* d, IteratorType type);
DEFAULT_CLASS(dict_iterator_cls);
}; };
Box* dictGetitem(BoxedDict* self, Box* k); Box* dictGetitem(BoxedDict* self, Box* k);
...@@ -49,7 +51,7 @@ Box* dictIterNext(Box* self); ...@@ -49,7 +51,7 @@ Box* dictIterNext(Box* self);
class BoxedDictView : public Box { class BoxedDictView : public Box {
public: public:
BoxedDict* d; BoxedDict* d;
BoxedDictView(BoxedDict* d, BoxedClass* view_cls); BoxedDictView(BoxedDict* d);
}; };
Box* dictViewKeysIter(Box* self); Box* dictViewKeysIter(Box* self);
......
...@@ -548,21 +548,21 @@ BoxedFloat* _floatNew(Box* a) { ...@@ -548,21 +548,21 @@ BoxedFloat* _floatNew(Box* a) {
if (a->cls == float_cls) { if (a->cls == float_cls) {
return static_cast<BoxedFloat*>(a); return static_cast<BoxedFloat*>(a);
} else if (isSubclass(a->cls, float_cls)) { } else if (isSubclass(a->cls, float_cls)) {
return new BoxedFloat(float_cls, static_cast<BoxedFloat*>(a)->d); return new BoxedFloat(static_cast<BoxedFloat*>(a)->d);
} else if (isSubclass(a->cls, int_cls)) { } else if (isSubclass(a->cls, int_cls)) {
return new BoxedFloat(float_cls, static_cast<BoxedInt*>(a)->n); return new BoxedFloat(static_cast<BoxedInt*>(a)->n);
} else if (a->cls == str_cls) { } else if (a->cls == str_cls) {
const std::string& s = static_cast<BoxedString*>(a)->s; const std::string& s = static_cast<BoxedString*>(a)->s;
if (s == "nan") if (s == "nan")
return new BoxedFloat(float_cls, NAN); return new BoxedFloat(NAN);
if (s == "-nan") if (s == "-nan")
return new BoxedFloat(float_cls, -NAN); return new BoxedFloat(-NAN);
if (s == "inf") if (s == "inf")
return new BoxedFloat(float_cls, INFINITY); return new BoxedFloat(INFINITY);
if (s == "-inf") if (s == "-inf")
return new BoxedFloat(float_cls, -INFINITY); return new BoxedFloat(-INFINITY);
return new BoxedFloat(float_cls, strtod(s.c_str(), NULL)); return new BoxedFloat(strtod(s.c_str(), NULL));
} else { } else {
static const std::string float_str("__float__"); static const std::string float_str("__float__");
Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), Box* r = callattr(a, &float_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
...@@ -596,13 +596,7 @@ Box* floatNew(BoxedClass* _cls, Box* a) { ...@@ -596,13 +596,7 @@ Box* floatNew(BoxedClass* _cls, Box* a) {
BoxedFloat* f = _floatNew(a); BoxedFloat* f = _floatNew(a);
assert(cls->tp_basicsize >= sizeof(BoxedFloat)); return new (cls) BoxedFloat(f->d);
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedFloat* rtn = ::new (mem) BoxedFloat(cls, 0);
initUserAttrs(rtn, cls);
rtn->d = f->d;
return rtn;
} }
Box* floatStr(BoxedFloat* self) { Box* floatStr(BoxedFloat* self) {
......
...@@ -145,8 +145,8 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B ...@@ -145,8 +145,8 @@ extern "C" BoxedGenerator* createGenerator(BoxedFunction* function, Box* arg1, B
extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args) extern "C" BoxedGenerator::BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args)
: Box(generator_cls), function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), : function(function), arg1(arg1), arg2(arg2), arg3(arg3), args(nullptr), entryExited(false), running(false),
running(false), returnValue(nullptr), exception(nullptr) { returnValue(nullptr), exception(nullptr) {
giveAttr("__name__", boxString(function->f->source->getName())); giveAttr("__name__", boxString(function->f->source->getName()));
...@@ -231,7 +231,7 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) { ...@@ -231,7 +231,7 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
void setupGenerator() { void setupGenerator() {
generator_cls = new BoxedHeapClass(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs), generator_cls = new BoxedHeapClass(object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false); sizeof(BoxedGenerator), false);
generator_cls->giveAttr("__name__", boxStrConstant("generator")); generator_cls->giveAttr("__name__", boxStrConstant("generator"));
generator_cls->giveAttr("__iter__", generator_cls->giveAttr("__iter__",
......
...@@ -62,7 +62,7 @@ Box* boxInt(int64_t n) { ...@@ -62,7 +62,7 @@ Box* boxInt(int64_t n) {
if (0 <= n && n < NUM_INTERNED_INTS) { if (0 <= n && n < NUM_INTERNED_INTS) {
return interned_ints[n]; return interned_ints[n];
} }
return new BoxedInt(int_cls, n); return new BoxedInt(n);
} }
// BoxedInt::BoxedInt(int64_t n) : Box(int_cls), n(n) {} // BoxedInt::BoxedInt(int64_t n) : Box(int_cls), n(n) {}
......
...@@ -23,7 +23,7 @@ namespace pyston { ...@@ -23,7 +23,7 @@ namespace pyston {
extern "C" inline Box* boxFloat(double d) __attribute__((visibility("default"))); extern "C" inline Box* boxFloat(double d) __attribute__((visibility("default")));
extern "C" inline Box* boxFloat(double d) { extern "C" inline Box* boxFloat(double d) {
return new BoxedFloat(float_cls, d); return new BoxedFloat(d);
} }
extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default"))); extern "C" inline Box* boxComplex(double r, double i) __attribute__((visibility("default")));
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace pyston { namespace pyston {
BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type) BoxedDictIterator::BoxedDictIterator(BoxedDict* d, IteratorType type)
: Box(dict_iterator_cls), d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) { : d(d), it(d->d.begin()), itEnd(d->d.end()), type(type) {
} }
Box* dictIterKeys(Box* s) { Box* dictIterKeys(Box* s) {
...@@ -72,7 +72,7 @@ Box* dictIterNext(Box* s) { ...@@ -72,7 +72,7 @@ Box* dictIterNext(Box* s) {
return rtn; return rtn;
} }
BoxedDictView::BoxedDictView(BoxedDict* d, BoxedClass* view_cls) : Box(view_cls), d(d) { BoxedDictView::BoxedDictView(BoxedDict* d) : d(d) {
} }
Box* dictViewKeysIter(Box* s) { Box* dictViewKeysIter(Box* s) {
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
namespace pyston { namespace pyston {
BoxedListIterator::BoxedListIterator(BoxedList* l) : Box(list_iterator_cls), l(l), pos(0) { BoxedListIterator::BoxedListIterator(BoxedList* l) : l(l), pos(0) {
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
namespace pyston { namespace pyston {
BoxedTupleIterator::BoxedTupleIterator(BoxedTuple* t) : Box(tuple_iterator_cls), t(t), pos(0) { BoxedTupleIterator::BoxedTupleIterator(BoxedTuple* t) : t(t), pos(0) {
} }
Box* tupleIterIter(Box* s) { Box* tupleIterIter(Box* s) {
......
...@@ -26,9 +26,11 @@ private: ...@@ -26,9 +26,11 @@ private:
const int64_t start, stop, step; const int64_t start, stop, step;
public: public:
BoxedXrange(i64 start, i64 stop, i64 step) : Box(xrange_cls), start(start), stop(stop), step(step) {} BoxedXrange(i64 start, i64 stop, i64 step) : start(start), stop(stop), step(step) {}
friend class BoxedXrangeIterator; friend class BoxedXrangeIterator;
DEFAULT_CLASS(xrange_cls);
}; };
class BoxedXrangeIterator : public Box { class BoxedXrangeIterator : public Box {
...@@ -37,7 +39,9 @@ private: ...@@ -37,7 +39,9 @@ private:
int64_t cur; int64_t cur;
public: public:
BoxedXrangeIterator(BoxedXrange* xrange) : Box(xrange_iterator_cls), xrange(xrange), cur(xrange->start) {} BoxedXrangeIterator(BoxedXrange* xrange) : xrange(xrange), cur(xrange->start) {}
DEFAULT_CLASS(xrange_iterator_cls);
static bool xrangeIteratorHasnextUnboxed(Box* s) __attribute__((visibility("default"))) { static bool xrangeIteratorHasnextUnboxed(Box* s) __attribute__((visibility("default"))) {
assert(s->cls == xrange_iterator_cls); assert(s->cls == xrange_iterator_cls);
...@@ -113,9 +117,9 @@ Box* xrangeIter(Box* self) { ...@@ -113,9 +117,9 @@ Box* xrangeIter(Box* self) {
} }
void setupXrange() { void setupXrange() {
xrange_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedXrange), false); xrange_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedXrange), false);
xrange_cls->giveAttr("__name__", boxStrConstant("xrange")); xrange_cls->giveAttr("__name__", boxStrConstant("xrange"));
xrange_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0, xrange_iterator_cls = new BoxedHeapClass(object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
sizeof(BoxedXrangeIterator), false); sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator")); xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
......
...@@ -758,17 +758,17 @@ BoxedInt* _intNew(Box* val) { ...@@ -758,17 +758,17 @@ BoxedInt* _intNew(Box* val) {
BoxedInt* n = static_cast<BoxedInt*>(val); BoxedInt* n = static_cast<BoxedInt*>(val);
if (val->cls == int_cls) if (val->cls == int_cls)
return n; return n;
return new BoxedInt(int_cls, n->n); return new BoxedInt(n->n);
} else if (val->cls == str_cls) { } else if (val->cls == str_cls) {
BoxedString* s = static_cast<BoxedString*>(val); BoxedString* s = static_cast<BoxedString*>(val);
std::istringstream ss(s->s); std::istringstream ss(s->s);
int64_t n; int64_t n;
ss >> n; ss >> n;
return new BoxedInt(int_cls, n); return new BoxedInt(n);
} else if (val->cls == float_cls) { } else if (val->cls == float_cls) {
double d = static_cast<BoxedFloat*>(val)->d; double d = static_cast<BoxedFloat*>(val)->d;
return new BoxedInt(int_cls, d); return new BoxedInt(d);
} else { } else {
static const std::string int_str("__int__"); static const std::string int_str("__int__");
Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }),
...@@ -801,13 +801,7 @@ extern "C" Box* intNew(Box* _cls, Box* val) { ...@@ -801,13 +801,7 @@ extern "C" Box* intNew(Box* _cls, Box* val) {
BoxedInt* n = _intNew(val); BoxedInt* n = _intNew(val);
assert(cls->tp_basicsize >= sizeof(BoxedInt)); return new (cls) BoxedInt(n->n);
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedInt* rtn = ::new (mem) BoxedInt(cls, 0);
initUserAttrs(rtn, cls);
rtn->n = n->n;
return rtn;
} }
extern "C" Box* intInit(BoxedInt* self, Box* val, Box* args) { extern "C" Box* intInit(BoxedInt* self, Box* val, Box* args) {
...@@ -849,7 +843,7 @@ static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type, ...@@ -849,7 +843,7 @@ static void _addFuncIntUnknown(const char* name, ConcreteCompilerType* rtn_type,
void setupInt() { void setupInt() {
for (int i = 0; i < NUM_INTERNED_INTS; i++) { for (int i = 0; i < NUM_INTERNED_INTS; i++) {
interned_ints[i] = new BoxedInt(int_cls, i); interned_ints[i] = new BoxedInt(i);
gc::registerPermanentRoot(interned_ints[i]); gc::registerPermanentRoot(interned_ints[i]);
} }
......
...@@ -57,7 +57,7 @@ Box* seqiterNext(Box* s) { ...@@ -57,7 +57,7 @@ Box* seqiterNext(Box* s) {
} }
void setupIter() { void setupIter() {
seqiter_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedSeqIter), false); seqiter_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedSeqIter), false);
seqiter_cls->giveAttr("__name__", boxStrConstant("iterator")); seqiter_cls->giveAttr("__name__", boxStrConstant("iterator"));
seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1))); seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
......
...@@ -29,7 +29,9 @@ public: ...@@ -29,7 +29,9 @@ public:
int64_t idx; int64_t idx;
Box* next; Box* next;
BoxedSeqIter(Box* b) : Box(seqiter_cls), b(b), idx(0), next(NULL) {} BoxedSeqIter(Box* b) : b(b), idx(0), next(NULL) {}
DEFAULT_CLASS(seqiter_cls);
}; };
void setupIter(); void setupIter();
......
...@@ -579,7 +579,7 @@ Box* listNe(BoxedList* self, Box* rhs) { ...@@ -579,7 +579,7 @@ Box* listNe(BoxedList* self, Box* rhs) {
} }
void setupList() { void setupList() {
list_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false); list_iterator_cls = new BoxedHeapClass(object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
list_cls->giveAttr("__name__", boxStrConstant("list")); list_cls->giveAttr("__name__", boxStrConstant("list"));
......
...@@ -26,6 +26,8 @@ public: ...@@ -26,6 +26,8 @@ public:
BoxedList* l; BoxedList* l;
int pos; int pos;
BoxedListIterator(BoxedList* l); BoxedListIterator(BoxedList* l);
DEFAULT_CLASS(list_iterator_cls);
}; };
Box* listIter(Box* self); Box* listIter(Box* self);
......
...@@ -148,13 +148,13 @@ extern "C" PyObject* PyLong_FromDouble(double v) noexcept { ...@@ -148,13 +148,13 @@ extern "C" PyObject* PyLong_FromDouble(double v) noexcept {
} }
extern "C" PyObject* PyLong_FromLong(long ival) noexcept { extern "C" PyObject* PyLong_FromLong(long ival) noexcept {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set_si(rtn->n, ival); mpz_init_set_si(rtn->n, ival);
return rtn; return rtn;
} }
extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) noexcept { extern "C" PyObject* PyLong_FromUnsignedLong(unsigned long ival) noexcept {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set_ui(rtn->n, ival); mpz_init_set_ui(rtn->n, ival);
return rtn; return rtn;
} }
...@@ -261,39 +261,39 @@ extern "C" PyObject* _PyLong_FromByteArray(const unsigned char* bytes, size_t n, ...@@ -261,39 +261,39 @@ extern "C" PyObject* _PyLong_FromByteArray(const unsigned char* bytes, size_t n,
return 0; return 0;
} }
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init(rtn->n); mpz_init(rtn->n);
mpz_import(rtn->n, 1, 1, n, little_endian ? -1 : 1, 0, &bytes[0]); mpz_import(rtn->n, 1, 1, n, little_endian ? -1 : 1, 0, &bytes[0]);
return rtn; return rtn;
} }
extern "C" Box* createLong(const std::string* s) { extern "C" Box* createLong(const std::string* s) {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
int r = mpz_init_set_str(rtn->n, s->c_str(), 10); int r = mpz_init_set_str(rtn->n, s->c_str(), 10);
RELEASE_ASSERT(r == 0, "%d: '%s'", r, s->c_str()); RELEASE_ASSERT(r == 0, "%d: '%s'", r, s->c_str());
return rtn; return rtn;
} }
extern "C" BoxedLong* boxLong(int64_t n) { extern "C" BoxedLong* boxLong(int64_t n) {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set_si(rtn->n, n); mpz_init_set_si(rtn->n, n);
return rtn; return rtn;
} }
extern "C" PyObject* PyLong_FromLongLong(long long ival) noexcept { extern "C" PyObject* PyLong_FromLongLong(long long ival) noexcept {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set_si(rtn->n, ival); mpz_init_set_si(rtn->n, ival);
return rtn; return rtn;
} }
extern "C" PyObject* PyLong_FromUnsignedLongLong(unsigned long long ival) noexcept { extern "C" PyObject* PyLong_FromUnsignedLongLong(unsigned long long ival) noexcept {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set_ui(rtn->n, ival); mpz_init_set_ui(rtn->n, ival);
return rtn; return rtn;
} }
BoxedLong* _longNew(Box* val, Box* _base) { BoxedLong* _longNew(Box* val, Box* _base) {
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
if (_base) { if (_base) {
if (!isSubclass(_base->cls, int_cls)) if (!isSubclass(_base->cls, int_cls))
raiseExcHelper(TypeError, "an integer is required"); raiseExcHelper(TypeError, "an integer is required");
...@@ -320,7 +320,7 @@ BoxedLong* _longNew(Box* val, Box* _base) { ...@@ -320,7 +320,7 @@ BoxedLong* _longNew(Box* val, Box* _base) {
BoxedLong* l = static_cast<BoxedLong*>(val); BoxedLong* l = static_cast<BoxedLong*>(val);
if (val->cls == long_cls) if (val->cls == long_cls)
return l; return l;
BoxedLong* rtn = new BoxedLong(long_cls); BoxedLong* rtn = new BoxedLong();
mpz_init_set(rtn->n, l->n); mpz_init_set(rtn->n, l->n);
return rtn; return rtn;
} else if (isSubclass(val->cls, int_cls)) { } else if (isSubclass(val->cls, int_cls)) {
...@@ -365,10 +365,7 @@ extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) { ...@@ -365,10 +365,7 @@ extern "C" Box* longNew(Box* _cls, Box* val, Box* _base) {
if (cls == long_cls) if (cls == long_cls)
return l; return l;
assert(cls->tp_basicsize >= sizeof(BoxedInt)); BoxedLong* rtn = new (cls) BoxedLong();
void* mem = gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
BoxedLong* rtn = ::new (mem) BoxedLong(cls);
initUserAttrs(rtn, cls);
mpz_init_set(rtn->n, l->n); mpz_init_set(rtn->n, l->n);
return rtn; return rtn;
...@@ -408,7 +405,7 @@ Box* longNeg(BoxedLong* v1) { ...@@ -408,7 +405,7 @@ Box* longNeg(BoxedLong* v1) {
raiseExcHelper(TypeError, "descriptor '__neg__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__neg__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str()); getTypeName(v1)->c_str());
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_neg(r->n, v1->n); mpz_neg(r->n, v1->n);
return r; return r;
...@@ -416,7 +413,7 @@ Box* longNeg(BoxedLong* v1) { ...@@ -416,7 +413,7 @@ Box* longNeg(BoxedLong* v1) {
Box* longAbs(BoxedLong* v1) { Box* longAbs(BoxedLong* v1) {
assert(isSubclass(v1->cls, long_cls)); assert(isSubclass(v1->cls, long_cls));
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_abs(r->n, v1->n); mpz_abs(r->n, v1->n);
return r; return r;
...@@ -430,14 +427,14 @@ Box* longAdd(BoxedLong* v1, Box* _v2) { ...@@ -430,14 +427,14 @@ Box* longAdd(BoxedLong* v1, Box* _v2) {
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_add(r->n, v1->n, v2->n); mpz_add(r->n, v1->n, v2->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2); BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
if (v2->n >= 0) if (v2->n >= 0)
mpz_add_ui(r->n, v1->n, v2->n); mpz_add_ui(r->n, v1->n, v2->n);
...@@ -455,13 +452,13 @@ extern "C" Box* longAnd(BoxedLong* v1, Box* _v2) { ...@@ -455,13 +452,13 @@ extern "C" Box* longAnd(BoxedLong* v1, Box* _v2) {
getTypeName(v1)->c_str()); getTypeName(v1)->c_str());
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_and(r->n, v1->n, v2->n); mpz_and(r->n, v1->n, v2->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2_int = static_cast<BoxedInt*>(_v2); BoxedInt* v2_int = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_t v2_long; mpz_t v2_long;
mpz_init(v2_long); mpz_init(v2_long);
...@@ -482,13 +479,13 @@ extern "C" Box* longXor(BoxedLong* v1, Box* _v2) { ...@@ -482,13 +479,13 @@ extern "C" Box* longXor(BoxedLong* v1, Box* _v2) {
getTypeName(v1)->c_str()); getTypeName(v1)->c_str());
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_xor(r->n, v1->n, v2->n); mpz_xor(r->n, v1->n, v2->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2_int = static_cast<BoxedInt*>(_v2); BoxedInt* v2_int = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_t v2_long; mpz_t v2_long;
mpz_init(v2_long); mpz_init(v2_long);
...@@ -624,7 +621,7 @@ Box* longLshift(BoxedLong* v1, Box* _v2) { ...@@ -624,7 +621,7 @@ Box* longLshift(BoxedLong* v1, Box* _v2) {
raiseExcHelper(ValueError, "negative shift count"); raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(v2); uint64_t n = asUnsignedLong(v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, n); mpz_mul_2exp(r->n, v1->n, n);
return r; return r;
...@@ -633,7 +630,7 @@ Box* longLshift(BoxedLong* v1, Box* _v2) { ...@@ -633,7 +630,7 @@ Box* longLshift(BoxedLong* v1, Box* _v2) {
if (v2->n < 0) if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count"); raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_mul_2exp(r->n, v1->n, v2->n); mpz_mul_2exp(r->n, v1->n, v2->n);
return r; return r;
...@@ -654,7 +651,7 @@ Box* longRshift(BoxedLong* v1, Box* _v2) { ...@@ -654,7 +651,7 @@ Box* longRshift(BoxedLong* v1, Box* _v2) {
raiseExcHelper(ValueError, "negative shift count"); raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(v2); uint64_t n = asUnsignedLong(v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, n); mpz_div_2exp(r->n, v1->n, n);
return r; return r;
...@@ -663,7 +660,7 @@ Box* longRshift(BoxedLong* v1, Box* _v2) { ...@@ -663,7 +660,7 @@ Box* longRshift(BoxedLong* v1, Box* _v2) {
if (v2->n < 0) if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count"); raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, v2->n); mpz_div_2exp(r->n, v1->n, v2->n);
return r; return r;
...@@ -680,14 +677,14 @@ Box* longSub(BoxedLong* v1, Box* _v2) { ...@@ -680,14 +677,14 @@ Box* longSub(BoxedLong* v1, Box* _v2) {
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_sub(r->n, v1->n, v2->n); mpz_sub(r->n, v1->n, v2->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2); BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
if (v2->n >= 0) if (v2->n >= 0)
mpz_sub_ui(r->n, v1->n, v2->n); mpz_sub_ui(r->n, v1->n, v2->n);
...@@ -715,14 +712,14 @@ Box* longMul(BoxedLong* v1, Box* _v2) { ...@@ -715,14 +712,14 @@ Box* longMul(BoxedLong* v1, Box* _v2) {
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_mul(r->n, v1->n, v2->n); mpz_mul(r->n, v1->n, v2->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2); BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_mul_si(r->n, v1->n, v2->n); mpz_mul_si(r->n, v1->n, v2->n);
return r; return r;
...@@ -742,7 +739,7 @@ Box* longDiv(BoxedLong* v1, Box* _v2) { ...@@ -742,7 +739,7 @@ Box* longDiv(BoxedLong* v1, Box* _v2) {
if (mpz_cmp_si(v2->n, 0) == 0) if (mpz_cmp_si(v2->n, 0) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_fdiv_q(r->n, v1->n, v2->n); mpz_fdiv_q(r->n, v1->n, v2->n);
return r; return r;
...@@ -752,7 +749,7 @@ Box* longDiv(BoxedLong* v1, Box* _v2) { ...@@ -752,7 +749,7 @@ Box* longDiv(BoxedLong* v1, Box* _v2) {
if (v2->n == 0) if (v2->n == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init_set_si(r->n, v2->n); mpz_init_set_si(r->n, v2->n);
mpz_fdiv_q(r->n, v1->n, r->n); mpz_fdiv_q(r->n, v1->n, r->n);
return r; return r;
...@@ -772,8 +769,8 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) { ...@@ -772,8 +769,8 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) {
if (mpz_cmp_si(rhs->n, 0) == 0) if (mpz_cmp_si(rhs->n, 0) == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong(long_cls); BoxedLong* q = new BoxedLong();
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(q->n); mpz_init(q->n);
mpz_init(r->n); mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, rhs->n); mpz_fdiv_qr(q->n, r->n, lhs->n, rhs->n);
...@@ -784,8 +781,8 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) { ...@@ -784,8 +781,8 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) {
if (rhs->n == 0) if (rhs->n == 0)
raiseExcHelper(ZeroDivisionError, "long division or modulo by zero"); raiseExcHelper(ZeroDivisionError, "long division or modulo by zero");
BoxedLong* q = new BoxedLong(long_cls); BoxedLong* q = new BoxedLong();
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(q->n); mpz_init(q->n);
mpz_init_set_si(r->n, rhs->n); mpz_init_set_si(r->n, rhs->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, r->n); mpz_fdiv_qr(q->n, r->n, lhs->n, r->n);
...@@ -806,14 +803,14 @@ Box* longRdiv(BoxedLong* v1, Box* _v2) { ...@@ -806,14 +803,14 @@ Box* longRdiv(BoxedLong* v1, Box* _v2) {
if (isSubclass(_v2->cls, long_cls)) { if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2); BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_fdiv_q(r->n, v2->n, v1->n); mpz_fdiv_q(r->n, v2->n, v1->n);
return r; return r;
} else if (isSubclass(_v2->cls, int_cls)) { } else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2); BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init_set_si(r->n, v2->n); mpz_init_set_si(r->n, v2->n);
mpz_fdiv_q(r->n, r->n, v1->n); mpz_fdiv_q(r->n, r->n, v1->n);
return r; return r;
...@@ -836,7 +833,7 @@ Box* longPow(BoxedLong* v1, Box* _v2) { ...@@ -836,7 +833,7 @@ Box* longPow(BoxedLong* v1, Box* _v2) {
RELEASE_ASSERT(mpz_fits_ulong_p(v2->n), ""); RELEASE_ASSERT(mpz_fits_ulong_p(v2->n), "");
uint64_t n2 = mpz_get_ui(v2->n); uint64_t n2 = mpz_get_ui(v2->n);
BoxedLong* r = new BoxedLong(long_cls); BoxedLong* r = new BoxedLong();
mpz_init(r->n); mpz_init(r->n);
mpz_pow_ui(r->n, v1->n, n2); mpz_pow_ui(r->n, v1->n, n2);
return r; return r;
......
...@@ -30,7 +30,9 @@ class BoxedLong : public Box { ...@@ -30,7 +30,9 @@ class BoxedLong : public Box {
public: public:
mpz_t n; mpz_t n;
BoxedLong(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {} BoxedLong() __attribute__((visibility("default"))) {}
DEFAULT_CLASS(long_cls);
}; };
extern "C" Box* createLong(const std::string* s); extern "C" Box* createLong(const std::string* s);
......
...@@ -343,10 +343,9 @@ void BoxedClass::freeze() { ...@@ -343,10 +343,9 @@ void BoxedClass::freeze() {
is_constant = true; is_constant = true;
} }
BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
int instance_size, bool is_user_defined) bool is_user_defined)
: BoxVar(metaclass, 0), gc_visit(gc_visit), attrs_offset(attrs_offset), is_constant(false), : BoxVar(0), gc_visit(gc_visit), attrs_offset(attrs_offset), is_constant(false), is_user_defined(is_user_defined) {
is_user_defined(is_user_defined) {
// Zero out the CPython tp_* slots: // Zero out the CPython tp_* slots:
memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name)); memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name));
...@@ -358,10 +357,12 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_ ...@@ -358,10 +357,12 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
tp_base = base; tp_base = base;
if (metaclass == NULL) { tp_alloc = PyType_GenericAlloc;
if (cls == NULL) {
assert(type_cls == NULL); assert(type_cls == NULL);
} else { } else {
assert(isSubclass(metaclass, type_cls)); assert(isSubclass(cls, type_cls));
} }
assert(tp_dealloc == NULL); assert(tp_dealloc == NULL);
...@@ -396,10 +397,9 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_ ...@@ -396,10 +397,9 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
gc::registerPermanentRoot(this); gc::registerPermanentRoot(this);
} }
BoxedHeapClass::BoxedHeapClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
int instance_size, bool is_user_defined) bool is_user_defined)
: BoxedClass(metaclass, base, gc_visit, attrs_offset, instance_size, is_user_defined), ht_name(NULL), : BoxedClass(base, gc_visit, attrs_offset, instance_size, is_user_defined), ht_name(NULL), ht_slots(NULL) {
ht_slots(NULL) {
tp_as_number = &as_number; tp_as_number = &as_number;
tp_as_mapping = &as_mapping; tp_as_mapping = &as_mapping;
...@@ -3314,10 +3314,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -3314,10 +3314,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass* made; BoxedClass* made;
if (base->instancesHaveAttrs()) { if (base->instancesHaveAttrs()) {
made = new BoxedHeapClass(cls, base, NULL, base->attrs_offset, base->tp_basicsize, true); made = new (cls) BoxedHeapClass(base, NULL, base->attrs_offset, base->tp_basicsize, true);
} else { } else {
assert(base->tp_basicsize % sizeof(void*) == 0); assert(base->tp_basicsize % sizeof(void*) == 0);
made = new BoxedHeapClass(cls, base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs), true); made = new (cls) BoxedHeapClass(base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs), true);
} }
made->giveAttr("__module__", boxString(getCurrentModule()->name())); made->giveAttr("__module__", boxString(getCurrentModule()->name()));
......
...@@ -25,7 +25,7 @@ BoxedClass* set_cls, *set_iterator_cls; ...@@ -25,7 +25,7 @@ BoxedClass* set_cls, *set_iterator_cls;
BoxedClass* frozenset_cls; BoxedClass* frozenset_cls;
extern "C" Box* createSet() { extern "C" Box* createSet() {
return new BoxedSet(set_cls); return new BoxedSet();
} }
namespace set { namespace set {
...@@ -35,7 +35,9 @@ public: ...@@ -35,7 +35,9 @@ public:
BoxedSet* s; BoxedSet* s;
decltype(BoxedSet::s)::iterator it; decltype(BoxedSet::s)::iterator it;
BoxedSetIterator(BoxedSet* s) : Box(set_iterator_cls), s(s), it(s->s.begin()) {} BoxedSetIterator(BoxedSet* s) : s(s), it(s->s.begin()) {}
DEFAULT_CLASS(set_iterator_cls);
bool hasNext() { return it != s->s.end(); } bool hasNext() { return it != s->s.end(); }
...@@ -77,10 +79,11 @@ Box* setNew(Box* _cls, Box* container) { ...@@ -77,10 +79,11 @@ Box* setNew(Box* _cls, Box* container) {
BoxedClass* cls = static_cast<BoxedClass*>(_cls); BoxedClass* cls = static_cast<BoxedClass*>(_cls);
assert(cls == set_cls || cls == frozenset_cls); assert(cls == set_cls || cls == frozenset_cls);
Box* rtn = new (cls) BoxedSet();
if (container == None) if (container == None)
return new BoxedSet(cls); return rtn;
Box* rtn = new BoxedSet(cls);
for (Box* e : container->pyElements()) { for (Box* e : container->pyElements()) {
setAdd2(rtn, e); setAdd2(rtn, e);
} }
...@@ -118,7 +121,7 @@ Box* setOrSet(BoxedSet* lhs, BoxedSet* rhs) { ...@@ -118,7 +121,7 @@ Box* setOrSet(BoxedSet* lhs, BoxedSet* rhs) {
assert(lhs->cls == set_cls || lhs->cls == frozenset_cls); assert(lhs->cls == set_cls || lhs->cls == frozenset_cls);
assert(rhs->cls == set_cls || rhs->cls == frozenset_cls); assert(rhs->cls == set_cls || rhs->cls == frozenset_cls);
BoxedSet* rtn = new BoxedSet(lhs->cls); BoxedSet* rtn = new (lhs->cls) BoxedSet();
for (Box* elt : lhs->s) { for (Box* elt : lhs->s) {
rtn->s.insert(elt); rtn->s.insert(elt);
...@@ -133,7 +136,7 @@ Box* setAndSet(BoxedSet* lhs, BoxedSet* rhs) { ...@@ -133,7 +136,7 @@ Box* setAndSet(BoxedSet* lhs, BoxedSet* rhs) {
assert(lhs->cls == set_cls || lhs->cls == frozenset_cls); assert(lhs->cls == set_cls || lhs->cls == frozenset_cls);
assert(rhs->cls == set_cls || rhs->cls == frozenset_cls); assert(rhs->cls == set_cls || rhs->cls == frozenset_cls);
BoxedSet* rtn = new BoxedSet(lhs->cls); BoxedSet* rtn = new (lhs->cls) BoxedSet();
for (Box* elt : lhs->s) { for (Box* elt : lhs->s) {
if (rhs->s.count(elt)) if (rhs->s.count(elt))
...@@ -146,7 +149,7 @@ Box* setSubSet(BoxedSet* lhs, BoxedSet* rhs) { ...@@ -146,7 +149,7 @@ Box* setSubSet(BoxedSet* lhs, BoxedSet* rhs) {
assert(lhs->cls == set_cls || lhs->cls == frozenset_cls); assert(lhs->cls == set_cls || lhs->cls == frozenset_cls);
assert(rhs->cls == set_cls || rhs->cls == frozenset_cls); assert(rhs->cls == set_cls || rhs->cls == frozenset_cls);
BoxedSet* rtn = new BoxedSet(lhs->cls); BoxedSet* rtn = new (lhs->cls) BoxedSet();
for (Box* elt : lhs->s) { for (Box* elt : lhs->s) {
// TODO if len(rhs) << len(lhs), it might be more efficient // TODO if len(rhs) << len(lhs), it might be more efficient
...@@ -161,7 +164,7 @@ Box* setXorSet(BoxedSet* lhs, BoxedSet* rhs) { ...@@ -161,7 +164,7 @@ Box* setXorSet(BoxedSet* lhs, BoxedSet* rhs) {
assert(lhs->cls == set_cls || lhs->cls == frozenset_cls); assert(lhs->cls == set_cls || lhs->cls == frozenset_cls);
assert(rhs->cls == set_cls || rhs->cls == frozenset_cls); assert(rhs->cls == set_cls || rhs->cls == frozenset_cls);
BoxedSet* rtn = new BoxedSet(lhs->cls); BoxedSet* rtn = new (lhs->cls) BoxedSet();
for (Box* elt : lhs->s) { for (Box* elt : lhs->s) {
if (rhs->s.count(elt) == 0) if (rhs->s.count(elt) == 0)
...@@ -216,7 +219,7 @@ void setupSet() { ...@@ -216,7 +219,7 @@ void setupSet() {
set_cls->giveAttr("__name__", boxStrConstant("set")); set_cls->giveAttr("__name__", boxStrConstant("set"));
frozenset_cls->giveAttr("__name__", boxStrConstant("frozenset")); frozenset_cls->giveAttr("__name__", boxStrConstant("frozenset"));
set_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false); set_iterator_cls = new BoxedHeapClass(object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator")); set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__", set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
......
...@@ -34,11 +34,11 @@ public: ...@@ -34,11 +34,11 @@ public:
typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*>> Set; typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*>> Set;
Set s; Set s;
BoxedSet(BoxedClass* cls) __attribute__((visibility("default"))) : Box(cls) {} BoxedSet() __attribute__((visibility("default"))) {}
template <typename T> template <typename T> __attribute__((visibility("default"))) BoxedSet(T&& s) : s(std::forward<T>(s)) {}
__attribute__((visibility("default"))) BoxedSet(T&& s, BoxedClass* cls)
: Box(cls), s(std::forward<T>(s)) {} DEFAULT_CLASS(set_cls);
}; };
} }
......
...@@ -1604,7 +1604,9 @@ public: ...@@ -1604,7 +1604,9 @@ public:
BoxedString* s; BoxedString* s;
std::string::const_iterator it, end; std::string::const_iterator it, end;
BoxedStringIterator(BoxedString* s) : Box(str_iterator_cls), s(s), it(s->s.begin()), end(s->s.end()) {} BoxedStringIterator(BoxedString* s) : it(s->s.begin()), end(s->s.end()) {}
DEFAULT_CLASS(str_iterator_cls);
static bool hasnextUnboxed(BoxedStringIterator* self) { static bool hasnextUnboxed(BoxedStringIterator* self) {
assert(self->cls == str_iterator_cls); assert(self->cls == str_iterator_cls);
...@@ -1742,7 +1744,7 @@ static PyBufferProcs string_as_buffer = { ...@@ -1742,7 +1744,7 @@ static PyBufferProcs string_as_buffer = {
}; };
void setupStr() { void setupStr() {
str_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &strIteratorGCHandler, 0, sizeof(BoxedString), false); str_iterator_cls = new BoxedHeapClass(object_cls, &strIteratorGCHandler, 0, sizeof(BoxedStringIterator), false);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator")); str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__", str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
......
...@@ -32,8 +32,9 @@ public: ...@@ -32,8 +32,9 @@ public:
Box* obj; // "the instance invoking super(); make be None" Box* obj; // "the instance invoking super(); make be None"
BoxedClass* obj_type; // "the type of the instance invoking super(); may be None" BoxedClass* obj_type; // "the type of the instance invoking super(); may be None"
BoxedSuper(BoxedClass* type, Box* obj, BoxedClass* obj_type) BoxedSuper(BoxedClass* type, Box* obj, BoxedClass* obj_type) : type(type), obj(obj), obj_type(obj_type) {}
: Box(super_cls), type(type), obj(obj), obj_type(obj_type) {}
DEFAULT_CLASS(super_cls);
static void gcHandler(GCVisitor* v, Box* _o) { static void gcHandler(GCVisitor* v, Box* _o) {
assert(_o->cls == super_cls); assert(_o->cls == super_cls);
...@@ -131,7 +132,7 @@ Box* superInit(Box* _self, Box* _type, Box* obj) { ...@@ -131,7 +132,7 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
} }
void setupSuper() { void setupSuper() {
super_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false); super_cls = new BoxedHeapClass(object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false);
super_cls->giveAttr("__name__", boxStrConstant("super")); super_cls->giveAttr("__name__", boxStrConstant("super"));
......
...@@ -382,8 +382,7 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) { ...@@ -382,8 +382,7 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void setupTuple() { void setupTuple() {
tuple_iterator_cls tuple_iterator_cls = new BoxedHeapClass(object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false);
= new BoxedHeapClass(type_cls, object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false);
tuple_cls->giveAttr("__name__", boxStrConstant("tuple")); tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
......
...@@ -26,6 +26,8 @@ public: ...@@ -26,6 +26,8 @@ public:
BoxedTuple* t; BoxedTuple* t;
int pos; int pos;
BoxedTupleIterator(BoxedTuple* t); BoxedTupleIterator(BoxedTuple* t);
DEFAULT_CLASS(tuple_iterator_cls);
}; };
Box* tupleIter(Box* self); Box* tupleIter(Box* self);
......
...@@ -57,6 +57,38 @@ bool IN_SHUTDOWN = false; ...@@ -57,6 +57,38 @@ bool IN_SHUTDOWN = false;
#define SLICE_STOP_OFFSET ((char*)&(((BoxedSlice*)0x01)->stop) - (char*)0x1) #define SLICE_STOP_OFFSET ((char*)&(((BoxedSlice*)0x01)->stop) - (char*)0x1)
#define SLICE_STEP_OFFSET ((char*)&(((BoxedSlice*)0x01)->step) - (char*)0x1) #define SLICE_STEP_OFFSET ((char*)&(((BoxedSlice*)0x01)->step) - (char*)0x1)
extern "C" PyObject* PyType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept {
assert(cls);
RELEASE_ASSERT(nitems == 0, "");
RELEASE_ASSERT(cls->tp_itemsize == 0, "");
const size_t size = cls->tp_basicsize;
// Maybe we should only zero the extension memory?
// I'm not sure we have the information at the moment, but when we were in Box::operator new()
// we knew which memory was beyond C++ class.
void* mem = gc_alloc(size, gc::GCKind::PYTHON);
RELEASE_ASSERT(mem, "");
Box* rtn = static_cast<Box*>(mem);
PyObject_Init(rtn, cls);
assert(rtn->cls);
return rtn;
}
// Analogue of PyType_GenericNew
void* Box::operator new(size_t size, BoxedClass* cls) {
assert(cls);
ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name);
assert(cls->tp_alloc);
void* mem = cls->tp_alloc(cls, 0);
RELEASE_ASSERT(mem, "");
return mem;
}
Box* BoxedClass::callHasnextIC(Box* obj, bool null_on_nonexistent) { Box* BoxedClass::callHasnextIC(Box* obj, bool null_on_nonexistent) {
assert(obj->cls == this); assert(obj->cls == this);
...@@ -170,7 +202,7 @@ void BoxIterator::gcHandler(GCVisitor* v) { ...@@ -170,7 +202,7 @@ void BoxIterator::gcHandler(GCVisitor* v) {
std::string builtinStr("__builtin__"); std::string builtinStr("__builtin__");
extern "C" BoxedFunction::BoxedFunction(CLFunction* f) extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
: Box(function_cls), f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) { : f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) {
if (f->source) { if (f->source) {
assert(f->source->ast); assert(f->source->ast);
// this->giveAttr("__name__", boxString(&f->source->ast->name)); // this->giveAttr("__name__", boxString(&f->source->ast->name));
...@@ -188,7 +220,7 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) ...@@ -188,7 +220,7 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f)
extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure, extern "C" BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure,
bool isGenerator) bool isGenerator)
: Box(function_cls), f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) { : f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) {
if (defaults.size()) { if (defaults.size()) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults, // make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// and a GC can happen within this constructor: // and a GC can happen within this constructor:
...@@ -232,7 +264,7 @@ extern "C" void functionGCHandler(GCVisitor* v, Box* b) { ...@@ -232,7 +264,7 @@ extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
} }
} }
BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : Box(module_cls), fn(fn) { BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : fn(fn) {
this->giveAttr("__name__", boxString(name)); this->giveAttr("__name__", boxString(name));
this->giveAttr("__file__", boxString(fn)); this->giveAttr("__file__", boxString(fn));
} }
...@@ -690,7 +722,9 @@ private: ...@@ -690,7 +722,9 @@ private:
Box* b; Box* b;
public: public:
AttrWrapper(Box* b) : Box(attrwrapper_cls), b(b) {} AttrWrapper(Box* b) : b(b) {}
DEFAULT_CLASS(attrwrapper_cls);
static void gcHandler(GCVisitor* v, Box* b) { static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b); boxGCHandler(v, b);
...@@ -795,12 +829,7 @@ Box* objectNew(BoxedClass* cls, BoxedTuple* args) { ...@@ -795,12 +829,7 @@ Box* objectNew(BoxedClass* cls, BoxedTuple* args) {
raiseExcHelper(TypeError, objectNewParameterTypeErrorMsg()); raiseExcHelper(TypeError, objectNewParameterTypeErrorMsg());
} }
assert(cls->tp_basicsize >= sizeof(Box)); return new (cls) Box();
void* mem = gc::gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
Box* rtn = ::new (mem) Box(cls);
initUserAttrs(rtn, cls);
return rtn;
} }
Box* objectInit(Box* b, BoxedTuple* args) { Box* objectInit(Box* b, BoxedTuple* args) {
...@@ -821,27 +850,62 @@ Box* objectStr(Box* obj) { ...@@ -821,27 +850,62 @@ Box* objectStr(Box* obj) {
return obj->reprIC(); return obj->reprIC();
} }
// cls should be obj->cls.
// Added as parameter because it should typically be available
inline void initUserAttrs(Box* obj, BoxedClass* cls) {
assert(obj->cls == cls);
if (cls->attrs_offset) {
HCAttrs* attrs = obj->getAttrsPtr();
attrs = new ((void*)attrs) HCAttrs();
}
}
extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
assert(op);
assert(tp);
assert(gc::isValidGCObject(op));
assert(gc::isValidGCObject(tp));
Py_TYPE(op) = tp;
// I think CPython defers the dict creation (equivalent of our initUserAttrs) to the
// first time that an attribute gets set.
// Our HCAttrs object already includes this optimization of no-allocation-if-empty,
// but it's nice to initialize the hcls here so we don't have to check it on every getattr/setattr.
// TODO It does mean that anything not defering to this function will have to call
// initUserAttrs themselves, though.
initUserAttrs(op, tp);
return op;
}
bool TRACK_ALLOCATIONS = false; bool TRACK_ALLOCATIONS = false;
void setupRuntime() { void setupRuntime() {
root_hcls = HiddenClass::makeRoot(); root_hcls = HiddenClass::makeRoot();
gc::registerPermanentRoot(root_hcls); gc::registerPermanentRoot(root_hcls);
object_cls = new BoxedClass(NULL, NULL, &boxGCHandler, 0, sizeof(Box), false); // We have to do a little dance to get object_cls and type_cls set up, since the normal
type_cls // object-creation routines look at the class to see the allocation size.
= new BoxedHeapClass(NULL, object_cls, &typeGCHandler, offsetof(BoxedClass, attrs), sizeof(BoxedClass), false); void* mem = gc_alloc(sizeof(BoxedClass), gc::GCKind::PYTHON);
type_cls->cls = type_cls; object_cls = ::new (mem) BoxedClass(NULL, &boxGCHandler, 0, sizeof(Box), false);
object_cls->cls = type_cls; mem = gc_alloc(sizeof(BoxedHeapClass), gc::GCKind::PYTHON);
type_cls = ::new (mem)
none_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false); BoxedHeapClass(object_cls, &typeGCHandler, offsetof(BoxedClass, attrs), sizeof(BoxedHeapClass), false);
None = new Box(none_cls); PyObject_Init(object_cls, type_cls);
PyObject_Init(type_cls, type_cls);
none_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(Box), false);
None = new (none_cls) Box();
assert(None->cls);
gc::registerPermanentRoot(None); gc::registerPermanentRoot(None);
// You can't actually have an instance of basestring // You can't actually have an instance of basestring
basestring_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false); basestring_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(Box), false);
// TODO we leak all the string data! // TODO we leak all the string data!
str_cls = new BoxedHeapClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedString), false); str_cls = new BoxedHeapClass(basestring_cls, NULL, 0, sizeof(BoxedString), false);
unicode_cls = new BoxedHeapClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedUnicode), false); unicode_cls = new BoxedHeapClass(basestring_cls, NULL, 0, sizeof(BoxedUnicode), false);
// It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now: // It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now:
type_cls->giveAttr("__base__", object_cls); type_cls->giveAttr("__base__", object_cls);
...@@ -851,42 +915,39 @@ void setupRuntime() { ...@@ -851,42 +915,39 @@ void setupRuntime() {
object_cls->giveAttr("__base__", None); object_cls->giveAttr("__base__", None);
tuple_cls = new BoxedHeapClass(type_cls, object_cls, &tupleGCHandler, 0, sizeof(BoxedTuple), false); tuple_cls = new BoxedHeapClass(object_cls, &tupleGCHandler, 0, sizeof(BoxedTuple), false);
EmptyTuple = new BoxedTuple({}); EmptyTuple = new BoxedTuple({});
gc::registerPermanentRoot(EmptyTuple); gc::registerPermanentRoot(EmptyTuple);
module_cls module_cls = new BoxedHeapClass(object_cls, NULL, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
= new BoxedHeapClass(type_cls, object_cls, NULL, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
// TODO it'd be nice to be able to do these in the respective setupType methods, // TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects. // but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now. // We could have a multi-stage setup process, but that seems overkill for now.
int_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedInt), false); int_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedInt), false);
bool_cls = new BoxedHeapClass(type_cls, int_cls, NULL, 0, sizeof(BoxedBool), false); bool_cls = new BoxedHeapClass(int_cls, NULL, 0, sizeof(BoxedBool), false);
complex_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedComplex), false); complex_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedComplex), false);
// TODO we're leaking long memory! // TODO we're leaking long memory!
long_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedLong), false); long_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedLong), false);
float_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFloat), false); float_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedFloat), false);
function_cls = new BoxedHeapClass(type_cls, object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs), function_cls = new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
sizeof(BoxedFunction), false); sizeof(BoxedFunction), false);
instancemethod_cls instancemethod_cls
= new BoxedHeapClass(type_cls, object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false); = new BoxedHeapClass(object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false);
list_cls = new BoxedHeapClass(type_cls, object_cls, &listGCHandler, 0, sizeof(BoxedList), false); list_cls = new BoxedHeapClass(object_cls, &listGCHandler, 0, sizeof(BoxedList), false);
slice_cls = new BoxedHeapClass(type_cls, object_cls, &sliceGCHandler, 0, sizeof(BoxedSlice), false); slice_cls = new BoxedHeapClass(object_cls, &sliceGCHandler, 0, sizeof(BoxedSlice), false);
dict_cls = new BoxedHeapClass(type_cls, object_cls, &dictGCHandler, 0, sizeof(BoxedDict), false); dict_cls = new BoxedHeapClass(object_cls, &dictGCHandler, 0, sizeof(BoxedDict), false);
file_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFile), false); file_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedFile), false);
set_cls = new BoxedHeapClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false); set_cls = new BoxedHeapClass(object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
frozenset_cls = new BoxedHeapClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false); frozenset_cls = new BoxedHeapClass(object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
member_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMemberDescriptor), false); member_cls = new BoxedHeapClass(object_cls, NULL, 0, sizeof(BoxedMemberDescriptor), false);
closure_cls = new BoxedHeapClass(type_cls, object_cls, &closureGCHandler, offsetof(BoxedClosure, attrs), closure_cls
sizeof(BoxedClosure), false); = new BoxedHeapClass(object_cls, &closureGCHandler, offsetof(BoxedClosure, attrs), sizeof(BoxedClosure), false);
property_cls = new BoxedHeapClass(type_cls, object_cls, &propertyGCHandler, 0, sizeof(BoxedProperty), false); property_cls = new BoxedHeapClass(object_cls, &propertyGCHandler, 0, sizeof(BoxedProperty), false);
staticmethod_cls staticmethod_cls = new BoxedHeapClass(object_cls, &staticmethodGCHandler, 0, sizeof(BoxedStaticmethod), false);
= new BoxedHeapClass(type_cls, object_cls, &staticmethodGCHandler, 0, sizeof(BoxedStaticmethod), false); classmethod_cls = new BoxedHeapClass(object_cls, &classmethodGCHandler, 0, sizeof(BoxedClassmethod), false);
classmethod_cls attrwrapper_cls = new BoxedHeapClass(object_cls, &AttrWrapper::gcHandler, 0, sizeof(AttrWrapper), false);
= new BoxedHeapClass(type_cls, object_cls, &classmethodGCHandler, 0, sizeof(BoxedClassmethod), false);
attrwrapper_cls = new BoxedHeapClass(type_cls, object_cls, &AttrWrapper::gcHandler, 0, sizeof(AttrWrapper), false);
STR = typeFromClass(str_cls); STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls); BOXED_INT = typeFromClass(int_cls);
......
...@@ -216,8 +216,9 @@ public: ...@@ -216,8 +216,9 @@ public:
void freeze(); void freeze();
BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined);
bool is_user_defined);
DEFAULT_CLASS(type_cls);
}; };
class BoxedHeapClass : public BoxedClass { class BoxedHeapClass : public BoxedClass {
...@@ -228,8 +229,7 @@ public: ...@@ -228,8 +229,7 @@ public:
PyBufferProcs as_buffer; PyBufferProcs as_buffer;
PyObject* ht_name, *ht_slots; PyObject* ht_name, *ht_slots;
BoxedHeapClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined);
bool is_user_defined);
}; };
static_assert(sizeof(pyston::Box) == sizeof(struct _object), ""); static_assert(sizeof(pyston::Box) == sizeof(struct _object), "");
...@@ -278,19 +278,22 @@ public: ...@@ -278,19 +278,22 @@ public:
HiddenClass* delAttrToMakeHC(const std::string& attr); HiddenClass* delAttrToMakeHC(const std::string& attr);
}; };
class BoxedInt : public Box { class BoxedInt : public Box {
public: public:
int64_t n; int64_t n;
BoxedInt(BoxedClass* cls, int64_t n) __attribute__((visibility("default"))) : Box(cls), n(n) {} BoxedInt(int64_t n) __attribute__((visibility("default"))) : n(n) {}
DEFAULT_CLASS(int_cls);
}; };
class BoxedFloat : public Box { class BoxedFloat : public Box {
public: public:
double d; double d;
BoxedFloat(BoxedClass* cls, double d) __attribute__((visibility("default"))) : Box(cls), d(d) {} BoxedFloat(double d) __attribute__((visibility("default"))) : d(d) {}
DEFAULT_CLASS(float_cls);
}; };
class BoxedComplex : public Box { class BoxedComplex : public Box {
...@@ -298,12 +301,16 @@ public: ...@@ -298,12 +301,16 @@ public:
double real; double real;
double imag; double imag;
BoxedComplex(double r, double i) __attribute__((visibility("default"))) : Box(complex_cls), real(r), imag(i) {} BoxedComplex(double r, double i) __attribute__((visibility("default"))) : real(r), imag(i) {}
DEFAULT_CLASS(complex_cls);
}; };
class BoxedBool : public BoxedInt { class BoxedBool : public BoxedInt {
public: public:
BoxedBool(bool b) __attribute__((visibility("default"))) : BoxedInt(bool_cls, b ? 1 : 0) {} BoxedBool(bool b) __attribute__((visibility("default"))) : BoxedInt(b ? 1 : 0) {}
DEFAULT_CLASS(bool_cls);
}; };
class BoxedString : public Box { class BoxedString : public Box {
...@@ -311,9 +318,11 @@ public: ...@@ -311,9 +318,11 @@ public:
// const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s; // const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s;
std::string s; std::string s;
BoxedString(const char* s, size_t n) __attribute__((visibility("default"))) : Box(str_cls), s(s, n) {} BoxedString(const char* s, size_t n) __attribute__((visibility("default"))) : s(s, n) {}
BoxedString(const std::string&& s) __attribute__((visibility("default"))) : Box(str_cls), s(std::move(s)) {} BoxedString(const std::string&& s) __attribute__((visibility("default"))) : s(std::move(s)) {}
BoxedString(const std::string& s) __attribute__((visibility("default"))) : Box(str_cls), s(s) {} BoxedString(const std::string& s) __attribute__((visibility("default"))) : s(s) {}
DEFAULT_CLASS(str_cls);
}; };
class BoxedUnicode : public Box { class BoxedUnicode : public Box {
...@@ -325,8 +334,9 @@ public: ...@@ -325,8 +334,9 @@ public:
// obj is NULL for unbound instancemethod // obj is NULL for unbound instancemethod
Box* obj, *func; Box* obj, *func;
BoxedInstanceMethod(Box* obj, Box* func) __attribute__((visibility("default"))) BoxedInstanceMethod(Box* obj, Box* func) __attribute__((visibility("default"))) : obj(obj), func(func) {}
: Box(instancemethod_cls), obj(obj), func(func) {}
DEFAULT_CLASS(instancemethod_cls);
}; };
class GCdArray { class GCdArray {
...@@ -352,11 +362,13 @@ public: ...@@ -352,11 +362,13 @@ public:
DS_DEFINE_MUTEX(lock); DS_DEFINE_MUTEX(lock);
BoxedList() __attribute__((visibility("default"))) : Box(list_cls), size(0), capacity(0) {} BoxedList() __attribute__((visibility("default"))) : size(0), capacity(0) {}
void ensure(int space); void ensure(int space);
void shrink(); void shrink();
static const int INITIAL_CAPACITY; static const int INITIAL_CAPACITY;
DEFAULT_CLASS(list_cls);
}; };
class BoxedTuple : public Box { class BoxedTuple : public Box {
...@@ -364,8 +376,10 @@ public: ...@@ -364,8 +376,10 @@ public:
typedef std::vector<Box*, StlCompatAllocator<Box*>> GCVector; typedef std::vector<Box*, StlCompatAllocator<Box*>> GCVector;
GCVector elts; GCVector elts;
BoxedTuple(GCVector& elts) __attribute__((visibility("default"))) : Box(tuple_cls), elts(elts) {} BoxedTuple(GCVector& elts) __attribute__((visibility("default"))) : elts(elts) {}
BoxedTuple(GCVector&& elts) __attribute__((visibility("default"))) : Box(tuple_cls), elts(std::move(elts)) {} BoxedTuple(GCVector&& elts) __attribute__((visibility("default"))) : elts(std::move(elts)) {}
DEFAULT_CLASS(tuple_cls);
}; };
extern "C" BoxedTuple* EmptyTuple; extern "C" BoxedTuple* EmptyTuple;
...@@ -377,7 +391,9 @@ public: ...@@ -377,7 +391,9 @@ public:
bool closed; bool closed;
bool softspace; bool softspace;
BoxedFile(FILE* f, std::string fname, std::string fmode) __attribute__((visibility("default"))) BoxedFile(FILE* f, std::string fname, std::string fmode) __attribute__((visibility("default")))
: Box(file_cls), f(f), fname(fname), fmode(fmode), closed(false), softspace(false) {} : f(f), fname(fname), fmode(fmode), closed(false), softspace(false) {}
DEFAULT_CLASS(file_cls);
}; };
struct PyHasher { struct PyHasher {
...@@ -398,7 +414,9 @@ public: ...@@ -398,7 +414,9 @@ public:
DictMap d; DictMap d;
BoxedDict() __attribute__((visibility("default"))) : Box(dict_cls) {} BoxedDict() __attribute__((visibility("default"))) {}
DEFAULT_CLASS(dict_cls);
Box* getOrNull(Box* k) { Box* getOrNull(Box* k) {
const auto& p = d.find(k); const auto& p = d.find(k);
...@@ -424,6 +442,8 @@ public: ...@@ -424,6 +442,8 @@ public:
BoxedFunction(CLFunction* f); BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL, BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false); bool isGenerator = false);
DEFAULT_CLASS(function_cls);
}; };
class BoxedModule : public Box { class BoxedModule : public Box {
...@@ -434,12 +454,16 @@ public: ...@@ -434,12 +454,16 @@ public:
BoxedModule(const std::string& name, const std::string& fn); BoxedModule(const std::string& name, const std::string& fn);
std::string name(); std::string name();
DEFAULT_CLASS(module_cls);
}; };
class BoxedSlice : public Box { class BoxedSlice : public Box {
public: public:
Box* start, *stop, *step; Box* start, *stop, *step;
BoxedSlice(Box* lower, Box* upper, Box* step) : Box(slice_cls), start(lower), stop(upper), step(step) {} BoxedSlice(Box* lower, Box* upper, Box* step) : start(lower), stop(upper), step(step) {}
DEFAULT_CLASS(slice_cls);
}; };
class BoxedMemberDescriptor : public Box { class BoxedMemberDescriptor : public Box {
...@@ -468,9 +492,10 @@ public: ...@@ -468,9 +492,10 @@ public:
int offset; int offset;
BoxedMemberDescriptor(MemberType type, int offset) : Box(member_cls), type(type), offset(offset) {} BoxedMemberDescriptor(MemberType type, int offset) : type(type), offset(offset) {}
BoxedMemberDescriptor(PyMemberDef* member) BoxedMemberDescriptor(PyMemberDef* member) : type((MemberType)member->type), offset(member->offset) {}
: Box(member_cls), type((MemberType)member->type), offset(member->offset) {}
DEFAULT_CLASS(member_cls);
}; };
class BoxedProperty : public Box { class BoxedProperty : public Box {
...@@ -481,21 +506,27 @@ public: ...@@ -481,21 +506,27 @@ public:
Box* prop_doc; Box* prop_doc;
BoxedProperty(Box* get, Box* set, Box* del, Box* doc) BoxedProperty(Box* get, Box* set, Box* del, Box* doc)
: Box(property_cls), prop_get(get), prop_set(set), prop_del(del), prop_doc(doc) {} : prop_get(get), prop_set(set), prop_del(del), prop_doc(doc) {}
DEFAULT_CLASS(property_cls);
}; };
class BoxedStaticmethod : public Box { class BoxedStaticmethod : public Box {
public: public:
Box* sm_callable; Box* sm_callable;
BoxedStaticmethod(Box* callable) : Box(staticmethod_cls), sm_callable(callable){}; BoxedStaticmethod(Box* callable) : sm_callable(callable){};
DEFAULT_CLASS(staticmethod_cls);
}; };
class BoxedClassmethod : public Box { class BoxedClassmethod : public Box {
public: public:
Box* cm_callable; Box* cm_callable;
BoxedClassmethod(Box* callable) : Box(classmethod_cls), cm_callable(callable){}; BoxedClassmethod(Box* callable) : cm_callable(callable){};
DEFAULT_CLASS(classmethod_cls);
}; };
// TODO is there any particular reason to make this a Box, ie a python-level object? // TODO is there any particular reason to make this a Box, ie a python-level object?
...@@ -504,7 +535,9 @@ public: ...@@ -504,7 +535,9 @@ public:
HCAttrs attrs; HCAttrs attrs;
BoxedClosure* parent; BoxedClosure* parent;
BoxedClosure(BoxedClosure* parent) : Box(closure_cls), parent(parent) {} BoxedClosure(BoxedClosure* parent) : parent(parent) {}
DEFAULT_CLASS(closure_cls);
}; };
class BoxedGenerator : public Box { class BoxedGenerator : public Box {
...@@ -523,6 +556,8 @@ public: ...@@ -523,6 +556,8 @@ public:
void* stack_begin; void* stack_begin;
BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args); BoxedGenerator(BoxedFunction* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
DEFAULT_CLASS(generator_cls);
}; };
extern "C" void boxGCHandler(GCVisitor* v, Box* b); extern "C" void boxGCHandler(GCVisitor* v, Box* b);
...@@ -535,16 +570,6 @@ extern "C" BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError, ...@@ -535,16 +570,6 @@ extern "C" BoxedClass* Exception, *AssertionError, *AttributeError, *TypeError,
*IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError, *IOError, *OSError, *ZeroDivisionError, *ValueError, *UnboundLocalError, *RuntimeError, *ImportError,
*StopIteration, *GeneratorExit, *SyntaxError; *StopIteration, *GeneratorExit, *SyntaxError;
// cls should be obj->cls.
// Added as parameter because it should typically be available
inline void initUserAttrs(Box* obj, BoxedClass* cls) {
assert(obj->cls == cls);
if (cls->attrs_offset) {
HCAttrs* attrs = obj->getAttrsPtr();
attrs = new ((void*)attrs) HCAttrs();
}
}
Box* makeAttrWrapper(Box* b); Box* makeAttrWrapper(Box* b);
} }
#endif #endif
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