diff --git a/from_cpython/Include/object.h b/from_cpython/Include/object.h index c842467c5..7b1e76b45 100644 --- a/from_cpython/Include/object.h +++ b/from_cpython/Include/object.h @@ -456,7 +456,7 @@ struct _typeobject { void* _hcls; void* _hcattrs; - char _ics[32]; + char _ics[40]; void* _gcvisit_func; int _attrs_offset; char _flags[7]; // These are bools in C++ diff --git a/from_cpython/Objects/unicodeobject.c b/from_cpython/Objects/unicodeobject.c index 1476d16ce..4c069ce9c 100644 --- a/from_cpython/Objects/unicodeobject.c +++ b/from_cpython/Objects/unicodeobject.c @@ -7221,15 +7221,20 @@ old replaced by new. If the optional argument count is\n\ given, only the first count occurrences are replaced."); static PyObject* -unicode_replace(PyUnicodeObject *self, PyObject *args) +// Pyston change: don't use varags calling convention +// unicode_replace(PyUnicodeObject *self, PyObject *args) +unicode_replace(PyUnicodeObject *self, PyUnicodeObject *str1, PyUnicodeObject* str2, PyObject** args) { - PyUnicodeObject *str1; - PyUnicodeObject *str2; + PyObject* _maxcount = args[0]; Py_ssize_t maxcount = -1; PyObject *result; - if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount)) + // Pyston change: don't use varags calling convention + // if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount)) + // return NULL; + if (_maxcount && !PyArg_ParseSingle(_maxcount, 3, "replace", "n", &maxcount)) return NULL; + str1 = (PyUnicodeObject *)PyUnicode_FromObject((PyObject *)str1); if (str1 == NULL) return NULL; @@ -7832,7 +7837,7 @@ unicode_getnewargs(PyUnicodeObject *v) static PyMethodDef unicode_methods[] = { {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, - {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__}, + {"replace", (PyCFunction) unicode_replace, METH_O3 | METH_D1, replace__doc__}, {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__}, {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__}, {"join", (PyCFunction) unicode_join, METH_O, join__doc__}, diff --git a/src/capi/typeobject.cpp b/src/capi/typeobject.cpp index e7ed0151e..42df37a8f 100644 --- a/src/capi/typeobject.cpp +++ b/src/capi/typeobject.cpp @@ -1012,24 +1012,26 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* return res; } else if (return_convention == ReturnConvention::NO_RETURN) { assert(!res); - } else if (return_convention == ReturnConvention::CAPI_RETURN) { + } else if (return_convention == ReturnConvention::CAPI_RETURN + || return_convention == ReturnConvention::NOEXC_POSSIBLE) { // If we get a CAPI return, we probably did a function call, and these guards // will probably just make the rewrite fail: if (res) { rtn->addGuardNotEq(0); rewrite_args->setReturn(rtn, ReturnConvention::HAS_RETURN); return res; - } else - rtn->addGuard(0); + } else { + // this could set a CAPI exception and we won't clear it inside the rewrite. + rewrite_args = 0; + } } else { - assert(return_convention == ReturnConvention::NOEXC_POSSIBLE); - rewrite_args = NULL; + RELEASE_ASSERT(0, ""); } } } else { try { assert(!PyType_Check(self)); // There would be a getattribute - res = getattrInternalGeneric(self, name, NULL, false, false, NULL, NULL); + res = getattrInternalGeneric(self, name, NULL, false, false, NULL, NULL); } catch (ExcInfo e) { if (!e.matches(AttributeError)) { if (S == CAPI) { diff --git a/src/runtime/list.cpp b/src/runtime/list.cpp index c445b16da..d0f8256c4 100644 --- a/src/runtime/list.cpp +++ b/src/runtime/list.cpp @@ -1273,7 +1273,6 @@ void setupList() { static PyMappingMethods list_as_mapping; list_cls->tp_as_mapping = &list_as_mapping; - list_cls->tp_iter = listIter; list_iterator_cls = BoxedClass::create(type_cls, object_cls, &BoxedListIterator::gcHandler, 0, 0, sizeof(BoxedListIterator), false, "listiterator"); list_reverse_iterator_cls = BoxedClass::create(type_cls, object_cls, &BoxedListIterator::gcHandler, 0, 0, @@ -1356,6 +1355,7 @@ void setupList() { list_cls->giveAttr("__hash__", None); list_cls->freeze(); + list_cls->tp_iter = listIter; list_cls->tp_as_sequence->sq_length = list_length; list_cls->tp_as_sequence->sq_concat = (binaryfunc)list_concat; diff --git a/src/runtime/objmodel.cpp b/src/runtime/objmodel.cpp index 92980fa1c..7eb2ed1c7 100644 --- a/src/runtime/objmodel.cpp +++ b/src/runtime/objmodel.cpp @@ -5728,8 +5728,7 @@ Box* getiter(Box* o) { if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_ITER) && type->tp_iter != slot_tp_iter && type->tp_iter) { r = type->tp_iter(o); } else { - static BoxedString* iter_str = internStringImmortal("__iter__"); - r = callattrInternal0(o, iter_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(0)); + r = type->callIterIC(o); } if (r) { if (!PyIter_Check(r)) { diff --git a/src/runtime/types.cpp b/src/runtime/types.cpp index fa0dc6dec..4d9270edd 100644 --- a/src/runtime/types.cpp +++ b/src/runtime/types.cpp @@ -290,6 +290,20 @@ Box* BoxedClass::callReprIC(Box* obj) { return ic->call(obj, repr_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr); } +Box* BoxedClass::callIterIC(Box* obj) { + assert(obj->cls == this); + + auto ic = iter_ic.get(); + if (!ic) { + ic = new CallattrIC(); + iter_ic.reset(ic); + } + + static BoxedString* iter_str = internStringImmortal("__iter__"); + CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) }; + return ic->call(obj, iter_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr); +} + bool BoxedClass::callNonzeroIC(Box* obj) { assert(obj->cls == this); diff --git a/src/runtime/types.h b/src/runtime/types.h index 55a29ad67..d96576822 100644 --- a/src/runtime/types.h +++ b/src/runtime/types.h @@ -194,11 +194,12 @@ class BoxedClass : public BoxVar { // TODO: these don't actually get deallocated right now std::unique_ptr next_ic; - std::unique_ptr hasnext_ic, repr_ic; + std::unique_ptr hasnext_ic, repr_ic, iter_ic; std::unique_ptr nonzero_ic; Box* callHasnextIC(Box* obj, bool null_on_nonexistent); Box* call_nextIC(Box* obj) noexcept; Box* callReprIC(Box* obj); + Box* callIterIC(Box* obj); bool callNonzeroIC(Box* obj); gcvisit_func gc_visit;