Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread::Backtrace::Location#label for top-level blocks includes filename instead of <main> #5166

Open
ivoanjo opened this issue May 10, 2018 · 3 comments

Comments

@ivoanjo
Copy link
Contributor

ivoanjo commented May 10, 2018

Hello again!

I'm using Thread#backtrace_locations and noticed several differences between MRI and JRuby.

I'll report them separately because they may have different fixes, but feel free to mark any as duplicate if it makes sense to do so.


Environment

  • JRuby: jruby 9.1.17.0 (2.3.3) 2018-04-20 d8b1ff9 Java HotSpot(TM) 64-Bit Server VM 25.171-b11 on 1.8.0_171-b11 +jit [linux-x86_64]
  • Kernel: Linux u186024434db159d25c92 4.13.0-39-generic #44~16.04.1-Ubuntu SMP Thu Apr 5 16:43:10 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
  • Distro: Ubuntu 16.04.4 LTS

Expected Behavior

(Last one, I promise!)

When looking at a Thread::Backtrace::Location, for a top-level block, MRI returns block in <main>.

Testcase:

puts RUBY_DESCRIPTION

location = Thread.current.backtrace_locations[1]
puts "Top level: #label '#{location.label}'"

[:dummy].map do
  location = Thread.current.backtrace_locations[1]
  puts "Inside block: #label '#{location.label}'"
end

Output on MRI:

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
Top level: #label '<main>'
Inside block: #label 'block in <main>'

Actual Behavior

JRuby returns block in <filename> for the same testcase:

jruby 9.1.17.0 (2.3.3) 2018-04-20 d8b1ff9 Java HotSpot(TM) 64-Bit Server VM 25.171-b11 on 1.8.0_171-b11 +jit [linux-x86_64]
Top level: #label '<main>'
Inside block: #label 'block in testcase0.rb'

If it would be helpful I can also submit a testcase to RubySpec.

@headius
Copy link
Member

headius commented Aug 7, 2019

+1 testcase. Not sure I'll get to this for 9.2.8 but I'll look at it along with #5165.

@headius
Copy link
Member

headius commented Aug 10, 2019

Appears to only happen in the JIT:

[] ~/projects/jruby $ jruby -X-C testcase0.rb
jruby 9.2.8.0-SNAPSHOT (2.5.3) 2019-08-10 ec268a9 OpenJDK 64-Bit Server VM 11.0.2+9 on 11.0.2+9 +jit [darwin-x86_64]
Top level: #label '<main>'
Inside block: #label 'block in <main>'

[] ~/projects/jruby $ jruby testcase0.rb
jruby 9.2.8.0-SNAPSHOT (2.5.3) 2019-08-10 ec268a9 OpenJDK 64-Bit Server VM 11.0.2+9 on 11.0.2+9 +jit [darwin-x86_64]
Top level: #label '<main>'
Inside block: #label 'block in testcase0.rb'

@headius
Copy link
Member

headius commented Aug 10, 2019

Ok, I found a trivial fix for this, by encoding "<main>" as the block's method name rather than whatever we have in the IRClosure (the filename in this case):

diff --git a/core/src/main/java/org/jruby/util/JavaNameMangler.java b/core/src/main/java/org/jruby/util/JavaNameMangler.java
index daa2c2bc97..fab7f35eb2 100644
--- a/core/src/main/java/org/jruby/util/JavaNameMangler.java
+++ b/core/src/main/java/org/jruby/util/JavaNameMangler.java
@@ -286,7 +286,11 @@ public class JavaNameMangler {
             return "RUBY$method$" + mangleMethodNameInternal(scope.getId());
         }
         if (scope instanceof IRClosure) {
-            return "RUBY$block$" + mangleMethodNameInternal(scope.getNearestTopLocalVariableScope().getId());
+            if (scope.getNearestTopLocalVariableScope() instanceof IRScriptBody) {
+                return "RUBY$block$" + mangleMethodNameInternal("<main>");
+            } else {
+                return "RUBY$block$" + mangleMethodNameInternal(scope.getNearestTopLocalVariableScope().getId());
+            }
         }
         if (scope instanceof IRMetaClassBody) {
             return "RUBY$metaclass";

However I realized that MRI does not always use "<main>" for the top-level scope; in a loaded or required file, it uses "<top (required)>" or similar, which would require some clever handling to support.

I will punt this to 9.2.9 to think on it more. The tricky bit for us is that in general, we don't have access to the original code at each level when generating a stack trace, so any information we want to convey needs to be encoded into the Backtrace object or the Java method name. The latter requirement makes it challenging to support AOT-compiled code, since it would not reflect whether it was run directly ("<main>") or required ("<top (required)>").

@headius headius modified the milestones: JRuby 9.2.8.0, JRuby 9.2.9.0 Aug 10, 2019
ivoanjo added a commit to ivoanjo/spec that referenced this issue Aug 13, 2019
eregon pushed a commit to ruby/spec that referenced this issue Aug 22, 2019
@enebo enebo modified the milestones: JRuby 9.2.9.0, JRuby 9.2.10.0 Oct 21, 2019
@headius headius modified the milestones: JRuby 9.2.10.0, JRuby 9.3.0.0 Feb 14, 2020
@headius headius removed this from the JRuby 9.3.0.0 milestone Jul 1, 2021
@headius headius added this to the JRuby 9.3.1.0 milestone Jul 1, 2021
@headius headius removed this from the JRuby 9.3.1.0 milestone Oct 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants