Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/il-evm' into temp/always…
Browse files Browse the repository at this point in the history
…-on-ilvm
  • Loading branch information
Demuirgos committed Nov 8, 2024
2 parents 89efbcf + 11ae042 commit 86620d5
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 18 deletions.
128 changes: 111 additions & 17 deletions src/Nethermind/Nethermind.Evm/CodeAnalysis/IL/ILCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Nethermind.Evm.Config;
using Nethermind.Evm.IL;
using Nethermind.Evm.Tracing;
using Nethermind.Evm.Tracing.Debugger;
using Nethermind.Int256;
using Nethermind.State;
using Sigil;
Expand Down Expand Up @@ -210,7 +211,12 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadConstant(EvmStack.MaxStackSize);
method.BranchIfGreaterOrEqual(evmExceptionLabels[EvmExceptionType.StackOverflow]);
}

#if DEBUG
if(bakeInTracerCalls)
{
EmitDebuggerTracerCall(method, gasAvailable, programCounter, head, stack);
}
#endif
// else emit
switch (op.Operation)
{
Expand Down Expand Up @@ -1588,12 +1594,17 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadLocalAddress(uint256A);
method.LoadLocalAddress(localReadonOnlySpan);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);

MethodInfo sstoreMethod =
typeof(VirtualMachine<VirtualMachine.NotTracing>)
.GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.InstructionSStore), BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(VirtualMachine.NotTracing), typeof(VirtualMachine.NotTracing), typeof(VirtualMachine.NotTracing));
bakeInTracerCalls
? typeof(VirtualMachine<VirtualMachine.IsTracing>)
.GetMethod(nameof(VirtualMachine<VirtualMachine.IsTracing>.InstructionSStore), BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(VirtualMachine.IsTracing), typeof(VirtualMachine.IsTracing), typeof(VirtualMachine.IsTracing))
: typeof(VirtualMachine<VirtualMachine.NotTracing>)
.GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.InstructionSStore), BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(VirtualMachine.NotTracing), typeof(VirtualMachine.NotTracing), typeof(VirtualMachine.NotTracing));

method.Call(sstoreMethod);

Label endOfOpcode = method.DefineLabel();
Expand All @@ -1605,6 +1616,10 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadArgument(VMSTATE_INDEX);
method.LoadLocal(uint32A);
method.StoreField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.EvmException)));

method.LoadArgument(VMSTATE_INDEX);
method.LoadLocal(gasAvailable);
method.StoreField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.GasAvailable)));
method.Branch(exit);

method.MarkLabel(endOfOpcode);
Expand Down Expand Up @@ -1639,7 +1654,7 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadLocalAddress(storageCell);
method.LoadConstant((int)VirtualMachine<VirtualMachine.NotTracing>.StorageAccessType.SLOAD);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);
method.Call(typeof(VirtualMachine<VirtualMachine.NotTracing>).GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.ChargeStorageAccessGas), BindingFlags.Static | BindingFlags.NonPublic));
method.BranchIfFalse(evmExceptionLabels[EvmExceptionType.OutOfGas]);

Expand Down Expand Up @@ -1677,7 +1692,7 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadConstant(true);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);
method.LoadConstant(true);
method.Call(typeof(VirtualMachine<VirtualMachine.NotTracing>).GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.ChargeAccountAccessGas)));
method.BranchIfFalse(evmExceptionLabels[EvmExceptionType.OutOfGas]);
Expand Down Expand Up @@ -1739,7 +1754,7 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadConstant(true);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);
method.LoadConstant(true);
method.Call(typeof(VirtualMachine<VirtualMachine.NotTracing>).GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.ChargeAccountAccessGas)));
method.BranchIfFalse(evmExceptionLabels[EvmExceptionType.OutOfGas]);
Expand Down Expand Up @@ -1805,29 +1820,59 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadConstant(true);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);
method.LoadConstant(true);
method.Call(typeof(VirtualMachine<VirtualMachine.NotTracing>).GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.ChargeAccountAccessGas)));
method.BranchIfFalse(evmExceptionLabels[EvmExceptionType.OutOfGas]);

Label pushZeroLabel = method.DefineLabel();
Label pushhashcodeLabel = method.DefineLabel();

// account exists
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(address);
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IWorldState.AccountExists)));
method.LoadConstant(false);
method.CompareEqual();
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IReadOnlyStateProvider.AccountExists)));
method.BranchIfFalse(pushZeroLabel);

method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(address);
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IWorldState.IsDeadAccount)));
method.Or();
method.BranchIfTrue(endOfOpcode);
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IReadOnlyStateProvider.IsDeadAccount)));
method.BranchIfTrue(pushZeroLabel);

using Local delegateAddress = method.DeclareLocal<Address>();
method.LoadArgument(CODE_INFO_REPOSITORY_INDEX);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(address);
method.LoadLocalAddress(delegateAddress);
method.CallVirtual(typeof(ICodeInfoRepository).GetMethod(nameof(ICodeInfoRepository.TryGetDelegation), [typeof(IWorldState), typeof(Address), typeof(Address).MakeByRefType()]));
method.BranchIfFalse(pushhashcodeLabel);

method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(delegateAddress);
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IReadOnlyStateProvider.AccountExists)));
method.BranchIfFalse(pushZeroLabel);

method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(delegateAddress);
method.CallVirtual(typeof(IReadOnlyStateProvider).GetMethod(nameof(IReadOnlyStateProvider.IsDeadAccount)));
method.BranchIfTrue(pushZeroLabel);

method.MarkLabel(pushhashcodeLabel);
method.CleanAndLoadWord(stack, head);
method.LoadArgument(CODE_INFO_REPOSITORY_INDEX);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadLocal(address);
method.CallVirtual(typeof(IAccountStateProvider).GetMethod(nameof(IWorldState.GetCodeHash)));
method.CallVirtual(typeof(ICodeInfoRepository).GetMethod(nameof(ICodeInfoRepository.GetExecutableCodeHash), [typeof(IWorldState), typeof(Address)]));
method.Call(Word.SetKeccak);
method.Branch(endOfOpcode);

// Push 0
method.MarkLabel(pushZeroLabel);
method.CleanWord(stack, head);

method.MarkLabel(endOfOpcode);
method.StackPush(head);

}
break;
case Instruction.SELFBALANCE:
Expand Down Expand Up @@ -1865,7 +1910,7 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadConstant(false);
method.LoadArgument(WORLD_STATE_INDEX);
method.LoadArgument(SPEC_INDEX);
method.Call(GetPropertyInfo<NullTxTracer>(nameof(NullTxTracer.Instance), false, out _));
method.LoadArgument(TXTRACER_INDEX);
method.LoadConstant(true);
method.Call(typeof(VirtualMachine<VirtualMachine.NotTracing>).GetMethod(nameof(VirtualMachine<VirtualMachine.NotTracing>.ChargeAccountAccessGas)));
method.BranchIfFalse(evmExceptionLabels[EvmExceptionType.OutOfGas]);
Expand Down Expand Up @@ -2036,6 +2081,9 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
method.LoadArgument(VMSTATE_INDEX);
method.LoadConstant((int)kvp.Key);
method.StoreField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.EvmException)));
method.LoadArgument(VMSTATE_INDEX);
method.LoadLocal(gasAvailable);
method.StoreField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.GasAvailable)));
method.Branch(exit);
}

Expand All @@ -2046,6 +2094,52 @@ private static ushort[] EmitSegmentBody(Emit<ExecuteSegment> method, OpcodeInfo[
return jumpDestinations.Keys.ToArray();
}

private static void EmitDebuggerTracerCall(Emit<ExecuteSegment> method, Local gasAvailable, Local pc, Local head, Local stack)
{
// just experimental code
Label skipCall = method.DefineLabel();
using Local debugTracer = method.DeclareLocal<DebugTracer>();
using Local convertedPc = method.DeclareLocal<int>();
using Local castedStack = method.DeclareLocal(typeof(Span<byte>));
using Local vmState = method.DeclareLocal<EvmState>();

method.LoadArgument(TXTRACER_INDEX);
method.IsInstance(typeof(DebugTracer));
method.StoreLocal(debugTracer);
method.Print(convertedPc);

method.LoadLocal(debugTracer);
method.LoadNull();
method.BranchIfEqual(skipCall);


method.LoadLocal(pc);
method.Convert<int>();
method.StoreLocal(convertedPc);

method.LoadArgument(VMSTATE_INDEX);
method.LoadField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.EvmState)));
method.LoadLocal(stack);
method.Call(GetCastMethodInfo<Word, byte>());
method.StoreLocal(castedStack);
method.LoadLocalAddress(castedStack);
method.Call(typeof(Span<byte>).GetMethod(nameof(Span<byte>.ToArray)));
method.StoreField(GetFieldInfo(typeof(EvmState), nameof(EvmState.DataStack)));

method.LoadLocal(debugTracer);
method.LoadArgument(VMSTATE_INDEX);
method.LoadField(GetFieldInfo(typeof(ILEvmState), nameof(ILEvmState.EvmState)));
method.StoreLocal(vmState);

method.LoadLocalAddress(vmState);
method.LoadLocalAddress(convertedPc);
method.LoadLocalAddress(gasAvailable);
method.LoadLocalAddress(head);
method.CallVirtual(typeof(DebugTracer).GetMethod(nameof(DebugTracer.TryWait), BindingFlags.Instance | BindingFlags.Public));

method.MarkLabel(skipCall);
}

private static void EmitCallToErrorTrace(Emit<ExecuteSegment> method, Local gasAvailable, KeyValuePair<EvmExceptionType, Label> kvp)
{
Label skipTracing = method.DefineLabel();
Expand Down
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Evm/Instruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ public struct OpcodeMetadata(long gasCost, byte additionalBytes, byte stackBehav
[Instruction.EXTCODECOPY] = new(DYNAMIC + MEMORY_EXPANSION + ACCOUNT_ACCESS, 0, 4, 0),
[Instruction.RETURNDATASIZE] = new(GasCostOf.Base, 0, 0, 1),
[Instruction.RETURNDATACOPY] = new(GasCostOf.VeryLow + MEMORY_EXPANSION, 0, 3, 0),
[Instruction.EXTCODEHASH] = new(0, 0, 1, 1),
[Instruction.EXTCODEHASH] = new(DYNAMIC, 0, 1, 1),

[Instruction.BLOCKHASH] = new(GasCostOf.BlockHash, 0, 1, 1),
[Instruction.COINBASE] = new(GasCostOf.Base, 0, 0, 1),
Expand Down

0 comments on commit 86620d5

Please sign in to comment.