24
24
*/
25
25
package java .lang .invoke ;
26
26
27
+ import jdk .internal .vm .annotation .DontInline ;
27
28
import jdk .internal .vm .annotation .ForceInline ;
28
29
import jdk .internal .vm .annotation .Stable ;
29
30
33
34
import java .util .ArrayList ;
34
35
import java .util .List ;
35
36
37
+ import static java .lang .invoke .MethodHandleNatives .Constants .REF_invokeStatic ;
38
+
36
39
/**
37
40
* A var handle form containing a set of member name, one for each operation.
38
41
* Each member characterizes a static method.
39
42
*/
40
43
final class VarForm {
41
44
45
+ final Class <?> implClass ;
46
+
42
47
final @ Stable MethodType [] methodType_table ;
43
48
44
49
final @ Stable MemberName [] memberName_table ;
45
50
46
51
VarForm (Class <?> implClass , Class <?> receiver , Class <?> value , Class <?>... intermediate ) {
47
52
this .methodType_table = new MethodType [VarHandle .AccessType .values ().length ];
53
+ this .memberName_table = new MemberName [VarHandle .AccessMode .values ().length ];
54
+ this .implClass = implClass ;
48
55
if (receiver == null ) {
49
56
initMethodTypes (value , intermediate );
50
57
} else {
@@ -53,37 +60,46 @@ final class VarForm {
53
60
System .arraycopy (intermediate , 0 , coordinates , 1 , intermediate .length );
54
61
initMethodTypes (value , coordinates );
55
62
}
56
-
57
- // TODO lazily calculate
58
- this .memberName_table = linkFromStatic (implClass );
59
63
}
60
64
65
+ // Used by IndirectVarHandle
61
66
VarForm (Class <?> value , Class <?>[] coordinates ) {
62
67
this .methodType_table = new MethodType [VarHandle .AccessType .values ().length ];
63
68
this .memberName_table = null ;
69
+ this .implClass = null ;
64
70
initMethodTypes (value , coordinates );
65
71
}
66
72
67
73
void initMethodTypes (Class <?> value , Class <?>... coordinates ) {
74
+ Class <?> erasedValue = MethodTypeForm .canonicalize (value , MethodTypeForm .ERASE );
75
+ Class <?>[] erasedCoordinates = MethodTypeForm .canonicalizeAll (coordinates , MethodTypeForm .ERASE );
76
+
77
+ if (erasedValue != null ) {
78
+ value = erasedValue ;
79
+ }
80
+ if (erasedCoordinates != null ) {
81
+ coordinates = erasedCoordinates ;
82
+ }
83
+
84
+ MethodType type = MethodType .methodType (value , coordinates );
85
+
68
86
// (Receiver, <Intermediates>)Value
69
- methodType_table [VarHandle .AccessType .GET .ordinal ()] =
70
- MethodType .methodType (value , coordinates ).erase ();
87
+ methodType_table [VarHandle .AccessType .GET .ordinal ()] = type ;
88
+
89
+ // (Receiver, <Intermediates>, Value)Value
90
+ type = methodType_table [VarHandle .AccessType .GET_AND_UPDATE .ordinal ()] =
91
+ type .appendParameterTypes (value );
71
92
72
93
// (Receiver, <Intermediates>, Value)void
73
- methodType_table [VarHandle .AccessType .SET .ordinal ()] =
74
- MethodType .methodType (void .class , coordinates ).appendParameterTypes (value ).erase ();
94
+ methodType_table [VarHandle .AccessType .SET .ordinal ()] = type .changeReturnType (void .class );
75
95
76
- // (Receiver, <Intermediates>, Value)Value
77
- methodType_table [VarHandle .AccessType .GET_AND_UPDATE .ordinal ()] =
78
- MethodType . methodType ( value , coordinates ). appendParameterTypes (value ). erase ( );
96
+ // (Receiver, <Intermediates>, Value, Value )Value
97
+ type = methodType_table [VarHandle .AccessType .COMPARE_AND_EXCHANGE .ordinal ()] =
98
+ type . appendParameterTypes (value );
79
99
80
100
// (Receiver, <Intermediates>, Value, Value)boolean
81
101
methodType_table [VarHandle .AccessType .COMPARE_AND_SET .ordinal ()] =
82
- MethodType .methodType (boolean .class , coordinates ).appendParameterTypes (value , value ).erase ();
83
-
84
- // (Receiver, <Intermediates>, Value, Value)Value
85
- methodType_table [VarHandle .AccessType .COMPARE_AND_EXCHANGE .ordinal ()] =
86
- MethodType .methodType (value , coordinates ).appendParameterTypes (value , value ).erase ();
102
+ type .changeReturnType (boolean .class );
87
103
}
88
104
89
105
@ ForceInline
@@ -93,14 +109,30 @@ final MethodType getMethodType(int type) {
93
109
94
110
@ ForceInline
95
111
final MemberName getMemberName (int mode ) {
96
- // TODO calculate lazily
97
- MemberName mn = memberName_table [mode ];
112
+ MemberName mn = getMemberNameOrNull (mode );
98
113
if (mn == null ) {
99
114
throw new UnsupportedOperationException ();
100
115
}
101
116
return mn ;
102
117
}
103
118
119
+ @ ForceInline
120
+ final MemberName getMemberNameOrNull (int mode ) {
121
+ MemberName mn = memberName_table [mode ];
122
+ if (mn == null ) {
123
+ mn = resolveMemberName (mode );
124
+ }
125
+ return mn ;
126
+ }
127
+
128
+ @ DontInline
129
+ MemberName resolveMemberName (int mode ) {
130
+ AccessMode value = AccessMode .values ()[mode ];
131
+ String methodName = value .methodName ();
132
+ MethodType type = methodType_table [value .at .ordinal ()].insertParameterTypes (0 , VarHandle .class );
133
+ return memberName_table [mode ] = MethodHandles .Lookup .IMPL_LOOKUP
134
+ .resolveOrNull (REF_invokeStatic , implClass , methodName , type );
135
+ }
104
136
105
137
@ Stable
106
138
MethodType [] methodType_V_table ;
@@ -125,25 +157,4 @@ final MethodType getMethodType_V(int type) {
125
157
}
126
158
return table [type ];
127
159
}
128
-
129
-
130
- /**
131
- * Link all signature polymorphic methods.
132
- */
133
- private static MemberName [] linkFromStatic (Class <?> implClass ) {
134
- MemberName [] table = new MemberName [AccessMode .values ().length ];
135
-
136
- for (Class <?> c = implClass ; c != VarHandle .class ; c = c .getSuperclass ()) {
137
- for (Method m : c .getDeclaredMethods ()) {
138
- if (Modifier .isStatic (m .getModifiers ())) {
139
- AccessMode am = AccessMode .methodNameToAccessMode .get (m .getName ());
140
- if (am != null ) {
141
- assert table [am .ordinal ()] == null ;
142
- table [am .ordinal ()] = new MemberName (m );
143
- }
144
- }
145
- }
146
- }
147
- return table ;
148
- }
149
160
}
0 commit comments