diff --git a/docs/about/changelog.md b/docs/about/changelog.md index 2a6e9ee11..71186a314 100644 --- a/docs/about/changelog.md +++ b/docs/about/changelog.md @@ -6,6 +6,9 @@ priorities and future plans. ## Work in progress +- Avoid redundant modular masking of already unsigned 64-bit bitwise values, + improving general bitwise-heavy workloads such as Life. + - Restore `local` compatibility for tied hash and array elements, sparse arrays, magic stashes, implicit `$_` foreach aliases (including early return), and localized regex captures on both execution backends. diff --git a/src/main/java/org/perlonjava/runtime/operators/BitwiseOperators.java b/src/main/java/org/perlonjava/runtime/operators/BitwiseOperators.java index 381da5eee..fe1aa4f65 100644 --- a/src/main/java/org/perlonjava/runtime/operators/BitwiseOperators.java +++ b/src/main/java/org/perlonjava/runtime/operators/BitwiseOperators.java @@ -17,10 +17,20 @@ public class BitwiseOperators { private static final BigInteger UV_MASK = BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE); private static BigInteger unsignedValue(RuntimeScalar scalar) { - return scalar.getBigint().and(UV_MASK); + BigInteger value = scalar.getBigint(); + // Numeric bitwise operations are modulo 2^64. Their own results are + // already stored in that range, so avoid rebuilding BigInteger's + // backing array just to apply the same mask on the next operation. + if (value.signum() >= 0 && value.bitLength() <= 64) { + return value; + } + return value.and(UV_MASK); } private static RuntimeScalar unsignedResult(BigInteger value) { + if (value.signum() >= 0 && value.bitLength() <= 64) { + return new RuntimeScalar(value); + } return new RuntimeScalar(value.and(UV_MASK)); }