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: c9cc8a82718b
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: faa115baaa67
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on Dec 7, 2015

  1. In middle of debug but capturing calleriSite.call = null and couple o…

    …f other ugly hacks towards getting JIT to inline
    enebo committed Dec 7, 2015
    Copy the full SHA
    f8b0d6f View commit details

Commits on Dec 12, 2015

  1. Copy the full SHA
    faa115b View commit details
9 changes: 6 additions & 3 deletions core/src/main/java/org/jruby/compiler/JITCompiler.java
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@
import org.jruby.RubyModule;
import org.jruby.ast.util.SexpMaker;
import org.jruby.internal.runtime.methods.CompiledIRMethod;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
import org.jruby.ir.IRClosure;
import org.jruby.ir.interpreter.InterpreterContext;
@@ -404,7 +405,7 @@ public static String getHashForBytes(byte[] bytes) {
}

public static class MethodJITClassGenerator {
public MethodJITClassGenerator(String className, String methodName, String key, Ruby ruby, MixedModeIRMethod method, JVMVisitor visitor) {
public MethodJITClassGenerator(String className, String methodName, String key, Ruby ruby, Compilable method, JVMVisitor visitor) {
this.packageName = JITCompiler.RUBY_JIT_PREFIX;
if (RubyInstanceConfig.JAVA_VERSION == Opcodes.V1_7 || Options.COMPILE_INVOKEDYNAMIC.load() == true) {
// Some versions of Java 7 seems to have a bug that leaks definitions across cousin classloaders
@@ -426,7 +427,7 @@ public MethodJITClassGenerator(String className, String methodName, String key,
}

@SuppressWarnings("unchecked")
protected void compile(JVMVisitorMethodContext context) {
public void compile(JVMVisitorMethodContext context) {
if (bytecode != null) return;

// Time the compilation
@@ -440,6 +441,8 @@ protected void compile(JVMVisitorMethodContext context) {
throw new NotCompilableException("Could not compile " + method + "; instruction count " + insnCount + " exceeds threshold of " + Options.JIT_MAXSIZE.load());
}

method.getIRScope().setCompilable((DynamicMethod)method);
System.out.println("Adding compiable to " + method.getIRScope());
// This may not be ok since we'll end up running passes specific to JIT
// CON FIXME: Really should clone scope before passes in any case
bytecode = visitor.compileToBytecode(method.getIRScope(), context);
@@ -482,7 +485,7 @@ public String toString() {
private final String className;
private final String methodName;
private final String digestString;
private final MixedModeIRMethod method;
private final Compilable method;
private final JVMVisitor visitor;

private byte[] bytecode;
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package org.jruby.internal.runtime.methods;

import org.jruby.MetaClass;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.compiler.Compilable;
import org.jruby.ir.IRMethod;
import org.jruby.ir.IRScope;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
@@ -18,10 +22,10 @@

import org.jruby.runtime.Helpers;

public class CompiledIRMethod extends DynamicMethod implements IRMethodArgs, PositionAware {
protected final MethodHandle variable;
public class CompiledIRMethod extends DynamicMethod implements IRMethodArgs, PositionAware, Compilable<DynamicMethod> {
public MethodHandle variable;

protected final MethodHandle specific;
public MethodHandle specific;
protected final int specificArity;

protected final IRScope method;
@@ -241,11 +245,56 @@ public DynamicMethod dup() {
return new CompiledIRMethod(variable, specific, specificArity, method, getVisibility(), implementationClass, hasKwargs);
}

@Override
public void setCallCount(int count) {

}

@Override
public void completeBuild(DynamicMethod buildResult) {

}

@Override
public IRScope getIRScope() {
return getIRMethod();
}

@Override
public InterpreterContext ensureInstrsReady() {
return getIRMethod().getFullInterpreterContext();
}

@Override
public String getClassName(ThreadContext context) {
String className;
if (implementationClass.isSingleton()) {
MetaClass metaClass = (MetaClass) implementationClass;
RubyClass realClass = metaClass.getRealClass();
// if real class is Class
if (realClass == context.runtime.getClassClass()) {
// use the attached class's name
className = ((RubyClass) metaClass.getAttached()).getName();
} else {
// use the real class name
className = realClass.getName();
}
} else {
// use the class name
className = implementationClass.getName();
}
return className;
}

public String getFile() {
return method.getFileName();
}

public int getLine() {
return method.getLineNumber();
}

@Override
public void setInterpreterContext(InterpreterContext interpreterContext) {
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jruby.internal.runtime.methods;

import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.runtime.Signature;

86 changes: 83 additions & 3 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
package org.jruby.ir;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import org.jruby.ParseResult;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyModule;
import org.jruby.ast.util.SexpMaker;
import org.jruby.compiler.Compilable;
import org.jruby.compiler.JITCompiler;
import org.jruby.compiler.JITCompiler.MethodJITClassGenerator;
import org.jruby.internal.runtime.methods.CompiledIRMethod;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.ir.dataflow.analyses.LiveVariablesProblem;
import org.jruby.ir.dataflow.analyses.StoreLocalVarPlacementProblem;
import org.jruby.ir.dataflow.analyses.UnboxableOpsAnalysisProblem;
@@ -16,13 +24,16 @@
import org.jruby.ir.passes.*;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.representations.CFG;
import org.jruby.ir.targets.JVMVisitor;
import org.jruby.ir.targets.JVMVisitorMethodContext;
import org.jruby.ir.transformations.inlining.CFGInliner;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import org.jruby.util.OneShotClassLoader;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

@@ -123,7 +134,7 @@ public abstract class IRScope implements ParseResult {

private TemporaryVariable yieldClosureVariable;

private Compilable compilable;
private DynamicMethod compilable;

// Used by cloning code
protected IRScope(IRScope s, IRScope lexicalParent) {
@@ -543,13 +554,24 @@ public void prepareFullBuildCommon() {

fullInterpreterContext = new FullInterpreterContext(this, instrs);
}

// FIXME: This is a hack so JIT Compiler can store method in live scope so we can more easily extract it.
// The existence of compilable as a field feels wrong in this class.
public void setCompilable(DynamicMethod compilable) {
this.compilable = compilable;
}

public DynamicMethod getCompilable() {
return compilable;
}

/**
* This initializes a more complete(full) InterpreterContext which if used in mixed mode will be
* used by the JIT and if used in pure-interpreted mode it will be used by an interpreter engine.
*/
public synchronized FullInterpreterContext prepareFullBuild(Compilable compilable) {
// FIXME: This is gross
this.compilable = compilable;
this.compilable = (DynamicMethod) compilable;
// Don't run if same method was queued up in the tiny race for scheduling JIT/Full Build OR
// for any nested closures which got a a fullInterpreterContext but have not run any passes
// or generated instructions.
@@ -1027,10 +1049,68 @@ public void inlineMethod(Compilable method, RubyModule implClass, int classToken
this.fullInterpreterContext = newContext;

System.out.println(fullInterpreterContext.toStringInstrs());
compilable.setInterpreterContext(fullInterpreterContext);
((Compilable) compilable).setInterpreterContext(fullInterpreterContext);
// Since inline is an if/else of logic in this version of inlining we will just replace the FIC.
}

// FIXME: Passing in DynamicMethod is gross here we probably can minimally cast to Compilable
public void inlineMethodJIT(Compilable method, RubyModule implClass, int classToken, BasicBlock basicBlock, CallBase call, boolean cloneHost) {
IRMethod methodToInline = (IRMethod) method.getIRScope();

// We need fresh fic so we can modify it during inlining without making already running code explode.
FullInterpreterContext newContext = fullInterpreterContext.duplicate();

new CFGInliner(newContext).inlineMethod(methodToInline, implClass, classToken, basicBlock, call, cloneHost);

// Reset state
resetState();

// Re-run opts
for (CompilerPass pass: getManager().getInliningCompilerPasses(this)) {
pass.run(this);
}


//runCompilerPasses(getManager().getJITPasses(this));
newContext.generateInstructionsForIntepretation();
this.fullInterpreterContext = newContext;

System.out.println("FFFFFF\n" + fullInterpreterContext.toStringInstrs());
// ((Compilable) compilable).setInterpreterContext(fullInterpreterContext);
// Since inline is an if/else of logic in this version of inlining we will just replace the FIC.

Ruby runtime = implClass.getRuntime();
String key = SexpMaker.sha1(this);
JVMVisitor visitor = new JVMVisitor();
MethodJITClassGenerator generator = new MethodJITClassGenerator(implClass.getName(), getName(), key, runtime, (Compilable) compilable, visitor);

JVMVisitorMethodContext context = new JVMVisitorMethodContext();
generator.compile(context);

Class sourceClass = visitor.defineFromBytecode(this, generator.bytecode(), new OneShotClassLoader(runtime.getJRubyClassLoader()));

Map<Integer, MethodType> signatures = context.getNativeSignatures();
String jittedName = context.getJittedName();
try {
if (signatures.size() == 1) {
((CompiledIRMethod) compilable).variable = MethodHandles.publicLookup().findStatic(sourceClass, jittedName, signatures.get(-1));
} else {
((CompiledIRMethod) compilable).variable = MethodHandles.publicLookup().findStatic(sourceClass, jittedName, signatures.get(-1));

for (Map.Entry<Integer, MethodType> entry : signatures.entrySet()) {
if (entry.getKey() == -1) continue; // variable arity handle pushed above

((CompiledIRMethod) compilable).specific = MethodHandles.publicLookup().findStatic(sourceClass, jittedName, entry.getValue());
break;
}
}
} catch(Exception e) {
e.printStackTrace();
}

}


/** Record a begin block. Only eval and script body scopes support this */
public void recordBeginBlock(IRClosure beginBlockClosure) {
throw new RuntimeException("BEGIN blocks cannot be added to: " + this.getClass().getName());
Loading