jit.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  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. func NewProgram(code []byte) *Program {
  70. program := &Program{
  71. Id: crypto.Sha3Hash(code),
  72. mapping: make(map[uint64]int),
  73. destinations: make(map[uint64]struct{}),
  74. code: code,
  75. }
  76. programs.Add(program.Id, program)
  77. return program
  78. }
  79. func (p *Program) addInstr(op OpCode, pc uint64, fn instrFn, data *big.Int) {
  80. // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
  81. // PUSH is also allowed to calculate the same price for all PUSHes
  82. // DUP requirements are handled elsewhere (except for the stack limit check)
  83. baseOp := op
  84. if op >= PUSH1 && op <= PUSH32 {
  85. baseOp = PUSH1
  86. }
  87. if op >= DUP1 && op <= DUP16 {
  88. baseOp = DUP1
  89. }
  90. base := _baseCheck[baseOp]
  91. instr := instruction{op, pc, fn, nil, data, base.gas, base.stackPop, base.stackPush}
  92. p.instructions = append(p.instructions, instr)
  93. p.mapping[pc] = len(p.instructions) - 1
  94. }
  95. func CompileProgram(program *Program) (err error) {
  96. if progStatus(atomic.LoadInt32(&program.status)) == progCompile {
  97. return nil
  98. }
  99. atomic.StoreInt32(&program.status, int32(progCompile))
  100. defer func() {
  101. if err != nil {
  102. atomic.StoreInt32(&program.status, int32(progError))
  103. } else {
  104. atomic.StoreInt32(&program.status, int32(progReady))
  105. }
  106. }()
  107. // loop thru the opcodes and "compile" in to instructions
  108. for pc := uint64(0); pc < uint64(len(program.code)); pc++ {
  109. switch op := OpCode(program.code[pc]); op {
  110. case ADD:
  111. program.addInstr(op, pc, opAdd, nil)
  112. case SUB:
  113. program.addInstr(op, pc, opSub, nil)
  114. case MUL:
  115. program.addInstr(op, pc, opMul, nil)
  116. case DIV:
  117. program.addInstr(op, pc, opDiv, nil)
  118. case SDIV:
  119. program.addInstr(op, pc, opSdiv, nil)
  120. case MOD:
  121. program.addInstr(op, pc, opMod, nil)
  122. case SMOD:
  123. program.addInstr(op, pc, opSmod, nil)
  124. case EXP:
  125. program.addInstr(op, pc, opExp, nil)
  126. case SIGNEXTEND:
  127. program.addInstr(op, pc, opSignExtend, nil)
  128. case NOT:
  129. program.addInstr(op, pc, opNot, nil)
  130. case LT:
  131. program.addInstr(op, pc, opLt, nil)
  132. case GT:
  133. program.addInstr(op, pc, opGt, nil)
  134. case SLT:
  135. program.addInstr(op, pc, opSlt, nil)
  136. case SGT:
  137. program.addInstr(op, pc, opSgt, nil)
  138. case EQ:
  139. program.addInstr(op, pc, opEq, nil)
  140. case ISZERO:
  141. program.addInstr(op, pc, opIszero, nil)
  142. case AND:
  143. program.addInstr(op, pc, opAnd, nil)
  144. case OR:
  145. program.addInstr(op, pc, opOr, nil)
  146. case XOR:
  147. program.addInstr(op, pc, opXor, nil)
  148. case BYTE:
  149. program.addInstr(op, pc, opByte, nil)
  150. case ADDMOD:
  151. program.addInstr(op, pc, opAddmod, nil)
  152. case MULMOD:
  153. program.addInstr(op, pc, opMulmod, nil)
  154. case SHA3:
  155. program.addInstr(op, pc, opSha3, nil)
  156. case ADDRESS:
  157. program.addInstr(op, pc, opAddress, nil)
  158. case BALANCE:
  159. program.addInstr(op, pc, opBalance, nil)
  160. case ORIGIN:
  161. program.addInstr(op, pc, opOrigin, nil)
  162. case CALLER:
  163. program.addInstr(op, pc, opCaller, nil)
  164. case CALLVALUE:
  165. program.addInstr(op, pc, opCallValue, nil)
  166. case CALLDATALOAD:
  167. program.addInstr(op, pc, opCalldataLoad, nil)
  168. case CALLDATASIZE:
  169. program.addInstr(op, pc, opCalldataSize, nil)
  170. case CALLDATACOPY:
  171. program.addInstr(op, pc, opCalldataCopy, nil)
  172. case CODESIZE:
  173. program.addInstr(op, pc, opCodeSize, nil)
  174. case EXTCODESIZE:
  175. program.addInstr(op, pc, opExtCodeSize, nil)
  176. case CODECOPY:
  177. program.addInstr(op, pc, opCodeCopy, nil)
  178. case EXTCODECOPY:
  179. program.addInstr(op, pc, opExtCodeCopy, nil)
  180. case GASPRICE:
  181. program.addInstr(op, pc, opGasprice, nil)
  182. case BLOCKHASH:
  183. program.addInstr(op, pc, opBlockhash, nil)
  184. case COINBASE:
  185. program.addInstr(op, pc, opCoinbase, nil)
  186. case TIMESTAMP:
  187. program.addInstr(op, pc, opTimestamp, nil)
  188. case NUMBER:
  189. program.addInstr(op, pc, opNumber, nil)
  190. case DIFFICULTY:
  191. program.addInstr(op, pc, opDifficulty, nil)
  192. case GASLIMIT:
  193. program.addInstr(op, pc, opGasLimit, nil)
  194. 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:
  195. size := uint64(op - PUSH1 + 1)
  196. bytes := getData([]byte(program.code), new(big.Int).SetUint64(pc+1), new(big.Int).SetUint64(size))
  197. program.addInstr(op, pc, opPush, common.Bytes2Big(bytes))
  198. pc += size
  199. case POP:
  200. program.addInstr(op, pc, opPop, nil)
  201. case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
  202. program.addInstr(op, pc, opDup, big.NewInt(int64(op-DUP1+1)))
  203. case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
  204. program.addInstr(op, pc, opSwap, big.NewInt(int64(op-SWAP1+2)))
  205. case LOG0, LOG1, LOG2, LOG3, LOG4:
  206. program.addInstr(op, pc, opLog, big.NewInt(int64(op-LOG0)))
  207. case MLOAD:
  208. program.addInstr(op, pc, opMload, nil)
  209. case MSTORE:
  210. program.addInstr(op, pc, opMstore, nil)
  211. case MSTORE8:
  212. program.addInstr(op, pc, opMstore8, nil)
  213. case SLOAD:
  214. program.addInstr(op, pc, opSload, nil)
  215. case SSTORE:
  216. program.addInstr(op, pc, opSstore, nil)
  217. case JUMP:
  218. program.addInstr(op, pc, opJump, nil)
  219. case JUMPI:
  220. program.addInstr(op, pc, opJumpi, nil)
  221. case JUMPDEST:
  222. program.addInstr(op, pc, opJumpdest, nil)
  223. program.destinations[pc] = struct{}{}
  224. case PC:
  225. program.addInstr(op, pc, opPc, big.NewInt(int64(pc)))
  226. case MSIZE:
  227. program.addInstr(op, pc, opMsize, nil)
  228. case GAS:
  229. program.addInstr(op, pc, opGas, nil)
  230. case CREATE:
  231. program.addInstr(op, pc, opCreate, nil)
  232. case CALL:
  233. program.addInstr(op, pc, opCall, nil)
  234. case CALLCODE:
  235. program.addInstr(op, pc, opCallCode, nil)
  236. case RETURN:
  237. program.addInstr(op, pc, opReturn, nil)
  238. case SUICIDE:
  239. program.addInstr(op, pc, opSuicide, nil)
  240. case STOP: // Stop the context
  241. program.addInstr(op, pc, opStop, nil)
  242. default:
  243. program.addInstr(op, pc, nil, nil)
  244. }
  245. }
  246. return nil
  247. }
  248. func RunProgram(program *Program, env Environment, context *Context, input []byte) ([]byte, error) {
  249. return runProgram(program, 0, NewMemory(), newstack(), env, context, input)
  250. }
  251. func runProgram(program *Program, pcstart uint64, mem *Memory, stack *stack, env Environment, context *Context, input []byte) ([]byte, error) {
  252. context.Input = input
  253. var (
  254. caller = context.caller
  255. statedb = env.State()
  256. pc int = program.mapping[pcstart]
  257. jump = func(to *big.Int) error {
  258. if !validDest(program.destinations, to) {
  259. nop := context.GetOp(to.Uint64())
  260. return fmt.Errorf("invalid jump destination (%v) %v", nop, to)
  261. }
  262. pc = program.mapping[to.Uint64()]
  263. return nil
  264. }
  265. )
  266. for pc < len(program.instructions) {
  267. instr := program.instructions[pc]
  268. // calculate the new memory size and gas price for the current executing opcode
  269. newMemSize, cost, err := jitCalculateGasAndSize(env, context, caller, instr, statedb, mem, stack)
  270. if err != nil {
  271. return nil, err
  272. }
  273. // Use the calculated gas. When insufficient gas is present, use all gas and return an
  274. // Out Of Gas error
  275. if !context.UseGas(cost) {
  276. return nil, OutOfGasError
  277. }
  278. // Resize the memory calculated previously
  279. mem.Resize(newMemSize.Uint64())
  280. // These opcodes return an argument and are thefor handled
  281. // differently from the rest of the opcodes
  282. switch instr.op {
  283. case JUMP:
  284. if err := jump(stack.pop()); err != nil {
  285. return nil, err
  286. }
  287. continue
  288. case JUMPI:
  289. pos, cond := stack.pop(), stack.pop()
  290. if cond.Cmp(common.BigTrue) >= 0 {
  291. if err := jump(pos); err != nil {
  292. return nil, err
  293. }
  294. continue
  295. }
  296. case RETURN:
  297. offset, size := stack.pop(), stack.pop()
  298. ret := mem.GetPtr(offset.Int64(), size.Int64())
  299. return context.Return(ret), nil
  300. case SUICIDE:
  301. instr.fn(instr, env, context, mem, stack)
  302. return context.Return(nil), nil
  303. case STOP:
  304. return context.Return(nil), nil
  305. default:
  306. if instr.fn == nil {
  307. return nil, fmt.Errorf("Invalid opcode %x", instr.op)
  308. }
  309. instr.fn(instr, env, context, mem, stack)
  310. }
  311. pc++
  312. }
  313. return context.Return(nil), nil
  314. }
  315. // validDest checks if the given distination is a valid one given the
  316. // destination table of the program
  317. func validDest(dests map[uint64]struct{}, dest *big.Int) bool {
  318. // PC cannot go beyond len(code) and certainly can't be bigger than 64bits.
  319. // Don't bother checking for JUMPDEST in that case.
  320. if dest.Cmp(bigMaxUint64) > 0 {
  321. return false
  322. }
  323. _, ok := dests[dest.Uint64()]
  324. return ok
  325. }
  326. // jitCalculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
  327. // the operation. This does not reduce gas or resizes the memory.
  328. func jitCalculateGasAndSize(env Environment, context *Context, caller ContextRef, instr instruction, statedb *state.StateDB, mem *Memory, stack *stack) (*big.Int, *big.Int, error) {
  329. var (
  330. gas = new(big.Int)
  331. newMemSize *big.Int = new(big.Int)
  332. )
  333. err := jitBaseCheck(instr, stack, gas)
  334. if err != nil {
  335. return nil, nil, err
  336. }
  337. // stack Check, memory resize & gas phase
  338. switch op := instr.op; op {
  339. case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
  340. n := int(op - SWAP1 + 2)
  341. err := stack.require(n)
  342. if err != nil {
  343. return nil, nil, err
  344. }
  345. gas.Set(GasFastestStep)
  346. case DUP1, DUP2, DUP3, DUP4, DUP5, DUP6, DUP7, DUP8, DUP9, DUP10, DUP11, DUP12, DUP13, DUP14, DUP15, DUP16:
  347. n := int(op - DUP1 + 1)
  348. err := stack.require(n)
  349. if err != nil {
  350. return nil, nil, err
  351. }
  352. gas.Set(GasFastestStep)
  353. case LOG0, LOG1, LOG2, LOG3, LOG4:
  354. n := int(op - LOG0)
  355. err := stack.require(n + 2)
  356. if err != nil {
  357. return nil, nil, err
  358. }
  359. mSize, mStart := stack.data[stack.len()-2], stack.data[stack.len()-1]
  360. gas.Add(gas, params.LogGas)
  361. gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(n)), params.LogTopicGas))
  362. gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
  363. newMemSize = calcMemSize(mStart, mSize)
  364. case EXP:
  365. gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
  366. case SSTORE:
  367. err := stack.require(2)
  368. if err != nil {
  369. return nil, nil, err
  370. }
  371. var g *big.Int
  372. y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
  373. val := statedb.GetState(context.Address(), common.BigToHash(x))
  374. // This checks for 3 scenario's and calculates gas accordingly
  375. // 1. From a zero-value address to a non-zero value (NEW VALUE)
  376. // 2. From a non-zero value address to a zero-value address (DELETE)
  377. // 3. From a nen-zero to a non-zero (CHANGE)
  378. if common.EmptyHash(val) && !common.EmptyHash(common.BigToHash(y)) {
  379. // 0 => non 0
  380. g = params.SstoreSetGas
  381. } else if !common.EmptyHash(val) && common.EmptyHash(common.BigToHash(y)) {
  382. statedb.Refund(params.SstoreRefundGas)
  383. g = params.SstoreClearGas
  384. } else {
  385. // non 0 => non 0 (or 0 => 0)
  386. g = params.SstoreClearGas
  387. }
  388. gas.Set(g)
  389. case SUICIDE:
  390. if !statedb.IsDeleted(context.Address()) {
  391. statedb.Refund(params.SuicideRefundGas)
  392. }
  393. case MLOAD:
  394. newMemSize = calcMemSize(stack.peek(), u256(32))
  395. case MSTORE8:
  396. newMemSize = calcMemSize(stack.peek(), u256(1))
  397. case MSTORE:
  398. newMemSize = calcMemSize(stack.peek(), u256(32))
  399. case RETURN:
  400. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
  401. case SHA3:
  402. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
  403. words := toWordSize(stack.data[stack.len()-2])
  404. gas.Add(gas, words.Mul(words, params.Sha3WordGas))
  405. case CALLDATACOPY:
  406. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
  407. words := toWordSize(stack.data[stack.len()-3])
  408. gas.Add(gas, words.Mul(words, params.CopyGas))
  409. case CODECOPY:
  410. newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
  411. words := toWordSize(stack.data[stack.len()-3])
  412. gas.Add(gas, words.Mul(words, params.CopyGas))
  413. case EXTCODECOPY:
  414. newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
  415. words := toWordSize(stack.data[stack.len()-4])
  416. gas.Add(gas, words.Mul(words, params.CopyGas))
  417. case CREATE:
  418. newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
  419. case CALL, CALLCODE:
  420. gas.Add(gas, stack.data[stack.len()-1])
  421. if op == CALL {
  422. if env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
  423. gas.Add(gas, params.CallNewAccountGas)
  424. }
  425. }
  426. if len(stack.data[stack.len()-3].Bytes()) > 0 {
  427. gas.Add(gas, params.CallValueTransferGas)
  428. }
  429. x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
  430. y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
  431. newMemSize = common.BigMax(x, y)
  432. }
  433. if newMemSize.Cmp(common.Big0) > 0 {
  434. newMemSizeWords := toWordSize(newMemSize)
  435. newMemSize.Mul(newMemSizeWords, u256(32))
  436. if newMemSize.Cmp(u256(int64(mem.Len()))) > 0 {
  437. oldSize := toWordSize(big.NewInt(int64(mem.Len())))
  438. pow := new(big.Int).Exp(oldSize, common.Big2, Zero)
  439. linCoef := new(big.Int).Mul(oldSize, params.MemoryGas)
  440. quadCoef := new(big.Int).Div(pow, params.QuadCoeffDiv)
  441. oldTotalFee := new(big.Int).Add(linCoef, quadCoef)
  442. pow.Exp(newMemSizeWords, common.Big2, Zero)
  443. linCoef = new(big.Int).Mul(newMemSizeWords, params.MemoryGas)
  444. quadCoef = new(big.Int).Div(pow, params.QuadCoeffDiv)
  445. newTotalFee := new(big.Int).Add(linCoef, quadCoef)
  446. fee := new(big.Int).Sub(newTotalFee, oldTotalFee)
  447. gas.Add(gas, fee)
  448. }
  449. }
  450. return newMemSize, gas, nil
  451. }
  452. // jitBaseCheck is the same as baseCheck except it doesn't do the look up in the
  453. // gas table. This is done during compilation instead.
  454. func jitBaseCheck(instr instruction, stack *stack, gas *big.Int) error {
  455. err := stack.require(instr.spop)
  456. if err != nil {
  457. return err
  458. }
  459. if instr.spush > 0 && stack.len()-instr.spop+instr.spush > int(params.StackLimit.Int64()) {
  460. return fmt.Errorf("stack limit reached %d (%d)", stack.len(), params.StackLimit.Int64())
  461. }
  462. // nil on gas means no base calculation
  463. if instr.gas == nil {
  464. return nil
  465. }
  466. gas.Add(gas, instr.gas)
  467. return nil
  468. }