backtracie 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +4 -0
- data/README.adoc +102 -2
- data/backtracie.gemspec +8 -2
- data/ext/backtracie_native_extension/backtracie.c +264 -78
- data/ext/backtracie_native_extension/extconf.rb +44 -0
- data/ext/backtracie_native_extension/ruby_shards.c +585 -0
- data/ext/backtracie_native_extension/ruby_shards.h +175 -0
- data/lib/backtracie/location.rb +12 -1
- data/lib/backtracie/version.rb +1 -1
- metadata +8 -16
- data/.gitignore +0 -33
- data/.rspec +0 -2
- data/.ruby-version +0 -1
- data/.standard.yml +0 -14
- data/DEVELOPMENT_NOTES.adoc +0 -399
- data/Rakefile +0 -29
- data/bin/console +0 -8
- data/bin/setup +0 -8
- data/ext/backtracie_native_extension/ruby_3.0.0.c +0 -196
- data/ext/backtracie_native_extension/ruby_3.0.0.h +0 -7
- data/gems.rb +0 -15
@@ -0,0 +1,175 @@
|
|
1
|
+
// backtracie: Ruby gem for beautiful backtraces
|
2
|
+
// Copyright (C) 2021 Ivo Anjo <ivo@ivoanjo.me>
|
3
|
+
//
|
4
|
+
// This file is part of backtracie.
|
5
|
+
//
|
6
|
+
// backtracie is free software: you can redistribute it and/or modify
|
7
|
+
// it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
// the Free Software Foundation, either version 3 of the License, or
|
9
|
+
// (at your option) any later version.
|
10
|
+
//
|
11
|
+
// backtracie is distributed in the hope that it will be useful,
|
12
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
// GNU Lesser General Public License for more details.
|
15
|
+
//
|
16
|
+
// You should have received a copy of the GNU Lesser General Public License
|
17
|
+
// along with backtracie. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
// -----------------------------------------------------------------------------
|
20
|
+
// The file below has modified versions of code extracted from the Ruby project.
|
21
|
+
// The Ruby project copyright and license follow:
|
22
|
+
// -----------------------------------------------------------------------------
|
23
|
+
|
24
|
+
// Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
25
|
+
// You can redistribute it and/or modify it under either the terms of the
|
26
|
+
// 2-clause BSDL (see the file BSDL), or the conditions below:
|
27
|
+
|
28
|
+
// 1. You may make and give away verbatim copies of the source form of the
|
29
|
+
// software without restriction, provided that you duplicate all of the
|
30
|
+
// original copyright notices and associated disclaimers.
|
31
|
+
|
32
|
+
// 2. You may modify your copy of the software in any way, provided that
|
33
|
+
// you do at least ONE of the following:
|
34
|
+
|
35
|
+
// a. place your modifications in the Public Domain or otherwise
|
36
|
+
// make them Freely Available, such as by posting said
|
37
|
+
// modifications to Usenet or an equivalent medium, or by allowing
|
38
|
+
// the author to include your modifications in the software.
|
39
|
+
|
40
|
+
// b. use the modified software only within your corporation or
|
41
|
+
// organization.
|
42
|
+
|
43
|
+
// c. give non-standard binaries non-standard names, with
|
44
|
+
// instructions on where to get the original software distribution.
|
45
|
+
|
46
|
+
// d. make other distribution arrangements with the author.
|
47
|
+
|
48
|
+
// 3. You may distribute the software in object code or binary form,
|
49
|
+
// provided that you do at least ONE of the following:
|
50
|
+
|
51
|
+
// a. distribute the binaries and library files of the software,
|
52
|
+
// together with instructions (in the manual page or equivalent)
|
53
|
+
// on where to get the original distribution.
|
54
|
+
|
55
|
+
// b. accompany the distribution with the machine-readable source of
|
56
|
+
// the software.
|
57
|
+
|
58
|
+
// c. give non-standard binaries non-standard names, with
|
59
|
+
// instructions on where to get the original software distribution.
|
60
|
+
|
61
|
+
// d. make other distribution arrangements with the author.
|
62
|
+
|
63
|
+
// 4. You may modify and include the part of the software into any other
|
64
|
+
// software (possibly commercial). But some files in the distribution
|
65
|
+
// are not written by the author, so that they are not under these terms.
|
66
|
+
|
67
|
+
// For the list of those files and their copying conditions, see the
|
68
|
+
// file LEGAL.
|
69
|
+
|
70
|
+
// 5. The scripts and library files supplied as input to or produced as
|
71
|
+
// output from the software do not automatically fall under the
|
72
|
+
// copyright of the software, but belong to whomever generated them,
|
73
|
+
// and may be sold commercially, and may be aggregated with this
|
74
|
+
// software.
|
75
|
+
|
76
|
+
// 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
77
|
+
// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
78
|
+
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
79
|
+
// PURPOSE.
|
80
|
+
|
81
|
+
#ifndef RUBY_SHARDS_H
|
82
|
+
#define RUBY_SHARDS_H
|
83
|
+
|
84
|
+
// -----------------------------------------------------------------------------
|
85
|
+
|
86
|
+
/**********************************************************************
|
87
|
+
method.h -
|
88
|
+
created at: Wed Jul 15 20:02:33 2009
|
89
|
+
Copyright (C) 2009 Koichi Sasada
|
90
|
+
**********************************************************************/
|
91
|
+
|
92
|
+
#ifndef RUBY_MJIT_HEADER_INCLUDED
|
93
|
+
typedef enum {
|
94
|
+
VM_METHOD_TYPE_ISEQ, /*!< Ruby method */
|
95
|
+
VM_METHOD_TYPE_CFUNC, /*!< C method */
|
96
|
+
VM_METHOD_TYPE_ATTRSET, /*!< attr_writer or attr_accessor */
|
97
|
+
VM_METHOD_TYPE_IVAR, /*!< attr_reader or attr_accessor */
|
98
|
+
VM_METHOD_TYPE_BMETHOD,
|
99
|
+
VM_METHOD_TYPE_ZSUPER,
|
100
|
+
VM_METHOD_TYPE_ALIAS,
|
101
|
+
VM_METHOD_TYPE_UNDEF,
|
102
|
+
VM_METHOD_TYPE_NOTIMPLEMENTED,
|
103
|
+
VM_METHOD_TYPE_OPTIMIZED, /*!< Kernel#send, Proc#call, etc */
|
104
|
+
VM_METHOD_TYPE_MISSING, /*!< wrapper for method_missing(id) */
|
105
|
+
VM_METHOD_TYPE_REFINED, /*!< refinement */
|
106
|
+
} rb_method_type_t;
|
107
|
+
#define VM_METHOD_TYPE_MINIMUM_BITS 4
|
108
|
+
|
109
|
+
// Needed for Ruby 2.6 as this is not defined on any public header
|
110
|
+
void rb_hash_bulk_insert(long, const VALUE *, VALUE);
|
111
|
+
#endif
|
112
|
+
|
113
|
+
// -----------------------------------------------------------------------------
|
114
|
+
|
115
|
+
typedef struct {
|
116
|
+
unsigned int is_ruby_frame : 1; // 1 -> ruby frame / 0 -> cfunc frame
|
117
|
+
|
118
|
+
// for ruby frames where the callable_method_entry is not of type VM_METHOD_TYPE_ISEQ, most of the metadata we
|
119
|
+
// want can be found by querying the iseq, and there may not even be an callable_method_entry
|
120
|
+
unsigned int should_use_iseq : 1;
|
121
|
+
unsigned int should_use_cfunc_name : 1;
|
122
|
+
|
123
|
+
rb_method_type_t vm_method_type : VM_METHOD_TYPE_MINIMUM_BITS;
|
124
|
+
int line_number;
|
125
|
+
VALUE iseq;
|
126
|
+
VALUE callable_method_entry;
|
127
|
+
VALUE self;
|
128
|
+
VALUE cfunc_name;
|
129
|
+
} raw_location;
|
130
|
+
|
131
|
+
#ifndef PRE_MJIT_RUBY
|
132
|
+
int backtracie_rb_profile_frames(int limit, raw_location *raw_locations);
|
133
|
+
int backtracie_rb_profile_frames_for_thread(VALUE thread, int limit, raw_location *raw_locations);
|
134
|
+
#endif
|
135
|
+
VALUE backtracie_called_id(raw_location *the_location);
|
136
|
+
VALUE backtracie_defined_class(raw_location *the_location);
|
137
|
+
VALUE backtracie_rb_vm_top_self();
|
138
|
+
bool backtracie_iseq_is_block(raw_location *the_location);
|
139
|
+
bool backtracie_iseq_is_eval(raw_location *the_location);
|
140
|
+
VALUE backtracie_refinement_name(raw_location *the_location);
|
141
|
+
|
142
|
+
#ifdef PRE_MJIT_RUBY
|
143
|
+
int backtracie_profile_frames_from_ruby_locations(VALUE ruby_locations_array, raw_location *raw_locations);
|
144
|
+
#endif
|
145
|
+
|
146
|
+
// -----------------------------------------------------------------------------
|
147
|
+
|
148
|
+
// Ruby 3.0 finally added support for showing "cfunc frames" (frames for methods written in C) in stack traces:
|
149
|
+
// https://github.com/ruby/ruby/pull/3299/files
|
150
|
+
//
|
151
|
+
// The diff is rather trivial, and it makes a world of difference, given how most of Ruby's core classes are written in C.
|
152
|
+
// Thus, the methods below are copied from that PR so that we can make use of this functionality on older Ruby versions.
|
153
|
+
#ifdef CFUNC_FRAMES_BACKPORT_NEEDED
|
154
|
+
#define backtracie_rb_profile_frame_method_name backported_rb_profile_frame_method_name
|
155
|
+
|
156
|
+
VALUE backported_rb_profile_frame_method_name(VALUE frame);
|
157
|
+
#else // Ruby > 3.0, just use the stock functionality
|
158
|
+
#define backtracie_rb_profile_frame_method_name rb_profile_frame_method_name
|
159
|
+
#endif
|
160
|
+
|
161
|
+
// Backport https://github.com/ruby/ruby/pull/3084 (present in 2.7 and 3.0) to Ruby 2.6
|
162
|
+
// The interesting bit is actually the fix to rb_profile_frame_classpath BUT since rb_profile_frame_qualified_method_name
|
163
|
+
// internally relies on rb_profile_frame_classpath we also need to add a copy of that one as well.
|
164
|
+
#ifdef CLASSPATH_BACKPORT_NEEDED
|
165
|
+
#define backtracie_rb_profile_frame_classpath backported_rb_profile_frame_classpath
|
166
|
+
#define backtracie_rb_profile_frame_qualified_method_name backported_rb_profile_frame_qualified_method_name
|
167
|
+
|
168
|
+
VALUE backported_rb_profile_frame_classpath(VALUE frame);
|
169
|
+
VALUE backported_rb_profile_frame_qualified_method_name(VALUE frame);
|
170
|
+
#else
|
171
|
+
#define backtracie_rb_profile_frame_classpath rb_profile_frame_classpath
|
172
|
+
#define backtracie_rb_profile_frame_qualified_method_name rb_profile_frame_qualified_method_name
|
173
|
+
#endif
|
174
|
+
|
175
|
+
#endif
|
data/lib/backtracie/location.rb
CHANGED
@@ -26,15 +26,17 @@ module Backtracie
|
|
26
26
|
attr_accessor :label
|
27
27
|
attr_accessor :lineno
|
28
28
|
attr_accessor :path
|
29
|
+
attr_accessor :qualified_method_name
|
29
30
|
|
30
31
|
# Note: The order of arguments is hardcoded in the native extension in the `new_location` function --
|
31
32
|
# keep them in sync
|
32
|
-
def initialize(absolute_path, base_label, label, lineno, path, debug)
|
33
|
+
def initialize(absolute_path, base_label, label, lineno, path, qualified_method_name, debug)
|
33
34
|
@absolute_path = absolute_path
|
34
35
|
@base_label = base_label
|
35
36
|
@label = label
|
36
37
|
@lineno = lineno
|
37
38
|
@path = path
|
39
|
+
@qualified_method_name = qualified_method_name
|
38
40
|
@debug = debug
|
39
41
|
|
40
42
|
freeze
|
@@ -47,5 +49,14 @@ module Backtracie
|
|
47
49
|
"#{@path}:in `#{@label}'"
|
48
50
|
end
|
49
51
|
end
|
52
|
+
|
53
|
+
# Still WIP
|
54
|
+
def fancy_to_s
|
55
|
+
if @lineno != 0
|
56
|
+
"#{@path}:#{@lineno}:in #{@qualified_method_name}"
|
57
|
+
else
|
58
|
+
"#{@path}:in #{@qualified_method_name}"
|
59
|
+
end
|
60
|
+
end
|
50
61
|
end
|
51
62
|
end
|
data/lib/backtracie/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backtracie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivo Anjo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby gem for beautiful backtraces
|
14
14
|
email:
|
15
15
|
- ivo@ivoanjo.me
|
16
16
|
executables: []
|
17
|
-
extensions:
|
17
|
+
extensions:
|
18
|
+
- ext/backtracie_native_extension/extconf.rb
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
21
|
- ".editorconfig"
|
21
|
-
- ".gitignore"
|
22
|
-
- ".rspec"
|
23
|
-
- ".ruby-version"
|
24
|
-
- ".standard.yml"
|
25
22
|
- CODE_OF_CONDUCT.adoc
|
26
23
|
- COPYING
|
27
24
|
- COPYING.LESSER
|
28
|
-
- DEVELOPMENT_NOTES.adoc
|
29
25
|
- README.adoc
|
30
|
-
- Rakefile
|
31
26
|
- backtracie.gemspec
|
32
|
-
- bin/console
|
33
|
-
- bin/setup
|
34
27
|
- ext/backtracie_native_extension/backtracie.c
|
35
28
|
- ext/backtracie_native_extension/extconf.rb
|
36
|
-
- ext/backtracie_native_extension/
|
37
|
-
- ext/backtracie_native_extension/
|
38
|
-
- gems.rb
|
29
|
+
- ext/backtracie_native_extension/ruby_shards.c
|
30
|
+
- ext/backtracie_native_extension/ruby_shards.h
|
39
31
|
- lib/backtracie.rb
|
40
32
|
- lib/backtracie/location.rb
|
41
33
|
- lib/backtracie/version.rb
|
@@ -52,14 +44,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
44
|
requirements:
|
53
45
|
- - ">="
|
54
46
|
- !ruby/object:Gem::Version
|
55
|
-
version: 3.0
|
47
|
+
version: 2.3.0
|
56
48
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
49
|
requirements:
|
58
50
|
- - ">="
|
59
51
|
- !ruby/object:Gem::Version
|
60
52
|
version: '0'
|
61
53
|
requirements: []
|
62
|
-
rubygems_version: 3.
|
54
|
+
rubygems_version: 3.1.4
|
63
55
|
signing_key:
|
64
56
|
specification_version: 4
|
65
57
|
summary: Ruby gem for beautiful backtraces
|
data/.gitignore
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
*.gem
|
2
|
-
*.rbc
|
3
|
-
/.config
|
4
|
-
/coverage/
|
5
|
-
/InstalledFiles
|
6
|
-
/pkg/
|
7
|
-
/spec/reports/
|
8
|
-
/spec/examples.txt
|
9
|
-
/test/tmp/
|
10
|
-
/test/version_tmp/
|
11
|
-
/tmp/
|
12
|
-
|
13
|
-
# Used by dotenv library to load environment variables.
|
14
|
-
# .env
|
15
|
-
|
16
|
-
## Documentation cache and generated files:
|
17
|
-
/.yardoc/
|
18
|
-
/_yardoc/
|
19
|
-
/doc/
|
20
|
-
/rdoc/
|
21
|
-
|
22
|
-
## Environment normalization:
|
23
|
-
/.bundle/
|
24
|
-
/vendor/bundle
|
25
|
-
/lib/bundler/man/
|
26
|
-
|
27
|
-
gems.locked
|
28
|
-
Gemfile.lock
|
29
|
-
|
30
|
-
*.o
|
31
|
-
*.so
|
32
|
-
ext/**/extconf.h
|
33
|
-
ext/**/Makefile
|
data/.rspec
DELETED
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby-3.0.0
|
data/.standard.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Currently we only support >= 3.0.0 but I suspect we'll be able to support as far back as the Ruby version that
|
2
|
-
# introduced mjit without a lot of trouble, so let's avoid making the code dependent on 3.0-only features
|
3
|
-
ruby_version: 2.6
|
4
|
-
|
5
|
-
ignore:
|
6
|
-
- 'spec/unit/interesting_backtrace_helper.rb': # let's just say this file is special
|
7
|
-
- Lint/UselessTimes
|
8
|
-
- Style/EvalWithLocation
|
9
|
-
- Style/GlobalVars
|
10
|
-
- Style/MissingRespondToMissing
|
11
|
-
- 'ext/backtracie_native_extension/extconf.rb':
|
12
|
-
- Style/GlobalVars
|
13
|
-
- 'spec/unit/backtracie_spec.rb':
|
14
|
-
- Style/EvalWithLocation
|
data/DEVELOPMENT_NOTES.adoc
DELETED
@@ -1,399 +0,0 @@
|
|
1
|
-
= Development Notes
|
2
|
-
|
3
|
-
== Ideas to explore
|
4
|
-
|
5
|
-
=== Understand why `rb_profile_frames` does not return the correct iseq for a block.
|
6
|
-
|
7
|
-
Given
|
8
|
-
|
9
|
-
[source,ruby]
|
10
|
-
----
|
11
|
-
def run
|
12
|
-
puts "Backtracie: " + Backtracie.caller_locations.first.label
|
13
|
-
puts "Ruby: " + caller_locations.first.label
|
14
|
-
end
|
15
|
-
|
16
|
-
def run2
|
17
|
-
1.times do
|
18
|
-
run
|
19
|
-
end
|
20
|
-
end
|
21
|
-
----
|
22
|
-
|
23
|
-
the output is
|
24
|
-
|
25
|
-
----
|
26
|
-
Backtracie: run2
|
27
|
-
Ruby: block in run2
|
28
|
-
----
|
29
|
-
|
30
|
-
this is because inside `rb_profile_frames` the code goes
|
31
|
-
|
32
|
-
[source,c]
|
33
|
-
----
|
34
|
-
/* record frame info */
|
35
|
-
cme = rb_vm_frame_method_entry(cfp);
|
36
|
-
if (cme && cme->def->type == VM_METHOD_TYPE_ISEQ) {
|
37
|
-
buff[i] = (VALUE)cme;
|
38
|
-
}
|
39
|
-
else {
|
40
|
-
buff[i] = (VALUE)cfp->iseq;
|
41
|
-
}
|
42
|
-
----
|
43
|
-
|
44
|
-
and in this case the first branch is taken (we get the `cme`, not the `cfp->iseq`). I have no idea why.
|
45
|
-
|
46
|
-
==== Update:
|
47
|
-
|
48
|
-
When using the `cfp->iseq` instead of the `cme`, in many cases, the `full_label`, `classpath`, `qualified_method_name`, `singleton_method_p` and `first_lineno` become less accurate.
|
49
|
-
|
50
|
-
Why "less accurate"? Consider the following slightly compacted diff taken with backtracie and either `cme` or `cfp->iseq usage`, using the `interesting_backtrace_helper.rb`, looking at the output in the debug fields for the `Backtracie::Location` instances:
|
51
|
-
|
52
|
-
[source, diff]
|
53
|
-
----
|
54
|
-
--- cfp->iseq
|
55
|
-
+++ cme
|
56
|
-
@@ -6,16 +6,16 @@
|
57
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
58
|
-
"hello",
|
59
|
-
"hello",
|
60
|
-
- "ClassA#hello",
|
61
|
-
+ "hello",
|
62
|
-
18,
|
63
|
-
- "ClassA",
|
64
|
-
+ nil,
|
65
|
-
false,
|
66
|
-
"hello",
|
67
|
-
- "ClassA#hello"],
|
68
|
-
+ "hello"],
|
69
|
-
@@ -23,16 +23,16 @@
|
70
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
71
|
-
"hello",
|
72
|
-
"hello",
|
73
|
-
- "ModuleB::ClassB#hello",
|
74
|
-
+ "hello",
|
75
|
-
27,
|
76
|
-
- "ModuleB::ClassB",
|
77
|
-
+ nil,
|
78
|
-
false,
|
79
|
-
"hello",
|
80
|
-
- "ModuleB::ClassB#hello"],
|
81
|
-
+ "hello"],
|
82
|
-
@@ -40,16 +40,16 @@
|
83
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
84
|
-
"hello",
|
85
|
-
"hello",
|
86
|
-
- "ModuleC.hello",
|
87
|
-
+ "hello",
|
88
|
-
34,
|
89
|
-
- "ModuleC",
|
90
|
-
- true,
|
91
|
-
+ nil,
|
92
|
-
+ false,
|
93
|
-
"hello",
|
94
|
-
- "ModuleC.hello"],
|
95
|
-
+ "hello"],
|
96
|
-
@@ -57,16 +57,16 @@
|
97
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
98
|
-
"hello",
|
99
|
-
"hello",
|
100
|
-
- "ClassWithStaticMethod.hello",
|
101
|
-
+ "hello",
|
102
|
-
40,
|
103
|
-
- "ClassWithStaticMethod",
|
104
|
-
- true,
|
105
|
-
+ nil,
|
106
|
-
+ false,
|
107
|
-
"hello",
|
108
|
-
- "ClassWithStaticMethod.hello"],
|
109
|
-
+ "hello"],
|
110
|
-
@@ -74,16 +74,16 @@
|
111
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
112
|
-
"hello",
|
113
|
-
"hello",
|
114
|
-
- "ModuleD#hello",
|
115
|
-
+ "hello",
|
116
|
-
46,
|
117
|
-
- "ModuleD",
|
118
|
-
+ nil,
|
119
|
-
false,
|
120
|
-
"hello",
|
121
|
-
- "ModuleD#hello"],
|
122
|
-
+ "hello"],
|
123
|
-
@@ -125,16 +125,16 @@
|
124
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
125
|
-
"hello",
|
126
|
-
"hello",
|
127
|
-
- "#<ClassD:0x0000556485af28e8>.hello",
|
128
|
-
+ "hello",
|
129
|
-
63,
|
130
|
-
- "#<ClassD:0x0000556485af28e8>",
|
131
|
-
- true,
|
132
|
-
+ nil,
|
133
|
-
+ false,
|
134
|
-
"hello",
|
135
|
-
- "#<ClassD:0x0000556485af28e8>.hello"],
|
136
|
-
+ "hello"],
|
137
|
-
@@ -142,16 +142,16 @@
|
138
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
139
|
-
"hello",
|
140
|
-
"hello",
|
141
|
-
- "ClassE#hello",
|
142
|
-
+ "hello",
|
143
|
-
68,
|
144
|
-
- "ClassE",
|
145
|
-
+ nil,
|
146
|
-
false,
|
147
|
-
"hello",
|
148
|
-
- "ClassE#hello"],
|
149
|
-
+ "hello"],
|
150
|
-
@@ -176,16 +176,16 @@
|
151
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
152
|
-
"hello",
|
153
|
-
"hello",
|
154
|
-
- "#<Module:0x0000556485af2140>#hello",
|
155
|
-
+ "hello",
|
156
|
-
82,
|
157
|
-
- "#<Module:0x0000556485af2140>",
|
158
|
-
+ nil,
|
159
|
-
false,
|
160
|
-
"hello",
|
161
|
-
- "#<Module:0x0000556485af2140>#hello"],
|
162
|
-
+ "hello"],
|
163
|
-
@@ -193,16 +193,16 @@
|
164
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
165
|
-
"hello",
|
166
|
-
"hello",
|
167
|
-
- "ModuleE.hello",
|
168
|
-
+ "hello",
|
169
|
-
92,
|
170
|
-
- "ModuleE",
|
171
|
-
- true,
|
172
|
-
+ nil,
|
173
|
-
+ false,
|
174
|
-
"hello",
|
175
|
-
- "ModuleE.hello"],
|
176
|
-
+ "hello"],
|
177
|
-
@@ -210,33 +210,33 @@
|
178
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
179
|
-
"method_missing",
|
180
|
-
"method_missing",
|
181
|
-
- "ClassH#method_missing",
|
182
|
-
+ "method_missing",
|
183
|
-
98,
|
184
|
-
- "ClassH",
|
185
|
-
+ nil,
|
186
|
-
false,
|
187
|
-
"method_missing",
|
188
|
-
- "ClassH#method_missing"],
|
189
|
-
+ "method_missing"],
|
190
|
-
@label="method_missing",
|
191
|
-
@lineno=101,
|
192
|
-
@path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb">,
|
193
|
-
- #<Backtracie::Location:0x0000556486191a00
|
194
|
-
+ #<Backtracie::Location:0x0000563ca3800df0
|
195
|
-
@absolute_path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
196
|
-
@base_label="hello",
|
197
|
-
@debug=
|
198
|
-
["/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
199
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
200
|
-
+ "block in hello",
|
201
|
-
"hello",
|
202
|
-
- "hello",
|
203
|
-
- "ClassF#hello",
|
204
|
-
- 106,
|
205
|
-
- "ClassF",
|
206
|
-
+ "block in hello",
|
207
|
-
+ 107,
|
208
|
-
+ nil,
|
209
|
-
false,
|
210
|
-
"hello",
|
211
|
-
- "ClassF#hello"],
|
212
|
-
- @label="hello",
|
213
|
-
+ "hello"],
|
214
|
-
+ @label="block in hello",
|
215
|
-
@@ -252,16 +252,16 @@
|
216
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
217
|
-
"hello",
|
218
|
-
"hello",
|
219
|
-
- "ClassF#hello",
|
220
|
-
+ "hello",
|
221
|
-
106,
|
222
|
-
- "ClassF",
|
223
|
-
+ nil,
|
224
|
-
false,
|
225
|
-
"hello",
|
226
|
-
- "ClassF#hello"],
|
227
|
-
+ "hello"],
|
228
|
-
@@ -286,16 +286,16 @@
|
229
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
230
|
-
"hello",
|
231
|
-
"hello",
|
232
|
-
- "#<Class:0x0000556485af0a70>.hello",
|
233
|
-
+ "hello",
|
234
|
-
121,
|
235
|
-
- "#<Class:0x0000556485af0a70>",
|
236
|
-
- true,
|
237
|
-
+ nil,
|
238
|
-
+ false,
|
239
|
-
"hello",
|
240
|
-
- "#<Class:0x0000556485af0a70>.hello"],
|
241
|
-
+ "hello"],
|
242
|
-
@@ -303,16 +303,16 @@
|
243
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
244
|
-
"hello",
|
245
|
-
"hello",
|
246
|
-
- "#<Class:0x0000556485af07a0>#hello",
|
247
|
-
+ "hello",
|
248
|
-
126,
|
249
|
-
- "#<Class:0x0000556485af07a0>",
|
250
|
-
+ nil,
|
251
|
-
false,
|
252
|
-
"hello",
|
253
|
-
- "#<Class:0x0000556485af07a0>#hello"],
|
254
|
-
+ "hello"],
|
255
|
-
@@ -320,16 +320,16 @@
|
256
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
257
|
-
"hello",
|
258
|
-
"hello",
|
259
|
-
- "#<Module:0x0000556485af0430>.hello",
|
260
|
-
+ "hello",
|
261
|
-
132,
|
262
|
-
- "#<Module:0x0000556485af0430>",
|
263
|
-
- true,
|
264
|
-
+ nil,
|
265
|
-
+ false,
|
266
|
-
"hello",
|
267
|
-
- "#<Module:0x0000556485af0430>.hello"],
|
268
|
-
+ "hello"],
|
269
|
-
@@ -337,33 +337,33 @@
|
270
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
271
|
-
"method_with_complex_parameters",
|
272
|
-
"method_with_complex_parameters",
|
273
|
-
- "Object#method_with_complex_parameters",
|
274
|
-
+ "method_with_complex_parameters",
|
275
|
-
137,
|
276
|
-
- "Object",
|
277
|
-
+ nil,
|
278
|
-
false,
|
279
|
-
"method_with_complex_parameters",
|
280
|
-
- "Object#method_with_complex_parameters"],
|
281
|
-
+ "method_with_complex_parameters"],
|
282
|
-
@label="method_with_complex_parameters",
|
283
|
-
@lineno=138,
|
284
|
-
@path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb">,
|
285
|
-
- #<Backtracie::Location:0x00005564861925e0
|
286
|
-
+ #<Backtracie::Location:0x0000563ca3801d90
|
287
|
-
@absolute_path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
288
|
-
@base_label="hello",
|
289
|
-
@debug=
|
290
|
-
["/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
291
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
292
|
-
+ "block (2 levels) in hello",
|
293
|
-
"hello",
|
294
|
-
- "hello",
|
295
|
-
- "ClassJ#hello",
|
296
|
-
- 146,
|
297
|
-
- "ClassJ",
|
298
|
-
+ "block (2 levels) in hello",
|
299
|
-
+ 148,
|
300
|
-
+ nil,
|
301
|
-
false,
|
302
|
-
"hello",
|
303
|
-
- "ClassJ#hello"],
|
304
|
-
- @label="hello",
|
305
|
-
+ "hello"],
|
306
|
-
@@ -371,33 +371,33 @@
|
307
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
308
|
-
"hello_helper",
|
309
|
-
"hello_helper",
|
310
|
-
- "ClassJ#hello_helper",
|
311
|
-
+ "hello_helper",
|
312
|
-
142,
|
313
|
-
- "ClassJ",
|
314
|
-
+ nil,
|
315
|
-
false,
|
316
|
-
"hello_helper",
|
317
|
-
- "ClassJ#hello_helper"],
|
318
|
-
+ "hello_helper"],
|
319
|
-
@label="hello_helper",
|
320
|
-
@lineno=143,
|
321
|
-
@path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb">,
|
322
|
-
- #<Backtracie::Location:0x0000556486192928
|
323
|
-
+ #<Backtracie::Location:0x0000563ca3801f70
|
324
|
-
@absolute_path="/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
325
|
-
@base_label="hello",
|
326
|
-
@debug=
|
327
|
-
["/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
328
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
329
|
-
+ "block in hello",
|
330
|
-
"hello",
|
331
|
-
- "hello",
|
332
|
-
- "ClassJ#hello",
|
333
|
-
- 146,
|
334
|
-
- "ClassJ",
|
335
|
-
+ "block in hello",
|
336
|
-
+ 147,
|
337
|
-
+ nil,
|
338
|
-
false,
|
339
|
-
"hello",
|
340
|
-
- "ClassJ#hello"],
|
341
|
-
- @label="hello",
|
342
|
-
+ "hello"],
|
343
|
-
@@ -405,16 +405,16 @@
|
344
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
345
|
-
"hello_helper",
|
346
|
-
"hello_helper",
|
347
|
-
- "ClassJ#hello_helper",
|
348
|
-
+ "hello_helper",
|
349
|
-
142,
|
350
|
-
- "ClassJ",
|
351
|
-
+ nil,
|
352
|
-
false,
|
353
|
-
"hello_helper",
|
354
|
-
- "ClassJ#hello_helper"],
|
355
|
-
+ "hello_helper"],
|
356
|
-
@@ -422,16 +422,16 @@
|
357
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
358
|
-
"hello",
|
359
|
-
"hello",
|
360
|
-
- "ClassJ#hello",
|
361
|
-
+ "hello",
|
362
|
-
146,
|
363
|
-
- "ClassJ",
|
364
|
-
+ nil,
|
365
|
-
false,
|
366
|
-
"hello",
|
367
|
-
- "ClassJ#hello"],
|
368
|
-
+ "hello"],
|
369
|
-
@@ -439,16 +439,16 @@
|
370
|
-
"/ruby/backtracie/spec/unit/interesting_backtrace_helper.rb",
|
371
|
-
"top_level_hello",
|
372
|
-
"top_level_hello",
|
373
|
-
- "Object#top_level_hello",
|
374
|
-
+ "top_level_hello",
|
375
|
-
155,
|
376
|
-
- "Object",
|
377
|
-
+ nil,
|
378
|
-
false,
|
379
|
-
"top_level_hello",
|
380
|
-
- "Object#top_level_hello"],
|
381
|
-
+ "top_level_hello"],
|
382
|
-
----
|
383
|
-
|
384
|
-
We can see that we miss the information about module/class names (we only get methods), we lose the singleton info, etc. The `first_lineno` numbers that move (which is not very important since we get the exact line via a different method). The only thing that is correct in the `cfp->iseq` version is getting "block in method" in the few places where we were missing it.
|
385
|
-
|
386
|
-
So clearly the `cme` version in upstream Ruby is correct almost all of the time, except for the `label` missing the "block in method" in a few cases.
|
387
|
-
|
388
|
-
This seems to point to the "block in method" issue either being an implementation bug (I still don't quite understand what the two different objects being used here represent) OR more of a "limitation" -- perhaps it's awkward to provide the correct label on the objects that miss it, and since the current MRI object returns one `VALUE` per stack frame, not two, the slight issue is just ignored.
|
389
|
-
|
390
|
-
== TODO
|
391
|
-
|
392
|
-
* Benchmarking
|
393
|
-
* Tackle FIXMEs
|
394
|
-
* Support Ruby < 3.0
|
395
|
-
* Support showing class name, e.g. https://ivoanjo.me/blog/2020/07/05/ruby-experiment-include-class-names-in-backtraces/
|
396
|
-
* Go beyond class name, e.g. https://ivoanjo.me/blog/2020/07/19/better-backtraces-in-ruby-using-tracepoint/
|
397
|
-
* Implement equivalents to `Kernel#caller`, `Thread#backtrace`
|
398
|
-
* Implement limits (similar to the arguments passed to the regular Ruby APIs)
|
399
|
-
* User documentation
|