22
33use crate :: {
44 compiled_blob:: CompiledBlob ,
5- memory:: { BranchProtection , JITMemoryProvider , SystemMemoryProvider } ,
5+ memory:: { BranchProtection , JITMemoryKind , JITMemoryProvider , SystemMemoryProvider } ,
66} ;
77use cranelift_codegen:: binemit:: Reloc ;
88use cranelift_codegen:: isa:: { OwnedTargetIsa , TargetIsa } ;
@@ -19,7 +19,6 @@ use std::cell::RefCell;
1919use std:: collections:: HashMap ;
2020use std:: ffi:: CString ;
2121use std:: io:: Write ;
22- use std:: ptr;
2322use target_lexicon:: PointerWidth ;
2423
2524const WRITABLE_DATA_ALIGNMENT : u64 = 0x8 ;
@@ -217,7 +216,7 @@ impl JITModule {
217216 let ( name, linkage) = if ModuleDeclarations :: is_function ( name) {
218217 let func_id = FuncId :: from_name ( name) ;
219218 match & self . compiled_functions [ func_id] {
220- Some ( compiled) => return compiled. ptr ,
219+ Some ( compiled) => return compiled. ptr ( ) ,
221220 None => {
222221 let decl = self . declarations . get_function_decl ( func_id) ;
223222 ( & decl. name , decl. linkage )
@@ -226,7 +225,7 @@ impl JITModule {
226225 } else {
227226 let data_id = DataId :: from_name ( name) ;
228227 match & self . compiled_data_objects [ data_id] {
229- Some ( compiled) => return compiled. ptr ,
228+ Some ( compiled) => return compiled. ptr ( ) ,
230229 None => {
231230 let decl = self . declarations . get_data_decl ( data_id) ;
232231 ( & decl. name , decl. linkage )
@@ -251,7 +250,7 @@ impl JITModule {
251250 }
252251 ModuleRelocTarget :: FunctionOffset ( func_id, offset) => {
253252 match & self . compiled_functions [ * func_id] {
254- Some ( compiled) => return compiled. ptr . wrapping_add ( * offset as usize ) ,
253+ Some ( compiled) => return compiled. ptr ( ) . wrapping_add ( * offset as usize ) ,
255254 None => todo ! ( ) ,
256255 }
257256 }
@@ -271,7 +270,7 @@ impl JITModule {
271270 ) ;
272271 info. as_ref ( )
273272 . expect ( "function must be compiled before it can be finalized" )
274- . ptr
273+ . ptr ( )
275274 }
276275
277276 /// Returns the address and size of a finalized data object.
@@ -288,10 +287,10 @@ impl JITModule {
288287 . as_ref ( )
289288 . expect ( "data object must be compiled before it can be finalized" ) ;
290289
291- ( compiled. ptr , compiled. size )
290+ ( compiled. ptr ( ) , compiled. size ( ) )
292291 }
293292
294- fn record_function_for_perf ( & self , ptr : * mut u8 , size : usize , name : & str ) {
293+ fn record_function_for_perf ( & self , ptr : * const u8 , size : usize , name : & str ) {
295294 // The Linux perf tool supports JIT code via a /tmp/perf-$PID.map file,
296295 // which contains memory regions and their associated names. If we
297296 // are profiling with perf and saving binaries to PERF_BUILDID_DIR
@@ -407,8 +406,7 @@ impl JITModule {
407406 let data = self . compiled_functions [ func]
408407 . as_ref ( )
409408 . unwrap ( )
410- . exception_data
411- . as_ref ( ) ?;
409+ . wasmtime_exception_data ( ) ?;
412410 let exception_table = wasmtime_unwinder:: ExceptionTable :: parse ( data) . ok ( ) ?;
413411 Some ( ( start, exception_table) )
414412 }
@@ -485,22 +483,9 @@ impl Module for JITModule {
485483 let alignment = res. buffer . alignment as u64 ;
486484 let compiled_code = ctx. compiled_code ( ) . unwrap ( ) ;
487485
488- let size = compiled_code. code_info ( ) . total_size as usize ;
489486 let align = alignment
490487 . max ( self . isa . function_alignment ( ) . minimum as u64 )
491488 . max ( self . isa . symbol_alignment ( ) ) ;
492- let ptr =
493- self . memory
494- . allocate_readexec ( size, align)
495- . map_err ( |e| ModuleError :: Allocation {
496- message : "unable to alloc function" ,
497- err : e,
498- } ) ?;
499-
500- {
501- let mem = unsafe { std:: slice:: from_raw_parts_mut ( ptr, size) } ;
502- mem. copy_from_slice ( compiled_code. code_buffer ( ) ) ;
503- }
504489
505490 let relocs = compiled_code
506491 . buffer
@@ -509,22 +494,8 @@ impl Module for JITModule {
509494 . map ( |reloc| ModuleReloc :: from_mach_reloc ( reloc, & ctx. func , id) )
510495 . collect ( ) ;
511496
512- self . record_function_for_perf ( ptr, size, & decl. linkage_name ( id) ) ;
513- self . compiled_functions [ id] = Some ( CompiledBlob {
514- ptr,
515- size,
516- relocs,
517- #[ cfg( feature = "wasmtime-unwinder" ) ]
518- exception_data : None ,
519- } ) ;
520-
521- let range_start = ptr as usize ;
522- let range_end = range_start + size;
523- // These will be sorted when we finalize.
524- self . code_ranges . push ( ( range_start, range_end, id) ) ;
525-
526497 #[ cfg( feature = "wasmtime-unwinder" ) ]
527- {
498+ let wasmtime_exception_data = {
528499 let mut exception_builder = wasmtime_unwinder:: ExceptionTableBuilder :: default ( ) ;
529500 exception_builder
530501 . add_func ( 0 , compiled_code. buffer . call_sites ( ) )
@@ -533,9 +504,25 @@ impl Module for JITModule {
533504 "Invalid exception data" . into ( ) ,
534505 ) )
535506 } ) ?;
536- self . compiled_functions [ id] . as_mut ( ) . unwrap ( ) . exception_data =
537- Some ( exception_builder. to_vec ( ) ) ;
538- }
507+ Some ( exception_builder. to_vec ( ) )
508+ } ;
509+
510+ let blob = self . compiled_functions [ id] . insert ( CompiledBlob :: new (
511+ & mut * self . memory ,
512+ compiled_code. code_buffer ( ) ,
513+ align,
514+ relocs,
515+ #[ cfg( feature = "wasmtime-unwinder" ) ]
516+ wasmtime_exception_data,
517+ JITMemoryKind :: Executable ,
518+ ) ?) ;
519+ let ( ptr, size) = ( blob. ptr ( ) , blob. size ( ) ) ;
520+ self . record_function_for_perf ( ptr, size, & decl. linkage_name ( id) ) ;
521+
522+ let range_start = ptr. addr ( ) ;
523+ let range_end = range_start + size;
524+ // These will be sorted when we finalize.
525+ self . code_ranges . push ( ( range_start, range_end, id) ) ;
539526
540527 self . functions_to_finalize . push ( id) ;
541528
@@ -563,30 +550,21 @@ impl Module for JITModule {
563550 ) ) ;
564551 }
565552
566- let size = bytes. len ( ) ;
567553 let align = alignment
568554 . max ( self . isa . function_alignment ( ) . minimum as u64 )
569555 . max ( self . isa . symbol_alignment ( ) ) ;
570- let ptr =
571- self . memory
572- . allocate_readexec ( size, align)
573- . map_err ( |e| ModuleError :: Allocation {
574- message : "unable to alloc function bytes" ,
575- err : e,
576- } ) ?;
577-
578- unsafe {
579- ptr:: copy_nonoverlapping ( bytes. as_ptr ( ) , ptr, size) ;
580- }
581556
582- self . record_function_for_perf ( ptr , size , & decl . linkage_name ( id ) ) ;
583- self . compiled_functions [ id ] = Some ( CompiledBlob {
584- ptr ,
585- size ,
586- relocs : relocs . to_owned ( ) ,
557+ let blob = self . compiled_functions [ id ] . insert ( CompiledBlob :: new (
558+ & mut * self . memory ,
559+ bytes ,
560+ align ,
561+ relocs. to_owned ( ) ,
587562 #[ cfg( feature = "wasmtime-unwinder" ) ]
588- exception_data : None ,
589- } ) ;
563+ None ,
564+ JITMemoryKind :: Executable ,
565+ ) ?) ;
566+ let ( ptr, size) = ( blob. ptr ( ) , blob. size ( ) ) ;
567+ self . record_function_for_perf ( ptr, size, & decl. linkage_name ( id) ) ;
590568
591569 self . functions_to_finalize . push ( id) ;
592570
@@ -620,97 +598,62 @@ impl Module for JITModule {
620598 used : _,
621599 } = data;
622600
623- // Make sure to allocate at least 1 byte. Allocating 0 bytes is UB. Previously a dummy
624- // value was used, however as it turns out this will cause pc-relative relocations to
625- // fail on architectures where pc-relative offsets are range restricted as the dummy
626- // value is not close enough to the code that has the pc-relative relocation.
627- let alloc_size = std:: cmp:: max ( init. size ( ) , 1 ) ;
628-
629- let ptr = if decl. writable {
630- self . memory
631- . allocate_readwrite ( alloc_size, align. unwrap_or ( WRITABLE_DATA_ALIGNMENT ) )
632- . map_err ( |e| ModuleError :: Allocation {
633- message : "unable to alloc writable data" ,
634- err : e,
635- } ) ?
601+ let ( align, kind) = if decl. writable {
602+ (
603+ align. unwrap_or ( WRITABLE_DATA_ALIGNMENT ) ,
604+ JITMemoryKind :: Writable ,
605+ )
636606 } else {
637- self . memory
638- . allocate_readonly ( alloc_size, align. unwrap_or ( READONLY_DATA_ALIGNMENT ) )
639- . map_err ( |e| ModuleError :: Allocation {
640- message : "unable to alloc readonly data" ,
641- err : e,
642- } ) ?
607+ (
608+ align. unwrap_or ( READONLY_DATA_ALIGNMENT ) ,
609+ JITMemoryKind :: ReadOnly ,
610+ )
643611 } ;
644612
645- if ptr. is_null ( ) {
646- // FIXME pass a Layout to allocate and only compute the layout once.
647- std:: alloc:: handle_alloc_error (
648- std:: alloc:: Layout :: from_size_align (
649- alloc_size,
650- align. unwrap_or ( READONLY_DATA_ALIGNMENT ) . try_into ( ) . unwrap ( ) ,
651- )
652- . unwrap ( ) ,
653- ) ;
654- }
655-
656- match * init {
657- Init :: Uninitialized => {
658- panic ! ( "data is not initialized yet" ) ;
659- }
660- Init :: Zeros { size } => {
661- unsafe { ptr:: write_bytes ( ptr, 0 , size) } ;
662- }
663- Init :: Bytes { ref contents } => {
664- let src = contents. as_ptr ( ) ;
665- unsafe { ptr:: copy_nonoverlapping ( src, ptr, contents. len ( ) ) } ;
666- }
667- }
668-
669613 let pointer_reloc = match self . isa . triple ( ) . pointer_width ( ) . unwrap ( ) {
670614 PointerWidth :: U16 => panic ! ( ) ,
671615 PointerWidth :: U32 => Reloc :: Abs4 ,
672616 PointerWidth :: U64 => Reloc :: Abs8 ,
673617 } ;
674618 let relocs = data. all_relocs ( pointer_reloc) . collect :: < Vec < _ > > ( ) ;
675619
676- self . compiled_data_objects [ id] = Some ( CompiledBlob {
677- ptr,
678- size : init. size ( ) ,
679- relocs,
680- #[ cfg( feature = "wasmtime-unwinder" ) ]
681- exception_data : None ,
620+ self . compiled_data_objects [ id] = Some ( match * init {
621+ Init :: Uninitialized => {
622+ panic ! ( "data is not initialized yet" ) ;
623+ }
624+ Init :: Zeros { size } => CompiledBlob :: new_zeroed (
625+ & mut * self . memory ,
626+ size. max ( 1 ) ,
627+ align,
628+ relocs,
629+ #[ cfg( feature = "wasmtime-unwinder" ) ]
630+ None ,
631+ kind,
632+ ) ?,
633+ Init :: Bytes { ref contents } => CompiledBlob :: new (
634+ & mut * self . memory ,
635+ if contents. is_empty ( ) {
636+ // Make sure to allocate at least 1 byte. Allocating 0 bytes is UB. Previously
637+ // a dummy value was used, however as it turns out this will cause pc-relative
638+ // relocations to fail on architectures where pc-relative offsets are range
639+ // restricted as the dummy value is not close enough to the code that has the
640+ // pc-relative relocation.
641+ & [ 0 ]
642+ } else {
643+ & contents[ ..]
644+ } ,
645+ align,
646+ relocs,
647+ #[ cfg( feature = "wasmtime-unwinder" ) ]
648+ None ,
649+ kind,
650+ ) ?,
682651 } ) ;
652+
683653 self . data_objects_to_finalize . push ( id) ;
684654
685655 Ok ( ( ) )
686656 }
687-
688- fn get_name ( & self , name : & str ) -> Option < cranelift_module:: FuncOrDataId > {
689- self . declarations ( ) . get_name ( name)
690- }
691-
692- fn target_config ( & self ) -> cranelift_codegen:: isa:: TargetFrontendConfig {
693- self . isa ( ) . frontend_config ( )
694- }
695-
696- fn make_context ( & self ) -> cranelift_codegen:: Context {
697- let mut ctx = cranelift_codegen:: Context :: new ( ) ;
698- ctx. func . signature . call_conv = self . isa ( ) . default_call_conv ( ) ;
699- ctx
700- }
701-
702- fn clear_context ( & self , ctx : & mut cranelift_codegen:: Context ) {
703- ctx. clear ( ) ;
704- ctx. func . signature . call_conv = self . isa ( ) . default_call_conv ( ) ;
705- }
706-
707- fn make_signature ( & self ) -> ir:: Signature {
708- ir:: Signature :: new ( self . isa ( ) . default_call_conv ( ) )
709- }
710-
711- fn clear_signature ( & self , sig : & mut ir:: Signature ) {
712- sig. clear ( self . isa ( ) . default_call_conv ( ) ) ;
713- }
714657}
715658
716659#[ cfg( not( windows) ) ]
@@ -728,6 +671,7 @@ fn lookup_with_dlsym(name: &str) -> Option<*const u8> {
728671#[ cfg( windows) ]
729672fn lookup_with_dlsym ( name : & str ) -> Option < * const u8 > {
730673 use std:: os:: windows:: io:: RawHandle ;
674+ use std:: ptr;
731675 use windows_sys:: Win32 :: Foundation :: HMODULE ;
732676 use windows_sys:: Win32 :: System :: LibraryLoader ;
733677
@@ -763,13 +707,7 @@ fn use_bti(isa_flags: &Vec<settings::Value>) -> bool {
763707 . map_or ( false , |f| f. as_bool ( ) . unwrap_or ( false ) )
764708}
765709
766- #[ cfg( test) ]
767- mod tests {
768- use super :: * ;
769-
770- #[ test]
771- fn test_jit_module_is_send ( ) {
772- fn assert_is_send < T : Send > ( ) { }
773- assert_is_send :: < JITModule > ( ) ;
774- }
775- }
710+ const _ASSERT_JIT_MODULE_IS_SEND: ( ) = {
711+ const fn assert_is_send < T : Send > ( ) { }
712+ assert_is_send :: < JITModule > ( ) ;
713+ } ;
0 commit comments