Skip to content

Commit

Permalink
Showing 2 changed files with 76 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -27,6 +27,9 @@
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.backtrace.Backtrace;
import org.jruby.truffle.runtime.backtrace.BacktraceFormatter;
import org.jruby.truffle.runtime.backtrace.BacktraceInterleaver;
import org.jruby.truffle.runtime.cext.CExtManager;
import org.jruby.truffle.runtime.cext.CExtSubsystem;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -38,6 +41,7 @@
import org.jruby.util.Memo;

import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@@ -538,4 +542,28 @@ public Object synchronize(VirtualFrame frame, DynamicObject self, DynamicObject
}
}

@CoreMethod(names = "print_interleaved_backtrace", onSingleton = true)
public abstract static class PrintInterleavedBacktraceNode extends CoreMethodNode {

public PrintInterleavedBacktraceNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@TruffleBoundary
@Specialization
public DynamicObject printInterleavedBacktrace() {
final List<String> rubyBacktrace = BacktraceFormatter.createDefaultFormatter(getContext())
.formatBacktrace(null, RubyCallStack.getBacktrace(this));

final StackTraceElement[] javaStacktrace = new Exception().getStackTrace();

for (String line : BacktraceInterleaver.interleave(rubyBacktrace, javaStacktrace)) {
System.err.println(line);
}

return nil();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2015 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.runtime.backtrace;

import java.util.ArrayList;
import java.util.List;

public class BacktraceInterleaver {

public static List<String> interleave(List<String> rubyBacktrace, StackTraceElement[] javaStacktrace) {
final List<String> interleaved = new ArrayList<>();

int javaIndex = 0;

for (String rubyLine : rubyBacktrace) {
if (javaIndex < javaStacktrace.length) {
interleaved.add(format(javaStacktrace[javaIndex]));
javaIndex++;

while (javaIndex < javaStacktrace.length && !isCallBoundary(javaStacktrace[javaIndex])) {
interleaved.add(format(javaStacktrace[javaIndex]));
javaIndex++;
}
}

interleaved.add(rubyLine);
}

return interleaved;
}

private static boolean isCallBoundary(StackTraceElement element) {
return element.toString().startsWith("com.oracle.graal.truffle.OptimizedCallTarget.callProxy")
|| element.toString().startsWith("com.oracle.truffle.api.impl.DefaultCallTarget.call");
}

private static String format(StackTraceElement element) {
return String.format("\t\t%s", element);
}

}

0 comments on commit 5af8ba0

Please sign in to comment.