mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
RETURN implementation: JIT returns data
This commit is contained in:
parent
2c10328ef9
commit
06e0da25bc
3 changed files with 33 additions and 32 deletions
|
|
@ -5,14 +5,12 @@
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
int evmjit_run(void* _data, void* _env)
|
evmjit_result evmjit_run(void* _data, void* _env)
|
||||||
{
|
{
|
||||||
using namespace dev::eth::jit;
|
using namespace dev::eth::jit;
|
||||||
|
|
||||||
auto data = static_cast<RuntimeData*>(_data);
|
auto data = static_cast<RuntimeData*>(_data);
|
||||||
|
|
||||||
std::cerr << "GAS: " << data->elems[RuntimeData::Gas].a << "\n";
|
|
||||||
|
|
||||||
ExecutionEngine engine;
|
ExecutionEngine engine;
|
||||||
|
|
||||||
auto codePtr = data->code;
|
auto codePtr = data->code;
|
||||||
|
|
@ -20,30 +18,17 @@ int evmjit_run(void* _data, void* _env)
|
||||||
bytes bytecode;
|
bytes bytecode;
|
||||||
bytecode.insert(bytecode.end(), codePtr, codePtr + codeSize);
|
bytecode.insert(bytecode.end(), codePtr, codePtr + codeSize);
|
||||||
|
|
||||||
auto result = engine.run(bytecode, data, static_cast<Env*>(_env));
|
auto returnCode = engine.run(bytecode, data, static_cast<Env*>(_env));
|
||||||
return static_cast<int>(result);
|
evmjit_result result = {static_cast<int32_t>(returnCode), 0, nullptr};
|
||||||
}
|
if (returnCode == ReturnCode::Return && !engine.returnData.empty())
|
||||||
|
|
||||||
// Runtime callback functions - implementations must be provided by external language (Go, C++, Python)
|
|
||||||
void evm_jit_rt_sload(evm_jit_rt* _rt, i256* _index, i256* _ret);
|
|
||||||
void evm_jit_rt_sstore(evm_jit_rt* _rt, i256* _index, i256* _value);
|
|
||||||
void evm_jit_rt_balance(evm_jit_rt* _rt, h256* _address, i256* _ret);
|
|
||||||
// And so on...
|
|
||||||
|
|
||||||
evm_jit* evm_jit_create(evm_jit_rt*)
|
|
||||||
{
|
{
|
||||||
printf("EVM JIT create");
|
// TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea
|
||||||
|
result.returnDataSize = engine.returnData.size();
|
||||||
int* a = nullptr;
|
result.returnData = std::malloc(result.returnDataSize);
|
||||||
*a = 1;
|
std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize);
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_jit_return_code evm_jit_execute(evm_jit* _jit);
|
return result;
|
||||||
|
}
|
||||||
void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size);
|
|
||||||
|
|
||||||
void evm_jit_destroy(evm_jit* _jit);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,19 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int evmjit_run(void* _data, void* _env);
|
typedef struct evmjit_result
|
||||||
|
{
|
||||||
|
int32_t returnCode;
|
||||||
|
uint64_t returnDataSize;
|
||||||
|
void* returnData;
|
||||||
|
|
||||||
|
} evmjit_result;
|
||||||
|
|
||||||
|
evmjit_result evmjit_run(void* _data, void* _env);
|
||||||
|
|
||||||
// JIT object opaque type
|
// JIT object opaque type
|
||||||
typedef struct evm_jit evm_jit;
|
typedef struct evm_jit evm_jit;
|
||||||
|
|
|
||||||
15
vm/vm_jit.go
15
vm/vm_jit.go
|
|
@ -8,6 +8,7 @@ import "github.com/ethereum/go-ethereum/state"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#include "../evmjit/libevmjit/interface.h"
|
#include "../evmjit/libevmjit/interface.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#cgo LDFLAGS: -L/home/chfast/go/src/github.com/ethereum/go-ethereum/evmjit/build/libevmjit -levmjit
|
#cgo LDFLAGS: -L/home/chfast/go/src/github.com/ethereum/go-ethereum/evmjit/build/libevmjit -levmjit
|
||||||
*/
|
*/
|
||||||
|
|
@ -146,18 +147,24 @@ func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *bi
|
||||||
data.callData = getDataPtr(callData)
|
data.callData = getDataPtr(callData)
|
||||||
data.code = getDataPtr(code)
|
data.code = getDataPtr(code)
|
||||||
|
|
||||||
r := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self))
|
result := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self))
|
||||||
//fmt.Printf("JIT result: %d\n", r)
|
//fmt.Printf("JIT result: %d\n", r)
|
||||||
|
|
||||||
if r >= 100 {
|
if result.returnCode >= 100 {
|
||||||
err = errors.New("OOG from JIT")
|
err = errors.New("OOG from JIT")
|
||||||
gas.SetInt64(0) // Set gas to 0, JIT do not bother
|
gas.SetInt64(0) // Set gas to 0, JIT does not bother
|
||||||
} else {
|
} else {
|
||||||
gasLeft := llvm2big(&data.elems[Gas]) // TODO: Set value directly to gas instance
|
gasLeft := llvm2big(&data.elems[Gas]) // TODO: Set value directly to gas instance
|
||||||
gas.Set(gasLeft)
|
gas.Set(gasLeft)
|
||||||
|
if result.returnCode == 1 { // RETURN
|
||||||
|
returnData := llvm2bytes((*byte)(result.returnData), uint64(result.returnDataSize))
|
||||||
|
ret = make([]byte, len(returnData))
|
||||||
|
copy(ret, returnData)
|
||||||
|
C.free(result.returnData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret, err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine {
|
func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue