You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2012/09/28 18:30:22 UTC

svn commit: r1391523 - in /commons/sandbox/nabla/trunk: ./ src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/

Author: luc
Date: Fri Sep 28 16:30:21 2012
New Revision: 1391523

URL: http://svn.apache.org/viewvc?rev=1391523&view=rev
Log:
Updated to asm 4.0.

Modified:
    commons/sandbox/nabla/trunk/pom.xml
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/ForwardModeClassDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/MethodDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingInterpreter.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingValue.java

Modified: commons/sandbox/nabla/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/pom.xml?rev=1391523&r1=1391522&r2=1391523&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/pom.xml (original)
+++ commons/sandbox/nabla/trunk/pom.xml Fri Sep 28 16:30:21 2012
@@ -80,25 +80,38 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>asm</groupId>
+            <!-- we need the debug version at compile time because the non-debug versions
+                 do not contain generics information, so they fail compiling Nabla
+                 TrackingInterpreter which extends Interpreter<V extends Value> -->
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm-debug-all</artifactId>
+            <version>4.0</version>
+            <scope>provided</scope>
+            </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
             <artifactId>asm-analysis</artifactId>
-            <version>3.3.1</version>
-        </dependency>
+            <version>4.0</version>
+            <scope>runtime</scope>
+            </dependency>
         <dependency>
-            <groupId>asm</groupId>
+            <groupId>org.ow2.asm</groupId>
             <artifactId>asm-tree</artifactId>
-            <version>3.3.1</version>
-        </dependency>
+            <version>4.0</version>
+            <scope>runtime</scope>
+            </dependency>
         <dependency>
-            <groupId>asm</groupId>
+            <groupId>org.ow2.asm</groupId>
             <artifactId>asm-util</artifactId>
-            <version>3.3.1</version>
-        </dependency>
+            <version>4.0</version>
+            <scope>runtime</scope>
+            </dependency>
         <dependency>
-            <groupId>asm</groupId>
+            <groupId>org.ow2.asm</groupId>
             <artifactId>asm</artifactId>
-            <version>3.3.1</version>
-        </dependency>
+            <version>4.0</version>
+            <scope>runtime</scope>
+            </dependency>
     </dependencies>
 
     <build>

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/ForwardModeClassDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/ForwardModeClassDifferentiator.java?rev=1391523&r1=1391522&r2=1391523&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/ForwardModeClassDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/ForwardModeClassDifferentiator.java Fri Sep 28 16:30:21 2012
@@ -19,7 +19,6 @@ package org.apache.commons.nabla.algorit
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Field;
-import java.util.List;
 import java.util.Set;
 
 import org.apache.commons.nabla.core.DifferentiationException;
@@ -75,7 +74,6 @@ public class ForwardModeClassDifferentia
      * @exception DifferentiationException if class cannot be differentiated
      * @throws IOException if class cannot be read
      */
-    @SuppressWarnings("unchecked")
     public ForwardModeClassDifferentiator(Class<? extends UnivariateDifferentiable> primitiveClass,
                                           final Set<String> mathClasses)
         throws DifferentiationException, IOException {
@@ -85,15 +83,15 @@ public class ForwardModeClassDifferentia
         final String classResourceName = "/" + primitiveClass.getName().replace('.', '/') + ".class";
         final InputStream stream = primitiveClass.getResourceAsStream(classResourceName);
         final ClassReader reader = new ClassReader(stream);
-        primitiveNode = new ClassNode();
+        primitiveNode = new ClassNode(Opcodes.ASM4);
         reader.accept(primitiveNode, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
         this.mathClasses = mathClasses;
-        classNode = new ClassNode();
+        classNode = new ClassNode(Opcodes.ASM4);
 
         // check the UnivariateDifferentiable interface is implemented
         final Class<UnivariateDifferentiable> uDerClass = UnivariateDifferentiable.class;
         boolean isDifferentiable = false;
-        for (String interf : (List<String>) primitiveNode.interfaces) {
+        for (String interf : primitiveNode.interfaces) {
             final String interfName = interf.replace('/', '.');
             Class<?> interfClass = null;
             try {
@@ -138,12 +136,11 @@ public class ForwardModeClassDifferentia
      * @param derivativeDesc descriptor of the method in the derivative class
      * @exception DifferentiationException if method cannot be differentiated
      */
-    @SuppressWarnings("unchecked")
     public void differentiateMethod(final String name, final String primitiveDesc,
                                     final String derivativeDesc)
         throws DifferentiationException {
 
-        for (final MethodNode method : (List<MethodNode>) primitiveNode.methods) {
+        for (final MethodNode method : primitiveNode.methods) {
             if (method.name.equals(name) && method.desc.equals(primitiveDesc)) {
 
                 final MethodDifferentiator differentiator =
@@ -165,7 +162,6 @@ public class ForwardModeClassDifferentia
 
     /** Add the primitive field.
      */
-    @SuppressWarnings("unchecked")
     private void addPrimitiveField() {
         FieldNode primitiveField =
             new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
@@ -175,7 +171,6 @@ public class ForwardModeClassDifferentia
 
     /** Add the class constructor.
      */
-    @SuppressWarnings("unchecked")
     private void addConstructor() {
         final String init = "<init>";
         final MethodNode constructor =
@@ -193,7 +188,6 @@ public class ForwardModeClassDifferentia
 
     /** Add the {@link UnivariateDerivative#getPrimitive() getPrimitive()} method.
      */
-    @SuppressWarnings("unchecked")
     private void addGetPrimitiveMethod() {
         final MethodNode method =
             new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, "getPrimitive",
@@ -207,7 +201,6 @@ public class ForwardModeClassDifferentia
 
     /** Add the getPrimitiveField method.
      */
-    @SuppressWarnings("unchecked")
     private void addGetPrimitiveFieldMethod() {
         final MethodNode method =
             new MethodNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, "getPrimitiveField",

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/MethodDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/MethodDifferentiator.java?rev=1391523&r1=1391522&r2=1391523&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/MethodDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/MethodDifferentiator.java Fri Sep 28 16:30:21 2012
@@ -104,7 +104,6 @@ import org.objectweb.asm.tree.TypeInsnNo
 import org.objectweb.asm.tree.VarInsnNode;
 import org.objectweb.asm.tree.analysis.Analyzer;
 import org.objectweb.asm.tree.analysis.AnalyzerException;
-import org.objectweb.asm.tree.analysis.BasicValue;
 import org.objectweb.asm.tree.analysis.Frame;
 import org.objectweb.asm.tree.analysis.Interpreter;
 
@@ -167,7 +166,7 @@ public class MethodDifferentiator {
     private final Set<TrackingValue> converted;
 
     /** Frames for the original method. */
-    private final Map<AbstractInsnNode, Frame> frames;
+    private final Map<AbstractInsnNode, Frame<TrackingValue>> frames;
 
     /** Instructions successors array. */
     private final Map<AbstractInsnNode, Set<AbstractInsnNode>> successors;
@@ -184,7 +183,7 @@ public class MethodDifferentiator {
         this.mathClasses     = mathClasses;
         this.name            = name;
         this.converted       = new HashSet<TrackingValue>();
-        this.frames          = new IdentityHashMap<AbstractInsnNode, Frame>();
+        this.frames          = new IdentityHashMap<AbstractInsnNode, Frame<TrackingValue>>();
         this.successors      = new IdentityHashMap<AbstractInsnNode, Set<AbstractInsnNode>>();
         this.clonedLabels    = new HashMap<LabelNode, LabelNode>();
     }
@@ -211,7 +210,7 @@ public class MethodDifferentiator {
             // analyze the original code, tracing values production/consumption
             final FlowAnalyzer analyzer =
                 new FlowAnalyzer(new TrackingInterpreter(), method.instructions);
-            final Frame[] array = analyzer.analyze(primitiveName, method);
+            final Frame<TrackingValue>[] array = analyzer.analyze(primitiveName, method);
 
             // convert the array into a map, since code changes will shift all indices
             for (int i = 0; i < array.length; ++i) {
@@ -225,8 +224,8 @@ public class MethodDifferentiator {
 
                 // the method does not depend on the parameter at all!
                 // we replace all "return d;" by "return DifferentialPair.newConstant(d);"
-                for (final Iterator<?> i = method.instructions.iterator(); i.hasNext();) {
-                    final AbstractInsnNode insn = (AbstractInsnNode) i.next();
+                for (final Iterator<AbstractInsnNode> i = method.instructions.iterator(); i.hasNext();) {
+                    final AbstractInsnNode insn = i.next();
                     if (insn.getOpcode() == Opcodes.DRETURN) {
                         final InsnList list = new InsnList();
                         list.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
@@ -286,8 +285,8 @@ public class MethodDifferentiator {
      */
     private void addSpareLocalVariables(final InsnList instructions)
         throws DifferentiationException {
-        for (final Iterator<?> i = instructions.iterator(); i.hasNext();) {
-            final AbstractInsnNode insn = (AbstractInsnNode) i.next();
+        for (final Iterator<AbstractInsnNode> i = instructions.iterator(); i.hasNext();) {
+            final AbstractInsnNode insn = i.next();
             if (insn.getType() == AbstractInsnNode.VAR_INSN) {
                 final VarInsnNode varInsn = (VarInsnNode) insn;
                 if (varInsn.var > 2) {
@@ -316,8 +315,8 @@ public class MethodDifferentiator {
      * @see #addSpareLocalVariables()
      */
     private void removeUnusedSpareLocalVariables(final InsnList instructions) {
-        for (final Iterator<?> i = instructions.iterator(); i.hasNext();) {
-            final AbstractInsnNode insn = (AbstractInsnNode) i.next();
+        for (final Iterator<AbstractInsnNode> i = instructions.iterator(); i.hasNext();) {
+            final AbstractInsnNode insn = i.next();
             if (insn.getType() == AbstractInsnNode.VAR_INSN) {
                 shiftVariable((VarInsnNode) insn);
             }
@@ -346,7 +345,7 @@ public class MethodDifferentiator {
 
         // start by converting the parameter of the method,
         // which is kept in local variable 1 of the initial frame
-        final TrackingValue dpParameter = (TrackingValue) frames.get(instructions.get(0)).getLocal(1);
+        final TrackingValue dpParameter = frames.get(instructions.get(0)).getLocal(1);
         pending.add(dpParameter);
 
         // propagate the values conversions throughout the method
@@ -384,10 +383,9 @@ public class MethodDifferentiator {
 
         // the various GETFIELD/PUTFIELD instructions must also be changed
         // to retrieve the field from the outer class
-        @SuppressWarnings("unchecked")
-        ListIterator<AbstractInsnNode> iterator = (ListIterator<AbstractInsnNode>) instructions.iterator();
+        ListIterator<AbstractInsnNode> iterator = instructions.iterator();
         while (iterator.hasNext()) {
-            AbstractInsnNode ins = (AbstractInsnNode) iterator.next();
+            AbstractInsnNode ins = iterator.next();
             if ((ins.getOpcode() == Opcodes.GETFIELD) || (ins.getOpcode() == Opcodes.PUTFIELD)) {
                 changes.add(ins);
             }
@@ -406,7 +404,7 @@ public class MethodDifferentiator {
         final List<TrackingValue> values = new ArrayList<TrackingValue>();
 
         // get the frame before instruction execution
-        final Frame before = frames.get(instruction);
+        final Frame<TrackingValue> before = frames.get(instruction);
         final int beforeStackSize = before.getStackSize();
         final int locals = before.getLocals();
 
@@ -417,13 +415,13 @@ public class MethodDifferentiator {
 
             // loop over the successors of this instruction
             for (final AbstractInsnNode successor : set) {
-                final Frame produced = frames.get(successor);
+                final Frame<TrackingValue> produced = frames.get(successor);
 
                 // check the stack cells
                 for (int i = 0; i < produced.getStackSize(); ++i) {
-                    final TrackingValue value = (TrackingValue) produced.getStack(i);
+                    final TrackingValue value = produced.getStack(i);
                     if (((i >= beforeStackSize) || (value != before.getStack(i))) &&
-                        value.getValue().equals(BasicValue.DOUBLE_VALUE) &&
+                        value.getType().equals(Type.DOUBLE_TYPE) &&
                         !converted.contains(value)) {
                         values.add(value);
                     }
@@ -433,7 +431,7 @@ public class MethodDifferentiator {
                 for (int i = 0; i < locals; ++i) {
                     final TrackingValue value = (TrackingValue) produced.getLocal(i);
                     if ((value != before.getLocal(i)) &&
-                        value.getValue().equals(BasicValue.DOUBLE_VALUE) &&
+                        value.getType().equals(Type.DOUBLE_TYPE) &&
                         !converted.contains(value)) {
                         values.add(value);
                     }
@@ -484,7 +482,7 @@ public class MethodDifferentiator {
         throws DifferentiationException {
 
         // get the frame at the start of the instruction
-        final Frame frame = frames.get(insn);
+        final Frame<TrackingValue> frame = frames.get(insn);
         final int size = frame.getStackSize();
         final boolean stack1Converted = (size > 0) && converted.contains(frame.getStack(size - 2));
         final boolean stack0Converted = (size > 1) && converted.contains(frame.getStack(size - 1));
@@ -602,6 +600,9 @@ public class MethodDifferentiator {
         case Opcodes.INVOKEINTERFACE :
             // TODO add support for INVOKEINTERFACE differentiation
             throw new RuntimeException("INVOKEINTERFACE not handled yet");
+        case Opcodes.INVOKEDYNAMIC :
+            // TODO add support for INVOKEDYNAMIC differentiation
+            throw new RuntimeException("INVOKEDYNAMIC not handled yet");
         case Opcodes.NEWARRAY :
             // TODO add support for NEWARRAY differentiation
             throw new RuntimeException("NEWARRAY not handled yet");
@@ -679,7 +680,8 @@ public class MethodDifferentiator {
         }
         list.add(new TypeInsnNode(Opcodes.CHECKCAST, boxedType.getInternalName()));
         if (valueMethodName != null) {
-            list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, boxedType.getInternalName(), valueMethodName,
+            list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, boxedType.getInternalName(),
+                                        valueMethodName,
                                         Type.getMethodDescriptor(type, new Type[0])));
         }
 
@@ -830,7 +832,7 @@ public class MethodDifferentiator {
     }
 
     /** Analyzer preserving instructions successors information. */
-    private class FlowAnalyzer extends Analyzer {
+    private class FlowAnalyzer extends Analyzer<TrackingValue> {
 
         /** Instructions of the method. */
         private final InsnList instructions;
@@ -839,7 +841,7 @@ public class MethodDifferentiator {
          * @param interpreter associated interpreter
          * @param instructions instructions of the method
          */
-        public FlowAnalyzer(final Interpreter interpreter,
+        public FlowAnalyzer(final Interpreter<TrackingValue> interpreter,
                             final InsnList instructions) {
             super(interpreter);
             this.instructions = instructions;

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingInterpreter.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingInterpreter.java?rev=1391523&r1=1391522&r2=1391523&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingInterpreter.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingInterpreter.java Fri Sep 28 16:30:21 2012
@@ -19,130 +19,345 @@ package org.apache.commons.nabla.algorit
 import java.util.Iterator;
 import java.util.List;
 
+import org.objectweb.asm.Handle;
+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.InvokeDynamicInsnNode;
+import org.objectweb.asm.tree.LdcInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MultiANewArrayInsnNode;
+import org.objectweb.asm.tree.TypeInsnNode;
 import org.objectweb.asm.tree.analysis.AnalyzerException;
-import org.objectweb.asm.tree.analysis.BasicInterpreter;
-import org.objectweb.asm.tree.analysis.BasicValue;
-import org.objectweb.asm.tree.analysis.Value;
+import org.objectweb.asm.tree.analysis.Interpreter;
 
 /** An interpreter tracking which instructions use which values.
- * <p>This interpreter wraps {@link org.objectweb.asm.tree.analysis.BasicValue
- * BasicValue} instances into {@link TrackingValue TrackingValue} instances.</p>
+ * <p>
+ * The implementation of this class is largely copied from the original BasicInterpreter from asm,
+ * which is distributed under the following terms:
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * @see TrackingValue
  */
-public class TrackingInterpreter extends BasicInterpreter {
+public class TrackingInterpreter extends Interpreter<TrackingValue> {
 
     /** Build an interpreter.
      */
     public TrackingInterpreter() {
+        super(Opcodes.ASM4);
     }
 
     /** {@inheritDoc} */
     @Override
-    public Value newValue(final Type type) {
-        return (type == null) ? TrackingValue.UNINITIALIZED_VALUE : wrap(super.newValue(type), null);
+    public TrackingValue newValue(final Type type) {
+        return (type == null) ? TrackingValue.UNINITIALIZED_VALUE : new TrackingValue(type);
     }
 
-    /** {@inheritDoc} */
+    /** {@inheritDoc}
+     * <p>
+     * The implementation for this meth
+     */
     @Override
-    public Value newOperation(final AbstractInsnNode insn) throws AnalyzerException {
-        return wrap(super.newOperation(insn), insn);
+    public TrackingValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
+        switch (insn.getOpcode()) {
+            case Opcodes.ACONST_NULL:
+                return new TrackingValue(Type.getObjectType("null"), insn);
+            case Opcodes.ICONST_M1:
+            case Opcodes.ICONST_0:
+            case Opcodes.ICONST_1:
+            case Opcodes.ICONST_2:
+            case Opcodes.ICONST_3:
+            case Opcodes.ICONST_4:
+            case Opcodes.ICONST_5:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.LCONST_0:
+            case Opcodes.LCONST_1:
+                return new TrackingValue(Type.LONG_TYPE, insn);
+            case Opcodes.FCONST_0:
+            case Opcodes.FCONST_1:
+            case Opcodes.FCONST_2:
+                return new TrackingValue(Type.FLOAT_TYPE, insn);
+            case Opcodes.DCONST_0:
+            case Opcodes.DCONST_1:
+                return new TrackingValue(Type.DOUBLE_TYPE, insn);
+            case Opcodes.BIPUSH:
+            case Opcodes.SIPUSH:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.LDC:
+                Object cst = ((LdcInsnNode) insn).cst;
+                if (cst instanceof Integer) {
+                    return new TrackingValue(Type.INT_TYPE, insn);
+                } else if (cst instanceof Float) {
+                    return new TrackingValue(Type.FLOAT_TYPE, insn);
+                } else if (cst instanceof Long) {
+                    return new TrackingValue(Type.LONG_TYPE, insn);
+                } else if (cst instanceof Double) {
+                    return new TrackingValue(Type.DOUBLE_TYPE, insn);
+                } else if (cst instanceof String) {
+                    return new TrackingValue(Type.getType(String.class), insn);
+                } else if (cst instanceof Type) {
+                    int sort = ((Type) cst).getSort();
+                    if (sort == Type.OBJECT || sort == Type.ARRAY) {
+                        return new TrackingValue(Type.getType(Class.class), insn);
+                    } else if (sort == Type.METHOD) {
+                        return new TrackingValue(Type.getObjectType("java/lang/invoke/MethodType"), insn);
+                    } else {
+                        throw new IllegalArgumentException("Illegal LDC constant " + cst);
+                    }
+                } else if (cst instanceof Handle) {
+                    return new TrackingValue(Type.getObjectType("java/lang/invoke/MethodHandle"), insn);
+                } else {
+                    throw new IllegalArgumentException("Illegal LDC constant " + cst);
+                }
+            case Opcodes.JSR:
+                return new TrackingValue(Type.VOID_TYPE, insn); // return address value
+            case Opcodes.GETSTATIC:
+                return new TrackingValue(Type.getType(((FieldInsnNode) insn).desc), insn);
+            case Opcodes.NEW:
+                return new TrackingValue(Type.getObjectType(((TypeInsnNode) insn).desc), insn);
+            default:
+                throw new Error("Internal error.");
+        }
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Value unaryOperation(final AbstractInsnNode insn,
-                                final Value value)
+    public TrackingValue unaryOperation(final AbstractInsnNode insn, final TrackingValue value)
         throws AnalyzerException {
         ((TrackingValue) value).addConsumer(insn);
-        return wrap(super.unaryOperation(insn, value), insn);
+        switch (insn.getOpcode()) {
+            case Opcodes.INEG:
+            case Opcodes.IINC:
+            case Opcodes.L2I:
+            case Opcodes.F2I:
+            case Opcodes.D2I:
+            case Opcodes.I2B:
+            case Opcodes.I2C:
+            case Opcodes.I2S:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.FNEG:
+            case Opcodes.I2F:
+            case Opcodes.L2F:
+            case Opcodes.D2F:
+                return new TrackingValue(Type.FLOAT_TYPE, insn);
+            case Opcodes.LNEG:
+            case Opcodes.I2L:
+            case Opcodes.F2L:
+            case Opcodes.D2L:
+                return new TrackingValue(Type.LONG_TYPE, insn);
+            case Opcodes.DNEG:
+            case Opcodes.I2D:
+            case Opcodes.L2D:
+            case Opcodes.F2D:
+                return new TrackingValue(Type.DOUBLE_TYPE, insn);
+            case Opcodes.IFEQ:
+            case Opcodes.IFNE:
+            case Opcodes.IFLT:
+            case Opcodes.IFGE:
+            case Opcodes.IFGT:
+            case Opcodes.IFLE:
+            case Opcodes.TABLESWITCH:
+            case Opcodes.LOOKUPSWITCH:
+            case Opcodes.IRETURN:
+            case Opcodes.LRETURN:
+            case Opcodes.FRETURN:
+            case Opcodes.DRETURN:
+            case Opcodes.ARETURN:
+            case Opcodes.PUTSTATIC:
+                return null;
+            case Opcodes.GETFIELD:
+                return new TrackingValue(Type.getType(((FieldInsnNode) insn).desc), insn);
+            case Opcodes.NEWARRAY:
+                switch (((IntInsnNode) insn).operand) {
+                    case Opcodes.T_BOOLEAN:
+                        return new TrackingValue(Type.getType("[Z"), insn);
+                    case Opcodes.T_CHAR:
+                        return new TrackingValue(Type.getType("[C"), insn);
+                    case Opcodes.T_BYTE:
+                        return new TrackingValue(Type.getType("[B"), insn);
+                    case Opcodes.T_SHORT:
+                        return new TrackingValue(Type.getType("[S"), insn);
+                    case Opcodes.T_INT:
+                        return new TrackingValue(Type.getType("[I"), insn);
+                    case Opcodes.T_FLOAT:
+                        return new TrackingValue(Type.getType("[F"), insn);
+                    case Opcodes.T_DOUBLE:
+                        return new TrackingValue(Type.getType("[D"), insn);
+                    case Opcodes.T_LONG:
+                        return new TrackingValue(Type.getType("[J"), insn);
+                    default:
+                        throw new AnalyzerException(insn, "Invalid array type");
+                }
+            case Opcodes.ANEWARRAY:
+                String desc = ((TypeInsnNode) insn).desc;
+                return new TrackingValue(Type.getType("[" + Type.getObjectType(desc)), insn);
+            case Opcodes.ARRAYLENGTH:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.ATHROW:
+                return null;
+            case Opcodes.CHECKCAST:
+                desc = ((TypeInsnNode) insn).desc;
+                return new TrackingValue(Type.getObjectType(desc), insn);
+            case Opcodes.INSTANCEOF:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.MONITORENTER:
+            case Opcodes.MONITOREXIT:
+            case Opcodes.IFNULL:
+            case Opcodes.IFNONNULL:
+                return null;
+            default:
+                throw new Error("Internal error.");
+        }
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Value binaryOperation(final AbstractInsnNode insn,
-                                 final Value value1, final Value value2)
+    public TrackingValue binaryOperation(final AbstractInsnNode insn,
+                                         final TrackingValue value1, final TrackingValue value2)
         throws AnalyzerException {
         ((TrackingValue) value1).addConsumer(insn);
         ((TrackingValue) value2).addConsumer(insn);
-        return wrap(super.binaryOperation(insn, value1, value2), insn);
+        switch (insn.getOpcode()) {
+            case Opcodes.IALOAD:
+            case Opcodes.BALOAD:
+            case Opcodes.CALOAD:
+            case Opcodes.SALOAD:
+            case Opcodes.IADD:
+            case Opcodes.ISUB:
+            case Opcodes.IMUL:
+            case Opcodes.IDIV:
+            case Opcodes.IREM:
+            case Opcodes.ISHL:
+            case Opcodes.ISHR:
+            case Opcodes.IUSHR:
+            case Opcodes.IAND:
+            case Opcodes.IOR:
+            case Opcodes.IXOR:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.FALOAD:
+            case Opcodes.FADD:
+            case Opcodes.FSUB:
+            case Opcodes.FMUL:
+            case Opcodes.FDIV:
+            case Opcodes.FREM:
+                return new TrackingValue(Type.FLOAT_TYPE, insn);
+            case Opcodes.LALOAD:
+            case Opcodes.LADD:
+            case Opcodes.LSUB:
+            case Opcodes.LMUL:
+            case Opcodes.LDIV:
+            case Opcodes.LREM:
+            case Opcodes.LSHL:
+            case Opcodes.LSHR:
+            case Opcodes.LUSHR:
+            case Opcodes.LAND:
+            case Opcodes.LOR:
+            case Opcodes.LXOR:
+                return new TrackingValue(Type.LONG_TYPE, insn);
+            case Opcodes.DALOAD:
+            case Opcodes.DADD:
+            case Opcodes.DSUB:
+            case Opcodes.DMUL:
+            case Opcodes.DDIV:
+            case Opcodes.DREM:
+                return new TrackingValue(Type.DOUBLE_TYPE, insn);
+            case Opcodes.AALOAD:
+                return new TrackingValue(Type.getType(Object.class), insn); // reference value
+            case Opcodes.LCMP:
+            case Opcodes.FCMPL:
+            case Opcodes.FCMPG:
+            case Opcodes.DCMPL:
+            case Opcodes.DCMPG:
+                return new TrackingValue(Type.INT_TYPE, insn);
+            case Opcodes.IF_ICMPEQ:
+            case Opcodes.IF_ICMPNE:
+            case Opcodes.IF_ICMPLT:
+            case Opcodes.IF_ICMPGE:
+            case Opcodes.IF_ICMPGT:
+            case Opcodes.IF_ICMPLE:
+            case Opcodes.IF_ACMPEQ:
+            case Opcodes.IF_ACMPNE:
+            case Opcodes.PUTFIELD:
+                return null;
+            default:
+                throw new Error("Internal error.");
+        }
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Value ternaryOperation(final AbstractInsnNode insn,
-                                  final Value value1, final Value value2,
-                                  final Value value3)
+    public TrackingValue ternaryOperation(final AbstractInsnNode insn,
+                                          final TrackingValue value1, final TrackingValue value2,
+                                          final TrackingValue value3)
         throws AnalyzerException {
-        ((TrackingValue) value1).addConsumer(insn);
-        ((TrackingValue) value2).addConsumer(insn);
-        ((TrackingValue) value3).addConsumer(insn);
-        return wrap(super.ternaryOperation(insn, value1, value2, value3), insn);
+        value1.addConsumer(insn);
+        value2.addConsumer(insn);
+        value3.addConsumer(insn);
+        return new TrackingValue(null, insn);
     }
 
     /** {@inheritDoc} */
-    @SuppressWarnings("rawtypes")
-    @Override
-    public Value naryOperation(final AbstractInsnNode insn,
-                               final List values)
+    public TrackingValue naryOperation(final AbstractInsnNode insn, final List<? extends TrackingValue> values)
         throws AnalyzerException {
         for (final Iterator<?> iterator = values.iterator(); iterator.hasNext();) {
             ((TrackingValue) iterator.next()).addConsumer(insn);
         }
-        return wrap(super.naryOperation(insn, values), insn);
+        int opcode = insn.getOpcode();
+        if (opcode == Opcodes.MULTIANEWARRAY) {
+            return new TrackingValue(Type.getType(((MultiANewArrayInsnNode) insn).desc), insn);
+        } else if (opcode == Opcodes.INVOKEDYNAMIC){
+            return new TrackingValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc), insn);
+        } else {
+            return new TrackingValue(Type.getReturnType(((MethodInsnNode) insn).desc), insn);
+        }
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Value copyOperation(final AbstractInsnNode insn,
-                               final Value value)
+    public TrackingValue copyOperation(final AbstractInsnNode insn, final TrackingValue value)
         throws AnalyzerException {
         // we reuse the same instance instead of wrapping it again
         // thus simplifying transitive dependencies propagation
-        final TrackingValue tv = (TrackingValue) value;
-        tv.addConsumer(insn);
-        tv.addProducer(insn);
+        value.addConsumer(insn);
+        value.addProducer(insn);
         return value;
     }
 
     /** {@inheritDoc} */
-    @Override
-    public Value merge(final Value v, final Value w) {
-
-        final TrackingValue tv = (TrackingValue) v;
-        final TrackingValue tw = (TrackingValue) w;
-        TrackingValue.merge(tv, tw);
-
-        final BasicValue superMerged = (BasicValue) super.merge(tv.getValue(), tw.getValue());
-        return (superMerged == tv.getValue()) ? tv : new TrackingValue(superMerged);
-
+    public TrackingValue merge(final TrackingValue v, final TrackingValue w) {
+        TrackingValue.merge(v, w);
+        return v;
     }
 
-    /** Wrap a value returned by the superclass.
-     * @param value underlying value (may be null)
-     * @param producer instruction producing the value (may be null)
-     * @return the wrapped value
-     */
-    private TrackingValue wrap(final Value value,
-                               final AbstractInsnNode producer) {
-
-        if (value == null) {
-            return null;
-        }
-
-        // values produced by the superclass are either BasicValue instances
-        // (like BasicValue.DOUBLE_VALUE) or already TrackingValue if the
-        // superclass called our local implementation of newValue or newOperation
-        final TrackingValue tv = (value instanceof TrackingValue) ?
-                                 (TrackingValue) value :
-                                 new TrackingValue((BasicValue) value);
-
-        if (producer != null) {
-            tv.addProducer(producer);
-        }
-
-        return tv;
-
+    /** {@inheritDoc} */
+    public void returnOperation(AbstractInsnNode insn, TrackingValue value, TrackingValue expected) {
+        // nothing to do here, as unaryOperation has already been called
     }
 
 }

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingValue.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingValue.java?rev=1391523&r1=1391522&r2=1391523&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingValue.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/algorithmic/forward/analysis/TrackingValue.java Fri Sep 28 16:30:21 2012
@@ -19,8 +19,8 @@ package org.apache.commons.nabla.algorit
 import java.util.HashSet;
 import java.util.Set;
 
+import org.objectweb.asm.Type;
 import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.analysis.BasicValue;
 import org.objectweb.asm.tree.analysis.Value;
 
 /** A value that keep track of both instructions producing and consuming it.
@@ -28,11 +28,10 @@ import org.objectweb.asm.tree.analysis.V
 public class TrackingValue implements Value {
 
     /** Special value for uninitialized values. */
-    public static final TrackingValue UNINITIALIZED_VALUE =
-        new TrackingValue((BasicValue) BasicValue.UNINITIALIZED_VALUE);
+    public static final TrackingValue UNINITIALIZED_VALUE = new TrackingValue(null);
 
-    /** Underlying value. */
-    private final BasicValue value;
+    /** Value type. */
+    private final Type type;
 
     /** Instructions that consume this value. */
     private Set<AbstractInsnNode> consumers;
@@ -44,26 +43,35 @@ public class TrackingValue implements Va
     private Set<TrackingValue> merged;
 
     /** Build a new value without any link to instructions.
-     * @param value wrapped {@link BasicValue} value
+     * @param type value type
      */
-    public TrackingValue(final BasicValue value) {
-        this.value = value;
+    public TrackingValue(final Type type) {
+        this.type  = type;
         consumers  = new HashSet<AbstractInsnNode>();
         producers  = new HashSet<AbstractInsnNode>();
         merged     = new HashSet<TrackingValue>();
         merged.add(this);
     }
 
-    /** Get the wrapped {@link BasicValue}.
-     * @return wrapped {@link BasicValue}
+    /** Build a new value produced by a specified instruction.
+     * @param type value type
+     * @param producer producer for this value
+     */
+    public TrackingValue(final Type type, final AbstractInsnNode producer) {
+        this(type);
+        producers.add(producer);
+    }
+
+    /** Get the value type.
+     * @return value type
      */
-    public BasicValue getValue() {
-        return value;
+    public Type getType() {
+        return type;
     }
 
     /** {@inheritDoc} */
     public int getSize() {
-        return value.getSize();
+        return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
     }
 
     /** Add a consumer for this value.
@@ -101,8 +109,7 @@ public class TrackingValue implements Va
      * @param value1 first value to merge
      * @param value2 second value to merge
      */
-    public static void merge(final TrackingValue value1,
-                             final TrackingValue value2) {
+    public static void merge(final TrackingValue value1, final TrackingValue value2) {
 
         if (value1.merged.contains(value2)) {
             // the values have already been merged