@@ -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"
@@ -3082,14 +3087,75 @@ JL_DLLEXPORT jl_image_buf_t jl_preload_sysimg(const char *fname)
30823087 }
30833088}
30843089
3085- // From a shared library handle, verify consistency and return a jl_image_buf_t
3086- static jl_image_buf_t get_image_buf (void * handle , int is_pkgimage )
3090+ typedef void jl_image_unpack_func_t (void * handle , jl_image_buf_t * image );
3091+
3092+ static void jl_prefetch_system_image (const char * data , size_t size )
3093+ {
3094+ size_t page_size = jl_getpagesize (); /* jl_page_size is not set yet when loading sysimg */
3095+ void * start = (void * )((uintptr_t )data & ~(page_size - 1 ));
3096+ size_t size_aligned = LLT_ALIGN (size , page_size );
3097+ #ifdef _OS_WINDOWS_
3098+ WIN32_MEMORY_RANGE_ENTRY entry = {start , size_aligned };
3099+ PrefetchVirtualMemory (GetCurrentProcess (), 1 , & entry , 0 );
3100+ #else
3101+ madvise (start , size_aligned , MADV_WILLNEED );
3102+ #endif
3103+ }
3104+
3105+ JL_DLLEXPORT void jl_image_unpack_uncomp (void * handle , jl_image_buf_t * image )
3106+ {
3107+ size_t * plen ;
3108+ jl_dlsym (handle , "jl_system_image_size" , (void * * )& plen , 1 );
3109+ jl_dlsym (handle , "jl_system_image_data" , (void * * )& image -> data , 1 );
3110+ jl_dlsym (handle , "jl_image_pointers" , (void * * )& image -> pointers , 1 );
3111+ image -> size = * plen ;
3112+ jl_prefetch_system_image (image -> data , image -> size );
3113+ }
3114+
3115+ JL_DLLEXPORT void jl_image_unpack_zstd (void * handle , jl_image_buf_t * image )
30873116{
30883117 size_t * plen ;
30893118 const char * data ;
3090- const void * pointers ;
3091- uint64_t base ;
3119+ jl_dlsym (handle , "jl_system_image_size" , (void * * )& plen , 1 );
3120+ jl_dlsym (handle , "jl_system_image_data" , (void * * )& data , 1 );
3121+ jl_dlsym (handle , "jl_image_pointers" , (void * * )& image -> pointers , 1 );
3122+ jl_prefetch_system_image (data , * plen );
3123+ image -> size = ZSTD_getFrameContentSize (data , * plen );
3124+ size_t page_size = jl_getpagesize (); /* jl_page_size is not set yet when loading sysimg */
3125+ size_t aligned_size = LLT_ALIGN (image -> size , page_size );
3126+ #if defined(_OS_WINDOWS_ )
3127+ size_t large_page_size = GetLargePageMinimum ();
3128+ if (image -> size > 4 * large_page_size ) {
3129+ size_t aligned_size = LLT_ALIGN (image -> size , large_page_size );
3130+ image -> data = (char * )VirtualAlloc (
3131+ NULL , aligned_size , MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES , PAGE_READWRITE );
3132+ }
3133+ else {
3134+ image -> data = (char * )VirtualAlloc (NULL , aligned_size , MEM_COMMIT | MEM_RESERVE ,
3135+ PAGE_READWRITE );
3136+ }
3137+ #else
3138+ image -> data =
3139+ (char * )mmap (NULL , aligned_size , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
3140+ #endif
3141+ if (!image -> data || image -> data == (void * )-1 ) {
3142+ jl_printf (JL_STDERR , "ERROR: failed to allocate space for system image\n" );
3143+ jl_exit (1 );
3144+ }
3145+
3146+ ZSTD_decompress ((void * )image -> data , image -> size , data , * plen );
3147+ size_t len = (* plen ) & ~(page_size - 1 );
3148+ #ifdef _OS_WINDOWS_
3149+ if (len )
3150+ VirtualFree ((void * )data , len , MEM_RELEASE );
3151+ #else
3152+ munmap ((void * )data , len );
3153+ #endif
3154+ }
30923155
3156+ // From a shared library handle, verify consistency and return a jl_image_buf_t
3157+ static jl_image_buf_t get_image_buf (void * handle , int is_pkgimage )
3158+ {
30933159 // verify that the linker resolved the symbols in this image against ourselves (libjulia-internal)
30943160 void * * (* get_jl_RTLD_DEFAULT_handle_addr )(void ) = NULL ;
30953161 if (handle != jl_RTLD_DEFAULT_handle ) {
@@ -3098,39 +3164,42 @@ static jl_image_buf_t get_image_buf(void *handle, int is_pkgimage)
30983164 jl_error ("Image file failed consistency check: maybe opened the wrong version?" );
30993165 }
31003166
3167+ jl_image_unpack_func_t * * unpack ;
3168+ jl_image_buf_t image = {
3169+ .kind = JL_IMAGE_KIND_SO ,
3170+ .handle = handle ,
3171+ .pointers = NULL ,
3172+ .data = NULL ,
3173+ .size = 0 ,
3174+ .base = 0 ,
3175+ };
3176+
31013177 // verification passed, lookup the buffer pointers
31023178 if (jl_system_image_size == 0 || is_pkgimage ) {
31033179 // in the usual case, the sysimage was not statically linked to libjulia-internal
31043180 // look up the external sysimage symbols via the dynamic linker
3105- jl_dlsym (handle , "jl_system_image_size " , (void * * )& plen , 1 );
3106- jl_dlsym ( handle , "jl_system_image_data" , ( void * * ) & data , 1 );
3107- jl_dlsym ( handle , "jl_image_pointers" , ( void * * ) & pointers , 1 );
3108- } else {
3181+ jl_dlsym (handle , "jl_image_unpack " , (void * * )& unpack , 1 );
3182+ ( * unpack )( handle , & image );
3183+ }
3184+ else {
31093185 // the sysimage was statically linked directly against libjulia-internal
31103186 // use the internal symbols
3111- plen = & jl_system_image_size ;
3112- pointers = & jl_image_pointers ;
3113- data = & jl_system_image_data ;
3187+ image . size = jl_system_image_size ;
3188+ image . pointers = & jl_image_pointers ;
3189+ image . data = & jl_system_image_data ;
31143190 }
31153191
31163192#ifdef _OS_WINDOWS_
3117- base = (intptr_t )handle ;
3193+ image . base = (intptr_t )handle ;
31183194#else
31193195 Dl_info dlinfo ;
3120- if (dladdr ((void * )pointers , & dlinfo ) != 0 )
3121- base = (intptr_t )dlinfo .dli_fbase ;
3196+ if (dladdr ((void * )image . pointers , & dlinfo ) != 0 )
3197+ image . base = (intptr_t )dlinfo .dli_fbase ;
31223198 else
3123- base = 0 ;
3199+ image . base = 0 ;
31243200#endif
31253201
3126- return (jl_image_buf_t ) {
3127- .kind = JL_IMAGE_KIND_SO ,
3128- .handle = handle ,
3129- .pointers = pointers ,
3130- .data = data ,
3131- .size = * plen ,
3132- .base = base ,
3133- };
3202+ return image ;
31343203}
31353204
31363205// Allow passing in a module handle directly, rather than a path
0 commit comments