@@ -102,10 +102,8 @@ impl MemoryPlan {
102
102
pub struct MemoryInitializer {
103
103
/// The index of a linear memory to initialize.
104
104
pub memory_index : MemoryIndex ,
105
- /// Optionally, a global variable giving a base index.
106
- pub base : Option < GlobalIndex > ,
107
- /// The offset to add to the base.
108
- pub offset : u64 ,
105
+ /// The base offset to start this segment at.
106
+ pub offset : ConstExpr ,
109
107
/// The range of the data to write within the linear memory.
110
108
///
111
109
/// This range indexes into a separately stored data section which will be
@@ -201,37 +199,14 @@ impl MemoryInitialization {
201
199
/// only be called as part of initialization, however, as it's structured to
202
200
/// allow learning about memory ahead-of-time at compile time possibly.
203
201
///
204
- /// The various callbacks provided here are used to drive the smaller bits
205
- /// of initialization, such as:
206
- ///
207
- /// * `get_cur_size_in_pages` - gets the current size, in wasm pages, of the
208
- /// memory specified. For compile-time purposes this would be the memory
209
- /// type's minimum size.
210
- ///
211
- /// * `get_global` - gets the value of the global specified. This is
212
- /// statically, via validation, a pointer to the global of the correct
213
- /// type (either u32 or u64 depending on the memory), but the value
214
- /// returned here is `u64`. A `None` value can be returned to indicate
215
- /// that the global's value isn't known yet.
216
- ///
217
- /// * `write` - a callback used to actually write data. This indicates that
218
- /// the specified memory must receive the specified range of data at the
219
- /// specified offset. This can internally return an false error if it
220
- /// wants to fail.
221
- ///
222
202
/// This function will return true if all memory initializers are processed
223
203
/// successfully. If any initializer hits an error or, for example, a
224
204
/// global value is needed but `None` is returned, then false will be
225
205
/// returned. At compile-time this typically means that the "error" in
226
206
/// question needs to be deferred to runtime, and at runtime this means
227
207
/// that an invalid initializer has been found and a trap should be
228
208
/// generated.
229
- pub fn init_memory < T > (
230
- & self ,
231
- state : & mut T ,
232
- init : InitMemory < ' _ , T > ,
233
- mut write : impl FnMut ( & mut T , MemoryIndex , & StaticMemoryInitializer ) -> bool ,
234
- ) -> bool {
209
+ pub fn init_memory ( & self , state : & mut dyn InitMemory ) -> bool {
235
210
let initializers = match self {
236
211
// Fall through below to the segmented memory one-by-one
237
212
// initialization.
@@ -245,7 +220,7 @@ impl MemoryInitialization {
245
220
MemoryInitialization :: Static { map } => {
246
221
for ( index, init) in map {
247
222
if let Some ( init) = init {
248
- let result = write ( state , index, init) ;
223
+ let result = state . write ( index, init) ;
249
224
if !result {
250
225
return result;
251
226
}
@@ -256,28 +231,18 @@ impl MemoryInitialization {
256
231
} ;
257
232
258
233
for initializer in initializers {
259
- let MemoryInitializer {
234
+ let & MemoryInitializer {
260
235
memory_index,
261
- base,
262
- offset,
236
+ ref offset,
263
237
ref data,
264
- } = * initializer;
238
+ } = initializer;
265
239
266
240
// First up determine the start/end range and verify that they're
267
241
// in-bounds for the initial size of the memory at `memory_index`.
268
242
// Note that this can bail if we don't have access to globals yet
269
243
// (e.g. this is a task happening before instantiation at
270
244
// compile-time).
271
- let base = match base {
272
- Some ( index) => match & init {
273
- InitMemory :: Runtime {
274
- get_global_as_u64, ..
275
- } => get_global_as_u64 ( state, index) ,
276
- InitMemory :: CompileTime ( _) => return false ,
277
- } ,
278
- None => 0 ,
279
- } ;
280
- let start = match base. checked_add ( offset) {
245
+ let start = match state. eval_offset ( memory_index, offset) {
281
246
Some ( start) => start,
282
247
None => return false ,
283
248
} ;
@@ -287,13 +252,7 @@ impl MemoryInitialization {
287
252
None => return false ,
288
253
} ;
289
254
290
- let cur_size_in_pages = match & init {
291
- InitMemory :: CompileTime ( module) => module. memory_plans [ memory_index] . memory . minimum ,
292
- InitMemory :: Runtime {
293
- memory_size_in_pages,
294
- ..
295
- } => memory_size_in_pages ( state, memory_index) ,
296
- } ;
255
+ let cur_size_in_pages = state. memory_size_in_pages ( memory_index) ;
297
256
298
257
// Note that this `minimum` can overflow if `minimum` is
299
258
// `1 << 48`, the maximum number of minimum pages for 64-bit
@@ -318,7 +277,7 @@ impl MemoryInitialization {
318
277
offset : start,
319
278
data : data. clone ( ) ,
320
279
} ;
321
- let result = write ( state , memory_index, & init) ;
280
+ let result = state . write ( memory_index, & init) ;
322
281
if !result {
323
282
return result;
324
283
}
@@ -328,25 +287,23 @@ impl MemoryInitialization {
328
287
}
329
288
}
330
289
331
- /// Argument to [`MemoryInitialization::init_memory`] indicating the current
332
- /// status of the instance.
333
- pub enum InitMemory < ' a , T > {
334
- /// This evaluation of memory initializers is happening at compile time.
335
- /// This means that the current state of memories is whatever their initial
336
- /// state is, and additionally globals are not available if data segments
337
- /// have global offsets.
338
- CompileTime ( & ' a Module ) ,
339
-
340
- /// Evaluation of memory initializers is happening at runtime when the
341
- /// instance is available, and callbacks are provided to learn about the
342
- /// instance's state.
343
- Runtime {
344
- /// Returns the size, in wasm pages, of the the memory specified.
345
- memory_size_in_pages : & ' a dyn Fn ( & mut T , MemoryIndex ) -> u64 ,
346
- /// Returns the value of the global, as a `u64`. Note that this may
347
- /// involve zero-extending a 32-bit global to a 64-bit number.
348
- get_global_as_u64 : & ' a dyn Fn ( & mut T , GlobalIndex ) -> u64 ,
349
- } ,
290
+ /// The various callbacks provided here are used to drive the smaller bits of
291
+ /// memory initialization.
292
+ pub trait InitMemory {
293
+ /// Returns the size, in wasm pages, of the the memory specified. For
294
+ /// compile-time purposes this would be the memory type's minimum size.
295
+ fn memory_size_in_pages ( & mut self , memory_index : MemoryIndex ) -> u64 ;
296
+
297
+ /// Returns the value of the constant expression, as a `u64`. Note that
298
+ /// this may involve zero-extending a 32-bit global to a 64-bit number. May
299
+ /// return `None` to indicate that the expression involves a value which is
300
+ /// not available yet.
301
+ fn eval_offset ( & mut self , memory_index : MemoryIndex , expr : & ConstExpr ) -> Option < u64 > ;
302
+
303
+ /// A callback used to actually write data. This indicates that the
304
+ /// specified memory must receive the specified range of data at the
305
+ /// specified offset. This can return false on failure.
306
+ fn write ( & mut self , memory_index : MemoryIndex , init : & StaticMemoryInitializer ) -> bool ;
350
307
}
351
308
352
309
/// Implementation styles for WebAssembly tables.
0 commit comments