experiences with prototype
Remi Forax
forax at univ-mlv.fr
Sun Feb 8 17:50:00 UTC 2015
Hi Peter,
lambdas/method reference are desugared to an invokedynamic + a specific
bootstrap method,
so you need
1) javac to emit enough information for the specializer
javac as to indicate if the functional interface (the return value
of invokedynamic)
is a specilized type and if some captured values are also of a
specialized type.
This part is the same as when specializing invokedynamic.
2) javac also emit 3 informations,
two method types that correspond to the descriptor of the abstract
method of the
functional interface, the first one is erased, the second one is
not erased.
Both these method descriptors need to be specialized thus required
to generate
2 supplementary signatures in the bytecode mapping.
The last information is a method handle corresponding to the
implementation of
the body of the lambda.
3) javac currently doesn't emit any generics information for the body of
the lambda,
javac should emit such information and add the information in order
to specialize
the body if the lambda use some type variable bound by any.
4) now that we have all the information available, we need the bootstrap
method
(the lambda metafactory) to generate not the classical lambda proxy but
a specialized version of the lambda proxy. Given that the lambda
metafactory
use ASM to geenrate the lambda proxy, and the specializer use ASM too,
the idea is just to use the specializer as an adapter visitor
between the code
that generate the lambda proxy and the ASM bytecode writer.
This will generate a specialized lambda proxy.
As a corner case, while a lambda can not declare a type variable
(in retrospect, I should have pushed for it more during EG discussions
because
some of the function design patterns are harder to implement because of
that),
a method referenced by a method reference can declare a type variable so
either the code of the method inside the lambda proxy should emit an
invokedynamic
for such generics method reference call or the lambda metafactory should
be changed to support this kind of call.
Rémi
On 02/08/2015 12:50 PM, Peter Levart wrote:
> Hi Maurizzio,
>
> Testing javany.util further, I found that the following compiles
> without errors:
>
>
> default Comparator<T> thenComparing(Comparator<? super T> other) {
> Objects.requireNonNull(other);
> return (Comparator<T> & Serializable) (c1, c2) -> {
> int res = compare(c1, c2);
> return (res != 0) ? res : other.compare(c1, c2);
> };
> }
>
>
> ...but fails at runtime:
>
>
> Specializing method
> javany/util/Comparators$naturalOrder${}.naturalOrder()Ljavany/util/Comparator;
> with class=[] and method=[TT;]
> Specializing javany.util.Comparator${0=Z}; searching for
> javany/util/Comparator.class (not found)
> Specializing javany.util.Comparator${0=Z}; searching for
> javany/util/Comparator.class (found)
> Exception in thread "main" java.lang.BootstrapMethodError: call site
> initialization exception
> at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
> at
> java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
> at
> java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
> at javany.util.Comparators.<clinit>(Comparators.java:55)
> at
> javany.util.Comparators$naturalOrder${}/1831932724.naturalOrder(Comparators.java:44)
> at javany.util.Comparator.reverseOrder(Comparator.java:337)
> at Test.testStrings(Test.java:14)
> at Test.main(Test.java:26)
> Caused by: java.lang.VerifyError: Bad type on operand stack
> Exception Details:
> Location:
> javany/util/Comparator${0=Z}.lambda$thenComparing$10d9995b$1(Ljavany/util/Comparator;Ljava/lang/Object;Ljava/lang/Object;)I
> @3: invokeinterface
> Reason:
> Type 'java/lang/Object' (current frame, stack[2]) is not
> assignable to integer
> Current Frame:
> bci: @3
> flags: { }
> locals: { 'javany/util/Comparator${0=Z}',
> 'javany/util/Comparator', 'java/lang/Object', 'java/lang/Object' }
> stack: { 'javany/util/Comparator${0=Z}', 'java/lang/Object',
> 'java/lang/Object' }
> Bytecode:
> 0000000: 2a2c 2db9 007b 0300 3604 1504 9900 0815
> 0000010: 04a7 000b 2b2c 2db9 007d 0300 ac
> Stackmap Table:
> append_frame(@20,Integer)
> same_locals_1_stack_item_frame(@28,Integer)
>
> at sun.misc.Unsafe.defineAnonymousClass(Native Method)
> at
> java.lang.invoke.InnerClassLambdaMetafactory.spinInnerClass(InnerClassLambdaMetafactory.java:324)
> at
> java.lang.invoke.InnerClassLambdaMetafactory.buildCallSite(InnerClassLambdaMetafactory.java:194)
> at
> java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:304)
> at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
> ... 7 more
>
>
> Are lambdas/method references also not compatible with specialization
> currently?
>
>
> Peter
>
>
> On 02/08/2015 11:43 AM, Peter Levart wrote:
>> I've got it.
>>
>> The problem was that Any.<int>toStringImpl() instance method was
>> private. Since it is located in a specialized (Any${0=I}) class, it
>> is not accessible from Any class (or specialized VM anonymous class
>> generated for a specialized generic static method). The VerifyError:
>> "Bad invokespecial instruction: current class isn't assignable to
>> reference class." is not very informative though.
>>
>> By making the method(s) package-private, my test now runs correctly.
>>
>> Regards, Peter
>>
>> On 02/08/2015 11:27 AM, Peter Levart wrote:
>>> Hi Maurizio,
>>>
>>> This is great. I replaced all new-style for loops on <any T> T[]
>>> arrays with classic on-index iteration and applied your patch
>>> selectively without the redundant cast in javany/util/Arrays.java:823:
>>>
>>> a = (E[])Objects.requireNonNull(array)
>>>
>>> ... as I think your last langtools patch (99ab651be669) fixes that,
>>> right?
>>>
>>>
>>> Now with the following code:
>>>
>>> http://cr.openjdk.java.net/~plevart/misc/valhala-hacks/javany-src.02.jar
>>>
>>>
>>> And this test:
>>>
>>> public class Test {
>>>
>>> static void testStrings() {
>>> List<String> strings = Arrays.<String>asList("a", "b", "c");
>>> System.out.println(strings);
>>> }
>>>
>>> static void testInts() {
>>> List<int> ints = Arrays.<int>asList(1, 2, 3);
>>> System.out.println(ints);
>>> }
>>>
>>> public static void main(String[] args) {
>>> testStrings();
>>> testInts();
>>> }
>>> }
>>>
>>>
>>> I get:
>>>
>>> [a, b, c]
>>> Specializing javany.util.List${0=I}; searching for
>>> javany/util/List.class (not found)
>>> Specializing javany.util.List${0=I}; searching for
>>> javany/util/List.class (found)
>>> Specializing javany.util.Collection${0=I}; searching for
>>> javany/util/Collection.class (not found)
>>> Specializing javany.util.Collection${0=I}; searching for
>>> javany/util/Collection.class (found)
>>> Specializing javany.lang.Iterable${0=I}; searching for
>>> javany/lang/Iterable.class (not found)
>>> Specializing javany.lang.Iterable${0=I}; searching for
>>> javany/lang/Iterable.class (found)
>>> Specializing method
>>> javany/util/Arrays$asList${0=I}.asList([Ljava/lang/Object;)Ljavany/util/List;
>>> with class=[] and method=[I]
>>> Specializing javany.util.Arrays$ArrayList${0=I}; searching for
>>> javany/util/Arrays$ArrayList.class (not found)
>>> Specializing javany.util.Arrays$ArrayList${0=I}; searching for
>>> javany/util/Arrays$ArrayList.class (found)
>>> Specializing javany.util.AbstractList${0=I}; searching for
>>> javany/util/AbstractList.class (not found)
>>> Specializing javany.util.AbstractList${0=I}; searching for
>>> javany/util/AbstractList.class (found)
>>> Specializing javany.util.AbstractCollection${0=I}; searching for
>>> javany/util/AbstractCollection.class (not found)
>>> Specializing javany.util.AbstractCollection${0=I}; searching for
>>> javany/util/AbstractCollection.class (found)
>>> Specializing javany.util.Iterator${0=I}; searching for
>>> javany/util/Iterator.class (not found)
>>> Specializing javany.util.Iterator${0=I}; searching for
>>> javany/util/Iterator.class (found)
>>> Specializing javany.util.ListIterator${0=I}; searching for
>>> javany/util/ListIterator.class (not found)
>>> Specializing javany.util.ListIterator${0=I}; searching for
>>> javany/util/ListIterator.class (found)
>>> Specializing javany.util.AbstractList$Itr${0=I}; searching for
>>> javany/util/AbstractList$Itr.class (not found)
>>> Specializing javany.util.AbstractList$Itr${0=I}; searching for
>>> javany/util/AbstractList$Itr.class (found)
>>> Specializing method
>>> javany/util/Any$toString${0=I}.toString(Ljava/lang/Object;)Ljava/lang/String;
>>> with class=[] and method=[I]
>>> Specializing javany.util.Any${0=I}; searching for
>>> javany/util/Any.class (not found)
>>> Specializing javany.util.Any${0=I}; searching for
>>> javany/util/Any.class (found)
>>> Exception in thread "main" java.lang.BootstrapMethodError: call site
>>> initialization exception
>>> at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
>>> at
>>> java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
>>> at
>>> java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
>>> at
>>> javany.util.AbstractCollection${0=I}.toString(AbstractCollection.java:514)
>>> at java.lang.String.valueOf(String.java:2987)
>>> at java.io.PrintStream.println(PrintStream.java:821)
>>> at Test.testInts(Test.java:17)
>>> at Test.main(Test.java:22)
>>> Caused by: java.lang.VerifyError: Bad invokespecial instruction:
>>> current class isn't assignable to reference class.
>>> Exception Details:
>>> Location:
>>> javany/util/Any$toString${0=I}.toString(I)Ljava/lang/String; @8:
>>> invokespecial
>>> Reason:
>>> Error exists in the bytecode
>>> Bytecode:
>>> 0000000: bb00 0959 b700 0d1a b700 10b0
>>>
>>> at sun.misc.Unsafe.defineAnonymousClass(Native Method)
>>> at
>>> java.lang.invoke.GenericMethodSpecializer.metafactory(GenericMethodSpecializer.java:98)
>>> at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
>>> ... 7 more
>>>
>>>
>>> But looking at generated bytecode:
>>>
>>>
>>> Classfile
>>> /home/peter/work/local/valhalla-test/dump/javany.util.Any$toString${0=I}_ERROR.class
>>> Last modified Feb 8, 2015; size 321 bytes
>>> MD5 checksum 7dac6f4f515394e0aa2ed1990a092697
>>> Compiled from "Any.java"
>>> public class javany.util.Any$toString${0=I}
>>> minor version: 0
>>> major version: 52
>>> flags: ACC_PUBLIC, ACC_SUPER
>>> Constant pool:
>>> #1 = Utf8 javany/util/Any$toString${0=I}
>>> #2 = Class #1 //
>>> "javany/util/Any$toString${0=I}"
>>> #3 = Utf8 java/lang/Object
>>> #4 = Class #3 // java/lang/Object
>>> #5 = Utf8 Any.java
>>> #6 = Utf8 toString
>>> #7 = Utf8 (I)Ljava/lang/String;
>>> #8 = Utf8 javany/util/Any${0=I}
>>> #9 = Class #8 // "javany/util/Any${0=I}"
>>> #10 = Utf8 <init>
>>> #11 = Utf8 ()V
>>> #12 = NameAndType #10:#11 // "<init>":()V
>>> #13 = Methodref #9.#12 //
>>> "javany/util/Any${0=I}"."<init>":()V
>>> #14 = Utf8 toStringImpl
>>> #15 = NameAndType #14:#7 //
>>> toStringImpl:(I)Ljava/lang/String;
>>> #16 = Methodref #9.#15 //
>>> "javany/util/Any${0=I}".toStringImpl:(I)Ljava/lang/String;
>>> #17 = Utf8 Code
>>> #18 = Utf8 LineNumberTable
>>> #19 = Utf8 Signature
>>> #20 = Utf8 SourceFile
>>> {
>>> public static java.lang.String toString(int);
>>> descriptor: (I)Ljava/lang/String;
>>> flags: ACC_PUBLIC, ACC_STATIC
>>> Code:
>>> stack=2, locals=1, args_size=1
>>> 0: new #9 // class
>>> "javany/util/Any${0=I}"
>>> 3: dup
>>> 4: invokespecial #13 // Method
>>> "javany/util/Any${0=I}"."<init>":()V
>>> 7: iload_0
>>> 8: invokespecial #16 // Method
>>> "javany/util/Any${0=I}".toStringImpl:(I)Ljava/lang/String;
>>> 11: areturn
>>> LineNumberTable:
>>> line 31: 0
>>> Signature: #7 // (I)Ljava/lang/String;
>>> }
>>> SourceFile: "Any.java"
>>>
>>>
>>> Comparing it to original Any.class bytecode:
>>>
>>>
>>> public static <T extends java.lang.Object> java.lang.String
>>> toString(T);
>>> descriptor: (Ljava/lang/Object;)Ljava/lang/String;
>>> flags: ACC_PUBLIC, ACC_STATIC
>>> Code:
>>> stack=2, locals=1, args_size=1
>>> 0: new #3 // class javany/util/Any
>>> 3: dup
>>> 4: invokespecial #4 // Method "<init>":()V
>>> 7: aload_0
>>> 8: invokespecial #8 // Method
>>> toStringImpl:(Ljava/lang/Object;)Ljava/lang/String;
>>> 11: areturn
>>> LineNumberTable:
>>> line 31: 0
>>> Error: unknown attribute
>>> BytecodeMapping: length = 0x12
>>> 00 04 00 00 00 8C 00 04 00 8D 00 07 00 87 00 08
>>> 00 9F
>>> Signature: #160 //
>>> <T:Ljava/lang/Object;>(TT;)Ljava/lang/String;
>>> Error: unknown attribute
>>> TypeVariablesMap: length = 0x9
>>> 01 00 A1 01 01 00 92 00 86
>>>
>>>
>>> And also peeking at Any${0=I}.class:
>>>
>>>
>>> private java.lang.String toStringImpl(int);
>>> descriptor: (I)Ljava/lang/String;
>>> flags: ACC_PRIVATE
>>> Code:
>>> stack=2, locals=2, args_size=2
>>> 0: aload_0
>>> 1: iload_1
>>> 2: invokespecial #45 // Method
>>> toStringNonNullImpl:(I)Ljava/lang/String;
>>> 5: areturn
>>> LineNumberTable:
>>> line 181: 0
>>> Signature: #33 // (I)Ljava/lang/String;
>>>
>>>
>>> ...I can't spot what's wrong. Can you?
>>>
>>>
>>> Regards, Peter
>>>
>>>
>>> On 02/06/2015 03:38 PM, Maurizio Cimadamore wrote:
>>>> Peter,
>>>> I think I fixed most of the issues in the way; I've been able to
>>>> compile and run some tests successfully.
>>>> Attached is a patch of the changes that are required for the code
>>>> to run correctly; I had to desugar some constructs (i.e. for-each,
>>>> non-static inner class) as all desugared stuff currently has an
>>>> issue in that javac won't emit the special sauce that is required
>>>> by the specializer to correctly specialize a class. That's an issue
>>>> with timing of the compilation pipeline - we are aware of it; but,
>>>> as it's a no trivial fix, it means that, for now, it's better not
>>>> to rely too much of compiler-desugared code.
>>>>
>>>> Maurizio
>>>>
>>>> On 04/02/15 12:42, Maurizio Cimadamore wrote:
>>>>> Compiler fixes have been pushed, I will now look into the runtime
>>>>> issues you are getting...
>>>>>
>>>>> Maurizio
>>>>>
>>>>> On 04/02/15 10:18, Maurizio Cimadamore wrote:
>>>>>> Thanks for the additional feedback, I'll try to get at the bottom
>>>>>> of those issues.
>>>>>>
>>>>>> Maurizio
>>>>>>
>>>>>> On 04/02/15 08:46, Peter Levart wrote:
>>>>>>> Hi Maurizio,
>>>>>>>
>>>>>>> I have now managed to successfully compile the code. Here's the
>>>>>>> updated source:
>>>>>>>
>>>>>>> http://cr.openjdk.java.net/~plevart/misc/valhala-hacks/javany-src.jar
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> But there's a StringIndexOutOfBoundsException thrown from
>>>>>>> specializer when running the following Test:
>>>>>>>
>>>>>>> public class Test {
>>>>>>> public static void main(String[] args) {
>>>>>>> List<int> ints = Arrays.asList(new int[]{1, 2, 3, 4, 5,
>>>>>>> 6, 7, 8});
>>>>>>> Iterator<int> it = ints.iterator();
>>>>>>> while (it.hasNext()) {
>>>>>>> System.out.println(it.next());
>>>>>>> }
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Specializing javany.util.List${0=I}; searching for
>>>>>>> javany/util/List.class (not found)
>>>>>>> Specializing javany.util.List${0=I}; searching for
>>>>>>> javany/util/List.class (found)
>>>>>>> Specializing javany.util.Collection${0=I}; searching for
>>>>>>> javany/util/Collection.class (not found)
>>>>>>> Specializing javany.util.Collection${0=I}; searching for
>>>>>>> javany/util/Collection.class (found)
>>>>>>> Specializing javany.lang.Iterable${0=I}; searching for
>>>>>>> javany/lang/Iterable.class (not found)
>>>>>>> Specializing javany.lang.Iterable${0=I}; searching for
>>>>>>> javany/lang/Iterable.class (found)
>>>>>>> Specializing method
>>>>>>> javany/util/Arrays$asList${0=I}.asList([Ljava/lang/Object;)Ljavany/util/List;
>>>>>>> with class=[] and method=[I]
>>>>>>> Specializing javany.util.Arrays$ArrayList${0=I}; searching for
>>>>>>> javany/util/Arrays$ArrayList.class (not found)
>>>>>>> Specializing javany.util.Arrays$ArrayList${0=I}; searching for
>>>>>>> javany/util/Arrays$ArrayList.class (found)
>>>>>>> Exception in thread "main"
>>>>>>> java.lang.StringIndexOutOfBoundsException: String index out of
>>>>>>> range: 0
>>>>>>> at java.lang.String.charAt(String.java:646)
>>>>>>> at
>>>>>>> jdk.internal.org.objectweb.asm.signature.SignatureReader.accept(SignatureReader.java:107)
>>>>>>> at
>>>>>>> valhalla.specializer.SignatureSpecializer.forType(SignatureSpecializer.java:72)
>>>>>>> at
>>>>>>> valhalla.specializer.Specializer$ManglingMethodVisitor.visitInvokeDynamicInsn(Specializer.java:679)
>>>>>>> at
>>>>>>> jdk.internal.org.objectweb.asm.ClassReader.readCode(ClassReader.java:1507)
>>>>>>> at
>>>>>>> jdk.internal.org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1084)
>>>>>>> at
>>>>>>> jdk.internal.org.objectweb.asm.ClassReader.accept(ClassReader.java:729)
>>>>>>>
>>>>>>> at
>>>>>>> valhalla.specializer.Specializer.specialize(Specializer.java:79)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:409)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:386)
>>>>>>> at java.security.AccessController.doPrivileged(Native
>>>>>>> Method)
>>>>>>> at
>>>>>>> java.net.URLClassLoader.findClass(URLClassLoader.java:385)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
>>>>>>> at
>>>>>>> sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:317)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
>>>>>>> at
>>>>>>> javany.util.Arrays$asList${0=I}/511754216.asList(Arrays.java:810)
>>>>>>> at Test.main(Test.java:10)
>>>>>>>
>>>>>>>
>>>>>>> Appart from that, I learned that when the component type of
>>>>>>> vararg array is an <any> type variable (for example: <any T> T[]
>>>>>>> Arrays.asList(T ... a)), the invocation doesn't compile:
>>>>>>>
>>>>>>> src/Test.java:10: error: method invoked with incorrect number of
>>>>>>> arguments; expected 3, found 1
>>>>>>> List<int> ints = Arrays.<int>asList(1, 2, 3);
>>>>>>> ^
>>>>>>> 1 error
>>>>>>>
>>>>>>>
>>>>>>> Non-specialized code also has problems at runtime:
>>>>>>>
>>>>>>> public class Test {
>>>>>>> public static void main(String[] args) {
>>>>>>> List<String> strings = Arrays.<String>asList("a", "b",
>>>>>>> "c");
>>>>>>> Iterator<String> it = strings.iterator();
>>>>>>> while (it.hasNext()) {
>>>>>>> System.out.println(it.next());
>>>>>>> }
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>>
>>>>>>> Exception in thread "main" java.lang.ClassFormatError: Absent
>>>>>>> Code attribute in method that is not native or abstract in class
>>>>>>> file javany/util/AbstractList
>>>>>>> at java.lang.ClassLoader.defineClass1(Native Method)
>>>>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:762)
>>>>>>> at
>>>>>>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
>>>>>>>
>>>>>>> at
>>>>>>> java.net.URLClassLoader.defineClass(URLClassLoader.java:537)
>>>>>>> at
>>>>>>> java.net.URLClassLoader.access$300(URLClassLoader.java:78)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:438)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:386)
>>>>>>> at java.security.AccessController.doPrivileged(Native
>>>>>>> Method)
>>>>>>> at
>>>>>>> java.net.URLClassLoader.findClass(URLClassLoader.java:385)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
>>>>>>> at
>>>>>>> sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:317)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
>>>>>>> at java.lang.ClassLoader.defineClass1(Native Method)
>>>>>>> at java.lang.ClassLoader.defineClass(ClassLoader.java:762)
>>>>>>> at
>>>>>>> java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
>>>>>>>
>>>>>>> at
>>>>>>> java.net.URLClassLoader.defineClass(URLClassLoader.java:537)
>>>>>>> at
>>>>>>> java.net.URLClassLoader.access$300(URLClassLoader.java:78)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:438)
>>>>>>> at java.net.URLClassLoader$1.run(URLClassLoader.java:386)
>>>>>>> at java.security.AccessController.doPrivileged(Native
>>>>>>> Method)
>>>>>>> at
>>>>>>> java.net.URLClassLoader.findClass(URLClassLoader.java:385)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:426)
>>>>>>> at
>>>>>>> sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:317)
>>>>>>> at java.lang.ClassLoader.loadClass(ClassLoader.java:359)
>>>>>>> at javany.util.Arrays.asList(Arrays.java:810)
>>>>>>> at Test.main(Test.java:10)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Regards, Peter
>>>>>>>
>>>>>>> On 02/03/2015 10:34 PM, Maurizio Cimadamore wrote:
>>>>>>>>
>>>>>>>> On 03/02/15 21:05, Peter Levart wrote:
>>>>>>>>> Hi Maurizio,
>>>>>>>>>
>>>>>>>>> I see. I thought this could be a nice idiom for boxing, since
>>>>>>>>> the following:
>>>>>>>>>
>>>>>>>>> (Object) 42
>>>>>>>>>
>>>>>>>>> ...is legal and results in an Integer object at runtime.
>>>>>>>> I'm not saying this will never work - actually the compiler is
>>>>>>>> currently accepting this kind of idioms, but the specializer
>>>>>>>> does nothing with it, so you'll get runtime errors.
>>>>>>>>>
>>>>>>>>> But I don't know if a checkcast is actually inserted for
>>>>>>>>> (Object). Could javac redundantly do it in case casting to
>>>>>>>>> Object is from expression of <any> type and also equip
>>>>>>>>> checkcast with BMA indicating the type of expression so that
>>>>>>>>> specialization could replace it with boxing code?
>>>>>>>> That will be the way forward, yes
>>>>>>>>
>>>>>>>> Maurizio
>>>>>>>>>
>>>>>>>>> Regards, Peter
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 02/03/2015 08:09 PM, Maurizio Cimadamore wrote:
>>>>>>>>>>
>>>>>>>>>> On 03/02/15 18:46, Maurizio Cimadamore wrote:
>>>>>>>>>>> I will also investigate on the crash you are getting...
>>>>>>>>>> Hi Peter,
>>>>>>>>>> the crash is coming from this code in AbstractCollection (see
>>>>>>>>>> code in bold):
>>>>>>>>>>
>>>>>>>>>> public boolean contains(Object o) {
>>>>>>>>>> __WhereVal(E) {
>>>>>>>>>> Iterator<E> it = iterator();
>>>>>>>>>> if (o == null) {
>>>>>>>>>> return false;
>>>>>>>>>> } else {
>>>>>>>>>> while (it.hasNext())
>>>>>>>>>> *if (o.equals((Object) it.next()))*
>>>>>>>>>> return true;
>>>>>>>>>> }
>>>>>>>>>> return false;
>>>>>>>>>> }
>>>>>>>>>> __WhereRef(E) {
>>>>>>>>>> Iterator<E> it = iterator();
>>>>>>>>>> if (o == null) {
>>>>>>>>>> while (it.hasNext())
>>>>>>>>>> if (it.next() == null)
>>>>>>>>>> return true;
>>>>>>>>>> } else {
>>>>>>>>>> while (it.hasNext())
>>>>>>>>>> if (o.equals(it.next()))
>>>>>>>>>> return true;
>>>>>>>>>> }
>>>>>>>>>> return false;
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> I believe that, apart from the obvious javac bug, the code
>>>>>>>>>> has an issue, as it.next() is supposed to return a value
>>>>>>>>>> there, but you are casting to Object?
>>>>>>>>>>
>>>>>>>>>> For the records - a simpler test case for the bug is this:
>>>>>>>>>>
>>>>>>>>>> class Foo<any E> {
>>>>>>>>>> E e;
>>>>>>>>>> E get() { return e; }
>>>>>>>>>>
>>>>>>>>>> void test() {
>>>>>>>>>> __WhereVal(E) {
>>>>>>>>>> Object o = (Object)get();
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> Maurizio
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>
More information about the valhalla-dev
mailing list