[macruby-changes] [1709] MacRuby/branches/fp-optimized-experimental

source_changes at macosforge.org source_changes at macosforge.org
Wed Jun 3 12:46:19 PDT 2009


Revision: 1709
          http://trac.macosforge.org/projects/ruby/changeset/1709
Author:   pthomson at apple.com
Date:     2009-06-03 12:46:18 -0700 (Wed, 03 Jun 2009)
Log Message:
-----------
First attempt at adding floating-point optimization. 
Floats that do not use their last two bits will be represented as FixFloats.
THIS ONLY WORKS ON 64-BIT. PROCEED WITH CAUTION.

Modified Paths:
--------------
    MacRuby/branches/fp-optimized-experimental/compiler.cpp
    MacRuby/branches/fp-optimized-experimental/include/ruby/ruby.h
    MacRuby/branches/fp-optimized-experimental/numeric.c
    MacRuby/branches/fp-optimized-experimental/object.c
    MacRuby/branches/fp-optimized-experimental/vm.cpp

Modified: MacRuby/branches/fp-optimized-experimental/compiler.cpp
===================================================================
--- MacRuby/branches/fp-optimized-experimental/compiler.cpp	2009-06-03 19:43:40 UTC (rev 1708)
+++ MacRuby/branches/fp-optimized-experimental/compiler.cpp	2009-06-03 19:46:18 UTC (rev 1709)
@@ -4301,7 +4301,12 @@
 static inline double
 rval_to_double(VALUE rval)
 {
-    return RFLOAT_VALUE(rb_Float(bool_to_fix(rval)));
+	// workaround for C++'s refusal to cast union types.
+	VALUE r = rb_Float(bool_to_fix(rval));
+	if (FIXFLOAT_P(r)) {
+		return *(double*)(&r);
+	}
+	return RFLOAT(r)->float_value;
 }
 
 extern "C"

Modified: MacRuby/branches/fp-optimized-experimental/include/ruby/ruby.h
===================================================================
--- MacRuby/branches/fp-optimized-experimental/include/ruby/ruby.h	2009-06-03 19:43:40 UTC (rev 1708)
+++ MacRuby/branches/fp-optimized-experimental/include/ruby/ruby.h	2009-06-03 19:46:18 UTC (rev 1709)
@@ -167,10 +167,10 @@
 # endif
 #endif
 
-#define FIXNUM_MAX (LONG_MAX>>1)
-#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
+#define FIXNUM_MAX (LONG_MAX>>2)
+#define FIXNUM_MIN RSHIFT((long)LONG_MIN,2)
 
-#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG))
+#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<2 | FIXNUM_FLAG))
 #define LONG2FIX(i) INT2FIX(i)
 #define rb_fix_new(v) INT2FIX(v)
 VALUE rb_int2inum(SIGNED_VALUE);
@@ -224,15 +224,35 @@
 #define NUM2GIDT(v) NUM2LONG(v)
 #endif
 
-#define FIX2LONG(x) RSHIFT((SIGNED_VALUE)x,1)
-#define FIX2ULONG(x) ((((VALUE)(x))>>1)&LONG_MAX)
-#define FIXNUM_P(f) (((SIGNED_VALUE)(f))&FIXNUM_FLAG)
+#define FIX2LONG(x) RSHIFT((SIGNED_VALUE)x,2)
+#define FIX2ULONG(x) ((((VALUE)(x))>>2)&LONG_MAX)
+#define FIXNUM_P(f) ((((SIGNED_VALUE)(f)) & IMMEDIATE_MASK) == FIXNUM_FLAG)
 #define POSFIXABLE(f) ((f) < FIXNUM_MAX+1)
 #define NEGFIXABLE(f) ((f) >= FIXNUM_MIN)
 #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
 
 #define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
 
+// 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.
+// This doesn't work in C++, though. I need suggestions on how to do it there.
+typedef union {VALUE val; void* vd; double d;} hack_t;
+
+static inline double coerce_ptr_to_double(hack_t h)
+{
+	h.val ^= 3; // unset the last two bits.
+	return h.d;
+}
+
+
+#define VOODOO_DOUBLE(d) (*(VALUE*)(&d))
+#define DBL2FIXFLOAT(d) (VOODOO_DOUBLE(d) | FIXFLOAT_FLAG)
+#define FIXABLE_DBL(d) (!(VOODOO_DOUBLE(d) & FIXFLOAT_FLAG))
+#define FIXFLOAT_P(v)  (((VALUE)v & FIXFLOAT_FLAG) == FIXFLOAT_FLAG)
+#define FIXFLOAT2DBL(v) coerce_ptr_to_double((hack_t)v)
+
+
+
 #if WITH_OBJC
 # define SYMBOL_P(x) (TYPE(x) == T_SYMBOL)
 # define ID2SYM(x) (rb_id2str((ID)x))
@@ -252,6 +272,7 @@
 
     RUBY_IMMEDIATE_MASK = 0x03,
     RUBY_FIXNUM_FLAG    = 0x01,
+	RUBY_FIXFLOAT_FLAG	= 0x03,
 #if !WITH_OBJC
     RUBY_SYMBOL_FLAG    = 0x0e,
 #endif
@@ -264,6 +285,7 @@
 #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
 #if !WITH_OBJC
 # define SYMBOL_FLAG RUBY_SYMBOL_FLAG
 #endif
@@ -300,6 +322,7 @@
 #if WITH_OBJC
     RUBY_T_NATIVE = 0x16,
 #endif
+	RUBY_T_FIXFLOAT = 0x17,
 
     RUBY_T_UNDEF  = 0x1b,
     RUBY_T_NODE   = 0x1c,
@@ -323,6 +346,7 @@
 #define T_BIGNUM RUBY_T_BIGNUM
 #define T_FILE   RUBY_T_FILE
 #define T_FIXNUM RUBY_T_FIXNUM
+#define T_FIXFLOAT RUBY_T_FIXFLOAT
 #if WITH_OBJC
 # define T_NATIVE RUBY_T_NATIVE
 #endif
@@ -535,7 +559,7 @@
     struct RBasic basic;
     double float_value;
 };
-#define RFLOAT_VALUE(v) (RFLOAT(v)->float_value)
+#define RFLOAT_VALUE(v) (FIXFLOAT_P(v) ? FIXFLOAT2DBL(v) : RFLOAT(v)->float_value)
 #define DOUBLE2NUM(dbl)  rb_float_new(dbl)
 
 #if WITH_OBJC
@@ -1020,6 +1044,7 @@
 RUBY_EXTERN VALUE rb_cEnumerator;
 RUBY_EXTERN VALUE rb_cFile;
 RUBY_EXTERN VALUE rb_cFixnum;
+RUBY_EXTERN VALUE rb_cFixFloat;
 RUBY_EXTERN VALUE rb_cFloat;
 RUBY_EXTERN VALUE rb_cHash;
 RUBY_EXTERN VALUE rb_cInteger;
@@ -1149,6 +1174,7 @@
 #define CONDITION_TO_BOOLEAN(c) ((c) ? Qtrue : Qfalse)
 
 VALUE rb_box_fixnum(VALUE);
+VALUE rb_box_fixfloat(VALUE);
 
 static inline id
 rb_rval_to_ocid(VALUE obj)
@@ -1165,7 +1191,10 @@
         }
         if (FIXNUM_P(obj)) {
 	    return (id)rb_box_fixnum(obj);
-	}
+		}
+		if (FIXFLOAT_P(obj)) {
+		return (id)rb_box_fixfloat(obj);
+		}
     }
     return (id)obj;
 }
@@ -1185,6 +1214,10 @@
     if (*(Class *)obj == (Class)rb_cFixnum) {
 	return LONG2FIX(RFIXNUM(obj)->value);
     }
+	if (*(Class *)obj == (Class)rb_cFixFloat) {
+		extern VALUE rb_float_new(double);
+		return rb_float_new(RFLOAT(obj)->float_value);
+	}
     if (*(Class *)obj == (Class)rb_cCFNumber) {
 	/* TODO NSNumber should implement the Numeric primitive methods */
 	if (CFNumberIsFloatType((CFNumberRef)obj)) {
@@ -1218,6 +1251,7 @@
 {
     if (IMMEDIATE_P(obj)) {
 	if (FIXNUM_P(obj)) return rb_cFixnum;
+	if (FIXFLOAT_P(obj)) return rb_cFixFloat;
 	if (obj == Qtrue)  return rb_cTrueClass;
 #if !WITH_OBJC
 	if (SYMBOL_P(obj)) return rb_cSymbol;
@@ -1238,6 +1272,9 @@
 	if (FIXNUM_P(obj)) {
 	    return T_FIXNUM;
 	}
+	if (FIXFLOAT_P(obj)) {
+		return T_FLOAT;
+	}
 	if (obj == Qtrue) {
 	    return T_TRUE;
 	}
@@ -1289,6 +1326,9 @@
 	if (k == (Class)rb_cFixnum) {
 	    return T_FIXNUM;
 	}
+	if (k == (Class)rb_cFixFloat) {
+		return T_FLOAT;
+	}
 	if (NATIVE(obj)) {
 	    return T_NATIVE;
 	}

Modified: MacRuby/branches/fp-optimized-experimental/numeric.c
===================================================================
--- MacRuby/branches/fp-optimized-experimental/numeric.c	2009-06-03 19:43:40 UTC (rev 1708)
+++ MacRuby/branches/fp-optimized-experimental/numeric.c	2009-06-03 19:46:18 UTC (rev 1709)
@@ -87,6 +87,7 @@
 VALUE rb_cFloat;
 VALUE rb_cInteger;
 VALUE rb_cFixnum;
+VALUE rb_cFixFloat;
 
 VALUE rb_eZeroDivError;
 VALUE rb_eFloatDomainError;
@@ -95,6 +96,15 @@
 static struct RFixnum *fixnum_cache = NULL;
 
 VALUE
+rb_box_fixfloat(VALUE fixfloat)
+{
+	struct RFloat *val = malloc(sizeof(struct RFloat));
+	(val->basic).klass = rb_cFixFloat;
+	val->float_value = NUM2DBL(fixfloat);
+	return (VALUE)val;
+}
+
+VALUE
 rb_box_fixnum(VALUE fixnum)
 {
     struct RFixnum *val;
@@ -532,6 +542,7 @@
 VALUE
 rb_float_new(double d)
 {
+	if (FIXABLE_DBL(d)) return DBL2FIXFLOAT(d);
     NEWOBJ(flt, struct RFloat);
     OBJSETUP(flt, rb_cFloat, T_FLOAT);
 
@@ -3368,6 +3379,9 @@
     rb_objc_define_method(rb_cFloat, "nan?",      flo_is_nan_p, 0);
     rb_objc_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
     rb_objc_define_method(rb_cFloat, "finite?",   flo_is_finite_p, 0);
-
+	
+	rb_cFixFloat  = rb_define_class("FixFloat", rb_cFloat);
+	rb_undef_method(CLASS_OF(rb_cFixFloat), "new");
+	
     rb_install_nsnumber_primitives();
 }

Modified: MacRuby/branches/fp-optimized-experimental/object.c
===================================================================
--- MacRuby/branches/fp-optimized-experimental/object.c	2009-06-03 19:43:40 UTC (rev 1708)
+++ MacRuby/branches/fp-optimized-experimental/object.c	2009-06-03 19:46:18 UTC (rev 1709)
@@ -2484,7 +2484,6 @@
     switch (TYPE(val)) {
       case T_FLOAT:
 	return RFLOAT_VALUE(val);
-
       case T_STRING:
 	rb_raise(rb_eTypeError, "no implicit conversion to float from string");
 	break;

Modified: MacRuby/branches/fp-optimized-experimental/vm.cpp
===================================================================
--- MacRuby/branches/fp-optimized-experimental/vm.cpp	2009-06-03 19:43:40 UTC (rev 1708)
+++ MacRuby/branches/fp-optimized-experimental/vm.cpp	2009-06-03 19:46:18 UTC (rev 1709)
@@ -207,7 +207,7 @@
 
     emp = new ExistingModuleProvider(RoxorCompiler::module);
     jmm = new RoxorJITManager;
-    ee = ExecutionEngine::createJIT(emp, 0, jmm, CodeGenOpt::None);
+	ee = ExecutionEngine::createJIT(emp, 0, jmm, CodeGenOpt::None);
     assert(ee != NULL);
 
     fpm = new FunctionPassManager(emp);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090603/812ed2c1/attachment-0001.html>


More information about the macruby-changes mailing list