mruby 3.3.0
mruby is the lightweight implementation of the Ruby language
Loading...
Searching...
No Matches
boxing_nan.h
Go to the documentation of this file.
1
7#ifndef MRUBY_BOXING_NAN_H
8#define MRUBY_BOXING_NAN_H
9
10#ifdef MRB_USE_FLOAT32
11# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT32 conflict <<----
12#endif
13
14#ifdef MRB_NO_FLOAT
15# error ---->> MRB_NAN_BOXING and MRB_NO_FLOAT conflict <<----
16#endif
17
18#define MRB_FIXNUM_MIN INT32_MIN
19#define MRB_FIXNUM_MAX INT32_MAX
20
21enum mrb_nanbox_tt_inline {
22 MRB_NANBOX_TT_OBJECT = 0,
23 MRB_NANBOX_TT_INTEGER = 1,
24 MRB_NANBOX_TT_MISC = 2,
25 MRB_NANBOX_TT_CPTR = 3,
26};
27
28/* value representation by nan-boxing:
29 * float : SEEEEEEE EEEEFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
30 * +/-inf: S1111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000
31 * nan : 01111111 11111000 00000000 00000000 00000000 00000000 00000000 00000000
32 * int : 01111111 11111001 00000000 00000000 IIIIIIII IIIIIIII IIIIIIII IIIIIIII
33 * sym : 01111111 11111110 00000000 00TTTTTT SSSSSSSS SSSSSSSS SSSSSSSS SSSSSSSS
34 * misc : 01111111 11111110 00000000 00TTTTTT 00000000 00000000 00000000 0000MMMM
35 * object: 01111111 11111100 PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPP00
36 * cptr : 01111111 11111111 PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP PPPPPPPP
37 * Stored as O = R + 0x8004000000000000, retrieved as R = O - 0x8004000000000000.
38 * This makes pointers have all zeros in the top 32 bits.
39 */
40typedef struct mrb_value {
41 uint64_t u;
42} mrb_value;
43
44static inline mrb_float
45mrb_nan_boxing_value_float(mrb_value v)
46{
47 union {
48 mrb_float f;
49 uint64_t u;
50 } x;
51 x.u = v.u - 0x8004000000000000;
52 return x.f;
53}
54
55#define SET_FLOAT_VALUE(mrb,r,f) do { \
56 union { \
57 mrb_float f; \
58 uint64_t u; \
59 } float_uint_union; \
60 if ((f) != (f)) { /* NaN */ \
61 float_uint_union.u = 0x7ff8000000000000UL; \
62 } \
63 else { \
64 float_uint_union.f = (f); \
65 } \
66 r.u = float_uint_union.u + 0x8004000000000000; \
67} while(0)
68
69#define mrb_float_p(o) (((uint64_t)((o).u)&0xfffc000000000000) != 0)
70
71struct RInteger {
72 MRB_OBJECT_HEADER;
73 mrb_int i;
74};
75
76#define mrb_nb_tt(o) ((enum mrb_nanbox_tt_inline)((uint32_t)((o).u>>48)&3))
77
78MRB_INLINE enum mrb_vtype
79mrb_type(mrb_value o)
80{
81 if (mrb_float_p(o)) return MRB_TT_FLOAT;
82
83 int64_t u = o.u;
84 switch (mrb_nb_tt(o)) {
85 case MRB_NANBOX_TT_OBJECT: {
86 if (u == 0) return MRB_TT_FALSE;
87 return ((struct RBasic*)(uintptr_t)u)->tt;
88 }
89 case MRB_NANBOX_TT_INTEGER:
90 return MRB_TT_INTEGER;
91 case MRB_NANBOX_TT_MISC:
92 return (enum mrb_vtype)((uint32_t)(o.u >> 32) & 0x1f);
93 case MRB_NANBOX_TT_CPTR:
94 return MRB_TT_CPTR;
95 default:
96 /* never happen */
97 return MRB_TT_FLOAT;
98 }
99}
100
101#define NANBOX_SET_MISC_VALUE(r,t,i) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_MISC, ((uint64_t)(t)<<32) | (i))
102
103#define mrb_float(o) mrb_nan_boxing_value_float(o)
104#ifdef MRB_INT64
105/*
106#ifdef MRB_32BIT
107#define mrb_fixnum(o) ((mrb_int)((intptr_t)0xffffffffffff&((o).u))|(((o).u & 0x800000000000)?0xffff000000000000:0))
108#else
109#define mrb_fixnum(o) ((mrb_int)(int32_t)((o).u))
110#endif
111*/
112
113#define mrb_fixnum(o) ((mrb_int)(int32_t)((o).u))
114
115static inline mrb_int
116mrb_nan_boxing_value_int(mrb_value v)
117{
118 uint64_t u = v.u;
119 if (mrb_nb_tt(v)==MRB_NANBOX_TT_OBJECT) {
120 struct RInteger *p = (struct RInteger*)(uintptr_t)u;
121 return p->i;
122 }
123 return mrb_fixnum(v);
124}
125#define mrb_integer(o) mrb_nan_boxing_value_int(o)
126#else
127#define mrb_fixnum(o) ((mrb_int)(((uintptr_t)0xffffffff)&((o).u)))
128#define mrb_integer(o) mrb_fixnum(o)
129#endif
130#define mrb_symbol(o) ((mrb_sym)((uintptr_t)0xffffffff)&((o).u))
131#define mrb_ptr(o) ((void*)(uintptr_t)(o).u)
132#define mrb_cptr(o) ((void*)(uintptr_t)(0xffffffffffffULL&(o).u))
133
134#define NANBOX_SET_VALUE(o, tt, v) do { \
135 (o).u = ((uint64_t)(tt)<<48) | ((uint64_t)(v)); \
136} while (0)
137
138#define SET_NIL_VALUE(r) ((r).u = 0)
139#define SET_FALSE_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_FALSE, 1)
140#define SET_TRUE_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_TRUE, 1)
141#define SET_BOOL_VALUE(r,b) NANBOX_SET_MISC_VALUE(r, (b) ? MRB_TT_TRUE : MRB_TT_FALSE, 1)
142#ifdef MRB_INT64
143MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int);
144#define SET_INT_VALUE(mrb, r, n) ((r) = mrb_boxing_int_value(mrb, n))
145#else
146#define SET_INT_VALUE(mrb, r, n) SET_FIXNUM_VALUE(r, n)
147#endif
148#define SET_FIXNUM_VALUE(r,n) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_INTEGER, (uint32_t)(n))
149#define SET_SYM_VALUE(r,v) NANBOX_SET_MISC_VALUE(r, MRB_TT_SYMBOL, (uint32_t)(v))
150#define SET_OBJ_VALUE(r,v) do {(r).u = (uint64_t)(uintptr_t)(v);} while (0)
151#define SET_CPTR_VALUE(mrb,r,v) NANBOX_SET_VALUE(r, MRB_NANBOX_TT_CPTR, (uint64_t)(uintptr_t)(v) & 0x0000ffffffffffffULL)
152#define SET_UNDEF_VALUE(r) NANBOX_SET_MISC_VALUE(r, MRB_TT_UNDEF, 4)
153
154#define mrb_immediate_p(o) ((mrb_float_p(o) || mrb_nb_tt(o) != MRB_NANBOX_TT_OBJECT) || (o).u == 0)
155#define mrb_nil_p(o) ((o).u == 0)
156#define mrb_false_p(o) (mrb_type(o) == MRB_TT_FALSE || (o).u == 0)
157#define mrb_fixnum_p(o) (!mrb_float_p(o) && mrb_nb_tt(o)==MRB_NANBOX_TT_INTEGER)
158
159#endif /* MRUBY_BOXING_NAN_H */
#define MRB_INLINE
Declare a function as always inlined.
Definition common.h:68
#define MRB_API
Declare a public mruby API function.
Definition common.h:79
Definition object.h:19
Definition boxing_nan.h:71
Definition mruby.h:256
Definition boxing_nan.h:40