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);
......
This diff is collapsed.
......@@ -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