I have a quite good idea what change caused this; we recently moved lots of
explicit conversions into method handle signatures, e.g. instead of doing
LOAD x
INVOKEDYNAMIC "dyn:getMethod:get"
LOAD x
LDC 'test'
INVOKEDYNAMIC "dyn:call" (Object, Object, Object)Object
INVOKESTATIC "toBoolean" (Object)Z
to implement "x.get('test')" as a boolean predicate for the if statement, we
now do a simpler equivalent where we merge the expectation of the return type
into the function invocation and thus eliminate an explicit conversion from
bytecode:
LOAD x
INVOKEDYNAMIC "dyn:getMethod:get"
LOAD x
LDC 'test'
INVOKEDYNAMIC "dyn:call" (Object, Object, Object)Z
This has the advantage that when we link to Java API that already returns a
boolean (think: Map.isEmpty, etc.), we can more simply link through and avoid a
boxing to Object in the return value and then an unnecessary unboxing back to
boolean. NB: this change is not specific to booleans and if statements, we
eliminated a large amount of explicit conversions in bytecode this way.
Unfortunately, our built-in "to boolean" (and "to number" and "to string")
conversions when used directly on dynamically linked Java method invocation
don't apply to objects that are foreign to Nashorn. We'll happily convert a
native ScriptObject or NativeArray to boolean, or even a Double or a String (as
they are used internally), but we won't convert a java.io.File – a
runtime-foreign object – to boolean automatically.
We could modify the system so that it performs such conversions, but if we did,
then you could also pass a java.io.File to a Java API that expects a boolean
parameter (potentially making overload resolution ambiguities even more
aggravated, although we can mitigate that). The reason for this is that we have
a generic conversion architecture in our system that works symmetrically in
both directions - parameters and return types, so if you allow a conversion on
a return type, then you allow it on a parameter too.
How do people feel about allowing full spectrum of Object->(String, number,
boolean) conversions in both directions (both to Java and from Java)? We could
also be thinking along the lines of asymmetric conversion rules - some allowed
on Java parameters, some only allowed on Java return values, but it's not yet
crystal clear right now to me how to fit that into the architecture (not saying
it's impossible, just saying it needs more thinking on my part.) Also, some
people might end up thinking such asymmetry is a bug…
Attila.
On Nov 5, 2013, at 10:17 AM, Tal Liron <[email protected]> wrote:
> OK, after some work I've managed to isolate the bug. This short program will
> cause the exception:
>
> var x = new java.util.HashMap()
> x.put('test', new java.io.File('test'))
> if (x.get('test')) {
> print('Found!')
> }
>
> The issue seems to be with *casting return values of Java methods* (which
> should cast to boolean; I don't know why it tries to cast to a
> java.langNumber). Simple casting a Java object won't cause the exception.
>
> I'll remind you that this bug appeared only in a recent commit (last few
> days).
>
> On 11/05/2013 03:39 PM, A. Sundararajan wrote:
>> No, it is hard to debug with cast issue without access to code.
>