On 2007.12.07., at 13:43, Jochen Theodorou wrote:

> Attila Szegedi schrieb:
>>
>> Yup, it's all implemented. See
>>
>> <http://dynalang.svn.sourceforge.net/viewvc/dynalang/trunk/dynalang/src/org/dynalang/mop/beans/
>>>
>>
>> OverloadedDynamicMethod is the class you're looking for. It further
>> relies on both OverloadedFixArgMethod and OverloadedVarArgMethod,
>> which implement the actual nitty-gritty details for fixedarg  
>> overloads
>> and vararg overloads of a method, respectively.
>
> I must say I don't get it fully yet.. If I look at
> OverloadedMethodUtilities#isMoreSpecific then I see two classes  
> involved
> and this tells if one is more specific than the other.. so I would  
> have
> expected to find a usage where you try to sort a  set ci into for
> example c1<c2<c3 with c3 being the call argument class and c11/c2  
> being
> classes from two available method.. but I don't find a place where  
> this
> happens. Instead I think I you just compare the method parameters to
> find the most specific method.. but not the method "most fitting" the
> call... So coming back to my c1,c2,c3 this is all fine if you assume
> that c2<c3 and c1<c3, because the most specific one will then be the
> "most fitting" one too. But I don't find the place where the filtering
> happens.

My algorithm follows the JLS 3rd edition chapter 15.12 as closely as  
possible (considering JLS uses a compile-time resolution against  
statically computed types of parameter expressions at call site, and  
we're doing runtime resolution against actual types of parameter  
expressions at runtime).

<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.12 
 >

With that in mind I'll walk you through the code for fixarg resolution.

line 100 of OverloadedFixArgMethod says:
   objMember = argTypes.getMostSpecific(members);
"argTypes" is is an instanceof my ClassString class representing the  
actual arguments of the parameters at the call site. It is passed a  
list of all overloads (members) to select the most specific.

getMostSpecific() will do the following:
1. find all methods applicable to the argument types (as per JLS  
15.12.2) in its getApplicables() method. We do both applicability by  
subtyping (JLS 15.12.2.2) and by method invocation conversion (JLS  
15.12.2.3) in a single pass, which is greatly helped by the fact that  
we can not pass primitive values to our dynamically invoked methods  
anyway, they're already wrapped into their object counterparts :-)

2. then we try to find all maximally specific methods among the  
applicables (methods have a partial "is more specific" ordering based  
on their argument types, see JLS  15.12.2.5). In case there's exactly  
one maximal element, it is by definition of partial ordering the most  
specific element, and it'll be selected to be invoked. If there's more  
than one maximal element, we have an ambiguity and an exception needs  
to be thrown.

The "most specific method among all applicable methods for given  
types" is a formal expression of "method most fitting the call".

There's one additional hurdle though. With dynamic languages, there's  
the question of what's the assumed Java type of the arguments used for  
the call, right? I maintain a map of target types, one per number of  
arguments for the overloaded method. I.e. if you have two 2-arg  
overloads:

foo(java.lang.String, java.util.List)
foo(java.lang.String, java.util.Set)

then the target types for argument conversion for all 2-arg overloads  
of foo will be computed to be [java.lang.String,  
java.util.Collection]. When the method is dynamically invoked, the  
passed callProtocol will be asked to provide a representation of the  
first method as if it were a String, and to provide a representation  
of the second method as if it were a Collection. Hopefully in the real  
invocation, the second argument will already be either a list or a  
set, so it will be returned unchanged. If it is however a collection  
that is neither a list nor a set, then no method will be invoked and  
an error will be thrown.

In case your overloads are really convoluted:

foo(java.lang.String, boolean)
foo(boolean, java.lang.String)

the the target types become [java.lang.Object, java.lang.Object]. This  
basically means that the arguments will not be converted up front  
(CallProtocol.representAs() invoked with java.lang.Object as target  
type is expected to return its object argument unchanged). Note that  
you can still invoke foo() with argument expressions that evaluate to  
java.lang.String and java.lang.Boolean, i.e. both foo("", false) and  
foo(false, "") will work. But the overloaded method resolver won't be  
able to automatically coerce other types automatically in this case.  
I.e. would a JavaScript invocation of foo(0, 0) be interpreted as  
foo("0", false) or foo(false, "0")? It's undecidable.

All in all, it does the best job possible with most overloads, and if  
your overloads create a _very_ ambiguous situation, you'll just need  
explicit language support for casting the parameter types.

> ah yes, one more thing.. isn't your marshalTypes and selectorCache in
> OverloadedFixArgMethod a good place for memory wholes?

A memory leak?

marshalTypes certainly isn't. It might retain Class objects used in  
argument types of the overloaded method, but those can't be unloaded  
anyway until the class that the method itself belongs could be unloaded.

OTOH, selectorCache is, as it might retain a Class object that is a  
subclass of argument types of the method, loaded through a different  
class loader. I'd need a "WeakClassString" class that weakly  
references its Class objects.

That said, the "mops" map in BeansMetaobjectProtocol is the one that  
should really be rewritten using weak references for keys and soft  
references for MOP objects (and then when the class gets GCed, all  
associated Overloaded*ArgMethod objects will get GCed as well,  
resulting in marsalTypes going away). There are other places in the  
code that accumulate class references, i.e.  
ClassBasedMetaobjectProtocolImpl. I'm aware of these issues, and  
intend to address them. Caching information pertaining to Class  
objects is tricky business as it's hard to get right - I've  
implemented few systems already in the past. Most notably, you usually  
can't use a map with both weak key and weak value refs, as that way  
the value gets GCed too often and the cache miss ratio is too high,  
mostly defeating the purpose. Using a weak key ref and soft value ref  
is better in cache hit terms, but if your soft-cached value holds a  
direct or indirect strong ref to the key object (and it does if the  
value is a method or holds a method, and key is the class declaring  
said method), then you've essentially promoted the weakly-referenced  
key object to soft reachability instead of weak reachability once its  
strong references are gone. This'll postpone its GC and subsequent  
unloading of its class loader, but is fortunately usually okay with  
regard to memory management semantics otherwise, even if it can cause  
higher temporary memory pressure (until soft references are cleared).  
As usual, the lunch is not free, but if implemented properly it won't  
lead to an OOME and all class garbage will get GCed even if with a bit  
of an additional delay.

Anyway, these are issues I'm aware of, and intend to take care of. In  
the first pass, I'd like to see the API and the implementation  
stabilize without additional complexity of memory management issues.  
Then when we're happy with it, I'll apply the required dosage of weak  
and soft referencing where necessary :-)

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

Attila.

--
home: http://www.szegedi.org
weblog: http://constc.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