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: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org


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

Reply via email to