Skip to content

Commit aacf7d3

Browse files
committed
automatically search cache modules when calling require(::Symbol) or using/import
1 parent 3c3f46d commit aacf7d3

File tree

4 files changed

+79
-24
lines changed

4 files changed

+79
-24
lines changed

base/client.jl

+3
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,16 @@ is_interactive = false
322322
isinteractive() = (is_interactive::Bool)
323323

324324
const LOAD_PATH = ByteString[]
325+
const LOAD_CACHE_PATH = ByteString[]
325326
function init_load_path()
326327
vers = "v$(VERSION.major).$(VERSION.minor)"
327328
if haskey(ENV,"JULIA_LOAD_PATH")
328329
prepend!(LOAD_PATH, split(ENV["JULIA_LOAD_PATH"], @windows? ';' : ':'))
329330
end
330331
push!(LOAD_PATH,abspath(JULIA_HOME,"..","local","share","julia","site",vers))
331332
push!(LOAD_PATH,abspath(JULIA_HOME,"..","share","julia","site",vers))
333+
push!(LOAD_CACHE_PATH,abspath(homedir(),".julia",".libs"))
334+
push!(LOAD_CACHE_PATH,abspath(JULIA_HOME,"..","usr","lib","julia")) #TODO: fixme
332335
end
333336

334337
function load_juliarc()

base/loading.jl

+29
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,35 @@ require(f::AbstractString, fs::AbstractString...) = (require(f); for x in fs req
4343
# only broadcast top-level (not nested) requires and reloads
4444
toplevel_load = true
4545

46+
function _require_from_serialized(content)
47+
m = ccall(:jl_restore_new_module_from_buf, UInt, (Ptr{Uint8},Int), content, sizeof(content))
48+
#package_list[path] = time()
49+
return m
50+
end
51+
52+
function require(sname::Symbol)
53+
name = string(sname)
54+
for prefix in LOAD_CACHE_PATH
55+
path = joinpath(prefix, name*".ji")
56+
if isfile(path)
57+
if nprocs() == 1
58+
if ccall(:jl_restore_new_module, UInt, (Ptr{Uint8},), path) != 0
59+
#package_list[path] = time()
60+
return
61+
end
62+
else
63+
content = open(readbytes, path)
64+
if _require_from_serialized(content) != 0
65+
refs = Any[ @spawnat p _require_from_serialized(content) for p in filter(x->x!=1, procs()) ]
66+
for r in refs; wait(r); end
67+
return
68+
end
69+
end
70+
end
71+
end
72+
require(name)
73+
end
74+
4675
function require(name::AbstractString)
4776
path = find_in_node1_path(name)
4877
path == nothing && throw(ArgumentError("$name not found in path"))

src/dump.c

+46-20
Original file line numberDiff line numberDiff line change
@@ -1423,17 +1423,31 @@ int jl_deserialize_verify_mod_list(ios_t *s)
14231423
ios_read(s, name, len);
14241424
name[len] = '\0';
14251425
uint64_t uuid = read_uint64(s);
1426-
jl_module_t *m = (jl_module_t*)jl_get_global(jl_main_module, jl_symbol(name));
1426+
jl_sym_t *sym = jl_symbol(name);
1427+
jl_module_t *m = (jl_module_t*)jl_get_global(jl_main_module, sym);
14271428
if (!m) {
1428-
jl_printf(JL_STDERR, "error: Module %s must be loaded first\n", name);
1429+
static jl_value_t *require_func = NULL;
1430+
if (!require_func)
1431+
require_func = jl_get_global(jl_base_module, jl_symbol("require"));
1432+
JL_TRY {
1433+
jl_apply((jl_function_t*)require_func, (jl_value_t**)&sym, 1);
1434+
}
1435+
JL_CATCH {
1436+
ios_close(s);
1437+
jl_rethrow();
1438+
}
1439+
m = (jl_module_t*)jl_get_global(jl_main_module, sym);
1440+
}
1441+
if (!m) {
1442+
jl_printf(JL_STDERR, "error: requiring \"%s\" did not define a corresponding module\n", name);
14291443
return 0;
14301444
}
14311445
if (!jl_is_module(m)) {
14321446
ios_close(s);
1433-
jl_errorf("typeassert: expected %s::Module", name);
1447+
jl_errorf("invalid module path (%s does not name a module)", name);
14341448
}
14351449
if (m->uuid != uuid) {
1436-
jl_printf(JL_STDERR, "error: Module %s uuid did not match cache file\n", name);
1450+
jl_printf(JL_STDERR, "warning: Module %s uuid did not match cache file\n", name);
14371451
return 0;
14381452
}
14391453
}
@@ -1790,19 +1804,14 @@ DLLEXPORT int jl_save_new_module(const char *fname, jl_module_t *mod)
17901804
jl_function_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type,
17911805
jl_function_t *method);
17921806

1793-
DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname)
1807+
static jl_module_t *_jl_restore_new_module(ios_t *f)
17941808
{
1795-
ios_t f;
1796-
if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) {
1797-
jl_printf(JL_STDERR, "Cache file \"%s\" not found\n", fname);
1809+
if (ios_eof(f)) {
1810+
ios_close(f);
17981811
return NULL;
17991812
}
1800-
if (ios_eof(&f)) {
1801-
ios_close(&f);
1802-
return NULL;
1803-
}
1804-
if (!jl_deserialize_verify_mod_list(&f)) {
1805-
ios_close(&f);
1813+
if (!jl_deserialize_verify_mod_list(f)) {
1814+
ios_close(f);
18061815
return NULL;
18071816
}
18081817
arraylist_new(&backref_list, 4000);
@@ -1813,14 +1822,14 @@ DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname)
18131822
int en = jl_gc_enable(0);
18141823
DUMP_MODES last_mode = mode;
18151824
mode = MODE_MODULE;
1816-
jl_module_t *parent = (jl_module_t*)jl_deserialize_value(&f, NULL);
1817-
jl_sym_t *name = (jl_sym_t*)jl_deserialize_value(&f, NULL);
1825+
jl_module_t *parent = (jl_module_t*)jl_deserialize_value(f, NULL);
1826+
jl_sym_t *name = (jl_sym_t*)jl_deserialize_value(f, NULL);
18181827
jl_binding_t *b = jl_get_binding_wr(parent, name);
18191828
jl_declare_constant(b);
18201829
if (b->value != NULL) {
18211830
jl_printf(JL_STDERR, "Warning: replacing module %s\n", name->name);
18221831
}
1823-
b->value = jl_deserialize_value(&f, &b->value);
1832+
b->value = jl_deserialize_value(f, &b->value);
18241833

18251834
size_t i = 0;
18261835
while (i < flagref_list.len) {
@@ -1882,9 +1891,9 @@ DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname)
18821891
}
18831892

18841893
mode = MODE_MODULE_LAMBDAS;
1885-
jl_deserialize_lambdas_from_mod(&f);
1894+
jl_deserialize_lambdas_from_mod(f);
18861895

1887-
jl_module_init_order = (jl_array_t*)jl_deserialize_value(&f, NULL);
1896+
jl_module_init_order = (jl_array_t*)jl_deserialize_value(f, NULL);
18881897

18891898
for (i = 0; i < methtable_list.len; i++) {
18901899
jl_methtable_t *mt = (jl_methtable_t*)methtable_list.items[i];
@@ -1921,13 +1930,30 @@ DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname)
19211930
arraylist_free(&flagref_list);
19221931
arraylist_free(&methtable_list);
19231932
arraylist_free(&backref_list);
1924-
ios_close(&f);
1933+
ios_close(f);
19251934

19261935
jl_init_restored_modules();
19271936

19281937
return (jl_module_t*)b->value;
19291938
}
19301939

1940+
DLLEXPORT jl_module_t *jl_restore_new_module_from_buf(const char *buf, size_t sz)
1941+
{
1942+
ios_t f;
1943+
ios_static_buffer(&f, (char*)buf, sz);
1944+
return _jl_restore_new_module(&f);
1945+
}
1946+
1947+
DLLEXPORT jl_module_t *jl_restore_new_module(const char *fname)
1948+
{
1949+
ios_t f;
1950+
if (ios_file(&f, fname, 1, 0, 0, 0) == NULL) {
1951+
jl_printf(JL_STDERR, "Cache file \"%s\" not found\n", fname);
1952+
return NULL;
1953+
}
1954+
return _jl_restore_new_module(&f);
1955+
}
1956+
19311957
// --- init ---
19321958

19331959
void jl_init_serializer(void)

src/toplevel.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,7 @@ static jl_module_t *eval_import_path_(jl_array_t *args, int retrying)
348348
if (require_func == NULL && jl_base_module != NULL)
349349
require_func = jl_get_global(jl_base_module, jl_symbol("require"));
350350
if (require_func != NULL) {
351-
jl_value_t *str = jl_cstr_to_string(var->name);
352-
JL_GC_PUSH1(&str);
353-
jl_apply((jl_function_t*)require_func, &str, 1);
354-
JL_GC_POP();
351+
jl_apply((jl_function_t*)require_func, (jl_value_t**)&var, 1);
355352
return eval_import_path_(args, 1);
356353
}
357354
}

0 commit comments

Comments
 (0)