Skip to content

Commit 1ace62c

Browse files
committed
Optimize ints
1 parent 5466462 commit 1ace62c

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

mypyc/lib-rt/native_internal.c

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#define MAX_SHORT_LEN 127
1212
#define LONG_STR_TAG 1
1313

14-
#define MIN_SHORT_INT (-10)
14+
#define MIN_SHORT_INT -10
1515
#define MAX_SHORT_INT 117
1616
#define MEDIUM_INT_TAG 1
1717
#define LONG_INT_TAG 3
@@ -391,14 +391,21 @@ read_int_internal(PyObject *data) {
391391
if (_check_buffer(data) == 2)
392392
return CPY_INT_TAG;
393393

394-
if (_check_read((BufferObject *)data, sizeof(CPyTagged)) == 2)
395-
return CPY_INT_TAG;
396394
char *buf = ((BufferObject *)data)->buf;
395+
if (_check_read((BufferObject *)data, 1) == 2)
396+
return CPY_INT_TAG;
397397

398-
CPyTagged ret = *(CPyTagged *)(buf + ((BufferObject *)data)->pos);
399-
((BufferObject *)data)->pos += sizeof(CPyTagged);
400-
if ((ret & CPY_INT_TAG) == 0)
398+
uint8_t first = *(uint8_t *)(buf + ((BufferObject *)data)->pos);
399+
((BufferObject *)data)->pos += 1;
400+
if ((first & MEDIUM_INT_TAG) == 0) {
401+
return ((Py_ssize_t)(first >> 1) + MIN_SHORT_INT) << 1;
402+
}
403+
if (first == MEDIUM_INT_TAG) {
404+
CPyTagged ret = *(CPyTagged *)(buf + ((BufferObject *)data)->pos);
405+
((BufferObject *)data)->pos += sizeof(CPyTagged);
401406
return ret;
407+
}
408+
// first == LONG_INT_TAG
402409
// People who have literal ints not fitting in size_t should be punished :-)
403410
PyObject *str_ret = read_str_internal(data);
404411
if (str_ret == NULL)
@@ -426,17 +433,34 @@ write_int_internal(PyObject *data, CPyTagged value) {
426433
if (_check_buffer(data) == 2)
427434
return 2;
428435

429-
if (_check_size((BufferObject *)data, sizeof(CPyTagged)) == 2)
430-
return 2;
431-
char *buf = ((BufferObject *)data)->buf;
436+
char *buf;
432437
if ((value & CPY_INT_TAG) == 0) {
433-
*(CPyTagged *)(buf + ((BufferObject *)data)->pos) = value;
438+
Py_ssize_t real_value = CPyTagged_ShortAsSsize_t(value);
439+
if (real_value >= MIN_SHORT_INT && real_value <= MAX_SHORT_INT) {
440+
// Most common case: int that is small in absolute value.
441+
if (_check_size((BufferObject *)data, 1) == 2)
442+
return 2;
443+
buf = ((BufferObject *)data)->buf;
444+
*(uint8_t *)(buf + ((BufferObject *)data)->pos) = (uint8_t)(real_value - MIN_SHORT_INT) << 1;
445+
((BufferObject *)data)->pos += 1;
446+
((BufferObject *)data)->end += 1;
447+
} else {
448+
if (_check_size((BufferObject *)data, sizeof(CPyTagged) + 1) == 2)
449+
return 2;
450+
buf = ((BufferObject *)data)->buf;
451+
*(uint8_t *)(buf + ((BufferObject *)data)->pos) = MEDIUM_INT_TAG;
452+
((BufferObject *)data)->pos += 1;
453+
*(CPyTagged *)(buf + ((BufferObject *)data)->pos) = value;
454+
((BufferObject *)data)->pos += sizeof(CPyTagged);
455+
((BufferObject *)data)->end += sizeof(CPyTagged) + 1;
456+
}
434457
} else {
435-
*(CPyTagged *)(buf + ((BufferObject *)data)->pos) = CPY_INT_TAG;
436-
}
437-
((BufferObject *)data)->pos += sizeof(CPyTagged);
438-
((BufferObject *)data)->end += sizeof(CPyTagged);
439-
if ((value & CPY_INT_TAG) != 0) {
458+
if (_check_size((BufferObject *)data, 1) == 2)
459+
return 2;
460+
buf = ((BufferObject *)data)->buf;
461+
*(uint8_t *)(buf + ((BufferObject *)data)->pos) = LONG_INT_TAG;
462+
((BufferObject *)data)->pos += 1;
463+
((BufferObject *)data)->end += 1;
440464
PyObject *str_value = PyObject_Str(CPyTagged_LongAsObject(value));
441465
if (str_value == NULL)
442466
return 2;

mypyc/test-data/run-classes.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,7 +2741,9 @@ def test_buffer_roundtrip() -> None:
27412741
write_tag(b, TAG_B)
27422742
write_int(b, 2)
27432743
write_int(b, 2 ** 85)
2744+
write_int(b, 255)
27442745
write_int(b, -1)
2746+
write_int(b, -255)
27452747

27462748
b = Buffer(b.getvalue())
27472749
assert read_str(b) == "foo"
@@ -2756,7 +2758,9 @@ def test_buffer_roundtrip() -> None:
27562758
assert read_tag(b) == TAG_B
27572759
assert read_int(b) == 2
27582760
assert read_int(b) == 2 ** 85
2761+
assert read_int(b) == 255
27592762
assert read_int(b) == -1
2763+
assert read_int(b) == -255
27602764

27612765
[file driver.py]
27622766
from native import *
@@ -2782,7 +2786,9 @@ def test_buffer_roundtrip_interpreted() -> None:
27822786
write_tag(b, 255)
27832787
write_int(b, 2)
27842788
write_int(b, 2 ** 85)
2789+
write_int(b, 255)
27852790
write_int(b, -1)
2791+
write_int(b, -255)
27862792

27872793
b = Buffer(b.getvalue())
27882794
assert read_str(b) == "foo"
@@ -2797,7 +2803,9 @@ def test_buffer_roundtrip_interpreted() -> None:
27972803
assert read_tag(b) == 255
27982804
assert read_int(b) == 2
27992805
assert read_int(b) == 2 ** 85
2806+
assert read_int(b) == 255
28002807
assert read_int(b) == -1
2808+
assert read_int(b) == -255
28012809

28022810
test_buffer_basic_interpreted()
28032811
test_buffer_roundtrip_interpreted()

0 commit comments

Comments
 (0)