1010import java .io .File ;
1111import java .io .FileReader ;
1212import java .io .InputStream ;
13+ import java .lang .reflect .Field ;
14+ import java .lang .reflect .Method ;
1315import java .net .URI ;
1416import java .net .URL ;
1517import java .net .http .HttpClient ;
1618import java .net .http .HttpRequest ;
1719import java .net .http .HttpResponse ;
1820import java .nio .file .Files ;
21+ import java .util .ArrayList ;
22+ import java .util .HashSet ;
23+ import java .util .List ;
24+ import java .util .Set ;
1925import java .util .zip .ZipEntry ;
2026import java .util .zip .ZipInputStream ;
2127
@@ -149,6 +155,36 @@ private static MethodDef getMethod(ClassDef classDef, String namespace, String n
149155 return null ;
150156 }
151157
158+ private static Set <MethodDef > getOverloadedMethod (ClassDef classDef , String namespace , String name ) {
159+ Set <MethodDef > out = new HashSet <>();
160+ for (MethodDef def : classDef .getMethods ()) {
161+ if (def .getName (namespace ).equals (name )) {
162+ out .add (def );
163+ }
164+ }
165+
166+ try {
167+ Class <?> currentClass = Class .forName (classDef .getName (current ()).replace ('/' , '.' ));
168+ Class <?> parent = currentClass .getSuperclass ();
169+ if (parent != null ) {
170+ ClassDef def = getClass (current (), parent .getName ());
171+ if (def != null ) {
172+ out .addAll (getOverloadedMethod (def , namespace , name ));
173+ }
174+ }
175+ for (Class <?> iface : currentClass .getInterfaces ()) {
176+ ClassDef def = getClass (current (), iface .getName ());
177+ if (def != null ) {
178+ out .addAll (getOverloadedMethod (def , namespace , name ));
179+ }
180+ }
181+ } catch (ClassNotFoundException e ) {
182+ throw new RuntimeException (e );
183+ }
184+
185+ return out ;
186+ }
187+
152188 public static String current () {
153189 return current ;
154190 }
@@ -181,6 +217,20 @@ public static String remapMethod(String classNamespace, String className, String
181217 return res ;
182218 }
183219
220+ public static Set <String > remapOverloadedMethod (String classNamespace , String className , String from , String to , String name ) {
221+ ClassDef classDef = Mappings .getClass (classNamespace , className );
222+ if (classDef == null ) return new HashSet <>(Set .of (name ));
223+ Set <MethodDef > methodDefs = getOverloadedMethod (classDef , from , name );
224+ if (methodDefs .size () == 0 ) return new HashSet <>(Set .of (name ));
225+ Set <String > out = new HashSet <>();
226+ for (MethodDef def : methodDefs ) {
227+ String res = def .getName (to );
228+ if (res != null ) out .add (res );
229+ }
230+ if (out .size () == 0 ) return new HashSet <>(Set .of (name ));
231+ return out ;
232+ }
233+
184234 @ SuppressWarnings ("unused" )
185235 public static String graalRemapClass (String clazz ) {
186236 return remapClass ("named" , current (), clazz );
@@ -192,7 +242,69 @@ public static String graalRemapField(Class<?> clazz, String field) {
192242 }
193243
194244 @ SuppressWarnings ("unused" )
195- public static String graalRemapMethod (Class <?> clazz , String method ) {
196- return remapMethod (current (), clazz .getName (), "named" , current (), method );
245+ public static Object graalRemapOverloadedMethod (Object hostCtx , Class <?> clazz , String searchName , boolean onlyStatic ) {
246+ try {
247+ Set <String > names = remapOverloadedMethod (current (), clazz .getName (), "named" , current (), searchName );
248+
249+ Class <?> hostClassDescClass = Class .forName ("com.oracle.truffle.host.HostClassDesc" );
250+ Class <?> hostContextClass = Class .forName ("com.oracle.truffle.host.HostContext" );
251+ Class <?> overloadedMethodClass = Class .forName ("com.oracle.truffle.host.HostMethodDesc$OverloadedMethod" );
252+ Class <?> singleMethodClass = Class .forName ("com.oracle.truffle.host.HostMethodDesc$SingleMethod" );
253+ Class <?> hostMethodDescClass = Class .forName ("com.oracle.truffle.host.HostMethodDesc" );
254+ Class <?> membersClass = Class .forName ("com.oracle.truffle.host.HostClassDesc$Members" );
255+
256+ Method forClassMethod = hostClassDescClass .getDeclaredMethod ("forClass" , hostContextClass , Class .class );
257+ forClassMethod .setAccessible (true );
258+
259+ Object hostClassDesc = forClassMethod .invoke (null , hostCtx , clazz );
260+
261+ List <Object > overloads = new ArrayList <>();
262+ Method lookupMethodMethod = hostClassDescClass .getDeclaredMethod ("lookupMethod" , String .class , boolean .class );
263+ Method lookupMethodBySignatureMethod = hostClassDescClass .getDeclaredMethod ("lookupMethodBySignature" , String .class , boolean .class );
264+ Method lookupMethodByJNINameMethod = hostClassDescClass .getDeclaredMethod ("lookupMethodByJNIName" , String .class , boolean .class );
265+
266+ lookupMethodMethod .setAccessible (true );
267+ lookupMethodBySignatureMethod .setAccessible (true );
268+ lookupMethodByJNINameMethod .setAccessible (true );
269+
270+ Field overloadsField = overloadedMethodClass .getDeclaredField ("overloads" );
271+ overloadsField .setAccessible (true );
272+
273+ for (String name : names ) {
274+ overloads .add (lookupMethodMethod .invoke (hostClassDesc , name , onlyStatic ));
275+ overloads .add (lookupMethodBySignatureMethod .invoke (hostClassDesc , name , onlyStatic ));
276+ overloads .add (lookupMethodByJNINameMethod .invoke (hostClassDesc , name , onlyStatic ));
277+ }
278+
279+ while (overloads .contains (null )) {
280+ overloads .remove (null );
281+ }
282+
283+ List <Object > singleMethods = new ArrayList <>();
284+
285+ for (Object possibleMethod : overloads ) {
286+ if (singleMethodClass .isInstance (possibleMethod )) {
287+ singleMethods .add (possibleMethod );
288+ } else {
289+ singleMethods .addAll (List .of ((Object []) overloadsField .get (possibleMethod )));
290+ }
291+ }
292+
293+ if (singleMethods .size () == 0 ) {
294+ return null ;
295+ }
296+
297+ Method mergeMethod = membersClass .getDeclaredMethod ("merge" , hostMethodDescClass , hostMethodDescClass );
298+ mergeMethod .setAccessible (true );
299+
300+ Object out = singleMethods .get (0 );
301+ for (int i = 1 ; i < singleMethods .size (); i ++) {
302+ out = mergeMethod .invoke (null , out , singleMethods .get (i ));
303+ }
304+
305+ return out ;
306+ } catch (Exception e ) {
307+ throw new RuntimeException (e );
308+ }
197309 }
198310}
0 commit comments