@@ -62,8 +62,6 @@ public final class VTable {
62
62
*
63
63
* @param targetClass The type for which method tables should be created
64
64
* @param verbose Whether all declared methods should be unconditionally added to the vtable.
65
- * See {@link PartialMethod#sameOverrideAccess(PartialType, MethodAccess)} for more
66
- * details.
67
65
* @param allowInterfaceResolvingToPrivate Whether the runtime allows selection of interface
68
66
* invokes to select private methods. Requires implementing
69
67
* {@link PartialType#lookupOverrideWithPrivate(Symbol, Symbol)}.
@@ -79,6 +77,13 @@ public static <C extends TypeAccess<C, M, F>, M extends MethodAccess<C, M, F>, F
79
77
return new Builder <>(targetClass , verbose , allowInterfaceResolvingToPrivate ).build ();
80
78
}
81
79
80
+ /**
81
+ * Returns whether a given method may appear in a vtable.
82
+ */
83
+ public static <C extends TypeAccess <C , M , F >, M extends MethodAccess <C , M , F >, F extends FieldAccess <C , M , F >> boolean isVirtualEntry (PartialMethod <C , M , F > m ) {
84
+ return !m .isPrivate () && !m .isStatic () && !m .isConstructor () && !m .isClassInitializer ();
85
+ }
86
+
82
87
private static final class Builder <C extends TypeAccess <C , M , F >, M extends MethodAccess <C , M , F >, F extends FieldAccess <C , M , F >> {
83
88
private final boolean verbose ;
84
89
private final boolean allowInterfaceResolvingToPrivate ;
@@ -124,7 +129,7 @@ private void buildLocations() {
124
129
125
130
private void assignCandidateTargets () {
126
131
for (PartialMethod <C , M , F > impl : targetClass .getDeclaredMethodsList ()) {
127
- if (!impl . isVirtualEntry ()) {
132
+ if (!isVirtualEntry (impl )) {
128
133
continue ;
129
134
}
130
135
MethodKey k = MethodKey .of (impl );
@@ -159,7 +164,7 @@ private void resolveVirtual() throws MethodTableException {
159
164
MethodTableException .Kind .IllegalClassChangeError );
160
165
}
161
166
vtable .add (target );
162
- if (!target . sameOverrideAccess (targetClass , m )) {
167
+ if (!sameOverrideAccess (target , m )) {
163
168
currentLocations .markForPopulation ();
164
169
}
165
170
} else {
@@ -169,7 +174,7 @@ private void resolveVirtual() throws MethodTableException {
169
174
}
170
175
assert vtable .size () == parentTable .size ();
171
176
for (PartialMethod <C , M , F > impl : targetClass .getDeclaredMethodsList ()) {
172
- if (!impl . isVirtualEntry ()) {
177
+ if (!isVirtualEntry (impl )) {
173
178
continue ;
174
179
}
175
180
if (verbose ) {
@@ -191,7 +196,7 @@ private void resolveInterfaces() {
191
196
List <PartialMethod <C , M , F >> table = new ArrayList <>(cursor .getValue ().size ());
192
197
193
198
for (M m : parentTable ) {
194
- if (!m . isVirtualEntry ()) {
199
+ if (!isVirtualEntry (m )) {
195
200
// This should ideally not happen, but we must respect the decisions
196
201
// previously made for the tables of our super-interfaces.
197
202
table .add (m );
@@ -208,7 +213,7 @@ private void resolveInterfaces() {
208
213
private void registerFromTable (List <M > table , LocationKind kind ) {
209
214
int index = 0 ;
210
215
for (M m : table ) {
211
- if (!m . isVirtualEntry ()) {
216
+ if (!isVirtualEntry (m )) {
212
217
continue ;
213
218
}
214
219
MethodKey k = MethodKey .of (m );
@@ -222,21 +227,40 @@ private void registerFromTable(List<M> table, LocationKind kind) {
222
227
}
223
228
224
229
private boolean canOverride (PartialMethod <C , M , F > candidate , M parentMethod , int vtableIndex ) {
225
- if (candidate . canOverride (targetClass , parentMethod )) {
230
+ if (canOverride (candidate , parentMethod )) {
226
231
return true ;
227
232
}
228
233
C parentClass = parentMethod .getDeclaringClass ().getSuperClass ();
229
234
M currentMethod ;
230
235
while (parentClass != null &&
231
236
(currentMethod = parentClass .lookupVTableEntry (vtableIndex )) != null ) {
232
- if (candidate . canOverride (targetClass , currentMethod )) {
237
+ if (canOverride (candidate , currentMethod )) {
233
238
return true ;
234
239
}
235
240
parentClass = parentClass .getSuperClass ();
236
241
}
237
242
return false ;
238
243
}
239
244
245
+ private boolean canOverride (PartialMethod <C , M , F > candidate , M parentMethod ) {
246
+ assert isVirtualEntry (candidate ) && isVirtualEntry (parentMethod );
247
+ assert candidate .getSymbolicName () == parentMethod .getSymbolicName () && candidate .getSymbolicSignature () == parentMethod .getSymbolicSignature ();
248
+ if (parentMethod .isPublic () || parentMethod .isProtected ()) {
249
+ return true ;
250
+ }
251
+ return targetClass .sameRuntimePackage (parentMethod .getDeclaringClass ());
252
+ }
253
+
254
+ private boolean sameOverrideAccess (PartialMethod <C , M , F > candidate , M parentMethod ) {
255
+ assert isVirtualEntry (candidate ) && isVirtualEntry (parentMethod );
256
+ assert candidate .getSymbolicName () == parentMethod .getSymbolicName () && candidate .getSymbolicSignature () == parentMethod .getSymbolicSignature ();
257
+ if (candidate .isPublic () || candidate .isProtected ()) {
258
+ return parentMethod .isPublic () || parentMethod .isProtected ();
259
+ }
260
+ assert candidate .isPackagePrivate ();
261
+ return parentMethod .isPackagePrivate () && targetClass .sameRuntimePackage (parentMethod .getDeclaringClass ());
262
+ }
263
+
240
264
private record MethodKey (Symbol <Name > name , Symbol <Signature > signature ) {
241
265
static <C extends TypeAccess <C , M , F >, M extends MethodAccess <C , M , F >, F extends FieldAccess <C , M , F >> MethodKey of (PartialMethod <C , M , F > method ) {
242
266
return new MethodKey (method .getSymbolicName (), method .getSymbolicSignature ());
0 commit comments