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