Skip to content

Commit

Permalink
Showing 8 changed files with 366 additions and 133 deletions.
37 changes: 22 additions & 15 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -328,7 +329,7 @@ private IRubyObject addFloat(RubyFloat other) {
}

private IRubyObject addOther(ThreadContext context, IRubyObject other) {
return coerceBin(context, "+", other);
return coerceBin(context, sites(context).op_plus, other);
}

/** rb_big_minus
@@ -367,7 +368,7 @@ private IRubyObject subtractFloat(RubyFloat other) {
}

private IRubyObject subtractOther(ThreadContext context, IRubyObject other) {
return coerceBin(context, "-", other);
return coerceBin(context, sites(context).op_minus, other);
}

/** rb_big_mul
@@ -397,7 +398,7 @@ public IRubyObject opMulOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return RubyFloat.newFloat(getRuntime(), big2dbl(this) * ((RubyFloat) other).getDoubleValue());
}
return coerceBin(context, "*", other);
return coerceBin(context, sites(context).op_times, other);
}

/**
@@ -422,7 +423,7 @@ private IRubyObject op_divide(ThreadContext context, IRubyObject other, boolean
return RubyNumeric.dbl2num(runtime, div);
}
} else {
return coerceBin(context, slash ? "/" : "div", other);
return coerceBin(context, slash ? sites(context).op_quo : sites(context).div, other);
}

if (otherValue.signum() == 0) throw runtime.newZeroDivisionError();
@@ -465,7 +466,7 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyBignum) {
otherValue = ((RubyBignum) other).value;
} else {
return coerceBin(context, "divmod", other);
return coerceBin(context, sites(context).divmod, other);
}

if (otherValue.signum() == 0) throw runtime.newZeroDivisionError();
@@ -497,7 +498,7 @@ public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyBignum) {
otherValue = ((RubyBignum) other).value;
} else {
return coerceBin(context, "%", other);
return coerceBin(context, sites(context).op_mod, other);
}
Ruby runtime = context.runtime;
if (otherValue.signum() == 0) throw runtime.newZeroDivisionError();
@@ -530,7 +531,7 @@ public IRubyObject remainder(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyBignum) {
otherValue = ((RubyBignum) other).value;
} else {
return coerceBin(context, "remainder", other);
return coerceBin(context, sites(context).remainder, other);
}
Ruby runtime = context.runtime;
if (otherValue.signum() == 0) throw runtime.newZeroDivisionError();
@@ -554,7 +555,7 @@ public IRubyObject quo(ThreadContext context, IRubyObject other) {
if (other instanceof RubyNumeric) {
return RubyFloat.newFloat(getRuntime(), big2dbl(this) / ((RubyNumeric) other).getDoubleValue());
} else {
return coerceBin(context, "quo", other);
return coerceBin(context, sites(context).quo, other);
}
}

@@ -622,10 +623,11 @@ public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
d = ((RubyFloat) other).getDoubleValue();
if (this.compareTo(RubyFixnum.zero(runtime)) == -1
&& d != Math.round(d)) {
return RubyComplex.newComplexRaw(getRuntime(), this).callMethod(context, "**", other);
RubyComplex complex = RubyComplex.newComplexRaw(getRuntime(), this);
return sites(context).op_exp.call(context, complex, complex, other);
}
} else {
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);

}
double pow = Math.pow(big2dbl(this), d);
@@ -645,7 +647,7 @@ public IRubyObject op_and(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyFixnum) {
return bignorm(getRuntime(), value.and(fix2big((RubyFixnum)other)));
}
return coerceBit(context, "&", other);
return coerceBit(context, sites(context).op_and, other);
}

public IRubyObject op_and19(ThreadContext context, IRubyObject other) {
@@ -663,7 +665,7 @@ public IRubyObject op_or(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) { // no bignorm here needed
return bignorm(getRuntime(), value.or(fix2big((RubyFixnum)other)));
}
return coerceBit(context, "|", other);
return coerceBit(context, sites(context).op_or, other);
}

@JRubyMethod
@@ -686,7 +688,7 @@ public IRubyObject op_xor(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) {
return bignorm(getRuntime(), value.xor(BigInteger.valueOf(((RubyFixnum) other).getLongValue())));
}
return coerceBit(context, "^", other);
return coerceBit(context, sites(context).op_xor, other);
}

public IRubyObject op_xor19(ThreadContext context, IRubyObject other) {
@@ -789,7 +791,8 @@ public final int compareTo(IRubyObject other) {
if (other instanceof RubyBignum) {
return value.compareTo(((RubyBignum)other).value);
}
return (int)coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
ThreadContext context = getRuntime().getCurrentContext();
return (int)coerceCmp(context, sites(context).op_cmp, other).convertToInteger().getLongValue();
}

/** rb_big_cmp
@@ -810,7 +813,7 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
}
return dbl_cmp(getRuntime(), big2dbl(this), flt.getDoubleValue());
} else {
return coerceCmp(context, "<=>", other);
return coerceCmp(context, sites(context).op_cmp, other);
}

// wow, the only time we can use the java protocol ;)
@@ -932,4 +935,8 @@ public static RubyNumeric unmarshalFrom(UnmarshalStream input) throws IOExceptio
input.registerLinkTarget(result);
return result;
}

private static JavaSites.BignumSites sites(ThreadContext context) {
return context.sites.Bignum;
}
}
17 changes: 11 additions & 6 deletions core/src/main/java/org/jruby/RubyComplex.java
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
@@ -514,7 +515,7 @@ public IRubyObject op_add(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyNumeric && f_real_p(context, other).isTrue()) {
return newComplex(context, getMetaClass(), f_add(context, real, other), image);
}
return coerceBin(context, "+", other);
return coerceBin(context, sites(context).op_plus, other);
}

/** nucomp_sub
@@ -530,7 +531,7 @@ public IRubyObject op_sub(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyNumeric && f_real_p(context, other).isTrue()) {
return newComplex(context, getMetaClass(), f_sub(context, real, other), image);
}
return coerceBin(context, "-", other);
return coerceBin(context, sites(context).op_minus, other);
}

/** nucomp_mul
@@ -557,7 +558,7 @@ public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
f_mul(context, real, other),
f_mul(context, image, other));
}
return coerceBin(context, "*", other);
return coerceBin(context, sites(context).op_times, other);
}

/** nucomp_div / nucomp_quo
@@ -586,7 +587,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other) {
return RubyRational.newInstance(context, context.runtime.getRational(), coercedOther.first(), coercedOther.last());
}
}
return coerceBin(context, "/", other);
return coerceBin(context, sites(context).op_quo, other);
}

/** nucomp_fdiv
@@ -660,7 +661,7 @@ public IRubyObject op_expt(ThreadContext context, IRubyObject other) {
IRubyObject theta = a.eltInternal(1);
return f_complex_polar(context, getMetaClass(), f_expt(context, r, other), f_mul(context, theta, other));
}
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}

/** nucomp_equal_p
@@ -1052,5 +1053,9 @@ private static IRubyObject str_to_c_strict(ThreadContext context, IRubyObject re
throw context.runtime.newArgumentError("invalid value for convert(): " + s.convertToString());
}
return a.eltInternal(0);
}
}

private static JavaSites.ComplexSites sites(ThreadContext context) {
return context.sites.Complex;
}
}
67 changes: 38 additions & 29 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -43,8 +43,10 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.Signature;
import org.jruby.runtime.ThreadContext;
@@ -414,7 +416,7 @@ private IRubyObject addOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return context.runtime.newFloat((double) value + ((RubyFloat) other).getDoubleValue());
}
return coerceBin(context, "+", other);
return coerceBin(context, sites(context).op_plus, other);
}

/** fix_minus
@@ -476,7 +478,7 @@ private IRubyObject subtractOther(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyFloat) {
return context.runtime.newFloat((double) value - ((RubyFloat) other).getDoubleValue());
}
return coerceBin(context, "-", other);
return coerceBin(context, sites(context).op_minus, other);
}

/** fix_mul
@@ -498,7 +500,7 @@ private IRubyObject multiplyOther(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyFloat) {
return runtime.newFloat((double) value * ((RubyFloat) other).getDoubleValue());
}
return coerceBin(context, "*", other);
return coerceBin(context, sites(context).op_times, other);
}

public IRubyObject op_mul(ThreadContext context, long otherValue) {
@@ -548,12 +550,12 @@ public IRubyObject op_mul(ThreadContext context, long otherValue) {
public IRubyObject div_div(ThreadContext context, IRubyObject other) {
checkZeroDivisionError(context, other);

return idiv(context, other, "div");
return idiv(context, other, sites(context).div);
}

@JRubyMethod(name = "/")
public IRubyObject op_div(ThreadContext context, IRubyObject other) {
return idiv(context, other, "/");
return idiv(context, other, sites(context).op_quo);
}

public IRubyObject op_div(ThreadContext context, long other) {
@@ -587,6 +589,13 @@ public IRubyObject idiv(ThreadContext context, IRubyObject other, String method)
return coerceBin(context, method, other);
}

public IRubyObject idiv(ThreadContext context, IRubyObject other, CallSite site) {
if (other instanceof RubyFixnum) {
return idivLong(context, value, ((RubyFixnum) other).value);
}
return coerceBin(context, site, other);
}

public IRubyObject idiv(ThreadContext context, long y, String method) {
long x = value;

@@ -627,7 +636,7 @@ public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) {
return moduloFixnum(context, (RubyFixnum) other);
}
return coerceBin(context, "%", other);
return coerceBin(context, sites(context).op_mod, other);
}

public IRubyObject op_mod(ThreadContext context, long other) {
@@ -662,7 +671,7 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) {
return divmodFixnum(context, (RubyFixnum) other);
}
return coerceBin(context, "divmod", other);
return coerceBin(context, sites(context).divmod, other);
}

private IRubyObject divmodFixnum(ThreadContext context, RubyFixnum other) {
@@ -709,7 +718,7 @@ public IRubyObject quo(ThreadContext context, IRubyObject other) {
if (other instanceof RubyBignum) {
return RubyFloat.newFloat(context.runtime, (double) value / ((RubyBignum) other).getDoubleValue());
}
return coerceBin(context, "quo", other);
return coerceBin(context, sites(context).quo, other);
}

/** fix_pow
@@ -745,7 +754,7 @@ private IRubyObject powerOther(ThreadContext context, IRubyObject other) {
return RubyFloat.newFloat(runtime, Math.pow(value, ((RubyFloat) other)
.getDoubleValue()));
}
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}

public IRubyObject op_pow_19(ThreadContext context, IRubyObject other) {
@@ -780,7 +789,7 @@ private IRubyObject powerOther19(ThreadContext context, IRubyObject other) {
if (a == 0) return runtime.newFloat(b < 0 ? 1.0 / 0.0 : 0.0);
return RubyFloat.newFloat(runtime, Math.pow(a, b));
}
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}

private IRubyObject powerFixnum19(ThreadContext context, IRubyObject other) {
@@ -879,7 +888,8 @@ public final int compareTo(IRubyObject other) {
private int compareToOther(IRubyObject other) {
if (other instanceof RubyBignum) return BigInteger.valueOf(value).compareTo(((RubyBignum)other).getValue());
if (other instanceof RubyFloat) return Double.compare((double)value, ((RubyFloat)other).getDoubleValue());
return (int) coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
ThreadContext context = getRuntime().getCurrentContext();
return (int) coerceCmp(context, sites(context).op_cmp, other).convertToInteger().getLongValue();
}

/** fix_cmp
@@ -904,7 +914,7 @@ private IRubyObject compareOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return dbl_cmp(context.runtime, (double) value, ((RubyFloat) other).getDoubleValue());
}
return coerceCmp(context, "<=>", other);
return coerceCmp(context, sites(context).op_cmp, other);
}

/** fix_gt
@@ -935,7 +945,7 @@ private IRubyObject op_gtOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return RubyBoolean.newBoolean(context.runtime, (double) value > ((RubyFloat) other).getDoubleValue());
}
return coerceRelOp(context, ">", other);
return coerceRelOp(context, sites(context).op_gt, other);
}

/** fix_ge
@@ -965,7 +975,7 @@ private IRubyObject op_geOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return RubyBoolean.newBoolean(context.runtime, (double) value >= ((RubyFloat) other).getDoubleValue());
}
return coerceRelOp(context, ">=", other);
return coerceRelOp(context, sites(context).op_ge, other);
}

/** fix_lt
@@ -995,7 +1005,7 @@ private IRubyObject op_ltOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return RubyBoolean.newBoolean(context.runtime, (double) value < ((RubyFloat) other).getDoubleValue());
}
return coerceRelOp(context, "<", other);
return coerceRelOp(context, sites(context).op_lt, other);
}

/** fix_le
@@ -1025,7 +1035,7 @@ private IRubyObject op_leOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return RubyBoolean.newBoolean(context.runtime, (double) value <= ((RubyFloat) other).getDoubleValue());
}
return coerceRelOp(context, "<=", other);
return coerceRelOp(context, sites(context).op_le, other);
}

/** fix_rev
@@ -1224,19 +1234,6 @@ public static RubyFixnum unmarshalFrom(UnmarshalStream input) throws java.io.IOE
return input.getRuntime().newFixnum(input.unmarshalInt());
}

/* ================
* Singleton Methods
* ================
*/

/** rb_fix_induced_from
*
*/
@Deprecated
public static IRubyObject induced_from(IRubyObject recv, IRubyObject other) {
return RubyNumeric.num2fix(other);
}

private void checkZeroDivisionError(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat && ((RubyFloat) other).getDoubleValue() == 0.0d) {
throw context.runtime.newZeroDivisionError();
@@ -1247,4 +1244,16 @@ private void checkZeroDivisionError(ThreadContext context, IRubyObject other) {
public RubyInteger convertToInteger(String method) {
return this;
}

private static JavaSites.FixnumSites sites(ThreadContext context) {
return context.sites.Fixnum;
}

/** rb_fix_induced_from
*
*/
@Deprecated
public static IRubyObject induced_from(IRubyObject recv, IRubyObject other) {
return RubyNumeric.num2fix(other);
}
}
34 changes: 20 additions & 14 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -276,7 +277,7 @@ public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
case FLOAT:
return RubyFloat.newFloat(getRuntime(), value + ((RubyNumeric) other).getDoubleValue());
default:
return coerceBin(context, "+", other);
return coerceBin(context, sites(context).op_plus, other);
}
}

@@ -295,7 +296,7 @@ public IRubyObject op_minus(ThreadContext context, IRubyObject other) {
case FLOAT:
return RubyFloat.newFloat(getRuntime(), value - ((RubyNumeric) other).getDoubleValue());
default:
return coerceBin(context, "-", other);
return coerceBin(context, sites(context).op_minus, other);
}
}

@@ -315,7 +316,7 @@ public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
return RubyFloat.newFloat(
getRuntime(), value * ((RubyNumeric) other).getDoubleValue());
default:
return coerceBin(context, "*", other);
return coerceBin(context, sites(context).op_times, other);
}
}

@@ -335,7 +336,7 @@ public IRubyObject op_fdiv(ThreadContext context, IRubyObject other) { // don't
case FLOAT:
return RubyFloat.newFloat(getRuntime(), value / ((RubyNumeric) other).getDoubleValue());
default:
return coerceBin(context, "/", other);
return coerceBin(context, sites(context).op_quo, other);
}
}

@@ -362,7 +363,7 @@ public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
double y = ((RubyNumeric) other).getDoubleValue();
return op_mod(context, y);
default:
return coerceBin(context, "%", other);
return coerceBin(context, sites(context).op_mod, other);
}
}

@@ -417,7 +418,7 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
RubyFloat cdr = RubyFloat.newFloat(runtime, mod);
return RubyArray.newArray(runtime, car, cdr);
default:
return coerceBin(context, "divmod", other);
return coerceBin(context, sites(context).divmod, other);
}
}

@@ -444,7 +445,7 @@ public IRubyObject op_pow(ThreadContext context, IRubyObject other) {
return RubyFloat.newFloat(context.runtime, Math.pow(value, ((RubyNumeric) other)
.getDoubleValue()));
default:
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}
}

@@ -465,7 +466,7 @@ public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
return op_pow(context, other);
}
default:
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}
}

@@ -511,7 +512,8 @@ public final int compareTo(IRubyObject other) {
case FLOAT:
return Double.compare(value, ((RubyNumeric) other).getDoubleValue());
default:
return (int) coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
ThreadContext context = getRuntime().getCurrentContext();
return (int) coerceCmp(context, sites(context).op_cmp, other).convertToInteger().getLongValue();
}
}

@@ -544,7 +546,7 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
return value < 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.one(runtime);
}
}
return coerceCmp(context, "<=>", other);
return coerceCmp(context, sites(context).op_cmp, other);
}
}

@@ -564,7 +566,7 @@ public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value > b);
default:
return coerceRelOp(context, ">", other);
return coerceRelOp(context, sites(context).op_gt, other);
}
}

@@ -584,7 +586,7 @@ public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value >= b);
default:
return coerceRelOp(context, ">=", other);
return coerceRelOp(context, sites(context).op_ge, other);
}
}

@@ -604,7 +606,7 @@ public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value < b);
default:
return coerceRelOp(context, "<", other);
return coerceRelOp(context, sites(context).op_lt, other);
}
}

@@ -624,7 +626,7 @@ public IRubyObject op_le(ThreadContext context, IRubyObject other) {
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value <= b);
default:
return coerceRelOp(context, "<=", other);
return coerceRelOp(context, sites(context).op_le, other);
}
}

@@ -993,4 +995,8 @@ public IRubyObject next_float() {
public IRubyObject prev_float() {
return RubyFloat.newFloat(getRuntime(), Math.nextAfter(value, Double.NEGATIVE_INFINITY));
}

private static JavaSites.FloatSites sites(ThreadContext context) {
return context.sites.Float;
}
}
164 changes: 123 additions & 41 deletions core/src/main/java/org/jruby/RubyNumeric.java

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ObjectMarshal;
import org.jruby.runtime.ThreadContext;
@@ -485,7 +486,7 @@ public IRubyObject op_add(ThreadContext context, IRubyObject other) {
RubyRational otherRational = (RubyRational)other;
return f_addsub(context, num, den, otherRational.num, otherRational.den, true);
}
return coerceBin(context, "+", other);
return coerceBin(context, sites(context).op_plus, other);
}

/** nurat_sub
@@ -501,7 +502,7 @@ public IRubyObject op_sub(ThreadContext context, IRubyObject other) {
RubyRational otherRational = (RubyRational)other;
return f_addsub(context, num, den, otherRational.num, otherRational.den, false);
}
return coerceBin(context, "-", other);
return coerceBin(context, sites(context).op_minus, other);
}

/** f_muldiv
@@ -554,7 +555,7 @@ public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
RubyRational otherRational = (RubyRational)other;
return f_muldiv(context, num, den, otherRational.num, otherRational.den, true);
}
return coerceBin(context, "*", other);
return coerceBin(context, sites(context).op_times, other);
}

/** nurat_div
@@ -576,7 +577,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other) {
RubyRational otherRational = (RubyRational)other;
return f_muldiv(context, num, den, otherRational.num, otherRational.den, false);
}
return coerceBin(context, "/", other);
return coerceBin(context, sites(context).op_quo, other);
}

/** nurat_fdiv
@@ -638,7 +639,7 @@ public IRubyObject op_expt(ThreadContext context, IRubyObject other) {
} else if (other instanceof RubyFloat || other instanceof RubyRational) {
return f_expt(context, f_to_f(context, this), other);
}
return coerceBin(context, "**", other);
return coerceBin(context, sites(context).op_exp, other);
}


@@ -666,7 +667,7 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
}
return f_cmp(context, f_sub(context, num1, num2), RubyFixnum.zero(context.runtime));
}
return coerceBin(context, "<=>", other);
return coerceBin(context, sites(context).op_cmp, other);
}

/** nurat_equal_p
@@ -1113,8 +1114,12 @@ public static IRubyObject numericQuo(ThreadContext context, IRubyObject x, IRuby
if (Numeric.CANON && canonicalization) {
x = newRationalRaw(context.runtime, x);
} else {
x = TypeConverter.convertToType(x, context.runtime.getRational(), "to_r");
x = TypeConverter.convertToType(context, x, context.runtime.getRational(), sites(context).to_r_checked);
}
return x.callMethod(context, "/", y);
return sites(context).op_quo.call(context, x, x, y);
}

private static JavaSites.RationalSites sites(ThreadContext context) {
return context.sites.Rational;
}
}
45 changes: 25 additions & 20 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -56,6 +56,7 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
@@ -333,25 +334,25 @@ public static IRubyObject mode(ThreadContext context, IRubyObject recv, IRubyObj

RubyFixnum _EXCEPTION_INFINITY = (RubyFixnum)clazz.getConstant("EXCEPTION_INFINITY");
if ((longMode & _EXCEPTION_INFINITY.getLongValue()) != 0) {
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, "|", _EXCEPTION_INFINITY)
: (RubyFixnum)currentExceptionMode.callCoerced(context, "&", new RubyFixnum(context.runtime, ~(_EXCEPTION_INFINITY).getLongValue()));
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_or, _EXCEPTION_INFINITY)
: (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_and, new RubyFixnum(context.runtime, ~(_EXCEPTION_INFINITY).getLongValue()));
}

RubyFixnum _EXCEPTION_NaN = (RubyFixnum)clazz.getConstant("EXCEPTION_NaN");
if ((longMode & _EXCEPTION_NaN.getLongValue()) != 0) {
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, "|", _EXCEPTION_NaN)
: (RubyFixnum)currentExceptionMode.callCoerced(context, "&", new RubyFixnum(context.runtime, ~(_EXCEPTION_NaN).getLongValue()));
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_or, _EXCEPTION_NaN)
: (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_and, new RubyFixnum(context.runtime, ~(_EXCEPTION_NaN).getLongValue()));
}

RubyFixnum _EXCEPTION_UNDERFLOW = (RubyFixnum)clazz.getConstant("EXCEPTION_UNDERFLOW");
if ((longMode & _EXCEPTION_UNDERFLOW.getLongValue()) != 0) {
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, "|", _EXCEPTION_UNDERFLOW)
: (RubyFixnum)currentExceptionMode.callCoerced(context, "&", new RubyFixnum(context.runtime, ~(_EXCEPTION_UNDERFLOW).getLongValue()));
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_or, _EXCEPTION_UNDERFLOW)
: (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_and, new RubyFixnum(context.runtime, ~(_EXCEPTION_UNDERFLOW).getLongValue()));
}
RubyFixnum _EXCEPTION_OVERFLOW = (RubyFixnum)clazz.getConstant("EXCEPTION_OVERFLOW");
if ((longMode & _EXCEPTION_OVERFLOW.getLongValue()) != 0) {
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, "|", _EXCEPTION_OVERFLOW)
: (RubyFixnum)currentExceptionMode.callCoerced(context, "&", new RubyFixnum(context.runtime, ~(_EXCEPTION_OVERFLOW).getLongValue()));
newExceptionMode = (value.isTrue()) ? (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_or, _EXCEPTION_OVERFLOW)
: (RubyFixnum)currentExceptionMode.callCoerced(context, sites(context).op_and, new RubyFixnum(context.runtime, ~(_EXCEPTION_OVERFLOW).getLongValue()));
}
c.setInternalModuleVariable("vpExceptionMode", newExceptionMode);
return newExceptionMode;
@@ -696,7 +697,7 @@ public IRubyObject op_mod19(ThreadContext context, IRubyObject other) {
// TODO: full-precision divmod is 1000x slower than MRI!
RubyBigDecimal val = getVpValue19(context, other, false);

if (val == null) return callCoerced(context, "%", other, true);
if (val == null) return callCoerced(context, sites(context).op_mod, other, true);
if (isNaN() || val.isNaN() || isInfinity() && val.isInfinity()) return newNaN(context.runtime);
if (val.isZero()) throw context.runtime.newZeroDivisionError();
if (isInfinity()) return newNaN(context.runtime);
@@ -723,7 +724,7 @@ public IRubyObject remainder19(ThreadContext context, IRubyObject arg) {
private IRubyObject remainderInternal(ThreadContext context, RubyBigDecimal val, IRubyObject arg) {
// TODO: full-precision remainder is 1000x slower than MRI!
if (isInfinity() || isNaN()) return newNaN(context.runtime);
if (val == null) return callCoerced(context, "remainder", arg, true);
if (val == null) return callCoerced(context, sites(context).remainder, arg, true);
if (val.isInfinity() || val.isNaN() || val.isZero()) return newNaN(context.runtime);

// Java and MRI definitions of remainder are the same.
@@ -747,7 +748,7 @@ public IRubyObject mult2(ThreadContext context, IRubyObject b, IRubyObject n) {
public IRubyObject mult219(ThreadContext context, IRubyObject b, IRubyObject n) {
RubyBigDecimal val = getVpValue19(context, b, false);
if (val == null) { // TODO: what about n arg?
return callCoerced(context, "*", b, true);
return callCoerced(context, sites(context).op_times, b, true);
}
return multInternal(context.runtime, val, n);
}
@@ -891,7 +892,7 @@ private IRubyObject addInternal(ThreadContext context, RubyBigDecimal val, IRuby
// http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/17374
// return callCoerced(context, op, b, true); -- this is MRI behavior.
// We'll use ours for now, thus providing an ability to add Floats.
return callCoerced(context, "+", b, true);
return callCoerced(context, sites(context).op_plus, b, true);
}

RubyBigDecimal res = handleAddSpecialValues(context, val);
@@ -962,7 +963,7 @@ public IRubyObject sub219(ThreadContext context, IRubyObject b, IRubyObject n) {
}

private IRubyObject subInternal(ThreadContext context, RubyBigDecimal val, IRubyObject b) {
if (val == null) return callCoerced(context, "-", b);
if (val == null) return callCoerced(context, sites(context).op_minus, b);

RubyBigDecimal res = handleMinusSpecialValues(context, val);

@@ -1021,7 +1022,7 @@ public IRubyObject op_quo20(ThreadContext context, IRubyObject other) {

private IRubyObject op_quo19_20(ThreadContext context, IRubyObject other) {
RubyBigDecimal val = getVpValue19(context, other, false);
if (val == null) return callCoerced(context, "/", other, true);
if (val == null) return callCoerced(context, sites(context).op_quo, other, true);

// regular division with some default precision
// proper algorithm to set the precision
@@ -1037,7 +1038,7 @@ private IRubyObject op_quo19_20(ThreadContext context, IRubyObject other) {
public IRubyObject op_div(ThreadContext context, IRubyObject other) {
// integer division
RubyBigDecimal val = getVpValue(context, other, false);
if (val == null) return callCoerced(context, "div", other);
if (val == null) return callCoerced(context, sites(context).div, other);
if (isNaN() || val.isZero() || val.isNaN()) return newNaN(context.runtime);
if (isInfinity() || val.isInfinity()) return newNaN(context.runtime);

@@ -1048,7 +1049,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other) {
@JRubyMethod(name = "div")
public IRubyObject op_div19(ThreadContext context, IRubyObject r) {
RubyBigDecimal val = getVpValue19(context, r, false);
if (val == null) return callCoerced(context, "div", r, true);
if (val == null) return callCoerced(context, sites(context).div, r, true);

if (isNaN() || val.isNaN()) throw context.runtime.newFloatDomainError("Computation results to 'NaN'");
if (isInfinity() && val.isOne()) throw context.runtime.newFloatDomainError("Computation results to 'Infinity'");
@@ -1066,7 +1067,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other, IRubyObject
int scale = RubyNumeric.fix2int(digits);

RubyBigDecimal val = getVpValue(context, other, false);
if (val == null) return callCoerced(context, "div", other, true);
if (val == null) return callCoerced(context, sites(context).div, other, true);
if (isNaN() || (isZero() && val.isZero()) || val.isNaN()) return newNaN(context.runtime);

if (val.isZero()) {
@@ -1089,7 +1090,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other, IRubyObject
@JRubyMethod(name = "div")
public IRubyObject op_div19(ThreadContext context, IRubyObject other, IRubyObject digits) {
RubyBigDecimal val = getVpValue(context, other, false);
if (val == null) return callCoerced(context, "div", other, true);
if (val == null) return callCoerced(context, sites(context).div, other, true);

if (isNaN() || val.isNaN()) {
throw context.runtime.newFloatDomainError("Computation results to 'NaN'");
@@ -1102,7 +1103,7 @@ private IRubyObject cmp(ThreadContext context, final IRubyObject arg, final char
final int e;
RubyBigDecimal rb = getVpValue(context, arg, false);
if (rb == null) {
IRubyObject cmp = callCoerced(context, "<=>", arg, false);
IRubyObject cmp = callCoerced(context, sites(context).op_cmp, arg, false);
if ( cmp.isNil() ) { // arg.coerce failed
if (op == '*') return context.nil;
if (op == '=' || isNaN()) return context.runtime.getFalse();
@@ -1248,7 +1249,7 @@ public IRubyObject divmod19(ThreadContext context, IRubyObject other) {
Ruby runtime = context.runtime;
RubyBigDecimal val = getVpValue19(context, other, false);

if (val == null) return callCoerced(context, "divmod", other, true);
if (val == null) return callCoerced(context, sites(context).divmod, other, true);
if (isNaN() || val.isNaN() || isInfinity() && val.isInfinity()) return RubyArray.newArray(runtime, newNaN(runtime), newNaN(runtime));
if (val.isZero()) throw context.runtime.newZeroDivisionError();
if (isInfinity()) {
@@ -1817,4 +1818,8 @@ private boolean is_even(IRubyObject x) {

return false;
}

private static JavaSites.BigDecimalSites sites(ThreadContext context) {
return context.sites.BigDecimal;
}
}
114 changes: 114 additions & 0 deletions core/src/main/java/org/jruby/runtime/JavaSites.java
Original file line number Diff line number Diff line change
@@ -19,12 +19,19 @@ public class JavaSites {
public final ObjectSites Object = new ObjectSites();
public final ArraySites Array = new ArraySites();
public final StringSites String = new StringSites();
public final NumericSites Numeric = new NumericSites();
public final FixnumSites Fixnum = new FixnumSites();
public final FloatSites Float = new FloatSites();
public final BignumSites Bignum = new BignumSites();
public final TimeSites Time = new TimeSites();
public final EnumerableSites Enumerable = new EnumerableSites();
public final IOSites IO = new IOSites();
public final TypeConverterSites TypeConverter = new TypeConverterSites();
public final HelpersSites Helpers = new HelpersSites();
public final IRRuntimeHelpersSites IRRuntimeHelpers = new IRRuntimeHelpersSites();
public final BigDecimalSites BigDecimal = new BigDecimalSites();
public final ComplexSites Complex = new ComplexSites();
public final RationalSites Rational = new RationalSites();

public static class BasicObjectSites {
public final CallSite respond_to = new FunctionalCachingCallSite("respond_to?");
@@ -93,6 +100,76 @@ public IRubyObject call(ThreadContext context, IRubyObject recv, IRubyObject oth
};
}

public static class NumericSites {
public final RespondToCallSite respond_to_coerce = new RespondToCallSite("coerce");
public final CallSite coerce = new FunctionalCachingCallSite("coerce");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite floor = new FunctionalCachingCallSite("floor");
public final CallSite div = new FunctionalCachingCallSite("div");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite op_mod = new FunctionalCachingCallSite("%");
public final CallSite op_lt = new FunctionalCachingCallSite("<");
public final CallSite op_gt = new FunctionalCachingCallSite(">");
public final CallSite op_uminus = new FunctionalCachingCallSite("-@");
public final CallSite to_i = new FunctionalCachingCallSite("to_i");
public final CallSite zero = new FunctionalCachingCallSite("zero?");
public final CallSite op_equals = new FunctionalCachingCallSite("==");
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite numerator = new FunctionalCachingCallSite("numerator");
public final CallSite denominator = new FunctionalCachingCallSite("denominator");
}

public static class FixnumSites {
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite divmod = new FunctionalCachingCallSite("divmod");
public final CallSite div = new FunctionalCachingCallSite("div");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite op_mod = new FunctionalCachingCallSite("%");
public final CallSite op_exp = new FunctionalCachingCallSite("**");
public final CallSite quo = new FunctionalCachingCallSite("quo");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
public final CallSite op_ge = new FunctionalCachingCallSite(">=");
public final CallSite op_le = new FunctionalCachingCallSite("<=");
public final CallSite op_gt = new FunctionalCachingCallSite(">");
public final CallSite op_lt = new FunctionalCachingCallSite("<");
}

public static class BignumSites {
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
public final CallSite divmod = new FunctionalCachingCallSite("divmod");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite div = new FunctionalCachingCallSite("div");
public final CallSite op_mod = new FunctionalCachingCallSite("%");
public final CallSite op_exp = new FunctionalCachingCallSite("**");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite quo = new FunctionalCachingCallSite("quo");
public final CallSite remainder = new FunctionalCachingCallSite("remainder");
public final CallSite op_and = new FunctionalCachingCallSite("&");
public final CallSite op_or = new FunctionalCachingCallSite("|");
public final CallSite op_xor = new FunctionalCachingCallSite("^");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
}

public static class FloatSites {
public final CallSite divmod = new FunctionalCachingCallSite("divmod");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
public final CallSite op_mod = new FunctionalCachingCallSite("%");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite op_exp = new FunctionalCachingCallSite("**");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
public final CallSite op_ge = new FunctionalCachingCallSite(">=");
public final CallSite op_le = new FunctionalCachingCallSite("<=");
public final CallSite op_gt = new FunctionalCachingCallSite(">");
public final CallSite op_lt = new FunctionalCachingCallSite("<");
}

public static class TimeSites {
public final RespondToCallSite respond_to_cmp = new RespondToCallSite("<=>");
public final CallSite cmp = new FunctionalCachingCallSite("<=>");
@@ -141,6 +218,43 @@ public static class IRRuntimeHelpersSites {
public final CheckedSites to_a_checked = new CheckedSites("to_a");
}

public static class BigDecimalSites {
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
public final CallSite divmod = new FunctionalCachingCallSite("divmod");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite div = new FunctionalCachingCallSite("div");
public final CallSite op_mod = new FunctionalCachingCallSite("%");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite remainder = new FunctionalCachingCallSite("remainder");
public final CallSite op_or = new FunctionalCachingCallSite("|");
public final CallSite op_and = new FunctionalCachingCallSite("&");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
}

public static class ComplexSites {
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite op_exp = new FunctionalCachingCallSite("**");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
}

public static class RationalSites {
public final CallSite op_plus = new FunctionalCachingCallSite("+");
public final CallSite op_minus = new FunctionalCachingCallSite("-");
public final CallSite divmod = new FunctionalCachingCallSite("divmod");
public final CallSite op_quo = new FunctionalCachingCallSite("/");
public final CallSite div = new FunctionalCachingCallSite("div");
public final CallSite mod = new FunctionalCachingCallSite("mod");
public final CallSite op_exp = new FunctionalCachingCallSite("**");
public final CallSite op_times = new FunctionalCachingCallSite("*");
public final CallSite quo = new FunctionalCachingCallSite("quo");
public final CallSite remainder = new FunctionalCachingCallSite("remainder");
public final CallSite op_cmp = new FunctionalCachingCallSite("<=>");
public final CheckedSites to_r_checked = new CheckedSites("to_r");
}

public static class CheckedSites {
public final RespondToCallSite respond_to_X;
public final CachingCallSite respond_to_missing = new FunctionalCachingCallSite("respond_to_missing?");

0 comments on commit 5acd4ca

Please sign in to comment.