Commit 2358b49b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'tp_dictoffset'

parents 338af286 5b2747b1
...@@ -869,6 +869,10 @@ runpy_%: %.py ext_python ...@@ -869,6 +869,10 @@ runpy_%: %.py ext_python
PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7 python $< PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7 python $<
$(call make_search,runpy_%) $(call make_search,runpy_%)
check_%: %.py ext_python ext_pyston
$(MAKE) check_dbg ARGS="$(patsubst %.py,%,$(notdir $<)) -K"
$(call make_search,check_%)
dbgpy_%: %.py ext_pythondbg dbgpy_%: %.py ext_pythondbg
export PYTHON_VERSION=$$(python2.7-dbg -V 2>&1 | awk '{print $$2}'); PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7-pydebug $(GDB) --ex "dir $(DEPS_DIR)/python-src/python2.7-$$PYTHON_VERSION/debian" $(GDB_CMDS) --args python2.7-dbg $< export PYTHON_VERSION=$$(python2.7-dbg -V 2>&1 | awk '{print $$2}'); PYTHONPATH=test/test_extension/build/lib.linux-x86_64-2.7-pydebug $(GDB) --ex "dir $(DEPS_DIR)/python-src/python2.7-$$PYTHON_VERSION/debian" $(GDB_CMDS) --args python2.7-dbg $<
$(call make_search,dbgpy_%) $(call make_search,dbgpy_%)
......
...@@ -1762,9 +1762,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept { ...@@ -1762,9 +1762,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
cls->gc_visit = &conservativeGCHandler; cls->gc_visit = &conservativeGCHandler;
cls->is_user_defined = true; cls->is_user_defined = true;
// TODO not sure how we can handle extension types that manually
// specify a dict...
RELEASE_ASSERT(cls->tp_dictoffset == 0, "");
// this should get automatically initialized to 0 on this path: // this should get automatically initialized to 0 on this path:
assert(cls->attrs_offset == 0); assert(cls->attrs_offset == 0);
......
...@@ -1274,8 +1274,13 @@ public: ...@@ -1274,8 +1274,13 @@ public:
return c == cls; return c == cls;
} }
bool canStaticallyResolveGetattrs() {
return (cls->is_constant && !cls->instancesHaveHCAttrs() && !cls->instancesHaveDictAttrs()
&& cls->hasGenericGetattr());
}
CompilerType* getattrType(const std::string* attr, bool cls_only) override { CompilerType* getattrType(const std::string* attr, bool cls_only) override {
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) { if (canStaticallyResolveGetattrs()) {
Box* rtattr = cls->getattr(*attr); Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) if (rtattr == NULL)
return UNDEF; return UNDEF;
...@@ -1300,7 +1305,7 @@ public: ...@@ -1300,7 +1305,7 @@ public:
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var, CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool cls_only) override { const std::string* attr, bool cls_only) override {
// printf("%s.getattr %s\n", debugName().c_str(), attr->c_str()); // printf("%s.getattr %s\n", debugName().c_str(), attr->c_str());
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) { if (canStaticallyResolveGetattrs()) {
Box* rtattr = cls->getattr(*attr); Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) { if (rtattr == NULL) {
llvm::CallSite call = emitter.createCall2(info.unw_info, g.funcs.raiseAttributeErrorStr, llvm::CallSite call = emitter.createCall2(info.unw_info, g.funcs.raiseAttributeErrorStr,
...@@ -1346,7 +1351,7 @@ public: ...@@ -1346,7 +1351,7 @@ public:
const std::vector<CompilerVariable*>& args, const std::vector<CompilerVariable*>& args,
const std::vector<const std::string*>* keyword_names, const std::vector<const std::string*>* keyword_names,
bool raise_on_missing = true) { bool raise_on_missing = true) {
if (!cls->is_constant || cls->instancesHaveAttrs() || !cls->hasGenericGetattr()) if (!canStaticallyResolveGetattrs())
return NULL; return NULL;
Box* rtattr = cls->getattr(*attr); Box* rtattr = cls->getattr(*attr);
......
...@@ -381,6 +381,7 @@ public: ...@@ -381,6 +381,7 @@ public:
HCAttrs() : hcls(root_hcls), attr_list(nullptr) {} HCAttrs() : hcls(root_hcls), attr_list(nullptr) {}
}; };
class BoxedDict;
class BoxedString; class BoxedString;
class Box { class Box {
...@@ -396,7 +397,8 @@ public: ...@@ -396,7 +397,8 @@ public:
llvm::iterator_range<BoxIterator> pyElements(); llvm::iterator_range<BoxIterator> pyElements();
HCAttrs* getAttrsPtr(); HCAttrs* getHCAttrsPtr();
BoxedDict* getDict();
void setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args); void setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args);
void giveAttr(const std::string& attr, Box* val) { void giveAttr(const std::string& attr, Box* val) {
......
...@@ -91,12 +91,15 @@ extern "C" Box* dir(Box* obj) { ...@@ -91,12 +91,15 @@ extern "C" Box* dir(Box* obj) {
for (auto const& kv : obj->cls->attrs.hcls->attr_offsets) { for (auto const& kv : obj->cls->attrs.hcls->attr_offsets) {
listAppend(result, boxString(kv.first)); listAppend(result, boxString(kv.first));
} }
if (obj->cls->instancesHaveAttrs()) { if (obj->cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = obj->getAttrsPtr(); HCAttrs* attrs = obj->getHCAttrsPtr();
for (auto const& kv : attrs->hcls->attr_offsets) { for (auto const& kv : attrs->hcls->attr_offsets) {
listAppend(result, boxString(kv.first)); listAppend(result, boxString(kv.first));
} }
} }
if (obj->cls->instancesHaveDictAttrs()) {
Py_FatalError("unimplemented");
}
return result; return result;
} }
......
This diff is collapsed.
...@@ -349,8 +349,8 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) { ...@@ -349,8 +349,8 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) {
if (b->cls) { if (b->cls) {
v->visit(b->cls); v->visit(b->cls);
if (b->cls->instancesHaveAttrs()) { if (b->cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = b->getAttrsPtr(); HCAttrs* attrs = b->getHCAttrsPtr();
v->visit(attrs->hcls); v->visit(attrs->hcls);
int nattrs = attrs->hcls->attr_offsets.size(); int nattrs = attrs->hcls->attr_offsets.size();
...@@ -361,6 +361,10 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) { ...@@ -361,6 +361,10 @@ extern "C" void boxGCHandler(GCVisitor* v, Box* b) {
v->visitRange((void**)&attr_list->attrs[0], (void**)&attr_list->attrs[nattrs]); v->visitRange((void**)&attr_list->attrs[0], (void**)&attr_list->attrs[nattrs]);
} }
} }
if (b->cls->instancesHaveDictAttrs()) {
RELEASE_ASSERT(0, "Shouldn't all of these objects be conservatively scanned?");
}
} else { } else {
assert(type_cls == NULL || b == type_cls); assert(type_cls == NULL || b == type_cls);
} }
...@@ -776,7 +780,7 @@ private: ...@@ -776,7 +780,7 @@ private:
Box* b; Box* b;
public: public:
AttrWrapper(Box* b) : b(b) {} AttrWrapper(Box* b) : b(b) { assert(b->cls->instancesHaveHCAttrs()); }
DEFAULT_CLASS(attrwrapper_cls); DEFAULT_CLASS(attrwrapper_cls);
...@@ -829,7 +833,7 @@ public: ...@@ -829,7 +833,7 @@ public:
std::ostringstream os(""); std::ostringstream os("");
os << "attrwrapper({"; os << "attrwrapper({";
HCAttrs* attrs = self->b->getAttrsPtr(); HCAttrs* attrs = self->b->getHCAttrsPtr();
bool first = true; bool first = true;
for (const auto& p : attrs->hcls->attr_offsets) { for (const auto& p : attrs->hcls->attr_offsets) {
if (!first) if (!first)
...@@ -859,7 +863,7 @@ public: ...@@ -859,7 +863,7 @@ public:
BoxedList* rtn = new BoxedList(); BoxedList* rtn = new BoxedList();
HCAttrs* attrs = self->b->getAttrsPtr(); HCAttrs* attrs = self->b->getHCAttrsPtr();
for (const auto& p : attrs->hcls->attr_offsets) { for (const auto& p : attrs->hcls->attr_offsets) {
BoxedTuple* t = new BoxedTuple({ boxString(p.first), attrs->attr_list->attrs[p.second] }); BoxedTuple* t = new BoxedTuple({ boxString(p.first), attrs->attr_list->attrs[p.second] });
listAppend(rtn, t); listAppend(rtn, t);
...@@ -869,7 +873,7 @@ public: ...@@ -869,7 +873,7 @@ public:
}; };
Box* makeAttrWrapper(Box* b) { Box* makeAttrWrapper(Box* b) {
assert(b->cls->instancesHaveAttrs()); assert(b->cls->instancesHaveHCAttrs());
return new AttrWrapper(b); return new AttrWrapper(b);
} }
...@@ -908,8 +912,8 @@ Box* objectStr(Box* obj) { ...@@ -908,8 +912,8 @@ Box* objectStr(Box* obj) {
// Added as parameter because it should typically be available // Added as parameter because it should typically be available
inline void initUserAttrs(Box* obj, BoxedClass* cls) { inline void initUserAttrs(Box* obj, BoxedClass* cls) {
assert(obj->cls == cls); assert(obj->cls == cls);
if (cls->attrs_offset) { if (cls->instancesHaveHCAttrs()) {
HCAttrs* attrs = obj->getAttrsPtr(); HCAttrs* attrs = obj->getHCAttrsPtr();
attrs = new ((void*)attrs) HCAttrs(); attrs = new ((void*)attrs) HCAttrs();
} }
} }
......
...@@ -199,7 +199,8 @@ public: ...@@ -199,7 +199,8 @@ public:
// Analogous to tp_dictoffset // Analogous to tp_dictoffset
const int attrs_offset; const int attrs_offset;
bool instancesHaveAttrs() { return attrs_offset != 0; } bool instancesHaveHCAttrs() { return attrs_offset != 0; }
bool instancesHaveDictAttrs() { return tp_dictoffset != 0; }
// Whether this class object is constant or not, ie whether or not class-level // Whether this class object is constant or not, ie whether or not class-level
// attributes can be changed or added. // attributes can be changed or added.
......
#include <Python.h> #include <Python.h>
#include <stddef.h> /* For offsetof */
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD;
PyObject* dict;
int n; int n;
} slots_tester_object; } slots_tester_object;
...@@ -252,7 +255,7 @@ static PyTypeObject slots_tester_map= { ...@@ -252,7 +255,7 @@ static PyTypeObject slots_tester_map= {
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ offsetof(slots_tester_object, dict), /* tp_dictoffset */
0, /* tp_init */ 0, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
slots_tester_new, /* tp_new */ slots_tester_new, /* tp_new */
......
...@@ -88,3 +88,27 @@ try: ...@@ -88,3 +88,27 @@ try:
pass pass
except TypeError, e: except TypeError, e:
print e print e
try:
slots_test.SlotsTesterSeq(5).foo = 1
except AttributeError, e:
print e
try:
print slots_test.SlotsTesterSeq(5).__dict__
except AttributeError, e:
print e
c = C3(5)
c.foo = 1
print c.foo
print c.__dict__.items()
s = slots_test.SlotsTesterMap(6)
s.bar = 2
print s.bar
print hasattr(s, "bar"), hasattr(s, "foo")
try:
print s.__dict__
except AttributeError, e:
print e
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