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
  public static void generateMethodBody(
      @NotNull MethodVisitor mv,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext context,
      @NotNull JvmMethodSignature signature,
      @NotNull FunctionGenerationStrategy strategy,
      @NotNull MemberCodegen<?> parentCodegen) {
    mv.visitCode();

    Label methodBegin = new Label();
    mv.visitLabel(methodBegin);

    JetTypeMapper typeMapper = parentCodegen.typeMapper;
    if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(
        functionDescriptor, getSignatureMapper(typeMapper))) {
      generateTypeCheckBarrierIfNeeded(
          new InstructionAdapter(mv),
          functionDescriptor,
          signature.getReturnType(),
          /* delegateParameterType = */ null);
    }

    Label methodEnd;

    int functionFakeIndex = -1;
    int lambdaFakeIndex = -1;

    if (context.getParentContext() instanceof MultifileClassFacadeContext) {
      generateFacadeDelegateMethodBody(
          mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
      methodEnd = new Label();
    } else {
      FrameMap frameMap =
          createFrameMap(
              parentCodegen.state,
              functionDescriptor,
              signature,
              isStaticMethod(context.getContextKind(), functionDescriptor));
      if (context.isInlineMethodContext()) {
        functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
      }

      if (context instanceof InlineLambdaContext) {
        lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
      }

      Label methodEntry = new Label();
      mv.visitLabel(methodEntry);
      context.setMethodStartLabel(methodEntry);

      if (!JetTypeMapper.isAccessor(functionDescriptor)) {
        genNotNullAssertionsForParameters(
            new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
      }
      methodEnd = new Label();
      context.setMethodEndLabel(methodEnd);
      strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
    }

    mv.visitLabel(methodEnd);

    Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
    generateLocalVariableTable(
        mv,
        signature,
        functionDescriptor,
        thisType,
        methodBegin,
        methodEnd,
        context.getContextKind());

    if (context.isInlineMethodContext() && functionFakeIndex != -1) {
      mv.visitLocalVariable(
          JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION
              + functionDescriptor.getName().asString(),
          Type.INT_TYPE.getDescriptor(),
          null,
          methodBegin,
          methodEnd,
          functionFakeIndex);
    }

    if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
      String name = thisType.getClassName();
      int indexOfLambdaOrdinal = name.lastIndexOf("$");
      if (indexOfLambdaOrdinal > 0) {
        int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
        mv.visitLocalVariable(
            JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal,
            Type.INT_TYPE.getDescriptor(),
            null,
            methodBegin,
            methodEnd,
            lambdaFakeIndex);
      }
    }
  }