Skip to content

Commit

Permalink
Reduce UInt256 in EVMOperations (hyperledger#5331)
Browse files Browse the repository at this point in the history
Performance improvements
- Reduce the use of UInt256 in operations, replacing them with Bytes as
   appropriate.
- Use Java17 expression switch

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
  • Loading branch information
shemnon authored and elenduuche committed Aug 16, 2023
1 parent 72fbb5c commit e493862
Show file tree
Hide file tree
Showing 63 changed files with 428 additions and 420 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- Add new sepolia bootnodes, which should improve peering in the testnet. [#5352](https://github.com/hyperledger/besu/pull/5352)
- Renamed --bonsai-maximum-back-layers-to-load option to --bonsai-historical-block-limit for clarity. Removed --Xbonsai-use-snapshots option as it is no longer functional [#5337](https://github.com/hyperledger/besu/pull/5337)
- Change Forest to use TransactionDB instead of OptimisticTransactionDB [#5328](https://github.com/hyperledger/besu/pull/5328)
- Performance: Reduced usage of UInt256 in EVM operations [#5331](https://github.com/hyperledger/besu/pull/5331)

### Bug Fixes

Expand Down
268 changes: 113 additions & 155 deletions evm/src/main/java/org/hyperledger/besu/evm/EVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.internal.FixedStack.OverflowException;
import org.hyperledger.besu.evm.internal.FixedStack.UnderflowException;
import org.hyperledger.besu.evm.operation.AddModOperation;
import org.hyperledger.besu.evm.operation.AddOperation;
import org.hyperledger.besu.evm.operation.AndOperation;
import org.hyperledger.besu.evm.operation.ByteOperation;
import org.hyperledger.besu.evm.operation.DivOperation;
import org.hyperledger.besu.evm.operation.DupOperation;
import org.hyperledger.besu.evm.operation.ExpOperation;
import org.hyperledger.besu.evm.operation.GtOperation;
import org.hyperledger.besu.evm.operation.InvalidOperation;
import org.hyperledger.besu.evm.operation.IsZeroOperation;
import org.hyperledger.besu.evm.operation.JumpDestOperation;
import org.hyperledger.besu.evm.operation.JumpOperation;
import org.hyperledger.besu.evm.operation.JumpiOperation;
import org.hyperledger.besu.evm.operation.LtOperation;
import org.hyperledger.besu.evm.operation.ModOperation;
import org.hyperledger.besu.evm.operation.MulModOperation;
import org.hyperledger.besu.evm.operation.MulOperation;
import org.hyperledger.besu.evm.operation.NotOperation;
import org.hyperledger.besu.evm.operation.Operation;
Expand All @@ -42,11 +52,13 @@
import org.hyperledger.besu.evm.operation.PopOperation;
import org.hyperledger.besu.evm.operation.Push0Operation;
import org.hyperledger.besu.evm.operation.PushOperation;
import org.hyperledger.besu.evm.operation.SDivOperation;
import org.hyperledger.besu.evm.operation.SGtOperation;
import org.hyperledger.besu.evm.operation.SLtOperation;
import org.hyperledger.besu.evm.operation.SModOperation;
import org.hyperledger.besu.evm.operation.SignExtendOperation;
import org.hyperledger.besu.evm.operation.StopOperation;
import org.hyperledger.besu.evm.operation.SubOperation;
import org.hyperledger.besu.evm.operation.SwapOperation;
import org.hyperledger.besu.evm.operation.VirtualOperation;
import org.hyperledger.besu.evm.operation.XorOperation;
Expand Down Expand Up @@ -152,161 +164,107 @@ public void runToHalt(final MessageFrame frame, final OperationTracer tracing) {

OperationResult result;
try {
switch (opcode) {
// case 0x00: // STOP
// result = StopOperation.staticOperation(frame);
// break;
case 0x01: // ADD
result = AddOperation.staticOperation(frame);
break;
case 0x02: // MUL
result = MulOperation.staticOperation(frame);
break;
// case 0x03: // SUB
// result = SubOperation.staticOperation(frame);
// break;
// case 0x04: // DIV
// result = DivOperation.staticOperation(frame);
// break;
// case 0x05: // SDIV
// result = SDivOperation.staticOperation(frame);
// break;
// case 0x06: // MOD
// result = ModOperation.staticOperation(frame);
// break;
case 0x07: // SMOD
result = SModOperation.staticOperation(frame);
break;
// case 0x08: // ADDMOD
// result = AddModOperation.staticOperation(frame);
// break;
// case 0x09: // MULMOD
// result = MulModOperation.staticOperation(frame);
// break;
// case 0x0a: //EXP requires gasCalculator access, so it is skipped
case 0x0b: // SIGNEXTEND
result = SignExtendOperation.staticOperation(frame);
break;
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
result = InvalidOperation.INVALID_RESULT;
break;
// case 0x10: // LT
// result = LtOperation.staticOperation(frame);
// break;
// case 0x11: // GT
// result = GtOperation.staticOperation(frame);
// break;
case 0x12: // SLT
result = SLtOperation.staticOperation(frame);
break;
case 0x13: // SGT
result = SGtOperation.staticOperation(frame);
break;
case 0x15: // ISZERO
result = IsZeroOperation.staticOperation(frame);
break;
case 0x16: // AND
result = AndOperation.staticOperation(frame);
break;
case 0x17: // OR
result = OrOperation.staticOperation(frame);
break;
case 0x18: // XOR
result = XorOperation.staticOperation(frame);
break;
case 0x19: // NOT
result = NotOperation.staticOperation(frame);
break;
case 0x1a: // BYTE
result = ByteOperation.staticOperation(frame);
break;
case 0x50: // POP
result = PopOperation.staticOperation(frame);
break;
case 0x5f: // PUSH0
result =
enableShanghai
? Push0Operation.staticOperation(frame)
: InvalidOperation.INVALID_RESULT;
break;
case 0x60: // PUSH1-32
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x78:
case 0x79:
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
result = PushOperation.staticOperation(frame, code, pc, opcode - PUSH_BASE);
break;
case 0x80: // DUP1-16
case 0x81:
case 0x82:
case 0x83:
case 0x84:
case 0x85:
case 0x86:
case 0x87:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
result = DupOperation.staticOperation(frame, opcode - DupOperation.DUP_BASE);
break;
case 0x90: // SWAP1-16
case 0x91:
case 0x92:
case 0x93:
case 0x94:
case 0x95:
case 0x96:
case 0x97:
case 0x98:
case 0x99:
case 0x9a:
case 0x9b:
case 0x9c:
case 0x9d:
case 0x9e:
case 0x9f:
result = SwapOperation.staticOperation(frame, opcode - SWAP_BASE);
break;
default: // unoptimized operations
frame.setCurrentOperation(currentOperation);
result = currentOperation.execute(frame, this);
break;
}
result =
switch (opcode) {
case 0x00 -> StopOperation.staticOperation(frame);
case 0x01 -> AddOperation.staticOperation(frame);
case 0x02 -> MulOperation.staticOperation(frame);
case 0x03 -> SubOperation.staticOperation(frame);
case 0x04 -> DivOperation.staticOperation(frame);
case 0x05 -> SDivOperation.staticOperation(frame);
case 0x06 -> ModOperation.staticOperation(frame);
case 0x07 -> SModOperation.staticOperation(frame);
case 0x08 -> AddModOperation.staticOperation(frame);
case 0x09 -> MulModOperation.staticOperation(frame);
case 0x0a -> ExpOperation.staticOperation(frame, gasCalculator);
case 0x0b -> SignExtendOperation.staticOperation(frame);
case 0x0c, 0x0d, 0x0e, 0x0f -> InvalidOperation.INVALID_RESULT;
case 0x10 -> LtOperation.staticOperation(frame);
case 0x11 -> GtOperation.staticOperation(frame);
case 0x12 -> SLtOperation.staticOperation(frame);
case 0x13 -> SGtOperation.staticOperation(frame);
case 0x15 -> IsZeroOperation.staticOperation(frame);
case 0x16 -> AndOperation.staticOperation(frame);
case 0x17 -> OrOperation.staticOperation(frame);
case 0x18 -> XorOperation.staticOperation(frame);
case 0x19 -> NotOperation.staticOperation(frame);
case 0x1a -> ByteOperation.staticOperation(frame);
case 0x50 -> PopOperation.staticOperation(frame);
case 0x56 -> JumpOperation.staticOperation(frame);
case 0x57 -> JumpiOperation.staticOperation(frame);
case 0x5b -> JumpDestOperation.JUMPDEST_SUCCESS;
case 0x5f -> enableShanghai
? Push0Operation.staticOperation(frame)
: InvalidOperation.INVALID_RESULT;
case 0x60, // PUSH1-32
0x61,
0x62,
0x63,
0x64,
0x65,
0x66,
0x67,
0x68,
0x69,
0x6a,
0x6b,
0x6c,
0x6d,
0x6e,
0x6f,
0x70,
0x71,
0x72,
0x73,
0x74,
0x75,
0x76,
0x77,
0x78,
0x79,
0x7a,
0x7b,
0x7c,
0x7d,
0x7e,
0x7f -> PushOperation.staticOperation(frame, code, pc, opcode - PUSH_BASE);
case 0x80, // DUP1-16
0x81,
0x82,
0x83,
0x84,
0x85,
0x86,
0x87,
0x88,
0x89,
0x8a,
0x8b,
0x8c,
0x8d,
0x8e,
0x8f -> DupOperation.staticOperation(frame, opcode - DupOperation.DUP_BASE);
case 0x90, // SWAP1-16
0x91,
0x92,
0x93,
0x94,
0x95,
0x96,
0x97,
0x98,
0x99,
0x9a,
0x9b,
0x9c,
0x9d,
0x9e,
0x9f -> SwapOperation.staticOperation(frame, opcode - SWAP_BASE);
default -> { // unoptimized operations
frame.setCurrentOperation(currentOperation);
yield currentOperation.execute(frame, this);
}
};
} catch (final OverflowException oe) {
result = OVERFLOW_RESPONSE;
} catch (final UnderflowException ue) {
Expand Down
29 changes: 29 additions & 0 deletions evm/src/main/java/org/hyperledger/besu/evm/internal/Words.java
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,33 @@ static int readBigEndianI16(final int index, final byte[] array) {
}
return (array[index] << 8) | (array[index + 1] & 0xff);
}

/**
* Get the big-endian Bytes representation of an unsigned int, including leading zeros
*
* @param value the int value
* @return a Bytes object of the value, Big Endian order
*/
static Bytes intBytes(final int value) {
return Bytes.of(
(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) value);
}

/**
* Get the big-endian Bytes representation of an unsigned int, including leading zeros
*
* @param value the long value
* @return a Bytes object of the value, Big Endian order
*/
static Bytes longBytes(final long value) {
return Bytes.of(
(byte) (value >>> 56),
(byte) (value >>> 48),
(byte) (value >>> 40),
(byte) (value >>> 32),
(byte) (value >>> 24),
(byte) (value >>> 16),
(byte) (value >>> 8),
(byte) value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.hyperledger.besu.evm.gascalculator.GasCalculator;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.units.bigints.UInt256;

/**
* A skeleton class for implementing call operations.
Expand Down Expand Up @@ -184,7 +183,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
frame.expandMemory(outputDataOffset(frame), outputDataLength(frame));
frame.incrementRemainingGas(gasAvailableForChildCall(frame) + cost);
frame.popStackItems(getStackItemsConsumed());
frame.pushStackItem(UInt256.ZERO);
frame.pushStackItem(FAILURE_STACK_ITEM);
return new OperationResult(cost, null);
}

Expand Down Expand Up @@ -268,9 +267,9 @@ public void complete(final MessageFrame frame, final MessageFrame childFrame) {
frame.popStackItems(getStackItemsConsumed());
if (childFrame.getState() == MessageFrame.State.COMPLETED_SUCCESS) {
frame.mergeWarmedUpFields(childFrame);
frame.pushStackItem(UInt256.ONE);
frame.pushStackItem(SUCCESS_STACK_ITEM);
} else {
frame.pushStackItem(UInt256.ZERO);
frame.pushStackItem(FAILURE_STACK_ITEM);
}

final int currentPC = frame.getPC();
Expand Down
Loading

0 comments on commit e493862

Please sign in to comment.