001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.codegen;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.util.ArrayUtil;
021 import kotlin.Pair;
022 import kotlin.Unit;
023 import kotlin.collections.CollectionsKt;
024 import kotlin.jvm.functions.Function1;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
028 import org.jetbrains.kotlin.codegen.context.ClosureContext;
029 import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
030 import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
031 import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension;
032 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
033 import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
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.impl.LocalVariableDescriptor;
038 import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
039 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
040 import org.jetbrains.kotlin.load.java.JvmAbi;
041 import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
042 import org.jetbrains.kotlin.psi.KtElement;
043 import org.jetbrains.kotlin.resolve.BindingContext;
044 import org.jetbrains.kotlin.resolve.DescriptorUtils;
045 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
046 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
047 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
048 import org.jetbrains.kotlin.serialization.DescriptorSerializer;
049 import org.jetbrains.kotlin.serialization.ProtoBuf;
050 import org.jetbrains.kotlin.types.KotlinType;
051 import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
052 import org.jetbrains.kotlin.util.OperatorNameConventions;
053 import org.jetbrains.org.objectweb.asm.AnnotationVisitor;
054 import org.jetbrains.org.objectweb.asm.MethodVisitor;
055 import org.jetbrains.org.objectweb.asm.Type;
056 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
057 import org.jetbrains.org.objectweb.asm.commons.Method;
058
059 import java.util.ArrayList;
060 import java.util.Collections;
061 import java.util.List;
062
063 import static org.jetbrains.kotlin.codegen.AsmUtil.*;
064 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConst;
065 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE;
066 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
067 import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
068 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
069 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
070 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
071
072 public class ClosureCodegen extends MemberCodegen<KtElement> {
073 protected final FunctionDescriptor funDescriptor;
074 private final ClassDescriptor classDescriptor;
075 private final SamType samType;
076 private final KotlinType superClassType;
077 private final List<KotlinType> superInterfaceTypes;
078 private final FunctionDescriptor functionReferenceTarget;
079 private final FunctionGenerationStrategy strategy;
080 protected final CalculatedClosure closure;
081 protected final Type asmType;
082 protected final int visibilityFlag;
083 private final boolean shouldHaveBoundReferenceReceiver;
084
085 private Method constructor;
086 protected Type superClassAsmType;
087
088 public ClosureCodegen(
089 @NotNull GenerationState state,
090 @NotNull KtElement element,
091 @Nullable SamType samType,
092 @NotNull ClosureContext context,
093 @Nullable FunctionDescriptor functionReferenceTarget,
094 @NotNull FunctionGenerationStrategy strategy,
095 @NotNull MemberCodegen<?> parentCodegen,
096 @NotNull ClassBuilder classBuilder
097 ) {
098 super(state, parentCodegen, context, element, classBuilder);
099
100 this.funDescriptor = context.getFunctionDescriptor();
101 this.classDescriptor = context.getContextDescriptor();
102 this.samType = samType;
103 this.functionReferenceTarget = functionReferenceTarget;
104 this.strategy = strategy;
105
106 if (samType == null) {
107 this.superInterfaceTypes = new ArrayList<KotlinType>();
108
109 KotlinType superClassType = null;
110 for (KotlinType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
111 ClassifierDescriptor classifier = supertype.getConstructor().getDeclarationDescriptor();
112 if (DescriptorUtils.isInterface(classifier)) {
113 superInterfaceTypes.add(supertype);
114 }
115 else {
116 assert superClassType == null : "Closure class can't have more than one superclass: " + funDescriptor;
117 superClassType = supertype;
118 }
119 }
120 assert superClassType != null : "Closure class should have a superclass: " + funDescriptor;
121
122 this.superClassType = superClassType;
123 }
124 else {
125 this.superInterfaceTypes = Collections.singletonList(samType.getType());
126 this.superClassType = DescriptorUtilsKt.getBuiltIns(funDescriptor).getAnyType();
127 }
128
129 this.closure = bindingContext.get(CLOSURE, classDescriptor);
130 assert closure != null : "Closure must be calculated for class: " + classDescriptor;
131
132 this.shouldHaveBoundReferenceReceiver = CallableReferenceUtilKt.isForBoundCallableReference(closure);
133
134 this.asmType = typeMapper.mapClass(classDescriptor);
135
136 visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor);
137 }
138
139 @Override
140 protected void generateDeclaration() {
141 JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
142 if (samType != null) {
143 typeMapper.writeFormalTypeParameters(samType.getType().getConstructor().getParameters(), sw);
144 }
145 sw.writeSuperclass();
146 superClassAsmType = typeMapper.mapSupertype(superClassType, sw);
147 sw.writeSuperclassEnd();
148 String[] superInterfaceAsmTypes = new String[superInterfaceTypes.size()];
149 for (int i = 0; i < superInterfaceTypes.size(); i++) {
150 KotlinType superInterfaceType = superInterfaceTypes.get(i);
151 sw.writeInterface();
152 superInterfaceAsmTypes[i] = typeMapper.mapSupertype(superInterfaceType, sw).getInternalName();
153 sw.writeInterfaceEnd();
154 }
155
156 v.defineClass(element,
157 state.getClassFileVersion(),
158 ACC_FINAL | ACC_SUPER | visibilityFlag,
159 asmType.getInternalName(),
160 sw.makeJavaGenericSignature(),
161 superClassAsmType.getInternalName(),
162 superInterfaceAsmTypes
163 );
164
165 InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
166
167 v.visitSource(element.getContainingFile().getName(), null);
168 }
169
170 @Nullable
171 @Override
172 protected ClassDescriptor classForInnerClassRecord() {
173 return JvmCodegenUtil.isArgumentWhichWillBeInlined(bindingContext, funDescriptor) ? null : classDescriptor;
174 }
175
176 @Override
177 protected void generateBody() {
178 generateBridges();
179 generateClosureBody();
180
181 this.constructor = generateConstructor();
182
183 if (isConst(closure)) {
184 generateConstInstance(asmType, asmType);
185 }
186
187 genClosureFields(closure, v, typeMapper);
188 }
189
190 protected void generateClosureBody() {
191 functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), funDescriptor, strategy);
192
193 if (functionReferenceTarget != null) {
194 generateFunctionReferenceMethods(functionReferenceTarget);
195 }
196
197 functionCodegen.generateDefaultIfNeeded(
198 context.intoFunction(funDescriptor), funDescriptor, context.getContextKind(), DefaultParameterValueLoader.DEFAULT, null
199 );
200 }
201
202 protected void generateBridges() {
203 FunctionDescriptor erasedInterfaceFunction;
204 if (samType == null) {
205 erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
206 }
207 else {
208 erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
209 }
210
211 generateBridge(
212 typeMapper.mapAsmMethod(erasedInterfaceFunction),
213 typeMapper.mapAsmMethod(funDescriptor)
214 );
215
216 //TODO: rewrite cause ugly hack
217 if (samType != null) {
218 SimpleFunctionDescriptorImpl descriptorForBridges = SimpleFunctionDescriptorImpl
219 .create(funDescriptor.getContainingDeclaration(), funDescriptor.getAnnotations(),
220 erasedInterfaceFunction.getName(),
221 CallableMemberDescriptor.Kind.DECLARATION, funDescriptor.getSource());
222
223 descriptorForBridges
224 .initialize(null, erasedInterfaceFunction.getDispatchReceiverParameter(), erasedInterfaceFunction.getTypeParameters(),
225 erasedInterfaceFunction.getValueParameters(), erasedInterfaceFunction.getReturnType(),
226 Modality.OPEN, erasedInterfaceFunction.getVisibility());
227
228 DescriptorUtilsKt.setSingleOverridden(descriptorForBridges, erasedInterfaceFunction);
229 functionCodegen.generateBridges(descriptorForBridges);
230 }
231 }
232
233 @Override
234 protected void generateKotlinMetadataAnnotation() {
235 FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
236 FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
237 Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
238 assert method != null : "No method for " + frontendFunDescriptor;
239 v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
240
241 final DescriptorSerializer serializer =
242 DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
243
244 final ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
245
246 WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, new Function1<AnnotationVisitor, Unit>() {
247 @Override
248 public Unit invoke(AnnotationVisitor av) {
249 writeAnnotationData(av, serializer, functionProto);
250 return Unit.INSTANCE;
251 }
252 });
253 }
254
255 /**
256 * Given a function descriptor, creates another function descriptor with type parameters copied from outer context(s).
257 * This is needed because once we're serializing this to a proto, there's no place to store information about external type parameters.
258 */
259 @NotNull
260 private static FunctionDescriptor createFreeLambdaDescriptor(@NotNull FunctionDescriptor descriptor) {
261 FunctionDescriptor.CopyBuilder<? extends FunctionDescriptor> builder = descriptor.newCopyBuilder();
262 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
263 builder.setTypeParameters(typeParameters);
264
265 DeclarationDescriptor container = descriptor.getContainingDeclaration();
266 while (container != null) {
267 if (container instanceof ClassDescriptor) {
268 typeParameters.addAll(((ClassDescriptor) container).getDeclaredTypeParameters());
269 }
270 else if (container instanceof CallableDescriptor && !(container instanceof ConstructorDescriptor)) {
271 typeParameters.addAll(((CallableDescriptor) container).getTypeParameters());
272 }
273 container = container.getContainingDeclaration();
274 }
275
276 return typeParameters.isEmpty() ? descriptor : builder.build();
277 }
278
279 @Override
280 protected void done() {
281 writeOuterClassAndEnclosingMethod();
282 super.done();
283 }
284
285 @NotNull
286 public StackValue putInstanceOnStack(@NotNull final ExpressionCodegen codegen, @Nullable final StackValue functionReferenceReceiver) {
287 return StackValue.operation(
288 functionReferenceTarget != null ? K_FUNCTION : asmType,
289 new Function1<InstructionAdapter, Unit>() {
290 @Override
291 public Unit invoke(InstructionAdapter v) {
292 if (isConst(closure)) {
293 v.getstatic(asmType.getInternalName(), JvmAbi.INSTANCE_FIELD, asmType.getDescriptor());
294 }
295 else {
296 v.anew(asmType);
297 v.dup();
298
299 codegen.pushClosureOnStack(classDescriptor, true, codegen.defaultCallGenerator, functionReferenceReceiver);
300 v.invokespecial(asmType.getInternalName(), "<init>", constructor.getDescriptor(), false);
301 }
302
303 return Unit.INSTANCE;
304 }
305 }
306 );
307 }
308
309 protected void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
310 if (bridge.equals(delegate)) return;
311
312 MethodVisitor mv =
313 v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), ACC_PUBLIC | ACC_BRIDGE | ACC_SYNTHETIC,
314 bridge.getName(), bridge.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
315
316 if (!state.getClassBuilderMode().generateBodies) return;
317
318 mv.visitCode();
319
320 InstructionAdapter iv = new InstructionAdapter(mv);
321 MemberCodegen.markLineNumberForDescriptor(DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);
322
323 iv.load(0, asmType);
324
325 Type[] myParameterTypes = bridge.getArgumentTypes();
326
327 List<ParameterDescriptor> calleeParameters = CollectionsKt.plus(
328 org.jetbrains.kotlin.utils.CollectionsKt.<ParameterDescriptor>singletonOrEmptyList(funDescriptor.getExtensionReceiverParameter()),
329 funDescriptor.getValueParameters()
330 );
331
332 int slot = 1;
333 for (int i = 0; i < calleeParameters.size(); i++) {
334 Type type = myParameterTypes[i];
335 StackValue.local(slot, type).put(typeMapper.mapType(calleeParameters.get(i)), iv);
336 slot += type.getSize();
337 }
338
339 iv.invokevirtual(asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false);
340 StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), iv);
341
342 iv.areturn(bridge.getReturnType());
343
344 FunctionCodegen.endVisit(mv, "bridge", element);
345 }
346
347 // TODO: ImplementationBodyCodegen.markLineNumberForSyntheticFunction?
348 private void generateFunctionReferenceMethods(@NotNull FunctionDescriptor descriptor) {
349 int flags = ACC_PUBLIC | ACC_FINAL;
350 boolean generateBody = state.getClassBuilderMode().generateBodies;
351
352 {
353 MethodVisitor mv =
354 v.newMethod(NO_ORIGIN, flags, "getOwner", Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE), null, null);
355 if (generateBody) {
356 mv.visitCode();
357 InstructionAdapter iv = new InstructionAdapter(mv);
358 generateCallableReferenceDeclarationContainer(iv, descriptor, state);
359 iv.areturn(K_DECLARATION_CONTAINER_TYPE);
360 FunctionCodegen.endVisit(iv, "function reference getOwner", element);
361 }
362 }
363
364 {
365 MethodVisitor mv =
366 v.newMethod(NO_ORIGIN, flags, "getName", Type.getMethodDescriptor(JAVA_STRING_TYPE), null, null);
367 if (generateBody) {
368 mv.visitCode();
369 InstructionAdapter iv = new InstructionAdapter(mv);
370 iv.aconst(descriptor.getName().asString());
371 iv.areturn(JAVA_STRING_TYPE);
372 FunctionCodegen.endVisit(iv, "function reference getName", element);
373 }
374 }
375
376 {
377 MethodVisitor mv = v.newMethod(NO_ORIGIN, flags, "getSignature", Type.getMethodDescriptor(JAVA_STRING_TYPE), null, null);
378 if (generateBody) {
379 mv.visitCode();
380 InstructionAdapter iv = new InstructionAdapter(mv);
381 PropertyReferenceCodegen.generateCallableReferenceSignature(iv, descriptor, state);
382 iv.areturn(JAVA_STRING_TYPE);
383 FunctionCodegen.endVisit(iv, "function reference getSignature", element);
384 }
385 }
386 }
387
388 public static void generateCallableReferenceDeclarationContainer(
389 @NotNull InstructionAdapter iv,
390 @NotNull CallableDescriptor descriptor,
391 @NotNull GenerationState state
392 ) {
393 DeclarationDescriptor container = descriptor.getContainingDeclaration();
394 if (container instanceof ClassDescriptor) {
395 // TODO: getDefaultType() here is wrong and won't work for arrays
396 putJavaLangClassInstance(iv, state.getTypeMapper().mapType(((ClassDescriptor) container).getDefaultType()));
397 wrapJavaClassIntoKClass(iv);
398 }
399 else if (container instanceof PackageFragmentDescriptor) {
400 iv.aconst(state.getTypeMapper().mapOwner(descriptor));
401 iv.aconst(state.getModuleName());
402 iv.invokestatic(REFLECTION, "getOrCreateKotlinPackage",
403 Type.getMethodDescriptor(K_DECLARATION_CONTAINER_TYPE, getType(Class.class), getType(String.class)), false);
404 }
405 else {
406 iv.aconst(null);
407 }
408 }
409
410 @NotNull
411 protected Method generateConstructor() {
412 List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
413
414 Type[] argTypes = fieldListToTypeArray(args);
415
416 Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
417 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null,
418 ArrayUtil.EMPTY_STRING_ARRAY);
419 if (state.getClassBuilderMode().generateBodies) {
420 mv.visitCode();
421 InstructionAdapter iv = new InstructionAdapter(mv);
422
423 Pair<Integer, Type> receiverIndexAndType =
424 CallableReferenceUtilKt.generateClosureFieldsInitializationFromParameters(iv, closure, args);
425 if (shouldHaveBoundReferenceReceiver && receiverIndexAndType == null) {
426 throw new AssertionError("No bound reference receiver in constructor parameters: " + args);
427 }
428 int boundReferenceReceiverParameterIndex = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getFirst() : -1;
429 Type boundReferenceReceiverType = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getSecond() : null;
430
431 iv.load(0, superClassAsmType);
432
433 String superClassConstructorDescriptor;
434 if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) ||
435 superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) {
436 int arity = calculateArity();
437 iv.iconst(arity);
438 if (shouldHaveBoundReferenceReceiver) {
439 CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReferenceReceiverParameterIndex, boundReferenceReceiverType);
440 superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
441 }
442 else {
443 superClassConstructorDescriptor = "(I)V";
444 }
445 }
446 else {
447 assert !shouldHaveBoundReferenceReceiver : "Unexpected bound reference with supertype " + superClassAsmType;
448 superClassConstructorDescriptor = "()V";
449 }
450 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", superClassConstructorDescriptor, false);
451
452 iv.visitInsn(RETURN);
453
454 FunctionCodegen.endVisit(iv, "constructor", element);
455 }
456 return constructor;
457 }
458
459 protected int calculateArity() {
460 int arity = funDescriptor.getValueParameters().size();
461 if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
462 if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
463 return arity;
464 }
465
466 @NotNull
467 public static List<FieldInfo> calculateConstructorParameters(
468 @NotNull KotlinTypeMapper typeMapper,
469 @NotNull CalculatedClosure closure,
470 @NotNull Type ownerType
471 ) {
472 BindingContext bindingContext = typeMapper.getBindingContext();
473 List<FieldInfo> args = Lists.newArrayList();
474 ClassDescriptor captureThis = closure.getCaptureThis();
475 if (captureThis != null) {
476 Type type = typeMapper.mapType(captureThis);
477 args.add(FieldInfo.createForHiddenField(ownerType, type, CAPTURED_THIS_FIELD));
478 }
479 KotlinType captureReceiverType = closure.getCaptureReceiverType();
480 if (captureReceiverType != null) {
481 args.add(FieldInfo.createForHiddenField(ownerType, typeMapper.mapType(captureReceiverType), CAPTURED_RECEIVER_FIELD));
482 }
483
484 for (DeclarationDescriptor descriptor : closure.getCaptureVariables().keySet()) {
485 if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
486 Type type = typeMapper.getSharedVarType(descriptor);
487 if (type == null && descriptor instanceof LocalVariableDescriptor) {
488 KotlinType delegateType = JvmCodegenUtil.getPropertyDelegateType((LocalVariableDescriptor) descriptor, bindingContext);
489 if (delegateType != null) {
490 type = typeMapper.mapType(delegateType);
491 }
492 }
493 if (type == null) {
494 type = typeMapper.mapType((VariableDescriptor) descriptor);
495 }
496 args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().asString()));
497 }
498 else if (ExpressionTypingUtils.isLocalFunction(descriptor)) {
499 Type classType = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) descriptor);
500 args.add(FieldInfo.createForHiddenField(ownerType, classType, "$" + descriptor.getName().asString()));
501 }
502 else if (descriptor instanceof FunctionDescriptor) {
503 assert captureReceiverType != null;
504 }
505 }
506 return args;
507 }
508
509 private static Type[] fieldListToTypeArray(List<FieldInfo> args) {
510 Type[] argTypes = new Type[args.size()];
511 for (int i = 0; i != argTypes.length; ++i) {
512 argTypes[i] = args.get(i).getFieldType();
513 }
514 return argTypes;
515 }
516
517 @NotNull
518 public static FunctionDescriptor getErasedInvokeFunction(@NotNull FunctionDescriptor function) {
519 ClassDescriptor functionClass = DescriptorUtilsKt.getBuiltIns(function).getFunction(
520 function.getValueParameters().size() + (function.getExtensionReceiverParameter() != null ? 1 : 0)
521 );
522 MemberScope scope = functionClass.getDefaultType().getMemberScope();
523 return scope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).iterator().next();
524 }
525 }