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();
+ }
+
+}