final boolean merge()

in asm/src/main/java/org/objectweb/asm/Frame.java [1173:1258]


  final boolean merge(
      final SymbolTable symbolTable, final Frame dstFrame, final int catchTypeIndex) {
    boolean frameChanged = false;

    // Compute the concrete types of the local variables at the end of the basic block corresponding
    // to this frame, by resolving its abstract output types, and merge these concrete types with
    // those of the local variables in the input frame of dstFrame.
    int numLocal = inputLocals.length;
    int numStack = inputStack.length;
    if (dstFrame.inputLocals == null) {
      dstFrame.inputLocals = new int[numLocal];
      frameChanged = true;
    }
    for (int i = 0; i < numLocal; ++i) {
      int concreteOutputType;
      if (outputLocals != null && i < outputLocals.length) {
        int abstractOutputType = outputLocals[i];
        if (abstractOutputType == 0) {
          // If the local variable has never been assigned in this basic block, it is equal to its
          // value at the beginning of the block.
          concreteOutputType = inputLocals[i];
        } else {
          concreteOutputType = getConcreteOutputType(abstractOutputType, numStack);
        }
      } else {
        // If the local variable has never been assigned in this basic block, it is equal to its
        // value at the beginning of the block.
        concreteOutputType = inputLocals[i];
      }
      // concreteOutputType might be an uninitialized type from the input locals or from the input
      // stack. However, if a constructor has been called for this class type in the basic block,
      // then this type is no longer uninitialized at the end of basic block.
      if (initializations != null) {
        concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
      }
      frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputLocals, i);
    }

    // If dstFrame is an exception handler block, it can be reached from any instruction of the
    // basic block corresponding to this frame, in particular from the first one. Therefore, the
    // input locals of dstFrame should be compatible (i.e. merged) with the input locals of this
    // frame (and the input stack of dstFrame should be compatible, i.e. merged, with a one
    // element stack containing the caught exception type).
    if (catchTypeIndex > 0) {
      for (int i = 0; i < numLocal; ++i) {
        frameChanged |= merge(symbolTable, inputLocals[i], dstFrame.inputLocals, i);
      }
      if (dstFrame.inputStack == null) {
        dstFrame.inputStack = new int[1];
        frameChanged = true;
      }
      frameChanged |= merge(symbolTable, catchTypeIndex, dstFrame.inputStack, 0);
      return frameChanged;
    }

    // Compute the concrete types of the stack operands at the end of the basic block corresponding
    // to this frame, by resolving its abstract output types, and merge these concrete types with
    // those of the stack operands in the input frame of dstFrame.
    int numInputStack = inputStack.length + outputStackStart;
    if (dstFrame.inputStack == null) {
      dstFrame.inputStack = new int[numInputStack + outputStackTop];
      frameChanged = true;
    }
    // First, do this for the stack operands that have not been popped in the basic block
    // corresponding to this frame, and which are therefore equal to their value in the input
    // frame (except for uninitialized types, which may have been initialized).
    for (int i = 0; i < numInputStack; ++i) {
      int concreteOutputType = inputStack[i];
      if (initializations != null) {
        concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
      }
      frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputStack, i);
    }
    // Then, do this for the stack operands that have pushed in the basic block (this code is the
    // same as the one above for local variables).
    for (int i = 0; i < outputStackTop; ++i) {
      int abstractOutputType = outputStack[i];
      int concreteOutputType = getConcreteOutputType(abstractOutputType, numStack);
      if (initializations != null) {
        concreteOutputType = getInitializedType(symbolTable, concreteOutputType);
      }
      frameChanged |=
          merge(symbolTable, concreteOutputType, dstFrame.inputStack, numInputStack + i);
    }
    return frameChanged;
  }