@@ -74,15 +74,20 @@ External links:
7474#include <stdio.h> // printf
7575#include <inttypes.h> // PRIxPTR
7676
77+ #include <zstd.h>
78+
7779#include "julia.h"
7880#include "julia_internal.h"
7981#include "julia_gcext.h"
8082#include "builtin_proto.h"
8183#include "processor.h"
8284#include "serialize.h"
8385
84- #ifndef _OS_WINDOWS_
86+ #ifdef _OS_WINDOWS_
87+ #include <memoryapi.h>
88+ #else
8589#include <dlfcn.h>
90+ #include <sys/mman.h>
8691#endif
8792
8893#include "valgrind.h"
@@ -3080,14 +3085,75 @@ JL_DLLEXPORT jl_image_buf_t jl_preload_sysimg(const char *fname)
30803085 }
30813086}
30823087
3083- // From a shared library handle, verify consistency and return a jl_image_buf_t
3084- static jl_image_buf_t get_image_buf (void * handle , int is_pkgimage )
3088+ typedef void jl_image_unpack_func_t (void * handle , jl_image_buf_t * image );
3089+
3090+ static void jl_prefetch_system_image (const char * data , size_t size )
3091+ {
3092+ size_t page_size = jl_getpagesize (); /* jl_page_size is not set yet when loading sysimg */
3093+ void * start = (void * )((uintptr_t )data & ~(page_size - 1 ));
3094+ size_t size_aligned = LLT_ALIGN (size , page_size );
3095+ #ifdef _OS_WINDOWS_
3096+ WIN32_MEMORY_RANGE_ENTRY entry = {start , size_aligned };
3097+ PrefetchVirtualMemory (GetCurrentProcess (), 1 , & entry , 0 );
3098+ #else
3099+ madvise (start , size_aligned , MADV_WILLNEED );
3100+ #endif
3101+ }
3102+
3103+ JL_DLLEXPORT void jl_image_unpack_uncomp (void * handle , jl_image_buf_t * image )
3104+ {
3105+ size_t * plen ;
3106+ jl_dlsym (handle , "jl_system_image_size" , (void * * )& plen , 1 );
3107+ jl_dlsym (handle , "jl_system_image_data" , (void * * )& image -> data , 1 );
3108+ jl_dlsym (handle , "jl_image_pointers" , (void * * )& image -> pointers , 1 );
3109+ image -> size = * plen ;
3110+ jl_prefetch_system_image (image -> data , image -> size );
3111+ }
3112+
3113+ JL_DLLEXPORT void jl_image_unpack_zstd (void * handle , jl_image_buf_t * image )
30853114{
30863115 size_t * plen ;
30873116 const char * data ;
3088- const void * pointers ;
3089- uint64_t base ;
3117+ jl_dlsym (handle , "jl_system_image_size" , (void * * )& plen , 1 );
3118+ jl_dlsym (handle , "jl_system_image_data" , (void * * )& data , 1 );
3119+ jl_dlsym (handle , "jl_image_pointers" , (void * * )& image -> pointers , 1 );
3120+ jl_prefetch_system_image (data , * plen );
3121+ image -> size = ZSTD_getFrameContentSize (data , * plen );
3122+ size_t page_size = jl_getpagesize (); /* jl_page_size is not set yet when loading sysimg */
3123+ size_t aligned_size = LLT_ALIGN (image -> size , page_size );
3124+ #if defined(_OS_WINDOWS_ )
3125+ size_t large_page_size = GetLargePageMinimum ();
3126+ if (image -> size > 4 * large_page_size ) {
3127+ size_t aligned_size = LLT_ALIGN (image -> size , large_page_size );
3128+ image -> data = (char * )VirtualAlloc (
3129+ NULL , aligned_size , MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES , PAGE_READWRITE );
3130+ }
3131+ else {
3132+ image -> data = (char * )VirtualAlloc (NULL , aligned_size , MEM_COMMIT | MEM_RESERVE ,
3133+ PAGE_READWRITE );
3134+ }
3135+ #else
3136+ image -> data =
3137+ (char * )mmap (NULL , aligned_size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
3138+ #endif
3139+ if (!image -> data || image -> data == (void * )-1 ) {
3140+ jl_printf (JL_STDERR , "ERROR: failed to allocate space for system image\n" );
3141+ jl_exit (1 );
3142+ }
3143+
3144+ ZSTD_decompress ((void * )image -> data , image -> size , data , * plen );
3145+ size_t len = (* plen ) & ~(page_size - 1 );
3146+ #ifdef _OS_WINDOWS_
3147+ if (len )
3148+ VirtualFree ((void * )data , len , MEM_RELEASE );
3149+ #else
3150+ munmap ((void * )data , len );
3151+ #endif
3152+ }
30903153
3154+ // From a shared library handle, verify consistency and return a jl_image_buf_t
3155+ static jl_image_buf_t get_image_buf (void * handle , int is_pkgimage )
3156+ {
30913157 // verify that the linker resolved the symbols in this image against ourselves (libjulia-internal)
30923158 void * * (* get_jl_RTLD_DEFAULT_handle_addr )(void ) = NULL ;
30933159 if (handle != jl_RTLD_DEFAULT_handle ) {
@@ -3096,39 +3162,42 @@ static jl_image_buf_t get_image_buf(void *handle, int is_pkgimage)
30963162 jl_error ("Image file failed consistency check: maybe opened the wrong version?" );
30973163 }
30983164
3165+ jl_image_unpack_func_t * * unpack ;
3166+ jl_image_buf_t image = {
3167+ .kind = JL_IMAGE_KIND_SO ,
3168+ .handle = handle ,
3169+ .pointers = NULL ,
3170+ .data = NULL ,
3171+ .size = 0 ,
3172+ .base = 0 ,
3173+ };
3174+
30993175 // verification passed, lookup the buffer pointers
31003176 if (jl_system_image_size == 0 || is_pkgimage ) {
31013177 // in the usual case, the sysimage was not statically linked to libjulia-internal
31023178 // look up the external sysimage symbols via the dynamic linker
3103- jl_dlsym (handle , "jl_system_image_size " , (void * * )& plen , 1 );
3104- jl_dlsym ( handle , "jl_system_image_data" , ( void * * ) & data , 1 );
3105- jl_dlsym ( handle , "jl_image_pointers" , ( void * * ) & pointers , 1 );
3106- } else {
3179+ jl_dlsym (handle , "jl_image_unpack " , (void * * )& unpack , 1 );
3180+ ( * unpack )( handle , & image );
3181+ }
3182+ else {
31073183 // the sysimage was statically linked directly against libjulia-internal
31083184 // use the internal symbols
3109- plen = & jl_system_image_size ;
3110- pointers = & jl_image_pointers ;
3111- data = & jl_system_image_data ;
3185+ image . size = jl_system_image_size ;
3186+ image . pointers = & jl_image_pointers ;
3187+ image . data = & jl_system_image_data ;
31123188 }
31133189
31143190#ifdef _OS_WINDOWS_
3115- base = (intptr_t )handle ;
3191+ image . base = (intptr_t )handle ;
31163192#else
31173193 Dl_info dlinfo ;
3118- if (dladdr ((void * )pointers , & dlinfo ) != 0 )
3119- base = (intptr_t )dlinfo .dli_fbase ;
3194+ if (dladdr ((void * )image . pointers , & dlinfo ) != 0 )
3195+ image . base = (intptr_t )dlinfo .dli_fbase ;
31203196 else
3121- base = 0 ;
3197+ image . base = 0 ;
31223198#endif
31233199
3124- return (jl_image_buf_t ) {
3125- .kind = JL_IMAGE_KIND_SO ,
3126- .handle = handle ,
3127- .pointers = pointers ,
3128- .data = data ,
3129- .size = * plen ,
3130- .base = base ,
3131- };
3200+ return image ;
31323201}
31333202
31343203// Allow passing in a module handle directly, rather than a path
0 commit comments