vm_jit.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // Copyright 2015 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. // +build evmjit
  17. package vm
  18. /*
  19. void* evmjit_create();
  20. int evmjit_run(void* _jit, void* _data, void* _env);
  21. void evmjit_destroy(void* _jit);
  22. // Shared library evmjit (e.g. libevmjit.so) is expected to be installed in /usr/local/lib
  23. // More: https://github.com/ethereum/evmjit
  24. #cgo LDFLAGS: -levmjit
  25. */
  26. import "C"
  27. /*
  28. import (
  29. "bytes"
  30. "errors"
  31. "fmt"
  32. "math/big"
  33. "unsafe"
  34. "github.com/ethereum/go-ethereum/core/state"
  35. "github.com/ethereum/go-ethereum/crypto"
  36. "github.com/ethereum/go-ethereum/params"
  37. )
  38. type JitVm struct {
  39. env EVM
  40. me ContextRef
  41. callerAddr []byte
  42. price *big.Int
  43. data RuntimeData
  44. }
  45. type i256 [32]byte
  46. type RuntimeData struct {
  47. gas int64
  48. gasPrice int64
  49. callData *byte
  50. callDataSize uint64
  51. address i256
  52. caller i256
  53. origin i256
  54. callValue i256
  55. coinBase i256
  56. difficulty i256
  57. gasLimit i256
  58. number uint64
  59. timestamp int64
  60. code *byte
  61. codeSize uint64
  62. codeHash i256
  63. }
  64. func hash2llvm(h []byte) i256 {
  65. var m i256
  66. copy(m[len(m)-len(h):], h) // right aligned copy
  67. return m
  68. }
  69. func llvm2hash(m *i256) []byte {
  70. return C.GoBytes(unsafe.Pointer(m), C.int(len(m)))
  71. }
  72. func llvm2hashRef(m *i256) []byte {
  73. return (*[1 << 30]byte)(unsafe.Pointer(m))[:len(m):len(m)]
  74. }
  75. func address2llvm(addr []byte) i256 {
  76. n := hash2llvm(addr)
  77. bswap(&n)
  78. return n
  79. }
  80. // bswap swap bytes of the 256-bit integer on LLVM side
  81. // TODO: Do not change memory on LLVM side, that can conflict with memory access optimizations
  82. func bswap(m *i256) *i256 {
  83. for i, l := 0, len(m); i < l/2; i++ {
  84. m[i], m[l-i-1] = m[l-i-1], m[i]
  85. }
  86. return m
  87. }
  88. func trim(m []byte) []byte {
  89. skip := 0
  90. for i := 0; i < len(m); i++ {
  91. if m[i] == 0 {
  92. skip++
  93. } else {
  94. break
  95. }
  96. }
  97. return m[skip:]
  98. }
  99. func getDataPtr(m []byte) *byte {
  100. var p *byte
  101. if len(m) > 0 {
  102. p = &m[0]
  103. }
  104. return p
  105. }
  106. func big2llvm(n *big.Int) i256 {
  107. m := hash2llvm(n.Bytes())
  108. bswap(&m)
  109. return m
  110. }
  111. func llvm2big(m *i256) *big.Int {
  112. n := big.NewInt(0)
  113. for i := 0; i < len(m); i++ {
  114. b := big.NewInt(int64(m[i]))
  115. b.Lsh(b, uint(i)*8)
  116. n.Add(n, b)
  117. }
  118. return n
  119. }
  120. // llvm2bytesRef creates a []byte slice that references byte buffer on LLVM side (as of that not controller by GC)
  121. // User must ensure that referenced memory is available to Go until the data is copied or not needed any more
  122. func llvm2bytesRef(data *byte, length uint64) []byte {
  123. if length == 0 {
  124. return nil
  125. }
  126. if data == nil {
  127. panic("Unexpected nil data pointer")
  128. }
  129. return (*[1 << 30]byte)(unsafe.Pointer(data))[:length:length]
  130. }
  131. func untested(condition bool, message string) {
  132. if condition {
  133. panic("Condition `" + message + "` tested. Remove assert.")
  134. }
  135. }
  136. func assert(condition bool, message string) {
  137. if !condition {
  138. panic("Assert `" + message + "` failed!")
  139. }
  140. }
  141. func NewJitVm(env EVM) *JitVm {
  142. return &JitVm{env: env}
  143. }
  144. func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
  145. // TODO: depth is increased but never checked by VM. VM should not know about it at all.
  146. self.env.SetDepth(self.env.Depth() + 1)
  147. // TODO: Move it to Env.Call() or sth
  148. if Precompiled[string(me.Address())] != nil {
  149. // if it's address of precompiled contract
  150. // fallback to standard VM
  151. stdVm := New(self.env)
  152. return stdVm.Run(me, caller, code, value, gas, price, callData)
  153. }
  154. if self.me != nil {
  155. panic("JitVm.Run() can be called only once per JitVm instance")
  156. }
  157. self.me = me
  158. self.callerAddr = caller.Address()
  159. self.price = price
  160. self.data.gas = gas.Int64()
  161. self.data.gasPrice = price.Int64()
  162. self.data.callData = getDataPtr(callData)
  163. self.data.callDataSize = uint64(len(callData))
  164. self.data.address = address2llvm(self.me.Address())
  165. self.data.caller = address2llvm(caller.Address())
  166. self.data.origin = address2llvm(self.env.Origin())
  167. self.data.callValue = big2llvm(value)
  168. self.data.coinBase = address2llvm(self.env.Coinbase())
  169. self.data.difficulty = big2llvm(self.env.Difficulty())
  170. self.data.gasLimit = big2llvm(self.env.GasLimit())
  171. self.data.number = self.env.BlockNumber().Uint64()
  172. self.data.timestamp = self.env.Time()
  173. self.data.code = getDataPtr(code)
  174. self.data.codeSize = uint64(len(code))
  175. self.data.codeHash = hash2llvm(crypto.Keccak256(code)) // TODO: Get already computed hash?
  176. jit := C.evmjit_create()
  177. retCode := C.evmjit_run(jit, unsafe.Pointer(&self.data), unsafe.Pointer(self))
  178. if retCode < 0 {
  179. err = errors.New("OOG from JIT")
  180. gas.SetInt64(0) // Set gas to 0, JIT does not bother
  181. } else {
  182. gas.SetInt64(self.data.gas)
  183. if retCode == 1 { // RETURN
  184. ret = C.GoBytes(unsafe.Pointer(self.data.callData), C.int(self.data.callDataSize))
  185. } else if retCode == 2 { // SUICIDE
  186. // TODO: Suicide support logic should be moved to Env to be shared by VM implementations
  187. state := self.Env().State()
  188. receiverAddr := llvm2hashRef(bswap(&self.data.address))
  189. receiver := state.GetOrNewStateObject(receiverAddr)
  190. balance := state.GetBalance(me.Address())
  191. receiver.AddBalance(balance)
  192. state.Delete(me.Address())
  193. }
  194. }
  195. C.evmjit_destroy(jit)
  196. return
  197. }
  198. func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine {
  199. return self
  200. }
  201. func (self *JitVm) Endl() VirtualMachine {
  202. return self
  203. }
  204. func (self *JitVm) Env() EVM {
  205. return self.env
  206. }
  207. //export env_sha3
  208. func env_sha3(dataPtr *byte, length uint64, resultPtr unsafe.Pointer) {
  209. data := llvm2bytesRef(dataPtr, length)
  210. hash := crypto.Keccak256(data)
  211. result := (*i256)(resultPtr)
  212. *result = hash2llvm(hash)
  213. }
  214. //export env_sstore
  215. func env_sstore(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, valuePtr unsafe.Pointer) {
  216. vm := (*JitVm)(vmPtr)
  217. index := llvm2hash(bswap((*i256)(indexPtr)))
  218. value := llvm2hash(bswap((*i256)(valuePtr)))
  219. value = trim(value)
  220. if len(value) == 0 {
  221. prevValue := vm.env.State().GetState(vm.me.Address(), index)
  222. if len(prevValue) != 0 {
  223. vm.Env().State().Refund(vm.callerAddr, GasSStoreRefund)
  224. }
  225. }
  226. vm.env.State().SetState(vm.me.Address(), index, value)
  227. }
  228. //export env_sload
  229. func env_sload(vmPtr unsafe.Pointer, indexPtr unsafe.Pointer, resultPtr unsafe.Pointer) {
  230. vm := (*JitVm)(vmPtr)
  231. index := llvm2hash(bswap((*i256)(indexPtr)))
  232. value := vm.env.State().GetState(vm.me.Address(), index)
  233. result := (*i256)(resultPtr)
  234. *result = hash2llvm(value)
  235. bswap(result)
  236. }
  237. //export env_balance
  238. func env_balance(_vm unsafe.Pointer, _addr unsafe.Pointer, _result unsafe.Pointer) {
  239. vm := (*JitVm)(_vm)
  240. addr := llvm2hash((*i256)(_addr))
  241. balance := vm.Env().State().GetBalance(addr)
  242. result := (*i256)(_result)
  243. *result = big2llvm(balance)
  244. }
  245. //export env_blockhash
  246. func env_blockhash(_vm unsafe.Pointer, _number unsafe.Pointer, _result unsafe.Pointer) {
  247. vm := (*JitVm)(_vm)
  248. number := llvm2big((*i256)(_number))
  249. result := (*i256)(_result)
  250. currNumber := vm.Env().BlockNumber()
  251. limit := big.NewInt(0).Sub(currNumber, big.NewInt(256))
  252. if number.Cmp(limit) >= 0 && number.Cmp(currNumber) < 0 {
  253. hash := vm.Env().GetHash(uint64(number.Int64()))
  254. *result = hash2llvm(hash)
  255. } else {
  256. *result = i256{}
  257. }
  258. }
  259. //export env_call
  260. func env_call(_vm unsafe.Pointer, _gas *int64, _receiveAddr unsafe.Pointer, _value unsafe.Pointer, inDataPtr unsafe.Pointer, inDataLen uint64, outDataPtr *byte, outDataLen uint64, _codeAddr unsafe.Pointer) bool {
  261. vm := (*JitVm)(_vm)
  262. //fmt.Printf("env_call (depth %d)\n", vm.Env().Depth())
  263. defer func() {
  264. if r := recover(); r != nil {
  265. fmt.Printf("Recovered in env_call (depth %d, out %p %d): %s\n", vm.Env().Depth(), outDataPtr, outDataLen, r)
  266. }
  267. }()
  268. balance := vm.Env().State().GetBalance(vm.me.Address())
  269. value := llvm2big((*i256)(_value))
  270. if balance.Cmp(value) >= 0 {
  271. receiveAddr := llvm2hash((*i256)(_receiveAddr))
  272. inData := C.GoBytes(inDataPtr, C.int(inDataLen))
  273. outData := llvm2bytesRef(outDataPtr, outDataLen)
  274. codeAddr := llvm2hash((*i256)(_codeAddr))
  275. gas := big.NewInt(*_gas)
  276. var out []byte
  277. var err error
  278. if bytes.Equal(codeAddr, receiveAddr) {
  279. out, err = vm.env.Call(vm.me, codeAddr, inData, gas, vm.price, value)
  280. } else {
  281. out, err = vm.env.CallCode(vm.me, codeAddr, inData, gas, vm.price, value)
  282. }
  283. *_gas = gas.Int64()
  284. if err == nil {
  285. copy(outData, out)
  286. return true
  287. }
  288. }
  289. return false
  290. }
  291. //export env_create
  292. func env_create(_vm unsafe.Pointer, _gas *int64, _value unsafe.Pointer, initDataPtr unsafe.Pointer, initDataLen uint64, _result unsafe.Pointer) {
  293. vm := (*JitVm)(_vm)
  294. value := llvm2big((*i256)(_value))
  295. initData := C.GoBytes(initDataPtr, C.int(initDataLen)) // TODO: Unnecessary if low balance
  296. result := (*i256)(_result)
  297. *result = i256{}
  298. gas := big.NewInt(*_gas)
  299. ret, suberr, ref := vm.env.Create(vm.me, nil, initData, gas, vm.price, value)
  300. if suberr == nil {
  301. dataGas := big.NewInt(int64(len(ret))) // TODO: Not the best design. env.Create can do it, it has the reference to gas counter
  302. dataGas.Mul(dataGas, params.CreateDataGas)
  303. gas.Sub(gas, dataGas)
  304. *result = hash2llvm(ref.Address())
  305. }
  306. *_gas = gas.Int64()
  307. }
  308. //export env_log
  309. func env_log(_vm unsafe.Pointer, dataPtr unsafe.Pointer, dataLen uint64, _topic1 unsafe.Pointer, _topic2 unsafe.Pointer, _topic3 unsafe.Pointer, _topic4 unsafe.Pointer) {
  310. vm := (*JitVm)(_vm)
  311. data := C.GoBytes(dataPtr, C.int(dataLen))
  312. topics := make([][]byte, 0, 4)
  313. if _topic1 != nil {
  314. topics = append(topics, llvm2hash((*i256)(_topic1)))
  315. }
  316. if _topic2 != nil {
  317. topics = append(topics, llvm2hash((*i256)(_topic2)))
  318. }
  319. if _topic3 != nil {
  320. topics = append(topics, llvm2hash((*i256)(_topic3)))
  321. }
  322. if _topic4 != nil {
  323. topics = append(topics, llvm2hash((*i256)(_topic4)))
  324. }
  325. vm.Env().AddLog(state.NewLog(vm.me.Address(), topics, data, vm.env.BlockNumber().Uint64()))
  326. }
  327. //export env_extcode
  328. func env_extcode(_vm unsafe.Pointer, _addr unsafe.Pointer, o_size *uint64) *byte {
  329. vm := (*JitVm)(_vm)
  330. addr := llvm2hash((*i256)(_addr))
  331. code := vm.Env().State().GetCode(addr)
  332. *o_size = uint64(len(code))
  333. return getDataPtr(code)
  334. }*/