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

Commits on Feb 2, 2016

  1. Copy the full SHA
    acf9d27 View commit details
  2. Copy the full SHA
    0cb08a2 View commit details
  3. Copy the full SHA
    af800c3 View commit details
  4. Copy the full SHA
    05ab638 View commit details
  5. Revert "[Truffle] Add a SideEffectFreeNode interface, like JRuby's Si…

    …deEffectFree."
    
    This reverts commit acf9d27.
    chrisseaton committed Feb 2, 2016
    Copy the full SHA
    f8db812 View commit details
  6. Copy the full SHA
    febd443 View commit details
  7. Copy the full SHA
    b51d2cf View commit details
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -265,6 +265,7 @@ public class Options {
public static final Option<Boolean> TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA = bool(TRUFFLE, "truffle.exceptions.print_uncaught_java", false, "Print uncaught Java exceptions at the point of translating them to Ruby exceptions.");
public static final Option<Boolean> TRUFFLE_BACKTRACES_HIDE_CORE_FILES = bool(TRUFFLE, "truffle.backtraces.hide_core_files", true, "Hide core source files in backtraces, like MRI does.");
public static final Option<Integer> TRUFFLE_BACKTRACES_LIMIT = integer(TRUFFLE, "truffle.backtraces.limit", 9999, "Limit the size of Ruby backtraces.");
public static final Option<Boolean> TRUFFLE_BACKTRACES_OMIT_UNUSED = bool(TRUFFLE, "truffle.backtraces.omit_unused", true, "Omit backtraces that should be unused as they have pure rescue expressions.");
public static final Option<Boolean> TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = bool(TRUFFLE, "truffle.set_trace_func.include_core_file_callers", false, "Include internal core library calls in set_trace_func output.");

public static final Option<Boolean> TRUFFLE_METRICS_TIME = bool(TRUFFLE, "truffle.metrics.time", false, "Print the time at various stages of VM operation.");
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ public DynamicObject captureBacktrace(DynamicObject exception, NotProvided offse
@TruffleBoundary
@Specialization
public DynamicObject captureBacktrace(DynamicObject exception, int offset) {
Backtrace backtrace = RubyCallStack.getBacktrace(getContext(), this, offset);
Backtrace backtrace = RubyCallStack.getBacktrace(getContext(), this, offset, exception);
Layouts.EXCEPTION.setBacktrace(exception, backtrace);
return nil();
}
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ public DynamicObject absolutePath(DynamicObject threadBacktraceLocation) {
final Activation activation = ThreadBacktraceLocationLayoutImpl.INSTANCE.getActivation(threadBacktraceLocation);

if (activation.getCallNode() == null) {
return createString(StringOperations.encodeRope(BacktraceFormatter.OMITTED, UTF8Encoding.INSTANCE));
return createString(StringOperations.encodeRope(BacktraceFormatter.OMITTED_LIMIT, UTF8Encoding.INSTANCE));
}

final SourceSection sourceSection = activation.getCallNode().getEncapsulatingSourceSection();
@@ -90,7 +90,7 @@ public DynamicObject toS(DynamicObject threadBacktraceLocation) {
final Activation activation = ThreadBacktraceLocationLayoutImpl.INSTANCE.getActivation(threadBacktraceLocation);

if (activation.getCallNode() == null) {
return createString(StringOperations.encodeRope(BacktraceFormatter.OMITTED, UTF8Encoding.INSTANCE));
return createString(StringOperations.encodeRope(BacktraceFormatter.OMITTED_LIMIT, UTF8Encoding.INSTANCE));
}

final SourceSection sourceSection = activation.getCallNode().getEncapsulatingSourceSection();
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.language.exceptions;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;

public class DisablingBacktracesNode extends RubyNode {

@Child private RubyNode child;

private static ThreadLocal<Boolean> areBacktracesDisabledThreadLocal = new ThreadLocal<Boolean>() {

@Override
protected Boolean initialValue() {
return false;
}
};

public DisablingBacktracesNode(RubyContext context, SourceSection sourceSection, RubyNode child) {
super(context, sourceSection);
this.child = child;
}

@Override
public Object execute(VirtualFrame frame) {
final boolean backtracesPreviouslyDisabled = areBacktracesDisabledThreadLocal.get();

try {
areBacktracesDisabledThreadLocal.set(true);

return child.execute(frame);
} finally {
areBacktracesDisabledThreadLocal.set(backtracesPreviouslyDisabled);
}
}

public static boolean areBacktracesDisabled() {
return areBacktracesDisabledThreadLocal.get();
}

}
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@
import org.joni.NameEntry;
import org.joni.Regex;
import org.joni.Syntax;
import org.jruby.ast.SideEffectFree;
import org.jruby.ast.visitor.NodeVisitor;
import org.jruby.common.IRubyWarnings;
import org.jruby.lexer.yacc.InvalidSourcePosition;
@@ -28,6 +29,7 @@
import org.jruby.runtime.Helpers;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.language.control.*;
import org.jruby.truffle.language.exceptions.DisablingBacktracesNode;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.nodes.ThreadLocalObjectNode;
@@ -2667,59 +2669,78 @@ public RubyNode visitRescueNode(org.jruby.ast.RescueNode node) {

org.jruby.ast.RescueBodyNode rescueBody = node.getRescueNode();

while (rescueBody != null) {
if (rescueBody.getExceptionNodes() != null) {
if (rescueBody.getExceptionNodes() instanceof org.jruby.ast.ArrayNode) {
final org.jruby.ast.Node[] exceptionNodes = ((org.jruby.ast.ArrayNode) rescueBody.getExceptionNodes()).children();
if (context.getOptions().BACKTRACES_OMIT_UNUSED
&& rescueBody != null
&& rescueBody.getExceptionNodes() == null
&& rescueBody.getBodyNode() instanceof SideEffectFree
&& rescueBody.getOptRescueNode() == null) {
tryPart = new DisablingBacktracesNode(context, sourceSection, tryPart);

final RubyNode[] handlingClasses = new RubyNode[exceptionNodes.length];
RubyNode bodyNode;

for (int n = 0; n < handlingClasses.length; n++) {
handlingClasses[n] = exceptionNodes[n].accept(this);
}
if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
bodyNode = nilNode(sourceSection);
} else {
bodyNode = rescueBody.getBodyNode().accept(this);
}

RubyNode translatedBody;
final RescueAnyNode rescueNode = new RescueAnyNode(context, sourceSection, bodyNode);
rescueNodes.add(rescueNode);
} else {
while (rescueBody != null) {
if (rescueBody.getExceptionNodes() != null) {
if (rescueBody.getExceptionNodes() instanceof org.jruby.ast.ArrayNode) {
final org.jruby.ast.Node[] exceptionNodes = ((org.jruby.ast.ArrayNode) rescueBody.getExceptionNodes()).children();

if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
translatedBody = nilNode(sourceSection);
} else {
translatedBody = rescueBody.getBodyNode().accept(this);
}
final RubyNode[] handlingClasses = new RubyNode[exceptionNodes.length];

final RescueClassesNode rescueNode = new RescueClassesNode(context, sourceSection, handlingClasses, translatedBody);
rescueNodes.add(rescueNode);
} else if (rescueBody.getExceptionNodes() instanceof org.jruby.ast.SplatNode) {
final org.jruby.ast.SplatNode splat = (org.jruby.ast.SplatNode) rescueBody.getExceptionNodes();
for (int n = 0; n < handlingClasses.length; n++) {
handlingClasses[n] = exceptionNodes[n].accept(this);
}

RubyNode translatedBody;

if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
translatedBody = nilNode(sourceSection);
} else {
translatedBody = rescueBody.getBodyNode().accept(this);
}

final RescueClassesNode rescueNode = new RescueClassesNode(context, sourceSection, handlingClasses, translatedBody);
rescueNodes.add(rescueNode);
} else if (rescueBody.getExceptionNodes() instanceof org.jruby.ast.SplatNode) {
final org.jruby.ast.SplatNode splat = (org.jruby.ast.SplatNode) rescueBody.getExceptionNodes();

final RubyNode splatTranslated = translateNodeOrNil(sourceSection, splat.getValue());
final RubyNode splatTranslated = translateNodeOrNil(sourceSection, splat.getValue());

RubyNode bodyTranslated;
RubyNode bodyTranslated;

if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
bodyTranslated = nilNode(sourceSection);
} else {
bodyTranslated = rescueBody.getBodyNode().accept(this);
}

final RescueSplatNode rescueNode = new RescueSplatNode(context, sourceSection, splatTranslated, bodyTranslated);
rescueNodes.add(rescueNode);
} else {
unimplemented(node);
}
} else {
RubyNode bodyNode;

if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
bodyTranslated = nilNode(sourceSection);
bodyNode = nilNode(sourceSection);
} else {
bodyTranslated = rescueBody.getBodyNode().accept(this);
bodyNode = rescueBody.getBodyNode().accept(this);
}

final RescueSplatNode rescueNode = new RescueSplatNode(context, sourceSection, splatTranslated, bodyTranslated);
final RescueAnyNode rescueNode = new RescueAnyNode(context, sourceSection, bodyNode);
rescueNodes.add(rescueNode);
} else {
unimplemented(node);
}
} else {
RubyNode bodyNode;

if (rescueBody.getBodyNode() == null || rescueBody.getBodyNode().getPosition() == InvalidSourcePosition.INSTANCE) {
bodyNode = nilNode(sourceSection);
} else {
bodyNode = rescueBody.getBodyNode().accept(this);
}

final RescueAnyNode rescueNode = new RescueAnyNode(context, sourceSection, bodyNode);
rescueNodes.add(rescueNode);
rescueBody = rescueBody.getOptRescueNode();
}

rescueBody = rescueBody.getOptRescueNode();
}

RubyNode elsePart;
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ public class Options {
public final boolean EXCEPTIONS_PRINT_UNCAUGHT_JAVA = org.jruby.util.cli.Options.TRUFFLE_EXCEPTIONS_PRINT_UNCAUGHT_JAVA.load();
public final boolean BACKTRACES_HIDE_CORE_FILES = org.jruby.util.cli.Options.TRUFFLE_BACKTRACES_HIDE_CORE_FILES.load();
public final int BACKTRACES_LIMIT = org.jruby.util.cli.Options.TRUFFLE_BACKTRACES_LIMIT.load();
public final boolean BACKTRACES_OMIT_UNUSED = org.jruby.util.cli.Options.TRUFFLE_BACKTRACES_OMIT_UNUSED.load();
public final boolean INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC = org.jruby.util.cli.Options.TRUFFLE_INCLUDE_CORE_FILE_CALLERS_IN_SET_TRACE_FUNC.load();

// Call garph
20 changes: 17 additions & 3 deletions truffle/src/main/java/org/jruby/truffle/runtime/RubyCallStack.java
Original file line number Diff line number Diff line change
@@ -15,10 +15,13 @@
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.exceptions.DisablingBacktracesNode;
import org.jruby.truffle.runtime.backtrace.Activation;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.core.CoreSourceSection;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.runtime.methods.InternalMethod;

import java.util.ArrayList;
@@ -57,12 +60,23 @@ public static Backtrace getBacktrace(RubyContext context, Node currentNode) {
}

public static Backtrace getBacktrace(RubyContext context, Node currentNode, int omit) {
return getBacktrace(context, currentNode, omit, false);
return getBacktrace(context, currentNode, omit, null);
}

public static Backtrace getBacktrace(RubyContext context, Node currentNode, final int omit, final boolean filterNullSourceSection) {
public static Backtrace getBacktrace(RubyContext context, Node currentNode, int omit, DynamicObject exception) {
return getBacktrace(context, currentNode, omit, false, exception);
}

public static Backtrace getBacktrace(RubyContext context, Node currentNode, final int omit, final boolean filterNullSourceSection, DynamicObject exception) {
CompilerAsserts.neverPartOfCompilation();

if (exception != null
&& context.getOptions().BACKTRACES_OMIT_UNUSED
&& DisablingBacktracesNode.areBacktracesDisabled()
&& ModuleOperations.assignableTo(Layouts.BASIC_OBJECT.getLogicalClass(exception), context.getCoreLibrary().getStandardErrorClass())) {
return new Backtrace(new Activation[]{Activation.OMITTED_UNUSED});
}

final int limit = context.getOptions().BACKTRACES_LIMIT;

final ArrayList<Activation> activations = new ArrayList<>();
@@ -83,7 +97,7 @@ public static Backtrace getBacktrace(RubyContext context, Node currentNode, fina
@Override
public Object visitFrame(FrameInstance frameInstance) {
if (depth > limit) {
activations.add(Activation.OMITTED);
activations.add(Activation.OMITTED_LIMIT);
return new Object();
}

Original file line number Diff line number Diff line change
@@ -14,7 +14,8 @@

public class Activation {

public static final Activation OMITTED = new Activation(null, null);
public static final Activation OMITTED_LIMIT = new Activation(null, null);
public static final Activation OMITTED_UNUSED = new Activation(null, null);

private final Node callNode;
private final MaterializedFrame materializedFrame;
Original file line number Diff line number Diff line change
@@ -29,7 +29,8 @@

public class BacktraceFormatter {

public static final String OMITTED = "(omitted due to -Xtruffle.backtraces.limit)";
public static final String OMITTED_LIMIT = "(omitted due to -Xtruffle.backtraces.limit)";
public static final String OMITTED_UNUSED = "(omitted as the rescue expression was pure; use -Xtruffle.backtraces.omit_for_unused=false to disable)";

public enum FormattingFlags {
OMIT_FROM_PREFIX,
@@ -106,8 +107,12 @@ private String formatInLine(List<Activation> activations, DynamicObject exceptio

final Activation activation = activations.get(0);

if (activation == Activation.OMITTED) {
return "(omitted due to -Xtruffle.backtraces.limit)";
if (activation == Activation.OMITTED_LIMIT) {
return OMITTED_LIMIT;
}

if (activation == Activation.OMITTED_UNUSED) {
return OMITTED_UNUSED;
}

final SourceSection sourceSection = activation.getCallNode().getEncapsulatingSourceSection();
@@ -169,8 +174,12 @@ private String formatFromLine(List<Activation> activations, int n) {
public String formatLine(List<Activation> activations, int n) {
final Activation activation = activations.get(n);

if (activation == Activation.OMITTED) {
return OMITTED;
if (activation == Activation.OMITTED_LIMIT) {
return OMITTED_LIMIT;
}

if (activation == Activation.OMITTED_UNUSED) {
return OMITTED_UNUSED;
}

final SourceSection sourceSection = activation.getCallNode().getEncapsulatingSourceSection();