aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm/jit.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/vm/jit.go')
-rw-r--r--core/vm/jit.go82
1 files changed, 14 insertions, 68 deletions
diff --git a/core/vm/jit.go b/core/vm/jit.go
index 6ad574917..8cb95b860 100644
--- a/core/vm/jit.go
+++ b/core/vm/jit.go
@@ -86,9 +86,9 @@ type Program struct {
contract *Contract
- instructions []instruction // instruction set
- mapping map[uint64]int // real PC mapping to array indices
- destinations map[uint64]struct{} // cached jump destinations
+ instructions []programInstruction // instruction set
+ mapping map[uint64]uint64 // real PC mapping to array indices
+ destinations map[uint64]struct{} // cached jump destinations
code []byte
}
@@ -97,7 +97,7 @@ type Program struct {
func NewProgram(code []byte) *Program {
program := &Program{
Id: crypto.Sha3Hash(code),
- mapping: make(map[uint64]int),
+ mapping: make(map[uint64]uint64),
destinations: make(map[uint64]struct{}),
code: code,
}
@@ -118,10 +118,12 @@ func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
baseOp = DUP1
}
base := _baseCheck[baseOp]
- instr := instruction{op, pc, fn, data, base.gas, base.stackPop, base.stackPush}
+
+ returns := op == RETURN || op == SUICIDE || op == STOP
+ instr := instruction{op, pc, fn, data, base.gas, base.stackPop, base.stackPush, returns}
p.instructions = append(p.instructions, instr)
- p.mapping[pc] = len(p.instructions) - 1
+ p.mapping[pc] = uint64(len(p.instructions) - 1)
}
// 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
contract.Input = input
var (
- caller = contract.caller
- statedb = env.Db()
- pc int = program.mapping[pcstart]
- instrCount = 0
-
- jump = func(to *big.Int) error {
- if !validDest(program.destinations, to) {
- nop := contract.GetOp(to.Uint64())
- return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
- }
-
- pc = program.mapping[to.Uint64()]
-
- return nil
- }
+ pc uint64 = program.mapping[pcstart]
+ instrCount = 0
)
if glog.V(logger.Debug) {
@@ -326,62 +315,19 @@ func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env
}()
}
- for pc < len(program.instructions) {
+ for pc < uint64(len(program.instructions)) {
instrCount++
instr := program.instructions[pc]
- // calculate the new memory size and gas price for the current executing opcode
- newMemSize, cost, err := jitCalculateGasAndSize(env, contract, caller, instr, statedb, mem, stack)
+ ret, err := instr.do(program, &pc, env, contract, mem, stack)
if err != nil {
return nil, err
}
- // Use the calculated gas. When insufficient gas is present, use all gas and return an
- // Out Of Gas error
- if !contract.UseGas(cost) {
- return nil, OutOfGasError
- }
- // Resize the memory calculated previously
- mem.Resize(newMemSize.Uint64())
-
- // These opcodes return an argument and are thefor handled
- // differently from the rest of the opcodes
- switch instr.op {
- case JUMP:
- if err := jump(stack.pop()); err != nil {
- return nil, err
- }
- continue
- case JUMPI:
- pos, cond := stack.pop(), stack.pop()
-
- if cond.Cmp(common.BigTrue) >= 0 {
- if err := jump(pos); err != nil {
- return nil, err
- }
- continue
- }
- case RETURN:
- offset, size := stack.pop(), stack.pop()
- ret := mem.GetPtr(offset.Int64(), size.Int64())
-
+ if instr.halts() {
return contract.Return(ret), nil
- case SUICIDE:
- instr.fn(instr, nil, env, contract, mem, stack)
-
- return contract.Return(nil), nil
- case STOP:
- return contract.Return(nil), nil
- default:
- if instr.fn == nil {
- return nil, fmt.Errorf("Invalid opcode %x", instr.op)
- }
-
- instr.fn(instr, nil, env, contract, mem, stack)
}
-
- pc++
}
contract.Input = nil
@@ -403,7 +349,7 @@ func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
// jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
// the operation. This does not reduce gas or resizes the memory.
-func jitCalculateGasAndSize(env Environment, contract *Contract, caller ContractRef, instr instruction, statedb Database, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
+func jitCalculateGasAndSize(env Environment, contract *Contract, instr instruction, statedb Database, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
var (
gas = new(big.Int)
newMemSize *big.Int = new(big.Int)