Hi Rémi, thanks for the input. My idea is somewhat different. I no longer think of any kind of MOP interface. Rather, I'm thinking in terms of a linker framework that recognizes some special method names (I discussed this with John Rose last year at the lang summit, and I think his thinking is along the same lines). The way it'd work would be:
Source code: obj.foo Bytecode: ALOAD 2 (or wherever "obj" is) INVOKEDYNAMIC "dyn:getprop:foo"(Ljava/lang/Object;)Ljava/lang/Object; The linker framework is such that it has a master linker that contains sub-linkers for all available language runtimes on the classpath + has a fallback POJO linker. It first links the call site to a "relink" method that queries every sub-linker for a resolution of the name with particular arguments. These sub-linkers return an invocation MH + a guard MH when they recognize the receiver and the master linker then installs a guardWithTest(guard, invocation, relink) - where "relink" is a method handle to the same method doing the relinking, so it repeats the linking on guard failure (that is, then it'll again go around all the language sub-linkers). I actually implemented that over this week; you can go to <https://sourceforge.net/projects/dynalang/develop > and pull the source code from SVN, specifically all the work is in the "invoke" module. The linker framework, complete with autodiscovery of available language linkers and the master linker implementation (DynamicLinkerImpl) is complete. There's an embryonic POJO linker, it's quite unfinished for now, really just a proof-of-concept, but there's already a JUnit test in testsrc that dispatches a dyn:getprop call to two different classes using this embryonic POJO linker; you can use it as a demo example of where's this heading. Check out the README.txt for details: <http://dynalang.svn.sourceforge.net/viewvc/dynalang/trunk/invoke/README.txt?revision=159&view=markup > Of course, none of this is set in stone, but I think this is the generic direction I want to take it. I was thinking a bit about the possibility of a PIC with the current CallSite architecture, and I'm coming to the realization that I don't really see it... The fact of the matter is, CallSite can have only one method linked at a time, and this quite predisposes it for a MIC. Also, the guard MH is opaque - you can just invoke it, but can't analyze it, so it's impossible to do smart dispatching optimizations for a PIC. The only PIC I can imagine is having nested guardWithTest() - newly linked guardWithTest() MH that has the previously likned guardWithTest() MH as its fallback, creating a sequentially dispatchig PIC; if there's interest in that, it's actually easy to modify my master linker to provide several common caching strategies, or even make it pluggable. As each language runtime would create its own DynamicLinker instance, it is okay for it to customize its caching. Hm... I might actually just go and do that. So anyway, talk is cheap (and less exact!) compared to working code, so why don't you look at the "invoke" module in SVN above? Interface injection for getMOP() could also work, but my preferred approach are MOPs disguised as linkers responding to hierarchical method names (separated with colons), and a master linker that ties them together. Attila. On 2009.08.01., at 16:01, Rémi Forax wrote: > Hi Attila, > in my opinion a MOP (Meta Object Protocol) imposes > that all receiver should have a method like getMOP() > that returns an object implementing the following interface: > > public interface MOP { > // return an (Object)Object > public MethodHandle getMember(String member); > // returns an (Object,String)Object > public MethodHandle getMember(); > > // returns an (Object)Object > public MethodHandle getIndex(int[] index); > // returns an (Object,int...)Object > // i.e if indexDimension=2 returns (Object,int, int)Object > public MethodHandle getIndex(int indexDimension); > > // returns an (Object)Object > public MethodHandle convertTo(Class<?> anotherType); > // returns an (Object,Class<?>)Object i.e a kind of dynamic cast > public MethodHandle convertTo(); > > // returns a MethodHandle such as mh.type == methodType > public MethodHandle call(MethodType methodType); > // returns a (Object, Object[])Object > public MethodHandle call(); > > // retruns a MethodHandle such as mh.type == methodType > public MethodHandle methodCall(String name, MethodType methodType); > // returns a (Object, Object[])Object > public MethodHandle methodCall(String name); > > //etc. > } > > All methods are paired because the former knows statically some > informations by example for getMember, getMember(String) is used > if the name of the member is statically known and the later > getMember() > is used > if the name of the member is only given at runtime. > > a.m => getMember("m") > a["m"] => getMember() > > So the MOP linker is responsible for calling the MOP object > corresponding to > the receiver using any cache it wants: MIC, PIC, etc. > > Given that, we will able to see how to do a better invalidation, i.e > if a MOP returns a method handle which is a guard, > and if this guard detects that an invariant of the runtime isn't an > invariant > anymore, it will want to replace the current method handle by > another one. > A real MOP should provide a way to do that. > > A simple way to achieve that is to take another parameter providing > a way to invalidate a method handle and > a way to get the last method handle used (the one invalidated) if it > exists. > > public interface MOP { > // return an (Object)Object > public MethodHandle getMember(String member, MOPControl control); > // returns an (Object,String)Object > public MethodHandle getMember(MOPControl control); > ... > } > > public interface MOPControl { > public MethodHandle getInvalidatorFallback(); > public MethodHandle getInvalidatedMethodHandle(); > } > > In that case, it will be used like this: > > public class MyLanguageMOP implements MOP { > public MethodHandle getMember(String member, MOPControl control) { > // control.getInvalidatedMethodHandle() returns the last method > handle > // used or null, here I don't care but it will be usefull to > implement PIC > > // this method handle will call MOP.getMember with the method > handle > // retruns by this method in case of invalidation > MethodHandle invalidator = control.getInvalidatorFallback(); > > // to get a field my language provide a method Object > getField(String) > return MethodHandles.guardWithTest(INVARIANT_TEST, GET_FIELD, > invalidator); > } > > private static final MethodHandle GET_FIELD = > > MethodHandles.publicLookup().findVirtual(MyLanguageBaseObject.class, > "getField", > MethodType.make(Object.class, String.class)); > > private static final MethodHandle INVARIANT_TEST = ... > } > > > There is also a case where the receiver doesn't have a method > getMOP(), > in that case the MOP can consider it has a POJO and use a special > POJOMOP > object for that. Or perhaps it can try to inject an interface with the > method > getMOP() when interface injection will work. > > What do you think about that ? > > cheers, > Rémi --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "JVM Languages" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/jvm-languages?hl=en -~----------~----~----~----~------~----~------~--~---
