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