@@ -122,6 +122,51 @@ impl Counter {
122122
123123}
124124
125+ fn inject_inline_gas ( module : elements:: Module ) -> elements:: Module {
126+ use parity_wasm:: elements:: Instruction :: * ;
127+
128+ static DEFAULT_START_GAS : i32 = 2000000000 ; // 4 billion is too big for signed integer
129+
130+ let global_gas_index = module. globals_space ( ) as u32 ;
131+ println ! ( "total globals before injecting gas global: {:?}" , global_gas_index) ;
132+
133+ let b = builder:: from_module ( module) ;
134+
135+ let mut b2 = b. global ( ) . mutable ( )
136+ . value_type ( ) . i32 ( ) . init_expr ( elements:: Instruction :: I32Const ( DEFAULT_START_GAS ) )
137+ . build ( )
138+ . export ( )
139+ . field ( "gas_global" )
140+ . internal ( ) . global ( global_gas_index)
141+ . build ( ) ;
142+
143+ b2. push_function (
144+ builder:: function ( )
145+ . signature ( ) . param ( ) . i32 ( ) . build ( )
146+ . body ( )
147+ . with_locals ( vec ! [ elements:: Local :: new( 1 , elements:: ValueType :: I32 ) ] )
148+ . with_instructions ( elements:: Instructions :: new ( vec ! [
149+ GetGlobal ( global_gas_index) ,
150+ GetLocal ( 0 ) , // local 0 is the input param
151+ I32Sub ,
152+ TeeLocal ( 1 ) , // save deducted gas to local, because stack item will be consumed by i32.lte_s
153+ I32Const ( 0 as i32 ) ,
154+ I32LtS ,
155+ If ( elements:: BlockType :: NoResult ) ,
156+ Unreachable ,
157+ End ,
158+ GetLocal ( 1 ) , // put deducted gas back on stack
159+ SetGlobal ( global_gas_index) , // save to global
160+ End ,
161+ ] ) )
162+ . build ( )
163+ . build ( )
164+ ) ;
165+
166+ b2. build ( )
167+
168+ }
169+
125170fn inject_grow_counter ( instructions : & mut elements:: Instructions , grow_counter_func : u32 ) -> usize {
126171 use parity_wasm:: elements:: Instruction :: * ;
127172 let mut counter = 0 ;
@@ -292,8 +337,12 @@ pub fn inject_counter(
292337pub fn inject_gas_counter ( module : elements:: Module , rules : & rules:: Set )
293338 -> Result < elements:: Module , elements:: Module >
294339{
340+ let mbuilder = builder:: from_module ( module) ;
341+ let mut module = mbuilder. build ( ) ;
342+
343+ /*
344+ // we are doing inline gas metering, so disable the external metering
295345 // Injecting gas counting external
296- let mut mbuilder = builder:: from_module ( module) ;
297346 let import_sig = mbuilder.push_signature(
298347 builder::signature()
299348 .param().i64()
@@ -315,7 +364,16 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
315364 // (substract all imports that are NOT functions)
316365
317366 let gas_func = module.import_count(elements::ImportCountType::Function) as u32 - 1;
318- let total_func = module. functions_space ( ) as u32 ;
367+ */
368+
369+
370+ // for inline gas function
371+ let gas_func = module. functions_space ( ) as u32 ;
372+
373+ // need to inject inline gas function after the metering statements,
374+ // or the gas function itself with be metered and recursively call itself
375+
376+ let total_func = gas_func + 1 ;
319377 let mut need_grow_counter = false ;
320378 let mut error = false ;
321379
@@ -357,6 +415,9 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
357415
358416 if error { return Err ( module) ; }
359417
418+ // metering calls have been injected, now inject inline gas func
419+ module = inject_inline_gas ( module) ;
420+
360421 if need_grow_counter { Ok ( add_grow_counter ( module, rules, gas_func) ) } else { Ok ( module) }
361422}
362423
0 commit comments