in asm/src/main/java/org/objectweb/asm/Frame.java [1275:1351]
private static boolean merge(
final SymbolTable symbolTable,
final int sourceType,
final int[] dstTypes,
final int dstIndex) {
int dstType = dstTypes[dstIndex];
if (dstType == sourceType) {
// If the types are equal, merge(sourceType, dstType) = dstType, so there is no change.
return false;
}
int srcType = sourceType;
if ((sourceType & ~DIM_MASK) == NULL) {
if (dstType == NULL) {
return false;
}
srcType = NULL;
}
if (dstType == 0) {
// If dstTypes[dstIndex] has never been assigned, merge(srcType, dstType) = srcType.
dstTypes[dstIndex] = srcType;
return true;
}
int mergedType;
if ((dstType & DIM_MASK) != 0 || (dstType & KIND_MASK) == REFERENCE_KIND) {
// If dstType is a reference type of any array dimension.
if (srcType == NULL) {
// If srcType is the NULL type, merge(srcType, dstType) = dstType, so there is no change.
return false;
} else if ((srcType & (DIM_MASK | KIND_MASK)) == (dstType & (DIM_MASK | KIND_MASK))) {
// If srcType has the same array dimension and the same kind as dstType.
if ((dstType & KIND_MASK) == REFERENCE_KIND) {
// If srcType and dstType are reference types with the same array dimension,
// merge(srcType, dstType) = dim(srcType) | common super class of srcType and dstType.
mergedType =
(srcType & DIM_MASK)
| REFERENCE_KIND
| symbolTable.addMergedType(srcType & VALUE_MASK, dstType & VALUE_MASK);
} else {
// If srcType and dstType are array types of equal dimension but different element types,
// merge(srcType, dstType) = dim(srcType) - 1 | java/lang/Object.
int mergedDim = ELEMENT_OF + (srcType & DIM_MASK);
mergedType = mergedDim | REFERENCE_KIND | symbolTable.addType("java/lang/Object");
}
} else if ((srcType & DIM_MASK) != 0 || (srcType & KIND_MASK) == REFERENCE_KIND) {
// If srcType is any other reference or array type,
// merge(srcType, dstType) = min(srcDdim, dstDim) | java/lang/Object
// where srcDim is the array dimension of srcType, minus 1 if srcType is an array type
// with a non reference element type (and similarly for dstDim).
int srcDim = srcType & DIM_MASK;
if (srcDim != 0 && (srcType & KIND_MASK) != REFERENCE_KIND) {
srcDim = ELEMENT_OF + srcDim;
}
int dstDim = dstType & DIM_MASK;
if (dstDim != 0 && (dstType & KIND_MASK) != REFERENCE_KIND) {
dstDim = ELEMENT_OF + dstDim;
}
mergedType =
Math.min(srcDim, dstDim) | REFERENCE_KIND | symbolTable.addType("java/lang/Object");
} else {
// If srcType is any other type, merge(srcType, dstType) = TOP.
mergedType = TOP;
}
} else if (dstType == NULL) {
// If dstType is the NULL type, merge(srcType, dstType) = srcType, or TOP if srcType is not a
// an array type or a reference type.
mergedType =
(srcType & DIM_MASK) != 0 || (srcType & KIND_MASK) == REFERENCE_KIND ? srcType : TOP;
} else {
// If dstType is any other type, merge(srcType, dstType) = TOP whatever srcType.
mergedType = TOP;
}
if (mergedType != dstType) {
dstTypes[dstIndex] = mergedType;
return true;
}
return false;
}