Commit cffc1b89 authored by Marius Wachtler's avatar Marius Wachtler

hidden classes: split into subclasses to reduce memory consumption

+ use pyston::DenseMap to save a little more memory

this saves about 5%-10% of peak memory on django
parent 84b0c7be
......@@ -681,7 +681,8 @@ public:
};
class HiddenClass;
extern HiddenClass* root_hcls;
class HiddenClassNormal;
extern HiddenClassNormal* root_hcls;
struct SetattrRewriteArgs;
struct GetattrRewriteArgs;
......
......@@ -27,7 +27,35 @@
namespace pyston {
void HiddenClass::appendAttribute(BoxedString* attr) {
HiddenClassSingleton* HiddenClass::makeSingleton() {
return new HiddenClassSingleton;
}
HiddenClassNormal* HiddenClass::makeRoot() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClassNormal;
}
HiddenClassDict* HiddenClass::makeDictBacked() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClassDict;
}
int HiddenClass::attributeArraySize() {
if (type == HiddenClass::DICT_BACKED)
return getAsDictBacked()->attributeArraySize();
return getAsSingletonOrNormal()->attributeArraySize();
}
void HiddenClassSingleton::appendAttribute(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == SINGLETON);
dependent_getattrs.invalidateAll();
......@@ -36,14 +64,14 @@ void HiddenClass::appendAttribute(BoxedString* attr) {
attr_offsets[attr] = n;
}
void HiddenClass::appendAttrwrapper() {
void HiddenClassSingleton::appendAttrwrapper() {
assert(type == SINGLETON);
dependent_getattrs.invalidateAll();
assert(attrwrapper_offset == -1);
attrwrapper_offset = this->attributeArraySize();
}
void HiddenClass::delAttribute(BoxedString* attr) {
void HiddenClassSingleton::delAttribute(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == SINGLETON);
dependent_getattrs.invalidateAll();
......@@ -61,12 +89,12 @@ void HiddenClass::delAttribute(BoxedString* attr) {
attrwrapper_offset--;
}
void HiddenClass::addDependence(Rewriter* rewriter) {
void HiddenClassSingleton::addDependence(Rewriter* rewriter) {
assert(type == SINGLETON);
rewriter->addDependenceOn(dependent_getattrs);
}
HiddenClass* HiddenClass::getOrMakeChild(BoxedString* attr) {
HiddenClassNormal* HiddenClassNormal::getOrMakeChild(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_getOrMakeChild", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
......@@ -74,25 +102,25 @@ HiddenClass* HiddenClass::getOrMakeChild(BoxedString* attr) {
auto it = children.find(attr);
if (it != children.end())
return children.getMapped(it->second);
return it->second;
static StatCounter num_hclses("num_hidden_classes");
num_hclses.log();
// XXX: need to hold a ref to the string (or maybe we don't if we can hook the un-interning)
HiddenClass* rtn = new HiddenClass(this);
HiddenClassNormal* rtn = new HiddenClassNormal(this);
rtn->attr_offsets[attr] = this->attributeArraySize();
this->children[attr] = rtn;
assert(rtn->attributeArraySize() == this->attributeArraySize() + 1);
return rtn;
}
HiddenClass* HiddenClass::getAttrwrapperChild() {
HiddenClassNormal* HiddenClassNormal::getAttrwrapperChild() {
assert(type == NORMAL);
assert(attrwrapper_offset == -1);
if (!attrwrapper_child) {
HiddenClass* made = new HiddenClass(this);
HiddenClassNormal* made = new HiddenClassNormal(this);
made->attrwrapper_offset = this->attributeArraySize();
this->attrwrapper_child = made;
assert(made->attributeArraySize() == this->attributeArraySize() + 1);
......@@ -104,7 +132,7 @@ HiddenClass* HiddenClass::getAttrwrapperChild() {
/**
* del attr from current HiddenClass, maintaining the order of the remaining attrs
*/
HiddenClass* HiddenClass::delAttrToMakeHC(BoxedString* attr) {
HiddenClassNormal* HiddenClassNormal::delAttrToMakeHC(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_delAttrToMakeHC", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
......@@ -127,7 +155,7 @@ HiddenClass* HiddenClass::delAttrToMakeHC(BoxedString* attr) {
// TODO we can first locate the parent HiddenClass of the deleted
// attribute and hence avoid creation of its ancestors.
HiddenClass* cur = root_hcls;
HiddenClassNormal* cur = root_hcls;
int curidx = 0;
for (const auto& attr : new_attrs) {
if (curidx == new_attrwrapper_offset)
......
......@@ -19,16 +19,20 @@
#include "Python.h"
#include "core/contiguous_map.h"
#include "core/from_llvm/DenseMap.h"
#include "core/types.h"
namespace pyston {
class HiddenClassDict;
class HiddenClassNormal;
class HiddenClassSingleton;
class HiddenClassSingletonOrNormal;
class HiddenClass {
public:
// We have a couple different storage strategies for attributes, which
// are distinguished by having a different hidden class type.
enum HCType {
enum HCType : unsigned char {
NORMAL, // attributes stored in attributes array, name->offset map stored in hidden class
DICT_BACKED, // first attribute in array is a dict-like object which stores the attributes
SINGLETON, // name->offset map stored in hidden class, but hcls is mutable
......@@ -37,70 +41,76 @@ public:
static HiddenClass* dict_backed;
void dump() noexcept;
private:
protected:
HiddenClass(HCType type) : type(type) {}
HiddenClass(HiddenClass* parent)
: type(NORMAL), attr_offsets(parent->attr_offsets), attrwrapper_offset(parent->attrwrapper_offset) {
assert(parent->type == NORMAL);
}
virtual ~HiddenClass() = default;
// These fields only make sense for NORMAL or SINGLETON hidden classes:
llvm::DenseMap<BoxedString*, int> attr_offsets;
// If >= 0, is the offset where we stored an attrwrapper object
int attrwrapper_offset = -1;
public:
static HiddenClassSingleton* makeSingleton();
static HiddenClassNormal* makeRoot();
static HiddenClassDict* makeDictBacked();
// These are only for NORMAL hidden classes:
ContiguousMap<BoxedString*, HiddenClass*, llvm::DenseMap<BoxedString*, int>> children;
HiddenClass* attrwrapper_child = NULL;
int attributeArraySize();
// Only for SINGLETON hidden classes:
ICInvalidator dependent_getattrs;
HiddenClassDict* getAsDictBacked() {
assert(type == HiddenClass::DICT_BACKED);
return reinterpret_cast<HiddenClassDict*>(this);
}
public:
static HiddenClass* makeSingleton() { return new HiddenClass(SINGLETON); }
HiddenClassNormal* getAsNormal() {
assert(type == HiddenClass::NORMAL);
return reinterpret_cast<HiddenClassNormal*>(this);
}
static HiddenClass* makeRoot() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClass(NORMAL);
HiddenClassSingleton* getAsSingleton() {
assert(type == HiddenClass::SINGLETON);
return reinterpret_cast<HiddenClassSingleton*>(this);
}
static HiddenClass* makeDictBacked() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClass(DICT_BACKED);
HiddenClassSingletonOrNormal* getAsSingletonOrNormal() {
assert(type == HiddenClass::NORMAL || type == HiddenClass::SINGLETON);
return reinterpret_cast<HiddenClassSingletonOrNormal*>(this);
}
};
class HiddenClassDict final : public HiddenClass {
protected:
HiddenClassDict() : HiddenClass(HiddenClass::DICT_BACKED) {}
public:
// The total size of the attribute array. The slots in the attribute array may not correspond 1:1 to Python
// attributes.
int attributeArraySize() {
if (type == DICT_BACKED)
return 1;
int attributeArraySize() { return 1; }
ASSERT(type == NORMAL || type == SINGLETON, "%d", type);
int r = attr_offsets.size();
if (attrwrapper_offset != -1)
r += 1;
return r;
friend class HiddenClass;
};
class HiddenClassSingletonOrNormal : public HiddenClass {
protected:
HiddenClassSingletonOrNormal(HCType type) : HiddenClass(type) {}
HiddenClassSingletonOrNormal(HiddenClassSingletonOrNormal* parent)
: HiddenClass(HiddenClass::NORMAL),
attrwrapper_offset(parent->attrwrapper_offset),
attr_offsets(parent->attr_offsets) {
assert(parent->type == HiddenClass::NORMAL);
}
// If >= 0, is the offset where we stored an attrwrapper object
int attrwrapper_offset = -1;
typedef pyston::DenseMap<BoxedString*, int, pyston::DenseMapInfo<BoxedString*>,
pyston::detail::DenseMapPair<BoxedString*, int>, 16> Map;
Map attr_offsets;
public:
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// array.
// Only valid for NORMAL or SINGLETON hidden classes
BORROWED(const llvm::DenseMap<BoxedString*, int>&) getStrAttrOffsets() {
BORROWED(const Map&) getStrAttrOffsets() {
assert(type == NORMAL || type == SINGLETON);
return attr_offsets;
}
// Only valid for NORMAL hidden classes:
HiddenClass* getOrMakeChild(BoxedString* attr);
// Only valid for NORMAL or SINGLETON hidden classes:
int getOffset(BoxedString* attr) {
assert(type == NORMAL || type == SINGLETON);
auto it = attr_offsets.find(attr);
......@@ -114,17 +124,48 @@ public:
return attrwrapper_offset;
}
// Only valid for SINGLETON hidden classes:
// The total size of the attribute array. The slots in the attribute array may not correspond 1:1 to Python
// attributes.
int attributeArraySize() {
ASSERT(type == NORMAL || type == SINGLETON, "%d", type);
int r = attr_offsets.size();
if (attrwrapper_offset != -1)
r += 1;
return r;
}
friend class HiddenClass;
};
class HiddenClassNormal final : public HiddenClassSingletonOrNormal {
protected:
HiddenClassNormal() : HiddenClassSingletonOrNormal(HiddenClass::NORMAL) {}
HiddenClassNormal(HiddenClassNormal* parent) : HiddenClassSingletonOrNormal(parent) {}
pyston::SmallDenseMap<BoxedString*, HiddenClassNormal*> children;
HiddenClassNormal* attrwrapper_child = NULL;
public:
HiddenClassNormal* getOrMakeChild(BoxedString* attr);
HiddenClassNormal* getAttrwrapperChild();
HiddenClassNormal* delAttrToMakeHC(BoxedString* attr);
friend class HiddenClass;
};
class HiddenClassSingleton final : public HiddenClassSingletonOrNormal {
protected:
HiddenClassSingleton() : HiddenClassSingletonOrNormal(HiddenClass::SINGLETON) {}
ICInvalidator dependent_getattrs;
public:
void appendAttribute(BoxedString* attr);
void appendAttrwrapper();
void delAttribute(BoxedString* attr);
void addDependence(Rewriter* rewriter);
// Only valid for NORMAL hidden classes:
HiddenClass* getAttrwrapperChild();
// Only valid for NORMAL hidden classes:
HiddenClass* delAttrToMakeHC(BoxedString* attr);
friend class HiddenClass;
};
}
#endif
......@@ -1070,9 +1070,8 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
// otherwise the guard will fail anyway.;
if (cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = getHCAttrsPtr();
HiddenClass* hcls = attrs->hcls;
if (unlikely(hcls && hcls->type == HiddenClass::DICT_BACKED)) {
if (unlikely(attrs->hcls && attrs->hcls->type == HiddenClass::DICT_BACKED)) {
if (rewrite_args)
assert(!rewrite_args->isSuccessful());
rewrite_args = NULL;
......@@ -1084,7 +1083,8 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
return r;
}
assert(!hcls || hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);
assert(!attrs->hcls || attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON);
auto hcls = attrs->hcls ? attrs->hcls->getAsSingletonOrNormal() : NULL;
if (unlikely(rewrite_args)) {
if (!rewrite_args->obj_hcls_guarded) {
......@@ -1097,7 +1097,7 @@ template <Rewritable rewritable> BORROWED(Box*) Box::getattr(BoxedString* attr,
rewrite_args->obj->addAttrGuard(cls->attrs_offset + offsetof(HCAttrs, hcls), (intptr_t)hcls);
}
if (hcls && hcls->type == HiddenClass::SINGLETON)
hcls->addDependence(rewrite_args->rewriter);
hcls->getAsSingleton()->addDependence(rewrite_args->rewriter);
}
}
}
......@@ -1283,7 +1283,7 @@ void Box::setDictBacked(STOLEN(Box*) val) {
// e.g.:
// a = v.__dict__
// v.__dict__ = {} # 'a' must switch now from wrapping 'v' to a the private dict.
int offset = hcls->getAttrwrapperOffset();
int offset = hcls->getAsSingletonOrNormal()->getAttrwrapperOffset();
if (offset != -1) {
Box* wrapper = hcattrs->attr_list->attrs[offset];
RELEASE_ASSERT(wrapper->cls == attrwrapper_cls, "");
......@@ -1296,7 +1296,7 @@ void Box::setDictBacked(STOLEN(Box*) val) {
new_attr_list->attrs[0] = val;
auto old_attr_list = hcattrs->attr_list;
int old_attr_list_size = hcls->attributeArraySize();
int old_attr_list_size = hcls->getAsSingletonOrNormal()->attributeArraySize();
hcattrs->hcls = HiddenClass::dict_backed;
hcattrs->attr_list = new_attr_list;
......@@ -1337,7 +1337,7 @@ void HCAttrs::clearForDealloc() noexcept {
return;
if (hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON) {
int offset = hcls->getAttrwrapperOffset();
int offset = hcls->getAsSingletonOrNormal()->getAttrwrapperOffset();
if (offset != -1) {
Box* attrwrapper = this->attr_list->attrs[offset];
if (attrwrapper->ob_refcnt != 1)
......@@ -1377,7 +1377,7 @@ void HCAttrs::moduleClear() noexcept {
RELEASE_ASSERT(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON, "");
auto attr_list = this->attr_list;
for (auto&& p : hcls->getStrAttrOffsets()) {
for (auto&& p : hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
const char* s = p.first->c_str();
if (first_check_func(s)) {
int idx = p.second;
......@@ -1387,7 +1387,7 @@ void HCAttrs::moduleClear() noexcept {
}
}
for (auto&& p : hcls->getStrAttrOffsets()) {
for (auto&& p : hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
const char* s = p.first->c_str();
if (second_check_func(s)) {
int idx = p.second;
......@@ -1480,16 +1480,16 @@ void Box::setattr(BoxedString* attr, BORROWED(Box*) val, SetattrRewriteArgs* rew
if (cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = getHCAttrsPtr();
HiddenClass* hcls = attrs->hcls;
HiddenClass* hcls_ = attrs->hcls;
if (unlikely(hcls == NULL)) {
if (unlikely(hcls_ == NULL)) {
// We could update PyObject_Init and PyObject_INIT to do this, but that has a small compatibility
// issue (what if people don't call either of those) and I'm not sure that this check will be that
// harmful. But if it is we might want to try pushing this assignment to allocation time.
hcls = root_hcls;
hcls_ = root_hcls;
}
if (hcls->type == HiddenClass::DICT_BACKED) {
if (hcls_->type == HiddenClass::DICT_BACKED) {
if (rewrite_args)
assert(!rewrite_args->out_success);
rewrite_args = NULL;
......@@ -1501,8 +1501,9 @@ void Box::setattr(BoxedString* attr, BORROWED(Box*) val, SetattrRewriteArgs* rew
return;
}
assert(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);
assert(hcls_->type == HiddenClass::NORMAL || hcls_->type == HiddenClass::SINGLETON);
auto hcls = hcls_->getAsSingletonOrNormal();
int offset = hcls->getOffset(attr);
if (rewrite_args) {
......@@ -1512,7 +1513,7 @@ void Box::setattr(BoxedString* attr, BORROWED(Box*) val, SetattrRewriteArgs* rew
} else {
rewrite_args->obj->addAttrGuard(cls->attrs_offset + offsetof(HCAttrs, hcls), (intptr_t)attrs->hcls);
if (hcls->type == HiddenClass::SINGLETON)
hcls->addDependence(rewrite_args->rewriter);
hcls->getAsSingleton()->addDependence(rewrite_args->rewriter);
}
}
......@@ -1544,7 +1545,7 @@ void Box::setattr(BoxedString* attr, BORROWED(Box*) val, SetattrRewriteArgs* rew
assert(offset == -1);
if (hcls->type == HiddenClass::NORMAL) {
HiddenClass* new_hcls = hcls->getOrMakeChild(attr);
auto* new_hcls = hcls->getAsNormal()->getOrMakeChild(attr);
// make sure we don't need to rearrange the attributes
assert(new_hcls->getStrAttrOffsets().lookup(attr) == hcls->attributeArraySize());
......@@ -1567,7 +1568,7 @@ void Box::setattr(BoxedString* attr, BORROWED(Box*) val, SetattrRewriteArgs* rew
rewrite_args = NULL;
this->appendNewHCAttr(val, NULL);
hcls->appendAttribute(attr);
hcls->getAsSingleton()->appendAttribute(attr);
}
return;
......@@ -6617,9 +6618,8 @@ void Box::delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args) {
if (cls->instancesHaveHCAttrs()) {
// as soon as the hcls changes, the guard on hidden class won't pass.
HCAttrs* attrs = getHCAttrsPtr();
HiddenClass* hcls = attrs->hcls;
if (hcls->type == HiddenClass::DICT_BACKED) {
if (attrs->hcls->type == HiddenClass::DICT_BACKED) {
if (rewrite_args)
assert(!rewrite_args->out_success);
rewrite_args = NULL;
......@@ -6631,7 +6631,8 @@ void Box::delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args) {
return;
}
assert(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON);
assert(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON);
auto* hcls = attrs->hcls->getAsSingletonOrNormal();
// The order of attributes is pertained as delAttrToMakeHC constructs
// the new HiddenClass by invoking getOrMakeChild in the prevous order
......@@ -6644,11 +6645,11 @@ void Box::delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args) {
memmove(start + offset, start + offset + 1, (num_attrs - offset - 1) * sizeof(Box*));
if (hcls->type == HiddenClass::NORMAL) {
HiddenClass* new_hcls = hcls->delAttrToMakeHC(attr);
HiddenClass* new_hcls = hcls->getAsNormal()->delAttrToMakeHC(attr);
attrs->hcls = new_hcls;
} else {
assert(hcls->type == HiddenClass::SINGLETON);
hcls->delAttribute(attr);
hcls->getAsSingleton()->delAttribute(attr);
}
// guarantee the size of the attr_list equals the number of attrs
......@@ -7502,7 +7503,7 @@ extern "C" Box* importStar(Box* _from_module, Box* to_globals) {
}
HCAttrs* module_attrs = from_module->getHCAttrsPtr();
for (auto& p : module_attrs->hcls->getStrAttrOffsets()) {
for (auto& p : module_attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
if (p.first->data()[0] == '_')
continue;
......
......@@ -1793,7 +1793,7 @@ Box* trap_obj = NULL;
Box* range_obj = NULL;
}
HiddenClass* root_hcls;
HiddenClassNormal* root_hcls;
HiddenClass* HiddenClass::dict_backed;
extern "C" Box* createSlice(Box* start, Box* stop, Box* step) {
......@@ -2258,7 +2258,7 @@ private:
// Iterating over the an attrwrapper (~=dict) just gives the keys, which
// just depends on the hidden class of the object. Let's store only that:
HiddenClass* hcls;
llvm::DenseMap<BoxedString*, int>::const_iterator it;
pyston::DenseMap<BoxedString*, int>::const_iterator it;
public:
AttrWrapperIter(AttrWrapper* aw);
......@@ -2576,7 +2576,7 @@ public:
os << "{";
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
bool first = true;
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
if (!first)
os << ", ";
first = false;
......@@ -2644,7 +2644,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
listAppendInternal(rtn, p.first);
}
return rtn;
......@@ -2664,7 +2664,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
listAppendInternal(rtn, attrs->attr_list->attrs[p.second]);
}
return rtn;
......@@ -2684,7 +2684,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getAsSingletonOrNormal()->getStrAttrOffsets()) {
BoxedTuple* t = BoxedTuple::create({ p.first, attrs->attr_list->attrs[p.second] });
listAppendInternalStolen(rtn, t);
}
......@@ -2720,7 +2720,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
ASSERT(rtn->d.count(p.first) == 0, "need to decref existing keys");
rtn->d[incref(p.first)] = incref(attrs->attr_list->attrs[p.second]);
}
......@@ -2748,7 +2748,7 @@ public:
self->b->appendNewHCAttr(self, NULL);
if (!attrs->hcls)
attrs->hcls = root_hcls;
attrs->hcls = attrs->hcls->getAttrwrapperChild();
attrs->hcls = attrs->hcls->getAsNormal()->getAttrwrapperChild();
}
static Box* clear(Box* _self) {
......@@ -2770,7 +2770,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
return boxInt(attrs->hcls->getStrAttrOffsets().size());
return boxInt(attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets().size());
}
static Box* update(Box* _self, BoxedTuple* args, BoxedDict* kwargs) {
......@@ -2797,7 +2797,7 @@ public:
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON,
"");
for (const auto& p : attrs->hcls->getStrAttrOffsets()) {
for (const auto& p : attrs->hcls->getAsSingletonOrNormal()->getStrAttrOffsets()) {
self->b->setattr(p.first, attrs->attr_list->attrs[p.second], NULL);
}
} else {
......@@ -2871,7 +2871,7 @@ AttrWrapperIter::AttrWrapperIter(AttrWrapper* aw) {
hcls = aw->b->getHCAttrsPtr()->hcls;
assert(hcls);
RELEASE_ASSERT(hcls->type == HiddenClass::NORMAL || hcls->type == HiddenClass::SINGLETON, "");
it = hcls->getStrAttrOffsets().begin();
it = hcls->getAsSingletonOrNormal()->getStrAttrOffsets().begin();
}
Box* AttrWrapperIter::hasnext(Box* _self) {
......@@ -2879,7 +2879,7 @@ Box* AttrWrapperIter::hasnext(Box* _self) {
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
return boxBool(self->it != self->hcls->getStrAttrOffsets().end());
return boxBool(self->it != self->hcls->getAsSingletonOrNormal()->getStrAttrOffsets().end());
}
Box* AttrWrapperIter::next(Box* _self) {
......@@ -2887,7 +2887,7 @@ Box* AttrWrapperIter::next(Box* _self) {
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
assert(self->it != self->hcls->getStrAttrOffsets().end());
assert(self->it != self->hcls->getAsSingletonOrNormal()->getStrAttrOffsets().end());
Box* r = self->it->first;
++self->it;
return incref(r);
......@@ -2898,7 +2898,7 @@ Box* AttrWrapperIter::next_capi(Box* _self) noexcept {
AttrWrapperIter* self = static_cast<AttrWrapperIter*>(_self);
RELEASE_ASSERT(self->hcls->type == HiddenClass::NORMAL || self->hcls->type == HiddenClass::SINGLETON, "");
if (self->it == self->hcls->getStrAttrOffsets().end())
if (self->it == self->hcls->getAsSingletonOrNormal()->getStrAttrOffsets().end())
return NULL;
Box* r = self->it->first;
++self->it;
......@@ -2930,11 +2930,11 @@ BORROWED(Box*) Box::getAttrWrapper() {
return attrs->attr_list->attrs[0];
}
int offset = hcls->getAttrwrapperOffset();
int offset = hcls->getAsSingletonOrNormal()->getAttrwrapperOffset();
if (offset == -1) {
Box* aw = new AttrWrapper(this);
if (hcls->type == HiddenClass::NORMAL) {
auto new_hcls = hcls->getAttrwrapperChild();
auto new_hcls = hcls->getAsNormal()->getAttrwrapperChild();
appendNewHCAttr(aw, NULL);
attrs->hcls = new_hcls;
Py_DECREF(aw);
......@@ -2942,7 +2942,7 @@ BORROWED(Box*) Box::getAttrWrapper() {
} else {
assert(hcls->type == HiddenClass::SINGLETON);
appendNewHCAttr(aw, NULL);
hcls->appendAttrwrapper();
hcls->getAsSingleton()->appendAttrwrapper();
Py_DECREF(aw);
return aw;
}
......@@ -3731,8 +3731,8 @@ void HiddenClass::dump() noexcept {
printf("Singleton hcls:\n");
else
printf("Normal hcls:\n");
printf("Attrwrapper offset: %d\n", attrwrapper_offset);
for (auto p : attr_offsets) {
printf("Attrwrapper offset: %d\n", getAsSingletonOrNormal()->attrwrapper_offset);
for (auto p : getAsSingletonOrNormal()->attr_offsets) {
// printf("%d: %s\n", p.second, p.first->c_str());
printf("%d: %p\n", p.second, p.first);
}
......
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