static Box* _intNew(Box* val, Box* base) { if (isSubclass(val->cls, int_cls)) { RELEASE_ASSERT(!base, ""); BoxedInt* n = static_cast<BoxedInt*>(val); if (val->cls == int_cls) return n; return new BoxedInt(n->n); } else if (isSubclass(val->cls, str_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } BoxedString* s = static_cast<BoxedString*>(val); RELEASE_ASSERT(s->size() == strlen(s->data()), ""); Box* r = PyInt_FromString(s->data(), NULL, base_n); if (!r) throwCAPIException(); return r; } else if (isSubclass(val->cls, unicode_cls)) { int base_n; if (!base) base_n = 10; else { RELEASE_ASSERT(base->cls == int_cls, ""); base_n = static_cast<BoxedInt*>(base)->n; } Box* r = PyInt_FromUnicode(PyUnicode_AS_UNICODE(val), PyUnicode_GET_SIZE(val), base_n); if (!r) throwCAPIException(); return r; } else if (val->cls == float_cls) { RELEASE_ASSERT(!base, ""); double d = static_cast<BoxedFloat*>(val)->d; return new BoxedInt(d); } else { RELEASE_ASSERT(!base, ""); static const std::string int_str("__int__"); Box* r = callattr(val, &int_str, CallattrFlags({.cls_only = true, .null_on_nonexistent = true }), ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); if (!r) { fprintf(stderr, "TypeError: int() argument must be a string or a number, not '%s'\n", getTypeName(val)); raiseExcHelper(TypeError, ""); } if (!isSubclass(r->cls, int_cls) && !isSubclass(r->cls, long_cls)) { raiseExcHelper(TypeError, "__int__ returned non-int (type %s)", r->cls->tp_name); } return r; }
Box* tupleMul(BoxedTuple* self, Box* rhs) { Py_ssize_t n; if (PyIndex_Check(rhs)) { n = PyNumber_AsSsize_t(rhs, PyExc_OverflowError); if (n == -1 && PyErr_Occurred()) throwCAPIException(); } else { raiseExcHelper(TypeError, "can't multiply sequence by non-int of type '%s'", getTypeName(rhs)); } int s = self->size(); if (n < 0) n = 0; if ((s == 0 || n == 1) && PyTuple_CheckExact(self)) { return self; } else { BoxedTuple* rtn = BoxedTuple::create(n * s); int rtn_i = 0; for (int i = 0; i < n; ++i) { memmove(&rtn->elts[rtn_i], &self->elts[0], sizeof(Box*) * s); rtn_i += s; } return rtn; } }
Box* setInit(Box* _self, Box* container, BoxedDict* kwargs) { RELEASE_ASSERT(PySet_Check(_self), ""); if (PySet_Check(_self) && !_PyArg_NoKeywords("set()", kwargs)) { throwCAPIException(); } if (!container) return incref(None); BoxedSet* self = static_cast<BoxedSet*>(_self); setClearInternal(self); if (PyAnySet_Check(container)) { for (auto&& elt : ((BoxedSet*)container)->s) { self->s.insert(incref(elt)); } } else if (PyDict_CheckExact(container)) { for (auto&& elt : ((BoxedDict*)container)->d) { self->s.insert(incref(elt.first)); } } else { for (auto elt : container->pyElements()) { _setAddStolen(self, elt); } } return incref(None); }
Box* frozensetNew(Box* _cls, Box* container, BoxedDict* kwargs) { RELEASE_ASSERT(_cls->cls == type_cls, ""); BoxedClass* cls = static_cast<BoxedClass*>(_cls); RELEASE_ASSERT(isSubclass(cls, frozenset_cls), ""); if (_cls == frozenset_cls && !_PyArg_NoKeywords("frozenset()", kwargs)) { throwCAPIException(); } if (_cls != frozenset_cls) { return makeNewSet(cls, container); } if (container != NULL) { if (container->cls == frozenset_cls) return incref(container); BoxedSet* result = makeNewSet(cls, container); if (result->s.size() != 0) { return result; } Py_DECREF(result); } static Box* emptyfrozenset = NULL; if (!emptyfrozenset) { emptyfrozenset = new (frozenset_cls) BoxedSet(); PyGC_RegisterStaticConstant(emptyfrozenset); } Py_INCREF(emptyfrozenset); return emptyfrozenset; }
llvm_compat_bool calliterHasnextUnboxed(Box* b) { calliterobject* it = (calliterobject*)b; if (!it->it_nextvalue) { it->it_nextvalue = calliter_next(it); if (PyErr_Occurred()) { throwCAPIException(); } } return it->it_nextvalue != NULL; }
Box* setNew(Box* _cls, Box* container, BoxedDict* kwargs) { RELEASE_ASSERT(_cls->cls == type_cls, ""); BoxedClass* cls = static_cast<BoxedClass*>(_cls); RELEASE_ASSERT(isSubclass(cls, set_cls), ""); if (_cls == set_cls && !_PyArg_NoKeywords("set()", kwargs)) { throwCAPIException(); } // Note: set.__new__ explicitly ignores the container argument. return makeNewSet(cls, NULL); }
Box* tupleContains(BoxedTuple* self, Box* elt) { int size = self->size(); for (Box* e : *self) { int r = PyObject_RichCompareBool(elt, e, Py_EQ); if (r == -1) throwCAPIException(); if (r) return True; } return False; }
Box* tupleGetitem(BoxedTuple* self, Box* slice) { assert(self->cls == tuple_cls); if (PyIndex_Check(slice)) { Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) throwCAPIException(); return tupleGetitemUnboxed(self, i); } else if (slice->cls == slice_cls) return tupleGetitemSlice(self, static_cast<BoxedSlice*>(slice)); else raiseExcHelper(TypeError, "tuple indices must be integers, not %s", getTypeName(slice)); }
Box* tupleCount(BoxedTuple* self, Box* elt) { int size = self->size(); int count = 0; for (int i = 0; i < size; i++) { Box* e = self->elts[i]; int r = PyObject_RichCompareBool(e, elt, Py_EQ); if (r == -1) throwCAPIException(); if (r) count++; } return boxInt(count); }
extern "C" Box* tupleNew(Box* _cls, BoxedTuple* args, BoxedDict* kwargs) { if (!PyType_Check(_cls)) raiseExcHelper(TypeError, "tuple.__new__(X): X is not a type object (%s)", getTypeName(_cls)); BoxedClass* cls = static_cast<BoxedClass*>(_cls); if (!isSubclass(cls, tuple_cls)) raiseExcHelper(TypeError, "tuple.__new__(%s): %s is not a subtype of tuple", getNameOfClass(cls), getNameOfClass(cls)); int args_sz = args->size(); int kwargs_sz = kwargs ? kwargs->d.size() : 0; if (args_sz + kwargs_sz > 1) raiseExcHelper(TypeError, "tuple() takes at most 1 argument (%d given)", args_sz + kwargs_sz); 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]; } else { assert(kwargs_sz); auto const seq = *(kwargs->d.begin()); auto const kw = static_cast<BoxedString*>(seq.first.value); if (kw->s() == "sequence") elements = seq.second; else raiseExcHelper(TypeError, "'%s' is an invalid keyword argument for this function", kw->data()); } if (cls == tuple_cls) { // Call PySequence_Tuple since it has some perf special-cases // that can make it quite a bit faster than the generic pyElements iteration: Box* r = PySequence_Tuple(elements); if (!r) throwCAPIException(); return r; } std::vector<Box*, StlCompatAllocator<Box*>> elts; for (auto e : elements->pyElements()) elts.push_back(e); return BoxedTuple::create(elts.size(), &elts[0], cls); } else { if (cls == tuple_cls) return EmptyTuple; return BoxedTuple::create(0, cls); } }
llvm_compat_bool iterwrapperHasnextUnboxed(Box* s) { RELEASE_ASSERT(s->cls == iterwrapper_cls, ""); BoxedIterWrapper* self = static_cast<BoxedIterWrapper*>(s); Box* next = PyIter_Next(self->iter); RELEASE_ASSERT(!self->next, ""); self->next = next; if (!next) { if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_StopIteration)) throwCAPIException(); PyErr_Clear(); } return next != NULL; }
static Box* setRepr(BoxedSet* self) { RELEASE_ASSERT(PyAnySet_Check(self), ""); std::vector<char> chars; int status = Py_ReprEnter((PyObject*)self); if (status != 0) { if (status < 0) throwCAPIException(); std::string ty = std::string(self->cls->tp_name); chars.insert(chars.end(), ty.begin(), ty.end()); chars.push_back('('); chars.push_back('.'); chars.push_back('.'); chars.push_back('.'); chars.push_back(')'); return boxString(llvm::StringRef(&chars[0], chars.size())); } try { std::string ty = std::string(self->cls->tp_name); chars.insert(chars.end(), ty.begin(), ty.end()); chars.push_back('('); chars.push_back('['); bool first = true; for (auto&& elt : self->s) { if (!first) { chars.push_back(','); chars.push_back(' '); } BoxedString* str = static_cast<BoxedString*>(repr(elt.value)); AUTO_DECREF(str); chars.insert(chars.end(), str->s().begin(), str->s().end()); first = false; } chars.push_back(']'); chars.push_back(')'); } catch (ExcInfo e) { Py_ReprLeave((PyObject*)self); throw e; } Py_ReprLeave((PyObject*)self); return boxString(llvm::StringRef(&chars[0], chars.size())); }
Box* tupleIndex(BoxedTuple* self, Box* elt) { int size = self->size(); for (int i = 0; i < size; i++) { Box* e = self->elts[i]; int r = PyObject_RichCompareBool(e, elt, Py_EQ); if (r == -1) throwCAPIException(); if (r) return boxInt(i); } raiseExcHelper(ValueError, "tuple.index(x): x not in tuple"); }
Box* tupleRepr(BoxedTuple* t) { assert(isSubclass(t->cls, tuple_cls)); int n; std::vector<char> chars; int status = Py_ReprEnter((PyObject*)t); n = t->size(); if (n == 0) { chars.push_back('('); chars.push_back(')'); return boxString(llvm::StringRef(&chars[0], chars.size())); } if (status != 0) { if (status < 0) throwCAPIException(); chars.push_back('('); chars.push_back('.'); chars.push_back('.'); chars.push_back('.'); chars.push_back(')'); return boxString(llvm::StringRef(&chars[0], chars.size())); } try { chars.push_back('('); for (int i = 0; i < n; i++) { if (i) { chars.push_back(','); chars.push_back(' '); } BoxedString* elt_repr = static_cast<BoxedString*>(repr(t->elts[i])); chars.insert(chars.end(), elt_repr->s().begin(), elt_repr->s().end()); } if (n == 1) chars.push_back(','); chars.push_back(')'); } catch (ExcInfo e) { Py_ReprLeave((PyObject*)t); throw e; } Py_ReprLeave((PyObject*)t); return boxString(llvm::StringRef(&chars[0], chars.size())); }
template <ExceptionStyle S> Box* tupleGetitem(BoxedTuple* self, Box* slice) { if (S == CAPI) { try { return tupleGetitem<CXX>(self, slice); } catch (ExcInfo e) { setCAPIException(e); return NULL; } } assert(isSubclass(self->cls, tuple_cls)); if (PyIndex_Check(slice)) { Py_ssize_t i = PyNumber_AsSsize_t(slice, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) throwCAPIException(); return tupleGetitemUnboxed(self, i); } else if (slice->cls == slice_cls) return tupleGetitemSlice(self, static_cast<BoxedSlice*>(slice)); else raiseExcHelper(TypeError, "tuple indices must be integers, not %s", getTypeName(slice)); }
Box* tupleIndex(BoxedTuple* self, Box* elt, Box* startBox, Box** args) { Box* endBox = args[0]; Py_ssize_t start, end; _PyEval_SliceIndex(startBox, &start); _PyEval_SliceIndex(endBox, &end); Py_ssize_t size = self->size(); if (start < 0) { start += size; if (start < 0) { start = 0; } } if (end < 0) { end += size; if (end < 0) { end = 0; } } else if (end > size) { end = size; } for (Py_ssize_t i = start; i < end; i++) { Box* e = self->elts[i]; int r = PyObject_RichCompareBool(e, elt, Py_EQ); if (r == -1) throwCAPIException(); if (r) return boxInt(i); } raiseExcHelper(ValueError, "tuple.index(x): x not in tuple"); }
extern "C" Box* dir(Box* obj) { Box* r = PyObject_Dir(obj); if (!r) throwCAPIException(); return r; }
Box* sysCurrentFrames() { Box* rtn = _PyThread_CurrentFrames(); if (!rtn) throwCAPIException(); return rtn; }
Box* seqreviterHasnext(Box* s) { Box* rtn = seqreviterHasnext_capi(s); if (!rtn) throwCAPIException(); return rtn; }
SearchResult findModule(const std::string& name, BoxedString* full_name, BoxedList* path_list) { static BoxedString* meta_path_str = internStringImmortal("meta_path"); BoxedList* meta_path = static_cast<BoxedList*>(sys_module->getattr(meta_path_str)); if (!meta_path || meta_path->cls != list_cls) raiseExcHelper(RuntimeError, "sys.meta_path must be a list of import hooks"); static BoxedString* findmodule_str = internStringImmortal("find_module"); for (int i = 0; i < meta_path->size; i++) { Box* finder = meta_path->elts->elts[i]; auto path_pass = path_list ? path_list : None; CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(2) }; Box* loader = callattr(finder, findmodule_str, callattr_flags, full_name, path_pass, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (!path_list) path_list = getSysPath(); if (path_list == NULL || path_list->cls != list_cls) { raiseExcHelper(RuntimeError, "sys.path must be a list of directory names"); } static BoxedString* path_hooks_str = internStringImmortal("path_hooks"); BoxedList* path_hooks = static_cast<BoxedList*>(sys_module->getattr(path_hooks_str)); if (!path_hooks || path_hooks->cls != list_cls) raiseExcHelper(RuntimeError, "sys.path_hooks must be a list of import hooks"); static BoxedString* path_importer_cache_str = internStringImmortal("path_importer_cache"); BoxedDict* path_importer_cache = static_cast<BoxedDict*>(sys_module->getattr(path_importer_cache_str)); if (!path_importer_cache || path_importer_cache->cls != dict_cls) raiseExcHelper(RuntimeError, "sys.path_importer_cache must be a dict"); llvm::SmallString<128> joined_path; for (int i = 0; i < path_list->size; i++) { Box* _p = path_list->elts->elts[i]; if (_p->cls != str_cls) continue; BoxedString* p = static_cast<BoxedString*>(_p); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name); std::string dn(joined_path.str()); llvm::sys::path::append(joined_path, "__init__.py"); std::string fn(joined_path.str()); PyObject* importer = get_path_importer(path_importer_cache, path_hooks, _p); if (importer == NULL) throwCAPIException(); if (importer != None) { CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) }; Box* loader = callattr(importer, findmodule_str, callattr_flags, full_name, NULL, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (pathExists(fn)) return SearchResult(std::move(dn), SearchResult::PKG_DIRECTORY); joined_path.clear(); llvm::sys::path::append(joined_path, std::string(p->s()), name + ".py"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::PY_SOURCE); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name + ".pyston.so"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::C_EXTENSION); } return SearchResult("", SearchResult::SEARCH_ERROR); } PyObject* PyImport_GetImporter(PyObject* path) noexcept { PyObject* importer = NULL, * path_importer_cache = NULL, * path_hooks = NULL; if ((path_importer_cache = PySys_GetObject("path_importer_cache"))) { if ((path_hooks = PySys_GetObject("path_hooks"))) { importer = get_path_importer(path_importer_cache, path_hooks, path); } } Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ return importer; }
Box* methodDescrTppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) { if (S == CAPI) { try { return methodDescrTppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names); } catch (ExcInfo e) { setCAPIException(e); return NULL; } } STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10); assert(_self->cls == &PyMethodDescr_Type || _self->cls == &PyClassMethodDescr_Type); PyMethodDescrObject* self = reinterpret_cast<PyMethodDescrObject*>(_self); bool is_classmethod = (_self->cls == &PyClassMethodDescr_Type); int ml_flags = self->d_method->ml_flags; int call_flags = ml_flags & ~(METH_CLASS | METH_COEXIST | METH_STATIC); if (rewrite_args && !rewrite_args->func_guarded) { rewrite_args->obj->addAttrGuard(offsetof(PyMethodDescrObject, d_method), (intptr_t)self->d_method); } ParamReceiveSpec paramspec(0, 0, false, false); Box** defaults = NULL; if (call_flags == METH_NOARGS) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (call_flags == METH_VARARGS) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (call_flags == METH_O) { paramspec = ParamReceiveSpec(2, 0, false, false); } else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) { int num_args = 0; if (call_flags & METH_O) num_args++; if (call_flags & METH_O2) num_args += 2; int num_defaults = 0; if (call_flags & METH_D1) num_defaults++; if (call_flags & METH_D2) num_defaults += 2; paramspec = ParamReceiveSpec(1 + num_args, num_defaults, false, false); if (num_defaults) { static Box* _defaults[] = { NULL, NULL, NULL }; assert(num_defaults <= 3); defaults = _defaults; } } else { RELEASE_ASSERT(0, "0x%x", call_flags); } bool arg1_class_guarded = false; if (rewrite_args && argspec.num_args >= 1) { // Try to do the guard before rearrangeArguments if possible: rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)arg1->cls); arg1_class_guarded = true; } auto continuation = [=](CallRewriteArgs* rewrite_args, Box* arg1, Box* arg2, Box* arg3, Box** args) { if (is_classmethod) { rewrite_args = NULL; if (!PyType_Check(arg1)) raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->d_method->ml_name, getFullTypeName(arg1).c_str()); } else { if (!isSubclass(arg1->cls, self->d_type)) raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' arg1 but received a '%s'", self->d_method->ml_name, self->d_type->tp_name, getFullTypeName(arg1).c_str()); } if (rewrite_args && !arg1_class_guarded) { rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)arg1->cls); } Box* rtn; if (call_flags == METH_NOARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->d_method->ml_meth(arg1, NULL); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->rewriter->loadConst(0, Location::forArg(1))) ->setType(RefType::OWNED); } else if (call_flags == METH_VARARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->d_method->ml_meth(arg1, arg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)((PyCFunctionWithKeywords)self->d_method->ml_meth)(arg1, arg2, arg3); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3)->setType(RefType::OWNED); } else if (call_flags == METH_O) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->d_method->ml_meth(arg1, arg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); } else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = ((Box * (*)(Box*, Box*, Box*, Box**))self->d_method->ml_meth)(arg1, arg2, arg3, args); } if (rewrite_args) { if (paramspec.totalReceived() == 2) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2)->setType(RefType::OWNED); else if (paramspec.totalReceived() == 3) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3)->setType(RefType::OWNED); else if (paramspec.totalReceived() > 3) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->d_method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3, rewrite_args->args)->setType(RefType::OWNED); else abort(); } } else { RELEASE_ASSERT(0, "0x%x", call_flags); } if (!rtn) throwCAPIException(); if (rewrite_args) { rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } return rtn; }; return rearrangeArgumentsAndCall(paramspec, NULL, self->d_method->ml_name, defaults, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names, continuation); }
Box* wrapperDescrTppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI) { if (S == CAPI) { try { return wrapperDescrTppCall<CXX>(_self, NULL, argspec, arg1, arg2, arg3, args, keyword_names); } catch (ExcInfo e) { setCAPIException(e); return NULL; } } if (rewrite_args) { // We are going to embed references to _self->d_base->wrapper and _self->d_wrapped rewrite_args->obj->addGuard((intptr_t)_self); rewrite_args->rewriter->addGCReference(_self); } STAT_TIMER(t0, "us_timer_boxedwrapperdecsriptor_call", (_self->cls->is_user_defined ? 10 : 20)); assert(_self->cls == &PyWrapperDescr_Type); PyWrapperDescrObject* self = reinterpret_cast<PyWrapperDescrObject*>(_self); int flags = self->d_base->flags; wrapperfunc wrapper = self->d_base->wrapper; ParamReceiveSpec paramspec(1, 0, true, false); if (flags == PyWrapperFlag_KEYWORDS) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (flags == PyWrapperFlag_1ARG) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (flags == PyWrapperFlag_2ARG) { paramspec = ParamReceiveSpec(2, 0, false, false); } else { RELEASE_ASSERT(0, "%d", flags); } auto continuation = [=](CallRewriteArgs* rewrite_args, Box* arg1, Box* arg2, Box* arg3, Box** args) { #ifndef NDEBUG if (paramspec.takes_varargs) assert(arg2 && arg2->cls == tuple_cls); #endif Box* rtn; if (flags == PyWrapperFlag_KEYWORDS) { wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper; rtn = (*wk)(arg1, arg2, self->d_wrapped, arg3); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wk, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2)), rewrite_args->arg3)->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_PYSTON || flags == 0) { rtn = (*wrapper)(arg1, arg2, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_1ARG) { wrapperfunc_1arg wrapper_1arg = (wrapperfunc_1arg)wrapper; rtn = (*wrapper_1arg)(arg1, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(1))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else if (flags == PyWrapperFlag_2ARG) { rtn = (*wrapper)(arg1, arg2, self->d_wrapped); if (rewrite_args) { auto rewriter = rewrite_args->rewriter; rewrite_args->out_rtn = rewriter->call(true, (void*)wrapper, rewrite_args->arg1, rewrite_args->arg2, rewriter->loadConst((intptr_t)self->d_wrapped, Location::forArg(2))) ->setType(RefType::OWNED); rewrite_args->rewriter->checkAndThrowCAPIException(rewrite_args->out_rtn); rewrite_args->out_success = true; } } else { RELEASE_ASSERT(0, "%d", flags); } if (S == CXX && !rtn) throwCAPIException(); return rtn; }; return callCXXFromStyle<S>([&]() { return rearrangeArgumentsAndCall(paramspec, NULL, self->d_base->name, NULL, rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names, continuation); }); }
Box* superGetattribute(Box* _s, Box* _attr) { RELEASE_ASSERT(_s->cls == super_cls, ""); BoxedSuper* s = static_cast<BoxedSuper*>(_s); RELEASE_ASSERT(_attr->cls == str_cls, ""); BoxedString* attr = static_cast<BoxedString*>(_attr); bool skip = s->obj_type == NULL; if (!skip) { // Looks like __class__ is supposed to be "super", not the class of the the proxied object. skip = (attr->s() == class_str); } if (!skip) { PyObject* mro, *res, *tmp, *dict; PyTypeObject* starttype; descrgetfunc f; Py_ssize_t i, n; starttype = s->obj_type; mro = starttype->tp_mro; if (mro == NULL) n = 0; else { assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); } for (i = 0; i < n; i++) { if ((PyObject*)(s->type) == PyTuple_GET_ITEM(mro, i)) break; } i++; res = NULL; for (; i < n; i++) { tmp = PyTuple_GET_ITEM(mro, i); // Pyston change: #if 0 if (PyType_Check(tmp)) dict = ((PyTypeObject *)tmp)->tp_dict; else if (PyClass_Check(tmp)) dict = ((PyClassObject *)tmp)->cl_dict; else continue; res = PyDict_GetItem(dict, name); #endif res = tmp->getattr(attr); if (res != NULL) { // Pyston change: #if 0 Py_INCREF(res); f = Py_TYPE(res)->tp_descr_get; if (f != NULL) { tmp = f(res, /* Only pass 'obj' param if this is instance-mode sper (See SF ID #743627) */ (s->obj == (PyObject *) s->obj_type ? (PyObject *)NULL : s->obj), (PyObject *)starttype); Py_DECREF(res); res = tmp; } #endif return processDescriptor(res, (s->obj == s->obj_type ? None : s->obj), s->obj_type); } } } Box* rtn = PyObject_GenericGetAttr(s, attr); if (!rtn) throwCAPIException(); return rtn; }
Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names) { STAT_TIMER(t0, "us_timer_boxedmethoddescriptor__call__", 10); assert(_self->cls == method_cls); BoxedMethodDescriptor* self = static_cast<BoxedMethodDescriptor*>(_self); int ml_flags = self->method->ml_flags; int call_flags = ml_flags & (~METH_CLASS); if (rewrite_args && !rewrite_args->func_guarded) { rewrite_args->obj->addAttrGuard(offsetof(BoxedMethodDescriptor, method), (intptr_t)self->method); } ParamReceiveSpec paramspec(0, 0, false, false); if (call_flags == METH_NOARGS) { paramspec = ParamReceiveSpec(1, 0, false, false); } else if (call_flags == METH_VARARGS) { paramspec = ParamReceiveSpec(1, 0, true, false); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { paramspec = ParamReceiveSpec(1, 0, true, true); } else if (call_flags == METH_O) { paramspec = ParamReceiveSpec(2, 0, false, false); } else { RELEASE_ASSERT(0, "0x%x", call_flags); } Box* oarg1 = NULL; Box* oarg2 = NULL; Box* oarg3 = NULL; Box** oargs = NULL; bool rewrite_success = false; rearrangeArguments(paramspec, NULL, self->method->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1, arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, args); if (!rewrite_success) rewrite_args = NULL; if (ml_flags & METH_CLASS) { rewrite_args = NULL; if (!isSubclass(oarg1->cls, type_cls)) raiseExcHelper(TypeError, "descriptor '%s' requires a type but received a '%s'", self->method->ml_name, getFullTypeName(oarg1).c_str()); } else { if (!isSubclass(oarg1->cls, self->type)) raiseExcHelper(TypeError, "descriptor '%s' requires a '%s' oarg1 but received a '%s'", self->method->ml_name, getFullNameOfClass(self->type).c_str(), getFullTypeName(oarg1).c_str()); } if (rewrite_args) { rewrite_args->arg1->addAttrGuard(offsetof(Box, cls), (intptr_t)oarg1->cls); } Box* rtn; if (call_flags == METH_NOARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->method->ml_meth(oarg1, NULL); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->rewriter->loadConst(0, Location::forArg(1))); } else if (call_flags == METH_VARARGS) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->method->ml_meth(oarg1, oarg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->arg2); } else if (call_flags == (METH_VARARGS | METH_KEYWORDS)) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)((PyCFunctionWithKeywords)self->method->ml_meth)(oarg1, oarg2, oarg3); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3); } else if (call_flags == METH_O) { { UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins"); rtn = (Box*)self->method->ml_meth(oarg1, oarg2); } if (rewrite_args) rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->arg2); } else { RELEASE_ASSERT(0, "0x%x", call_flags); } if (!rtn) throwCAPIException(); if (rewrite_args) { rewrite_args->rewriter->call(false, (void*)checkAndThrowCAPIException); rewrite_args->out_success = true; } return rtn; }