Charles Oliver Nutter wrote:
[...]
We do want to move away from having the wrappers, however, since they
can sometimes interfere with object identity and certainly increase
the memory footprint of Java objects flowing through Rubyspace. In
that case we would have the same challenge as you to recover the
metaclass on each call. My strategy would most likely be to build in
per-site polymorphic caches that can hold references to previous
metaclasses they have seen, allowing for a simple identity check. I
assume you've done this already in your inline caching.

yes, the "call site" holds the meta class for the java object.

All classes in JRuby are mutable, which means every call must perform
a check to see if their cache is now stale. In JRuby, this boils down
to caching a tuple of [token, method] where the token is just an
Object instance. The token is compared with that on the incoming class
to know whether it's the same class in the same state as the previous
call. Failure means the tuple is dumped and re-cached. On the
metaclass side, changes to one metaclass flip the token of that class
but also flip the tokens of all descendants.

ok, but I doubt you can do that multithreaded and without synchronization.

Ultimately this means for a successfully cached call site in JRuby,
the cost is only a volatile read plus an object comparison (not
counting non-volatile fields to get the cache tuple and the token and
method, of course). It's pretty small.

small, yes. But as I talked about at the language summit, even using a volatile can cause hotspot to have big problems. Not to imagine multiple threads working on the same volatile for each method invocation. Not only does hotspot have to handle much bigger code than usual (there is probably no real solution to this) but the usage of volatiles makes it difficult for him to move code.

Even if we had method handles (Groovy is based on Java 1.5 atm), I would
still have to do things like checking if there is an active category, if the
metaclass is still the same and not mutated (ExpandoMetaClass allows
mutation)

For the category stuff it might be interesting to look at
org.codehaus.groovy.runtime.GroovyCategorySupport#hasCategoryInCurrentThread,
 which uses an AtomicInteger in the first place and if that check fails we
have to get a ThreadLocal storing the real category information.

The solution that comes to mind for me is that all calls should bounce
through some "invoker" that is per-thread.  The invoker would be a
non-category invoker normally and once a category is active the
threadlocal invoker would be replaced with a category-aware invoker.
Because no other threads would need to see the per-thread invoker, all
access to it would be nonvolatile, and you would avoid the cost of
checking for an installed category on every call.

Of course I must admit I don't know all the details of categories.

the problem is more about how to realize the threadlocal invoker. I have not found a way to do this unless I use ThreadLocal, which has issues on its own.

org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite#checkPojoMetaClass()
contains the check we do for a cached java method. Something similar is done
for method calls on groovy objects.

Yes, this will be interesting for us once we eliminate the wrappers
around Java object. For the moment, it appears the wrappers make it
about twice as expensive for a Java object to enter Ruby in JRuby as
it would cost for the same call to happen in Groovy.

actually I am not sure about the direction you talk here about. This is for calling a Java method on a Java object from Groovy. So the direction is from Groovy into Java. The cost for Java to call a Groovy method the static way is the same as for any other Java based method, since this works completely static. Only if you want the dynamic stuff, you have to use InvokerHelper and here it gets quite expensive, because here of course no call site caching is done.

bye Jochen

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

--
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.

Reply via email to