Commit d4d92177 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Let the attributes live at various offsets in an object.

Similar to the location of the dict attribute in CPython,
the 'hc attrs list' in Pyston will end up being located at
different offsets, depending on the class that's being subclassed
from.

This commit removes the HCBox class, which assumes that it always lives
at the same offset and so can be statically described with a C++ class,
and instead uses a runtime lookup.

This should hopefully make things a fair bit closer to supporting inheritance.
parent e7a250a0
......@@ -117,6 +117,7 @@ COMMON_CXXFLAGS += -std=c++11
COMMON_CXXFLAGS += -Wextra -Wno-sign-compare
COMMON_CXXFLAGS += -Wno-unused-parameter # should use the "unused" attribute
COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS += -Wno-invalid-offsetof # allow the use of "offsetof", and we'll just have to make sure to only use it legally.
ifeq ($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS += -DNVALGRIND
......
......@@ -840,8 +840,8 @@ public:
virtual bool isFitBy(BoxedClass* c) { return c == cls; }
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) {
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) {
Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL)
return UNDEF;
......@@ -861,8 +861,8 @@ public:
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool cls_only) {
// printf("%s.getattr %s\n", debugName().c_str(), attr->c_str());
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) {
Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(*getNameOfClass(cls) + "\0"),
......@@ -927,8 +927,8 @@ public:
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) {
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (cls->is_constant && !cls->instancesHaveAttrs() && cls->hasGenericGetattr()) {
Box* rtattr = cls->getattr(*attr);
if (rtattr == NULL) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
getStringConstantPtr(*getNameOfClass(cls) + "\0"),
......
......@@ -37,9 +37,6 @@ using namespace llvm;
namespace pyston {
#define CLS_HASATTRS_OFFSET ((const char*)&(((BoxedClass*)0x01)->hasattrs) - (const char*)0x1)
#define FLAVOR_KINDID_OFFSET ((const char*)&(((ObjectFlavor*)0x01)->kind_id) - (const char*)0x1)
class ConstClassesPass : public FunctionPass {
private:
void* getGVAddr(GlobalVariable* gv) {
......@@ -84,7 +81,7 @@ private:
assert(success);
int64_t offset = ap_offset.getSExtValue();
if (offset == FLAVOR_KINDID_OFFSET) {
if (offset == offsetof(ObjectFlavor, kind_id)) {
ObjectFlavor* flavor = getFlavorFromGV(cast<GlobalVariable>(gepce->getOperand(0)));
replaceUsesWithConstant(li, flavor->kind_id);
return true;
......@@ -150,9 +147,13 @@ private:
errs() << "Found a load: " << *gep_load << '\n';
if (offset == CLS_HASATTRS_OFFSET) {
errs() << "Hasattrs; replacing with " << cls->hasattrs << "\n";
replaceUsesWithConstant(gep_load, cls->hasattrs);
if (offset == offsetof(BoxedClass, attrs_offset)) {
errs() << "attrs_offset; replacing with " << cls->attrs_offset << "\n";
replaceUsesWithConstant(gep_load, cls->attrs_offset);
changed = true;
} else if (offset == offsetof(BoxedClass, instance_size)) {
errs() << "instance_size; replacing with " << cls->instance_size << "\n";
replaceUsesWithConstant(gep_load, cls->instance_size);
changed = true;
}
}
......
......@@ -140,15 +140,15 @@ PatchpointSetupInfo* createSetattrPatchpoint(CompiledFunction* parent_cf, TypeRe
}
PatchpointSetupInfo* createCallsitePatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder, int num_args) {
return PatchpointSetupInfo::initialize(true, 3, 256 + 36 * num_args, parent_cf, Callsite, type_recorder);
return PatchpointSetupInfo::initialize(true, 3, 320 + 36 * num_args, parent_cf, Callsite, type_recorder);
}
PatchpointSetupInfo* createGetGlobalPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 1, 80, parent_cf, GetGlobal, type_recorder);
return PatchpointSetupInfo::initialize(true, 1, 128, parent_cf, GetGlobal, type_recorder);
}
PatchpointSetupInfo* createBinexpPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
return PatchpointSetupInfo::initialize(true, 4, 196, parent_cf, Binexp, type_recorder);
return PatchpointSetupInfo::initialize(true, 4, 256, parent_cf, Binexp, type_recorder);
}
PatchpointSetupInfo* createNonzeroPatchpoint(CompiledFunction* parent_cf, TypeRecorder* type_recorder) {
......
......@@ -302,67 +302,63 @@ private:
};
extern bool TRACK_ALLOCATIONS;
class Box : public GCObject {
public:
BoxedClass* cls;
llvm::iterator_range<BoxIterator> pyElements();
constexpr Box(const ObjectFlavor* flavor, BoxedClass* c) __attribute__((visibility("default")))
: GCObject(flavor), cls(c) {
// if (TRACK_ALLOCATIONS) {
// int id = Stats::getStatId("allocated_" + *getNameOfClass(c));
// Stats::log(id);
//}
}
};
class SetattrRewriteArgs;
class SetattrRewriteArgs2;
class GetattrRewriteArgs;
class GetattrRewriteArgs2;
// I expect that most things will end up being represented by HCBox's rather than boxes,
// but I'm not putting these into Box so that things that don't have any python-level instance
// attributes (ex: integers) don't need to allocate the extra space.
class HCBox : public Box {
struct HCAttrs {
public:
struct AttrList : GCObject {
Box* attrs[0];
};
HiddenClass* hcls;
// Python-level attributes:
AttrList* attr_list;
HCBox(const ObjectFlavor* flavor, BoxedClass* cls);
HCAttrs() : hcls(HiddenClass::getRoot()), attr_list(nullptr) {}
};
class Box : public GCObject {
public:
BoxedClass* cls;
llvm::iterator_range<BoxIterator> pyElements();
Box(const ObjectFlavor* flavor, BoxedClass* cls);
HCAttrs* getAttrs();
void setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args,
SetattrRewriteArgs2* rewrite_args2);
void giveAttr(const std::string& attr, Box* val);
Box* getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, GetattrRewriteArgs2* rewrite_args2);
Box* peekattr(const std::string& attr) {
int offset = hcls->getOffset(attr);
if (offset == -1)
return NULL;
return attr_list->attrs[offset];
void giveAttr(const std::string& attr, Box* val) {
assert(this->getattr(attr) == NULL);
this->setattr(attr, val, NULL, NULL);
}
Box* getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, GetattrRewriteArgs2* rewrite_args2);
Box* getattr(const std::string& attr) { return getattr(attr, NULL, NULL); }
};
class BoxedClass : public HCBox {
class BoxedClass : public Box {
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;
// whether or not instances of this class are subclasses of HCBox,
// ie they have python-level instance attributes:
const bool hasattrs;
// Offset of the HCAttrs object or 0 if there are no hcattrs.
// Analogous to tp_dictoffset
const int attrs_offset;
// Analogous to tp_basicsize
const int instance_size;
bool instancesHaveAttrs() { return attrs_offset != 0; }
// Whether this class object is constant or not, ie whether or not class-level
// attributes can be changed or added.
......@@ -377,7 +373,7 @@ public:
// will need to update this once we support tp_getattr-style overriding:
bool hasGenericGetattr() { return true; }
BoxedClass(bool hasattrs, bool is_user_defined);
BoxedClass(int attrs_offset, int instance_size, bool is_user_defined);
void freeze() {
assert(!is_constant);
is_constant = true;
......
......@@ -65,7 +65,7 @@ void setupBool() {
bool_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)boolNeg, NULL, 1, false)));
bool_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)boolNonzero, NULL, 1, false)));
bool_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)boolRepr, NULL, 1, false)));
bool_cls->setattr("__str__", bool_cls->peekattr("__repr__"), NULL, NULL);
bool_cls->setattr("__str__", bool_cls->getattr("__repr__"), NULL, NULL);
CLFunction* __new__ = boxRTFunction((void*)boolNew1, NULL, 1, false);
addRTFunction(__new__, (void*)boolNew2, NULL, 2, false);
......
......@@ -335,17 +335,22 @@ Box* exceptionNew1(BoxedClass* cls) {
return exceptionNew2(cls, boxStrConstant(""));
}
class BoxedException : public Box {
public:
HCAttrs attrs;
BoxedException(BoxedClass* cls) : Box(&exception_flavor, cls) {}
};
Box* exceptionNew2(BoxedClass* cls, Box* message) {
HCBox* r = new HCBox(&exception_flavor, cls);
assert(cls->instance_size == sizeof(BoxedException));
Box* r = new BoxedException(cls);
r->giveAttr("message", message);
return r;
}
Box* exceptionStr(Box* b) {
HCBox* hcb = static_cast<HCBox*>(b);
// TODO In CPython __str__ and __repr__ pull from an internalized message field, but for now do this:
Box* message = hcb->peekattr("message");
Box* message = b->getattr("message");
assert(message);
message = str(message);
assert(message->cls == str_cls);
......@@ -354,10 +359,8 @@ Box* exceptionStr(Box* b) {
}
Box* exceptionRepr(Box* b) {
HCBox* hcb = static_cast<HCBox*>(b);
// TODO In CPython __str__ and __repr__ pull from an internalized message field, but for now do this:
Box* message = hcb->peekattr("message");
Box* message = b->getattr("message");
assert(message);
message = repr(message);
assert(message->cls == str_cls);
......@@ -367,7 +370,7 @@ Box* exceptionRepr(Box* b) {
}
static BoxedClass* makeBuiltinException(const char* name) {
BoxedClass* cls = new BoxedClass(true, false);
BoxedClass* cls = new BoxedClass(offsetof(BoxedException, attrs), sizeof(BoxedException), false);
cls->giveAttr("__name__", boxStrConstant(name));
// TODO these should be on the base Exception class:
......@@ -385,7 +388,7 @@ void setupBuiltins() {
builtins_module->setattr("None", None, NULL, NULL);
notimplemented_cls = new BoxedClass(false, false);
notimplemented_cls = new BoxedClass(0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)notimplementedRepr, NULL, 1, false)));
......
......@@ -28,7 +28,7 @@ BoxedDict* sys_modules_dict;
BoxedDict* getSysModulesDict() {
// PyPy's behavior: fetch from sys.modules each time:
// Box *_sys_modules = sys_module->peekattr("modules");
// Box *_sys_modules = sys_module->getattr("modules");
// assert(_sys_modules);
// assert(_sys_modules->cls == dict_cls);
// return static_cast<BoxedDict*>(_sys_modules);
......@@ -39,7 +39,7 @@ BoxedDict* getSysModulesDict() {
BoxedList* getSysPath() {
// Unlike sys.modules, CPython handles sys.path by fetching it each time:
Box* _sys_path = sys_module->peekattr("path");
Box* _sys_path = sys_module->getattr("path");
assert(_sys_path);
if (_sys_path->cls != list_cls) {
......@@ -52,7 +52,7 @@ BoxedList* getSysPath() {
}
void addToSysArgv(const char* str) {
Box* sys_argv = sys_module->peekattr("argv");
Box* sys_argv = sys_module->getattr("argv");
assert(sys_argv);
assert(sys_argv->cls == list_cls);
listAppendInternal(sys_argv, boxStrConstant(str));
......
......@@ -120,12 +120,12 @@ BoxedModule* getTestModule() {
}
void setupCAPI() {
capifunc_cls = new BoxedClass(false, false);
capifunc_cls = new BoxedClass(0, sizeof(BoxedCApiFunction), false);
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, NULL, 1, false)));
capifunc_cls->setattr("__str__", capifunc_cls->peekattr("__repr__"), NULL, NULL);
capifunc_cls->setattr("__str__", capifunc_cls->getattr("__repr__"), NULL, NULL);
capifunc_cls->giveAttr("__call__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__call__, NULL, 1, true)));
......
......@@ -152,16 +152,16 @@ void setupDict() {
// dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, NULL, 1, false)));
// dict_cls->giveAttr("__init__", new BoxedFunction(boxRTFunction((void*)dictInit, NULL, 1, false)));
dict_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)dictRepr, NULL, 1, false)));
dict_cls->setattr("__str__", dict_cls->peekattr("__repr__"), NULL, NULL);
dict_cls->setattr("__str__", dict_cls->getattr("__repr__"), NULL, NULL);
dict_cls->giveAttr("items", new BoxedFunction(boxRTFunction((void*)dictItems, NULL, 1, false)));
dict_cls->setattr("iteritems", dict_cls->peekattr("items"), NULL, NULL);
dict_cls->setattr("iteritems", dict_cls->getattr("items"), NULL, NULL);
dict_cls->giveAttr("values", new BoxedFunction(boxRTFunction((void*)dictValues, NULL, 1, false)));
dict_cls->setattr("itervalues", dict_cls->peekattr("values"), NULL, NULL);
dict_cls->setattr("itervalues", dict_cls->getattr("values"), NULL, NULL);
dict_cls->giveAttr("keys", new BoxedFunction(boxRTFunction((void*)dictKeys, NULL, 1, false)));
dict_cls->setattr("iterkeys", dict_cls->peekattr("keys"), NULL, NULL);
dict_cls->setattr("iterkeys", dict_cls->getattr("keys"), NULL, NULL);
CLFunction* pop = boxRTFunction((void*)dictPop2, UNKNOWN, 2, false);
addRTFunction(pop, (void*)dictPop3, UNKNOWN, 3, false);
......
......@@ -182,7 +182,7 @@ void setupFile() {
file_cls->giveAttr("close", new BoxedFunction(boxRTFunction((void*)fileClose, NULL, 1, false)));
file_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)fileRepr, NULL, 1, false)));
file_cls->setattr("__str__", file_cls->peekattr("__repr__"), NULL, NULL);
file_cls->setattr("__str__", file_cls->getattr("__repr__"), NULL, NULL);
file_cls->giveAttr("__enter__", new BoxedFunction(boxRTFunction((void*)fileEnter, NULL, 1, false)));
file_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)fileExit, NULL, 4, false)));
......
......@@ -565,7 +565,7 @@ void setupFloat() {
float_cls->giveAttr("__name__", boxStrConstant("float"));
_addFunc("__add__", BOXED_FLOAT, (void*)floatAddFloat, (void*)floatAddInt, (void*)floatAdd);
float_cls->setattr("__radd__", float_cls->peekattr("__add__"), NULL, NULL);
float_cls->setattr("__radd__", float_cls->getattr("__add__"), NULL, NULL);
_addFunc("__div__", BOXED_FLOAT, (void*)floatDivFloat, (void*)floatDivInt, (void*)floatDiv);
_addFunc("__rdiv__", BOXED_FLOAT, (void*)floatRDivFloat, (void*)floatRDivInt, (void*)floatRDiv);
......@@ -581,7 +581,7 @@ void setupFloat() {
_addFunc("__mod__", BOXED_FLOAT, (void*)floatModFloat, (void*)floatModInt, (void*)floatMod);
_addFunc("__rmod__", BOXED_FLOAT, (void*)floatRModFloat, (void*)floatRModInt, (void*)floatRMod);
_addFunc("__mul__", BOXED_FLOAT, (void*)floatMulFloat, (void*)floatMulInt, (void*)floatMul);
float_cls->setattr("__rmul__", float_cls->peekattr("__mul__"), NULL, NULL);
float_cls->setattr("__rmul__", float_cls->getattr("__mul__"), NULL, NULL);
_addFunc("__pow__", BOXED_FLOAT, (void*)floatPowFloat, (void*)floatPowInt, (void*)floatPow);
_addFunc("__sub__", BOXED_FLOAT, (void*)floatSubFloat, (void*)floatSubInt, (void*)floatSub);
......
......@@ -120,9 +120,9 @@ Box* xrangeIter(Box* self) {
}
void setupXrange() {
xrange_cls = new BoxedClass(false, false);
xrange_cls = new BoxedClass(0, sizeof(BoxedXrange), false);
xrange_cls->giveAttr("__name__", boxStrConstant("xrange"));
xrange_iterator_cls = new BoxedClass(false, false);
xrange_iterator_cls = new BoxedClass(0, sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
CLFunction* xrange_clf = boxRTFunction((void*)xrange1, NULL, 2, false);
......
......@@ -533,7 +533,7 @@ void setupInt() {
int_cls->giveAttr("__neg__", new BoxedFunction(boxRTFunction((void*)intNeg, BOXED_INT, 1, false)));
int_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)intNonzero, BOXED_BOOL, 1, false)));
int_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)intRepr, STR, 1, false)));
int_cls->setattr("__str__", int_cls->peekattr("__repr__"), NULL, NULL);
int_cls->setattr("__str__", int_cls->getattr("__repr__"), NULL, NULL);
int_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)intHash, BOXED_INT, 1, false)));
int_cls->giveAttr("__divmod__", new BoxedFunction(boxRTFunction((void*)intDivmod, BOXED_TUPLE, 2, false)));
......
......@@ -433,7 +433,7 @@ extern "C" Box* listNew2(Box* cls, Box* container) {
}
void setupList() {
list_iterator_cls = new BoxedClass(false, false);
list_iterator_cls = new BoxedClass(0, sizeof(BoxedList), false);
list_cls->giveAttr("__name__", boxStrConstant("list"));
......@@ -449,7 +449,7 @@ void setupList() {
new BoxedFunction(boxRTFunction((void*)listIter, typeFromClass(list_iterator_cls), 1, false)));
list_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)listRepr, STR, 1, false)));
list_cls->setattr("__str__", list_cls->peekattr("__repr__"), NULL, NULL);
list_cls->setattr("__str__", list_cls->getattr("__repr__"), NULL, NULL);
list_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)listNonzero, BOXED_BOOL, 1, false)));
CLFunction* pop = boxRTFunction((void*)listPop1, NULL, 1, false);
......
......@@ -40,12 +40,11 @@
#include "runtime/types.h"
#include "runtime/util.h"
#define BOX_NREFS_OFFSET ((char*)&(((HCBox*)0x01)->nrefs) - (char*)0x1)
#define BOX_CLS_OFFSET ((char*)&(((HCBox*)0x01)->cls) - (char*)0x1)
#define BOX_HCLS_OFFSET ((char*)&(((HCBox*)0x01)->hcls) - (char*)0x1)
#define BOX_ATTRS_OFFSET ((char*)&(((HCBox*)0x01)->attr_list) - (char*)0x1)
#define ATTRLIST_ATTRS_OFFSET ((char*)&(((HCBox::AttrList*)0x01)->attrs) - (char*)0x1)
#define ATTRLIST_KIND_OFFSET ((char*)&(((HCBox::AttrList*)0x01)->gc_header.kind_id) - (char*)0x1)
#define BOX_CLS_OFFSET ((char*)&(((Box*)0x01)->cls) - (char*)0x1)
#define HCATTRS_HCLS_OFFSET ((char*)&(((HCAttrs*)0x01)->hcls) - (char*)0x1)
#define HCATTRS_ATTRS_OFFSET ((char*)&(((HCAttrs*)0x01)->attr_list) - (char*)0x1)
#define ATTRLIST_ATTRS_OFFSET ((char*)&(((HCAttrs::AttrList*)0x01)->attrs) - (char*)0x1)
#define ATTRLIST_KIND_OFFSET ((char*)&(((HCAttrs::AttrList*)0x01)->gc_header.kind_id) - (char*)0x1)
#define INSTANCEMETHOD_FUNC_OFFSET ((char*)&(((BoxedInstanceMethod*)0x01)->func) - (char*)0x1)
#define INSTANCEMETHOD_OBJ_OFFSET ((char*)&(((BoxedInstanceMethod*)0x01)->obj) - (char*)0x1)
#define BOOL_B_OFFSET ((char*)&(((BoxedBool*)0x01)->b) - (char*)0x1)
......@@ -273,12 +272,17 @@ extern "C" void checkUnpackingLength(i64 expected, i64 given) {
}
}
BoxedClass::BoxedClass(bool hasattrs, bool is_user_defined)
: HCBox(&type_flavor, type_cls), hasattrs(hasattrs), is_constant(false), is_user_defined(is_user_defined) {
BoxedClass::BoxedClass(int attrs_offset, int instance_size, bool is_user_defined)
: Box(&type_flavor, type_cls), attrs_offset(attrs_offset), instance_size(instance_size), is_constant(false),
is_user_defined(is_user_defined) {
if (attrs_offset) {
assert(instance_size >= attrs_offset + sizeof(HCAttrs));
assert(attrs_offset % sizeof(void*) == 0);
}
}
extern "C" const std::string* getNameOfClass(BoxedClass* cls) {
Box* b = cls->peekattr("__name__");
Box* b = cls->getattr("__name__");
assert(b);
ASSERT(b->cls == str_cls, "%p", b->cls);
BoxedString* sb = static_cast<BoxedString*>(b);
......@@ -308,8 +312,11 @@ HiddenClass* HiddenClass::getRoot() {
return root;
}
HCBox::HCBox(const ObjectFlavor* flavor, BoxedClass* cls)
: Box(flavor, cls), hcls(HiddenClass::getRoot()), attr_list(NULL) {
Box::Box(const ObjectFlavor* flavor, BoxedClass* cls) : GCObject(flavor), cls(cls) {
// if (TRACK_ALLOCATIONS) {
// int id = Stats::getStatId("allocated_" + *getNameOfClass(c));
// Stats::log(id);
//}
// the only way cls should be NULL is if we're creating the type_cls
// object itself:
......@@ -317,24 +324,51 @@ HCBox::HCBox(const ObjectFlavor* flavor, BoxedClass* cls)
assert(type_cls == NULL);
} else {
assert(flavor->isUserDefined() == isUserDefined(cls));
assert(cls->hasattrs);
}
}
Box* HCBox::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, GetattrRewriteArgs2* rewrite_args2) {
HCAttrs* Box::getAttrs() {
assert(cls->instancesHaveAttrs());
char* p = reinterpret_cast<char*>(this);
p += cls->attrs_offset;
return reinterpret_cast<HCAttrs*>(p);
}
Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, GetattrRewriteArgs2* rewrite_args2) {
// Have to guard on the memory layout of this object.
// Right now, guard on the specific Python-class, which in turn
// specifies the C structure.
// In the future, we could create another field (the flavor?)
// that also specifies the structure and can include multiple
// classes.
// Only matters if we end up getting multiple classes with the same
// structure (ex user class) and the same hidden classes, because
// otherwise the guard will fail anyway.;
if (rewrite_args) {
rewrite_args->out_success = true;
rewrite_args->obj.addAttrGuard(BOX_CLS_OFFSET, (intptr_t)cls);
}
if (rewrite_args2) {
rewrite_args2->out_success = true;
rewrite_args2->obj.addAttrGuard(BOX_CLS_OFFSET, (intptr_t)cls);
}
if (!cls->instancesHaveAttrs())
return NULL;
HCAttrs* attrs = getAttrs();
HiddenClass* hcls = attrs->hcls;
if (rewrite_args) {
if (!rewrite_args->obj_hcls_guarded)
rewrite_args->obj.addAttrGuard(BOX_HCLS_OFFSET, (intptr_t) this->hcls);
rewrite_args->obj.addAttrGuard(cls->attrs_offset + HCATTRS_HCLS_OFFSET, (intptr_t)hcls);
}
if (rewrite_args2) {
rewrite_args2->out_success = true;
if (!rewrite_args2->obj_hcls_guarded)
rewrite_args2->obj.addAttrGuard(BOX_HCLS_OFFSET, (intptr_t) this->hcls);
rewrite_args2->obj.addAttrGuard(cls->attrs_offset + HCATTRS_HCLS_OFFSET, (intptr_t)hcls);
}
int offset = hcls->getOffset(attr);
......@@ -349,7 +383,7 @@ Box* HCBox::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, G
// temp_reg = -3;
int temp_reg = rewrite_args->preferred_dest_reg;
RewriterVar attrs = rewrite_args->obj.getAttr(BOX_ATTRS_OFFSET, temp_reg);
RewriterVar attrs = rewrite_args->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, temp_reg);
rewrite_args->out_rtn
= attrs.getAttr(offset * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, rewrite_args->preferred_dest_reg);
......@@ -360,22 +394,35 @@ Box* HCBox::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args, G
if (!rewrite_args2->more_guards_after)
rewrite_args2->rewriter->setDoneGuarding();
RewriterVarUsage2 attrs = rewrite_args2->obj.getAttr(BOX_ATTRS_OFFSET, RewriterVarUsage2::Kill);
RewriterVarUsage2 attrs
= rewrite_args2->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, RewriterVarUsage2::Kill);
rewrite_args2->out_rtn = attrs.getAttr(offset * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, RewriterVarUsage2::Kill,
rewrite_args2->destination);
}
Box* rtn = attr_list->attrs[offset];
Box* rtn = attrs->attr_list->attrs[offset];
return rtn;
}
void HCBox::giveAttr(const std::string& attr, Box* val) {
assert(this->peekattr(attr) == NULL);
this->setattr(attr, val, NULL, NULL);
}
void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args,
SetattrRewriteArgs2* rewrite_args2) {
assert(cls->instancesHaveAttrs());
// Have to guard on the memory layout of this object.
// Right now, guard on the specific Python-class, which in turn
// specifies the C structure.
// In the future, we could create another field (the flavor?)
// that also specifies the structure and can include multiple
// classes.
// Only matters if we end up getting multiple classes with the same
// structure (ex user class) and the same hidden classes, because
// otherwise the guard will fail anyway.;
if (rewrite_args)
rewrite_args->obj.addAttrGuard(BOX_CLS_OFFSET, (intptr_t)cls);
if (rewrite_args2)
rewrite_args2->obj.addAttrGuard(BOX_CLS_OFFSET, (intptr_t)cls);
void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite_args,
SetattrRewriteArgs2* rewrite_args2) {
static const std::string none_str("None");
static const std::string getattr_str("__getattr__");
static const std::string getattribute_str("__getattribute__");
......@@ -393,18 +440,19 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
self->dependent_icgetattrs.invalidateAll();
}
HiddenClass* hcls = this->hcls;
HCAttrs* attrs = getAttrs();
HiddenClass* hcls = attrs->hcls;
int numattrs = hcls->attr_offsets.size();
int offset = hcls->getOffset(attr);
if (rewrite_args) {
rewrite_args->obj.addAttrGuard(BOX_HCLS_OFFSET, (intptr_t)hcls);
rewrite_args->obj.addAttrGuard(cls->attrs_offset + HCATTRS_HCLS_OFFSET, (intptr_t)hcls);
rewrite_args->rewriter->addDecision(offset == -1 ? 1 : 0);
}
if (rewrite_args2) {
rewrite_args2->obj.addAttrGuard(BOX_HCLS_OFFSET, (intptr_t)hcls);
rewrite_args2->obj.addAttrGuard(cls->attrs_offset + HCATTRS_HCLS_OFFSET, (intptr_t)hcls);
if (!rewrite_args2->more_guards_after)
rewrite_args2->rewriter->setDoneGuarding();
......@@ -413,11 +461,11 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
if (offset >= 0) {
assert(offset < numattrs);
Box* prev = this->attr_list->attrs[offset];
this->attr_list->attrs[offset] = val;
Box* prev = attrs->attr_list->attrs[offset];
attrs->attr_list->attrs[offset] = val;
if (rewrite_args) {
RewriterVar r_hattrs = rewrite_args->obj.getAttr(BOX_ATTRS_OFFSET, 1);
RewriterVar r_hattrs = rewrite_args->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, 1);
r_hattrs.setAttr(offset * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, rewrite_args->attrval);
rewrite_args->out_success = true;
......@@ -425,8 +473,8 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
if (rewrite_args2) {
RewriterVarUsage2 r_hattrs
= rewrite_args2->obj.getAttr(BOX_ATTRS_OFFSET, RewriterVarUsage2::Kill, Location::any());
RewriterVarUsage2 r_hattrs = rewrite_args2->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET,
RewriterVarUsage2::Kill, Location::any());
r_hattrs.setAttr(offset * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, std::move(rewrite_args2->attrval));
r_hattrs.setDoneUsing();
......@@ -457,10 +505,10 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
RewriterVar r_new_array;
RewriterVarUsage2 r_new_array2(RewriterVarUsage2::empty());
int new_size = sizeof(HCBox::AttrList) + sizeof(Box*) * (numattrs + 1);
int new_size = sizeof(HCAttrs::AttrList) + sizeof(Box*) * (numattrs + 1);
if (numattrs == 0) {
this->attr_list = (HCBox::AttrList*)rt_alloc(new_size);
this->attr_list->gc_header.kind_id = untracked_kind.kind_id;
attrs->attr_list = (HCAttrs::AttrList*)rt_alloc(new_size);
attrs->attr_list->gc_header.kind_id = untracked_kind.kind_id;
if (rewrite_args) {
rewrite_args->rewriter->loadConst(0, new_size);
r_new_array = rewrite_args->rewriter->call((void*)rt_alloc);
......@@ -474,15 +522,15 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
r_new_array2.setAttr(ATTRLIST_KIND_OFFSET, std::move(r_flavor));
}
} else {
this->attr_list = (HCBox::AttrList*)rt_realloc(this->attr_list, new_size);
attrs->attr_list = (HCAttrs::AttrList*)rt_realloc(attrs->attr_list, new_size);
if (rewrite_args) {
rewrite_args->obj.getAttr(BOX_ATTRS_OFFSET, 0);
rewrite_args->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, 0);
rewrite_args->rewriter->loadConst(1, new_size);
r_new_array = rewrite_args->rewriter->call((void*)rt_realloc);
}
if (rewrite_args2) {
RewriterVarUsage2 r_oldarray
= rewrite_args2->obj.getAttr(BOX_ATTRS_OFFSET, RewriterVarUsage2::NoKill, Location::forArg(0));
RewriterVarUsage2 r_oldarray = rewrite_args2->obj.getAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET,
RewriterVarUsage2::NoKill, Location::forArg(0));
RewriterVarUsage2 r_newsize = rewrite_args2->rewriter->loadConst(new_size, Location::forArg(1));
r_new_array2
= rewrite_args2->rewriter->call(false, (void*)rt_realloc, std::move(r_oldarray), std::move(r_newsize));
......@@ -491,28 +539,28 @@ void HCBox::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewri
// Don't set the new hcls until after we do the allocation for the new attr_list;
// that allocation can cause a collection, and we want the collector to always
// see a consistent state between the hcls and the attr_list
this->hcls = new_hcls;
attrs->hcls = new_hcls;
if (rewrite_args) {
RewriterVar attrval = rewrite_args->rewriter->pop(0);
RewriterVar obj = rewrite_args->rewriter->pop(2);
obj.setAttr(BOX_ATTRS_OFFSET, r_new_array);
obj.setAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, r_new_array);
r_new_array.setAttr(numattrs * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, attrval);
RewriterVar hcls = rewrite_args->rewriter->loadConst(1, (intptr_t)new_hcls);
obj.setAttr(BOX_HCLS_OFFSET, hcls);
obj.setAttr(cls->attrs_offset + HCATTRS_HCLS_OFFSET, hcls);
rewrite_args->out_success = true;
}
if (rewrite_args2) {
r_new_array2.setAttr(numattrs * sizeof(Box*) + ATTRLIST_ATTRS_OFFSET, std::move(rewrite_args2->attrval));
rewrite_args2->obj.setAttr(BOX_ATTRS_OFFSET, std::move(r_new_array2));
rewrite_args2->obj.setAttr(cls->attrs_offset + HCATTRS_ATTRS_OFFSET, std::move(r_new_array2));
RewriterVarUsage2 r_hcls = rewrite_args2->rewriter->loadConst((intptr_t)new_hcls);
rewrite_args2->obj.setAttr(BOX_HCLS_OFFSET, std::move(r_hcls));
rewrite_args2->obj.setAttr(cls->attrs_offset + HCATTRS_HCLS_OFFSET, std::move(r_hcls));
rewrite_args2->obj.setDoneUsing();
rewrite_args2->out_success = true;
}
this->attr_list->attrs[numattrs] = val;
attrs->attr_list->attrs[numattrs] = val;
}
static Box* _handleClsAttr(Box* obj, Box* attr) {
......@@ -700,14 +748,12 @@ Box* getattr_internal(Box* obj, const std::string& attr, bool check_cls, bool al
rewrite_args->out_success = false;
if (rewrite_args2)
rewrite_args2->out_success = false;
} else if (obj->cls->hasattrs) {
HCBox* hobj = static_cast<HCBox*>(obj);
} else {
Box* val = NULL;
if (rewrite_args) {
GetattrRewriteArgs hrewrite_args(rewrite_args->rewriter, rewrite_args->obj);
hrewrite_args.preferred_dest_reg = rewrite_args->preferred_dest_reg;
val = hobj->getattr(attr, &hrewrite_args, NULL);
val = obj->getattr(attr, &hrewrite_args, NULL);
if (hrewrite_args.out_success) {
if (val)
......@@ -718,7 +764,7 @@ Box* getattr_internal(Box* obj, const std::string& attr, bool check_cls, bool al
} else if (rewrite_args2) {
GetattrRewriteArgs2 hrewrite_args(rewrite_args2->rewriter, std::move(rewrite_args2->obj),
rewrite_args2->destination, rewrite_args2->more_guards_after);
val = hobj->getattr(attr, NULL, &hrewrite_args);
val = obj->getattr(attr, NULL, &hrewrite_args);
if (hrewrite_args.out_success) {
if (val)
......@@ -729,7 +775,7 @@ Box* getattr_internal(Box* obj, const std::string& attr, bool check_cls, bool al
rewrite_args2 = NULL;
}
} else {
val = hobj->getattr(attr, NULL, NULL);
val = obj->getattr(attr, NULL, NULL);
}
if (val) {
......@@ -851,7 +897,7 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
static StatCounter slowpath_setattr("slowpath_setattr");
slowpath_setattr.log();
if (!obj->cls->hasattrs) {
if (!obj->cls->instancesHaveAttrs()) {
raiseAttributeError(obj, attr);
}
......@@ -863,37 +909,22 @@ extern "C" void setattr(Box* obj, const char* attr, Box* attr_val) {
}
}
HCBox* hobj = static_cast<HCBox*>(obj);
#if 0
std::unique_ptr<Rewriter> rewriter(Rewriter::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, 1, "setattr"));
if (rewriter.get()) {
//rewriter->trap();
SetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getArg(2));
hobj->setattr(attr, attr_val, &rewrite_args);
if (rewrite_args.out_success) {
rewriter->commit();
}
#else
std::unique_ptr<Rewriter2> rewriter(
Rewriter2::createRewriter(__builtin_extract_return_addr(__builtin_return_address(0)), 3, "setattr"));
if (rewriter.get()) {
// rewriter->trap();
SetattrRewriteArgs2 rewrite_args(rewriter.get(), rewriter->getArg(0), rewriter->getArg(2), false);
hobj->setattr(attr, attr_val, NULL, &rewrite_args);
obj->setattr(attr, attr_val, NULL, &rewrite_args);
if (rewrite_args.out_success) {
rewriter->commit();
} else {
rewrite_args.obj.setDoneUsing();
rewrite_args.attrval.setDoneUsing();
}
#endif
}
else {
hobj->setattr(attr, attr_val, NULL, NULL);
}
} else {
obj->setattr(attr, attr_val, NULL, NULL);
}
}
bool isUserDefined(BoxedClass* cls) {
......@@ -2170,12 +2201,6 @@ extern "C" void delitem(Box* target, Box* slice) {
}
}
// A wrapper around the HCBox constructor
// TODO is there a way to avoid the indirection?
static Box* makeHCBox(ObjectFlavor* flavor, BoxedClass* cls) {
return new HCBox(flavor, cls);
}
// For use on __init__ return values
static void assertInitNone(Box* obj) {
if (obj != None) {
......@@ -2183,6 +2208,11 @@ static void assertInitNone(Box* obj) {
}
}
// Wrapping the ctor to get a defined ABI for calling from an IC:
static Box* makeUserObject(BoxedClass* cls) {
return new BoxedUserObject(cls);
}
Box* typeCallInternal(CallRewriteArgs* rewrite_args, int64_t nargs, Box* arg1, Box* arg2, Box* arg3, Box** args) {
static StatCounter slowpath_typecall("slowpath_typecall");
slowpath_typecall.log();
......@@ -2305,7 +2335,7 @@ Box* typeCallInternal(CallRewriteArgs* rewrite_args, int64_t nargs, Box* arg1, B
}
} else {
if (isUserDefined(ccls)) {
made = new HCBox(&user_flavor, ccls);
made = new BoxedUserObject(ccls);
if (rewrite_args) {
if (init_attr)
......@@ -2319,9 +2349,8 @@ Box* typeCallInternal(CallRewriteArgs* rewrite_args, int64_t nargs, Box* arg1, B
if (nargs >= 4)
rewrite_args->args.push();
r_ccls.move(1);
rewrite_args->rewriter->loadConst(0, (intptr_t) & user_flavor);
r_made = rewrite_args->rewriter->call((void*)&makeHCBox);
r_ccls.move(0);
r_made = rewrite_args->rewriter->call((void*)&makeUserObject);
if (nargs >= 4)
rewrite_args->args = rewrite_args->rewriter->pop(3);
......@@ -2335,8 +2364,6 @@ Box* typeCallInternal(CallRewriteArgs* rewrite_args, int64_t nargs, Box* arg1, B
r_init = rewrite_args->rewriter->pop(-2);
}
} else {
// Not sure what type of object to make here; maybe an HCBox? would be disastrous if it ever
// made the wrong one though, so just err for now:
fprintf(stderr, "no __new__ defined for %s!\n", getNameOfClass(ccls)->c_str());
abort();
}
......
......@@ -176,7 +176,7 @@ using namespace pyston::set;
void setupSet() {
set_cls->giveAttr("__name__", boxStrConstant("set"));
set_iterator_cls = new BoxedClass(false, false);
set_iterator_cls = new BoxedClass(0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1, false)));
......
......@@ -138,9 +138,8 @@ void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
std::string formatException(Box* b) {
const std::string* name = getTypeName(b);
HCBox* hcb = static_cast<HCBox*>(b);
Box* attr = hcb->peekattr("message");
Box* attr = b->getattr("message");
if (attr == nullptr)
return *name;
......
......@@ -524,7 +524,7 @@ Box* strCount2(BoxedString* self, Box* elt) {
}
void setupStr() {
str_iterator_cls = new BoxedClass(false, false);
str_iterator_cls = new BoxedClass(0, sizeof(BoxedString), false);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, NULL, 1, false)));
......@@ -558,7 +558,7 @@ void setupStr() {
CLFunction* strSplit = boxRTFunction((void*)strSplit1, LIST, 1, false);
addRTFunction(strSplit, (void*)strSplit2, LIST, 2, false);
str_cls->giveAttr("split", new BoxedFunction(strSplit));
str_cls->giveAttr("rsplit", str_cls->peekattr("split"));
str_cls->giveAttr("rsplit", str_cls->getattr("split"));
CLFunction* count = boxRTFunction((void*)strCount2Unboxed, INT, 2, false);
addRTFunction(count, (void*)strCount2, BOXED_INT, 2, false);
......
......@@ -203,7 +203,7 @@ void setupTuple() {
tuple_cls->giveAttr("__hash__", new BoxedFunction(boxRTFunction((void*)tupleHash, BOXED_INT, 1, false)));
tuple_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)tupleLen, NULL, 1, false)));
tuple_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)tupleRepr, NULL, 1, false)));
tuple_cls->setattr("__str__", tuple_cls->peekattr("__repr__"), NULL, NULL);
tuple_cls->setattr("__str__", tuple_cls->getattr("__repr__"), NULL, NULL);
tuple_cls->freeze();
}
......
......@@ -15,6 +15,7 @@
#include "runtime/types.h"
#include <cassert>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
......@@ -63,7 +64,7 @@ llvm::iterator_range<BoxIterator> Box::pyElements() {
raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(this)->c_str());
}
extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : HCBox(&function_flavor, function_cls), f(f) {
extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : Box(&function_flavor, function_cls), f(f) {
if (f->source) {
assert(f->source->ast);
// this->giveAttr("__name__", boxString(&f->source->ast->name));
......@@ -74,13 +75,13 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction* f) : HCBox(&function_flavor,
}
}
BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : HCBox(&module_flavor, module_cls), fn(fn) {
BoxedModule::BoxedModule(const std::string& name, const std::string& fn) : Box(&module_flavor, module_cls), fn(fn) {
this->giveAttr("__name__", boxString(name));
this->giveAttr("__file__", boxString(fn));
}
std::string BoxedModule::name() {
Box* name = this->peekattr("__name__");
Box* name = this->getattr("__name__");
if (!name || name->cls != str_cls) {
return "?";
} else {
......@@ -102,27 +103,26 @@ extern "C" void boxGCHandler(GCVisitor* v, void* p) {
if (b->cls) {
v->visit(b->cls);
if (b->cls->instancesHaveAttrs()) {
HCAttrs* attrs = b->getAttrs();
v->visit(attrs->hcls);
int nattrs = attrs->hcls->attr_offsets.size();
if (nattrs) {
HCAttrs::AttrList* attr_list = attrs->attr_list;
assert(attr_list);
v->visit(attr_list);
v->visitRange((void**)&attr_list->attrs[0], (void**)&attr_list->attrs[nattrs]);
}
}
} else {
assert(type_cls == NULL || p == type_cls);
}
}
extern "C" void hcBoxGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
HCBox* b = (HCBox*)p;
v->visit(b->hcls);
int nattrs = b->hcls->attr_offsets.size();
if (nattrs) {
HCBox::AttrList* attr_list = b->attr_list;
assert(attr_list);
v->visit(attr_list);
v->visitRange((void**)&attr_list->attrs[0], (void**)&attr_list->attrs[nattrs]);
}
}
extern "C" void typeGCHandler(GCVisitor* v, void* p) {
hcBoxGCHandler(v, p);
boxGCHandler(v, p);
BoxedClass* b = (BoxedClass*)p;
}
......@@ -213,15 +213,15 @@ const ObjectFlavor bool_flavor(&boxGCHandler, NULL);
const ObjectFlavor int_flavor(&boxGCHandler, NULL);
const ObjectFlavor float_flavor(&boxGCHandler, NULL);
const ObjectFlavor str_flavor(&boxGCHandler, NULL);
const ObjectFlavor function_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor function_flavor(&boxGCHandler, NULL);
const ObjectFlavor instancemethod_flavor(&instancemethodGCHandler, NULL);
const ObjectFlavor list_flavor(&listGCHandler, NULL);
const ObjectFlavor slice_flavor(&sliceGCHandler, NULL);
const ObjectFlavor module_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor module_flavor(&boxGCHandler, NULL);
const ObjectFlavor dict_flavor(&dictGCHandler, NULL);
const ObjectFlavor tuple_flavor(&tupleGCHandler, NULL);
const ObjectFlavor file_flavor(&boxGCHandler, NULL);
const ObjectFlavor user_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor user_flavor(&boxGCHandler, NULL);
const ObjectFlavor member_flavor(&boxGCHandler, NULL);
const AllocationKind untracked_kind(NULL, NULL);
......@@ -230,7 +230,7 @@ const AllocationKind conservative_kind(&conservativeGCHandler, NULL);
}
extern "C" Box* createUserClass(std::string* name, BoxedModule* parent_module) {
BoxedClass* rtn = new BoxedClass(true, true);
BoxedClass* rtn = new BoxedClass(offsetof(BoxedUserObject, attrs), sizeof(BoxedUserObject), true);
rtn->giveAttr("__name__", boxString(*name));
Box* modname = parent_module->getattr("__name__", NULL, NULL);
......@@ -329,14 +329,14 @@ Box* typeRepr(BoxedClass* self) {
std::ostringstream os;
os << "<class '";
Box* m = self->peekattr("__module__");
Box* m = self->getattr("__module__");
RELEASE_ASSERT(m, "");
if (m->cls == str_cls) {
BoxedString* sm = static_cast<BoxedString*>(m);
os << sm->s << '.';
}
Box* n = self->peekattr("__name__");
Box* n = self->getattr("__name__");
RELEASE_ASSERT(n, "");
RELEASE_ASSERT(n->cls == str_cls, "should have prevented you from setting __name__ to non-string");
BoxedString* sn = static_cast<BoxedString*>(n);
......@@ -375,31 +375,31 @@ bool TRACK_ALLOCATIONS = false;
void setupRuntime() {
HiddenClass::getRoot();
type_cls = new BoxedClass(true, false);
type_cls = new BoxedClass(offsetof(BoxedClass, attrs), sizeof(BoxedClass), false);
type_cls->cls = type_cls;
none_cls = new BoxedClass(false, false);
none_cls = new BoxedClass(0, sizeof(Box), false);
None = new Box(&none_flavor, none_cls);
gc::registerStaticRootObj(None);
module_cls = new BoxedClass(true, false);
module_cls = new BoxedClass(offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls = new BoxedClass(false, false);
int_cls = new BoxedClass(false, false);
float_cls = new BoxedClass(false, false);
str_cls = new BoxedClass(false, false);
function_cls = new BoxedClass(true, false);
instancemethod_cls = new BoxedClass(false, false);
list_cls = new BoxedClass(false, false);
slice_cls = new BoxedClass(false, false);
dict_cls = new BoxedClass(false, false);
tuple_cls = new BoxedClass(false, false);
file_cls = new BoxedClass(false, false);
set_cls = new BoxedClass(false, false);
member_cls = new BoxedClass(false, false);
bool_cls = new BoxedClass(0, sizeof(BoxedBool), false);
int_cls = new BoxedClass(0, sizeof(BoxedInt), false);
float_cls = new BoxedClass(0, sizeof(BoxedFloat), false);
str_cls = new BoxedClass(0, sizeof(BoxedString), false);
function_cls = new BoxedClass(offsetof(BoxedFunction, attrs), sizeof(BoxedFunction), false);
instancemethod_cls = new BoxedClass(0, sizeof(BoxedInstanceMethod), false);
list_cls = new BoxedClass(0, sizeof(BoxedList), false);
slice_cls = new BoxedClass(0, sizeof(BoxedSlice), false);
dict_cls = new BoxedClass(0, sizeof(BoxedDict), false);
tuple_cls = new BoxedClass(0, sizeof(BoxedTuple), false);
file_cls = new BoxedClass(0, sizeof(BoxedFile), false);
set_cls = new BoxedClass(0, sizeof(BoxedSet), false);
member_cls = new BoxedClass(0, sizeof(BoxedMemberDescriptor), false);
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
......@@ -417,17 +417,17 @@ void setupRuntime() {
type_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)typeCall, NULL, 1, true)));
type_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)typeNew, NULL, 2, true)));
type_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)typeRepr, NULL, 1, true)));
type_cls->setattr("__str__", type_cls->peekattr("__repr__"), NULL, NULL);
type_cls->setattr("__str__", type_cls->getattr("__repr__"), NULL, NULL);
type_cls->freeze();
none_cls->giveAttr("__name__", boxStrConstant("NoneType"));
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, NULL, 1, false)));
none_cls->setattr("__str__", none_cls->peekattr("__repr__"), NULL, NULL);
none_cls->setattr("__str__", none_cls->getattr("__repr__"), NULL, NULL);
none_cls->freeze();
module_cls->giveAttr("__name__", boxStrConstant("module"));
module_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)moduleRepr, NULL, 1, false)));
module_cls->setattr("__str__", module_cls->peekattr("__repr__"), NULL, NULL);
module_cls->setattr("__str__", module_cls->getattr("__repr__"), NULL, NULL);
module_cls->freeze();
member_cls->giveAttr("__name__", boxStrConstant("member"));
......@@ -445,7 +445,7 @@ void setupRuntime() {
function_cls->giveAttr("__name__", boxStrConstant("function"));
function_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)functionRepr, NULL, 1, false)));
function_cls->setattr("__str__", function_cls->peekattr("__repr__"), NULL, NULL);
function_cls->setattr("__str__", function_cls->getattr("__repr__"), NULL, NULL);
function_cls->freeze();
instancemethod_cls->giveAttr("__name__", boxStrConstant("instancemethod"));
......@@ -459,7 +459,7 @@ void setupRuntime() {
addRTFunction(slice_new, (void*)sliceNew4, NULL, 4, false);
slice_cls->giveAttr("__new__", new BoxedFunction(slice_new));
slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, NULL, 1, true)));
slice_cls->setattr("__str__", slice_cls->peekattr("__repr__"), NULL, NULL);
slice_cls->setattr("__str__", slice_cls->getattr("__repr__"), NULL, NULL);
slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET));
slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET));
slice_cls->giveAttr("step", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STEP_OFFSET));
......
......@@ -260,15 +260,25 @@ public:
BoxedDict() __attribute__((visibility("default"))) : Box(&dict_flavor, dict_cls) {}
};
class BoxedFunction : public HCBox {
class BoxedFunction : public Box {
public:
HCAttrs attrs;
CLFunction* f;
BoxedFunction(CLFunction* f);
};
class BoxedModule : public HCBox {
// TODO hack
class BoxedUserObject : public Box {
public:
HCAttrs attrs;
BoxedUserObject(BoxedClass* cls) : Box(&user_flavor, cls) {}
};
class BoxedModule : public Box {
public:
HCAttrs attrs;
const std::string fn; // for traceback purposes; not the same as __file__
BoxedModule(const std::string& name, const std::string& fn);
......
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