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); }
@NotNull protected ExpressionCodegen createOrGetClInitCodegen() { DeclarationDescriptor descriptor = context.getContextDescriptor(); assert state.getClassBuilderMode() == ClassBuilderMode.FULL : "<clinit> should not be generated for light classes. Descriptor: " + descriptor; if (clInit == null) { MethodVisitor mv = v.newMethod(null, ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); SimpleFunctionDescriptorImpl clInit = SimpleFunctionDescriptorImpl.create( descriptor, Annotations.EMPTY, Name.special("<clinit>"), SYNTHESIZED); clInit.initialize( null, null, Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE); this.clInit = new ExpressionCodegen( mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this); } return clInit; }
void generateDefaultIfNeeded( @NotNull MethodContext owner, @NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind, @NotNull DefaultParameterValueLoader loadStrategy, @Nullable KtNamedFunction function) { DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration(); if (kind != OwnerKind.DEFAULT_IMPLS && isInterface(contextClass)) { return; } if (!isDefaultNeeded(functionDescriptor)) { return; } int flags = getVisibilityAccessFlag(functionDescriptor) | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC; if (!(functionDescriptor instanceof ConstructorDescriptor)) { flags |= ACC_STATIC | ACC_BRIDGE; } // $default methods are never private to be accessible from other class files (e.g. inner) // without the need of synthetic accessors flags &= ~ACC_PRIVATE; Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind); MethodVisitor mv = v.newMethod( JvmDeclarationOriginKt.Synthetic(function, functionDescriptor), flags, defaultMethod.getName(), defaultMethod.getDescriptor(), null, getThrownExceptions(functionDescriptor, typeMapper)); // Only method annotations are copied to the $default method. Parameter annotations are not // copied until there are valid use cases; // enum constructors have two additional synthetic parameters which somewhat complicate this // task AnnotationCodegen.forMethod(mv, typeMapper) .genAnnotations(functionDescriptor, defaultMethod.getReturnType()); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (this.owner instanceof MultifileClassFacadeContext) { mv.visitCode(); generateFacadeDelegateMethodBody( mv, defaultMethod, (MultifileClassFacadeContext) this.owner); endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor)); } else { mv.visitCode(); generateDefaultImplBody( owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod); endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor)); } } }
private void generateStaticInitializer() { if (staticInitializerChunks.size() > 0) { MethodVisitor mv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null); if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { mv.visitCode(); InstructionAdapter v = new InstructionAdapter(mv); for (CodeChunk chunk : staticInitializerChunks) { chunk.generate(v); } mv.visitInsn(RETURN); FunctionCodegen.endVisit(v, "static initializer", myClass); } } }
private void generatePrimaryConstructorProperties( PropertyCodegen propertyCodegen, JetClassOrObject origin) { boolean isAnnotation = origin instanceof JetClass && ((JetClass) origin).isAnnotation(); for (JetParameter p : getPrimaryConstructorParameters()) { if (p.getValOrVarNode() != null) { PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); if (propertyDescriptor != null) { if (!isAnnotation) { propertyCodegen.generatePrimaryConstructorProperty(p, propertyDescriptor); } else { Type type = state.getTypeMapper().mapType(propertyDescriptor); v.newMethod( p, ACC_PUBLIC | ACC_ABSTRACT, p.getName(), "()" + type.getDescriptor(), null, null); } } } } }
public void generateDefaultSetter( PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) { if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { throw new IllegalStateException("must not generate code for fake overrides"); } if (kind == OwnerKind.TRAIT_IMPL) { return; } if (kind == OwnerKind.NAMESPACE) { flags |= Opcodes.ACC_STATIC; } PsiElement psiElement = state .getBindingContext() .get( BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration()); boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait(); if (isTrait && !(kind instanceof OwnerKind.DelegateKind)) flags |= Opcodes.ACC_ABSTRACT; if (propertyDescriptor.getModality() == Modality.FINAL) { flags |= Opcodes.ACC_FINAL; } JvmPropertyAccessorSignature signature = state.getInjector().getJetTypeMapper().mapSetterSignature(propertyDescriptor, kind); final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); MethodVisitor mv = v.newMethod( origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null); generateJetPropertyAnnotation( mv, signature.getPropertyTypeKotlinSignature(), signature.getJvmMethodSignature().getKotlinTypeParameter()); if (propertyDescriptor.getSetter() != null) { assert !propertyDescriptor.getSetter().hasBody(); AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()) .genAnnotations(propertyDescriptor.getSetter()); } if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { if (propertyDescriptor.getModality() != Modality.ABSTRACT) { mv.visitCode(); if (v.generateCode() == ClassBuilder.Mode.STUBS) { StubCodegen.generateStubThrow(mv); } else { InstructionAdapter iv = new InstructionAdapter(mv); final Type type = state .getInjector() .getJetTypeMapper() .mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); int paramCode = 0; if (kind != OwnerKind.NAMESPACE) { iv.load(0, JetTypeMapper.TYPE_OBJECT); paramCode = 1; } if ((kind instanceof OwnerKind.DelegateKind) != (propertyDescriptor.getKind() == FunctionDescriptor.Kind.DELEGATION)) { throw new IllegalStateException("mismatching kind in " + propertyDescriptor); } if (kind instanceof OwnerKind.DelegateKind) { OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; iv.load(0, JetTypeMapper.TYPE_OBJECT); dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); iv.load(paramCode, type); iv.invokeinterface( dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor); } else { iv.load(paramCode, type); iv.visitFieldInsn( kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, state.getInjector().getJetTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } iv.visitInsn(Opcodes.RETURN); } } FunctionCodegen.endVisit(mv, "setter", origin); } }
public void generateBridges(@NotNull FunctionDescriptor descriptor) { if (descriptor instanceof ConstructorDescriptor) return; if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return; if (isInterface(descriptor.getContainingDeclaration())) return; // equals(Any?), hashCode(), toString() never need bridges if (isMethodOfAny(descriptor)) return; // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter // or alike and doesn't need bridges if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return; boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null; Set<Bridge<Method>> bridgesToGenerate; if (!isSpecial) { bridgesToGenerate = ImplKt.generateBridgesForFunctionDescriptor(descriptor, getSignatureMapper(typeMapper)); if (!bridgesToGenerate.isEmpty()) { PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null; boolean isSpecialBridge = BuiltinMethodsWithSpecialGenericSignature .getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) != null; for (Bridge<Method> bridge : bridgesToGenerate) { generateBridge( origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false); } } } else { Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial( descriptor, getSignatureMapper(typeMapper)); if (!specials.isEmpty()) { PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null; for (BridgeForBuiltinSpecial<Method> bridge : specials) { generateBridge( origin, descriptor, bridge.getFrom(), bridge.getTo(), bridge.isSpecial(), bridge.isDelegateToSuper()); } } if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) { CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor); assert overridden != null; Method method = typeMapper.mapSignature(descriptor).getAsmMethod(); int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor); v.newMethod( JvmDeclarationOriginKt.OtherOrigin(overridden), flags, method.getName(), method.getDescriptor(), null, null); } } }
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()); }