1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36798 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2012-08-23 07:22:40 +00:00
parent ce5af582a0
commit b3b5e626ad
13 changed files with 324 additions and 104 deletions

View file

@ -1,3 +1,37 @@
Thu Aug 23 16:20:04 2012 Koichi Sasada <ko1@atdot.net>
* 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@ruby-lang.org>
* lib/mkmf.rb (create_makefile): add dependency to header files when

View file

@ -1,9 +1,5 @@
def m
nil
end
i = 0
while i<800000 # benchmark loop 2
i+=1
m; m; m; m; m; m; m; m;
a = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
end

12
gc.c
View file

@ -1606,6 +1606,7 @@ id2ref(VALUE obj, VALUE objid)
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,8 +1686,15 @@ rb_obj_id(VALUE obj)
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);
}

View file

@ -516,7 +516,6 @@ NORETURN(void rb_num_zerodiv(void));
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);

View file

@ -350,11 +350,59 @@ rb_long2int_inline(long n)
#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 @@ enum ruby_special_consts {
RUBY_FIXNUM_FLAG = 0x01,
RUBY_SYMBOL_FLAG = 0x0e,
RUBY_SPECIAL_SHIFT = 8
#endif
};
#define Qfalse ((VALUE)RUBY_Qfalse)
@ -372,6 +421,10 @@ enum ruby_special_consts {
#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 RFloat {
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 @@ struct RBignum {
#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 @@ rb_class_of(VALUE obj)
{
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 @@ rb_type(VALUE obj)
{
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 @@ rb_type(VALUE obj)
((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__

143
insns.def
View file

@ -1333,12 +1333,8 @@ opt_plus
(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 @@ opt_plus
}
#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 @@ opt_minus
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 @@ opt_mult
}
}
}
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 @@ opt_div
}
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 @@ opt_mod
}
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 @@ opt_lt
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 @@ opt_le
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 @@ opt_gt
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 @@ opt_ge
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 @@ opt_ltlt
(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 &&

View file

@ -636,6 +636,10 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
else if (SYMBOL_P(obj)) {
w_symbol(SYM2ID(obj), arg);
}
else if (FLONUM_P(obj)) {
w_byte(TYPE_FLOAT, arg);
w_float(RFLOAT_VALUE(obj), arg);
}
else {
arg->infection |= (int)FL_TEST(obj, MARSHAL_INFECTION);

View file

@ -615,7 +615,7 @@ num_to_int(VALUE num)
*/
VALUE
rb_float_new(double d)
rb_float_new_in_heap(double d)
{
NEWOBJ(flt, struct RFloat);
OBJSETUP(flt, rb_cFloat, T_FLOAT);

View file

@ -9346,7 +9346,16 @@ negate_lit(NODE *node)
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;

View file

@ -1122,8 +1122,7 @@ rand_range(struct MT* mt, VALUE range)
case T_FLOAT: {
VALUE f = rb_check_to_float(beg);
if (!NIL_P(f)) {
RFLOAT_VALUE(v) += RFLOAT_VALUE(f);
return v;
return DBL2NUM(RFLOAT_VALUE(v) + RFLOAT_VALUE(f));
}
}
default:

10
vm.c
View file

@ -990,22 +990,22 @@ vm_init_redefined_flag(void)
#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
}

View file

@ -1776,10 +1776,14 @@ opt_eq_func(VALUE recv, VALUE obj, IC ic)
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 @@ check_match(VALUE pattern, VALUE target, enum vm_check_match_type type)
}
}
#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;
}

View file

@ -211,9 +211,15 @@ enum vm_regan_acttype {
#define SYMBOL_REDEFINED_OP_FLAG (1 << 6)
#define TIME_REDEFINED_OP_FLAG (1 << 7)
#define FIXNUM_2_P(a, b) ((a) & (b) & 1)
#define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((ruby_vm_redefined_flag[(op)]&(klass)) == 0))
#define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
#define FIXNUM_2_P(a, b) ((a) & (b) & 1)
#if USE_FLONUM
#define FLONUM_2_P(a, b) (((((a)^2) | ((b)^2)) & 3) == 0) /* (FLONUM_P(a) && FLONUM_P(b)) */
#else
#define FLONUM_2_P(a, b) 0
#endif
#define HEAP_CLASS_OF(obj) (RBASIC(obj)->klass)
#ifndef USE_IC_FOR_SPECIALIZED_METHOD
#define USE_IC_FOR_SPECIALIZED_METHOD 1