py: Extend nan-boxing config to have 47-bit small integers.
The nan-boxing representation has an extra 16-bits of space to store small-int values, and making use of it allows to create and manipulate full 32-bit positive integers (ie up to 0xffffffff) without using the heap.
This commit is contained in:
parent
9c02707356
commit
2759bec858
|
@ -79,7 +79,7 @@
|
|||
// - seeeeeee eeeeffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff 64-bit fp, e != 0x7ff
|
||||
// - s1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 +/- inf
|
||||
// - 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 normalised nan
|
||||
// - 01111111 11111101 00000000 00000000 iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int
|
||||
// - 01111111 11111101 iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int
|
||||
// - 01111111 11111110 00000000 00000000 qqqqqqqq qqqqqqqq qqqqqqqq qqqqqqq1 str
|
||||
// - 01111111 11111100 00000000 00000000 pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)
|
||||
// Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000.
|
||||
|
|
4
py/obj.h
4
py/obj.h
|
@ -170,8 +170,8 @@ static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
|
|||
|
||||
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)
|
||||
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0001000000000000); }
|
||||
#define MP_OBJ_SMALL_INT_VALUE(o) (((intptr_t)(o)) >> 1)
|
||||
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((uintptr_t)(small_int)) << 1) | 0x0001000000000001)
|
||||
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)((o) << 16)) >> 17)
|
||||
#define MP_OBJ_NEW_SMALL_INT(small_int) (((((uint64_t)(small_int)) & 0x7fffffffffff) << 1) | 0x0001000000000001)
|
||||
|
||||
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)
|
||||
{ return ((((mp_int_t)(o)) & 0xffff000000000000) == 0x0002000000000000); }
|
||||
|
|
18
py/parse.c
18
py/parse.c
|
@ -369,6 +369,18 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line,
|
|||
return (mp_parse_node_t)pn;
|
||||
}
|
||||
|
||||
STATIC mp_parse_node_t mp_parse_node_new_small_int_checked(parser_t *parser, mp_obj_t o_val) {
|
||||
(void)parser;
|
||||
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_val);
|
||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||
// A parse node is only 32-bits and the small-int value must fit in 31-bits
|
||||
if (((val ^ (val << 1)) & 0xffffffff80000000) != 0) {
|
||||
return make_node_const_object(parser, 0, o_val);
|
||||
}
|
||||
#endif
|
||||
return mp_parse_node_new_small_int(val);
|
||||
}
|
||||
|
||||
STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
|
||||
mp_parse_node_t pn;
|
||||
mp_lexer_t *lex = parser->lexer;
|
||||
|
@ -380,7 +392,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
|
|||
if (rule->rule_id == RULE_atom
|
||||
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
|
||||
if (MP_OBJ_IS_SMALL_INT(elem->value)) {
|
||||
pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
|
||||
pn = mp_parse_node_new_small_int_checked(parser, elem->value);
|
||||
} else {
|
||||
pn = make_node_const_object(parser, lex->tok_line, elem->value);
|
||||
}
|
||||
|
@ -394,7 +406,7 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
|
|||
} else if (lex->tok_kind == MP_TOKEN_INTEGER) {
|
||||
mp_obj_t o = mp_parse_num_integer(lex->vstr.buf, lex->vstr.len, 0, lex);
|
||||
if (MP_OBJ_IS_SMALL_INT(o)) {
|
||||
pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(o));
|
||||
pn = mp_parse_node_new_small_int_checked(parser, o);
|
||||
} else {
|
||||
pn = make_node_const_object(parser, lex->tok_line, o);
|
||||
}
|
||||
|
@ -686,7 +698,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
|
|||
pop_result(parser);
|
||||
}
|
||||
if (MP_OBJ_IS_SMALL_INT(arg0)) {
|
||||
push_result_node(parser, mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(arg0)));
|
||||
push_result_node(parser, mp_parse_node_new_small_int_checked(parser, arg0));
|
||||
} else {
|
||||
// TODO reuse memory for parse node struct?
|
||||
push_result_node(parser, make_node_const_object(parser, 0, arg0));
|
||||
|
|
|
@ -50,10 +50,10 @@
|
|||
|
||||
#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||
|
||||
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffffffff80000000) >> 1))
|
||||
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffffffff80000000) == 0)
|
||||
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)0xffff800000000000) >> 1))
|
||||
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & 0xffff800000000000) == 0)
|
||||
// Mask to truncate mp_int_t to positive value
|
||||
#define MP_SMALL_INT_POSITIVE_MASK ~(0xffffffff80000000 | (0xffffffff80000000 >> 1))
|
||||
#define MP_SMALL_INT_POSITIVE_MASK ~(0xffff800000000000 | (0xffff800000000000 >> 1))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue