Commit 96c7b4f2 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #554 from kmod/fast_attrwrapper_clear

Faster version of attrwrapper.clear()
parents fec260af 7025806b
......@@ -454,9 +454,6 @@ struct _typeobject {
void* _hcls;
void* _hcattrs;
// FIXME: this is hardcoding the size of this particular implementation of std::unordered_map
char _dep_getattrs[56]; // gcc 4.8
// char _dep_getattrs[64]; // gcc 4.9
char _ics[32];
void* _gcvisit_func;
void* _dtor;
......
......@@ -2964,7 +2964,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
assert(cls->attrs.hcls == NULL);
new (&cls->attrs) HCAttrs(HiddenClass::makeSingleton());
#define INITIALIZE(a) new (&(a)) decltype(a)
INITIALIZE(cls->dependent_icgetattrs);
#undef INITIALIZE
BoxedClass* base = cls->tp_base;
......
......@@ -500,6 +500,8 @@ public:
bool nonzeroIC();
Box* hasnextOrNullIC();
Box* nextIC();
friend class AttrWrapper;
};
static_assert(offsetof(Box, cls) == offsetof(struct _object, ob_type), "");
......
......@@ -536,6 +536,8 @@ HiddenClass* HiddenClass::getOrMakeChild(const std::string& attr) {
HiddenClass* HiddenClass::getAttrwrapperChild() {
assert(type == NORMAL);
assert(attrwrapper_offset == -1);
if (!attrwrapper_child) {
attrwrapper_child = new HiddenClass(this);
attrwrapper_child->attrwrapper_offset = this->attributeArraySize();
......@@ -1932,17 +1934,6 @@ void setattrGeneric(Box* obj, const std::string& attr, Box* val, SetattrRewriteA
if (isSubclass(obj->cls, type_cls)) {
BoxedClass* self = static_cast<BoxedClass*>(obj);
if (attr == getattr_str || attr == getattribute_str) {
if (rewrite_args)
REWRITE_ABORTED("");
// Will have to embed the clear in the IC, so just disable the patching for now:
rewrite_args = NULL;
// TODO should put this clearing behavior somewhere else, since there are probably more
// cases in which we want to do it.
self->dependent_icgetattrs.invalidateAll();
}
if (attr == "__base__" && self->getattr("__base__"))
raiseExcHelper(TypeError, "readonly attribute");
......@@ -3995,17 +3986,6 @@ extern "C" void delattrGeneric(Box* obj, const std::string& attr, DelattrRewrite
if (isSubclass(obj->cls, type_cls)) {
BoxedClass* self = static_cast<BoxedClass*>(obj);
if (attr == getattr_str || attr == getattribute_str) {
if (rewrite_args)
REWRITE_ABORTED("");
// Will have to embed the clear in the IC, so just disable the patching for now:
rewrite_args = NULL;
// TODO should put this clearing behavior somewhere else, since there are probably more
// cases in which we want to do it.
self->dependent_icgetattrs.invalidateAll();
}
if (attr == "__base__" && self->getattr("__base__"))
raiseExcHelper(TypeError, "readonly attribute");
......@@ -4015,6 +3995,9 @@ extern "C" void delattrGeneric(Box* obj, const std::string& attr, DelattrRewrite
REWRITE_ABORTED("");
}
}
// Extra "use" of rewrite_args to make the compiler happy:
(void)rewrite_args;
}
extern "C" void delattrInternal(Box* obj, const std::string& attr, DelattrRewriteArgs* rewrite_args) {
......
......@@ -1563,12 +1563,12 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL || attrs->hcls->type == HiddenClass::SINGLETON, "");
while (true) {
const auto& attrMap = attrs->hcls->getStrAttrOffsets();
if (attrMap.size() == 0)
break;
self->b->delattr(attrMap.begin()->first(), NULL);
}
// Clear the attrs array:
new ((void*)attrs) HCAttrs(root_hcls);
// Add the existing attrwrapper object (ie self) back as the attrwrapper:
self->b->appendNewHCAttr(self, NULL);
attrs->hcls = attrs->hcls->getAttrwrapperChild();
return None;
}
......
......@@ -152,12 +152,6 @@ public:
HCAttrs attrs;
// If the user sets __getattribute__ or __getattr__, we will have to invalidate
// all getattr IC entries that relied on the fact that those functions didn't exist.
// Doing this via invalidation means that instance attr lookups don't have
// to guard on anything about the class.
ICInvalidator dependent_icgetattrs;
// TODO: these don't actually get deallocated right now
std::unique_ptr<CallattrIC> hasnext_ic, next_ic, repr_ic;
std::unique_ptr<NonzeroIC> nonzero_ic;
......@@ -268,7 +262,6 @@ static_assert(offsetof(pyston::Box, cls) == offsetof(struct _object, ob_type), "
static_assert(offsetof(pyston::BoxedClass, cls) == offsetof(struct _typeobject, ob_type), "");
static_assert(offsetof(pyston::BoxedClass, tp_name) == offsetof(struct _typeobject, tp_name), "");
static_assert(offsetof(pyston::BoxedClass, attrs) == offsetof(struct _typeobject, _hcls), "");
static_assert(offsetof(pyston::BoxedClass, dependent_icgetattrs) == offsetof(struct _typeobject, _dep_getattrs), "");
static_assert(offsetof(pyston::BoxedClass, gc_visit) == offsetof(struct _typeobject, _gcvisit_func), "");
static_assert(sizeof(pyston::BoxedClass) == sizeof(struct _typeobject), "");
......
......@@ -44,6 +44,8 @@ class C(object):
return 0
c = C()
c.attr = "test"
c.__dict__.clear()
d1 = c.__dict__
d1.clear()
print hasattr(c, "attr")
print hasattr(c, "foo")
print c.__dict__ is d1
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