|
From: <ls...@us...> - 2007-01-07 13:45:47
|
Revision: 3032
http://jnode.svn.sourceforge.net/jnode/?rev=3032&view=rev
Author: lsantha
Date: 2007-01-07 05:45:46 -0800 (Sun, 07 Jan 2007)
Log Message:
-----------
Classpath patches.
Added Paths:
-----------
trunk/core/src/classpath/org/org/objectweb/asm/tree/
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Frame.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/IntMap.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Interpreter.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/SimpleVerifier.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/SmallSet.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Subroutine.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Value.java
trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/package.html
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/Analyzer.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,416 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.IincInsnNode;
+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.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer.
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer implements Opcodes {
+
+ private Interpreter interpreter;
+
+ private int n;
+
+ private IntMap indexes;
+
+ private List[] handlers;
+
+ private Frame[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ private boolean jsr;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter the interpreter to be used to symbolically interpret
+ * the bytecode instructions.
+ */
+ public Analyzer(final Interpreter 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[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException
+ {
+ n = m.instructions.size();
+ indexes = new IntMap(2 * n);
+ handlers = new List[n];
+ frames = new Frame[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes instruction indexes
+ for (int i = 0; i < n; ++i) {
+ Object insn = m.instructions.get(i);
+ if (insn instanceof LabelNode) {
+ insn = ((LabelNode) insn).label;
+ }
+ indexes.put(insn, i);
+ }
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = (TryCatchBlockNode) m.tryCatchBlocks.get(i);
+ int begin = indexes.get(tcb.start);
+ int end = indexes.get(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ // algorithm
+ Frame current = newFrame(m.maxLocals, m.maxStack);
+ Frame handler = newFrame(m.maxLocals, m.maxStack);
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getType("L" + 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);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ try {
+ Object o = m.instructions.get(insn);
+ jsr = false;
+
+ if (o instanceof LabelNode) {
+ merge(insn + 1, f, subroutine);
+ } else {
+ AbstractInsnNode insnNode = (AbstractInsnNode) o;
+ int insnOpcode = insnNode.getOpcode();
+
+ 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);
+ }
+ if (insnOpcode == JSR) {
+ jsr = true;
+ merge(indexes.get(j.label),
+ current,
+ new Subroutine(j.label, m.maxLocals, j));
+ } else {
+ merge(indexes.get(j.label), current, subroutine);
+ }
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ merge(indexes.get(lsi.dflt), current, subroutine);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ Label label = (Label) lsi.labels.get(j);
+ merge(indexes.get(label), current, subroutine);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ merge(indexes.get(tsi.dflt), current, subroutine);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ Label label = (Label) tsi.labels.get(j);
+ merge(indexes.get(label), current, subroutine);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException("RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ int caller = indexes.get(subroutine.callers.get(i));
+ merge(caller + 1,
+ frames[caller],
+ current,
+ subroutines[caller],
+ subroutine.access);
+ }
+ } 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);
+ }
+ }
+
+ List insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getType("Ljava/lang/Throwable;");
+ } else {
+ type = Type.getType("L" + tcb.type + ";");
+ }
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(indexes.get(tcb.handler), handler, subroutine);
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException("Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ } catch(Exception e) {
+ throw new AnalyzerException("Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ /**
+ * 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[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the index of the given instruction.
+ *
+ * @param insn a {@link Label} or {@link AbstractInsnNode} of the last
+ * recently analyzed method.
+ * @return the index of the given instruction of the last recently analyzed
+ * method.
+ */
+ public int getIndex(final Object insn) {
+ return indexes.get(insn);
+ }
+
+ /**
+ * 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 getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * 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 newFrame(final int nLocals, final int nStack) {
+ return new Frame(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src a frame.
+ * @return the created frame.
+ */
+ protected Frame newFrame(final Frame src) {
+ return new Frame(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 frame the frame corresponding to an instruction.
+ * @param successor the frame corresponding to a successor instruction.
+ */
+ protected void newControlFlowEdge(final Frame frame, final Frame successor)
+ {
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(
+ final int insn,
+ final Frame frame,
+ final Subroutine subroutine) throws AnalyzerException
+ {
+ if (insn > n - 1) {
+ throw new AnalyzerException("Execution can fall off end of the code");
+ }
+
+ Frame oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes = false;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes |= oldFrame.merge(frame, interpreter);
+ }
+
+ newControlFlowEdge(frame, oldFrame);
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine, !jsr);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(
+ final int insn,
+ final Frame beforeJSR,
+ final Frame afterRET,
+ final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException
+ {
+ if (insn > n - 1) {
+ throw new AnalyzerException("Execution can fall off end of the code");
+ }
+
+ Frame oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes = false;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes |= oldFrame.merge(afterRET, access);
+ }
+
+ newControlFlowEdge(afterRET, oldFrame);
+
+ if (oldSubroutine == null) {
+ if (subroutineBeforeJSR != null) {
+ subroutines[insn] = subroutineBeforeJSR.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR, !jsr);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/AnalyzerException.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,56 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public AnalyzerException(final String msg) {
+ super(msg);
+ }
+
+ public AnalyzerException(final String msg, final Throwable exception) {
+ super(msg, exception);
+ }
+
+ public AnalyzerException(
+ final String msg,
+ final Object expected,
+ final Value encountered)
+ {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ }
+}
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicInterpreter.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,335 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.IntInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.objectweb.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter implements Opcodes, Interpreter {
+
+ public Value newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ }
+
+ public Value newOperation(final AbstractInsnNode insn) {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(Type.getType("Lnull;"));
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ if (cst instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (cst instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (cst instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (cst instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (cst instanceof Type) {
+ return newValue(Type.getType("Ljava/lang/Class;"));
+ } else {
+ return newValue(Type.getType(cst.getClass()));
+ }
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getType("L" + ((TypeInsnNode) insn).desc
+ + ";"));
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ }
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ return value;
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ throw new AnalyzerException("Invalid array type");
+ }
+ case ANEWARRAY:
+ String desc = ((TypeInsnNode) insn).desc;
+ if (desc.charAt(0) == '[') {
+ return newValue(Type.getType("[" + desc));
+ } else {
+ return newValue(Type.getType("[L" + desc + ";"));
+ }
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ desc = ((TypeInsnNode) insn).desc;
+ if (desc.charAt(0) == '[') {
+ return newValue(Type.getType(desc));
+ } else {
+ return newValue(Type.getType("L" + desc + ";"));
+ }
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2) throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ Type t = ((BasicValue) value1).getType();
+ if (t != null && t.getSort() == Type.ARRAY) {
+ return newValue(t.getElementType());
+ } else {
+ return BasicValue.REFERENCE_VALUE;
+ }
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
+ return null;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3) throws AnalyzerException
+ {
+ return null;
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values)
+ throws AnalyzerException
+ {
+ if (insn.getOpcode() == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+ }
+ }
+
+ public Value merge(final Value v, final Value w) {
+ if (!v.equals(w)) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+}
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicValue.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,105 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+import org.objectweb.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type sytem.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ *
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+ public final static Value UNINITIALIZED_VALUE = new BasicValue(null);
+
+ public final static Value INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ public final static Value FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ public final static Value LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ public final static Value DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);
+
+ public final static Value REFERENCE_VALUE = new BasicValue(Type.getType("Ljava/lang/Object;"));
+
+ public final static Value RETURNADDRESS_VALUE = new BasicValue(null);
+
+ private Type type;
+
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ public boolean isReference() {
+ return type != null
+ && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/BasicVerifier.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,428 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+import java.util.List;
+
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return value;
+ case ASTORE:
+ if (!((BasicValue) value).isReference()
+ && value != BasicValue.RETURNADDRESS_VALUE)
+ {
+ throw new AnalyzerException(null,
+ "an object reference or a return address",
+ value);
+ }
+ return value;
+ default:
+ return value;
+ }
+ // type is necessarily a primitive type here,
+ // so value must be == to expected value
+ if (value != expected) {
+ throw new AnalyzerException(null, expected, value);
+ }
+ return value;
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, Value value)
+ throws AnalyzerException
+ {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type.getType("L"
+ + ((FieldInsnNode) insn).owner + ";"));
+ break;
+ case CHECKCAST:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(null,
+ "an array reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(null, expected, value);
+ }
+ return super.unaryOperation(insn, value);
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2) throws AnalyzerException
+ {
+ Value expected1;
+ Value expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[B"));
+ } else {
+ expected1 = newValue(Type.getType("[Z"));
+ }
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fin = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getType("L" + fin.owner + ";"));
+ expected2 = newValue(Type.getType(fin.desc));
+ break;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException("First argument", expected1, value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException("Second argument", expected2, value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
+ }
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3) throws AnalyzerException
+ {
+ Value expected1;
+ Value expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (!isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[B"));
+ } else {
+ expected1 = newValue(Type.getType("[Z"));
+ }
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new RuntimeException("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException("First argument", "a " + expected1
+ + " array reference", value1);
+ } else if (value2 != BasicValue.INT_VALUE) {
+ throw new AnalyzerException("Second argument",
+ BasicValue.INT_VALUE,
+ value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException("Third argument", expected3, value3);
+ }
+ return null;
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values)
+ throws AnalyzerException
+ {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (int i = 0; i < values.size(); ++i) {
+ if (values.get(i) != BasicValue.INT_VALUE) {
+ throw new AnalyzerException(null,
+ BasicValue.INT_VALUE,
+ (Value) values.get(i));
+ }
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC) {
+ String own = ((MethodInsnNode) insn).owner;
+ if (own.charAt(0) != '[') { // can happen with JDK1.5 clone()
+ own = "L" + own + ";";
+ }
+ Type owner = Type.getType(own);
+ if (!isSubTypeOf((Value) values.get(i++), newValue(owner))) {
+ throw new AnalyzerException("Method owner",
+ newValue(owner),
+ (Value) values.get(0));
+ }
+ }
+ Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc);
+ while (i < values.size()) {
+ Value expected = newValue(args[j++]);
+ Value encountered = (Value) values.get(i++);
+ if (!isSubTypeOf(encountered, expected)) {
+ throw new AnalyzerException("Argument " + j,
+ expected,
+ encountered);
+ }
+ }
+ }
+ return super.naryOperation(insn, values);
+ }
+
+ protected boolean isArrayValue(final Value value) {
+ return ((BasicValue) value).isReference();
+ }
+
+ protected Value getElementValue(final Value objectArrayValue)
+ throws AnalyzerException
+ {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ protected boolean isSubTypeOf(final Value value, final Value expected) {
+ return value == expected;
+ }
+}
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowInterpreter.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,174 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 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.tree.analysis;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.FieldInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link DataflowValue} values.
+ *
+ * @author Eric Bruneton
+ */
+public class DataflowInterpreter implements Opcodes, Interpreter {
+
+ public Value newValue(final Type type) {
+ return new DataflowValue(type == null ? 1 : type.getSize());
+ }
+
+ public Value newOperation(final AbstractInsnNode insn) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ size = 2;
+ break;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+ break;
+ case GETSTATIC:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new DataflowValue(size, insn);
+ }
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value) {
+ return new DataflowValue(value.getSize(), insn);
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LNEG:
+ case DNEG:
+ case I2L:
+ case I2D:
+ case L2D:
+ case F2L:
+ case F2D:
+ case D2L:
+ size = 2;
+ break;
+ case GETFIELD:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new DataflowValue(size, insn);
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LALOAD:
+ case DALOAD:
+ case LADD:
+ case DADD:
+ case LSUB:
+ case DSUB:
+ case LMUL:
+ case DMUL:
+ case LDIV:
+ case DDIV:
+ case LREM:
+ case DREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ size = 2;
+ break;
+ default:
+ size = 1;
+ }
+ return new DataflowValue(size, insn);
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3)
+ {
+ return new DataflowValue(1, insn);
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values) {
+ int size;
+ if (insn.getOpcode() == MULTIANEWARRAY) {
+ size = 1;
+ } else {
+ size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
+ }
+ return new DataflowValue(size, insn);
+ }
+
+ public Value merge(final Value v, final Value w) {
+ DataflowValue dv = (DataflowValue) v;
+ DataflowValue dw = (DataflowValue) w;
+ if (dv.insns instanceof SmallSet && dw.insns instanceof SmallSet) {
+ Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns);
+ if (s == dv.insns && dv.size == dw.size) {
+ return v;
+ } else {
+ return new DataflowValue(Math.min(dv.size, dw.size), s);
+ }
+ }
+ if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) {
+ Set s = new HashSet();
+ s.addAll(dv.insns);
+ s.addAll(dw.insns);
+ return new DataflowValue(Math.min(dv.size, dw.size), s);
+ }
+ return v;
+ }
+}
Added: trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java
===================================================================
--- trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java (rev 0)
+++ trunk/core/src/classpath/org/org/objectweb/asm/tree/analysis/DataflowValue.java 2007-01-07 13:45:46 UTC (rev 3032)
@@ -0,0 +1,92 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * ...
[truncated message content] |