Skip to content

Commit c3f9dd3

Browse files
committed
by-ref peek
1 parent c01e6d8 commit c3f9dd3

File tree

2 files changed

+87
-97
lines changed

2 files changed

+87
-97
lines changed

src/Nethermind/Nethermind.Evm/EvmStack.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public void PopLimbo()
165165
}
166166

167167
/// <summary>
168-
/// Pops an Uint256 written in big endian.
168+
/// Pops an <see cref="UInt256"/>.
169169
/// </summary>
170170
/// <param name="result">The returned value.</param>
171171
public bool PopUInt256(out UInt256 result)
@@ -177,6 +177,20 @@ public bool PopUInt256(out UInt256 result)
177177
return true;
178178
}
179179

180+
/// <summary>
181+
/// Peeks a reference to an <see cref="UInt256"/>.
182+
/// </summary>
183+
public ref UInt256 PeekUInt256Ref()
184+
{
185+
int head = Head;
186+
if (head == 0)
187+
{
188+
return ref Unsafe.NullRef<UInt256>();
189+
}
190+
191+
return ref Unsafe.As<Word, UInt256>(ref _words[head - 1]);
192+
}
193+
180194
private static void Reshuffle(ref Word word)
181195
{
182196
if (Avx2.IsSupported)
@@ -250,7 +264,7 @@ public ref Word PopRef()
250264

251265
head--;
252266
Head = head;
253-
return ref Unsafe.Add(ref MemoryMarshal.GetReference(_words), head);
267+
return ref _words[head];
254268
}
255269

256270
public Span<byte> PopWord256(out UInt256 destination)

src/Nethermind/Nethermind.Evm/VirtualMachine.cs

Lines changed: 71 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,8 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
708708
#if DEBUG
709709
DebugTracer? debugger = _txTracer.GetTracer<DebugTracer>();
710710
#endif
711+
ref UInt256 byRef = ref NullRef<UInt256>();
712+
711713
SkipInit(out UInt256 a);
712714
SkipInit(out UInt256 b);
713715
SkipInit(out UInt256 c);
@@ -741,75 +743,74 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
741743
{
742744
goto EmptyReturn;
743745
}
746+
// Arithmetic operations that pop 2 operands and push one result use PeekUInt256Ref that allows
747+
// to get a ref to the top of the stack.
744748
case Instruction.ADD:
745749
{
746750
gasAvailable -= GasCostOf.VeryLow;
747751

748-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
749752
if (!stack.PopUInt256(out a)) goto StackUnderflow;
750-
UInt256.Add(in a, in b, out result);
751-
stack.PushUInt256(in result);
752-
753+
byRef = ref stack.PeekUInt256Ref();
754+
if (IsNullRef(ref byRef)) goto StackUnderflow;
755+
UInt256.Add(in a, in byRef, out byRef);
753756
break;
754757
}
755758
case Instruction.MUL:
756759
{
757760
gasAvailable -= GasCostOf.Low;
758761

759762
if (!stack.PopUInt256(out a)) goto StackUnderflow;
760-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
761-
UInt256.Multiply(in a, in b, out result);
762-
stack.PushUInt256(in result);
763+
byRef = ref stack.PeekUInt256Ref();
764+
if (IsNullRef(ref byRef)) goto StackUnderflow;
765+
UInt256.Multiply(in a, in byRef, out byRef);
763766
break;
764767
}
765768
case Instruction.SUB:
766769
{
767770
gasAvailable -= GasCostOf.VeryLow;
768771

769772
if (!stack.PopUInt256(out a)) goto StackUnderflow;
770-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
771-
UInt256.Subtract(in a, in b, out result);
772-
773-
stack.PushUInt256(in result);
773+
byRef = ref stack.PeekUInt256Ref();
774+
if (IsNullRef(ref byRef)) goto StackUnderflow;
775+
UInt256.Subtract(in a, in byRef, out byRef);
774776
break;
775777
}
776778
case Instruction.DIV:
777779
{
778780
gasAvailable -= GasCostOf.Low;
779781

780782
if (!stack.PopUInt256(out a)) goto StackUnderflow;
781-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
782-
if (b.IsZero)
783+
byRef = ref stack.PeekUInt256Ref();
784+
if (IsNullRef(ref byRef)) goto StackUnderflow;
785+
if (byRef.IsZero)
783786
{
784-
stack.PushZero();
787+
byRef = default;
785788
}
786789
else
787790
{
788-
UInt256.Divide(in a, in b, out result);
789-
stack.PushUInt256(in result);
791+
UInt256.Divide(in a, in byRef, out byRef);
790792
}
791-
792793
break;
793794
}
794795
case Instruction.SDIV:
795796
{
796797
gasAvailable -= GasCostOf.Low;
797798

798799
if (!stack.PopUInt256(out a)) goto StackUnderflow;
799-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
800-
if (b.IsZero)
800+
byRef = ref stack.PeekUInt256Ref();
801+
if (IsNullRef(ref byRef)) goto StackUnderflow;
802+
if (byRef.IsZero)
801803
{
802-
stack.PushZero();
804+
// NOP
805+
// byRef = default;
803806
}
804-
else if (As<UInt256, Int256>(ref b) == Int256.MinusOne && a == P255)
807+
else if (As<UInt256, Int256>(ref byRef) == Int256.MinusOne && a == P255)
805808
{
806-
result = P255;
807-
stack.PushUInt256(in result);
809+
byRef = P255;
808810
}
809811
else
810812
{
811-
Int256.Divide(in As<UInt256, Int256>(ref a), in As<UInt256, Int256>(ref b), out As<UInt256, Int256>(ref result));
812-
stack.PushUInt256(in result);
813+
Int256.Divide(in As<UInt256, Int256>(ref a), in As<UInt256, Int256>(ref byRef), out As<UInt256, Int256>(ref byRef));
813814
}
814815

815816
break;
@@ -819,26 +820,26 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
819820
gasAvailable -= GasCostOf.Low;
820821

821822
if (!stack.PopUInt256(out a)) goto StackUnderflow;
822-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
823-
UInt256.Mod(in a, in b, out result);
824-
stack.PushUInt256(in result);
823+
byRef = ref stack.PeekUInt256Ref();
824+
if (IsNullRef(ref byRef)) goto StackUnderflow;
825+
UInt256.Mod(in a, in byRef, out byRef);
825826
break;
826827
}
827828
case Instruction.SMOD:
828829
{
829830
gasAvailable -= GasCostOf.Low;
830831

831832
if (!stack.PopUInt256(out a)) goto StackUnderflow;
832-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
833+
byRef = ref stack.PeekUInt256Ref();
834+
if (IsNullRef(ref byRef)) goto StackUnderflow;
833835
if (b.IsZeroOrOne)
834836
{
835-
stack.PushZero();
837+
byRef = default;
836838
}
837839
else
838840
{
839841
As<UInt256, Int256>(ref a)
840-
.Mod(in As<UInt256, Int256>(ref b), out As<UInt256, Int256>(ref result));
841-
stack.PushUInt256(in result);
842+
.Mod(in As<UInt256, Int256>(ref byRef), out As<UInt256, Int256>(ref byRef));
842843
}
843844

844845
break;
@@ -849,16 +850,17 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
849850

850851
if (!stack.PopUInt256(out a)) goto StackUnderflow;
851852
if (!stack.PopUInt256(out b)) goto StackUnderflow;
852-
if (!stack.PopUInt256(out c)) goto StackUnderflow;
853+
byRef = ref stack.PeekUInt256Ref();
854+
if (IsNullRef(ref byRef)) goto StackUnderflow;
853855

854-
if (c.IsZero)
856+
if (byRef.IsZero)
855857
{
856-
stack.PushZero();
858+
// NOP
859+
// byRef = default;
857860
}
858861
else
859862
{
860-
UInt256.AddMod(a, b, c, out result);
861-
stack.PushUInt256(in result);
863+
UInt256.AddMod(a, b, byRef, out byRef);
862864
}
863865

864866
break;
@@ -869,16 +871,17 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
869871

870872
if (!stack.PopUInt256(out a)) goto StackUnderflow;
871873
if (!stack.PopUInt256(out b)) goto StackUnderflow;
872-
if (!stack.PopUInt256(out c)) goto StackUnderflow;
874+
byRef = ref stack.PeekUInt256Ref();
875+
if (IsNullRef(ref byRef)) goto StackUnderflow;
873876

874877
if (c.IsZero)
875878
{
876-
stack.PushZero();
879+
// NOP
880+
// byRef = default;
877881
}
878882
else
879883
{
880-
UInt256.MultiplyMod(in a, in b, in c, out result);
881-
stack.PushUInt256(in result);
884+
UInt256.MultiplyMod(in a, in b, in byRef, out byRef);
882885
}
883886

884887
break;
@@ -953,15 +956,10 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
953956
gasAvailable -= GasCostOf.VeryLow;
954957

955958
if (!stack.PopUInt256(out a)) goto StackUnderflow;
956-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
957-
if (a < b)
958-
{
959-
stack.PushOne();
960-
}
961-
else
962-
{
963-
stack.PushZero();
964-
}
959+
byRef = ref stack.PeekUInt256Ref();
960+
if (IsNullRef(ref byRef)) goto StackUnderflow;
961+
962+
byRef = a < byRef ? UInt256.One : UInt256.Zero;
965963

966964
break;
967965
}
@@ -970,15 +968,10 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
970968
gasAvailable -= GasCostOf.VeryLow;
971969

972970
if (!stack.PopUInt256(out a)) goto StackUnderflow;
973-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
974-
if (a > b)
975-
{
976-
stack.PushOne();
977-
}
978-
else
979-
{
980-
stack.PushZero();
981-
}
971+
byRef = ref stack.PeekUInt256Ref();
972+
if (IsNullRef(ref byRef)) goto StackUnderflow;
973+
974+
byRef = a > byRef ? UInt256.One : UInt256.Zero;
982975

983976
break;
984977
}
@@ -987,16 +980,12 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
987980
gasAvailable -= GasCostOf.VeryLow;
988981

989982
if (!stack.PopUInt256(out a)) goto StackUnderflow;
990-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
983+
byRef = ref stack.PeekUInt256Ref();
984+
if (IsNullRef(ref byRef)) goto StackUnderflow;
991985

992-
if (As<UInt256, Int256>(ref a).CompareTo(As<UInt256, Int256>(ref b)) < 0)
993-
{
994-
stack.PushOne();
995-
}
996-
else
997-
{
998-
stack.PushZero();
999-
}
986+
byRef = As<UInt256, Int256>(ref a).CompareTo(As<UInt256, Int256>(ref byRef)) < 0
987+
? UInt256.One
988+
: UInt256.Zero;
1000989

1001990
break;
1002991
}
@@ -1005,15 +994,12 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
1005994
gasAvailable -= GasCostOf.VeryLow;
1006995

1007996
if (!stack.PopUInt256(out a)) goto StackUnderflow;
1008-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
1009-
if (As<UInt256, Int256>(ref a).CompareTo(As<UInt256, Int256>(ref b)) > 0)
1010-
{
1011-
stack.PushOne();
1012-
}
1013-
else
1014-
{
1015-
stack.PushZero();
1016-
}
997+
byRef = ref stack.PeekUInt256Ref();
998+
if (IsNullRef(ref byRef)) goto StackUnderflow;
999+
1000+
byRef = As<UInt256, Int256>(ref a).CompareTo(As<UInt256, Int256>(ref byRef)) > 0
1001+
? UInt256.One
1002+
: UInt256.Zero;
10171003

10181004
break;
10191005
}
@@ -1022,31 +1008,21 @@ private CallResult ExecuteCode<TTracingInstructions, TTracingRefunds, TTracingSt
10221008
gasAvailable -= GasCostOf.VeryLow;
10231009

10241010
if (!stack.PopUInt256(out a)) goto StackUnderflow;
1025-
if (!stack.PopUInt256(out b)) goto StackUnderflow;
1026-
if (a.Equals(b))
1027-
{
1028-
stack.PushOne();
1029-
}
1030-
else
1031-
{
1032-
stack.PushZero();
1033-
}
1011+
byRef = ref stack.PeekUInt256Ref();
1012+
if (IsNullRef(ref byRef)) goto StackUnderflow;
1013+
1014+
byRef = a.Equals(byRef) ? UInt256.One : UInt256.Zero;
10341015

10351016
break;
10361017
}
10371018
case Instruction.ISZERO:
10381019
{
10391020
gasAvailable -= GasCostOf.VeryLow;
10401021

1041-
if (!stack.PopUInt256(out a)) goto StackUnderflow;
1042-
if (a.IsZero)
1043-
{
1044-
stack.PushOne();
1045-
}
1046-
else
1047-
{
1048-
stack.PushZero();
1049-
}
1022+
byRef = ref stack.PeekUInt256Ref();
1023+
if (IsNullRef(ref byRef)) goto StackUnderflow;
1024+
1025+
byRef = byRef.IsZero ? UInt256.One : UInt256.Zero;
10501026

10511027
break;
10521028
}

0 commit comments

Comments
 (0)