experiences with prototype

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Feb 6 14:38:56 UTC 2015


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

-------------- next part --------------
diff -r src-old/javany/util/AbstractList.java src-new/javany/util/AbstractList.java
331c331
<         return new Itr();
---
>         return new Itr<>(this);
372c372
<         return new ListItr(index);
---
>         return new ListItr<>(this, index);
375c375,383
<     private class Itr implements Iterator<E> {
---
>     private static class Itr<any E> implements Iterator<E> {
> 
> 		AbstractList<E> this$0;
> 
> 		Itr(AbstractList<E> this$0) {
> 			this.this$0 = this$0;
> 			expectedModCount = this$0.modCount;
>         }
> 
393c401
<         int expectedModCount = modCount;
---
>         int expectedModCount;
396c404
<             return cursor != size();
---
>             return cursor != this$0.size();
403c411
<                 E next = get(i);
---
>                 E next = this$0.get(i);
419c427
<                 AbstractList.this.remove(lastRet);
---
>                 this$0.remove(lastRet);
423c431
<                 expectedModCount = modCount;
---
>                 expectedModCount = this$0.modCount;
430c438
<             if (modCount != expectedModCount)
---
>             if (this$0.modCount != expectedModCount)
435,436c443,446
<     private class ListItr extends Itr implements ListIterator<E> {
<         ListItr(int index) {
---
>     private static class ListItr<any E> extends Itr<E> implements ListIterator<E> {
> 
>         ListItr(AbstractList<E> this$0, int index) {
> 			super(this$0);
448c458
<                 E previous = get(i);
---
>                 E previous = this$0.get(i);
471,472c481,482
<                 AbstractList.this.set(lastRet, e);
<                 expectedModCount = modCount;
---
>                 this$0.set(lastRet, e);
>                 expectedModCount = this$0.modCount;
483c493
<                 AbstractList.this.add(i, e);
---
>                 this$0.add(i, e);
486c496
<                 expectedModCount = modCount;
---
>                 expectedModCount = this$0.modCount;
Only in src-new/javany/util: AbstractList.java~
diff -r src-old/javany/util/Arrays.java src-new/javany/util/Arrays.java
823c823
<             a = Objects.requireNonNull(array);
---
>             a = (E[])Objects.requireNonNull(array);
916c916,917
<             for (E e : a) {
---
>             for (int i = 0; i < a.length ; i++) {
> 				E e = a[i];
Only in src-new/javany/util: Arrays.java~
diff -r src-old/javany/util/List.java src-new/javany/util/List.java
482c482,483
<         for (E e : a) {
---
>         for (int idx = 0; idx < a.length ; idx++) {
>             E e = a[idx];
Only in src-new/javany/util: List.java~
diff -r src-old/Test.java src-new/Test.java
9,10c9,18
<     public static void main(String[] args) {
<         List<String> strings = Arrays.<String>asList("a", "b", "c");
---
> 	static void testInt() {
> 		List<int> ints = Arrays.asList(1, 2, 3);
>         Iterator<int> it = ints.iterator();
>         while (it.hasNext()) {
>             System.out.println(it.next());
>         }
>     }
> 
> 	static void testString() {
> 		List<String> strings = Arrays.asList("a", "b", "c");
14a23,27
>     }
> 
>     public static void main(String[] args) {
>         testString();
> 		testInt();


More information about the valhalla-dev mailing list