public void setPositions()

in src/main/java/org/apache/bcel/generic/InstructionList.java [1079:1153]


    public void setPositions(final boolean check) { // called by code in other packages
        int maxAdditionalBytes = 0;
        int additionalBytes = 0;
        int index = 0;
        int count = 0;
        final int[] pos = new int[length];
        /*
         * Pass 0: Sanity checks
         */
        if (check) {
            for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
                final Instruction i = ih.getInstruction();
                if (i instanceof BranchInstruction) { // target instruction within list?
                    Instruction inst = ((BranchInstruction) i).getTarget().getInstruction();
                    if (!contains(inst)) {
                        throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
                    }
                    if (i instanceof Select) {
                        final InstructionHandle[] targets = ((Select) i).getTargets();
                        for (final InstructionHandle target : targets) {
                            inst = target.getInstruction();
                            if (!contains(inst)) {
                                throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
                            }
                        }
                    }
                    if (!(ih instanceof BranchHandle)) {
                        throw new ClassGenException(
                            "Branch instruction " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not contained in BranchHandle.");
                    }
                }
            }
        }
        /*
         * Pass 1: Set position numbers and sum up the maximum number of bytes an instruction may be shifted.
         */
        for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
            final Instruction i = ih.getInstruction();
            ih.setPosition(index);
            pos[count++] = index;
            /*
             * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
             * depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH).
             */
            switch (i.getOpcode()) {
            case Const.JSR:
            case Const.GOTO:
                maxAdditionalBytes += 2;
                break;
            case Const.TABLESWITCH:
            case Const.LOOKUPSWITCH:
                maxAdditionalBytes += 3;
                break;
            }
            index += i.getLength();
        }
        /*
         * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that
         * branch targets are within this list.
         */
        for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
            additionalBytes += ih.updatePosition(additionalBytes, maxAdditionalBytes);
        }
        /*
         * Pass 3: Update position numbers (which may have changed due to the preceding expansions), like pass 1.
         */
        index = count = 0;
        for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
            final Instruction i = ih.getInstruction();
            ih.setPosition(index);
            pos[count++] = index;
            index += i.getLength();
        }
        bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size
    }