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 }