MacRuby : patch : for Ticket #1211
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index ad7b1cb..94d38ed 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -146,22 +146,6 @@ typedef unsigned LONG_LONG ID;
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
-#if __LP64__
-#define VOODOO_DOUBLE(d) (*(VALUE*)(&d))
-#define DBL2FIXFLOAT(d) (VOODOO_DOUBLE(d) | FIXFLOAT_FLAG)
-#else
-// voodoo_float must be a function
-// because the parameter must be converted to float
-static inline VALUE
-voodoo_float(float f)
-{
- return *(VALUE *)(&f);
-}
-#define DBL2FIXFLOAT(d) (voodoo_float(d) | FIXFLOAT_FLAG)
-#endif
-#define FIXFLOAT_P(v) (((VALUE)v & IMMEDIATE_MASK) == FIXFLOAT_FLAG)
-#define FIXFLOAT2DBL(v) coerce_ptr_to_double((VALUE)v)
-
#define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
#define ID2SYM(x) (rb_id2str((ID)x))
#define SYM2ID(x) (rb_sym2id((VALUE)x))
@@ -175,34 +159,15 @@ enum ruby_special_consts {
RUBY_IMMEDIATE_MASK = 0x03,
RUBY_FIXNUM_FLAG = 0x01,
- RUBY_FIXFLOAT_FLAG = 0x03,
RUBY_SPECIAL_SHIFT = 8,
};
-// We can't directly cast a void* to a double, so we cast it to a union
-// and then extract its double member. Hacky, but effective.
-static inline double
-coerce_ptr_to_double(VALUE v)
-{
- union {
- VALUE val;
-#if __LP64__
- double d;
-#else
- float d;
-#endif
- } coerced_value;
- coerced_value.val = v & ~RUBY_FIXFLOAT_FLAG; // unset the last two bits.
- return coerced_value.d;
-}
-
#define Qfalse ((VALUE)RUBY_Qfalse)
#define Qtrue ((VALUE)RUBY_Qtrue)
#define Qnil ((VALUE)RUBY_Qnil)
#define Qundef ((VALUE)RUBY_Qundef) /* undefined value for placeholder */
#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK
#define FIXNUM_FLAG RUBY_FIXNUM_FLAG
-#define FIXFLOAT_FLAG RUBY_FIXFLOAT_FLAG
#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
#define NIL_P(v) ((VALUE)(v) == Qnil)
@@ -432,9 +397,16 @@ struct RBasic {
#define RCLASS_SET_SUPER(m, s) (class_setSuperclass((Class)m, (Class)s))
#define RCLASS_META(m) (class_isMetaClass((Class)m))
-#define RFLOAT_VALUE(v) FIXFLOAT2DBL(v)
+struct RFloat {
+ struct RBasic basic;
+ double float_value;
+};
+#define RFLOAT_VALUE(v) (RFLOAT(v)->float_value)
#define DOUBLE2NUM(dbl) rb_float_new(dbl)
#define DBL2NUM DOUBLE2NUM
+#define DBL2FIXFLOAT DBL2NUM
+#define FIXFLOAT_P(v) (!SPECIAL_CONST_P(v) && RBASIC(v)->flags == T_FLOAT)
+#define FIXFLOAT2DBL RFLOAT_VALUE
#define ELTS_SHARED FL_USER2
@@ -564,6 +536,7 @@ struct RBignum {
#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
+#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#define RARRAY(obj) (R_CAST(RArray)(obj))
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
@@ -885,9 +858,6 @@ rb_class_of(VALUE obj)
if (FIXNUM_P(obj)) {
return rb_cFixnum;
}
- if (FIXFLOAT_P(obj)) {
- return rb_cFloat;
- }
if (obj == Qtrue) {
return rb_cTrueClass;
}
@@ -912,9 +882,6 @@ rb_type(VALUE obj)
if (FIXNUM_P(obj)) {
return T_FIXNUM;
}
- if (FIXFLOAT_P(obj)) {
- return T_FLOAT;
- }
if (obj == Qtrue) {
return T_TRUE;
}
@@ -930,6 +897,9 @@ rb_type(VALUE obj)
return T_FALSE;
}
}
+ else if (RBASIC(obj)->flags == T_FLOAT) {
+ return T_FLOAT;
+ }
return rb_objc_type(obj);
}
diff --git a/kernel.c b/kernel.c
index c0f8d14..1470f37 100644
--- a/kernel.c
+++ b/kernel.c
@@ -338,7 +338,7 @@ vm_get_block(VALUE obj)
}
// Only numeric immediates have their lsb at 1.
-#define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1)
+#define NUMERIC_IMM_P(x) ((x & 0x1) == 0x1 || FIXFLOAT_P(x))
#define IMM2DBL(x) (FIXFLOAT_P(x) ? FIXFLOAT2DBL(x) : FIX2LONG(x))
diff --git a/numeric.c b/numeric.c
index 5cb37c6..a5f0ef5 100644
--- a/numeric.c
+++ b/numeric.c
@@ -577,7 +577,11 @@ num_to_int(VALUE num, SEL sel)
VALUE
rb_float_new(double d)
{
- return DBL2FIXFLOAT(d);
+ NEWOBJ(flt, struct RFloat);
+ OBJSETUP(flt, rb_cFloat, T_FLOAT);
+
+ flt->float_value = d;
+ return (VALUE)flt;
}
/*
diff --git a/parse.y b/parse.y
index 1a12788..32dd80d 100644
--- a/parse.y
+++ b/parse.y
@@ -8719,10 +8719,7 @@ negate_lit(NODE *node)
GC_WB(&node->nd_lit, rb_funcall(node->nd_lit,tUMINUS,0,0));
break;
case T_FLOAT:
- {
- double v = -RFLOAT_VALUE(node->nd_lit);
- node->nd_lit = DBL2FIXFLOAT(v);
- }
+ RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit);
break;
default:
break;