Skip to content

Commit

Permalink
Showing 78 changed files with 738 additions and 372 deletions.
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -1391,7 +1391,7 @@ public synchronized void reify(String classDumpDir, boolean useChildLoader) {
switch (methodEntry.getValue().getArity().getValue()) {
case 0:
signature = sig(IRubyObject.class);
m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, javaMethodName, signature, null, null);
generateMethodAnnotations(methodAnnos, m, parameterAnnos);

m.aload(0);
@@ -1426,7 +1426,7 @@ public synchronized void reify(String classDumpDir, boolean useChildLoader) {
int rubyIndex = baseIndex;

signature = sig(methodSignature[0], params);
m = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_VARARGS, javaMethodName, signature, null, null);
m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, javaMethodName, signature, null, null);
generateMethodAnnotations(methodAnnos, m, parameterAnnos);

m.getstatic(javaPath, "ruby", ci(Ruby.class));
6 changes: 5 additions & 1 deletion core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
@@ -659,7 +659,11 @@ public IRubyObject max(ThreadContext context, Block block) {
if (!(begin instanceof RubyInteger)) {
throw context.runtime.newTypeError("cannot exclude end value with non Integer begin value");
}
rangeEnd = RubyFixnum.newFixnum(context.runtime, ((RubyInteger) end).getLongValue() - 1);
if (end instanceof RubyFixnum) {
rangeEnd = RubyFixnum.newFixnum(context.runtime, ((RubyFixnum)end).getLongValue() - 1);
} else {
rangeEnd = end.callMethod(context, "-", RubyFixnum.one(context.runtime));
}
} else {
rangeEnd = end;
}
75 changes: 63 additions & 12 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -167,6 +167,7 @@ public RubyBigDecimal(Ruby runtime, RubyClass klass) {
this.isNaN = false;
this.infinitySign = 0;
this.zeroSign = 0;
this.value = BigDecimal.ZERO;
}

public RubyBigDecimal(Ruby runtime, BigDecimal value) {
@@ -499,26 +500,49 @@ private static RubyBigDecimal newInstance(Ruby runtime, IRubyObject recv, RubyBi
return new RubyBigDecimal(runtime, (RubyClass) recv, new BigDecimal(arg.getBigIntegerValue(), mathContext));
}

private final static Pattern NUMBER_PATTERN = Pattern.compile("^([+-]?\\d*\\.?\\d*([eE][+-]?)?\\d*).*");
private final static Pattern NUMBER_PATTERN = Pattern.compile("^([+-]?\\d*\\.?\\d*([eE]?)([+-]?\\d*)).*");

private static RubyBigDecimal newInstance(ThreadContext context, IRubyObject recv, IRubyObject arg, MathContext mathContext) {
String strValue = arg.convertToString().toString().trim();

switch ( strValue.length() > 2 ? strValue.charAt(0) : ' ' ) { // do not case length == 1
case 'N' :
if ( "NaN".equals(strValue) ) return newNaN(context.runtime);
case 'I' :
if ( "Infinity".equals(strValue) ) return newInfinity(context.runtime, 1);
case '-' :
if ( "-Infinity".equals(strValue) ) return newInfinity(context.runtime, -1);
case '+' :
if ( "+Infinity".equals(strValue) ) return newInfinity(context.runtime, +1);
int sign = 1;
if(strValue.length() > 0) {
switch (strValue.charAt(0)) {
case '_' :
return newZero(context.runtime, 1); // leading "_" are not allowed
case 'N' :
if ( "NaN".equals(strValue) ) return newNaN(context.runtime);
break;
case 'I' :
if ( "Infinity".equals(strValue) ) return newInfinity(context.runtime, 1);
break;
case '-' :
if ( "-Infinity".equals(strValue) ) return newInfinity(context.runtime, -1);
sign = -1;
break;
case '+' :
if ( "+Infinity".equals(strValue) ) return newInfinity(context.runtime, +1);
break;
}
}

// Convert String to Java understandable format (for BigDecimal).
strValue = strValue.replaceFirst("[dD]", "E"); // 1. MRI allows d and D as exponent separators
strValue = strValue.replaceAll("_", ""); // 2. MRI allows underscores anywhere
strValue = NUMBER_PATTERN.matcher(strValue).replaceFirst("$1"); // 3. MRI ignores the trailing junk

Matcher matcher = NUMBER_PATTERN.matcher(strValue);
strValue = matcher.replaceFirst("$1"); // 3. MRI ignores the trailing junk

String exp = matcher.group(2);
if(!exp.isEmpty()) {
String expValue = matcher.group(3);
if (expValue.isEmpty() || expValue.equals("-") || expValue.equals("+")) {
strValue = strValue.concat("0"); // 4. MRI allows 1E, 1E-, 1E+
} else if (isExponentOutOfRange(expValue)) {
// Handle infinity (Integer.MIN_VALUE + 1) < expValue < Integer.MAX_VALUE
return newInfinity(context.runtime, sign);
}
}

BigDecimal decimal;
try {
@@ -531,11 +555,38 @@ private static RubyBigDecimal newInstance(ThreadContext context, IRubyObject rec
}

// MRI behavior: -0 and +0 are two different things
if (decimal.signum() == 0) return newZero(context.runtime, strValue.matches("^\\s*-.*") ? -1 : 1);
if (decimal.signum() == 0) return newZero(context.runtime, sign);

return new RubyBigDecimal(context.runtime, (RubyClass) recv, decimal);
}

private static boolean isExponentOutOfRange(final String expValue) {
int num = 0;
int sign = 1;
final int len = expValue.length();
final char ch = expValue.charAt(0);
if (ch == '-') {
sign = -1;
} else if (ch != '+') {
num = '0' - ch;
}
int i = 1;
final int max = (sign == 1) ? -Integer.MAX_VALUE : Integer.MIN_VALUE + 1;
final int multmax = max / 10;
while (i < len) {
int d = expValue.charAt(i++) - '0';
if (num < multmax) {
return true;
}
num *= 10;
if (num < (max + d)) {
return true;
}
num -= d;
}
return false;
}

@Deprecated
public static RubyBigDecimal newInstance(IRubyObject recv, IRubyObject[] args) {
final ThreadContext context = recv.getRuntime().getCurrentContext();
Original file line number Diff line number Diff line change
@@ -238,7 +238,7 @@ public IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyM

@Override
public DynamicMethod dup() {
return new CompiledIRMethod(variable, specific, specificArity, method, visibility, implementationClass, hasKwargs);
return new CompiledIRMethod(variable, specific, specificArity, method, getVisibility(), implementationClass, hasKwargs);
}

public String getFile() {
Original file line number Diff line number Diff line change
@@ -103,11 +103,6 @@ public void setVisibility(Visibility visibility) {
delegate.setVisibility(visibility);
}

@Override
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik) {
delegate.setNativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik);
}

@Override
public void setIsBuiltin(boolean isBuiltin) {
delegate.setIsBuiltin(isBuiltin);
@@ -153,11 +148,6 @@ protected RubyModule getProtectedClass() {
return delegate.getProtectedClass();
}

@Override
public NativeCall getNativeCall() {
return delegate.getNativeCall();
}

@Override
public RubyModule getImplementationClass() {
return delegate.getImplementationClass();
@@ -208,11 +198,6 @@ public Object getHandle() {
return delegate.getHandle(); //To change body of overridden methods use File | Settings | File Templates.
}

@Override
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik, boolean java) {
delegate.setNativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, java); //To change body of overridden methods use File | Settings | File Templates.
}

@Override
public DynamicMethod dup() {
return new ProfilingDynamicMethod(delegate.dup());
Original file line number Diff line number Diff line change
@@ -55,14 +55,12 @@ public abstract class DynamicMethod {
protected RubyModule implementationClass;
/** The "protected class" used for calculating protected access. */
protected RubyModule protectedClass;
/** The visibility of this method. */
protected Visibility visibility;
/** The visibility of this method. This is the ordinal of the Visibility enum value. */
private byte visibility;
/** The serial number for this method object, to globally identify it */
protected long serialNumber;
/** Flags for builtin, notimpl, etc */
protected byte flags;
/** Single-arity native call */
protected NativeCall nativeCall;
/** The simple, base name this method was defined under. May be null.*/
protected String name;
/** An arbitrarily-typed "method handle" for use by compilers and call sites */
@@ -108,7 +106,7 @@ protected DynamicMethod() {
}

protected void init(RubyModule implementationClass, Visibility visibility) {
this.visibility = visibility;
this.visibility = (byte)visibility.ordinal();
this.implementationClass = implementationClass;
// TODO: Determine whether we should perhaps store non-singleton class
// in the implementationClass
@@ -241,7 +239,7 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klaz
* @return true if the call would not violate visibility; false otherwise
*/
public boolean isCallableFrom(IRubyObject caller, CallType callType) {
switch (visibility) {
switch (Visibility.values()[visibility]) {
case PUBLIC:
return true;
case PRIVATE:
@@ -324,7 +322,7 @@ public void setImplementationClass(RubyModule implClass) {
* @return The visibility of this method
*/
public Visibility getVisibility() {
return visibility;
return Visibility.values()[visibility];
}

/**
@@ -333,7 +331,7 @@ public Visibility getVisibility() {
* @param visibility The visibility of this method
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
this.visibility = (byte)visibility.ordinal();
}

/**
@@ -452,40 +450,6 @@ public String toString() {
}
}

/**
* Set the single-arity NativeCall for this method. All signatures for the
* non-single-arity getNativeCall will also be set to this value.
*
* @param nativeTarget native method target
* @param nativeName native method name
* @param nativeReturn native method return
* @param nativeSignature native method arguments
* @param statik static?
* @param java plain Java method?
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik, boolean java) {
this.nativeCall = new NativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, java);
}


/**
* Set the single-arity NativeCall for this method. All signatures for the
* non-single-arity getNativeCall will also be set to this value.
*
* @param nativeTarget native method target
* @param nativeName native method name
* @param nativeReturn native method return
* @param nativeSignature native method arguments
* @param statik static?
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik) {
setNativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, false);
}

public NativeCall getNativeCall() {
return this.nativeCall;
}

/**
* Returns true if this method is backed by native (i.e. Java) code.
*
Original file line number Diff line number Diff line change
@@ -187,7 +187,7 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public DynamicMethod dup() {
return new HandleMethod(implementationClass, visibility, targetsGenerator, signature, builtin, notImplemented, parameterDesc);
return new HandleMethod(implementationClass, getVisibility(), targetsGenerator, signature, builtin, notImplemented, parameterDesc);
}

@Override
Original file line number Diff line number Diff line change
@@ -273,7 +273,7 @@ protected void promoteToFullBuild(ThreadContext context) {

@Override
public DynamicMethod dup() {
return new InterpretedIRMethod(method, visibility, implementationClass);
return new InterpretedIRMethod(method, getVisibility(), implementationClass);
}

public String getClassName(ThreadContext context) {
Original file line number Diff line number Diff line change
@@ -36,14 +36,17 @@

/**
*/
public abstract class JavaMethod extends DynamicMethod implements Cloneable, MethodArgs2 {
public abstract class JavaMethod extends DynamicMethod implements Cloneable, MethodArgs2, NativeCallMethod {
protected Arity arity = Arity.OPTIONAL;
private String javaName;
private boolean isSingleton;
protected StaticScope staticScope;
private String parameterDesc;
private String[] parameterList;

/** Single-arity native call */
protected NativeCall nativeCall;

private static final String[] ONE_REQ = new String[] { "q" };
private static final String[] TWO_REQ = new String[] { "q", "q" };
private static final String[] THREE_REQ = new String[] { "q", "q", "q" };
@@ -238,6 +241,28 @@ public String[] getParameterList() {
return parameterList;
}

/**
* @see NativeCallMethod#setNativeCall(Class, String, Class, Class[], boolean, boolean)
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik, boolean java) {
this.nativeCall = new NativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, java);
}


/**
* @see NativeCallMethod#setNativeCall(Class, String, Class, Class[], boolean)
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik) {
setNativeCall(nativeTarget, nativeName, nativeReturn, nativeSignature, statik, false);
}

/**
* @see NativeCallMethod#getNativeCall()
*/
public NativeCall getNativeCall() {
return this.nativeCall;
}

protected static IRubyObject raiseArgumentError(JavaMethod method, ThreadContext context, String name, int given, int min, int max) {
Arity.raiseArgumentError(context.runtime, name, given, min, max);
throw new AssertionError("expected to throw ArgumentError"); // never reached
Original file line number Diff line number Diff line change
@@ -341,7 +341,7 @@ protected void dupBox(MixedModeIRMethod orig) {

@Override
public DynamicMethod dup() {
MixedModeIRMethod x = new MixedModeIRMethod(method, visibility, implementationClass);
MixedModeIRMethod x = new MixedModeIRMethod(method, getVisibility(), implementationClass);
x.box = box;

return x;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.jruby.internal.runtime.methods;


/**
* Created by headius on 8/1/15.
*/
public interface NativeCallMethod {
/**
* Set the single-arity NativeCall for this method. All signatures for the
* non-single-arity getNativeCall will also be set to this value.
*
* @param nativeTarget native method target
* @param nativeName native method name
* @param nativeReturn native method return
* @param nativeSignature native method arguments
* @param statik static?
* @param java plain Java method?
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik, boolean java);

/**
* Set the single-arity NativeCall for this method. All signatures for the
* non-single-arity getNativeCall will also be set to this value.
*
* @param nativeTarget native method target
* @param nativeName native method name
* @param nativeReturn native method return
* @param nativeSignature native method arguments
* @param statik static?
*/
public void setNativeCall(Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeSignature, boolean statik);

/**
* Get the NativeCall for the method, if available.
*
* @return a NativeCall if the method has a native representation.
*/
public DynamicMethod.NativeCall getNativeCall();
}
Loading

0 comments on commit 28797d4

Please sign in to comment.