Skip to content

Commit 5e54126

Browse files
committed
Support deleteing methods for delayed package loading
1 parent 6a722ff commit 5e54126

File tree

6 files changed

+48
-28
lines changed

6 files changed

+48
-28
lines changed

src/clangsa/GCChecker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,7 +1438,8 @@ bool GCChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
14381438
} else if (name == "JL_GC_PUSH1" || name == "JL_GC_PUSH2" ||
14391439
name == "JL_GC_PUSH3" || name == "JL_GC_PUSH4" ||
14401440
name == "JL_GC_PUSH5" || name == "JL_GC_PUSH6" ||
1441-
name == "JL_GC_PUSH7" || name == "JL_GC_PUSH8") {
1441+
name == "JL_GC_PUSH7" || name == "JL_GC_PUSH8" ||
1442+
name == "JL_GC_PUSH9") {
14421443
ProgramStateRef State = C.getState();
14431444
// Transform slots to roots, transform values to rooted
14441445
unsigned NumArgs = CE->getNumArgs();

src/gf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,6 +1926,7 @@ JL_DLLEXPORT void jl_method_table_disable_incremental(jl_methtable_t *mt, jl_met
19261926
jl_typemap_entry_t *methodentry = do_typemap_search(mt, method);
19271927
JL_LOCK(&mt->writelock);
19281928
// Narrow the world age on the method to make it uncallable
1929+
// size_t world = jl_atomic_load_acquire(&jl_world_counter);
19291930
size_t world = jl_atomic_fetch_add(&jl_world_counter, 1);
19301931
jl_method_table_invalidate(mt, methodentry, world, 1);
19311932
JL_UNLOCK(&mt->writelock);

src/julia.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,7 @@ extern void JL_GC_PUSH4(void *, void *, void *, void *) JL_NOTSAFEPOINT;
932932
extern void JL_GC_PUSH5(void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
933933
extern void JL_GC_PUSH7(void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
934934
extern void JL_GC_PUSH8(void *, void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
935+
extern void JL_GC_PUSH9(void *, void *, void *, void *, void *, void *, void *, void *) JL_NOTSAFEPOINT;
935936
extern void _JL_GC_PUSHARGS(jl_value_t **, size_t) JL_NOTSAFEPOINT;
936937
// This is necessary, because otherwise the analyzer considers this undefined
937938
// behavior and terminates the exploration
@@ -974,6 +975,9 @@ extern void JL_GC_POP() JL_NOTSAFEPOINT;
974975
#define JL_GC_PUSH8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
975976
void *__gc_stkf[] = {(void*)JL_GC_ENCODE_PUSH(8), jl_pgcstack, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8}; \
976977
jl_pgcstack = (jl_gcframe_t*)__gc_stkf;
978+
#define JL_GC_PUSH9(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
979+
void *__gc_stkf[] = {(void*)JL_GC_ENCODE_PUSH(9), jl_pgcstack, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9}; \
980+
jl_pgcstack = (jl_gcframe_t*)__gc_stkf;
977981

978982

979983
#define JL_GC_PUSHARGS(rts_var,n) \
@@ -1901,6 +1905,7 @@ JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *d
19011905

19021906
JL_DLLEXPORT void jl_set_newly_inferred(jl_value_t *newly_inferred);
19031907
JL_DLLEXPORT void jl_push_newly_inferred(jl_value_t *ci);
1908+
JL_DLLEXPORT void jl_method_table_disable_incremental(jl_methtable_t *mt, jl_method_t *m);
19041909
JL_DLLEXPORT void jl_set_newly_deleted(jl_value_t *newly_deleted);
19051910
JL_DLLEXPORT void jl_push_newly_deleted(jl_value_t *m);
19061911
JL_DLLEXPORT void jl_write_compiler_output(void);

src/staticdata.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,7 +2393,7 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
23932393
static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
23942394
jl_array_t *worklist, jl_array_t *extext_methods,
23952395
jl_array_t *new_specializations, jl_array_t *method_roots_list,
2396-
jl_array_t *ext_targets, jl_array_t *edges) JL_GC_DISABLED
2396+
jl_array_t *ext_targets, jl_array_t *edges, jl_array_t *newly_deleted) JL_GC_DISABLED
23972397
{
23982398
htable_new(&field_replace, 0);
23992399
// strip metadata and IR when requested
@@ -2514,6 +2514,10 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
25142514
jl_queue_for_serialization(&s, ext_targets);
25152515
jl_queue_for_serialization(&s, edges);
25162516
}
2517+
if (newly_deleted) {
2518+
jl_queue_for_serialization(&s, newly_deleted);
2519+
}
2520+
25172521
jl_serialize_reachable(&s);
25182522
// step 1.2: ensure all gvars are part of the sysimage too
25192523
record_gvars(&s, &gvars);
@@ -2647,6 +2651,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
26472651
jl_write_value(&s, method_roots_list);
26482652
jl_write_value(&s, ext_targets);
26492653
jl_write_value(&s, edges);
2654+
jl_write_value(&s, newly_deleted);
26502655
}
26512656
write_uint32(f, jl_array_len(s.link_ids_gctags));
26522657
ios_write(f, (char*)jl_array_data(s.link_ids_gctags), jl_array_len(s.link_ids_gctags) * sizeof(uint32_t));
@@ -2725,11 +2730,11 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
27252730
}
27262731

27272732
jl_array_t *mod_array = NULL, *extext_methods = NULL, *new_specializations = NULL;
2728-
jl_array_t *method_roots_list = NULL, *ext_targets = NULL, *edges = NULL;
2733+
jl_array_t *method_roots_list = NULL, *ext_targets = NULL, *edges = NULL, *_newly_deleted = NULL;
27292734
int64_t checksumpos = 0;
27302735
int64_t checksumpos_ff = 0;
27312736
int64_t datastartpos = 0;
2732-
JL_GC_PUSH6(&mod_array, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges);
2737+
JL_GC_PUSH7(&mod_array, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &_newly_deleted);
27332738

27342739
if (worklist) {
27352740
mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
@@ -2776,7 +2781,10 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
27762781
}
27772782
if (_native_data != NULL)
27782783
native_functions = *_native_data;
2779-
jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges);
2784+
// Otherwise serialization will be confused.
2785+
if (newly_deleted)
2786+
_newly_deleted = jl_array_copy(newly_deleted);
2787+
jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges, _newly_deleted);
27802788
if (_native_data != NULL)
27812789
native_functions = NULL;
27822790
// make sure we don't run any Julia code concurrently before this point
@@ -2860,6 +2868,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
28602868
jl_array_t **extext_methods,
28612869
jl_array_t **new_specializations, jl_array_t **method_roots_list,
28622870
jl_array_t **ext_targets, jl_array_t **edges,
2871+
jl_array_t **newly_deleted,
28632872
char **base, arraylist_t *ccallable_list, pkgcachesizes *cachesizes) JL_GC_DISABLED
28642873
{
28652874
int en = jl_gc_enable(0);
@@ -2921,7 +2930,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
29212930
assert(!ios_eof(f));
29222931
s.s = f;
29232932
uintptr_t offset_restored = 0, offset_init_order = 0, offset_extext_methods = 0, offset_new_specializations = 0, offset_method_roots_list = 0;
2924-
uintptr_t offset_ext_targets = 0, offset_edges = 0;
2933+
uintptr_t offset_ext_targets = 0, offset_edges = 0, offset_newly_deleted = 0;
29252934
if (!s.incremental) {
29262935
size_t i;
29272936
for (i = 0; tags[i] != NULL; i++) {
@@ -2955,6 +2964,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
29552964
offset_method_roots_list = jl_read_offset(&s);
29562965
offset_ext_targets = jl_read_offset(&s);
29572966
offset_edges = jl_read_offset(&s);
2967+
offset_newly_deleted = jl_read_offset(&s);
29582968
}
29592969
s.buildid_depmods_idxs = depmod_to_imageidx(depmods);
29602970
size_t nlinks_gctags = read_uint32(f);
@@ -2988,6 +2998,7 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
29882998
*method_roots_list = (jl_array_t*)jl_delayed_reloc(&s, offset_method_roots_list);
29892999
*ext_targets = (jl_array_t*)jl_delayed_reloc(&s, offset_ext_targets);
29903000
*edges = (jl_array_t*)jl_delayed_reloc(&s, offset_edges);
3001+
*newly_deleted = (jl_array_t*)jl_delayed_reloc(&s, offset_newly_deleted);
29913002
if (!*new_specializations)
29923003
*new_specializations = jl_alloc_vec_any(0);
29933004
}
@@ -3175,6 +3186,11 @@ static void jl_restore_system_image_from_stream_(ios_t *f, jl_image_t *image, jl
31753186
assert(jl_is_datatype(obj));
31763187
jl_cache_type_((jl_datatype_t*)obj);
31773188
}
3189+
3190+
// Delete methods before inserting new ones.
3191+
if (newly_deleted)
3192+
jl_delete_methods(*newly_deleted);
3193+
31783194
// Perform fixups: things like updating world ages, inserting methods & specializations, etc.
31793195
size_t world = jl_atomic_load_acquire(&jl_world_counter);
31803196
for (size_t i = 0; i < s.uniquing_objs.len; i++) {
@@ -3401,11 +3417,11 @@ static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *im
34013417
assert(datastartpos > 0 && datastartpos < dataendpos);
34023418
needs_permalloc = jl_options.permalloc_pkgimg || needs_permalloc;
34033419
jl_value_t *restored = NULL;
3404-
jl_array_t *init_order = NULL, *extext_methods = NULL, *new_specializations = NULL, *method_roots_list = NULL, *ext_targets = NULL, *edges = NULL;
3420+
jl_array_t *init_order = NULL, *extext_methods = NULL, *new_specializations = NULL, *method_roots_list = NULL, *ext_targets = NULL, *edges = NULL, *newly_deleted = NULL;
34053421
jl_svec_t *cachesizes_sv = NULL;
34063422
char *base;
34073423
arraylist_t ccallable_list;
3408-
JL_GC_PUSH8(&restored, &init_order, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &cachesizes_sv);
3424+
JL_GC_PUSH9(&restored, &init_order, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &newly_deleted, &cachesizes_sv);
34093425

34103426
{ // make a permanent in-memory copy of f (excluding the header)
34113427
ios_bufmode(f, bm_none);
@@ -3429,11 +3445,12 @@ static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *im
34293445
ios_close(f);
34303446
ios_static_buffer(f, sysimg, len);
34313447
pkgcachesizes cachesizes;
3432-
jl_restore_system_image_from_stream_(f, image, depmods, checksum, (jl_array_t**)&restored, &init_order, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &base, &ccallable_list, &cachesizes);
3448+
jl_restore_system_image_from_stream_(f, image, depmods, checksum, (jl_array_t**)&restored, &init_order, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &newly_deleted, &base, &ccallable_list, &cachesizes);
34333449
JL_SIGATOMIC_END();
34343450

34353451
// Insert method extensions
34363452
jl_insert_methods(extext_methods);
3453+
34373454
// No special processing of `new_specializations` is required because recaching handled it
34383455
// Add roots to methods
34393456
jl_copy_roots(method_roots_list, jl_worklist_key((jl_array_t*)restored));
@@ -3469,7 +3486,7 @@ static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *im
34693486
static void jl_restore_system_image_from_stream(ios_t *f, jl_image_t *image, uint32_t checksum)
34703487
{
34713488
JL_TIMING(LOAD_IMAGE, LOAD_Sysimg);
3472-
jl_restore_system_image_from_stream_(f, image, NULL, checksum | ((uint64_t)0xfdfcfbfa << 32), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3489+
jl_restore_system_image_from_stream_(f, image, NULL, checksum | ((uint64_t)0xfdfcfbfa << 32), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
34733490
}
34743491

34753492
JL_DLLEXPORT jl_value_t *jl_restore_incremental_from_buf(const char *buf, jl_image_t *image, size_t sz, jl_array_t *depmods, int completeinfo, const char *pkgname, bool needs_permalloc)

src/staticdata_utils.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,19 @@ static void jl_insert_methods(jl_array_t *list)
838838
}
839839
}
840840

841+
static void jl_delete_methods(jl_array_t *list)
842+
{
843+
size_t i, l = jl_array_len(list);
844+
for (i = 0; i < l; i++) {
845+
jl_method_t *meth = (jl_method_t*)jl_array_ptr_ref(list, i);
846+
assert(jl_is_method(meth));
847+
assert(!meth->is_for_opaque_closure);
848+
jl_methtable_t *mt = jl_method_get_table(meth);
849+
assert((jl_value_t*)mt != jl_nothing);
850+
jl_method_table_disable_incremental(mt, meth);
851+
}
852+
}
853+
841854
static void jl_copy_roots(jl_array_t *method_roots_list, uint64_t key)
842855
{
843856
size_t i, l = jl_array_len(method_roots_list);

stdlib/Random/src/Random.jl

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,11 @@ export rand!, randn!,
3131

3232
## general definitions
3333

34-
# Remove the shim methods
35-
# TODO: If we could support this as part of package loading
36-
# That would be much nicer.
37-
# for m in Base.methods(rand)
38-
# if m.module == Base
39-
# Base.delete_method(m)
40-
# end
41-
# end
34+
Base.Stubs.delete_stubs(Base.Stubs.Random)
4235

4336
function __init__()
4437
seed!()
4538
ccall(:jl_gc_init_finalizer_rng_state, Cvoid, ())
46-
47-
# Remove the shim methods
48-
# Is this too coarse? We want to only delete the method
49-
# in Base, not any added by the user later on.
50-
# We are currently not allowed to run this during any precompilation
51-
# so we must guard it until "normal runtime".
52-
# TODO: What to do when we are including Random into a sysimg.
53-
if !Base.generating_output()
54-
Base.Stubs.delete_stubs(Base.Stubs.Random)
55-
end
5639
end
5740

5841
"""

0 commit comments

Comments
 (0)