Box* objectNew(BoxedClass* cls, BoxedTuple* args) { assert(isSubclass(cls->cls, type_cls)); assert(args->cls == tuple_cls); if (args->elts.size() != 0) { if (typeLookup(cls, "__init__", NULL, NULL) == NULL) raiseExcHelper(TypeError, "object.__new__() takes no parameters"); } assert(cls->instance_size >= sizeof(Box)); void* mem = rt_alloc(cls->instance_size); Box* rtn = ::new (mem) Box(&object_flavor, cls); initUserAttrs(rtn, cls); return rtn; }
extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) { 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; }