ruby-changes:24747
From: ko1 <ko1@a...>
Date: Thu, 23 Aug 2012 16:22:57 +0900 (JST)
Subject: [ruby-changes:24747] ko1:r36798 (trunk): * include/ruby/ruby.h: introduce flonum technique for
ko1 2012-08-23 16:22:40 +0900 (Thu, 23 Aug 2012) New Revision: 36798 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36798 Log: * include/ruby/ruby.h: introduce flonum technique for 64bit CPU environment (sizeof(double) == sizeof(VALUE)). flonum technique enables to avoid double object creation if the double value d is in range about between 1.72723e-77 < |d| <= 1.15792e+77 or 0.0. flonum Float value is immediate and their lowest two bits are b10. If flonum is activated, then USE_FLONUM macro is 1. I'll write detailed in this technique on https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/Flonum_tech * benchmark/bmx_temp.rb: add an benchmark for simple Float calculation. * gc.c (id2ref, rb_obj_id): add flonum Float support. * include/ruby/intern.h: move decl of rb_float_new(double) to include/ruby/ruby.h. * insns.def, vm.c, vm_insnhelper.c: add flonum optimization and simplify source code. * vm_insnhelper.h (FLONUM_2_P): added. * marshal.c: support flonum output. * numeric.c (rb_float_new_in_heap): added. * parse.y: support flonum. * random.c: ditto. Modified files: trunk/ChangeLog trunk/benchmark/bmx_temp.rb trunk/gc.c trunk/include/ruby/intern.h trunk/include/ruby/ruby.h trunk/insns.def trunk/marshal.c trunk/numeric.c trunk/parse.y trunk/random.c trunk/vm.c trunk/vm_insnhelper.c trunk/vm_insnhelper.h Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 36797) +++ include/ruby/intern.h (revision 36798) @@ -516,7 +516,6 @@ VALUE rb_num_coerce_bin(VALUE, VALUE, ID); VALUE rb_num_coerce_cmp(VALUE, VALUE, ID); VALUE rb_num_coerce_relop(VALUE, VALUE, ID); -VALUE rb_float_new(double); VALUE rb_num2fix(VALUE); VALUE rb_fix2str(VALUE, int); VALUE rb_dbl_cmp(double, double); Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 36797) +++ include/ruby/ruby.h (revision 36798) @@ -350,11 +350,59 @@ #define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG) #define SYM2ID(x) RSHIFT((unsigned long)(x),RUBY_SPECIAL_SHIFT) +#ifndef USE_FLONUM +#if SIZEOF_VALUE >= SIZEOF_DOUBLE +#define USE_FLONUM 1 +#else +#define USE_FLONUM 0 +#endif +#endif + +#if USE_FLONUM +#define FLONUM_P(x) ((((int)(SIGNED_VALUE)(x))&FLONUM_MASK) == FLONUM_FLAG) +#else +#define FLONUM_P(x) 0 +#endif + /* Module#methods, #singleton_methods and so on return Symbols */ #define USE_SYMBOL_AS_METHOD_NAME 1 +/* +!USE_FLONUM +------------------------- +...xxxx xxx1 Fixnum +...0000 1110 Symbol +...0000 0000 Qfalse +...0000 0010 Qtrue +...0000 0100 Qnil +...0000 0110 Qundef + +USE_FLONUM +------------------------- +...xxxx xxx1 Fixnum +...xxxx xx10 Flonum +...0000 1100 Symbol +...0000 0000 Qfalse 0x00 = 0 +...0000 1000 Qnil 0x08 = 8 +...0001 0100 Qtrue 0x14 = 20 +...0011 0100 Qundef 0x34 = 52 + */ + /* special constants - i.e. non-zero and non-fixnum constants */ enum ruby_special_consts { +#if USE_FLONUM + RUBY_Qfalse = 0x00, + RUBY_Qtrue = 0x14, + RUBY_Qnil = 0x08, + RUBY_Qundef = 0x34, + + RUBY_IMMEDIATE_MASK = 0x07, + RUBY_FIXNUM_FLAG = 0x01, + RUBY_FLONUM_MASK = 0x03, + RUBY_FLONUM_FLAG = 0x02, + RUBY_SYMBOL_FLAG = 0x0c, + RUBY_SPECIAL_SHIFT = 8 +#else RUBY_Qfalse = 0, RUBY_Qtrue = 2, RUBY_Qnil = 4, @@ -364,6 +412,7 @@ RUBY_FIXNUM_FLAG = 0x01, RUBY_SYMBOL_FLAG = 0x0e, RUBY_SPECIAL_SHIFT = 8 +#endif }; #define Qfalse ((VALUE)RUBY_Qfalse) @@ -372,6 +421,10 @@ #define Qundef ((VALUE)RUBY_Qundef) /* undefined value for placeholder */ #define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK #define FIXNUM_FLAG RUBY_FIXNUM_FLAG +#if USE_FLONUM +#define FLONUM_MASK RUBY_FLONUM_MASK +#define FLONUM_FLAG RUBY_FLONUM_FLAG +#endif #define SYMBOL_FLAG RUBY_SYMBOL_FLAG #define RTEST(v) (((VALUE)(v) & ~Qnil) != 0) @@ -669,7 +722,87 @@ struct RBasic basic; double float_value; }; -#define RFLOAT_VALUE(v) (RFLOAT(v)->float_value) + +VALUE rb_float_new_in_heap(double); + +#if USE_FLONUM +#define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) +#define RUBY_BIT_ROTR(v, n) (((v) >> (n)) | ((v) << ((sizeof(v) * 8) - n))) + +static inline double +rb_float_value(VALUE v) +{ + if (FLONUM_P(v)) { + if (v == (VALUE)0x8000000000000002) { + return 0.0; + } + else { + union { + double d; + VALUE v; + } t; + + VALUE b63 = (v >> 63); + /* e: xx1... -> 011... */ + /* xx0... -> 100... */ + /* ^b63 */ + t.v = RUBY_BIT_ROTR(((b63 ^ 1) << 1) | b63 | (v & ~0x03), 3); + return t.d; + } + } + else { + return ((struct RFloat *)v)->float_value; + } +} + +static inline VALUE +rb_float_new(double d) +{ + union { + double d; + VALUE v; + } t; + int bits; + + t.d = d; + bits = (int)((VALUE)(t.v >> 60) & 0x7); + /* bits contains 3 bits of b62..b60. */ + /* bits - 3 = */ + /* b011 -> b000 */ + /* b100 -> b001 */ + + if (t.v != 0x3000000000000000 /* 1.72723e-77 */ && + !((bits-3) & ~0x01)) { + return (RUBY_BIT_ROTL(t.v, 3) & ~0x01 | 0x02); + } + else { + if (t.v == (VALUE)0) { + /* +0.0 */ + return 0x8000000000000002; + } + else { + /* out of range */ + return rb_float_new_in_heap(d); + } + } +} + +#else /* USE_FLONUM */ + +static inline double +rb_float_value(VALUE v) +{ + return ((struct RFloat *)v)->float_value; +} + +static inline VALUE +rb_float_new(double d) +{ + return rb_float_new_in_heap(d); +} +#endif + +#define RFLOAT_VALUE(v) rb_float_value(v) #define DBL2NUM(dbl) rb_float_new(dbl) #define ELTS_SHARED FL_USER2 @@ -990,7 +1123,11 @@ #define OBJ_TAINT(x) FL_SET((x), FL_TAINT) #define OBJ_UNTRUSTED(x) (!!FL_TEST((x), FL_UNTRUSTED)) #define OBJ_UNTRUST(x) FL_SET((x), FL_UNTRUSTED) -#define OBJ_INFECT(x,s) do {if (FL_ABLE(x) && FL_ABLE(s)) RBASIC(x)->flags |= RBASIC(s)->flags & (FL_TAINT | FL_UNTRUSTED);} while (0) +#define OBJ_INFECT(x,s) do { \ + if (FL_ABLE(x) && FL_ABLE(s)) \ + RBASIC(x)->flags |= RBASIC(s)->flags & \ + (FL_TAINT | FL_UNTRUSTED); \ +} while (0) #define OBJ_FROZEN(x) (!!FL_TEST((x), FL_FREEZE)) #define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE) @@ -1332,6 +1469,7 @@ { if (IMMEDIATE_P(obj)) { if (FIXNUM_P(obj)) return rb_cFixnum; + if (FLONUM_P(obj)) return rb_cFloat; if (obj == Qtrue) return rb_cTrueClass; if (SYMBOL_P(obj)) return rb_cSymbol; } @@ -1347,17 +1485,24 @@ { if (IMMEDIATE_P(obj)) { if (FIXNUM_P(obj)) return T_FIXNUM; - if (obj == Qtrue) return T_TRUE; + if (FLONUM_P(obj)) return T_FLOAT; + if (obj == Qtrue) return T_TRUE; if (SYMBOL_P(obj)) return T_SYMBOL; if (obj == Qundef) return T_UNDEF; } else if (!RTEST(obj)) { - if (obj == Qnil) return T_NIL; + if (obj == Qnil) return T_NIL; if (obj == Qfalse) return T_FALSE; } return BUILTIN_TYPE(obj); } +#if USE_FLONUM +#define RB_FLOAT_TYPE_P(obj) (FLONUM_P(obj) || TYPE(obj) == T_FLOAT) +#else +#define RB_FLOAT_TYPE_P(obj) (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == T_FLOAT) +#endif + #define RB_TYPE_P(obj, type) ( \ ((type) == T_FIXNUM) ? FIXNUM_P(obj) : \ ((type) == T_TRUE) ? ((obj) == Qtrue) : \ @@ -1365,6 +1510,7 @@ ((type) == T_NIL) ? ((obj) == Qnil) : \ ((type) == T_UNDEF) ? ((obj) == Qundef) : \ ((type) == T_SYMBOL) ? SYMBOL_P(obj) : \ + ((type) == T_FLOAT) ? RB_FLOAT_TYPE_P(obj) : \ (!SPECIAL_CONST_P(obj) && BUILTIN_TYPE(obj) == (type))) #ifdef __GNUC__ Index: ChangeLog =================================================================== --- ChangeLog (revision 36797) +++ ChangeLog (revision 36798) @@ -1,3 +1,37 @@ +Thu Aug 23 16:20:04 2012 Koichi Sasada <ko1@a...> + + * include/ruby/ruby.h: introduce flonum technique for + 64bit CPU environment (sizeof(double) == sizeof(VALUE)). + flonum technique enables to avoid double object creation + if the double value d is in range about between + 1.72723e-77 < |d| <= 1.15792e+77 or 0.0. + flonum Float value is immediate and their lowest two bits + are b10. + If flonum is activated, then USE_FLONUM macro is 1. + I'll write detailed in this technique on + https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/Flonum_tech + + * benchmark/bmx_temp.rb: add an benchmark for simple + Float calculation. + + * gc.c (id2ref, rb_obj_id): add flonum Float support. + + * include/ruby/intern.h: move decl of rb_float_new(double) + to include/ruby/ruby.h. + + * insns.def, vm.c, vm_insnhelper.c: add flonum optimization + and simplify source code. + + * vm_insnhelper.h (FLONUM_2_P): added. + + * marshal.c: support flonum output. + + * numeric.c (rb_float_new_in_heap): added. + + * parse.y: support flonum. + + * random.c: ditto. + Thu Aug 23 16:12:40 2012 NAKAMURA Usaku <usa@r...> * lib/mkmf.rb (create_makefile): add dependency to header files when Index: insns.def =================================================================== --- insns.def (revision 36797) +++ insns.def (revision 36798) @@ -1333,12 +1333,8 @@ (VALUE recv, VALUE obj) (VALUE val) { - if (0) { - - } -#if 1 - else if (FIXNUM_2_P(recv, obj) && - BASIC_OP_UNREDEFINED_P(BOP_PLUS,FIXNUM_REDEFINED_OP_FLAG)) { + if (FIXNUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS,FIXNUM_REDEFINED_OP_FLAG)) { /* fixnum + fixnum */ #ifndef LONG_LONG_VALUE val = (recv + (obj & (~1))); @@ -1360,38 +1356,29 @@ } #endif } -#endif - + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) { + val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj)); } -#endif - -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cString && - HEAP_CLASS_OF(obj) == rb_cString && + else if (HEAP_CLASS_OF(recv) == rb_cString && HEAP_CLASS_OF(obj) == rb_cString && BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) { val = rb_str_plus(recv, obj); } -#endif -#if 1 else if (HEAP_CLASS_OF(recv) == rb_cArray && BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) { val = rb_ary_plus(recv, obj); } -#endif else { goto INSN_LABEL(normal_dispatch); } } else { - INSN_LABEL(normal_dispatch): + INSN_LABEL(normal_dispatch): PUSH(recv); PUSH(obj); CALL_SIMPLE_METHOD(1, idPLUS, recv); @@ -1424,16 +1411,15 @@ val = rb_big_minus(rb_int2big(a), rb_int2big(b)); } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) { + val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj)); } -#endif else { goto INSN_LABEL(normal_dispatch); } @@ -1479,16 +1465,15 @@ } } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) { + val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj)); } -#endif else { goto INSN_LABEL(normal_dispatch); } @@ -1543,16 +1528,15 @@ } val = LONG2NUM(div); } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) { + val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj)); } -#endif else { goto INSN_LABEL(normal_dispatch); } @@ -1608,12 +1592,13 @@ } val = LONG2FIX(mod); } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) { + val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj))); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { - } - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) { val = DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj))); } else { @@ -1702,22 +1687,16 @@ val = Qfalse; } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { + /* flonum is not NaN */ + val = RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { + val = double_cmp_lt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) { - double a = RFLOAT_VALUE(recv); - double b = RFLOAT_VALUE(obj); -#if defined(_MSC_VER) && _MSC_VER < 1300 - if (isnan(a) || isnan(b)) val = Qfalse; - else -#endif - val = a < b ? Qtrue : Qfalse; - } -#endif else { goto INSN_LABEL(normal_dispatch); } @@ -1752,6 +1731,11 @@ val = Qfalse; } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) { + /* flonum is not NaN */ + val = RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + } else { /* other */ PUSH(recv); @@ -1782,22 +1766,16 @@ val = Qfalse; } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { + /* flonum is not NaN */ + val = RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { - if (0) { + if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && + BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { + val = double_cmp_gt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)); } -#if 1 - else if (HEAP_CLASS_OF(recv) == rb_cFloat && - HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) { - double a = RFLOAT_VALUE(recv); - double b = RFLOAT_VALUE(obj); -#if defined(_MSC_VER) && _MSC_VER < 1300 - if (isnan(a) || isnan(b)) val = Qfalse; - else -#endif - val = a > b ? Qtrue : Qfalse; - } -#endif else { goto INSN_LABEL(normal_dispatch); } @@ -1832,6 +1810,11 @@ val = Qfalse; } } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) { + /* flonum is not NaN */ + val = RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse; + } else { PUSH(recv); PUSH(obj); @@ -1851,10 +1834,8 @@ (VALUE val) { if (!SPECIAL_CONST_P(recv)) { - if (0) { - } - else if (HEAP_CLASS_OF(recv) == rb_cString && - BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) { + if (HEAP_CLASS_OF(recv) == rb_cString && + BASIC_OP_UNREDEFINED_P(BOP_LTLT, STRING_REDEFINED_OP_FLAG)) { val = rb_str_concat(recv, obj); } else if (HEAP_CLASS_OF(recv) == rb_cArray && Index: gc.c =================================================================== --- gc.c (revision 36797) +++ gc.c (revision 36798) @@ -1606,6 +1606,7 @@ if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; if (FIXNUM_P(ptr)) return (VALUE)ptr; + if (FLONUM_P(ptr)) return (VALUE)ptr; ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ if ((ptr % sizeof(RVALUE)) == (4 << 2)) { @@ -1685,9 +1686,16 @@ if (SYMBOL_P(obj)) { return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG; } - if (SPECIAL_CONST_P(obj)) { - return LONG2NUM((SIGNED_VALUE)obj); + else if (FLONUM_P(obj)) { +#if SIZEOF_LONG == SIZEOF_VOIDP + return LONG2NUM((SIGNED_VALUE)obj); +#else + return LL2NUM((SIGNED_VALUE)obj); +#endif } + else if (SPECIAL_CONST_P(obj)) { + return LONG2NUM((SIGNED_VALUE)obj); + } return nonspecial_obj_id(obj); } Index: parse.y =================================================================== --- parse.y (revision 36797) +++ parse.y (revision 36798) @@ -9346,7 +9346,16 @@ node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0); break; case T_FLOAT: +#if USE_FLONUM + if (FLONUM_P(node->nd_lit)) { + node->nd_lit = DBL2NUM(-RFLOAT_VALUE(node->nd_lit)); + } + else { + RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit); + } +#else RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit); +#endif break; default: break; Index: numeric.c =================================================================== --- numeric.c (revision 36797) +++ numeric.c (revision 36798) @@ -615,7 +615,7 @@ */ VALUE -rb_float_new(double d) +rb_float_new_in_heap(double d) { NEWOBJ(flt, struct RFloat); OBJSETUP(flt, rb_cFloat, T_FLOAT); Index: vm.c =================================================================== --- vm.c (revision 36797) +++ vm.c (revision 36798) @@ -990,22 +990,22 @@ #define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0) #define C(k) add_opt_method(rb_c##k, mid, bop) OP(PLUS, PLUS), (C(Fixnum), C(Float), C(String), C(Array)); - OP(MINUS, MINUS), (C(Fixnum)); + OP(MINUS, MINUS), (C(Fixnum), C(Float)); OP(MULT, MULT), (C(Fixnum), C(Float)); OP(DIV, DIV), (C(Fixnum), C(Float)); OP(MOD, MOD), (C(Fixnum), C(Float)); OP(Eq, EQ), (C(Fixnum), C(Float), C(String)); OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String)); - OP(LT, LT), (C(Fixnum)); - OP(LE, LE), (C(Fixnum)); + OP(LT, LT), (C(Fixnum), C(Float)); + OP(LE, LE), (C(Fixnum), C(Float)); + OP(GT, GT), (C(Fixnum), C(Float)); + OP(GE, GE), (C(Fixnum), C(Float)); OP(LTLT, LTLT), (C(String), C(Array)); OP(AREF, AREF), (C(Array), C(Hash)); OP(ASET, ASET), (C(Array), C(Hash)); OP(Length, LENGTH), (C(Array), C(String), C(Hash)); OP(Size, SIZE), (C(Array), C(String), C(Hash)); OP(Succ, SUCC), (C(Fixnum), C(String), C(Time)); - OP(GT, GT), (C(Fixnum)); - OP(GE, GE), (C(Fixnum)); #undef C #undef OP } Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 36797) +++ vm_insnhelper.c (revision 36798) @@ -1776,10 +1776,14 @@ BASIC_OP_UNREDEFINED_P(BOP_EQ, FIXNUM_REDEFINED_OP_FLAG)) { return (recv == obj) ? Qtrue : Qfalse; } + else if (FLONUM_2_P(recv, obj) && + BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) { + return (recv == obj) ? Qtrue : Qfalse; + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (HEAP_CLASS_OF(recv) == rb_cFloat && HEAP_CLASS_OF(obj) == rb_cFloat && - BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) { + BASIC_OP_UNREDEFINED_P(BOP_EQ, FLOAT_REDEFINED_OP_FLAG)) { double a = RFLOAT_VALUE(recv); double b = RFLOAT_VALUE(obj); @@ -1865,3 +1869,37 @@ } } + +#if defined(_MSC_VER) && _MSC_VER < 1300 +#define CHECK_CMP_NAN(a, b) if (isnan(a) || isnan(b)) return Qfalse; +#else +#define CHECK_CMP_NAN(a, b) +#endif + +static inline VALUE +double_cmp_lt(double a, double b) +{ + CHECK_CMP_NAN(a, b); + return a < b ? Qtrue : Qfalse; +} + +static inline VALUE +double_cmp_le(double a, double b) +{ + CHECK_CMP_NAN(a, b); + return a <= b ? Qtrue : Qfalse; +} + +static inline VALUE +double_cmp_gt(double a, double b) +{ + CHECK_CMP_NAN(a, b); + return a > b ? Qtrue : Qfalse; +} + +static inline VALUE +double_cmp_ge(double a, double b) +{ + CHECK_CMP_NAN(a, b); + return a >= b ? Qtrue : Qfalse; +} Index: benchmark/bmx_temp.rb === (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/