EVMC: Make `hostInterface` a statically initialised global
We've been filling a "vtable"-like at run time, but it's not necessary. The new object is a global `let x = evmc_host_interface(...)`, we assume it's initialised before the first use, and we take its address with `.unsafeAddr`. (If we use `ref evmc_host_interface`, Nim decides (correctly) that the functions which use it aren't GC-safe because it's a global.) Signed-off-by: Jamie Lokier <jamie@shareable.org>
This commit is contained in:
parent
edd642c048
commit
b783756ff3
|
@ -72,26 +72,22 @@ proc accessStorage(p: evmc_host_context, address: var evmc_address,
|
||||||
key: var evmc_bytes32): evmc_access_status {.cdecl.} =
|
key: var evmc_bytes32): evmc_access_status {.cdecl.} =
|
||||||
toHost(p).accessStorage(address.fromEvmc, key.fromEvmc)
|
toHost(p).accessStorage(address.fromEvmc, key.fromEvmc)
|
||||||
|
|
||||||
proc evmcGetHostInterface(): ref evmc_host_interface =
|
let hostInterface = evmc_host_interface(
|
||||||
var theHostInterface {.global, threadvar.}: ref evmc_host_interface
|
account_exists: accountExists,
|
||||||
if theHostInterface.isNil:
|
get_storage: getStorage,
|
||||||
theHostInterface = (ref evmc_host_interface)(
|
set_storage: setStorage,
|
||||||
account_exists: accountExists,
|
get_balance: getBalance,
|
||||||
get_storage: getStorage,
|
get_code_size: getCodeSize,
|
||||||
set_storage: setStorage,
|
get_code_hash: getCodeHash,
|
||||||
get_balance: getBalance,
|
copy_code: copyCode,
|
||||||
get_code_size: getCodeSize,
|
selfdestruct: selfDestruct,
|
||||||
get_code_hash: getCodeHash,
|
call: call,
|
||||||
copy_code: copyCode,
|
get_tx_context: getTxContext,
|
||||||
selfdestruct: selfDestruct,
|
get_block_hash: getBlockHash,
|
||||||
call: call,
|
emit_log: emitLog,
|
||||||
get_tx_context: getTxContext,
|
access_account: accessAccount,
|
||||||
get_block_hash: getBlockHash,
|
access_storage: accessStorage,
|
||||||
emit_log: emitLog,
|
)
|
||||||
access_account: accessAccount,
|
|
||||||
access_storage: accessStorage,
|
|
||||||
)
|
|
||||||
return theHostInterface
|
|
||||||
|
|
||||||
# The built-in Nimbus EVM, via imported C function.
|
# The built-in Nimbus EVM, via imported C function.
|
||||||
proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, importc.}
|
proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, importc.}
|
||||||
|
@ -111,7 +107,6 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult {.inline.} =
|
||||||
host.showCallReturn(result)
|
host.showCallReturn(result)
|
||||||
return
|
return
|
||||||
|
|
||||||
let hostInterface = evmcGetHostInterface()
|
|
||||||
let hostContext = cast[evmc_host_context](host)
|
let hostContext = cast[evmc_host_context](host)
|
||||||
|
|
||||||
# Without `{.gcsafe.}:` here, the call via `vm.execute` results in a Nim
|
# Without `{.gcsafe.}:` here, the call via `vm.execute` results in a Nim
|
||||||
|
@ -131,7 +126,7 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult {.inline.} =
|
||||||
# TODO: But wait: Why does the Nim EVMC test program compile fine without
|
# TODO: But wait: Why does the Nim EVMC test program compile fine without
|
||||||
# any `gcsafe`, even with `--threads:on`?
|
# any `gcsafe`, even with `--threads:on`?
|
||||||
{.gcsafe.}:
|
{.gcsafe.}:
|
||||||
result = vm.execute(vm, hostInterface[].addr, hostContext,
|
result = vm.execute(vm, hostInterface.unsafeAddr, hostContext,
|
||||||
evmc_revision(host.vmState.fork), host.msg,
|
evmc_revision(host.vmState.fork), host.msg,
|
||||||
if host.code.len > 0: host.code[0].unsafeAddr else: nil,
|
if host.code.len > 0: host.code[0].unsafeAddr else: nil,
|
||||||
host.code.len.csize_t)
|
host.code.len.csize_t)
|
||||||
|
|
Loading…
Reference in New Issue