Commit 5c821d67 authored by Travis Hance's avatar Travis Hance

The slots should already be null-initialized, so just assert that they are...

The slots should already be null-initialized, so just assert that they are NULL rather than re-initializing them.
parent a043eed8
...@@ -479,7 +479,6 @@ typedef struct _heaptypeobject { ...@@ -479,7 +479,6 @@ typedef struct _heaptypeobject {
see add_operators() in typeobject.c . */ see add_operators() in typeobject.c . */
PyBufferProcs as_buffer; PyBufferProcs as_buffer;
PyObject *ht_name, *ht_slots; PyObject *ht_name, *ht_slots;
Py_ssize_t nslots;
/* here are optional user slots, followed by the members. */ /* here are optional user slots, followed by the members. */
} PyHeapTypeObject; } PyHeapTypeObject;
......
...@@ -393,9 +393,9 @@ void BoxedClass::finishInitialization() { ...@@ -393,9 +393,9 @@ void BoxedClass::finishInitialization() {
} }
BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, BoxedString* name, size_t nslots) int instance_size, bool is_user_defined, BoxedString* name)
: BoxedClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined), ht_name(name), : BoxedClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined), ht_name(name),
ht_slots(NULL), nslots(nslots) { ht_slots(NULL) {
tp_as_number = &as_number; tp_as_number = &as_number;
tp_as_mapping = &as_mapping; tp_as_mapping = &as_mapping;
...@@ -424,7 +424,7 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, ...@@ -424,7 +424,7 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base,
int weaklist_offset, int instance_size, bool is_user_defined, BoxedString* name, int weaklist_offset, int instance_size, bool is_user_defined, BoxedString* name,
BoxedTuple* bases, size_t nslots) { BoxedTuple* bases, size_t nslots) {
BoxedHeapClass* made = new (metaclass, nslots) BoxedHeapClass* made = new (metaclass, nslots)
BoxedHeapClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined, name, nslots); BoxedHeapClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined, name);
assert((name || str_cls == NULL) && "name can only be NULL before str_cls has been initialized."); assert((name || str_cls == NULL) && "name can only be NULL before str_cls has been initialized.");
...@@ -4187,7 +4187,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -4187,7 +4187,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
basic_size = cur_offset; basic_size = cur_offset;
size_t total_slots = final_slot_names.size() size_t total_slots = final_slot_names.size()
+ (base->tp_flags & Py_TPFLAGS_HEAPTYPE ? static_cast<BoxedHeapClass*>(base)->nslots : 0); + (base->tp_flags & Py_TPFLAGS_HEAPTYPE ? static_cast<BoxedHeapClass*>(base)->nslots() : 0);
BoxedHeapClass* made = BoxedHeapClass::create(metatype, base, NULL, attrs_offset, weaklist_offset, basic_size, true, BoxedHeapClass* made = BoxedHeapClass::create(metatype, base, NULL, attrs_offset, weaklist_offset, basic_size, true,
name, bases, total_slots); name, bases, total_slots);
made->tp_dictoffset = dict_offset; made->tp_dictoffset = dict_offset;
...@@ -4214,13 +4214,14 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -4214,13 +4214,14 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
} }
// Add slot offsets for slots of the base // Add slot offsets for slots of the base
// NOTE: I don't think CPython does this // NOTE: CPython does this, but I don't want to have to traverse the class hierarchy to
// traverse all the slots, so I'm putting them all here.
if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) { if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
BoxedHeapClass::SlotOffset* slot_offsets = made->slotOffsets(); BoxedHeapClass::SlotOffset* slot_offsets = made->slotOffsets();
BoxedHeapClass* base_heap_cls = static_cast<BoxedHeapClass*>(base); BoxedHeapClass* base_heap_cls = static_cast<BoxedHeapClass*>(base);
BoxedHeapClass::SlotOffset* base_slot_offsets = base_heap_cls->slotOffsets(); BoxedHeapClass::SlotOffset* base_slot_offsets = base_heap_cls->slotOffsets();
memcpy(&slot_offsets[final_slot_names.size()], base_slot_offsets, memcpy(&slot_offsets[final_slot_names.size()], base_slot_offsets,
base_heap_cls->nslots * sizeof(BoxedHeapClass::SlotOffset)); base_heap_cls->nslots() * sizeof(BoxedHeapClass::SlotOffset));
} }
if (!made->getattr("__dict__") && (made->instancesHaveHCAttrs() || made->instancesHaveDictAttrs())) if (!made->getattr("__dict__") && (made->instancesHaveHCAttrs() || made->instancesHaveDictAttrs()))
......
...@@ -467,7 +467,7 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) { ...@@ -467,7 +467,7 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) {
if (b->cls->tp_flags & Py_TPFLAGS_HEAPTYPE) { if (b->cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(b->cls); BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(b->cls);
BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets(); BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets();
for (int i = 0; i < heap_cls->nslots; i++) { for (int i = 0; i < heap_cls->nslots(); i++) {
v->visit(*((Box**)((char*)b + slotOffsets[i]))); v->visit(*((Box**)((char*)b + slotOffsets[i])));
} }
} }
...@@ -1981,16 +1981,19 @@ extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept { ...@@ -1981,16 +1981,19 @@ extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) noexcept {
// initUserAttrs themselves, though. // initUserAttrs themselves, though.
initUserAttrs(op, tp); initUserAttrs(op, tp);
// Initialize the variables declared in __slots__ to NULL. #ifndef NDEBUG
if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) { if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(tp); BoxedHeapClass* heap_cls = static_cast<BoxedHeapClass*>(tp);
if (heap_cls->nslots > 0) { if (heap_cls->nslots() > 0) {
BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets(); BoxedHeapClass::SlotOffset* slotOffsets = heap_cls->slotOffsets();
for (int i = 0; i < heap_cls->nslots; i++) { for (int i = 0; i < heap_cls->nslots(); i++) {
*(Box**)((char*)op + slotOffsets[i]) = NULL; // This should be set to 0 on allocation:
// (If it wasn't, we would need to initialize it to 0 here.)
assert(*(Box**)((char*)op + slotOffsets[i]) == NULL);
} }
} }
} }
#endif
return op; return op;
} }
......
...@@ -236,9 +236,9 @@ public: ...@@ -236,9 +236,9 @@ public:
BoxedString* ht_name; BoxedString* ht_name;
PyObject* ht_slots; PyObject* ht_slots;
size_t nslots;
typedef size_t SlotOffset; typedef size_t SlotOffset;
SlotOffset* slotOffsets() { return (BoxedHeapClass::SlotOffset*)((char*)this + this->cls->tp_basicsize); } SlotOffset* slotOffsets() { return (BoxedHeapClass::SlotOffset*)((char*)this + this->cls->tp_basicsize); }
size_t nslots() { return this->ob_size; }
// These functions are the preferred way to construct new types: // These functions are the preferred way to construct new types:
static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
...@@ -253,7 +253,7 @@ private: ...@@ -253,7 +253,7 @@ private:
// by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class // by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
// creation due to bootstrapping issues. // creation due to bootstrapping issues.
BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size, BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
bool is_user_defined, BoxedString* name, size_t nslots = 0); bool is_user_defined, BoxedString* name);
friend void setupRuntime(); friend void setupRuntime();
friend void setupSys(); friend void setupSys();
......
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