1010import java .lang .invoke .MethodHandles .Lookup ;
1111import java .lang .invoke .MethodType ;
1212import java .lang .invoke .VarHandle ;
13- import java .lang .invoke .VarHandle .AccessMode ;
1413import java .util .Collections ;
1514import java .util .HashMap ;
1615import java .util .Map ;
@@ -1311,43 +1310,12 @@ public static final class SMUtil {
13111310 */
13121311 static final MethodHandle asJavaBoolean ;
13131312
1314- /**
1315- * Method handle on {@link BaseType#cast(PyType)}, which checks
1316- * a type is a {@code BaseType}, therefore "one of ours". This
1317- * may raise {@code TypeError}.
1318- */
1319- static final MethodHandle asBaseType ;
1320-
1321- /**
1322- * Method handle applicable to a {@code SpecialMethod} and a
1323- * {@link BaseType}, that retrieves the cached method handle
1324- * from the provided type. It is equivalent to
1325- * {@link SpecialMethod#handle(Representation)}, except it does
1326- * not check whether the cache exists for the
1327- * {@code SpecialMethod}. (If {@code sm.hasCache()} is false,
1328- * you should invoke {@code sm.generic}. It is used to form
1329- * {@code sm.bounce}.
1330- */
1331- static final MethodHandle getCache ;
1332-
1333- private static final Class <BaseType > BT = BaseType .class ;
1334- private static final Class <Representation > REP =
1335- Representation .class ;
1336- private static final Class <MethodHandle > MH =
1337- MethodHandle .class ;
1338-
13391313 static {
13401314 try {
13411315 asJavaInt = LOOKUP .findStatic (PyLong .class , "asInt" ,
13421316 MethodType .methodType (I , O ));
13431317 asJavaBoolean = LOOKUP .findStatic (Abstract .class ,
13441318 "isTrue" , MethodType .methodType (B , O ));
1345- asBaseType = LOOKUP .findStatic (BT , "cast" ,
1346- MethodType .methodType (BT , T ));
1347- // MethodType here has to match actual of sm.cache
1348- getCache = MethodHandles .varHandleExactInvoker (
1349- AccessMode .GET , MethodType .methodType (MH , REP ));
1350-
13511319 } catch (NoSuchMethodException | IllegalAccessException e ) {
13521320 // Handle lookup fails somewhere
13531321 throw new InterpreterError (e ,
@@ -1449,55 +1417,47 @@ static MethodHandle slotMH(SpecialMethod sm) {
14491417 }
14501418
14511419 /**
1452- * Helper for {@link SpecialMethod} providing a method handle
1453- * that accesses the special method cache on the type of
1454- * {@code self}, and invokes the handle it finds there.
1420+ * Helper for {@link SpecialMethod} providing a method handle on
1421+ * the corresponding trampoline method (e.g.
1422+ * {@link #op_neg(BaseType, Object)}) invokes the special method
1423+ * cache on the type of {@code self}. We place this type of
1424+ * handle in a {@link SharedRepresentation}, and the type is
1425+ * always a {@link ReplaceableType}.
14551426 *
14561427 * @param sm to access on the type of {@code self}
14571428 * @return a handle that looks up and calls {@code sm}
14581429 */
14591430 static MethodHandle bounceMH (SpecialMethod sm ) {
14601431
14611432 // We aim to create:
1462- // bounce = λ(s, ...): sm.cache (type(s)).invoke(s, ...)
1433+ // bounce = λ(s, ...): trampoline(sm) (type(s), s, ...)
14631434 try {
1435+ /*
1436+ * Find the trampoline method handle smt. The signature
1437+ * is that of the special method, with PyType inserted
1438+ * first.
1439+ */
1440+ // smt = λ(t,s): BaseType.cast(t,s,...)
1441+ MethodHandle smt = LOOKUP .findStatic (
1442+ SpecialMethod .class , sm .name (),
1443+ sm .signature .type .insertParameterTypes (0 , T ));
1444+
14641445 /*
14651446 * As bounce is only published from shared
1466- * representations, we can use WithClass.getType().
1447+ * representations, we can rely on WithClass.getType().
14671448 */
1468- // type = λ(s): (Representation) BaseType.cast(type(s))
1449+ // type = λ(s): BaseType.cast(type(s))
14691450 MethodHandle type = LOOKUP .findVirtual (WithClass .class ,
14701451 "getType" , MethodType .methodType (T ));
1471- type = MethodHandles .filterReturnValue (type ,
1472- asBaseType );
14731452 /*
14741453 * It will be safe to cast from Object to WithClass as
14751454 * the self-class was mapped to a SharedRepresentation.
1476- * Also from BaseType to Representation, obviously.
14771455 */
1478- type = type .asType (MethodType .methodType (REP , O ));
1456+ type = type .asType (MethodType .methodType (T , O ));
14791457
1480- /*
1481- * Use the sm.cache VarHandle to make a method that will
1482- * access the sm cache on type(self).
1483- */
1484- // getter = λ(s): sm.cache.get(type(s))
1485- assert sm .hasCache ();
1486- MethodHandle getter = MethodHandles .filterArguments (
1487- getCache .bindTo (sm .cache ), 0 , type );
1488-
1489- /*
1490- * Create a handle to invoke the handle we shall get
1491- * from type(self) with the arguments originally
1492- * supplied.
1493- */
1494- // invoker = λ(h, s,...): h.invoke(s,...)
1495- MethodHandle invoker =
1496- MethodHandles .invoker (sm .signature .type );
1497-
1498- // bounce = λ(s,...): getter(type(s)).invoke(s,...)
1458+ // bounce = λ(s,...): smt(type(s),s,...)
14991459 MethodHandle bounce =
1500- MethodHandles .foldArguments (invoker , getter );
1460+ MethodHandles .foldArguments (smt , type );
15011461
15021462 assert bounce .type () == sm .signature .type ;
15031463 return bounce ;
@@ -1508,6 +1468,7 @@ static MethodHandle bounceMH(SpecialMethod sm) {
15081468 }
15091469 }
15101470
1471+
15111472 /**
15121473 * Helper for {@link SpecialMethod} and thereby for call sites
15131474 * providing a method handle that raises a Python exception when
@@ -1749,4 +1710,18 @@ PyBaseException attributeError(PyType type) {
17491710
17501711 private static final String UNSUPPORTED_TYPES =
17511712 "unsupported operand type(s) for %s: '%.100s' and '%.100s'" ;
1713+
1714+ // Trampolines ---------------------------------------------------
1715+ /*
1716+ * These methods are referenced in SMUtil.bounceMH to create the
1717+ * bounce handle of corresponding special methods for which a cache
1718+ * is allocated on Representation objects. Their signature is always
1719+ * that of the special method, with PyType inserted first.
1720+ */
1721+ @ SuppressWarnings ("unused" )
1722+ private static Object op_neg (PyType type , Object self )
1723+ throws Throwable {
1724+ return BaseType .cast (type ).op_neg ().invokeExact (self );
1725+ }
1726+
17521727}
0 commit comments