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

Refactor generated function implementation to provide bindings/method #57230

Merged
merged 1 commit into from
Feb 3, 2025

Conversation

Keno
Copy link
Member

@Keno Keno commented Feb 1, 2025

This PR refactors the generated function implementation in multiple ways:

  1. Rather than allocating a new LineNumber node to pass to the generator, we just pass the original method from which this LineNumberNode was constructed. This has been a bit of a longer-standing annoyance of mine, since the generator needs to know properties of the original method to properly interpret the return value from the generator, but this information was only available on the C side.

  2. Move the handling of Expr returns fully into Julia. Right not things were a bit split with the julia code post-processing an Expr return, but then handing it back to C for lowering. By moving it fully into Julia, we can keep the C-side interface simpler by always getting a CodeInfo.

With these refactorings done, amend the post-processing code to provide binding edges for Expr returns. Ordinarily, bindings in lowered code do not need edges, because we will scan the lowered code of the method to find them. However, generated functions are different, because we do not in general have the lowered code available. To still give them binding edges, we simply scan through the post-lowered code and all of the bindings we find into the edges array.

I will note that both of these will require minor adjustments to @generated functions that use the CodeInfo interface (N.B.: this interface is not considered stable and we've broken it in almost every release so far). In particular, the following adjustments need to be made:

  1. Adjusting the source argument to the new Method ABI
  2. If necessary, adding any edges that correspond to GlobalRefs used - the code will treat the returned CodeInfo mostly opaquely and (unlike in the Expr case) will not automatically compute these edges.

@Keno Keno mentioned this pull request Feb 1, 2025
14 tasks
@Keno Keno force-pushed the kf/generatedrefactor branch 3 times, most recently from 018796a to a016b2b Compare February 2, 2025 02:04
base/expr.jl Outdated Show resolved Hide resolved
@Keno Keno force-pushed the kf/generatedrefactor branch 6 times, most recently from 3fb8912 to 62b3fcf Compare February 2, 2025 23:26
This PR refactors the generated function implementation in multiple ways:

1. Rather than allocating a new LineNumber node to pass to the generator,
   we just pass the original method from which this LineNumberNode was
   constructed. This has been a bit of a longer-standing annoyance of mine,
   since the generator needs to know properties of the original method to
   properly interpret the return value from the generator, but this
   information was only available on the C side.

2. Move the handling of `Expr` returns fully into Julia. Right not things
   were a bit split with the julia code post-processing an `Expr` return,
   but then handing it back to C for lowering. By moving it fully into
   Julia, we can keep the C-side interface simpler by always getting a
   `CodeInfo`.

With these refactorings done, amend the post-processing code to provide
binding edges for `Expr` returns. Ordinarily, bindings in lowered
code do not need edges, because we will scan the lowered code of
the method to find them. However, generated functions are different,
because we do not in general have the lowered code available.
To still give them binding edges, we simply scan through the
post-lowered code and all of the bindings we find into the edges array.

I will note that both of these will require minor adjustments to
`@generated` functions that use the CodeInfo interface (N.B.: this
interface is not considered stable and we've broken it in almost
every release so far). In particular, the following adjustments
need to be made:

1. Adjusting the `source` argument to the new `Method` ABI
2. If necessary, adding any edges that correspond to GlobalRefs used -
   the code will treat the returned CodeInfo mostly opaquely and
   (unlike in the `Expr` case) will not automatically compute these edges.
@Keno Keno force-pushed the kf/generatedrefactor branch from 62b3fcf to 30c6ff9 Compare February 2, 2025 23:30
@Keno Keno merged commit ce507a7 into master Feb 3, 2025
5 of 7 checks passed
@Keno Keno deleted the kf/generatedrefactor branch February 3, 2025 02:47
JL_DLLEXPORT void jl_add_binding_backedge(jl_binding_t *b, jl_value_t *edge)
{
if (!b->backedges) {
b->backedges = jl_alloc_vec_any(0);
Copy link
Member

@vtjnash vtjnash Feb 3, 2025

Choose a reason for hiding this comment

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

It looks like there is no lock on this, so any uses of ./julia (which now defaults to using threads) and which run any code now may trigger this UB memory corruption?

Expr(:meta, :pop_loc))))
spnames = g.spnames
return generated_body_to_codeinfo(spnames === Core.svec() ? lam : Expr(Symbol("with-static-parameters"), lam, spnames...),
typename(typeof(g.gen)).module,
Copy link
Member

Choose a reason for hiding this comment

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

Why aren't we using source.module here anymore? I suppose they probably usually resolve to the same thing, but might be good to document the intent of this change anyways?

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.

3 participants