Watson1978
4/20/2011 - 3:06 PM

MacRuby : patch : for Ticket #1211

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;