com.sun.org.apache.bcel.internal.generic.InstructionHandle

Here are the examples of the java api class com.sun.org.apache.bcel.internal.generic.InstructionHandle taken from open source projects.

1. AlternativePattern#translate()

Project: openjdk
Source File: AlternativePattern.java
View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final InstructionList il = methodGen.getInstructionList();
    _left.translate(classGen, methodGen);
    final InstructionHandle gotot = il.append(new GOTO(null));
    il.append(methodGen.loadContextNode());
    _right.translate(classGen, methodGen);
    _left._trueList.backPatch(gotot);
    _left._falseList.backPatch(gotot.getNext());
    _trueList.append(_right._trueList.add(gotot));
    _falseList.append(_right._falseList);
}

2. MethodGenerator#widenConditionalBranchTargetOffsets()

Project: openjdk
Source File: MethodGenerator.java
View license
/**
     * <p>Rewrites branches to avoid the JVM limits of relative branch
     * offsets.  There is no need to invoke this method if the bytecode for the
     * {@link MethodGenerator} does not exceed 32KB.</p>
     * <p>The Java Virtual Machine Specification permits the code portion of a
     * method to be up to 64KB in length.  However, some control transfer
     * instructions specify relative offsets as a signed 16-bit quantity,
     * limiting the range to a subset of the instructions that might be in a
     * method.</p>
     * <p>The <code>TABLESWITCH</code> and <code>LOOKUPSWITCH</code>
     * instructions always use 32-bit signed relative offsets, so they are
     * immune to this problem.</p>
     * <p>The <code>GOTO</code> and <code>JSR</code>
     * instructions come in two forms, one of which uses 16-bit relative
     * offsets, and the other of which uses 32-bit relative offsets.  The BCEL
     * library decides whether to use the wide form of <code>GOTO</code> or
     * <code>JSR</code>instructions based on the relative offset of the target
     * of the instruction without any intervention by the user of the
     * library.</p>
     * <p>This leaves the various conditional branch instructions,
     * <code>IFEQ</code>, <code>IFNULL</code>, <code>IF_ICMPEQ</code>,
     * <em>et al.</em>, all of which use 16-bit signed relative offsets, with no
     * 32-bit wide form available.</p>
     * <p>This method scans the {@link InstructionList} associated with this
     * {@link MethodGenerator} and finds all conditional branch instructions
     * that might exceed the 16-bit limitation for relative branch offsets.
     * The logic of each such instruction is inverted, and made to target the
     * instruction which follows it.  An unconditional branch to the original
     * target of the instruction is then inserted between the conditional
     * branch and the instruction which previously followed it.  The
     * unconditional branch is permitted to have a 16-bit or a 32-bit relative
     * offset, as described above.  For example,
     * <code>
     * 1234:   NOP
     *          ...
     * 55278:  IFEQ -54044
     * 55280:  NOP
     * </code>
     * is rewritten as
     * <code>
     * 1234:   NOP
     *          ...
     * 55278:  IFNE 7
     * 55280:  GOTO_W -54046
     * 55285:  NOP
     * </code></p>
     * <p><b>Preconditions:</b>
     * <ul><li>The {@link InstructionList#setPositions()} has been called for
     * the <code>InstructionList</code> associated with this
     * <code>MethodGenerator</code>.
     * </li></ul></p>
     * <p><b>Postconditions:</b>
     * <ul><li>Any further changes to the <code>InstructionList</code> for this
     * <code>MethodGenerator</code> will invalidate the changes made by this
     * method.</li></ul>
     * </p>
     * @return <code>true</code> if the <code>InstructionList</code> was
     * modified; <code>false</code> otherwise
     * @see The Java Virtual Machine Specification, Second Edition
     */
boolean widenConditionalBranchTargetOffsets() {
    boolean ilChanged = false;
    int maxOffsetChange = 0;
    InstructionList il = getInstructionList();
    // processing here.
    for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
        Instruction inst = ih.getInstruction();
        switch(inst.getOpcode()) {
            // The size of the branch offset might increase by two bytes.
            case Constants.GOTO:
            case Constants.JSR:
                maxOffsetChange = maxOffsetChange + 2;
                break;
            // their APIs do not expose that information.
            case Constants.TABLESWITCH:
            case Constants.LOOKUPSWITCH:
                maxOffsetChange = maxOffsetChange + 3;
                break;
            // The unconditional branch would require five bytes.
            case Constants.IF_ACMPEQ:
            case Constants.IF_ACMPNE:
            case Constants.IF_ICMPEQ:
            case Constants.IF_ICMPGE:
            case Constants.IF_ICMPGT:
            case Constants.IF_ICMPLE:
            case Constants.IF_ICMPLT:
            case Constants.IF_ICMPNE:
            case Constants.IFEQ:
            case Constants.IFGE:
            case Constants.IFGT:
            case Constants.IFLE:
            case Constants.IFLT:
            case Constants.IFNE:
            case Constants.IFNONNULL:
            case Constants.IFNULL:
                maxOffsetChange = maxOffsetChange + 5;
                break;
        }
    }
    // might possibly exceed the 16-bit relative offset.
    for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
        Instruction inst = ih.getInstruction();
        if (inst instanceof IfInstruction) {
            IfInstruction oldIfInst = (IfInstruction) inst;
            BranchHandle oldIfHandle = (BranchHandle) ih;
            InstructionHandle target = oldIfInst.getTarget();
            int relativeTargetOffset = target.getPosition() - oldIfHandle.getPosition();
            // signed quantity, rewrite the instruction as described above.
            if ((relativeTargetOffset - maxOffsetChange < MIN_BRANCH_TARGET_OFFSET) || (relativeTargetOffset + maxOffsetChange > MAX_BRANCH_TARGET_OFFSET)) {
                // Invert the logic of the IF instruction, and append
                // that to the InstructionList following the original IF
                // instruction
                InstructionHandle nextHandle = oldIfHandle.getNext();
                IfInstruction invertedIfInst = oldIfInst.negate();
                BranchHandle invertedIfHandle = il.append(oldIfHandle, invertedIfInst);
                // Append an unconditional branch to the target of the
                // original IF instruction after the new IF instruction
                BranchHandle gotoHandle = il.append(invertedIfHandle, new GOTO(target));
                // of the new IF
                if (nextHandle == null) {
                    nextHandle = il.append(gotoHandle, NOP);
                }
                // Make the new IF instruction branch around the GOTO
                invertedIfHandle.updateTarget(target, nextHandle);
                // instruction
                if (oldIfHandle.hasTargeters()) {
                    InstructionTargeter[] targeters = oldIfHandle.getTargeters();
                    for (int i = 0; i < targeters.length; i++) {
                        InstructionTargeter targeter = targeters[i];
                        // which wouldn't be accommodated seemlessly.
                        if (targeter instanceof LocalVariableGen) {
                            LocalVariableGen lvg = (LocalVariableGen) targeter;
                            if (lvg.getStart() == oldIfHandle) {
                                lvg.setStart(invertedIfHandle);
                            } else if (lvg.getEnd() == oldIfHandle) {
                                lvg.setEnd(gotoHandle);
                            }
                        } else {
                            targeter.updateTarget(oldIfHandle, invertedIfHandle);
                        }
                    }
                }
                try {
                    il.delete(oldIfHandle);
                } catch (TargetLostException tle) {
                    String msg = new ErrorMsg(ErrorMsg.OUTLINE_ERR_DELETED_TARGET, tle.getMessage()).toString();
                    throw new InternalError(msg);
                }
                // Adjust the pointer in the InstructionList to point after
                // the newly inserted IF instruction
                ih = gotoHandle;
                // Indicate that this method rewrote at least one IF
                ilChanged = true;
            }
        }
    }
    // Did this method rewrite any IF instructions?
    return ilChanged;
}

3. MethodGenerator#offsetInLocalVariableGenRange()

Project: openjdk
Source File: MethodGenerator.java
View license
/**
     * Determines whether a particular variable is in use at a particular offset
     * in the byte code for this method.
     * <p><b>Preconditions:</b>
     * <ul>
     * <li>The {@link InstructionList#setPositions()} has been called for the
     * {@link InstructionList} associated with this {@link MethodGenerator}.
     * </li></ul></p>
     * @param lvg the {@link LocalVariableGen} for the variable
     * @param offset the position in the byte code
     * @return <code>true</code> if and only if the specified variable is in
     * use at the particular byte code offset.
     */
boolean offsetInLocalVariableGenRange(LocalVariableGen lvg, int offset) {
    InstructionHandle lvgStart = lvg.getStart();
    InstructionHandle lvgEnd = lvg.getEnd();
    // assumed to be in use from the beginning of the method.
    if (lvgStart == null) {
        lvgStart = getInstructionList().getStart();
    }
    // to be in use to the end of the method.
    if (lvgEnd == null) {
        lvgEnd = getInstructionList().getEnd();
    }
    // varible is in range at a particular offset.
    return ((lvgStart.getPosition() <= offset) && (lvgEnd.getPosition() + lvgEnd.getInstruction().getLength() >= offset));
}

4. Key#translate()

Project: openjdk
Source File: Key.java
View license
/**
     * Gather all nodes that match the expression in the attribute "match"
     * and add one (or more) entries in this key's index.
     */
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    final int current = methodGen.getLocalIndex("current");
    // AbstractTranslet.buildKeyIndex(name,node_id,value) => void
    final int key = cpg.addMethodref(TRANSLET_CLASS, "buildKeyIndex", "(" + STRING_SIG + "I" + STRING_SIG + ")V");
    // AbstractTranslet.SetKeyIndexDom(name, Dom) => void
    final int keyDom = cpg.addMethodref(TRANSLET_CLASS, "setKeyIndexDom", "(" + STRING_SIG + DOM_INTF_SIG + ")V");
    final int getNodeIdent = cpg.addInterfaceMethodref(DOM_INTF, "getNodeIdent", "(I)" + NODE_SIG);
    // DOM.getAxisIterator(root) => NodeIterator
    final int git = cpg.addInterfaceMethodref(DOM_INTF, "getAxisIterator", "(I)" + NODE_ITERATOR_SIG);
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadIterator());
    // Get an iterator for all nodes in the DOM
    il.append(methodGen.loadDOM());
    il.append(new PUSH(cpg, Axis.DESCENDANT));
    il.append(new INVOKEINTERFACE(git, 2));
    // Reset the iterator to start with the root node
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.setStartNode());
    il.append(methodGen.storeIterator());
    // Loop for traversing all nodes in the DOM
    final BranchHandle nextNode = il.append(new GOTO(null));
    final InstructionHandle loop = il.append(NOP);
    // Check if the current node matches the pattern in "match"
    il.append(methodGen.loadCurrentNode());
    _match.translate(classGen, methodGen);
    // Leaves 0 or 1 on stack
    _match.synthesize(classGen, methodGen);
    final BranchHandle skipNode = il.append(new IFEQ(null));
    // If this is a node-set we must go through each node in the set
    if (_useType instanceof NodeSetType) {
        // Pass current node as parameter (we're indexing on that node)
        il.append(methodGen.loadCurrentNode());
        traverseNodeSet(classGen, methodGen, key);
    } else {
        il.append(classGen.loadTranslet());
        il.append(DUP);
        il.append(new PUSH(cpg, _name.toString()));
        il.append(DUP_X1);
        il.append(methodGen.loadCurrentNode());
        _use.translate(classGen, methodGen);
        il.append(new INVOKEVIRTUAL(key));
        il.append(methodGen.loadDOM());
        il.append(new INVOKEVIRTUAL(keyDom));
    }
    // Get the next node from the iterator and do loop again...
    final InstructionHandle skip = il.append(NOP);
    il.append(methodGen.loadIterator());
    il.append(methodGen.nextNode());
    il.append(DUP);
    il.append(methodGen.storeCurrentNode());
    il.append(new IFGT(loop));
    // Restore current node and current iterator from the stack
    il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
    nextNode.setTarget(skip);
    skipNode.setTarget(skip);
}

5. StepPattern#translateGeneralContext()

Project: openjdk
Source File: StepPattern.java
View license
private void translateGeneralContext(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    int iteratorIndex = 0;
    BranchHandle ifBlock = null;
    LocalVariableGen iter, node, node2;
    final String iteratorName = getNextFieldName();
    // Store node on the stack into a local variable
    node = methodGen.addLocalVariable("step_pattern_tmp1", Util.getJCRefType(NODE_SIG), null, null);
    node.setStart(il.append(new ISTORE(node.getIndex())));
    // Create a new local to store the iterator
    iter = methodGen.addLocalVariable("step_pattern_tmp2", Util.getJCRefType(NODE_ITERATOR_SIG), null, null);
    // Add a new private field if this is the main class
    if (!classGen.isExternal()) {
        final Field iterator = new Field(ACC_PRIVATE, cpg.addUtf8(iteratorName), cpg.addUtf8(NODE_ITERATOR_SIG), null, cpg.getConstantPool());
        classGen.addField(iterator);
        iteratorIndex = cpg.addFieldref(classGen.getClassName(), iteratorName, NODE_ITERATOR_SIG);
        il.append(classGen.loadTranslet());
        il.append(new GETFIELD(iteratorIndex));
        il.append(DUP);
        iter.setStart(il.append(new ASTORE(iter.getIndex())));
        ifBlock = il.append(new IFNONNULL(null));
        il.append(classGen.loadTranslet());
    }
    // Compile the step created at type checking time
    _step.translate(classGen, methodGen);
    InstructionHandle iterStore = il.append(new ASTORE(iter.getIndex()));
    // If in the main class update the field too
    if (!classGen.isExternal()) {
        il.append(new ALOAD(iter.getIndex()));
        il.append(new PUTFIELD(iteratorIndex));
        ifBlock.setTarget(il.append(NOP));
    } else {
        // If class is not external, start of range for iter variable was
        // set above
        iter.setStart(iterStore);
    }
    // Get the parent of the node on the stack
    il.append(methodGen.loadDOM());
    il.append(new ILOAD(node.getIndex()));
    int index = cpg.addInterfaceMethodref(DOM_INTF, GET_PARENT, GET_PARENT_SIG);
    il.append(new INVOKEINTERFACE(index, 2));
    // Initialize the iterator with the parent
    il.append(new ALOAD(iter.getIndex()));
    il.append(SWAP);
    il.append(methodGen.setStartNode());
    /*
         * Inline loop:
         *
         * int node2;
         * while ((node2 = iter.next()) != NodeIterator.END
         *                && node2 < node);
         * return node2 == node;
         */
    BranchHandle skipNext;
    InstructionHandle begin, next;
    node2 = methodGen.addLocalVariable("step_pattern_tmp3", Util.getJCRefType(NODE_SIG), null, null);
    skipNext = il.append(new GOTO(null));
    next = il.append(new ALOAD(iter.getIndex()));
    node2.setStart(next);
    begin = il.append(methodGen.nextNode());
    il.append(DUP);
    il.append(new ISTORE(node2.getIndex()));
    // NodeIterator.END
    _falseList.add(il.append(new IFLT(null)));
    il.append(new ILOAD(node2.getIndex()));
    il.append(new ILOAD(node.getIndex()));
    iter.setEnd(il.append(new IF_ICMPLT(next)));
    node2.setEnd(il.append(new ILOAD(node2.getIndex())));
    node.setEnd(il.append(new ILOAD(node.getIndex())));
    _falseList.add(il.append(new IF_ICMPNE(null)));
    skipNext.setTarget(begin);
}

6. Sort#compileExtract()

Project: openjdk
Source File: Sort.java
View license
/**
     * Compiles a method that overloads NodeSortRecord.extractValueFromDOM()
     */
private static MethodGenerator compileExtract(Vector<Sort> sortObjects, NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) {
    final InstructionList il = new InstructionList();
    // String NodeSortRecord.extractValueFromDOM(dom,node,level);
    final CompareGenerator extractMethod = new CompareGenerator(ACC_PUBLIC | ACC_FINAL, com.sun.org.apache.bcel.internal.generic.Type.STRING, new com.sun.org.apache.bcel.internal.generic.Type[] { Util.getJCRefType(DOM_INTF_SIG), com.sun.org.apache.bcel.internal.generic.Type.INT, com.sun.org.apache.bcel.internal.generic.Type.INT, Util.getJCRefType(TRANSLET_SIG), com.sun.org.apache.bcel.internal.generic.Type.INT }, new String[] { "dom", "current", "level", "translet", "last" }, "extractValueFromDOM", className, il, cpg);
    // Values needed for the switch statement
    final int levels = sortObjects.size();
    final int match[] = new int[levels];
    final InstructionHandle target[] = new InstructionHandle[levels];
    InstructionHandle tblswitch = null;
    // Compile switch statement only if the key has multiple levels
    if (levels > 1) {
        // Put the parameter to the swtich statement on the stack
        il.append(new ILOAD(extractMethod.getLocalIndex("level")));
        // Append the switch statement here later on
        tblswitch = il.append(new NOP());
    }
    // Append all the cases for the switch statment
    for (int level = 0; level < levels; level++) {
        match[level] = level;
        final Sort sort = sortObjects.elementAt(level);
        target[level] = il.append(NOP);
        sort.translateSelect(sortRecord, extractMethod);
        il.append(ARETURN);
    }
    // Compile def. target for switch statement if key has multiple levels
    if (levels > 1) {
        // Append the default target - it will _NEVER_ be reached
        InstructionHandle defaultTarget = il.append(new PUSH(cpg, EMPTYSTRING));
        il.insert(tblswitch, new TABLESWITCH(match, target, defaultTarget));
        il.append(ARETURN);
    }
    return extractMethod;
}

7. Whitespace#compilePreserveSpace()

Project: openjdk
Source File: Whitespace.java
View license
public static void compilePreserveSpace(BranchHandle preserve[], int pCount, InstructionList il) {
    final InstructionHandle target = il.append(ICONST_0);
    il.append(IRETURN);
    for (int i = 0; i < pCount; i++) {
        preserve[i].setTarget(target);
    }
}

8. AbsolutePathPattern#translate()

Project: openjdk
Source File: AbsolutePathPattern.java
View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    if (_left != null) {
        if (_left instanceof StepPattern) {
            final LocalVariableGen local = // absolute path pattern temporary
            methodGen.addLocalVariable2("apptmp", Util.getJCRefType(NODE_SIG), null);
            il.append(DUP);
            local.setStart(il.append(new ISTORE(local.getIndex())));
            _left.translate(classGen, methodGen);
            il.append(methodGen.loadDOM());
            local.setEnd(il.append(new ILOAD(local.getIndex())));
            methodGen.removeLocalVariable(local);
        } else {
            _left.translate(classGen, methodGen);
        }
    }
    final int getParent = cpg.addInterfaceMethodref(DOM_INTF, GET_PARENT, GET_PARENT_SIG);
    final int getType = cpg.addInterfaceMethodref(DOM_INTF, "getExpandedTypeID", "(I)I");
    InstructionHandle begin = il.append(methodGen.loadDOM());
    il.append(SWAP);
    il.append(new INVOKEINTERFACE(getParent, 2));
    if (_left instanceof AncestorPattern) {
        il.append(methodGen.loadDOM());
        il.append(SWAP);
    }
    il.append(new INVOKEINTERFACE(getType, 2));
    il.append(new PUSH(cpg, DTM.DOCUMENT_NODE));
    final BranchHandle skip = il.append(new IF_ICMPEQ(null));
    _falseList.add(il.append(new GOTO_W(null)));
    skip.setTarget(il.append(NOP));
    if (_left != null) {
        _left.backPatchTrueList(begin);
        /*
             * If _left is an ancestor pattern, backpatch this pattern's false
             * list to the loop that searches for more ancestors.
             */
        if (_left instanceof AncestorPattern) {
            final AncestorPattern ancestor = (AncestorPattern) _left;
            // clears list
            _falseList.backPatch(ancestor.getLoopHandle());
        }
        _falseList.append(_left._falseList);
    }
}

9. Whitespace#compileStripSpace()

Project: openjdk
Source File: Whitespace.java
View license
public static void compileStripSpace(BranchHandle strip[], int sCount, InstructionList il) {
    final InstructionHandle target = il.append(ICONST_1);
    il.append(IRETURN);
    for (int i = 0; i < sCount; i++) {
        strip[i].setTarget(target);
    }
}

10. MethodGenerator#getGeneratedMethods()

Project: openjdk
Source File: MethodGenerator.java
View license
/**
     * <p>Get all {@link Method}s generated by this {@link MethodGenerator}.
     * The {@link MethodGen#getMethod()} only returns a single
     * <code>Method</code> object.  This method takes into account the Java
     * Virtual Machine Specification limit of 64KB on the size of a method, and
     * may return more than one <code>Method</code>.</p>
     * <p>If the code associated with the <code>MethodGenerator</code> would
     * exceed the 64KB limit, this method will attempt to split the code in
     * the {@link InstructionList} associated with this
     * <code>MethodGenerator</code> into several methods.</p>
     * @param classGen the {@link ClassGenerator} of which these methods are
     *                 members
     * @return an array of all the <code>Method</code>s generated
     */
Method[] getGeneratedMethods(ClassGenerator classGen) {
    Method[] generatedMethods;
    InstructionList il = getInstructionList();
    InstructionHandle last = il.getEnd();
    il.setPositions();
    int instructionListSize = last.getPosition() + last.getInstruction().getLength();
    // [-32768,32767]
    if (instructionListSize > MAX_BRANCH_TARGET_OFFSET) {
        boolean ilChanged = widenConditionalBranchTargetOffsets();
        // of the byte code for the method
        if (ilChanged) {
            il.setPositions();
            last = il.getEnd();
            instructionListSize = last.getPosition() + last.getInstruction().getLength();
        }
    }
    if (instructionListSize > MAX_METHOD_SIZE) {
        generatedMethods = outlineChunks(classGen, instructionListSize);
    } else {
        generatedMethods = new Method[] { getThisMethod() };
    }
    return generatedMethods;
}

11. MethodGenerator#getCandidateChunks()

Project: openjdk
Source File: MethodGenerator.java
View license
/**
     * Find the outlineable chunks in this method that would be the best choices
     * to outline, based on size and position in the method.
     * @param classGen The {@link ClassGen} with which the generated methods
     *                 will be associated
     * @param totalMethodSize the size of the bytecode in the original method
     * @return a <code>java.util.ArrayList</code> containing the
     *  {@link MethodGenerator.Chunk}s that may be outlined from this method
     */
private ArrayList getCandidateChunks(ClassGenerator classGen, int totalMethodSize) {
    Iterator instructions = getInstructionList().iterator();
    ArrayList candidateChunks = new ArrayList();
    ArrayList currLevelChunks = new ArrayList();
    Stack subChunkStack = new Stack();
    boolean openChunkAtCurrLevel = false;
    boolean firstInstruction = true;
    InstructionHandle currentHandle;
    if (m_openChunks != 0) {
        String msg = (new ErrorMsg(ErrorMsg.OUTLINE_ERR_UNBALANCED_MARKERS)).toString();
        throw new InternalError(msg);
    }
    //     for outlining
    do {
        // Get the next instruction.  The loop will perform one extra
        // iteration after it reaches the end of the InstructionList, with
        // currentHandle set to null.
        currentHandle = instructions.hasNext() ? (InstructionHandle) instructions.next() : null;
        Instruction inst = (currentHandle != null) ? currentHandle.getInstruction() : null;
        // this chunk can never be outlined because it will be too big.
        if (firstInstruction) {
            openChunkAtCurrLevel = true;
            currLevelChunks.add(currentHandle);
            firstInstruction = false;
        }
        // Found a new chunk
        if (inst instanceof OutlineableChunkStart) {
            // from the outer level onto the stack
            if (openChunkAtCurrLevel) {
                subChunkStack.push(currLevelChunks);
                currLevelChunks = new ArrayList();
            }
            openChunkAtCurrLevel = true;
            currLevelChunks.add(currentHandle);
        // Close off an open chunk
        } else if (currentHandle == null || inst instanceof OutlineableChunkEnd) {
            ArrayList nestedSubChunks = null;
            // are better candidates for outlining than the current chunk.
            if (!openChunkAtCurrLevel) {
                nestedSubChunks = currLevelChunks;
                currLevelChunks = (ArrayList) subChunkStack.pop();
            }
            // Get the handle for the start of this chunk (the last entry
            // in currLevelChunks)
            InstructionHandle chunkStart = (InstructionHandle) currLevelChunks.get(currLevelChunks.size() - 1);
            int chunkEndPosition = (currentHandle != null) ? currentHandle.getPosition() : totalMethodSize;
            int chunkSize = chunkEndPosition - chunkStart.getPosition();
            //      chunks that are as large as possible
            if (chunkSize <= TARGET_METHOD_SIZE) {
                currLevelChunks.add(currentHandle);
            } else {
                if (!openChunkAtCurrLevel) {
                    int childChunkCount = nestedSubChunks.size() / 2;
                    if (childChunkCount > 0) {
                        Chunk[] childChunks = new Chunk[childChunkCount];
                        // Gather all the child chunks of the current chunk
                        for (int i = 0; i < childChunkCount; i++) {
                            InstructionHandle start = (InstructionHandle) nestedSubChunks.get(i * 2);
                            InstructionHandle end = (InstructionHandle) nestedSubChunks.get(i * 2 + 1);
                            childChunks[i] = new Chunk(start, end);
                        }
                        // Merge adjacent siblings
                        ArrayList mergedChildChunks = mergeAdjacentChunks(childChunks);
                        // to the list of candidate chunks for outlining
                        for (int i = 0; i < mergedChildChunks.size(); i++) {
                            Chunk mergedChunk = (Chunk) mergedChildChunks.get(i);
                            int mergedSize = mergedChunk.getChunkSize();
                            if (mergedSize >= MINIMUM_OUTLINEABLE_CHUNK_SIZE && mergedSize <= TARGET_METHOD_SIZE) {
                                candidateChunks.add(mergedChunk);
                            }
                        }
                    }
                }
                // Drop the chunk which was too big
                currLevelChunks.remove(currLevelChunks.size() - 1);
            }
            // currLevelChunks contains pairs of InstructionHandles.  If
            // its size is an odd number, the loop has encountered the
            // start of a chunk at this level, but not its end.
            openChunkAtCurrLevel = ((currLevelChunks.size() & 0x1) == 1);
        }
    } while (currentHandle != null);
    return candidateChunks;
}

12. TestSeq#compile()

Project: openjdk
Source File: TestSeq.java
View license
/**
     * Compile the code for this test sequence. Compile patterns
     * from highest to lowest priority. Note that since patterns
     * can be share by multiple test sequences, instruction lists
     * must be copied before backpatching.
     */
public InstructionHandle compile(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle continuation) {
    // Returned cached value if already compiled
    if (_start != null) {
        return _start;
    }
    // If not patterns, then return handle for default template
    final int count = _patterns.size();
    if (count == 0) {
        return (_start = getTemplateHandle(_default));
    }
    // Init handle to jump when all patterns failed
    InstructionHandle fail = (_default == null) ? continuation : getTemplateHandle(_default);
    // Compile all patterns in reverse order
    for (int n = count - 1; n >= 0; n--) {
        final LocationPathPattern pattern = getPattern(n);
        final Template template = pattern.getTemplate();
        final InstructionList il = new InstructionList();
        // Patterns expect current node on top of stack
        il.append(methodGen.loadCurrentNode());
        // Apply the test-code compiled for the pattern
        InstructionList ilist = methodGen.getInstructionList(pattern);
        if (ilist == null) {
            ilist = pattern.compile(classGen, methodGen);
            methodGen.addInstructionList(pattern, ilist);
        }
        // Make a copy of the instruction list for backpatching
        InstructionList copyOfilist = ilist.copy();
        FlowList trueList = pattern.getTrueList();
        if (trueList != null) {
            trueList = trueList.copyAndRedirect(ilist, copyOfilist);
        }
        FlowList falseList = pattern.getFalseList();
        if (falseList != null) {
            falseList = falseList.copyAndRedirect(ilist, copyOfilist);
        }
        il.append(copyOfilist);
        // On success branch to the template code
        final InstructionHandle gtmpl = getTemplateHandle(template);
        final InstructionHandle success = il.append(new GOTO_W(gtmpl));
        if (trueList != null) {
            trueList.backPatch(success);
        }
        if (falseList != null) {
            falseList.backPatch(fail);
        }
        // Next pattern's 'fail' target is this pattern's first instruction
        fail = il.getStart();
        // Append existing instruction list to the end of this one
        if (_instructionList != null) {
            il.append(_instructionList);
        }
        // Set current instruction list to be this one
        _instructionList = il;
    }
    return (_start = fail);
}

13. StepPattern#translateSimpleContext()

Project: openjdk
Source File: StepPattern.java
View license
private void translateSimpleContext(ClassGenerator classGen, MethodGenerator methodGen) {
    int index;
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    // Store matching node into a local variable
    LocalVariableGen match;
    match = methodGen.addLocalVariable("step_pattern_tmp1", Util.getJCRefType(NODE_SIG), null, null);
    match.setStart(il.append(new ISTORE(match.getIndex())));
    // If pattern not reduced then check kernel
    if (!_isEpsilon) {
        il.append(new ILOAD(match.getIndex()));
        translateKernel(classGen, methodGen);
    }
    // Push current iterator and current node on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadIterator());
    // Create a new matching iterator using the matching node
    index = cpg.addMethodref(MATCHING_ITERATOR, "<init>", "(I" + NODE_ITERATOR_SIG + ")V");
    // Backwards branches are prohibited if an uninitialized object is
    // on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
    // We don't know whether this code might contain backwards branches,
    // so we mustn't create the new object until after we've created
    // the suspect arguments to its constructor.  Instead we calculate
    // the values of the arguments to the constructor first, store them
    // in temporary variables, create the object and reload the
    // arguments from the temporaries to avoid the problem.
    _step.translate(classGen, methodGen);
    LocalVariableGen stepIteratorTemp = methodGen.addLocalVariable("step_pattern_tmp2", Util.getJCRefType(NODE_ITERATOR_SIG), null, null);
    stepIteratorTemp.setStart(il.append(new ASTORE(stepIteratorTemp.getIndex())));
    il.append(new NEW(cpg.addClass(MATCHING_ITERATOR)));
    il.append(DUP);
    il.append(new ILOAD(match.getIndex()));
    stepIteratorTemp.setEnd(il.append(new ALOAD(stepIteratorTemp.getIndex())));
    il.append(new INVOKESPECIAL(index));
    // Get the parent of the matching node
    il.append(methodGen.loadDOM());
    il.append(new ILOAD(match.getIndex()));
    index = cpg.addInterfaceMethodref(DOM_INTF, GET_PARENT, GET_PARENT_SIG);
    il.append(new INVOKEINTERFACE(index, 2));
    // Start the iterator with the parent
    il.append(methodGen.setStartNode());
    // Overwrite current iterator and current node
    il.append(methodGen.storeIterator());
    match.setEnd(il.append(new ILOAD(match.getIndex())));
    il.append(methodGen.storeCurrentNode());
    // Translate the expression of the predicate
    Predicate pred = (Predicate) _predicates.elementAt(0);
    Expression exp = pred.getExpr();
    exp.translateDesynthesized(classGen, methodGen);
    // Backpatch true list and restore current iterator/node
    InstructionHandle restore = il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
    exp.backPatchTrueList(restore);
    BranchHandle skipFalse = il.append(new GOTO(null));
    // Backpatch false list and restore current iterator/node
    restore = il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
    exp.backPatchFalseList(restore);
    _falseList.add(il.append(new GOTO(null)));
    // True list falls through
    skipFalse.setTarget(il.append(NOP));
}

14. StepPattern#translateNoContext()

Project: openjdk
Source File: StepPattern.java
View license
private void translateNoContext(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    // Push current node on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(SWAP);
    // Overwrite current node with matching node
    il.append(methodGen.storeCurrentNode());
    // If pattern not reduced then check kernel
    if (!_isEpsilon) {
        il.append(methodGen.loadCurrentNode());
        translateKernel(classGen, methodGen);
    }
    // Compile the expressions within the predicates
    final int n = _predicates.size();
    for (int i = 0; i < n; i++) {
        Predicate pred = (Predicate) _predicates.elementAt(i);
        Expression exp = pred.getExpr();
        exp.translateDesynthesized(classGen, methodGen);
        _trueList.append(exp._trueList);
        _falseList.append(exp._falseList);
    }
    // Backpatch true list and restore current iterator/node
    InstructionHandle restore;
    restore = il.append(methodGen.storeCurrentNode());
    backPatchTrueList(restore);
    BranchHandle skipFalse = il.append(new GOTO(null));
    // Backpatch false list and restore current iterator/node
    restore = il.append(methodGen.storeCurrentNode());
    backPatchFalseList(restore);
    _falseList.add(il.append(new GOTO(null)));
    // True list falls through
    skipFalse.setTarget(il.append(NOP));
}

15. ProcessingInstructionPattern#translate()

View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    // context node is on the stack
    int gname = cpg.addInterfaceMethodref(DOM_INTF, "getNodeName", "(I)Ljava/lang/String;");
    int cmp = cpg.addMethodref(STRING_CLASS, "equals", "(Ljava/lang/Object;)Z");
    // Push current node on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(SWAP);
    // Overwrite current node with matching node
    il.append(methodGen.storeCurrentNode());
    // If pattern not reduced then check kernel
    if (!_typeChecked) {
        il.append(methodGen.loadCurrentNode());
        final int getType = cpg.addInterfaceMethodref(DOM_INTF, "getExpandedTypeID", "(I)I");
        il.append(methodGen.loadDOM());
        il.append(methodGen.loadCurrentNode());
        il.append(new INVOKEINTERFACE(getType, 2));
        il.append(new PUSH(cpg, DTM.PROCESSING_INSTRUCTION_NODE));
        _falseList.add(il.append(new IF_ICMPEQ(null)));
    }
    // Load the requested processing instruction name
    il.append(new PUSH(cpg, _name));
    // Load the current processing instruction's name
    il.append(methodGen.loadDOM());
    il.append(methodGen.loadCurrentNode());
    il.append(new INVOKEINTERFACE(gname, 2));
    // Compare the two strings
    il.append(new INVOKEVIRTUAL(cmp));
    _falseList.add(il.append(new IFEQ(null)));
    // Compile the expressions within the predicates
    if (hasPredicates()) {
        final int n = _predicates.size();
        for (int i = 0; i < n; i++) {
            Predicate pred = (Predicate) _predicates.elementAt(i);
            Expression exp = pred.getExpr();
            exp.translateDesynthesized(classGen, methodGen);
            _trueList.append(exp._trueList);
            _falseList.append(exp._falseList);
        }
    }
    // Backpatch true list and restore current iterator/node
    InstructionHandle restore;
    restore = il.append(methodGen.storeCurrentNode());
    backPatchTrueList(restore);
    BranchHandle skipFalse = il.append(new GOTO(null));
    // Backpatch false list and restore current iterator/node
    restore = il.append(methodGen.storeCurrentNode());
    backPatchFalseList(restore);
    _falseList.add(il.append(new GOTO(null)));
    // True list falls through
    skipFalse.setTarget(il.append(NOP));
}

16. Mode#peepHoleOptimization()

Project: openjdk
Source File: Mode.java
View license
/**
      * Peephole optimization.
      */
private void peepHoleOptimization(MethodGenerator methodGen) {
    InstructionList il = methodGen.getInstructionList();
    InstructionFinder find = new InstructionFinder(il);
    InstructionHandle ih;
    String pattern;
    // LoadInstruction, POP => (removed)
    // pattern = "LoadInstruction POP";
    // changed to lower case - changing to all lower case although only the instruction with capital I
    // is creating a problem in the Turkish locale
    pattern = "loadinstruction pop";
    for (Iterator iter = find.search(pattern); iter.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) iter.next();
        try {
            if (!match[0].hasTargeters() && !match[1].hasTargeters()) {
                il.delete(match[0], match[1]);
            }
        } catch (TargetLostException e) {
        }
    }
    // ILOAD_N, ILOAD_N, SWAP, ISTORE_N => ILOAD_N
    // pattern = "ILOAD ILOAD SWAP ISTORE";
    // changed to lower case - changing to all lower case although only the instruction with capital I
    // is creating a problem in the Turkish locale
    pattern = "iload iload swap istore";
    for (Iterator iter = find.search(pattern); iter.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) iter.next();
        try {
            com.sun.org.apache.bcel.internal.generic.ILOAD iload1 = (com.sun.org.apache.bcel.internal.generic.ILOAD) match[0].getInstruction();
            com.sun.org.apache.bcel.internal.generic.ILOAD iload2 = (com.sun.org.apache.bcel.internal.generic.ILOAD) match[1].getInstruction();
            com.sun.org.apache.bcel.internal.generic.ISTORE istore = (com.sun.org.apache.bcel.internal.generic.ISTORE) match[3].getInstruction();
            if (!match[1].hasTargeters() && !match[2].hasTargeters() && !match[3].hasTargeters() && iload1.getIndex() == iload2.getIndex() && iload2.getIndex() == istore.getIndex()) {
                il.delete(match[1], match[3]);
            }
        } catch (TargetLostException e) {
        }
    }
    // LoadInstruction_N, LoadInstruction_M, SWAP => LoadInstruction_M, LoadInstruction_N
    // pattern = "LoadInstruction LoadInstruction SWAP";
    // changed to lower case - changing to all lower case although only the instruction with capital I
    // is creating a problem in the Turkish locale
    pattern = "loadinstruction loadinstruction swap";
    for (Iterator iter = find.search(pattern); iter.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) iter.next();
        try {
            if (!match[0].hasTargeters() && !match[1].hasTargeters() && !match[2].hasTargeters()) {
                Instruction load_m = match[1].getInstruction();
                il.insert(match[0], load_m);
                il.delete(match[1], match[2]);
            }
        } catch (TargetLostException e) {
        }
    }
    // ALOAD_N ALOAD_N => ALOAD_N DUP
    // pattern = "ALOAD ALOAD";
    // changed to lower case - changing to all lower case although only the instruction with capital I
    // is creating a problem in the Turkish locale
    pattern = "aload aload";
    for (Iterator iter = find.search(pattern); iter.hasNext(); ) {
        InstructionHandle[] match = (InstructionHandle[]) iter.next();
        try {
            if (!match[1].hasTargeters()) {
                com.sun.org.apache.bcel.internal.generic.ALOAD aload1 = (com.sun.org.apache.bcel.internal.generic.ALOAD) match[0].getInstruction();
                com.sun.org.apache.bcel.internal.generic.ALOAD aload2 = (com.sun.org.apache.bcel.internal.generic.ALOAD) match[1].getInstruction();
                if (aload1.getIndex() == aload2.getIndex()) {
                    il.insert(match[1], new DUP());
                    il.delete(match[1]);
                }
            }
        } catch (TargetLostException e) {
        }
    }
}

17. Mode#compileNamespaces()

Project: openjdk
Source File: Mode.java
View license
private InstructionList compileNamespaces(ClassGenerator classGen, MethodGenerator methodGen, boolean[] isNamespace, boolean[] isAttribute, boolean attrFlag, InstructionHandle defaultTarget) {
    final XSLTC xsltc = classGen.getParser().getXSLTC();
    final ConstantPoolGen cpg = classGen.getConstantPool();
    // Append switch() statement - namespace test dispatch loop
    final Vector namespaces = xsltc.getNamespaceIndex();
    final Vector names = xsltc.getNamesIndex();
    final int namespaceCount = namespaces.size() + 1;
    final int namesCount = names.size();
    final InstructionList il = new InstructionList();
    final int[] types = new int[namespaceCount];
    final InstructionHandle[] targets = new InstructionHandle[types.length];
    if (namespaceCount > 0) {
        boolean compiled = false;
        // Initialize targets for namespace() switch statement
        for (int i = 0; i < namespaceCount; i++) {
            targets[i] = defaultTarget;
            types[i] = i;
        }
        // Add test sequences for known namespace types
        for (int i = DTM.NTYPES; i < (DTM.NTYPES + namesCount); i++) {
            if ((isNamespace[i]) && (isAttribute[i] == attrFlag)) {
                String name = (String) names.elementAt(i - DTM.NTYPES);
                String namespace = name.substring(0, name.lastIndexOf(':'));
                final int type = xsltc.registerNamespace(namespace);
                if ((i < _testSeq.length) && (_testSeq[i] != null)) {
                    targets[type] = (_testSeq[i]).compile(classGen, methodGen, defaultTarget);
                    compiled = true;
                }
            }
        }
        // Return "null" if no test sequences were compiled
        if (!compiled)
            return (null);
        // Append first code in applyTemplates() - get type of current node
        final int getNS = cpg.addInterfaceMethodref(DOM_INTF, "getNamespaceType", "(I)I");
        il.append(methodGen.loadDOM());
        il.append(new ILOAD(_currentIndex));
        il.append(new INVOKEINTERFACE(getNS, 2));
        il.append(new SWITCH(types, targets, defaultTarget));
        return (il);
    } else {
        return (null);
    }
}

18. Key#traverseNodeSet()

Project: openjdk
Source File: Key.java
View license
/**
     * This method is called if the "use" attribute of the key contains a
     * node set. In this case we must traverse all nodes in the set and
     * create one entry in this key's index for each node in the set.
     */
public void traverseNodeSet(ClassGenerator classGen, MethodGenerator methodGen, int buildKeyIndex) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    // DOM.getStringValueX(nodeIndex) => String
    final int getNodeValue = cpg.addInterfaceMethodref(DOM_INTF, GET_NODE_VALUE, "(I)" + STRING_SIG);
    final int getNodeIdent = cpg.addInterfaceMethodref(DOM_INTF, "getNodeIdent", "(I)" + NODE_SIG);
    // AbstractTranslet.SetKeyIndexDom(name, Dom) => void
    final int keyDom = cpg.addMethodref(TRANSLET_CLASS, "setKeyIndexDom", "(" + STRING_SIG + DOM_INTF_SIG + ")V");
    // This variable holds the id of the node we found with the "match"
    // attribute of xsl:key. This is the id we store, with the value we
    // get from the nodes we find here, in the index for this key.
    final LocalVariableGen parentNode = methodGen.addLocalVariable("parentNode", Util.getJCRefType("I"), null, null);
    // Get the 'parameter' from the stack and store it in a local var.
    parentNode.setStart(il.append(new ISTORE(parentNode.getIndex())));
    // Save current node and current iterator on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadIterator());
    // Overwrite current iterator with one that gives us only what we want
    _use.translate(classGen, methodGen);
    _use.startIterator(classGen, methodGen);
    il.append(methodGen.storeIterator());
    final BranchHandle nextNode = il.append(new GOTO(null));
    final InstructionHandle loop = il.append(NOP);
    // Prepare to call buildKeyIndex(String name, int node, String value);
    il.append(classGen.loadTranslet());
    il.append(new PUSH(cpg, _name.toString()));
    parentNode.setEnd(il.append(new ILOAD(parentNode.getIndex())));
    // Now get the node value and push it on the parameter stack
    il.append(methodGen.loadDOM());
    il.append(methodGen.loadCurrentNode());
    il.append(new INVOKEINTERFACE(getNodeValue, 2));
    // Finally do the call to add an entry in the index for this key.
    il.append(new INVOKEVIRTUAL(buildKeyIndex));
    il.append(classGen.loadTranslet());
    il.append(new PUSH(cpg, getName()));
    il.append(methodGen.loadDOM());
    il.append(new INVOKEVIRTUAL(keyDom));
    nextNode.setTarget(il.append(methodGen.loadIterator()));
    il.append(methodGen.nextNode());
    il.append(DUP);
    il.append(methodGen.storeCurrentNode());
    // Go on to next matching node....
    il.append(new IFGE(loop));
    // Restore current node and current iterator from the stack
    il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
}

19. If#translate()

Project: openjdk
Source File: If.java
View license
/**
     * Translate the "test" expression and contents of this element.
     * The contents will be ignored if we know the test will always fail.
     */
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final InstructionList il = methodGen.getInstructionList();
    _test.translateDesynthesized(classGen, methodGen);
    // remember end of condition
    final InstructionHandle truec = il.getEnd();
    if (!_ignore) {
        translateContents(classGen, methodGen);
    }
    _test.backPatchFalseList(il.append(NOP));
    _test.backPatchTrueList(truec.getNext());
}

20. ForEach#translate()

Project: openjdk
Source File: ForEach.java
View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    // Save current node and current iterator on the stack
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadIterator());
    // Collect sort objects associated with this instruction
    final Vector sortObjects = new Vector();
    Iterator<SyntaxTreeNode> children = elements();
    while (children.hasNext()) {
        final Object child = children.next();
        if (child instanceof Sort) {
            sortObjects.addElement(child);
        }
    }
    if ((_type != null) && (_type instanceof ResultTreeType)) {
        // Store existing DOM on stack - must be restored when loop is done
        il.append(methodGen.loadDOM());
        // <xsl:sort> cannot be applied to a result tree - issue warning
        if (sortObjects.size() > 0) {
            ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR, this);
            getParser().reportError(WARNING, msg);
        }
        // Put the result tree on the stack (DOM)
        _select.translate(classGen, methodGen);
        // Get an iterator for the whole DOM - excluding the root node
        _type.translateTo(classGen, methodGen, Type.NodeSet);
        // Store the result tree as the default DOM
        il.append(SWAP);
        il.append(methodGen.storeDOM());
    } else {
        // Compile node iterator
        if (sortObjects.size() > 0) {
            Sort.translateSortIterator(classGen, methodGen, _select, sortObjects);
        } else {
            _select.translate(classGen, methodGen);
        }
        if (_type instanceof ReferenceType == false) {
            il.append(methodGen.loadContextNode());
            il.append(methodGen.setStartNode());
        }
    }
    // Overwrite current iterator
    il.append(methodGen.storeIterator());
    // Give local variables (if any) default values before starting loop
    initializeVariables(classGen, methodGen);
    final BranchHandle nextNode = il.append(new GOTO(null));
    final InstructionHandle loop = il.append(NOP);
    translateContents(classGen, methodGen);
    nextNode.setTarget(il.append(methodGen.loadIterator()));
    il.append(methodGen.nextNode());
    il.append(DUP);
    il.append(methodGen.storeCurrentNode());
    il.append(new IFGT(loop));
    // Restore current DOM (if result tree was used instead for this loop)
    if ((_type != null) && (_type instanceof ResultTreeType)) {
        il.append(methodGen.storeDOM());
    }
    // Restore current node and current iterator from the stack
    il.append(methodGen.storeIterator());
    il.append(methodGen.storeCurrentNode());
}

21. Copy#translate()

Project: openjdk
Source File: Copy.java
View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    final LocalVariableGen name = methodGen.addLocalVariable2("name", Util.getJCRefType(STRING_SIG), null);
    final LocalVariableGen length = methodGen.addLocalVariable2("length", Util.getJCRefType("I"), null);
    // Get the name of the node to copy and save for later
    il.append(methodGen.loadDOM());
    il.append(methodGen.loadCurrentNode());
    il.append(methodGen.loadHandler());
    final int cpy = cpg.addInterfaceMethodref(DOM_INTF, "shallowCopy", "(" + NODE_SIG + TRANSLET_OUTPUT_SIG + ")" + STRING_SIG);
    il.append(new INVOKEINTERFACE(cpy, 3));
    il.append(DUP);
    name.setStart(il.append(new ASTORE(name.getIndex())));
    final BranchHandle ifBlock1 = il.append(new IFNULL(null));
    // Get the length of the node name and save for later
    il.append(new ALOAD(name.getIndex()));
    final int lengthMethod = cpg.addMethodref(STRING_CLASS, "length", "()I");
    il.append(new INVOKEVIRTUAL(lengthMethod));
    il.append(DUP);
    length.setStart(il.append(new ISTORE(length.getIndex())));
    // Ignore attribute sets if current node is ROOT. DOM.shallowCopy()
    // returns "" for ROOT, so skip attribute sets if length == 0
    final BranchHandle ifBlock4 = il.append(new IFEQ(null));
    // Copy in attribute sets if specified
    if (_useSets != null) {
        // If the parent of this element will result in an element being
        // output then we know that it is safe to copy out the attributes
        final SyntaxTreeNode parent = getParent();
        if ((parent instanceof LiteralElement) || (parent instanceof LiteralElement)) {
            _useSets.translate(classGen, methodGen);
        } else // If not we have to check to see if the copy will result in an
        // element being output.
        {
            // check if element; if not skip to translate body
            il.append(new ILOAD(length.getIndex()));
            final BranchHandle ifBlock2 = il.append(new IFEQ(null));
            // length != 0 -> element -> do attribute sets
            _useSets.translate(classGen, methodGen);
            // not an element; root
            ifBlock2.setTarget(il.append(NOP));
        }
    }
    // Instantiate body of xsl:copy
    ifBlock4.setTarget(il.append(NOP));
    translateContents(classGen, methodGen);
    // Call the output handler's endElement() if we copied an element
    // (The DOM.shallowCopy() method calls startElement().)
    length.setEnd(il.append(new ILOAD(length.getIndex())));
    final BranchHandle ifBlock3 = il.append(new IFEQ(null));
    il.append(methodGen.loadHandler());
    name.setEnd(il.append(new ALOAD(name.getIndex())));
    il.append(methodGen.endElement());
    final InstructionHandle end = il.append(NOP);
    ifBlock1.setTarget(end);
    ifBlock3.setTarget(end);
    methodGen.removeLocalVariable(name);
    methodGen.removeLocalVariable(length);
}

22. Choose#translate()

Project: openjdk
Source File: Choose.java
View license
/**
     * Translate this Choose element. Generate a test-chain for the various
     * <xsl:when> elements and default to the <xsl:otherwise> if present.
     */
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    final Vector whenElements = new Vector();
    Otherwise otherwise = null;
    Iterator<SyntaxTreeNode> elements = elements();
    // These two are for reporting errors only
    ErrorMsg error = null;
    final int line = getLineNumber();
    // Traverse all child nodes - must be either When or Otherwise
    while (elements.hasNext()) {
        SyntaxTreeNode element = elements.next();
        // Add a When child element
        if (element instanceof When) {
            whenElements.addElement(element);
        } else // Add an Otherwise child element
        if (element instanceof Otherwise) {
            if (otherwise == null) {
                otherwise = (Otherwise) element;
            } else {
                error = new ErrorMsg(ErrorMsg.MULTIPLE_OTHERWISE_ERR, this);
                getParser().reportError(Constants.ERROR, error);
            }
        } else if (element instanceof Text) {
            ((Text) element).ignore();
        } else // It is an error if we find some other element here
        {
            error = new ErrorMsg(ErrorMsg.WHEN_ELEMENT_ERR, this);
            getParser().reportError(Constants.ERROR, error);
        }
    }
    // Make sure that there is at least one <xsl:when> element
    if (whenElements.size() == 0) {
        error = new ErrorMsg(ErrorMsg.MISSING_WHEN_ERR, this);
        getParser().reportError(Constants.ERROR, error);
        return;
    }
    InstructionList il = methodGen.getInstructionList();
    // next element will hold a handle to the beginning of next
    // When/Otherwise if test on current When fails
    BranchHandle nextElement = null;
    Vector exitHandles = new Vector();
    InstructionHandle exit = null;
    Enumeration whens = whenElements.elements();
    while (whens.hasMoreElements()) {
        final When when = (When) whens.nextElement();
        final Expression test = when.getTest();
        InstructionHandle truec = il.getEnd();
        if (nextElement != null)
            nextElement.setTarget(il.append(NOP));
        test.translateDesynthesized(classGen, methodGen);
        if (test instanceof FunctionCall) {
            FunctionCall call = (FunctionCall) test;
            try {
                Type type = call.typeCheck(getParser().getSymbolTable());
                if (type != Type.Boolean) {
                    test._falseList.add(il.append(new IFEQ(null)));
                }
            } catch (TypeCheckError e) {
            }
        }
        // remember end of condition
        truec = il.getEnd();
        // for the support of a non-available element
        if (!when.ignore())
            when.translateContents(classGen, methodGen);
        // goto exit after executing the body of when
        exitHandles.addElement(il.append(new GOTO(null)));
        if (whens.hasMoreElements() || otherwise != null) {
            nextElement = il.append(new GOTO(null));
            test.backPatchFalseList(nextElement);
        } else
            test.backPatchFalseList(exit = il.append(NOP));
        test.backPatchTrueList(truec.getNext());
    }
    // Translate any <xsl:otherwise> element
    if (otherwise != null) {
        nextElement.setTarget(il.append(NOP));
        otherwise.translateContents(classGen, methodGen);
        exit = il.append(NOP);
    }
    // now that end is known set targets of exit gotos
    Enumeration exitGotos = exitHandles.elements();
    while (exitGotos.hasMoreElements()) {
        BranchHandle gotoExit = (BranchHandle) exitGotos.nextElement();
        gotoExit.setTarget(exit);
    }
}

23. AncestorPattern#translate()

Project: openjdk
Source File: AncestorPattern.java
View license
public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
    InstructionHandle parent;
    final ConstantPoolGen cpg = classGen.getConstantPool();
    final InstructionList il = methodGen.getInstructionList();
    /*
         * The scope of this local var must be the entire method since
         * a another pattern may decide to jump back into the loop
         */
    final LocalVariableGen local = methodGen.addLocalVariable2("app", Util.getJCRefType(NODE_SIG), il.getEnd());
    final com.sun.org.apache.bcel.internal.generic.Instruction loadLocal = new ILOAD(local.getIndex());
    final com.sun.org.apache.bcel.internal.generic.Instruction storeLocal = new ISTORE(local.getIndex());
    if (_right instanceof StepPattern) {
        il.append(DUP);
        il.append(storeLocal);
        _right.translate(classGen, methodGen);
        il.append(methodGen.loadDOM());
        il.append(loadLocal);
    } else {
        _right.translate(classGen, methodGen);
        if (_right instanceof AncestorPattern) {
            il.append(methodGen.loadDOM());
            il.append(SWAP);
        }
    }
    if (_left != null) {
        final int getParent = cpg.addInterfaceMethodref(DOM_INTF, GET_PARENT, GET_PARENT_SIG);
        parent = il.append(new INVOKEINTERFACE(getParent, 2));
        il.append(DUP);
        il.append(storeLocal);
        _falseList.add(il.append(new IFLT(null)));
        il.append(loadLocal);
        _left.translate(classGen, methodGen);
        final SyntaxTreeNode p = getParent();
        if (p == null || p instanceof Instruction || p instanceof TopLevelElement) {
        // do nothing
        } else {
            il.append(loadLocal);
        }
        final BranchHandle exit = il.append(new GOTO(null));
        _loop = il.append(methodGen.loadDOM());
        il.append(loadLocal);
        local.setEnd(_loop);
        il.append(new GOTO(parent));
        exit.setTarget(il.append(NOP));
        _left.backPatchFalseList(_loop);
        _trueList.append(_left._trueList);
    } else {
        il.append(POP2);
    }
    /*
         * If _right is an ancestor pattern, backpatch this pattern's false
         * list to the loop that searches for more ancestors.
         */
    if (_right instanceof AncestorPattern) {
        final AncestorPattern ancestor = (AncestorPattern) _right;
        // clears list
        _falseList.backPatch(ancestor.getLoopHandle());
    }
    _trueList.append(_right._trueList);
    _falseList.append(_right._falseList);
}