Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3802 from jruby/ji-native
moving Ruby Java extensions into native
  • Loading branch information
kares committed Apr 27, 2016
2 parents 8e0a058 + 5f147cc commit 08e4b1b
Show file tree
Hide file tree
Showing 34 changed files with 3,673 additions and 356 deletions.
6 changes: 1 addition & 5 deletions core/src/main/java/org/jruby/RubyComparable.java
Expand Up @@ -35,13 +35,9 @@

import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.common.RubyWarnings;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.concurrent.Callable;

import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.runtime.invokedynamic.MethodNames.OP_CMP;

Expand All @@ -68,7 +64,7 @@ public static RubyModule createComparable(Ruby runtime) {
*
*/
public static int cmpint(ThreadContext context, IRubyObject val, IRubyObject a, IRubyObject b) {
if (val.isNil()) cmperr(a, b);
if (val == context.nil) cmperr(a, b);
if (val instanceof RubyFixnum) {
final int asInt = RubyNumeric.fix2int((RubyFixnum) val);

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyProc.java
Expand Up @@ -81,7 +81,7 @@ protected RubyProc(Ruby runtime, RubyClass rubyClass, Block.Type type, String fi
}


RubyProc(Ruby runtime, RubyClass rubyClass, Block block, String file, int line) {
public RubyProc(Ruby runtime, RubyClass rubyClass, Block block, String file, int line) {
this(runtime, rubyClass, block.type);
this.block = block;
this.file = file;
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/RubyRange.java
Expand Up @@ -760,6 +760,8 @@ public IRubyObject size(ThreadContext context) {
return context.nil;
}

public final boolean isExcludeEnd() { return isExclusive; }

private static final ObjectMarshal RANGE_MARSHAL = new ObjectMarshal() {
@Override
public void marshalTo(Ruby runtime, Object obj, RubyClass type,
Expand Down
60 changes: 59 additions & 1 deletion core/src/main/java/org/jruby/java/proxies/ArrayJavaProxy.java
Expand Up @@ -26,7 +26,7 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;

public class ArrayJavaProxy extends JavaProxy {
public final class ArrayJavaProxy extends JavaProxy {

private final JavaUtil.JavaConverter converter;

Expand Down Expand Up @@ -343,6 +343,64 @@ public int hashCode() {
return 11 * Arrays.hashCode((Object[]) array);
}

@Override
public IRubyObject dup() {
final Ruby runtime = getRuntime();

RubyObject dup = new ArrayJavaProxy(runtime, getMetaClass(), cloneObject(), converter);

if (isTaint()) dup.setTaint(true);
initCopy(dup, this, "initialize_dup");

return dup;
}

private static void initCopy(IRubyObject clone, IRubyObject original, String method) {
original.copySpecialInstanceVariables(clone);
if (original.hasVariables()) clone.syncVariables(original);
}

@Override
@JRubyMethod(name = "clone")
public IRubyObject rbClone() {
final Ruby runtime = getRuntime();

RubyObject clone = new ArrayJavaProxy(runtime, getMetaClass(), cloneObject(), converter);
clone.setMetaClass(getSingletonClassClone());

if (isTaint()) clone.setTaint(true);
initCopy(clone, this, "initialize_clone");
if (isFrozen()) clone.setFrozen(true);

return clone;
}

@Override
protected Object cloneObject() {
final Object array = getObject();
final Class<?> componentType = array.getClass().getComponentType();
if ( componentType.isPrimitive() ) {
switch ( componentType.getName().charAt(0) ) {
case 'b':
if (componentType == byte.class) return ((byte[]) array).clone();
else /* if (componentType == boolean.class) */ return ((boolean[]) array).clone();
case 's':
/* if (componentType == short.class) */ return ((short[]) array).clone();
case 'c':
/* if (componentType == char.class) */ return ((char[]) array).clone();
case 'i':
/* if (componentType == int.class) */ return ((int[]) array).clone();
case 'l':
/* if (componentType == long.class) */ return ((long[]) array).clone();
case 'f':
/* if (componentType == float.class) */ return ((float[]) array).clone();
case 'd':
/* if (componentType == double.class) */ return ((double[]) array).clone();
}
}
return ((Object[]) array).clone();
}

public IRubyObject getRange(ThreadContext context, IRubyObject[] args) {
if (args.length == 1) {
return getRange(context, args[0]);
Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/org/jruby/java/proxies/JavaProxy.java
Expand Up @@ -36,6 +36,7 @@
import org.jruby.javasupport.JavaClass;
import org.jruby.javasupport.JavaMethod;
import org.jruby.javasupport.JavaObject;
import org.jruby.javasupport.JavaUtil;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
Expand Down Expand Up @@ -171,10 +172,20 @@ public static IRubyObject persistent(final ThreadContext context, final IRubyObj
public IRubyObject initialize_copy(IRubyObject original) {
super.initialize_copy(original);
// because we lazily init JavaObject in the data-wrapped slot, explicitly copy over the object
setObject( ((JavaProxy) original).getObject() );
setObject( ((JavaProxy) original).cloneObject() );
return this;
}

protected Object cloneObject() {
final Object object = getObject();
if (object instanceof Cloneable) {
// sufficient for java.util collection classes e.g. HashSet, ArrayList
Object clone = JavaUtil.clone(object);
return clone == null ? object : clone;
}
return object; // this is what JRuby did prior to <= 9.0.5
}

/**
* Create a name/newname map of fields to be exposed as methods.
*/
Expand Down
12 changes: 6 additions & 6 deletions core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java
Expand Up @@ -638,7 +638,7 @@ public RubyArray keys() {
/** rb_hash_values
*
*/
@JRubyMethod(name = "values")
@JRubyMethod(name = { "values", "ruby_values" }) // collision with java.util.Map#values
public RubyArray rb_values() {
return getOrCreateRubyHashMap().rb_values();
}
Expand Down Expand Up @@ -694,8 +694,8 @@ public IRubyObject reject_bang(final ThreadContext context, final Block block) {
/** rb_hash_clear
*
*/
@JRubyMethod(name = "clear")
public RubyHash rb_clear() {
@JRubyMethod(name = { "clear", "ruby_clear" }) // collision with java.util.Map#clear (return type)
public IRubyObject rb_clear() {
return getOrCreateRubyHashMap().rb_clear();
}

Expand All @@ -710,15 +710,15 @@ public RubyHash invert(final ThreadContext context) {
/** rb_hash_merge_bang
*
*/
@JRubyMethod(name = {"merge!", "update"}, required = 1)
@JRubyMethod(name = { "merge!", "update" }, required = 1)
public RubyHash merge_bang(final ThreadContext context, final IRubyObject other, final Block block) {
return getOrCreateRubyHashMap().merge_bang(context, other, block);
}

/** rb_hash_merge
*
*/
@JRubyMethod(name = "merge")
@JRubyMethod(name = { "merge", "ruby_merge" }) // collision with java.util.Map#merge on Java 8+
public RubyHash merge(ThreadContext context, IRubyObject other, Block block) {
return getOrCreateRubyHashMap().merge(context, other, block);
}
Expand All @@ -734,7 +734,7 @@ public RubyHash initialize_copy(ThreadContext context, IRubyObject other) {
/** rb_hash_replace
*
*/
@JRubyMethod(name = "replace", required = 1)
@JRubyMethod(name = { "replace", "ruby_replace" }, required = 1) // collision with java.util.Map#replace on Java 8+
public RubyHash replace(final ThreadContext context, IRubyObject other) {
return getOrCreateRubyHashMap().replace(context, other);
}
Expand Down
15 changes: 11 additions & 4 deletions core/src/main/java/org/jruby/javasupport/Java.java
Expand Up @@ -91,13 +91,11 @@
import org.jruby.java.proxies.JavaInterfaceTemplate;
import org.jruby.java.proxies.JavaProxy;
import org.jruby.java.proxies.RubyObjectHolderProxy;
import org.jruby.java.util.BlankSlateWrapper;
import org.jruby.java.util.SystemPropertiesMap;
import org.jruby.javasupport.proxy.JavaProxyClassFactory;
import org.jruby.util.OneShotClassLoader;
import org.jruby.util.ByteList;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.ClassProvider;
import org.jruby.util.IdUtil;
import org.jruby.util.JRubyClassLoader;
import org.jruby.util.SafePropertyAccessor;
Expand All @@ -118,10 +116,19 @@ public void load(Ruby runtime, boolean wrap) {

JavaPackage.createJavaPackageClass(runtime, Java);

org.jruby.javasupport.ext.Kernel.define(runtime);

org.jruby.javasupport.ext.JavaLang.define(runtime);
org.jruby.javasupport.ext.JavaLangReflect.define(runtime);
org.jruby.javasupport.ext.JavaUtil.define(runtime);
org.jruby.javasupport.ext.JavaUtilRegex.define(runtime);
org.jruby.javasupport.ext.JavaIo.define(runtime);
org.jruby.javasupport.ext.JavaNet.define(runtime);

// load Ruby parts of the 'java' library
runtime.getLoadService().load("jruby/java.rb", false);

// rewite ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
// rewire ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
final RubyClass ArrayJavaProxy = runtime.getClass("ArrayJavaProxy");
ArrayJavaProxy.setSuperClass(runtime.getJavaSupport().getObjectJavaClass().getProxyClass());
ArrayJavaProxy.includeModule(runtime.getEnumerable());
Expand Down Expand Up @@ -689,7 +696,7 @@ public static RubyModule getJavaPackageModule(final Ruby runtime, final Package
return getJavaPackageModule(runtime, pkg == null ? "" : pkg.getName());
}

private static RubyModule getJavaPackageModule(final Ruby runtime, final String packageString) {
public static RubyModule getJavaPackageModule(final Ruby runtime, final String packageString) {
final String packageName; final int length;
if ( ( length = packageString.length() ) == 0 ) {
packageName = "Default";
Expand Down
9 changes: 2 additions & 7 deletions core/src/main/java/org/jruby/javasupport/JavaCallable.java
Expand Up @@ -139,16 +139,11 @@ protected final void checkArity(final int length) {
}

final Object[] convertArguments(final IRubyObject[] args) {
return convertArguments(args, 0);
return JavaUtil.convertArguments(args, parameterTypes, 0);
}

final Object[] convertArguments(final IRubyObject[] args, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
final Class<?>[] types = parameterTypes;
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava( types[i] );
}
return arguments;
return JavaUtil.convertArguments(args, parameterTypes, offset);
}

protected final IRubyObject handleThrowable(ThreadContext context, final Throwable ex) {
Expand Down
36 changes: 36 additions & 0 deletions core/src/main/java/org/jruby/javasupport/JavaUtil.java
Expand Up @@ -36,6 +36,7 @@
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static java.lang.Character.isLetter;
import static java.lang.Character.isLowerCase;
Expand Down Expand Up @@ -507,6 +508,41 @@ else if (rubyName.startsWith("is_")) {
}
}

public static Object[] convertArguments(final IRubyObject[] args, final Class<?>[] types) {
return convertArguments(args, types, 0);
}

public static Object[] convertArguments(final IRubyObject[] args, final Class<?>[] types, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava( types[i] );
}
return arguments;
}

/**
* Clone a Java object, assuming its class has an accessible <code>clone</code> method.
* @param object
* @return cloned object or null (if method is not found or inaccessible)
*/
public static <T> T clone(final Object object) {
return (T) clone(object, false);
}

static Object clone(final Object object, final boolean silent) {
try {
final Method clone = object.getClass().getMethod("clone");
return clone.invoke(object);
}
catch (NoSuchMethodException|IllegalAccessException e) {
return null;
}
catch (InvocationTargetException e) {
if ( ! silent ) Helpers.throwException(e.getTargetException());
return null;
}
}

public static abstract class JavaConverter {
private final Class type;
public JavaConverter(Class type) {this.type = type;}
Expand Down

0 comments on commit 08e4b1b

Please sign in to comment.