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); }
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); }