@@ -35,43 +35,56 @@ mod test;
35
35
const TRAP_TIMEOUT : & str = "trap: interrupt" ;
36
36
37
37
/// Handle to a WASM instance, which is terminated if and only if this is dropped.
38
- pub ( crate ) struct WasmInstanceHandle {
39
- // This is the only reference to `WasmInstance` that's not within the instance itself, so we can
40
- // always borrow the `RefCell` with no concern for race conditions.
38
+ pub ( crate ) struct WasmInstance {
39
+ instance : wasmtime:: Instance ,
40
+
41
+ // This is the only reference to `WasmInstanceContext` that's not within the instance itself, so
42
+ // we can always borrow the `RefCell` with no concern for race conditions.
41
43
//
42
44
// Also this is the only strong reference, so the instance will be dropped once this is dropped.
43
45
// The weak references are circulary held by instance itself through host exports.
44
- instance : Rc < RefCell < Option < WasmInstance > > > ,
46
+ instance_ctx : Rc < RefCell < Option < WasmInstanceContext > > > ,
45
47
}
46
48
47
- impl Drop for WasmInstanceHandle {
49
+ impl Drop for WasmInstance {
48
50
fn drop ( & mut self ) {
49
51
// Assert that the instance will be dropped.
50
- assert_eq ! ( Rc :: strong_count( & self . instance ) , 1 ) ;
52
+ assert_eq ! ( Rc :: strong_count( & self . instance_ctx ) , 1 ) ;
51
53
}
52
54
}
53
55
54
- impl WasmInstanceHandle {
56
+ /// Proxies to the WasmInstanceContext.
57
+ impl AscHeap for WasmInstance {
58
+ fn raw_new ( & mut self , bytes : & [ u8 ] ) -> u32 {
59
+ let mut ctx = RefMut :: map ( self . instance_ctx . borrow_mut ( ) , |i| i. as_mut ( ) . unwrap ( ) ) ;
60
+ ctx. raw_new ( bytes)
61
+ }
62
+
63
+ fn get ( & self , offset : u32 , size : u32 ) -> Vec < u8 > {
64
+ self . instance_ctx ( ) . get ( offset, size)
65
+ }
66
+ }
67
+
68
+ impl WasmInstance {
55
69
pub ( crate ) fn handle_json_callback (
56
70
mut self ,
57
71
handler_name : & str ,
58
72
value : & serde_json:: Value ,
59
73
user_data : & store:: Value ,
60
74
) -> Result < BlockState , anyhow:: Error > {
61
- let value = self . instance_mut ( ) . asc_new ( value) ;
62
- let user_data = self . instance_mut ( ) . asc_new ( user_data) ;
75
+ let value = self . asc_new ( value) ;
76
+ let user_data = self . asc_new ( user_data) ;
63
77
64
78
// Invoke the callback
65
79
let func = self
66
- . instance ( )
67
80
. instance
68
81
. get_func ( handler_name)
69
82
. with_context ( || format ! ( "function {} not found" , handler_name) ) ?
70
83
. get2 ( ) ?;
71
84
func ( value. wasm_ptr ( ) , user_data. wasm_ptr ( ) )
72
85
. with_context ( || format ! ( "Failed to handle callback '{}'" , handler_name) ) ?;
73
86
74
- Ok ( self . take_instance ( ) . ctx . state )
87
+ Ok ( self . take_ctx ( ) . ctx . state )
75
88
}
76
89
77
90
pub ( crate ) fn handle_ethereum_log (
@@ -81,42 +94,40 @@ impl WasmInstanceHandle {
81
94
log : Arc < Log > ,
82
95
params : Vec < LogParam > ,
83
96
) -> Result < BlockState , anyhow:: Error > {
84
- let block = self . instance ( ) . ctx . block . clone ( ) ;
97
+ let block = self . instance_ctx ( ) . ctx . block . clone ( ) ;
85
98
86
99
// Prepare an EthereumEvent for the WASM runtime
87
100
// Decide on the destination type using the mapping
88
101
// api version provided in the subgraph manifest
89
- let event = if self . instance ( ) . ctx . host_exports . api_version >= Version :: new ( 0 , 0 , 2 ) {
90
- self . instance_mut ( )
91
- . asc_new :: < AscEthereumEvent < AscEthereumTransaction_0_0_2 > , _ > ( & EthereumEventData {
92
- block : EthereumBlockData :: from ( block. as_ref ( ) ) ,
93
- transaction : EthereumTransactionData :: from ( transaction. deref ( ) ) ,
94
- address : log. address ,
95
- log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
96
- transaction_log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
97
- log_type : log. log_type . clone ( ) ,
98
- params,
99
- } )
100
- . erase ( )
102
+ let event = if self . instance_ctx ( ) . ctx . host_exports . api_version >= Version :: new ( 0 , 0 , 2 ) {
103
+ self . asc_new :: < AscEthereumEvent < AscEthereumTransaction_0_0_2 > , _ > ( & EthereumEventData {
104
+ block : EthereumBlockData :: from ( block. as_ref ( ) ) ,
105
+ transaction : EthereumTransactionData :: from ( transaction. deref ( ) ) ,
106
+ address : log. address ,
107
+ log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
108
+ transaction_log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
109
+ log_type : log. log_type . clone ( ) ,
110
+ params,
111
+ } )
112
+ . erase ( )
101
113
} else {
102
- self . instance_mut ( )
103
- . asc_new :: < AscEthereumEvent < AscEthereumTransaction > , _ > ( & EthereumEventData {
104
- block : EthereumBlockData :: from ( block. as_ref ( ) ) ,
105
- transaction : EthereumTransactionData :: from ( transaction. deref ( ) ) ,
106
- address : log. address ,
107
- log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
108
- transaction_log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
109
- log_type : log. log_type . clone ( ) ,
110
- params,
111
- } )
112
- . erase ( )
114
+ self . asc_new :: < AscEthereumEvent < AscEthereumTransaction > , _ > ( & EthereumEventData {
115
+ block : EthereumBlockData :: from ( block. as_ref ( ) ) ,
116
+ transaction : EthereumTransactionData :: from ( transaction. deref ( ) ) ,
117
+ address : log. address ,
118
+ log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
119
+ transaction_log_index : log. log_index . unwrap_or ( U256 :: zero ( ) ) ,
120
+ log_type : log. log_type . clone ( ) ,
121
+ params,
122
+ } )
123
+ . erase ( )
113
124
} ;
114
125
115
126
// Invoke the event handler
116
127
self . invoke_handler ( handler_name, event) ?;
117
128
118
129
// Return the output state
119
- Ok ( self . take_instance ( ) . ctx . state )
130
+ Ok ( self . take_ctx ( ) . ctx . state )
120
131
}
121
132
122
133
pub ( crate ) fn handle_ethereum_call (
@@ -130,55 +141,56 @@ impl WasmInstanceHandle {
130
141
let call = EthereumCallData {
131
142
to : call. to ,
132
143
from : call. from ,
133
- block : EthereumBlockData :: from ( self . instance ( ) . ctx . block . as_ref ( ) ) ,
144
+ block : EthereumBlockData :: from ( self . instance_ctx ( ) . ctx . block . as_ref ( ) ) ,
134
145
transaction : EthereumTransactionData :: from ( transaction. deref ( ) ) ,
135
146
inputs,
136
147
outputs,
137
148
} ;
138
- let arg = if self . instance ( ) . ctx . host_exports . api_version >= Version :: new ( 0 , 0 , 3 ) {
139
- self . instance_mut ( )
140
- . asc_new :: < AscEthereumCall_0_0_3 , _ > ( & call)
141
- . erase ( )
149
+ let arg = if self . instance_ctx ( ) . ctx . host_exports . api_version >= Version :: new ( 0 , 0 , 3 ) {
150
+ self . asc_new :: < AscEthereumCall_0_0_3 , _ > ( & call) . erase ( )
142
151
} else {
143
- self . instance_mut ( )
144
- . asc_new :: < AscEthereumCall , _ > ( & call)
145
- . erase ( )
152
+ self . asc_new :: < AscEthereumCall , _ > ( & call) . erase ( )
146
153
} ;
147
154
148
155
self . invoke_handler ( handler_name, arg) ?;
149
156
150
- Ok ( self . take_instance ( ) . ctx . state )
157
+ Ok ( self . take_ctx ( ) . ctx . state )
151
158
}
152
159
153
160
pub ( crate ) fn handle_ethereum_block (
154
161
mut self ,
155
162
handler_name : & str ,
156
163
) -> Result < BlockState , anyhow:: Error > {
157
- let block = EthereumBlockData :: from ( self . instance ( ) . ctx . block . as_ref ( ) ) ;
164
+ let block = EthereumBlockData :: from ( self . instance_ctx ( ) . ctx . block . as_ref ( ) ) ;
158
165
159
166
// Prepare an EthereumBlock for the WASM runtime
160
- let arg = self . instance_mut ( ) . asc_new ( & block) ;
167
+ let arg = self . asc_new ( & block) ;
161
168
162
169
self . invoke_handler ( handler_name, arg) ?;
163
170
164
- Ok ( self . take_instance ( ) . ctx . state )
171
+ Ok ( self . take_ctx ( ) . ctx . state )
165
172
}
166
173
167
- pub ( crate ) fn instance_mut ( & mut self ) -> RefMut < ' _ , WasmInstance > {
168
- RefMut :: map ( self . instance . borrow_mut ( ) , |i| i . as_mut ( ) . unwrap ( ) )
174
+ pub ( crate ) fn take_ctx ( & mut self ) -> WasmInstanceContext {
175
+ self . instance_ctx . borrow_mut ( ) . take ( ) . unwrap ( )
169
176
}
170
177
171
- pub ( crate ) fn take_instance ( & mut self ) -> WasmInstance {
172
- self . instance . borrow_mut ( ) . take ( ) . unwrap ( )
178
+ pub ( crate ) fn instance_ctx ( & self ) -> std :: cell :: Ref < ' _ , WasmInstanceContext > {
179
+ std :: cell :: Ref :: map ( self . instance_ctx . borrow ( ) , |i| i . as_ref ( ) . unwrap ( ) )
173
180
}
174
181
175
- pub ( crate ) fn instance ( & self ) -> std:: cell:: Ref < ' _ , WasmInstance > {
176
- std:: cell:: Ref :: map ( self . instance . borrow ( ) , |i| i. as_ref ( ) . unwrap ( ) )
182
+ #[ cfg( test) ]
183
+ pub ( crate ) fn instance_ctx_mut ( & self ) -> std:: cell:: RefMut < ' _ , WasmInstanceContext > {
184
+ std:: cell:: RefMut :: map ( self . instance_ctx . borrow_mut ( ) , |i| i. as_mut ( ) . unwrap ( ) )
185
+ }
186
+
187
+ #[ cfg( test) ]
188
+ pub ( crate ) fn get_func ( & self , func_name : & str ) -> wasmtime:: Func {
189
+ self . instance . get_func ( func_name) . unwrap ( )
177
190
}
178
191
179
192
fn invoke_handler < C > ( & mut self , handler : & str , arg : AscPtr < C > ) -> Result < ( ) , anyhow:: Error > {
180
193
let func = self
181
- . instance ( )
182
194
. instance
183
195
. get_func ( handler)
184
196
. with_context ( || format ! ( "function {} not found" , handler) ) ?;
@@ -190,7 +202,7 @@ impl WasmInstanceHandle {
190
202
format ! (
191
203
"Handler '{}' hit the timeout of '{}' seconds" ,
192
204
handler,
193
- self . instance ( ) . timeout. unwrap( ) . as_secs( )
205
+ self . instance_ctx ( ) . timeout. unwrap( ) . as_secs( )
194
206
) ,
195
207
)
196
208
} else {
@@ -204,11 +216,9 @@ impl WasmInstanceHandle {
204
216
///
205
217
/// ```compile_fail
206
218
/// fn assert_sync<T: Sync>() {}
207
- /// assert_sync::<WasmInstance >();
219
+ /// assert_sync::<WasmInstanceContext >();
208
220
/// ```
209
- pub ( crate ) struct WasmInstance {
210
- instance : wasmtime:: Instance ,
211
-
221
+ pub ( crate ) struct WasmInstanceContext {
212
222
// In the future there may be multiple memories, but currently there is only one memory per
213
223
// module. And at least AS calls it "memory". There is no uninitialized memory in Wasm, memory
214
224
// is zeroed when initialized or grown.
@@ -237,12 +247,12 @@ impl WasmInstance {
237
247
ctx : MappingContext ,
238
248
host_metrics : Arc < HostMetrics > ,
239
249
timeout : Option < Duration > ,
240
- ) -> Result < WasmInstanceHandle , anyhow:: Error > {
250
+ ) -> Result < WasmInstance , anyhow:: Error > {
241
251
let mut linker = wasmtime:: Linker :: new ( & wasmtime:: Store :: new ( valid_module. module . engine ( ) ) ) ;
242
252
243
253
// Used by exports to access the instance context. It is `None` while the module is not yet
244
254
// instantiated. A desirable consequence is that start function cannot access host exports.
245
- let shared_instance : Rc < RefCell < Option < WasmInstance > > > = Rc :: new ( RefCell :: new ( None ) ) ;
255
+ let shared_ctx : Rc < RefCell < Option < WasmInstanceContext > > > = Rc :: new ( RefCell :: new ( None ) ) ;
246
256
247
257
macro_rules! link {
248
258
( $wasm_name: expr, $rust_name: ident, $( $param: ident) ,* ) => {
@@ -258,12 +268,12 @@ impl WasmInstance {
258
268
259
269
// link an import with all the modules that require it.
260
270
for module in modules {
261
- let func_shared_instance = Rc :: downgrade( & shared_instance ) ;
271
+ let func_shared_ctx = Rc :: downgrade( & shared_ctx ) ;
262
272
linker. func(
263
273
module,
264
274
$wasm_name,
265
275
move |$( $param: u32 ) ,* | {
266
- let instance = func_shared_instance . upgrade( ) . unwrap( ) ;
276
+ let instance = func_shared_ctx . upgrade( ) . unwrap( ) ;
267
277
let mut instance = instance. borrow_mut( ) ;
268
278
let instance = instance. as_mut( ) . unwrap( ) ;
269
279
let _section = instance. host_metrics. stopwatch. start_section( $section) ;
@@ -283,10 +293,10 @@ impl WasmInstance {
283
293
. flatten ( ) ;
284
294
285
295
for module in modules {
286
- let func_shared_instance = Rc :: downgrade ( & shared_instance ) ;
296
+ let func_shared_ctx = Rc :: downgrade ( & shared_ctx ) ;
287
297
linker. func ( module, "store.get" , move |entity_ptr : u32 , id_ptr : u32 | {
288
298
let start = Instant :: now ( ) ;
289
- let instance = func_shared_instance . upgrade ( ) . unwrap ( ) ;
299
+ let instance = func_shared_ctx . upgrade ( ) . unwrap ( ) ;
290
300
let mut instance = instance. borrow_mut ( ) ;
291
301
let instance = instance. as_mut ( ) . unwrap ( ) ;
292
302
let stopwatch = & instance. host_metrics . stopwatch ;
@@ -308,10 +318,10 @@ impl WasmInstance {
308
318
. flatten ( ) ;
309
319
310
320
for module in modules {
311
- let func_shared_instance = Rc :: downgrade ( & shared_instance ) ;
321
+ let func_shared_ctx = Rc :: downgrade ( & shared_ctx ) ;
312
322
linker. func ( module, "ethereum.call" , move |call_ptr : u32 | {
313
323
let start = Instant :: now ( ) ;
314
- let instance = func_shared_instance . upgrade ( ) . unwrap ( ) ;
324
+ let instance = func_shared_ctx . upgrade ( ) . unwrap ( ) ;
315
325
let mut instance = instance. borrow_mut ( ) ;
316
326
let instance = instance. as_mut ( ) . unwrap ( ) ;
317
327
let stopwatch = & instance. host_metrics . stopwatch ;
@@ -441,8 +451,7 @@ impl WasmInstance {
441
451
} ) ;
442
452
}
443
453
444
- * shared_instance. borrow_mut ( ) = Some ( WasmInstance {
445
- instance,
454
+ * shared_ctx. borrow_mut ( ) = Some ( WasmInstanceContext {
446
455
memory_allocate : Box :: new ( memory_allocate) ,
447
456
memory,
448
457
ctx,
@@ -456,13 +465,14 @@ impl WasmInstance {
456
465
arena_start_ptr : 0 ,
457
466
} ) ;
458
467
459
- Ok ( WasmInstanceHandle {
460
- instance : shared_instance. clone ( ) ,
468
+ Ok ( WasmInstance {
469
+ instance : instance,
470
+ instance_ctx : shared_ctx,
461
471
} )
462
472
}
463
473
}
464
474
465
- impl AscHeap for WasmInstance {
475
+ impl AscHeap for WasmInstanceContext {
466
476
fn raw_new ( & mut self , bytes : & [ u8 ] ) -> u32 {
467
477
// We request large chunks from the AssemblyScript allocator to use as arenas that we
468
478
// manage directly.
@@ -511,7 +521,7 @@ impl AscHeap for WasmInstance {
511
521
}
512
522
513
523
// Implementation of externals.
514
- impl WasmInstance {
524
+ impl WasmInstanceContext {
515
525
/// function abort(message?: string | null, fileName?: string | null, lineNumber?: u32, columnNumber?: u32): void
516
526
/// Always returns a trap.
517
527
fn abort (
0 commit comments