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

Optionally disallow defining new methods and drop backedges #198

Merged
merged 5 commits into from
Nov 21, 2024

Conversation

Drvi
Copy link
Member

@Drvi Drvi commented Nov 14, 2024

PR Description

By disabling new method definitions we can assert that the loading of cache packages can skip the expensive back edge reinsertion step.

Checklist

Requirements for merging:

@github-actions github-actions bot added port-to-v1.10 This change should apply to Julia v1.10 builds port-to-master This change should apply to all future Julia builds labels Nov 14, 2024
@Drvi Drvi added port-to-master This change should apply to all future Julia builds and removed port-to-v1.10 This change should apply to Julia v1.10 builds port-to-master This change should apply to all future Julia builds labels Nov 19, 2024
Comment on lines +1923 to +1950
static int erase_method_backedges(jl_typemap_entry_t *def, void *closure)
{
jl_method_t *method = def->func.method;
jl_value_t *specializations = jl_atomic_load_relaxed(&method->specializations);
if (jl_is_svec(specializations)) {
size_t i, l = jl_svec_len(specializations);
for (i = 0; i < l; i++) {
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
if ((jl_value_t*)mi != jl_nothing) {
mi->backedges = NULL;
}
}
}
else {
jl_method_instance_t *mi = (jl_method_instance_t*)specializations;
mi->backedges = NULL;
}
return 1;
}

static int erase_all_backedges(jl_methtable_t *mt, void *env)
{
// removes all method caches
// this might not be entirely safe (GC or MT), thus we only do it very early in bootstrapping
mt->backedges = NULL;
jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), erase_method_backedges, env);
return 1;
}
Copy link
Member

Choose a reason for hiding this comment

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

Interesting that we just NULL the backedges field, and don't erase/free anything.
Are these GC-managed objects that we were pointing to?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I am also curious to know how are these objects managed and freed

Copy link
Member Author

Choose a reason for hiding this comment

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

backedges are jl_vector_ts which are managed by the GC unless they are explicitly constructed to opt-out (owned=0), IIUC. Them being GC tracked is relied on even elsewhere e.g. invalidate_method_instance also does this

Copy link
Member

Choose a reason for hiding this comment

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

Maybe @d-netto can weigh in?

Copy link
Member

Choose a reason for hiding this comment

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

@Drvi I think here it becomes clear how GC is made ware of it (notice jl_gc_wb).

Let's merge it?

Copy link
Member

@adnan-alhomssi adnan-alhomssi Nov 21, 2024

Choose a reason for hiding this comment

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

Or, do we need jl_gc_wb(mt, mt->backedges); ?

Copy link
Member

Choose a reason for hiding this comment

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

From documentation,

If the object being stored is a `jl_value_t`, the Julia garbage collector must be notified also:

It is NULL so it looks fine the way it currently is.

Copy link
Member

Choose a reason for hiding this comment

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

Interesting that we just NULL the backedges field, and don't erase/free anything.

This should be fine. If the reference we erased happened to be the last one pointing to the given object, then the mark phase will detect that this object is unreachable and free it during sweeping.

It is NULL so it looks fine the way it currently is.

Yes, you don't need a write barrier here because you are storing NULL.

Copy link
Member

@NHDaly NHDaly left a comment

Choose a reason for hiding this comment

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

LGTM! 🎉 Amazing stuff 😊

// No special processing of `new_specializations` is required because recaching handled it
// Add roots to methods
jl_copy_roots(method_roots_list, jl_worklist_key((jl_array_t*)restored));
// Insert method extensions
Copy link
Member

Choose a reason for hiding this comment

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

what difference does this move make?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know, but it was in the diff we were given, so I included it.

src/gf.c Outdated Show resolved Hide resolved
Comment on lines +1923 to +1950
static int erase_method_backedges(jl_typemap_entry_t *def, void *closure)
{
jl_method_t *method = def->func.method;
jl_value_t *specializations = jl_atomic_load_relaxed(&method->specializations);
if (jl_is_svec(specializations)) {
size_t i, l = jl_svec_len(specializations);
for (i = 0; i < l; i++) {
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
if ((jl_value_t*)mi != jl_nothing) {
mi->backedges = NULL;
}
}
}
else {
jl_method_instance_t *mi = (jl_method_instance_t*)specializations;
mi->backedges = NULL;
}
return 1;
}

static int erase_all_backedges(jl_methtable_t *mt, void *env)
{
// removes all method caches
// this might not be entirely safe (GC or MT), thus we only do it very early in bootstrapping
mt->backedges = NULL;
jl_typemap_visitor(jl_atomic_load_relaxed(&mt->defs), erase_method_backedges, env);
return 1;
}
Copy link
Member

Choose a reason for hiding this comment

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

Yeah I am also curious to know how are these objects managed and freed

src/gf.c Outdated Show resolved Hide resolved
@Drvi Drvi merged commit 918a99d into v1.10.2+RAI Nov 21, 2024
2 checks passed
@Drvi Drvi deleted the td-disable-new-worlds branch November 21, 2024 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
port-to-master This change should apply to all future Julia builds
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants