Skip to content

Commit cf4b89e

Browse files
committed
Add MUL and DIV operations for EVM v2 with JMH benchmarks
Implements MulOperationV2 and DivOperationV2 using the v2 stack data layout, along with corresponding JMH benchmarks showing ~4x performance improvement over v1 implementations.
1 parent 1df6b70 commit cf4b89e

File tree

4 files changed

+210
-0
lines changed

4 files changed

+210
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.ethereum.vm.operations.v2;
16+
17+
import org.hyperledger.besu.evm.frame.MessageFrame;
18+
import org.hyperledger.besu.evm.operation.Operation;
19+
import org.hyperledger.besu.evm.operation.v2.DivOperationV2;
20+
21+
public class DivOperationBenchmarkV2 extends BinaryOperationBenchmarkV2 {
22+
23+
@Override
24+
protected Operation.OperationResult invoke(final MessageFrame frame) {
25+
return DivOperationV2.staticOperation(frame, frame.stackDataV2());
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.ethereum.vm.operations.v2;
16+
17+
import org.hyperledger.besu.evm.frame.MessageFrame;
18+
import org.hyperledger.besu.evm.operation.Operation;
19+
import org.hyperledger.besu.evm.operation.v2.MulOperationV2;
20+
21+
public class MulOperationBenchmarkV2 extends BinaryOperationBenchmarkV2 {
22+
23+
@Override
24+
protected Operation.OperationResult invoke(final MessageFrame frame) {
25+
return MulOperationV2.staticOperation(frame, frame.stackDataV2());
26+
}
27+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.evm.operation.v2;
16+
17+
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
19+
import org.hyperledger.besu.evm.frame.MessageFrame;
20+
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
21+
import org.hyperledger.besu.evm.operation.Operation;
22+
23+
/**
24+
* EVM v2 DIV operation using long[] stack representation.
25+
*
26+
* <p>Delegates to {@link UInt256#div(UInt256)} for the 256-bit unsigned division, reading operands
27+
* directly from and writing the result back to the long[] stack. Division by zero returns zero per
28+
* EVM specification.
29+
*/
30+
public class DivOperationV2 extends AbstractFixedCostOperationV2 {
31+
32+
private static final Operation.OperationResult DIV_SUCCESS =
33+
new Operation.OperationResult(5, null);
34+
35+
/**
36+
* Instantiates a new Div operation.
37+
*
38+
* @param gasCalculator the gas calculator
39+
*/
40+
public DivOperationV2(final GasCalculator gasCalculator) {
41+
super(0x04, "DIV", 2, 1, gasCalculator, gasCalculator.getLowTierGasCost());
42+
}
43+
44+
@Override
45+
public Operation.OperationResult executeFixedCostOperation(
46+
final MessageFrame frame, final EVM evm) {
47+
return staticOperation(frame, frame.stackDataV2());
48+
}
49+
50+
/**
51+
* Performs DIV on the v2 long[] stack.
52+
*
53+
* @param frame the message frame
54+
* @param s the stack data as a long[] array
55+
* @return the operation result
56+
*/
57+
public static Operation.OperationResult staticOperation(
58+
final MessageFrame frame, final long[] s) {
59+
final int top = frame.stackTopV2();
60+
final int a = (top - 1) * 4;
61+
final int b = (top - 2) * 4;
62+
63+
if (s[b] == 0L && s[b + 1] == 0L && s[b + 2] == 0L && s[b + 3] == 0L) {
64+
s[b] = 0L;
65+
s[b + 1] = 0L;
66+
s[b + 2] = 0L;
67+
s[b + 3] = 0L;
68+
} else {
69+
final UInt256 val0 = new UInt256(s[a], s[a + 1], s[a + 2], s[a + 3]);
70+
final UInt256 val1 = new UInt256(s[b], s[b + 1], s[b + 2], s[b + 3]);
71+
final UInt256 result = val0.div(val1);
72+
73+
s[b] = result.u3();
74+
s[b + 1] = result.u2();
75+
s[b + 2] = result.u1();
76+
s[b + 3] = result.u0();
77+
}
78+
79+
frame.setTopV2(top - 1);
80+
return DIV_SUCCESS;
81+
}
82+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.evm.operation.v2;
16+
17+
import org.hyperledger.besu.evm.EVM;
18+
import org.hyperledger.besu.evm.UInt256;
19+
import org.hyperledger.besu.evm.frame.MessageFrame;
20+
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
21+
import org.hyperledger.besu.evm.operation.Operation;
22+
23+
/**
24+
* EVM v2 MUL operation using long[] stack representation.
25+
*
26+
* <p>Delegates to {@link UInt256#mul(UInt256)} for the 256-bit multiplication, reading operands
27+
* directly from and writing the result back to the long[] stack.
28+
*/
29+
public class MulOperationV2 extends AbstractFixedCostOperationV2 {
30+
31+
private static final Operation.OperationResult MUL_SUCCESS =
32+
new Operation.OperationResult(5, null);
33+
34+
/**
35+
* Instantiates a new Mul operation.
36+
*
37+
* @param gasCalculator the gas calculator
38+
*/
39+
public MulOperationV2(final GasCalculator gasCalculator) {
40+
super(0x02, "MUL", 2, 1, gasCalculator, gasCalculator.getLowTierGasCost());
41+
}
42+
43+
@Override
44+
public Operation.OperationResult executeFixedCostOperation(
45+
final MessageFrame frame, final EVM evm) {
46+
return staticOperation(frame, frame.stackDataV2());
47+
}
48+
49+
/**
50+
* Performs MUL on the v2 long[] stack.
51+
*
52+
* @param frame the message frame
53+
* @param s the stack data as a long[] array
54+
* @return the operation result
55+
*/
56+
public static Operation.OperationResult staticOperation(
57+
final MessageFrame frame, final long[] s) {
58+
final int top = frame.stackTopV2();
59+
final int a = (top - 1) * 4;
60+
final int b = (top - 2) * 4;
61+
62+
final UInt256 val0 = new UInt256(s[a], s[a + 1], s[a + 2], s[a + 3]);
63+
final UInt256 val1 = new UInt256(s[b], s[b + 1], s[b + 2], s[b + 3]);
64+
final UInt256 result = val0.mul(val1);
65+
66+
s[b] = result.u3();
67+
s[b + 1] = result.u2();
68+
s[b + 2] = result.u1();
69+
s[b + 3] = result.u0();
70+
71+
frame.setTopV2(top - 1);
72+
return MUL_SUCCESS;
73+
}
74+
}

0 commit comments

Comments
 (0)