001    /*
002     * Copyright 2010-2016 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.Unit;
025    import kotlin.collections.CollectionsKt;
026    import kotlin.jvm.functions.Function1;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.annotations.Nullable;
029    import org.jetbrains.kotlin.backend.common.bridges.Bridge;
030    import org.jetbrains.kotlin.backend.common.bridges.ImplKt;
031    import org.jetbrains.kotlin.codegen.annotation.AnnotatedWithOnlyTargetedAnnotations;
032    import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
033    import org.jetbrains.kotlin.codegen.context.*;
034    import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
035    import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
036    import org.jetbrains.kotlin.codegen.state.GenerationState;
037    import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
038    import org.jetbrains.kotlin.descriptors.*;
039    import org.jetbrains.kotlin.descriptors.annotations.Annotated;
040    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
041    import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
042    import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
043    import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature;
044    import org.jetbrains.kotlin.load.java.JvmAbi;
045    import org.jetbrains.kotlin.load.java.SpecialBuiltinMembers;
046    import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
047    import org.jetbrains.kotlin.name.FqName;
048    import org.jetbrains.kotlin.psi.*;
049    import org.jetbrains.kotlin.resolve.BindingContext;
050    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
051    import org.jetbrains.kotlin.resolve.DescriptorUtils;
052    import org.jetbrains.kotlin.resolve.calls.util.UnderscoreUtilKt;
053    import org.jetbrains.kotlin.resolve.constants.ArrayValue;
054    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
055    import org.jetbrains.kotlin.resolve.constants.KClassValue;
056    import org.jetbrains.kotlin.resolve.inline.InlineUtil;
057    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
058    import org.jetbrains.kotlin.resolve.jvm.RuntimeAssertionInfo;
059    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
060    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind;
061    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
062    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
063    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
064    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
065    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
066    import org.jetbrains.kotlin.types.KotlinType;
067    import org.jetbrains.kotlin.types.TypeUtils;
068    import org.jetbrains.org.objectweb.asm.*;
069    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
070    import org.jetbrains.org.objectweb.asm.commons.Method;
071    import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor;
072    
073    import java.io.PrintWriter;
074    import java.io.StringWriter;
075    import java.util.Collection;
076    import java.util.Iterator;
077    import java.util.List;
078    import java.util.Set;
079    
080    import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
081    import static org.jetbrains.kotlin.codegen.AsmUtil.*;
082    import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
083    import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
084    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
085    import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
086    import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnlyOrReifiable;
087    import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
088    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
089    import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
090    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
091    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
092    
093    public class FunctionCodegen {
094        public final GenerationState state;
095        private final KotlinTypeMapper typeMapper;
096        private final BindingContext bindingContext;
097        private final CodegenContext owner;
098        private final ClassBuilder v;
099        private final MemberCodegen<?> memberCodegen;
100    
101        private final Function1<DeclarationDescriptor, Boolean> IS_PURE_INTERFACE_CHECKER = new Function1<DeclarationDescriptor, Boolean>() {
102            @Override
103            public Boolean invoke(DeclarationDescriptor descriptor) {
104                return JvmCodegenUtil.isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, state);
105            }
106        };
107    
108        public FunctionCodegen(
109                @NotNull CodegenContext owner,
110                @NotNull ClassBuilder v,
111                @NotNull GenerationState state,
112                @NotNull MemberCodegen<?> memberCodegen
113        ) {
114            this.owner = owner;
115            this.v = v;
116            this.state = state;
117            this.typeMapper = state.getTypeMapper();
118            this.bindingContext = state.getBindingContext();
119            this.memberCodegen = memberCodegen;
120        }
121    
122        public void gen(@NotNull KtNamedFunction function) {
123            SimpleFunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, function);
124            if (bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, functionDescriptor) != null) {
125                functionDescriptor =
126                        (SimpleFunctionDescriptor) bindingContext.get(CodegenBinding.SUSPEND_FUNCTION_TO_JVM_VIEW, functionDescriptor);
127            }
128    
129            if (functionDescriptor == null) {
130                throw ExceptionLogger.logDescriptorNotFound("No descriptor for function " + function.getName(), function);
131            }
132    
133            if (owner.getContextKind() != OwnerKind.DEFAULT_IMPLS || function.hasBody()) {
134                FunctionGenerationStrategy strategy;
135                if (functionDescriptor.isSuspend()) {
136                    strategy = new SuspendFunctionGenerationStrategy(
137                            state,
138                            CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(functionDescriptor),
139                            function
140                    );
141                }
142                else {
143                    strategy = new FunctionGenerationStrategy.FunctionDefault(state, function);
144                }
145    
146                generateMethod(JvmDeclarationOriginKt.OtherOrigin(function, functionDescriptor), functionDescriptor, strategy);
147            }
148    
149            generateDefaultIfNeeded(owner.intoFunction(functionDescriptor, true), functionDescriptor, owner.getContextKind(),
150                                    DefaultParameterValueLoader.DEFAULT, function);
151    
152            generateOverloadsWithDefaultValues(function, functionDescriptor, functionDescriptor);
153        }
154    
155        public void generateOverloadsWithDefaultValues(
156                @Nullable KtNamedFunction function,
157                @NotNull FunctionDescriptor functionDescriptor,
158                @NotNull FunctionDescriptor delegateFunctionDescriptor
159        ) {
160            new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded(
161                    function, functionDescriptor, delegateFunctionDescriptor, owner.getContextKind(), v, memberCodegen
162            );
163        }
164    
165        public void generateMethod(
166                @NotNull JvmDeclarationOrigin origin,
167                @NotNull FunctionDescriptor descriptor,
168                @NotNull FunctionGenerationStrategy strategy
169        ) {
170            if (CoroutineCodegenUtilKt.isSuspendFunctionNotSuspensionView(descriptor)) {
171                generateMethod(origin, CoroutineCodegenUtilKt.getOrCreateJvmSuspendFunctionView(descriptor, bindingContext), strategy);
172                return;
173            }
174    
175            generateMethod(origin, descriptor, owner.intoFunction(descriptor), strategy);
176        }
177    
178        public void generateMethod(
179                @NotNull JvmDeclarationOrigin origin,
180                @NotNull FunctionDescriptor functionDescriptor,
181                @NotNull MethodContext methodContext,
182                @NotNull FunctionGenerationStrategy strategy
183        ) {
184            OwnerKind contextKind = methodContext.getContextKind();
185            if (isInterface(functionDescriptor.getContainingDeclaration()) &&
186                functionDescriptor.getVisibility() == Visibilities.PRIVATE &&
187                !processInterfaceMember(functionDescriptor, contextKind, state)) {
188                return;
189            }
190    
191            JvmMethodGenericSignature jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, contextKind);
192            Method asmMethod = jvmSignature.getAsmMethod();
193    
194            int flags = getMethodAsmFlags(functionDescriptor, contextKind, state);
195    
196            if (origin.getOriginKind() == JvmDeclarationOriginKind.SAM_DELEGATION) {
197                flags |= ACC_SYNTHETIC;
198            }
199    
200            if (functionDescriptor.isExternal() && owner instanceof MultifileClassFacadeContext) {
201                // Native methods are only defined in facades and do not need package part implementations
202                return;
203            }
204            MethodVisitor mv = v.newMethod(origin,
205                                           flags,
206                                           asmMethod.getName(),
207                                           asmMethod.getDescriptor(),
208                                           jvmSignature.getGenericsSignature(),
209                                           getThrownExceptions(functionDescriptor, typeMapper));
210    
211            if (CodegenContextUtil.isImplClassOwner(owner)) {
212                v.getSerializationBindings().put(
213                        METHOD_FOR_FUNCTION,
214                        CodegenUtilKt.<FunctionDescriptor>unwrapFrontendVersion(functionDescriptor),
215                        asmMethod
216                );
217            }
218    
219            generateMethodAnnotations(functionDescriptor, asmMethod, mv);
220    
221            JvmMethodSignature signature = typeMapper.mapSignatureSkipGeneric(functionDescriptor);
222            generateParameterAnnotations(functionDescriptor, mv, signature);
223            GenerateJava8ParameterNamesKt.generateParameterNames(functionDescriptor, mv, signature, state, (flags & ACC_SYNTHETIC) != 0);
224    
225            generateBridges(functionDescriptor);
226    
227            if (isJvm8InterfaceWithDefaultsMember(functionDescriptor, state) && contextKind != OwnerKind.DEFAULT_IMPLS && state.getGenerateDefaultImplsForJvm8()) {
228                generateDelegateForDefaultImpl(functionDescriptor, origin.getElement());
229            }
230    
231            boolean staticInCompanionObject = CodegenUtilKt.isJvmStaticInCompanionObject(functionDescriptor);
232            if (staticInCompanionObject) {
233                ImplementationBodyCodegen parentBodyCodegen = (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
234                parentBodyCodegen.addAdditionalTask(new JvmStaticGenerator(functionDescriptor, origin, state, parentBodyCodegen));
235            }
236    
237            if (!state.getClassBuilderMode().generateBodies || isAbstractMethod(functionDescriptor, contextKind, state)) {
238                generateLocalVariableTable(
239                        mv,
240                        jvmSignature,
241                        functionDescriptor,
242                        getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
243                        new Label(),
244                        new Label(),
245                        contextKind,
246                        typeMapper,
247                        0);
248    
249                mv.visitEnd();
250                return;
251            }
252    
253            if (!functionDescriptor.isExternal()) {
254                generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
255            }
256            else if (staticInCompanionObject) {
257                // native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
258                mv.visitCode();
259                FunctionDescriptor staticFunctionDescriptor = JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
260                Method accessorMethod =
261                        typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
262                Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
263                generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName());
264            }
265    
266            endVisit(mv, null, origin.getElement());
267        }
268    
269        private void generateDelegateForDefaultImpl(
270                @NotNull final FunctionDescriptor functionDescriptor,
271                @Nullable PsiElement element
272        ) {
273            Method defaultImplMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
274    
275            CodegenUtilKt.generateMethod(
276                    v, "Default Impl delegate in interface", Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC,
277                    new Method(defaultImplMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, defaultImplMethod.getDescriptor()),
278                    element, JvmDeclarationOrigin.NO_ORIGIN,
279                    state, new Function1<InstructionAdapter, Unit>() {
280                        @Override
281                        public Unit invoke(InstructionAdapter adapter) {
282                            Method interfaceMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.IMPLEMENTATION);
283                            Type type = typeMapper.mapOwner(functionDescriptor);
284                            generateDelegateToMethodBody(
285                                    -1, adapter,
286                                    interfaceMethod,
287                                    type.getInternalName(),
288                                    Opcodes.INVOKESPECIAL,
289                                    true
290                            );
291                            return null;
292                        }
293                    }
294            );
295        }
296    
297        private void generateMethodAnnotations(
298                @NotNull FunctionDescriptor functionDescriptor,
299                Method asmMethod,
300                MethodVisitor mv
301        ) {
302            generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper);
303        }
304    
305        public static void generateMethodAnnotations(
306                @NotNull FunctionDescriptor functionDescriptor,
307                Method asmMethod,
308                MethodVisitor mv,
309                @NotNull InnerClassConsumer consumer,
310                @NotNull KotlinTypeMapper typeMapper
311        ) {
312            AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, consumer, typeMapper);
313    
314            if (functionDescriptor instanceof PropertyAccessorDescriptor) {
315                AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER;
316                annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType(), target);
317            }
318            else {
319                annotationCodegen.genAnnotations(functionDescriptor, asmMethod.getReturnType());
320            }
321        }
322    
323        private void generateParameterAnnotations(
324                @NotNull FunctionDescriptor functionDescriptor,
325                @NotNull MethodVisitor mv,
326                @NotNull JvmMethodSignature jvmSignature
327        ) {
328            generateParameterAnnotations(functionDescriptor, mv, jvmSignature, memberCodegen, state);
329        }
330    
331        public static void generateParameterAnnotations(
332                @NotNull FunctionDescriptor functionDescriptor,
333                @NotNull MethodVisitor mv,
334                @NotNull JvmMethodSignature jvmSignature,
335                @NotNull InnerClassConsumer innerClassConsumer,
336                @NotNull GenerationState state
337        ) {
338            generateParameterAnnotations(
339                    functionDescriptor, mv, jvmSignature, functionDescriptor.getValueParameters(), innerClassConsumer, state
340            );
341        }
342    
343        public static void generateParameterAnnotations(
344                @NotNull FunctionDescriptor functionDescriptor,
345                @NotNull MethodVisitor mv,
346                @NotNull JvmMethodSignature jvmSignature,
347                @NotNull List<ValueParameterDescriptor> valueParameters,
348                @NotNull InnerClassConsumer innerClassConsumer,
349                @NotNull GenerationState state
350        ) {
351            KotlinTypeMapper typeMapper = state.getTypeMapper();
352            Iterator<ValueParameterDescriptor> iterator = valueParameters.iterator();
353            List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();
354    
355            for (int i = 0; i < kotlinParameterTypes.size(); i++) {
356                JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
357                JvmMethodParameterKind kind = parameterSignature.getKind();
358                if (kind.isSkippedInGenericSignature()) {
359                    markEnumOrInnerConstructorParameterAsSynthetic(mv, i, state.getClassBuilderMode());
360                    continue;
361                }
362    
363                if (kind == JvmMethodParameterKind.VALUE) {
364                    ValueParameterDescriptor parameter = iterator.next();
365                    AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper);
366    
367                    if (functionDescriptor instanceof PropertySetterDescriptor) {
368                        PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
369                        Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
370                        annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
371                    }
372    
373                    if (functionDescriptor instanceof ConstructorDescriptor) {
374                        annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType(), CONSTRUCTOR_PARAMETER);
375                    }
376                    else {
377                        annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType());
378                    }
379                }
380                else if (kind == JvmMethodParameterKind.RECEIVER) {
381                    ReceiverParameterDescriptor receiver = JvmCodegenUtil.getDirectMember(functionDescriptor).getExtensionReceiverParameter();
382    
383                    if (receiver != null) {
384                        AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper);
385                        Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
386                        annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
387    
388                        annotationCodegen.genAnnotations(receiver, parameterSignature.getAsmType());
389                    }
390                }
391            }
392        }
393    
394        private static void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i, ClassBuilderMode mode) {
395            // IDEA's ClsPsi builder fails to annotate synthetic parameters
396            if (mode == ClassBuilderMode.LIGHT_CLASSES) return;
397    
398            // This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac:
399            // see MethodWriter.visitParameterAnnotation()
400    
401            AnnotationVisitor av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", true);
402            if (av != null) {
403                av.visitEnd();
404            }
405        }
406    
407        @Nullable
408        private static Type getThisTypeForFunction(
409                @NotNull FunctionDescriptor functionDescriptor,
410                @NotNull MethodContext context,
411                @NotNull KotlinTypeMapper typeMapper
412        ) {
413            ReceiverParameterDescriptor dispatchReceiver = functionDescriptor.getDispatchReceiverParameter();
414            if (functionDescriptor instanceof ConstructorDescriptor) {
415                return typeMapper.mapType(functionDescriptor);
416            }
417            else if (dispatchReceiver != null) {
418                return typeMapper.mapType(dispatchReceiver.getType());
419            }
420            else if (isFunctionLiteral(functionDescriptor) ||
421                     isLocalFunction(functionDescriptor) ||
422                     isFunctionExpression(functionDescriptor)) {
423                return typeMapper.mapType(context.getThisDescriptor());
424            }
425            else {
426                return null;
427            }
428        }
429    
430        public static void generateMethodBody(
431                @NotNull MethodVisitor mv,
432                @NotNull FunctionDescriptor functionDescriptor,
433                @NotNull MethodContext context,
434                @NotNull JvmMethodSignature signature,
435                @NotNull FunctionGenerationStrategy strategy,
436                @NotNull MemberCodegen<?> parentCodegen
437        ) {
438            mv.visitCode();
439    
440            Label methodBegin = new Label();
441            mv.visitLabel(methodBegin);
442    
443            KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
444            if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, getSignatureMapper(typeMapper))) {
445                generateTypeCheckBarrierIfNeeded(
446                        new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterTypes = */null);
447            }
448    
449            Label methodEnd;
450    
451            int functionFakeIndex = -1;
452            int lambdaFakeIndex = -1;
453    
454            if (context.getParentContext() instanceof MultifileClassFacadeContext) {
455                generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
456                methodEnd = new Label();
457            }
458            else if (OwnerKind.DEFAULT_IMPLS == context.getContextKind() && isJvm8InterfaceWithDefaultsMember(functionDescriptor, parentCodegen.state)) {
459                int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
460                assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
461                Type type = typeMapper.mapOwner(functionDescriptor);
462                Method asmMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
463                generateDelegateToStaticMethodBody(
464                        true, mv,
465                        new Method(asmMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, asmMethod.getDescriptor()),
466                        type.getInternalName()
467                );
468                methodEnd = new Label();
469            }
470            else {
471                FrameMap frameMap = createFrameMap(parentCodegen.state, functionDescriptor, signature, isStaticMethod(context.getContextKind(),
472                                                                                                                      functionDescriptor));
473                if (context.isInlineMethodContext()) {
474                    functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
475                }
476    
477                if (context instanceof InlineLambdaContext) {
478                    lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
479                }
480    
481                Label methodEntry = new Label();
482                mv.visitLabel(methodEntry);
483                context.setMethodStartLabel(methodEntry);
484    
485                if (!KotlinTypeMapper.isAccessor(functionDescriptor)) {
486                    genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
487                }
488    
489                parentCodegen.beforeMethodBody(mv);
490    
491                methodEnd = new Label();
492                context.setMethodEndLabel(methodEnd);
493                strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
494            }
495    
496            mv.visitLabel(methodEnd);
497    
498            Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
499            generateLocalVariableTable(
500                    mv, signature, functionDescriptor, thisType, methodBegin, methodEnd, context.getContextKind(), typeMapper,
501                    (functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0)
502            );
503    
504            //TODO: it's best to move all below logic to 'generateLocalVariableTable' method
505            if (context.isInlineMethodContext() && functionFakeIndex != -1) {
506                mv.visitLocalVariable(
507                        JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + typeMapper.mapAsmMethod(functionDescriptor).getName(),
508                        Type.INT_TYPE.getDescriptor(), null,
509                        methodBegin, methodEnd,
510                        functionFakeIndex);
511            }
512    
513            if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
514                String name = thisType.getClassName();
515                int indexOfLambdaOrdinal = name.lastIndexOf("$");
516                if (indexOfLambdaOrdinal > 0) {
517                    int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
518    
519                    KtPureElement functionArgument = parentCodegen.element;
520                    String functionName = "unknown";
521                    if (functionArgument instanceof KtFunction) {
522                        ValueParameterDescriptor inlineArgumentDescriptor =
523                                InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
524                        if (inlineArgumentDescriptor != null) {
525                            functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
526                        }
527                    }
528                    mv.visitLocalVariable(
529                            JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal +  "$" + functionName,
530                            Type.INT_TYPE.getDescriptor(), null,
531                            methodBegin, methodEnd,
532                            lambdaFakeIndex);
533                }
534            }
535        }
536    
537        private static void generateLocalVariableTable(
538                @NotNull MethodVisitor mv,
539                @NotNull JvmMethodSignature jvmMethodSignature,
540                @NotNull FunctionDescriptor functionDescriptor,
541                @Nullable Type thisType,
542                @NotNull Label methodBegin,
543                @NotNull Label methodEnd,
544                @NotNull OwnerKind ownerKind,
545                @NotNull KotlinTypeMapper typeMapper,
546                int shiftForDestructuringVariables
547        ) {
548            generateLocalVariablesForParameters(mv, jvmMethodSignature, thisType, methodBegin, methodEnd,
549                                                functionDescriptor.getValueParameters(),
550                                                AsmUtil.isStaticMethod(ownerKind, functionDescriptor), typeMapper, shiftForDestructuringVariables
551            );
552        }
553    
554        public static void generateLocalVariablesForParameters(
555                @NotNull MethodVisitor mv,
556                @NotNull JvmMethodSignature jvmMethodSignature,
557                @Nullable Type thisType,
558                @NotNull Label methodBegin,
559                @NotNull Label methodEnd,
560                Collection<ValueParameterDescriptor> valueParameters,
561                boolean isStatic,
562                KotlinTypeMapper typeMapper
563        ) {
564            generateLocalVariablesForParameters(
565                    mv, jvmMethodSignature, thisType, methodBegin, methodEnd, valueParameters, isStatic, typeMapper, 0
566            );
567        }
568    
569        private static void generateLocalVariablesForParameters(
570                @NotNull MethodVisitor mv,
571                @NotNull JvmMethodSignature jvmMethodSignature,
572                @Nullable Type thisType,
573                @NotNull Label methodBegin,
574                @NotNull Label methodEnd,
575                Collection<ValueParameterDescriptor> valueParameters,
576                boolean isStatic,
577                KotlinTypeMapper typeMapper,
578                int shiftForDestructuringVariables
579        ) {
580            Iterator<ValueParameterDescriptor> valueParameterIterator = valueParameters.iterator();
581            List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
582            int shift = 0;
583    
584            if (!isStatic) {
585                //add this
586                if (thisType != null) {
587                    mv.visitLocalVariable("this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
588                }
589                else {
590                    //TODO: provide thisType for callable reference
591                }
592                shift++;
593            }
594    
595            for (int i = 0; i < params.size(); i++) {
596                JvmMethodParameterSignature param = params.get(i);
597                JvmMethodParameterKind kind = param.getKind();
598                String parameterName;
599    
600                if (kind == JvmMethodParameterKind.VALUE) {
601                    ValueParameterDescriptor parameter = valueParameterIterator.next();
602                    List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
603    
604                    parameterName =
605                            destructuringVariables == null
606                            ? computeParameterName(i, parameter)
607                            : "$" + joinParameterNames(destructuringVariables);
608                }
609                else {
610                    String lowercaseKind = kind.name().toLowerCase();
611                    parameterName = needIndexForVar(kind)
612                                    ? "$" + lowercaseKind + "$" + i
613                                    : "$" + lowercaseKind;
614                }
615    
616                Type type = param.getAsmType();
617                mv.visitLocalVariable(parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift);
618                shift += type.getSize();
619            }
620    
621            shift += shiftForDestructuringVariables;
622            for (ValueParameterDescriptor parameter : valueParameters) {
623                List<VariableDescriptor> destructuringVariables = ValueParameterDescriptorImpl.getDestructuringVariablesOrNull(parameter);
624                if (destructuringVariables == null) continue;
625    
626                for (VariableDescriptor entry : CodegenUtilKt.filterOutDescriptorsWithSpecialNames(destructuringVariables)) {
627                    Type type = typeMapper.mapType(entry.getType());
628                    mv.visitLocalVariable(entry.getName().asString(), type.getDescriptor(), null, methodBegin, methodEnd, shift);
629                    shift += type.getSize();
630                }
631            }
632        }
633    
634        private static String computeParameterName(int i, ValueParameterDescriptor parameter) {
635            PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
636            if (element instanceof KtParameter && UnderscoreUtilKt.isSingleUnderscore((KtParameter) element)) {
637                return "$noName_" + i;
638            }
639    
640            return parameter.getName().asString();
641        }
642    
643        private static String joinParameterNames(@NotNull List<VariableDescriptor> variables) {
644            return org.jetbrains.kotlin.utils.StringsKt.join(CollectionsKt.map(variables, new Function1<VariableDescriptor, String>() {
645                @Override
646                public String invoke(VariableDescriptor descriptor) {
647                    // stub for anonymous destructuring declaration entry
648                    if (descriptor.getName().isSpecial()) return "$_$";
649                    return descriptor.getName().asString();
650                }
651            }), "_");
652        }
653    
654        private static void generateFacadeDelegateMethodBody(
655                @NotNull MethodVisitor mv,
656                @NotNull Method asmMethod,
657                @NotNull MultifileClassFacadeContext context
658        ) {
659            generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName());
660        }
661    
662        private static void generateDelegateToMethodBody(
663                // -1 means to add additional this parameter on stack
664                int firstParamIndex,
665                @NotNull MethodVisitor mv,
666                @NotNull Method asmMethod,
667                @NotNull String classToDelegateTo,
668                int opcode,
669                boolean isInterface
670        ) {
671            InstructionAdapter iv = new InstructionAdapter(mv);
672            Type[] argTypes = asmMethod.getArgumentTypes();
673    
674            // The first line of some package file is written to the line number attribute of a static delegate to allow to 'step into' it
675            // This is similar to what javac does with bridge methods
676            Label label = new Label();
677            iv.visitLabel(label);
678            iv.visitLineNumber(1, label);
679    
680            int paramIndex = firstParamIndex;
681            if (paramIndex == -1) {
682                iv.load(0, AsmTypes.OBJECT_TYPE);
683                paramIndex = 1;
684            }
685    
686            for (Type argType : argTypes) {
687                iv.load(paramIndex, argType);
688                paramIndex += argType.getSize();
689            }
690            iv.visitMethodInsn(opcode, classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), isInterface);
691            iv.areturn(asmMethod.getReturnType());
692        }
693    
694        private static void generateDelegateToStaticMethodBody(
695                boolean isStatic,
696                @NotNull MethodVisitor mv,
697                @NotNull Method asmMethod,
698                @NotNull String classToDelegateTo
699        ) {
700            generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, false);
701        }
702    
703        private static boolean needIndexForVar(JvmMethodParameterKind kind) {
704            return kind == JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE ||
705                   kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL ||
706                   kind == JvmMethodParameterKind.SUPER_CALL_PARAM;
707        }
708    
709        public static void endVisit(MethodVisitor mv, @Nullable String description) {
710            endVisit(mv, description, (PsiElement)null);
711        }
712    
713        public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable KtPureElement method) {
714            endVisit(mv, description, (PsiElement)(method == null ? null : method.getPsiOrParent()));
715        }
716    
717        public static void endVisit(MethodVisitor mv, @Nullable String description, @NotNull KtElement method) {
718            endVisit(mv, description, (PsiElement)method);
719        }
720    
721        public static void endVisit(MethodVisitor mv, @Nullable String description, @Nullable PsiElement method) {
722            try {
723                mv.visitMaxs(-1, -1);
724                mv.visitEnd();
725            }
726            catch (ProcessCanceledException e) {
727                throw e;
728            }
729            catch (Throwable t) {
730                String bytecode = renderByteCodeIfAvailable(mv);
731                throw new CompilationException(
732                        "wrong code generated\n" +
733                        (description != null ? " for " + description : "") +
734                        t.getClass().getName() +
735                        " " +
736                        t.getMessage() +
737                        (bytecode != null ? "\nbytecode:\n" + bytecode : ""),
738                        t, method);
739            }
740        }
741    
742        private static String renderByteCodeIfAvailable(MethodVisitor mv) {
743            String bytecode = null;
744    
745            if (mv instanceof TransformationMethodVisitor) {
746                mv = ((TransformationMethodVisitor) mv).getTraceMethodVisitorIfPossible();
747            }
748    
749            if (mv instanceof TraceMethodVisitor) {
750                TraceMethodVisitor traceMethodVisitor = (TraceMethodVisitor) mv;
751                StringWriter sw = new StringWriter();
752                PrintWriter pw = new PrintWriter(sw);
753                traceMethodVisitor.p.print(pw);
754                pw.close();
755                bytecode = sw.toString();
756            }
757            return bytecode;
758        }
759    
760        public void generateBridges(@NotNull FunctionDescriptor descriptor) {
761            if (descriptor instanceof ConstructorDescriptor) return;
762            if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
763            if (isAnnotationOrJvmInterfaceWithoutDefaults(descriptor.getContainingDeclaration(), state)) return;
764    
765            // equals(Any?), hashCode(), toString() never need bridges
766            if (isMethodOfAny(descriptor)) return;
767    
768            boolean isSpecial = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;
769    
770            Set<Bridge<Method>> bridgesToGenerate;
771            if (!isSpecial) {
772                bridgesToGenerate = ImplKt.generateBridgesForFunctionDescriptor(
773                        descriptor,
774                        getSignatureMapper(typeMapper),
775                        IS_PURE_INTERFACE_CHECKER
776                );
777                if (!bridgesToGenerate.isEmpty()) {
778                    PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
779                    boolean isSpecialBridge =
780                            BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor) != null;
781    
782                    for (Bridge<Method> bridge : bridgesToGenerate) {
783                        generateBridge(origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false);
784                    }
785                }
786            }
787            else {
788                Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
789                        descriptor,
790                        getSignatureMapper(typeMapper),
791                        IS_PURE_INTERFACE_CHECKER
792                );
793    
794                if (!specials.isEmpty()) {
795                    PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
796                    for (BridgeForBuiltinSpecial<Method> bridge : specials) {
797                        generateBridge(
798                                origin, descriptor, bridge.getFrom(), bridge.getTo(),
799                                bridge.isSpecial(), bridge.isDelegateToSuper());
800                    }
801                }
802    
803                if (!descriptor.getKind().isReal() && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION, state)) {
804                    CallableDescriptor overridden = SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
805                    assert overridden != null;
806    
807                    if (!isThereOverriddenInKotlinClass(descriptor)) {
808                        Method method = typeMapper.mapAsmMethod(descriptor);
809                        int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
810                        v.newMethod(JvmDeclarationOriginKt.OtherOrigin(overridden), flags, method.getName(), method.getDescriptor(), null, null);
811                    }
812                }
813            }
814        }
815    
816        public static boolean isThereOverriddenInKotlinClass(@NotNull CallableMemberDescriptor descriptor) {
817            return CollectionsKt.any(getAllOverriddenDescriptors(descriptor), new Function1<CallableMemberDescriptor, Boolean>() {
818                @Override
819                public Boolean invoke(CallableMemberDescriptor descriptor) {
820                    return !(descriptor.getContainingDeclaration() instanceof JavaClassDescriptor) &&
821                                isClass(descriptor.getContainingDeclaration());
822                }
823            });
824        }
825    
826        @NotNull
827        private static Function1<FunctionDescriptor, Method> getSignatureMapper(final @NotNull KotlinTypeMapper typeMapper) {
828            return new Function1<FunctionDescriptor, Method>() {
829                @Override
830                public Method invoke(FunctionDescriptor descriptor) {
831                    return typeMapper.mapAsmMethod(descriptor);
832                }
833            };
834        }
835    
836        public static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
837            String name = descriptor.getName().asString();
838            List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
839            if (parameters.isEmpty()) {
840                return name.equals("hashCode") || name.equals("toString");
841            }
842            else if (parameters.size() == 1 && name.equals("equals")) {
843                return isNullableAny(parameters.get(0).getType());
844            }
845            return false;
846        }
847    
848        @NotNull
849        public static String[] getThrownExceptions(@NotNull FunctionDescriptor function, @NotNull final KotlinTypeMapper mapper) {
850            AnnotationDescriptor annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.throws"));
851            if (annotation == null) {
852                annotation = function.getAnnotations().findAnnotation(new FqName("kotlin.jvm.Throws"));
853            }
854    
855            if (annotation == null) return ArrayUtil.EMPTY_STRING_ARRAY;
856    
857            Collection<ConstantValue<?>> values = annotation.getAllValueArguments().values();
858            if (values.isEmpty()) return ArrayUtil.EMPTY_STRING_ARRAY;
859    
860            Object value = values.iterator().next();
861            if (!(value instanceof ArrayValue)) return ArrayUtil.EMPTY_STRING_ARRAY;
862            ArrayValue arrayValue = (ArrayValue) value;
863    
864            List<String> strings = ContainerUtil.mapNotNull(
865                    arrayValue.getValue(),
866                    new Function<ConstantValue<?>, String>() {
867                        @Override
868                        public String fun(ConstantValue<?> constant) {
869                            if (constant instanceof KClassValue) {
870                                KClassValue classValue = (KClassValue) constant;
871                                ClassDescriptor classDescriptor = DescriptorUtils.getClassDescriptorForType(classValue.getValue());
872                                return mapper.mapClass(classDescriptor).getInternalName();
873                            }
874                            return null;
875                        }
876                    }
877            );
878            return ArrayUtil.toStringArray(strings);
879        }
880    
881        void generateDefaultIfNeeded(
882                @NotNull MethodContext owner,
883                @NotNull FunctionDescriptor functionDescriptor,
884                @NotNull OwnerKind kind,
885                @NotNull DefaultParameterValueLoader loadStrategy,
886                @Nullable KtNamedFunction function
887        ) {
888            DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
889    
890            if (isInterface(contextClass) && !processInterface(contextClass, kind, state)) {
891                return;
892            }
893    
894            if (!isDefaultNeeded(functionDescriptor)) {
895                return;
896            }
897    
898            // $default methods are never private to be accessible from other class files (e.g. inner) without the need of synthetic accessors
899            // $default methods are never protected to be accessible from subclass nested classes
900            int visibilityFlag = Visibilities.isPrivate(functionDescriptor.getVisibility()) ||
901                                 isInlineOnlyOrReifiable(functionDescriptor) ?
902                                 AsmUtil.NO_FLAG_PACKAGE_PRIVATE : Opcodes.ACC_PUBLIC;
903            int flags =  visibilityFlag | getDeprecatedAccessFlag(functionDescriptor) | ACC_SYNTHETIC;
904            if (!(functionDescriptor instanceof ConstructorDescriptor)) {
905                flags |= ACC_STATIC | ACC_BRIDGE;
906            }
907    
908            Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);
909    
910            MethodVisitor mv = v.newMethod(
911                    JvmDeclarationOriginKt.Synthetic(function, functionDescriptor),
912                    flags,
913                    defaultMethod.getName(),
914                    defaultMethod.getDescriptor(), null,
915                    getThrownExceptions(functionDescriptor, typeMapper)
916            );
917    
918            // Only method annotations are copied to the $default method. Parameter annotations are not copied until there are valid use cases;
919            // enum constructors have two additional synthetic parameters which somewhat complicate this task
920            AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper).genAnnotations(functionDescriptor, defaultMethod.getReturnType());
921    
922            if (state.getClassBuilderMode().generateBodies) {
923                if (this.owner instanceof MultifileClassFacadeContext) {
924                    mv.visitCode();
925                    generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
926                    endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
927                }
928                else {
929                    mv.visitCode();
930                    generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
931                    endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
932                }
933            }
934        }
935    
936        public static void generateDefaultImplBody(
937                @NotNull MethodContext methodContext,
938                @NotNull FunctionDescriptor functionDescriptor,
939                @NotNull MethodVisitor mv,
940                @NotNull DefaultParameterValueLoader loadStrategy,
941                @Nullable KtNamedFunction function,
942                @NotNull MemberCodegen<?> parentCodegen,
943                @NotNull Method defaultMethod
944        ) {
945            GenerationState state = parentCodegen.state;
946            JvmMethodSignature signature = state.getTypeMapper().mapSignatureWithGeneric(functionDescriptor, methodContext.getContextKind());
947    
948            boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
949            FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic);
950    
951            ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);
952    
953            CallGenerator generator = codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);
954    
955            InstructionAdapter iv = new InstructionAdapter(mv);
956            genDefaultSuperCallCheckIfNeeded(iv, functionDescriptor, defaultMethod);
957    
958            List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
959            int capturedArgumentsCount = 0;
960            while (capturedArgumentsCount < mappedParameters.size() &&
961                   mappedParameters.get(capturedArgumentsCount).getKind() != JvmMethodParameterKind.VALUE) {
962                capturedArgumentsCount++;
963            }
964    
965            int maskIndex = 0;
966            List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
967            for (int index = 0; index < valueParameters.size(); index++) {
968                if (index % Integer.SIZE == 0) {
969                    maskIndex = frameMap.enterTemp(Type.INT_TYPE);
970                }
971                ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
972                Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
973    
974                int parameterIndex = frameMap.getIndex(parameterDescriptor);
975                if (parameterDescriptor.declaresDefaultValue()) {
976                    iv.load(maskIndex, Type.INT_TYPE);
977                    iv.iconst(1 << (index % Integer.SIZE));
978                    iv.and(Type.INT_TYPE);
979                    Label loadArg = new Label();
980                    iv.ifeq(loadArg);
981    
982                    StackValue.local(parameterIndex, type).store(loadStrategy.genValue(parameterDescriptor, codegen), iv);
983    
984                    iv.mark(loadArg);
985                }
986            }
987    
988            // load arguments after defaults generation to avoid redundant stack normalization operations
989            loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
990    
991            for (int index = 0; index < valueParameters.size(); index++) {
992                ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
993                Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
994                int parameterIndex = frameMap.getIndex(parameterDescriptor);
995                generator.putValueIfNeeded(type, StackValue.local(parameterIndex, type));
996            }
997    
998            CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);
999    
1000            generator.genCall(method, null, false, codegen);
1001    
1002            iv.areturn(signature.getReturnType());
1003        }
1004    
1005        private static void genDefaultSuperCallCheckIfNeeded(
1006                @NotNull InstructionAdapter iv, @NotNull FunctionDescriptor descriptor, @NotNull Method defaultMethod
1007        ) {
1008            if (descriptor instanceof ConstructorDescriptor) return;
1009    
1010            DeclarationDescriptor container = descriptor.getContainingDeclaration();
1011            if (!(container instanceof ClassDescriptor)) return;
1012            if (((ClassDescriptor) container).getModality() == Modality.FINAL) return;
1013    
1014            Label end = new Label();
1015            int handleIndex = (Type.getArgumentsAndReturnSizes(defaultMethod.getDescriptor()) >> 2) - 2; /*-1 for this, and -1 for handle*/
1016            iv.load(handleIndex, OBJECT_TYPE);
1017            iv.ifnull(end);
1018            AsmUtil.genThrow(
1019                    iv, "java/lang/UnsupportedOperationException",
1020                    "Super calls with default arguments not supported in this target, function: " + descriptor.getName().asString()
1021            );
1022            iv.visitLabel(end);
1023        }
1024    
1025        @NotNull
1026        public static FrameMap createFrameMap(
1027                @NotNull GenerationState state,
1028                @NotNull FunctionDescriptor function,
1029                @NotNull JvmMethodSignature signature,
1030                boolean isStatic
1031        ) {
1032            FrameMap frameMap = new FrameMap();
1033            if (!isStatic) {
1034                frameMap.enterTemp(OBJECT_TYPE);
1035            }
1036    
1037            for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
1038                if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) {
1039                    ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
1040                    if (receiverParameter != null) {
1041                        frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter));
1042                    }
1043                    else {
1044                        frameMap.enterTemp(parameter.getAsmType());
1045                    }
1046                }
1047                else if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
1048                    frameMap.enterTemp(parameter.getAsmType());
1049                }
1050            }
1051    
1052            for (ValueParameterDescriptor parameter : function.getValueParameters()) {
1053                frameMap.enter(parameter, state.getTypeMapper().mapType(parameter));
1054            }
1055    
1056            return frameMap;
1057        }
1058    
1059        private static void loadExplicitArgumentsOnStack(
1060                @NotNull Type ownerType,
1061                boolean isStatic,
1062                @NotNull JvmMethodSignature signature,
1063                @NotNull CallGenerator callGenerator
1064        ) {
1065            int var = 0;
1066            if (!isStatic) {
1067                callGenerator.putValueIfNeeded(ownerType, StackValue.local(var, ownerType));
1068                var += ownerType.getSize();
1069            }
1070    
1071            for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
1072                if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
1073                    Type type = parameterSignature.getAsmType();
1074                    callGenerator.putValueIfNeeded(type, StackValue.local(var, type));
1075                    var += type.getSize();
1076                }
1077            }
1078        }
1079    
1080        private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) {
1081            boolean needed = false;
1082            if (functionDescriptor != null) {
1083                for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
1084                    if (parameterDescriptor.declaresDefaultValue()) {
1085                        needed = true;
1086                        break;
1087                    }
1088                }
1089            }
1090            return needed;
1091        }
1092    
1093        private void generateBridge(
1094                @Nullable PsiElement origin,
1095                @NotNull FunctionDescriptor descriptor,
1096                @NotNull Method bridge,
1097                @NotNull Method delegateTo,
1098                boolean isSpecialBridge,
1099                boolean isStubDeclarationWithDelegationToSuper
1100        ) {
1101            boolean isSpecialOrDelegationToSuper = isSpecialBridge || isStubDeclarationWithDelegationToSuper;
1102            int flags = ACC_PUBLIC | ACC_BRIDGE | (!isSpecialOrDelegationToSuper ? ACC_SYNTHETIC : 0) | (isSpecialBridge ? ACC_FINAL : 0); // TODO.
1103    
1104            MethodVisitor mv =
1105                    v.newMethod(JvmDeclarationOriginKt.Bridge(descriptor, origin), flags, bridge.getName(), bridge.getDescriptor(), null, null);
1106            if (!state.getClassBuilderMode().generateBodies) return;
1107    
1108            mv.visitCode();
1109    
1110            Type[] argTypes = bridge.getArgumentTypes();
1111            Type[] originalArgTypes = delegateTo.getArgumentTypes();
1112    
1113            InstructionAdapter iv = new InstructionAdapter(mv);
1114            MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);
1115    
1116            if (delegateTo.getArgumentTypes().length > 0 && isSpecialBridge) {
1117                generateTypeCheckBarrierIfNeeded(iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes());
1118            }
1119    
1120            iv.load(0, OBJECT_TYPE);
1121            for (int i = 0, reg = 1; i < argTypes.length; i++) {
1122                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
1123                //noinspection AssignmentToForLoopParameter
1124                reg += argTypes[i].getSize();
1125            }
1126    
1127            if (isStubDeclarationWithDelegationToSuper) {
1128                ClassDescriptor parentClass = getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
1129                assert parentClass != null;
1130                String parentInternalName = typeMapper.mapClass(parentClass).getInternalName();
1131                iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
1132            }
1133            else {
1134                if (isJvm8InterfaceWithDefaultsMember(descriptor, state)) {
1135                    iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
1136                }
1137                else {
1138                    iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor(), false);
1139                }
1140            }
1141    
1142            StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
1143            iv.areturn(bridge.getReturnType());
1144    
1145            endVisit(mv, "bridge method", origin);
1146        }
1147    
1148        private static void generateTypeCheckBarrierIfNeeded(
1149                @NotNull InstructionAdapter iv,
1150                @NotNull FunctionDescriptor descriptor,
1151                @NotNull Type returnType,
1152                @Nullable Type[] delegateParameterTypes
1153        ) {
1154            BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription typeSafeBarrierDescription =
1155                    BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor);
1156            if (typeSafeBarrierDescription == null) return;
1157    
1158            FunctionDescriptor overriddenBuiltin =
1159                    BuiltinMethodsWithSpecialGenericSignature.getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor);
1160    
1161            assert overriddenBuiltin != null : "Overridden built-in method should not be null for " + descriptor;
1162    
1163            Label defaultBranch = new Label();
1164    
1165            for (int i = 0; i < descriptor.getValueParameters().size(); i++) {
1166                if (!typeSafeBarrierDescription.checkParameter(i)) continue;
1167                boolean isCheckForAny = delegateParameterTypes == null || OBJECT_TYPE.equals(delegateParameterTypes[i]);
1168    
1169                KotlinType kotlinType = descriptor.getValueParameters().get(i).getType();
1170    
1171                if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) continue;
1172    
1173                iv.load(1 + i, OBJECT_TYPE);
1174    
1175                if (isCheckForAny) {
1176                    assert !TypeUtils.isNullableType(kotlinType) : "Only bridges for not-nullable types are necessary";
1177                    iv.ifnull(defaultBranch);
1178                }
1179                else {
1180                    CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterTypes[i]));
1181                    iv.ifeq(defaultBranch);
1182                }
1183            }
1184    
1185            Label afterDefaultBranch = new Label();
1186    
1187            iv.goTo(afterDefaultBranch);
1188    
1189            iv.visitLabel(defaultBranch);
1190    
1191            if (typeSafeBarrierDescription.equals(BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)) {
1192                iv.load(2, returnType);
1193            }
1194            else {
1195                StackValue.constant(typeSafeBarrierDescription.getDefaultValue(), returnType).put(returnType, iv);
1196            }
1197            iv.areturn(returnType);
1198    
1199            iv.visitLabel(afterDefaultBranch);
1200        }
1201    
1202        public void genSamDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
1203            FunctionDescriptor delegatedTo = overriddenDescriptor.getOriginal();
1204            JvmDeclarationOrigin declarationOrigin =
1205                    JvmDeclarationOriginKt.SamDelegation(functionDescriptor);
1206            genDelegate(
1207                    functionDescriptor, delegatedTo,
1208                    declarationOrigin,
1209                    (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(),
1210                    field);
1211        }
1212    
1213        public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
1214            genDelegate(functionDescriptor, overriddenDescriptor.getOriginal(),
1215                        (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(), field);
1216        }
1217    
1218        public void genDelegate(
1219                @NotNull FunctionDescriptor delegateFunction,
1220                FunctionDescriptor delegatedTo,
1221                ClassDescriptor toClass,
1222                StackValue field
1223        ) {
1224            JvmDeclarationOrigin declarationOrigin =
1225                    JvmDeclarationOriginKt.Delegation(DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction);
1226            genDelegate(delegateFunction, delegatedTo, declarationOrigin, toClass, field);
1227        }
1228    
1229        private void genDelegate(
1230                @NotNull final FunctionDescriptor delegateFunction,
1231                final FunctionDescriptor delegatedTo,
1232                @NotNull JvmDeclarationOrigin declarationOrigin,
1233                final ClassDescriptor toClass,
1234                final StackValue field
1235        ) {
1236            generateMethod(
1237                    declarationOrigin, delegateFunction,
1238                    new FunctionGenerationStrategy() {
1239                        @Override
1240                        public void generateBody(
1241                                @NotNull MethodVisitor mv,
1242                                @NotNull FrameMap frameMap,
1243                                @NotNull JvmMethodSignature signature,
1244                                @NotNull MethodContext context,
1245                                @NotNull MemberCodegen<?> parentCodegen
1246                        ) {
1247                            Method delegateToMethod = typeMapper.mapToCallableMethod(delegatedTo, /* superCall = */ false).getAsmMethod();
1248                            Method delegateMethod = typeMapper.mapAsmMethod(delegateFunction);
1249    
1250                            Type[] argTypes = delegateMethod.getArgumentTypes();
1251                            Type[] originalArgTypes = delegateToMethod.getArgumentTypes();
1252    
1253                            InstructionAdapter iv = new InstructionAdapter(mv);
1254                            iv.load(0, OBJECT_TYPE);
1255                            field.put(field.type, iv);
1256                            for (int i = 0, reg = 1; i < argTypes.length; i++) {
1257                                StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
1258                                //noinspection AssignmentToForLoopParameter
1259                                reg += argTypes[i].getSize();
1260                            }
1261    
1262                            String internalName = typeMapper.mapType(toClass).getInternalName();
1263                            if (toClass.getKind() == ClassKind.INTERFACE) {
1264                                iv.invokeinterface(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor());
1265                            }
1266                            else {
1267                                iv.invokevirtual(internalName, delegateToMethod.getName(), delegateToMethod.getDescriptor(), false);
1268                            }
1269    
1270                            StackValue stackValue = AsmUtil.genNotNullAssertions(
1271                                    state,
1272                                    StackValue.onStack(delegateToMethod.getReturnType()),
1273                                    RuntimeAssertionInfo.create(
1274                                            delegateFunction.getReturnType(),
1275                                            delegatedTo.getReturnType(),
1276                                            new RuntimeAssertionInfo.DataFlowExtras.OnlyMessage(delegatedTo.getName() + "(...)")
1277                                    )
1278                            );
1279    
1280                            stackValue.put(delegateMethod.getReturnType(), iv);
1281    
1282                            iv.areturn(delegateMethod.getReturnType());
1283                        }
1284                    }
1285            );
1286        }
1287    
1288        public static boolean processInterfaceMember(
1289                @NotNull CallableMemberDescriptor function,
1290                @NotNull OwnerKind kind,
1291                @NotNull GenerationState state
1292        ) {
1293            return processInterface(function.getContainingDeclaration(), kind, state);
1294        }
1295    
1296        public static boolean processInterface(
1297                @NotNull DeclarationDescriptor contextClass,
1298                @NotNull OwnerKind kind,
1299                @NotNull GenerationState state
1300        ) {
1301            assert isInterface(contextClass) : "'processInterface' method should be called only for interfaces, but: " + contextClass;
1302            return JvmCodegenUtil.isJvm8InterfaceWithDefaults(contextClass, state) ? kind != OwnerKind.DEFAULT_IMPLS : kind == OwnerKind.DEFAULT_IMPLS;
1303        }
1304    }