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

Commits on Jan 5, 2015

  1. [Truffle] Don't swallow exceptions from loading core library code - i…

    …n fact make it a hard failure.
    chrisseaton committed Jan 5, 2015
    Copy the full SHA
    7aeda4b View commit details
  2. Copy the full SHA
    34eb633 View commit details
Original file line number Diff line number Diff line change
@@ -1606,7 +1606,7 @@ public boolean require(RubyString feature) {
notDesignedForCompilation();

try {
getContext().getFeatureManager().require(feature.toString(), this);
getContext().getFeatureManager().require(null, feature.toString(), this);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -1627,14 +1627,14 @@ public RequireRelativeNode(RequireRelativeNode prev) {
}

@Specialization
public boolean require(VirtualFrame frame, RubyString feature) {
public boolean require(RubyString feature) {
notDesignedForCompilation();

final String sourcePath = Truffle.getRuntime().getCallerFrame().getCallNode().getEncapsulatingSourceSection().getSource().getPath();
final String directoryPath = new File(sourcePath).getParent();

try {
getContext().getFeatureManager().requireInPath(directoryPath, feature.toString(), this);
getContext().getFeatureManager().require(directoryPath, feature.toString(), this);
} catch (IOException e) {
throw new RuntimeException(e);
}
24 changes: 22 additions & 2 deletions core/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -18,10 +18,14 @@
import org.jcodings.specific.UTF8Encoding;
import org.jruby.runtime.Constants;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.load.LoadServiceResource;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.core.ArrayNodes;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.control.TruffleFatalException;
import org.jruby.truffle.runtime.hash.HashOperations;
import org.jruby.truffle.runtime.hash.KeyValue;
import org.jruby.truffle.translator.TranslatorDriver;
@@ -348,7 +352,17 @@ public void initializeAfterMethodsAdded() {
objectClass.setConstant(null, "RUBY_DESCRIPTION", context.makeString(OutputStrings.getVersionString()));

if (Options.TRUFFLE_LOAD_CORE.load()) {
loadRubyCore("jruby/truffle/core.rb");
try {
loadRubyCore("jruby/truffle/core.rb");
} catch (RaiseException e) {
final RubyException rubyException = e.getRubyException();

for (String line : Backtrace.DISPLAY_FORMATTER.format(getContext(), rubyException, rubyException.getBacktrace())) {
System.err.println(line);
}

throw new TruffleFatalException("couldn't load the core library", e);
}
}

// ENV is supposed to be an object that actually updates the environment, and sees any updates
@@ -361,7 +375,13 @@ public void loadRubyCore(String fileName) {
final Source source;

try {
source = Source.fromReader(new InputStreamReader(context.getRuntime().getLoadService().getClassPathResource(context.getRuntime().getJRubyClassLoader(), fileName).getInputStream()), "core:/" + fileName);
final LoadServiceResource resource = context.getRuntime().getLoadService().getClassPathResource(context.getRuntime().getJRubyClassLoader(), fileName);

if (resource == null) {
throw new RuntimeException("couldn't load Truffle core library " + fileName);
}

source = Source.fromReader(new InputStreamReader(resource.getInputStream()), "core:/" + fileName);
} catch (IOException e) {
throw new RuntimeException(e);
}
Original file line number Diff line number Diff line change
@@ -14,7 +14,9 @@
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.RubyConstant;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyException;
import org.jruby.truffle.runtime.core.RubyFile;

import java.io.File;
@@ -34,62 +36,68 @@ public FeatureManager(RubyContext context) {
this.context = context;
}

public boolean require(String feature, RubyNode currentNode) throws IOException {
public boolean require(String path, String feature, RubyNode currentNode) throws IOException {
final RubyConstant dataConstantBefore = ModuleOperations.lookupConstant(context, LexicalScope.NONE, context.getCoreLibrary().getObjectClass(), "DATA");

try {
// Some features are handled specially
if (path != null) {
if (requireInPath(path, feature, currentNode)) {
return true;
}
} else {
// Some features are handled specially

if (feature.equals("zlib")) {
context.getWarnings().warn("zlib not yet implemented");
return true;
}
if (feature.equals("zlib")) {
context.getWarnings().warn("zlib not yet implemented");
return true;
}

if (feature.equals("enumerator")) {
context.getWarnings().warn("enumerator not yet implemented");
return true;
}
if (feature.equals("enumerator")) {
context.getWarnings().warn("enumerator not yet implemented");
return true;
}

if (feature.equals("rbconfig")) {
// Kernel#rbconfig is always there
return true;
}
if (feature.equals("rbconfig")) {
// Kernel#rbconfig is always there
return true;
}

if (feature.equals("pp")) {
// Kernel#pretty_inspect is always there
return true;
}
if (feature.equals("pp")) {
// Kernel#pretty_inspect is always there
return true;
}

if (feature.equals("thread")) {
return true;
}
if (feature.equals("thread")) {
return true;
}

// Get the load path
// Try as a full path

// Try as a full path
if (requireFile(feature, currentNode)) {
return true;
}

if (requireInPath("", feature, currentNode)) {
return true;
}
if (requireFile(feature + ".rb", currentNode)) {
return true;
}

// Try as a path relative to the current director
// Try as a path relative to the current directory

if (requireInPath(context.getRuntime().getCurrentDirectory(), feature, currentNode)) {
return true;
}
if (requireInPath(context.getRuntime().getCurrentDirectory(), feature, currentNode)) {
return true;
}

// Try each load path in turn
// Try each load path in turn

for (Object pathObject : context.getCoreLibrary().getLoadPath().slowToArray()) {
final String path = pathObject.toString();
for (Object pathObject : context.getCoreLibrary().getLoadPath().slowToArray()) {
final String loadPath = pathObject.toString();

if (requireInPath(path, feature, currentNode)) {
return true;
if (requireInPath(loadPath, feature, currentNode)) {
return true;
}
}
}

// Didn't find the feature

throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature, currentNode));
} finally {
if (dataConstantBefore == null) {
@@ -100,15 +108,7 @@ public boolean require(String feature, RubyNode currentNode) throws IOException
}
}

public boolean requireInPath(String path, String feature, RubyNode currentNode) throws IOException {
if (requireFile(feature, currentNode)) {
return true;
}

if (requireFile(feature + ".rb", currentNode)) {
return true;
}

private boolean requireInPath(String path, String feature, RubyNode currentNode) throws IOException {
if (requireFile(new File(path, feature).getPath(), currentNode)) {
return true;
}
@@ -121,37 +121,44 @@ public boolean requireInPath(String path, String feature, RubyNode currentNode)
}

private boolean requireFile(String fileName, RubyNode currentNode) throws IOException {
// We expect '/' in various classpath URLs, so normalize Windows file paths to use '/'.
// We expect '/' in various classpath URLs, so normalize Windows file paths to use '/'
fileName = fileName.replace('\\', '/');

// Loading from core:/ always just goes ahead without a proper check
if (fileName.startsWith("core:/")) {
try {
context.getCoreLibrary().loadRubyCore(fileName.substring("core:/".length()));
return true;
} catch (Exception e) {
// TODO(CS): obviously not the best way to do this
return false;
for (Object loaded : Arrays.asList(context.getCoreLibrary().getLoadedFeatures().slowToArray())) {
if (loaded.toString().equals(fileName)) {
return true;
}
}
}

final File file = new File(fileName);
final String coreFileName = fileName.substring("core:/".length());

if (!file.isFile()) {
return false;
}
if (context.getRuntime().getLoadService().getClassPathResource(context.getRuntime().getJRubyClassLoader(), coreFileName) == null) {
return false;
}

final String expandedPath = RubyFile.expandPath(fileName);
context.getCoreLibrary().loadRubyCore(coreFileName);
context.getCoreLibrary().getLoadedFeatures().slowPush(context.makeString(fileName));

for (Object loaded : Arrays.asList(context.getCoreLibrary().getLoadedFeatures().slowToArray())) {
if (loaded.toString().equals(expandedPath)) {
return true;
return true;
} else {
final File file = new File(fileName);

if (!file.isFile()) {
return false;
}
}

context.loadFile(fileName, currentNode);
final String expandedPath = RubyFile.expandPath(fileName);

for (Object loaded : Arrays.asList(context.getCoreLibrary().getLoadedFeatures().slowToArray())) {
if (loaded.toString().equals(expandedPath)) {
return true;
}
}

context.getCoreLibrary().getLoadedFeatures().slowPush(context.makeString(expandedPath));
context.loadFile(fileName, currentNode);
context.getCoreLibrary().getLoadedFeatures().slowPush(context.makeString(expandedPath));
}

return true;
}
1 change: 0 additions & 1 deletion core/src/main/ruby/jruby/truffle/core.rb
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@
require_relative 'core/rubinius/api/shims/rubinius'
require_relative 'core/rubinius/api/shims/lookuptable'
require_relative 'core/rubinius/api/shims/thread'
require_relative 'core/rubinius/api/shims/type'
require_relative 'core/rubinius/api/shims/enumerator'
require_relative 'core/rubinius/api/shims/undefined'