Exemplo n.º 1
0
  private void generateConstInstance() {
    MethodVisitor mv =
        v.newMethod(
            OtherOrigin(element, funDescriptor),
            ACC_STATIC | ACC_SYNTHETIC,
            "<clinit>",
            "()V",
            null,
            ArrayUtil.EMPTY_STRING_ARRAY);
    InstructionAdapter iv = new InstructionAdapter(mv);

    v.newField(
        OtherOrigin(element, funDescriptor),
        ACC_STATIC | ACC_FINAL | ACC_PUBLIC,
        JvmAbi.INSTANCE_FIELD,
        asmType.getDescriptor(),
        null,
        null);

    if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
      mv.visitCode();
      iv.anew(asmType);
      iv.dup();
      iv.invokespecial(asmType.getInternalName(), "<init>", "()V", false);
      iv.putstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
      mv.visitInsn(RETURN);
      FunctionCodegen.endVisit(mv, "<clinit>", element);
    }
  }
Exemplo n.º 2
0
  @Override
  protected void generateDeclaration() {
    BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
    if (samType != null) {
      typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw);
    }
    sw.writeSuperclass();
    superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
    sw.writeSuperclassEnd();
    String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()];
    for (int i = 0; i < superInterfaceTypes.size(); i++) {
      JetType superInterfaceType = superInterfaceTypes.get(i);
      sw.writeInterface();
      superInterfaceAsmTypes[i] = typeMapper.mapSupertype(superInterfaceType, sw).getInternalName();
      sw.writeInterfaceEnd();
    }

    v.defineClass(
        element,
        V1_6,
        ACC_FINAL | ACC_SUPER | visibilityFlag,
        asmType.getInternalName(),
        sw.makeJavaGenericSignature(),
        superClassAsmType.getInternalName(),
        superInterfaceAsmTypes);

    InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);

    v.visitSource(element.getContainingFile().getName(), null);
  }
Exemplo n.º 3
0
  private static String getInlineName(
      @NotNull CodegenContext codegenContext,
      @NotNull DeclarationDescriptor currentDescriptor,
      @NotNull JetTypeMapper typeMapper,
      @NotNull JvmFileClassesProvider fileClassesProvider) {
    if (currentDescriptor instanceof PackageFragmentDescriptor) {
      PsiFile file = getContainingFile(codegenContext);

      Type implementationOwnerType;
      if (file == null) {
        implementationOwnerType =
            CodegenContextUtil.getImplementationOwnerClassType(codegenContext);
      } else {
        implementationOwnerType =
            FileClassesPackage.getFileClassType(fileClassesProvider, (JetFile) file);
      }

      if (implementationOwnerType == null) {
        DeclarationDescriptor contextDescriptor = codegenContext.getContextDescriptor();
        //noinspection ConstantConditions
        throw new RuntimeException(
            "Couldn't find declaration for "
                + contextDescriptor.getContainingDeclaration().getName()
                + "."
                + contextDescriptor.getName()
                + "; context: "
                + codegenContext);
      }

      return implementationOwnerType.getInternalName();
    } else if (currentDescriptor instanceof ClassifierDescriptor) {
      Type type = typeMapper.mapType((ClassifierDescriptor) currentDescriptor);
      return type.getInternalName();
    } else if (currentDescriptor instanceof FunctionDescriptor) {
      ClassDescriptor descriptor =
          typeMapper
              .getBindingContext()
              .get(CodegenBinding.CLASS_FOR_CALLABLE, (FunctionDescriptor) currentDescriptor);
      if (descriptor != null) {
        Type type = typeMapper.mapType(descriptor);
        return type.getInternalName();
      }
    }

    // TODO: add suffix for special case
    String suffix =
        currentDescriptor.getName().isSpecial() ? "" : currentDescriptor.getName().asString();

    //noinspection ConstantConditions
    return getInlineName(
            codegenContext,
            currentDescriptor.getContainingDeclaration(),
            typeMapper,
            fileClassesProvider)
        + "$"
        + suffix;
  }
  @NotNull
  private InlineResult inlineMethod(
      @NotNull AnonymousObjectGeneration anonymousObjectGen,
      @NotNull FieldRemapper parentRemapper,
      @NotNull MethodVisitor deferringVisitor,
      @NotNull MethodNode sourceNode,
      @NotNull ParametersBuilder capturedBuilder,
      boolean isConstructor) {
    ReifiedTypeParametersUsages typeParametersToReify =
        inliningContext.reifedTypeInliner.reifyInstructions(sourceNode);
    Parameters parameters =
        isConstructor
            ? capturedBuilder.buildParameters()
            : getMethodParametersWithCaptured(capturedBuilder, sourceNode);

    RegeneratedLambdaFieldRemapper remapper =
        new RegeneratedLambdaFieldRemapper(
            oldObjectType.getInternalName(),
            newLambdaType.getInternalName(),
            parameters,
            anonymousObjectGen.getCapturedLambdasToInline(),
            parentRemapper,
            isConstructor);

    MethodInliner inliner =
        new MethodInliner(
            sourceNode,
            parameters,
            inliningContext.subInline(inliningContext.nameGenerator.subGenerator("lambda")),
            remapper,
            isSameModule,
            "Transformer for " + anonymousObjectGen.getOwnerInternalName(),
            sourceMapper,
            new InlineCallSiteInfo(
                anonymousObjectGen.getOwnerInternalName(),
                sourceNode.name,
                isConstructor
                    ? anonymousObjectGen.getNewConstructorDescriptor()
                    : sourceNode.desc));

    InlineResult result =
        inliner.doInline(
            deferringVisitor,
            new LocalVarRemapper(parameters, 0),
            false,
            LabelOwner.NOT_APPLICABLE);
    result.getReifiedTypeParametersUsages().mergeAll(typeParametersToReify);
    deferringVisitor.visitMaxs(-1, -1);
    return result;
  }
Exemplo n.º 5
0
  @NotNull
  private Method generateConstructor(@NotNull Type superClassAsmType) {
    List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);

    Type[] argTypes = fieldListToTypeArray(args);

    Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
    MethodVisitor mv =
        v.newMethod(
            OtherOrigin(element, funDescriptor),
            visibilityFlag,
            "<init>",
            constructor.getDescriptor(),
            null,
            ArrayUtil.EMPTY_STRING_ARRAY);
    if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
      mv.visitCode();
      InstructionAdapter iv = new InstructionAdapter(mv);

      int k = 1;
      for (FieldInfo fieldInfo : args) {
        k = genAssignInstanceFieldFromParam(fieldInfo, k, iv);
      }

      iv.load(0, superClassAsmType);

      if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE)) {
        int arity = funDescriptor.getValueParameters().size();
        if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
        if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
        iv.iconst(arity);
        iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(I)V", false);
      } else {
        iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false);
      }

      iv.visitInsn(RETURN);

      FunctionCodegen.endVisit(iv, "constructor", element);
    }
    return constructor;
  }
Exemplo n.º 6
0
  private void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
    if (bridge.equals(delegate)) return;

    MethodVisitor mv =
        v.newMethod(
            OtherOrigin(element, funDescriptor),
            ACC_PUBLIC | ACC_BRIDGE,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            ArrayUtil.EMPTY_STRING_ARRAY);

    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    InstructionAdapter iv = new InstructionAdapter(mv);
    ImplementationBodyCodegen.markLineNumberForSyntheticFunction(
        DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);

    iv.load(0, asmType);

    ReceiverParameterDescriptor receiver = funDescriptor.getExtensionReceiverParameter();
    int count = 1;
    if (receiver != null) {
      StackValue.local(count, bridge.getArgumentTypes()[count - 1])
          .put(typeMapper.mapType(receiver.getType()), iv);
      count++;
    }

    List<ValueParameterDescriptor> params = funDescriptor.getValueParameters();
    for (ValueParameterDescriptor param : params) {
      StackValue.local(count, bridge.getArgumentTypes()[count - 1])
          .put(typeMapper.mapType(param.getType()), iv);
      count++;
    }

    iv.invokevirtual(
        asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false);
    StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), iv);

    iv.areturn(bridge.getReturnType());

    FunctionCodegen.endVisit(mv, "bridge", element);
  }
Exemplo n.º 7
0
  protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
    List<JetProperty> delegatedProperties = new ArrayList<JetProperty>();
    for (JetDeclaration declaration : ((JetDeclarationContainer) element).getDeclarations()) {
      if (declaration instanceof JetProperty) {
        JetProperty property = (JetProperty) declaration;
        if (property.getDelegate() != null) {
          delegatedProperties.add(property);
        }
      }
    }
    if (delegatedProperties.isEmpty()) return;

    v.newField(
        null,
        ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
        JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
        "[" + PROPERTY_METADATA_TYPE,
        null,
        null);

    InstructionAdapter iv = createOrGetClInitCodegen().v;
    iv.iconst(delegatedProperties.size());
    iv.newarray(PROPERTY_METADATA_TYPE);

    for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
      VariableDescriptor property =
          BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));

      iv.dup();
      iv.iconst(i);
      iv.anew(PROPERTY_METADATA_IMPL_TYPE);
      iv.dup();
      iv.visitLdcInsn(property.getName().asString());
      iv.invokespecial(
          PROPERTY_METADATA_IMPL_TYPE.getInternalName(), "<init>", "(Ljava/lang/String;)V");
      iv.astore(PROPERTY_METADATA_IMPL_TYPE);
    }

    iv.putstatic(
        thisAsmType.getInternalName(),
        JvmAbi.PROPERTY_METADATA_ARRAY_NAME,
        "[" + PROPERTY_METADATA_TYPE);
  }
Exemplo n.º 8
0
 @Override
 public void writeClassBegin(Type asmType) {
   signatureVisitor().visitClassType(asmType.getInternalName());
   super.writeClassBegin(asmType);
 }
Exemplo n.º 9
0
  @NotNull
  private SMAPAndMethodNode createMethodNode(boolean callDefault)
      throws ClassNotFoundException, IOException {
    JvmMethodSignature jvmSignature =
        typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    Method asmMethod;
    if (callDefault) {
      asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
    } else {
      asmMethod = jvmSignature.getAsmMethod();
    }

    SMAPAndMethodNode nodeAndSMAP;
    if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
      JetTypeMapper.ContainingClassesInfo containingClasses =
          typeMapper.getContainingClassesForDeserializedCallable(
              (DeserializedSimpleFunctionDescriptor) functionDescriptor);

      VirtualFile file =
          InlineCodegenUtil.getVirtualFileForCallable(containingClasses.getImplClassId(), state);
      nodeAndSMAP =
          InlineCodegenUtil.getMethodNode(
              file.contentsToByteArray(),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              containingClasses.getFacadeClassId());

      if (nodeAndSMAP == null) {
        throw new RuntimeException(
            "Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
      }
    } else {
      PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);

      if (element == null || !(element instanceof JetNamedFunction)) {
        throw new RuntimeException(
            "Couldn't find declaration for function " + descriptorName(functionDescriptor));
      }
      JetNamedFunction inliningFunction = (JetNamedFunction) element;

      MethodNode node =
          new MethodNode(
              InlineCodegenUtil.API,
              getMethodAsmFlags(functionDescriptor, context.getContextKind())
                  | (callDefault ? Opcodes.ACC_STATIC : 0),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              jvmSignature.getGenericsSignature(),
              null);

      // for maxLocals calculation
      MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
      MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor);

      SMAP smap;
      if (callDefault) {
        Type implementationOwner = typeMapper.mapOwner(functionDescriptor);
        FakeMemberCodegen parentCodegen =
            new FakeMemberCodegen(
                codegen.getParentCodegen(),
                inliningFunction,
                (FieldOwnerContext) methodContext.getParentContext(),
                implementationOwner.getInternalName());
        FunctionCodegen.generateDefaultImplBody(
            methodContext,
            functionDescriptor,
            maxCalcAdapter,
            DefaultParameterValueLoader.DEFAULT,
            inliningFunction,
            parentCodegen);
        smap =
            createSMAPWithDefaultMapping(
                inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
      } else {
        smap =
            generateMethodBody(
                maxCalcAdapter,
                functionDescriptor,
                methodContext,
                inliningFunction,
                jvmSignature,
                false);
      }

      nodeAndSMAP = new SMAPAndMethodNode(node, smap);
      maxCalcAdapter.visitMaxs(-1, -1);
      maxCalcAdapter.visitEnd();
    }
    return nodeAndSMAP;
  }
Exemplo n.º 10
0
  @NotNull
  public InlineResult doTransform(
      @NotNull AnonymousObjectGeneration anonymousObjectGen,
      @NotNull FieldRemapper parentRemapper) {
    final List<InnerClassNode> innerClassNodes = new ArrayList<InnerClassNode>();
    ClassBuilder classBuilder = createClassBuilder();
    final List<MethodNode> methodsToTransform = new ArrayList<MethodNode>();

    reader.accept(
        new ClassVisitor(InlineCodegenUtil.API, classBuilder.getVisitor()) {
          @Override
          public void visit(
              int version,
              int access,
              @NotNull String name,
              String signature,
              String superName,
              String[] interfaces) {
            InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name);
            super.visit(version, access, name, signature, superName, interfaces);
          }

          @Override
          public void visitInnerClass(
              @NotNull String name, String outerName, String innerName, int access) {
            innerClassNodes.add(new InnerClassNode(name, outerName, innerName, access));
          }

          @Override
          public MethodVisitor visitMethod(
              int access,
              @NotNull String name,
              @NotNull String desc,
              String signature,
              String[] exceptions) {
            MethodNode node = new MethodNode(access, name, desc, signature, exceptions);
            if (name.equals("<init>")) {
              if (constructor != null)
                throw new RuntimeException(
                    "Lambda, SAM or anonymous object should have only one constructor");

              constructor = node;
            } else {
              methodsToTransform.add(node);
            }
            return node;
          }

          @Override
          public FieldVisitor visitField(
              int access,
              @NotNull String name,
              @NotNull String desc,
              String signature,
              Object value) {
            addUniqueField(name);
            if (InlineCodegenUtil.isCapturedFieldName(name)) {
              return null;
            } else {
              return super.visitField(access, name, desc, signature, value);
            }
          }

          @Override
          public void visitSource(String source, String debug) {
            sourceInfo = source;
            debugInfo = debug;
          }

          @Override
          public void visitEnd() {}
        },
        ClassReader.SKIP_FRAMES);

    if (!inliningContext.isInliningLambda) {
      if (debugInfo != null && !debugInfo.isEmpty()) {
        sourceMapper = SourceMapper.Companion.createFromSmap(SMAPParser.parse(debugInfo));
      } else {
        // seems we can't do any clever mapping cause we don't know any about original class name
        sourceMapper = IdenticalSourceMapper.INSTANCE;
      }
      if (sourceInfo != null && !InlineCodegenUtil.GENERATE_SMAP) {
        classBuilder.visitSource(sourceInfo, debugInfo);
      }
    } else {
      if (sourceInfo != null) {
        classBuilder.visitSource(sourceInfo, debugInfo);
      }
      sourceMapper = IdenticalSourceMapper.INSTANCE;
    }

    ParametersBuilder allCapturedParamBuilder = ParametersBuilder.newBuilder();
    ParametersBuilder constructorParamBuilder = ParametersBuilder.newBuilder();
    List<CapturedParamInfo> additionalFakeParams =
        extractParametersMappingAndPatchConstructor(
            constructor,
            allCapturedParamBuilder,
            constructorParamBuilder,
            anonymousObjectGen,
            parentRemapper);
    List<MethodVisitor> deferringMethods = new ArrayList<MethodVisitor>();

    for (MethodNode next : methodsToTransform) {
      MethodVisitor deferringVisitor = newMethod(classBuilder, next);
      InlineResult funResult =
          inlineMethodAndUpdateGlobalResult(
              anonymousObjectGen,
              parentRemapper,
              deferringVisitor,
              next,
              allCapturedParamBuilder,
              false);

      Type returnType = Type.getReturnType(next.desc);
      if (!AsmUtil.isPrimitive(returnType)) {
        String oldFunReturnType = returnType.getInternalName();
        String newFunReturnType = funResult.getChangedTypes().get(oldFunReturnType);
        if (newFunReturnType != null) {
          inliningContext.typeRemapper.addAdditionalMappings(oldFunReturnType, newFunReturnType);
        }
      }
      deferringMethods.add(deferringVisitor);
    }

    for (MethodVisitor method : deferringMethods) {
      method.visitEnd();
    }

    generateConstructorAndFields(
        classBuilder,
        allCapturedParamBuilder,
        constructorParamBuilder,
        anonymousObjectGen,
        parentRemapper,
        additionalFakeParams);

    SourceMapper.Companion.flushToClassBuilder(sourceMapper, classBuilder);

    ClassVisitor visitor = classBuilder.getVisitor();
    for (InnerClassNode node : innerClassNodes) {
      visitor.visitInnerClass(node.name, node.outerName, node.innerName, node.access);
    }

    writeOuterInfo(visitor);

    classBuilder.done();

    anonymousObjectGen.setNewLambdaType(newLambdaType);
    return transformationResult;
  }
Exemplo n.º 11
0
  public void generateMethod(
      @NotNull JvmDeclarationOrigin origin,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext methodContext,
      @NotNull FunctionGenerationStrategy strategy) {
    OwnerKind contextKind = methodContext.getContextKind();
    if (isInterface(functionDescriptor.getContainingDeclaration())
        && functionDescriptor.getVisibility() == Visibilities.PRIVATE
        && contextKind != OwnerKind.DEFAULT_IMPLS) {
      return;
    }

    JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, contextKind);
    Method asmMethod = jvmSignature.getAsmMethod();

    int flags = getMethodAsmFlags(functionDescriptor, contextKind);
    boolean isNative = NativeKt.hasNativeAnnotation(functionDescriptor);

    if (isNative && owner instanceof MultifileClassFacadeContext) {
      // Native methods are only defined in facades and do not need package part implementations
      return;
    }
    MethodVisitor mv =
        v.newMethod(
            origin,
            flags,
            asmMethod.getName(),
            asmMethod.getDescriptor(),
            jvmSignature.getGenericsSignature(),
            getThrownExceptions(functionDescriptor, typeMapper));

    if (CodegenContextUtil.isImplClassOwner(owner)) {
      v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
    }

    generateMethodAnnotations(functionDescriptor, asmMethod, mv);

    generateParameterAnnotations(
        functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));

    generateBridges(functionDescriptor);

    boolean staticInCompanionObject =
        AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor);
    if (staticInCompanionObject) {
      ImplementationBodyCodegen parentBodyCodegen =
          (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
      parentBodyCodegen.addAdditionalTask(
          new JvmStaticGenerator(functionDescriptor, origin, state));
    }

    if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES
        || isAbstractMethod(functionDescriptor, contextKind)) {
      generateLocalVariableTable(
          mv,
          jvmSignature,
          functionDescriptor,
          getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
          new Label(),
          new Label(),
          contextKind);

      mv.visitEnd();
      return;
    }

    if (!isNative) {
      generateMethodBody(
          mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
    } else if (staticInCompanionObject) {
      // native @JvmStatic foo() in companion object should delegate to the static native function
      // moved to the outer class
      mv.visitCode();
      FunctionDescriptor staticFunctionDescriptor =
          JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
      JvmMethodSignature jvmMethodSignature =
          typeMapper.mapSignature(
              memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
      Type owningType =
          typeMapper.mapClass(
              (ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
      generateDelegateToMethodBody(
          false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
    }

    endVisit(mv, null, origin.getElement());
  }