001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.codegen;
018    
019    import com.intellij.openapi.progress.ProcessCanceledException;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.util.ArrayUtil;
022    import com.intellij.util.Function;
023    import com.intellij.util.containers.ContainerUtil;
024    import kotlin.jvm.functions.Function1;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.kotlin.backend.common.bridges.Bridge;
028    import org.jetbrains.kotlin.backend.common.bridges.BridgesPackage;
029    import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
030    import org.jetbrains.kotlin.codegen.context.*;
031    import org.jetbrains.kotlin.codegen.optimization.OptimizationMethodVisitor;
032    import org.jetbrains.kotlin.codegen.state.GenerationState;
033    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
034    import org.jetbrains.kotlin.descriptors.*;
035    import org.jetbrains.kotlin.descriptors.annotations.Annotated;
036    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
037    import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
038    import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo;
039    import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
040    import org.jetbrains.kotlin.load.kotlin.nativeDeclarations.NativeDeclarationsPackage;
041    import org.jetbrains.kotlin.name.FqName;
042    import org.jetbrains.kotlin.psi.JetNamedFunction;
043    import org.jetbrains.kotlin.resolve.BindingContext;
044    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
045    import org.jetbrains.kotlin.resolve.DescriptorUtils;
046    import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
047    import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilPackage;
048    import org.jetbrains.kotlin.resolve.constants.ArrayValue;
049    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
050    import org.jetbrains.kotlin.resolve.constants.KClassValue;
051    import org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage;
052    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
053    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
054    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
055    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
056    import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
057    import org.jetbrains.org.objectweb.asm.Label;
058    import org.jetbrains.org.objectweb.asm.MethodVisitor;
059    import org.jetbrains.org.objectweb.asm.Type;
060    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
061    import org.jetbrains.org.objectweb.asm.commons.Method;
062    import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
063    
064    import java.io.PrintWriter;
065    import java.io.StringWriter;
066    import java.util.Collection;
067    import java.util.Iterator;
068    import java.util.List;
069    import java.util.Set;
070    
071    import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
072    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
073    import static org.jetbrains.kotlin.codegen.JvmSerializationBindings.*;
074    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
075    import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
076    import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
077    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
078    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
079    import static org.jetbrains.kotlin.resolve.jvm.diagnostics.DiagnosticsPackage.*;
080    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
081    
082    public class FunctionCodegen {
083        public final GenerationState state;
084        private final JetTypeMapper typeMapper;
085        private final BindingContext bindingContext;
086        private final CodegenContext owner;
087        private final ClassBuilder v;
088        private final MemberCodegen<?> memberCodegen;
089    
090        public FunctionCodegen(
091                @NotNull CodegenContext owner,
092                @NotNull ClassBuilder v,
093                @NotNull GenerationState state,
094                @NotNull MemberCodegen<?> memberCodegen
095        ) {
096            this.owner = owner;
097            this.v = v;
098            this.state = state;
099            this.typeMapper = state.getTypeMapper();
100            this.bindingContext = state.getBindingContext();
101            this.memberCodegen = memberCodegen;
102        }
103    
104        public void gen(@NotNull JetNamedFunction function) {
105            SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, function);
106            assert functionDescriptor != null : "No descriptor for function " + function.getText() + "\n" +
107                                                "in " + function.getContainingFile().getVirtualFile();
108    
109            if (owner.getContextKind() != OwnerKind.TRAIT_IMPL || function.hasBody()) {
110                generateMethod(OtherOrigin(function, functionDescriptor), functionDescriptor,
111                               new FunctionGenerationStrategy.FunctionDefault(state, functionDescriptor, function));
112            }
113    
114            generateDefaultIfNeeded(owner.intoFunction(functionDescriptor), functionDescriptor, owner.getContextKind(),
115                                    DefaultParameterValueLoader.DEFAULT, function);
116    
117            generateOverloadsWithDefaultValues(function, functionDescriptor, functionDescriptor);
118        }
119    
120        public void generateOverloadsWithDefaultValues(
121                @Nullable JetNamedFunction function,
122                @NotNull FunctionDescriptor functionDescriptor,
123                @NotNull FunctionDescriptor delegateFunctionDescriptor
124        ) {
125            new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded(
126                    function, functionDescriptor, delegateFunctionDescriptor, owner.getContextKind(), v
127            );
128        }
129    
130        public void generateMethod(
131                @NotNull JvmDeclarationOrigin origin,
132                @NotNull FunctionDescriptor descriptor,
133                @NotNull FunctionGenerationStrategy strategy
134        ) {
135            generateMethod(origin, descriptor, owner.intoFunction(descriptor), strategy);
136        }
137    
138        public void generateMethod(
139                @NotNull JvmDeclarationOrigin origin,
140                @NotNull FunctionDescriptor functionDescriptor,
141                @NotNull MethodContext methodContext,
142                @NotNull FunctionGenerationStrategy strategy
143        ) {
144            OwnerKind contextKind = methodContext.getContextKind();
145            if (isTrait(functionDescriptor.getContainingDeclaration()) &&
146                functionDescriptor.getVisibility() == Visibilities.PRIVATE &&
147                contextKind != OwnerKind.TRAIT_IMPL) {
148                return;
149            }
150    
151            JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, contextKind);
152            Method asmMethod = jvmSignature.getAsmMethod();
153    
154            int flags = getMethodAsmFlags(functionDescriptor, contextKind);
155            boolean isNative = NativeDeclarationsPackage.hasNativeAnnotation(functionDescriptor);
156    
157            if (isNative && owner instanceof DelegatingFacadeContext) {
158                // Native methods are only defined in facades and do not need package part implementations
159                return;
160            }
161            MethodVisitor mv = v.newMethod(origin,
162                                           flags,
163                                           asmMethod.getName(),
164                                           asmMethod.getDescriptor(),
165                                           jvmSignature.getGenericsSignature(),
166                                           getThrownExceptions(functionDescriptor, typeMapper));
167    
168            String implClassName = CodegenContextUtil.getImplementationClassShortName(owner);
169            if (implClassName != null) {
170                v.getSerializationBindings().put(IMPL_CLASS_NAME_FOR_CALLABLE, functionDescriptor, implClassName);
171            }
172            if (CodegenContextUtil.isImplClassOwner(owner)) {
173                v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
174            }
175    
176            generateMethodAnnotations(functionDescriptor, asmMethod, mv);
177    
178            generateParameterAnnotations(functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));
179    
180            generateBridges(functionDescriptor);
181    
182            boolean staticInCompanionObject = AnnotationsPackage.isPlatformStaticInCompanionObject(functionDescriptor);
183            if (staticInCompanionObject) {
184                ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
185                parentBodyCodegen.addAdditionalTask(new PlatformStaticGenerator(functionDescriptor, origin, state));
186            }
187    
188            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES || isAbstractMethod(functionDescriptor, contextKind)) {
189                generateLocalVariableTable(
190                        mv,
191                        jvmSignature,
192                        functionDescriptor,
193                        getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
194                        new Label(),
195                        new Label(),
196                        contextKind
197                );
198    
199                mv.visitEnd();
200                return;
201            }
202    
203            if (!isNative) {
204                generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
205            }
206            else if (staticInCompanionObject) {
207                // native platformStatic foo() in companion object should delegate to the static native function moved to the outer class
208                mv.visitCode();
209                FunctionDescriptor staticFunctionDescriptor = PlatformStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
210                JvmMethodSignature jvmMethodSignature =
211                        typeMapper.mapSignature(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
212                Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
213                generateDelegateToMethodBody(false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
214            }
215    
216            endVisit(mv, null, origin.getElement());
217    
218            methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext);
219        }
220    
221        private void generateMethodAnnotations(
222                @NotNull FunctionDescriptor functionDescriptor,
223                Method asmMethod,
224                MethodVisitor mv
225        ) {
226            AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, typeMapper);
227    
228            if (functionDescriptor instanceof PropertyAccessorDescriptor) {
229                AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
230                annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType(), target);
231            }
232            else {
233                annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
234            }
235    
236            writePackageFacadeMethodAnnotationsIfNeeded(mv);
237        }
238    
239        private void writePackageFacadeMethodAnnotationsIfNeeded(MethodVisitor mv) {
240            if (owner instanceof PackageFacadeContext) {
241                PackageFacadeContext packageFacadeContext = (PackageFacadeContext) owner;
242                Type delegateToClassType = packageFacadeContext.getDelegateToClassType();
243                if (delegateToClassType != null) {
244                    String className = delegateToClassType.getClassName();
245                    AnnotationVisitor
246                            av = mv.visitAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_DELEGATED_METHOD), true);
247                    av.visit(JvmAnnotationNames.IMPLEMENTATION_CLASS_NAME_FIELD_NAME, className);
248                    av.visitEnd();
249                }
250            }
251        }
252    
253        private void generateParameterAnnotations(
254                @NotNull FunctionDescriptor functionDescriptor,
255                @NotNull MethodVisitor mv,
256                @NotNull JvmMethodSignature jvmSignature
257        ) {
258            Iterator<ValueParameterDescriptor> iterator = functionDescriptor.getValueParameters().iterator();
259            List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
260    
261            for (int i = 0; i < kotlinParameterTypes.size(); i++) {
262                JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
263                JvmMethodParameterKind kind = parameterSignature.getKind();
264                if (kind.isSkippedInGenericSignature()) {
265                    markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
266                    continue;
267                }
268    
269                if (kind == JvmMethodParameterKind.VALUE) {
270                    ValueParameterDescriptor parameter = iterator.next();
271                    v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
272                    AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
273    
274                    if (functionDescriptor instanceof PropertySetterDescriptor) {
275                        PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
276                        Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
277                        annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
278                    }
279    
280                    if (functionDescriptor instanceof ConstructorDescriptor) {
281                        annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType(), CONSTRUCTOR_PARAMETER);
282                    }
283                    else {
284                        annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType());
285                    }
286                }
287                else if (kind == JvmMethodParameterKind.RECEIVER) {
288                    ReceiverParameterDescriptor receiver = ((functionDescriptor instanceof PropertyAccessorDescriptor)
289                                                 ? ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty()
290                                                 : functionDescriptor).getExtensionReceiverParameter();
291                    if (receiver != null) {
292                        AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
293                        Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
294                        annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
295                    }
296                }
297            }
298        }
299    
300        private void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i) {
301            // IDEA's ClsPsi builder fails to annotate synthetic parameters
302            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
303    
304            // This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac:
305            // see MethodWriter.visitParameterAnnotation()
306    
307            AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", true);
308            if (av != null) {
309                av.visitEnd();
310            }
311        }
312    
313        @Nullable
314        private static Type getThisTypeForFunction(
315                @NotNull FunctionDescriptor functionDescriptor,
316                @NotNull MethodContext context,
317                @NotNull JetTypeMapper typeMapper
318        ) {
319            ReceiverParameterDescriptor dispatchReceiver = functionDescriptor.getDispatchReceiverParameter();
320            if (functionDescriptor instanceof ConstructorDescriptor) {
321                return typeMapper.mapType(functionDescriptor);
322            }
323            else if (dispatchReceiver != null) {
324                return typeMapper.mapType(dispatchReceiver.getType());
325            }
326            else if (isFunctionLiteral(functionDescriptor) ||
327                     isLocalFunction(functionDescriptor) ||
328                     isFunctionExpression(functionDescriptor)
329                    ) {
330                return typeMapper.mapType(context.getThisDescriptor());
331            }
332            else {
333                return null;
334            }
335        }
336    
337        public static void generateMethodBody(
338                @NotNull MethodVisitor mv,
339                @NotNull FunctionDescriptor functionDescriptor,
340                @NotNull MethodContext context,
341                @NotNull JvmMethodSignature signature,
342                @NotNull FunctionGenerationStrategy strategy,
343                @NotNull MemberCodegen<?> parentCodegen
344        ) {
345            mv.visitCode();
346    
347            Label methodBegin = new Label();
348            mv.visitLabel(methodBegin);
349    
350            JetTypeMapper typeMapper = parentCodegen.typeMapper;
351    
352            Label methodEnd;
353            if (context.getParentContext() instanceof DelegatingFacadeContext) {
354                generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (DelegatingFacadeContext) context.getParentContext());
355                methodEnd = new Label();
356            }
357            else {
358                FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(),
359                                                                                                                      functionDescriptor));
360    
361                Label methodEntry = new Label();
362                mv.visitLabel(methodEntry);
363                context.setMethodStartLabel(methodEntry);
364    
365                if (!JetTypeMapper.isAccessor(functionDescriptor)) {
366                    genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
367                }
368                methodEnd = new Label();
369                context.setMethodEndLabel(methodEnd);
370                strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
371            }
372    
373            mv.visitLabel(methodEnd);
374    
375            Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
376            generateLocalVariableTable(mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind());
377        }
378    
379        private static void generateLocalVariableTable(
380                @NotNull MethodVisitor mv,
381                @NotNull JvmMethodSignature jvmMethodSignature,
382                @NotNull FunctionDescriptor functionDescriptor,
383                @Nullable Type thisType,
384                @NotNull Label methodBegin,
385                @NotNull Label methodEnd,
386                @NotNull OwnerKind ownerKind
387        ) {
388            Iterator<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters().iterator();
389            List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
390            int shift = 0;
391    
392            boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
393            if (!isStatic) {
394                //add this
395                if (thisType != null) {
396                    mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
397                }
398                else {
399                    //TODO: provide thisType for callable reference
400                }
401                shift++;
402            }
403    
404            for (int i = 0; i < params.size(); i++) {
405                JvmMethodParameterSignature param = params.get(i);
406                JvmMethodParameterKind kind = param.getKind();
407                String parameterName;
408    
409                if (kind == JvmMethodParameterKind.VALUE) {
410                    ValueParameterDescriptor parameter = valueParameters.next();
411                    parameterName = parameter.getName().asString();
412                }
413                else {
414                    String lowercaseKind = kind.name().toLowerCase();
415                    parameterName = needIndexForVar(kind)
416                                    ? "$" + lowercaseKind + "$" + i
417                                    : "$" + lowercaseKind;
418                }
419    
420                Type type = param.getAsmType();
421                mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift);
422                shift += type.getSize();
423            }
424        }
425    
426        private static void generateFacadeDelegateMethodBody(
427                @NotNull MethodVisitor mv,
428                @NotNull Method asmMethod,
429                @NotNull DelegatingFacadeContext context
430        ) {
431            generateDelegateToMethodBody(true, mv, asmMethod, context.getDelegateToClassType().getInternalName());
432        }
433    
434        private static void generateDelegateToMethodBody(
435                boolean isStatic,
436                @NotNull MethodVisitor mv,
437                @NotNull Method asmMethod,
438                @NotNull String classToDelegateTo
439        ) {
440            InstructionAdapter iv = new InstructionAdapter(mv);
441            Type[] argTypes = asmMethod.getArgumentTypes();
442    
443            // The first line of some package file is written to the line number attribute of a static delegate to allow to 'step into' it
444            // This is similar to what javac does with bridge methods
445            Label label = new Label();
446            iv.visitLabel(label);
447            iv.visitLineNumber(1, label);
448    
449            int k = isStatic ? 0 : 1;
450            for (Type argType : argTypes) {
451                iv.load(k, argType);
452                k += argType.getSize();
453            }
454            iv.invokestatic(classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), false);
455            iv.areturn(asmMethod.getReturnType());
456        }
457    
458        private static boolean needIndexForVar(JvmMethodParameterKind kind) {
459            return kind == JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE ||
460                   kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL ||
461                   kind == JvmMethodParameterKind.SUPER_CALL_PARAM;
462        }
463    
464        public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) {
465            try {
466                mv.visitMaxs(-1, -1);
467                mv.visitEnd();
468            }
469            catch (ProcessCanceledException e) {
470                throw e;
471            }
472            catch (Throwable t) {
473                String bytecode = renderByteCodeIfAvailable(mv);
474                throw new CompilationException(
475                        "wrong code generated" +
476                        (description != null ? " for " + description : "") +
477                        t.getClass().getName() +
478                        " " +
479                        t.getMessage() +
480                        (bytecode != null ? "\nbytecode:\n" + bytecode : ""),
481                        t, method);
482            }
483        }
484    
485        private static String renderByteCodeIfAvailable(MethodVisitor mv) {
486            String bytecode = null;
487    
488            if (mv instanceof OptimizationMethodVisitor) {
489                mv = ((OptimizationMethodVisitor) mv).getTraceMethodVisitorIfPossible();
490            }
491    
492            if (mv instanceof TraceMethodVisitor) {
493                TraceMethodVisitor traceMethodVisitor = (TraceMethodVisitor) mv;
494                StringWriter sw = new StringWriter();
495                PrintWriter pw = new PrintWriter(sw);
496                traceMethodVisitor.p.print(pw);
497                pw.close();
498                bytecode = sw.toString();
499            }
500            return bytecode;
501        }
502    
503        public void generateBridges(@NotNull FunctionDescriptor descriptor) {
504            if (descriptor instanceof ConstructorDescriptor) return;
505            if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) return;
506            if (isTrait(descriptor.getContainingDeclaration())) return;
507    
508            // equals(Any?), hashCode(), toString() never need bridges
509            if (isMethodOfAny(descriptor)) return;
510    
511            // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter or alike and doesn't need bridges
512            if (CallResolverUtilPackage.isOrOverridesSynthesized(descriptor)) return;
513    
514            Set<Bridge<Method>> bridgesToGenerate = BridgesPackage.generateBridgesForFunctionDescriptor(
515                    descriptor,
516                    new Function1<FunctionDescriptor, Method>() {
517                        @Override
518                        public Method invoke(FunctionDescriptor descriptor) {
519                            return typeMapper.mapSignature(descriptor).getAsmMethod();
520                        }
521                    }
522            );
523    
524            if (!bridgesToGenerate.isEmpty()) {
525                PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
526                for (Bridge<Method> bridge : bridgesToGenerate) {
527                    generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo());
528                }
529            }
530        }
531    
532        private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
533            String name = descriptor.getName().asString();
534            List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
535            if (parameters.isEmpty()) {
536                return name.equals("hashCode") || name.equals("toString");
537            }
538            else if (parameters.size() == 1 && name.equals("equals")) {
539                return isNullableAny(parameters.get(0).getType());
540            }
541            return false;
542        }
543    
544        @NotNull
545        public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull final JetTypeMapper mapper) {
546            AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
547            if (annotation == null) {
548                annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
549            }
550    
551            if (annotation == null) return ArrayUtil.EMPTY_STRING_ARRAY;
552    
553            Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
554            if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
555    
556            Object value = values.iterator().next();
557            if (!(value instanceof ArrayValue)) return ArrayUtil.EMPTY_STRING_ARRAY;
558            ArrayValue arrayValue = (ArrayValue) value;
559    
560            List<String> strings = ContainerUtil.mapNotNull(
561                    arrayValue.getValue(),
562                    new Function<ConstantValue<?>, String>() {
563                        @Override
564                        public String fun(ConstantValue<?> constant) {
565                            if (constant instanceof KClassValue) {
566                                KClassValue classValue = (KClassValue) constant;
567                                ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(classValue.getValue());
568                                return mapper.mapClass(classDescriptor).getInternalName();
569                            }
570                            return null;
571                        }
572                    }
573            );
574            return ArrayUtil.toStringArray(strings);
575        }
576    
577        void generateDefaultIfNeeded(
578                @NotNull MethodContext owner,
579                @NotNull FunctionDescriptor functionDescriptor,
580                @NotNull OwnerKind kind,
581                @NotNull DefaultParameterValueLoader loadStrategy,
582                @Nullable JetNamedFunction function
583        ) {
584            DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
585    
586            if (kind != OwnerKind.TRAIT_IMPL && isTrait(contextClass)) {
587                return;
588            }
589    
590            if (!isDefaultNeeded(functionDescriptor)) {
591                return;
592            }
593    
594            int flags = getVisibilityAccessFlag(functionDescriptor) |
595                        getDeprecatedAccessFlag(functionDescriptor) |
596                        ACC_SYNTHETIC;
597            if (!(functionDescriptor instanceof ConstructorDescriptor)) {
598                flags |= ACC_STATIC;
599            }
600            // $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
601            flags &= ~ACC_PRIVATE;
602    
603            Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);
604    
605            MethodVisitor mv = v.newMethod(
606                    Synthetic(function, functionDescriptor),
607                    flags,
608                    defaultMethod.getName(),
609                    defaultMethod.getDescriptor(), null,
610                    getThrownExceptions(functionDescriptor, typeMapper)
611            );
612    
613            // Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases;
614            // enum constructors have two additional synthetic parameters which somewhat complicate this task
615            AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
616    
617            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
618                if (this.owner instanceof DelegatingFacadeContext) {
619                    mv.visitCode();
620                    generateFacadeDelegateMethodBody(mv, defaultMethod, (DelegatingFacadeContext) this.owner);
621                    endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
622                }
623                else {
624                    mv.visitCode();
625                    generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen);
626                    endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
627                }
628            }
629        }
630    
631        public static void generateDefaultImplBody(
632                @NotNull MethodContext methodContext,
633                @NotNull FunctionDescriptor functionDescriptor,
634                @NotNull MethodVisitor mv,
635                @NotNull DefaultParameterValueLoader loadStrategy,
636                @Nullable JetNamedFunction function,
637                @NotNull MemberCodegen<?> parentCodegen
638        ) {
639            GenerationState state = parentCodegen.state;
640            JvmMethodSignature signature = state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());
641    
642            boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
643            FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic);
644    
645            ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
646    
647            CallGenerator generator = codegen.getOrCreateCallGenerator(functionDescriptor, function);
648    
649            loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
650    
651            List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
652            int capturedArgumentsCount = 0;
653            while (capturedArgumentsCount < mappedParameters.size() &&
654                   mappedParameters.get(capturedArgumentsCount).getKind() != JvmMethodParameterKind.VALUE) {
655                capturedArgumentsCount++;
656            }
657    
658            InstructionAdapter iv = new InstructionAdapter(mv);
659    
660            int maskIndex = 0;
661            List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
662            for (int index = 0; index < valueParameters.size(); index++) {
663                if (index % Integer.SIZE == 0) {
664                    maskIndex = frameMap.enterTemp(Type.INT_TYPE);
665                }
666                ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
667                Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
668    
669                int parameterIndex = frameMap.getIndex(parameterDescriptor);
670                if (parameterDescriptor.declaresDefaultValue()) {
671                    iv.load(maskIndex, Type.INT_TYPE);
672                    iv.iconst(1 << (index % Integer.SIZE));
673                    iv.and(Type.INT_TYPE);
674                    Label loadArg = new Label();
675                    iv.ifeq(loadArg);
676    
677                    StackValue.local(parameterIndex, type).store(loadStrategy.genValue(parameterDescriptor, codegen), iv);
678    
679                    iv.mark(loadArg);
680                }
681    
682                generator.putValueIfNeeded(parameterDescriptor, type, StackValue.local(parameterIndex, type));
683            }
684    
685            CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);
686    
687            generator.genCallWithoutAssertions(method, codegen);
688    
689            iv.areturn(signature.getReturnType());
690        }
691    
692        @NotNull
693        private static FrameMap createFrameMap(
694                @NotNull GenerationState state,
695                @NotNull FunctionDescriptor function,
696                @NotNull JvmMethodSignature signature,
697                boolean isStatic
698        ) {
699            FrameMap frameMap = new FrameMap();
700            if (!isStatic) {
701                frameMap.enterTemp(OBJECT_TYPE);
702            }
703    
704            for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
705                if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) {
706                    ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
707                    if (receiverParameter != null) {
708                        frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter));
709                    }
710                }
711                else if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
712                    frameMap.enterTemp(parameter.getAsmType());
713                }
714            }
715    
716            for (ValueParameterDescriptor parameter : function.getValueParameters()) {
717                frameMap.enter(parameter, state.getTypeMapper().mapType(parameter));
718            }
719    
720            return frameMap;
721        }
722    
723        private static void loadExplicitArgumentsOnStack(
724                @NotNull Type ownerType,
725                boolean isStatic,
726                @NotNull JvmMethodSignature signature,
727                @NotNull CallGenerator callGenerator
728        ) {
729            int var = 0;
730            if (!isStatic) {
731                callGenerator.putValueIfNeeded(null, ownerType, StackValue.local(var, ownerType));
732                var += ownerType.getSize();
733            }
734    
735            for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
736                if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
737                    Type type = parameterSignature.getAsmType();
738                    callGenerator.putValueIfNeeded(null, type, StackValue.local(var, type));
739                    var += type.getSize();
740                }
741            }
742        }
743    
744        private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) {
745            boolean needed = false;
746            if (functionDescriptor != null) {
747                for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
748                    if (parameterDescriptor.declaresDefaultValue()) {
749                        needed = true;
750                        break;
751                    }
752                }
753            }
754            return needed;
755        }
756    
757        private void generateBridge(
758                @Nullable PsiElement origin,
759                @NotNull FunctionDescriptor descriptor,
760                @NotNull Method bridge,
761                @NotNull Method delegateTo
762        ) {
763            int flags = ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC; // TODO.
764    
765            MethodVisitor mv =
766                    v.newMethod(DiagnosticsPackage.Bridge(descriptor, origin), flags, bridge.getName(), bridge.getDescriptor(), null, null);
767            if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
768    
769            mv.visitCode();
770    
771            Type[] argTypes = bridge.getArgumentTypes();
772            Type[] originalArgTypes = delegateTo.getArgumentTypes();
773    
774            InstructionAdapter iv = new InstructionAdapter(mv);
775            ImplementationBodyCodegen.markLineNumberForSyntheticFunction(owner.getThisDescriptor(), iv);
776    
777            iv.load(0, OBJECT_TYPE);
778            for (int i = 0, reg = 1; i < argTypes.length; i++) {
779                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
780                //noinspection AssignmentToForLoopParameter
781                reg += argTypes[i].getSize();
782            }
783    
784            iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
785    
786            StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
787            iv.areturn(bridge.getReturnType());
788    
789            endVisit(mv, "bridge method", origin);
790        }
791    
792        public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
793            genDelegate(functionDescriptor, overriddenDescriptor.getOriginal(),
794                        (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(), field);
795        }
796    
797        public void genDelegate(
798                @NotNull final FunctionDescriptor delegateFunction,
799                final FunctionDescriptor delegatedTo,
800                final ClassDescriptor toClass,
801                final StackValue field
802        ) {
803            generateMethod(
804                    Delegation(DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction), delegateFunction,
805                    new FunctionGenerationStrategy() {
806                        @Override
807                        public void generateBody(
808                                @NotNull MethodVisitor mv,
809                                @NotNull FrameMap frameMap,
810                                @NotNull JvmMethodSignature signature,
811                                @NotNull MethodContext context,
812                                @NotNull MemberCodegen<?> parentCodegen
813                        ) {
814                            Method delegateToMethod = typeMapper.mapSignature(delegatedTo).getAsmMethod();
815                            Method delegateMethod = typeMapper.mapSignature(delegateFunction).getAsmMethod();
816    
817                            Type[] argTypes = delegateMethod.getArgumentTypes();
818                            Type[] originalArgTypes = delegateToMethod.getArgumentTypes();
819    
820                            InstructionAdapter iv = new InstructionAdapter(mv);
821                            iv.load(0, OBJECT_TYPE);
822                            field.put(field.type, iv);
823                            for (int i = 0, reg = 1; i < argTypes.length; i++) {
824                                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
825                                //noinspection AssignmentToForLoopParameter
826                                reg += argTypes[i].getSize();
827                            }
828    
829                            String internalName = typeMapper.mapType(toClass).getInternalName();
830                            if (toClass.getKind() == ClassKind.INTERFACE) {
831                                iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
832                            }
833                            else {
834                                iv.invokevirtual(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
835                            }
836    
837                            StackValue stackValue = AsmUtil.genNotNullAssertions(
838                                    state,
839                                    StackValue.onStack(delegateToMethod.getReturnType()),
840                                    RuntimeAssertionInfo.create(
841                                            delegateFunction.getReturnType(),
842                                            delegatedTo.getReturnType(),
843                                            new RuntimeAssertionInfo.DataFlowExtras.OnlyMessage(delegatedTo.getName() + "(...)")
844                                    )
845                            );
846    
847                            stackValue.put(delegateMethod.getReturnType(), iv);
848    
849                            iv.areturn(delegateMethod.getReturnType());
850                        }
851                    }
852            );
853        }
854    }