diff --git a/src/staticdata.c b/src/staticdata.c index 91c0b04bac5d0..ac45afe2df9bc 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -71,6 +71,7 @@ External links: */ #include #include +#include #include // printf #include // PRIxPTR @@ -3209,7 +3210,7 @@ static jl_value_t *jl_validate_cache_file(ios_t *f, jl_array_t *depmods, uint64_ } // TODO?: refactor to make it easier to create the "package inspector" -static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *image, jl_array_t *depmods, int complete) +static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *image, jl_array_t *depmods, int complete, bool needs_permalloc) { uint64_t checksum = 0; int64_t dataendpos = 0; @@ -3228,18 +3229,26 @@ static jl_value_t *jl_restore_package_image_from_stream(ios_t *f, jl_image_t *im arraylist_t ccallable_list; JL_GC_PUSH8(&restored, &init_order, &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges, &cachesizes_sv); - { // make a permanent in-memory copy of f (excluding the header) + { // make a permanent in-memory copy of f (excluding the header) if needed ios_bufmode(f, bm_none); JL_SIGATOMIC_BEGIN(); size_t len = dataendpos - datastartpos; - char *sysimg = (char*)jl_gc_perm_alloc(len, 0, 64, 0); + char *sysimg; + bool success = !needs_permalloc; ios_seek(f, datastartpos); - if (ios_readall(f, sysimg, len) != len || jl_crc32c(0, sysimg, len) != (uint32_t)checksum) { - restored = jl_get_exceptionf(jl_errorexception_type, "Error reading system image file."); + if (needs_permalloc) + sysimg = (char*)jl_gc_perm_alloc(len, 0, 64, 0); + else + sysimg = &f->buf[f->bpos]; + if (needs_permalloc) + success = ios_readall(f, sysimg, len) == len; + if (!success || jl_crc32c(0, sysimg, len) != (uint32_t)checksum) { + restored = jl_get_exceptionf(jl_errorexception_type, "Error reading package image file."); JL_SIGATOMIC_END(); } else { - ios_close(f); + if (needs_permalloc) + ios_close(f); ios_static_buffer(f, sysimg, len); htable_new(&new_code_instance_validate, 0); pkgcachesizes cachesizes; @@ -3285,11 +3294,11 @@ static void jl_restore_system_image_from_stream(ios_t *f, jl_image_t *image) jl_restore_system_image_from_stream_(f, image, NULL, checksum, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } -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 complete) +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 complete, bool needs_permalloc) { ios_t f; ios_static_buffer(&f, (char*)buf, sz); - jl_value_t *ret = jl_restore_package_image_from_stream(&f, image, depmods, complete); + jl_value_t *ret = jl_restore_package_image_from_stream(&f, image, depmods, complete, needs_permalloc); ios_close(&f); return ret; } @@ -3302,7 +3311,7 @@ JL_DLLEXPORT jl_value_t *jl_restore_incremental(const char *fname, jl_array_t *d "Cache file \"%s\" not found.\n", fname); } jl_image_t pkgimage = {}; - jl_value_t *ret = jl_restore_package_image_from_stream(&f, &pkgimage, depmods, complete); + jl_value_t *ret = jl_restore_package_image_from_stream(&f, &pkgimage, depmods, complete, true); ios_close(&f); return ret; } @@ -3402,7 +3411,7 @@ JL_DLLEXPORT jl_value_t *jl_restore_package_image_from_file(const char *fname, j } #endif - jl_value_t* mod = jl_restore_incremental_from_buf(pkgimg_data, &pkgimage, *plen, depmods, complete); + jl_value_t* mod = jl_restore_incremental_from_buf(pkgimg_data, &pkgimage, *plen, depmods, complete, false); return mod; } diff --git a/test/loading.jl b/test/loading.jl index f98f08103c9d7..ea42abdd1bcba 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1079,5 +1079,26 @@ end end end +@testset "--pkgimages=no" begin + old_depot_path = copy(DEPOT_PATH) + try + tmp = mktempdir() + push!(empty!(DEPOT_PATH), joinpath(tmp, "depot")) + + proj = joinpath(@__DIR__, "project", "Extensions", "HasDepWithExtensions.jl") + for compile in (`--pkgimages=no`, `--pkgimages=no`) # Once when requiring precomilation, once where it is already precompiled + cmd = `$(Base.julia_cmd()) $compile --project=$proj --startup-file=no -e ' + begin + using HasExtensions + using HasDepWithExtensions + end + '` + @test success(cmd) + end + finally + copy!(DEPOT_PATH, old_depot_path) + end +end + empty!(Base.DEPOT_PATH) append!(Base.DEPOT_PATH, original_depot_path) diff --git a/test/precompile.jl b/test/precompile.jl index 0febfecb78b69..557b39610a6d5 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -339,20 +339,17 @@ precompile_test_harness(false) do dir cachedir = joinpath(dir, "compiled", "v$(VERSION.major).$(VERSION.minor)") cachedir2 = joinpath(dir2, "compiled", "v$(VERSION.major).$(VERSION.minor)") cachefile = joinpath(cachedir, "$Foo_module.ji") - if Base.JLOptions().use_pkgimages == 1 - ocachefile = Base.ocachefile_from_cachefile(cachefile) - else - ocachefile = nothing - end - # use _require_from_serialized to ensure that the test fails if - # the module doesn't reload from the image: - @test_warn "@ccallable was already defined for this method name" begin - @test_logs (:warn, "Replacing module `$Foo_module`") begin - m = Base._require_from_serialized(Base.PkgId(Foo), cachefile, ocachefile) - @test isa(m, Module) + if Base.JLOptions().use_pkgimages == 0 + ocachefile=nothing + # use _require_from_serialized to ensure that the test fails if + # the module doesn't reload from the image: + @test_warn "@ccallable was already defined for this method name" begin + @test_logs (:warn, "Replacing module `$Foo_module`") begin + m = Base._require_from_serialized(Base.PkgId(Foo), cachefile, ocachefile) + @test isa(m, Module) + end end end - @test_throws MethodError Foo.foo(17) # world shouldn't be visible yet Base.invokelatest() do # use invokelatest to see the results of loading the compile @test Foo.foo(17) == 18