/* * This function returns a NEW reference, i.e. caller must decref it in the end. */ inline PyObject* JyNI_AllocVar(TypeMapEntry* tme, Py_ssize_t nitems) { size_t size = (tme->flags & JY_TRUNCATE_FLAG_MASK) ? sizeof(PyVarObject)+tme->truncate_trailing : _PyObject_VAR_SIZE(tme->py_type, nitems+1); // note that we need to add one, for the sentinel /* JyNI note: What if the allocated object is not var size? * At the end of this method happens a decision, whether to use * PyObject_INIT(obj, tme->py_type); * or * (void) PyObject_INIT_VAR((PyVarObject *)obj, tme->py_type, nitems); * * This shows that the original method PyType_GenericAlloc was also * intended for non var size objects. I suspect that nitems == 0 should * indicate that an object is not var size; _PyObject_VAR_SIZE seems to * behave like _PyObject_SIZE for nitems == 0. Unfortunately this sentinel * thing adds 1 to nitems, also if nitems == 0. So nitems == -1 would in * fact indicate a non var size object. I wonder whether this is intended * or whether there should be a decision like nitems == 0 ? 0 : nitems + 1 * For now I keep it unchanged to stick to original behavior and implement * JyNI_Alloc for fixed size objects. */ ALLOC_FULL(size, tme->flags, tme, tme->py_type) INIT_FULL(obj, tme->py_type, nitems) return obj; }
static PyObject* QtGuiObject_alloc(PyTypeObject *type, Py_ssize_t nitems) { PyObject *obj; const size_t size = _PyObject_VAR_SIZE(type, nitems+1); /* note that we need to add one, for the sentinel */ if (PyType_IS_GC(type)) obj = _PyObject_GC_Malloc(size); else obj = (PyObject *)PyObject_MALLOC(size); if (obj == NULL) return PyErr_NoMemory(); // This is why we need this custom alloc: To call the C++ constructor. memset(obj, '\0', size); new ((PyQtGuiObject*) obj) PyQtGuiObject(); if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_INCREF(type); if (type->tp_itemsize == 0) PyObject_INIT(obj, type); else (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); if (PyType_IS_GC(type)) _PyObject_GC_TRACK(obj); return obj; }
/* * This function returns a NEW reference, i.e. caller must decref it in the end. */ inline PyObject* JyNI_AllocSubtypeVar(PyTypeObject* subtype, TypeMapEntry* tme, Py_ssize_t nitems) { // jputs(__FUNCTION__); // jputs(subtype->tp_name); /* * In subtype-case we cannot save any memory by truncation, because the subtype-code might depend * on all memory positions including the type field, i.e. the beginning. * So eventually (i.e. if (tme->flags & JY_TRUNCATE_FLAG_MASK)) we have unused memory between the * positions * * obj + sizeof(PyVarObject)+tme->truncate_trailing * * and * * obj + _PyObject_VAR_SIZE(tme->py_type, nitems+1) * * For now this memory is just wasted. Maybe we can return the unused section to the Python memory * manager one day. It would be -however- an effort then to get malloc and clean right. Especially * if the surrounding blocks are freed while the middle is still in use. On the other hand it might * be a rarely needed feature, so might not be worth any further optimization. */ size_t size = _PyObject_VAR_SIZE(subtype, nitems+1); /* note that we need to add one, for the sentinel */ ALLOC_FULL(size, tme->flags, tme, tme->py_type) INIT_FULL(obj, subtype, nitems) return obj; }
PyVarObject * _PyObject_GC_NewVar(PyTypeObject *tp, int nitems) { const size_t size = _PyObject_VAR_SIZE(tp, nitems); PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(size); if (op != NULL) op = PyObject_INIT_VAR(op, tp, nitems); return op; }
PyVarObject * _PyObject_NewVar(PyTypeObject *tp, int nitems) { PyVarObject *op; const size_t size = _PyObject_VAR_SIZE(tp, nitems); op = (PyVarObject *) PyObject_MALLOC(size); if (op == NULL) return (PyVarObject *)PyErr_NoMemory(); return PyObject_INIT_VAR(op, tp, nitems); }
/* * This function returns a NEW reference, i.e. caller must decref it in the end. * Note that the resulting object is tracked by gc, but not yet explored. Though * JyNI is robust against this, it is cleaner and more efficient if objects are * explicitly explored by gc after they were created and fully populated. * Use JyNI_GC_Explore(PyObject* op) to let gc explore an object. Exploration * is not performed on GC_TRACK, because often the values of the object are not * yet populated at that time. */ inline PyObject* JyNI_AllocNativeVar(PyTypeObject* type, Py_ssize_t nitems) { size_t size = _PyObject_VAR_SIZE(type, nitems+1); /* note that we need to add one, for the sentinel */ ALLOC_FULL(size, JY_CPEER_FLAG_MASK, NULL, type) INIT_FULL(obj, type, nitems) return obj; }
PyVarObject * _PyObject_GC_Resize(PyVarObject *op, int nitems) { const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems); PyGC_Head *g = AS_GC(op); g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); if (g == NULL) return (PyVarObject *)PyErr_NoMemory(); op = (PyVarObject *) FROM_GC(g); op->ob_size = nitems; return op; }
PyVarObject * _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); if (g == NULL) return (PyVarObject *)PyErr_NoMemory(); op = (PyVarObject *) FROM_GC(g); Py_SIZE(op) = nitems; return op; }
/* Print summary info about the state of the optimized allocator */ void _PyTuple_DebugMallocStats(FILE *out) { #if PyTuple_MAXSAVESIZE > 0 int i; char buf[128]; for (i = 1; i < PyTuple_MAXSAVESIZE; i++) { PyOS_snprintf(buf, sizeof(buf), "free %d-sized PyTupleObject", i); _PyDebugAllocatorStats(out, buf, numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i)); } #endif }
PyObject * Base_getattro(PyObject *obj, PyObject *name) { /* This is a modified copy of PyObject_GenericGetAttr. See the change note below. */ PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; long dictoffset; PyObject **dictptr; if (!PyString_Check(name)){ #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return NULL; } else #endif { PyErr_SetString(PyExc_TypeError, "attribute name must be string"); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } #if !defined(Py_TPFLAGS_HAVE_VERSION_TAG) /* Inline _PyType_Lookup */ /* this is not quite _PyType_Lookup anymore */ { int i, n; PyObject *mro, *base, *dict; /* Look in tp_dict of types in MRO */ mro = tp->tp_mro; assert(mro != NULL); assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); descr = PyDict_GetItem(dict, name); if (descr != NULL) break; } } #else descr = _PyType_Lookup(tp, name); #endif Py_XINCREF(descr); f = NULL; if (descr != NULL && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } } /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { PyObject *dict; if (dictoffset < 0) { int tsize; size_t size; tsize = ((PyVarObject *)obj)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(tp, tsize); dictoffset += (long)size; assert(dictoffset > 0); assert(dictoffset % SIZEOF_VOID_P == 0); } dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { Py_INCREF(dict); res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); Py_DECREF(dict); /* CHANGED! If the tp_descr_get of res is of_get, then call it. */ if ((strcmp(PyString_AsString(name), "__parent__") != 0) && PyObject_TypeCheck(res->ob_type, &ExtensionClassType) && res->ob_type->tp_descr_get != NULL) { PyObject *tres; tres = res->ob_type->tp_descr_get( res, obj, OBJECT(obj->ob_type)); Py_DECREF(res); res = tres; } goto done; } Py_DECREF(dict); } } if (f != NULL) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; /* descr was already increfed above */ goto done; } /* CHANGED: Just use the name. Don't format. */ PyErr_SetObject(PyExc_AttributeError, name); done: Py_DECREF(name); return res; }
PyObject *LOOKUP_ATTRIBUTE_CLASS_SLOT(PyObject *source) { CHECK_OBJECT(source); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, const_str_plain___class__); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, const_str_plain___class__); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyInstanceObject *source_instance = (PyInstanceObject *)source; PyObject *result = (PyObject *)source_instance->in_class; Py_INCREF(result); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, const_str_plain___class__); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)"__class__"); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '__class__'", type->tp_name); return NULL; } }
PyObject *LOOKUP_ATTRIBUTE(PyObject *source, PyObject *attr_name) { /* Note: There are 2 specializations of this function, that need to be * updated in line with this: LOOKUP_ATTRIBUTE_[DICT|CLASS]_SLOT */ CHECK_OBJECT(source); CHECK_OBJECT(attr_name); PyTypeObject *type = Py_TYPE(source); if (type->tp_getattro == PyObject_GenericGetAttr) { // Unfortunately this is required, although of cause rarely necessary. if (unlikely(type->tp_dict == NULL)) { if (unlikely(PyType_Ready(type) < 0)) { return NULL; } } PyObject *descr = _PyType_Lookup(type, attr_name); descrgetfunc func = NULL; if (descr != NULL) { Py_INCREF(descr); #if PYTHON_VERSION < 300 if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS)) { #endif func = Py_TYPE(descr)->tp_descr_get; if (func != NULL && PyDescr_IsData(descr)) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); return result; } #if PYTHON_VERSION < 300 } #endif } Py_ssize_t dictoffset = type->tp_dictoffset; PyObject *dict = NULL; if (dictoffset != 0) { // Negative dictionary offsets have special meaning. if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)source)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(type, tsize); dictoffset += (long)size; } PyObject **dictptr = (PyObject **)((char *)source + dictoffset); dict = *dictptr; } if (dict != NULL) { CHECK_OBJECT(dict); Py_INCREF(dict); PyObject *result = PyDict_GetItem(dict, attr_name); if (result != NULL) { Py_INCREF(result); Py_XDECREF(descr); Py_DECREF(dict); CHECK_OBJECT(result); return result; } Py_DECREF(dict); } if (func != NULL) { PyObject *result = func(descr, source, (PyObject *)type); Py_DECREF(descr); CHECK_OBJECT(result); return result; } if (descr != NULL) { CHECK_OBJECT(descr); return descr; } #if PYTHON_VERSION < 300 PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, PyString_AS_STRING(attr_name)); #else PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%U'", type->tp_name, attr_name); #endif return NULL; } #if PYTHON_VERSION < 300 else if (type->tp_getattro == PyInstance_Type.tp_getattro) { PyObject *result = LOOKUP_INSTANCE(source, attr_name); return result; } #endif else if (type->tp_getattro != NULL) { PyObject *result = (*type->tp_getattro)(source, attr_name); if (unlikely(result == NULL)) { return NULL; } CHECK_OBJECT(result); return result; } else if (type->tp_getattr != NULL) { PyObject *result = (*type->tp_getattr)(source, (char *)Nuitka_String_AsString_Unchecked(attr_name)); return result; } else { PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type->tp_name, Nuitka_String_AsString_Unchecked(attr_name)); return NULL; } }
PyObject * PyObject_GenericGetAttr(PyObject *obj, PyObject *name) { PyTypeObject *tp = obj->ob_type; PyObject *descr = NULL; PyObject *res = NULL; descrgetfunc f; Py_ssize_t dictoffset; PyObject **dictptr; if (!PyString_Check(name)){ #ifdef Py_USING_UNICODE /* The Unicode to string conversion is done here because the existing tp_setattro slots expect a string object as name and we wouldn't want to break those. */ if (PyUnicode_Check(name)) { name = PyUnicode_AsEncodedString(name, NULL, NULL); if (name == NULL) return NULL; } else #endif { PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); return NULL; } } else Py_INCREF(name); if (tp->tp_dict == NULL) { if (PyType_Ready(tp) < 0) goto done; } /* Inline _PyType_Lookup */ { Py_ssize_t i, n; PyObject *mro, *base, *dict; /* Look in tp_dict of types in MRO */ mro = tp->tp_mro; assert(mro != NULL); assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { base = PyTuple_GET_ITEM(mro, i); if (PyClass_Check(base)) dict = ((PyClassObject *)base)->cl_dict; else { assert(PyType_Check(base)); dict = ((PyTypeObject *)base)->tp_dict; } assert(dict && PyDict_Check(dict)); descr = PyDict_GetItem(dict, name); if (descr != NULL) break; } } Py_XINCREF(descr); f = NULL; if (descr != NULL && PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) { f = descr->ob_type->tp_descr_get; if (f != NULL && PyDescr_IsData(descr)) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } } /* Inline _PyObject_GetDictPtr */ dictoffset = tp->tp_dictoffset; if (dictoffset != 0) { PyObject *dict; if (dictoffset < 0) { Py_ssize_t tsize; size_t size; tsize = ((PyVarObject *)obj)->ob_size; if (tsize < 0) tsize = -tsize; size = _PyObject_VAR_SIZE(tp, tsize); dictoffset += (long)size; assert(dictoffset > 0); assert(dictoffset % SIZEOF_VOID_P == 0); } dictptr = (PyObject **) ((char *)obj + dictoffset); dict = *dictptr; if (dict != NULL) { res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); Py_XDECREF(descr); goto done; } } } if (f != NULL) { res = f(descr, obj, (PyObject *)obj->ob_type); Py_DECREF(descr); goto done; } if (descr != NULL) { res = descr; /* descr was already increfed above */ goto done; } PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", tp->tp_name, PyString_AS_STRING(name)); done: Py_DECREF(name); return res; }