Skip to content

Commit

Permalink
Showing 2 changed files with 51 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -17,10 +17,12 @@
import org.jruby.RubyProc;
import org.jruby.RubyString;
import org.jruby.java.invokers.RubyToJavaInvoker;
import org.jruby.javasupport.Java;
import org.jruby.javasupport.JavaCallable;
import org.jruby.javasupport.JavaClass;
import org.jruby.javasupport.JavaUtil;
import org.jruby.javasupport.ParameterTypes;
import org.jruby.javasupport.proxy.JavaProxyConstructor;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.collections.IntHashMap;
import static org.jruby.util.CodegenUtils.getBoxType;
@@ -36,12 +38,12 @@ private CallableSelector() { /* no-instances */ }

//private static final boolean DEBUG = true;

public static <T extends ParameterTypes> T matchingCallableArityN(Ruby runtime, IntHashMap<T> cache, T[] methods, IRubyObject[] args) {
public static JavaProxyConstructor matchingCallableArityN(Ruby runtime, Java.JCreateMethod invoker, JavaProxyConstructor[] methods, IRubyObject[] args) {
final int signatureCode = argsHashCode(args);
T method = cache.get(signatureCode);
org.jruby.javasupport.proxy.JavaProxyConstructor method = invoker.getSignature(signatureCode);
if (method == null) {
method = findMatchingCallableForArgs(runtime, methods, args);
if (method != null) cache.put(signatureCode, method);
if (method != null) invoker.putSignature(signatureCode, method);
}
return method;
}
75 changes: 46 additions & 29 deletions core/src/main/java/org/jruby/javasupport/Java.java
Original file line number Diff line number Diff line change
@@ -605,44 +605,61 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
});

subclass.addMethod("__jcreate!", new JavaMethodN(subclassSingleton, PUBLIC) {
subclass.addMethod("__jcreate!", new JCreateMethod(subclassSingleton));
}

private final IntHashMap<JavaProxyConstructor> cache = newCallableCache();
public static class JCreateMethod extends JavaMethodN {
private final IntHashMap<JavaProxyConstructor> writeCache = newCallableCache();
private volatile IntHashMap<JavaProxyConstructor> readCache = (IntHashMap)writeCache.clone();

@Override
public IRubyObject call(final ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
IRubyObject proxyClass = self.getMetaClass().getInstanceVariables().getInstanceVariable("@java_proxy_class");
if (proxyClass == null || proxyClass.isNil()) {
proxyClass = JavaProxyClass.get_with_class(self, self.getMetaClass());
self.getMetaClass().getInstanceVariables().setInstanceVariable("@java_proxy_class", proxyClass);
}
JCreateMethod(RubyModule cls) {
super(cls, PUBLIC);
}

final int argsLength = args.length;
final JavaProxyConstructor[] constructors = ((JavaProxyClass) proxyClass).getConstructors();
ArrayList<JavaProxyConstructor> forArity = findCallablesForArity(argsLength, constructors);
public JavaProxyConstructor getSignature(int signatureCode) {
return readCache.get(signatureCode);
}

if ( forArity.size() == 0 ) {
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}
public void putSignature(int signatureCode, JavaProxyConstructor callable) {
synchronized (writeCache) {
writeCache.put(signatureCode, callable);
readCache = (IntHashMap<JavaProxyConstructor>)writeCache.clone();
}
}

final JavaProxyConstructor matching;
synchronized (cache) {
matching = CallableSelector.matchingCallableArityN(
context.runtime, cache,
forArity.toArray(new JavaProxyConstructor[forArity.size()]), args
);
}
@Override
public IRubyObject call(final ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
IRubyObject proxyClass = self.getMetaClass().getInstanceVariables().getInstanceVariable("@java_proxy_class");
if (proxyClass == null || proxyClass.isNil()) {
proxyClass = JavaProxyClass.get_with_class(self, self.getMetaClass());
self.getMetaClass().getInstanceVariables().setInstanceVariable("@java_proxy_class", proxyClass);
}

if ( matching == null ) {
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}
final int argsLength = args.length;
final JavaProxyConstructor[] constructors = ((JavaProxyClass) proxyClass).getConstructors();
ArrayList<JavaProxyConstructor> forArity = findCallablesForArity(argsLength, constructors);

final Object[] javaArgs = convertArguments(matching, args);
JavaObject newObject = matching.newInstance(self, javaArgs);
if ( forArity.size() == 0 ) {
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}

return JavaUtilities.set_java_object(self, self, newObject);
final JavaProxyConstructor matching;
synchronized (writeCache) {
matching = CallableSelector.matchingCallableArityN(
context.runtime, this,
forArity.toArray(new JavaProxyConstructor[forArity.size()]), args
);
}
});

if ( matching == null ) {
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}

final Object[] javaArgs = convertArguments(matching, args);
JavaObject newObject = matching.newInstance(self, javaArgs);

return JavaUtilities.set_java_object(self, self, newObject);
}
}

// NOTE: move to RubyToJavaInvoker for re-use ?!

0 comments on commit a18758f

Please sign in to comment.