Le 21/10/2011 20:33, Phil Steitz a écrit :
> 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?
It's an inner class, but not static. This was done precisely to be able
to access private fields :-(
> 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.
Good catch. I guess the accessor is in the enclosing class then ?
Unortunately, we cannot change this class.
>
> 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.
This would be a big drawback. If we can find some way to do it, we
should really try hard. Perhaps using the reflection API ? It's ugly,
but it allows to temporarily lift access restrictions. I used it
sometimes in unit tests to reset some singletons to null.
Luc
>
> Phil
>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]