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.intellij.openapi.progress.ProcessCanceledException;
020    import com.intellij.psi.PsiElement;
021    import kotlin.Unit;
022    import kotlin.jvm.functions.Function0;
023    import kotlin.jvm.functions.Function1;
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.codegen.context.*;
028    import org.jetbrains.kotlin.codegen.inline.*;
029    import org.jetbrains.kotlin.codegen.state.GenerationState;
030    import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
031    import org.jetbrains.kotlin.descriptors.*;
032    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
033    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
034    import org.jetbrains.kotlin.fileClasses.FileClasses;
035    import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
036    import org.jetbrains.kotlin.load.java.JavaVisibilities;
037    import org.jetbrains.kotlin.load.java.JvmAbi;
038    import org.jetbrains.kotlin.name.Name;
039    import org.jetbrains.kotlin.name.SpecialNames;
040    import org.jetbrains.kotlin.psi.*;
041    import org.jetbrains.kotlin.resolve.*;
042    import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt;
043    import org.jetbrains.kotlin.resolve.constants.ConstantValue;
044    import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
045    import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
046    import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
047    import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
048    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
049    import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
050    import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
051    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
052    import org.jetbrains.kotlin.storage.NotNullLazyValue;
053    import org.jetbrains.kotlin.types.ErrorUtils;
054    import org.jetbrains.kotlin.types.KotlinType;
055    import org.jetbrains.org.objectweb.asm.Label;
056    import org.jetbrains.org.objectweb.asm.MethodVisitor;
057    import org.jetbrains.org.objectweb.asm.Type;
058    import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
059    import org.jetbrains.org.objectweb.asm.commons.Method;
060    
061    import java.util.*;
062    
063    import static org.jetbrains.kotlin.codegen.AsmUtil.calculateInnerClassAccessFlags;
064    import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
065    import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
066    import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
067    import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
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.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic;
071    import static org.jetbrains.org.objectweb.asm.Opcodes.*;
072    
073    public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclarationContainer*/> {
074        protected final GenerationState state;
075        protected final T element;
076        protected final FieldOwnerContext context;
077        protected final ClassBuilder v;
078        protected final FunctionCodegen functionCodegen;
079        protected final PropertyCodegen propertyCodegen;
080        protected final JetTypeMapper typeMapper;
081        protected final BindingContext bindingContext;
082        protected final JvmFileClassesProvider fileClassesProvider;
083        private final MemberCodegen<?> parentCodegen;
084        private final ReifiedTypeParametersUsages reifiedTypeParametersUsages = new ReifiedTypeParametersUsages();
085        protected final Collection<ClassDescriptor> innerClasses = new LinkedHashSet<ClassDescriptor>();
086    
087        protected ExpressionCodegen clInit;
088        private NameGenerator inlineNameGenerator;
089    
090        private SourceMapper sourceMapper;
091        private final ConstantExpressionEvaluator constantExpressionEvaluator;
092    
093        public MemberCodegen(
094                @NotNull GenerationState state,
095                @Nullable MemberCodegen<?> parentCodegen,
096                @NotNull FieldOwnerContext context,
097                T element,
098                @NotNull ClassBuilder builder
099        ) {
100            this.state = state;
101            this.typeMapper = state.getTypeMapper();
102            this.bindingContext = state.getBindingContext();
103            this.fileClassesProvider = state.getFileClassesProvider();
104            this.element = element;
105            this.context = context;
106            this.v = builder;
107            this.functionCodegen = new FunctionCodegen(context, v, state, this);
108            this.propertyCodegen = new PropertyCodegen(context, v, functionCodegen, this);
109            this.parentCodegen = parentCodegen;
110            this.constantExpressionEvaluator = new ConstantExpressionEvaluator(state.getModule().getBuiltIns());
111        }
112    
113        protected MemberCodegen(@NotNull MemberCodegen<T> wrapped, T declaration, FieldOwnerContext codegenContext) {
114            this(wrapped.state, wrapped.getParentCodegen(), codegenContext, declaration, wrapped.v);
115        }
116    
117        public void generate() {
118            generateDeclaration();
119    
120            generateBody();
121    
122            generateSyntheticParts();
123    
124            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
125                generateKotlinAnnotation();
126            }
127    
128            done();
129        }
130    
131        protected abstract void generateDeclaration();
132    
133        protected abstract void generateBody();
134    
135        protected void generateSyntheticParts() {
136        }
137    
138        protected abstract void generateKotlinAnnotation();
139    
140        @Nullable
141        protected ClassDescriptor classForInnerClassRecord() {
142            return null;
143        }
144    
145        public static void markLineNumberForDescriptor(@Nullable ClassDescriptor declarationDescriptor, @NotNull InstructionAdapter v) {
146            if (declarationDescriptor == null) {
147                return;
148            }
149    
150            PsiElement classElement = DescriptorToSourceUtils.getSourceFromDescriptor(declarationDescriptor);
151            if (classElement != null) {
152                markLineNumberForElement(classElement, v);
153            }
154        }
155    
156        public static void markLineNumberForElement(@NotNull PsiElement element, @NotNull InstructionAdapter v) {
157            Integer lineNumber = CodegenUtil.getLineNumberForElement(element, false);
158            if (lineNumber != null) {
159                Label label = new Label();
160                v.visitLabel(label);
161                v.visitLineNumber(lineNumber, label);
162            }
163        }
164    
165        protected void done() {
166            if (clInit != null) {
167                clInit.v.visitInsn(RETURN);
168                FunctionCodegen.endVisit(clInit.v, "static initializer", element);
169            }
170    
171            writeInnerClasses();
172    
173            if (sourceMapper != null) {
174                SourceMapper.Companion.flushToClassBuilder(sourceMapper, v);
175            }
176    
177            v.done();
178        }
179    
180        public void genFunctionOrProperty(@NotNull KtDeclaration functionOrProperty) {
181            if (functionOrProperty instanceof KtNamedFunction) {
182                try {
183                    functionCodegen.gen((KtNamedFunction) functionOrProperty);
184                }
185                catch (ProcessCanceledException e) {
186                    throw e;
187                }
188                catch (CompilationException e) {
189                    throw e;
190                }
191                catch (Exception e) {
192                    throw new CompilationException("Failed to generate function " + functionOrProperty.getName(), e, functionOrProperty);
193                }
194            }
195            else if (functionOrProperty instanceof KtProperty) {
196                try {
197                    propertyCodegen.gen((KtProperty) functionOrProperty);
198                }
199                catch (ProcessCanceledException e) {
200                    throw e;
201                }
202                catch (CompilationException e) {
203                    throw e;
204                }
205                catch (Exception e) {
206                    throw new CompilationException("Failed to generate property " + functionOrProperty.getName(), e, functionOrProperty);
207                }
208            }
209            else {
210                throw new IllegalArgumentException("Unknown parameter: " + functionOrProperty);
211            }
212        }
213    
214        public static void genClassOrObject(
215                @NotNull CodegenContext parentContext,
216                @NotNull KtClassOrObject aClass,
217                @NotNull GenerationState state,
218                @Nullable MemberCodegen<?> parentCodegen
219        ) {
220            ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
221    
222            if (descriptor == null || ErrorUtils.isError(descriptor)) {
223                badDescriptor(descriptor, state.getClassBuilderMode());
224                return;
225            }
226    
227            if (descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED)) {
228                badDescriptor(descriptor, state.getClassBuilderMode());
229            }
230    
231            Type classType = state.getTypeMapper().mapClass(descriptor);
232            ClassBuilder classBuilder = state.getFactory().newVisitor(JvmDeclarationOriginKt.OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile());
233            ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
234            new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
235        }
236    
237        private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {
238            if (mode != ClassBuilderMode.LIGHT_CLASSES) {
239                throw new IllegalStateException("Generating bad descriptor in ClassBuilderMode = " + mode + ": " + descriptor);
240            }
241        }
242    
243        public void genClassOrObject(KtClassOrObject aClass) {
244            genClassOrObject(context, aClass, state, this);
245        }
246    
247        private void writeInnerClasses() {
248            // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
249            // for each enclosing class and for each immediate member
250            ClassDescriptor classDescriptor = classForInnerClassRecord();
251            if (classDescriptor != null) {
252                if (parentCodegen != null) {
253                    parentCodegen.innerClasses.add(classDescriptor);
254                }
255    
256                for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
257                    ClassDescriptor outerClass = codegen.classForInnerClassRecord();
258                    if (outerClass != null) {
259                        innerClasses.add(outerClass);
260                    }
261                }
262            }
263    
264            for (ClassDescriptor innerClass : innerClasses) {
265                writeInnerClass(innerClass);
266            }
267        }
268    
269        private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
270            DeclarationDescriptor containing = innerClass.getContainingDeclaration();
271            String outerClassInternalName = null;
272            if (containing instanceof ClassDescriptor) {
273                outerClassInternalName = typeMapper.mapClass((ClassDescriptor) containing).getInternalName();
274            }
275            String innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
276            String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName();
277            v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass));
278        }
279    
280        protected void writeOuterClassAndEnclosingMethod() {
281            CodegenContext context = this.context.getParentContext();
282    
283            while (context instanceof InlineLambdaContext) {
284                // If this is a lambda which will be inlined, skip its MethodContext and enclosing ClosureContext
285                //noinspection ConstantConditions
286                context = context.getParentContext().getParentContext();
287            }
288            assert context != null : "Outermost context can't be null: " + this.context;
289    
290            Type enclosingAsmType = computeOuterClass(context);
291            if (enclosingAsmType != null) {
292                Method method = computeEnclosingMethod(context);
293    
294                v.visitOuterClass(
295                        enclosingAsmType.getInternalName(),
296                        method == null ? null : method.getName(),
297                        method == null ? null : method.getDescriptor()
298                );
299            }
300        }
301    
302        @Nullable
303        private Type computeOuterClass(@NotNull CodegenContext<?> context) {
304            CodegenContext<? extends ClassOrPackageFragmentDescriptor> outermost = context.getClassOrPackageParentContext();
305            if (outermost instanceof ClassContext) {
306                return typeMapper.mapType(((ClassContext) outermost).getContextDescriptor());
307            }
308            else if (outermost instanceof DelegatingFacadeContext || outermost instanceof DelegatingToPartContext) {
309                Type implementationOwnerType = CodegenContextUtil.getImplementationOwnerClassType(outermost);
310                if (implementationOwnerType != null) {
311                    return implementationOwnerType;
312                }
313                else {
314                    return FileClasses.getFileClassType(fileClassesProvider, element.getContainingKtFile());
315                }
316            }
317    
318            return null;
319        }
320    
321        @Nullable
322        private Method computeEnclosingMethod(@NotNull CodegenContext context) {
323            if (context instanceof MethodContext) {
324                Method method = typeMapper.mapSignature(((MethodContext) context).getFunctionDescriptor()).getAsmMethod();
325                if (!method.getName().equals("<clinit>")) {
326                    return method;
327                }
328            }
329            return null;
330        }
331    
332        @NotNull
333        public NameGenerator getInlineNameGenerator() {
334            if (inlineNameGenerator == null) {
335                String prefix = InlineCodegenUtil.getInlineName(context, typeMapper, fileClassesProvider);
336                inlineNameGenerator = new NameGenerator(prefix);
337            }
338            return inlineNameGenerator;
339        }
340    
341        @NotNull
342        protected ExpressionCodegen createOrGetClInitCodegen() {
343            DeclarationDescriptor descriptor = context.getContextDescriptor();
344            if (clInit == null) {
345                MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(descriptor), ACC_STATIC, "<clinit>", "()V", null, null);
346                SimpleFunctionDescriptorImpl clInit =
347                        SimpleFunctionDescriptorImpl.create(descriptor, Annotations.Companion.getEMPTY(), Name.special("<clinit>"), SYNTHESIZED,
348                                                            KotlinSourceElementKt.toSourceElement(element));
349                clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
350                                  Collections.<ValueParameterDescriptor>emptyList(),
351                                  DescriptorUtilsKt.getModule(descriptor).getBuiltIns().getUnitType(),
352                                  null, Visibilities.PRIVATE);
353    
354                this.clInit = new ExpressionCodegen(mv, new FrameMap(), Type.VOID_TYPE, context.intoFunction(clInit), state, this);
355            }
356            return clInit;
357        }
358    
359        protected void generateInitializers(@NotNull Function0<ExpressionCodegen> createCodegen) {
360            NotNullLazyValue<ExpressionCodegen> codegen = LockBasedStorageManager.NO_LOCKS.createLazyValue(createCodegen);
361            for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
362                if (declaration instanceof KtProperty) {
363                    if (shouldInitializeProperty((KtProperty) declaration)) {
364                        initializeProperty(codegen.invoke(), (KtProperty) declaration);
365                    }
366                }
367                else if (declaration instanceof KtAnonymousInitializer) {
368                    KtExpression body = ((KtAnonymousInitializer) declaration).getBody();
369                    if (body != null) {
370                        codegen.invoke().gen(body, Type.VOID_TYPE);
371                    }
372                }
373            }
374        }
375    
376        private void initializeProperty(@NotNull ExpressionCodegen codegen, @NotNull KtProperty property) {
377            PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
378            assert propertyDescriptor != null;
379    
380            KtExpression initializer = property.getDelegateExpressionOrInitializer();
381            assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
382    
383            StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, false, null, true, StackValue.LOCAL_0);
384    
385            propValue.store(codegen.gen(initializer), codegen.v);
386        }
387    
388        private boolean shouldInitializeProperty(@NotNull KtProperty property) {
389            if (!property.hasDelegateExpressionOrInitializer()) return false;
390    
391            PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property);
392            assert propertyDescriptor != null;
393    
394            if (propertyDescriptor.isConst()) {
395                //const initializer always inlined
396                return false;
397            }
398    
399            KtExpression initializer = property.getInitializer();
400    
401            ConstantValue<?> initializerValue = computeInitializerValue(property, propertyDescriptor, initializer);
402            // we must write constant values for fields in light classes,
403            // because Java's completion for annotation arguments uses this information
404            if (initializerValue == null) return state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES;
405    
406            //TODO: OPTIMIZATION: don't initialize static final fields
407            KotlinType jetType = getPropertyOrDelegateType(property, propertyDescriptor);
408            Type type = typeMapper.mapType(jetType);
409            return !skipDefaultValue(propertyDescriptor, initializerValue.getValue(), type);
410        }
411    
412        @Nullable
413        private ConstantValue<?> computeInitializerValue(
414                @NotNull KtProperty property,
415                @NotNull PropertyDescriptor propertyDescriptor,
416                @Nullable KtExpression initializer
417        ) {
418            if (property.isVar() && initializer != null) {
419                BindingTrace tempTrace = TemporaryBindingTrace.create(state.getBindingTrace(), "property initializer");
420                return constantExpressionEvaluator.evaluateToConstantValue(initializer, tempTrace, propertyDescriptor.getType());
421            }
422            return propertyDescriptor.getCompileTimeInitializer();
423        }
424    
425        @NotNull
426        private KotlinType getPropertyOrDelegateType(@NotNull KtProperty property, @NotNull PropertyDescriptor descriptor) {
427            KtExpression delegateExpression = property.getDelegateExpression();
428            if (delegateExpression != null) {
429                KotlinType delegateType = bindingContext.getType(delegateExpression);
430                assert delegateType != null : "Type of delegate expression should be recorded";
431                return delegateType;
432            }
433            return descriptor.getType();
434        }
435    
436        private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) {
437            if (isPrimitive(type)) {
438                if (!propertyDescriptor.getType().isMarkedNullable() && value instanceof Number) {
439                    if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) {
440                        return true;
441                    }
442                    if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) {
443                        return true;
444                    }
445                    if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) {
446                        return true;
447                    }
448                    if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) {
449                        return true;
450                    }
451                    if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) {
452                        return true;
453                    }
454                    if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) {
455                        return true;
456                    }
457                }
458                if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) {
459                    return true;
460                }
461                if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) {
462                    return true;
463                }
464            }
465            else {
466                if (value == null) {
467                    return true;
468                }
469            }
470            return false;
471        }
472    
473        protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
474            List<KtProperty> delegatedProperties = new ArrayList<KtProperty>();
475            for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
476                if (declaration instanceof KtProperty) {
477                    KtProperty property = (KtProperty) declaration;
478                    if (property.hasDelegate()) {
479                        delegatedProperties.add(property);
480                    }
481                }
482            }
483            if (delegatedProperties.isEmpty()) return;
484    
485            v.newField(NO_ORIGIN, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
486                       "[" + K_PROPERTY_TYPE, null, null);
487    
488            if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
489    
490            InstructionAdapter iv = createOrGetClInitCodegen().v;
491            iv.iconst(delegatedProperties.size());
492            iv.newarray(K_PROPERTY_TYPE);
493    
494            for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
495                PropertyDescriptor property =
496                        (PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
497    
498                iv.dup();
499                iv.iconst(i);
500    
501                StackValue value;
502                // TODO: remove this option and always generate PropertyReferenceNImpl creation
503                if ("true".equalsIgnoreCase(System.getProperty("kotlin.jvm.optimize.delegated.properties"))) {
504                    int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) +
505                                        (property.getExtensionReceiverParameter() != null ? 1 : 0);
506                    Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
507                    iv.anew(implType);
508                    iv.dup();
509                    // TODO: generate the container once and save to a local field instead
510                    ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
511                    iv.aconst(property.getName().asString());
512                    iv.aconst(PropertyReferenceCodegen.getPropertyReferenceSignature(property, state));
513                    iv.invokespecial(
514                            implType.getInternalName(), "<init>",
515                            Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false
516                    );
517                    value = StackValue.onStack(implType);
518                    Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
519                    iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
520                }
521                else {
522                    ReceiverParameterDescriptor dispatchReceiver = property.getDispatchReceiverParameter();
523    
524                    //noinspection ConstantConditions
525                    value = createOrGetClInitCodegen().generatePropertyReference(
526                            delegatedProperties.get(i).getDelegate(), property, property,
527                            dispatchReceiver != null ? new TransientReceiver(dispatchReceiver.getType()) : null
528                    );
529                }
530    
531                value.put(K_PROPERTY_TYPE, iv);
532    
533                iv.astore(K_PROPERTY_TYPE);
534            }
535    
536            iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE);
537        }
538    
539        public String getClassName() {
540            return v.getThisName();
541        }
542    
543        @NotNull
544        public FieldOwnerContext<?> getContext() {
545            return context;
546        }
547    
548        @NotNull
549        public ReifiedTypeParametersUsages getReifiedTypeParametersUsages() {
550            return reifiedTypeParametersUsages;
551        }
552    
553        public MemberCodegen<?> getParentCodegen() {
554            return parentCodegen;
555        }
556    
557        @Override
558        public String toString() {
559            return context.toString();
560        }
561    
562        @NotNull
563        public SourceMapper getOrCreateSourceMapper() {
564            if (sourceMapper == null) {
565                sourceMapper = new DefaultSourceMapper(SourceInfo.Companion.createInfo(element, getClassName()), null);
566            }
567            return sourceMapper;
568        }
569    
570        protected void generateConstInstance(
571                @NotNull Type thisAsmType,
572                @NotNull Type fieldAsmType,
573                @NotNull Function1<InstructionAdapter, Unit> initialization
574        ) {
575            v.newField(JvmDeclarationOriginKt.OtherOrigin(element), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor(),
576                       null, null);
577    
578            if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
579                InstructionAdapter iv = createOrGetClInitCodegen().v;
580                iv.anew(thisAsmType);
581                iv.dup();
582                iv.invokespecial(thisAsmType.getInternalName(), "<init>", "()V", false);
583                initialization.invoke(iv);
584                iv.putstatic(thisAsmType.getInternalName(), JvmAbi.INSTANCE_FIELD, fieldAsmType.getDescriptor());
585            }
586        }
587    
588        protected void generateSyntheticAccessors() {
589            for (AccessorForCallableDescriptor<?> accessor : ((CodegenContext<?>) context).getAccessors()) {
590                generateSyntheticAccessor(accessor);
591            }
592        }
593    
594        private void generateSyntheticAccessor(@NotNull AccessorForCallableDescriptor<?> accessorForCallableDescriptor) {
595            if (accessorForCallableDescriptor instanceof FunctionDescriptor) {
596                final FunctionDescriptor accessor = (FunctionDescriptor) accessorForCallableDescriptor;
597                final FunctionDescriptor original = (FunctionDescriptor) accessorForCallableDescriptor.getCalleeDescriptor();
598                functionCodegen.generateMethod(
599                        Synthetic(null, original), accessor,
600                        new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, accessor) {
601                            @Override
602                            public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
603                                markLineNumberForElement(element, codegen.v);
604    
605                                generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), codegen.v);
606    
607                                codegen.v.areturn(signature.getReturnType());
608                            }
609                        }
610                );
611            }
612            else if (accessorForCallableDescriptor instanceof AccessorForPropertyDescriptor) {
613                final AccessorForPropertyDescriptor accessor = (AccessorForPropertyDescriptor) accessorForCallableDescriptor;
614                final PropertyDescriptor original = accessor.getCalleeDescriptor();
615    
616                class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> {
617                    public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) {
618                        super(MemberCodegen.this.state, callableDescriptor);
619                    }
620    
621                    @Override
622                    public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
623                        boolean syntheticBackingField = accessor instanceof AccessorForPropertyBackingFieldFromLocal;
624                        boolean forceField = (AsmUtil.isPropertyWithBackingFieldInOuterClass(original) &&
625                                              !isCompanionObject(accessor.getContainingDeclaration())) ||
626                                             syntheticBackingField ||
627                                             original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
628                        StackValue property = codegen.intermediateValueForProperty(
629                                original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), true, StackValue.none()
630                        );
631    
632                        InstructionAdapter iv = codegen.v;
633    
634                        markLineNumberForElement(element, iv);
635    
636                        Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
637                        for (int i = 0, reg = 0; i < argTypes.length; i++) {
638                            Type argType = argTypes[i];
639                            iv.load(reg, argType);
640                            //noinspection AssignmentToForLoopParameter
641                            reg += argType.getSize();
642                        }
643    
644                        if (callableDescriptor instanceof PropertyGetterDescriptor) {
645                            property.put(signature.getReturnType(), iv);
646                        }
647                        else {
648                            property.store(StackValue.onStack(property.type), iv, true);
649                        }
650    
651                        iv.areturn(signature.getReturnType());
652                    }
653                }
654    
655                if (accessor.isWithSyntheticGetterAccessor()) {
656                    PropertyGetterDescriptor getter = accessor.getGetter();
657                    assert getter != null;
658                    functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original),
659                                                   getter, new PropertyAccessorStrategy(getter));
660                }
661    
662                if (accessor.isVar() && accessor.isWithSyntheticSetterAccessor()) {
663                    PropertySetterDescriptor setter = accessor.getSetter();
664                    assert setter != null;
665    
666                    functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original),
667                                                   setter, new PropertyAccessorStrategy(setter));
668                }
669            }
670            else {
671                throw new UnsupportedOperationException();
672            }
673        }
674    
675        private StackValue generateMethodCallTo(
676                @NotNull FunctionDescriptor functionDescriptor,
677                @Nullable FunctionDescriptor accessorDescriptor,
678                @NotNull InstructionAdapter iv
679        ) {
680            CallableMethod callableMethod = typeMapper.mapToCallableMethod(
681                    functionDescriptor,
682                    accessorDescriptor instanceof AccessorForCallableDescriptor &&
683                    ((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
684            );
685    
686            boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
687            int reg = hasDispatchReceiver ? 1 : 0;
688            boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
689            if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
690                iv.anew(callableMethod.getOwner());
691                iv.dup();
692                reg = 0;
693            }
694            else if (accessorIsConstructor || (accessorDescriptor != null && JetTypeMapper.isAccessor(accessorDescriptor) && hasDispatchReceiver)) {
695                if (!AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor)) {
696                    iv.load(0, OBJECT_TYPE);
697                }
698            }
699    
700            for (Type argType : callableMethod.getParameterTypes()) {
701                if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) {
702                    iv.aconst(null);
703                }
704                else {
705                    iv.load(reg, argType);
706                    reg += argType.getSize();
707                }
708            }
709    
710            callableMethod.genInvokeInstruction(iv);
711    
712            return StackValue.onStack(callableMethod.getReturnType());
713        }
714    }