Пример #1
0
  @NotNull
  // process local and global returns (local substituted with goto end-label global kept unchanged)
  public static List<PointForExternalFinallyBlocks> processReturns(
      @NotNull MethodNode node,
      @NotNull LabelOwner labelOwner,
      boolean remapReturn,
      Label endLabel) {
    if (!remapReturn) {
      return Collections.emptyList();
    }
    List<PointForExternalFinallyBlocks> result = new ArrayList<PointForExternalFinallyBlocks>();
    InsnList instructions = node.instructions;
    AbstractInsnNode insnNode = instructions.getFirst();
    while (insnNode != null) {
      if (InlineCodegenUtil.isReturnOpcode(insnNode.getOpcode())) {
        AbstractInsnNode previous = insnNode.getPrevious();
        MethodInsnNode flagNode;
        boolean isLocalReturn = true;
        String labelName = null;
        if (previous != null
            && previous instanceof MethodInsnNode
            && InlineCodegenUtil.NON_LOCAL_RETURN.equals(((MethodInsnNode) previous).owner)) {
          flagNode = (MethodInsnNode) previous;
          labelName = flagNode.name;
        }

        if (labelName != null) {
          isLocalReturn = labelOwner.isMyLabel(labelName);
          // remove global return flag
          if (isLocalReturn) {
            instructions.remove(previous);
          }
        }

        if (isLocalReturn && endLabel != null) {
          LabelNode labelNode = (LabelNode) endLabel.info;
          JumpInsnNode jumpInsnNode = new JumpInsnNode(Opcodes.GOTO, labelNode);
          instructions.insert(insnNode, jumpInsnNode);
          instructions.remove(insnNode);
          insnNode = jumpInsnNode;
        }

        // genetate finally block before nonLocalReturn flag/return/goto
        result.add(
            new PointForExternalFinallyBlocks(
                isLocalReturn ? insnNode : insnNode.getPrevious(),
                getReturnType(insnNode.getOpcode())));
      }
      insnNode = insnNode.getNext();
    }
    return result;
  }
Пример #2
0
  // TODO: check it's external module
  // TODO?: assert method exists in facade?
  public String changeOwnerForExternalPackage(String type, int opcode) {
    if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) {
      return type;
    }

    JvmClassName name = JvmClassName.byInternalName(type);
    String packageClassInternalName =
        PackageClassUtils.getPackageClassInternalName(name.getPackageFqName());
    if (type.startsWith(packageClassInternalName + '$')) {
      VirtualFile virtualFile =
          InlineCodegenUtil.findVirtualFile(inliningContext.state.getProject(), type);
      if (virtualFile != null) {
        KotlinJvmBinaryClass klass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile);
        if (klass != null
            && klass.getClassHeader().getSyntheticClassKind()
                == KotlinSyntheticClass.Kind.PACKAGE_PART) {
          return packageClassInternalName;
        }
      }
    }

    return type;
  }