should get picked up.  I will look at this some more.
>
> You are right, the data flow analysis is not sufficient here. In
> fact, we should not only track what comes from the method
> parameters (i.e. the local variables), but also make sure that a
> GETFIELD that refers to the original instance should be either
> split in two GETFIELD if the variable is extended to include a
> deriviative (when there is another PUTFIELD elsewhere), or that
> event if the field is only read, that we try to recover it from
> the primitive and not from the instance itself.

Thanks again, Luc, for your patience explaining things that I should
have been able to see in the code.  Things are getting much clearer
now.  I have been able to get field access to work as follows:

The data flow analysis is never going to flag the GETFIELD
instruction as needing to be transformed.  It works beautifully for
what it does, but instructions that are not producers or consumers
of values originating from method parameters are not going to be
picked up.  To just handle GETFIELD, I added the following at the
end of MethodDifferentiator#changeCode:

// transform GETFIELD
Iterator<AbstractInsnNode> iter = instructions.iterator();
while (iter.hasNext()) {
    AbstractInsnNode insn = iter.next();
    if (insn.getOpcode() == Opcodes.GETFIELD) {
        instructions.insert(insn, getReplacement(insn));
        instructions.remove(insn);
     }
}

and then inside getReplacement replace the RTE on GETFIELD with
case Opcodes.GETFIELD :
            return 
GetFieldTransformer.getInstance().getReplacement(insn, this);

where GetFieldTransformer does
FieldInsnNode fieldIns = (FieldInsnNode) insn.clone(null);
String owner = fieldIns.owner;
final InsnList list = new InsnList();
list.add(new FieldInsnNode(Opcodes.GETFIELD, owner +
"$NablaForwardModeUnivariateDerivative",
    "primitive", "L" + owner + ";")); // primitive
list.add(fieldIns);
return list;

For a primitive class named "PartialFunction" this generates
ALOAD 0
GETFIELD
PartialFunction$NablaForwardModeUnivariateDerivative.primitive :
LPartialFunction;
GETFIELD PartialFunction.x : D

This works great except for one problem:

If the field in the primitive, "x"  in the example above, is not
public, you get
 java.lang.IllegalAccessError: tried to access field
PartialFunction.x from class
PartialFunction$NablaForwardModeUnivariateDerivative
    at
PartialFunction$NablaForwardModeUnivariateDerivative.f(Unknown Source)

(one case where I am not cursing the "Unknown Source" he he)

I am not sure exactly what to do about that.  Is
PartialFunction$NablaForwardModeUnivariateDerivative a static inner
class?  Shouldn't it in theory be able to access the field from an
instance reference?  I think the compiler generates a hidden field
accessor when static inner classes are defined.  It looks like it
does that when I manually add a static inner class, in any case.
Could be we need to manufacture that and attach it to the
primitive.  Or could be I am misunderstanding things.

Alternatively, we could document and require that for a method to be
"differentiable" it must use only fields that have public getters
with bean naming and we could generate code to invoke the getter on
the primitive.

Phil

>
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to