70
70
import com .oracle .svm .hosted .FallbackFeature ;
71
71
import com .oracle .svm .hosted .FeatureImpl ;
72
72
import com .oracle .svm .hosted .FeatureImpl .BeforeCompilationAccessImpl ;
73
+ import com .oracle .svm .hosted .FeatureImpl .DuringAnalysisAccessImpl ;
73
74
import com .oracle .svm .hosted .FeatureImpl .DuringSetupAccessImpl ;
74
75
import com .oracle .svm .hosted .ImageClassLoader ;
75
76
import com .oracle .svm .hosted .analysis .Inflation ;
@@ -163,6 +164,7 @@ public SubstrateAccessor getOrCreateAccessor(Executable member) {
163
164
private SubstrateAccessor createAccessor (Executable member ) {
164
165
MethodPointer expandSignature ;
165
166
MethodPointer directTarget = null ;
167
+ AnalysisMethod targetMethod = null ;
166
168
DynamicHub initializeBeforeInvoke = null ;
167
169
if (member instanceof Method ) {
168
170
int vtableOffset = SubstrateMethodAccessor .STATICALLY_BOUND ;
@@ -171,7 +173,7 @@ private SubstrateAccessor createAccessor(Executable member) {
171
173
172
174
if (member .getDeclaringClass () == MethodHandle .class && (member .getName ().equals ("invoke" ) || member .getName ().equals ("invokeExact" ))) {
173
175
/* Method handles must not be invoked via reflection. */
174
- expandSignature = register (analysisAccess .getMetaAccess ().lookupJavaMethod (methodHandleInvokeErrorMethod ), "Registered in " + ReflectionFeature . class );
176
+ expandSignature = asMethodPointer (analysisAccess .getMetaAccess ().lookupJavaMethod (methodHandleInvokeErrorMethod ));
175
177
} else {
176
178
Method target = (Method ) member ;
177
179
try {
@@ -184,18 +186,17 @@ private SubstrateAccessor createAccessor(Executable member) {
184
186
throw VMError .shouldNotReachHere (ex );
185
187
}
186
188
expandSignature = createExpandSignatureMethod (target , callerSensitiveAdapter );
187
- AnalysisMethod targetMethod = analysisAccess .getMetaAccess ().lookupJavaMethod (target );
189
+ targetMethod = analysisAccess .getMetaAccess ().lookupJavaMethod (target );
188
190
/*
189
191
* The SubstrateMethodAccessor is also used for the implementation of MethodHandle
190
192
* that are created to do an invokespecial. So non-abstract instance methods have
191
193
* both a directTarget and a vtableOffset.
192
194
*/
193
195
if (!targetMethod .isAbstract ()) {
194
- directTarget = register (targetMethod , "Reflection target, registered in " + ReflectionFeature . class );
196
+ directTarget = asMethodPointer (targetMethod );
195
197
}
196
198
if (!targetMethod .canBeStaticallyBound ()) {
197
199
vtableOffset = SubstrateMethodAccessor .OFFSET_NOT_YET_COMPUTED ;
198
- analysisAccess .registerAsRoot (targetMethod , false , "Accessor method for reflection, registered in " + ReflectionFeature .class );
199
200
}
200
201
VMError .guarantee (directTarget != null || vtableOffset != SubstrateMethodAccessor .STATICALLY_BOUND , "Must have either a directTarget or a vtableOffset" );
201
202
if (!targetMethod .isStatic ()) {
@@ -205,7 +206,7 @@ private SubstrateAccessor createAccessor(Executable member) {
205
206
initializeBeforeInvoke = analysisAccess .getHostVM ().dynamicHub (targetMethod .getDeclaringClass ());
206
207
}
207
208
}
208
- return new SubstrateMethodAccessor (member , receiverType , expandSignature , directTarget , vtableOffset , initializeBeforeInvoke , callerSensitiveAdapter );
209
+ return new SubstrateMethodAccessor (member , receiverType , expandSignature , directTarget , targetMethod , vtableOffset , initializeBeforeInvoke , callerSensitiveAdapter );
209
210
210
211
} else {
211
212
Class <?> holder = member .getDeclaringClass ();
@@ -216,31 +217,30 @@ private SubstrateAccessor createAccessor(Executable member) {
216
217
* an interface, array, or primitive type, but we are defensive and throw the
217
218
* exception in that case too.
218
219
*/
219
- expandSignature = register (analysisAccess .getMetaAccess ().lookupJavaMethod (newInstanceErrorMethod ), "Registered in " + ReflectionFeature . class );
220
+ expandSignature = asMethodPointer (analysisAccess .getMetaAccess ().lookupJavaMethod (newInstanceErrorMethod ));
220
221
} else {
221
222
expandSignature = createExpandSignatureMethod (member , false );
222
223
AnalysisMethod constructor = analysisAccess .getMetaAccess ().lookupJavaMethod (member );
223
- AnalysisMethod factoryMethod = FactoryMethodSupport .singleton ().lookup (analysisAccess .getMetaAccess (), constructor , false );
224
- directTarget = register ( factoryMethod , "Factory method, registered in " + ReflectionFeature . class );
224
+ targetMethod = FactoryMethodSupport .singleton ().lookup (analysisAccess .getMetaAccess (), constructor , false );
225
+ directTarget = asMethodPointer ( targetMethod );
225
226
if (!constructor .getDeclaringClass ().isInitialized ()) {
226
227
initializeBeforeInvoke = analysisAccess .getHostVM ().dynamicHub (constructor .getDeclaringClass ());
227
228
}
228
229
}
229
- return new SubstrateConstructorAccessor (member , expandSignature , directTarget , initializeBeforeInvoke );
230
+ return new SubstrateConstructorAccessor (member , expandSignature , directTarget , targetMethod , initializeBeforeInvoke );
230
231
}
231
232
}
232
233
233
234
private MethodPointer createExpandSignatureMethod (Executable member , boolean callerSensitiveAdapter ) {
234
235
return expandSignatureMethods .computeIfAbsent (new SignatureKey (member , callerSensitiveAdapter ), signatureKey -> {
235
236
ResolvedJavaMethod prototype = analysisAccess .getMetaAccess ().lookupJavaMethod (callerSensitiveAdapter ? invokePrototypeForCallerSensitiveAdapter : invokePrototype ).getWrapped ();
236
- return register (new ReflectionExpandSignatureMethod ("invoke_" + signatureKey .uniqueShortName (), prototype , signatureKey .isStatic , signatureKey .argTypes , signatureKey .returnKind ,
237
- signatureKey .callerSensitiveAdapter ), "Registered in " + ReflectionFeature . class );
237
+ return asMethodPointer (new ReflectionExpandSignatureMethod ("invoke_" + signatureKey .uniqueShortName (), prototype , signatureKey .isStatic , signatureKey .argTypes , signatureKey .returnKind ,
238
+ signatureKey .callerSensitiveAdapter ));
238
239
});
239
240
}
240
241
241
- private MethodPointer register (ResolvedJavaMethod method , String reason ) {
242
+ private MethodPointer asMethodPointer (ResolvedJavaMethod method ) {
242
243
AnalysisMethod aMethod = method instanceof AnalysisMethod ? (AnalysisMethod ) method : analysisAccess .getUniverse ().lookup (method );
243
- analysisAccess .registerAsRoot (aMethod , true , reason );
244
244
return new MethodPointer (aMethod );
245
245
}
246
246
@@ -273,6 +273,27 @@ public void duringSetup(DuringSetupAccess a) {
273
273
for (Class <?> primitiveClass : PRIMITIVE_CLASSES ) {
274
274
ClassForNameSupport .registerNegativeQuery (primitiveClass .getName ());
275
275
}
276
+
277
+ access .registerObjectReachableCallback (SubstrateAccessor .class , ReflectionFeature ::onAccessorReachable );
278
+ }
279
+
280
+ private static void onAccessorReachable (DuringAnalysisAccess a , SubstrateAccessor accessor ) {
281
+ DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl ) a ;
282
+
283
+ String reason = "Registered in " + ReflectionFeature .class ;
284
+ ResolvedJavaMethod expandSignatureMethod = ((MethodPointer ) accessor .getExpandSignature ()).getMethod ();
285
+ access .registerAsRoot ((AnalysisMethod ) expandSignatureMethod , true , reason );
286
+
287
+ ResolvedJavaMethod targetMethod = accessor .getTargetMethod ();
288
+ if (targetMethod != null ) {
289
+ if (!targetMethod .isAbstract ()) {
290
+ access .registerAsRoot ((AnalysisMethod ) targetMethod , true , reason );
291
+ }
292
+ /* If the accessor can be used for a virtual call, register virtual root method. */
293
+ if (accessor instanceof SubstrateMethodAccessor mAccessor && mAccessor .getVTableOffset () != SubstrateMethodAccessor .STATICALLY_BOUND ) {
294
+ access .registerAsRoot ((AnalysisMethod ) targetMethod , false , reason );
295
+ }
296
+ }
276
297
}
277
298
278
299
@ Override
0 commit comments