diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2018-07-24 07:55:47 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-24 07:55:47 (GMT) |
commit | c5734998d91e9953fd179ba6ed7015b6343e8191 (patch) | |
tree | bec1c297d0facde44b327c079bf4ae9d0f19deac /Python/marshal.c | |
parent | e22072fb11246f125aa9ff7629c832b9e2407ef0 (diff) | |
download | cpython-c5734998d91e9953fd179ba6ed7015b6343e8191.zip cpython-c5734998d91e9953fd179ba6ed7015b6343e8191.tar.gz cpython-c5734998d91e9953fd179ba6ed7015b6343e8191.tar.bz2 |
bpo-33720: Refactor marshalling/unmarshalling floats. (GH-8071)
Diffstat (limited to 'Python/marshal.c')
-rw-r--r-- | Python/marshal.c | 181 |
1 files changed, 72 insertions, 109 deletions
diff --git a/Python/marshal.c b/Python/marshal.c index 6d06266..21cdd60 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -266,6 +266,32 @@ w_PyLong(const PyLongObject *ob, char flag, WFILE *p) } while (d != 0); } +static void +w_float_bin(double v, WFILE *p) +{ + unsigned char buf[8]; + if (_PyFloat_Pack8(v, buf, 1) < 0) { + p->error = WFERR_UNMARSHALLABLE; + return; + } + w_string((const char *)buf, 8, p); +} + +static void +w_float_str(double v, WFILE *p) +{ + int n; + char *buf = PyOS_double_to_string(v, 'g', 17, 0, NULL); + if (!buf) { + p->error = WFERR_NOMEMORY; + return; + } + n = (int)strlen(buf); + w_byte(n, p); + w_string(buf, n, p); + PyMem_Free(buf); +} + static int w_ref(PyObject *v, char *flag, WFILE *p) { @@ -375,69 +401,24 @@ w_complex_object(PyObject *v, char flag, WFILE *p) } else if (PyFloat_CheckExact(v)) { if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyFloat_AsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } W_TYPE(TYPE_BINARY_FLOAT, p); - w_string((char*)buf, 8, p); + w_float_bin(PyFloat_AS_DOUBLE(v), p); } else { - char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); W_TYPE(TYPE_FLOAT, p); - w_byte((int)n, p); - w_string(buf, n, p); - PyMem_Free(buf); + w_float_str(PyFloat_AS_DOUBLE(v), p); } } else if (PyComplex_CheckExact(v)) { if (p->version > 1) { - unsigned char buf[8]; - if (_PyFloat_Pack8(PyComplex_RealAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } W_TYPE(TYPE_BINARY_COMPLEX, p); - w_string((char*)buf, 8, p); - if (_PyFloat_Pack8(PyComplex_ImagAsDouble(v), - buf, 1) < 0) { - p->error = WFERR_UNMARSHALLABLE; - return; - } - w_string((char*)buf, 8, p); + w_float_bin(PyComplex_RealAsDouble(v), p); + w_float_bin(PyComplex_ImagAsDouble(v), p); } else { - char *buf; W_TYPE(TYPE_COMPLEX, p); - buf = PyOS_double_to_string(PyComplex_RealAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, n, p); - PyMem_Free(buf); - buf = PyOS_double_to_string(PyComplex_ImagAsDouble(v), - 'g', 17, 0, NULL); - if (!buf) { - p->error = WFERR_NOMEMORY; - return; - } - n = strlen(buf); - w_byte((int)n, p); - w_string(buf, n, p); - PyMem_Free(buf); + w_float_str(PyComplex_RealAsDouble(v), p); + w_float_str(PyComplex_ImagAsDouble(v), p); } } else if (PyBytes_CheckExact(v)) { @@ -880,6 +861,38 @@ r_PyLong(RFILE *p) return NULL; } +static double +r_float_bin(RFILE *p) +{ + const unsigned char *buf = (const unsigned char *) r_string(8, p); + if (buf == NULL) + return -1; + return _PyFloat_Unpack8(buf, 1); +} + +/* Issue #33720: Disable inlining for reducing the C stack consumption + on PGO builds. */ +_Py_NO_INLINE static double +r_float_str(RFILE *p) +{ + int n; + char buf[256]; + const char *ptr; + n = r_byte(p); + if (n == EOF) { + PyErr_SetString(PyExc_EOFError, + "EOF read where object expected"); + return -1; + } + ptr = r_string(n, p); + if (ptr == NULL) { + return -1; + } + memcpy(buf, ptr, n); + buf[n] = '\0'; + return PyOS_string_to_double(buf, NULL, NULL); +} + /* allocate the reflist index for a new object. Return -1 on failure */ static Py_ssize_t r_ref_reserve(int flag, RFILE *p) @@ -1016,36 +1029,17 @@ r_object(RFILE *p) case TYPE_FLOAT: { - char buf[256]; - const char *ptr; - double dx; - n = r_byte(p); - if (n == EOF) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - ptr = r_string(n, p); - if (ptr == NULL) - break; - memcpy(buf, ptr, n); - buf[n] = '\0'; - dx = PyOS_string_to_double(buf, NULL, NULL); - if (dx == -1.0 && PyErr_Occurred()) + double x = r_float_str(p); + if (x == -1.0 && PyErr_Occurred()) break; - retval = PyFloat_FromDouble(dx); + retval = PyFloat_FromDouble(x); R_REF(retval); break; } case TYPE_BINARY_FLOAT: { - const unsigned char *buf; - double x; - buf = (const unsigned char *) r_string(8, p); - if (buf == NULL) - break; - x = _PyFloat_Unpack8(buf, 1); + double x = r_float_bin(p); if (x == -1.0 && PyErr_Occurred()) break; retval = PyFloat_FromDouble(x); @@ -1055,35 +1049,11 @@ r_object(RFILE *p) case TYPE_COMPLEX: { - char buf[256]; - const char *ptr; Py_complex c; - n = r_byte(p); - if (n == EOF) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - ptr = r_string(n, p); - if (ptr == NULL) - break; - memcpy(buf, ptr, n); - buf[n] = '\0'; - c.real = PyOS_string_to_double(buf, NULL, NULL); + c.real = r_float_str(p); if (c.real == -1.0 && PyErr_Occurred()) break; - n = r_byte(p); - if (n == EOF) { - PyErr_SetString(PyExc_EOFError, - "EOF read where object expected"); - break; - } - ptr = r_string(n, p); - if (ptr == NULL) - break; - memcpy(buf, ptr, n); - buf[n] = '\0'; - c.imag = PyOS_string_to_double(buf, NULL, NULL); + c.imag = r_float_str(p); if (c.imag == -1.0 && PyErr_Occurred()) break; retval = PyComplex_FromCComplex(c); @@ -1093,18 +1063,11 @@ r_object(RFILE *p) case TYPE_BINARY_COMPLEX: { - const unsigned char *buf; Py_complex c; - buf = (const unsigned char *) r_string(8, p); - if (buf == NULL) - break; - c.real = _PyFloat_Unpack8(buf, 1); + c.real = r_float_bin(p); if (c.real == -1.0 && PyErr_Occurred()) break; - buf = (const unsigned char *) r_string(8, p); - if (buf == NULL) - break; - c.imag = _PyFloat_Unpack8(buf, 1); + c.imag = r_float_bin(p); if (c.imag == -1.0 && PyErr_Occurred()) break; retval = PyComplex_FromCComplex(c); |