Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Only load the IR compiler if it will be needed
Browse files Browse the repository at this point in the history
donv committed May 20, 2015
1 parent 4da5af7 commit 4c5c563
Showing 20 changed files with 104 additions and 88 deletions.
15 changes: 15 additions & 0 deletions core/src/main/java/org/jruby/Compiler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.jruby;

import org.jruby.ast.Node;
import org.jruby.ast.executable.Script;
import org.jruby.ast.executable.ScriptAndCode;
import org.jruby.util.ClassDefiningClassLoader;

/**
* Created by uwe on 20/5/15.
*/
public interface Compiler {
Script tryCompile(Node scriptNode);

ScriptAndCode tryCompile(Node scriptNode, ClassDefiningClassLoader classDefiningClassLoader);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.jruby.compiler;
package org.jruby;

/**
* Represents an object that can produce a JIT-optimizable "constant" version of itself. Currently this is only used
75 changes: 37 additions & 38 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -48,15 +48,12 @@
import org.jruby.ast.GlobalVarNode;
import org.jruby.ast.VCallNode;
import org.jruby.ast.WhileNode;
import org.jruby.compiler.Constantizable;
import org.jruby.compiler.NotCompilableException;
import org.jruby.ext.thread.ThreadLibrary;
import org.jruby.ir.IRScriptBody;
import org.jruby.javasupport.JavaSupport;
import org.jruby.javasupport.JavaSupportImpl;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.parser.StaticScope;
import org.jruby.util.ClassDefiningClassLoader;
import org.objectweb.asm.util.TraceClassVisitor;

import jnr.constants.Constant;
@@ -75,7 +72,6 @@
import org.jruby.ast.executable.ScriptAndCode;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.common.RubyWarnings;
import org.jruby.compiler.JITCompiler;
import org.jruby.embed.Extension;
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.MainExitException;
@@ -94,7 +90,6 @@
import org.jruby.internal.runtime.methods.CallConfiguration;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.ir.Compiler;
import org.jruby.ir.IRManager;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.persistence.IRReader;
@@ -104,6 +99,7 @@
import org.jruby.management.BeanManager;
import org.jruby.management.BeanManagerFactory;
import org.jruby.management.Config;
import org.jruby.management.JITCompiler;
import org.jruby.management.ParserStats;
import org.jruby.parser.Parser;
import org.jruby.parser.ParserConfiguration;
@@ -280,9 +276,36 @@ private Ruby(RubyInstanceConfig config) {
objectSpacer = DISABLED_OBJECTSPACE;
}

this.interpreter = new Interpreter(this);

if (getInstanceConfig().getCompileMode().shouldJIT()) {
final Class<?> clazz;

try {
clazz = getJRubyClassLoader().loadClass("org.jruby.ir.Compiler");
} catch (Exception e) {
throw new RuntimeException("Compiler not available", e);
}

try {
Constructor<?> con = clazz.getConstructor(Ruby.class);
compiler = (org.jruby.Compiler) con.newInstance(this);
} catch (Exception e) {
throw new RuntimeException("Error while calling the constructor of IR Compiler", e);
}
} else {
compiler = null;
}

reinitialize(false);
}

private final org.jruby.Compiler compiler;

public Compiler getCompiler() {
return compiler;
}

public void registerMBeans() {
this.beanManager.register(jitCompiler);
this.beanManager.register(configBean);
@@ -471,7 +494,7 @@ public IRubyObject evalScriptlet(String script, DynamicScope scope) {
context.preEvalScriptlet(scope);

try {
return Interpreter.getInstance().execute(this, rootNode, context.getFrameSelf());
return interpreter.execute(this, rootNode, context.getFrameSelf());
} finally {
context.postEvalScriptlet();
}
@@ -651,7 +674,7 @@ public IRubyObject runWithGetsLoop(Node scriptNode, boolean printing, boolean pr
boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
if (compile) {
try {
script = tryCompile(scriptNode);
script = compiler.tryCompile(scriptNode);
if (Options.JIT_LOGGING.load()) {
LOG.info("Successfully compiled: " + scriptNode.getPosition().getFile());
}
@@ -764,7 +787,7 @@ private ScriptAndCode precompileCLI(Node scriptNode) {
// IR JIT does not handle all scripts yet, so let those that fail run in interpreter instead
// FIXME: restore error once JIT should handle everything
try {
scriptAndCode = tryCompile(scriptNode, new ClassDefiningJRubyClassLoader(getJRubyClassLoader()));
scriptAndCode = compiler.tryCompile(scriptNode, new ClassDefiningJRubyClassLoader(getJRubyClassLoader()));
if (scriptAndCode != null && Options.JIT_LOGGING.load()) {
LOG.info("done compiling target script: " + scriptNode.getPosition().getFile());
}
@@ -779,18 +802,6 @@ private ScriptAndCode precompileCLI(Node scriptNode) {
return scriptAndCode;
}

/**
* Try to compile the code associated with the given Node, returning an
* instance of the successfully-compiled Script or null if the script could
* not be compiled.
*
* @param node The node to attempt to compiled
* @return an instance of the successfully-compiled Script, or null.
*/
public Script tryCompile(Node node) {
return tryCompile(node, new ClassDefiningJRubyClassLoader(getJRubyClassLoader())).script();
}

private void failForcedCompile(Node scriptNode) throws RaiseException {
if (config.getCompileMode().shouldPrecompileAll()) {
throw newRuntimeError("could not compile and compile mode is 'force': " + scriptNode.getPosition().getFile());
@@ -804,20 +815,6 @@ private void handeCompileError(Node node, Throwable t) {
}
}

private ScriptAndCode tryCompile(Node node, ClassDefiningClassLoader classLoader) {
try {
return Compiler.getInstance().execute(this, node, classLoader);
} catch (NotCompilableException e) {
if (Options.JIT_LOGGING.load()) {
LOG.error("failed to compile target script " + node.getPosition().getFile() + ": " + e.getLocalizedMessage());
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error(e);
}
}
return null;
}
}

public IRubyObject runScript(Script script) {
return runScript(script, false);
}
@@ -856,7 +853,7 @@ public IRubyObject runInterpreter(ThreadContext context, ParseResult parseResult
}

try {
return Interpreter.getInstance().execute(this, parseResult, self);
return interpreter.execute(this, parseResult, self);
} catch (JumpException.ReturnJump rj) {
return (IRubyObject) rj.getValue();
}
@@ -874,7 +871,7 @@ public IRubyObject runInterpreter(ThreadContext context, Node rootNode, IRubyObj
try {

// FIXME: retrieve from IRManager unless lifus does it later
return Interpreter.getInstance().execute(this, rootNode, self);
return interpreter.execute(this, rootNode, self);
} catch (JumpException.ReturnJump rj) {
return (IRubyObject) rj.getValue();
}
@@ -2981,7 +2978,7 @@ public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
// script was not found in cache above, so proceed to compile
Node scriptNode = parseFile(readStream, filename, null);
if (script == null) {
scriptAndCode = tryCompile(scriptNode, new ClassDefiningJRubyClassLoader(jrubyClassLoader));
scriptAndCode = compiler.tryCompile(scriptNode, new ClassDefiningJRubyClassLoader(jrubyClassLoader));
if (scriptAndCode != null) script = scriptAndCode.script();
}

@@ -3058,6 +3055,8 @@ public JavaProxyClassFactory getJavaProxyClassFactory() {
return javaProxyClassFactory;
}

private final Interpreter interpreter;

public class CallTraceFuncHook extends EventHook {
private RubyProc traceFunc;
private EnumSet<RubyEvent> interest =
@@ -4775,7 +4774,7 @@ private void setNetworkStack() {
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyBoolean.java
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@

import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -91,7 +90,7 @@ public Class<?> getJavaClass() {
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyEncoding.java
Original file line number Diff line number Diff line change
@@ -41,7 +41,6 @@
import org.jcodings.util.Hash.HashEntryIterator;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -101,7 +100,7 @@ private RubyEncoding(Ruby runtime, ByteList name, Encoding encoding, boolean isD
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
4 changes: 1 addition & 3 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -39,9 +39,7 @@
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
@@ -133,7 +131,7 @@ public ClassIndex getNativeClassIndex() {
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyNil.java
Original file line number Diff line number Diff line change
@@ -34,7 +34,6 @@

import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
@@ -110,7 +109,7 @@ public Class<?> getJavaClass() {
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
4 changes: 1 addition & 3 deletions core/src/main/java/org/jruby/RubySymbol.java
Original file line number Diff line number Diff line change
@@ -41,9 +41,7 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.compiler.Constantizable;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.Block.Type;
@@ -207,7 +205,7 @@ public static RubySymbol newSymbol(Ruby runtime, String name, Encoding encoding)
}

/**
* @see org.jruby.compiler.Constantizable
* @see Constantizable
*/
@Override
public Object constant() {
Original file line number Diff line number Diff line change
@@ -33,8 +33,8 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.jruby.compiler.JITCompiler;
import org.jruby.compiler.impl.SkinnyMethodAdapter;
import org.jruby.management.JITCompiler;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.ClassDefiningJRubyClassLoader;
import org.objectweb.asm.ClassVisitor;
Original file line number Diff line number Diff line change
@@ -36,7 +36,6 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.net.URL;

import org.jruby.Ruby;
@@ -192,7 +191,7 @@ private EmbedEvalUnit runParser(Object input, String filename, int... lines) {
CompileMode compileMode = runtime.getInstanceConfig().getCompileMode();
if (compileMode == CompileMode.FORCE) {
// CON FIXME: We may need to force heap variables here so the compiled script uses our provided scope
Script script = runtime.tryCompile(node);
Script script = runtime.getCompiler().tryCompile(node);
if (script != null) {
return new EmbedEvalUnitImpl(container, node, scope, script);
} else {
43 changes: 34 additions & 9 deletions core/src/main/java/org/jruby/ir/Compiler.java
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.ast.Node;
import org.jruby.ast.executable.AbstractScript;
import org.jruby.ast.executable.Script;
import org.jruby.ast.executable.ScriptAndCode;
@@ -22,27 +23,51 @@
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ClassDefiningClassLoader;
import org.jruby.util.ClassDefiningJRubyClassLoader;
import org.jruby.util.cli.Options;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;

public class Compiler extends IRTranslator<ScriptAndCode, ClassDefiningClassLoader> {
public class Compiler extends IRTranslator<ScriptAndCode, ClassDefiningClassLoader> implements org.jruby.Compiler {
private static final Logger LOG = LoggerFactory.getLogger("Compiler");
private final Ruby ruby;

// Compiler is singleton
private Compiler() {}
public Compiler(Ruby ruby) {
this.ruby = ruby;
}

private static class CompilerHolder {
// FIXME: Remove as singleton unless lifus does later
public static final Compiler instance = new Compiler();
/**
* Try to compile the code associated with the given Node, returning an
* instance of the successfully-compiled Script or null if the script could
* not be compiled.
*
* @param node The node to attempt to compiled
* @return an instance of the successfully-compiled Script, or null.
*/
public Script tryCompile(Node node) {
return tryCompile(node, new ClassDefiningJRubyClassLoader(ruby.getJRubyClassLoader())).script();
}

public static Compiler getInstance() {
return CompilerHolder.instance;
public ScriptAndCode tryCompile(Node node, ClassDefiningClassLoader classLoader) {
try {
return execute(ruby, node, classLoader);
} catch (NotCompilableException e) {
if (Options.JIT_LOGGING.load()) {
LOG.error("failed to compile target script " + node.getPosition().getFile() + ": " + e.getLocalizedMessage());
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error(e);
}
}
return null;
}
}

@Override
protected ScriptAndCode execute(final Ruby runtime, final IRScriptBody scope, ClassDefiningClassLoader classLoader) {
protected ScriptAndCode execute(final IRScriptBody scope, ClassDefiningClassLoader classLoader) {
JVMVisitor visitor;
byte[] bytecode;
Class compiled;
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/IRTranslator.java
Original file line number Diff line number Diff line change
@@ -39,8 +39,8 @@ public R execute(Ruby runtime, ParseResult result, S specificObject) {
}
}

return execute(runtime, scope, specificObject);
return execute(scope, specificObject);
}

protected abstract R execute(Ruby runtime, IRScriptBody producedIrScope, S specificObject);
protected abstract R execute(IRScriptBody producedIrScope, S specificObject);
}
14 changes: 4 additions & 10 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
@@ -35,18 +35,12 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> {
private static final IRubyObject[] EMPTY_ARGS = new IRubyObject[]{};
public static final String ROOT = "(root)";
static int interpInstrsCount = 0;
private final Ruby runtime;

// we do not need instances of Interpreter
// FIXME: Should we make it real singleton and get rid of static methods?
private Interpreter() { }

private static class InterpreterHolder {
// FIXME: Remove static reference unless lifus does later
public static final Interpreter instance = new Interpreter();
}

public static Interpreter getInstance() {
return InterpreterHolder.instance;
public Interpreter(Ruby runtime) {
this.runtime = runtime;
}

public static void dumpStats() {
@@ -71,7 +65,7 @@ public static void runBeginBlocks(List<IRClosure> beBlocks, ThreadContext contex
}

@Override
protected IRubyObject execute(Ruby runtime, IRScriptBody irScope, IRubyObject self) {
protected IRubyObject execute(IRScriptBody irScope, IRubyObject self) {
BeginEndInterpreterContext ic = (BeginEndInterpreterContext) irScope.getInterpreterContext();
ThreadContext context = runtime.getCurrentContext();
String name = ROOT;
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package org.jruby.ir.targets;

import com.headius.invokebinder.Binder;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.builtin.IRubyObject;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
6 changes: 1 addition & 5 deletions core/src/main/java/org/jruby/ir/targets/LazyObjectSite.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package org.jruby.ir.targets;

import com.headius.invokebinder.Binder;
import com.headius.invokebinder.SmartBinder;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ThreadContext;
import org.jruby.Constantizable;
import org.jruby.runtime.builtin.IRubyObject;

import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;

/**
* Created by headius on 10/23/14.
2 changes: 0 additions & 2 deletions core/src/main/java/org/jruby/management/BeanManager.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.jruby.management;

import org.jruby.compiler.JITCompilerMBean;

public interface BeanManager {

void register(JITCompilerMBean jitCompiler);
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@

import java.lang.reflect.Constructor;
import org.jruby.Ruby;
import org.jruby.compiler.JITCompilerMBean;

public class BeanManagerFactory {
private static final Class BeanManagerImpl;
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.jruby.Ruby;
import org.jruby.compiler.JITCompilerMBean;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.compiler;
package org.jruby.management;


import org.jruby.MetaClass;
@@ -35,6 +35,7 @@
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyModule;
import org.jruby.ast.util.SexpMaker;
import org.jruby.compiler.Compilable;
import org.jruby.internal.runtime.methods.CompiledIRMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
import org.jruby.ir.IRMethod;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.jruby.compiler;
package org.jruby.management;

public interface JITCompilerMBean {
public long getSuccessCount();

0 comments on commit 4c5c563

Please sign in to comment.