Commit e871f4ef authored by Chris Toshok's avatar Chris Toshok

Merge pull request #411 from toshok/tuple-colocate3

colocate string and tuple data
parents 3486e84c b44b06f9
......@@ -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());
......
......@@ -46,16 +46,29 @@ extern "C" PyObject* string_splitlines(PyStringObject* self, PyObject* args) noe
namespace pyston {
BoxedString::BoxedString(const char* s, size_t n) : s(s, n) {
gc::registerGCManagedBytes(this->s.size());
BoxedString::BoxedString(const char* s, size_t n) : s(storage(), n) {
if (s) {
memmove(data(), s, n);
data()[n] = 0;
} else {
memset(data(), 0, n + 1);
}
}
BoxedString::BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) : s(storage(), lhs.size() + rhs.size()) {
memmove(data(), lhs.data(), lhs.size());
memmove(data() + lhs.size(), rhs.data(), rhs.size());
data()[lhs.size() + rhs.size()] = 0;
}
BoxedString::BoxedString(std::string&& s) : s(std::move(s)) {
gc::registerGCManagedBytes(this->s.size());
BoxedString::BoxedString(llvm::StringRef s) : s(storage(), s.size()) {
memmove(data(), s.data(), s.size());
data()[s.size()] = 0;
}
BoxedString::BoxedString(const std::string& s) : s(s) {
gc::registerGCManagedBytes(this->s.size());
BoxedString::BoxedString(size_t n, char c) : s(storage(), n) {
memset(data(), c, n);
data()[n] = 0;
}
extern "C" char PyString_GetItem(PyObject* op, ssize_t n) noexcept {
......@@ -318,11 +331,11 @@ extern "C" Box* strAdd(BoxedString* lhs, Box* _rhs) {
}
BoxedString* rhs = static_cast<BoxedString*>(_rhs);
return new BoxedString(lhs->s + rhs->s);
return new (lhs->size() + rhs->size()) BoxedString(lhs->s, rhs->s);
}
extern "C" PyObject* PyString_InternFromString(const char* s) noexcept {
return new BoxedString(s);
return boxString(s);
}
extern "C" void PyString_InternInPlace(PyObject**) noexcept {
......@@ -1086,12 +1099,12 @@ extern "C" Box* strMul(BoxedString* lhs, Box* rhs) {
return NotImplemented;
// TODO: use createUninitializedString and getWriteableStringContents
int sz = lhs->s.size();
int sz = lhs->size();
std::string buf(sz * n, '\0');
for (int i = 0; i < n; i++) {
memcpy(&buf[sz * i], lhs->s.c_str(), sz);
memcpy(&buf[sz * i], lhs->data(), sz);
}
return new BoxedString(std::move(buf));
return boxString(buf);
}
extern "C" Box* strLt(BoxedString* lhs, Box* rhs) {
......@@ -1160,8 +1173,8 @@ extern "C" Box* strNe(BoxedString* lhs, Box* rhs) {
static Box* pad(BoxedString* self, Box* width, Box* fillchar, int justType) {
assert(width->cls == int_cls);
assert(isSubclass(fillchar->cls, str_cls));
assert(static_cast<BoxedString*>(fillchar)->s.size() == 1);
int64_t curWidth = self->s.size();
assert(static_cast<BoxedString*>(fillchar)->size() == 1);
int64_t curWidth = self->size();
int64_t targetWidth = static_cast<BoxedInt*>(width)->n;
if (curWidth >= targetWidth) {
......@@ -1169,7 +1182,7 @@ static Box* pad(BoxedString* self, Box* width, Box* fillchar, int justType) {
return self;
} else {
// If self isn't a string but a subclass of str, then make a new string to return
return new BoxedString(self->s);
return boxString(self->s);
}
}
......@@ -1195,9 +1208,7 @@ static Box* pad(BoxedString* self, Box* width, Box* fillchar, int justType) {
}
// TODO this is probably slow
std::string res = std::string(padLeft, c) + self->s + std::string(padRight, c);
return new BoxedString(std::move(res));
return boxStringTwine(llvm::Twine(std::string(padLeft, c)) + self->s + std::string(padRight, c));
}
extern "C" Box* strLjust(BoxedString* lhs, Box* width, Box* fillchar) {
return pad(lhs, width, fillchar, JUST_LEFT);
......@@ -1212,7 +1223,7 @@ extern "C" Box* strCenter(BoxedString* lhs, Box* width, Box* fillchar) {
extern "C" Box* strLen(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
return boxInt(self->s.size());
return boxInt(self->size());
}
extern "C" Box* strStr(BoxedString* self) {
......@@ -1221,7 +1232,7 @@ extern "C" Box* strStr(BoxedString* self) {
if (self->cls == str_cls)
return self;
return new BoxedString(self->s);
return boxString(self->s);
}
static bool _needs_escaping[256]
......@@ -1249,7 +1260,7 @@ extern "C" PyObject* PyString_Repr(PyObject* obj, int smartquotes) noexcept {
std::ostringstream os("");
const std::string& s = self->s;
llvm::StringRef s(self->s);
char quote = '\'';
if (smartquotes && s.find('\'', 0) != std::string::npos && s.find('\"', 0) == std::string::npos) {
quote = '\"';
......@@ -1491,14 +1502,14 @@ extern "C" size_t unicodeHashUnboxed(PyUnicodeObject* self) {
extern "C" Box* strHash(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
StringHash<std::string> H;
return boxInt(H(self->s));
StringHash<char> H;
return boxInt(H(self->data(), self->size()));
}
extern "C" Box* strNonzero(BoxedString* self) {
ASSERT(isSubclass(self->cls, str_cls), "%s", self->cls->tp_name);
return boxBool(self->s.size() != 0);
return boxBool(self->size() != 0);
}
extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
......@@ -1510,7 +1521,9 @@ extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
if (cls == str_cls)
return rtn;
return new (cls) BoxedString(static_cast<BoxedString*>(rtn)->s);
BoxedString* _rtn = static_cast<BoxedString*>(rtn);
return new (cls, _rtn->size()) BoxedString(_rtn->s);
}
extern "C" Box* basestringNew(BoxedClass* cls, Box* args, Box* kwargs) {
......@@ -1520,7 +1533,7 @@ extern "C" Box* basestringNew(BoxedClass* cls, Box* args, Box* kwargs) {
Box* _strSlice(BoxedString* self, i64 start, i64 stop, i64 step, i64 length) {
assert(isSubclass(self->cls, str_cls));
const std::string& s = self->s;
llvm::StringRef s = self->s;
assert(step != 0);
if (step > 0) {
......@@ -1531,18 +1544,18 @@ Box* _strSlice(BoxedString* self, i64 start, i64 stop, i64 step, i64 length) {
assert(-1 <= stop);
}
std::string chars;
if (length > 0) {
chars.resize(length);
copySlice(&chars[0], &s[0], start, step, length);
}
return boxString(std::move(chars));
if (length == 0)
return EmptyString;
BoxedString* bs = new (length) BoxedString(nullptr, length);
copySlice(bs->data(), s.data(), start, step, length);
return bs;
}
Box* strIsAlpha(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1557,7 +1570,7 @@ Box* strIsAlpha(BoxedString* self) {
Box* strIsDigit(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1572,7 +1585,7 @@ Box* strIsDigit(BoxedString* self) {
Box* strIsAlnum(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1587,7 +1600,7 @@ Box* strIsAlnum(BoxedString* self) {
Box* strIsLower(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
bool lowered = false;
if (str.empty())
......@@ -1609,7 +1622,7 @@ Box* strIsLower(BoxedString* self) {
Box* strIsUpper(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1628,7 +1641,7 @@ Box* strIsUpper(BoxedString* self) {
Box* strIsSpace(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1643,7 +1656,7 @@ Box* strIsSpace(BoxedString* self) {
Box* strIsTitle(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
const std::string& str(self->s);
llvm::StringRef str(self->s);
if (str.empty())
return False;
......@@ -1678,9 +1691,49 @@ Box* strIsTitle(BoxedString* self) {
Box* strJoin(BoxedString* self, Box* rhs) {
assert(isSubclass(self->cls, str_cls));
int i = 0;
if (rhs->cls == str_cls) {
BoxedString* srhs = static_cast<BoxedString*>(rhs);
size_t rtn_len = self->size() * (srhs->size() - 1) + srhs->size();
BoxedString* rtn = new (rtn_len) BoxedString(nullptr, rtn_len);
char* p = rtn->data();
for (auto c : srhs->s) {
if (i > 0) {
memmove(p, self->data(), self->size());
p += self->size();
}
*p++ = c;
++i;
}
return rtn;
} else if (rhs->cls == list_cls) {
BoxedList* lrhs = static_cast<BoxedList*>(rhs);
size_t rtn_len = self->size() * (lrhs->size - 1);
for (int l = 0; l < lrhs->size; l++) {
// if we hit anything but a string (unicode objects can be here), bail out since we're
// going to pay the cost of converting the unicode to string objects anyway.
if (lrhs->elts->elts[l]->cls != str_cls)
goto fallback;
rtn_len += static_cast<BoxedString*>(lrhs->elts->elts[l])->size();
}
BoxedString* rtn = new (rtn_len) BoxedString(nullptr, rtn_len);
char* p = rtn->data();
for (i = 0; i < lrhs->size; i++) {
if (i > 0) {
memmove(p, self->data(), self->size());
p += self->size();
}
auto lrhs_el = static_cast<BoxedString*>(lrhs->elts->elts[i]);
memmove(p, lrhs_el->data(), lrhs_el->size());
p += lrhs_el->size();
}
return rtn;
}
fallback:
std::string output_str;
llvm::raw_string_ostream os(output_str);
int i = 0;
for (Box* e : rhs->pyElements()) {
if (i > 0)
os << self->s;
......@@ -1731,10 +1784,10 @@ Box* strReplace(Box* _self, Box* _old, Box* _new, Box** _args) {
start_pos = s.find(old->s, start_pos);
if (start_pos == std::string::npos)
break;
s.replace(start_pos, old->s.length(), new_->s);
start_pos += new_->s.length(); // Handles case where 'to' is a substring of 'from'
s.replace(start_pos, old->size(), new_->s);
start_pos += new_->size(); // Handles case where 'to' is a substring of 'from'
}
return new BoxedString(std::move(s));
return boxString(s);
}
Box* strPartition(BoxedString* self, BoxedString* sep) {
......@@ -1743,13 +1796,12 @@ Box* strPartition(BoxedString* self, BoxedString* sep) {
size_t found_idx = self->s.find(sep->s);
if (found_idx == std::string::npos)
return new BoxedTuple({ self, boxStrConstant(""), boxStrConstant("") });
return BoxedTuple::create({ self, EmptyString, EmptyString });
return new BoxedTuple({ boxStrConstantSize(self->s.c_str(), found_idx),
boxStrConstantSize(self->s.c_str() + found_idx, sep->s.size()),
boxStrConstantSize(self->s.c_str() + found_idx + sep->s.size(),
self->s.size() - found_idx - sep->s.size()) });
return BoxedTuple::create(
{ boxStrConstantSize(self->data(), found_idx), boxStrConstantSize(self->data() + found_idx, sep->size()),
boxStrConstantSize(self->data() + found_idx + sep->size(), self->size() - found_idx - sep->size()) });
}
Box* strRpartition(BoxedString* self, BoxedString* sep) {
......@@ -1758,13 +1810,11 @@ Box* strRpartition(BoxedString* self, BoxedString* sep) {
size_t found_idx = self->s.rfind(sep->s);
if (found_idx == std::string::npos)
return new BoxedTuple({ boxStrConstant(""), boxStrConstant(""), self });
return BoxedTuple::create({ EmptyString, EmptyString, self });
return new BoxedTuple({ boxStrConstantSize(self->s.c_str(), found_idx),
boxStrConstantSize(self->s.c_str() + found_idx, sep->s.size()),
boxStrConstantSize(self->s.c_str() + found_idx + sep->s.size(),
self->s.size() - found_idx - sep->s.size()) });
return BoxedTuple::create(
{ boxStrConstantSize(self->data(), found_idx), boxStrConstantSize(self->data() + found_idx, sep->size()),
boxStrConstantSize(self->data() + found_idx + sep->size(), self->size() - found_idx - sep->size()) });
}
extern "C" PyObject* _do_string_format(PyObject* self, PyObject* args, PyObject* kwargs);
......@@ -1781,11 +1831,13 @@ Box* strFormat(BoxedString* self, BoxedTuple* args, BoxedDict* kwargs) {
Box* strStrip(BoxedString* self, Box* chars) {
assert(isSubclass(self->cls, str_cls));
auto str = self->s;
if (isSubclass(chars->cls, str_cls)) {
return new BoxedString(llvm::StringRef(self->s).trim(static_cast<BoxedString*>(chars)->s));
auto chars_str = static_cast<BoxedString*>(chars)->s;
return boxStringRef(str.trim(chars_str));
} else if (chars->cls == none_cls) {
return new BoxedString(llvm::StringRef(self->s).trim(" \t\n\r\f\v"));
return boxStringRef(str.trim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "strip arg must be None, str or unicode");
}
......@@ -1793,11 +1845,13 @@ Box* strStrip(BoxedString* self, Box* chars) {
Box* strLStrip(BoxedString* self, Box* chars) {
assert(isSubclass(self->cls, str_cls));
auto str = self->s;
if (isSubclass(chars->cls, str_cls)) {
return new BoxedString(llvm::StringRef(self->s).ltrim(static_cast<BoxedString*>(chars)->s));
auto chars_str = static_cast<BoxedString*>(chars)->s;
return boxStringRef(str.ltrim(chars_str));
} else if (chars->cls == none_cls) {
return new BoxedString(llvm::StringRef(self->s).ltrim(" \t\n\r\f\v"));
return boxStringRef(str.ltrim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "lstrip arg must be None, str or unicode");
}
......@@ -1805,11 +1859,13 @@ Box* strLStrip(BoxedString* self, Box* chars) {
Box* strRStrip(BoxedString* self, Box* chars) {
assert(isSubclass(self->cls, str_cls));
auto str = self->s;
if (isSubclass(chars->cls, str_cls)) {
return new BoxedString(llvm::StringRef(self->s).rtrim(static_cast<BoxedString*>(chars)->s));
auto chars_str = static_cast<BoxedString*>(chars)->s;
return boxStringRef(str.rtrim(chars_str));
} else if (chars->cls == none_cls) {
return new BoxedString(llvm::StringRef(self->s).rtrim(" \t\n\r\f\v"));
return boxStringRef(str.rtrim(" \t\n\r\f\v"));
} else {
raiseExcHelper(TypeError, "rstrip arg must be None, str or unicode");
}
......@@ -1871,7 +1927,7 @@ Box* strTranslate(BoxedString* self, BoxedString* table, BoxedString* delete_cha
if (have_table) {
if (!isSubclass(table->cls, str_cls))
raiseExcHelper(TypeError, "expected a character buffer object");
if (table->s.size() != 256)
if (table->size() != 256)
raiseExcHelper(ValueError, "translation table must be 256 characters long");
}
......@@ -1880,30 +1936,37 @@ Box* strTranslate(BoxedString* self, BoxedString* table, BoxedString* delete_cha
if (!delete_set.count(c))
str.append(1, have_table ? table->s[(unsigned char)c] : c);
}
return boxString(std::move(str));
return boxString(str);
}
Box* strLower(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
return boxString(llvm::StringRef(self->s).lower());
BoxedString* rtn = static_cast<BoxedString*>(boxString(self->s));
for (int i = 0; i < rtn->size(); i++)
rtn->data()[i] = std::tolower(rtn->data()[i]);
return rtn;
}
Box* strUpper(BoxedString* self) {
assert(isSubclass(self->cls, str_cls));
return boxString(llvm::StringRef(self->s).upper());
BoxedString* rtn = static_cast<BoxedString*>(boxString(self->s));
for (int i = 0; i < rtn->size(); i++)
rtn->data()[i] = std::toupper(rtn->data()[i]);
return rtn;
}
Box* strSwapcase(BoxedString* self) {
std::string s(self->s);
for (auto& i : s) {
if (std::islower(i))
i = std::toupper(i);
else if (std::isupper(i))
i = std::tolower(i);
assert(isSubclass(self->cls, str_cls));
BoxedString* rtn = static_cast<BoxedString*>(boxString(self->s));
for (int i = 0; i < rtn->size(); i++) {
char c = rtn->data()[i];
if (std::islower(c))
rtn->data()[i] = std::toupper(c);
else if (std::isupper(c))
rtn->data()[i] = std::tolower(c);
}
return boxString(s);
return rtn;
}
Box* strContains(BoxedString* self, Box* elt) {
......@@ -1927,6 +1990,16 @@ Box* strContains(BoxedString* self, Box* elt) {
return True;
}
// compares (a+a_pos, len) with (str)
// if len == npos, compare to the end of a
static int compareStringRefs(llvm::StringRef a, size_t a_pos, size_t len, llvm::StringRef str) {
if (len == llvm::StringRef::npos)
len = a.size() - a_pos;
if (a_pos + len > a.size())
throw std::out_of_range("pos+len out of range");
return llvm::StringRef(a.data() + a_pos, len).compare(str);
}
Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Box* end = _args[0];
......@@ -1948,7 +2021,7 @@ Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
}
if (isSubclass(elt->cls, tuple_cls)) {
for (auto e : static_cast<BoxedTuple*>(elt)->elts) {
for (auto e : *static_cast<BoxedTuple*>(elt)) {
auto b = strStartswith(self, e, start, _args);
assert(b->cls == bool_cls);
if (b == True)
......@@ -1970,7 +2043,7 @@ Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
BoxedString* sub = static_cast<BoxedString*>(elt);
Py_ssize_t n = self->s.size();
Py_ssize_t n = self->size();
iend = std::min(iend, n);
if (iend < 0)
iend += n;
......@@ -1985,9 +2058,9 @@ Box* strStartswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Py_ssize_t compare_len = iend - istart;
if (compare_len < 0)
return False;
if (sub->s.size() > compare_len)
if (sub->size() > compare_len)
return False;
return boxBool(self->s.compare(istart, sub->s.size(), sub->s) == 0);
return boxBool(compareStringRefs(self->s, istart, sub->size(), sub->s) == 0);
}
Box* strEndswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
......@@ -2019,7 +2092,7 @@ Box* strEndswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
}
if (isSubclass(elt->cls, tuple_cls)) {
for (auto e : static_cast<BoxedTuple*>(elt)->elts) {
for (auto e : *static_cast<BoxedTuple*>(elt)) {
auto b = strEndswith(self, e, start, _args);
assert(b->cls == bool_cls);
if (b == True)
......@@ -2033,7 +2106,7 @@ Box* strEndswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
BoxedString* sub = static_cast<BoxedString*>(elt);
Py_ssize_t n = self->s.size();
Py_ssize_t n = self->size();
iend = std::min(iend, n);
if (iend < 0)
iend += n;
......@@ -2048,11 +2121,11 @@ Box* strEndswith(BoxedString* self, Box* elt, Box* start, Box** _args) {
Py_ssize_t compare_len = iend - istart;
if (compare_len < 0)
return False;
if (sub->s.size() > compare_len)
if (sub->size() > compare_len)
return False;
// XXX: this line is the only difference between startswith and endswith:
istart += compare_len - sub->s.size();
return boxBool(self->s.compare(istart, sub->s.size(), sub->s) == 0);
istart += compare_len - sub->size();
return boxBool(compareStringRefs(self->s, istart, sub->size(), sub->s) == 0);
}
Box* strDecode(BoxedString* self, Box* encoding, Box* error) {
......@@ -2075,7 +2148,7 @@ Box* strDecode(BoxedString* self, Box* encoding, Box* error) {
raiseExcHelper(TypeError, "decode() argument 2 must be string, not '%s'", getTypeName(error_str));
Box* result
= PyCodec_Decode(self, encoding_str ? encoding_str->s.c_str() : NULL, error_str ? error_str->s.c_str() : NULL);
= PyCodec_Decode(self, encoding_str ? encoding_str->data() : NULL, error_str ? error_str->data() : NULL);
checkAndThrowCAPIException();
return result;
}
......@@ -2099,8 +2172,8 @@ Box* strEncode(BoxedString* self, Box* encoding, Box* error) {
if (error_str && !isSubclass(error_str->cls, str_cls))
raiseExcHelper(TypeError, "encode() argument 2 must be string, not '%s'", getTypeName(error_str));
Box* result = PyCodec_Encode(self, encoding_str ? encoding_str->s.c_str() : PyUnicode_GetDefaultEncoding(),
error_str ? error_str->s.c_str() : NULL);
Box* result = PyCodec_Encode(self, encoding_str ? encoding_str->data() : PyUnicode_GetDefaultEncoding(),
error_str ? error_str->data() : NULL);
checkAndThrowCAPIException();
return result;
}
......@@ -2111,7 +2184,7 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
if (isSubclass(slice->cls, int_cls)) {
BoxedInt* islice = static_cast<BoxedInt*>(slice);
int64_t n = islice->n;
int size = self->s.size();
int size = self->size();
if (n < 0)
n = size + n;
......@@ -2120,12 +2193,12 @@ extern "C" Box* strGetitem(BoxedString* self, Box* slice) {
}
char c = self->s[n];
return new BoxedString(std::string(1, c));
return boxStringRef(llvm::StringRef(&c, 1));
} else if (slice->cls == slice_cls) {
BoxedSlice* sslice = static_cast<BoxedSlice*>(slice);
i64 start, stop, step, length;
parseSlice(sslice, self->s.size(), &start, &stop, &step, &length);
parseSlice(sslice, self->size(), &start, &stop, &step, &length);
return _strSlice(self, start, stop, step, length);
} else {
raiseExcHelper(TypeError, "string indices must be integers, not %s", getTypeName(slice));
......@@ -2169,7 +2242,7 @@ public:
char c = *self->it;
++self->it;
return new BoxedString(std::string(1, c));
return boxStringRef(llvm::StringRef(&c, 1));
}
};
......@@ -2222,18 +2295,11 @@ extern "C" int PyString_AsStringAndSize(register PyObject* obj, register char**
BoxedString* createUninitializedString(ssize_t n) {
// I *think* this should avoid doing any copies, by using move constructors:
return new BoxedString(std::string(n, '\x00'));
return new (n) BoxedString(n, 0);
}
char* getWriteableStringContents(BoxedString* s) {
// After doing some reading, I think this is ok:
// http://stackoverflow.com/questions/14290795/why-is-modifying-a-string-through-a-retrieved-pointer-to-its-data-not-allowed
// In C++11, std::string is required to store its data contiguously.
// It looks like it's also required to make it available to write via the [] operator.
// - Taking a look at GCC's libstdc++, calling operator[] on a non-const string will return
// a writeable reference, and "unshare" the string.
// So surprisingly, this looks ok!
return &s->s[0];
return s->data();
}
extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexcept {
......@@ -2251,7 +2317,7 @@ extern "C" char* PyString_AsString(PyObject* o) noexcept {
extern "C" Py_ssize_t PyString_Size(PyObject* op) noexcept {
if (isSubclass(op->cls, str_cls))
return static_cast<BoxedString*>(op)->s.size();
return static_cast<BoxedString*>(op)->size();
char* _s;
Py_ssize_t len;
......@@ -2266,7 +2332,27 @@ extern "C" int _PyString_Resize(PyObject** pv, Py_ssize_t newsize) noexcept {
assert(pv);
assert(isSubclass((*pv)->cls, str_cls));
BoxedString* s = static_cast<BoxedString*>(*pv);
s->s.resize(newsize, '\0');
if (newsize == s->size())
return 0;
if (newsize < s->size()) {
// XXX resize the box (by reallocating) smaller if it makes sense
s->s = llvm::StringRef(s->data(), newsize);
s->data()[newsize] = 0;
return 0;
}
BoxedString* resized;
if (s->cls == str_cls)
resized = new (newsize) BoxedString(newsize, 0); // we need an uninitialized string, but this will memset
else
resized = new (s->cls, newsize)
BoxedString(newsize, 0); // we need an uninitialized string, but this will memset
memmove(resized->data(), s->data(), s->size());
*pv = resized;
return 0;
}
......@@ -2426,8 +2512,8 @@ static int string_print(PyObject* _op, FILE* fp, int flags) noexcept {
// Pyston change
// char *data = op->ob_sval;
// Py_ssize_t size = Py_SIZE(op);
const char* data = op->s.c_str();
Py_ssize_t size = op->s.size();
const char* data = op->data();
Py_ssize_t size = op->size();
Py_BEGIN_ALLOW_THREADS while (size > INT_MAX) {
/* Very long strings cannot be written atomically.
* But don't write exactly INT_MAX bytes at a time
......@@ -2451,12 +2537,12 @@ static int string_print(PyObject* _op, FILE* fp, int flags) noexcept {
quote = '\'';
// Pyston change
// if (memchr(op->ob_sval, '\'', Py_SIZE(op)) && !memchr(op->ob_sval, '"', Py_SIZE(op)))
if (memchr(op->s.c_str(), '\'', Py_SIZE(op)) && !memchr(op->s.c_str(), '"', Py_SIZE(op)))
if (memchr(op->data(), '\'', Py_SIZE(op)) && !memchr(op->data(), '"', Py_SIZE(op)))
quote = '"';
// Pyston change
// str_len = Py_SIZE(op);
str_len = op->s.size();
str_len = op->size();
Py_BEGIN_ALLOW_THREADS fputc(quote, fp);
for (i = 0; i < str_len; i++) {
/* Since strings are immutable and the caller should have a
......@@ -2489,8 +2575,8 @@ static Py_ssize_t string_buffer_getreadbuf(PyObject* self, Py_ssize_t index, con
RELEASE_ASSERT(isSubclass(self->cls, str_cls), "");
auto s = static_cast<BoxedString*>(self);
*ptr = s->s.c_str();
return s->s.size();
*ptr = s->data();
return s->size();
}
static Py_ssize_t string_buffer_getsegcount(PyObject* o, Py_ssize_t* lenp) noexcept {
......@@ -2510,7 +2596,7 @@ static Py_ssize_t string_buffer_getcharbuf(PyStringObject* self, Py_ssize_t inde
static int string_buffer_getbuffer(BoxedString* self, Py_buffer* view, int flags) noexcept {
assert(isSubclass(self->cls, str_cls));
return PyBuffer_FillInfo(view, (PyObject*)self, &self->s[0], self->s.size(), 1, flags);
return PyBuffer_FillInfo(view, (PyObject*)self, self->data(), self->size(), 1, flags);
}
static PyBufferProcs string_as_buffer = {
......@@ -2522,13 +2608,6 @@ static PyBufferProcs string_as_buffer = {
(releasebufferproc)NULL,
};
void strDestructor(Box* b) {
assert(isSubclass(b->cls, str_cls));
BoxedString* self = static_cast<BoxedString*>(b);
self->s.~basic_string();
}
static PyMethodDef string_methods[] = {
{ "count", (PyCFunction)string_count, METH_VARARGS, NULL },
{ "split", (PyCFunction)string_split, METH_VARARGS, NULL },
......@@ -2543,7 +2622,6 @@ static PyMethodDef string_methods[] = {
};
void setupStr() {
str_cls->simple_destructor = strDestructor;
str_cls->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
str_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &strIteratorGCHandler, 0, 0,
......@@ -2617,7 +2695,7 @@ void setupStr() {
str_cls->giveAttr("__eq__", new BoxedFunction(boxRTFunction((void*)strEq, UNKNOWN, 2)));
str_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)strNe, UNKNOWN, 2)));
BoxedString* spaceChar = new BoxedString(" ");
BoxedString* spaceChar = boxStrConstant(" ");
str_cls->giveAttr("ljust",
new BoxedFunction(boxRTFunction((void*)strLjust, UNKNOWN, 3, 1, false, false), { spaceChar }));
str_cls->giveAttr("rjust",
......@@ -2638,8 +2716,8 @@ void setupStr() {
str_cls->giveAttr(md.ml_name, new BoxedMethodDescriptor(&md, str_cls));
}
str_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)strNew, UNKNOWN, 2, 1, false, false),
{ boxStrConstant("") }));
str_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)strNew, UNKNOWN, 2, 1, false, false), { EmptyString }));
str_cls->freeze();
......
......@@ -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);
}
......
......@@ -18,9 +18,10 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stdint.h>
#include "llvm/Support/raw_ostream.h"
#include "capi/typeobject.h"
#include "capi/types.h"
#include "core/options.h"
......@@ -89,10 +90,8 @@ bool IN_SHUTDOWN = false;
// Analogue of PyType_GenericAlloc (default tp_alloc), but should only be used for Pyston classes!
extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) noexcept {
assert(cls);
RELEASE_ASSERT(nitems == 0, "");
RELEASE_ASSERT(cls->tp_itemsize == 0, "");
const size_t size = cls->tp_basicsize;
const size_t size = _PyObject_VAR_SIZE(cls, nitems + 1);
#ifndef NDEBUG
#if 0
......@@ -109,7 +108,7 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
} else {
assert(cls->tp_mro && "maybe we should just skip these checks if !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)) {
// old-style classes are always pyston classes:
if (b->cls == classobj_cls)
continue;
......@@ -611,7 +610,7 @@ extern "C" void tupleGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedTuple* t = (BoxedTuple*)b;
v->visitPotentialRange((void* const*)&t->elts, (void* const*)(&t->elts + 1));
v->visitRange((void* const*)&t->elts[0], (void* const*)&t->elts[t->size()]);
}
// This probably belongs in dict.cpp?
......@@ -651,6 +650,7 @@ BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls,
*builtin_function_or_method_cls, *attrwrapperiter_cls;
BoxedTuple* EmptyTuple;
BoxedString* EmptyString;
}
extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr_dict) {
......@@ -664,7 +664,7 @@ extern "C" Box* createUserClass(const std::string* name, Box* _bases, Box* _attr
metaclass = attr_dict->getOrNull(boxStrConstant("__metaclass__"));
if (metaclass != NULL) {
} else if (bases->elts.size() > 0) {
} else if (bases->size() > 0) {
// TODO Apparently this is supposed to look up __class__, and if that throws
// an error, then look up ob_type (aka cls)
metaclass = bases->elts[0]->cls;
......@@ -717,7 +717,7 @@ extern "C" Box* boxUnboundInstanceMethod(Box* func) {
}
extern "C" BoxedString* noneRepr(Box* v) {
return new BoxedString("None");
return boxStrConstant("None");
}
extern "C" Box* noneHash(Box* v) {
......@@ -756,7 +756,7 @@ extern "C" BoxedString* builtinFunctionOrMethodRepr(BoxedBuiltinFunctionOrMethod
}
extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return new BoxedString("function");
return boxStrConstant("function");
}
static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
......@@ -822,7 +822,7 @@ static Box* functionDefaults(Box* self, void*) {
BoxedFunction* func = static_cast<BoxedFunction*>(self);
if (!func->ndefaults)
return None;
return new BoxedTuple(BoxedTuple::GCVector(&func->defaults->elts[0], &func->defaults->elts[func->ndefaults]));
return BoxedTuple::create(func->ndefaults, &func->defaults->elts[0]);
}
static Box* functionNonzero(BoxedFunction* self) {
......@@ -937,8 +937,7 @@ Box* sliceRepr(BoxedSlice* self) {
BoxedString* start = static_cast<BoxedString*>(repr(self->start));
BoxedString* stop = static_cast<BoxedString*>(repr(self->stop));
BoxedString* step = static_cast<BoxedString*>(repr(self->step));
std::string s = "slice(" + start->s + ", " + stop->s + ", " + step->s + ")";
return new BoxedString(std::move(s));
return boxStringTwine(llvm::Twine("slice(") + start->s + ", " + stop->s + ", " + step->s + ")");
}
extern "C" int PySlice_GetIndices(PySliceObject* r, Py_ssize_t length, Py_ssize_t* start, Py_ssize_t* stop,
......@@ -962,7 +961,9 @@ extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssi
}
Box* typeRepr(BoxedClass* self) {
std::ostringstream os;
std::string O("");
llvm::raw_string_ostream os(O);
if ((self->tp_flags & Py_TPFLAGS_HEAPTYPE) && isUserDefined(self))
os << "<class '";
else
......@@ -1079,7 +1080,9 @@ Box* moduleNew(BoxedClass* cls, BoxedString* name, BoxedString* fn) {
Box* moduleRepr(BoxedModule* m) {
RELEASE_ASSERT(isSubclass(m->cls, module_cls), "");
std::ostringstream os;
std::string O("");
llvm::raw_string_ostream os(O);
os << "<module '" << m->name() << "' ";
if (m->fn == "__builtin__") {
......@@ -1198,7 +1201,7 @@ public:
BoxedString* key = static_cast<BoxedString*>(_key);
Box* r = self->b->getattr(key->s);
if (!r)
raiseExcHelper(KeyError, "'%s'", key->s.c_str());
raiseExcHelper(KeyError, "'%s'", key->data());
return r;
}
......@@ -1213,7 +1216,7 @@ public:
if (self->b->getattr(key->s))
self->b->delattr(key->s, NULL);
else
raiseExcHelper(KeyError, "'%s'", key->s.c_str());
raiseExcHelper(KeyError, "'%s'", key->data());
return None;
}
......@@ -1221,7 +1224,9 @@ public:
RELEASE_ASSERT(_self->cls == attrwrapper_cls, "");
AttrWrapper* self = static_cast<AttrWrapper*>(_self);
std::ostringstream os("");
std::string O("");
llvm::raw_string_ostream os(O);
os << "attrwrapper({";
HCAttrs* attrs = self->b->getHCAttrsPtr();
......@@ -1288,7 +1293,7 @@ public:
HCAttrs* attrs = self->b->getHCAttrsPtr();
RELEASE_ASSERT(attrs->hcls->type == HiddenClass::NORMAL, "");
for (const auto& p : attrs->hcls->getAttrOffsets()) {
BoxedTuple* t = new BoxedTuple({ boxString(p.first()), attrs->attr_list->attrs[p.second] });
BoxedTuple* t = BoxedTuple::create({ boxString(p.first()), attrs->attr_list->attrs[p.second] });
listAppend(rtn, t);
}
return rtn;
......@@ -1405,7 +1410,7 @@ Box* objectNew(BoxedClass* cls, BoxedTuple* args, BoxedDict* kwargs) {
// We use a different strategy from CPython: we let object.__new__ take extra
// arguments, but raise an error if they wouldn't be handled by the corresponding init.
// TODO switch to the CPython approach?
if (args->elts.size() != 0 || kwargs->d.size() != 0) {
if (args->size() != 0 || kwargs->d.size() != 0) {
// TODO slow (We already cache these in typeCall -- should use that here too?)
if (typeLookup(cls, "__new__", NULL) != typeLookup(object_cls, "__new__", NULL)
|| typeLookup(cls, "__init__", NULL) == typeLookup(object_cls, "__init__", NULL))
......@@ -1700,12 +1705,12 @@ static void objectSetClass(Box* obj, Box* val, void* context) {
// and that they don't define any extra C-level fields
RELEASE_ASSERT(val->cls == type_cls, "");
RELEASE_ASSERT(obj->cls->cls == type_cls, "");
for (auto _base : static_cast<BoxedTuple*>(obj->cls->tp_mro)->elts) {
BoxedClass* base = static_cast<BoxedClass*>(_base);
for (auto b : *static_cast<BoxedTuple*>(obj->cls->tp_mro)) {
BoxedClass* base = static_cast<BoxedClass*>(b);
RELEASE_ASSERT(base->is_pyston_class, "");
}
for (auto _base : static_cast<BoxedTuple*>(new_cls->tp_mro)->elts) {
BoxedClass* base = static_cast<BoxedClass*>(_base);
for (auto b : *static_cast<BoxedTuple*>(new_cls->tp_mro)) {
BoxedClass* base = static_cast<BoxedClass*>(b);
RELEASE_ASSERT(base->is_pyston_class, "");
}
......@@ -1769,13 +1774,13 @@ static void typeSetName(Box* b, Box* v, void*) {
}
BoxedString* s = static_cast<BoxedString*>(v);
if (strlen(s->s.c_str()) != s->s.size()) {
if (strlen(s->data()) != s->size()) {
raiseExcHelper(ValueError, "__name__ must not contain null bytes");
}
BoxedHeapClass* ht = static_cast<BoxedHeapClass*>(type);
ht->ht_name = s;
ht->tp_name = s->s.c_str();
ht->tp_name = s->data();
}
static Box* typeBases(Box* b, void*) {
......@@ -1833,6 +1838,7 @@ Box* decodeUTF8StringPtr(const std::string* s) {
bool TRACK_ALLOCATIONS = false;
void setupRuntime() {
root_hcls = HiddenClass::makeRoot();
gc::registerPermanentRoot(root_hcls);
HiddenClass::dict_backed = HiddenClass::makeDictBacked();
......@@ -1862,21 +1868,22 @@ void setupRuntime() {
str_cls = new BoxedHeapClass(basestring_cls, NULL, 0, 0, sizeof(BoxedString), false, NULL);
str_cls->tp_flags |= Py_TPFLAGS_STRING_SUBCLASS;
str_cls->tp_itemsize = sizeof(char);
// Hold off on assigning names until str_cls is ready
object_cls->tp_name = "object";
BoxedString* boxed_type_name = new BoxedString("type");
BoxedString* boxed_basestring_name = new BoxedString("basestring");
BoxedString* boxed_str_name = new BoxedString("str");
BoxedString* boxed_none_name = new BoxedString("NoneType");
BoxedString* boxed_type_name = static_cast<BoxedString*>(boxStrConstant("type"));
BoxedString* boxed_basestring_name = static_cast<BoxedString*>(boxStrConstant("basestring"));
BoxedString* boxed_str_name = static_cast<BoxedString*>(boxStrConstant("str"));
BoxedString* boxed_none_name = static_cast<BoxedString*>(boxStrConstant("NoneType"));
static_cast<BoxedHeapClass*>(type_cls)->ht_name = boxed_type_name;
static_cast<BoxedHeapClass*>(basestring_cls)->ht_name = boxed_basestring_name;
static_cast<BoxedHeapClass*>(str_cls)->ht_name = boxed_str_name;
static_cast<BoxedHeapClass*>(none_cls)->ht_name = boxed_none_name;
type_cls->tp_name = boxed_type_name->s.c_str();
basestring_cls->tp_name = boxed_basestring_name->s.c_str();
str_cls->tp_name = boxed_str_name->s.c_str();
none_cls->tp_name = boxed_none_name->s.c_str();
type_cls->tp_name = boxed_type_name->data();
basestring_cls->tp_name = boxed_basestring_name->data();
str_cls->tp_name = boxed_str_name->data();
none_cls->tp_name = boxed_none_name->data();
gc::enableGC();
......@@ -1891,73 +1898,82 @@ void setupRuntime() {
tuple_cls
= new BoxedHeapClass(object_cls, &tupleGCHandler, 0, 0, sizeof(BoxedTuple), false, boxStrConstant("tuple"));
tuple_cls->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
EmptyTuple = new BoxedTuple({});
tuple_cls->tp_itemsize = sizeof(Box*);
tuple_cls->tp_mro = BoxedTuple::create({ tuple_cls, object_cls });
EmptyTuple = BoxedTuple::create({});
gc::registerPermanentRoot(EmptyTuple);
list_cls = new BoxedHeapClass(object_cls, &listGCHandler, 0, 0, sizeof(BoxedList), false, boxStrConstant("list"));
list_cls->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
pyston_getset_cls
= new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedGetsetDescriptor), false, boxStrConstant("getset"));
attrwrapper_cls = new BoxedHeapClass(object_cls, &AttrWrapper::gcHandler, 0, 0, sizeof(AttrWrapper), false,
new BoxedString("attrwrapper"));
dict_cls = new BoxedHeapClass(object_cls, &dictGCHandler, 0, 0, sizeof(BoxedDict), false, new BoxedString("dict"));
static_cast<BoxedString*>(boxStrConstant("attrwrapper")));
dict_cls = new BoxedHeapClass(object_cls, &dictGCHandler, 0, 0, sizeof(BoxedDict), false,
static_cast<BoxedString*>(boxStrConstant("dict")));
dict_cls->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
file_cls = new BoxedHeapClass(object_cls, &BoxedFile::gcHandler, 0, offsetof(BoxedFile, weakreflist),
sizeof(BoxedFile), false, new BoxedString("file"));
int_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedInt), false, new BoxedString("int"));
file_cls = new BoxedHeapClass(object_cls, NULL, 0, offsetof(BoxedFile, weakreflist), sizeof(BoxedFile), false,
static_cast<BoxedString*>(boxStrConstant("file")));
int_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedInt), false,
static_cast<BoxedString*>(boxStrConstant("int")));
int_cls->tp_flags |= Py_TPFLAGS_INT_SUBCLASS;
bool_cls = new BoxedHeapClass(int_cls, NULL, 0, 0, sizeof(BoxedBool), false, new BoxedString("bool"));
complex_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedComplex), false, new BoxedString("complex"));
bool_cls = new BoxedHeapClass(int_cls, NULL, 0, 0, sizeof(BoxedBool), false,
static_cast<BoxedString*>(boxStrConstant("bool")));
complex_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedComplex), false,
static_cast<BoxedString*>(boxStrConstant("complex")));
long_cls = new BoxedHeapClass(object_cls, &BoxedLong::gchandler, 0, 0, sizeof(BoxedLong), false,
new BoxedString("long"));
static_cast<BoxedString*>(boxStrConstant("long")));
long_cls->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
float_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedFloat), false, new BoxedString("float"));
float_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedFloat), false,
static_cast<BoxedString*>(boxStrConstant("float")));
function_cls = new BoxedHeapClass(object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
offsetof(BoxedFunction, in_weakreflist), sizeof(BoxedFunction), false,
new BoxedString("function"));
builtin_function_or_method_cls = new BoxedHeapClass(
object_cls, &functionGCHandler, 0, offsetof(BoxedBuiltinFunctionOrMethod, in_weakreflist),
sizeof(BoxedBuiltinFunctionOrMethod), false, new BoxedString("builtin_function_or_method"));
static_cast<BoxedString*>(boxStrConstant("function")));
builtin_function_or_method_cls
= new BoxedHeapClass(object_cls, &functionGCHandler, 0, offsetof(BoxedBuiltinFunctionOrMethod, in_weakreflist),
sizeof(BoxedBuiltinFunctionOrMethod), false,
static_cast<BoxedString*>(boxStrConstant("builtin_function_or_method")));
function_cls->simple_destructor = builtin_function_or_method_cls->simple_destructor = functionDtor;
module_cls = new BoxedHeapClass(object_cls, &moduleGCHandler, offsetof(BoxedModule, attrs), 0, sizeof(BoxedModule),
false, new BoxedString("module"));
member_cls
= new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false, new BoxedString("member"));
capifunc_cls
= new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false, new BoxedString("capifunc"));
method_cls
= new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false, new BoxedString("method"));
false, static_cast<BoxedString*>(boxStrConstant("module")));
member_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMemberDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("member")));
capifunc_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false,
static_cast<BoxedString*>(boxStrConstant("capifunc")));
method_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false,
static_cast<BoxedString*>(boxStrConstant("method")));
wrapperobject_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedWrapperObject), false,
new BoxedString("method-wrapper"));
static_cast<BoxedString*>(boxStrConstant("method-wrapper")));
wrapperdescr_cls = new BoxedHeapClass(object_cls, NULL, 0, 0, sizeof(BoxedWrapperDescriptor), false,
new BoxedString("wrapper_descriptor"));
static_cast<BoxedString*>(boxStrConstant("wrapper_descriptor")));
EmptyString = boxStrConstant("");
gc::registerPermanentRoot(EmptyString);
// Kind of hacky, but it's easier to manually construct the mro for a couple key classes
// than try to make the MRO construction code be safe against say, tuple_cls not having
// an mro (since the mro is stored as a tuple).
object_cls->tp_mro = new BoxedTuple({ object_cls });
tuple_cls->tp_mro = new BoxedTuple({ tuple_cls, object_cls });
list_cls->tp_mro = new BoxedTuple({ list_cls, object_cls });
type_cls->tp_mro = new BoxedTuple({ type_cls, object_cls });
pyston_getset_cls->tp_mro = new BoxedTuple({ pyston_getset_cls, object_cls });
attrwrapper_cls->tp_mro = new BoxedTuple({ attrwrapper_cls, object_cls });
dict_cls->tp_mro = new BoxedTuple({ dict_cls, object_cls });
file_cls->tp_mro = new BoxedTuple({ file_cls, object_cls });
int_cls->tp_mro = new BoxedTuple({ int_cls, object_cls });
bool_cls->tp_mro = new BoxedTuple({ bool_cls, object_cls });
complex_cls->tp_mro = new BoxedTuple({ complex_cls, object_cls });
long_cls->tp_mro = new BoxedTuple({ long_cls, object_cls });
float_cls->tp_mro = new BoxedTuple({ float_cls, object_cls });
function_cls->tp_mro = new BoxedTuple({ function_cls, object_cls });
builtin_function_or_method_cls->tp_mro = new BoxedTuple({ builtin_function_or_method_cls, object_cls });
member_cls->tp_mro = new BoxedTuple({ member_cls, object_cls });
capifunc_cls->tp_mro = new BoxedTuple({ capifunc_cls, object_cls });
module_cls->tp_mro = new BoxedTuple({ module_cls, object_cls });
method_cls->tp_mro = new BoxedTuple({ method_cls, object_cls });
wrapperobject_cls->tp_mro = new BoxedTuple({ wrapperobject_cls, object_cls });
wrapperdescr_cls->tp_mro = new BoxedTuple({ wrapperdescr_cls, object_cls });
object_cls->tp_mro = BoxedTuple::create({ object_cls });
list_cls->tp_mro = BoxedTuple::create({ list_cls, object_cls });
type_cls->tp_mro = BoxedTuple::create({ type_cls, object_cls });
pyston_getset_cls->tp_mro = BoxedTuple::create({ pyston_getset_cls, object_cls });
attrwrapper_cls->tp_mro = BoxedTuple::create({ attrwrapper_cls, object_cls });
dict_cls->tp_mro = BoxedTuple::create({ dict_cls, object_cls });
file_cls->tp_mro = BoxedTuple::create({ file_cls, object_cls });
int_cls->tp_mro = BoxedTuple::create({ int_cls, object_cls });
bool_cls->tp_mro = BoxedTuple::create({ bool_cls, object_cls });
complex_cls->tp_mro = BoxedTuple::create({ complex_cls, object_cls });
long_cls->tp_mro = BoxedTuple::create({ long_cls, object_cls });
float_cls->tp_mro = BoxedTuple::create({ float_cls, object_cls });
function_cls->tp_mro = BoxedTuple::create({ function_cls, object_cls });
builtin_function_or_method_cls->tp_mro = BoxedTuple::create({ builtin_function_or_method_cls, object_cls });
member_cls->tp_mro = BoxedTuple::create({ member_cls, object_cls });
capifunc_cls->tp_mro = BoxedTuple::create({ capifunc_cls, object_cls });
module_cls->tp_mro = BoxedTuple::create({ module_cls, object_cls });
method_cls->tp_mro = BoxedTuple::create({ method_cls, object_cls });
wrapperobject_cls->tp_mro = BoxedTuple::create({ wrapperobject_cls, object_cls });
wrapperdescr_cls->tp_mro = BoxedTuple::create({ wrapperdescr_cls, object_cls });
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
......
......@@ -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