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

Lookup metadata for inlined frames for stack traces #41099

Merged
merged 9 commits into from
Apr 26, 2023

Conversation

BioTurboNick
Copy link
Contributor

@BioTurboNick BioTurboNick commented Jun 5, 2021

Partially resolves #41031

This PR implements a lookup for information about an inlined stack frame from the parent frame's cached, inferred CodeInfo.

Currently, this lookup fails if a parent frame's code has not been inferred. This merely results in the status quo for those frames.

I was giving a best guess about populating the MethodInstance and Method fields necessary to make things work. I also stumbled into what might be a nicer display for the inlined methods as well, if the arguments information can't be populated. (Though note how the top frame shows the aforementioned issue:

New approach (10/16/21) to avoid freaking out the GC: LineInfoNodes for inlined frames stored directly in the MethodInstance (via new field inlined) for the parent method after the inlining compiler pass. jl_frame_t->linfo is now a union that either holds a MethodInstance (linfo->mi), or Module (linfo->module), modeled after the def union in MethodInstance. When the stack frame lookup occurs in lookup_pointer, the inlined frames are matched with the LineInfoNodes from the parent frame, and the module is stored in jl_frame_t->linfo.module. The stack frame printing code has been adjusted to match.

Approach as of 5/19/22: Storing MethodInstance reference in the LineInfoNode instead of just the method name, then doing a multi-stage lookup when generating stack traces, that first tries to find the specific MethodInstance; if that fails, uses the Method; if that fails, uses the Module. This allows inlined stack frames to present more detailed information.

a() = k
@noinline b() = a()
c() = b()
d() = c()
e() = d()
e()

Current:
image

This PR:
image

Also added documentation to clarify that inferred in a jl_code_instance_t may contain a jl_array_t.

@BioTurboNick

This comment has been minimized.

@BioTurboNick

This comment has been minimized.

@BioTurboNick
Copy link
Contributor Author

Reopening because I have a different approach that might be okay, need to run CI to check.

@BioTurboNick BioTurboNick reopened this Oct 16, 2021
@BioTurboNick BioTurboNick force-pushed the inline_info2 branch 2 times, most recently from 50fc39d to 676f0c7 Compare October 17, 2021 03:42
@timholy
Copy link
Sponsor Member

timholy commented Oct 17, 2021

This looks like great foundational work, but just to check my understanding from a quick perusal, does this only add the module info? A full resolution of #41031 would seem to allow, e.g., Cthulhu to directly look up an inlined caller on its own (needs the full MethodInstance), something that I know people like @chriselrod might appreciate.

Could we get this from the MethodInstance backedges? Meaning, jump ahead to the next non-inlined callee, then walk through the backedges towards the caller, and use these to link the two together. The only question really is how perform that efficiently for MethodInstances with a ton of backedges: how do you know which path through the graph will take you to the place you want? An exhaustive breadth-first search might at least ensure you find it with the minimal number of steps, but it would be great if there's something clever that would do even better. Can you use the debuginfo?

If this is unfamiliar to you, check out some of the code in MethodAnalysis.jl, especially src/backedges.jl.

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 18, 2021

Great questions, and thank you. Yes, it only adds module info. I'm probably not appreciating something about the internals. When I first tried to store a dummy MethodInstance for the inlined frames that could be returned in the lookup method, I got an error about the system image being too large during the build.

lookup_pointer only gets information about the parent frame. The reason my first attempt didn't work was because the only way I could see to find forward-looking information from the current stack frame was to uncompress its CodeInfo, which is apparently not allowed in a JL_NOTSAFEPOINT function.

I suppose you would do what you propose within stacktrace on the Julia side, where you'd have access to all the frames?

Although, your approach would not work for terminal inlined frames, right? So it would potentially enable something to be done for intermediate inlined frames but would not a complete solution.

I'd think it would be best to store information about inlined frames in the MethodInstance they're inlined into, which avoids an extensive search.

Your comment spurred me to look harder for the MethodInstance of the inlined frame during the optimization passes, so I could try storing that directly. And that works great if I place a switch I can turn on after Julia itself compiles. (I put this code in the inline_info3 branch)

image

But... what I'm finding is that if I allow that to be active when Julia compiles, it either leads to a "system image is too large" error or a hang after "namedtuples.jl" for a slimmer variant. I guess there are just way too many inlined methods to make that work.

I think perhaps the ideal solution may require deeper study and architecture than I can currently commit to.

@timholy
Copy link
Sponsor Member

timholy commented Oct 18, 2021

Maybe this will help:

a() = k
@noinline b() = a()
c() = b()
d() = c()
e() = d()
e()             # note that you have to run the code once in order for the rest of this to work

julia> using MethodAnalysis

julia> mis = methodinstances(a)
1-element Vector{Core.MethodInstance}:
 MethodInstance for a()

julia> mi = mis[1]
MethodInstance for a()

julia> direct_backedges(mi)
1-element Vector{Core.MethodInstance}:
 MethodInstance for b()

julia> all_backedges(mi)
4-element Vector{Core.MethodInstance}:
 MethodInstance for e()
 MethodInstance for c()
 MethodInstance for d()
 MethodInstance for b()

@vchuravy
Copy link
Sponsor Member

I don't think you can use the backedges since there might be multiple callsites withing the same function? Recording the information as debuginfo during inlinling might be more beneficial?

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 18, 2021

I don't think you can use the backedges since there might be multiple callsites withing the same function? Recording the information as debuginfo during inlinling might be more beneficial?

Yeah... and in the current framework, all you have at that point is the name of the method (as symbol), the file name (as symbol), and the line number. Additional information stored in a MethodInstance seems to have to be simple to avoid blowing up the initial build. (Array of LineInfoNodes seem fine, Array of MethodInstances are not).

So it seems you'd have to do some sort of dynamic lookup on demand. With code based on MethodAnalysis.jl, I could look up all MethodInstances associated with the inlined method from the name, and then filter based on the file and line number.

a() = 4
frame = StackFrame(:a, :"REPL[1]", 1)
mis = methodinstances(methods(eval(frame.func)))
filter!(x -> x.def isa Method && x.def.file == frame.file && x.def.line == frame.line, mis)

But that leaves you with specializations. If you have a following frame, I guess you could do a union of its backedges with this list, but you could still end up with multiple matches if several specializations of the same method are used, as @vchuravy noted.

So, what additional information is necessary to store for a specific lookup? Just the list of argument types? Maybe that can be stored in the parent non-inlined MethodInstance.

@vchuravy
Copy link
Sponsor Member

The inlined_at line info is inserted here

push!(linetable, LineInfoNode(def.module, def.name, def.file, Int(def.line), inlined_at))

@BioTurboNick you want the method right? Not the precise method instance? Then storing the signature (and not atypes) should suffice, cc: @aviatesk

@BioTurboNick
Copy link
Contributor Author

@BioTurboNick you want the method right? Not the precise method instance? Then storing the signature (and not atypes) should suffice, cc: @aviatesk

Other stack frames display the specialized types, so it wouldn't be consistent, though it would be easier.

@BioTurboNick
Copy link
Contributor Author

Tada!

a(x) = l
@noinline b(x) = a(x)
c(x) = b(x)
d(x) = c(x)
d(4)
d(4.0)

image

@codecov
Copy link

codecov bot commented Oct 19, 2021

Codecov Report

Merging #41099 (f2c627e) into master (84e9989) will decrease coverage by 0.07%.
The diff coverage is n/a.

❗ Current head f2c627e differs from pull request most recent head 7955e35. Consider uploading reports for the commit 7955e35 to get more accurate results

@@            Coverage Diff             @@
##           master   #41099      +/-   ##
==========================================
- Coverage   89.23%   89.16%   -0.08%     
==========================================
  Files         342      343       +1     
  Lines       78400    78671     +271     
==========================================
+ Hits        69964    70146     +182     
- Misses       8436     8525      +89     
Impacted Files Coverage Δ
stdlib/LibGit2/src/error.jl 81.81% <0.00%> (-9.10%) ⬇️
stdlib/LibGit2/src/callbacks.jl 42.44% <0.00%> (-8.98%) ⬇️
stdlib/Profile/src/Allocs.jl 86.53% <0.00%> (-7.70%) ⬇️
stdlib/LibGit2/src/gitcredential.jl 86.30% <0.00%> (-7.54%) ⬇️
stdlib/Markdown/src/Common/block.jl 90.52% <0.00%> (-4.74%) ⬇️
base/secretbuffer.jl 96.84% <0.00%> (-3.16%) ⬇️
stdlib/Markdown/src/parse/util.jl 88.07% <0.00%> (-2.76%) ⬇️
stdlib/Dates/src/io.jl 94.17% <0.00%> (-2.70%) ⬇️
stdlib/LibGit2/src/types.jl 85.94% <0.00%> (-2.41%) ⬇️
base/util.jl 68.75% <0.00%> (-2.09%) ⬇️
... and 56 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8ccf2d6...7955e35. Read the comment docs.

@timholy
Copy link
Sponsor Member

timholy commented Oct 19, 2021

Very cool! Does this increase the size of the system image file substantially? Another concern might be serialization; perhaps other than the module, the current LineInfoNode is very portable. It's not so obvious that this will be. Bugs like those hunted down in #37809 and #38127 are the kind of thing I might worry about. (They arose from different code on different nodes, and communication between the nodes led to serialization errors.)

Recording the information as debuginfo during inlining might be more beneficial?

I was imagining that between the LineInfo and the backedges you could probably figure things out, but it might take a dive into the type-inferred code. That is, if the debuginfo says you were called from a specific spot in the code, then you go check the unoptimized inferred code and find the corresponding call, and extract the types from there.. Since inlining will happen only for inferrable calls, I don't think you need to worry about how to handle cases of non-concrete inference. (Maybe 😁 ) But this sounds like quite a lot of work, so if @BioTurboNick's solution doesn't have significant downsides, clearly it's easier.

base/stacktraces.jl Outdated Show resolved Hide resolved
@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 19, 2021

Very cool! Does this increase the size of the system image file substantially?

How do I check that? There might also be some excess to be trimmed even, as there seemed like there were a lot more linetable entries than inlined frames.

With respect to serialization errors, what could the source of that be, in theory?

EDIT: Also working through an issue with certain frames from generated functions e.g. #invokelatest#2 or #9.

@KristofferC
Copy link
Sponsor Member

How do I check that?

Probably just look at the size of the sysimage (usr/lib/julia/sys.so) with this PR and without it.

base/stacktraces.jl Outdated Show resolved Hide resolved
base/boot.jl Outdated Show resolved Hide resolved
base/compiler/optimize.jl Outdated Show resolved Hide resolved
@BioTurboNick
Copy link
Contributor Author

I implemented the suggestion to use the method field as designed to contain MethodInstances and addressed some edge cases.

sysimage (sys-o.a) size is 265 Mb with this PR. On master it is 182 Mb... a pretty significant increase. (Believe it or not, an earlier iteration was closer to 500 Mb).

Maybe I can get that down by avoiding creating a new LineInfoNode for the subsequent frames that are associated with a Method instead of MethodInstance. Maybe once I match that line in the lookup function, I can backtrack to find the first one.

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 20, 2021

Welp, that didn't reduce the size at all. Not sure how to proceed.

EDIT:
Investigating further:

There are ~1.2 million inlining passes building Juila. Just adding an empty array of LineInfoNodes to all MethodInstances with inlined methods increases the sysimage size from 182 MB to 205 MB. They are occurring across ~70 thousand method instances containing inlined methods, and involve ~14 thousand unique method instances (this last might actually combine some specialiations unintentionally).

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 21, 2021

Okay, completely new approach:

const inline_mi_cache = IdDict{Tuple{Symbol, Symbol, Int}, Union{MethodInstance, Method, Module}}()

The post-inlining-pass line table is used to insert the MethodInstance, Method (if no MethodInstance found), or Module (if no MethodInstance found; relevant for "macro expansion") associated with the tuple of function name, file name, and line number.

Base.StackTraces.lookup then grabs the associated MethodInstance/Method/Module from this dictionary and loads it into the StackFrame.

sysimage size (sys-so.a) is now 201 MB. Which seems more managable?

EDIT: D'oh, that's not fully specified then; the parent method instance should be part of the key. Hang on...

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 21, 2021

Turns out that version is even worse when done right.

It may be impossible to do without grossly inflating the sysimage.

So, what about turning this off for sysimage creation, and only running it for code loaded later? Is there a bool somewhere to check? Could just store the module of the func/file/line for those functions cheaply. Shouldn't matter quite as much if type information is left out from those frames, yes?

@BioTurboNick
Copy link
Contributor Author

BioTurboNick commented Oct 21, 2021

Oh. I think I got it? Turns out I was doing ccall wrong. If I figured that out, my original approach would have worked great from the Julia side.

ci = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, mi.cache.inferred)
CodeInfo(
    @ REPL[2]:1 within `b`
   ┌ @ REPL[1]:1 within `a`
1 ─│ %1 = Main.g::Any
│  └
└──      return %1
)

julia> ci.linetable
3-element Vector{Core.LineInfoNode}:
 Core.LineInfoNode(Main, b(x) in Main at REPL[2]:1, Symbol("REPL[2]"), 1, 0)
 Core.LineInfoNode(Main, MethodInstance for a(::Int64), Symbol("REPL[1]"), 1, 1)
 Core.LineInfoNode(Main, a(x) in Main at REPL[1]:1, Symbol("REPL[1]"), 1, 1)

@BioTurboNick
Copy link
Contributor Author

The current code works except for certain frames where the inferred field of the uncompressed CodeInfo is nothing, so the linetable cannot be looked up.

An example of this case is seen when running @btime not_defined_var, e.g. #run_result#38 and #invokelatest#2.

The parent MethodInstance for these two inlined frames is MethodInstance for BenchmarkTools.var"#run#42"(::Nothing, ::Float64, ::Float64, ::Base.Pairs{Symbol, Integer, NTuple{5, Symbol}, NamedTuple{(:verbose, :samples, :evals, :gctrial, :gcsample), Tuple{Bool, Int64, Int64, Bool, Bool}}}, ::typeof(run), ::BenchmarkTools.Benchmark, ::BenchmarkTools.Parameters)

This issue could be resolved by, in these rare cases, relying on one of the other approaches I used. But before I try that, is there another place that a linetable could be found?

@aviatesk
Copy link
Sponsor Member

My reasoning is that method errors are usually caused by dynamic dispatch, which often results in the inlining cost for the parent frame being too high for it to be inlined. As a result, we typically see type information for frames that are close to where the error occurs:

Stacktrace:
  [1] zero(#unused#::Type{Any})
    @ Base ./missing.jl:106
  [2] reduce_empty(#unused#::typeof(+), #unused#::Type{Any})
    @ Base ./reduce.jl:338
  [3] reduce_empty(#unused#::typeof(Base.add_sum), #unused#::Type{Any})
    @ Base ./reduce.jl:347
  [4] mapreduce_empty(#unused#::typeof(identity), op::Function, T::Type)
    @ Base ./reduce.jl:367
  [5] reduce_empty(op::Base.MappingRF{typeof(identity), typeof(Base.add_sum)}, #unused#::Type{Any})
    @ Base ./reduce.jl:356
  [6] reduce_empty_iter
    @ ./reduce.jl:379 [inlined]
  [7] mapreduce_empty_iter(f::Function, op::Function, itr::Vector{Any}, ItrEltype::Base.HasEltype)
    @ Base ./reduce.jl:375
  [8] _mapreduce(f::typeof(identity), op::typeof(Base.add_sum), #unused#::IndexLinear, A::Vector{Any})
    @ Base ./reduce.jl:427
  [9] _mapreduce_dim
    @ ./reducedim.jl:365 [inlined]
 [10] #mapreduce#800
    @ ./reducedim.jl:357 [inlined]
 [11] mapreduce
    @ ./reducedim.jl:357 [inlined]
 [12] #_sum#810
    @ ./reducedim.jl:999 [inlined]
 [13] _sum
    @ ./reducedim.jl:999 [inlined]
 [14] #_sum#809
    @ ./reducedim.jl:998 [inlined]
 [15] _sum
    @ ./reducedim.jl:998 [inlined]
 [16] #sum#807
    @ ./reducedim.jl:994 [inlined]
 [17] sum(a::Vector{Any})
    @ Base ./reducedim.jl:994
 [18] top-level scope
    @ REPL[11]:1

The other frames might indeed be inlined, so you are right, it might be an overstatement to say "it's rare to be involved". But I'm still wondering if the type information for those frames are really valuable enough to justify the performance cost associated with it.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Apr 27, 2023

When inlined, you also know that Cthulhu will always recover that type information as well, so this is likely unnecessary to store for the user experience

@vchuravy
Copy link
Sponsor Member

When inlined, you also know that Cthulhu will always recover that type information as well, so this is likely unnecessary to store for the user experience

Most people do not (and arguably should not) use Cthulhu. Giving more precision in the inlined stack traces is useful from a general usability perspective.

Julia often and deeply inlines code and I for one have been frustrated by the stacktraces more than once.
(Partially why I wrote Cthulhu in the first place, we couldn't answer the question "How did we get there" without a dedicated tool). So the existence of Cthulhu is not an argument for the previous state, but an indictment thereof.

@ToucheSir
Copy link

But I'm still wondering if the type information for those frames are really valuable enough to justify the performance cost associated with it.

If you ever have the pleasure of trying to differentiate through a non-trivial function using Zygote, the answer is a resounding "yes". For this particular case, any errors are usually not MethodErrors and the entire call stack is type stable.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Apr 28, 2023

I am still concerned this is an implementation problem here, since the system image contains a fairly small amount of optimized code, yet this PR is allocating a noticeably disproportionate about of extra junk:

sysimg size breakdown:
     sys data: 77039052
  isbits data: 56610644
      symbols:   463373
    tags list:  1076419
   reloc list:  4204985
    gvar list:   118728
    fptr list:   213656

sysimg size breakdown:                                                                                                                                                                           
     sys data: 79207516                                                                                                                                                                          
  isbits data: 58603452                                                                                                                                                                          
      symbols:   463610                                                                                                                                                                          
    tags list:  1078555                                                                         
   reloc list:  4491653                                                                                                                                                                          
    gvar list:   118848                                                                                                                                                                          
    fptr list:   214000                                                                         

@BioTurboNick
Copy link
Contributor Author

sys data: +2.07 MB
isbits data: +1.90 MB
symbols: +237 B
tags list: +2.09 kB
reloc list: +280 kB
gvar list: +120 B
fptr list: +344 B

I'm guessing most of that is from storing MethodInstances of inlined functions in the line table entries?

There are two places where a MethodInstance is placed in a LineInfoNode - typeinf_ext (previously was method name) and ir_inline_linetable! (previously was method def). Perhaps one of those is unnecessary?

Perhaps there's some point where it could be determined that MethodInstances aren't needed for some entries and could be stripped back out?

How did you generate those numbers, so I could check myself?

@vtjnash
Copy link
Sponsor Member

vtjnash commented Apr 28, 2023

This is a PkgCacheInspector feature

@BioTurboNick
Copy link
Contributor Author

This is a PkgCacheInspector feature

I've poked around a bit and it's not clear how to use it for the sysimage, vs. packages?

@fonsp
Copy link
Member

fonsp commented May 15, 2023

Nice work! 🎉

This PR broke a feature in Pluto.jl that iterates a backtrace. It might be nice to run nanosoldier on this PR to check other packages? (It would have caught our issue 🌝)

@BioTurboNick
Copy link
Contributor Author

Thanks! And thanks for the heads-up @fonsp. So the issue is just that sometimes a Module appears where there previously was Nothing?

@pankgeorg
Copy link

Thanks! And thanks for the heads-up @fonsp. So the issue is just that sometimes a Module appears where there previously was Nothing?

Yes, the types of linfo were extended from Union{Nothing, Core.CodeInfo, Core.MethodInstance} to Union{Nothing, Core.CodeInfo, Core.MethodInstance, Method, Module}

This is how we handle frames:

https://github.com/fonsp/Pluto.jl/blob/8edd75b1e76599ab0bf69f75e634d9762502e431/src/runner/PlutoRunner.jl#L1075-L1105

maleadt pushed a commit that referenced this pull request Jul 23, 2023
Due to #50082, reverting the causative portion from #41099, which stored
MethodInstances in LineInfoNodes.
KristofferC pushed a commit that referenced this pull request Jul 24, 2023
Due to #50082, reverting the causative portion from #41099, which stored
MethodInstances in LineInfoNodes.

(cherry picked from commit ae798cd)
Comment on lines +55 to +57
"the MethodInstance or CodeInfo containing the execution context (if it could be found), \
or Module (for macro expansions)"
linfo::Union{MethodInstance, Method, Module, CodeInfo, Nothing}
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it really necessary to allow linfo::Module? From what I can tell, this module information is never used or explicitly tested, so there's no need to store it here. I'm concerned that this heavy-union field definition complicates the code unnecessarily.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible it's out of date, but at least at one point it was needed to look up the module for macro expansion frame.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have implemented test cases for these new features. Do you have any use case for that information? Otherwise we should clean that up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. But I just described the use case. Is this causing a problem somewhere right now? Otherwise something to look at when the underlying problem #50204 is resolved someway and the full functionality can be restored here.

vtjnash pushed a commit that referenced this pull request Sep 28, 2023
The work I did in #41099 introduced code which, if method information
could not be found for an inlined frame, would fall back to use the
module of the next-higher stack frame. This often worked there because
the only frames that would not be assigned a module at this point would
be e.g., `macro expansion` frames.

However, due to the performance impact of the way method roots are
currently encoded, the extra method roots were removed in #50546.

The result is that inlined frames were being assigned a potentially
incorrect module, rather than being left blank.

Example:
```
julia> @Btime plot([1 2 3], seriestype = :blah)
...
 [13] #invokelatest#2
    @ BenchmarkTools ./essentials.jl:901 [inlined]
 [14] invokelatest
    @ BenchmarkTools ./essentials.jl:896 [inlined]
...
```
KristofferC pushed a commit that referenced this pull request Oct 3, 2023
The work I did in #41099 introduced code which, if method information
could not be found for an inlined frame, would fall back to use the
module of the next-higher stack frame. This often worked there because
the only frames that would not be assigned a module at this point would
be e.g., `macro expansion` frames.

However, due to the performance impact of the way method roots are
currently encoded, the extra method roots were removed in #50546.

The result is that inlined frames were being assigned a potentially
incorrect module, rather than being left blank.

Example:
```
julia> @Btime plot([1 2 3], seriestype = :blah)
...
 [13] #invokelatest#2
    @ BenchmarkTools ./essentials.jl:901 [inlined]
 [14] invokelatest
    @ BenchmarkTools ./essentials.jl:896 [inlined]
...
```

(cherry picked from commit ed891d6)
nalimilan pushed a commit that referenced this pull request Nov 5, 2023
The work I did in #41099 introduced code which, if method information
could not be found for an inlined frame, would fall back to use the
module of the next-higher stack frame. This often worked there because
the only frames that would not be assigned a module at this point would
be e.g., `macro expansion` frames.

However, due to the performance impact of the way method roots are
currently encoded, the extra method roots were removed in #50546.

The result is that inlined frames were being assigned a potentially
incorrect module, rather than being left blank.

Example:
```
julia> @Btime plot([1 2 3], seriestype = :blah)
...
 [13] #invokelatest#2
    @ BenchmarkTools ./essentials.jl:901 [inlined]
 [14] invokelatest
    @ BenchmarkTools ./essentials.jl:896 [inlined]
...
```

(cherry picked from commit ed891d6)
aviatesk pushed a commit that referenced this pull request Jan 14, 2024
The fallback code that was written for #41099 is causing unintended
issues with some inlined stack frames (one previous #51405, new #52709),
since the main piece, linetable storage and lookup, was removed in
#50546. Probably better to strip it all back to how it was previously,
until it can all be revisited more fully.

Should be backported to 1.10.
aviatesk pushed a commit that referenced this pull request Jan 14, 2024
The fallback code that was written for #41099 is causing unintended
issues with some inlined stack frames (one previous #51405, new #52709),
since the main piece, linetable storage and lookup, was removed in
#50546. Probably better to strip it all back to how it was previously,
until it can all be revisited more fully.

Should be backported to 1.10.
Drvi pushed a commit to RelationalAI/julia that referenced this pull request Jun 7, 2024
The fallback code that was written for JuliaLang#41099 is causing unintended
issues with some inlined stack frames (one previous JuliaLang#51405, new JuliaLang#52709),
since the main piece, linetable storage and lookup, was removed in
JuliaLang#50546. Probably better to strip it all back to how it was previously,
until it can all be revisited more fully.

Should be backported to 1.10.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Metadata missing from inlined frames in backtraces
9 participants