Commit b44b06f9 authored by Chris Toshok's avatar Chris Toshok

colocate string and tuple contents with the object, and share a single allocation.

Tuples now contain a pointer to their storage (Box**) + size, and strings contain
an llvm::StringRef which contains the pointer+size.
parent 3486e84c
......@@ -43,7 +43,7 @@ Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, Boxe
Box* rtn;
if (call_flags == METH_NOARGS) {
assert(varargs->elts.size() == 0);
assert(varargs->size() == 0);
assert(kwargs->d.size() == 0);
rtn = (Box*)self->method->ml_meth(obj, NULL);
} else if (call_flags == METH_VARARGS) {
......@@ -53,7 +53,7 @@ Box* BoxedMethodDescriptor::__call__(BoxedMethodDescriptor* self, Box* obj, Boxe
rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(obj, varargs, kwargs);
} else if (call_flags == METH_O) {
assert(kwargs->d.size() == 0);
assert(varargs->elts.size() == 1);
assert(varargs->size() == 1);
rtn = (Box*)self->method->ml_meth(obj, varargs->elts[0]);
} else {
RELEASE_ASSERT(0, "0x%x", call_flags);
......
......@@ -29,17 +29,17 @@ static float_format_type double_format, float_format;
static float_format_type detected_double_format, detected_float_format;
static PyObject* float_getformat(PyTypeObject* v, PyObject* arg) noexcept {
char* s;
float_format_type r;
BoxedString* str = static_cast<BoxedString*>(arg);
if (!PyString_Check(arg)) {
PyErr_Format(PyExc_TypeError, "__getformat__() argument must be string, not %.500s", Py_TYPE(arg)->tp_name);
return NULL;
}
s = PyString_AS_STRING(arg);
if (strcmp(s, "double") == 0) {
if (str->s == "double") {
r = double_format;
} else if (strcmp(s, "float") == 0) {
} else if (str->s == "float") {
r = float_format;
} else {
PyErr_SetString(PyExc_ValueError, "__getformat__() argument 1 must be "
......@@ -49,11 +49,11 @@ static PyObject* float_getformat(PyTypeObject* v, PyObject* arg) noexcept {
switch (r) {
case unknown_format:
return PyString_FromString("unknown");
return static_cast<PyObject*>(boxStrConstant("unknown"));
case ieee_little_endian_format:
return PyString_FromString("IEEE, little-endian");
return static_cast<PyObject*>(boxStrConstant("IEEE, little-endian"));
case ieee_big_endian_format:
return PyString_FromString("IEEE, big-endian");
return static_cast<PyObject*>(boxStrConstant("IEEE, big-endian"));
default:
Py_FatalError("insane float_format or double_format");
return NULL;
......
......@@ -421,9 +421,9 @@ extern "C" PyObject* PyObject_SelfIter(PyObject* obj) noexcept {
extern "C" int PyObject_GenericSetAttr(PyObject* obj, PyObject* name, PyObject* value) noexcept {
try {
if (value == NULL)
delattrGeneric(obj, static_cast<BoxedString*>(name)->s, NULL);
delattrGeneric(obj, std::string(static_cast<BoxedString*>(name)->s), NULL);
else
setattrGeneric(obj, static_cast<BoxedString*>(name)->s.c_str(), value, NULL);
setattrGeneric(obj, std::string(static_cast<BoxedString*>(name)->s), value, NULL);
} catch (ExcInfo e) {
setCAPIException(e);
return -1;
......
......@@ -1577,7 +1577,7 @@ bool update_slot(BoxedClass* type, const std::string& attr) noexcept {
}
if (ptrs[0] == NULL)
return false; /* Not an attribute that affects any slots */
int r = update_subclasses(type, new BoxedString(attr), update_slots_callback, (void*)ptrs);
int r = update_subclasses(type, boxString(attr), update_slots_callback, (void*)ptrs);
// TODO this is supposed to be a CAPI function!
if (r)
......@@ -1634,13 +1634,13 @@ static PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds)
RELEASE_ASSERT(args->cls == tuple_cls, "");
RELEASE_ASSERT(kwds->cls == dict_cls, "");
RELEASE_ASSERT(args->elts.size() >= 1, "");
RELEASE_ASSERT(args->size() >= 1, "");
BoxedClass* subtype = static_cast<BoxedClass*>(args->elts[0]);
RELEASE_ASSERT(isSubclass(subtype->cls, type_cls), "");
RELEASE_ASSERT(isSubclass(subtype, self), "");
BoxedTuple* new_args = new BoxedTuple(BoxedTuple::GCVector(args->elts.begin() + 1, args->elts.end()));
BoxedTuple* new_args = BoxedTuple::create(args->size() - 1, &args->elts[1]);
return self->tp_new(subtype, new_args, kwds);
}
......@@ -2553,13 +2553,13 @@ static void remove_subclass(PyTypeObject* base, PyTypeObject* type) noexcept {
void commonClassSetup(BoxedClass* cls) {
if (cls->tp_bases == NULL) {
if (cls->tp_base)
cls->tp_bases = new BoxedTuple({ cls->tp_base });
cls->tp_bases = BoxedTuple::create({ cls->tp_base });
else
cls->tp_bases = new BoxedTuple({});
cls->tp_bases = BoxedTuple::create({});
}
/* Link into each base class's list of subclasses */
for (PyObject* b : static_cast<BoxedTuple*>(cls->tp_bases)->elts) {
for (PyObject* b : *static_cast<BoxedTuple*>(cls->tp_bases)) {
if (PyType_Check(b) && add_subclass((PyTypeObject*)b, cls) < 0)
throwCAPIException();
}
......@@ -2573,7 +2573,8 @@ void commonClassSetup(BoxedClass* cls) {
assert(cls->tp_mro);
assert(cls->tp_mro->cls == tuple_cls);
for (auto b : static_cast<BoxedTuple*>(cls->tp_mro)->elts) {
for (auto b : *static_cast<BoxedTuple*>(cls->tp_mro)) {
if (b == cls)
continue;
if (PyType_Check(b))
......
......@@ -68,11 +68,11 @@ public:
rtn = (Box*)((PyCFunctionWithKeywords)self->func)(self->passthrough, varargs, kwargs);
} else if (self->ml_flags == METH_NOARGS) {
assert(kwargs->d.size() == 0);
assert(varargs->elts.size() == 0);
assert(varargs->size() == 0);
rtn = (Box*)self->func(self->passthrough, NULL);
} else if (self->ml_flags == METH_O) {
assert(kwargs->d.size() == 0);
assert(varargs->elts.size() == 1);
assert(varargs->size() == 1);
rtn = (Box*)self->func(self->passthrough, varargs->elts[0]);
} else {
RELEASE_ASSERT(0, "0x%x", self->ml_flags);
......
......@@ -580,7 +580,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
Box* type = last_exception.type;
Box* value = last_exception.value ? last_exception.value : None;
Box* traceback = last_exception.traceback ? last_exception.traceback : None;
v = new BoxedTuple({ type, value, traceback });
v = BoxedTuple::create({ type, value, traceback });
last_exception = ExcInfo(NULL, NULL, NULL);
} else if (node->opcode == AST_LangPrimitive::CHECK_EXC_MATCH) {
assert(node->args.size() == 2);
......@@ -747,11 +747,11 @@ Value ASTInterpreter::visit_makeClass(AST_MakeClass* mkclass) {
ScopeInfo* scope_info = source_info->scoping->getScopeInfoForNode(node);
assert(scope_info);
BoxedTuple::GCVector bases;
for (AST_expr* b : node->bases)
bases.push_back(visit_expr(b).o);
BoxedTuple* basesTuple = new BoxedTuple(std::move(bases));
BoxedTuple* basesTuple = BoxedTuple::create(node->bases.size());
int base_idx = 0;
for (AST_expr* b : node->bases) {
basesTuple->elts[base_idx++] = visit_expr(b).o;
}
std::vector<Box*, StlCompatAllocator<Box*>> decorators;
for (AST_expr* d : node->decorator_list)
......@@ -1132,10 +1132,11 @@ Value ASTInterpreter::visit_list(AST_List* node) {
}
Value ASTInterpreter::visit_tuple(AST_Tuple* node) {
BoxedTuple::GCVector elts;
BoxedTuple* rtn = BoxedTuple::create(node->elts.size());
int rtn_idx = 0;
for (AST_expr* e : node->elts)
elts.push_back(visit_expr(e).o);
return new BoxedTuple(std::move(elts));
rtn->elts[rtn_idx++] = visit_expr(e).o;
return rtn;
}
Value ASTInterpreter::visit_attribute(AST_Attribute* node) {
......@@ -1194,7 +1195,7 @@ Box* astInterpretFrom(CompiledFunction* cf, AST_expr* after_expr, AST_stmt* encl
for (const auto& p : frame_state.locals->d) {
assert(p.first->cls == str_cls);
std::string name = static_cast<BoxedString*>(p.first)->s;
auto& name = static_cast<BoxedString*>(p.first)->s;
if (name == PASSED_GENERATOR_NAME) {
interpreter.setGenerator(p.second);
} else if (name == PASSED_CLOSURE_NAME) {
......
......@@ -2203,20 +2203,20 @@ public:
Box* deserializeFromFrame(const FrameVals& vals) override {
assert(vals.size() == numFrameArgs());
BoxedTuple::GCVector elts;
BoxedTuple* rtn = BoxedTuple::create(elt_types.size());
int rtn_idx = 0;
int cur_idx = 0;
for (auto e : elt_types) {
int num_args = e->numFrameArgs();
// TODO: inefficient to make these copies
FrameVals sub_vals(vals.begin() + cur_idx, vals.begin() + cur_idx + num_args);
elts.push_back(e->deserializeFromFrame(sub_vals));
rtn->elts[rtn_idx++] = e->deserializeFromFrame(sub_vals);
cur_idx += num_args;
}
assert(cur_idx == vals.size());
return new BoxedTuple(std::move(elts));
return rtn;
}
int numFrameArgs() override {
......
......@@ -364,7 +364,7 @@ Box* eval(Box* boxedCode) {
// TODO should have a cleaner interface that can parse the Expression directly
// TODO this memory leaks
RELEASE_ASSERT(boxedCode->cls == str_cls, "");
const char* code = static_cast<BoxedString*>(boxedCode)->s.c_str();
const char* code = static_cast<BoxedString*>(boxedCode)->s.data();
AST_Module* parsedModule = parse_string(code);
RELEASE_ASSERT(parsedModule->body[0]->type == AST_TYPE::Expr, "");
AST_Expression* parsedExpr = new AST_Expression(std::move(parsedModule->interned_strings));
......@@ -385,7 +385,7 @@ Box* exec(Box* boxedCode) {
// TODO same issues as in `eval`
RELEASE_ASSERT(boxedCode->cls == str_cls, "");
const char* code = static_cast<BoxedString*>(boxedCode)->s.c_str();
const char* code = static_cast<BoxedString*>(boxedCode)->s.data();
AST_Module* parsedModule = parse_string(code);
AST_Suite* parsedSuite = new AST_Suite(std::move(parsedModule->interned_strings));
parsedSuite->body = parsedModule->body;
......
......@@ -850,12 +850,12 @@ pypa::String pypaUnicodeEscapeDecoder(pypa::String s, bool raw_prefix, bool& err
checkAndThrowCAPIException();
BoxedString* str_utf8 = (BoxedString*)PyUnicode_AsUTF8String(unicode);
checkAndThrowCAPIException();
return str_utf8->s;
return std::string(str_utf8->s);
} catch (ExcInfo e) {
error = true;
BoxedString* error_message = str(e.value);
if (error_message && error_message->cls == str_cls)
return error_message->s;
return std::string(error_message->s);
return "Encountered an unknown error inside pypaUnicodeEscapeDecoder";
}
}
......
......@@ -166,7 +166,7 @@ static int main(int argc, char** argv) {
if (!Py_NoSiteFlag) {
try {
std::string module_name = "site";
importModuleLevel(&module_name, None, None, 0);
importModuleLevel(module_name, None, None, 0);
} catch (ExcInfo e) {
e.printExcAndTraceback();
return 1;
......
......@@ -148,7 +148,7 @@ extern "C" Box* min(Box* arg0, BoxedTuple* args) {
Box* minElement;
Box* container;
if (args->elts.size() == 0) {
if (args->size() == 0) {
minElement = nullptr;
container = arg0;
} else {
......@@ -178,7 +178,7 @@ extern "C" Box* max(Box* arg0, BoxedTuple* args) {
Box* maxElement;
Box* container;
if (args->elts.size() == 0) {
if (args->size() == 0) {
maxElement = nullptr;
container = arg0;
} else {
......@@ -250,7 +250,8 @@ extern "C" Box* chr(Box* arg) {
raiseExcHelper(ValueError, "chr() arg not in range(256)");
}
return boxString(std::string(1, (char)n));
char c = (char)n;
return boxStringRef(llvm::StringRef(&c, 1));
}
extern "C" Box* unichr(Box* arg) {
......@@ -382,7 +383,8 @@ Box* bltinImport(Box* name, Box* globals, Box* locals, Box** args) {
raiseExcHelper(TypeError, "an integer is required");
}
return importModuleLevel(&static_cast<BoxedString*>(name)->s, globals, fromlist, ((BoxedInt*)level)->n);
std::string _name = static_cast<BoxedString*>(name)->s;
return importModuleLevel(_name, globals, fromlist, ((BoxedInt*)level)->n);
}
Box* delattrFunc(Box* obj, Box* _str) {
......@@ -391,7 +393,7 @@ Box* delattrFunc(Box* obj, Box* _str) {
if (_str->cls != str_cls)
raiseExcHelper(TypeError, "attribute name must be string, not '%s'", getTypeName(_str));
BoxedString* str = static_cast<BoxedString*>(_str);
delattr(obj, str->s.c_str());
delattr(obj, str->s.data());
return None;
}
......@@ -406,7 +408,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
Box* rtn = NULL;
try {
rtn = getattr(obj, str->s.c_str());
rtn = getattr(obj, str->s.data());
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
......@@ -416,7 +418,7 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
if (default_value)
return default_value;
else
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj), str->s.c_str());
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj), str->s.data());
}
return rtn;
......@@ -430,7 +432,7 @@ Box* setattrFunc(Box* obj, Box* _str, Box* value) {
}
BoxedString* str = static_cast<BoxedString*>(_str);
setattr(obj, str->s.c_str(), value);
setattr(obj, str->s.data(), value);
return None;
}
......@@ -465,7 +467,7 @@ Box* map2(Box* f, Box* container) {
Box* map(Box* f, BoxedTuple* args) {
assert(args->cls == tuple_cls);
auto num_iterable = args->elts.size();
auto num_iterable = args->size();
if (num_iterable < 1)
raiseExcHelper(TypeError, "map() requires at least two args");
......@@ -475,7 +477,8 @@ Box* map(Box* f, BoxedTuple* args) {
std::vector<BoxIterator> args_it;
std::vector<BoxIterator> args_end;
for (auto& e : args->elts) {
for (auto e : *args) {
auto range = e->pyElements();
args_it.emplace_back(range.begin());
args_end.emplace_back(range.end());
......@@ -559,8 +562,7 @@ Box* zip2(Box* container1, Box* container2) {
BoxIterator it2 = range2.begin();
for (; it1 != range1.end() && it2 != range2.end(); ++it1, ++it2) {
BoxedTuple::GCVector elts{ *it1, *it2 };
listAppendInternal(rtn, new BoxedTuple(std::move(elts)));
listAppendInternal(rtn, BoxedTuple::create({ *it1, *it2 }));
}
return rtn;
}
......@@ -583,7 +585,7 @@ public:
RELEASE_ASSERT(isSubclass(self->cls, BaseException), "");
BoxedException* exc = static_cast<BoxedException*>(self);
return new BoxedTuple({ self->cls, EmptyTuple, makeAttrWrapper(self) });
return BoxedTuple::create({ self->cls, EmptyTuple, makeAttrWrapper(self) });
}
};
......@@ -598,7 +600,7 @@ Box* exceptionNew(BoxedClass* cls, BoxedTuple* args) {
BoxedException* rtn = new (cls) BoxedException();
// TODO: this should be a MemberDescriptor and set during init
if (args->elts.size() == 1)
if (args->size() == 1)
rtn->giveAttr("message", args->elts[0]);
else
rtn->giveAttr("message", boxStrConstant(""));
......@@ -623,7 +625,7 @@ Box* exceptionRepr(Box* b) {
assert(message->cls == str_cls);
BoxedString* message_s = static_cast<BoxedString*>(message);
return boxString(std::string(getTypeName(b)) + "(" + message_s->s + ",)");
return boxStringTwine(llvm::Twine(getTypeName(b)) + "(" + message_s->s + ",)");
}
static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int size = 0) {
......@@ -667,7 +669,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
}
checkAndThrowCAPIException();
Box* cls = runtimeCall(type_cls, ArgPassSpec(3), boxedName, new BoxedTuple({ base }), dict, NULL, NULL);
Box* cls = runtimeCall(type_cls, ArgPassSpec(3), boxedName, BoxedTuple::create({ base }), dict, NULL, NULL);
return cls;
} catch (ExcInfo e) {
abort();
......@@ -706,7 +708,7 @@ public:
BoxedEnumerate* self = static_cast<BoxedEnumerate*>(_self);
Box* val = *self->iterator;
++self->iterator;
return new BoxedTuple({ boxInt(self->idx++), val });
return BoxedTuple::create({ boxInt(self->idx++), val });
}
static Box* hasnext(Box* _self) {
......@@ -766,14 +768,14 @@ Box* execfile(Box* _fn) {
#endif
#else
bool exists = llvm::sys::fs::exists(fn->s);
bool exists = llvm::sys::fs::exists(std::string(fn->s));
#endif
if (!exists)
raiseExcHelper(IOError, "No such file or directory: '%s'", fn->s.c_str());
raiseExcHelper(IOError, "No such file or directory: '%s'", fn->s.data());
// Run directly inside the current module:
AST_Module* ast = caching_parse_file(fn->s.c_str());
AST_Module* ast = caching_parse_file(fn->s.data());
compileAndRunModule(ast, getCurrentModule());
return None;
......@@ -785,7 +787,7 @@ Box* print(BoxedTuple* args, BoxedDict* kwargs) {
Box* dest, *end;
auto it = kwargs->d.find(new BoxedString("file"));
auto it = kwargs->d.find(boxStrConstant("file"));
if (it != kwargs->d.end()) {
dest = it->second;
kwargs->d.erase(it);
......@@ -793,23 +795,23 @@ Box* print(BoxedTuple* args, BoxedDict* kwargs) {
dest = getSysStdout();
}
it = kwargs->d.find(new BoxedString("end"));
it = kwargs->d.find(boxStrConstant("end"));
if (it != kwargs->d.end()) {
end = it->second;
kwargs->d.erase(it);
} else {
end = new BoxedString("\n");
end = boxStrConstant("\n");
}
RELEASE_ASSERT(kwargs->d.size() == 0, "print() got unexpected keyword arguments");
static const std::string write_str("write");
Box* space_box = new BoxedString(" ");
Box* space_box = boxStrConstant(" ");
// TODO softspace handling?
bool first = true;
for (auto e : args->elts) {
for (auto e : *args) {
BoxedString* s = str(e);
if (!first) {
......
......@@ -43,7 +43,7 @@ static Box* setOption(Box* option, Box* value) {
else CHECK(REOPT_THRESHOLD_BASELINE);
else CHECK(OSR_THRESHOLD_BASELINE);
else CHECK(SPECULATION_THRESHOLD);
else raiseExcHelper(ValueError, "unknown option name '%s", option_string->s.c_str());
else raiseExcHelper(ValueError, "unknown option name '%s", option_string->s.data());
return None;
}
......
......@@ -43,7 +43,7 @@ Box* sysExcInfo() {
assert(exc->type);
assert(exc->value);
assert(exc->traceback);
return new BoxedTuple({ exc->type, exc->value, exc->traceback });
return BoxedTuple::create({ exc->type, exc->value, exc->traceback });
}
Box* sysExcClear() {
......@@ -184,7 +184,7 @@ void prependToSysPath(const std::string& path) {
BoxedList* sys_path = getSysPath();
static std::string attr = "insert";
callattr(sys_path, &attr, CallattrFlags({.cls_only = false, .null_on_nonexistent = false }), ArgPassSpec(2),
boxInt(0), new BoxedString(path), NULL, NULL, NULL);
boxInt(0), boxString(path), NULL, NULL, NULL);
}
static BoxedClass* sys_flags_cls;
......@@ -258,7 +258,7 @@ void setupSys() {
sys_module->giveAttr("warnoptions", new BoxedList());
sys_module->giveAttr("py3kwarning", False);
sys_module->giveAttr("byteorder", new BoxedString(isLittleEndian() ? "little" : "big"));
sys_module->giveAttr("byteorder", boxStrConstant(isLittleEndian() ? "little" : "big"));
sys_module->giveAttr("platform", boxStrConstant("unknown")); // seems like a reasonable, if poor, default
......@@ -293,14 +293,14 @@ void setupSys() {
sys_module->giveAttr("hexversion", boxInt(PY_VERSION_HEX));
// TODO: this should be a "sys.version_info" object, not just a tuple (ie can access fields by name)
sys_module->giveAttr("version_info",
new BoxedTuple({ boxInt(PYTHON_VERSION_MAJOR), boxInt(PYTHON_VERSION_MINOR),
boxInt(PYTHON_VERSION_MICRO), boxStrConstant("beta"), boxInt(0) }));
BoxedTuple::create({ boxInt(PYTHON_VERSION_MAJOR), boxInt(PYTHON_VERSION_MINOR),
boxInt(PYTHON_VERSION_MICRO), boxStrConstant("beta"), boxInt(0) }));
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_module->giveAttr("maxsize", boxInt(PY_SSIZE_T_MAX));
sys_flags_cls = new BoxedHeapClass(object_cls, BoxedSysFlags::gcHandler, 0, 0, sizeof(BoxedSysFlags), false,
new BoxedString("flags"));
static_cast<BoxedString*>(boxString("flags")));
sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
#define ADD(name) \
......@@ -311,7 +311,7 @@ void setupSys() {
ADD(no_user_site);
#undef ADD
sys_flags_cls->tp_mro = new BoxedTuple({ sys_flags_cls, object_cls });
sys_flags_cls->tp_mro = BoxedTuple::create({ sys_flags_cls, object_cls });
sys_flags_cls->freeze();
sys_module->giveAttr("flags", new BoxedSysFlags());
......@@ -326,7 +326,8 @@ void setupSysEnd() {
std::sort<decltype(builtin_module_names)::iterator, PyLt>(builtin_module_names.begin(), builtin_module_names.end(),
PyLt());
sys_module->giveAttr("builtin_module_names", new BoxedTuple(std::move(builtin_module_names)));
sys_module->giveAttr("builtin_module_names",
BoxedTuple::create(builtin_module_names.size(), &builtin_module_names[0]));
sys_flags_cls->finishInitialization();
}
}
......@@ -250,7 +250,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept
}
try {
return getattr(o, static_cast<BoxedString*>(attr_name)->s.c_str());
return getattr(o, static_cast<BoxedString*>(attr_name)->data());
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
......@@ -258,7 +258,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept
}
extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept {
Box* r = getattrInternalGeneric(o, static_cast<BoxedString*>(name)->s.c_str(), NULL, false, false, NULL, NULL);
Box* r = getattrInternalGeneric(o, static_cast<BoxedString*>(name)->data(), NULL, false, false, NULL, NULL);
if (!r)
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
PyString_AS_STRING(name));
......@@ -879,7 +879,8 @@ extern "C" PyObject* PyImport_Import(PyObject* module_name) noexcept {
RELEASE_ASSERT(module_name->cls == str_cls, "");
try {
return importModuleLevel(&static_cast<BoxedString*>(module_name)->s, None, None, -1);
std::string _module_name = static_cast<BoxedString*>(module_name)->s;
return importModuleLevel(_module_name, None, None, -1);
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
}
......
......@@ -33,7 +33,7 @@ static Box* classLookup(BoxedClassobj* cls, const std::string& attr) {
if (r)
return r;
for (auto b : cls->bases->elts) {
for (auto b : *cls->bases) {
RELEASE_ASSERT(b->cls == classobj_cls, "");
Box* r = classLookup(static_cast<BoxedClassobj*>(b), attr);
if (r)
......@@ -88,7 +88,7 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
raiseExcHelper(TypeError, "PyClass_New: bases must be a tuple");
BoxedTuple* bases = static_cast<BoxedTuple*>(_bases);
for (auto base : bases->elts) {
for (auto base : *bases) {
if (!PyClass_Check(base) && PyCallable_Check(base->cls)) {
Box* r = PyObject_CallFunctionObjArgs(base->cls, name, bases, dict, NULL);
if (!r)
......@@ -104,7 +104,7 @@ Box* classobjNew(Box* _cls, Box* _name, Box* _bases, Box** _args) {
for (auto& p : dict->d) {
RELEASE_ASSERT(p.first->cls == str_cls, "");
made->setattr(static_cast<BoxedString*>(p.first)->s, p.second, NULL);
made->setattr(std::string(static_cast<BoxedString*>(p.first)->s), p.second, NULL);
}
// Note: make sure to do this after assigning the attrs, since it will overwrite any defined __name__
......@@ -134,7 +134,7 @@ Box* classobjCall(Box* _cls, Box* _args, Box* _kwargs) {
if (init_rtn != None)
raiseExcHelper(TypeError, "__init__() should return None");
} else {
if (args->elts.size() || kwargs->d.size())
if (args->size() || kwargs->d.size())
raiseExcHelper(TypeError, "this constructor takes no arguments");
}
return made;
......@@ -162,9 +162,9 @@ static Box* classobjGetattribute(Box* _cls, Box* _attr) {
}
}
Box* r = classLookup(cls, attr->s);
Box* r = classLookup(cls, std::string(attr->s));
if (!r)
raiseExcHelper(AttributeError, "class %s has no attribute '%s'", cls->name->s.c_str(), attr->s.c_str());
raiseExcHelper(AttributeError, "class %s has no attribute '%s'", cls->name->data(), attr->data());
r = processDescriptor(r, None, cls);
return r;
......@@ -242,7 +242,7 @@ Box* classobjStr(Box* _obj) {
Box* _mod = cls->getattr("__module__");
RELEASE_ASSERT(_mod, "");
RELEASE_ASSERT(_mod->cls == str_cls, "");
return boxString(static_cast<BoxedString*>(_mod)->s + "." + cls->name->s);
return boxStringTwine(llvm::Twine(static_cast<BoxedString*>(_mod)->s) + "." + cls->name->s);
}
static Box* _instanceGetattribute(Box* _inst, Box* _attr, bool raise_on_missing) {
......@@ -282,8 +282,7 @@ static Box* _instanceGetattribute(Box* _inst, Box* _attr, bool raise_on_missing)
if (!raise_on_missing)
return NULL;
raiseExcHelper(AttributeError, "%s instance has no attribute '%s'", inst->inst_cls->name->s.c_str(),
attr->s.c_str());
raiseExcHelper(AttributeError, "%s instance has no attribute '%s'", inst->inst_cls->name->data(), attr->data());
}
Box* instanceGetattribute(Box* _inst, Box* _attr) {
......@@ -361,7 +360,7 @@ Box* instanceRepr(Box* _inst) {
assert(class_str->cls == str_cls);
char buf[80];
snprintf(buf, 80, "<%s instance at %p>", static_cast<BoxedString*>(class_str)->s.c_str(), inst);
snprintf(buf, 80, "<%s instance at %p>", static_cast<BoxedString*>(class_str)->data(), inst);
return boxStrConstant(buf);
}
}
......@@ -495,7 +494,7 @@ Box* instanceCall(Box* _inst, Box* _args, Box* _kwargs) {
Box* call_func = _instanceGetattribute(inst, boxStrConstant("__call__"), false);
if (!call_func)
raiseExcHelper(AttributeError, "%s instance has no __call__ method", inst->inst_cls->name->s.c_str());
raiseExcHelper(AttributeError, "%s instance has no __call__ method", inst->inst_cls->name->data());
return runtimeCall(call_func, ArgPassSpec(0, 0, true, true), _args, _kwargs, NULL, NULL, NULL);
}
......
......@@ -55,12 +55,12 @@ public:
BoxedTuple::GCVector elts;
for (auto sr : param_names.args)
elts.push_back(new BoxedString(sr));
elts.push_back(boxString(sr));
if (param_names.vararg.size())
elts.push_back(new BoxedString(param_names.vararg));
elts.push_back(boxString(param_names.vararg));
if (param_names.kwarg.size())
elts.push_back(new BoxedString(param_names.kwarg));
return new BoxedTuple(std::move(elts));
elts.push_back(boxString(param_names.kwarg));
return BoxedTuple::create(elts.size(), &elts[0]);
}
static Box* flags(Box* b, void*) {
......
......@@ -44,7 +44,7 @@ Box* dictRepr(BoxedDict* self) {
chars.insert(chars.end(), v->s.begin(), v->s.end());
}
chars.push_back('}');
return boxString(std::string(chars.begin(), chars.end()));
return boxString(llvm::StringRef(&chars[0], chars.size()));
}
Box* dictClear(BoxedDict* self) {
......@@ -69,10 +69,7 @@ Box* dictItems(BoxedDict* self) {
rtn->ensure(self->d.size());
for (const auto& p : self->d) {
BoxedTuple::GCVector elts;
elts.push_back(p.first);
elts.push_back(p.second);
BoxedTuple* t = new BoxedTuple(std::move(elts));
BoxedTuple* t = BoxedTuple::create({ p.first, p.second });
listAppendInternal(rtn, t);
}
......@@ -378,7 +375,7 @@ Box* dictPopitem(BoxedDict* self) {
Box* value = it->second;
self->d.erase(it);
auto rtn = new BoxedTuple({ key, value });
auto rtn = BoxedTuple::create({ key, value });
return rtn;
}
......@@ -506,9 +503,9 @@ void dictMergeFromSeq2(BoxedDict* self, Box* other) {
self->d[list->elts->elts[0]] = list->elts->elts[1];
} else if (element->cls == tuple_cls) {
BoxedTuple* tuple = static_cast<BoxedTuple*>(element);
if (tuple->elts.size() != 2)
if (tuple->size() != 2)
raiseExcHelper(ValueError, "dictionary update sequence element #%d has length %d; 2 is required", idx,
tuple->elts.size());
tuple->size());
self->d[tuple->elts[0]] = tuple->elts[1];
} else
......@@ -541,8 +538,8 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
assert(kwargs);
assert(kwargs->cls == dict_cls);
RELEASE_ASSERT(args->elts.size() <= 1, ""); // should throw a TypeError
if (args->elts.size()) {
RELEASE_ASSERT(args->size() <= 1, ""); // should throw a TypeError
if (args->size()) {
Box* arg = args->elts[0];
if (getattrInternal(arg, "keys", NULL)) {
dictMerge(self, arg);
......@@ -558,7 +555,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
}
extern "C" Box* dictInit(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
int args_sz = args->elts.size();
int args_sz = args->size();
int kwargs_sz = kwargs->d.size();
// CPython accepts a single positional and keyword arguments, in any combination
......
......@@ -195,7 +195,7 @@ BoxedFile::BoxedFile(FILE* f, std::string fname, const char* fmode, int (*close)
f_bufptr(0),
f_setbuf(0),
unlocked_count(0) {
Box* r = fill_file_fields(this, f, new BoxedString(fname), fmode, close);
Box* r = fill_file_fields(this, f, boxString(fname), fmode, close);
checkAndThrowCAPIException();
assert(r == this);
}
......@@ -823,17 +823,17 @@ Box* fileNew(BoxedClass* cls, Box* s, Box* m) {
raiseExcHelper(TypeError, "");
}
const std::string& fn = static_cast<BoxedString*>(s)->s;
const std::string& mode = static_cast<BoxedString*>(m)->s;
auto fn = static_cast<BoxedString*>(s);
auto mode = static_cast<BoxedString*>(m);
FILE* f = fopen(fn.c_str(), mode.c_str());
FILE* f = fopen(fn->data(), mode->data());
if (!f) {
PyErr_SetFromErrnoWithFilename(IOError, fn.c_str());
PyErr_SetFromErrnoWithFilename(IOError, fn->data());
throwCAPIException();
abort(); // unreachable;
}
return new BoxedFile(f, fn, PyString_AsString(m));
return new BoxedFile(f, fn->s, PyString_AsString(m));
}
static PyObject* file_readlines(BoxedFile* f, PyObject* args) noexcept {
......
......@@ -166,7 +166,7 @@ SearchResult findModule(const std::string& name, const std::string& full_name, B
auto path_pass = path_list ? path_list : None;
Box* loader
= callattr(finder, &find_module_str, CallattrFlags({.cls_only = false, .null_on_nonexistent = false }),
ArgPassSpec(2), new BoxedString(full_name), path_pass, NULL, NULL, NULL);
ArgPassSpec(2), boxString(full_name), path_pass, NULL, NULL, NULL);
if (loader != None)
return SearchResult(loader);
......@@ -195,7 +195,7 @@ SearchResult findModule(const std::string& name, const std::string& full_name, B
BoxedString* p = static_cast<BoxedString*>(_p);
joined_path.clear();
llvm::sys::path::append(joined_path, p->s, name);
llvm::sys::path::append(joined_path, std::string(p->s), name);
std::string dn(joined_path.str());
llvm::sys::path::append(joined_path, "__init__.py");
......@@ -209,7 +209,7 @@ SearchResult findModule(const std::string& name, const std::string& full_name, B
auto path_pass = path_list ? path_list : None;
Box* loader = callattr(importer, &find_module_str,
CallattrFlags({.cls_only = false, .null_on_nonexistent = false }), ArgPassSpec(2),
new BoxedString(full_name), path_pass, NULL, NULL, NULL);
boxString(full_name), path_pass, NULL, NULL, NULL);
if (loader != None)
return SearchResult(loader);
}
......@@ -218,7 +218,7 @@ SearchResult findModule(const std::string& name, const std::string& full_name, B
return SearchResult(std::move(dn), SearchResult::PKG_DIRECTORY);
joined_path.clear();
llvm::sys::path::append(joined_path, p->s, name + ".py");
llvm::sys::path::append(joined_path, std::string(p->s), name + ".py");
fn = joined_path.str();
if (pathExists(fn))
......@@ -250,7 +250,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
if (pkgname->cls != str_cls) {
raiseExcHelper(ValueError, "__package__ set to non-string");
}
size_t len = pkgname->s.size();
size_t len = pkgname->size();
if (len == 0) {
if (level > 0) {
raiseExcHelper(ValueError, "Attempted relative import in non-package");
......@@ -270,7 +270,7 @@ static Box* getParent(Box* globals, int level, std::string& buf) {
Box* modpath = getattrInternal(globals, path_str, NULL);
if (modpath != NULL) {
/* __path__ is set, so modname is already the package name */
if (modname->s.size() > PATH_MAX) {
if (modname->size() > PATH_MAX) {
raiseExcHelper(ValueError, "Module name too long");
}
buf += modname->s;
......@@ -357,7 +357,7 @@ static Box* importSub(const std::string& name, const std::string& full_name, Box
const static std::string load_module_str("load_module");
module = callattr(sr.loader, &load_module_str,
CallattrFlags({.cls_only = false, .null_on_nonexistent = false }), ArgPassSpec(1),
new BoxedString(full_name), NULL, NULL, NULL, NULL);
boxString(full_name), NULL, NULL, NULL, NULL);
} else
RELEASE_ASSERT(0, "%d", sr.type);
......@@ -441,9 +441,8 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf,
}
static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive);
Box* importModuleLevel(std::string* name, Box* globals, Box* from_imports, int level) {
Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) {
bool return_first = from_imports == None;
assert(name);
static StatCounter slowpath_import("slowpath_import");
slowpath_import.log();
......@@ -453,7 +452,9 @@ Box* importModuleLevel(std::string* name, Box* globals, Box* from_imports, int l
if (!parent)
return NULL;
std::string _name = *name;
// make a copy of the string we pass in, since loadNext while
// modify the string as we load the modules along the path.
std::string _name = name;
Box* head;
bool again = loadNext(parent, level < 0 ? NULL : parent, _name, buf, &head);
......@@ -505,7 +506,7 @@ extern "C" PyObject* PyImport_ImportModuleLevel(const char* name, PyObject* glob
PyObject* fromlist, int level) noexcept {
try {
std::string module_name = name;
return importModuleLevel(&module_name, globals, fromlist ? fromlist : None, level);
return importModuleLevel(module_name, globals, fromlist ? fromlist : None, level);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
......@@ -539,7 +540,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
continue;
// Just want to import it and add it to the modules list for now:
importSub(s->s, buf + '.' + s->s, module);
importSub(s->s, (llvm::Twine(buf) + "." + s->s).str(), module);
}
}
......@@ -586,7 +587,7 @@ extern "C" PyObject* PyImport_ExecCodeModuleEx(char* name, PyObject* co, char* p
if (module == NULL)
return NULL;
AST_Module* ast = parse_string(code->s.c_str());
AST_Module* ast = parse_string(code->data());
compileAndRunModule(ast, module);
module->setattr("__file__", boxString(pathname), NULL);
return module;
......@@ -611,7 +612,7 @@ Box* nullImporterInit(Box* self, Box* _path) {
if (path->s.empty())
raiseExcHelper(ImportError, "empty pathname");
if (isdir(path->s.c_str()))
if (isdir(path->data()))
raiseExcHelper(ImportError, "existing directory");
return None;
......@@ -623,7 +624,7 @@ Box* nullImporterFindModule(Box* self, Box* fullname, Box* path) {
extern "C" Box* import(int level, Box* from_imports, const std::string* module_name) {
std::string _module_name(*module_name);
return importModuleLevel(&_module_name, getCurrentModule(), from_imports, level);
return importModuleLevel(_module_name, getCurrentModule(), from_imports, level);
}
Box* impFindModule(Box* _name, BoxedList* path) {
......@@ -635,19 +636,19 @@ Box* impFindModule(Box* _name, BoxedList* path) {
SearchResult sr = findModule(name->s, name->s, path_list);
if (sr.type == SearchResult::SEARCH_ERROR)
raiseExcHelper(ImportError, "%s", name->s.c_str());
raiseExcHelper(ImportError, "%s", name->data());
if (sr.type == SearchResult::PY_SOURCE) {
Box* path = boxString(sr.path);
Box* mode = boxStrConstant("r");
Box* f = runtimeCall(file_cls, ArgPassSpec(2), path, mode, NULL, NULL, NULL);
return new BoxedTuple({ f, path, new BoxedTuple({ boxStrConstant(".py"), mode, boxInt(sr.type) }) });
return BoxedTuple::create({ f, path, BoxedTuple::create({ boxStrConstant(".py"), mode, boxInt(sr.type) }) });
}
if (sr.type == SearchResult::PKG_DIRECTORY) {
Box* path = boxString(sr.path);
Box* mode = boxStrConstant("");
return new BoxedTuple({ None, path, new BoxedTuple({ mode, mode, boxInt(sr.type) }) });
Box* mode = EmptyString;
return BoxedTuple::create({ None, path, BoxedTuple::create({ mode, mode, boxInt(sr.type) }) });
}
Py_FatalError("unimplemented");
......@@ -665,7 +666,7 @@ Box* impLoadModule(Box* _name, Box* _file, Box* _pathname, Box** args) {
BoxedString* pathname = (BoxedString*)_pathname;
BoxedTuple* description = (BoxedTuple*)_description;
RELEASE_ASSERT(description->elts.size() == 3, "");
RELEASE_ASSERT(description->size() == 3, "");
BoxedString* suffix = (BoxedString*)description->elts[0];
BoxedString* mode = (BoxedString*)description->elts[1];
BoxedInt* type = (BoxedInt*)description->elts[2];
......@@ -678,7 +679,7 @@ Box* impLoadModule(Box* _name, Box* _file, Box* _pathname, Box** args) {
RELEASE_ASSERT(mode->s.empty(), "");
if (type->n == SearchResult::PKG_DIRECTORY) {
return createAndRunModule(name->s, pathname->s + "/__init__.py", pathname->s);
return createAndRunModule(name->s, (llvm::Twine(pathname->s) + "/__init__.py").str(), pathname->s);
}
Py_FatalError("unimplemented");
......@@ -688,7 +689,7 @@ Box* impGetSuffixes() {
BoxedList* list = new BoxedList;
// For now only add *.py
listAppendInternal(
list, new BoxedTuple({ new BoxedString(".py"), new BoxedString("U"), boxInt(SearchResult::PY_SOURCE) }));
list, BoxedTuple::create({ boxStrConstant(".py"), boxStrConstant("U"), boxInt(SearchResult::PY_SOURCE) }));
return list;
}
......
......@@ -20,7 +20,7 @@
namespace pyston {
extern "C" Box* import(int level, Box* from_imports, const std::string* module_name);
extern Box* importModuleLevel(std::string* module_name, Box* globals, Box* from_imports, int level);
extern Box* importModuleLevel(const std::string& module_name, Box* globals, Box* from_imports, int level);
}
#endif
......@@ -14,6 +14,8 @@
#include "runtime/inline/boxing.h"
#include "llvm/ADT/SmallString.h"
#include "runtime/int.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -28,25 +30,43 @@ extern "C" Box* createList() {
return new BoxedList();
}
BoxedString* _boxStrConstant(const char* chars) {
size_t len = strlen(chars);
return new (len) BoxedString(chars, len);
}
extern "C" BoxedString* boxStrConstant(const char* chars) {
return new BoxedString(chars);
return _boxStrConstant(chars);
}
BoxedString* _boxStrConstantSize(const char* chars, size_t n) {
return new (n) BoxedString(chars, n);
}
extern "C" BoxedString* boxStrConstantSize(const char* chars, size_t n) {
return new BoxedString(chars, n);
return _boxStrConstantSize(chars, n);
}
extern "C" Box* boxStringPtr(const std::string* s) {
return new BoxedString(*s);
return new (s->size()) BoxedString(s->c_str(), s->size());
}
Box* boxStringRef(llvm::StringRef s) {
return new (s.size()) BoxedString(s);
}
Box* boxString(const std::string& s) {
return new BoxedString(s);
return new (s.size()) BoxedString(s.c_str(), s.size());
}
Box* boxString(std::string&& s) {
return new BoxedString(std::move(s));
return new (s.size()) BoxedString(s.c_str(), s.size());
}
Box* boxStringTwine(const llvm::Twine& t) {
llvm::SmallString<256> Vec;
return boxString(t.toStringRef(Vec));
}
extern "C" double unboxFloat(Box* b) {
ASSERT(b->cls == float_cls, "%s", getTypeName(b));
BoxedFloat* f = (BoxedFloat*)b;
......
......@@ -66,8 +66,7 @@ Box* dictIterNext(Box* s) {
} else if (self->type == BoxedDictIterator::ValueIterator) {
rtn = self->it->second;
} else if (self->type == BoxedDictIterator::ItemIterator) {
BoxedTuple::GCVector elts{ self->it->first, self->it->second };
rtn = new BoxedTuple(std::move(elts));
rtn = BoxedTuple::create({ self->it->first, self->it->second });
}
++self->it;
return rtn;
......
......@@ -40,14 +40,14 @@ i1 tupleiterHasnextUnboxed(Box* s) {
assert(s->cls == tuple_iterator_cls);
BoxedTupleIterator* self = static_cast<BoxedTupleIterator*>(s);
return self->pos < self->t->elts.size();
return self->pos < self->t->size();
}
Box* tupleiterNext(Box* s) {
assert(s->cls == tuple_iterator_cls);
BoxedTupleIterator* self = static_cast<BoxedTupleIterator*>(s);
if (!(self->pos >= 0 && self->pos < self->t->elts.size())) {
if (!(self->pos >= 0 && self->pos < self->t->size())) {
raiseExcHelper(StopIteration, "");
}
......
......@@ -873,7 +873,7 @@ extern "C" BoxedString* intRepr(BoxedInt* v) {
char buf[80];
int len = snprintf(buf, 80, "%ld", v->n);
return new BoxedString(std::string(buf, len));
return static_cast<BoxedString*>(boxString(llvm::StringRef(buf, len)));
}
extern "C" Box* intHash(BoxedInt* self) {
......@@ -898,7 +898,7 @@ extern "C" Box* intHex(BoxedInt* self) {
len = snprintf(buf, sizeof(buf), "-0x%lx", std::abs(self->n));
else
len = snprintf(buf, sizeof(buf), "0x%lx", self->n);
return new BoxedString(std::string(buf, len));
return boxStringRef(llvm::StringRef(buf, len));
}
extern "C" Box* intOct(BoxedInt* self) {
......@@ -913,7 +913,7 @@ extern "C" Box* intOct(BoxedInt* self) {
len = snprintf(buf, sizeof(buf), "-%#lo", std::abs(self->n));
else
len = snprintf(buf, sizeof(buf), "%#lo", self->n);
return new BoxedString(std::string(buf, len));
return boxString(llvm::StringRef(buf, len));
}
extern "C" Box* intTrunc(BoxedInt* self) {
......@@ -942,8 +942,8 @@ static Box* _intNew(Box* val, Box* base) {
BoxedString* s = static_cast<BoxedString*>(val);
RELEASE_ASSERT(s->s.size() == strlen(s->s.c_str()), "");
Box* r = PyInt_FromString(s->s.c_str(), NULL, base_n);
RELEASE_ASSERT(s->size() == strlen(s->data()), "");
Box* r = PyInt_FromString(s->data(), NULL, base_n);
if (!r)
throwCAPIException();
return r;
......
......@@ -80,11 +80,11 @@ private:
static bool hasnext(BoxedList* o, uint64_t i) { return i < o->size; }
static Box* getValue(BoxedList* o, uint64_t i) { return o->elts->elts[i]; }
static bool hasnext(BoxedTuple* o, uint64_t i) { return i < o->elts.size(); }
static bool hasnext(BoxedTuple* o, uint64_t i) { return i < o->size(); }
static Box* getValue(BoxedTuple* o, uint64_t i) { return o->elts[i]; }
static bool hasnext(BoxedString* o, uint64_t i) { return i < o->s.size(); }
static Box* getValue(BoxedString* o, uint64_t i) { return new BoxedString(std::string(1, o->s[i])); }
static bool hasnext(BoxedString* o, uint64_t i) { return i < o->size(); }
static Box* getValue(BoxedString* o, uint64_t i) { return boxString(llvm::StringRef(o->data() + i, 1)); }
public:
BoxIteratorIndex(T* obj) : obj(obj), index(0) {
......
......@@ -16,7 +16,8 @@
#include <algorithm>
#include <cstring>
#include <sstream>
#include "llvm/Support/raw_ostream.h"
#include "capi/types.h"
#include "core/ast.h"
......@@ -55,14 +56,16 @@ extern "C" PyObject* PyList_AsTuple(PyObject* v) noexcept {
}
auto l = static_cast<BoxedList*>(v);
return new BoxedTuple(BoxedTuple::GCVector(l->elts->elts, l->elts->elts + l->size));
return BoxedTuple::create(l->size, &l->elts->elts[0]);
}
extern "C" Box* listRepr(BoxedList* self) {
LOCK_REGION(self->lock.asRead());
// TODO highly inefficient with all the string copying
std::ostringstream os;
std::string O("");
llvm::raw_string_ostream os(O);
os << '[';
for (int i = 0; i < self->size; i++) {
if (i > 0)
......@@ -75,7 +78,7 @@ extern "C" Box* listRepr(BoxedList* self) {
os << s->s;
}
os << ']';
return new BoxedString(os.str());
return boxString(os.str());
}
extern "C" Box* listNonzero(BoxedList* self) {
......@@ -282,7 +285,7 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
if (!v) {
v_size = 0;
v_elts = NULL;
} else if (isSubclass(v->cls, list_cls)) {
} else if (v->cls == list_cls || isSubclass(v->cls, list_cls)) {
BoxedList* lv = static_cast<BoxedList*>(v);
v_size = lv->size;
// If lv->size is 0, lv->elts->elts is garbage
......@@ -290,9 +293,9 @@ extern "C" Box* listSetitemSlice(BoxedList* self, BoxedSlice* slice, Box* v) {
v_elts = lv->elts->elts;
else
v_elts = NULL;
} else if (isSubclass(v->cls, tuple_cls)) {
} else if (v->cls == tuple_cls || isSubclass(v->cls, tuple_cls)) {
BoxedTuple* tv = static_cast<BoxedTuple*>(v);
v_size = tv->elts.size();
v_size = tv->size();
v_elts = &tv->elts[0];
} else {
RELEASE_ASSERT(0, "unsupported type for list slice assignment: '%s'", getTypeName(v));
......@@ -517,7 +520,7 @@ void listSort(BoxedList* self, Box* cmp, Box* key, Box* reverse) {
// original object.
// TODO we could potentially make this faster by copying the CPython approach of
// creating special sortwrapper objects that compare only based on the key.
Box* new_obj = new BoxedTuple({ key_val, boxInt(i), *obj_loc });
Box* new_obj = BoxedTuple::create({ key_val, boxInt(i), *obj_loc });
*obj_loc = new_obj;
num_keys_added++;
......@@ -629,7 +632,7 @@ Box* listIndex(BoxedList* self, Box* elt, BoxedInt* _start, Box** args) {
}
BoxedString* tostr = static_cast<BoxedString*>(repr(elt));
raiseExcHelper(ValueError, "%s is not in list", tostr->s.c_str());
raiseExcHelper(ValueError, "%s is not in list", tostr->data());
}
Box* listRemove(BoxedList* self, Box* elt) {
......
......@@ -268,7 +268,7 @@ extern "C" PyAPI_FUNC(PyObject*) _PyLong_Format(PyObject* aa, int base, int addL
os << "L";
os.flush();
auto rtn = new BoxedString(std::move(str));
auto rtn = boxString(str);
free(buf);
return rtn;
}
......@@ -451,7 +451,7 @@ BoxedLong* _longNew(Box* val, Box* _base) {
raiseExcHelper(TypeError, "long() arg2 must be >= 2 and <= 36");
}
int r = mpz_init_set_str(rtn->n, s->s.c_str(), base);
int r = mpz_init_set_str(rtn->n, s->data(), base);
RELEASE_ASSERT(r == 0, "");
} else {
if (isSubclass(val->cls, long_cls)) {
......@@ -936,7 +936,7 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) {
mpz_init(q->n);
mpz_init(r->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, rhs->n);
return new BoxedTuple({ q, r });
return BoxedTuple::create({ q, r });
} else if (isSubclass(_rhs->cls, int_cls)) {
BoxedInt* rhs = static_cast<BoxedInt*>(_rhs);
......@@ -948,7 +948,7 @@ extern "C" Box* longDivmod(BoxedLong* lhs, Box* _rhs) {
mpz_init(q->n);
mpz_init_set_si(r->n, rhs->n);
mpz_fdiv_qr(q->n, r->n, lhs->n, r->n);
return new BoxedTuple({ q, r });
return BoxedTuple::create({ q, r });
} else {
return NotImplemented;
}
......
......@@ -128,8 +128,9 @@ static Box* (*callattrInternal3)(Box*, const std::string*, LookupScope, CallRewr
size_t PyHasher::operator()(Box* b) const {
if (b->cls == str_cls) {
StringHash<std::string> H;
return H(static_cast<BoxedString*>(b)->s);
StringHash<char> H;
auto s = static_cast<BoxedString*>(b);
return H(s->data(), s->size());
}
BoxedInt* i = hash(b);
......@@ -218,7 +219,7 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent) {
extern "C" void assertFail(BoxedModule* inModule, Box* msg) {
if (msg) {
BoxedString* tostr = str(msg);
raiseExcHelper(AssertionError, "%s", tostr->s.c_str());
raiseExcHelper(AssertionError, "%s", tostr->data());
} else {
raiseExcHelper(AssertionError, "");
}
......@@ -272,7 +273,7 @@ static void _checkUnpackingLength(i64 expected, i64 given) {
extern "C" Box** unpackIntoArray(Box* obj, int64_t expected_size) {
if (obj->cls == tuple_cls) {
BoxedTuple* t = static_cast<BoxedTuple*>(obj);
_checkUnpackingLength(expected_size, t->elts.size());
_checkUnpackingLength(expected_size, t->size());
return &t->elts[0];
}
......@@ -413,7 +414,7 @@ BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attr
if (!ht_name)
assert(str_cls == NULL);
else
tp_name = ht_name->s.c_str();
tp_name = ht_name->data();
memset(&as_number, 0, sizeof(as_number));
memset(&as_mapping, 0, sizeof(as_mapping));
......@@ -425,7 +426,7 @@ BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base,
int weaklist_offset, int instance_size, bool is_user_defined,
const std::string& name) {
return create(metaclass, base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined,
new BoxedString(name), NULL);
static_cast<BoxedString*>(boxString(name)), NULL);
}
BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
......@@ -458,7 +459,7 @@ std::string getFullNameOfClass(BoxedClass* cls) {
BoxedString* module = static_cast<BoxedString*>(b);
return module->s + "." + cls->tp_name;
return (llvm::Twine(module->s) + "." + cls->tp_name).str();
}
std::string getFullTypeName(Box* o) {
......@@ -782,7 +783,7 @@ Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* re
// address.
obj_saved->addAttrGuard(offsetof(BoxedClass, tp_mro), (intptr_t)mro);
for (auto base : mro->elts) {
for (auto base : *mro) {
rewrite_args->out_success = false;
if (base == cls) {
// Small optimization: don't have to load the class again since it was given to us in
......@@ -801,7 +802,7 @@ Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* re
} else {
assert(cls->tp_mro);
assert(cls->tp_mro->cls == tuple_cls);
for (auto b : static_cast<BoxedTuple*>(cls->tp_mro)->elts) {
for (auto b : *static_cast<BoxedTuple*>(cls->tp_mro)) {
val = b->getattr(attr, NULL);
if (val)
return val;
......@@ -952,7 +953,7 @@ Box* descriptorClsSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedClass* cls
Box* boxChar(char c) {
char d[1];
d[0] = c;
return new BoxedString(std::string(d, 1));
return boxStringRef(llvm::StringRef(d, 1));
}
static Box* noneIfNull(Box* b) {
......@@ -967,12 +968,12 @@ static Box* boxStringOrNone(const char* s) {
if (s == NULL) {
return None;
} else {
return boxString(std::string(s));
return boxStrConstant(s);
}
}
static Box* boxStringFromCharPtr(const char* s) {
return boxString(std::string(s));
return boxStrConstant(s);
}
Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, const std::string& attr_name, Box* obj,
......@@ -1100,7 +1101,7 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, const
rewrite_args = NULL;
REWRITE_ABORTED("");
char* rtn = reinterpret_cast<char*>((char*)obj + member_desc->offset);
return boxString(std::string(rtn));
return boxStringRef(llvm::StringRef(rtn));
}
default:
......@@ -1164,7 +1165,7 @@ Box* getattrInternalEx(Box* obj, const std::string& attr, GetattrRewriteArgs* re
if (!cls_only) {
BoxedClass* cls = obj->cls;
if (obj->cls->tp_getattro && obj->cls->tp_getattro != PyObject_GenericGetAttr) {
Box* r = obj->cls->tp_getattro(obj, new BoxedString(attr));
Box* r = obj->cls->tp_getattro(obj, boxString(attr));
if (!r)
throwCAPIException();
return r;
......@@ -2205,7 +2206,7 @@ extern "C" void dump(void* p) {
if (cls->tp_mro && cls->tp_mro->cls == tuple_cls) {
bool first = true;
for (auto b : static_cast<BoxedTuple*>(cls->tp_mro)->elts) {
for (auto b : *static_cast<BoxedTuple*>(cls->tp_mro)) {
if (!first)
printf(" ->");
first = false;
......@@ -2216,11 +2217,11 @@ extern "C" void dump(void* p) {
}
if (isSubclass(b->cls, str_cls)) {
printf("String value: %s\n", static_cast<BoxedString*>(b)->s.c_str());
printf("String value: %s\n", static_cast<BoxedString*>(b)->data());
}
if (isSubclass(b->cls, tuple_cls)) {
printf("%ld elements\n", static_cast<BoxedTuple*>(b)->elts.size());
printf("%ld elements\n", static_cast<BoxedTuple*>(b)->size());
}
if (isSubclass(b->cls, int_cls)) {
......@@ -2760,7 +2761,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
rewrite_args->args->setAttr((varargs_idx - 3) * sizeof(Box*), emptyTupleConst);
}
Box* ovarargs = new BoxedTuple(BoxedTuple::GCVector(unused_positional.begin(), unused_positional.end()));
Box* ovarargs = BoxedTuple::create(unused_positional.size(), &unused_positional[0]);
getArg(varargs_idx, oarg1, oarg2, oarg3, oargs) = ovarargs;
} else if (unused_positional.size()) {
raiseExcHelper(TypeError, "%s() takes at most %d argument%s (%d given)", getFunctionName(f).c_str(),
......@@ -2851,7 +2852,7 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
Box*& v = okwargs->d[p.first];
if (v) {
raiseExcHelper(TypeError, "%s() got multiple values for keyword argument '%s'",
getFunctionName(f).c_str(), s->s.c_str());
getFunctionName(f).c_str(), s->data());
}
v = p.second;
}
......@@ -3840,14 +3841,15 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
RELEASE_ASSERT(arg1->cls == str_cls, "");
BoxedString* name = static_cast<BoxedString*>(arg1);
if (bases->elts.size() == 0) {
bases = new BoxedTuple({ object_cls });
if (bases->size() == 0) {
bases = BoxedTuple::create({ object_cls });
}
// Ported from CPython:
int nbases = bases->elts.size();
int nbases = bases->size();
BoxedClass* winner = metatype;
for (auto tmp : bases->elts) {
for (auto tmp : *bases) {
auto tmptype = tmp->cls;
if (tmptype == classobj_cls)
continue;
......@@ -3926,7 +3928,7 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
made->tp_alloc = PyType_GenericAlloc;
assert(!made->simple_destructor);
for (auto b : bases->elts) {
for (auto b : *bases) {
if (!isSubclass(b->cls, type_cls))
continue;
BoxedClass* b_cls = static_cast<BoxedClass*>(b);
......@@ -4228,7 +4230,7 @@ Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPa
Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) {
assert(vararg->cls == tuple_cls);
int n = vararg->elts.size();
int n = vararg->size();
int args_to_pass = n + 2; // 1 for obj, 1 for kwargs
Box** args = NULL;
......@@ -4371,7 +4373,7 @@ extern "C" Box* importStar(Box* _from_module, BoxedModule* to_module) {
Box* attr_value = from_module->getattr(casted_attr_name->s);
if (!attr_value)
raiseExcHelper(AttributeError, "'module' object has no attribute '%s'", casted_attr_name->s.c_str());
raiseExcHelper(AttributeError, "'module' object has no attribute '%s'", casted_attr_name->data());
to_module->setattr(casted_attr_name->s, attr_value, NULL);
}
......
......@@ -14,7 +14,7 @@
#include "runtime/set.h"
#include <sstream>
#include <llvm/Support/raw_ostream.h>
#include "gc/collector.h"
#include "runtime/objmodel.h"
......@@ -97,7 +97,8 @@ Box* setNew(Box* _cls, Box* container) {
}
static Box* _setRepr(BoxedSet* self, const char* type_name) {
std::ostringstream os("");
std::string O("");
llvm::raw_string_ostream os(O);
os << type_name << "([";
bool first = true;
......@@ -232,7 +233,7 @@ Box* setUpdate(BoxedSet* self, BoxedTuple* args) {
assert(self->cls == set_cls);
assert(args->cls == tuple_cls);
for (auto l : args->elts) {
for (auto l : *args) {
if (l->cls == set_cls) {
BoxedSet* s2 = static_cast<BoxedSet*>(l);
self->s.insert(s2->s.begin(), s2->s.end());
......
This diff is collapsed.
......@@ -51,7 +51,7 @@ public:
}
};
static const std::string class_str("__class__");
static const char* class_str = "__class__";
Box* superGetattribute(Box* _s, Box* _attr) {
RELEASE_ASSERT(_s->cls == super_cls, "");
......@@ -101,7 +101,7 @@ Box* superGetattribute(Box* _s, Box* _attr) {
continue;
res = PyDict_GetItem(dict, name);
#endif
res = tmp->getattr(attr->s);
res = tmp->getattr(std::string(attr->s));
if (res != NULL) {
// Pyston change:
......@@ -128,7 +128,7 @@ Box* superGetattribute(Box* _s, Box* _attr) {
}
}
Box* r = typeLookup(s->cls, attr->s, NULL);
Box* r = typeLookup(s->cls, std::string(attr->s), NULL);
// TODO implement this
RELEASE_ASSERT(r, "should call the equivalent of objectGetattr here");
return processDescriptor(r, s, s->cls);
......@@ -139,10 +139,11 @@ Box* superRepr(Box* _s) {
BoxedSuper* s = static_cast<BoxedSuper*>(_s);
if (s->obj_type) {
return boxString("<super: <class '" + std::string(s->type ? getNameOfClass(s->type) : "NULL") + "'>, <"
+ std::string(getNameOfClass(s->obj_type)) + " object>>");
return boxStringTwine(llvm::Twine("<super: <class '") + (s->type ? getNameOfClass(s->type) : "NULL") + "'>, <"
+ getNameOfClass(s->obj_type) + " object>>");
} else {
return boxString("<super: <class '" + std::string(s->type ? getNameOfClass(s->type) : "NULL") + "'>, <NULL>>");
return boxStringTwine(llvm::Twine("<super: <class '") + (s->type ? getNameOfClass(s->type) : "NULL")
+ "'>, <NULL>>");
}
}
......
......@@ -98,7 +98,7 @@ Box* BoxedTraceback::getLines(Box* b) {
BoxedList* lines = new BoxedList();
lines->ensure(tb->lines.size());
for (auto line : tb->lines) {
auto l = new BoxedTuple({ boxString(line->file), boxString(line->func), boxInt(line->line) });
auto l = BoxedTuple::create({ boxString(line->file), boxString(line->func), boxInt(line->line) });
listAppendInternal(lines, l);
}
tb->py_lines = lines;
......
......@@ -15,7 +15,8 @@
#include "runtime/tuple.h"
#include <algorithm>
#include <sstream>
#include "llvm/Support/raw_ostream.h"
#include "core/ast.h"
#include "core/common.h"
......@@ -29,13 +30,12 @@
namespace pyston {
extern "C" Box* createTuple(int64_t nelts, Box** elts) {
BoxedTuple::GCVector velts(elts, elts + nelts);
return new BoxedTuple(std::move(velts));
return BoxedTuple::create(nelts, elts);
}
Box* _tupleSlice(BoxedTuple* self, i64 start, i64 stop, i64 step, i64 length) {
i64 size = self->elts.size();
i64 size = self->size();
assert(step != 0);
if (step > 0) {
assert(0 <= start);
......@@ -45,15 +45,15 @@ Box* _tupleSlice(BoxedTuple* self, i64 start, i64 stop, i64 step, i64 length) {
assert(-1 <= stop);
}
// FIXME: No need to initialize with 0.
BoxedTuple::GCVector velts(length, 0);
// FIXME: No need to initialize with NULL, since we're going to fill it in
auto rtn = BoxedTuple::create(length);
if (length > 0)
copySlice(&velts[0], &self->elts[0], start, step, length);
return new BoxedTuple(std::move(velts));
copySlice(&rtn->elts[0], &self->elts[0], start, step, length);
return rtn;
}
Box* tupleGetitemUnboxed(BoxedTuple* self, i64 n) {
i64 size = self->elts.size();
i64 size = self->size();
if (n < 0)
n = size + n;
......@@ -89,7 +89,7 @@ Box* tupleGetitemSlice(BoxedTuple* self, BoxedSlice* slice) {
assert(slice->cls == slice_cls);
i64 start, stop, step, length;
parseSlice(slice, self->elts.size(), &start, &stop, &step, &length);
parseSlice(slice, self->size(), &start, &stop, &step, &length);
return _tupleSlice(self, start, stop, step, length);
}
......@@ -97,7 +97,7 @@ extern "C" PyObject* PyTuple_GetSlice(PyObject* p, Py_ssize_t low, Py_ssize_t hi
RELEASE_ASSERT(isSubclass(p->cls, tuple_cls), "");
BoxedTuple* t = static_cast<BoxedTuple*>(p);
Py_ssize_t n = t->elts.size();
Py_ssize_t n = t->size();
if (low < 0)
low = 0;
if (high > n)
......@@ -108,7 +108,39 @@ extern "C" PyObject* PyTuple_GetSlice(PyObject* p, Py_ssize_t low, Py_ssize_t hi
if (low == 0 && high == n)
return p;
return new BoxedTuple(BoxedTuple::GCVector(&t->elts[low], &t->elts[high]));
return BoxedTuple::create(high - low, &t->elts[low]);
}
extern "C" int _PyTuple_Resize(PyObject** pv, Py_ssize_t newsize) noexcept {
// This is only allowed to be called when there is only one user of the tuple (ie a refcount of 1 in CPython)
assert(pv);
return BoxedTuple::Resize((BoxedTuple**)pv, newsize);
}
int BoxedTuple::Resize(BoxedTuple** pv, size_t newsize) noexcept {
assert(isSubclass((*pv)->cls, tuple_cls));
BoxedTuple* t = static_cast<BoxedTuple*>(*pv);
if (newsize == t->size())
return 0;
if (newsize < t->size()) {
// XXX resize the box (by reallocating) smaller if it makes sense
t->nelts = newsize;
return 0;
}
BoxedTuple* resized;
if (t->cls == tuple_cls)
resized = new (newsize) BoxedTuple(newsize); // we want an uninitialized tuple, but this will memset it with 0.
else
resized = new (t->cls, newsize) BoxedTuple(newsize); // we need an uninitialized string, but this will memset
memmove(resized->elts, t->elts, t->size());
*pv = resized;
return 0;
}
Box* tupleGetitem(BoxedTuple* self, Box* slice) {
......@@ -128,10 +160,11 @@ Box* tupleAdd(BoxedTuple* self, Box* rhs) {
}
BoxedTuple* _rhs = static_cast<BoxedTuple*>(rhs);
BoxedTuple::GCVector velts;
velts.insert(velts.end(), self->elts.begin(), self->elts.end());
velts.insert(velts.end(), _rhs->elts.begin(), _rhs->elts.end());
return new BoxedTuple(std::move(velts));
BoxedTuple* rtn = BoxedTuple::create(self->size() + _rhs->size());
memmove(&rtn->elts[0], &self->elts[0], self->size() * sizeof(Box*));
memmove(&rtn->elts[self->size()], &_rhs->elts[0], _rhs->size() * sizeof(Box*));
return rtn;
}
Box* tupleMul(BoxedTuple* self, Box* rhs) {
......@@ -140,7 +173,7 @@ Box* tupleMul(BoxedTuple* self, Box* rhs) {
}
int n = static_cast<BoxedInt*>(rhs)->n;
int s = self->elts.size();
int s = self->size();
if (n < 0)
n = 0;
......@@ -148,33 +181,34 @@ Box* tupleMul(BoxedTuple* self, Box* rhs) {
if (s == 0 || n == 1) {
return self;
} else {
BoxedTuple::GCVector velts(n * s);
auto iter = velts.begin();
BoxedTuple* rtn = BoxedTuple::create(n * s);
int rtn_i = 0;
for (int i = 0; i < n; ++i) {
std::copy(self->elts.begin(), self->elts.end(), iter);
iter += s;
memmove(&rtn->elts[rtn_i], &self->elts[0], sizeof(Box*) * s);
rtn_i += s;
}
return new BoxedTuple(std::move(velts));
return rtn;
}
}
Box* tupleLen(BoxedTuple* t) {
assert(isSubclass(t->cls, tuple_cls));
return boxInt(t->elts.size());
return boxInt(t->size());
}
extern "C" Py_ssize_t PyTuple_Size(PyObject* op) noexcept {
RELEASE_ASSERT(PyTuple_Check(op), "");
return static_cast<BoxedTuple*>(op)->elts.size();
return static_cast<BoxedTuple*>(op)->size();
}
Box* tupleRepr(BoxedTuple* t) {
assert(isSubclass(t->cls, tuple_cls));
std::ostringstream os("");
std::string O("");
llvm::raw_string_ostream os(O);
os << "(";
int n = t->elts.size();
int n = t->size();
for (int i = 0; i < n; i++) {
if (i)
os << ", ";
......@@ -190,8 +224,8 @@ Box* tupleRepr(BoxedTuple* t) {
}
Box* _tupleCmp(BoxedTuple* lhs, BoxedTuple* rhs, AST_TYPE::AST_TYPE op_type) {
int lsz = lhs->elts.size();
int rsz = rhs->elts.size();
int lsz = lhs->size();
int rsz = rhs->size();
bool is_order
= (op_type == AST_TYPE::Lt || op_type == AST_TYPE::LtE || op_type == AST_TYPE::Gt || op_type == AST_TYPE::GtE);
......@@ -274,11 +308,11 @@ Box* tupleNe(BoxedTuple* self, Box* rhs) {
Box* tupleNonzero(BoxedTuple* self) {
RELEASE_ASSERT(isSubclass(self->cls, tuple_cls), "");
return boxBool(self->elts.size() != 0);
return boxBool(self->size() != 0);
}
Box* tupleContains(BoxedTuple* self, Box* elt) {
int size = self->elts.size();
int size = self->size();
for (int i = 0; i < size; i++) {
Box* e = self->elts[i];
Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL);
......@@ -290,7 +324,7 @@ Box* tupleContains(BoxedTuple* self, Box* elt) {
}
Box* tupleIndex(BoxedTuple* self, Box* elt) {
int size = self->elts.size();
int size = self->size();
for (int i = 0; i < size; i++) {
Box* e = self->elts[i];
Box* cmp = compareInternal(e, elt, AST_TYPE::Eq, NULL);
......@@ -306,7 +340,7 @@ Box* tupleHash(BoxedTuple* self) {
assert(isSubclass(self->cls, tuple_cls));
int64_t rtn = 3527539;
for (Box* e : self->elts) {
for (auto e : *self) {
BoxedInt* h = hash(e);
assert(isSubclass(h->cls, int_cls));
rtn ^= h->n + 0x9e3779b9 + (rtn << 6) + (rtn >> 2);
......@@ -324,16 +358,14 @@ extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) {
raiseExcHelper(TypeError, "tuple.__new__(%s): %s is not a subtype of tuple", getNameOfClass(cls),
getNameOfClass(cls));
int args_sz = args->elts.size();
int args_sz = args->size();
int kwargs_sz = kwargs->d.size();
if (args_sz + kwargs_sz > 1)
raiseExcHelper(TypeError, "tuple() takes at most 1 argument (%d given)", args_sz + kwargs_sz);
BoxedTuple::GCVector velts;
Box* elements;
if (args_sz || kwargs_sz) {
Box* elements;
// if initializing from iterable argument, check common case positional args first
if (args_sz) {
elements = args->elts[0];
......@@ -345,21 +377,24 @@ extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) {
if (kw->s == "sequence")
elements = seq.second;
else
raiseExcHelper(TypeError, "'%s' is an invalid keyword argument for this function", kw->s.c_str());
raiseExcHelper(TypeError, "'%s' is an invalid keyword argument for this function", kw->data());
}
std::vector<Box*, StlCompatAllocator<Box*>> elts;
for (auto e : elements->pyElements())
velts.push_back(e);
}
elts.push_back(e);
return new (cls) BoxedTuple(std::move(velts));
return BoxedTuple::create(elts.size(), &elts[0], cls);
} else {
return BoxedTuple::create(0, cls);
}
}
extern "C" int PyTuple_SetItem(PyObject* op, Py_ssize_t i, PyObject* newitem) noexcept {
RELEASE_ASSERT(PyTuple_Check(op), "");
BoxedTuple* t = static_cast<BoxedTuple*>(op);
RELEASE_ASSERT(i >= 0 && i < t->elts.size(), "");
RELEASE_ASSERT(i >= 0 && i < t->size(), "");
t->elts[i] = newitem;
return 0;
}
......@@ -386,7 +421,7 @@ extern "C" PyObject* PyTuple_Pack(Py_ssize_t n, ...) noexcept {
extern "C" PyObject* PyTuple_New(Py_ssize_t size) noexcept {
RELEASE_ASSERT(size >= 0, "");
return new BoxedTuple(BoxedTuple::GCVector(size, NULL));
return BoxedTuple::create(size);
}
......
This diff is collapsed.
......@@ -16,6 +16,7 @@
#define PYSTON_RUNTIME_TYPES_H
#include <llvm/ADT/StringMap.h>
#include <llvm/ADT/Twine.h>
#include <ucontext.h>
#include "Python.h"
......@@ -110,6 +111,9 @@ extern "C" Box* boxUnboundInstanceMethod(Box* func);
extern "C" Box* boxStringPtr(const std::string* s);
Box* boxString(const std::string& s);
Box* boxString(std::string&& s);
Box* boxStringRef(llvm::StringRef s);
Box* boxStringTwine(const llvm::Twine& s);
extern "C" BoxedString* boxStrConstant(const char* chars);
extern "C" BoxedString* boxStrConstantSize(const char* chars, size_t n);
extern "C" Box* decodeUTF8StringPtr(const std::string* s);
......@@ -371,14 +375,34 @@ public:
class BoxedString : public Box {
public:
// const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s;
std::string s;
llvm::StringRef s;
char* data() { return const_cast<char*>(s.data()); }
size_t size() { return s.size(); }
void* operator new(size_t size, size_t ssize) __attribute__((visibility("default"))) {
Box* rtn = static_cast<Box*>(gc_alloc(str_cls->tp_basicsize + ssize + 1, gc::GCKind::PYTHON));
rtn->cls = str_cls;
return rtn;
}
void* operator new(size_t size, BoxedClass* cls, size_t ssize) __attribute__((visibility("default"))) {
Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, ssize + 1));
rtn->cls = cls;
return rtn;
}
// these should be private, but strNew needs them
BoxedString(const char* s, size_t n) __attribute__((visibility("default")));
BoxedString(std::string&& s) __attribute__((visibility("default")));
BoxedString(const std::string& s) __attribute__((visibility("default")));
explicit BoxedString(size_t n, char c) __attribute__((visibility("default")));
explicit BoxedString(llvm::StringRef s) __attribute__((visibility("default")));
explicit BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) __attribute__((visibility("default")));
private:
// used only in ctors to give our llvm::StringRef the proper pointer
char* storage() { return (char*)this + cls->tp_basicsize; }
DEFAULT_CLASS_SIMPLE(str_cls);
void* operator new(size_t size) = delete;
};
class BoxedUnicode : public Box {
......@@ -464,14 +488,65 @@ public:
class BoxedTuple : public Box {
public:
typedef std::vector<Box*, StlCompatAllocator<Box*>> GCVector;
GCVector elts;
BoxedTuple(GCVector& elts) __attribute__((visibility("default"))) : elts(elts) {}
BoxedTuple(GCVector&& elts) __attribute__((visibility("default"))) : elts(std::move(elts)) {}
Box** elts;
void* operator new(size_t size, size_t nelts) __attribute__((visibility("default"))) {
Box* rtn = static_cast<Box*>(gc_alloc(_PyObject_VAR_SIZE(tuple_cls, nelts + 1), gc::GCKind::PYTHON));
rtn->cls = tuple_cls;
return rtn;
}
void* operator new(size_t size, BoxedClass* cls, size_t nelts) __attribute__((visibility("default"))) {
Box* rtn = static_cast<Box*>(cls->tp_alloc(cls, nelts));
rtn->cls = cls;
return rtn;
}
static BoxedTuple* create(int64_t size) { return new (size) BoxedTuple(size); }
static BoxedTuple* create(int64_t nelts, Box** elts) {
BoxedTuple* rtn = new (nelts) BoxedTuple(nelts);
memmove(&rtn->elts[0], elts, sizeof(Box*) * nelts);
return rtn;
}
static BoxedTuple* create(std::initializer_list<Box*> members) { return new (members.size()) BoxedTuple(members); }
static BoxedTuple* create(int64_t size, BoxedClass* cls) { return new (cls, size) BoxedTuple(size); }
static BoxedTuple* create(int64_t nelts, Box** elts, BoxedClass* cls) {
BoxedTuple* rtn = new (cls, nelts) BoxedTuple(nelts);
memmove(&rtn->elts[0], elts, sizeof(Box*) * nelts);
return rtn;
}
static BoxedTuple* create(std::initializer_list<Box*> members, BoxedClass* cls) {
return new (cls, members.size()) BoxedTuple(members);
}
static int Resize(BoxedTuple** pt, size_t newsize) noexcept;
Box** begin() const { return &elts[0]; }
Box** end() const { return &elts[nelts]; }
size_t size() const { return nelts; }
DEFAULT_CLASS_SIMPLE(tuple_cls);
private:
size_t nelts;
BoxedTuple(size_t size) : elts(reinterpret_cast<Box**>((char*)this + this->cls->tp_basicsize)), nelts(size) {
memset(elts, 0, sizeof(Box*) * size);
}
BoxedTuple(std::initializer_list<Box*>& members)
: elts(reinterpret_cast<Box**>((char*)this + this->cls->tp_basicsize)), nelts(members.size()) {
// by the time we make it here elts[] is big enough to contain members
Box** p = &elts[0];
for (auto b : members) {
*p++ = b;
}
}
};
extern "C" BoxedTuple* EmptyTuple;
extern "C" BoxedString* EmptyString;
struct PyHasher {
size_t operator()(Box*) const;
......@@ -735,4 +810,5 @@ extern Box* dict_descr;
Box* codeForFunction(BoxedFunction*);
}
#endif
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