You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by ka...@apache.org on 2014/03/25 19:29:57 UTC
[09/23] FIXED - TAP5-2214: Make tapestry5 java8 compatible - update
ASM source to 5.0.1, should be jdk 1.5 compatible,
see ASM bug "317132 ASM 5.0 do not supported JDK 1.5?"
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
index d2d461c..ce959df 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MethodNode.java
@@ -1,7 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
- * Copyright (c) 2011 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,22 +29,29 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.*;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Attribute;
+import org.apache.tapestry5.internal.plastic.asm.ClassVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Handle;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+
/**
* A node that represents a method.
- *
+ *
* @author Eric Bruneton
*/
-public class MethodNode extends MethodVisitor
-{
+public class MethodNode extends MethodVisitor {
/**
- * The method's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}). This field also
+ * The method's access flags (see {@link Opcodes}). This field also
* indicates if the method is synthetic and/or deprecated.
*/
public int access;
@@ -56,7 +62,7 @@ public class MethodNode extends MethodVisitor
public String name;
/**
- * The method's descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * The method's descriptor (see {@link Type}).
*/
public String desc;
@@ -67,16 +73,21 @@ public class MethodNode extends MethodVisitor
/**
* The internal names of the method's exception classes (see
- * {@link org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). This list is a list of
+ * {@link Type#getInternalName() getInternalName}). This list is a list of
* {@link String} objects.
*/
public List<String> exceptions;
/**
+ * The method parameter info (access flags and name)
+ */
+ public List<ParameterNode> parameters;
+
+ /**
* The runtime visible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
@@ -84,17 +95,35 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible annotations of this method. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
+ * The runtime visible type annotations of this method. This list is a list
+ * of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations of this method. This list is a
+ * list of {@link TypeAnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* The non standard attributes of this method. This list is a list of
- * {@link org.apache.tapestry5.internal.plastic.asm.Attribute} objects. May be <tt>null</tt>.
- *
- * @associates Attribute
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
*/
public List<Attribute> attrs;
@@ -102,7 +131,7 @@ public class MethodNode extends MethodVisitor
* The default value of this annotation interface method. This field must be
* a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
* {@link Integer}, {@link Long}, {@link Float}, {@link Double},
- * {@link String} or {@link org.apache.tapestry5.internal.plastic.asm.Type}, or an two elements String array (for
+ * {@link String} or {@link Type}, or an two elements String array (for
* enumeration values), a {@link AnnotationNode}, or a {@link List} of
* values of one of the preceding types. May be <tt>null</tt>.
*/
@@ -111,8 +140,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime visible parameter annotations of this method. These lists are
* lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible parameters
*/
public List<AnnotationNode>[] visibleParameterAnnotations;
@@ -120,8 +149,8 @@ public class MethodNode extends MethodVisitor
/**
* The runtime invisible parameter annotations of this method. These lists
* are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
- *
- * @associates AnnotationNode
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
* @label visible parameters
*/
public List<AnnotationNode>[] invisibleParameterAnnotations;
@@ -129,8 +158,8 @@ public class MethodNode extends MethodVisitor
/**
* The instructions of this method. This list is a list of
* {@link AbstractInsnNode} objects.
- *
- * @associates AbstractInsnNode
+ *
+ * @associates org.objectweb.asm.tree.AbstractInsnNode
* @label instructions
*/
public InsnList instructions;
@@ -138,8 +167,8 @@ public class MethodNode extends MethodVisitor
/**
* The try catch blocks of this method. This list is a list of
* {@link TryCatchBlockNode} objects.
- *
- * @associates TryCatchBlockNode
+ *
+ * @associates org.objectweb.asm.tree.TryCatchBlockNode
*/
public List<TryCatchBlockNode> tryCatchBlocks;
@@ -156,30 +185,53 @@ public class MethodNode extends MethodVisitor
/**
* The local variables of this method. This list is a list of
* {@link LocalVariableNode} objects. May be <tt>null</tt>
- *
- * @associates LocalVariableNode
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableNode
*/
public List<LocalVariableNode> localVariables;
/**
+ * The visible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> visibleLocalVariableAnnotations;
+
+ /**
+ * The invisible local variable annotations of this method. This list is a
+ * list of {@link LocalVariableAnnotationNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableAnnotationNode
+ */
+ public List<LocalVariableAnnotationNode> invisibleLocalVariableAnnotations;
+
+ /**
* If the accept method has been called on this object.
*/
private boolean visited;
-
+
/**
* Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
* use this constructor</i>. Instead, they must use the
* {@link #MethodNode(int)} version.
+ *
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
public MethodNode() {
- this(Opcodes.ASM4);
+ this(Opcodes.ASM5);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs an uninitialized {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
*/
public MethodNode(final int api) {
super(api);
@@ -190,57 +242,61 @@ public class MethodNode extends MethodVisitor
* Constructs a new {@link MethodNode}. <i>Subclasses must not use this
* constructor</i>. Instead, they must use the
* {@link #MethodNode(int, int, String, String, String, String[])} version.
- *
- * @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 org.apache.tapestry5.internal.plastic.asm.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 org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @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>.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
*/
- public MethodNode(
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
- this(Opcodes.ASM4, access, name, desc, signature, exceptions);
+ public MethodNode(final int access, final String name, final String desc,
+ final String signature, final String[] exceptions) {
+ this(Opcodes.ASM5, access, name, desc, signature, exceptions);
+ if (getClass() != MethodNode.class) {
+ throw new IllegalStateException();
+ }
}
/**
* Constructs a new {@link MethodNode}.
- *
- * @param api the ASM API version implemented by this visitor. Must be one
- * of {@link Opcodes#ASM4}.
- * @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 org.apache.tapestry5.internal.plastic.asm.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 org.apache.tapestry5.internal.plastic.asm.Type#getInternalName() getInternalName}). May be
- * <tt>null</tt>.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @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 MethodNode(
- final int api,
- final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions)
- {
+ public MethodNode(final int api, final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
super(api);
this.access = access;
this.name = name;
this.desc = desc;
this.signature = signature;
- this.exceptions = new ArrayList<String>(exceptions == null
- ? 0
+ this.exceptions = new ArrayList<String>(exceptions == null ? 0
: exceptions.length);
boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
if (!isAbstract) {
@@ -258,6 +314,14 @@ public class MethodNode extends MethodVisitor
// ------------------------------------------------------------------------
@Override
+ public void visitParameter(String name, int access) {
+ if (parameters == null) {
+ parameters = new ArrayList<ParameterNode>(5);
+ }
+ parameters.add(new ParameterNode(name, access));
+ }
+
+ @Override
public AnnotationVisitor visitAnnotationDefault() {
return new AnnotationNode(new ArrayList<Object>(0) {
@Override
@@ -269,10 +333,8 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitAnnotation(
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
@@ -289,28 +351,45 @@ public class MethodNode extends MethodVisitor
}
@Override
- public AnnotationVisitor visitParameterAnnotation(
- final int parameter,
- final String desc,
- final boolean visible)
- {
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (visibleTypeAnnotations == null) {
+ visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ visibleTypeAnnotations.add(an);
+ } else {
+ if (invisibleTypeAnnotations == null) {
+ invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(1);
+ }
+ invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ visibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (visibleParameterAnnotations[parameter] == null) {
- visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
visibleParameterAnnotations[parameter].add(an);
} else {
if (invisibleParameterAnnotations == null) {
int params = Type.getArgumentTypes(this.desc).length;
- invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ invisibleParameterAnnotations = (List<AnnotationNode>[]) new List<?>[params];
}
if (invisibleParameterAnnotations[parameter] == null) {
- invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(
+ 1);
}
invisibleParameterAnnotations[parameter].add(an);
}
@@ -330,17 +409,10 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFrame(
- final int type,
- final int nLocal,
- final Object[] local,
- final int nStack,
- final Object[] stack)
- {
- instructions.add(new FrameNode(type, nLocal, local == null
- ? null
- : getLabelNodes(local), nStack, stack == null
- ? null
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ instructions.add(new FrameNode(type, nLocal, local == null ? null
+ : getLabelNodes(local), nStack, stack == null ? null
: getLabelNodes(stack)));
}
@@ -365,32 +437,35 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitFieldInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
instructions.add(new FieldInsnNode(opcode, owner, name, desc));
}
+ @Deprecated
@Override
- public void visitMethodInsn(
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
instructions.add(new MethodInsnNode(opcode, owner, name, desc));
}
@Override
- public void visitInvokeDynamicInsn(
- String name,
- String desc,
- Handle bsm,
- Object... bsmArgs)
- {
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ instructions.add(new MethodInsnNode(opcode, owner, name, desc, itf));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
}
@@ -415,26 +490,16 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTableSwitchInsn(
- final int min,
- final int max,
- final Label dflt,
- final Label... labels)
- {
- instructions.add(new TableSwitchInsnNode(min,
- max,
- getLabelNode(dflt),
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ instructions.add(new TableSwitchInsnNode(min, max, getLabelNode(dflt),
getLabelNodes(labels)));
}
@Override
- public void visitLookupSwitchInsn(
- final Label dflt,
- final int[] keys,
- final Label[] labels)
- {
- instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
- keys,
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt), keys,
getLabelNodes(labels)));
}
@@ -444,33 +509,89 @@ public class MethodNode extends MethodVisitor
}
@Override
- public void visitTryCatchBlock(
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ // Finds the last real instruction, i.e. the instruction targeted by
+ // this annotation.
+ AbstractInsnNode insn = instructions.getLast();
+ while (insn.getOpcode() == -1) {
+ insn = insn.getPrevious();
+ }
+ // Adds the annotation to this instruction.
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (insn.visibleTypeAnnotations == null) {
+ insn.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.visibleTypeAnnotations.add(an);
+ } else {
+ if (insn.invisibleTypeAnnotations == null) {
+ insn.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ insn.invisibleTypeAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
- getLabelNode(end),
- getLabelNode(handler),
- type));
+ getLabelNode(end), getLabelNode(handler), type));
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get((typeRef & 0x00FFFF00) >> 8);
+ TypeAnnotationNode an = new TypeAnnotationNode(typeRef, typePath, desc);
+ if (visible) {
+ if (tcb.visibleTypeAnnotations == null) {
+ tcb.visibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.visibleTypeAnnotations.add(an);
+ } else {
+ if (tcb.invisibleTypeAnnotations == null) {
+ tcb.invisibleTypeAnnotations = new ArrayList<TypeAnnotationNode>(
+ 1);
+ }
+ tcb.invisibleTypeAnnotations.add(an);
+ }
+ return an;
}
@Override
- public void visitLocalVariable(
- final String name,
- final String desc,
- final String signature,
- final Label start,
- final Label end,
- final int index)
- {
- localVariables.add(new LocalVariableNode(name,
- desc,
- signature,
- getLabelNode(start),
- getLabelNode(end),
- index));
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ localVariables.add(new LocalVariableNode(name, desc, signature,
+ getLabelNode(start), getLabelNode(end), index));
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ LocalVariableAnnotationNode an = new LocalVariableAnnotationNode(
+ typeRef, typePath, getLabelNodes(start), getLabelNodes(end),
+ index, desc);
+ if (visible) {
+ if (visibleLocalVariableAnnotations == null) {
+ visibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ visibleLocalVariableAnnotations.add(an);
+ } else {
+ if (invisibleLocalVariableAnnotations == null) {
+ invisibleLocalVariableAnnotations = new ArrayList<LocalVariableAnnotationNode>(
+ 1);
+ }
+ invisibleLocalVariableAnnotations.add(an);
+ }
+ return an;
}
@Override
@@ -493,13 +614,14 @@ public class MethodNode extends MethodVisitor
* LabelNode if necessary. The default implementation of this method uses
* the {@link Label#info} field to store associations between labels and
* label nodes.
- *
- * @param l a Label.
+ *
+ * @param l
+ * a Label.
* @return the LabelNode corresponding to l.
*/
protected LabelNode getLabelNode(final Label l) {
if (!(l.info instanceof LabelNode)) {
- l.info = new LabelNode(l);
+ l.info = new LabelNode();
}
return (LabelNode) l.info;
}
@@ -533,25 +655,71 @@ public class MethodNode extends MethodVisitor
* version. This methods checks that this node, and all its nodes
* recursively, do not contain elements that were introduced in more recent
* versions of the ASM API than the given version.
- *
- * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ *
+ * @param api
+ * an ASM API version. Must be one of {@link Opcodes#ASM4} or
+ * {@link Opcodes#ASM5}.
*/
public void check(final int api) {
- // nothing to do
+ if (api == Opcodes.ASM4) {
+ if (visibleTypeAnnotations != null
+ && visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleTypeAnnotations != null
+ && invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ int n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
+ for (int i = 0; i < n; ++i) {
+ TryCatchBlockNode tcb = tryCatchBlocks.get(i);
+ if (tcb.visibleTypeAnnotations != null
+ && tcb.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (tcb.invisibleTypeAnnotations != null
+ && tcb.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
+ for (int i = 0; i < instructions.size(); ++i) {
+ AbstractInsnNode insn = instructions.get(i);
+ if (insn.visibleTypeAnnotations != null
+ && insn.visibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn.invisibleTypeAnnotations != null
+ && insn.invisibleTypeAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (insn instanceof MethodInsnNode) {
+ boolean itf = ((MethodInsnNode) insn).itf;
+ if (itf != (insn.opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new RuntimeException();
+ }
+ }
+ }
+ if (visibleLocalVariableAnnotations != null
+ && visibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ if (invisibleLocalVariableAnnotations != null
+ && invisibleLocalVariableAnnotations.size() > 0) {
+ throw new RuntimeException();
+ }
+ }
}
/**
* Makes the given class visitor visit this method.
- *
- * @param cv a class visitor.
+ *
+ * @param cv
+ * a class visitor.
*/
public void accept(final ClassVisitor cv) {
String[] exceptions = new String[this.exceptions.size()];
this.exceptions.toArray(exceptions);
- MethodVisitor mv = cv.visitMethod(access,
- name,
- desc,
- signature,
+ MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
exceptions);
if (mv != null) {
accept(mv);
@@ -560,12 +728,19 @@ public class MethodNode extends MethodVisitor
/**
* Makes the given method visitor visit this method.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- // visits the method attributes
+ // visits the method parameters
int i, j, n;
+ n = parameters == null ? 0 : parameters.size();
+ for (i = 0; i < n; i++) {
+ ParameterNode parameter = parameters.get(i);
+ mv.visitParameter(parameter.name, parameter.access);
+ }
+ // visits the method attributes
if (annotationDefault != null) {
AnnotationVisitor av = mv.visitAnnotationDefault();
AnnotationNode.accept(av, null, annotationDefault);
@@ -583,8 +758,20 @@ public class MethodNode extends MethodVisitor
AnnotationNode an = invisibleAnnotations.get(i);
an.accept(mv.visitAnnotation(an.desc, false));
}
- n = visibleParameterAnnotations == null
- ? 0
+ n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc,
+ false));
+ }
+ n = visibleParameterAnnotations == null ? 0
: visibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = visibleParameterAnnotations[i];
@@ -596,8 +783,7 @@ public class MethodNode extends MethodVisitor
an.accept(mv.visitParameterAnnotation(i, an.desc, true));
}
}
- n = invisibleParameterAnnotations == null
- ? 0
+ n = invisibleParameterAnnotations == null ? 0
: invisibleParameterAnnotations.length;
for (i = 0; i < n; ++i) {
List<?> l = invisibleParameterAnnotations[i];
@@ -622,6 +808,7 @@ public class MethodNode extends MethodVisitor
// visits try catch blocks
n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
for (i = 0; i < n; ++i) {
+ tryCatchBlocks.get(i).updateIndex(i);
tryCatchBlocks.get(i).accept(mv);
}
// visits instructions
@@ -631,6 +818,17 @@ public class MethodNode extends MethodVisitor
for (i = 0; i < n; ++i) {
localVariables.get(i).accept(mv);
}
+ // visits local variable annotations
+ n = visibleLocalVariableAnnotations == null ? 0
+ : visibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ visibleLocalVariableAnnotations.get(i).accept(mv, true);
+ }
+ n = invisibleLocalVariableAnnotations == null ? 0
+ : invisibleLocalVariableAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ invisibleLocalVariableAnnotations.get(i).accept(mv, false);
+ }
// visits maxs
mv.visitMaxs(maxStack, maxLocals);
visited = true;
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
index d27837d..f0d2b6b 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/MultiANewArrayInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.Map;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-import java.util.Map;
-
/**
* A node that represents a MULTIANEWARRAY instruction.
- *
+ *
* @author Eric Bruneton
*/
public class MultiANewArrayInsnNode extends AbstractInsnNode {
@@ -53,9 +53,11 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link MultiANewArrayInsnNode}.
- *
- * @param desc an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
- * @param dims number of dimensions of the array to allocate.
+ *
+ * @param desc
+ * an array type descriptor (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
*/
public MultiANewArrayInsnNode(final String desc, final int dims) {
super(Opcodes.MULTIANEWARRAY);
@@ -71,11 +73,12 @@ public class MultiANewArrayInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitMultiANewArrayInsn(desc, dims);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new MultiANewArrayInsnNode(desc, dims);
+ return new MultiANewArrayInsnNode(desc, dims).cloneAnnotations(this);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
new file mode 100644
index 0000000..d5435de
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/ParameterNode.java
@@ -0,0 +1,76 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
+/**
+ * A node that represents a parameter access and name.
+ *
+ * @author Remi Forax
+ */
+public class ParameterNode {
+ /**
+ * The parameter's name.
+ */
+ public String name;
+
+ /**
+ * The parameter's access flags (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * Valid values are <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> and
+ * <tt>ACC_MANDATED</tt>.
+ */
+ public int access;
+
+ /**
+ * Constructs a new {@link ParameterNode}.
+ *
+ * @param access
+ * The parameter's access flags. Valid values are
+ * <tt>ACC_FINAL</tt>, <tt>ACC_SYNTHETIC</tt> or/and
+ * <tt>ACC_MANDATED</tt> (see {@link org.apache.tapestry5.internal.plastic.asm.Opcodes}).
+ * @param name
+ * the parameter's name.
+ */
+ public ParameterNode(final String name, final int access) {
+ this.name = name;
+ this.access = access;
+ }
+
+ /**
+ * Makes the given visitor visit this parameter declaration.
+ *
+ * @param mv
+ * a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitParameter(name, access);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
index 17ad4ec..e9ef6f2 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TableSwitchInsnNode.java
@@ -29,18 +29,18 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.Label;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-import org.apache.tapestry5.internal.plastic.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.Label;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+
/**
* A node that represents a TABLESWITCH instruction.
- *
+ *
* @author Eric Bruneton
*/
public class TableSwitchInsnNode extends AbstractInsnNode {
@@ -68,19 +68,19 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TableSwitchInsnNode}.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
- * the beginning of the handler block for the <tt>min + i</tt> key.
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
*/
- public TableSwitchInsnNode(
- final int min,
- final int max,
- final LabelNode dflt,
- final LabelNode... labels)
- {
+ public TableSwitchInsnNode(final int min, final int max,
+ final LabelNode dflt, final LabelNode... labels) {
super(Opcodes.TABLESWITCH);
this.min = min;
this.max = max;
@@ -103,13 +103,12 @@ public class TableSwitchInsnNode extends AbstractInsnNode {
labels[i] = this.labels.get(i).getLabel();
}
mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TableSwitchInsnNode(min,
- max,
- clone(dflt, labels),
- clone(this.labels, labels));
+ return new TableSwitchInsnNode(min, max, clone(dflt, labels), clone(
+ this.labels, labels)).cloneAnnotations(this);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
index 52ea45f..a4c8dde 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TryCatchBlockNode.java
@@ -29,11 +29,13 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
+import java.util.List;
+
import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
/**
* A node that represents a try catch block.
- *
+ *
* @author Eric Bruneton
*/
public class TryCatchBlockNode {
@@ -60,21 +62,41 @@ public class TryCatchBlockNode {
public String type;
/**
+ * The runtime visible type annotations on the exception handler type. This
+ * list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label visible
+ */
+ public List<TypeAnnotationNode> visibleTypeAnnotations;
+
+ /**
+ * The runtime invisible type annotations on the exception handler type.
+ * This list is a list of {@link TypeAnnotationNode} objects. May be
+ * <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.TypeAnnotationNode
+ * @label invisible
+ */
+ public List<TypeAnnotationNode> invisibleTypeAnnotations;
+
+ /**
* Constructs a new {@link TryCatchBlockNode}.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the
- * handler, or <tt>null</tt> to catch any exceptions (for "finally"
- * blocks).
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
*/
- public TryCatchBlockNode(
- final LabelNode start,
- final LabelNode end,
- final LabelNode handler,
- final String type)
- {
+ public TryCatchBlockNode(final LabelNode start, final LabelNode end,
+ final LabelNode handler, final String type) {
this.start = start;
this.end = end;
this.handler = handler;
@@ -82,13 +104,50 @@ public class TryCatchBlockNode {
}
/**
+ * Updates the index of this try catch block in the method's list of try
+ * catch block nodes. This index maybe stored in the 'target' field of the
+ * type annotations of this block.
+ *
+ * @param index
+ * the new index of this try catch block in the method's list of
+ * try catch block nodes.
+ */
+ public void updateIndex(final int index) {
+ int newTypeRef = 0x42000000 | (index << 8);
+ if (visibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : visibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ if (invisibleTypeAnnotations != null) {
+ for (TypeAnnotationNode tan : invisibleTypeAnnotations) {
+ tan.typeRef = newTypeRef;
+ }
+ }
+ }
+
+ /**
* Makes the given visitor visit this try catch block.
- *
- * @param mv a method visitor.
+ *
+ * @param mv
+ * a method visitor.
*/
public void accept(final MethodVisitor mv) {
- mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
- ? null
- : handler.getLabel(), type);
+ mv.visitTryCatchBlock(start.getLabel(), end.getLabel(),
+ handler == null ? null : handler.getLabel(), type);
+ int n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = visibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, true));
+ }
+ n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations
+ .size();
+ for (int i = 0; i < n; ++i) {
+ TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
+ an.accept(mv.visitTryCatchAnnotation(an.typeRef, an.typePath,
+ an.desc, false));
+ }
}
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
new file mode 100644
index 0000000..66ec2d3
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeAnnotationNode.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.apache.tapestry5.internal.plastic.asm.tree;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.TypePath;
+import org.apache.tapestry5.internal.plastic.asm.TypeReference;
+
+/**
+ * A node that represents a type annotationn.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeAnnotationNode extends AnnotationNode {
+
+ /**
+ * A reference to the annotated type. See {@link TypeReference}.
+ */
+ public int typeRef;
+
+ /**
+ * The path to the annotated type argument, wildcard bound, array element
+ * type, or static outer type within the referenced type. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ */
+ public TypePath typePath;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #TypeAnnotationNode(int, int, TypePath, String)} version.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @throws IllegalStateException
+ * If a subclass calls this constructor.
+ */
+ public TypeAnnotationNode(final int typeRef, final TypePath typePath,
+ final String desc) {
+ this(Opcodes.ASM5, typeRef, typePath, desc);
+ if (getClass() != TypeAnnotationNode.class) {
+ throw new IllegalStateException();
+ }
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ */
+ public TypeAnnotationNode(final int api, final int typeRef,
+ final TypePath typePath, final String desc) {
+ super(api, desc);
+ this.typeRef = typeRef;
+ this.typePath = typePath;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
index e5bc30e..b4572e5 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/TypeInsnNode.java
@@ -29,14 +29,14 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a type instruction. A type instruction is an
* instruction that takes a type descriptor as parameter.
- *
+ *
* @author Eric Bruneton
*/
public class TypeInsnNode extends AbstractInsnNode {
@@ -49,11 +49,13 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link TypeInsnNode}.
- *
- * @param opcode the opcode of the type instruction to be constructed. This
- * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param desc the operand of the instruction to be constructed. This
- * operand is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
+ *
+ * @param opcode
+ * the opcode of the type instruction to be constructed. This
+ * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param desc
+ * the operand of the instruction to be constructed. This operand
+ * is an internal name (see {@link org.apache.tapestry5.internal.plastic.asm.Type}).
*/
public TypeInsnNode(final int opcode, final String desc) {
super(opcode);
@@ -62,9 +64,10 @@ public class TypeInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be NEW,
- * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -78,10 +81,11 @@ public class TypeInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitTypeInsn(opcode, desc);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new TypeInsnNode(opcode, desc);
+ return new TypeInsnNode(opcode, desc).cloneAnnotations(this);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
index 3819d31..58552de 100644
--- a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/VarInsnNode.java
@@ -1,6 +1,6 @@
/***
* ASM: a very small and fast Java bytecode manipulation framework
-` * Copyright (c) 2000-2011 INRIA, France Telecom
+ * Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,15 +29,15 @@
*/
package org.apache.tapestry5.internal.plastic.asm.tree;
-import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
-
import java.util.Map;
+import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
+
/**
* A node that represents a local variable instruction. A local variable
* instruction is an instruction that loads or stores the value of a local
* variable.
- *
+ *
* @author Eric Bruneton
*/
public class VarInsnNode extends AbstractInsnNode {
@@ -50,12 +50,14 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Constructs a new {@link VarInsnNode}.
- *
- * @param opcode the opcode of the local variable instruction to be
- * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
- * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be constructed. This operand
- * is the index of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be
+ * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be constructed. This operand
+ * is the index of a local variable.
*/
public VarInsnNode(final int opcode, final int var) {
super(opcode);
@@ -64,10 +66,11 @@ public class VarInsnNode extends AbstractInsnNode {
/**
* Sets the opcode of this instruction.
- *
- * @param opcode the new instruction opcode. This opcode must be ILOAD,
- * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
- * or RET.
+ *
+ * @param opcode
+ * the new instruction opcode. This opcode must be ILOAD, LLOAD,
+ * FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or
+ * RET.
*/
public void setOpcode(final int opcode) {
this.opcode = opcode;
@@ -81,10 +84,11 @@ public class VarInsnNode extends AbstractInsnNode {
@Override
public void accept(final MethodVisitor mv) {
mv.visitVarInsn(opcode, var);
+ acceptAnnotations(mv);
}
@Override
public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
- return new VarInsnNode(opcode, var);
+ return new VarInsnNode(opcode, var).cloneAnnotations(this);
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..a78fff4
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry5.internal.plastic.asm.Opcodes;
+import org.apache.tapestry5.internal.plastic.asm.Type;
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.IincInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.InsnList;
+import org.apache.tapestry5.internal.plastic.asm.tree.JumpInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LabelNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.LookupSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.MethodNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TableSwitchInsnNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.TryCatchBlockNode;
+import org.apache.tapestry5.internal.plastic.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ *
+ * @param <V>
+ * type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+ private final Interpreter<V> interpreter;
+
+ private int n;
+
+ private InsnList insns;
+
+ private List<TryCatchBlockNode>[] handlers;
+
+ private Frame<V>[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter
+ * the interpreter to be used to symbolically interpret the
+ * bytecode instructions.
+ */
+ public Analyzer(final Interpreter<V> interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException
+ * if a problem occurs during the analysis.
+ */
+ public Frame<V>[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException {
+ if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = (Frame<V>[]) new Frame<?>[0];
+ return frames;
+ }
+ n = m.instructions.size();
+ insns = m.instructions;
+ handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
+ frames = (Frame<V>[]) new Frame<?>[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+ int begin = insns.indexOf(tcb.start);
+ int end = insns.indexOf(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List<TryCatchBlockNode> insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList<TryCatchBlockNode>();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // computes the subroutine for each instruction:
+ Subroutine main = new Subroutine(null, m.maxLocals, null);
+ List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+ Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+ findSubroutine(0, main, subroutineCalls);
+ while (!subroutineCalls.isEmpty()) {
+ JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+ Subroutine sub = subroutineHeads.get(jsr.label);
+ if (sub == null) {
+ sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+ subroutineHeads.put(jsr.label, sub);
+ findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ } else {
+ sub.callers.add(jsr);
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+ Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+ current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getObjectType(owner);
+ current.setLocal(local++, interpreter.newValue(ctype));
+ }
+ for (int i = 0; i < args.length; ++i) {
+ current.setLocal(local++, interpreter.newValue(args[i]));
+ if (args[i].getSize() == 2) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ }
+ while (local < m.maxLocals) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ merge(0, current, null);
+
+ init(owner, m);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame<V> f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ AbstractInsnNode insnNode = null;
+ try {
+ insnNode = m.instructions.get(insn);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME) {
+ merge(insn + 1, f, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ } else {
+ current.init(f).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : subroutine.copy();
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode j = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ int jump = insns.indexOf(j.label);
+ if (insnOpcode == JSR) {
+ merge(jump, current, new Subroutine(j.label,
+ m.maxLocals, j));
+ } else {
+ merge(jump, current, subroutine);
+ }
+ newControlFlowEdge(insn, jump);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(lsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ LabelNode label = lsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(tsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ LabelNode label = tsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException(insnNode,
+ "RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ int call = insns.indexOf(caller);
+ if (frames[call] != null) {
+ merge(call + 1, frames[call], current,
+ subroutines[call], subroutine.access);
+ newControlFlowEdge(insn, call + 1);
+ }
+ }
+ } else if (insnOpcode != ATHROW
+ && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ if (insnOpcode == LLOAD || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE) {
+ subroutine.access[var + 1] = true;
+ }
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ }
+ }
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ }
+
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getObjectType("java/lang/Throwable");
+ } else {
+ type = Type.getObjectType(tcb.type);
+ }
+ int jump = insns.indexOf(tcb.handler);
+ if (newControlFlowExceptionEdge(insn, tcb)) {
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(jump, handler, subroutine);
+ }
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException(e.node, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw new AnalyzerException(insnNode, "Error at instruction "
+ + insn + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ private void findSubroutine(int insn, final Subroutine sub,
+ final List<AbstractInsnNode> calls) throws AnalyzerException {
+ while (true) {
+ if (insn < 0 || insn >= n) {
+ throw new AnalyzerException(null,
+ "Execution can fall off end of the code");
+ }
+ if (subroutines[insn] != null) {
+ return;
+ }
+ subroutines[insn] = sub.copy();
+ AbstractInsnNode node = insns.get(insn);
+
+ // calls findSubroutine recursively on normal successors
+ if (node instanceof JumpInsnNode) {
+ if (node.getOpcode() == JSR) {
+ // do not follow a JSR, it leads to another subroutine!
+ calls.add(node);
+ } else {
+ JumpInsnNode jnode = (JumpInsnNode) node;
+ findSubroutine(insns.indexOf(jnode.label), sub, calls);
+ }
+ } else if (node instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+ for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = tsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ } else if (node instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+ for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = lsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ }
+
+ // calls findSubroutine recursively on exception handler successors
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+ }
+ }
+
+ // if insn does not falls through to the next instruction, return.
+ switch (node.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ return;
+ }
+ insn++;
+ }
+ }
+
+ /**
+ * Returns the symbolic stack frame for each instruction of the last
+ * recently analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if the corresponding instruction
+ * cannot be reached, or if an error occured during the analysis of
+ * the method.
+ */
+ public Frame<V>[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insn
+ * the index of an instruction of the last recently analyzed
+ * method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List<TryCatchBlockNode> getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * Initializes this analyzer. This method is called just before the
+ * execution of control flow analysis loop in #analyze. The default
+ * implementation of this method does nothing.
+ *
+ * @param owner
+ * the internal name of the class to which the method belongs.
+ * @param m
+ * the method to be analyzed.
+ * @throws AnalyzerException
+ * if a problem occurs.
+ */
+ protected void init(String owner, MethodNode m) throws AnalyzerException {
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals
+ * the maximum number of local variables of the frame.
+ * @param nStack
+ * the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final int nLocals, final int nStack) {
+ return new Frame<V>(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src
+ * a frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final Frame<? extends V> src) {
+ return new Frame<V>(src);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this
+ * method does nothing. It can be overriden in order to construct the
+ * control flow graph of a method (this method is called by the
+ * {@link #analyze analyze} method during its visit of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insn, final int successor) {
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method does nothing. It can be
+ * overridden in order to construct the control flow graph of a method (this
+ * method is called by the {@link #analyze analyze} method during its visit
+ * of the method's code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param successor
+ * index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method always returns true.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final int successor) {
+ return true;
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+ * construct the control flow graph of a method (this method is called by
+ * the {@link #analyze analyze} method during its visit of the method's
+ * code).
+ *
+ * @param insn
+ * an instruction index.
+ * @param tcb
+ * TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(final int insn,
+ final TryCatchBlockNode tcb) {
+ return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(final int insn, final Frame<V> frame,
+ final Subroutine subroutine) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(frame, interpreter);
+ }
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(final int insn, final Frame<V> beforeJSR,
+ final Frame<V> afterRET, final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(afterRET, interpreter);
+ }
+
+ if (oldSubroutine != null && subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR);
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/a0ac605d/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
----------------------------------------------------------------------
diff --git a/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..66c9df9
--- /dev/null
+++ b/plastic/src/external/java/org/apache/tapestry5/internal/plastic/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,61 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 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.apache.tapestry5.internal.plastic.asm.tree.analysis;
+
+import org.apache.tapestry5.internal.plastic.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public final AbstractInsnNode node;
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg) {
+ super(msg);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Throwable exception) {
+ super(msg, exception);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg,
+ final Object expected, final Value encountered) {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ this.node = node;
+ }
+}