static int merge ( int current , int incoming , ConstantPool pool ) { int currentTag = getTag ( current ) ; int incomingTag = getTag ( incoming ) ; boolean currentIsObject = currentTag == TypeInfo . OBJECT_TAG ; boolean incomingIsObject = incomingTag == TypeInfo . OBJECT_TAG ; if ( current == incoming || ( currentIsObject && incoming == NULL ) ) { return current ; } else if ( currentTag == TypeInfo . TOP || incomingTag == TypeInfo . TOP ) { return TypeInfo . TOP ; } else if ( current == NULL && incomingIsObject ) { return incoming ; } else if ( currentIsObject && incomingIsObject ) { String currentName = getPayloadAsType ( current , pool ) ; String incomingName = getPayloadAsType ( incoming , pool ) ; // The class file always has the class and super names in the same // spot. The constant order is: class_data, class_name, super_data, // super_name. String currentlyGeneratedName = ( String ) pool . getConstantData ( 2 ) ; String currentlyGeneratedSuperName = ( String ) pool . getConstantData ( 4 ) ; // If any of the merged types are the class that's currently being // generated, automatically start at the super class instead. At // this point, we already know the classes are different, so we // don't need to handle that case. if ( currentName . equals ( currentlyGeneratedName ) ) { currentName = currentlyGeneratedSuperName ; } if ( incomingName . equals ( currentlyGeneratedName ) ) { incomingName = currentlyGeneratedSuperName ; } Class < ? > currentClass = getClassFromInternalName ( currentName ) ; Class < ? > incomingClass = getClassFromInternalName ( incomingName ) ; if ( currentClass . isAssignableFrom ( incomingClass ) ) { return current ; } else if ( incomingClass . isAssignableFrom ( currentClass ) ) { return incoming ; } else if ( incomingClass . isInterface ( ) || currentClass . isInterface ( ) ) { // For verification purposes, Sun specifies that interfaces are // subtypes of Object. Therefore, we know that the merge result // involving interfaces where one is not assignable to the // other results in Object. return OBJECT ( "java/lang/Object" , pool ) ; } else { Class < ? > commonClass = incomingClass . getSuperclass ( ) ; while ( commonClass != null ) { if ( commonClass . isAssignableFrom ( currentClass ) ) { String name = commonClass . getName ( ) ; name = ClassFileWriter . getSlashedForm ( name ) ; return OBJECT ( name , pool ) ; } commonClass = commonClass . getSuperclass ( ) ; } } } throw new IllegalArgumentException ( "bad merge attempt between " + toString ( current , pool ) + " and " + toString ( incoming , pool ) ) ; }
Merge two verification types .