[issue4258] Use 30-bit digits instead of 15-bit digits for Python integers. - Code Review (original) (raw)

OLD

NEW

1

1

2 /* Write Python objects to files and read them back.

2 /* Write Python objects to files and read them back.

3 This is intended for writing and reading compiled Python code only;

3 This is intended for writing and reading compiled Python code only;

4 a true persistent storage facility would be much harder, since

4 a true persistent storage facility would be much harder, since

5 it would have to take circular links and sharing into account. */

5 it would have to take circular links and sharing into account. */

6

6

7 #define PY_SSIZE_T_CLEAN

7 #define PY_SSIZE_T_CLEAN

8

8

9 #include "Python.h"

9 #include "Python.h"

10 #include "longintrepr.h"

10 #include "longintrepr.h"

11 #include "code.h"

11 #include "code.h"

12 #include "marshal.h"

12 #include "marshal.h"

13

13

14 #define ABS(x) ((x) < 0 ? -(x) : (x))

15

14 /* High water mark to determine when the marshalled object is dangerously deep

16 /* High water mark to determine when the marshalled object is dangerously deep

15 * and risks coring the interpreter. When the object stack gets this deep,

17 * and risks coring the interpreter. When the object stack gets this deep,

16 * raise an exception instead of continuing.

18 * raise an exception instead of continuing.

17 * On Windows debug builds, reduce this value.

19 * On Windows debug builds, reduce this value.

18 */

20 */

19 #if defined(MS_WINDOWS) && defined(_DEBUG)

21 #if defined(MS_WINDOWS) && defined(_DEBUG)

20 #define MAX_MARSHAL_STACK_DEPTH 1500

22 #define MAX_MARSHAL_STACK_DEPTH 1500

21 #else

23 #else

22 #define MAX_MARSHAL_STACK_DEPTH 2000

24 #define MAX_MARSHAL_STACK_DEPTH 2000

23 #endif

25 #endif

(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading...

115

117

116 #if SIZEOF_LONG > 4

118 #if SIZEOF_LONG > 4

117 static void

119 static void

118 w_long64(long x, WFILE *p)

120 w_long64(long x, WFILE *p)

119 {

121 {

120 w_long(x, p);

122 w_long(x, p);

121 w_long(x>>32, p);

123 w_long(x>>32, p);

122 }

124 }

123 #endif

125 #endif

124

126

127 /* We assume that Python longs are stored internally in base some power of

128 2**15; for the sake of portability we'll always read and write them in base

129 exactly 2**15. */

130

131 #define PyLong_MARSHAL_SHIFT 15

132 #define PyLong_MARSHAL_BASE ((short)1 << PyLong_MARSHAL_SHIFT)

133 #define PyLong_MARSHAL_MASK (PyLong_MARSHAL_BASE - 1)

134 #if PyLong_SHIFT % PyLong_MARSHAL_SHIFT != 0

135 #error "PyLong_SHIFT must be a multiple of PyLong_MARSHAL_SHIFT"

136 #endif

137 #define PyLong_MARSHAL_RATIO (PyLong_SHIFT / PyLong_MARSHAL_SHIFT)

138

139 static void

140 w_PyLong(const PyLongObject *ob, WFILE *p)

141 {

142 Py_ssize_t i, j, n, l;

143 digit d;

144

145 w_byte(TYPE_LONG, p);

146 if (Py_SIZE(ob) == 0) {

147 w_long((long)0, p);

148 return;

149 }

150

151 /* set l to number of base PyLong_MARSHAL_BASE digits */

152 n = ABS(Py_SIZE(ob));

153 l = (n-1) * PyLong_MARSHAL_RATIO;

154 d = ob->ob_digit[n-1];

155 assert(d != 0); /* a PyLong is always normalized */

156 do {

157 d >>= PyLong_MARSHAL_SHIFT;

158 l++;

159 } while (d != 0);

160 w_long((long)(Py_SIZE(ob) > 0 ? l : -l), p);

161

162 for (i=0; i < n-1; i++) {

163 d = ob->ob_digit[i];

164 for (j=0; j < PyLong_MARSHAL_RATIO; j++) {

165 w_short(d & PyLong_MARSHAL_MASK, p);

166 d >>= PyLong_MARSHAL_SHIFT;

167 }

168 assert (d == 0);

169 }

170 d = ob->ob_digit[n-1];

171 do {

172 w_short(d & PyLong_MARSHAL_MASK, p);

173 d >>= PyLong_MARSHAL_SHIFT;

174 } while (d != 0);

175 }

176

125 static void

177 static void

126 w_object(PyObject *v, WFILE *p)

178 w_object(PyObject *v, WFILE *p)

127 {

179 {

128 Py_ssize_t i, n;

180 Py_ssize_t i, n;

129

181

130 p->depth++;

182 p->depth++;

131

183

132 if (p->depth > MAX_MARSHAL_STACK_DEPTH) {

184 if (p->depth > MAX_MARSHAL_STACK_DEPTH) {

133 p->error = 2;

185 p->error = 2;

134 }

186 }

(...skipping 13 matching lines...) Expand all Loading...

148 w_byte(TYPE_FALSE, p);

200 w_byte(TYPE_FALSE, p);

149 }

201 }

150 else if (v == Py_True) {

202 else if (v == Py_True) {

151 w_byte(TYPE_TRUE, p);

203 w_byte(TYPE_TRUE, p);

152 }

204 }

153 else if (PyLong_CheckExact(v)) {

205 else if (PyLong_CheckExact(v)) {

154 long x = PyLong_AsLong(v);

206 long x = PyLong_AsLong(v);

155 if ((x == -1) && PyErr_Occurred()) {

207 if ((x == -1) && PyErr_Occurred()) {

156 PyLongObject *ob = (PyLongObject *)v;

208 PyLongObject *ob = (PyLongObject *)v;

157 PyErr_Clear();

209 PyErr_Clear();

158 » » » w_byte(TYPE_LONG, p);

210 » » » w_PyLong(ob, p);

159 » » » n = Py_SIZE(ob);

211 » » }

160 » » » w_long((long)n, p);

161 » » » if (n < 0)

162 » » » » n = -n;

163 » » » for (i = 0; i < n; i++)

164 » » » » w_short(ob->ob_digit[i], p);

165 » » }·

166 else {

212 else {

167 #if SIZEOF_LONG > 4

213 #if SIZEOF_LONG > 4

168 long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);

214 long y = Py_ARITHMETIC_RIGHT_SHIFT(long, x, 31);

169 if (y && y != -1) {

215 if (y && y != -1) {

170 w_byte(TYPE_INT64, p);

216 w_byte(TYPE_INT64, p);

171 w_long64(x, p);

217 w_long64(x, p);

172 }

218 }

173 else

219 else

174 #endif

220 #endif

175 {

221 {

(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading...

474 }

520 }

475 else {

521 else {

476 memcpy(buf, &hi4, 4);

522 memcpy(buf, &hi4, 4);

477 memcpy(buf+4, &lo4, 4);

523 memcpy(buf+4, &lo4, 4);

478 }

524 }

479 return _PyLong_FromByteArray(buf, 8, is_little_endian, 1);

525 return _PyLong_FromByteArray(buf, 8, is_little_endian, 1);

480 #endif

526 #endif

481 }

527 }

482

528

483 static PyObject *

529 static PyObject *

530 r_PyLong(RFILE *p)

531 {

532 PyLongObject *ob;

533 int size, i, j, md;

534 long n;

535 digit d;

536

537 n = r_long(p);

538 if (n == 0)

539 return (PyObject *)_PyLong_New(0);

540 if (n < -INT_MAX || n > INT_MAX)

541 goto bad_data;

542

543 size = 1 + (ABS(n)-1) / PyLong_MARSHAL_RATIO;

544 ob = _PyLong_New(size);

545 if (ob == NULL)

546 return NULL;

547 Py_SIZE(ob) = n > 0 ? size : -size;

548

549 for (i = 0; i < size-1; i++) {

550 d = 0;

551 for (j=0; j < PyLong_MARSHAL_RATIO; j++) {

552 md = r_short(p);

553 if (md < 0 || md > PyLong_MARSHAL_BASE) {

554 Py_DECREF(ob);

555 goto bad_data;

556 }

557 d += (digit)md << j*PyLong_MARSHAL_SHIFT;

558 }

559 ob->ob_digit[i] = d;

560 }

561 d = 0;

562 for (j=0; j < (ABS(n)-1)%PyLong_MARSHAL_RATIO + 1; j++) {

563 md = r_short(p);

564 if (md < 0 || md > PyLong_MARSHAL_BASE) {

565 Py_DECREF(ob);

566 goto bad_data;

567 }

568 d += (digit)md << (j*PyLong_MARSHAL_SHIFT);

569 }

570 ob->ob_digit[size-1] = d;

571 return (PyObject *)ob;

572 bad_data:

573 PyErr_SetString(PyExc_ValueError, "bad marshal data");

574 return NULL;

575 }

576

577

578 static PyObject *

484 r_object(RFILE *p)

579 r_object(RFILE *p)

485 {

580 {

486 /* NULL is a valid return value, it does not necessarily means that

581 /* NULL is a valid return value, it does not necessarily means that

487 an exception is set. */

582 an exception is set. */

488 PyObject *v, *v2;

583 PyObject *v, *v2;

489 long i, n;

584 long i, n;

490 int type = r_byte(p);

585 int type = r_byte(p);

491 PyObject *retval;

586 PyObject *retval;

492

587

493 p->depth++;

588 p->depth++;

(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading...

537

632

538 case TYPE_INT:

633 case TYPE_INT:

539 retval = PyLong_FromLong(r_long(p));

634 retval = PyLong_FromLong(r_long(p));

540 break;

635 break;

541

636

542 case TYPE_INT64:

637 case TYPE_INT64:

543 retval = r_long64(p);

638 retval = r_long64(p);

544 break;

639 break;

545

640

546 case TYPE_LONG:

641 case TYPE_LONG:

547 » » {

642 » » retval = r_PyLong(p);

548 » » » int size;

643 » » break;

549 » » » PyLongObject *ob;

550 » » » n = r_long(p);

551 » » » if (n < -INT_MAX || n > INT_MAX) {

552 » » » » PyErr_SetString(PyExc_ValueError,

553 » » » » » » "bad marshal data");

554 » » » » retval = NULL;

555 » » » » break;

556 » » » }

557 » » » size = n<0 ? -n : n;

558 » » » ob = _PyLong_New(size);

559 » » » if (ob == NULL) {

560 » » » » retval = NULL;

561 » » » » break;

562 » » » }

563 » » » Py_SIZE(ob) = n;

564 » » » for (i = 0; i < size; i++) {

565 » » » » int digit = r_short(p);

566 » » » » if (digit < 0) {

567 » » » » » Py_DECREF(ob);

568 » » » » » PyErr_SetString(PyExc_ValueError,

569 » » » » » » » "bad marshal data");

570 » » » » » ob = NULL;

571 » » » » » break;

572 » » » » }

573 » » » » if (ob != NULL)

574 » » » » » ob->ob_digit[i] = digit;

575 » » » }

576 » » » retval = (PyObject *)ob;

577 » » » break;

578 » » }

579

644

580 case TYPE_FLOAT:

645 case TYPE_FLOAT:

581 {

646 {

582 char buf[256];

647 char buf[256];

583 double dx;

648 double dx;

584 n = r_byte(p);

649 n = r_byte(p);

585 if (n == EOF || r_string(buf, (int)n, p) != n) {

650 if (n == EOF || r_string(buf, (int)n, p) != n) {

586 PyErr_SetString(PyExc_EOFError,

651 PyErr_SetString(PyExc_EOFError,

587 "EOF read where object expected");

652 "EOF read where object expected");

588 retval = NULL;

653 retval = NULL;

(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading...

1211

1276

1212 PyMODINIT_FUNC

1277 PyMODINIT_FUNC

1213 PyMarshal_Init(void)

1278 PyMarshal_Init(void)

1214 {

1279 {

1215 PyObject *mod = PyModule_Create(&marshalmodule);

1280 PyObject *mod = PyModule_Create(&marshalmodule);

1216 if (mod == NULL)

1281 if (mod == NULL)

1217 return NULL;

1282 return NULL;

1218 PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION);

1283 PyModule_AddIntConstant(mod, "version", Py_MARSHAL_VERSION);

1219 return mod;

1284 return mod;

1220 }

1285 }

OLD

NEW