Esempio n. 1
0
  public InlineCodegen(
      @NotNull ExpressionCodegen codegen,
      @NotNull GenerationState state,
      @NotNull SimpleFunctionDescriptor functionDescriptor,
      @NotNull JetElement callElement,
      @Nullable ReifiedTypeParameterMappings typeParameterMappings) {
    assert InlineUtil.isInline(functionDescriptor)
        : "InlineCodegen could inline only inline function: " + functionDescriptor;

    this.state = state;
    this.typeMapper = state.getTypeMapper();
    this.codegen = codegen;
    this.callElement = callElement;
    this.functionDescriptor = functionDescriptor.getOriginal();

    reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);

    initialFrameSize = codegen.getFrameMap().getCurrentSize();

    context = (MethodContext) getContext(functionDescriptor, state);
    jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    // TODO: implement AS_FUNCTION inline strategy
    InlineStrategy inlineStrategy = InlineUtil.getInlineStrategy(functionDescriptor);
    this.asFunctionInline = false;

    isSameModule =
        JvmCodegenUtil.isCallInsideSameModuleAsDeclared(
            functionDescriptor, codegen.getContext(), state.getOutDirectory());

    sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
    reportIncrementalInfo(
        functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
  }
Esempio n. 2
0
  private SMAPAndMethodNode generateLambdaBody(LambdaInfo info) {
    JetExpression declaration = info.getFunctionWithBodyOrCallableReference();
    FunctionDescriptor descriptor = info.getFunctionDescriptor();

    MethodContext parentContext = codegen.getContext();

    MethodContext context =
        parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor);

    JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor);
    Method asmMethod = jvmMethodSignature.getAsmMethod();
    MethodNode methodNode =
        new MethodNode(
            InlineCodegenUtil.API,
            getMethodAsmFlags(descriptor, context.getContextKind()),
            asmMethod.getName(),
            asmMethod.getDescriptor(),
            jvmMethodSignature.getGenericsSignature(),
            null);

    MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);

    SMAP smap =
        generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true);
    adapter.visitMaxs(-1, -1);
    return new SMAPAndMethodNode(methodNode, smap);
  }
Esempio n. 3
0
  public void removeFinallyMarkers(@NotNull MethodNode intoNode) {
    if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;

    InsnList instructions = intoNode.instructions;
    AbstractInsnNode curInstr = instructions.getFirst();
    while (curInstr != null) {
      if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
        AbstractInsnNode marker = curInstr;
        // just to assert
        getConstant(marker.getPrevious());
        curInstr = curInstr.getNext();
        instructions.remove(marker.getPrevious());
        instructions.remove(marker);
        continue;
      }
      curInstr = curInstr.getNext();
    }
  }
Esempio n. 4
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);
  }
Esempio n. 5
0
  private InlineResult inlineCall(SMAPAndMethodNode nodeAndSmap) {
    MethodNode node = nodeAndSmap.getNode();
    ReifiedTypeParametersUsages reificationResult =
        reifiedTypeInliner.reifyInstructions(node.instructions);
    generateClosuresBodies();

    // through generation captured parameters will be added to invocationParamBuilder
    putClosureParametersOnStack();

    addInlineMarker(codegen.v, true);

    Parameters parameters = invocationParamBuilder.buildParameters();

    InliningContext info =
        new RootInliningContext(
            expressionMap,
            state,
            codegen.getInlineNameGenerator().subGenerator(functionDescriptor.getName().asString()),
            codegen.getContext(),
            callElement,
            codegen.getParentCodegen().getClassName(),
            reifiedTypeInliner);

    MethodInliner inliner =
        new MethodInliner(
            node,
            parameters,
            info,
            new FieldRemapper(null, null, parameters),
            isSameModule,
            "Method inlining " + callElement.getText(),
            createNestedSourceMapper(nodeAndSmap)); // with captured

    LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);

    MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
    // hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
    adapter.visitInsn(Opcodes.NOP);

    InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
    result.getReifiedTypeParametersUsages().mergeAll(reificationResult);

    CallableMemberDescriptor descriptor = codegen.getContext().getContextDescriptor();
    final Set<String> labels =
        getDeclarationLabels(
            DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor);
    LabelOwner labelOwner =
        new LabelOwner() {
          @Override
          public boolean isMyLabel(@NotNull String name) {
            return labels.contains(name);
          }
        };

    List<MethodInliner.PointForExternalFinallyBlocks> infos =
        MethodInliner.processReturns(adapter, labelOwner, true, null);
    generateAndInsertFinallyBlocks(
        adapter,
        infos,
        ((StackValue.Local) remapper.remap(parameters.totalSize() + 1).value).index);
    removeFinallyMarkers(adapter);

    adapter.accept(new InliningInstructionAdapter(codegen.v));

    addInlineMarker(codegen.v, false);

    return result;
  }