From d242b190c387a4e2d564f7100c9e7176e1753fbe Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Tue, 18 Oct 2022 17:14:31 +0200 Subject: [PATCH 1/2] Add methods for emitting bitwise AND, OR, XOR --- .../io/quarkus/gizmo/BytecodeCreator.java | 27 +++++++++++++++++++ .../io/quarkus/gizmo/BytecodeCreatorImpl.java | 22 ++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/quarkus/gizmo/BytecodeCreator.java b/src/main/java/io/quarkus/gizmo/BytecodeCreator.java index f493d8e..e1fdf44 100644 --- a/src/main/java/io/quarkus/gizmo/BytecodeCreator.java +++ b/src/main/java/io/quarkus/gizmo/BytecodeCreator.java @@ -996,6 +996,33 @@ default void breakScope() { */ ResultHandle multiply(ResultHandle a1, ResultHandle a2); + /** + * Computes the bitwise AND of the two result handles and returns the result + * + * @param a1 The first number + * @param a2 The second number + * @return The result + */ + ResultHandle bitwiseAnd(ResultHandle a1, ResultHandle a2); + + /** + * Computes the bitwise OR of the two result handles and returns the result + * + * @param a1 The first number + * @param a2 The second number + * @return The result + */ + ResultHandle bitwiseOr(ResultHandle a1, ResultHandle a2); + + /** + * Computes the bitwise XOR of the two result handles and returns the result + * + * @param a1 The first number + * @param a2 The second number + * @return The result + */ + ResultHandle bitwiseXor(ResultHandle a1, ResultHandle a2); + /** * Increments a ResultHandle * diff --git a/src/main/java/io/quarkus/gizmo/BytecodeCreatorImpl.java b/src/main/java/io/quarkus/gizmo/BytecodeCreatorImpl.java index 4d7085b..832ef27 100644 --- a/src/main/java/io/quarkus/gizmo/BytecodeCreatorImpl.java +++ b/src/main/java/io/quarkus/gizmo/BytecodeCreatorImpl.java @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -1249,15 +1248,30 @@ public ForEachLoop forEach(ResultHandle iterable) { @Override public ResultHandle add(ResultHandle a1, ResultHandle a2) { - return emitArithmetic(Opcodes.IADD, a1, a2); + return emitBinaryArithmetic(Opcodes.IADD, a1, a2); } @Override public ResultHandle multiply(ResultHandle a1, ResultHandle a2) { - return emitArithmetic(Opcodes.IMUL, a1, a2); + return emitBinaryArithmetic(Opcodes.IMUL, a1, a2); } - private ResultHandle emitArithmetic(int intOpcode, ResultHandle a1, ResultHandle a2) { + @Override + public ResultHandle bitwiseAnd(ResultHandle a1, ResultHandle a2) { + return emitBinaryArithmetic(Opcodes.IAND, a1, a2); + } + + @Override + public ResultHandle bitwiseOr(ResultHandle a1, ResultHandle a2) { + return emitBinaryArithmetic(Opcodes.IOR, a1, a2); + } + + @Override + public ResultHandle bitwiseXor(ResultHandle a1, ResultHandle a2) { + return emitBinaryArithmetic(Opcodes.IXOR, a1, a2); + } + + private ResultHandle emitBinaryArithmetic(int intOpcode, ResultHandle a1, ResultHandle a2) { Objects.requireNonNull(a1); Objects.requireNonNull(a2); if (!a1.getType().equals(a2.getType())) { From af71b0c6a6eca2c7d7e853e155efe8549e293831 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Tue, 18 Oct 2022 17:32:41 +0200 Subject: [PATCH 2/2] Small change to how `float` and `double` fields are compared in generated `equals()` The `Gizmo.generateEquals()` method used to emit direct `==` comparison even for `float` and `double` fields. This is inconsistent with how arrays of these types are compared (`Arrays.equals()`) and also with the template code IntelliJ generates. This commit changes that to bitwise comparison. Specifically, `float` comparison is now an `int` comparison of `Float.floatToIntBits`, and `double` comparison is `long` comparison of `Double.doubleToLongBits`. --- src/main/java/io/quarkus/gizmo/Gizmo.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/quarkus/gizmo/Gizmo.java b/src/main/java/io/quarkus/gizmo/Gizmo.java index 41d7d9e..4e72d01 100644 --- a/src/main/java/io/quarkus/gizmo/Gizmo.java +++ b/src/main/java/io/quarkus/gizmo/Gizmo.java @@ -1022,6 +1022,9 @@ public ResultHandle getInstance() { } private static class EqualsHashCodeToStringGenerator { + private static final MethodDescriptor FLOAT_TO_INT_BITS = MethodDescriptor.ofMethod(Float.class, "floatToIntBits", int.class, float.class); + private static final MethodDescriptor DOUBLE_TO_LONG_BITS = MethodDescriptor.ofMethod(Double.class, "doubleToLongBits", long.class, double.class); + private static final MethodDescriptor BOOLEAN_ARRAY_EQUALS = MethodDescriptor.ofMethod(Arrays.class, "equals", boolean.class, boolean[].class, boolean[].class); private static final MethodDescriptor BYTE_ARRAY_EQUALS = MethodDescriptor.ofMethod(Arrays.class, "equals", boolean.class, byte[].class, byte[].class); private static final MethodDescriptor SHORT_ARRAY_EQUALS = MethodDescriptor.ofMethod(Arrays.class, "equals", boolean.class, short[].class, short[].class); @@ -1110,13 +1113,13 @@ private void generateEquals() { .falseBranch().returnBoolean(false); break; case "F": // float - // could use `Float.compare` instead of `==` - equals.ifZero(equals.compareFloat(thisValue, thatValue, false)) + // this is consistent with Arrays.equals() and it's also what IntelliJ generates + equals.ifIntegerEqual(equals.invokeStaticMethod(FLOAT_TO_INT_BITS, thisValue), equals.invokeStaticMethod(FLOAT_TO_INT_BITS, thatValue)) .falseBranch().returnBoolean(false); break; case "D": // double - // could use `Double.compare` instead of `==` - equals.ifZero(equals.compareDouble(thisValue, thatValue, false)) + // this is consistent with Arrays.equals() and it's also what IntelliJ generates + equals.ifZero(equals.compareLong(equals.invokeStaticMethod(DOUBLE_TO_LONG_BITS, thisValue), equals.invokeStaticMethod(DOUBLE_TO_LONG_BITS, thatValue))) .falseBranch().returnBoolean(false); break; case "[Z": // boolean[]