[pypy-commit] pypy cpyext-ext: define/modify for upstream compatibity PyMem_Malloc, PyStringObject, _Py_HashDouble

mattip noreply at buildbot.pypy.org
Thu Nov 26 18:55:14 EST 2015


Author: mattip <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r80981:c114f7d51108
Date: 2015-11-27 01:55 +0200
http://bitbucket.org/pypy/pypy/changeset/c114f7d51108/

Log:	define/modify for upstream compatibity PyMem_Malloc, PyStringObject,
	_Py_HashDouble

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -1056,6 +1056,7 @@
                                source_dir / "pythread.c",
                                source_dir / "ndarrayobject.c",
                                source_dir / "missing.c",
+                               source_dir / "pymem.c",
                                ],
         separate_module_sources=separate_module_sources,
         compile_extra=compile_extra,
diff --git a/pypy/module/cpyext/include/pymem.h b/pypy/module/cpyext/include/pymem.h
--- a/pypy/module/cpyext/include/pymem.h
+++ b/pypy/module/cpyext/include/pymem.h
@@ -5,7 +5,7 @@
 #define PyMem_REALLOC(p, n)	realloc((p), (n) ? (n) : 1)
 #define PyMem_FREE		free
 
-#define PyMem_Malloc PyMem_MALLOC
+void * PyMem_Malloc(size_t);
 #define PyMem_Free  PyMem_FREE
 #define PyMem_Realloc  PyMem_REALLOC
 
diff --git a/pypy/module/cpyext/include/pyport.h b/pypy/module/cpyext/include/pyport.h
--- a/pypy/module/cpyext/include/pyport.h
+++ b/pypy/module/cpyext/include/pyport.h
@@ -64,6 +64,14 @@
 #   error "Python needs a typedef for Py_uintptr_t in pyport.h."
 #endif /* HAVE_UINTPTR_T */
 
+/* Py_hash_t is the same size as a pointer. */
+#define SIZEOF_PY_HASH_T SIZEOF_SIZE_T
+typedef Py_ssize_t Py_hash_t;
+/* Py_uhash_t is the unsigned equivalent needed to calculate numeric hash. */
+#define SIZEOF_PY_UHASH_T SIZEOF_SIZE_T
+typedef size_t Py_uhash_t;
+
+
 /*******************************
  * stat() and fstat() fiddling *
  *******************************/
diff --git a/pypy/module/cpyext/include/stringobject.h b/pypy/module/cpyext/include/stringobject.h
--- a/pypy/module/cpyext/include/stringobject.h
+++ b/pypy/module/cpyext/include/stringobject.h
@@ -7,15 +7,59 @@
 extern "C" {
 #endif
 
+#include <stdarg.h>
+
+/*
+Type PyStringObject represents a character string.  An extra zero byte is
+reserved at the end to ensure it is zero-terminated, but a size is
+present so strings with null bytes in them can be represented.  This
+is an immutable object type.
+
+There are functions to create new string objects, to test
+an object for string-ness, and to get the
+string value.  The latter function returns a null pointer
+if the object is not of the proper type.
+There is a variant that takes an explicit size as well as a
+variant that assumes a zero-terminated string.  Note that none of the
+functions should be applied to nil objects.
+*/
+
+/* Caching the hash (ob_shash) saves recalculation of a string's hash value.
+   Interning strings (ob_sstate) tries to ensure that only one string
+   object with a given value exists, so equality tests can be one pointer
+   comparison.  This is generally restricted to strings that "look like"
+   Python identifiers, although the intern() builtin can be used to force
+   interning of any string.
+   Together, these sped cpython up by up to 20%, and since they are part of the
+   "public" interface PyPy must reimpliment them. */
+
+
 #define PyString_GET_SIZE(op) PyString_Size(op)
 #define PyString_AS_STRING(op) PyString_AsString(op)
 
 typedef struct {
     PyObject_HEAD
-    char* buffer;
+    long ob_shash;
+    int ob_sstate;
+    char * buffer;
     Py_ssize_t size;
+
+    /* Invariants:
+     *     ob_sval contains space for 'ob_size+1' elements.
+     *     ob_sval[ob_size] == 0.
+     *     ob_shash is the hash of the string or -1 if not computed yet.
+     *     ob_sstate != 0 iff the string object is in stringobject.c's
+     *       'interned' dictionary; in this case the two references
+     *       from 'interned' to this object are *not counted* in ob_refcnt.
+     */
+
 } PyStringObject;
 
+#define SSTATE_NOT_INTERNED 0
+#define SSTATE_INTERNED_MORTAL 1
+#define SSTATE_INTERNED_IMMORTAL 2
+#define PyString_CHECK_INTERNED(op) (((PyStringObject *)(op))->ob_sstate)
+
 PyAPI_FUNC(PyObject *) PyString_FromFormatV(const char *format, va_list vargs);
 PyAPI_FUNC(PyObject *) PyString_FromFormat(const char *format, ...);
 
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -387,6 +387,11 @@
     This is the equivalent of the Python expression hash(o)."""
     return space.int_w(space.hash(w_obj))
 
+ at cpython_api([rffi.LONG], rffi.DOUBLE, error=-1)
+def _Py_HashDouble(space, w_obj):
+    raise OperationError(space.w_NotImplementedError, 
+                space.wrap("_Py_HashDouble not implemented yet"))
+
 @cpython_api([PyObject], lltype.Signed, error=-1)
 def PyObject_HashNotImplemented(space, o):
     """Set a TypeError indicating that type(o) is not hashable and return -1.
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -53,7 +53,8 @@
 PyStringObjectStruct = lltype.ForwardReference()
 PyStringObject = lltype.Ptr(PyStringObjectStruct)
 PyStringObjectFields = PyObjectFields + \
-    (("buffer", rffi.CCHARP), ("size", Py_ssize_t))
+    (("ob_shash", rffi.LONG), ("ob_sstate", rffi.INT), 
+     ("buffer", rffi.CCHARP), ("size", Py_ssize_t))
 cpython_struct("PyStringObject", PyStringObjectFields, PyStringObjectStruct)
 
 @bootstrap_function
@@ -81,6 +82,7 @@
     py_str.c_size = length
     py_str.c_buffer = lltype.malloc(rffi.CCHARP.TO, buflen,
                                     flavor='raw', zero=True)
+    py_str.c_ob_sstate = 0 # SSTATE_NOT_INTERNED
     return py_str
 
 def string_attach(space, py_obj, w_obj):
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -173,6 +173,9 @@
             api.PyErr_Occurred() is space.w_TypeError)
         api.PyErr_Clear()
 
+    def test_hash_double(self, space, api):
+        assert False
+
     def test_type(self, space, api):
         assert api.PyObject_Type(space.wrap(72)) is space.w_int
 
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -189,6 +189,10 @@
         # This does not test much, but at least the refcounts are checked.
         assert module.test_intern_inplace('s') == 's'
 
+    def test_hash_and_state(self):
+        # XXX write tests for ob_shash and ob_sstate
+        assert False
+
 class TestString(BaseApiTest):
     def test_string_resize(self, space, api):
         py_str = new_empty_str(space, 10)


More information about the pypy-commit mailing list