Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2d92991
ENH: represent UInt256 as big-endian limbs
thomas-quadratic Nov 28, 2025
943b56a
FIX: array indices bugs for fromBytesBE and mulMod.
thomas-quadratic Nov 29, 2025
9290696
FIX: offset indices in mulMod and fromBytesBE
thomas-quadratic Dec 7, 2025
8f512d7
FIX: spotless
thomas-quadratic Dec 7, 2025
d5e61e3
ENH: cleaning addition and compareLimbs
thomas-quadratic Jan 9, 2026
61c809a
ENH: big-endian long limbs for UInt256
thomas-quadratic Jan 12, 2026
c8ef15e
ENH: migrated mod to record based UInt256
thomas-quadratic Jan 20, 2026
7ba2571
FIX: uint256 mod bugs
thomas-quadratic Jan 22, 2026
90f664f
ENH: improve on worst case fromBytesBE
thomas-quadratic Jan 23, 2026
50760c3
FIX: spotless
thomas-quadratic Jan 23, 2026
66dc8dd
REF: records for addMod and mulMod
thomas-quadratic Jan 26, 2026
92b15c9
FIX: spotless and mod bugs
thomas-quadratic Jan 27, 2026
edf16df
FIX: tests passing
thomas-quadratic Jan 28, 2026
b3812e3
FIX: spotless
thomas-quadratic Jan 28, 2026
a343f5c
ENH: use div2by1 instead of div3by2
thomas-quadratic Jan 29, 2026
4a793b4
FIX: spotless
thomas-quadratic Jan 29, 2026
dc2ef2c
FIX: javadoc
thomas-quadratic Jan 30, 2026
6593ae4
Merge branch 'feat/uint256-as-record' into stack_bytes32
daniellehrner Feb 21, 2026
1899bee
first batch of uint256 native stack
daniellehrner Feb 22, 2026
0adc5df
second batch of uint256 native stack, replaced legacy implementations…
daniellehrner Feb 22, 2026
f690fc8
fix benchmarks
daniellehrner Feb 22, 2026
89877eb
stack unsafe methods with stack pool
daniellehrner Feb 23, 2026
ae82cad
do op code operations directly on stack without intermediate values
daniellehrner Feb 23, 2026
88e6391
branch free add and sub
daniellehrner Feb 25, 2026
429f829
use varhandle for byte conversions
daniellehrner Feb 25, 2026
83fa271
bug fixes, mload and mstore improvements
daniellehrner Feb 25, 2026
8273e34
only use primitive byte array in memory
daniellehrner Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
*/
package org.hyperledger.besu.ethereum.vm.operations;

import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomNegativeValue;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomPositiveValue;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomValue;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.bytesToUInt256;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomNegativeUInt256Value;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomPositiveUInt256Value;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomUInt256Value;

import org.hyperledger.besu.evm.UInt256;

import java.util.concurrent.ThreadLocalRandom;

import org.apache.tuweni.bytes.Bytes;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
Expand Down Expand Up @@ -58,10 +60,6 @@ public enum Case {
FULL_RANDOM
}

/** All bits set (32 bytes of 0xFF) - represents -1 in two's complement. */
protected static final Bytes ALL_BITS =
Bytes.fromHexString("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");

@Param({
"SHIFT_0",
"NEGATIVE_SHIFT_1",
Expand All @@ -83,76 +81,70 @@ public void setUp() {
frame = BenchmarkHelper.createMessageCallFrame();

final Case scenario = Case.valueOf(caseName);
aPool = new Bytes[SAMPLE_SIZE]; // shift amount (pushed second, popped first)
bPool = new Bytes[SAMPLE_SIZE]; // value (pushed first, popped second)
aPool = new UInt256[SAMPLE_SIZE]; // shift amount (pushed second, popped first)
bPool = new UInt256[SAMPLE_SIZE]; // value (pushed first, popped second)

final ThreadLocalRandom random = ThreadLocalRandom.current();

for (int i = 0; i < SAMPLE_SIZE; i++) {
switch (scenario) {
case SHIFT_0:
aPool[i] = Bytes.of(0);
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(0);
bPool[i] = randomUInt256Value(random);
break;

case NEGATIVE_SHIFT_1:
// shiftAmount = 0x1, value = 0xfff...fff (negative, tests OR path)
aPool[i] = Bytes.of(1);
bPool[i] = randomNegativeValue(random);
aPool[i] = UInt256.fromInt(1);
bPool[i] = randomNegativeUInt256Value(random);
break;

case ALL_BITS_SHIFT_1:
// shiftAmount = 0x1, value = 0xfff...fff (negative, tests OR path)
aPool[i] = Bytes.of(1);
bPool[i] = ALL_BITS;
aPool[i] = UInt256.fromInt(1);
bPool[i] = UInt256.MAX;
break;

case POSITIVE_SHIFT_1:
// shiftAmount = 0x1, random positive value (no sign extension)
aPool[i] = Bytes.of(1);
bPool[i] = randomPositiveValue(random);
aPool[i] = UInt256.fromInt(1);
bPool[i] = randomPositiveUInt256Value(random);
break;

case NEGATIVE_SHIFT_128:
aPool[i] = Bytes.of(128);
bPool[i] = randomNegativeValue(random);
aPool[i] = UInt256.fromInt(128);
bPool[i] = randomNegativeUInt256Value(random);
break;

case NEGATIVE_SHIFT_255:
aPool[i] = Bytes.of(255);
bPool[i] = randomNegativeValue(random);
aPool[i] = UInt256.fromInt(255);
bPool[i] = randomNegativeUInt256Value(random);
break;

case POSITIVE_SHIFT_128:
aPool[i] = Bytes.of(128);
bPool[i] = randomPositiveValue(random);
aPool[i] = UInt256.fromInt(128);
bPool[i] = randomPositiveUInt256Value(random);
break;
case POSITIVE_SHIFT_255:
aPool[i] = Bytes.of(255);
bPool[i] = randomPositiveValue(random);
aPool[i] = UInt256.fromInt(255);
bPool[i] = randomPositiveUInt256Value(random);
break;

case OVERFLOW_SHIFT_256:
// Shift of exactly 256 - overflow path
aPool[i] = Bytes.fromHexString("0x0100"); // 256
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(256);
bPool[i] = randomUInt256Value(random);
break;

case OVERFLOW_LARGE_SHIFT:
// Shift amount > 4 bytes - overflow path
aPool[i] = Bytes.fromHexString("0x010000000000"); // > 4 bytes
bPool[i] = randomValue(random);
aPool[i] = bytesToUInt256(new byte[] {0x01, 0x00, 0x00, 0x00, 0x00, 0x00});
bPool[i] = randomUInt256Value(random);
break;

case FULL_RANDOM:
default:
// Original random behavior
final byte[] shift = new byte[1 + random.nextInt(2)];
final byte[] value = new byte[1 + random.nextInt(32)];
random.nextBytes(shift);
random.nextBytes(value);
aPool[i] = Bytes.wrap(shift);
bPool[i] = Bytes.wrap(value);
aPool[i] = bytesToUInt256(shift);
bPool[i] = bytesToUInt256(value);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
*/
package org.hyperledger.besu.ethereum.vm.operations;

import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomValue;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.bytesToUInt256;
import static org.hyperledger.besu.ethereum.vm.operations.BenchmarkHelper.randomUInt256Value;

import org.hyperledger.besu.evm.UInt256;

import java.util.concurrent.ThreadLocalRandom;

import org.apache.tuweni.bytes.Bytes;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
Expand Down Expand Up @@ -65,41 +67,41 @@ public void setUp() {
frame = BenchmarkHelper.createMessageCallFrame();

final Case scenario = Case.valueOf(caseName);
aPool = new Bytes[SAMPLE_SIZE]; // shift amount (pushed second, popped first)
bPool = new Bytes[SAMPLE_SIZE]; // value (pushed first, popped second)
aPool = new UInt256[SAMPLE_SIZE]; // shift amount (pushed second, popped first)
bPool = new UInt256[SAMPLE_SIZE]; // value (pushed first, popped second)

final ThreadLocalRandom random = ThreadLocalRandom.current();

for (int i = 0; i < SAMPLE_SIZE; i++) {
switch (scenario) {
case SHIFT_0:
aPool[i] = Bytes.of(0);
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(0);
bPool[i] = randomUInt256Value(random);
break;

case SHIFT_1:
aPool[i] = Bytes.of(1);
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(1);
bPool[i] = randomUInt256Value(random);
break;

case SHIFT_128:
aPool[i] = Bytes.of(128);
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(128);
bPool[i] = randomUInt256Value(random);
break;

case SHIFT_255:
aPool[i] = Bytes.of(255);
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(255);
bPool[i] = randomUInt256Value(random);
break;

case OVERFLOW_SHIFT_256:
aPool[i] = Bytes.fromHexString("0x0100"); // 256
bPool[i] = randomValue(random);
aPool[i] = UInt256.fromInt(256);
bPool[i] = randomUInt256Value(random);
break;

case OVERFLOW_LARGE_SHIFT:
aPool[i] = Bytes.fromHexString("0x010000000000"); // > 4 bytes
bPool[i] = randomValue(random);
aPool[i] = bytesToUInt256(new byte[] {0x01, 0x00, 0x00, 0x00, 0x00, 0x00});
bPool[i] = randomUInt256Value(random);
break;

case FULL_RANDOM:
Expand All @@ -108,8 +110,8 @@ public void setUp() {
final byte[] value = new byte[1 + random.nextInt(32)];
random.nextBytes(shift);
random.nextBytes(value);
aPool[i] = Bytes.wrap(shift);
bPool[i] = Bytes.wrap(value);
aPool[i] = bytesToUInt256(shift);
bPool[i] = bytesToUInt256(value);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
*/
package org.hyperledger.besu.ethereum.vm.operations;

import org.hyperledger.besu.evm.UInt256;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.operation.AddModOperationOptimized;
import org.hyperledger.besu.evm.operation.AddModOperation;
import org.hyperledger.besu.evm.operation.Operation;

import java.util.concurrent.ThreadLocalRandom;

import org.apache.tuweni.bytes.Bytes;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
Expand Down Expand Up @@ -131,9 +131,9 @@ public void setUp() {
frame = BenchmarkHelper.createMessageCallFrame();

Case scenario = Case.valueOf(caseName);
aPool = new Bytes[SAMPLE_SIZE];
bPool = new Bytes[SAMPLE_SIZE];
cPool = new Bytes[SAMPLE_SIZE];
aPool = new UInt256[SAMPLE_SIZE];
bPool = new UInt256[SAMPLE_SIZE];
cPool = new UInt256[SAMPLE_SIZE];

final ThreadLocalRandom random = ThreadLocalRandom.current();
int aSize;
Expand All @@ -154,15 +154,15 @@ public void setUp() {
random.nextBytes(a);
random.nextBytes(b);
random.nextBytes(c);
aPool[i] = Bytes.wrap(a);
bPool[i] = Bytes.wrap(b);
cPool[i] = Bytes.wrap(c);
aPool[i] = BenchmarkHelper.bytesToUInt256(a);
bPool[i] = BenchmarkHelper.bytesToUInt256(b);
cPool[i] = BenchmarkHelper.bytesToUInt256(c);
}
index = 0;
}

@Override
protected Operation.OperationResult invoke(final MessageFrame frame) {
return AddModOperationOptimized.staticOperation(frame);
return AddModOperation.staticOperation(frame, frame.stackData());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
package org.hyperledger.besu.ethereum.vm.operations;

import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.operation.AddOperationOptimized;
import org.hyperledger.besu.evm.operation.AddOperation;
import org.hyperledger.besu.evm.operation.Operation;

public class AddOperationBenchmark extends BinaryOperationBenchmark {

@Override
protected Operation.OperationResult invoke(final MessageFrame frame) {
return AddOperationOptimized.staticOperation(frame);
return AddOperation.staticOperation(frame, frame.stackData());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ public class AndOperationBenchmark extends BinaryOperationBenchmark {

@Override
protected Operation.OperationResult invoke(final MessageFrame frame) {
return AndOperation.staticOperation(frame);
return AndOperation.staticOperation(frame, frame.stackData());
}
}

This file was deleted.

Loading