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:
parent
ce5af582a0
commit
b3b5e626ad
13 changed files with 324 additions and 104 deletions
34
ChangeLog
34
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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
12
gc.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
143
insns.def
|
@ -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 &&
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
9
parse.y
9
parse.y
|
@ -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;
|
||||
|
|
3
random.c
3
random.c
|
@ -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
10
vm.c
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue