in drools-mvel/src/main/java/org/drools/mvel/asm/DefaultBeanClassBuilder.java [1595:1740]
protected void buildHashCode(ClassVisitor cw,
ClassDefinition classDef) {
MethodVisitor mv;
// Building hashCode() method
{
mv = cw.visitMethod( Opcodes.ACC_PUBLIC,
"hashCode",
"()I",
null,
null );
mv.visitCode();
Label l0 = null;
if ( this.debug ) {
l0 = new Label();
mv.visitLabel( l0 );
}
// int result = 1;
mv.visitInsn( Opcodes.ICONST_1 );
mv.visitVarInsn( Opcodes.ISTORE,
1 );
// for each key field
for ( FieldDefinition field : classDef.getFieldsDefinitions() ) {
if ( field.isKey() ) {
// result = result * 31 + <attr_hash>
mv.visitVarInsn( Opcodes.ILOAD,
1 );
mv.visitIntInsn( Opcodes.BIPUSH,
31 );
mv.visitVarInsn( Opcodes.ILOAD,
1 );
mv.visitInsn( Opcodes.IMUL );
mv.visitVarInsn(Opcodes.ALOAD,
0);
visitFieldOrGetter(mv, classDef, field);
if ( "boolean".equals( field.getTypeName() ) ) {
// attr_hash ::== <boolean_attr> ? 1231 : 1237;
Label blabel1 = new Label();
mv.visitJumpInsn( Opcodes.IFEQ,
blabel1 );
mv.visitIntInsn( Opcodes.SIPUSH,
1231 );
Label blabel2 = new Label();
mv.visitJumpInsn( Opcodes.GOTO,
blabel2 );
mv.visitLabel( blabel1 );
mv.visitIntInsn( Opcodes.SIPUSH,
1237 );
mv.visitLabel( blabel2 );
} else if ( "long".equals( field.getTypeName() ) ) {
// attr_hash ::== (int) (longAttr ^ (longAttr >>> 32))
mv.visitVarInsn( Opcodes.ALOAD,
0 );
visitFieldOrGetter(mv, classDef, field);
mv.visitIntInsn( Opcodes.BIPUSH,
32 );
mv.visitInsn( Opcodes.LUSHR );
mv.visitInsn( Opcodes.LXOR );
mv.visitInsn( Opcodes.L2I );
} else if ( "float".equals( field.getTypeName() ) ) {
// attr_hash ::== Float.floatToIntBits( floatAttr );
mv.visitMethodInsn( Opcodes.INVOKESTATIC,
Type.getInternalName( Float.class ),
"floatToIntBits",
"(F)I" );
} else if ( "double".equals( field.getTypeName() ) ) {
// attr_hash ::== (int) (Double.doubleToLongBits( doubleAttr ) ^ (Double.doubleToLongBits( doubleAttr ) >>> 32));
mv.visitMethodInsn( Opcodes.INVOKESTATIC,
Type.getInternalName( Double.class ),
"doubleToLongBits",
"(D)J" );
mv.visitInsn( Opcodes.DUP2 );
mv.visitIntInsn( Opcodes.BIPUSH,
32 );
mv.visitInsn( Opcodes.LUSHR );
mv.visitInsn( Opcodes.LXOR );
mv.visitInsn( Opcodes.L2I );
} else if ( !BuildUtils.isPrimitive(field.getTypeName()) ) {
// attr_hash ::== ((objAttr == null) ? 0 : objAttr.hashCode());
Label olabel1 = new Label();
mv.visitJumpInsn( Opcodes.IFNONNULL,
olabel1 );
mv.visitInsn( Opcodes.ICONST_0 );
Label olabel2 = new Label();
mv.visitJumpInsn( Opcodes.GOTO,
olabel2 );
mv.visitLabel( olabel1 );
mv.visitVarInsn( Opcodes.ALOAD,
0 );
visitFieldOrGetter(mv, classDef, field);
if ( ! BuildUtils.isArray( field.getTypeName() ) ) {
mv.visitMethodInsn( Opcodes.INVOKEVIRTUAL,
"java/lang/Object",
"hashCode",
"()I" );
} else {
mv.visitMethodInsn( INVOKESTATIC,
"java/util/Arrays",
"hashCode",
"(" + BuildUtils.arrayType( field.getTypeName() ) + ")I");
}
mv.visitLabel( olabel2 );
}
mv.visitInsn( Opcodes.IADD );
mv.visitVarInsn( Opcodes.ISTORE,
1 );
}
}
mv.visitVarInsn( Opcodes.ILOAD,
1 );
mv.visitInsn( Opcodes.IRETURN );
Label lastLabel;
if ( this.debug ) {
lastLabel = new Label();
mv.visitLabel( lastLabel );
mv.visitLocalVariable( "this",
BuildUtils.getTypeDescriptor( classDef.getClassName() ),
null,
l0,
lastLabel,
0 );
mv.visitLocalVariable( "hash",
Type.getDescriptor( int.class ),
null,
l0,
lastLabel,
1 );
}
mv.visitMaxs( 0,
0 );
mv.visitEnd();
}
}