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.inline;
018    
019    import com.intellij.openapi.vfs.VirtualFile;
020    import com.intellij.psi.PsiElement;
021    import com.intellij.psi.PsiFile;
022    import com.intellij.util.ArrayUtil;
023    import kotlin.jvm.functions.Function0;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.kotlin.backend.common.CodegenUtil;
027    import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment;
028    import org.jetbrains.kotlin.codegen.*;
029    import org.jetbrains.kotlin.codegen.context.*;
030    import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
031    import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
032    import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicArrayConstructorsKt;
033    import org.jetbrains.kotlin.codegen.state.GenerationState;
034    import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
035    import org.jetbrains.kotlin.descriptors.*;
036    import org.jetbrains.kotlin.incremental.KotlinLookupLocation;
037    import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache;
038    import org.jetbrains.kotlin.name.ClassId;
039    import org.jetbrains.kotlin.name.Name;
040    import org.jetbrains.kotlin.psi.*;
041    import org.jetbrains.kotlin.resolve.BindingContext;
042    import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
043    import org.jetbrains.kotlin.resolve.DescriptorUtils;
044    import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor;
045    import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
046    import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
047    import org.jetbrains.kotlin.resolve.inline.InlineUtil;
048    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
049    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
050    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
051    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
052    import org.jetbrains.kotlin.resolve.scopes.MemberScope;
053    import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
054    import org.jetbrains.kotlin.types.KotlinType;
055    import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
056    import org.jetbrains.kotlin.types.expressions.LabelResolver;
057    import org.jetbrains.org.objectweb.asm.Label;
058    import org.jetbrains.org.objectweb.asm.MethodVisitor;
059    import org.jetbrains.org.objectweb.asm.Opcodes;
060    import org.jetbrains.org.objectweb.asm.Type;
061    import org.jetbrains.org.objectweb.asm.commons.Method;
062    import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
063    import org.jetbrains.org.objectweb.asm.tree.InsnList;
064    import org.jetbrains.org.objectweb.asm.tree.LabelNode;
065    import org.jetbrains.org.objectweb.asm.tree.MethodNode;
066    
067    import java.io.IOException;
068    import java.util.*;
069    
070    import static org.jetbrains.kotlin.codegen.AsmUtil.getMethodAsmFlags;
071    import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
072    import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil.*;
073    import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isInlineOnly;
074    import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral;
075    
076    public class InlineCodegen extends CallGenerator {
077        private final GenerationState state;
078        private final KotlinTypeMapper typeMapper;
079    
080        private final FunctionDescriptor functionDescriptor;
081        private final JvmMethodSignature jvmSignature;
082        private final KtElement callElement;
083        private final MethodContext context;
084        private final ExpressionCodegen codegen;
085    
086        private final boolean asFunctionInline;
087        private final int initialFrameSize;
088        private final boolean isSameModule;
089    
090        private final ParametersBuilder invocationParamBuilder = ParametersBuilder.newBuilder();
091        private final Map<Integer, LambdaInfo> expressionMap = new HashMap<Integer, LambdaInfo>();
092    
093        private final ReifiedTypeInliner reifiedTypeInliner;
094    
095        @Nullable
096        private final TypeParameterMappings typeParameterMappings;
097    
098        private LambdaInfo activeLambda;
099    
100        private final SourceMapper sourceMapper;
101    
102        private Runnable delayedHiddenWriting;
103    
104        public InlineCodegen(
105                @NotNull ExpressionCodegen codegen,
106                @NotNull GenerationState state,
107                @NotNull FunctionDescriptor function,
108                @NotNull KtElement callElement,
109                @Nullable TypeParameterMappings typeParameterMappings
110        ) {
111            assert InlineUtil.isInline(function) || InlineUtil.isArrayConstructorWithLambda(function) :
112                    "InlineCodegen can inline only inline functions and array constructors: " + function;
113            this.state = state;
114            this.typeMapper = state.getTypeMapper();
115            this.codegen = codegen;
116            this.callElement = callElement;
117            this.functionDescriptor =
118                    InlineUtil.isArrayConstructorWithLambda(function)
119                    ? FictitiousArrayConstructor.create((ConstructorDescriptor) function)
120                    : function.getOriginal();
121            this.typeParameterMappings = typeParameterMappings;
122    
123            reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);
124    
125            initialFrameSize = codegen.getFrameMap().getCurrentSize();
126    
127            PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
128            context = (MethodContext) getContext(functionDescriptor, state, element != null ? (KtFile) element.getContainingFile() : null);
129            jvmSignature = typeMapper.mapSignatureWithGeneric(functionDescriptor, context.getContextKind());
130    
131            // TODO: implement AS_FUNCTION inline strategy
132            this.asFunctionInline = false;
133    
134            isSameModule = JvmCodegenUtil.isCallInsideSameModuleAsDeclared(functionDescriptor, codegen.getContext(), state.getOutDirectory());
135    
136            sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
137    
138            if (!(functionDescriptor instanceof FictitiousArrayConstructor)) {
139                reportIncrementalInfo(functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal(), jvmSignature, state);
140                String functionOrAccessorName = typeMapper.mapAsmMethod(function).getName();
141                //track changes for property accessor and @JvmName inline functions/property accessors
142                if(!functionOrAccessorName.equals(functionDescriptor.getName().asString())) {
143                    MemberScope scope = getMemberScope(functionDescriptor);
144                    if (scope != null) {
145                        //Fake lookup to track track changes for property accessors and @JvmName functions/property accessors
146                        scope.getContributedFunctions(Name.identifier(functionOrAccessorName), new KotlinLookupLocation(callElement));
147                    }
148                }
149            }
150        }
151    
152        @Nullable
153        private static MemberScope getMemberScope(@NotNull FunctionDescriptor functionOrAccessor) {
154            CallableMemberDescriptor callableMemberDescriptor = JvmCodegenUtil.getDirectMember(functionOrAccessor);
155            DeclarationDescriptor classOrPackageFragment = callableMemberDescriptor.getContainingDeclaration();
156            if (classOrPackageFragment instanceof ClassDescriptor) {
157                return ((ClassDescriptor) classOrPackageFragment).getUnsubstitutedMemberScope();
158            }
159            else if (classOrPackageFragment instanceof PackageFragmentDescriptor) {
160                return ((PackageFragmentDescriptor) classOrPackageFragment).getMemberScope();
161            }
162            return null;
163        }
164    
165        @Override
166        public void genCallInner(
167                @NotNull Callable callableMethod,
168                @Nullable ResolvedCall<?> resolvedCall,
169                boolean callDefault,
170                @NotNull ExpressionCodegen codegen
171        ) {
172            if (!state.getInlineCycleReporter().enterIntoInlining(resolvedCall)) {
173                generateStub(resolvedCall, codegen);
174                return;
175            }
176    
177            SMAPAndMethodNode nodeAndSmap = null;
178            try {
179                nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall);
180                endCall(inlineCall(nodeAndSmap));
181            }
182            catch (CompilationException e) {
183                throw e;
184            }
185            catch (InlineException e) {
186                throw throwCompilationException(nodeAndSmap, e, false);
187            }
188            catch (Exception e) {
189                throw throwCompilationException(nodeAndSmap, e, true);
190            }
191            finally {
192                state.getInlineCycleReporter().exitFromInliningOf(resolvedCall);
193            }
194        }
195    
196        @NotNull
197        private CompilationException throwCompilationException(
198                @Nullable SMAPAndMethodNode nodeAndSmap, @NotNull Exception e, boolean generateNodeText
199        ) {
200            CallableMemberDescriptor contextDescriptor = codegen.getContext().getContextDescriptor();
201            PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(contextDescriptor);
202            MethodNode node = nodeAndSmap != null ? nodeAndSmap.getNode() : null;
203            throw new CompilationException(
204                    "Couldn't inline method call '" + functionDescriptor.getName() + "' into\n" +
205                    contextDescriptor + "\n" +
206                    (element != null ? element.getText() : "<no source>") +
207                    (generateNodeText ? ("\nCause: " + InlineCodegenUtil.getNodeText(node)) : ""),
208                    e, callElement
209            );
210        }
211    
212        private void generateStub(@Nullable ResolvedCall<?> resolvedCall, @NotNull ExpressionCodegen codegen) {
213            leaveTemps();
214            assert resolvedCall != null;
215            String message = "Call is part of inline cycle: " + resolvedCall.getCall().getCallElement().getText();
216            AsmUtil.genThrow(codegen.v, "java/lang/UnsupportedOperationException", message);
217        }
218    
219        private void endCall(@NotNull InlineResult result) {
220            leaveTemps();
221    
222            codegen.propagateChildReifiedTypeParametersUsages(result.getReifiedTypeParametersUsages());
223    
224            state.getFactory().removeClasses(result.calcClassesToRemove());
225    
226            codegen.markLineNumberAfterInlineIfNeeded();
227        }
228    
229        @NotNull
230        static SMAPAndMethodNode createMethodNode(
231                @NotNull final FunctionDescriptor functionDescriptor,
232                @NotNull JvmMethodSignature jvmSignature,
233                @NotNull ExpressionCodegen codegen,
234                @NotNull CodegenContext context,
235                boolean callDefault,
236                @Nullable ResolvedCall<?> resolvedCall
237        ) {
238            if (InlineCodegenUtil.isSpecialEnumMethod(functionDescriptor)) {
239                assert resolvedCall != null : "Resolved call for " + functionDescriptor + " should be not null";
240                Map<TypeParameterDescriptor, KotlinType> arguments = resolvedCall.getTypeArguments();
241                assert arguments.size() == 1 : "Resolved call for " + functionDescriptor + " should have 1 type argument";
242    
243                MethodNode node =
244                        InlineCodegenUtil.createSpecialEnumMethodBody(
245                                codegen,
246                                functionDescriptor.getName().asString(),
247                                arguments.keySet().iterator().next().getDefaultType(),
248                                codegen.getState().getTypeMapper()
249                        );
250                return new SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1));
251            }
252            else if (CoroutineCodegenUtilKt.isBuiltInSuspendCoroutineOrReturnInJvm(functionDescriptor)) {
253                return new SMAPAndMethodNode(
254                        CoroutineCodegenUtilKt.createMethodNodeForSuspendCoroutineOrReturn(
255                                functionDescriptor, codegen.getState().getTypeMapper()
256                        ),
257                        SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)
258                );
259            }
260    
261            final GenerationState state = codegen.getState();
262            final Method asmMethod =
263                    callDefault
264                    ? state.getTypeMapper().mapDefaultMethod(functionDescriptor, context.getContextKind())
265                    : jvmSignature.getAsmMethod();
266    
267            MethodId methodId = new MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.getContainingDeclaration()), asmMethod);
268            final CallableMemberDescriptor directMember = getDirectMemberAndCallableFromObject(functionDescriptor);
269            if (!isBuiltInArrayIntrinsic(functionDescriptor) && !(directMember instanceof DeserializedCallableMemberDescriptor)) {
270                return doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, codegen, context, callDefault, state, asmMethod);
271            }
272    
273            SMAPAndMethodNode resultInCache = InlineCacheKt.getOrPut(
274                    state.getInlineCache().getMethodNodeById(), methodId, new Function0<SMAPAndMethodNode>() {
275                        @Override
276                        public SMAPAndMethodNode invoke() {
277                            SMAPAndMethodNode result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod);
278                            if (result == null) {
279                                throw new IllegalStateException("Couldn't obtain compiled function body for " + functionDescriptor);
280                            }
281                            return result;
282                        }
283                    }
284            );
285    
286            return resultInCache.copyWithNewNode(cloneMethodNode(resultInCache.getNode()));
287        }
288    
289        @NotNull
290        private static CallableMemberDescriptor getDirectMemberAndCallableFromObject(@NotNull FunctionDescriptor functionDescriptor) {
291            CallableMemberDescriptor directMember = JvmCodegenUtil.getDirectMember(functionDescriptor);
292            if (directMember instanceof ImportedFromObjectCallableDescriptor) {
293                return  ((ImportedFromObjectCallableDescriptor) directMember).getCallableFromObject();
294            }
295            return directMember;
296        }
297    
298        @NotNull
299        private static MethodNode cloneMethodNode(@NotNull MethodNode methodNode) {
300            methodNode.instructions.resetLabels();
301            MethodNode result = new MethodNode(
302                    API, methodNode.access, methodNode.name, methodNode.desc, methodNode.signature,
303                    ArrayUtil.toStringArray(methodNode.exceptions)
304            );
305            methodNode.accept(result);
306            return result;
307        }
308    
309        @Nullable
310        private static SMAPAndMethodNode doCreateMethodNodeFromCompiled(
311                @NotNull CallableMemberDescriptor callableDescriptor,
312                @NotNull final GenerationState state,
313                @NotNull Method asmMethod
314        ) {
315            if (isBuiltInArrayIntrinsic(callableDescriptor)) {
316                ClassId classId = IntrinsicArrayConstructorsKt.getClassId();
317                byte[] bytes = InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), classId, new Function0<byte[]>() {
318                    @Override
319                    public byte[] invoke() {
320                        return IntrinsicArrayConstructorsKt.getBytecode();
321                    }
322                });
323    
324                return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state);
325            }
326    
327            assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
328    
329            KotlinTypeMapper.ContainingClassesInfo containingClasses =
330                    state.getTypeMapper().getContainingClassesForDeserializedCallable((DeserializedCallableMemberDescriptor) callableDescriptor);
331    
332            final ClassId containerId = containingClasses.getImplClassId();
333    
334            byte[] bytes = InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), containerId, new Function0<byte[]>() {
335                @Override
336                public byte[] invoke() {
337                    VirtualFile file = InlineCodegenUtil.findVirtualFile(state, containerId);
338                    if (file == null) {
339                        throw new IllegalStateException("Couldn't find declaration file for " + containerId);
340                    }
341                    try {
342                        return file.contentsToByteArray();
343                    }
344                    catch (IOException e) {
345                        throw new RuntimeException(e);
346                    }
347                }
348            });
349    
350    
351            return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), containerId, state);
352        }
353    
354        @NotNull
355        private static SMAPAndMethodNode doCreateMethodNodeFromSource(
356                @NotNull FunctionDescriptor callableDescriptor,
357                @NotNull JvmMethodSignature jvmSignature,
358                @NotNull ExpressionCodegen codegen,
359                @NotNull CodegenContext context,
360                boolean callDefault,
361                @NotNull GenerationState state,
362                @NotNull Method asmMethod
363        ) {
364            PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
365    
366            if (!(element instanceof KtNamedFunction || element instanceof KtPropertyAccessor)) {
367                throw new IllegalStateException("Couldn't find declaration for function " + callableDescriptor);
368            }
369            KtDeclarationWithBody inliningFunction = (KtDeclarationWithBody) element;
370    
371            MethodNode node = new MethodNode(
372                    InlineCodegenUtil.API,
373                    getMethodAsmFlags(callableDescriptor, context.getContextKind(), state) | (callDefault ? Opcodes.ACC_STATIC : 0),
374                    asmMethod.getName(),
375                    asmMethod.getDescriptor(),
376                    null, null
377            );
378    
379            //for maxLocals calculation
380            MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
381            CodegenContext parentContext = context.getParentContext();
382            assert parentContext != null : "Context has no parent: " + context;
383            MethodContext methodContext = parentContext.intoFunction(callableDescriptor);
384    
385            SMAP smap;
386            if (callDefault) {
387                Type implementationOwner = state.getTypeMapper().mapImplementationOwner(callableDescriptor);
388                FakeMemberCodegen parentCodegen = new FakeMemberCodegen(
389                        codegen.getParentCodegen(), inliningFunction, (FieldOwnerContext) methodContext.getParentContext(),
390                        implementationOwner.getInternalName()
391                );
392                if (!(element instanceof KtNamedFunction)) {
393                    throw new IllegalStateException("Propertiy accessors with default parameters not supported " + callableDescriptor);
394                }
395                FunctionCodegen.generateDefaultImplBody(
396                        methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
397                        (KtNamedFunction) inliningFunction, parentCodegen, asmMethod
398                );
399                smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
400            }
401            else {
402                smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction, jvmSignature, codegen,
403                                          null);
404            }
405            maxCalcAdapter.visitMaxs(-1, -1);
406            maxCalcAdapter.visitEnd();
407    
408            return new SMAPAndMethodNode(node, smap);
409        }
410    
411        private static boolean isBuiltInArrayIntrinsic(@NotNull CallableMemberDescriptor callableDescriptor) {
412            if (callableDescriptor instanceof FictitiousArrayConstructor) return true;
413            String name = callableDescriptor.getName().asString();
414            return (name.equals("arrayOf") || name.equals("emptyArray")) &&
415                   callableDescriptor.getContainingDeclaration() instanceof BuiltInsPackageFragment;
416        }
417    
418        @NotNull
419        private InlineResult inlineCall(@NotNull SMAPAndMethodNode nodeAndSmap) {
420            assert delayedHiddenWriting == null : "'putHiddenParamsIntoLocals' should be called after 'processAndPutHiddenParameters(true)'";
421            DefaultSourceMapper defaultSourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
422            defaultSourceMapper.setCallSiteMarker(new CallSiteMarker(codegen.getLastLineNumber()));
423            MethodNode node = nodeAndSmap.getNode();
424            ReifiedTypeParametersUsages reificationResult = reifiedTypeInliner.reifyInstructions(node);
425            generateClosuresBodies();
426    
427            //through generation captured parameters will be added to invocationParamBuilder
428            putClosureParametersOnStack();
429    
430            addInlineMarker(codegen.v, true);
431    
432            Parameters parameters = invocationParamBuilder.buildParameters();
433    
434            InliningContext info = new RootInliningContext(
435                    expressionMap, state, codegen.getInlineNameGenerator().subGenerator(jvmSignature.getAsmMethod().getName()),
436                    callElement, getInlineCallSiteInfo(), reifiedTypeInliner, typeParameterMappings
437            );
438    
439            MethodInliner inliner = new MethodInliner(
440                    node, parameters, info, new FieldRemapper(null, null, parameters), isSameModule,
441                    "Method inlining " + callElement.getText(),
442                    createNestedSourceMapper(nodeAndSmap, sourceMapper), info.getCallSiteInfo(),
443                    isInlineOnly(functionDescriptor) ? new InlineOnlySmapSkipper(codegen) : null
444            ); //with captured
445    
446            LocalVarRemapper remapper = new LocalVarRemapper(parameters, initialFrameSize);
447    
448            MethodNode adapter = InlineCodegenUtil.createEmptyMethodNode();
449            //hack to keep linenumber info, otherwise jdi will skip begin of linenumber chain
450            adapter.visitInsn(Opcodes.NOP);
451    
452            InlineResult result = inliner.doInline(adapter, remapper, true, LabelOwner.SKIP_ALL);
453            result.getReifiedTypeParametersUsages().mergeAll(reificationResult);
454    
455            CallableMemberDescriptor descriptor = getLabelOwnerDescriptor(codegen.getContext());
456            final Set<String> labels = getDeclarationLabels(DescriptorToSourceUtils.descriptorToDeclaration(descriptor), descriptor);
457            LabelOwner labelOwner = new LabelOwner() {
458                @Override
459                public boolean isMyLabel(@NotNull String name) {
460                    return labels.contains(name);
461                }
462            };
463    
464            List<MethodInliner.PointForExternalFinallyBlocks> infos = MethodInliner.processReturns(adapter, labelOwner, true, null);
465            generateAndInsertFinallyBlocks(
466                    adapter, infos, ((StackValue.Local) remapper.remap(parameters.getArgsSizeOnStack() + 1).value).index
467            );
468            removeStaticInitializationTrigger(adapter);
469            removeFinallyMarkers(adapter);
470    
471            adapter.accept(new MethodBodyVisitor(codegen.v));
472    
473            addInlineMarker(codegen.v, false);
474    
475            defaultSourceMapper.setCallSiteMarker(null);
476    
477            return result;
478        }
479    
480        @NotNull
481        private static CallableMemberDescriptor getLabelOwnerDescriptor(@NotNull MethodContext context) {
482            if (context.getParentContext() instanceof ClosureContext &&
483                ((ClosureContext) context.getParentContext()).getOriginalSuspendLambdaDescriptor() != null) {
484                //noinspection ConstantConditions
485                return ((ClosureContext) context.getParentContext()).getOriginalSuspendLambdaDescriptor();
486            }
487    
488            return context.getContextDescriptor();
489        }
490    
491        private static void removeStaticInitializationTrigger(@NotNull MethodNode methodNode) {
492            InsnList insnList = methodNode.instructions;
493            AbstractInsnNode insn = insnList.getFirst();
494            while (insn != null) {
495                if (MultifileClassPartCodegen.isStaticInitTrigger(insn)) {
496                    AbstractInsnNode clinitTriggerCall = insn;
497                    insn = insn.getNext();
498                    insnList.remove(clinitTriggerCall);
499                }
500                else {
501                    insn = insn.getNext();
502                }
503            }
504        }
505    
506        @NotNull
507        private InlineCallSiteInfo getInlineCallSiteInfo() {
508            MethodContext context = codegen.getContext();
509            MemberCodegen<?> parentCodegen = codegen.getParentCodegen();
510            while (context instanceof InlineLambdaContext) {
511                CodegenContext closureContext = context.getParentContext();
512                assert closureContext instanceof ClosureContext : "Parent context of inline lambda should be closure context";
513                assert closureContext.getParentContext() instanceof MethodContext : "Closure context should appear in method context";
514                context = (MethodContext) closureContext.getParentContext();
515                assert parentCodegen instanceof FakeMemberCodegen : "Parent codegen of inlined lambda should be FakeMemberCodegen";
516                parentCodegen = ((FakeMemberCodegen) parentCodegen).delegate;
517            }
518    
519            JvmMethodSignature signature = typeMapper.mapSignatureSkipGeneric(context.getFunctionDescriptor(), context.getContextKind());
520            return new InlineCallSiteInfo(
521                    parentCodegen.getClassName(), signature.getAsmMethod().getName(), signature.getAsmMethod().getDescriptor()
522            );
523        }
524    
525        private void generateClosuresBodies() {
526            for (LambdaInfo info : expressionMap.values()) {
527                info.setNode(generateLambdaBody(info));
528            }
529        }
530    
531        @NotNull
532        private SMAPAndMethodNode generateLambdaBody(@NotNull LambdaInfo info) {
533            KtExpression declaration = info.getFunctionWithBodyOrCallableReference();
534            FunctionDescriptor descriptor = info.getFunctionDescriptor();
535    
536            ClassContext closureContext = info.isPropertyReference()
537                                            ? codegen.getContext().intoAnonymousClass(info.getClassDescriptor(), codegen, OwnerKind.IMPLEMENTATION)
538                                            : codegen.getContext().intoClosure(descriptor, codegen, typeMapper);
539            MethodContext context = closureContext.intoInlinedLambda(descriptor, info.isCrossInline, info.isPropertyReference());
540    
541            JvmMethodSignature jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(descriptor);
542            Method asmMethod = jvmMethodSignature.getAsmMethod();
543            MethodNode methodNode = new MethodNode(
544                    InlineCodegenUtil.API, getMethodAsmFlags(descriptor, context.getContextKind(), state),
545                    asmMethod.getName(), asmMethod.getDescriptor(), null, null
546            );
547    
548            MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);
549    
550            SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, codegen, info);
551            adapter.visitMaxs(-1, -1);
552            return new SMAPAndMethodNode(methodNode, smap);
553        }
554    
555        @NotNull
556        private static SMAP generateMethodBody(
557                @NotNull MethodVisitor adapter,
558                @NotNull FunctionDescriptor descriptor,
559                @NotNull MethodContext context,
560                @NotNull KtExpression expression,
561                @NotNull JvmMethodSignature jvmMethodSignature,
562                @NotNull ExpressionCodegen codegen,
563                @Nullable LambdaInfo lambdaInfo
564        ) {
565            boolean isLambda = lambdaInfo != null;
566            GenerationState state = codegen.getState();
567    
568            // Wrapping for preventing marking actual parent codegen as containing reified markers
569            FakeMemberCodegen parentCodegen = new FakeMemberCodegen(
570                    codegen.getParentCodegen(), expression, (FieldOwnerContext) context.getParentContext(),
571                    isLambda ? codegen.getParentCodegen().getClassName()
572                             : state.getTypeMapper().mapImplementationOwner(descriptor).getInternalName()
573            );
574    
575            FunctionGenerationStrategy strategy;
576            if (expression instanceof KtCallableReferenceExpression) {
577                KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
578                KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
579                Type receiverType =
580                        receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
581                        ? codegen.getState().getTypeMapper().mapType(codegen.getBindingContext().getType(receiverExpression))
582                        : null;
583    
584                if (isLambda && lambdaInfo.isPropertyReference()) {
585                    Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
586                    PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
587                    strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
588                            true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state, true);
589                }
590                else {
591                    strategy = new FunctionReferenceGenerationStrategy(
592                            state,
593                            descriptor,
594                            CallUtilKt
595                                    .getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
596                            receiverType,
597                            null,
598                            true
599                    );
600                }
601            }
602            else if (expression instanceof KtFunctionLiteral) {
603                strategy = new ClosureGenerationStrategy(state, (KtDeclarationWithBody) expression);
604            }
605            else if (descriptor.isSuspend() && expression instanceof KtFunction) {
606                strategy =
607                        new SuspendFunctionGenerationStrategy(
608                                state,
609                                CoroutineCodegenUtilKt.<FunctionDescriptor>unwrapInitialDescriptorForSuspendFunction(descriptor),
610                                (KtFunction) expression
611                        );
612            }
613            else {
614                strategy = new FunctionGenerationStrategy.FunctionDefault(state, (KtDeclarationWithBody) expression);
615            }
616    
617            FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen);
618    
619            if (isLambda) {
620                codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.getReifiedTypeParametersUsages());
621            }
622    
623            return createSMAPWithDefaultMapping(expression, parentCodegen.getOrCreateSourceMapper().getResultMappings());
624        }
625    
626        private static SMAP createSMAPWithDefaultMapping(
627                @NotNull KtExpression declaration,
628                @NotNull List<FileMapping> mappings
629        ) {
630            PsiFile containingFile = declaration.getContainingFile();
631            Integer lineNumbers = CodegenUtil.getLineNumberForElement(containingFile, true);
632            assert lineNumbers != null : "Couldn't extract line count in " + containingFile;
633    
634            return new SMAP(mappings);
635        }
636    
637        private static class FakeMemberCodegen extends MemberCodegen {
638            private final MemberCodegen delegate;
639            private final String className;
640    
641            @SuppressWarnings("unchecked")
642            public FakeMemberCodegen(
643                    @NotNull MemberCodegen wrapped,
644                    @NotNull KtElement declaration,
645                    @NotNull FieldOwnerContext codegenContext,
646                    @NotNull String className
647            ) {
648                super(wrapped, declaration, codegenContext);
649                this.delegate = wrapped;
650                this.className = className;
651            }
652    
653            @Override
654            protected void generateDeclaration() {
655                throw new IllegalStateException();
656            }
657    
658            @Override
659            protected void generateBody() {
660                throw new IllegalStateException();
661            }
662    
663            @Override
664            protected void generateKotlinMetadataAnnotation() {
665                throw new IllegalStateException();
666            }
667    
668            @NotNull
669            @Override
670            public NameGenerator getInlineNameGenerator() {
671                return delegate.getInlineNameGenerator();
672            }
673    
674            @NotNull
675            @Override
676            //TODO: obtain name from context
677            public String getClassName() {
678                return className;
679            }
680        }
681    
682        @Override
683        public void afterParameterPut(@NotNull Type type, @Nullable StackValue stackValue, int parameterIndex) {
684            putArgumentOrCapturedToLocalVal(type, stackValue, -1, parameterIndex);
685        }
686    
687        private void putArgumentOrCapturedToLocalVal(
688                @NotNull Type type,
689                @Nullable StackValue stackValue,
690                int capturedParamIndex,
691                int parameterIndex
692        ) {
693            if (!asFunctionInline && Type.VOID_TYPE != type) {
694                //TODO remap only inlinable closure => otherwise we could get a lot of problem
695                boolean couldBeRemapped = !shouldPutValue(type, stackValue);
696                StackValue remappedValue = couldBeRemapped ? stackValue : null;
697    
698                ParameterInfo info;
699                if (capturedParamIndex >= 0) {
700                    CapturedParamDesc capturedParamInfoInLambda = activeLambda.getCapturedVars().get(capturedParamIndex);
701                    info = invocationParamBuilder.addCapturedParam(capturedParamInfoInLambda, capturedParamInfoInLambda.getFieldName(), false);
702                    info.setRemapValue(remappedValue);
703                }
704                else {
705                    info = invocationParamBuilder.addNextValueParameter(type, false, remappedValue, parameterIndex);
706                }
707    
708                recordParameterValueInLocalVal(false, info);
709            }
710        }
711    
712        /*descriptor is null for captured vars*/
713        private static boolean shouldPutValue(@NotNull Type type, @Nullable StackValue stackValue) {
714            if (stackValue == null) {
715                //default or vararg
716                return true;
717            }
718    
719            //remap only inline functions (and maybe non primitives)
720            //TODO - clean asserion and remapping logic
721            if (isPrimitive(type) != isPrimitive(stackValue.type)) {
722                //don't remap boxing/unboxing primitives - lost identity and perfomance
723                return true;
724            }
725    
726            if (stackValue instanceof StackValue.Local) {
727                return false;
728            }
729    
730            StackValue field = stackValue;
731            if (stackValue instanceof StackValue.FieldForSharedVar) {
732                field = ((StackValue.FieldForSharedVar) stackValue).receiver;
733            }
734    
735            //check that value corresponds to captured inlining parameter
736            if (field instanceof StackValue.Field) {
737                DeclarationDescriptor varDescriptor = ((StackValue.Field) field).descriptor;
738                //check that variable is inline function parameter
739                return !(varDescriptor instanceof ParameterDescriptor &&
740                         InlineUtil.isInlineLambdaParameter((ParameterDescriptor) varDescriptor) &&
741                         InlineUtil.isInline(varDescriptor.getContainingDeclaration()));
742            }
743    
744            return true;
745        }
746    
747        private Runnable recordParameterValueInLocalVal(boolean delayedWritingToLocals, @NotNull final ParameterInfo... infos) {
748            final int[] index = new int[infos.length];
749            for (int i = 0; i < infos.length; i++) {
750                ParameterInfo info = infos[i];
751                if (!info.isSkippedOrRemapped()) {
752                    index[i] = codegen.getFrameMap().enterTemp(info.getType());
753                }
754                else {
755                    index[i] = -1;
756                }
757            }
758    
759            Runnable runnable = new Runnable() {
760                @Override
761                public void run() {
762                    for (int i = infos.length - 1; i >= 0; i--) {
763                        ParameterInfo info = infos[i];
764                        if (!info.isSkippedOrRemapped()) {
765                            Type type = info.type;
766                            StackValue.Local local = StackValue.local(index[i], type);
767                            local.store(StackValue.onStack(type), codegen.v);
768                            if (info instanceof CapturedParamInfo) {
769                                info.setRemapValue(local);
770                                ((CapturedParamInfo) info).setSynthetic(true);
771                            }
772                        }
773                    }
774                }
775            };
776    
777            if (delayedWritingToLocals) return runnable;
778            runnable.run();
779            return null;
780        }
781    
782        @Override
783        public void processAndPutHiddenParameters(boolean justProcess) {
784            if ((getMethodAsmFlags(functionDescriptor, context.getContextKind(), state) & Opcodes.ACC_STATIC) == 0) {
785                invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false);
786            }
787    
788            for (JvmMethodParameterSignature param : jvmSignature.getValueParameters()) {
789                if (param.getKind() == JvmMethodParameterKind.VALUE) {
790                    break;
791                }
792                invocationParamBuilder.addNextParameter(param.getAsmType(), false);
793            }
794    
795            invocationParamBuilder.markValueParametersStart();
796            List<ParameterInfo> hiddenParameters = invocationParamBuilder.buildParameters().getParameters();
797    
798            delayedHiddenWriting = recordParameterValueInLocalVal(justProcess, hiddenParameters.toArray(new ParameterInfo[hiddenParameters.size()]));
799        }
800    
801        private void leaveTemps() {
802            List<ParameterInfo> infos = invocationParamBuilder.listAllParams();
803            for (ListIterator<? extends ParameterInfo> iterator = infos.listIterator(infos.size()); iterator.hasPrevious(); ) {
804                ParameterInfo param = iterator.previous();
805                if (!param.isSkippedOrRemapped() || CapturedParamInfo.isSynthetic(param)) {
806                    codegen.getFrameMap().leaveTemp(param.type);
807                }
808            }
809        }
810    
811        /*lambda or callable reference*/
812        private static boolean isInliningParameter(@NotNull KtExpression expression, @NotNull ValueParameterDescriptor valueParameterDescriptor) {
813            //TODO deparenthisise typed
814            KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression);
815    
816            return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
817                   isInlinableParameterExpression(deparenthesized);
818        }
819    
820        private static boolean isInlinableParameterExpression(@Nullable KtExpression deparenthesized) {
821            return deparenthesized instanceof KtLambdaExpression ||
822                   deparenthesized instanceof KtNamedFunction ||
823                   deparenthesized instanceof KtCallableReferenceExpression;
824        }
825    
826        private LambdaInfo rememberClosure(@NotNull KtExpression expression, @NotNull Type type, @NotNull ValueParameterDescriptor parameter) {
827            KtExpression lambda = KtPsiUtil.deparenthesize(expression);
828            assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
829    
830            LambdaInfo info =
831                    new LambdaInfo(lambda, typeMapper, parameter.isCrossinline(), getBoundCallableReferenceReceiver(expression) != null);
832    
833            ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
834            closureInfo.setLambda(info);
835            expressionMap.put(closureInfo.getIndex(), info);
836            return info;
837        }
838    
839        @NotNull
840        public static Set<String> getDeclarationLabels(@Nullable PsiElement lambdaOrFun, @NotNull DeclarationDescriptor descriptor) {
841            Set<String> result = new HashSet<String>();
842    
843            if (lambdaOrFun != null) {
844                Name label = LabelResolver.INSTANCE.getLabelNameIfAny(lambdaOrFun);
845                if (label != null) {
846                    result.add(label.asString());
847                }
848            }
849    
850            if (!isFunctionLiteral(descriptor)) {
851                if (!descriptor.getName().isSpecial()) {
852                    result.add(descriptor.getName().asString());
853                }
854                result.add(InlineCodegenUtil.FIRST_FUN_LABEL);
855            }
856            return result;
857        }
858    
859        private void putClosureParametersOnStack() {
860            for (LambdaInfo next : expressionMap.values()) {
861                //closure parameters for bounded callable references are generated inplace
862                if (next.isBoundCallableReference()) continue;
863                putClosureParametersOnStack(next, null);
864            }
865        }
866    
867        private void putClosureParametersOnStack(@NotNull LambdaInfo next, @Nullable StackValue functionReferenceReceiver) {
868            activeLambda = next;
869            codegen.pushClosureOnStack(next.getClassDescriptor(), true, this, functionReferenceReceiver);
870            activeLambda = null;
871        }
872    
873        @NotNull
874        public static CodegenContext getContext(
875                @NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state, @Nullable KtFile sourceFile
876        ) {
877            if (descriptor instanceof PackageFragmentDescriptor) {
878                return new PackageContext((PackageFragmentDescriptor) descriptor, state.getRootContext(), null, sourceFile);
879            }
880    
881            DeclarationDescriptor container = descriptor.getContainingDeclaration();
882            assert container != null : "No container for descriptor: " + descriptor;
883            CodegenContext parent = getContext(container, state, sourceFile);
884    
885            if (descriptor instanceof ScriptDescriptor) {
886                List<ScriptDescriptor> earlierScripts = state.getReplSpecific().getEarlierScriptsForReplInterpreter();
887                return parent.intoScript(
888                        (ScriptDescriptor) descriptor,
889                        earlierScripts == null ? Collections.emptyList() : earlierScripts,
890                        (ClassDescriptor) descriptor, state.getTypeMapper()
891                );
892            }
893            else if (descriptor instanceof ClassDescriptor) {
894                OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION;
895                return parent.intoClass((ClassDescriptor) descriptor, kind, state);
896            }
897            else if (descriptor instanceof FunctionDescriptor) {
898                return parent.intoFunction((FunctionDescriptor) descriptor);
899            }
900    
901            throw new IllegalStateException("Couldn't build context for " + descriptor);
902        }
903    
904        @Override
905        public void genValueAndPut(
906                @NotNull ValueParameterDescriptor valueParameterDescriptor,
907                @NotNull KtExpression argumentExpression,
908                @NotNull Type parameterType,
909                int parameterIndex
910        ) {
911            if (isInliningParameter(argumentExpression, valueParameterDescriptor)) {
912                LambdaInfo lambdaInfo = rememberClosure(argumentExpression, parameterType, valueParameterDescriptor);
913    
914                KtExpression receiver = getBoundCallableReferenceReceiver(argumentExpression);
915                if (receiver != null) {
916                    putClosureParametersOnStack(lambdaInfo, codegen.gen(receiver));
917                }
918            }
919            else {
920                StackValue value = codegen.gen(argumentExpression);
921                putValueIfNeeded(parameterType, value, valueParameterDescriptor.getIndex());
922            }
923        }
924    
925        private KtExpression getBoundCallableReferenceReceiver(
926                @NotNull KtExpression argumentExpression
927        ) {
928            KtExpression deparenthesized = KtPsiUtil.deparenthesize(argumentExpression);
929            if (deparenthesized instanceof KtCallableReferenceExpression) {
930                KtExpression receiverExpression = ((KtCallableReferenceExpression) deparenthesized).getReceiverExpression();
931                if (receiverExpression != null) {
932                    DoubleColonLHS lhs = state.getBindingContext().get(BindingContext.DOUBLE_COLON_LHS, receiverExpression);
933                    if (lhs instanceof DoubleColonLHS.Expression) return receiverExpression;
934                }
935            }
936            return null;
937        }
938    
939        @Override
940        public void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value) {
941            putValueIfNeeded(parameterType, value, -1);
942        }
943    
944        private void putValueIfNeeded(@NotNull Type parameterType, @NotNull StackValue value, int index) {
945            if (shouldPutValue(parameterType, value)) {
946                value.put(parameterType, codegen.v);
947            }
948            afterParameterPut(parameterType, value, index);
949        }
950    
951        @Override
952        public void putCapturedValueOnStack(@NotNull StackValue stackValue, @NotNull Type valueType, int paramIndex) {
953            if (shouldPutValue(stackValue.type, stackValue)) {
954                stackValue.put(stackValue.type, codegen.v);
955            }
956            putArgumentOrCapturedToLocalVal(stackValue.type, stackValue, paramIndex, paramIndex);
957        }
958    
959        private void generateAndInsertFinallyBlocks(
960                @NotNull MethodNode intoNode,
961                @NotNull List<MethodInliner.PointForExternalFinallyBlocks> insertPoints,
962                int offsetForFinallyLocalVar
963        ) {
964            if (!codegen.hasFinallyBlocks()) return;
965    
966            Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints =
967                    new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>();
968            for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) {
969                extensionPoints.put(insertPoint.beforeIns, insertPoint);
970            }
971    
972            DefaultProcessor processor = new DefaultProcessor(intoNode, offsetForFinallyLocalVar);
973    
974            int curFinallyDepth = 0;
975            AbstractInsnNode curInstr = intoNode.instructions.getFirst();
976            while (curInstr != null) {
977                processor.processInstruction(curInstr, true);
978                if (InlineCodegenUtil.isFinallyStart(curInstr)) {
979                    //TODO depth index calc could be more precise
980                    curFinallyDepth = getConstant(curInstr.getPrevious());
981                }
982    
983                MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr);
984                if (extension != null) {
985                    Label start = new Label();
986    
987                    MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode();
988                    finallyNode.visitLabel(start);
989    
990                    ExpressionCodegen finallyCodegen =
991                            new ExpressionCodegen(finallyNode, codegen.getFrameMap(), codegen.getReturnType(),
992                                                  codegen.getContext(), codegen.getState(), codegen.getParentCodegen());
993                    finallyCodegen.addBlockStackElementsForNonLocalReturns(codegen.getBlockStackElements(), curFinallyDepth);
994    
995                    FrameMap frameMap = finallyCodegen.getFrameMap();
996                    FrameMap.Mark mark = frameMap.mark();
997                    int marker = -1;
998                    Set<LocalVarNodeWrapper> intervals = processor.getLocalVarsMetaInfo().getCurrentIntervals();
999                    for (LocalVarNodeWrapper interval : intervals) {
1000                        marker = Math.max(interval.getNode().index + 1, marker);
1001                    }
1002                    while (frameMap.getCurrentSize() < Math.max(processor.getNextFreeLocalIndex(), offsetForFinallyLocalVar + marker)) {
1003                        frameMap.enterTemp(Type.INT_TYPE);
1004                    }
1005    
1006                    finallyCodegen.generateFinallyBlocksIfNeeded(extension.returnType, extension.finallyIntervalEnd.getLabel());
1007    
1008                    //Exception table for external try/catch/finally blocks will be generated in original codegen after exiting this method
1009                    InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr);
1010    
1011                    SimpleInterval splitBy = new SimpleInterval((LabelNode) start.info, extension.finallyIntervalEnd);
1012                    processor.getTryBlocksMetaInfo().splitCurrentIntervals(splitBy, true);
1013    
1014                    //processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy);
1015    
1016                    mark.dropTo();
1017                }
1018    
1019                curInstr = curInstr.getNext();
1020            }
1021    
1022            processor.substituteTryBlockNodes(intoNode);
1023    
1024            //processor.substituteLocalVarTable(intoNode);
1025        }
1026    
1027        private void removeFinallyMarkers(@NotNull MethodNode intoNode) {
1028            if (InlineCodegenUtil.isFinallyMarkerRequired(codegen.getContext())) return;
1029    
1030            InsnList instructions = intoNode.instructions;
1031            AbstractInsnNode curInstr = instructions.getFirst();
1032            while (curInstr != null) {
1033                if (InlineCodegenUtil.isFinallyMarker(curInstr)) {
1034                    AbstractInsnNode marker = curInstr;
1035                    //just to assert
1036                    getConstant(marker.getPrevious());
1037                    curInstr = curInstr.getNext();
1038                    instructions.remove(marker.getPrevious());
1039                    instructions.remove(marker);
1040                    continue;
1041                }
1042                curInstr = curInstr.getNext();
1043            }
1044        }
1045    
1046        @NotNull
1047        public static SourceMapper createNestedSourceMapper(@NotNull SMAPAndMethodNode nodeAndSmap, @NotNull SourceMapper parent) {
1048            return new NestedSourceMapper(parent, nodeAndSmap.getSortedRanges(), nodeAndSmap.getClassSMAP().getSourceInfo());
1049        }
1050    
1051        static void reportIncrementalInfo(
1052                @NotNull FunctionDescriptor sourceDescriptor,
1053                @NotNull FunctionDescriptor targetDescriptor,
1054                @NotNull JvmMethodSignature jvmSignature,
1055                @NotNull GenerationState state
1056        ) {
1057            IncrementalCache incrementalCache = state.getIncrementalCacheForThisTarget();
1058            if (incrementalCache == null) return;
1059            String classFilePath = InlineCodegenUtilsKt.getClassFilePath(sourceDescriptor, state.getTypeMapper(), incrementalCache);
1060            String sourceFilePath = InlineCodegenUtilsKt.getSourceFilePath(targetDescriptor);
1061            Method method = jvmSignature.getAsmMethod();
1062            incrementalCache.registerInline(classFilePath, method.getName() + method.getDescriptor(), sourceFilePath);
1063        }
1064    
1065        @Override
1066        public void reorderArgumentsIfNeeded(
1067                @NotNull List<ArgumentAndDeclIndex> actualArgsWithDeclIndex, @NotNull List<? extends Type> valueParameterTypes
1068        ) {
1069        }
1070    
1071        @Override
1072        public void putHiddenParamsIntoLocals() {
1073            assert delayedHiddenWriting != null : "processAndPutHiddenParameters(true) should be called before putHiddenParamsIntoLocals";
1074            delayedHiddenWriting.run();
1075            delayedHiddenWriting = null;
1076        }
1077    }