NUITKA_MAY_BE_UNUSED static bool STRING_ADD_INCREMENTAL( PyObject **operand1, PyObject *operand2 ) { assert( PyString_CheckExact( *operand1 ) ); assert( !PyString_CHECK_INTERNED( *operand1 ) ); assert( PyString_CheckExact( operand2 ) ); Py_ssize_t operand1_size = PyString_GET_SIZE( *operand1 ); Py_ssize_t operand2_size = PyString_GET_SIZE( operand2 ); Py_ssize_t new_size = operand1_size + operand2_size; if (unlikely( new_size < 0 )) { PyErr_Format( PyExc_OverflowError, "strings are too large to concat" ); return false; } if (unlikely( STRING_RESIZE( operand1, new_size ) == false )) { return false; } memcpy( PyString_AS_STRING( *operand1 ) + operand1_size, PyString_AS_STRING( operand2 ), operand2_size ); return true; }
bool BINARY_OPERATION_ADD_STR_STR_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyString_CheckExact(*operand1)); assert(PyString_CheckExact(operand2)); if (!PyString_CHECK_INTERNED(*operand1) && Py_REFCNT(*operand1) == 1) { return STRING_ADD_INCREMENTAL(operand1, operand2); } PyString_Concat(operand1, operand2); return !ERROR_OCCURRED(); PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; }
extern "C" void PyString_InternInPlace(PyObject** p) noexcept { BoxedString* s = (BoxedString*)*p; if (s == NULL || !PyString_Check(s)) Py_FatalError("PyString_InternInPlace: strings only please!"); /* If it's a string subclass, we don't really know what putting it in the interned dict might do. */ if (!PyString_CheckExact(s)) return; if (PyString_CHECK_INTERNED(s)) return; auto it = interned_strings.find(s); if (it != interned_strings.end()) { auto entry = *it; Py_INCREF(entry); Py_DECREF(*p); *p = entry; } else { // TODO: do CPython's refcounting here num_interned_strings.log(); interned_strings.insert(s); Py_INCREF(s); // CPython returns mortal but in our current implementation they are inmortal s->interned_state = SSTATE_INTERNED_IMMORTAL; } }
/* This is implemented as a standalone function instead of the ``tp_new`` of ``stolenbuf`` because we need to create a function using the METH_O flag to support Python 3.6. In python 3.6, PyCFunction calls from python code now count the reference owned by the argument tuple. This would cause the object to have 2 references if used with a direct call like: ``stolenbuf(a)``; however, if called through *unpacking like ``stolenbuf(*(a,))`` it would only have the one reference (the tuple). */ static PyObject* move_into_mutable_buffer(PyObject *self, PyObject *bytes_rvalue) { stolenbufobject *ret; if (!PyString_CheckExact(bytes_rvalue)) { PyErr_SetString(PyExc_TypeError, "stolenbuf can only steal from bytes objects"); return NULL; } if (Py_REFCNT(bytes_rvalue) != 1 || PyString_CHECK_INTERNED(bytes_rvalue)) { /* there is a reference other than the caller's stack or the string is interned */ PyErr_SetObject(badmove, bytes_rvalue); return NULL; } if (!(ret = PyObject_New(stolenbufobject, &stolenbuf_type))) { return NULL; } /* store the original bytes object in a field that is not exposed to python */ Py_INCREF(bytes_rvalue); ret->invalid_bytes = bytes_rvalue; return (PyObject*) ret; }
void PyString_InternInPlace(PyObject **p) { LOG("> PyString_InternInPlace\n"); register PyStringObject *s = (PyStringObject *)(*p); PyObject *t; if (s == NULL || !PyString_Check(s)) Py_FatalError("PyString_InternInPlace: strings only please!"); if (interned == NULL) { interned = PyDict_New(); if (interned == NULL) { LOG("< PyString_InternInPlace\n"); return; } } if ((t = PyDict_GetItem(interned, (PyObject *)s)) !=NULL) { Py_INCREF(t); Py_DECREF(*p); *p = t; LOG("< PyString_InternInPlace\n"); return; } /* Ensure that only true string objects appear in the intern dict */ if (!PyString_CheckExact(s)) { t = PyString_FromStringAndSize(PyString_AS_STRING(s), PyString_GET_SIZE(s)); if (t == NULL) { /* ERROR */ return; } } else { t = (PyObject*) s; Py_INCREF(t); } if (PyDict_SetItem(interned, t, t) == 0) { ((PyObject *)t)->ob_refcnt-=2; PyString_CHECK_INTERNED(t) = SSTATE_INTERNED_MORTAL; Py_DECREF(*p); *p = t; LOG("< PyString_InternInPlace\n"); return; } Py_DECREF(t); LOG("< PyString_InternInPlace\n"); }
NUITKA_MAY_BE_UNUSED static bool BINARY_OPERATION_ADD_INPLACE( PyObject **operand1, PyObject *operand2 ) { assert( operand1 ); CHECK_OBJECT( *operand1 ); CHECK_OBJECT( operand2 ); #if PYTHON_VERSION < 300 // Something similar for Python3 should exist too. if ( PyInt_CheckExact( *operand1 ) && PyInt_CheckExact( operand2 ) ) { long a, b, i; a = PyInt_AS_LONG( *operand1 ); b = PyInt_AS_LONG( operand2 ); i = a + b; // Detect overflow, in which case, a "long" object would have to be // created, which we won't handle here. TODO: Add an else for that // case. if (likely(!( (i^a) < 0 && (i^b) < 0 ) )) { PyObject *result = PyInt_FromLong( i ); Py_DECREF( *operand1 ); *operand1 = result; return true; } } #endif #if PYTHON_VERSION < 300 if ( Py_REFCNT( *operand1 ) == 1 ) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. if ( PyString_CheckExact( *operand1 ) && !PyString_CHECK_INTERNED( *operand1 ) && PyString_CheckExact( operand2 ) ) { return STRING_ADD_INCREMENTAL( operand1, operand2 ); } else if ( PyFloat_CheckExact( *operand1 ) && PyFloat_CheckExact( operand2 ) ) { return FLOAT_ADD_INCREMENTAL( operand1, operand2 ); } } // Strings are to be treated differently. if ( PyString_CheckExact( *operand1 ) && PyString_CheckExact( operand2 ) ) { PyString_Concat( operand1, operand2 ); return !ERROR_OCCURRED(); } #else if ( Py_REFCNT( *operand1 ) == 1 ) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. if ( PyUnicode_CheckExact( *operand1 ) && !PyUnicode_CHECK_INTERNED( *operand1 ) && PyUnicode_CheckExact( operand2 ) ) { return UNICODE_ADD_INCREMENTAL( operand1, operand2 ); } else if ( PyFloat_CheckExact( *operand1 ) && PyFloat_CheckExact( operand2 ) ) { return FLOAT_ADD_INCREMENTAL( operand1, operand2 ); } } // Strings are to be treated differently. if ( PyUnicode_CheckExact( *operand1 ) && PyUnicode_CheckExact( operand2 ) ) { PyObject *result = PyUnicode_Concat( *operand1, operand2 ); if (unlikely( result == NULL )) { return false; } Py_DECREF( *operand1 ); *operand1 = result; return true; } #endif PyObject *result = PyNumber_InPlaceAdd( *operand1, operand2 ); if (unlikely( result == NULL )) { return false; } // We got an object handed, that we have to release. Py_DECREF( *operand1 ); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; }