RFR: 8322292: Rearrange comparison of fields in Record.equals() [v5]

Rob Spoor duke at openjdk.org
Thu Dec 21 18:33:48 UTC 2023


On Thu, 21 Dec 2023 16:58:00 GMT, Sergey Tsypanov <stsypanov at openjdk.org> wrote:

>> Currently if we create a record it's fields are compared in their declaration order. This might be ineffective in cases when two objects have "heavy" fields equals to each other, but different "lightweight" fields (heavy and lightweight in terms of comparison) e.g. primitives, enums, nullable/non-nulls etc.
>> 
>> If we have declared a record like
>> 
>> public record MyRecord(String field1, int field2) {}
>> 
>> It's equals() looks like:
>> 
>>   public final equals(Ljava/lang/Object;)Z
>>    L0
>>     LINENUMBER 3 L0
>>     ALOAD 0
>>     ALOAD 1
>>     INVOKEDYNAMIC equals(Lcom/caspianone/openbanking/productservice/controller/MyRecord;Ljava/lang/Object;)Z [
>>       // handle kind 0x6 : INVOKESTATIC
>>       java/lang/runtime/ObjectMethods.bootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;
>>       // arguments:
>>       com.caspianone.openbanking.productservice.controller.MyRecord.class,
>>       "field1;field2",
>>       // handle kind 0x1 : GETFIELD
>>       com/caspianone/openbanking/productservice/controller/MyRecord.field1(Ljava/lang/String;),
>>       // handle kind 0x1 : GETFIELD
>>       com/caspianone/openbanking/productservice/controller/MyRecord.field2(I)
>>     ]
>>     IRETURN
>>    L1
>>     LOCALVARIABLE this Lcom/caspianone/openbanking/productservice/controller/MyRecord; L0 L1 0
>>     LOCALVARIABLE o Ljava/lang/Object; L0 L1 1
>>     MAXSTACK = 2
>>     MAXLOCALS = 2
>> 
>> This can be improved by rearranging the comparison order of the fields moving enums and primitives upper, and collections/arrays lower.
>
> Sergey Tsypanov has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Update src/java.base/share/classes/java/lang/runtime/ObjectMethods.java
>   
>   Co-authored-by: ExE Boss <3889017+ExE-Boss at users.noreply.github.com>

src/java.base/share/classes/java/lang/runtime/ObjectMethods.java line 224:

> 222:             var rt2 = mh2.type().returnType();
> 223:             return Integer.compare(
> 224:                 rt1.isPrimitive() || rt1.isEnum() || rt1.isArray() ? 1 : Iterable.class.isAssignableFrom(rt1) ? -1 : 0,

Doesn't this put primitives, enums and arrays at the end instead of at the start? I've tried this with a simple array:

Class<?>[] types = { int.class, String.class, List.class, long.class, TimeUnit.class, byte[].class, Integer.class };

The result of sorting:

 Class[7] { interface java.util.List, class java.lang.String, class java.lang.Integer, int, long, class java.util.concurrent.TimeUnit, class [B }

By switching the -1 and 1 I get the primitives etc.  at the start:

 Class[7] { int, long, class java.util.concurrent.TimeUnit, class [B, class java.lang.String, class java.lang.Integer, interface java.util.List }
``

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/17143#discussion_r1434386929


More information about the core-libs-dev mailing list