7070import com .oracle .svm .hosted .FallbackFeature ;
7171import com .oracle .svm .hosted .FeatureImpl ;
7272import com .oracle .svm .hosted .FeatureImpl .BeforeCompilationAccessImpl ;
73+ import com .oracle .svm .hosted .FeatureImpl .DuringAnalysisAccessImpl ;
7374import com .oracle .svm .hosted .FeatureImpl .DuringSetupAccessImpl ;
7475import com .oracle .svm .hosted .ImageClassLoader ;
7576import com .oracle .svm .hosted .analysis .Inflation ;
@@ -163,6 +164,7 @@ public SubstrateAccessor getOrCreateAccessor(Executable member) {
163164 private SubstrateAccessor createAccessor (Executable member ) {
164165 MethodPointer expandSignature ;
165166 MethodPointer directTarget = null ;
167+ AnalysisMethod targetMethod = null ;
166168 DynamicHub initializeBeforeInvoke = null ;
167169 if (member instanceof Method ) {
168170 int vtableOffset = SubstrateMethodAccessor .STATICALLY_BOUND ;
@@ -171,7 +173,7 @@ private SubstrateAccessor createAccessor(Executable member) {
171173
172174 if (member .getDeclaringClass () == MethodHandle .class && (member .getName ().equals ("invoke" ) || member .getName ().equals ("invokeExact" ))) {
173175 /* 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 ));
175177 } else {
176178 Method target = (Method ) member ;
177179 try {
@@ -184,18 +186,17 @@ private SubstrateAccessor createAccessor(Executable member) {
184186 throw VMError .shouldNotReachHere (ex );
185187 }
186188 expandSignature = createExpandSignatureMethod (target , callerSensitiveAdapter );
187- AnalysisMethod targetMethod = analysisAccess .getMetaAccess ().lookupJavaMethod (target );
189+ targetMethod = analysisAccess .getMetaAccess ().lookupJavaMethod (target );
188190 /*
189191 * The SubstrateMethodAccessor is also used for the implementation of MethodHandle
190192 * that are created to do an invokespecial. So non-abstract instance methods have
191193 * both a directTarget and a vtableOffset.
192194 */
193195 if (!targetMethod .isAbstract ()) {
194- directTarget = register (targetMethod , "Reflection target, registered in " + ReflectionFeature . class );
196+ directTarget = asMethodPointer (targetMethod );
195197 }
196198 if (!targetMethod .canBeStaticallyBound ()) {
197199 vtableOffset = SubstrateMethodAccessor .OFFSET_NOT_YET_COMPUTED ;
198- analysisAccess .registerAsRoot (targetMethod , false , "Accessor method for reflection, registered in " + ReflectionFeature .class );
199200 }
200201 VMError .guarantee (directTarget != null || vtableOffset != SubstrateMethodAccessor .STATICALLY_BOUND , "Must have either a directTarget or a vtableOffset" );
201202 if (!targetMethod .isStatic ()) {
@@ -205,7 +206,7 @@ private SubstrateAccessor createAccessor(Executable member) {
205206 initializeBeforeInvoke = analysisAccess .getHostVM ().dynamicHub (targetMethod .getDeclaringClass ());
206207 }
207208 }
208- return new SubstrateMethodAccessor (member , receiverType , expandSignature , directTarget , vtableOffset , initializeBeforeInvoke , callerSensitiveAdapter );
209+ return new SubstrateMethodAccessor (member , receiverType , expandSignature , directTarget , targetMethod , vtableOffset , initializeBeforeInvoke , callerSensitiveAdapter );
209210
210211 } else {
211212 Class <?> holder = member .getDeclaringClass ();
@@ -216,31 +217,30 @@ private SubstrateAccessor createAccessor(Executable member) {
216217 * an interface, array, or primitive type, but we are defensive and throw the
217218 * exception in that case too.
218219 */
219- expandSignature = register (analysisAccess .getMetaAccess ().lookupJavaMethod (newInstanceErrorMethod ), "Registered in " + ReflectionFeature . class );
220+ expandSignature = asMethodPointer (analysisAccess .getMetaAccess ().lookupJavaMethod (newInstanceErrorMethod ));
220221 } else {
221222 expandSignature = createExpandSignatureMethod (member , false );
222223 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 );
225226 if (!constructor .getDeclaringClass ().isInitialized ()) {
226227 initializeBeforeInvoke = analysisAccess .getHostVM ().dynamicHub (constructor .getDeclaringClass ());
227228 }
228229 }
229- return new SubstrateConstructorAccessor (member , expandSignature , directTarget , initializeBeforeInvoke );
230+ return new SubstrateConstructorAccessor (member , expandSignature , directTarget , targetMethod , initializeBeforeInvoke );
230231 }
231232 }
232233
233234 private MethodPointer createExpandSignatureMethod (Executable member , boolean callerSensitiveAdapter ) {
234235 return expandSignatureMethods .computeIfAbsent (new SignatureKey (member , callerSensitiveAdapter ), signatureKey -> {
235236 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 ));
238239 });
239240 }
240241
241- private MethodPointer register (ResolvedJavaMethod method , String reason ) {
242+ private MethodPointer asMethodPointer (ResolvedJavaMethod method ) {
242243 AnalysisMethod aMethod = method instanceof AnalysisMethod ? (AnalysisMethod ) method : analysisAccess .getUniverse ().lookup (method );
243- analysisAccess .registerAsRoot (aMethod , true , reason );
244244 return new MethodPointer (aMethod );
245245 }
246246
@@ -273,6 +273,27 @@ public void duringSetup(DuringSetupAccess a) {
273273 for (Class <?> primitiveClass : PRIMITIVE_CLASSES ) {
274274 ClassForNameSupport .registerNegativeQuery (primitiveClass .getName ());
275275 }
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+ }
276297 }
277298
278299 @ Override
0 commit comments