Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 16992c2e9022
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: e54dc35a2a49
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Oct 23, 2014

  1. Copy the full SHA
    6cf0535 View commit details
  2. Copy the full SHA
    e54dc35 View commit details
46 changes: 29 additions & 17 deletions core/src/main/java/org/jruby/compiler/JITCompiler.java
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
import org.jruby.ast.util.SexpMaker;
import org.jruby.internal.runtime.methods.CompiledIRMethod;
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
import org.jruby.ir.IRMethod;
import org.jruby.ir.targets.JVMVisitor;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Block;
@@ -53,10 +54,12 @@

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
@@ -227,17 +230,6 @@ public void run() {
// successfully got back a jitted method
long methodCount = counts.successCount.incrementAndGet();

// finally, grab the script
Method scriptMethod = sourceClass.getMethod(
"__script__",
ThreadContext.class,
StaticScope.class,
IRubyObject.class,
IRubyObject[].class,
Block.class,
RubyModule.class);
MethodHandle handle = MethodHandles.publicLookup().unreflect(scriptMethod);

// logEvery n methods based on configuration
if (config.getJitLogEvery() > 0) {
if (methodCount % config.getJitLogEvery() == 0) {
@@ -249,12 +241,32 @@ public void run() {
log(method, className + "." + methodName, "done jitting");
}

method.switchToJitted(
new CompiledIRMethod(
handle,
method.getIRMethod(),
method.getVisibility(),
method.getImplementationClass()));
Map<Integer, MethodType> signatures = ((IRMethod)method.getIRMethod()).getNativeSignatures();
String jittedName = ((IRMethod)method.getIRMethod()).getJittedName();
if (signatures.size() == 1) {
// only variable-arity
method.switchToJitted(
new CompiledIRMethod(
MethodHandles.publicLookup().findStatic(sourceClass, jittedName, signatures.get(-1)),
method.getIRMethod(),
method.getVisibility(),
method.getImplementationClass()));
} else {
// also specific-arity
for (Map.Entry<Integer, MethodType> entry : signatures.entrySet()) {
if (entry.getKey() == -1) continue; // variable arity handle pushed above

method.switchToJitted(
new CompiledIRMethod(
MethodHandles.publicLookup().findStatic(sourceClass, jittedName, signatures.get(-1)),
MethodHandles.publicLookup().findStatic(sourceClass, jittedName, entry.getValue()),
entry.getKey(),
method.getIRMethod(),
method.getVisibility(),
method.getImplementationClass()));
break;
}
}

return;
} catch (Throwable t) {
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.PositionAware;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
@@ -116,6 +117,102 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, block);

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

if (ic.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, IRubyObject.NULL_ARRAY, block);
} else {
try {
pre(ic, context, self, name, block);

return Interpreter.INTERPRET_METHOD(context, this, self, name, IRubyObject.NULL_ARRAY, block);
} finally {
post(ic, context);
}
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, block);

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

if (ic.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0), block);
} else {
try {
pre(ic, context, self, name, block);

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0), block);
} finally {
post(ic, context);
}
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, arg1, block);

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

if (ic.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1), block);
} else {
try {
pre(ic, context, self, name, block);

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1), block);
} finally {
post(ic, context);
}
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
DynamicMethodBox box = this.box;
if (box.callCount >= 0) tryJit(context, box);
DynamicMethod actualMethod = box.actualMethod;
if (actualMethod != null) return actualMethod.call(context, self, clazz, name, arg0, arg1, arg2, block);

InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

if (ic.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1, arg2), block);
} else {
try {
pre(ic, context, self, name, block);

return Interpreter.INTERPRET_METHOD(context, this, self, name, Helpers.arrayOf(arg0, arg1, arg2), block);
} finally {
post(ic, context);
}
}
}

protected void doDebug() {
// FIXME: name should probably not be "" ever.
String realName = name == null || "".equals(name) ? method.getName() : name;
31 changes: 31 additions & 0 deletions core/src/main/java/org/jruby/ir/IRMethod.java
Original file line number Diff line number Diff line change
@@ -9,8 +9,12 @@
import org.jruby.ir.operands.Splat;
import org.jruby.parser.StaticScope;

import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class IRMethod extends IRScope {
public final boolean isInstanceMethod;
@@ -23,13 +27,20 @@ public class IRMethod extends IRScope {
// Argument description of the form [:req, "a"], [:opt, "b"] ..
private List<String[]> argDesc;

// Signatures to the jitted versions of this method
private Map<Integer, MethodType> signatures;

// Method name in the jitted version of this method
private String jittedName;

public IRMethod(IRManager manager, IRScope lexicalParent, String name,
boolean isInstanceMethod, int lineNumber, StaticScope staticScope) {
super(manager, lexicalParent, name, lexicalParent.getFileName(), lineNumber, staticScope);

this.isInstanceMethod = isInstanceMethod;
this.callArgs = new ArrayList<Operand>();
this.argDesc = new ArrayList<String[]>();
this.signatures = new HashMap<>();

if (!getManager().isDryRun() && staticScope != null) {
staticScope.setIRScope(this);
@@ -75,4 +86,24 @@ public LocalVariable getLocalVariable(String name, int scopeDepth) {
if (lvar == null) lvar = getNewLocalVariable(name, scopeDepth);
return lvar;
}

public void addNativeSignature(int arity, MethodType signature) {
signatures.put(arity, signature);
}

public MethodType getNativeSignature(int arity) {
return signatures.get(arity);
}

public Map<Integer, MethodType> getNativeSignatures() {
return Collections.unmodifiableMap(signatures);
}

public String getJittedName() {
return jittedName;
}

public void setJittedName(String jittedName) {
this.jittedName = jittedName;
}
}
2 changes: 0 additions & 2 deletions core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -822,8 +822,6 @@ private static MethodHandle getHandle(RubyClass selfClass, String fallbackName,
}

if (compiledIRMethod != null) {
assert compiledIRMethod.hasExplicitCallProtocol() : "all jitted methods must have call protocol";

binder = SmartBinder.from(site.signature)
.drop("caller");

Loading