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