Example #1
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);
  }
Example #2
0
  @NotNull
  public StackValue putInstanceOnStack(
      @NotNull final ExpressionCodegen codegen,
      @Nullable final FunctionDescriptor functionReferenceTarget) {
    return StackValue.operation(
        asmType,
        new Function1<InstructionAdapter, Unit>() {
          @Override
          public Unit invoke(InstructionAdapter v) {
            if (isConst(closure)) {
              v.getstatic(
                  asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
            } else {
              v.anew(asmType);
              v.dup();

              codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator);
              v.invokespecial(
                  asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
            }

            if (functionReferenceTarget != null) {
              equipFunctionReferenceWithReflection(v, functionReferenceTarget);
            }

            return Unit.INSTANCE$;
          }
        });
  }
Example #3
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);
  }
Example #4
0
  private static void loadExplicitArgumentsOnStack(
      @NotNull Type ownerType,
      boolean isStatic,
      @NotNull JvmMethodSignature signature,
      @NotNull CallGenerator callGenerator) {
    int var = 0;
    if (!isStatic) {
      callGenerator.putValueIfNeeded(ownerType, StackValue.local(var, ownerType));
      var += ownerType.getSize();
    }

    for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
      if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
        Type type = parameterSignature.getAsmType();
        callGenerator.putValueIfNeeded(type, StackValue.local(var, type));
        var += type.getSize();
      }
    }
  }
Example #5
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);
  }
Example #6
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);
  }
Example #7
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());
  }