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:
Jamie Lokier 2021-08-09 17:38:59 +01:00
parent edd642c048
commit b783756ff3
No known key found for this signature in database
GPG Key ID: CBC25C68435C30A2
1 changed files with 17 additions and 22 deletions

View File

@ -72,26 +72,22 @@ proc accessStorage(p: evmc_host_context, address: var evmc_address,
key: var evmc_bytes32): evmc_access_status {.cdecl.} =
toHost(p).accessStorage(address.fromEvmc, key.fromEvmc)
proc evmcGetHostInterface(): ref evmc_host_interface =
var theHostInterface {.global, threadvar.}: ref evmc_host_interface
if theHostInterface.isNil:
theHostInterface = (ref evmc_host_interface)(
account_exists: accountExists,
get_storage: getStorage,
set_storage: setStorage,
get_balance: getBalance,
get_code_size: getCodeSize,
get_code_hash: getCodeHash,
copy_code: copyCode,
selfdestruct: selfDestruct,
call: call,
get_tx_context: getTxContext,
get_block_hash: getBlockHash,
emit_log: emitLog,
access_account: accessAccount,
access_storage: accessStorage,
)
return theHostInterface
let hostInterface = evmc_host_interface(
account_exists: accountExists,
get_storage: getStorage,
set_storage: setStorage,
get_balance: getBalance,
get_code_size: getCodeSize,
get_code_hash: getCodeHash,
copy_code: copyCode,
selfdestruct: selfDestruct,
call: call,
get_tx_context: getTxContext,
get_block_hash: getBlockHash,
emit_log: emitLog,
access_account: accessAccount,
access_storage: accessStorage,
)
# The built-in Nimbus EVM, via imported C function.
proc evmc_create_nimbus_evm(): ptr evmc_vm {.cdecl, importc.}
@ -111,7 +107,6 @@ proc evmcExecComputation*(host: TransactionHost): EvmcResult {.inline.} =
host.showCallReturn(result)
return
let hostInterface = evmcGetHostInterface()
let hostContext = cast[evmc_host_context](host)
# 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
# any `gcsafe`, even with `--threads:on`?
{.gcsafe.}:
result = vm.execute(vm, hostInterface[].addr, hostContext,
result = vm.execute(vm, hostInterface.unsafeAddr, hostContext,
evmc_revision(host.vmState.fork), host.msg,
if host.code.len > 0: host.code[0].unsafeAddr else: nil,
host.code.len.csize_t)