@@ -136,6 +136,50 @@ impl Counter {
136136 }
137137}
138138
139+ fn inject_inline_gas ( module : elements:: Module ) -> elements:: Module {
140+ use parity_wasm:: elements:: Instruction :: * ;
141+
142+ static DEFAULT_START_GAS : i32 = 2000000000 ; // 4 billion is too big for signed integer
143+
144+ let global_gas_index = module. globals_space ( ) as u32 ;
145+ println ! ( "total globals before injecting gas global: {:?}" , global_gas_index) ;
146+
147+ let b = builder:: from_module ( module) ;
148+
149+ let mut b2 = b. global ( ) . mutable ( )
150+ . value_type ( ) . i32 ( ) . init_expr ( elements:: Instruction :: I32Const ( DEFAULT_START_GAS ) )
151+ . build ( )
152+ . export ( )
153+ . field ( "gas_global" )
154+ . internal ( ) . global ( global_gas_index)
155+ . build ( ) ;
156+
157+ b2. push_function (
158+ builder:: function ( )
159+ . signature ( ) . param ( ) . i32 ( ) . build ( )
160+ . body ( )
161+ . with_instructions ( elements:: Instructions :: new ( vec ! [
162+ GetGlobal ( global_gas_index) ,
163+ GetLocal ( 0 ) ,
164+ I32Sub ,
165+ TeeLocal ( 0 ) , // overwrite local 0 is a workaround to keep wasm2wat generate names working (dont know how to declare local with builder)
166+ I32Const ( 0 as i32 ) ,
167+ I32LtS ,
168+ If ( elements:: BlockType :: NoResult ) ,
169+ Unreachable ,
170+ End ,
171+ GetLocal ( 0 ) ,
172+ SetGlobal ( global_gas_index) ,
173+ End ,
174+ ] ) )
175+ . build ( )
176+ . build ( )
177+ ) ;
178+
179+ b2. build ( )
180+
181+ }
182+
139183fn inject_grow_counter ( instructions : & mut elements:: Instructions , grow_counter_func : u32 ) -> usize {
140184 use parity_wasm:: elements:: Instruction :: * ;
141185 let mut counter = 0 ;
@@ -312,8 +356,12 @@ pub fn inject_counter(
312356pub fn inject_gas_counter ( module : elements:: Module , rules : & rules:: Set )
313357 -> Result < elements:: Module , elements:: Module >
314358{
359+ let mbuilder = builder:: from_module ( module) ;
360+ let mut module = mbuilder. build ( ) ;
361+
362+ /*
363+ // we are doing inline gas metering, so disable the external metering
315364 // Injecting gas counting external
316- let mut mbuilder = builder:: from_module ( module) ;
317365 let import_sig = mbuilder.push_signature(
318366 builder::signature()
319367 .param().i32()
@@ -335,7 +383,16 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
335383 // (substract all imports that are NOT functions)
336384
337385 let gas_func = module.import_count(elements::ImportCountType::Function) as u32 - 1;
338- let total_func = module. functions_space ( ) as u32 ;
386+ */
387+
388+
389+ // for inline gas function
390+ let gas_func = module. functions_space ( ) as u32 ;
391+
392+ // need to inject inline gas function after the metering statements,
393+ // or the gas function itself with be metered and recursively call itself
394+
395+ let total_func = gas_func + 1 ;
339396 let mut need_grow_counter = false ;
340397 let mut error = false ;
341398
@@ -378,6 +435,9 @@ pub fn inject_gas_counter(module: elements::Module, rules: &rules::Set)
378435
379436 if error { return Err ( module) ; }
380437
438+ // metering calls have been injected, now inject inline gas func
439+ module = inject_inline_gas ( module) ;
440+
381441 if need_grow_counter { Ok ( add_grow_counter ( module, rules, gas_func) ) } else { Ok ( module) }
382442}
383443
0 commit comments