@@ -86,9 +86,9 @@ type Program struct {
86
86
87
87
contract * Contract
88
88
89
- instructions []instruction // instruction set
90
- mapping map [uint64 ]int // real PC mapping to array indices
91
- destinations map [uint64 ]struct {} // cached jump destinations
89
+ instructions []programInstruction // instruction set
90
+ mapping map [uint64 ]uint64 // real PC mapping to array indices
91
+ destinations map [uint64 ]struct {} // cached jump destinations
92
92
93
93
code []byte
94
94
}
@@ -97,7 +97,7 @@ type Program struct {
97
97
func NewProgram (code []byte ) * Program {
98
98
program := & Program {
99
99
Id : crypto .Sha3Hash (code ),
100
- mapping : make (map [uint64 ]int ),
100
+ mapping : make (map [uint64 ]uint64 ),
101
101
destinations : make (map [uint64 ]struct {}),
102
102
code : code ,
103
103
}
@@ -118,10 +118,12 @@ func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
118
118
baseOp = DUP1
119
119
}
120
120
base := _baseCheck [baseOp ]
121
- instr := instruction {op , pc , fn , data , base .gas , base .stackPop , base .stackPush }
121
+
122
+ returns := op == RETURN || op == SUICIDE || op == STOP
123
+ instr := instruction {op , pc , fn , data , base .gas , base .stackPop , base .stackPush , returns }
122
124
123
125
p .instructions = append (p .instructions , instr )
124
- p .mapping [pc ] = len (p .instructions ) - 1
126
+ p .mapping [pc ] = uint64 ( len (p .instructions ) - 1 )
125
127
}
126
128
127
129
// CompileProgram compiles the given program and return an error when it fails
@@ -301,21 +303,8 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
301
303
contract .Input = input
302
304
303
305
var (
304
- caller = contract .caller
305
- statedb = env .Db ()
306
- pc int = program .mapping [pcstart ]
307
- instrCount = 0
308
-
309
- jump = func (to * big.Int ) error {
310
- if ! validDest (program .destinations , to ) {
311
- nop := contract .GetOp (to .Uint64 ())
312
- return fmt .Errorf ("invalid jump destination (%v) %v" , nop , to )
313
- }
314
-
315
- pc = program .mapping [to .Uint64 ()]
316
-
317
- return nil
318
- }
306
+ pc uint64 = program .mapping [pcstart ]
307
+ instrCount = 0
319
308
)
320
309
321
310
if glog .V (logger .Debug ) {
@@ -326,62 +315,19 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
326
315
}()
327
316
}
328
317
329
- for pc < len (program .instructions ) {
318
+ for pc < uint64 ( len (program .instructions ) ) {
330
319
instrCount ++
331
320
332
321
instr := program .instructions [pc ]
333
322
334
- // calculate the new memory size and gas price for the current executing opcode
335
- newMemSize , cost , err := jitCalculateGasAndSize (env , contract , caller , instr , statedb , mem , stack )
323
+ ret , err := instr .do (program , & pc , env , contract , mem , stack )
336
324
if err != nil {
337
325
return nil , err
338
326
}
339
327
340
- // Use the calculated gas. When insufficient gas is present, use all gas and return an
341
- // Out Of Gas error
342
- if ! contract .UseGas (cost ) {
343
- return nil , OutOfGasError
344
- }
345
- // Resize the memory calculated previously
346
- mem .Resize (newMemSize .Uint64 ())
347
-
348
- // These opcodes return an argument and are thefor handled
349
- // differently from the rest of the opcodes
350
- switch instr .op {
351
- case JUMP :
352
- if err := jump (stack .pop ()); err != nil {
353
- return nil , err
354
- }
355
- continue
356
- case JUMPI :
357
- pos , cond := stack .pop (), stack .pop ()
358
-
359
- if cond .Cmp (common .BigTrue ) >= 0 {
360
- if err := jump (pos ); err != nil {
361
- return nil , err
362
- }
363
- continue
364
- }
365
- case RETURN :
366
- offset , size := stack .pop (), stack .pop ()
367
- ret := mem .GetPtr (offset .Int64 (), size .Int64 ())
368
-
328
+ if instr .halts () {
369
329
return contract .Return (ret ), nil
370
- case SUICIDE :
371
- instr .fn (instr , nil , env , contract , mem , stack )
372
-
373
- return contract .Return (nil ), nil
374
- case STOP :
375
- return contract .Return (nil ), nil
376
- default :
377
- if instr .fn == nil {
378
- return nil , fmt .Errorf ("Invalid opcode %x" , instr .op )
379
- }
380
-
381
- instr .fn (instr , nil , env , contract , mem , stack )
382
330
}
383
-
384
- pc ++
385
331
}
386
332
387
333
contract .Input = nil
@@ -403,7 +349,7 @@ func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
403
349
404
350
// jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
405
351
// the operation. This does not reduce gas or resizes the memory.
406
- func jitCalculateGasAndSize (env Environment , contract * Contract , caller ContractRef , instr instruction , statedb Database , mem * Memory , stack * stack ) (* big.Int , * big.Int , error ) {
352
+ func jitCalculateGasAndSize (env Environment , contract * Contract , instr instruction , statedb Database , mem * Memory , stack * stack ) (* big.Int , * big.Int , error ) {
407
353
var (
408
354
gas = new (big.Int )
409
355
newMemSize * big.Int = new (big.Int )
0 commit comments