jit.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. // Copyright 2014 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package vm
  17. import (
  18. "fmt"
  19. "math/big"
  20. "sync/atomic"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/core/state"
  23. "github.com/ethereum/go-ethereum/crypto"
  24. "github.com/ethereum/go-ethereum/params"
  25. "github.com/hashicorp/golang-lru"
  26. )
  27. type progStatus int32
  28. const (
  29. progUnknown progStatus = iota
  30. progCompile
  31. progReady
  32. progError
  33. )
  34. var programs *lru.Cache
  35. func init() {
  36. programs, _ = lru.New(defaultJitMaxCache)
  37. }
  38. // SetJITCacheSize recreates the program cache with the max given size. Setting
  39. // a new cache is **not** thread safe. Use with caution.
  40. func SetJITCacheSize(size int) {
  41. programs, _ = lru.New(size)
  42. }
  43. // GetProgram returns the program by id or nil when non-existent
  44. func GetProgram(id common.Hash) *Program {
  45. if p, ok := programs.Get(id); ok {
  46. return p.(*Program)
  47. }
  48. return nil
  49. }
  50. // GenProgramStatus returns the status of the given program id
  51. func GetProgramStatus(id common.Hash) progStatus {
  52. program := GetProgram(id)
  53. if program != nil {
  54. return progStatus(atomic.LoadInt32(&program.status))
  55. }
  56. return progUnknown
  57. }
  58. // Program is a compiled program for the JIT VM and holds all required for
  59. // running a compiled JIT program.
  60. type Program struct {
  61. Id common.Hash // Id of the program
  62. status int32 // status should be accessed atomically
  63. context *Context
  64. instructions []instruction // instruction set
  65. mapping map[uint64]int // real PC mapping to array indices
  66. destinations map[uint64]struct{} // cached jump destinations
  67. code []byte
  68. }
  69. // NewProgram returns a new JIT program
  70. func NewProgram(code []byte) *Program {
  71. program := &Program{
  72. Id: crypto.Sha3Hash(code),
  73. mapping: make(map[uint64]int),
  74. destinations: make(map[uint64]struct{}),
  75. code: code,
  76. }
  77. programs.Add(program.Id, program)
  78. return program
  79. }
  80. func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
  81. // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
  82. // PUSH is also allowed to calculate the same price for all PUSHes
  83. // DUP requirements are handled elsewhere (except for the stack limit check)
  84. baseOp := op
  85. if op >= PUSH1 && op <= PUSH32 {
  86. baseOp = PUSH1
  87. }
  88. if op >= DUP1 && op <= DUP16 {
  89. baseOp = DUP1
  90. }
  91. base := _baseCheck[baseOp]
  92. instr := instruction{op, pc, fn, nil, data, base.gas, base.stackPop, base.stackPush}
  93. p.instructions = append(p.instructions, instr)
  94. p.mapping[pc] = len(p.instructions) - 1
  95. }
  96. // CompileProgram compiles the given program and return an error when it fails
  97. func CompileProgram(program *Program) (err error) {
  98. if progStatus(atomic.LoadInt32(&program.status)) == progCompile {
  99. return nil
  100. }
  101. atomic.StoreInt32(&program.status, int32(progCompile))
  102. defer func() {
  103. if err != nil {
  104. atomic.StoreInt32(&program.status, int32(progError))
  105. } else {
  106. atomic.StoreInt32(&program.status, int32(progReady))
  107. }
  108. }()
  109. // loop thru the opcodes and "compile" in to instructions
  110. for pc := uint64(0); pc < uint64(len(program.code)); pc++ {
  111. switch op := OpCode(program.code[pc]); op {
  112. case ADD:
  113. program.addInstr(op, pc, opAdd, nil)
  114. case SUB:
  115. program.addInstr(op, pc, opSub, nil)
  116. case MUL:
  117. program.addInstr(op, pc, opMul, nil)
  118. case DIV:
  119. program.addInstr(op, pc, opDiv, nil)
  120. case SDIV:
  121. program.addInstr(op, pc, opSdiv, nil)
  122. case MOD:
  123. program.addInstr(op, pc, opMod, nil)
  124. case SMOD:
  125. program.addInstr(op, pc, opSmod, nil)
  126. case EXP:
  127. program.addInstr(op, pc, opExp, nil)
  128. case SIGNEXTEND:
  129. program.addInstr(op, pc, opSignExtend, nil)
  130. case NOT:
  131. program.addInstr(op, pc, opNot, nil)
  132. case LT:
  133. program.addInstr(op, pc, opLt, nil)
  134. case GT:
  135. program.addInstr(op, pc, opGt, nil)
  136. case SLT:
  137. program.addInstr(op, pc, opSlt, nil)
  138. case SGT:
  139. program.addInstr(op, pc, opSgt, nil)
  140. case EQ:
  141. program.addInstr(op, pc, opEq, nil)
  142. case ISZERO:
  143. program.addInstr(op, pc, opIszero, nil)
  144. case AND:
  145. program.addInstr(op, pc, opAnd, nil)
  146. case OR:
  147. program.addInstr(op, pc, opOr, nil)
  148. case XOR:
  149. program.addInstr(op, pc, opXor, nil)
  150. case BYTE:
  151. program.addInstr(op, pc, opByte, nil)
  152. case ADDMOD:
  153. program.addInstr(op, pc, opAddmod, nil)
  154. case MULMOD:
  155. program.addInstr(op, pc, opMulmod, nil)
  156. case SHA3:
  157. program.addInstr(op, pc, opSha3, nil)
  158. case ADDRESS:
  159. program.addInstr(op, pc, opAddress, nil)
  160. case BALANCE:
  161. program.addInstr(op, pc, opBalance, nil)
  162. case ORIGIN:
  163. program.addInstr(op, pc, opOrigin, nil)
  164. case CALLER:
  165. program.addInstr(op, pc, opCaller, nil)
  166. case CALLVALUE:
  167. program.addInstr(op, pc, opCallValue, nil)
  168. case CALLDATALOAD:
  169. program.addInstr(op, pc, opCalldataLoad, nil)
  170. case CALLDATASIZE:
  171. program.addInstr(op, pc, opCalldataSize, nil)
  172. case CALLDATACOPY:
  173. program.addInstr(op, pc, opCalldataCopy, nil)
  174. case CODESIZE:
  175. program.addInstr(op, pc, opCodeSize, nil)
  176. case EXTCODESIZE:
  177. program.addInstr(op, pc, opExtCodeSize, nil)
  178. case CODECOPY:
  179. program.addInstr(op, pc, opCodeCopy, nil)
  180. case EXTCODECOPY:
  181. program.addInstr(op, pc, opExtCodeCopy, nil)
  182. case GASPRICE:
  183. program.addInstr(op, pc, opGasprice, nil)
  184. case BLOCKHASH:
  185. program.addInstr(op, pc, opBlockhash, nil)
  186. case COINBASE:
  187. program.addInstr(op, pc, opCoinbase, nil)
  188. case TIMESTAMP:
  189. program.addInstr(op, pc, opTimestamp, nil)
  190. case NUMBER:
  191. program.addInstr(op, pc, opNumber, nil)
  192. case DIFFICULTY:
  193. program.addInstr(op, pc, opDifficulty, nil)
  194. case GASLIMIT:
  195. program.addInstr(op, pc, opGasLimit, nil)
  196. case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
  197. size := uint64(op - PUSH1 + 1)
  198. bytes := getData([]byte(program.code), new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size))
  199. program.addInstr(op, pc, opPush, common.Bytes2Big(bytes))
  200. pc += size
  201. case POP:
  202. program.addInstr(op, pc, opPop, nil)
  203. case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
  204. program.addInstr(op, pc, opDup, big.NewInt(int64(op-DUP1+1)))
  205. case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
  206. program.addInstr(op, pc, opSwap, big.NewInt(int64(op-SWAP1+2)))
  207. case LOG0, LOG1, LOG2, LOG3, LOG4:
  208. program.addInstr(op, pc, opLog, big.NewInt(int64(op-LOG0)))
  209. case MLOAD:
  210. program.addInstr(op, pc, opMload, nil)
  211. case MSTORE:
  212. program.addInstr(op, pc, opMstore, nil)
  213. case MSTORE8:
  214. program.addInstr(op, pc, opMstore8, nil)
  215. case SLOAD:
  216. program.addInstr(op, pc, opSload, nil)
  217. case SSTORE:
  218. program.addInstr(op, pc, opSstore, nil)
  219. case JUMP:
  220. program.addInstr(op, pc, opJump, nil)
  221. case JUMPI:
  222. program.addInstr(op, pc, opJumpi, nil)
  223. case JUMPDEST:
  224. program.addInstr(op, pc, opJumpdest, nil)
  225. program.destinations[pc] = struct{}{}
  226. case PC:
  227. program.addInstr(op, pc, opPc, big.NewInt(int64(pc)))
  228. case MSIZE:
  229. program.addInstr(op, pc, opMsize, nil)
  230. case GAS:
  231. program.addInstr(op, pc, opGas, nil)
  232. case CREATE:
  233. program.addInstr(op, pc, opCreate, nil)
  234. case CALL:
  235. program.addInstr(op, pc, opCall, nil)
  236. case CALLCODE:
  237. program.addInstr(op, pc, opCallCode, nil)
  238. case RETURN:
  239. program.addInstr(op, pc, opReturn, nil)
  240. case SUICIDE:
  241. program.addInstr(op, pc, opSuicide, nil)
  242. case STOP: // Stop the context
  243. program.addInstr(op, pc, opStop, nil)
  244. default:
  245. program.addInstr(op, pc, nil, nil)
  246. }
  247. }
  248. return nil
  249. }
  250. // RunProgram runs the program given the enviroment and context and returns an
  251. // error if the execution failed (non-consensus)
  252. func RunProgram(program *Program, env Environment, context *Context, input []byte) ([]byte, error) {
  253. return runProgram(program, 0, NewMemory(), newstack(), env, context, input)
  254. }
  255. func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env Environment, context *Context, input []byte) ([]byte, error) {
  256. context.Input = input
  257. var (
  258. caller = context.caller
  259. statedb = env.State()
  260. pc int = program.mapping[pcstart]
  261. jump = func(to *big.Int) error {
  262. if !validDest(program.destinations, to) {
  263. nop := context.GetOp(to.Uint64())
  264. return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
  265. }
  266. pc = program.mapping[to.Uint64()]
  267. return nil
  268. }
  269. )
  270. for pc < len(program.instructions) {
  271. instr := program.instructions[pc]
  272. // calculate the new memory size and gas price for the current executing opcode
  273. newMemSize, cost, err := jitCalculateGasAndSize(env, context, caller, instr, statedb, mem, stack)
  274. if err != nil {
  275. return nil, err
  276. }
  277. // Use the calculated gas. When insufficient gas is present, use all gas and return an
  278. // Out Of Gas error
  279. if !context.UseGas(cost) {
  280. return nil, OutOfGasError
  281. }
  282. // Resize the memory calculated previously
  283. mem.Resize(newMemSize.Uint64())
  284. // These opcodes return an argument and are thefor handled
  285. // differently from the rest of the opcodes
  286. switch instr.op {
  287. case JUMP:
  288. if err := jump(stack.pop()); err != nil {
  289. return nil, err
  290. }
  291. continue
  292. case JUMPI:
  293. pos, cond := stack.pop(), stack.pop()
  294. if cond.Cmp(common.BigTrue) >= 0 {
  295. if err := jump(pos); err != nil {
  296. return nil, err
  297. }
  298. continue
  299. }
  300. case RETURN:
  301. offset, size := stack.pop(), stack.pop()
  302. ret := mem.GetPtr(offset.Int64(), size.Int64())
  303. return context.Return(ret), nil
  304. case SUICIDE:
  305. instr.fn(instr, env, context, mem, stack)
  306. return context.Return(nil), nil
  307. case STOP:
  308. return context.Return(nil), nil
  309. default:
  310. if instr.fn == nil {
  311. return nil, fmt.Errorf("Invalid opcode %x", instr.op)
  312. }
  313. instr.fn(instr, env, context, mem, stack)
  314. }
  315. pc++
  316. }
  317. context.Input = nil
  318. return context.Return(nil), nil
  319. }
  320. // validDest checks if the given distination is a valid one given the
  321. // destination table of the program
  322. func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
  323. // PC cannot go beyond len(code) and certainly can't be bigger than 64bits.
  324. // Don't bother checking for JUMPDEST in that case.
  325. if dest.Cmp(bigMaxUint64) > 0 {
  326. return false
  327. }
  328. _, ok := dests[dest.Uint64()]
  329. return ok
  330. }
  331. // jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
  332. // the operation. This does not reduce gas or resizes the memory.
  333. func jitCalculateGasAndSize(env Environment, context *Context, caller ContextRef, instr instruction, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
  334. var (
  335. gas = new(big.Int)
  336. newMemSize *big.Int = new(big.Int)
  337. )
  338. err := jitBaseCheck(instr, stack, gas)
  339. if err != nil {
  340. return nil, nil, err
  341. }
  342. // stack Check, memory resize & gas phase
  343. switch op := instr.op; op {
  344. case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
  345. n := int(op - SWAP1 + 2)
  346. err := stack.require(n)
  347. if err != nil {
  348. return nil, nil, err
  349. }
  350. gas.Set(GasFastestStep)
  351. case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
  352. n := int(op - DUP1 + 1)
  353. err := stack.require(n)
  354. if err != nil {
  355. return nil, nil, err
  356. }
  357. gas.Set(GasFastestStep)
  358. case LOG0, LOG1, LOG2, LOG3, LOG4:
  359. n := int(op - LOG0)
  360. err := stack.require(n + 2)
  361. if err != nil {
  362. return nil, nil, err
  363. }
  364. mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
  365. add := new(big.Int)
  366. gas.Add(gas, params.LogGas)
  367. gas.Add(gas, add.Mul(big.NewInt(int64(n)), params.LogTopicGas))
  368. gas.Add(gas, add.Mul(mSize, params.LogDataGas))
  369. newMemSize = calcMemSize(mStart, mSize)
  370. case EXP:
  371. gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
  372. case SSTORE:
  373. err := stack.require(2)
  374. if err != nil {
  375. return nil, nil, err
  376. }
  377. var g *big.Int
  378. y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
  379. val := statedb.GetState(context.Address(), common.BigToHash(x))
  380. // This checks for 3 scenario's and calculates gas accordingly
  381. // 1. From a zero-value address to a non-zero value (NEW VALUE)
  382. // 2. From a non-zero value address to a zero-value address (DELETE)
  383. // 3. From a nen-zero to a non-zero (CHANGE)
  384. if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
  385. // 0 => non 0
  386. g = params.SstoreSetGas
  387. } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
  388. statedb.Refund(params.SstoreRefundGas)
  389. g = params.SstoreClearGas
  390. } else {
  391. // non 0 => non 0 (or 0 => 0)
  392. g = params.SstoreClearGas
  393. }
  394. gas.Set(g)
  395. case SUICIDE:
  396. if !statedb.IsDeleted(context.Address()) {
  397. statedb.Refund(params.SuicideRefundGas)
  398. }
  399. case MLOAD:
  400. newMemSize = calcMemSize(stack.peek(), u256(32))
  401. case MSTORE8:
  402. newMemSize = calcMemSize(stack.peek(), u256(1))
  403. case MSTORE:
  404. newMemSize = calcMemSize(stack.peek(), u256(32))
  405. case RETURN:
  406. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
  407. case SHA3:
  408. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
  409. words := toWordSize(stack.data[stack.len()-2])
  410. gas.Add(gas, words.Mul(words, params.Sha3WordGas))
  411. case CALLDATACOPY:
  412. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
  413. words := toWordSize(stack.data[stack.len()-3])
  414. gas.Add(gas, words.Mul(words, params.CopyGas))
  415. case CODECOPY:
  416. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
  417. words := toWordSize(stack.data[stack.len()-3])
  418. gas.Add(gas, words.Mul(words, params.CopyGas))
  419. case EXTCODECOPY:
  420. newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
  421. words := toWordSize(stack.data[stack.len()-4])
  422. gas.Add(gas, words.Mul(words, params.CopyGas))
  423. case CREATE:
  424. newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
  425. case CALL, CALLCODE:
  426. gas.Add(gas, stack.data[stack.len()-1])
  427. if op == CALL {
  428. if env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
  429. gas.Add(gas, params.CallNewAccountGas)
  430. }
  431. }
  432. if len(stack.data[stack.len()-3].Bytes()) > 0 {
  433. gas.Add(gas, params.CallValueTransferGas)
  434. }
  435. x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
  436. y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
  437. newMemSize = common.BigMax(x, y)
  438. }
  439. if newMemSize.Cmp(common.Big0) > 0 {
  440. newMemSizeWords := toWordSize(newMemSize)
  441. newMemSize.Mul(newMemSizeWords, u256(32))
  442. if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
  443. // be careful reusing variables here when changing.
  444. // The order has been optimised to reduce allocation
  445. oldSize := toWordSize(big.NewInt(int64(mem.Len())))
  446. pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
  447. linCoef := oldSize.Mul(oldSize, params.MemoryGas)
  448. quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
  449. oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
  450. pow.Exp(newMemSizeWords, common.Big2, Zero)
  451. linCoef = linCoef.Mul(newMemSizeWords, params.MemoryGas)
  452. quadCoef = quadCoef.Div(pow, params.QuadCoeffDiv)
  453. newTotalFee := linCoef.Add(linCoef, quadCoef)
  454. fee := newTotalFee.Sub(newTotalFee, oldTotalFee)
  455. gas.Add(gas, fee)
  456. }
  457. }
  458. return newMemSize, gas, nil
  459. }
  460. // jitBaseCheck is the same as baseCheck except it doesn't do the look up in the
  461. // gas table. This is done during compilation instead.
  462. func jitBaseCheck(instr instruction, stack *stack, gas *big.Int) error {
  463. err := stack.require(instr.spop)
  464. if err != nil {
  465. return err
  466. }
  467. if instr.spush > 0 && stack.len()-instr.spop+instr.spush > int(params.StackLimit.Int64()) {
  468. return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
  469. }
  470. // nil on gas means no base calculation
  471. if instr.gas == nil {
  472. return nil
  473. }
  474. gas.Add(gas, instr.gas)
  475. return nil
  476. }