experiences with prototype
Peter Levart
peter.levart at gmail.com
Sun Feb 8 10:27:42 UTC 2015
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