diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-10-28 22:27:26 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-10-30 17:43:35 +0900 |
| commit | 85fcd2dc6f91ae4ff1ccf3954c951f19efa3570c (patch) | |
| tree | 01892f6a6cf62fb8225e94896d111cff013d0087 /include | |
| parent | 0069e6738ac60dc3df9163af37c35f6908e86d23 (diff) | |
| download | mruby-85fcd2dc6f91ae4ff1ccf3954c951f19efa3570c.tar.gz mruby-85fcd2dc6f91ae4ff1ccf3954c951f19efa3570c.zip | |
boxing_nan.h: implement Favor pointer NaN Boxing.
Favor pointer means encode NaN boxed values to keep pointer values
unmodified, to reduce the cost of far frequent pointer value retrievals.
Diffstat (limited to 'include')
| -rw-r--r-- | include/mruby/boxing_nan.h | 103 |
1 files changed, 49 insertions, 54 deletions
diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index a7dab2f40..a752a5be7 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -25,111 +25,106 @@ #define MRB_FIXNUM_MAX INT32_MAX enum mrb_nanbox_tt_inline { - MRB_NANBOX_TT_OBJECT = 1, - MRB_NANBOX_TT_INTEGER, - MRB_NANBOX_TT_SYMBOL, - MRB_NANBOX_TT_POINTER, - MRB_NANBOX_TT_MISC, + MRB_NANBOX_TT_POINTER = 0, + MRB_NANBOX_TT_INTEGER = 1, + MRB_NANBOX_TT_SYMBOL = 2, + MRB_NANBOX_TT_MISC = 3, }; /* value representation by nan-boxing: - * float : FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF - * object: 1111111111110001 PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP - * int : 1111111111110010 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII - * sym : 1111111111110011 0000000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS - * ptr : 1111111111110100 0000000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS - * misc : 1111111111110101 0000000000000000 0000000000000000 TTTTTT000000MMMM + * float : SEEEEEEE EEEEFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF + * +/-inf: S1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000 + * nan : 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000 + * int : 01111111 11111001 00000000 00000000 IIIIIIII IIIIIIII IIIIIIII IIIIIIII + * sym : 01111111 11111110 00000000 00000000 SSSSSSSS SSSSSSSS SSSSSSSS SSSSSSSS + * misc : 01111111 11111111 00000000 00000000 00000000 00000000 00TTTTTT 0000MMMM + * object: 01111111 11111100 PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPP00 + * ptr : 01111111 11111100 PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPP01 + * Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000. + * This makes pointers have all zeros in the top 32 bits. + * Small-ints and strs have 1 as LSB to make sure they don't look like pointers + * to the garbage collector. */ typedef struct mrb_value { uint64_t u; } mrb_value; -union mrb_value_ { - mrb_float f; - uint64_t u; -#ifdef MRB_64BIT - void *p; -# define NANBOX_IMMEDIATE_VALUE uint32_t i -#else -# define NANBOX_IMMEDIATE_VALUE union { uint32_t i; void *p; } -#endif - struct { - MRB_ENDIAN_LOHI( - uint32_t ttt; - ,NANBOX_IMMEDIATE_VALUE; - ) - }; - mrb_value value; -}; - -mrb_static_assert(sizeof(mrb_value) == sizeof(union mrb_value_)); - static inline mrb_float -mrb_float(mrb_value v) +mrb_nan_boxing_value_float(mrb_value v) { union { mrb_float f; uint64_t u; } x; - x.u = v.u; + x.u = v.u - 0x8004000000000000; return x.f; } -#define SET_FLOAT_VALUE(mrb,r,v) do { \ +#define SET_FLOAT_VALUE(mrb,r,f) do { \ union { \ mrb_float f; \ uint64_t u; \ } float_uint_union; \ - if ((v) != (v)) { /* NaN */ \ + if ((f) != (f)) { /* NaN */ \ float_uint_union.u = 0x7ff8000000000000UL; \ } \ else { \ - float_uint_union.f = (v); \ + float_uint_union.f = (f); \ } \ - r.u = float_uint_union.u; \ + r.u = float_uint_union.u + 0x8004000000000000; \ } while(0) #define NANBOX_SET_VALUE(o, tt, v) do { \ - (o).u = ((0xfff0|(tt))<<48) | (v).u; \ + (o).u = ((uint64_t)tt<<48) | (uint64_t)(v); \ } while (0) +#define mrb_float_p(o) (((uint64_t)(o.u)&0xfffc000000000000) != 0) + MRB_INLINE enum mrb_vtype mrb_type(mrb_value o) { - if ((o.u >> 52) == 0xfff) return MRB_TT_FLOAT; - switch ((o.u >> 48) & 7) { - case MRB_NANBOX_TT_OBJECT: { - uintptr_t u = o.u & ~((~0)<<48); - return ((struct RBasic *)u)->tt; + if (mrb_float_p(o)) return MRB_TT_FLOAT; + + uint64_t u = o.u; + switch ((enum mrb_nanbox_tt_inline)((u >> 48) & 3)) { + case MRB_NANBOX_TT_POINTER: { + if (u == 0) return MRB_TT_FALSE; + if (u & 1) return MRB_TT_CPTR; + return ((struct RBasic*)(uintptr_t)u)->tt; } case MRB_NANBOX_TT_INTEGER: return MRB_TT_INTEGER; case MRB_NANBOX_TT_SYMBOL: return MRB_TT_SYMBOL; - case MRB_NANBOX_TT_POINTER: - return MRB_TT_CPTR; case MRB_NANBOX_TT_MISC: - return (enum mrb_vtype)(o.u >> 5) & 0x1f; + return (enum mrb_vtype)(o.u >> 8) & 0x1f; default: + /* never happen */ return MRB_TT_FLOAT; } } -#define mrb_fixnum(o) ((mrb_int)((uintptr_t)0xffffffff)&((o).u)) -#define mrb_integer(o) mrb_fixnum(o) -#define mrb_symbol(o) ((mrb_sym)((uintptr_t)0xffffffff)&((o).u)) -#define mrb_ptr(o) ((void*)(((uintptr_t)0xfffffffffff)&((o).u))) -#define mrb_cptr(o) mrb_ptr(o) +#define NANBOX_SET_MISC_VALUE(r,t,i) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_MISC, ((t)<<8) | i) + +#define mrb_float(o) mrb_nan_boxing_value_float(o) +#define mrb_fixnum(o) ((mrb_int)(((uintptr_t)0xffffffff)&((o).u))) +#define mrb_integer(o) mrb_fixnum(o) +#define mrb_symbol(o) ((mrb_sym)((uintptr_t)0xffffffff)&((o).u)) +#define mrb_ptr(o) ((void*)(uintptr_t)(o).u) +#define mrb_cptr(o) ((void*)(uintptr_t)(0xfffffffffffe&(o).u)) #define SET_NIL_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_FALSE, 0) #define SET_FALSE_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_FALSE, 1) #define SET_TRUE_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_TRUE, 1) -#define SET_BOOL_VALUE(r,b) NANBOX_SET_MISC_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, 1) +#define SET_BOOL_VALUE(r,b) NANBOX_SET_MISC_VALUE(r, (b) ? MRB_TT_TRUE : MRB_TT_FALSE, 1) #define SET_INT_VALUE(mrb,r,n) SET_FIXNUM_VALUE(r,n) #define SET_FIXNUM_VALUE(r,n) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_INTEGER, (uint32_t)(n)) #define SET_SYM_VALUE(r,v) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_SYMBOL, (uint32_t)(v)) -#define SET_OBJ_VALUE(r,v) NANBOX_SET_VALUE(o, MRB_NANBOT_TT_OBJECT, v) -#define SET_CPTR_VALUE(mrb,r,v) NANBOX_SET_VALUE(o, MRB_NANBOT_TT_POINTER, v) +#define SET_OBJ_VALUE(r,v) do {(r).u = (uint64_t)(uintptr_t)v;} while (0) +#define SET_CPTR_VALUE(mrb,r,v) do {(r).u = ((uint64_t)(uintptr_t)v) | 1;} while (0) #define SET_UNDEF_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_UNDEF, 4) +#define mrb_nil_p(o) (mrb_type(o) == MRB_TT_FALSE && ((o).u & 3) == 0) +#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE && ((o).u & 2) == 0) + #endif /* MRUBY_BOXING_NAN_H */ |
