Esempio 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);
    }
  }
Esempio n. 2
0
  private void generateBridge(
      @Nullable PsiElement origin,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Method bridge,
      @NotNull Method delegateTo,
      boolean isSpecialBridge,
      boolean isStubDeclarationWithDelegationToSuper) {
    boolean isSpecialOrDelegationToSuper =
        isSpecialBridge || isStubDeclarationWithDelegationToSuper;
    int flags =
        ACC_PUBLIC
            | ACC_BRIDGE
            | (!isSpecialOrDelegationToSuper ? ACC_SYNTHETIC : 0)
            | (isSpecialBridge ? ACC_FINAL : 0); // TODO.

    MethodVisitor mv =
        v.newMethod(
            JvmDeclarationOriginKt.Bridge(descriptor, origin),
            flags,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            null);
    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    Type[] argTypes = bridge.getArgumentTypes();
    Type[] originalArgTypes = delegateTo.getArgumentTypes();

    InstructionAdapter iv = new InstructionAdapter(mv);
    MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);

    if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) {
      generateTypeCheckBarrierIfNeeded(
          iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]);
    }

    iv.load(0, OBJECT_TYPE);
    for (int i = 0, reg = 1; i < argTypes.length; i++) {
      StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
      //noinspection AssignmentToForLoopParameter
      reg += argTypes[i].getSize();
    }

    if (isStubDeclarationWithDelegationToSuper) {
      ClassDescriptor parentClass =
          getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
      assert parentClass != null;
      String parentInternalName = typeMapper.mapClass(parentClass).getInternalName();
      iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor());
    } else {
      iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
    }

    StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
    iv.areturn(bridge.getReturnType());

    endVisit(mv, "bridge method", origin);
  }
 public static void generateFinallyMarker(
     @NotNull InstructionAdapter v, int depth, boolean start) {
   v.iconst(depth);
   v.invokestatic(
       INLINE_MARKER_CLASS_NAME,
       start ? INLINE_MARKER_FINALLY_START : INLINE_MARKER_FINALLY_END,
       "(I)V",
       false);
 }
 public static void addInlineMarker(@NotNull InstructionAdapter v, boolean isStartNotEnd) {
   v.visitMethodInsn(
       Opcodes.INVOKESTATIC,
       INLINE_MARKER_CLASS_NAME,
       (isStartNotEnd ? INLINE_MARKER_BEFORE_METHOD_NAME : INLINE_MARKER_AFTER_METHOD_NAME),
       "()V",
       false);
 }
Esempio n. 5
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);
  }
Esempio n. 6
0
 private static void genDefaultSuperCallCheckIfNeeded(
     @NotNull InstructionAdapter iv, @NotNull Method defaultMethod) {
   String defaultMethodName = defaultMethod.getName();
   if ("<init>".equals(defaultMethodName)) {
     return;
   }
   Label end = new Label();
   int handleIndex =
       (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2)
           - 2; /*-1 for this, and -1 for handle*/
   iv.load(handleIndex, OBJECT_TYPE);
   iv.ifnull(end);
   AsmUtil.genThrow(
       iv,
       "java/lang/UnsupportedOperationException",
       "Super calls with default arguments not supported in this target, function: "
           + StringsKt.substringBeforeLast(
               defaultMethodName, JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, defaultMethodName));
   iv.visitLabel(end);
 }
Esempio n. 7
0
  private static void generateTypeCheckBarrierIfNeeded(
      @NotNull InstructionAdapter iv,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Type returnType,
      @Nullable final Type delegateParameterType) {
    BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue =
        BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(
            descriptor);
    if (defaultValue == null) return;

    assert descriptor.getValueParameters().size() == 1
        : "Should be descriptor with one value parameter, but found: " + descriptor;

    boolean isCheckForAny =
        delegateParameterType == null || OBJECT_TYPE.equals(delegateParameterType);

    final KotlinType kotlinType = descriptor.getValueParameters().get(0).getType();

    if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) return;

    iv.load(1, OBJECT_TYPE);

    Label afterBarrier = new Label();

    if (isCheckForAny) {
      assert !TypeUtils.isNullableType(kotlinType)
          : "Only bridges for not-nullable types are necessary";
      iv.ifnonnull(afterBarrier);
    } else {
      CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterType));
      iv.ifne(afterBarrier);
    }

    StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv);
    iv.areturn(returnType);

    iv.visitLabel(afterBarrier);
  }
Esempio n. 8
0
  private static void equipFunctionReferenceWithReflection(
      @NotNull InstructionAdapter v, @NotNull FunctionDescriptor target) {
    DeclarationDescriptor container = target.getContainingDeclaration();

    Type type;
    if (container instanceof PackageFragmentDescriptor) {
      type =
          target.getExtensionReceiverParameter() != null
              ? K_TOP_LEVEL_EXTENSION_FUNCTION
              : K_TOP_LEVEL_FUNCTION;
    } else if (container instanceof ClassDescriptor) {
      type = K_MEMBER_FUNCTION;
    } else {
      type = K_LOCAL_FUNCTION;
    }

    Method method = method("function", K_FUNCTION, FUNCTION_REFERENCE);
    v.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false);
    StackValue.coerce(K_FUNCTION, type, v);
  }
Esempio n. 9
0
  public static void putStackValuesIntoLocals(
      List<Type> directOrder, int shift, InstructionAdapter iv, String descriptor) {
    Type[] actualParams = Type.getArgumentTypes(descriptor);
    assert actualParams.length == directOrder.size()
        : "Number of expected and actual params should be equals!";

    int size = 0;
    for (Type next : directOrder) {
      size += next.getSize();
    }

    shift += size;
    int index = directOrder.size();

    for (Type next : Lists.reverse(directOrder)) {
      shift -= next.getSize();
      Type typeOnStack = actualParams[--index];
      if (!typeOnStack.equals(next)) {
        StackValue.onStack(typeOnStack).put(next, iv);
      }
      iv.store(shift, next);
    }
  }
Esempio n. 10
0
 public void visitVarInsn(int opcode, int var, InstructionAdapter mv) {
   RemapInfo remapInfo = remap(var);
   StackValue value = remapInfo.value;
   if (value instanceof StackValue.Local) {
     if (remapInfo.parameterInfo != null) {
       // All remapped value parameters can't be rewritten except case of default ones.
       // On remapping default parameter to actual value there is only one instruction that writes
       // to it according to mask value
       // but if such parameter remapped then it passed and this mask branch code never executed
       // TODO add assertion about parameter default value: descriptor is required
       opcode =
           value.type.getOpcode(
               InlineCodegenUtil.isStoreInstruction(opcode) ? Opcodes.ISTORE : Opcodes.ILOAD);
     }
     mv.visitVarInsn(opcode, ((StackValue.Local) value).index);
     if (remapInfo.parameterInfo != null) {
       StackValue.coerce(value.type, remapInfo.parameterInfo.type, mv);
     }
   } else {
     assert remapInfo.parameterInfo != null : "Non local value should have parameter info";
     value.put(remapInfo.parameterInfo.type, mv);
   }
 }
Esempio n. 11
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;
  }
Esempio n. 12
0
  private static void generateDelegateToMethodBody(
      boolean isStatic,
      @NotNull MethodVisitor mv,
      @NotNull Method asmMethod,
      @NotNull String classToDelegateTo) {
    InstructionAdapter iv = new InstructionAdapter(mv);
    Type[] argTypes = asmMethod.getArgumentTypes();

    // The first line of some package file is written to the line number attribute of a static
    // delegate to allow to 'step into' it
    // This is similar to what javac does with bridge methods
    Label label = new Label();
    iv.visitLabel(label);
    iv.visitLineNumber(1, label);

    int k = isStatic ? 0 : 1;
    for (Type argType : argTypes) {
      iv.load(k, argType);
      k += argType.getSize();
    }
    iv.invokestatic(classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), false);
    iv.areturn(asmMethod.getReturnType());
  }
Esempio n. 13
0
  public static void generateDefaultImplBody(
      @NotNull MethodContext methodContext,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodVisitor mv,
      @NotNull DefaultParameterValueLoader loadStrategy,
      @Nullable KtNamedFunction function,
      @NotNull MemberCodegen<?> parentCodegen,
      @NotNull Method defaultMethod) {
    GenerationState state = parentCodegen.state;
    JvmMethodSignature signature =
        state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());

    boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
    FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic);

    ExpressionCodegen codegen =
        new ExpressionCodegen(
            mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);

    CallGenerator generator =
        codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);

    InstructionAdapter iv = new InstructionAdapter(mv);
    genDefaultSuperCallCheckIfNeeded(iv, defaultMethod);

    loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);

    List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
    int capturedArgumentsCount = 0;
    while (capturedArgumentsCount < mappedParameters.size()
        && mappedParameters.get(capturedArgumentsCount).getKind() != JvmMethodParameterKind.VALUE) {
      capturedArgumentsCount++;
    }

    int maskIndex = 0;
    List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
    for (int index = 0; index < valueParameters.size(); index++) {
      if (index % Integer.SIZE == 0) {
        maskIndex = frameMap.enterTemp(Type.INT_TYPE);
      }
      ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
      Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();

      int parameterIndex = frameMap.getIndex(parameterDescriptor);
      if (parameterDescriptor.declaresDefaultValue()) {
        iv.load(maskIndex, Type.INT_TYPE);
        iv.iconst(1 << (index % Integer.SIZE));
        iv.and(Type.INT_TYPE);
        Label loadArg = new Label();
        iv.ifeq(loadArg);

        StackValue.local(parameterIndex, type)
            .store(loadStrategy.genValue(parameterDescriptor, codegen), iv);

        iv.mark(loadArg);
      }

      generator.putValueIfNeeded(type, StackValue.local(parameterIndex, type));
    }

    CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);

    generator.genCallWithoutAssertions(method, codegen);

    iv.areturn(signature.getReturnType());
  }
 public static void generateGlobalReturnFlag(
     @NotNull InstructionAdapter iv, @NotNull String labelName) {
   iv.invokestatic(NON_LOCAL_RETURN, labelName, "()V", false);
 }
Esempio n. 15
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);
  }