Skip to content

Commit

Permalink
Showing 26 changed files with 647 additions and 417 deletions.
26 changes: 23 additions & 3 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -80,6 +80,7 @@

import org.jcodings.Encoding;
import org.joda.time.DateTimeZone;
import org.joni.WarnCallback;
import org.jruby.ast.Node;
import org.jruby.ast.RootNode;
import org.jruby.ast.executable.RuntimeCache;
@@ -2847,6 +2848,10 @@ public RubyWarnings getWarnings() {
return warnings;
}

WarnCallback getRegexpWarnings() {
return regexpWarnings;
}

public PrintStream getErrorStream() {
// FIXME: We can't guarantee this will always be a RubyIO...so the old code here is not safe
/*java.io.OutputStream os = ((RubyIO) getGlobalVariables().getService("$stderr")).getOutStream();
@@ -3030,13 +3035,23 @@ public void addBoundMethod(String className, String methodName, String rubyName)
javaToRuby.put(methodName, rubyName);
}

public void addBoundMethods(String className, String... tuples) {
Map<String, String> javaToRuby = boundMethods.get(className);
if (javaToRuby == null) boundMethods.put(className, javaToRuby = new HashMap<>(tuples.length / 2 + 1, 1));
for (int i = 0; i < tuples.length; i += 2) {
javaToRuby.put(tuples[i], tuples[i+1]);
}
}

@Deprecated // no longer used -> except for IndyBinder
public void addBoundMethodsPacked(String className, String packedTuples) {
List<String> names = StringSupport.split(packedTuples, ';');
for (int i = 0; i < names.size(); i += 2) {
addBoundMethod(className, names.get(i), names.get(i+1));
}
}

@Deprecated // no longer used -> except for IndyBinder
public void addSimpleBoundMethodsPacked(String className, String packedNames) {
List<String> names = StringSupport.split(packedNames, ';');
for (String name : names) {
@@ -4502,8 +4517,7 @@ public List<StrptimeToken> getCachedStrptimePattern(String pattern) {
* @param method
*/
void addProfiledMethod(final String name, final DynamicMethod method) {
if (!config.isProfiling()) return;
if (method.isUndefined()) return;
if (!config.isProfiling() || method.isUndefined()) return;

getProfilingService().addProfiledMethod( name, method );
}
@@ -5007,7 +5021,7 @@ private MRIRecursionGuard oldRecursionGuard() {

private final long startTime = System.currentTimeMillis();

private final RubyInstanceConfig config;
final RubyInstanceConfig config;

private InputStream in;
private PrintStream out;
@@ -5058,6 +5072,12 @@ private MRIRecursionGuard oldRecursionGuard() {

private GlobalVariables globalVariables = new GlobalVariables(this);
private final RubyWarnings warnings = new RubyWarnings(this);
private final WarnCallback regexpWarnings = new WarnCallback() {
@Override
public void warn(String message) {
getWarnings().warning(message);
}
};

// Contains a list of all blocks (as Procs) that should be called when
// the runtime environment exits.
84 changes: 39 additions & 45 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -1743,50 +1743,6 @@ public IRubyObject send(ThreadContext context, IRubyObject[] args, Block block)
return getMetaClass().finvoke(context, this, name, args, block);
}

@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval19(ThreadContext context, Block block) {
return specificEval(context, getInstanceEvalClass(), block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block, EvalType.INSTANCE_EVAL);
}

@JRubyMethod(name = "instance_exec", optional = 3, rest = true,
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Block block) {
if (!block.isGiven()) {
throw context.runtime.newLocalJumpErrorNoBlock();
}

RubyModule klazz;
if (isImmediate()) {
// Ruby uses Qnil here, we use "dummy" because we need a class
klazz = context.runtime.getDummy();
} else {
klazz = getSingletonClass();
}

return yieldUnder(context, klazz, args, block, EvalType.INSTANCE_EVAL);
}

/**
* Will yield to the specific block changing the self to be the
* current object instead of the self that is part of the frame
@@ -2631,19 +2587,49 @@ public RubyArray to_a() {
* k = Klass.new
* k.instance_eval { @secret } #=> 99
*/

@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval(ThreadContext context, Block block) {
return specificEval(context, getInstanceEvalClass(), block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block, EvalType.INSTANCE_EVAL);
}
@JRubyMethod(name = "instance_eval",
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block, EvalType.INSTANCE_EVAL);
}

@Deprecated
public IRubyObject instance_eval19(ThreadContext context, Block block) {
return specificEval(context, getInstanceEvalClass(), block, EvalType.INSTANCE_EVAL);
}
@Deprecated
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, block, EvalType.INSTANCE_EVAL);
}
@Deprecated
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block, EvalType.INSTANCE_EVAL);
}
@Deprecated
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block, EvalType.INSTANCE_EVAL);
}

/** rb_obj_instance_exec
*
* call-seq:
@@ -2662,9 +2648,12 @@ public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, IRubyO
* k = Klass.new
* k.instance_exec(5) {|x| @secret+x } #=> 104
*/
@JRubyMethod(name = "instance_exec", optional = 3, rest = true,
reads = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE},
writes = {LASTLINE, BACKREF, VISIBILITY, BLOCK, SELF, METHODNAME, LINE, CLASS, FILENAME, SCOPE})
public IRubyObject instance_exec(ThreadContext context, IRubyObject[] args, Block block) {
if (!block.isGiven()) {
throw context.runtime.newArgumentError("block not supplied");
throw context.runtime.newLocalJumpErrorNoBlock();
}

RubyModule klazz;
@@ -2678,6 +2667,11 @@ public IRubyObject instance_exec(ThreadContext context, IRubyObject[] args, Bloc
return yieldUnder(context, klazz, args, block, EvalType.INSTANCE_EVAL);
}

@Deprecated
public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Block block) {
return instance_exec(context, args, block);
}

/** rb_obj_extend
*
* call-seq:
72 changes: 46 additions & 26 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -218,12 +218,12 @@ public static double big2dbl(RubyBignum value) {
return dbl;
}

private IRubyObject checkShiftDown(RubyBignum other) {
if (other.value.signum() == 0) return RubyFixnum.zero(getRuntime());
private RubyFixnum checkShiftDown(ThreadContext context, RubyBignum other) {
if (other.value.signum() == 0) return RubyFixnum.zero(context.runtime);
if (value.compareTo(LONG_MIN) < 0 || value.compareTo(LONG_MAX) > 0) {
return other.value.signum() >= 0 ? RubyFixnum.zero(getRuntime()) : RubyFixnum.minus_one(getRuntime());
return other.value.signum() >= 0 ? RubyFixnum.zero(context.runtime) : RubyFixnum.minus_one(context.runtime);
}
return getRuntime().getNil();
return null;
}

/**
@@ -626,27 +626,32 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
*/
@JRubyMethod(name = {"%", "modulo"}, required = 1)
public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
if (!other.isNil() && other instanceof RubyFloat
&& ((RubyFloat)other).getDoubleValue() == 0) {
throw context.runtime.newZeroDivisionError();
if (other instanceof RubyFixnum) {
return op_mod(context, ((RubyFixnum) other).getLongValue());
}

final BigInteger otherValue;
if (other instanceof RubyFixnum) {
otherValue = fix2big((RubyFixnum) other);
} else if (other instanceof RubyBignum) {
if (other instanceof RubyBignum) {
otherValue = ((RubyBignum) other).value;
} else {
if (other instanceof RubyFloat && ((RubyFloat) other).getDoubleValue() == 0) {
throw context.runtime.newZeroDivisionError();
}
return coerceBin(context, sites(context).op_mod, other);
if (otherValue.signum() == 0) throw context.runtime.newZeroDivisionError();

BigInteger result = value.mod(otherValue.abs());
if (otherValue.signum() == -1 && result.signum() != 0) result = otherValue.add(result);
return bignorm(context.runtime, result);
}

if (otherValue.signum() == 0) throw context.runtime.newZeroDivisionError();
if (other instanceof RubyFloat && ((RubyFloat) other).getDoubleValue() == 0) {
throw context.runtime.newZeroDivisionError();
}
return coerceBin(context, sites(context).op_mod, other);
}

@Override
public IRubyObject op_mod(ThreadContext context, long other) {
if (other == 0) throw context.runtime.newZeroDivisionError();

BigInteger result = value.mod(otherValue.abs());
if (otherValue.signum() == -1 && result.signum() != 0) result = otherValue.add(result);
BigInteger result = value.mod(long2big(other < 0 ? -other : other));
if (other < 0 && result.signum() != 0) result = long2big(other).add(result);
return bignorm(context.runtime, result);
}

@@ -850,13 +855,13 @@ public IRubyObject op_lshift(ThreadContext context, IRubyObject other) {

for (;;) {
if (other instanceof RubyFixnum) {
shift = ((RubyFixnum)other).getLongValue();
shift = ((RubyFixnum) other).getLongValue();
break;
} else if (other instanceof RubyBignum) {
RubyBignum otherBignum = (RubyBignum)other;
RubyBignum otherBignum = (RubyBignum) other;
if (otherBignum.value.signum() < 0) {
IRubyObject tmp = otherBignum.checkShiftDown(this);
if (!tmp.isNil()) return tmp;
IRubyObject tmp = otherBignum.checkShiftDown(context, this);
if (tmp != null) return tmp;
}
shift = big2long(otherBignum);
break;
@@ -876,13 +881,13 @@ public IRubyObject op_rshift(ThreadContext context, IRubyObject other) {

for (;;) {
if (other instanceof RubyFixnum) {
shift = ((RubyFixnum)other).getLongValue();
shift = ((RubyFixnum) other).getLongValue();
break;
} else if (other instanceof RubyBignum) {
RubyBignum otherBignum = (RubyBignum)other;
RubyBignum otherBignum = (RubyBignum) other;
if (otherBignum.value.signum() >= 0) {
IRubyObject tmp = otherBignum.checkShiftDown(this);
if (!tmp.isNil()) return tmp;
IRubyObject tmp = otherBignum.checkShiftDown(context, this);
if (tmp != null) return tmp;
}
shift = big2long(otherBignum);
break;
@@ -1177,6 +1182,21 @@ public boolean isImmediate() {
return true;
}

@Override
public IRubyObject numerator(ThreadContext context) {
return this;
}

@Override
public IRubyObject denominator(ThreadContext context) {
return RubyFixnum.one(context.runtime);
}

public RubyRational convertToRational() {
final Ruby runtime = getRuntime();
return RubyRational.newRationalRaw(runtime, this, RubyFixnum.one(runtime));
}

private static JavaSites.BignumSites sites(ThreadContext context) {
return context.sites.Bignum;
}
36 changes: 34 additions & 2 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -730,6 +730,7 @@ public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
return coerceBin(context, sites(context).op_mod, other);
}

@Override
public IRubyObject op_mod(ThreadContext context, long other) {
return moduloFixnum(context, other);
}
@@ -846,13 +847,13 @@ private IRubyObject powerOther(ThreadContext context, IRubyObject other) {
return coerceBin(context, sites(context).op_exp, other);
}

private IRubyObject powerFixnum(ThreadContext context, RubyFixnum other) {
private RubyNumeric powerFixnum(ThreadContext context, RubyFixnum other) {
Ruby runtime = context.runtime;
long a = value;
long b = other.value;
if (b < 0) {
RubyRational rational = RubyRational.newRationalRaw(runtime, this);
return numFuncall(context, rational, sites(context).op_exp_rational, other);
return (RubyNumeric) numFuncall(context, rational, sites(context).op_exp_rational, other);
}
if (b == 0) {
return RubyFixnum.one(runtime);
@@ -1363,6 +1364,37 @@ protected boolean int_round_zero_p(ThreadContext context, int ndigits) {
return (-0.415241 * ndigits - 0.125 > bytes);
}

@Override
public IRubyObject numerator(ThreadContext context) {
return this;
}

@Override
public IRubyObject denominator(ThreadContext context) {
return one(context.runtime);
}

public RubyRational convertToRational() {
final Ruby runtime = getRuntime();
return RubyRational.newRationalRaw(runtime, this, one(runtime));
}

@Override
public IRubyObject remainder(ThreadContext context, IRubyObject y) {
RubyFixnum x = this;
JavaSites.FixnumSites sites = sites(context);
IRubyObject z = sites.op_mod.call(context, this, this, y);

if ((!Helpers.rbEqual(context, z, RubyFixnum.zero(context.runtime), sites.op_equal).isTrue()) &&
((x.isNegative() &&
((RubyInteger) y).isPositive()) ||
(x.isPositive() &&
((RubyInteger) y).isNegative()))) {
return sites.op_minus.call(context, z, z, y);
}
return z;
}

private static JavaSites.FixnumSites sites(ThreadContext context) {
return context.sites.Fixnum;
}
15 changes: 12 additions & 3 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -198,11 +198,13 @@ public int signum() {
}

@Override
@JRubyMethod(name = "negative?")
public IRubyObject isNegative(ThreadContext context) {
return context.runtime.newBoolean(signum() < 0);
}

@Override
@JRubyMethod(name = "positive?")
public IRubyObject isPositive(ThreadContext context) {
return context.runtime.newBoolean(signum() > 0);
}
@@ -232,7 +234,7 @@ public static IRubyObject induced_from(ThreadContext context, IRubyObject recv,
/** flo_to_s
*
*/
@JRubyMethod(name = "to_s")
@JRubyMethod(name = {"to_s", "inspect"})
@Override
public IRubyObject to_s() {
final Ruby runtime = getRuntime();
@@ -283,6 +285,12 @@ public IRubyObject coerce(IRubyObject other) {
*
*/
@JRubyMethod(name = "-@")
@Override
public IRubyObject op_uminus(ThreadContext context) {
return RubyFloat.newFloat(context.runtime, -value);
}

@Deprecated
public IRubyObject op_uminus() {
return RubyFloat.newFloat(getRuntime(), -value);
}
@@ -291,6 +299,7 @@ public IRubyObject op_uminus() {
*
*/
@JRubyMethod(name = "+", required = 1)
@Override
public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
switch (other.getMetaClass().getClassIndex()) {
case INTEGER:
@@ -366,7 +375,7 @@ public IRubyObject op_div(ThreadContext context, double other) { // don't overri
/** flo_quo
*
*/
@JRubyMethod(name = "quo")
@JRubyMethod(name = {"quo", "fdiv"})
public IRubyObject quo(ThreadContext context, IRubyObject other) {
return numFuncall(context, this, sites(context).op_quo, other);
}
@@ -467,7 +476,7 @@ public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
/** flo_eq
*
*/
@JRubyMethod(name = "==", required = 1)
@JRubyMethod(name = {"==", "==="}, required = 1)
@Override
public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
if (Double.isNaN(value)) {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -1529,7 +1529,7 @@ public static ClassLoader defaultClassLoader() {

private ProfilingMode profilingMode = Options.CLI_PROFILING_MODE.load();
private ProfileOutput profileOutput = new ProfileOutput(System.err);
private String profilingService;
private String profilingService = Options.CLI_PROFILING_SERVICE.load();;

private ClassLoader loader = defaultClassLoader();

32 changes: 21 additions & 11 deletions core/src/main/java/org/jruby/RubyInteger.java
Original file line number Diff line number Diff line change
@@ -619,16 +619,9 @@ public IRubyObject gcd(ThreadContext context, IRubyObject other) {

// MRI: rb_int_fdiv_double and rb_int_fdiv in one
@Override
@JRubyMethod(name = "fdiv")
public IRubyObject fdiv(ThreadContext context, IRubyObject y) {
RubyInteger x = this;
if (y instanceof RubyInteger && !((RubyInteger) y).isZero()) {
IRubyObject gcd = gcd(context, y);
if (!((RubyInteger) gcd).isZero()) {
x = (RubyInteger) div(context, gcd);
y = ((RubyInteger) y).div(context, gcd);
}
}
return x.fdivDouble(context, y);
return fdivDouble(context, y);
}

public abstract IRubyObject fdivDouble(ThreadContext context, IRubyObject y);
@@ -687,8 +680,8 @@ public IRubyObject denominator(ThreadContext context) {
return RubyFixnum.one(context.runtime);
}

@JRubyMethod(name = "to_s")
@Override
@JRubyMethod(name = {"to_s", "inspect"})
public abstract RubyString to_s();

@JRubyMethod(name = "to_s")
@@ -733,6 +726,10 @@ public final IRubyObject div_div(ThreadContext context, IRubyObject other) {
@JRubyMethod(name = {"%", "modulo"})
public abstract IRubyObject op_mod(ThreadContext context, IRubyObject other);

public IRubyObject op_mod(ThreadContext context, long other) {
return op_mod(context, RubyFixnum.newFixnum(context.runtime, other));
}

@JRubyMethod(name = "**")
public abstract IRubyObject op_pow(ThreadContext context, IRubyObject other);

@@ -745,7 +742,7 @@ public IRubyObject magnitude(ThreadContext context) {
return abs(context);
}

@JRubyMethod(name = "==")
@JRubyMethod(name = {"==", "==="})
@Override
public abstract IRubyObject op_equal(ThreadContext context, IRubyObject other);

@@ -790,21 +787,34 @@ boolean isOne() {
return getBigIntegerValue().equals(BigInteger.ONE);
}

@JRubyMethod(name = ">")
public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
return RubyComparable.op_gt(context, this, other);
}

@JRubyMethod(name = "<")
public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
return RubyComparable.op_lt(context, this, other);
}

@JRubyMethod(name = ">=")
public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
return RubyComparable.op_ge(context, this, other);
}

@JRubyMethod(name = "<=")
public IRubyObject op_le(ThreadContext context, IRubyObject other) {
return RubyComparable.op_le(context, this, other);
}
@JRubyMethod(name = "remainder")
public IRubyObject remainder(ThreadContext context, IRubyObject dividend) {
return context.nil;
}

@JRubyMethod(name = "divmod")
public IRubyObject divmod(ThreadContext context, IRubyObject other) {
return context.nil;
}

public IRubyObject op_uminus() {
return op_uminus(getRuntime().getCurrentContext());
61 changes: 39 additions & 22 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -483,14 +483,26 @@ public Map<String, DynamicMethod> getMethodsForWrite() {
// note that addMethod now does its own put, so any change made to
// functionality here should be made there as well
private void putMethod(String name, DynamicMethod method) {
putMethod(getRuntime(), name, method);
}

/**
* @note Internal API - only public as its used by generated code!
* @param runtime
* @param name
* @param method
* @return method
*/ // NOTE: used by AnnotationBinder
public final DynamicMethod putMethod(final Ruby runtime, String name, DynamicMethod method) {
if (hasPrepends()) {
method = method.dup();
method.setImplementationClass(methodLocation);
}

methodLocation.getMethodsForWrite().put(name, method);

getRuntime().addProfiledMethod(name, method);
runtime.addProfiledMethod(name, method);
return method;
}

/**
@@ -976,19 +988,23 @@ public static final class MethodClumper {
public Map<Set<FrameField>, List<String>> readGroups = Collections.EMPTY_MAP;
public Map<Set<FrameField>, List<String>> writeGroups = Collections.EMPTY_MAP;

public void clump(final Class cls) {
Method[] declaredMethods = Initializer.DECLARED_METHODS.get(cls);
@SuppressWarnings("deprecation")
public void clump(final Class klass) {
Method[] declaredMethods = Initializer.DECLARED_METHODS.get(klass);
for (Method method: declaredMethods) {
JRubyMethod anno = method.getAnnotation(JRubyMethod.class);

if (anno == null) continue;

if (anno.compat() == org.jruby.CompatVersion.RUBY1_8) continue;

// skip bridge methods, as generated by JDK8 javac for e.g. return-value overloaded methods
if (method.isBridge()) continue;

JavaMethodDescriptor desc = new JavaMethodDescriptor(method);

String name = anno.name().length == 0 ? method.getName() : anno.name()[0];
final String[] names = anno.name();
String name = names.length == 0 ? method.getName() : names[0];

Map<String, List<JavaMethodDescriptor>> methodsHash;
if (desc.isStatic) {
@@ -1003,7 +1019,7 @@ public void clump(final Class cls) {

List<JavaMethodDescriptor> methodDescs = methodsHash.get(name);
if (methodDescs == null) {
methodsHash.put(name, methodDescs = new ArrayList(4));
methodsHash.put(name, methodDescs = new ArrayList<>(4));
}

methodDescs.add(desc);
@@ -1012,7 +1028,7 @@ public void clump(final Class cls) {
if (anno.reads().length > 0 && readGroups == Collections.EMPTY_MAP) readGroups = new HashMap<>();
if (anno.writes().length > 0 && writeGroups == Collections.EMPTY_MAP) writeGroups = new HashMap<>();

AnnotationHelper.groupFrameFields(readGroups, writeGroups, anno, method.getName().toString());
AnnotationHelper.groupFrameFields(readGroups, writeGroups, anno, method.getName());
}
}

@@ -1192,7 +1208,7 @@ public void addMethod(String name, DynamicMethod method) {

public final void addMethodInternal(String name, DynamicMethod method) {
synchronized(methodLocation.getMethodsForWrite()) {
addMethodAtBootTimeOnly(name, method);
putMethod(name, method);
invalidateCoreClasses();
invalidateCacheDescendants();
}
@@ -1205,16 +1221,10 @@ public final void addMethodInternal(String name, DynamicMethod method) {
*
* @param name The name to which to bind the method
* @param method The method to bind
* @deprecated No longer used, internal API!
*/
public final void addMethodAtBootTimeOnly(String name, DynamicMethod method) {
if (hasPrepends()) {
method = method.dup();
method.setImplementationClass(methodLocation);
}

methodLocation.getMethodsForWrite().put(name, method);

getRuntime().addProfiledMethod(name, method);
putMethod(getRuntime(), name, method);
}

public void removeMethod(ThreadContext context, String name) {
@@ -1616,24 +1626,31 @@ public void addModuleFunction(String name, DynamicMethod method) {
*/
public synchronized void defineAlias(String name, String oldName) {
testFrozen("module");
if (oldName.equals(name)) return;

DynamicMethod method = searchForAliasMethod(getRuntime(), oldName);

putMethod(name, new AliasMethod(this, method, oldName));
putAlias(name, searchForAliasMethod(getRuntime(), oldName), oldName);

methodLocation.invalidateCoreClasses();
methodLocation.invalidateCacheDescendants();
}

/**
* @note Internal API - only public as its used by generated code!
* @param name
* @param method
* @param oldName
*/ // NOTE: used by AnnotationBinder
public final void putAlias(String name, DynamicMethod method, String oldName) {
if (name.equals(oldName)) return;
putMethod(name, new AliasMethod(this, method, oldName));
}

public synchronized void defineAliases(List<String> aliases, String oldName) {
testFrozen("module");

DynamicMethod method = searchForAliasMethod(getRuntime(), oldName);

for (String name: aliases) {
if (oldName.equals(name)) continue;

putMethod(name, new AliasMethod(this, method, oldName));
putAlias(name, new AliasMethod(this, method, oldName), oldName);
}

methodLocation.invalidateCoreClasses();
5 changes: 5 additions & 0 deletions core/src/main/java/org/jruby/RubyNumeric.java
Original file line number Diff line number Diff line change
@@ -1223,6 +1223,11 @@ public IRubyObject denominator(ThreadContext context) {
return sites(context).denominator.call(context, rational, rational);
}

public RubyRational convertToRational() {
final ThreadContext context = getRuntime().getCurrentContext();
return RubyRational.newRationalRaw(context.runtime, numerator(context), denominator(context));
}

/** numeric_to_c
*
*/
88 changes: 54 additions & 34 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -449,6 +449,8 @@ public RubyInteger getDenominator() {
return den;
}

public RubyRational convertToRational() { return this; }

@Override
public IRubyObject zero_p(ThreadContext context) {
return context.runtime.newBoolean(isZero());
@@ -496,7 +498,7 @@ private static RubyInteger f_imul(ThreadContext context, long a, long b) {
/** f_addsub
*
*/
private static IRubyObject f_addsub(ThreadContext context, RubyClass metaClass,
private static RubyNumeric f_addsub(ThreadContext context, RubyClass metaClass,
RubyInteger anum, RubyInteger aden, RubyInteger bnum, RubyInteger bden,
final boolean plus) {
RubyInteger newNum, newDen, g, a, b;
@@ -528,42 +530,51 @@ private static IRubyObject f_addsub(ThreadContext context, RubyClass metaClass,
return RubyRational.newRationalNoReduce(context, metaClass, newNum, newDen);
}

/** nurat_add
*
*/
/** nurat_add */
@JRubyMethod(name = "+")
public IRubyObject op_add(ThreadContext context, IRubyObject other) {
@Override
public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
if (other instanceof RubyInteger) {
return f_addsub(context, getMetaClass(), num, den, (RubyInteger) other, RubyFixnum.one(context.runtime), true);
}
if (other instanceof RubyFloat) {
return f_add(context, f_to_f(context, this), other);
}
if (other instanceof RubyRational) {
RubyRational otherRational = (RubyRational)other;
return f_addsub(context, getMetaClass(), num, den, otherRational.num, otherRational.den, true);
}
return op_plus(context, (RubyRational) other);
}
return coerceBin(context, sites(context).op_plus, other);
}

/** nurat_sub
*
*/

public final RubyNumeric op_plus(ThreadContext context, RubyRational other) {
return f_addsub(context, getMetaClass(), num, den, other.num, other.den, true);
}

@Deprecated
public IRubyObject op_add(ThreadContext context, IRubyObject other) { return op_plus(context, other); }

/** nurat_sub */
@JRubyMethod(name = "-")
public IRubyObject op_sub(ThreadContext context, IRubyObject other) {
public IRubyObject op_minus(ThreadContext context, IRubyObject other) {
if (other instanceof RubyInteger) {
return f_addsub(context, getMetaClass(), num, den, (RubyInteger) other, RubyFixnum.one(context.runtime), false);
}
if (other instanceof RubyFloat) {
return f_sub(context, f_to_f(context, this), other);
}
if (other instanceof RubyRational) {
RubyRational otherRational = (RubyRational)other;
return f_addsub(context, getMetaClass(), num, den, otherRational.num, otherRational.den, false);
return op_minus(context, (RubyRational) other);
}
return coerceBin(context, sites(context).op_minus, other);
}


public final RubyNumeric op_minus(ThreadContext context, RubyRational other) {
return f_addsub(context, getMetaClass(), num, den, other.num, other.den, false);
}

@Deprecated
public IRubyObject op_sub(ThreadContext context, IRubyObject other) { return op_minus(context, other); }

/** f_muldiv
*
*/
@@ -644,7 +655,7 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other) {
return coerceBin(context, sites(context).op_quo, other);
}

final IRubyObject op_div(ThreadContext context, RubyInteger other) {
public final RubyNumeric op_div(ThreadContext context, RubyInteger other) {
if (other.isZero()) {
throw context.runtime.newZeroDivisionError();
}
@@ -670,13 +681,13 @@ public IRubyObject op_expt(ThreadContext context, IRubyObject other) {

if (other instanceof RubyRational) {
RubyRational otherRational = (RubyRational)other;
if (f_one_p(context, otherRational.den)) other = otherRational.num;
if (otherRational.den.isOne()) other = otherRational.num;
}

// Deal with special cases of 0**n and 1**n
if (k_numeric_p(other) && k_exact_p(other)) {
if (f_one_p(context, den)) {
if (f_one_p(context, num)) {
if (den.isOne()) {
if (num.isOne()) {
return RubyRational.newRationalBang(context, getMetaClass(), 1);
}
if (f_minus_one_p(context, num) && k_integer_p(other)) {
@@ -707,8 +718,8 @@ public final IRubyObject op_expt(ThreadContext context, long other) {
}

// Deal with special cases of 0**n and 1**n
if (f_one_p(context, den)) {
if (f_one_p(context, num)) {
if (den.isOne()) {
if (num.isOne()) {
return RubyRational.newRationalBang(context, getMetaClass(), 1);
}
if (f_minus_one_p(context, num)) {
@@ -724,7 +735,7 @@ public final IRubyObject op_expt(ThreadContext context, long other) {
return fix_expt(context, RubyFixnum.newFixnum(runtime, other), Long.signum(other));
}

private IRubyObject fix_expt(ThreadContext context, RubyInteger other, final int sign) {
private RubyNumeric fix_expt(ThreadContext context, RubyInteger other, final int sign) {
final RubyInteger tnum, tden;
if (sign > 0) { // other > 0
tnum = (RubyInteger) f_expt(context, num, other); // exp > 0
@@ -774,27 +785,36 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
@JRubyMethod(name = "==")
@Override
public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
Ruby runtime = context.runtime;
if (other instanceof RubyFixnum || other instanceof RubyBignum) {
RubyInteger that = (RubyInteger) other;
if (num.isZero() && that.isZero()) return runtime.getTrue();
if (!(den instanceof RubyFixnum) || den.getLongValue() != 1) return runtime.getFalse();
return f_equal(context, num, other);
return op_equal(context, (RubyInteger) other);
}
if (other instanceof RubyFloat) {
return f_equal(context, f_to_f(context, this), other);
}
if (other instanceof RubyRational) {
RubyRational otherRational = (RubyRational)other;
if (num.isZero() && otherRational.num.isZero()) return runtime.getTrue();
return runtime.newBoolean(
f_equal(context, num, otherRational.num).isTrue() &&
f_equal(context, den, otherRational.den).isTrue());

return op_equal(context, (RubyRational) other);
}
return f_equal(context, other, this);
}

public final IRubyObject op_equal(ThreadContext context, RubyInteger other) {
if (num.isZero()) return context.runtime.newBoolean(other.isZero());
if (!(den instanceof RubyFixnum) || den.getLongValue() != 1) return context.fals;
return f_equal(context, num, other);
}

final RubyBoolean op_equal(ThreadContext context, RubyRational other) {
if (num.isZero()) return context.runtime.newBoolean(other.num.isZero());
return context.runtime.newBoolean(
f_equal(context, num, other.num).isTrue() && f_equal(context, den, other.den).isTrue());
}

@Override // "eql?"
public IRubyObject eql_p(ThreadContext context, IRubyObject other) {
if (!(other instanceof RubyRational)) return context.fals;
return op_equal(context, (RubyRational) other);
}

/** nurat_coerce
*
*/
5 changes: 3 additions & 2 deletions core/src/main/java/org/jruby/RubyRegexp.java
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@
import org.joni.Regex;
import org.joni.Region;
import org.joni.Syntax;
import org.joni.WarnCallback;
import org.joni.exception.JOniException;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
@@ -148,7 +149,7 @@ public Encoding getMarshalEncoding() {
private static Regex makeRegexp(Ruby runtime, ByteList bytes, RegexpOptions options, Encoding enc) {
try {
int p = bytes.getBegin();
return new Regex(bytes.getUnsafeBytes(), p, p + bytes.getRealSize(), options.toJoniOptions(), enc, Syntax.DEFAULT, runtime.getWarnings());
return new Regex(bytes.getUnsafeBytes(), p, p + bytes.getRealSize(), options.toJoniOptions(), enc, Syntax.DEFAULT, runtime.getRegexpWarnings());
} catch (Exception e) {
RegexpSupport.raiseRegexpError19(runtime, bytes, enc, options, e.getMessage());
return null; // not reached
@@ -1405,7 +1406,7 @@ public RubyString to_s() {

if (bytes[p] == ':' && bytes[p + len - 1] == ')') {
try {
new Regex(bytes, ++p, p + (len -= 2), Option.DEFAULT, str.getEncoding(), Syntax.DEFAULT);
new Regex(bytes, ++p, p + (len -= 2), Option.DEFAULT, str.getEncoding(), Syntax.DEFAULT, WarnCallback.NONE);
err = false;
} catch (JOniException e) {
err = true;
336 changes: 174 additions & 162 deletions core/src/main/java/org/jruby/anno/AnnotationBinder.java

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/anno/AnnotationHelper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jruby.anno;

import javax.lang.model.element.ExecutableElement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -109,7 +108,7 @@ public static void populateMethodIndex(Map<Set<FrameField>, List<String>> access
List<String> names = accessEntry.getValue();

int bits = FrameField.pack(reads.stream().toArray(n -> new FrameField[n]));
String namesJoined = names.stream().collect(Collectors.joining(";"));
String namesJoined = names.stream().distinct().collect(Collectors.joining(";"));

action.accept(bits, namesJoined);
}
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/anno/IndyBinder.java
Original file line number Diff line number Diff line change
@@ -110,6 +110,7 @@ public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}

@SuppressWarnings("deprecation")
public void processType(TypeElement cd) {
// process inner classes
for (TypeElement innerType : ElementFilter.typesIn(cd.getEnclosedElements())) {
@@ -188,6 +189,8 @@ public void processType(TypeElement cd) {
JRubyMethod anno = method.getAnnotation(JRubyMethod.class);
if (anno == null) continue;

if (anno.compat() == org.jruby.CompatVersion.RUBY1_8) continue;

methodCount++;

AnnotationBinder.checkForThrows(cd, method);
23 changes: 14 additions & 9 deletions core/src/main/java/org/jruby/anno/JavaMethodDescriptor.java
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@

import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.util.CodegenUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@@ -39,22 +38,28 @@ public class JavaMethodDescriptor extends MethodDescriptor<Method> {
public final Class[] parameters;
public final Class returnClass;
public final Class declaringClass;
public final String signature;
public final Class[] argumentTypes;
@Deprecated // no longer used
public String signature;
@Deprecated // initialized on demand
public Class[] argumentTypes;

public JavaMethodDescriptor(Method method) {
super(method);

declaringClass = method.getDeclaringClass();
parameters = method.getParameterTypes();
returnClass = method.getReturnType();
}

int start = (hasContext ? 1 : 0) + (isStatic ? 1 : 0);
int end = parameters.length - (hasBlock ? 1 : 0);
argumentTypes = new Class[end - start];
System.arraycopy(parameters, start, argumentTypes, 0, end - start);

signature = CodegenUtils.sig(method.getReturnType(), method.getParameterTypes());
public final Class[] getArgumentTypes() {
if (argumentTypes == null) {
int start = (hasContext ? 1 : 0) + (isStatic ? 1 : 0);
int end = parameters.length - (hasBlock ? 1 : 0);
Class[] argumentTypes = new Class[end - start];
System.arraycopy(parameters, start, argumentTypes, 0, end - start);
return this.argumentTypes = argumentTypes;
}
return argumentTypes;
}

public Class getDeclaringClass() {
49 changes: 48 additions & 1 deletion core/src/main/java/org/jruby/anno/TypePopulator.java
Original file line number Diff line number Diff line change
@@ -36,11 +36,15 @@
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.MethodFactory;
import org.jruby.runtime.MethodIndex;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;

public abstract class TypePopulator {

public static void populateMethod(JavaMethod javaMethod, int arity, String simpleName, boolean isStatic, boolean notImplemented) {
javaMethod.setIsBuiltin(true);
javaMethod.setArity(Arity.createArity(arity));
@@ -65,7 +69,7 @@ public static DynamicMethod populateModuleMethod(RubyModule cls, DynamicMethod j
moduleMethod.setVisibility(Visibility.PUBLIC);
return moduleMethod;
}

public abstract void populate(RubyModule clsmod, Class clazz);

public static final TypePopulator DEFAULT = new DefaultTypePopulator();
@@ -126,4 +130,47 @@ private static void addBoundMethodsUnlessOmitted(final Ruby runtime, final Strin
}
}
}

// used by generated code (populators) - @see AnnorationBinder

protected static final Class[] ARG0 = new Class[] {};
protected static final Class[] ARG1 = new Class[] { IRubyObject.class };
protected static final Class[] ARG2 = new Class[] { IRubyObject.class, IRubyObject.class };
protected static final Class[] ARG3 = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] ARG4 = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };

protected static final Class[] ARG0_ARY = new Class[] { IRubyObject[].class };
protected static final Class[] ARG1_ARY = new Class[] { IRubyObject.class, IRubyObject[].class };
//protected static final Class[] ARG2_ARY = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject[].class };

protected static final Class[] CONTEXT_ARG0 = new Class[] { ThreadContext.class };
protected static final Class[] CONTEXT_ARG1 = new Class[] { ThreadContext.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG2 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG3 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG4 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };

protected static final Class[] CONTEXT_ARG0_ARY = new Class[] { ThreadContext.class, IRubyObject[].class };
protected static final Class[] CONTEXT_ARG1_ARY = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject[].class };
//protected static final Class[] CONTEXT_ARG2_ARY = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject[].class };

protected static final Class[] ARG0_BLOCK = new Class[] { Block.class };
protected static final Class[] ARG1_BLOCK = new Class[] { IRubyObject.class, Block.class };
protected static final Class[] ARG2_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] ARG3_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] ARG4_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };

protected static final Class[] ARG0_ARY_BLOCK = new Class[] { IRubyObject[].class, Block.class };
protected static final Class[] ARG1_ARY_BLOCK = new Class[] { IRubyObject.class, IRubyObject[].class, Block.class };
//protected static final Class[] ARG2_ARY_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject[].class, Block.class };

protected static final Class[] CONTEXT_ARG0_BLOCK = new Class[] { ThreadContext.class, Block.class };
protected static final Class[] CONTEXT_ARG1_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG2_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG3_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG4_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };

protected static final Class[] CONTEXT_ARG0_ARY_BLOCK = new Class[] { ThreadContext.class, IRubyObject[].class, Block.class };
protected static final Class[] CONTEXT_ARG1_ARY_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject[].class, Block.class };
//protected static final Class[] CONTEXT_ARG2_ARY_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject[].class, Block.class };

}
Original file line number Diff line number Diff line change
@@ -198,7 +198,6 @@ public InvocationMethodFactory(ClassLoader classLoader) {
*/
public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, List<JavaMethodDescriptor> descs, String name) {
JavaMethodDescriptor desc1 = descs.get(0);
final JRubyMethod anno = desc1.anno;
final String javaMethodName = desc1.name;

if (DEBUG) LOG.debug("Binding multiple: " + desc1.declaringClassName + '.' + javaMethodName);
@@ -217,10 +216,10 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, List<Jav
javaMethodName,
desc1.isStatic,
desc1.anno.notImplemented(),
desc1.getDeclaringClass(),
desc1.declaringClass,
desc1.name,
desc1.getReturnClass(),
desc1.getParameterClasses());
desc1.returnClass,
desc1.parameters);
return ic;
} catch(Exception e) {
LOG.error(e);
@@ -237,7 +236,7 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, List<Jav
public Class getAnnotatedMethodClass(List<JavaMethodDescriptor> descs) {
JavaMethodDescriptor desc1 = descs.get(0);

if (!Modifier.isPublic(desc1.getDeclaringClass().getModifiers())) {
if (!Modifier.isPublic(desc1.declaringClass.getModifiers())) {
LOG.warn("binding non-public class {} reflected handles won't work", desc1.declaringClassName);
}

@@ -262,11 +261,11 @@ public Class getAnnotatedMethodClass(List<JavaMethodDescriptor> descs) {

Class superclass = determineSuperclass(info);

Class c = tryClass(generatedClassName, desc1.getDeclaringClass(), superclass);
Class c = tryClass(generatedClassName, desc1.declaringClass, superclass);
if (c == null) {
synchronized (syncObject) {
// try again
c = tryClass(generatedClassName, desc1.getDeclaringClass(), superclass);
c = tryClass(generatedClassName, desc1.declaringClass, superclass);
if (c == null) {
if (DEBUG) LOG.debug("Generating " + generatedClassName + ", min: " + info.getMin() + ", max: " + info.getMax() + ", hasBlock: " + info.isBlock() + ", rest: " + info.isRest());

@@ -332,10 +331,10 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, JavaMeth
javaMethodName,
desc.isStatic,
desc.anno.notImplemented(),
desc.getDeclaringClass(),
desc.declaringClass,
desc.name,
desc.getReturnClass(),
desc.getParameterClasses());
desc.returnClass,
desc.parameters);
return ic;
} catch(Exception e) {
LOG.error(e);
@@ -536,6 +535,7 @@ public static String getPostMethod(CallConfiguration callConfig) {
}

private static void loadArguments(SkinnyMethodAdapter mv, JavaMethodDescriptor desc, int specificArity) {
Class[] argumentTypes;
switch (specificArity) {
default:
case -1:
@@ -545,16 +545,19 @@ private static void loadArguments(SkinnyMethodAdapter mv, JavaMethodDescriptor d
// no args
break;
case 1:
loadArgumentWithCast(mv, 1, desc.argumentTypes[0]);
argumentTypes = desc.getArgumentTypes();
loadArgumentWithCast(mv, 1, argumentTypes[0]);
break;
case 2:
loadArgumentWithCast(mv, 1, desc.argumentTypes[0]);
loadArgumentWithCast(mv, 2, desc.argumentTypes[1]);
argumentTypes = desc.getArgumentTypes();
loadArgumentWithCast(mv, 1, argumentTypes[0]);
loadArgumentWithCast(mv, 2, argumentTypes[1]);
break;
case 3:
loadArgumentWithCast(mv, 1, desc.argumentTypes[0]);
loadArgumentWithCast(mv, 2, desc.argumentTypes[1]);
loadArgumentWithCast(mv, 3, desc.argumentTypes[2]);
argumentTypes = desc.getArgumentTypes();
loadArgumentWithCast(mv, 1, argumentTypes[0]);
loadArgumentWithCast(mv, 2, argumentTypes[1]);
loadArgumentWithCast(mv, 3, argumentTypes[2]);
break;
}
}
@@ -765,14 +768,12 @@ private void createAnnotatedMethodInvocation(JavaMethodDescriptor desc, SkinnyMe
loadBlock(method, specificArity, block);

if (Modifier.isStatic(desc.modifiers)) {
// static invocation
method.invokestatic(typePath, javaMethodName, desc.signature);
method.invokestatic(typePath, javaMethodName, sig(desc.returnClass, desc.parameters));
} else {
// virtual invocation
method.invokevirtual(typePath, javaMethodName, desc.signature);
method.invokevirtual(typePath, javaMethodName, sig(desc.returnClass, desc.parameters));
}

if (desc.getReturnClass() == void.class) {
if (desc.returnClass == void.class) {
// void return type, so we need to load a nil for returning below
method.aload(THREADCONTEXT_INDEX);
method.getfield(p(ThreadContext.class), "nil", ci(IRubyObject.class));
Original file line number Diff line number Diff line change
@@ -83,7 +83,7 @@ public DynamicMethod getAnnotatedMethod(final RubyModule implementationClass, fi
return super.getAnnotatedMethod(implementationClass, descs, name);
}

if (!Modifier.isPublic(desc1.getDeclaringClass().getModifiers())) {
if (!Modifier.isPublic(desc1.declaringClass.getModifiers())) {
LOG.warn("warning: binding non-public class {}; reflected handles won't work", desc1.declaringClassName);
}

@@ -198,8 +198,7 @@ public static SmartBinder preAdaptHandle(int specificArity, final boolean isStat
targetBinder = SmartBinder.from(baseSignature);

// unused by Java-based methods
targetBinder = targetBinder
.exclude("class", "name");
targetBinder = targetBinder.exclude("class", "name");

if (isStatic) {
if (hasContext) {
17 changes: 16 additions & 1 deletion core/src/main/java/org/jruby/runtime/Helpers.java
Original file line number Diff line number Diff line change
@@ -1879,7 +1879,22 @@ public static Block getBlock(Ruby runtime, ThreadContext context, IRubyObject se
public static RubyBoolean rbEqual(ThreadContext context, IRubyObject a, IRubyObject b) {
Ruby runtime = context.runtime;
if (a == b) return runtime.getTrue();
IRubyObject res = invokedynamic(context, a, OP_EQUAL, b);
IRubyObject res = sites(context).op_equal.call(context, a, a, b);
return runtime.newBoolean(res.isTrue());
}

/**
* Equivalent to rb_equal in MRI
*
* @param context
* @param a
* @param b
* @return
*/
public static RubyBoolean rbEqual(ThreadContext context, IRubyObject a, IRubyObject b, CallSite equal) {
Ruby runtime = context.runtime;
if (a == b) return runtime.getTrue();
IRubyObject res = equal.call(context, a, a, b);
return runtime.newBoolean(res.isTrue());
}

2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/runtime/JavaSites.java
Original file line number Diff line number Diff line change
@@ -236,6 +236,7 @@ public static class FixnumSites {
public final CheckedSites checked_op_and = new CheckedSites("&");
public final CheckedSites checked_op_or = new CheckedSites("|");
public final CheckedSites checked_op_xor = new CheckedSites("^");
public final CallSite op_equal = new FunctionalCachingCallSite("==");
}

public static class BignumSites {
@@ -339,6 +340,7 @@ public static class TypeConverterSites {

public static class HelpersSites {
public final CallSite hash = new FunctionalCachingCallSite("hash");
public final CallSite op_equal = new FunctionalCachingCallSite("==");

public final ThreadContext.RecursiveFunctionEx<Ruby> recursive_hash = new ThreadContext.RecursiveFunctionEx<Ruby>() {
public IRubyObject call(ThreadContext context, Ruby runtime, IRubyObject obj, boolean recur) {
3 changes: 3 additions & 0 deletions core/src/main/java/org/jruby/runtime/MethodIndex.java
Original file line number Diff line number Diff line change
@@ -43,6 +43,7 @@
import org.jruby.runtime.callsite.LtCallSite;
import org.jruby.runtime.callsite.LeCallSite;
import org.jruby.runtime.callsite.MinusCallSite;
import org.jruby.runtime.callsite.ModCallSite;
import org.jruby.runtime.callsite.MulCallSite;
import org.jruby.runtime.callsite.NormalCachingCallSite;
import org.jruby.runtime.callsite.GtCallSite;
@@ -122,6 +123,7 @@ public static CallSite getCallSite(String name) {
{"+", "op_plus"},
{"-", "op_minus"},
{"*", "op_mul"},
{"%", "op_mod"},
{"==", "op_equal"},
{"<", "op_lt"},
{"<=", "op_le"},
@@ -169,6 +171,7 @@ public static CallSite getFastFixnumOpsCallSite(String name) {
case "+" : return new PlusCallSite();
case "-" : return new MinusCallSite();
case "*" : return new MulCallSite();
case "%" : return new ModCallSite();
case "<" : return new LtCallSite();
case "<=" : return new LeCallSite();
case ">" : return new GtCallSite();
Original file line number Diff line number Diff line change
@@ -234,6 +234,10 @@ public static IRubyObject fixnum_op_mul(ThreadContext context, IRubyObject calle
return ((RubyFixnum)self).op_mul(context, value);
}

public static IRubyObject fixnum_op_mod(ThreadContext context, IRubyObject caller, IRubyObject self, long value) throws Throwable {
return ((RubyFixnum)self).op_mod(context, value);
}

public static IRubyObject fixnum_op_equal(ThreadContext context, IRubyObject caller, IRubyObject self, long value) throws Throwable {
return ((RubyFixnum)self).op_equal(context, value);
}
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.util.collections.NonBlockingHashMapLong;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
135 changes: 68 additions & 67 deletions core/src/main/java/org/jruby/util/Numeric.java

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -224,6 +224,7 @@ public class Options {
public static final Option<String> CLI_RECORD_SEPARATOR = string(CLI, "cli.record.separator", "\n", "Default record separator.");
public static final Option<String> CLI_BACKUP_EXTENSION = string(CLI, "cli.backup.extension", "Backup extension for in-place ARGV files. Same as -i.");
public static final Option<ProfilingMode> CLI_PROFILING_MODE = enumeration(CLI, "cli.profiling.mode", ProfilingMode.class, ProfilingMode.OFF, "Enable instrumented profiling modes.");
public static final Option<String> CLI_PROFILING_SERVICE = string(CLI, "cli.profiling.service", "Profiling service class to use.");
public static final Option<Boolean> CLI_RUBYGEMS_ENABLE = bool(CLI, "cli.rubygems.enable", true, "Enable/disable RubyGems.");
public static final Option<Boolean> CLI_DID_YOU_MEAN_ENABLE = bool(CLI, "cli.did_you_mean.enable", true, "Enable/disable did_you_mean.");
public static final Option<Boolean> CLI_RUBYOPT_ENABLE = bool(CLI, "cli.rubyopt.enable", true, "Enable/disable RUBYOPT processing at start.");
13 changes: 12 additions & 1 deletion core/src/test/java/org/jruby/runtime/profile/ProfilingTest.java
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ public void testNoProfilingServerAvailableIfProfilingIsDisabled() {
Ruby ruby = Ruby.newInstance( configOne );

assertNull(ruby.getProfilingService());

}
/**
* Tests the {@link org.jruby.runtime.profile.ProfilingServiceLookup} too
@@ -47,7 +48,17 @@ public void testProfilingServiceLookupWorks() {
assertTrue(ruby.getProfilingService() instanceof TestProfilingService);
} catch( RaiseException e ) {
//e.printStackTrace();
// TODO hwo to mock org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- jruby/profiler/shutdown_hook
// TODO how to mock org.jruby.exceptions.RaiseException: (LoadError) no such file to load -- jruby/profiler/shutdown_hook
}
}

/**
* Tests if the profiling service can be configured as java property
*/
public void testProfilingServiceAsJavaProperty() {

// java -Djruby.cli.profiling.mode=SERVICE -Djruby.cli.profiling.service=org.jruby.runtime.profile.builtin.BuiltinProfilingService -cp jruby.jar org.jruby.Main

// TODO how to test it ??
}
}

0 comments on commit fdbbe97

Please sign in to comment.