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

Commits on Nov 24, 2016

  1. Revert "[Truffle] Use isTruffle rather than == TRUFFLE"

    This reverts commit d6b317b.
    chrisseaton committed Nov 24, 2016
    Copy the full SHA
    60670f2 View commit details
  2. Revert "Revert "[Truffle] Don't create a classic context in classic m…

    …ain if we're using Truffle.""
    
    This reverts commit 727f529.
    chrisseaton committed Nov 24, 2016
    Copy the full SHA
    b6f6311 View commit details
  3. Copy the full SHA
    c1f8abe View commit details
6 changes: 5 additions & 1 deletion core/src/main/java/org/jruby/JRubyTruffleInterface.java
Original file line number Diff line number Diff line change
@@ -9,12 +9,16 @@
*/
package org.jruby;

import java.io.InputStream;

public interface JRubyTruffleInterface {

String RUNTIME_SYMBOL = "org.jruby.truffle.runtime";

int execute(String path);

void dispose();


int doCheckSyntax(InputStream in, String filename);

}
91 changes: 80 additions & 11 deletions core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -60,6 +60,7 @@
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -219,7 +220,7 @@ public static void main(String[] args) {
catch (Throwable t) {
// If a Truffle exception gets this far it's a hard failure - don't try and dress it up as a Ruby exception

if (main.config.getCompileMode().isTruffle()) {
if (main.isTruffle()) {
System.err.println("Truffle internal error: " + t);
t.printStackTrace(System.err);
} else {
@@ -273,18 +274,22 @@ private Status internalRun() {

Ruby _runtime;

if (DripMain.DRIP_RUNTIME != null) {
// use drip's runtime, reinitializing config
_runtime = DripMain.DRIP_RUNTIME;
_runtime.reinitialize(true);
if (isTruffle()) {
_runtime = null;
} else {
_runtime = Ruby.newInstance(config);
if (DripMain.DRIP_RUNTIME != null) {
// use drip's runtime, reinitializing config
_runtime = DripMain.DRIP_RUNTIME;
_runtime.reinitialize(true);
} else {
_runtime = Ruby.newInstance(config);
}
}

final Ruby runtime = _runtime;
final AtomicBoolean didTeardown = new AtomicBoolean();

if (config.isHardExit()) {
if (runtime != null && config.isHardExit()) {
// we're the command-line JRuby, and should set a shutdown hook for
// teardown.
Runtime.getRuntime().addShutdownHook(new Thread() {
@@ -297,7 +302,9 @@ public void run() {
}

try {
doSetContextClassLoader(runtime);
if (runtime != null) {
doSetContextClassLoader(runtime);
}

if (in == null) {
// no script to run, return success
@@ -307,13 +314,38 @@ public void run() {
throw new MainExitException(1, "jruby: no Ruby script found in input (LoadError)");
} else if (config.getShouldCheckSyntax()) {
// check syntax only and exit
return doCheckSyntax(runtime, in, filename);
if (isTruffle()) {
final JRubyTruffleInterface truffle = loadTruffle();

try {
final int exitCode = truffle.doCheckSyntax(in, filename);
return new Status(exitCode);
} finally {
truffle.dispose();
}
} else {
return doCheckSyntax(runtime, in, filename);
}
} else {
// proceed to run the script
return doRunFromMain(runtime, in, filename);
if (isTruffle()) {
final JRubyTruffleInterface truffle = loadTruffle();

printTruffleTimeMetric("before-run");

try {
final int exitCode = truffle.execute(filename);
return new Status(exitCode);
} finally {
printTruffleTimeMetric("after-run");
truffle.dispose();
}
} else {
return doRunFromMain(runtime, in, filename);
}
}
} finally {
if (didTeardown.compareAndSet(false, true)) {
if (runtime != null && didTeardown.compareAndSet(false, true)) {
runtime.tearDown();
}
}
@@ -576,6 +608,43 @@ else if ( ex instanceof JumpException.FlowControlException ) {
// TODO: should match MRI (>= 2.2.3) exit status - @see ruby/test_enum.rb#test_first
return 2;
}

private boolean isTruffle() {
return config.getCompileMode().isTruffle();
}

private JRubyTruffleInterface loadTruffle() {
Main.printTruffleTimeMetric("before-load-context");

String javaVersion = System.getProperty("java.version");
String[] parts = javaVersion.split("\\D+");
int firstPart = Integer.valueOf(parts[0]);
if (!(firstPart >= 9 || Integer.valueOf(parts[1]) >= 8)) {
System.err.println("JRuby+Truffle needs Java 8 to run (found " + javaVersion + ").");
System.exit(1);
}

final Class<?> clazz;

try {
clazz = Class.forName("org.jruby.truffle.JRubyTruffleImpl");
} catch (Exception e) {
throw new RuntimeException("JRuby's Truffle backend not available - either it was not compiled because JRuby was built with Java 7, or it has been removed", e);
}

final JRubyTruffleInterface truffleContext;

try {
Constructor<?> con = clazz.getConstructor(RubyInstanceConfig.class);
truffleContext = (JRubyTruffleInterface) con.newInstance(config);
} catch (Exception e) {
throw new RuntimeException("Error while calling the constructor of Truffle's RubyContext", e);
}

Main.printTruffleTimeMetric("after-load-context");

return truffleContext;
}

public static void printTruffleTimeMetric(String id) {
if (Options.TRUFFLE_METRICS_TIME.load()) {
114 changes: 19 additions & 95 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -238,6 +238,10 @@ public final class Ruby implements Constantizable {
* @see org.jruby.RubyInstanceConfig
*/
private Ruby(RubyInstanceConfig config) {
if (config.getCompileMode().isTruffle()) {
throw new UnsupportedOperationException("Truffle isn't supported using a classic context - use PolyglotEngine instead.");
}

this.config = config;
this.threadService = new ThreadService(this);

@@ -554,20 +558,6 @@ public void runFromMain(InputStream inputStream, String filename) {
return;
}

if (getInstanceConfig().getCompileMode().isTruffle()) {
final JRubyTruffleInterface truffleContext = getTruffleContext();
Main.printTruffleTimeMetric("before-run");
int exitCode;
try {
exitCode = truffleContext.execute(filename);
} finally {
Main.printTruffleTimeMetric("after-run");
shutdownTruffleContextIfRunning();
}

throw new MainExitException(exitCode);
}

ParseResult parseResult = parseFromMain(filename, inputStream);

// if no DATA, we're done with the stream, shut it down
@@ -839,10 +829,6 @@ public IRubyObject runScript(Script script) {
}

public IRubyObject runScript(Script script, boolean wrap) {
if (getInstanceConfig().getCompileMode().isTruffle()) {
throw new UnsupportedOperationException();
}

return script.load(getCurrentContext(), getTopSelf(), wrap);
}

@@ -855,10 +841,6 @@ public IRubyObject runScriptBody(Script script) {
}

public IRubyObject runInterpreter(ThreadContext context, ParseResult parseResult, IRubyObject self) {
if (getInstanceConfig().getCompileMode().isTruffle()) {
throw new UnsupportedOperationException();
}

return interpreter.execute(this, parseResult, self);
}

@@ -898,56 +880,6 @@ public JITCompiler getJITCompiler() {
return jitCompiler;
}

public JRubyTruffleInterface getTruffleContext() {
synchronized (truffleContextMonitor) {
if (truffleContext == null) {
truffleContext = loadTruffle();
}
return truffleContext;
}
}

private JRubyTruffleInterface loadTruffle() {
Main.printTruffleTimeMetric("before-load-context");

String javaVersion = System.getProperty("java.version");
String[] parts = javaVersion.split("\\D+");
int firstPart = Integer.valueOf(parts[0]);
if (!(firstPart >= 9 || Integer.valueOf(parts[1]) >= 8)) {
System.err.println("JRuby+Truffle needs Java 8 to run (found " + javaVersion + ").");
System.exit(1);
}

final Class<?> clazz;

try {
clazz = getJRubyClassLoader().loadClass("org.jruby.truffle.JRubyTruffleImpl");
} catch (Exception e) {
throw new RuntimeException("JRuby's Truffle backend not available - either it was not compiled because JRuby was built with Java 7, or it has been removed", e);
}

final JRubyTruffleInterface truffleContext;

try {
Constructor<?> con = clazz.getConstructor(RubyInstanceConfig.class);
truffleContext = (JRubyTruffleInterface) con.newInstance(config);
} catch (Exception e) {
throw new RuntimeException("Error while calling the constructor of Truffle's RubyContext", e);
}

Main.printTruffleTimeMetric("after-load-context");

return truffleContext;
}

public void shutdownTruffleContextIfRunning() {
synchronized (truffleContextMonitor) {
if (truffleContext != null) {
truffleContext.dispose();
}
}
}

/**
* @deprecated use #newInstance()
*/
@@ -1276,8 +1208,7 @@ private void init() {
// if we can't use reflection, 'jruby' and 'java' won't work; no load.
boolean reflectionWorks = doesReflectionWork();

if (!RubyInstanceConfig.DEBUG_PARSER && reflectionWorks
&& !getInstanceConfig().getCompileMode().isTruffle()) {
if (!RubyInstanceConfig.DEBUG_PARSER && reflectionWorks) {
loadService.require("jruby");
}

@@ -1286,23 +1217,21 @@ private void init() {
// out of base boot mode
bootingCore = false;

if (!getInstanceConfig().getCompileMode().isTruffle()) {
// init Ruby-based kernel
initRubyKernel();
// init Ruby-based kernel
initRubyKernel();

// Define blank modules for feature detection in preludes
if (!config.isDisableGems()) {
defineModule("Gem");
}
if (!config.isDisableDidYouMean()) {
defineModule("DidYouMean");
}
// Define blank modules for feature detection in preludes
if (!config.isDisableGems()) {
defineModule("Gem");
}
if (!config.isDisableDidYouMean()) {
defineModule("DidYouMean");
}

initRubyPreludes();
initRubyPreludes();

// everything booted, so SizedQueue should be available; set up root fiber
ThreadFiber.initRootFiber(context);
}
// everything booted, so SizedQueue should be available; set up root fiber
ThreadFiber.initRootFiber(context);

if(config.isProfiling()) {
// additional twiddling for profiled mode
@@ -1324,10 +1253,8 @@ private void init() {
bootingRuntime = false;

// Require in all libraries specified on command line
if (!getInstanceConfig().getCompileMode().isTruffle()) {
for (String scriptName : config.getRequiredLibraries()) {
topSelf.callMethod(context, "require", RubyString.newString(this, scriptName));
}
for (String scriptName : config.getRequiredLibraries()) {
topSelf.callMethod(context, "require", RubyString.newString(this, scriptName));
}
}

@@ -5187,9 +5114,6 @@ public IRubyObject call(ThreadContext context, RecursiveFunction func, IRubyObje
// Compilation
private final JITCompiler jitCompiler;

private JRubyTruffleInterface truffleContext;
private final Object truffleContextMonitor = new Object();

// Note: this field and the following static initializer
// must be located be in this order!
private volatile static boolean securityRestricted = false;
2 changes: 0 additions & 2 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
@@ -146,7 +146,6 @@ public static IRubyObject INTERPRET_BLOCK(ThreadContext context, Block block, IR
*/
public static IRubyObject evalSimple(ThreadContext context, RubyModule under, IRubyObject self, RubyString src, String file, int lineNumber, EvalType evalType) {
Ruby runtime = context.runtime;
if (runtime.getInstanceConfig().getCompileMode().isTruffle()) throw new UnsupportedOperationException();

// no binding, just eval in "current" frame (caller's frame)
DynamicScope parentScope = context.getCurrentScope();
@@ -192,7 +191,6 @@ private static IRubyObject evalCommon(ThreadContext context, DynamicScope evalSc
*/
public static IRubyObject evalWithBinding(ThreadContext context, IRubyObject self, IRubyObject src, Binding binding) {
Ruby runtime = context.runtime;
if (runtime.getInstanceConfig().getCompileMode().isTruffle()) throw new UnsupportedOperationException();

DynamicScope evalScope = binding.getEvalScope(runtime);
evalScope.getStaticScope().determineModule(); // FIXME: It would be nice to just set this or remove it from staticScope altogether
7 changes: 7 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/JRubyTruffleImpl.java
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@
import org.jruby.JRubyTruffleInterface;
import org.jruby.RubyInstanceConfig;

import java.io.InputStream;

public class JRubyTruffleImpl implements JRubyTruffleInterface {

private final RubyEngine engine;
@@ -27,6 +29,11 @@ public int execute(String path) {
return engine.execute(path);
}

@Override
public int doCheckSyntax(InputStream in, String filename) {
return engine.doCheckSyntax(in, filename);
}

@Override
public void dispose() {
engine.dispose();
36 changes: 2 additions & 34 deletions truffle/src/main/java/org/jruby/truffle/Main.java
Original file line number Diff line number Diff line change
@@ -49,9 +49,6 @@
import org.jruby.util.cli.Options;
import org.jruby.util.cli.OutputStrings;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.management.ManagementFactory;

@@ -63,6 +60,7 @@ public static void main(String[] args) {
final RubyInstanceConfig config = new RubyInstanceConfig(false);
config.setHardExit(true);
config.processArguments(args);
config.setCompileMode(RubyInstanceConfig.CompileMode.TRUFFLE);

doShowVersion(config);
doShowCopyright(config);
@@ -86,7 +84,7 @@ public static void main(String[] args) {
exitCode = 1;
} else if (config.getShouldCheckSyntax()) {
// check syntax only and exit
exitCode = doCheckSyntax(rubyEngine, in, filename);
exitCode = rubyEngine.doCheckSyntax(in, filename);
} else {
exitCode = rubyEngine.execute(filename);
}
@@ -129,36 +127,6 @@ private static void doShowVersion(RubyInstanceConfig config) {
}
}

private static int doCheckSyntax(RubyEngine engine, InputStream in, String filename) {
// check primary script
boolean status = checkStreamSyntax(engine, in, filename);

// check other scripts specified on argv
for (String arg : engine.getContext().getInstanceConfig().getArgv()) {
status = status && checkFileSyntax(engine, arg);
}

return status ? 0 : -1;
}

private static boolean checkFileSyntax(RubyEngine engine, String filename) {
File file = new File(filename);
if (file.exists()) {
try {
return checkStreamSyntax(engine, new FileInputStream(file), filename);
} catch (FileNotFoundException fnfe) {
engine.getContext().getInstanceConfig().getError().println("File not found: " + filename);
return false;
}
} else {
return false;
}
}

private static boolean checkStreamSyntax(RubyEngine engine, InputStream in, String filename) {
return engine.checkSyntax(in, filename);
}

public static void printTruffleTimeMetric(String id) {
if (Options.TRUFFLE_METRICS_TIME.load()) {
final long millis = System.currentTimeMillis();
47 changes: 40 additions & 7 deletions truffle/src/main/java/org/jruby/truffle/RubyEngine.java
Original file line number Diff line number Diff line change
@@ -18,6 +18,9 @@
import org.jruby.truffle.platform.graal.Graal;
import org.jruby.util.cli.Options;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class RubyEngine {
@@ -26,6 +29,10 @@ public class RubyEngine {
private final RubyContext context;

public RubyEngine(RubyInstanceConfig instanceConfig) {
if (!instanceConfig.getCompileMode().isTruffle()) {
throw new UnsupportedOperationException();
}

engine = PolyglotEngine.newBuilder()
.globalSymbol(JRubyTruffleInterface.RUNTIME_SYMBOL, new InstanceConfigWrapper(instanceConfig))
.build();
@@ -45,13 +52,6 @@ public int execute(String path) {
return engine.eval(loadSource("Truffle::Boot.main", "main")).as(Integer.class);
}

public boolean checkSyntax(InputStream in, String filename) {
context.setSyntaxCheckInputStream(in);
context.setOriginalInputFile(filename);

return engine.eval(loadSource("Truffle::Boot.check_syntax", "check_syntax")).as(Boolean.class);
}

public RubyContext getContext() {
return context;
}
@@ -65,4 +65,37 @@ private Source loadSource(String source, String name) {
return Source.newBuilder(source).name(name).mimeType(RubyLanguage.MIME_TYPE).build();
}

public int doCheckSyntax(InputStream in, String filename) {
// check primary script
boolean status = checkSyntax(in, filename);

// check other scripts specified on argv
for (String arg : context.getInstanceConfig().getArgv()) {
status = status && checkFileSyntax(arg);
}

return status ? 0 : -1;
}

private boolean checkFileSyntax(String filename) {
File file = new File(filename);
if (file.exists()) {
try {
return checkSyntax(new FileInputStream(file), filename);
} catch (FileNotFoundException fnfe) {
context.getInstanceConfig().getError().println("File not found: " + filename);
return false;
}
} else {
return false;
}
}

public boolean checkSyntax(InputStream in, String filename) {
context.setSyntaxCheckInputStream(in);
context.setOriginalInputFile(filename);

return engine.eval(loadSource("Truffle::Boot.check_syntax", "check_syntax")).as(Boolean.class);
}

}