You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/04/06 21:11:38 UTC

svn commit: r1089584 [10/21] - in /tapestry/tapestry5/trunk/plastic: ./ src/external/ src/external/java/ src/external/java/org/ src/external/java/org/objectweb/ src/external/java/org/objectweb/asm/ src/external/java/org/objectweb/asm/attrs/ src/externa...

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/JSRInlinerAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/JSRInlinerAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/JSRInlinerAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/JSRInlinerAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,728 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.commons;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.InsnList;
+import org.objectweb.asm.tree.InsnNode;
+import org.objectweb.asm.tree.JumpInsnNode;
+import org.objectweb.asm.tree.LabelNode;
+import org.objectweb.asm.tree.LookupSwitchInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TableSwitchInsnNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+import org.objectweb.asm.tree.LocalVariableNode;
+
+/**
+ * A {@link org.objectweb.asm.MethodAdapter} that removes JSR instructions and
+ * inlines the referenced subroutines.
+ * 
+ * <b>Explanation of how it works</b> TODO
+ * 
+ * @author Niko Matsakis
+ */
+public class JSRInlinerAdapter extends MethodNode implements Opcodes {
+
+    private static final boolean LOGGING = false;
+
+    /**
+     * The visitor to which we will emit a translation of this method without
+     * internal subroutines.
+     */
+    private final MethodVisitor mv;
+
+    /**
+     * For each label that is jumped to by a JSR, we create a Subroutine
+     * instance. Map<LabelNode,Subroutine> is the generic type.
+     */
+    private final Map subroutineHeads = new HashMap();
+
+    /**
+     * This subroutine instance denotes the line of execution that is not
+     * contained within any subroutine; i.e., the "subroutine" that is executing
+     * when a method first begins.
+     */
+    private final Subroutine mainSubroutine = new Subroutine();
+
+    /**
+     * This BitSet contains the index of every instruction that belongs to more
+     * than one subroutine. This should not happen often.
+     */
+    final BitSet dualCitizens = new BitSet();
+
+    /**
+     * Creates a new JSRInliner.
+     * 
+     * @param mv the <code>MethodVisitor</code> to send the resulting inlined
+     *        method code to (use <code>null</code> for none).
+     * @param access the method's access flags (see {@link Opcodes}). This
+     *        parameter also indicates if the method is synthetic and/or
+     *        deprecated.
+     * @param name the method's name.
+     * @param desc the method's descriptor (see {@link Type}).
+     * @param signature the method's signature. May be <tt>null</tt>.
+     * @param exceptions the internal names of the method's exception classes
+     *        (see {@link Type#getInternalName() getInternalName}). May be
+     *        <tt>null</tt>.
+     */
+    public JSRInlinerAdapter(
+        final MethodVisitor mv,
+        final int access,
+        final String name,
+        final String desc,
+        final String signature,
+        final String[] exceptions)
+    {
+        super(access, name, desc, signature, exceptions);
+        this.mv = mv;
+    }
+
+    /**
+     * Detects a JSR instruction and sets a flag to indicate we will need to do
+     * inlining.
+     */
+    public void visitJumpInsn(final int opcode, final Label lbl) {
+        super.visitJumpInsn(opcode, lbl);
+        LabelNode ln = ((JumpInsnNode) instructions.getLast()).label;
+        if (opcode == JSR && !subroutineHeads.containsKey(ln)) {
+            subroutineHeads.put(ln, new Subroutine());
+        }
+    }
+
+    /**
+     * If any JSRs were seen, triggers the inlining process. Otherwise, forwards
+     * the byte codes untouched.
+     */
+    public void visitEnd() {
+        if (!subroutineHeads.isEmpty()) {
+            markSubroutines();
+            if (LOGGING) {
+                log(mainSubroutine.toString());
+                Iterator it = subroutineHeads.values().iterator();
+                while (it.hasNext()) {
+                    Subroutine sub = (Subroutine) it.next();
+                    log(sub.toString());
+                }
+            }
+            emitCode();
+        }
+
+        // Forward the translate opcodes on if appropriate:
+        if (mv != null) {
+            accept(mv);
+        }
+    }
+
+    /**
+     * Walks the method and determines which internal subroutine(s), if any,
+     * each instruction is a method of.
+     */
+    private void markSubroutines() {
+        BitSet anyvisited = new BitSet();
+
+        // First walk the main subroutine and find all those instructions which
+        // can be reached without invoking any JSR at all
+        markSubroutineWalk(mainSubroutine, 0, anyvisited);
+
+        // Go through the head of each subroutine and find any nodes reachable
+        // to that subroutine without following any JSR links.
+        for (Iterator it = subroutineHeads.entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            LabelNode lab = (LabelNode) entry.getKey();
+            Subroutine sub = (Subroutine) entry.getValue();
+            int index = instructions.indexOf(lab);
+            markSubroutineWalk(sub, index, anyvisited);
+        }
+    }
+
+    /**
+     * Performs a depth first search walking the normal byte code path starting
+     * at <code>index</code>, and adding each instruction encountered into
+     * the subroutine <code>sub</code>. After this walk is complete, iterates
+     * over the exception handlers to ensure that we also include those byte
+     * codes which are reachable through an exception that may be thrown during
+     * the execution of the subroutine. Invoked from
+     * <code>markSubroutines()</code>.
+     * 
+     * @param sub the subroutine whose instructions must be computed.
+     * @param index an instruction of this subroutine.
+     * @param anyvisited indexes of the already visited instructions, i.e.
+     *        marked as part of this subroutine or any previously computed
+     *        subroutine.
+     */
+    private void markSubroutineWalk(
+        final Subroutine sub,
+        final int index,
+        final BitSet anyvisited)
+    {
+        if (LOGGING) {
+            log("markSubroutineWalk: sub=" + sub + " index=" + index);
+        }
+
+        // First find those instructions reachable via normal execution
+        markSubroutineWalkDFS(sub, index, anyvisited);
+
+        // Now, make sure we also include any applicable exception handlers
+        boolean loop = true;
+        while (loop) {
+            loop = false;
+            for (Iterator it = tryCatchBlocks.iterator(); it.hasNext();) {
+                TryCatchBlockNode trycatch = (TryCatchBlockNode) it.next();
+
+                if (LOGGING) {
+                    // TODO use of default toString().
+                    log("Scanning try/catch " + trycatch);
+                }
+
+                // If the handler has already been processed, skip it.
+                int handlerindex = instructions.indexOf(trycatch.handler);
+                if (sub.instructions.get(handlerindex)) {
+                    continue;
+                }
+
+                int startindex = instructions.indexOf(trycatch.start);
+                int endindex = instructions.indexOf(trycatch.end);
+                int nextbit = sub.instructions.nextSetBit(startindex);
+                if (nextbit != -1 && nextbit < endindex) {
+                    if (LOGGING) {
+                        log("Adding exception handler: " + startindex + '-'
+                                + endindex + " due to " + nextbit + " handler "
+                                + handlerindex);
+                    }
+                    markSubroutineWalkDFS(sub, handlerindex, anyvisited);
+                    loop = true;
+                }
+            }
+        }
+    }
+
+    /**
+     * Performs a simple DFS of the instructions, assigning each to the
+     * subroutine <code>sub</code>. Starts from <code>index</code>.
+     * Invoked only by <code>markSubroutineWalk()</code>.
+     * 
+     * @param sub the subroutine whose instructions must be computed.
+     * @param index an instruction of this subroutine.
+     * @param anyvisited indexes of the already visited instructions, i.e.
+     *        marked as part of this subroutine or any previously computed
+     *        subroutine.
+     */
+    private void markSubroutineWalkDFS(
+        final Subroutine sub,
+        int index,
+        final BitSet anyvisited)
+    {
+        while (true) {
+            AbstractInsnNode node = instructions.get(index);
+
+            // don't visit a node twice
+            if (sub.instructions.get(index)) {
+                return;
+            }
+            sub.instructions.set(index);
+
+            // check for those nodes already visited by another subroutine
+            if (anyvisited.get(index)) {
+                dualCitizens.set(index);
+                if (LOGGING) {
+                    log("Instruction #" + index + " is dual citizen.");
+                }
+            }
+            anyvisited.set(index);
+
+            if (node.getType() == AbstractInsnNode.JUMP_INSN
+                    && node.getOpcode() != JSR)
+            {
+                // we do not follow recursively called subroutines here; but any
+                // other sort of branch we do follow
+                JumpInsnNode jnode = (JumpInsnNode) node;
+                int destidx = instructions.indexOf(jnode.label);
+                markSubroutineWalkDFS(sub, destidx, anyvisited);
+            }
+            if (node.getType() == AbstractInsnNode.TABLESWITCH_INSN) {
+                TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+                int destidx = instructions.indexOf(tsnode.dflt);
+                markSubroutineWalkDFS(sub, destidx, anyvisited);
+                for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = (LabelNode) tsnode.labels.get(i);
+                    destidx = instructions.indexOf(l);
+                    markSubroutineWalkDFS(sub, destidx, anyvisited);
+                }
+            }
+            if (node.getType() == AbstractInsnNode.LOOKUPSWITCH_INSN) {
+                LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+                int destidx = instructions.indexOf(lsnode.dflt);
+                markSubroutineWalkDFS(sub, destidx, anyvisited);
+                for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+                    LabelNode l = (LabelNode) lsnode.labels.get(i);
+                    destidx = instructions.indexOf(l);
+                    markSubroutineWalkDFS(sub, destidx, anyvisited);
+                }
+            }
+
+            // check to see if this opcode falls through to the next instruction
+            // or not; if not, return.
+            switch (instructions.get(index).getOpcode()) {
+                case GOTO:
+                case RET:
+                case TABLESWITCH:
+                case LOOKUPSWITCH:
+                case IRETURN:
+                case LRETURN:
+                case FRETURN:
+                case DRETURN:
+                case ARETURN:
+                case RETURN:
+                case ATHROW:
+                    /*
+                     * note: this either returns from this subroutine, or a
+                     * parent subroutine which invoked it
+                     */
+                    return;
+            }
+
+            // Use tail recursion here in the form of an outer while loop to
+            // avoid our stack growing needlessly:
+            index++;
+        }
+    }
+
+    /**
+     * Creates the new instructions, inlining each instantiation of each
+     * subroutine until the code is fully elaborated.
+     */
+    private void emitCode() {
+        LinkedList worklist = new LinkedList();
+        // Create an instantiation of the "root" subroutine, which is just the
+        // main routine
+        worklist.add(new Instantiation(null, mainSubroutine));
+
+        // Emit instantiations of each subroutine we encounter, including the
+        // main subroutine
+        InsnList newInstructions = new InsnList();
+        List newTryCatchBlocks = new ArrayList();
+        List newLocalVariables = new ArrayList();
+        while (!worklist.isEmpty()) {
+            Instantiation inst = (Instantiation) worklist.removeFirst();
+            emitSubroutine(inst,
+                    worklist,
+                    newInstructions,
+                    newTryCatchBlocks,
+                    newLocalVariables);
+        }
+        instructions = newInstructions;
+        tryCatchBlocks = newTryCatchBlocks;
+        localVariables = newLocalVariables;
+    }
+
+    /**
+     * Emits one instantiation of one subroutine, specified by
+     * <code>instant</code>. May add new instantiations that are invoked by
+     * this one to the <code>worklist</code> parameter, and new try/catch
+     * blocks to <code>newTryCatchBlocks</code>.
+     * 
+     * @param instant the instantiation that must be performed.
+     * @param worklist list of the instantiations that remain to be done.
+     * @param newInstructions the instruction list to which the instantiated
+     *        code must be appended.
+     * @param newTryCatchBlocks the exception handler list to which the
+     *        instantiated handlers must be appended.
+     */
+    private void emitSubroutine(
+        final Instantiation instant,
+        final List worklist,
+        final InsnList newInstructions,
+        final List newTryCatchBlocks,
+        final List newLocalVariables)
+    {
+        LabelNode duplbl = null;
+
+        if (LOGGING) {
+            log("--------------------------------------------------------");
+            log("Emitting instantiation of subroutine " + instant.subroutine);
+        }
+
+        // Emit the relevant instructions for this instantiation, translating
+        // labels and jump targets as we go:
+        for (int i = 0, c = instructions.size(); i < c; i++) {
+            AbstractInsnNode insn = instructions.get(i);
+            Instantiation owner = instant.findOwner(i);
+
+            // Always remap labels:
+            if (insn.getType() == AbstractInsnNode.LABEL) {
+                // Translate labels into their renamed equivalents.
+                // Avoid adding the same label more than once. Note
+                // that because we own this instruction the gotoTable
+                // and the rangeTable will always agree.
+                LabelNode ilbl = (LabelNode) insn;
+                LabelNode remap = instant.rangeLabel(ilbl);
+                if (LOGGING) {
+                    // TODO use of default toString().
+                    log("Translating lbl #" + i + ':' + ilbl + " to " + remap);
+                }
+                if (remap != duplbl) {
+                    newInstructions.add(remap);
+                    duplbl = remap;
+                }
+                continue;
+            }
+
+            // We don't want to emit instructions that were already
+            // emitted by a subroutine higher on the stack. Note that
+            // it is still possible for a given instruction to be
+            // emitted twice because it may belong to two subroutines
+            // that do not invoke each other.
+            if (owner != instant) {
+                continue;
+            }
+
+            if (LOGGING) {
+                log("Emitting inst #" + i);
+            }
+
+            if (insn.getOpcode() == RET) {
+                // Translate RET instruction(s) to a jump to the return label
+                // for the appropriate instantiation. The problem is that the
+                // subroutine may "fall through" to the ret of a parent
+                // subroutine; therefore, to find the appropriate ret label we
+                // find the lowest subroutine on the stack that claims to own
+                // this instruction. See the class javadoc comment for an
+                // explanation on why this technique is safe (note: it is only
+                // safe if the input is verifiable).
+                LabelNode retlabel = null;
+                for (Instantiation p = instant; p != null; p = p.previous) {
+                    if (p.subroutine.ownsInstruction(i)) {
+                        retlabel = p.returnLabel;
+                    }
+                }
+                if (retlabel == null) {
+                    // This is only possible if the mainSubroutine owns a RET
+                    // instruction, which should never happen for verifiable
+                    // code.
+                    throw new RuntimeException("Instruction #" + i
+                            + " is a RET not owned by any subroutine");
+                }
+                newInstructions.add(new JumpInsnNode(GOTO, retlabel));
+            } else if (insn.getOpcode() == JSR) {
+                LabelNode lbl = ((JumpInsnNode) insn).label;
+                Subroutine sub = (Subroutine) subroutineHeads.get(lbl);
+                Instantiation newinst = new Instantiation(instant, sub);
+                LabelNode startlbl = newinst.gotoLabel(lbl);
+
+                if (LOGGING) {
+                    log(" Creating instantiation of subr " + sub);
+                }
+
+                // Rather than JSRing, we will jump to the inline version and
+                // push NULL for what was once the return value. This hack
+                // allows us to avoid doing any sort of data flow analysis to
+                // figure out which instructions manipulate the old return value
+                // pointer which is now known to be unneeded.
+                newInstructions.add(new InsnNode(ACONST_NULL));
+                newInstructions.add(new JumpInsnNode(GOTO, startlbl));
+                newInstructions.add(newinst.returnLabel);
+
+                // Insert this new instantiation into the queue to be emitted
+                // later.
+                worklist.add(newinst);
+            } else {
+                newInstructions.add(insn.clone(instant));
+            }
+        }
+
+        // Emit try/catch blocks that are relevant to this method.
+        for (Iterator it = tryCatchBlocks.iterator(); it.hasNext();) {
+            TryCatchBlockNode trycatch = (TryCatchBlockNode) it.next();
+
+            if (LOGGING) {
+                // TODO use of default toString().
+                log("try catch block original labels=" + trycatch.start + '-'
+                        + trycatch.end + "->" + trycatch.handler);
+            }
+
+            final LabelNode start = instant.rangeLabel(trycatch.start);
+            final LabelNode end = instant.rangeLabel(trycatch.end);
+
+            // Ignore empty try/catch regions
+            if (start == end) {
+                if (LOGGING) {
+                    log(" try catch block empty in this subroutine");
+                }
+                continue;
+            }
+
+            final LabelNode handler = instant.gotoLabel(trycatch.handler);
+
+            if (LOGGING) {
+                // TODO use of default toString().
+                log(" try catch block new labels=" + start + '-' + end + "->"
+                        + handler);
+            }
+
+            if (start == null || end == null || handler == null) {
+                throw new RuntimeException("Internal error!");
+            }
+
+            newTryCatchBlocks.add(new TryCatchBlockNode(start,
+                    end,
+                    handler,
+                    trycatch.type));
+        }
+
+        for (Iterator it = localVariables.iterator(); it.hasNext();) {
+            LocalVariableNode lvnode = (LocalVariableNode) it.next();
+            if (LOGGING) {
+                log("local var " + lvnode.name);
+            }
+            final LabelNode start = instant.rangeLabel(lvnode.start);
+            final LabelNode end = instant.rangeLabel(lvnode.end);
+            if (start == end) {
+                if (LOGGING) {
+                    log("  local variable empty in this sub");
+                }
+                continue;
+            }
+            newLocalVariables.add(new LocalVariableNode(lvnode.name,
+                    lvnode.desc,
+                    lvnode.signature,
+                    start,
+                    end,
+                    lvnode.index));
+        }
+    }
+
+    private static void log(final String str) {
+        System.err.println(str);
+    }
+
+    protected static class Subroutine {
+
+        public final BitSet instructions = new BitSet();
+
+        public void addInstruction(final int idx) {
+            instructions.set(idx);
+        }
+
+        public boolean ownsInstruction(final int idx) {
+            return instructions.get(idx);
+        }
+
+        public String toString() {
+            return "Subroutine: " + instructions;
+        }
+    }
+
+    /**
+     * A class that represents an instantiation of a subroutine. Each
+     * instantiation has an associate "stack" --- which is a listing of those
+     * instantiations that were active when this particular instance of this
+     * subroutine was invoked. Each instantiation also has a map from the
+     * original labels of the program to the labels appropriate for this
+     * instantiation, and finally a label to return to.
+     */
+    private class Instantiation extends AbstractMap {
+
+        /**
+         * Previous instantiations; the stack must be statically predictable to
+         * be inlinable.
+         */
+        final Instantiation previous;
+
+        /**
+         * The subroutine this is an instantiation of.
+         */
+        public final Subroutine subroutine;
+
+        /**
+         * This table maps Labels from the original source to Labels pointing at
+         * code specific to this instantiation, for use in remapping try/catch
+         * blocks,as well as gotos.
+         * 
+         * Note that in the presence of dual citizens instructions, that is,
+         * instructions which belong to more than one subroutine due to the
+         * merging of control flow without a RET instruction, we will map the
+         * target label of a GOTO to the label used by the instantiation lowest
+         * on the stack. This avoids code duplication during inlining in most
+         * cases.
+         * 
+         * @see #findOwner(int)
+         */
+        public final Map rangeTable = new HashMap();
+
+        /**
+         * All returns for this instantiation will be mapped to this label
+         */
+        public final LabelNode returnLabel;
+
+        Instantiation(final Instantiation prev, final Subroutine sub) {
+            previous = prev;
+            subroutine = sub;
+            for (Instantiation p = prev; p != null; p = p.previous) {
+                if (p.subroutine == sub) {
+                    throw new RuntimeException("Recursive invocation of " + sub);
+                }
+            }
+
+            // Determine the label to return to when this subroutine terminates
+            // via RET: note that the main subroutine never terminates via RET.
+            if (prev != null) {
+                returnLabel = new LabelNode();
+            } else {
+                returnLabel = null;
+            }
+
+            // Each instantiation will remap the labels from the code above to
+            // refer to its particular copy of its own instructions. Note that
+            // we collapse labels which point at the same instruction into one:
+            // this is fairly common as we are often ignoring large chunks of
+            // instructions, so what were previously distinct labels become
+            // duplicates.
+            LabelNode duplbl = null;
+            for (int i = 0, c = instructions.size(); i < c; i++) {
+                AbstractInsnNode insn = instructions.get(i);
+
+                if (insn.getType() == AbstractInsnNode.LABEL) {
+                    LabelNode ilbl = (LabelNode) insn;
+
+                    if (duplbl == null) {
+                        // if we already have a label pointing at this spot,
+                        // don't recreate it.
+                        duplbl = new LabelNode();
+                    }
+
+                    // Add an entry in the rangeTable for every label
+                    // in the original code which points at the next
+                    // instruction of our own to be emitted.
+                    rangeTable.put(ilbl, duplbl);
+                } else if (findOwner(i) == this) {
+                    // We will emit this instruction, so clear the 'duplbl' flag
+                    // since the next Label will refer to a distinct
+                    // instruction.
+                    duplbl = null;
+                }
+            }
+        }
+
+        /**
+         * Returns the "owner" of a particular instruction relative to this
+         * instantiation: the owner referes to the Instantiation which will emit
+         * the version of this instruction that we will execute.
+         * 
+         * Typically, the return value is either <code>this</code> or
+         * <code>null</code>. <code>this</code> indicates that this
+         * instantiation will generate the version of this instruction that we
+         * will execute, and <code>null</code> indicates that this
+         * instantiation never executes the given instruction.
+         * 
+         * Sometimes, however, an instruction can belong to multiple
+         * subroutines; this is called a "dual citizen" instruction (though it
+         * may belong to more than 2 subroutines), and occurs when multiple
+         * subroutines branch to common points of control. In this case, the
+         * owner is the subroutine that appears lowest on the stack, and which
+         * also owns the instruction in question.
+         * 
+         * @param i the index of the instruction in the original code
+         * @return the "owner" of a particular instruction relative to this
+         *         instantiation.
+         */
+        public Instantiation findOwner(final int i) {
+            if (!subroutine.ownsInstruction(i)) {
+                return null;
+            }
+            if (!dualCitizens.get(i)) {
+                return this;
+            }
+            Instantiation own = this;
+            for (Instantiation p = previous; p != null; p = p.previous) {
+                if (p.subroutine.ownsInstruction(i)) {
+                    own = p;
+                }
+            }
+            return own;
+        }
+
+        /**
+         * Looks up the label <code>l</code> in the <code>gotoTable</code>,
+         * thus translating it from a Label in the original code, to a Label in
+         * the inlined code that is appropriate for use by an instruction that
+         * branched to the original label.
+         * 
+         * @param l The label we will be translating
+         * @return a label for use by a branch instruction in the inlined code
+         * @see #rangeLabel
+         */
+        public LabelNode gotoLabel(final LabelNode l) {
+            // owner should never be null, because owner is only null
+            // if an instruction cannot be reached from this subroutine
+            Instantiation owner = findOwner(instructions.indexOf(l));
+            return (LabelNode) owner.rangeTable.get(l);
+        }
+
+        /**
+         * Looks up the label <code>l</code> in the <code>rangeTable</code>,
+         * thus translating it from a Label in the original code, to a Label in
+         * the inlined code that is appropriate for use by an try/catch or
+         * variable use annotation.
+         * 
+         * @param l The label we will be translating
+         * @return a label for use by a try/catch or variable annotation in the
+         *         original code
+         * @see #rangeTable
+         */
+        public LabelNode rangeLabel(final LabelNode l) {
+            return (LabelNode) rangeTable.get(l);
+        }
+
+        // AbstractMap implementation
+
+        public Set entrySet() {
+            return null;
+        }
+
+        public Object get(final Object o) {
+            return gotoLabel((LabelNode) o);
+        }
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/LocalVariablesSorter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/LocalVariablesSorter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/LocalVariablesSorter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/LocalVariablesSorter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,318 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * A {@link MethodAdapter} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method. It may be used by inheriting from this class, but the preferred way
+ * of using it is via delegation: the next visitor in the chain can indeed add
+ * new locals when needed by calling {@link #newLocal} on this adapter (this
+ * requires a reference back to this {@link LocalVariablesSorter}).
+ *
+ * @author Chris Nokleberg
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodAdapter {
+
+    private static final Type OBJECT_TYPE = Type.getObjectType("java/lang/Object");
+
+    /**
+     * Mapping from old to new local variable indexes. A local variable at index
+     * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+     * index i of size 2 is remapped to 'mapping[2*i+1]'.
+     */
+    private int[] mapping = new int[40];
+
+    /**
+     * Array used to store stack map local variable types after remapping.
+     */
+    private Object[] newLocals = new Object[20];
+
+    /**
+     * Index of the first local variable, after formal parameters.
+     */
+    protected final int firstLocal;
+
+    /**
+     * Index of the next local variable to be created by {@link #newLocal}.
+     */
+    protected int nextLocal;
+
+    /**
+     * Indicates if at least one local variable has moved due to remapping.
+     */
+    private boolean changed;
+
+    /**
+     * Creates a new {@link LocalVariablesSorter}.
+     *
+     * @param access access flags of the adapted method.
+     * @param desc the method's descriptor (see {@link Type Type}).
+     * @param mv the method visitor to which this adapter delegates calls.
+     */
+    public LocalVariablesSorter(
+        final int access,
+        final String desc,
+        final MethodVisitor mv)
+    {
+        super(mv);
+        Type[] args = Type.getArgumentTypes(desc);
+        nextLocal = (Opcodes.ACC_STATIC & access) == 0 ? 1 : 0;
+        for (int i = 0; i < args.length; i++) {
+            nextLocal += args[i].getSize();
+        }
+        firstLocal = nextLocal;
+    }
+
+    public void visitVarInsn(final int opcode, final int var) {
+        Type type;
+        switch (opcode) {
+            case Opcodes.LLOAD:
+            case Opcodes.LSTORE:
+                type = Type.LONG_TYPE;
+                break;
+
+            case Opcodes.DLOAD:
+            case Opcodes.DSTORE:
+                type = Type.DOUBLE_TYPE;
+                break;
+
+            case Opcodes.FLOAD:
+            case Opcodes.FSTORE:
+                type = Type.FLOAT_TYPE;
+                break;
+
+            case Opcodes.ILOAD:
+            case Opcodes.ISTORE:
+                type = Type.INT_TYPE;
+                break;
+
+            default:
+            // case Opcodes.ALOAD:
+            // case Opcodes.ASTORE:
+            // case RET:
+                type = OBJECT_TYPE;
+                break;
+        }
+        mv.visitVarInsn(opcode, remap(var, type));
+    }
+
+    public void visitIincInsn(final int var, final int increment) {
+        mv.visitIincInsn(remap(var, Type.INT_TYPE), increment);
+    }
+
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        mv.visitMaxs(maxStack, nextLocal);
+    }
+
+    public void visitLocalVariable(
+        final String name,
+        final String desc,
+        final String signature,
+        final Label start,
+        final Label end,
+        final int index)
+    {
+        int newIndex = remap(index, Type.getType(desc));
+        mv.visitLocalVariable(name, desc, signature, start, end, newIndex);
+    }
+
+    public void visitFrame(
+        final int type,
+        final int nLocal,
+        final Object[] local,
+        final int nStack,
+        final Object[] stack)
+    {
+        if (type != Opcodes.F_NEW) { // uncompressed frame
+            throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag");
+        }
+
+        if (!changed) { // optimization for the case where mapping = identity
+            mv.visitFrame(type, nLocal, local, nStack, stack);
+            return;
+        }
+
+        // creates a copy of newLocals
+        Object[] oldLocals = new Object[newLocals.length];
+        System.arraycopy(newLocals, 0, oldLocals, 0, oldLocals.length);
+
+        // copies types from 'local' to 'newLocals'
+        // 'newLocals' already contains the variables added with 'newLocal'
+
+        int index = 0; // old local variable index
+        int number = 0; // old local variable number
+        for (; number < nLocal; ++number) {
+            Object t = local[number];
+            int size = t == Opcodes.LONG || t == Opcodes.DOUBLE ? 2 : 1;
+            if (t != Opcodes.TOP) {
+                Type typ = OBJECT_TYPE;
+                if (t == Opcodes.INTEGER) {
+                    typ = Type.INT_TYPE;
+                } else if (t == Opcodes.FLOAT) {
+                    typ = Type.FLOAT_TYPE;
+                } else if (t == Opcodes.LONG) {
+                    typ = Type.LONG_TYPE;
+                } else if (t == Opcodes.DOUBLE) {
+                    typ = Type.DOUBLE_TYPE;
+                } else if (t instanceof String) {
+                    typ = Type.getObjectType((String) t);
+                }
+                setFrameLocal(remap(index, typ), t);
+            }
+            index += size;
+        }
+
+        // removes TOP after long and double types as well as trailing TOPs
+
+        index = 0;
+        number = 0;
+        for (int i = 0; index < newLocals.length; ++i) {
+            Object t = newLocals[index++];
+            if (t != null && t != Opcodes.TOP) {
+                newLocals[i] = t;
+                number = i + 1;
+                if (t == Opcodes.LONG || t == Opcodes.DOUBLE) {
+                    index += 1;
+                }
+            } else {
+                newLocals[i] = Opcodes.TOP;
+            }
+        }
+
+        // visits remapped frame
+        mv.visitFrame(type, number, newLocals, nStack, stack);
+
+        // restores original value of 'newLocals'
+        newLocals = oldLocals;
+    }
+
+    // -------------
+
+    /**
+     * Creates a new local variable of the given type.
+     *
+     * @param type the type of the local variable to be created.
+     * @return the identifier of the newly created local variable.
+     */
+    public int newLocal(final Type type) {
+        Object t;
+        switch (type.getSort()) {
+            case Type.BOOLEAN:
+            case Type.CHAR:
+            case Type.BYTE:
+            case Type.SHORT:
+            case Type.INT:
+                t = Opcodes.INTEGER;
+                break;
+            case Type.FLOAT:
+                t = Opcodes.FLOAT;
+                break;
+            case Type.LONG:
+                t = Opcodes.LONG;
+                break;
+            case Type.DOUBLE:
+                t = Opcodes.DOUBLE;
+                break;
+            case Type.ARRAY:
+                t = type.getDescriptor();
+                break;
+            // case Type.OBJECT:
+            default:
+                t = type.getInternalName();
+                break;
+        }
+        int local = nextLocal;
+        nextLocal += type.getSize();
+        setLocalType(local, type);
+        setFrameLocal(local, t);
+        return local;
+    }
+
+    /**
+     * Sets the current type of the given local variable. The default
+     * implementation of this method does nothing.
+     *
+     * @param local a local variable identifier, as returned by {@link #newLocal
+     *        newLocal()}.
+     * @param type the type of the value being stored in the local variable
+     */
+    protected void setLocalType(final int local, final Type type) {
+    }
+
+    private void setFrameLocal(final int local, final Object type) {
+        int l = newLocals.length;
+        if (local >= l) {
+            Object[] a = new Object[Math.max(2 * l, local + 1)];
+            System.arraycopy(newLocals, 0, a, 0, l);
+            newLocals = a;
+        }
+        newLocals[local] = type;
+    }
+
+    private int remap(final int var, final Type type) {
+        if (var + type.getSize() <= firstLocal) {
+            return var;
+        }
+        int key = 2 * var + type.getSize() - 1;
+        int size = mapping.length;
+        if (key >= size) {
+            int[] newMapping = new int[Math.max(2 * size, key + 1)];
+            System.arraycopy(mapping, 0, newMapping, 0, size);
+            mapping = newMapping;
+        }
+        int value = mapping[key];
+        if (value == 0) {
+            value = newLocalMapping(type);
+            setLocalType(value, type);
+            mapping[key] = value + 1;
+        } else {
+            value--;
+        }
+        if (value != var) {
+            changed = true;
+        }
+        return value;
+    }
+
+    protected int newLocalMapping(final Type type) {
+        int local = nextLocal;
+        nextLocal += type.getSize();
+        return local;
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Method.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Method.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Method.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Method.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,275 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.objectweb.asm.commons;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.objectweb.asm.Type;
+
+/**
+ * A named method descriptor.
+ * 
+ * @author Juozas Baliuka
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class Method {
+
+    /**
+     * The method name.
+     */
+    private final String name;
+
+    /**
+     * The method descriptor.
+     */
+    private final String desc;
+
+    /**
+     * Maps primitive Java type names to their descriptors.
+     */
+    private static final Map DESCRIPTORS;
+
+    static {
+        DESCRIPTORS = new HashMap();
+        DESCRIPTORS.put("void", "V");
+        DESCRIPTORS.put("byte", "B");
+        DESCRIPTORS.put("char", "C");
+        DESCRIPTORS.put("double", "D");
+        DESCRIPTORS.put("float", "F");
+        DESCRIPTORS.put("int", "I");
+        DESCRIPTORS.put("long", "J");
+        DESCRIPTORS.put("short", "S");
+        DESCRIPTORS.put("boolean", "Z");
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name the method's name.
+     * @param desc the method's descriptor.
+     */
+    public Method(final String name, final String desc) {
+        this.name = name;
+        this.desc = desc;
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param name the method's name.
+     * @param returnType the method's return type.
+     * @param argumentTypes the method's argument types.
+     */
+    public Method(
+        final String name,
+        final Type returnType,
+        final Type[] argumentTypes)
+    {
+        this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+    }
+    
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param m a java.lang.reflect method descriptor
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Method m) {
+        return new Method(m.getName(), Type.getMethodDescriptor(m));
+    }
+
+    /**
+     * Creates a new {@link Method}.
+     * 
+     * @param c a java.lang.reflect constructor descriptor
+     * @return a {@link Method} corresponding to the given Java constructor
+     *         declaration.
+     */
+    public static Method getMethod(java.lang.reflect.Constructor c) {
+        return new Method("<init>", Type.getConstructorDescriptor(c));
+    }
+    
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method a Java method declaration, without argument names, of the
+     *        form "returnType name (argumentType1, ... argumentTypeN)", where
+     *        the types are in plain Java (e.g. "int", "float",
+     *        "java.util.List", ...). Classes of the java.lang package can be
+     *        specified by their unqualified name; all other classes names must
+     *        be fully qualified.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException if <code>method</code> could not get
+     *         parsed.
+     */
+    public static Method getMethod(final String method)
+            throws IllegalArgumentException
+    {
+        return getMethod(method, false);
+    }
+
+    /**
+     * Returns a {@link Method} corresponding to the given Java method
+     * declaration.
+     * 
+     * @param method a Java method declaration, without argument names, of the
+     *        form "returnType name (argumentType1, ... argumentTypeN)", where
+     *        the types are in plain Java (e.g. "int", "float",
+     *        "java.util.List", ...). Classes of the java.lang package may be
+     *        specified by their unqualified name, depending on the
+     *        defaultPackage argument; all other classes names must be fully
+     *        qualified.
+     * @param defaultPackage true if unqualified class names belong to the
+     *        default package, or false if they correspond to java.lang classes.
+     *        For instance "Object" means "Object" if this option is true, or
+     *        "java.lang.Object" otherwise.
+     * @return a {@link Method} corresponding to the given Java method
+     *         declaration.
+     * @throws IllegalArgumentException if <code>method</code> could not get
+     *         parsed.
+     */
+    public static Method getMethod(
+        final String method,
+        final boolean defaultPackage) throws IllegalArgumentException
+    {
+        int space = method.indexOf(' ');
+        int start = method.indexOf('(', space) + 1;
+        int end = method.indexOf(')', start);
+        if (space == -1 || start == -1 || end == -1) {
+            throw new IllegalArgumentException();
+        }
+        String returnType = method.substring(0, space);
+        String methodName = method.substring(space + 1, start - 1).trim();
+        StringBuffer sb = new StringBuffer();
+        sb.append('(');
+        int p;
+        do {
+            String s;
+            p = method.indexOf(',', start);
+            if (p == -1) {
+                s = map(method.substring(start, end).trim(), defaultPackage);
+            } else {
+                s = map(method.substring(start, p).trim(), defaultPackage);
+                start = p + 1;
+            }
+            sb.append(s);
+        } while (p != -1);
+        sb.append(')');
+        sb.append(map(returnType, defaultPackage));
+        return new Method(methodName, sb.toString());
+    }
+
+    private static String map(final String type, final boolean defaultPackage) {
+        if ("".equals(type)) {
+            return type;
+        }
+
+        StringBuffer sb = new StringBuffer();
+        int index = 0;
+        while ((index = type.indexOf("[]", index) + 1) > 0) {
+            sb.append('[');
+        }
+
+        String t = type.substring(0, type.length() - sb.length() * 2);
+        String desc = (String) DESCRIPTORS.get(t);
+        if (desc != null) {
+            sb.append(desc);
+        } else {
+            sb.append('L');
+            if (t.indexOf('.') < 0) {
+                if (!defaultPackage) {
+                    sb.append("java/lang/");
+                }
+                sb.append(t);
+            } else {
+                sb.append(t.replace('.', '/'));
+            }
+            sb.append(';');
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the name of the method described by this object.
+     * 
+     * @return the name of the method described by this object.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the descriptor of the method described by this object.
+     * 
+     * @return the descriptor of the method described by this object.
+     */
+    public String getDescriptor() {
+        return desc;
+    }
+
+    /**
+     * Returns the return type of the method described by this object.
+     * 
+     * @return the return type of the method described by this object.
+     */
+    public Type getReturnType() {
+        return Type.getReturnType(desc);
+    }
+
+    /**
+     * Returns the argument types of the method described by this object.
+     * 
+     * @return the argument types of the method described by this object.
+     */
+    public Type[] getArgumentTypes() {
+        return Type.getArgumentTypes(desc);
+    }
+
+    public String toString() {
+        return name + desc;
+    }
+
+    public boolean equals(final Object o) {
+        if (!(o instanceof Method)) {
+            return false;
+        }
+        Method other = (Method) o;
+        return name.equals(other.name) && desc.equals(other.desc);
+    }
+
+    public int hashCode() {
+        return name.hashCode() ^ desc.hashCode();
+    }
+}
\ No newline at end of file

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Remapper.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Remapper.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Remapper.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/Remapper.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,187 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+import org.objectweb.asm.signature.SignatureWriter;
+
+/**
+ * A class responsible for remapping types and names.
+ * Subclasses can override the following methods:
+ * 
+ * <ul>
+ * <li>{@link #map(String)} - map type</li>
+ * <li>{@link #mapFieldName(String, String, String)} - map field name</li>
+ * <li>{@link #mapMethodName(String, String, String)} - map method name</li>
+ * </ul>
+ * 
+ * @author Eugene Kuleshov
+ */
+public abstract class Remapper {
+
+    public String mapDesc(String desc) {
+        Type t = Type.getType(desc);
+        switch (t.getSort()) {
+            case Type.ARRAY:
+                String s = mapDesc(t.getElementType().getDescriptor());
+                for (int i = 0; i < t.getDimensions(); ++i) {
+                    s = '[' + s;
+                }
+                return s;
+            case Type.OBJECT:
+                String newType = map(t.getInternalName());
+                if (newType != null) {
+                    return 'L' + newType + ';';
+                }
+        }
+        return desc;
+    }
+
+    private Type mapType(Type t) {
+        switch (t.getSort()) {
+            case Type.ARRAY:
+                String s = mapDesc(t.getElementType().getDescriptor());
+                for (int i = 0; i < t.getDimensions(); ++i) {
+                    s = '[' + s;
+                }
+                return Type.getType(s);
+            case Type.OBJECT:
+                s = map(t.getInternalName());
+                if(s != null) {
+                    return Type.getObjectType(s);
+                }
+        }
+        return t;
+    }
+
+    public String mapType(String type) {
+        if (type == null) {
+            return null;
+        }
+        return mapType(Type.getObjectType(type)).getInternalName();
+    }
+
+    public String[] mapTypes(String[] types) {
+        String[] newTypes = null;
+        boolean needMapping = false;
+        for (int i = 0; i < types.length; i++) {
+            String type = types[i];
+            String newType = map(type);
+            if (newType != null && newTypes == null) {
+                newTypes = new String[types.length];
+                if (i > 0) {
+                    System.arraycopy(types, 0, newTypes, 0, i);
+                }
+                needMapping = true;
+            }
+            if (needMapping) {
+                newTypes[i] = newType == null 
+                    ? type 
+                    : newType;
+            }
+        }
+        return needMapping 
+           ? newTypes 
+           : types;
+    }
+
+    public String mapMethodDesc(String desc) {
+        if("()V".equals(desc)) {
+            return desc;
+        }
+        
+        Type[] args = Type.getArgumentTypes(desc);
+        String s = "(";
+        for (int i = 0; i < args.length; i++) {
+            s += mapDesc(args[i].getDescriptor());
+        }
+        Type returnType = Type.getReturnType(desc);
+        if(returnType == Type.VOID_TYPE) {
+            return s + ")V";
+        }
+        return s + ')' + mapDesc(returnType.getDescriptor());
+    }
+
+    public Object mapValue(Object value) {
+        return value instanceof Type ? mapType((Type) value) : value;
+    }
+
+    /**
+     * 
+     * @param typeSignature true if signature is a FieldTypeSignature, such as
+     *        the signature parameter of the ClassVisitor.visitField or
+     *        MethodVisitor.visitLocalVariable methods
+     */
+    public String mapSignature(String signature, boolean typeSignature) {
+        if (signature == null) {
+            return null;
+        }
+        SignatureReader r = new SignatureReader(signature);
+        SignatureWriter w = new SignatureWriter();
+        SignatureVisitor a = createRemappingSignatureAdapter(w);
+        if (typeSignature) {
+            r.acceptType(a);
+        } else {
+            r.accept(a);
+        }
+        return w.toString();
+    }
+
+    protected SignatureVisitor createRemappingSignatureAdapter(
+        SignatureVisitor v)
+    {
+        return new RemappingSignatureAdapter(v, this);
+    }
+    
+    /**
+     * Map method name to the new name. Subclasses can override. 
+     */
+    public String mapMethodName(String owner, String name, String desc) {
+        return name;
+    }
+
+    /**
+     * Map field name to the new name. Subclasses can override. 
+     */
+    public String mapFieldName(String owner, String name, String desc) {
+        return name;
+    }
+    
+    /**
+     * Map type name to the new name. Subclasses can override. 
+     */
+    public String map(String typeName) {
+        return typeName;
+    }
+
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingAnnotationAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingAnnotationAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingAnnotationAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingAnnotationAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+ * An <code>AnnotationVisitor</code> adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingAnnotationAdapter implements AnnotationVisitor {
+    
+    private final AnnotationVisitor av;
+    
+    private final Remapper renamer;
+
+    public RemappingAnnotationAdapter(AnnotationVisitor av, Remapper renamer) {
+        this.av = av;
+        this.renamer = renamer;
+    }
+
+    public void visit(String name, Object value) {
+        av.visit(name, renamer.mapValue(value));
+    }
+
+    public void visitEnum(String name, String desc, String value) {
+        av.visitEnum(name, renamer.mapDesc(desc), value);
+    }
+
+    public AnnotationVisitor visitAnnotation(String name, String desc) {
+        AnnotationVisitor v = av.visitAnnotation(name, renamer.mapDesc(desc));
+        return v == null ? null : (v == av
+                ? this
+                : new RemappingAnnotationAdapter(v, renamer));
+    }
+
+    public AnnotationVisitor visitArray(String name) {
+        AnnotationVisitor v = av.visitArray(name);
+        return v == null ? null : (v == av
+                ? this
+                : new RemappingAnnotationAdapter(v, renamer));
+    }
+
+    public void visitEnd() {
+        av.visitEnd();
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingClassAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingClassAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingClassAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingClassAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,145 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+
+/**
+ * A <code>ClassAdapter</code> for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingClassAdapter extends ClassAdapter {
+
+    protected final Remapper remapper;
+    
+    protected String className;
+
+    public RemappingClassAdapter(ClassVisitor cv, Remapper remapper) {
+        super(cv);
+        this.remapper = remapper;
+    }
+
+    public void visit(
+        int version,
+        int access,
+        String name,
+        String signature,
+        String superName,
+        String[] interfaces)
+    {
+        this.className = name;
+        super.visit(version,
+                access,
+                remapper.mapType(name),
+                remapper.mapSignature(signature, false),
+                remapper.mapType(superName),
+                interfaces == null ? null 
+                        : remapper.mapTypes(interfaces));
+    }
+
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av;
+        av = super.visitAnnotation(remapper.mapDesc(desc), visible);
+        return av == null ? null : createRemappingAnnotationAdapter(av);
+    }
+
+    public FieldVisitor visitField(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        Object value)
+    {
+        FieldVisitor fv = super.visitField(access,
+                remapper.mapFieldName(className, name, desc),
+                remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true),
+                remapper.mapValue(value));
+        return fv == null ? null : createRemappingFieldAdapter(fv);
+    }
+
+    public MethodVisitor visitMethod(
+        int access,
+        String name,
+        String desc,
+        String signature,
+        String[] exceptions)
+    {
+        String newDesc = remapper.mapMethodDesc(desc);
+        MethodVisitor mv = super.visitMethod(access,
+                remapper.mapMethodName(className, name, desc),
+                newDesc,
+                remapper.mapSignature(signature, false),
+                exceptions == null ? null : remapper.mapTypes(exceptions));
+        return mv == null ? null : createRemappingMethodAdapter(access, newDesc, mv);
+    }
+
+    public void visitInnerClass(
+        String name,
+        String outerName,
+        String innerName,
+        int access)
+    {
+        super.visitInnerClass(remapper.mapType(name),
+                outerName == null ? null : remapper.mapType(outerName),
+                innerName, // TODO should it be changed?
+                access);
+    }
+
+    public void visitOuterClass(String owner, String name, String desc) {
+        super.visitOuterClass(remapper.mapType(owner), 
+                name == null ? null : remapper.mapMethodName(owner, name, desc), 
+                desc == null ? null : remapper.mapMethodDesc(desc));
+    }
+
+    protected FieldVisitor createRemappingFieldAdapter(FieldVisitor fv) {
+        return new RemappingFieldAdapter(fv, remapper);
+    }
+    
+    protected MethodVisitor createRemappingMethodAdapter(
+        int access,
+        String newDesc,
+        MethodVisitor mv)
+    {
+        return new RemappingMethodAdapter(access, newDesc, mv, remapper);
+    }
+
+    protected AnnotationVisitor createRemappingAnnotationAdapter(
+        AnnotationVisitor av)
+    {
+        return new RemappingAnnotationAdapter(av, remapper);
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingFieldAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingFieldAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingFieldAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingFieldAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,65 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.FieldVisitor;
+
+/**
+ * A <code>FieldVisitor</code> adapter for type remapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingFieldAdapter implements FieldVisitor {
+
+    private final FieldVisitor fv;
+    
+    private final Remapper remapper;
+
+    public RemappingFieldAdapter(FieldVisitor fv, Remapper remapper) {
+        this.fv = fv;
+        this.remapper = remapper;
+    }
+
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = fv.visitAnnotation(remapper.mapDesc(desc), visible);
+        return av == null ? null : new RemappingAnnotationAdapter(av, remapper);
+    }
+
+    public void visitAttribute(Attribute attr) {
+        fv.visitAttribute(attr);
+    }
+
+    public void visitEnd() {
+        fv.visitEnd();
+    }
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingMethodAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingMethodAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingMethodAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingMethodAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,168 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+
+/**
+ * A <code>MethodAdapter</code> for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingMethodAdapter extends LocalVariablesSorter {
+
+    protected final Remapper remapper;
+
+    public RemappingMethodAdapter(
+        int access,
+        String desc,
+        MethodVisitor mv,
+        Remapper renamer)
+    {
+        super(access, desc, mv);
+        this.remapper = renamer;
+    }
+
+    public void visitFieldInsn(
+        int opcode,
+        String owner,
+        String name,
+        String desc)
+    {
+        super.visitFieldInsn(opcode,
+                remapper.mapType(owner),
+                remapper.mapFieldName(owner, name, desc),
+                remapper.mapDesc(desc));
+    }
+
+    public void visitMethodInsn(
+        int opcode,
+        String owner,
+        String name,
+        String desc)
+    {
+        super.visitMethodInsn(opcode,
+                remapper.mapType(owner),
+                remapper.mapMethodName(owner, name, desc),
+                remapper.mapMethodDesc(desc));
+    }
+
+    public void visitTypeInsn(int opcode, String type) {
+        super.visitTypeInsn(opcode, remapper.mapType(type));
+    }
+
+    public void visitLdcInsn(Object cst) {
+        super.visitLdcInsn(remapper.mapValue(cst));
+    }
+
+    public void visitMultiANewArrayInsn(String desc, int dims) {
+        super.visitMultiANewArrayInsn(remapper.mapDesc(desc), dims);
+    }
+
+    public void visitTryCatchBlock(
+        Label start,
+        Label end,
+        Label handler,
+        String type)
+    {
+        super.visitTryCatchBlock(start, end, handler, // 
+                type == null ? null : remapper.mapType(type));
+    }
+    
+    public void visitLocalVariable(
+        String name,
+        String desc,
+        String signature,
+        Label start,
+        Label end,
+        int index)
+    {
+        super.visitLocalVariable(name,
+                remapper.mapDesc(desc),
+                remapper.mapSignature(signature, true),
+                start,
+                end,
+                index);
+    }
+
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        AnnotationVisitor av = mv.visitAnnotation(remapper.mapDesc(desc), visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+    
+    public AnnotationVisitor visitAnnotationDefault() {
+        AnnotationVisitor av = mv.visitAnnotationDefault();
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+    
+    public AnnotationVisitor visitParameterAnnotation(
+        int parameter,
+        String desc,
+        boolean visible)
+    {
+        AnnotationVisitor av = mv.visitParameterAnnotation(parameter,
+                remapper.mapDesc(desc),
+                visible);
+        return av == null ? av : new RemappingAnnotationAdapter(av, remapper);
+    }
+    
+    public void visitFrame(
+        int type,
+        int nLocal,
+        Object[] local,
+        int nStack,
+        Object[] stack)
+    {
+        super.visitFrame(type, nLocal, remapEntries(nLocal, local), nStack, remapEntries(nStack, stack));
+    }
+
+    private Object[] remapEntries(int n, Object[] entries) {
+        for (int i = 0; i < n; i++) {
+            if (entries[i] instanceof String) {
+                Object[] newEntries = new Object[n];
+                if (i > 0) {
+                    System.arraycopy(entries, 0, newEntries, 0, i);
+                }
+                do {
+                    Object t = entries[i];
+                    newEntries[i++] = t instanceof String
+                            ? remapper.mapType((String) t)
+                            : t;
+                } while (i < n);
+                return newEntries;
+            }
+        }
+        return entries;
+    }
+    
+}

Added: tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingSignatureAdapter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingSignatureAdapter.java?rev=1089584&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingSignatureAdapter.java (added)
+++ tapestry/tapestry5/trunk/plastic/src/external/java/org/objectweb/asm/commons/RemappingSignatureAdapter.java Wed Apr  6 19:11:34 2011
@@ -0,0 +1,126 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.objectweb.asm.commons;
+
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * A <code>SignatureVisitor</code> adapter for type mapping.
+ * 
+ * @author Eugene Kuleshov
+ */
+public class RemappingSignatureAdapter implements SignatureVisitor {
+    private final SignatureVisitor v;
+    private final Remapper remapper;
+    private String className;
+    
+    public RemappingSignatureAdapter(SignatureVisitor v, Remapper remapper) {
+        this.v = v;
+        this.remapper = remapper;
+    }
+
+    public void visitClassType(String name) {
+        className = name;
+        v.visitClassType(remapper.mapType(name));
+    }
+
+    public void visitInnerClassType(String name) {
+        className = className + '$' + name;
+        String remappedName = remapper.mapType(className);
+        v.visitInnerClassType(remappedName.substring(remappedName.lastIndexOf('$') + 1));
+    }
+
+    public void visitFormalTypeParameter(String name) {
+        v.visitFormalTypeParameter(name);
+    }
+
+    public void visitTypeVariable(String name) {
+        v.visitTypeVariable(name);
+    }
+
+    public SignatureVisitor visitArrayType() {
+        v.visitArrayType();
+        return this;
+    }
+
+    public void visitBaseType(char descriptor) {
+        v.visitBaseType(descriptor);
+    }
+
+    public SignatureVisitor visitClassBound() {
+        v.visitClassBound();
+        return this;
+    }
+
+    public SignatureVisitor visitExceptionType() {
+        v.visitExceptionType();
+        return this;
+    }
+
+    public SignatureVisitor visitInterface() {
+        v.visitInterface();
+        return this;
+    }
+
+    public SignatureVisitor visitInterfaceBound() {
+        v.visitInterfaceBound();
+        return this;
+    }
+
+    public SignatureVisitor visitParameterType() {
+        v.visitParameterType();
+        return this;
+    }
+
+    public SignatureVisitor visitReturnType() {
+        v.visitReturnType();
+        return this;
+    }
+
+    public SignatureVisitor visitSuperclass() {
+        v.visitSuperclass();
+        return this;
+    }
+
+    public void visitTypeArgument() {
+        v.visitTypeArgument();
+    }
+
+    public SignatureVisitor visitTypeArgument(char wildcard) {
+        v.visitTypeArgument(wildcard);
+        return this;
+    }
+
+    public void visitEnd() {
+        v.visitEnd();
+    }
+
+}