diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/mruby.h | 2 | ||||
| -rw-r--r-- | include/mruby/boxing_nan.h | 203 | ||||
| -rw-r--r-- | include/mruby/boxing_word.h | 4 |
3 files changed, 119 insertions, 90 deletions
diff --git a/include/mruby.h b/include/mruby.h index 99cd5fa2f..21b96817a 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -106,7 +106,7 @@ * mrb_static_assert(expect_condition, error_message); */ # define mrb_static_assert(...) \ - mrb_static_assert_expand(mrb_static_assert_selector(__VA_ARGS__, mrb_static_assert2, mrb_static_assert1)(__VA_ARGS__)) + mrb_static_assert_expand(mrb_static_assert_selector(__VA_ARGS__, mrb_static_assert2, mrb_static_assert1, _)(__VA_ARGS__)) #endif #include "mrbconf.h" diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h index 90866ab55..7f7478420 100644 --- a/include/mruby/boxing_nan.h +++ b/include/mruby/boxing_nan.h @@ -15,116 +15,145 @@ # error ---->> MRB_NAN_BOXING and MRB_NO_FLOAT conflict <<---- #endif -#ifdef MRB_INT64 -# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<---- -#endif - -#define MRB_FIXNUM_SHIFT 0 -#define MRB_SYMBOL_SHIFT 0 #define MRB_FIXNUM_MIN INT32_MIN #define MRB_FIXNUM_MAX INT32_MAX +enum mrb_nanbox_tt_inline { + 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: 111111111111TTTT TTPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPP - * int : 1111111111110001 0000000000000000 IIIIIIIIIIIIIIII IIIIIIIIIIIIIIII - * sym : 1111111111110001 0100000000000000 SSSSSSSSSSSSSSSS SSSSSSSSSSSSSSSS - * In order to get enough bit size to save TT, all pointers are shifted 2 bits - * in the right direction. Also, TTTTTT is the mrb_vtype + 1; + * 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; -}; +static inline mrb_float +mrb_nan_boxing_value_float(mrb_value v) +{ + union { + mrb_float f; + uint64_t u; + } x; + x.u = v.u - 0x8004000000000000; + return x.f; +} + +#define SET_FLOAT_VALUE(mrb,r,f) do { \ + union { \ + mrb_float f; \ + uint64_t u; \ + } float_uint_union; \ + if ((f) != (f)) { /* NaN */ \ + float_uint_union.u = 0x7ff8000000000000UL; \ + } \ + else { \ + float_uint_union.f = (f); \ + } \ + r.u = float_uint_union.u + 0x8004000000000000; \ +} while(0) -mrb_static_assert1(sizeof(mrb_value) == sizeof(union mrb_value_)); +#define mrb_float_p(o) (((uint64_t)(o.u)&0xfffc000000000000) != 0) -static inline union mrb_value_ -mrb_val_union(mrb_value v) +struct RInteger { + MRB_OBJECT_HEADER; + mrb_int i; +}; + +MRB_INLINE enum mrb_vtype +mrb_type(mrb_value o) { - union mrb_value_ x; - x.value = v; - return x; + if (mrb_float_p(o)) return MRB_TT_FLOAT; + + int64_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_MISC: + return (enum mrb_vtype)(o.u >> 8) & 0x1f; + default: + /* never happen */ + return MRB_TT_FLOAT; + } } -#define mrb_tt(o) ((enum mrb_vtype)((mrb_val_union(o).ttt & 0xfc000)>>14)-1) -#define mrb_type(o) (enum mrb_vtype)((uint32_t)0xfff00000 < mrb_val_union(o).ttt ? mrb_tt(o) : MRB_TT_FLOAT) -#define mrb_float(o) mrb_val_union(o).f -#define mrb_fixnum(o) ((mrb_int)mrb_val_union(o).i) -#define mrb_integer(o) mrb_fixnum(o) -#define mrb_symbol(o) ((mrb_sym)mrb_val_union(o).i) - -#ifdef MRB_64BIT -#define mrb_ptr(o) ((void*)((((uintptr_t)0x3fffffffffff)&((uintptr_t)(mrb_val_union(o).p)))<<2)) -#define mrb_cptr(o) (((struct RCptr*)mrb_ptr(o))->p) -#define NANBOX_SHIFT_LONG_POINTER(v) (((uintptr_t)(v)>>34)&0x3fff) +#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) +#ifdef MRB_INT64 +/* +#ifdef MRB_32BIT +#define mrb_fixnum(o) ((mrb_int)((intptr_t)0xffffffffffff&((o).u))|(((o).u & 0x800000000000)?0xffff000000000000:0)) #else -#define mrb_ptr(o) ((void*)mrb_val_union(o).i) -#define mrb_cptr(o) mrb_ptr(o) -#define NANBOX_SHIFT_LONG_POINTER(v) 0 +#define mrb_fixnum(o) ((mrb_int)(int32_t)((o).u)) #endif +*/ -#define NANBOX_SET_VALUE(o, tt, attr, v) do { \ - union mrb_value_ mrb_value_union_variable; \ - mrb_value_union_variable.attr = (v);\ - mrb_value_union_variable.ttt = 0xfff00000 | (((tt)+1)<<14);\ - o = mrb_value_union_variable.value;\ -} while (0) +#define mrb_fixnum(o) ((mrb_int)(int32_t)((o).u)) -#ifdef MRB_64BIT -#define NANBOX_SET_OBJ_VALUE(o, tt, v) do {\ - union mrb_value_ mrb_value_union_variable;\ - mrb_value_union_variable.p = (void*)((uintptr_t)(v)>>2);\ - mrb_value_union_variable.ttt = (0xfff00000|(((tt)+1)<<14)|NANBOX_SHIFT_LONG_POINTER(v));\ - o = mrb_value_union_variable.value;\ -} while (0) +static inline mrb_int +mrb_nan_boxing_value_int(mrb_value v) +{ + uint64_t u = v.u; + if (((u>>48)&3)==MRB_NANBOX_TT_POINTER) { + struct RInteger *p = (struct RInteger*)(uintptr_t)u; + return p->i; + } + return mrb_fixnum(v); +} +#define mrb_integer(o) mrb_nan_boxing_value_int(o) #else -#define NANBOX_SET_OBJ_VALUE(o, tt, v) NANBOX_SET_VALUE(o, tt, i, (uint32_t)v) +#define mrb_fixnum(o) ((mrb_int)(((uintptr_t)0xffffffff)&((o).u))) +#define mrb_integer(o) mrb_fixnum(o) #endif +#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_FLOAT_VALUE(mrb,r,v) do { \ - union mrb_value_ mrb_value_union_variable; \ - if ((v) != (v)) { /* NaN */ \ - mrb_value_union_variable.ttt = 0x7ff80000; \ - mrb_value_union_variable.i = 0; \ - } \ - else { \ - mrb_value_union_variable.f = (v); \ - } \ - r = mrb_value_union_variable.value; \ -} while(0) +#define NANBOX_SET_VALUE(o, tt, v) do { \ + (o).u = ((uint64_t)tt<<48) | ((uint64_t)(v)); \ +} while (0) -#define SET_NIL_VALUE(r) NANBOX_SET_VALUE(r, MRB_TT_FALSE, i, 0) -#define SET_FALSE_VALUE(r) NANBOX_SET_VALUE(r, MRB_TT_FALSE, i, 1) -#define SET_TRUE_VALUE(r) NANBOX_SET_VALUE(r, MRB_TT_TRUE, i, 1) -#define SET_BOOL_VALUE(r,b) NANBOX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, i, 1) -#define SET_INT_VALUE(mrb, r,n) NANBOX_SET_VALUE(r, MRB_TT_INTEGER, i, (uint32_t)(n)) -#define SET_FIXNUM_VALUE(r,n) NANBOX_SET_VALUE(r, MRB_TT_INTEGER, i, (uint32_t)(n)) -#define SET_SYM_VALUE(r,v) NANBOX_SET_VALUE(r, MRB_TT_SYMBOL, i, (uint32_t)(v)) -#define SET_OBJ_VALUE(r,v) NANBOX_SET_OBJ_VALUE(r, (((struct RObject*)(v))->tt), (v)) -#ifdef MRB_64BIT -MRB_API mrb_value mrb_nan_boxing_cptr_value(struct mrb_state*, void*); -#define SET_CPTR_VALUE(mrb,r,v) ((r) = mrb_nan_boxing_cptr_value(mrb, v)) +#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) +#ifdef MRB_INT64 +MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int); +#define SET_INT_VALUE(mrb, r, n) ((r) = mrb_boxing_int_value(mrb, n)) #else -#define SET_CPTR_VALUE(mrb,r,v) NANBOX_SET_VALUE(r, MRB_TT_CPTR, p, v) +#define SET_INT_VALUE(mrb, r, n) SET_FIXNUM_VALUE(r, n) #endif -#define SET_UNDEF_VALUE(r) NANBOX_SET_VALUE(r, MRB_TT_UNDEF, i, 0) +#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) 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) +#define mrb_fixnum_p(o) (!mrb_float_p(o) && ((o.u>>48)&3)==MRB_NANBOX_TT_INTEGER) #endif /* MRUBY_BOXING_NAN_H */ diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 42ae05fea..ab1aef36e 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -144,7 +144,7 @@ MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*); #ifndef MRB_NO_FLOAT MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float); #endif -MRB_API mrb_value mrb_word_boxing_int_value(struct mrb_state*, mrb_int); +MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int); #define mrb_immediate_p(o) ((o).w & WORDBOX_IMMEDIATE_MASK || (o).w == MRB_Qnil) @@ -210,7 +210,7 @@ mrb_integer_func(mrb_value o) { #define SET_FALSE_VALUE(r) ((r).w = MRB_Qfalse) #define SET_TRUE_VALUE(r) ((r).w = MRB_Qtrue) #define SET_BOOL_VALUE(r,b) ((b) ? SET_TRUE_VALUE(r) : SET_FALSE_VALUE(r)) -#define SET_INT_VALUE(mrb,r,n) ((r) = mrb_word_boxing_int_value(mrb, n)) +#define SET_INT_VALUE(mrb,r,n) ((r) = mrb_boxing_int_value(mrb, n)) #define SET_FIXNUM_VALUE(r,n) WORDBOX_SET_SHIFT_VALUE(r, FIXNUM, n) #define SET_SYM_VALUE(r,n) WORDBOX_SET_SHIFT_VALUE(r, SYMBOL, n) #define SET_OBJ_VALUE(r,v) ((r).w = (uintptr_t)(v)) |
