src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
changeset 59075 355f4f42dda5
parent 58038 aa3715655834
equal deleted inserted replaced
59072:b987ea528c21 59075:355f4f42dda5
  1166       *  try {
  1166       *  try {
  1167       *      return a1.invokeBasic(a6, a7);
  1167       *      return a1.invokeBasic(a6, a7);
  1168       *  } catch (Throwable e) {
  1168       *  } catch (Throwable e) {
  1169       *      if (!a2.isInstance(e)) throw e;
  1169       *      if (!a2.isInstance(e)) throw e;
  1170       *      return a3.invokeBasic(ex, a6, a7);
  1170       *      return a3.invokeBasic(ex, a6, a7);
  1171       *  }}
  1171       *  }}</pre></blockquote>
  1172       */
  1172       */
  1173     private Name emitGuardWithCatch(int pos) {
  1173     private Name emitGuardWithCatch(int pos) {
  1174         Name args    = lambdaForm.names[pos];
  1174         Name args    = lambdaForm.names[pos];
  1175         Name invoker = lambdaForm.names[pos+1];
  1175         Name invoker = lambdaForm.names[pos+1];
  1176         Name result  = lambdaForm.names[pos+2];
  1176         Name result  = lambdaForm.names[pos+2];
  1261      * <blockquote><pre>{@code
  1261      * <blockquote><pre>{@code
  1262      * TRY:                 (--)
  1262      * TRY:                 (--)
  1263      *                      load target                             (-- target)
  1263      *                      load target                             (-- target)
  1264      *                      load args                               (-- args... target)
  1264      *                      load args                               (-- args... target)
  1265      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (depends)
  1265      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (depends)
  1266      * FINALLY_NORMAL:      (-- r)
  1266      * FINALLY_NORMAL:      (-- r_2nd* r)
  1267      *                      load cleanup                            (-- cleanup r)
  1267      *                      store returned value                    (--)
  1268      *                      SWAP                                    (-- r cleanup)
  1268      *                      load cleanup                            (-- cleanup)
  1269      *                      ACONST_NULL                             (-- t r cleanup)
  1269      *                      ACONST_NULL                             (-- t cleanup)
  1270      *                      SWAP                                    (-- r t cleanup)
  1270      *                      load returned value                     (-- r_2nd* r t cleanup)
  1271      *                      load args                               (-- args... r t cleanup)
  1271      *                      load args                               (-- args... r_2nd* r t cleanup)
  1272      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (-- r)
  1272      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (-- r_2nd* r)
  1273      *                      GOTO DONE
  1273      *                      GOTO DONE
  1274      * CATCH:               (-- t)
  1274      * CATCH:               (-- t)
  1275      *                      DUP                                     (-- t t)
  1275      *                      DUP                                     (-- t t)
  1276      * FINALLY_EXCEPTIONAL: (-- t t)
  1276      * FINALLY_EXCEPTIONAL: (-- t t)
  1277      *                      load cleanup                            (-- cleanup t t)
  1277      *                      load cleanup                            (-- cleanup t t)
  1278      *                      SWAP                                    (-- t cleanup t)
  1278      *                      SWAP                                    (-- t cleanup t)
  1279      *                      load default for r                      (-- r t cleanup t)
  1279      *                      load default for r                      (-- r_2nd* r t cleanup t)
  1280      *                      load args                               (-- args... r t cleanup t)
  1280      *                      load args                               (-- args... r_2nd* r t cleanup t)
  1281      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (-- r t)
  1281      *                      INVOKEVIRTUAL MethodHandle.invokeBasic  (-- r_2nd* r t)
  1282      *                      POP                                     (-- t)
  1282      *                      POP/POP2*                               (-- t)
  1283      *                      ATHROW
  1283      *                      ATHROW
  1284      * DONE:                (-- r)
  1284      * DONE:                (-- r)
  1285      * }</pre></blockquote>
  1285      * }</pre></blockquote>
       
  1286      * * = depends on whether the return type takes up 2 stack slots.
  1286      */
  1287      */
  1287     private Name emitTryFinally(int pos) {
  1288     private Name emitTryFinally(int pos) {
  1288         Name args    = lambdaForm.names[pos];
  1289         Name args    = lambdaForm.names[pos];
  1289         Name invoker = lambdaForm.names[pos+1];
  1290         Name invoker = lambdaForm.names[pos+1];
  1290         Name result  = lambdaForm.names[pos+2];
  1291         Name result  = lambdaForm.names[pos+2];
  1293         Label lTo = new Label();
  1294         Label lTo = new Label();
  1294         Label lCatch = new Label();
  1295         Label lCatch = new Label();
  1295         Label lDone = new Label();
  1296         Label lDone = new Label();
  1296 
  1297 
  1297         Class<?> returnType = result.function.resolvedHandle().type().returnType();
  1298         Class<?> returnType = result.function.resolvedHandle().type().returnType();
       
  1299         BasicType basicReturnType = BasicType.basicType(returnType);
  1298         boolean isNonVoid = returnType != void.class;
  1300         boolean isNonVoid = returnType != void.class;
       
  1301 
  1299         MethodType type = args.function.resolvedHandle().type()
  1302         MethodType type = args.function.resolvedHandle().type()
  1300                 .dropParameterTypes(0,1)
  1303                 .dropParameterTypes(0,1)
  1301                 .changeReturnType(returnType);
  1304                 .changeReturnType(returnType);
  1302         MethodType cleanupType = type.insertParameterTypes(0, Throwable.class);
  1305         MethodType cleanupType = type.insertParameterTypes(0, Throwable.class);
  1303         if (isNonVoid) {
  1306         if (isNonVoid) {
  1314         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1317         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1315         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
  1318         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", type.basicType().toMethodDescriptorString(), false);
  1316         mv.visitLabel(lTo);
  1319         mv.visitLabel(lTo);
  1317 
  1320 
  1318         // FINALLY_NORMAL:
  1321         // FINALLY_NORMAL:
       
  1322         int index = extendLocalsMap(new Class<?>[]{ returnType });
       
  1323         if (isNonVoid) {
       
  1324             emitStoreInsn(basicReturnType, index);
       
  1325         }
  1319         emitPushArgument(invoker, 1); // load cleanup
  1326         emitPushArgument(invoker, 1); // load cleanup
  1320         if (isNonVoid) {
       
  1321             mv.visitInsn(Opcodes.SWAP);
       
  1322         }
       
  1323         mv.visitInsn(Opcodes.ACONST_NULL);
  1327         mv.visitInsn(Opcodes.ACONST_NULL);
  1324         if (isNonVoid) {
  1328         if (isNonVoid) {
  1325             mv.visitInsn(Opcodes.SWAP);
  1329             emitLoadInsn(basicReturnType, index);
  1326         }
  1330         }
  1327         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1331         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1328         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", cleanupDesc, false);
  1332         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", cleanupDesc, false);
  1329         mv.visitJumpInsn(Opcodes.GOTO, lDone);
  1333         mv.visitJumpInsn(Opcodes.GOTO, lDone);
  1330 
  1334 
  1339             emitZero(BasicType.basicType(returnType)); // load default for result
  1343             emitZero(BasicType.basicType(returnType)); // load default for result
  1340         }
  1344         }
  1341         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1345         emitPushArguments(args, 1); // load args (skip 0: method handle)
  1342         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", cleanupDesc, false);
  1346         mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, MH, "invokeBasic", cleanupDesc, false);
  1343         if (isNonVoid) {
  1347         if (isNonVoid) {
  1344             mv.visitInsn(Opcodes.POP);
  1348             emitPopInsn(basicReturnType);
  1345         }
  1349         }
  1346         mv.visitInsn(Opcodes.ATHROW);
  1350         mv.visitInsn(Opcodes.ATHROW);
  1347 
  1351 
  1348         // DONE:
  1352         // DONE:
  1349         mv.visitLabel(lDone);
  1353         mv.visitLabel(lDone);
  1350 
  1354 
  1351         return result;
  1355         return result;
       
  1356     }
       
  1357 
       
  1358     private void emitPopInsn(BasicType type) {
       
  1359         mv.visitInsn(popInsnOpcode(type));
       
  1360     }
       
  1361 
       
  1362     private static int popInsnOpcode(BasicType type) {
       
  1363         switch (type) {
       
  1364             case I_TYPE:
       
  1365             case F_TYPE:
       
  1366             case L_TYPE:
       
  1367                 return Opcodes.POP;
       
  1368             case J_TYPE:
       
  1369             case D_TYPE:
       
  1370                 return Opcodes.POP2;
       
  1371             default:
       
  1372                 throw new InternalError("unknown type: " + type);
       
  1373         }
  1352     }
  1374     }
  1353 
  1375 
  1354     /**
  1376     /**
  1355      * Emit bytecode for the loop idiom.
  1377      * Emit bytecode for the loop idiom.
  1356      * <p>
  1378      * <p>