HHH-16091 AbstractStandardBasicType to avoid megamorphic dispatch when dealing with AbstractClassJavaType

This commit is contained in:
Sanne Grinovero 2023-01-24 15:12:01 +00:00 committed by Sanne Grinovero
parent 567697db55
commit 12abcc4c60
1 changed files with 33 additions and 3 deletions

View File

@ -26,6 +26,7 @@ import org.hibernate.query.sqm.CastType;
import org.hibernate.type.descriptor.ValueBinder; import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor; import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions; import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter; import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
@ -47,6 +48,7 @@ public abstract class AbstractStandardBasicType<T>
private final ValueBinder<T> jdbcValueBinder; private final ValueBinder<T> jdbcValueBinder;
private final ValueExtractor<T> jdbcValueExtractor; private final ValueExtractor<T> jdbcValueExtractor;
private final JdbcLiteralFormatter<T> jdbcLiteralFormatter; private final JdbcLiteralFormatter<T> jdbcLiteralFormatter;
private final AbstractClassJavaType<T> javaTypeAsAbstractClassJavaType;
public AbstractStandardBasicType(JdbcType jdbcType, JavaType<T> javaType) { public AbstractStandardBasicType(JdbcType jdbcType, JavaType<T> javaType) {
this.jdbcType = jdbcType; this.jdbcType = jdbcType;
@ -56,6 +58,13 @@ public abstract class AbstractStandardBasicType<T>
this.jdbcValueBinder = jdbcType.getBinder( javaType ); this.jdbcValueBinder = jdbcType.getBinder( javaType );
this.jdbcValueExtractor = jdbcType.getExtractor( javaType ); this.jdbcValueExtractor = jdbcType.getExtractor( javaType );
this.jdbcLiteralFormatter = jdbcType.getJdbcLiteralFormatter( javaType ); this.jdbcLiteralFormatter = jdbcType.getJdbcLiteralFormatter( javaType );
//This is a dispatch optimisation to avoid megamorphic invocations on the most common type:
if ( javaType instanceof AbstractClassJavaType ) {
this.javaTypeAsAbstractClassJavaType = (AbstractClassJavaType) javaType;
}
else {
this.javaTypeAsAbstractClassJavaType = null;
}
} }
@Override @Override
@ -165,14 +174,35 @@ public abstract class AbstractStandardBasicType<T>
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public boolean isEqual(Object one, Object another) { public boolean isEqual(Object one, Object another) {
return ( one == another ) //optimisation to attempt avoid the need for the method on javaType: if ( one == another ) {
|| javaType.areEqual( (T) one, (T) another ); return true;
}
else if ( one == null || another == null ) {
return false;
}
else {
final AbstractClassJavaType<T> type = this.javaTypeAsAbstractClassJavaType;
if ( type != null ) {
//Optimize for the most common case: avoid the megamorphic call
return type.areEqual( (T) one, (T) another );
}
else {
return javaType.areEqual( (T) one, (T) another );
}
}
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public int getHashCode(Object x) { public int getHashCode(Object x) {
return javaType.extractHashCode( (T) x ); final AbstractClassJavaType<T> type = this.javaTypeAsAbstractClassJavaType;
if ( type != null ) {
//Optimize for the most common case: avoid the megamorphic call
return type.extractHashCode( (T) x );
}
else {
return javaType.extractHashCode( (T) x );
}
} }
@Override @Override