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/10/03 21:16:20 UTC

svn commit: r1393692 - in /commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward: analysis/MethodDifferentiator.java instructions/DReturnTransformer.java

Author: luc
Date: Wed Oct  3 19:16:20 2012
New Revision: 1393692

URL: http://svn.apache.org/viewvc?rev=1393692&view=rev
Log:
Leveraged DRETURN handling, suppressing special cases.

Some methods may have code branches like:
  if (x < 0) return x else return 0
It is therefore possible that in the same method, some DRETURN
instructions depend on the input parameter while other DRETURN
instructions are independent and therefore must return a constant
converted to a DerivativeStructure. We must handle both cases at the
same time.

Modified:
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java
    commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/DReturnTransformer.java

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java?rev=1393692&r1=1393691&r2=1393692&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/analysis/MethodDifferentiator.java Wed Oct  3 19:16:20 2012
@@ -128,43 +128,17 @@ public class MethodDifferentiator {
                 frames.put(method.instructions.get(i), array[i]);
             }
 
-            // identify the needed changes
-            final Set<AbstractInsnNode> changes = identifyChanges(method.instructions);
-
-            if (changes.isEmpty()) {
-
-                // TODO: merge this case with the general case: DRETURN must always be
-                // changed when the function signature changes, and the change is either
-                // converting DRETURN to ARETURN, possibly with a prepended call to
-                // convertDoubleToDerivativeStructure before the ARETURN when stack0converted
-                // is false
-
-                // the method does not depend on the parameter at all!
-                // we replace all "return d;" by "return new DerivativeStructure(parameters, order, d);"
-                for (final Iterator<AbstractInsnNode> i = method.instructions.iterator(); i.hasNext();) {
-                    final AbstractInsnNode insn = i.next();
-                    if (insn.getOpcode() == Opcodes.DRETURN) {
-                        final InsnList list = new DReturnTransformer(false).getReplacement(insn, this, dsIndex);
-                        method.instructions.insert(insn, list);
-                        method.instructions.remove(insn);
-                    }
-                }
-
-            } else {
-
-                // perform the code changes
-                for (final AbstractInsnNode insn : changes) {
-                    method.instructions.insert(insn, getReplacement(insn, method.maxLocals));
-                    method.instructions.remove(insn);
-                }
-
-                // trim generated instructions list
-                new SwappedDloadTrimmer().trim(method.instructions);
-                new SwappedDstoreTrimmer().trim(method.instructions);
-                new DLoadPop2Trimmer().trim(method.instructions);
-
+            // perform the code changes
+            for (final AbstractInsnNode insn : identifyChanges(method.instructions, isStatic)) {
+                method.instructions.insert(insn, getReplacement(insn, method.maxLocals));
+                method.instructions.remove(insn);
             }
 
+            // trim generated instructions list
+            new SwappedDloadTrimmer().trim(method.instructions);
+            new SwappedDstoreTrimmer().trim(method.instructions);
+            new DLoadPop2Trimmer().trim(method.instructions);
+
             // insert the preservation of the reference derivative structure
             method.instructions.insert(preserveReferenceDerivativeStructure(derivedMethodType, isStatic, dsIndex));
 
@@ -190,12 +164,21 @@ public class MethodDifferentiator {
      * the local variables in the initial frame to match the parameters of
      * the derivative method, and propagate these variables following the
      * instructions path, updating stack cells and local variables as needed.
-     * Instructions that must be changed are the ones that consume changed
-     * variables or stack cells.</p>
+     * Instructions that must be changed are:
+     * </p>
+     * <ul>
+     *   <li>the ones that consume changed variables or stack cells</li>
+     *   <li>the GETFIELD/PUTFIELD instruction as they must access the
+     *       primitive instance fields</li>
+     *   <li>all DRETURN instructions (regardless of the returned value being
+     *       converted or not, as in some branch codes the value may return
+     *       simple constants like "return 0")</li>
+     * </ul>
      * @param instructions instructions of the method
+     * @param isStatic if true, the method is a static method
      * @return set containing all the instructions that must be changed
      */
-    private Set<AbstractInsnNode> identifyChanges(final InsnList instructions) {
+    private Set<AbstractInsnNode> identifyChanges(final InsnList instructions, final boolean isStatic) {
 
         // the pending set contains the values (local variables or stack cells)
         // that have been changed, they will trigger changes on the instructions
@@ -206,8 +189,8 @@ public class MethodDifferentiator {
         final Set<AbstractInsnNode> changes = new HashSet<AbstractInsnNode>();
 
         // start by converting the parameter of the method,
-        // which is kept in local variable 1 of the initial frame
-        final TrackingValue dpParameter = frames.get(instructions.get(0)).getLocal(1);
+        // which is kept in local variable 0 or 1 of the initial frame (depending on the method being static or not)
+        final TrackingValue dpParameter = frames.get(instructions.get(0)).getLocal(isStatic ? 0 : 1);
         pending.add(dpParameter);
 
         // propagate the values conversions throughout the method
@@ -243,12 +226,13 @@ public class MethodDifferentiator {
             }
         }
 
-        // the various GETFIELD/PUTFIELD instructions must also be changed
-        // to retrieve the field from the primitive class
+        // the various GETFIELD/PUTFIELD/DRETURN instructions must also be changed
         final ListIterator<AbstractInsnNode> iterator = instructions.iterator();
         while (iterator.hasNext()) {
             final AbstractInsnNode ins = iterator.next();
-            if ((ins.getOpcode() == Opcodes.GETFIELD) || (ins.getOpcode() == Opcodes.PUTFIELD)) {
+            if ((ins.getOpcode() == Opcodes.GETFIELD) ||
+                (ins.getOpcode() == Opcodes.PUTFIELD) ||
+                (ins.getOpcode() == Opcodes.DRETURN)) {
                 changes.add(ins);
             }
         }
@@ -377,8 +361,7 @@ public class MethodDifferentiator {
             case Opcodes.DCMPG :
                 return new DcmpTransformer().getReplacement(insn, this, dsIndex);
             case Opcodes.DRETURN :
-                // TODO: the constructor parameter forced to true seems strange...
-                return new DReturnTransformer(true).getReplacement(insn, this, dsIndex);
+                return new DReturnTransformer().getReplacement(insn, this, dsIndex);
             case Opcodes.GETSTATIC :
                 // TODO: add support for GETSTATIC differentiation
                 throw new RuntimeException("GETSTATIC not handled yet");

Modified: commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/DReturnTransformer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/DReturnTransformer.java?rev=1393692&r1=1393691&r2=1393692&view=diff
==============================================================================
--- commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/DReturnTransformer.java (original)
+++ commons/sandbox/nabla/trunk/src/main/java/org/apache/commons/nabla/forward/instructions/DReturnTransformer.java Wed Oct  3 19:16:20 2012
@@ -33,16 +33,6 @@ import org.objectweb.asm.tree.InsnNode;
  */
 public class DReturnTransformer implements InstructionsTransformer {
 
-    /** Indicator for top stack element conversion. */
-    private final boolean stack0Converted;
-
-    /** Simple constructor.
-     * @param stack0Converted if true, the top level stack element has already been converted
-     */
-    public DReturnTransformer(final boolean stack0Converted) {
-        this.stack0Converted = stack0Converted;
-    }
-
     /** {@inheritDoc} */
     public InsnList getReplacement(final AbstractInsnNode insn,
                                    final MethodDifferentiator methodDifferentiator,
@@ -51,7 +41,7 @@ public class DReturnTransformer implemen
 
         final InsnList list = new InsnList();
 
-        if (!stack0Converted) {
+        if (!methodDifferentiator.stackElementIsConverted(insn, 0)) {
             // add conversion for top level stack element
             list.add(methodDifferentiator.doubleToDerivativeStructureConversion(dsIndex));
         }