1
1
//! Defines `JITModule`.
2
2
3
- use crate :: { compiled_blob:: CompiledBlob , memory:: BranchProtection , memory:: Memory } ;
3
+ use crate :: {
4
+ compiled_blob:: CompiledBlob ,
5
+ memory:: { BranchProtection , JITMemoryProvider , SystemMemoryProvider } ,
6
+ } ;
4
7
use cranelift_codegen:: binemit:: Reloc ;
5
8
use cranelift_codegen:: isa:: { OwnedTargetIsa , TargetIsa } ;
6
9
use cranelift_codegen:: settings:: Configurable ;
@@ -28,6 +31,7 @@ pub struct JITBuilder {
28
31
symbols : HashMap < String , SendWrapper < * const u8 > > ,
29
32
lookup_symbols : Vec < Box < dyn Fn ( & str ) -> Option < * const u8 > + Send > > ,
30
33
libcall_names : Box < dyn Fn ( ir:: LibCall ) -> String + Send + Sync > ,
34
+ memory : Option < Box < dyn JITMemoryProvider > > ,
31
35
}
32
36
33
37
impl JITBuilder {
@@ -91,6 +95,7 @@ impl JITBuilder {
91
95
symbols,
92
96
lookup_symbols,
93
97
libcall_names,
98
+ memory : None ,
94
99
}
95
100
}
96
101
@@ -141,6 +146,14 @@ impl JITBuilder {
141
146
self . lookup_symbols . push ( symbol_lookup_fn) ;
142
147
self
143
148
}
149
+
150
+ /// Set the memory provider for the module.
151
+ ///
152
+ /// If unset, defaults to [`SystemMemoryProvider`].
153
+ pub fn memory_provider ( & mut self , provider : Box < dyn JITMemoryProvider > ) -> & mut Self {
154
+ self . memory = Some ( provider) ;
155
+ self
156
+ }
144
157
}
145
158
146
159
/// A wrapper that impls Send for the contents.
@@ -159,21 +172,14 @@ pub struct JITModule {
159
172
symbols : RefCell < HashMap < String , SendWrapper < * const u8 > > > ,
160
173
lookup_symbols : Vec < Box < dyn Fn ( & str ) -> Option < * const u8 > + Send > > ,
161
174
libcall_names : Box < dyn Fn ( ir:: LibCall ) -> String + Send + Sync > ,
162
- memory : MemoryHandle ,
175
+ memory : Box < dyn JITMemoryProvider > ,
163
176
declarations : ModuleDeclarations ,
164
177
compiled_functions : SecondaryMap < FuncId , Option < CompiledBlob > > ,
165
178
compiled_data_objects : SecondaryMap < DataId , Option < CompiledBlob > > ,
166
179
functions_to_finalize : Vec < FuncId > ,
167
180
data_objects_to_finalize : Vec < DataId > ,
168
181
}
169
182
170
- /// A handle to allow freeing memory allocated by the `Module`.
171
- struct MemoryHandle {
172
- code : Memory ,
173
- readonly : Memory ,
174
- writable : Memory ,
175
- }
176
-
177
183
impl JITModule {
178
184
/// Free memory allocated for code and data segments of compiled functions.
179
185
///
@@ -184,9 +190,7 @@ impl JITModule {
184
190
/// from that module are currently executing and none of the `fn` pointers
185
191
/// are called afterwards.
186
192
pub unsafe fn free_memory ( mut self ) {
187
- self . memory . code . free_memory ( ) ;
188
- self . memory . readonly . free_memory ( ) ;
189
- self . memory . writable . free_memory ( ) ;
193
+ self . memory . free_memory ( ) ;
190
194
}
191
195
192
196
fn lookup_symbol ( & self , name : & str ) -> Option < * const u8 > {
@@ -325,8 +329,12 @@ impl JITModule {
325
329
}
326
330
327
331
// Now that we're done patching, prepare the memory for execution!
328
- self . memory . readonly . set_readonly ( ) ?;
329
- self . memory . code . set_readable_and_executable ( ) ?;
332
+ let branch_protection = if cfg ! ( target_arch = "aarch64" ) && use_bti ( & self . isa . isa_flags ( ) ) {
333
+ BranchProtection :: BTI
334
+ } else {
335
+ BranchProtection :: None
336
+ } ;
337
+ self . memory . finalize ( branch_protection) ?;
330
338
331
339
Ok ( ( ) )
332
340
}
@@ -338,23 +346,15 @@ impl JITModule {
338
346
"cranelift-jit needs is_pic=false"
339
347
) ;
340
348
341
- let branch_protection =
342
- if cfg ! ( target_arch = "aarch64" ) && use_bti ( & builder. isa . isa_flags ( ) ) {
343
- BranchProtection :: BTI
344
- } else {
345
- BranchProtection :: None
346
- } ;
349
+ let memory = builder
350
+ . memory
351
+ . unwrap_or_else ( || Box :: new ( SystemMemoryProvider :: new ( ) ) ) ;
347
352
Self {
348
353
isa : builder. isa ,
349
354
symbols : RefCell :: new ( builder. symbols ) ,
350
355
lookup_symbols : builder. lookup_symbols ,
351
356
libcall_names : builder. libcall_names ,
352
- memory : MemoryHandle {
353
- code : Memory :: new ( branch_protection) ,
354
- // Branch protection is not applicable to non-executable memory.
355
- readonly : Memory :: new ( BranchProtection :: None ) ,
356
- writable : Memory :: new ( BranchProtection :: None ) ,
357
- } ,
357
+ memory,
358
358
declarations : ModuleDeclarations :: default ( ) ,
359
359
compiled_functions : SecondaryMap :: new ( ) ,
360
360
compiled_data_objects : SecondaryMap :: new ( ) ,
@@ -436,15 +436,16 @@ impl Module for JITModule {
436
436
let compiled_code = ctx. compiled_code ( ) . unwrap ( ) ;
437
437
438
438
let size = compiled_code. code_info ( ) . total_size as usize ;
439
- let align = alignment. max ( self . isa . symbol_alignment ( ) ) ;
440
- let ptr = self
441
- . memory
442
- . code
443
- . allocate ( size, align)
444
- . map_err ( |e| ModuleError :: Allocation {
445
- message : "unable to alloc function" ,
446
- err : e,
447
- } ) ?;
439
+ let align = alignment
440
+ . max ( self . isa . function_alignment ( ) . minimum as u64 )
441
+ . max ( self . isa . symbol_alignment ( ) ) ;
442
+ let ptr =
443
+ self . memory
444
+ . allocate_readexec ( size, align)
445
+ . map_err ( |e| ModuleError :: Allocation {
446
+ message : "unable to alloc function" ,
447
+ err : e,
448
+ } ) ?;
448
449
449
450
{
450
451
let mem = unsafe { std:: slice:: from_raw_parts_mut ( ptr, size) } ;
@@ -488,15 +489,16 @@ impl Module for JITModule {
488
489
}
489
490
490
491
let size = bytes. len ( ) ;
491
- let align = alignment. max ( self . isa . symbol_alignment ( ) ) ;
492
- let ptr = self
493
- . memory
494
- . code
495
- . allocate ( size, align)
496
- . map_err ( |e| ModuleError :: Allocation {
497
- message : "unable to alloc function bytes" ,
498
- err : e,
499
- } ) ?;
492
+ let align = alignment
493
+ . max ( self . isa . function_alignment ( ) . minimum as u64 )
494
+ . max ( self . isa . symbol_alignment ( ) ) ;
495
+ let ptr =
496
+ self . memory
497
+ . allocate_readexec ( size, align)
498
+ . map_err ( |e| ModuleError :: Allocation {
499
+ message : "unable to alloc function bytes" ,
500
+ err : e,
501
+ } ) ?;
500
502
501
503
unsafe {
502
504
ptr:: copy_nonoverlapping ( bytes. as_ptr ( ) , ptr, size) ;
@@ -548,16 +550,14 @@ impl Module for JITModule {
548
550
549
551
let ptr = if decl. writable {
550
552
self . memory
551
- . writable
552
- . allocate ( alloc_size, align. unwrap_or ( WRITABLE_DATA_ALIGNMENT ) )
553
+ . allocate_readwrite ( alloc_size, align. unwrap_or ( WRITABLE_DATA_ALIGNMENT ) )
553
554
. map_err ( |e| ModuleError :: Allocation {
554
555
message : "unable to alloc writable data" ,
555
556
err : e,
556
557
} ) ?
557
558
} else {
558
559
self . memory
559
- . readonly
560
- . allocate ( alloc_size, align. unwrap_or ( READONLY_DATA_ALIGNMENT ) )
560
+ . allocate_readonly ( alloc_size, align. unwrap_or ( READONLY_DATA_ALIGNMENT ) )
561
561
. map_err ( |e| ModuleError :: Allocation {
562
562
message : "unable to alloc readonly data" ,
563
563
err : e,
0 commit comments