author | martin |
Tue, 15 Sep 2015 21:56:04 -0700 | |
changeset 32649 | 2ee9017c7597 |
parent 13423 | 17843fff200d |
child 40684 | 2e37c119dc2a |
permissions | -rw-r--r-- |
13423
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
1 |
/* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
2 |
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
4 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
5 |
* This code is free software; you can redistribute it and/or modify it |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
7 |
* published by the Free Software Foundation. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
8 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
13 |
* accompanied this code). |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
14 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
15 |
* You should have received a copy of the GNU General Public License version |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
18 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
21 |
* questions. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
22 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
23 |
*/ |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
24 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
25 |
/* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
26 |
7157574 method handles returned by reflective lookup API sometimes have wrong receiver type |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
27 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
28 |
When an inherited non-static field or method is looked up in a class C using Lookup.findVirtual(C...), etc., the JSR 292 API, the first argument of the resulting method handle must be the receiver ('this'), and must be the requested class (or more specific, in the case of findSpecial or a lookup of a protected method). |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
29 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
30 |
But currently, if a supertype T defines the looked-up method or field and C inherits it, the returned method handle might have the more specific initial type T. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
31 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
32 |
The relevant javadoc (and 292 spec.) is as follows: |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
33 |
* The formal parameter {@code this} stands for the self-reference of type {@code C}; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
34 |
* if it is present, it is always the leading argument to the method handle invocation. |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
35 |
* (In the case of some {@code protected} members, {@code this} may be |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
36 |
* restricted in type to the lookup class; see below.) |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
37 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
38 |
Because of this bug, all of the assertions fail in the following example: |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
39 |
*/ |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
40 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
41 |
/* @test |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
42 |
* @bug 7157574 |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
43 |
* @summary method handles returned by reflective lookup API sometimes have wrong receiver type |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
44 |
* |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
45 |
* @run main Test7157574 |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
46 |
*/ |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
47 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
48 |
import java.lang.invoke.*; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
49 |
import static java.lang.invoke.MethodHandles.*; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
50 |
import static java.lang.invoke.MethodType.*; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
51 |
public class Test7157574 { |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
52 |
interface Intf { void ig1(); void ig2(); void ig3(); void ig4(); void m1(); } |
32649
2ee9017c7597
8136583: Core libraries should use blessed modifier order
martin
parents:
13423
diff
changeset
|
53 |
abstract static class Super implements Intf { public abstract void m2(); public int f2; } |
2ee9017c7597
8136583: Core libraries should use blessed modifier order
martin
parents:
13423
diff
changeset
|
54 |
abstract static class Sub extends Super { } |
13423
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
55 |
public static void main(String... av) throws Throwable { |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
56 |
MethodHandle m1 = lookup().findVirtual(Sub.class, "m1", methodType(void.class)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
57 |
System.out.println(m1); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
58 |
MethodHandle m2 = lookup().findVirtual(Sub.class, "m2", methodType(void.class)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
59 |
System.out.println(m2); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
60 |
MethodHandle f2 = lookup().findGetter(Sub.class, "f2", int.class); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
61 |
System.out.println(f2); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
62 |
MethodHandle f2s = lookup().findSetter(Sub.class, "f2", int.class); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
63 |
System.out.println(f2s); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
64 |
MethodHandle chc = lookup().findVirtual(Sub.class, "hashCode", methodType(int.class)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
65 |
System.out.println(chc); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
66 |
MethodHandle ihc = lookup().findVirtual(Intf.class, "hashCode", methodType(int.class)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
67 |
System.out.println(ihc); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
68 |
assertEquals(Sub.class, m1.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
69 |
assertEquals(Sub.class, m2.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
70 |
assertEquals(Sub.class, f2.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
71 |
assertEquals(Sub.class, f2s.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
72 |
assertEquals(Sub.class, chc.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
73 |
assertEquals(Intf.class, ihc.type().parameterType(0)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
74 |
// test the MHs on a concrete version of Sub |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
75 |
class C extends Sub { |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
76 |
public void m1() { this.f2 = -1; } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
77 |
public void m2() { this.f2 = -2; } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
78 |
// Pack the vtable of Intf with leading junk: |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
79 |
private void ig() { throw new RuntimeException(); } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
80 |
public void ig1() { ig(); } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
81 |
public void ig2() { ig(); } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
82 |
public void ig3() { ig(); } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
83 |
public void ig4() { ig(); } |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
84 |
} |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
85 |
testConcrete(new C(), m1, m2, f2, f2s, chc, ihc); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
86 |
} |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
87 |
private static void testConcrete(Sub s, |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
88 |
MethodHandle m1, MethodHandle m2, |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
89 |
MethodHandle f2, MethodHandle f2s, |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
90 |
MethodHandle chc, MethodHandle ihc |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
91 |
) throws Throwable { |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
92 |
s.f2 = 0; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
93 |
m1.invokeExact(s); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
94 |
assertEquals(-1, s.f2); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
95 |
m2.invokeExact(s); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
96 |
assertEquals(-2, s.f2); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
97 |
s.f2 = 2; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
98 |
assertEquals(2, (int) f2.invokeExact(s)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
99 |
f2s.invokeExact(s, 0); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
100 |
assertEquals(0, s.f2); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
101 |
assertEquals(s.hashCode(), (int) chc.invokeExact(s)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
102 |
assertEquals(s.hashCode(), (int) ihc.invokeExact((Intf)s)); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
103 |
} |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
104 |
|
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
105 |
private static void assertEquals(Object expect, Object observe) { |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
106 |
if (java.util.Objects.equals(expect, observe)) return; |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
107 |
String msg = ("expected "+expect+" but observed "+observe); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
108 |
System.out.println("FAILED: "+msg); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
109 |
throw new AssertionError(msg); |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
110 |
} |
17843fff200d
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
diff
changeset
|
111 |
} |