Example #1
0
  public InlineResult doInline(
      @NotNull MethodVisitor adapter,
      @NotNull LocalVarRemapper remapper,
      boolean remapReturn,
      @NotNull LabelOwner labelOwner) {
    // analyze body
    MethodNode transformedNode = markPlacesForInlineAndRemoveInlinable(node);

    // substitute returns with "goto end" instruction to keep non local returns in lambdas
    Label end = new Label();
    transformedNode = doInline(transformedNode);
    removeClosureAssertions(transformedNode);
    InsnList instructions = transformedNode.instructions;
    instructions.resetLabels();

    MethodNode resultNode =
        new MethodNode(
            InlineCodegenUtil.API,
            transformedNode.access,
            transformedNode.name,
            transformedNode.desc,
            transformedNode.signature,
            ArrayUtil.toStringArray(transformedNode.exceptions));
    RemapVisitor visitor = new RemapVisitor(resultNode, remapper, nodeRemapper);
    try {
      transformedNode.accept(visitor);
    } catch (Exception e) {
      throw wrapException(e, transformedNode, "couldn't inline method call");
    }

    resultNode.visitLabel(end);

    if (inliningContext.isRoot()) {
      InternalFinallyBlockInliner.processInlineFunFinallyBlocks(resultNode, lambdasFinallyBlocks);
    }

    processReturns(resultNode, labelOwner, remapReturn, end);
    // flush transformed node to output
    resultNode.accept(new InliningInstructionAdapter(adapter));

    return result;
  }
Example #2
0
  public void generateAndInsertFinallyBlocks(
      @NotNull MethodNode intoNode,
      @NotNull List<MethodInliner.PointForExternalFinallyBlocks> insertPoints,
      int offsetForFinallyLocalVar) {
    if (!codegen.hasFinallyBlocks()) return;

    Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints =
        new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>();
    for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) {
      extensionPoints.put(insertPoint.beforeIns, insertPoint);
    }

    DefaultProcessor processor = new DefaultProcessor(intoNode, offsetForFinallyLocalVar);

    int curFinallyDepth = 0;
    AbstractInsnNode curInstr = intoNode.instructions.getFirst();
    while (curInstr != null) {
      processor.processInstruction(curInstr, true);
      if (InlineCodegenUtil.isFinallyStart(curInstr)) {
        // TODO depth index calc could be more precise
        curFinallyDepth = getConstant(curInstr.getPrevious());
      }

      MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr);
      if (extension != null) {
        Label start = new Label();

        MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode();
        finallyNode.visitLabel(start);

        ExpressionCodegen finallyCodegen =
            new ExpressionCodegen(
                finallyNode,
                codegen.getFrameMap(),
                codegen.getReturnType(),
                codegen.getContext(),
                codegen.getState(),
                codegen.getParentCodegen());
        finallyCodegen.addBlockStackElementsForNonLocalReturns(
            codegen.getBlockStackElements(), curFinallyDepth);

        FrameMap frameMap = finallyCodegen.getFrameMap();
        FrameMap.Mark mark = frameMap.mark();
        while (frameMap.getCurrentSize() < processor.getNextFreeLocalIndex()) {
          frameMap.enterTemp(Type.INT_TYPE);
        }

        finallyCodegen.generateFinallyBlocksIfNeeded(
            extension.returnType, extension.finallyIntervalEnd.getLabel());

        // Exception table for external try/catch/finally blocks will be generated in original
        // codegen after exiting this method
        InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr);

        SimpleInterval splitBy =
            new SimpleInterval((LabelNode) start.info, extension.finallyIntervalEnd);
        processor.getTryBlocksMetaInfo().splitCurrentIntervals(splitBy, true);

        // processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);

        mark.dropTo();
      }

      curInstr = curInstr.getNext();
    }

    processor.substituteTryBlockNodes(intoNode);

    // processor.substituteLocalVarTable(intoNode);
  }