Skip to content

Commit 183edef

Browse files
committed
py: Add object repr "C", where 30-bit floats are stuffed in obj word.
This new object representation puts floats into the object word instead of on the heap, at the expense of reducing their precision to 30 bits. It only makes sense when the word size is 32-bits.
1 parent aedb859 commit 183edef

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

py/mpconfig.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@
6363
// - xxxx...xxx0 : a pointer to an mp_obj_base_t (unless a fake object)
6464
#define MICROPY_OBJ_REPR_B (1)
6565

66+
// A MicroPython object is a machine word having the following form:
67+
// - iiiiiiii iiiiiiii iiiiiiii iiiiiii1 small int with 31-bit signed value
68+
// - x1111111 1qqqqqqq qqqqqqqq qqqqq110 str with 20-bit qstr value
69+
// - s1111111 10000000 00000000 00000010 +/- inf
70+
// - s1111111 1xxxxxxx xxxxxxxx xxxxx010 nan, x != 0
71+
// - seeeeeee efffffff ffffffff ffffff10 30-bit fp, e != 0xff
72+
// - pppppppp pppppppp pppppppp pppppp00 ptr (4 byte alignment)
73+
// This scheme only works with 32-bit word size and float enabled.
74+
#define MICROPY_OBJ_REPR_C (2)
75+
6676
#ifndef MICROPY_OBJ_REPR
6777
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
6878
#endif

py/obj.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,41 @@ mp_obj_t mp_obj_new_float(mp_float_t value);
123123
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
124124
{ return ((((mp_int_t)(o)) & 1) == 0); }
125125

126+
#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
127+
128+
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o)
129+
{ return ((((mp_int_t)(o)) & 1) != 0); }
130+
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1)
131+
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_int_t)(small_int)) << 1) | 1))
132+
133+
#define mp_const_float_e ((mp_obj_t)((0x402df854 & ~3) | 2))
134+
#define mp_const_float_pi ((mp_obj_t)((0x40490fdb & ~3) | 2))
135+
136+
static inline bool mp_obj_is_float(mp_const_obj_t o)
137+
{ return (((mp_uint_t)(o)) & 3) == 2 && (((mp_uint_t)(o)) & 0x7f800004) != 0x7f800004; }
138+
static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) {
139+
union {
140+
mp_float_t f;
141+
mp_uint_t u;
142+
} num = {.u = (mp_uint_t)o & ~3};
143+
return num.f;
144+
}
145+
static inline mp_obj_t mp_obj_new_float(mp_float_t f) {
146+
union {
147+
mp_float_t f;
148+
mp_uint_t u;
149+
} num = {.f = f};
150+
return (mp_obj_t)((num.u & ~0x3) | 2);
151+
}
152+
153+
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o)
154+
{ return (((mp_uint_t)(o)) & 0x7f800007) == 0x7f800006; }
155+
#define MP_OBJ_QSTR_VALUE(o) ((((mp_uint_t)(o)) >> 3) & 0xfffff)
156+
#define MP_OBJ_NEW_QSTR(qst) ((mp_obj_t)((((mp_uint_t)(qst)) << 3) | 0x7f800006))
157+
158+
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
159+
{ return ((((mp_int_t)(o)) & 3) == 0); }
160+
126161
#endif
127162

128163
// Macros to convert between mp_obj_t and concrete object types.

py/objfloat.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <math.h>
4040
#include "py/formatfloat.h"
4141

42+
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C
43+
4244
typedef struct _mp_obj_float_t {
4345
mp_obj_base_t base;
4446
mp_float_t value;
@@ -47,6 +49,8 @@ typedef struct _mp_obj_float_t {
4749
const mp_obj_float_t mp_const_float_e_obj = {{&mp_type_float}, M_E};
4850
const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};
4951

52+
#endif
53+
5054
STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
5155
(void)kind;
5256
mp_float_t o_val = mp_obj_float_get(o_in);
@@ -121,6 +125,8 @@ const mp_obj_type_t mp_type_float = {
121125
.binary_op = float_binary_op,
122126
};
123127

128+
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C
129+
124130
mp_obj_t mp_obj_new_float(mp_float_t value) {
125131
mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
126132
o->base.type = &mp_type_float;
@@ -134,6 +140,8 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) {
134140
return self->value;
135141
}
136142

143+
#endif
144+
137145
STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) {
138146
// logic here follows that of CPython
139147
// https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations

py/smallint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
// Functions for small integer arithmetic
3333

3434
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
35-
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A
35+
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
3636

3737
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1))
3838
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)

0 commit comments

Comments
 (0)