001 /*
002 * Copyright 2010-2016 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.codegen;
018
019 import com.intellij.openapi.progress.ProcessCanceledException;
020 import com.intellij.psi.PsiElement;
021 import com.intellij.util.ArrayUtil;
022 import kotlin.Unit;
023 import kotlin.collections.CollectionsKt;
024 import kotlin.jvm.functions.Function0;
025 import kotlin.jvm.functions.Function1;
026 import kotlin.jvm.functions.Function2;
027 import org.jetbrains.annotations.NotNull;
028 import org.jetbrains.annotations.Nullable;
029 import org.jetbrains.kotlin.backend.common.CodegenUtil;
030 import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator;
031 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
032 import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
033 import org.jetbrains.kotlin.codegen.binding.MutableClosure;
034 import org.jetbrains.kotlin.codegen.context.*;
035 import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension;
036 import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
037 import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter;
038 import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
039 import org.jetbrains.kotlin.codegen.state.GenerationState;
040 import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
041 import org.jetbrains.kotlin.descriptors.*;
042 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
043 import org.jetbrains.kotlin.lexer.KtTokens;
044 import org.jetbrains.kotlin.load.java.JvmAbi;
045 import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
046 import org.jetbrains.kotlin.name.FqName;
047 import org.jetbrains.kotlin.name.Name;
048 import org.jetbrains.kotlin.psi.*;
049 import org.jetbrains.kotlin.resolve.BindingContext;
050 import org.jetbrains.kotlin.resolve.DelegationResolver;
051 import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
052 import org.jetbrains.kotlin.resolve.DescriptorUtils;
053 import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
054 import org.jetbrains.kotlin.resolve.calls.model.*;
055 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
056 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
057 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
058 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
059 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
060 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
061 import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
062 import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
063 import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
064 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
065 import org.jetbrains.kotlin.types.KotlinType;
066 import org.jetbrains.org.objectweb.asm.FieldVisitor;
067 import org.jetbrains.org.objectweb.asm.Label;
068 import org.jetbrains.org.objectweb.asm.MethodVisitor;
069 import org.jetbrains.org.objectweb.asm.Type;
070 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
071 import org.jetbrains.org.objectweb.asm.commons.Method;
072
073 import java.util.*;
074
075 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES;
076 import static org.jetbrains.kotlin.codegen.AsmUtil.*;
077 import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isGenericToArray;
078 import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray;
079 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*;
080 import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
081 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall;
082 import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull;
083 import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration;
084 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
085 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE;
086 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
087 import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
088 import static org.jetbrains.kotlin.types.Variance.INVARIANT;
089 import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isLocalFunction;
090 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
091
092 public class ImplementationBodyCodegen extends ClassBodyCodegen {
093 private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
094 private Type superClassAsmType;
095 @NotNull
096 private SuperClassInfo superClassInfo;
097 private final Type classAsmType;
098 private final boolean isLocal;
099
100 private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy;
101
102 private final DelegationFieldsInfo delegationFieldsInfo;
103
104 private final List<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>> additionalTasks =
105 new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>();
106
107 public ImplementationBodyCodegen(
108 @NotNull KtPureClassOrObject aClass,
109 @NotNull ClassContext context,
110 @NotNull ClassBuilder v,
111 @NotNull GenerationState state,
112 @Nullable MemberCodegen<?> parentCodegen,
113 boolean isLocal
114 ) {
115 super(aClass, context, v, state, parentCodegen);
116 this.classAsmType = typeMapper.mapClass(descriptor);
117 this.isLocal = isLocal;
118 delegationFieldsInfo = getDelegationFieldsInfo(myClass.getSuperTypeListEntries());
119 }
120
121 @Override
122 protected void generateDeclaration() {
123 getSuperClass();
124
125 JvmClassSignature signature = signature();
126
127 boolean isAbstract = false;
128 boolean isInterface = false;
129 boolean isFinal = false;
130 boolean isStatic;
131 boolean isAnnotation = false;
132 boolean isEnum = false;
133
134 ClassKind kind = descriptor.getKind();
135
136 if (kind == ClassKind.OBJECT) {
137 isStatic = isCompanionObject(descriptor);
138 isFinal = true;
139 }
140 else {
141 Modality modality = descriptor.getModality();
142
143 if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
144 isAbstract = true;
145 }
146
147 if (kind == ClassKind.INTERFACE) {
148 isAbstract = true;
149 isInterface = true;
150 }
151 else if (kind == ClassKind.ANNOTATION_CLASS) {
152 isAbstract = true;
153 isInterface = true;
154 isAnnotation = true;
155 }
156 else if (kind == ClassKind.ENUM_CLASS) {
157 isAbstract = hasAbstractMembers(descriptor);
158 isEnum = true;
159 }
160
161 if (modality != Modality.OPEN && !isAbstract) {
162 // Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
163 isFinal = !(kind == ClassKind.ENUM_CLASS && !state.getClassBuilderMode().generateBodies);
164 }
165
166 isStatic = !descriptor.isInner();
167 }
168
169 int access = 0;
170
171 if (!state.getClassBuilderMode().generateBodies && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
172 // !ClassBuilderMode.generateBodies means we are generating light classes & looking at a nested or inner class
173 // Light class generation is implemented so that Cls-classes only read bare code of classes,
174 // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY)
175 // Thus we must write full accessibility flags on inner classes in this mode
176 access |= getVisibilityAccessFlag(descriptor);
177 // Same for STATIC
178 if (isStatic) {
179 access |= ACC_STATIC;
180 }
181 }
182 else {
183 access |= getVisibilityAccessFlagForClass(descriptor);
184 }
185 if (isAbstract) {
186 access |= ACC_ABSTRACT;
187 }
188 if (isInterface) {
189 access |= ACC_INTERFACE; // ACC_SUPER
190 }
191 else {
192 access |= ACC_SUPER;
193 }
194 if (isFinal) {
195 access |= ACC_FINAL;
196 }
197 if (isAnnotation) {
198 access |= ACC_ANNOTATION;
199 }
200 if (KotlinBuiltIns.isDeprecated(descriptor)) {
201 access |= ACC_DEPRECATED;
202 }
203 if (isEnum) {
204 for (KtDeclaration declaration : myClass.getDeclarations()) {
205 if (declaration instanceof KtEnumEntry) {
206 if (enumEntryNeedSubclass(bindingContext, (KtEnumEntry) declaration)) {
207 access &= ~ACC_FINAL;
208 }
209 }
210 }
211 access |= ACC_ENUM;
212 }
213
214 v.defineClass(
215 myClass.getPsiOrParent(),
216 state.getClassFileVersion(),
217 access,
218 signature.getName(),
219 signature.getJavaGenericSignature(),
220 signature.getSuperclassName(),
221 ArrayUtil.toStringArray(signature.getInterfaces())
222 );
223
224 v.visitSource(myClass.getContainingKtFile().getName(), null);
225
226 InlineCodegenUtil.initDefaultSourceMappingIfNeeded(context, this, state);
227
228 writeEnclosingMethod();
229
230 AnnotationCodegen.forClass(v.getVisitor(), this, typeMapper).genAnnotations(descriptor, null);
231
232 generateEnumEntries();
233 }
234
235 @Override
236 protected void generateDefaultImplsIfNeeded() {
237 if (isInterface(descriptor) && !isLocal && (!JvmCodegenUtil.isJvm8InterfaceWithDefaults(descriptor, state) || state.getGenerateDefaultImplsForJvm8())) {
238 Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
239 ClassBuilder defaultImplsBuilder =
240 state.getFactory().newVisitor(JvmDeclarationOriginKt.DefaultImpls(myClass.getPsiOrParent(), descriptor), defaultImplsType, myClass.getContainingKtFile());
241
242 CodegenContext parentContext = context.getParentContext();
243 assert parentContext != null : "Parent context of interface declaration should not be null";
244
245 ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
246 new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
247 }
248 }
249
250 @Override
251 protected void generateKotlinMetadataAnnotation() {
252 generateKotlinClassMetadataAnnotation(descriptor, false);
253 }
254
255 private void writeEnclosingMethod() {
256 // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level
257 if (!state.getClassBuilderMode().generateBodies) {
258 return;
259 }
260
261 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
262 if (isAnonymousObject(descriptor) || !(descriptor.getContainingDeclaration() instanceof ClassOrPackageFragmentDescriptor)) {
263 writeOuterClassAndEnclosingMethod();
264 }
265 }
266
267 private static final Map<FqName, String> KOTLIN_MARKER_INTERFACES = new HashMap<FqName, String>();
268 static {
269 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterator, "kotlin/jvm/internal/markers/KMappedMarker");
270 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.iterable, "kotlin/jvm/internal/markers/KMappedMarker");
271 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.collection, "kotlin/jvm/internal/markers/KMappedMarker");
272 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.list, "kotlin/jvm/internal/markers/KMappedMarker");
273 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.listIterator, "kotlin/jvm/internal/markers/KMappedMarker");
274 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.set, "kotlin/jvm/internal/markers/KMappedMarker");
275 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.map, "kotlin/jvm/internal/markers/KMappedMarker");
276 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mapEntry, "kotlin/jvm/internal/markers/KMappedMarker");
277
278 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterator, "kotlin/jvm/internal/markers/KMutableIterator");
279 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableIterable, "kotlin/jvm/internal/markers/KMutableIterable");
280 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableCollection, "kotlin/jvm/internal/markers/KMutableCollection");
281 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableList, "kotlin/jvm/internal/markers/KMutableList");
282 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableListIterator, "kotlin/jvm/internal/markers/KMutableListIterator");
283 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableSet, "kotlin/jvm/internal/markers/KMutableSet");
284 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMap, "kotlin/jvm/internal/markers/KMutableMap");
285 KOTLIN_MARKER_INTERFACES.put(FQ_NAMES.mutableMapEntry, "kotlin/jvm/internal/markers/KMutableMap$Entry");
286 }
287
288 @NotNull
289 private JvmClassSignature signature() {
290 return signature(descriptor, classAsmType, superClassInfo, typeMapper);
291 }
292
293 @NotNull
294 public static JvmClassSignature signature(
295 @NotNull ClassDescriptor descriptor,
296 @NotNull Type classAsmType,
297 @NotNull SuperClassInfo superClassInfo,
298 @NotNull KotlinTypeMapper typeMapper
299 ) {
300 JvmSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
301
302 typeMapper.writeFormalTypeParameters(descriptor.getDeclaredTypeParameters(), sw);
303
304 sw.writeSuperclass();
305 if (superClassInfo.getKotlinType() == null) {
306 sw.writeClassBegin(superClassInfo.getType());
307 sw.writeClassEnd();
308 }
309 else {
310 typeMapper.mapSupertype(superClassInfo.getKotlinType(), sw);
311 }
312 sw.writeSuperclassEnd();
313
314 LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>();
315 Set<String> kotlinMarkerInterfaces = new LinkedHashSet<String>();
316
317 for (KotlinType supertype : descriptor.getTypeConstructor().getSupertypes()) {
318 if (isJvmInterface(supertype.getConstructor().getDeclarationDescriptor())) {
319 sw.writeInterface();
320 Type jvmInterfaceType = typeMapper.mapSupertype(supertype, sw);
321 sw.writeInterfaceEnd();
322 String jvmInterfaceInternalName = jvmInterfaceType.getInternalName();
323 superInterfaces.add(jvmInterfaceInternalName);
324
325 FqName kotlinInterfaceName = DescriptorUtils.getFqName(supertype.getConstructor().getDeclarationDescriptor()).toSafe();
326 String kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName);
327 if (kotlinMarkerInterfaceInternalName != null) {
328 kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName);
329 }
330 }
331 }
332
333 for (String kotlinMarkerInterface : kotlinMarkerInterfaces) {
334 sw.writeInterface();
335 sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface));
336 sw.writeInterfaceEnd();
337 }
338
339 superInterfaces.addAll(kotlinMarkerInterfaces);
340
341 return new JvmClassSignature(classAsmType.getInternalName(), superClassInfo.getType().getInternalName(),
342 new ArrayList<String>(superInterfaces), sw.makeJavaGenericSignature());
343 }
344
345 private void getSuperClass() {
346 superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper);
347 superClassAsmType = superClassInfo.getType();
348 }
349
350 @Override
351 protected void generateSyntheticParts() {
352 generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
353
354 generateFieldForSingleton();
355
356 generateCompanionObjectBackingFieldCopies();
357
358 generateTraitMethods();
359
360 generateDelegates(delegationFieldsInfo);
361
362 if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
363 generateSyntheticAccessors();
364 }
365
366 generateEnumMethods();
367
368 generateFunctionsForDataClasses();
369
370 new CollectionStubMethodGenerator(typeMapper, descriptor).generate(functionCodegen, v);
371
372 generateToArray();
373
374 if (context.closure != null)
375 genClosureFields(context.closure, v, typeMapper);
376
377 for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
378 extension.generateClassSyntheticParts(this);
379 }
380 }
381
382 @Override
383 protected void generateConstructors() {
384 try {
385 lookupConstructorExpressionsInClosureIfPresent();
386 generatePrimaryConstructor(delegationFieldsInfo);
387 for (ClassConstructorDescriptor secondaryConstructor : DescriptorUtilsKt.getSecondaryConstructors(descriptor)) {
388 generateSecondaryConstructor(secondaryConstructor);
389 }
390 }
391 catch (CompilationException e) {
392 throw e;
393 }
394 catch (ProcessCanceledException e) {
395 throw e;
396 }
397 catch (RuntimeException e) {
398 throw new RuntimeException("Error generating constructors of class " + myClass.getName() + " with kind " + kind, e);
399 }
400 }
401
402 private void generateToArray() {
403 if (descriptor.getKind() == ClassKind.INTERFACE) return;
404
405 final KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
406 if (!isSubclass(descriptor, builtIns.getCollection())) return;
407
408 if (CollectionsKt.any(DescriptorUtilsKt.getAllSuperclassesWithoutAny(descriptor), new Function1<ClassDescriptor, Boolean>() {
409 @Override
410 public Boolean invoke(ClassDescriptor classDescriptor) {
411 return !(classDescriptor instanceof JavaClassDescriptor) && isSubclass(classDescriptor, builtIns.getCollection());
412 }
413 })) return;
414
415 Collection<SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(
416 Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND
417 );
418 boolean hasGenericToArray = false;
419 boolean hasNonGenericToArray = false;
420 for (FunctionDescriptor function : functions) {
421 hasGenericToArray |= isGenericToArray(function);
422 hasNonGenericToArray |= isNonGenericToArray(function);
423 }
424
425 if (!hasNonGenericToArray) {
426 MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null);
427
428 InstructionAdapter iv = new InstructionAdapter(mv);
429 mv.visitCode();
430
431 iv.load(0, classAsmType);
432 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false);
433 iv.areturn(Type.getType("[Ljava/lang/Object;"));
434
435 FunctionCodegen.endVisit(mv, "toArray", myClass);
436 }
437
438 if (!hasGenericToArray) {
439 MethodVisitor mv = v.newMethod(
440 NO_ORIGIN, ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", "<T:Ljava/lang/Object;>([TT;)[TT;", null);
441
442 InstructionAdapter iv = new InstructionAdapter(mv);
443 mv.visitCode();
444
445 iv.load(0, classAsmType);
446 iv.load(1, Type.getType("[Ljava/lang/Object;"));
447
448 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray",
449 "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false);
450 iv.areturn(Type.getType("[Ljava/lang/Object;"));
451
452 FunctionCodegen.endVisit(mv, "toArray", myClass);
453 }
454 }
455
456 public Type genPropertyOnStack(
457 InstructionAdapter iv,
458 MethodContext context,
459 @NotNull PropertyDescriptor propertyDescriptor,
460 Type classAsmType,
461 int index
462 ) {
463 iv.load(index, classAsmType);
464 if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true,
465 /* isDelegated = */ false, context, state.getShouldInlineConstVals())) {
466 Type type = typeMapper.mapType(propertyDescriptor.getType());
467 String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false);
468 iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor());
469 return type;
470 }
471 else {
472 //noinspection ConstantConditions
473 Method method = typeMapper.mapAsmMethod(propertyDescriptor.getGetter());
474 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor(), false);
475 return method.getReturnType();
476 }
477 }
478
479 private void generateFunctionsForDataClasses() {
480 if (!descriptor.isData()) return;
481 if (!(myClass instanceof KtClassOrObject)) return;
482 new DataClassMethodGeneratorImpl((KtClassOrObject)myClass, bindingContext).generate();
483 }
484
485 private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator {
486 DataClassMethodGeneratorImpl(
487 KtClassOrObject klass,
488 BindingContext bindingContext
489 ) {
490 super(klass, bindingContext);
491 }
492
493 @Override
494 public void generateEqualsMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
495 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
496 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
497 InstructionAdapter iv = new InstructionAdapter(mv);
498
499 mv.visitCode();
500 Label eq = new Label();
501 Label ne = new Label();
502
503 iv.load(0, OBJECT_TYPE);
504 iv.load(1, OBJECT_TYPE);
505 iv.ifacmpeq(eq);
506
507 iv.load(1, OBJECT_TYPE);
508 iv.instanceOf(classAsmType);
509 iv.ifeq(ne);
510
511 iv.load(1, OBJECT_TYPE);
512 iv.checkcast(classAsmType);
513 iv.store(2, OBJECT_TYPE);
514
515 for (PropertyDescriptor propertyDescriptor : properties) {
516 Type asmType = typeMapper.mapType(propertyDescriptor);
517
518 Type thisPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
519 StackValue.coerce(thisPropertyType, asmType, iv);
520
521 Type otherPropertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 2);
522 StackValue.coerce(otherPropertyType, asmType, iv);
523
524 if (asmType.getSort() == Type.FLOAT) {
525 iv.invokestatic("java/lang/Float", "compare", "(FF)I", false);
526 iv.ifne(ne);
527 }
528 else if (asmType.getSort() == Type.DOUBLE) {
529 iv.invokestatic("java/lang/Double", "compare", "(DD)I", false);
530 iv.ifne(ne);
531 }
532 else {
533 StackValue value = genEqualsForExpressionsOnStack(KtTokens.EQEQ, StackValue.onStack(asmType), StackValue.onStack(asmType));
534 value.put(Type.BOOLEAN_TYPE, iv);
535 iv.ifeq(ne);
536 }
537 }
538
539 iv.mark(eq);
540 iv.iconst(1);
541 iv.areturn(Type.INT_TYPE);
542
543 iv.mark(ne);
544 iv.iconst(0);
545 iv.areturn(Type.INT_TYPE);
546
547 FunctionCodegen.endVisit(mv, "equals", myClass);
548 }
549
550 @Override
551 public void generateHashCodeMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
552 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
553 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "hashCode", "()I", null, null);
554 InstructionAdapter iv = new InstructionAdapter(mv);
555
556 mv.visitCode();
557 boolean first = true;
558 for (PropertyDescriptor propertyDescriptor : properties) {
559 if (!first) {
560 iv.iconst(31);
561 iv.mul(Type.INT_TYPE);
562 }
563
564 Type propertyType = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
565 Type asmType = typeMapper.mapType(propertyDescriptor);
566 StackValue.coerce(propertyType, asmType, iv);
567
568 Label ifNull = null;
569 if (!isPrimitive(asmType)) {
570 ifNull = new Label();
571 iv.dup();
572 iv.ifnull(ifNull);
573 }
574
575 genHashCode(mv, iv, asmType);
576
577 if (ifNull != null) {
578 Label end = new Label();
579 iv.goTo(end);
580 iv.mark(ifNull);
581 iv.pop();
582 iv.iconst(0);
583 iv.mark(end);
584 }
585
586 if (first) {
587 first = false;
588 }
589 else {
590 iv.add(Type.INT_TYPE);
591 }
592 }
593
594 mv.visitInsn(IRETURN);
595
596 FunctionCodegen.endVisit(mv, "hashCode", myClass);
597 }
598
599 @Override
600 public void generateToStringMethod(@NotNull FunctionDescriptor function, @NotNull List<? extends PropertyDescriptor> properties) {
601 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(function);
602 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(function), ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
603 InstructionAdapter iv = new InstructionAdapter(mv);
604
605 mv.visitCode();
606 genStringBuilderConstructor(iv);
607
608 boolean first = true;
609 for (PropertyDescriptor propertyDescriptor : properties) {
610 if (first) {
611 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"=");
612 first = false;
613 }
614 else {
615 iv.aconst(", " + propertyDescriptor.getName().asString() + "=");
616 }
617 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
618
619 Type type = genPropertyOnStack(iv, context, propertyDescriptor, ImplementationBodyCodegen.this.classAsmType, 0);
620
621 if (type.getSort() == Type.ARRAY) {
622 Type elementType = correctElementType(type);
623 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
624 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false);
625 type = JAVA_STRING_TYPE;
626 }
627 else {
628 if (elementType.getSort() != Type.CHAR) {
629 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;", false);
630 type = JAVA_STRING_TYPE;
631 }
632 }
633 }
634 genInvokeAppendMethod(iv, type);
635 }
636
637 iv.aconst(")");
638 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
639
640 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
641 iv.areturn(JAVA_STRING_TYPE);
642
643 FunctionCodegen.endVisit(mv, "toString", myClass);
644 }
645
646 @Override
647 public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
648 PsiElement originalElement = DescriptorToSourceUtils.descriptorToDeclaration(parameter);
649 functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(originalElement, function), function, new FunctionGenerationStrategy() {
650 @Override
651 public void generateBody(
652 @NotNull MethodVisitor mv,
653 @NotNull FrameMap frameMap,
654 @NotNull JvmMethodSignature signature,
655 @NotNull MethodContext context,
656 @NotNull MemberCodegen<?> parentCodegen
657 ) {
658 Type componentType = signature.getReturnType();
659 InstructionAdapter iv = new InstructionAdapter(mv);
660 if (!componentType.equals(Type.VOID_TYPE)) {
661 PropertyDescriptor property =
662 bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, descriptorToDeclaration(parameter));
663 assert property != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
664
665 Type propertyType = genPropertyOnStack(iv, context, property, ImplementationBodyCodegen.this.classAsmType, 0);
666 StackValue.coerce(propertyType, componentType, iv);
667 }
668 iv.areturn(componentType);
669 }
670 });
671 }
672
673 @Override
674 public void generateCopyFunction(
675 @NotNull final FunctionDescriptor function,
676 @NotNull List<? extends KtParameter> constructorParameters
677 ) {
678 final Type thisDescriptorType = typeMapper.mapType(descriptor);
679
680 functionCodegen.generateMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, function), function, new FunctionGenerationStrategy() {
681 @Override
682 public void generateBody(
683 @NotNull MethodVisitor mv,
684 @NotNull FrameMap frameMap,
685 @NotNull JvmMethodSignature signature,
686 @NotNull MethodContext context,
687 @NotNull MemberCodegen<?> parentCodegen
688 ) {
689 InstructionAdapter iv = new InstructionAdapter(mv);
690
691 iv.anew(thisDescriptorType);
692 iv.dup();
693
694 ConstructorDescriptor constructor = getPrimaryConstructorOfDataClass(descriptor);
695 assert function.getValueParameters().size() == constructor.getValueParameters().size() :
696 "Number of parameters of copy function and constructor are different. " +
697 "Copy: " + function.getValueParameters().size() + ", " +
698 "constructor: " + constructor.getValueParameters().size();
699
700 MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
701 if (closure != null) {
702 pushCapturedFieldsOnStack(iv, closure);
703 }
704
705 int parameterIndex = 1; // localVariable 0 = this
706 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
707 Type type = typeMapper.mapType(parameterDescriptor.getType());
708 iv.load(parameterIndex, type);
709 parameterIndex += type.getSize();
710 }
711
712 Method constructorAsmMethod = typeMapper.mapAsmMethod(constructor);
713 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorAsmMethod.getDescriptor(), false);
714
715 iv.areturn(thisDescriptorType);
716 }
717
718 private void pushCapturedFieldsOnStack(InstructionAdapter iv, MutableClosure closure) {
719 ClassDescriptor captureThis = closure.getCaptureThis();
720 if (captureThis != null) {
721 iv.load(0, classAsmType);
722 Type type = typeMapper.mapType(captureThis);
723 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
724 }
725
726 KotlinType captureReceiver = closure.getCaptureReceiverType();
727 if (captureReceiver != null) {
728 iv.load(0, classAsmType);
729 Type type = typeMapper.mapType(captureReceiver);
730 iv.getfield(classAsmType.getInternalName(), CAPTURED_RECEIVER_FIELD, type.getDescriptor());
731 }
732
733 for (Map.Entry<DeclarationDescriptor, EnclosedValueDescriptor> entry : closure.getCaptureVariables().entrySet()) {
734 DeclarationDescriptor declarationDescriptor = entry.getKey();
735 EnclosedValueDescriptor enclosedValueDescriptor = entry.getValue();
736 StackValue capturedValue = enclosedValueDescriptor.getInstanceValue();
737 Type sharedVarType = typeMapper.getSharedVarType(declarationDescriptor);
738 if (sharedVarType == null) {
739 sharedVarType = typeMapper.mapType((VariableDescriptor) declarationDescriptor);
740 }
741 capturedValue.put(sharedVarType, iv);
742 }
743 }
744 });
745
746 functionCodegen.generateDefaultIfNeeded(
747 context.intoFunction(function), function, OwnerKind.IMPLEMENTATION,
748 new DefaultParameterValueLoader() {
749 @Override
750 public StackValue genValue(ValueParameterDescriptor valueParameter, ExpressionCodegen codegen) {
751 assert ((ClassDescriptor) function.getContainingDeclaration()).isData()
752 : "Function container must have [data] modifier: " + function;
753 PropertyDescriptor property = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter);
754 assert property != null : "Copy function doesn't correspond to any property: " + function;
755 return codegen.intermediateValueForProperty(property, false, null, StackValue.LOCAL_0);
756 }
757 },
758 null
759 );
760 }
761 }
762
763 @NotNull
764 private static ConstructorDescriptor getPrimaryConstructorOfDataClass(@NotNull ClassDescriptor classDescriptor) {
765 ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
766 assert constructor != null : "Data class must have primary constructor: " + classDescriptor;
767 return constructor;
768 }
769
770 private void generateEnumMethods() {
771 if (isEnumClass(descriptor)) {
772 generateEnumValuesMethod();
773 generateEnumValueOfMethod();
774 }
775 }
776
777 private void generateEnumValuesMethod() {
778 Type type = typeMapper.mapType(DescriptorUtilsKt.getBuiltIns(descriptor).getArrayType(INVARIANT, descriptor.getDefaultType()));
779
780 FunctionDescriptor valuesFunction =
781 CollectionsKt.single(descriptor.getStaticScope().getContributedFunctions(ENUM_VALUES, NoLookupLocation.FROM_BACKEND));
782 MethodVisitor mv = v.newMethod(
783 JvmDeclarationOriginKt.OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
784 "()" + type.getDescriptor(), null, null
785 );
786 if (!state.getClassBuilderMode().generateBodies) return;
787
788 mv.visitCode();
789 mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, type.getDescriptor());
790 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false);
791 mv.visitTypeInsn(CHECKCAST, type.getInternalName());
792 mv.visitInsn(ARETURN);
793 FunctionCodegen.endVisit(mv, "values()", myClass);
794 }
795
796 private void generateEnumValueOfMethod() {
797 FunctionDescriptor valueOfFunction =
798 CollectionsKt.single(descriptor.getStaticScope().getContributedFunctions(ENUM_VALUE_OF, NoLookupLocation.FROM_BACKEND), new Function1<FunctionDescriptor, Boolean>() {
799 @Override
800 public Boolean invoke(FunctionDescriptor descriptor) {
801 return DescriptorUtilsKt.isEnumValueOfMethod(descriptor);
802 }
803 });
804 MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(),
805 "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
806 if (!state.getClassBuilderMode().generateBodies) return;
807
808 mv.visitCode();
809 mv.visitLdcInsn(classAsmType);
810 mv.visitVarInsn(ALOAD, 0);
811 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
812 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName());
813 mv.visitInsn(ARETURN);
814 FunctionCodegen.endVisit(mv, "valueOf()", myClass);
815 }
816
817 private void generateFieldForSingleton() {
818 if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return;
819
820 if (isNonCompanionObject(descriptor)) {
821 StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
822 v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass),
823 ACC_PUBLIC | ACC_STATIC | ACC_FINAL,
824 field.name, field.type.getDescriptor(), null, null);
825
826 if (!state.getClassBuilderMode().generateBodies) return;
827 // Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
828 InstructionAdapter v = createOrGetClInitCodegen().v;
829 markLineNumberForElement(element.getPsiOrParent(), v);
830 v.anew(classAsmType);
831 v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
832
833 return;
834 }
835
836 ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
837 if (companionObjectDescriptor == null) {
838 return;
839 }
840
841 @Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects());
842
843 StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
844 v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject),
845 ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
846 }
847
848 private void generateCompanionObjectBackingFieldCopies() {
849 if (companionObjectPropertiesToCopy == null) return;
850
851 for (PropertyAndDefaultValue info : companionObjectPropertiesToCopy) {
852 PropertyDescriptor property = info.descriptor;
853
854 Type type = typeMapper.mapType(property);
855 int modifiers = ACC_STATIC | ACC_FINAL | ACC_PUBLIC;
856 FieldVisitor fv = v.newField(JvmDeclarationOriginKt.Synthetic(DescriptorToSourceUtils.descriptorToDeclaration(property), property),
857 modifiers, context.getFieldName(property, false),
858 type.getDescriptor(), typeMapper.mapFieldSignature(property.getType(), property),
859 info.defaultValue);
860
861 AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(property, type);
862
863 //This field are always static and final so if it has constant initializer don't do anything in clinit,
864 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
865 // TODO: test this code
866 if (state.getClassBuilderMode().generateBodies && info.defaultValue == null) {
867 ExpressionCodegen codegen = createOrGetClInitCodegen();
868 int companionObjectIndex = putCompanionObjectInLocalVar(codegen);
869 StackValue.local(companionObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
870 copyFieldFromCompanionObject(property);
871 }
872 }
873 }
874
875 private int putCompanionObjectInLocalVar(ExpressionCodegen codegen) {
876 FrameMap frameMap = codegen.myFrameMap;
877 ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
878 int companionObjectIndex = frameMap.getIndex(companionObjectDescriptor);
879 if (companionObjectIndex == -1) {
880 companionObjectIndex = frameMap.enter(companionObjectDescriptor, OBJECT_TYPE);
881 StackValue companionObject = StackValue.singleton(companionObjectDescriptor, typeMapper);
882 StackValue.local(companionObjectIndex, companionObject.type).store(companionObject, codegen.v);
883 }
884 return companionObjectIndex;
885 }
886
887 private void copyFieldFromCompanionObject(PropertyDescriptor propertyDescriptor) {
888 ExpressionCodegen codegen = createOrGetClInitCodegen();
889 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null, StackValue.none());
890 StackValue.Field field = StackValue
891 .field(property.type, classAsmType, propertyDescriptor.getName().asString(), true, StackValue.none(), propertyDescriptor);
892 field.store(property, codegen.v);
893 }
894
895 private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
896 ExpressionCodegen codegen = createOrGetClInitCodegen();
897
898 FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor(
899 CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null
900 );
901 generateMethodCallTo(constructor, null, codegen.v);
902 StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
903 StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true);
904 }
905
906 private void generatePrimaryConstructor(final DelegationFieldsInfo delegationFieldsInfo) {
907 if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
908
909 final ClassConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
910 if (constructorDescriptor == null) return;
911
912 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
913
914 final KtPrimaryConstructor primaryConstructor = myClass.getPrimaryConstructor();
915 JvmDeclarationOrigin origin = JvmDeclarationOriginKt
916 .OtherOrigin(primaryConstructor != null ? primaryConstructor : myClass.getPsiOrParent(), constructorDescriptor);
917 functionCodegen.generateMethod(origin, constructorDescriptor, constructorContext,
918 new FunctionGenerationStrategy.CodegenBased(state) {
919 @Override
920 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
921 generatePrimaryConstructorImpl(constructorDescriptor, codegen, delegationFieldsInfo, primaryConstructor);
922 }
923 }
924 );
925
926 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
927 DefaultParameterValueLoader.DEFAULT, null);
928
929 new DefaultParameterValueSubstitutor(state).generatePrimaryConstructorOverloadsIfNeeded(constructorDescriptor, v, this, kind, myClass);
930 }
931
932 private void generateSecondaryConstructor(@NotNull final ClassConstructorDescriptor constructorDescriptor) {
933 if (!canHaveDeclaredConstructors(descriptor)) return;
934
935 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
936
937 KtSecondaryConstructor constructor = (KtSecondaryConstructor) descriptorToDeclaration(constructorDescriptor);
938
939 functionCodegen.generateMethod(
940 JvmDeclarationOriginKt.OtherOrigin(constructor, constructorDescriptor),
941 constructorDescriptor, constructorContext,
942 new FunctionGenerationStrategy.CodegenBased(state) {
943 @Override
944 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
945 generateSecondaryConstructorImpl(constructorDescriptor, codegen);
946 }
947 }
948 );
949
950 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorDescriptor, OwnerKind.IMPLEMENTATION,
951 DefaultParameterValueLoader.DEFAULT, null);
952
953 new DefaultParameterValueSubstitutor(state).generateOverloadsIfNeeded(
954 constructor, constructorDescriptor, constructorDescriptor, kind, v, this
955 );
956 }
957
958 private void generatePrimaryConstructorImpl(
959 @NotNull ClassConstructorDescriptor constructorDescriptor,
960 @NotNull ExpressionCodegen codegen,
961 @NotNull DelegationFieldsInfo fieldsInfo,
962 @Nullable KtPrimaryConstructor primaryConstructor
963 ) {
964 InstructionAdapter iv = codegen.v;
965
966 markLineNumberForConstructor(constructorDescriptor, primaryConstructor, codegen);
967
968 generateClosureInitialization(iv);
969
970 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor,
971 getDelegationConstructorCall(bindingContext, constructorDescriptor));
972
973 if (isNonCompanionObject(descriptor)) {
974 StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv);
975 }
976
977 for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
978 if (specifier instanceof KtDelegatedSuperTypeEntry) {
979 genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo);
980 }
981 }
982
983 int curParam = 0;
984 List<ValueParameterDescriptor> parameters = constructorDescriptor.getValueParameters();
985 for (KtParameter parameter : getPrimaryConstructorParameters()) {
986 if (parameter.hasValOrVar()) {
987 VariableDescriptor descriptor = parameters.get(curParam);
988 Type type = typeMapper.mapType(descriptor);
989 iv.load(0, classAsmType);
990 iv.load(codegen.myFrameMap.getIndex(descriptor), type);
991 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
992 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
993 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor, false), type.getDescriptor());
994 }
995 curParam++;
996 }
997
998 if (isCompanionObject(descriptor)) {
999 ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
1000 parentCodegen.generateCompanionObjectInitializer(descriptor);
1001 }
1002
1003 if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) {
1004 final ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen();
1005 generateInitializers(new Function0<ExpressionCodegen>() {
1006 @Override
1007 public ExpressionCodegen invoke() {
1008 return parentCodegen.createOrGetClInitCodegen();
1009 }
1010 });
1011 }
1012 else {
1013 generateInitializers(codegen);
1014 }
1015
1016 iv.visitInsn(RETURN);
1017 }
1018
1019 private void generateSecondaryConstructorImpl(
1020 @NotNull ClassConstructorDescriptor constructorDescriptor,
1021 @NotNull ExpressionCodegen codegen
1022 ) {
1023 InstructionAdapter iv = codegen.v;
1024
1025 KtSecondaryConstructor constructor =
1026 (KtSecondaryConstructor) DescriptorToSourceUtils.descriptorToDeclaration(constructorDescriptor);
1027
1028 markLineNumberForConstructor(constructorDescriptor, constructor, codegen);
1029
1030 ResolvedCall<ConstructorDescriptor> constructorDelegationCall =
1031 getDelegationConstructorCall(bindingContext, constructorDescriptor);
1032 ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null :
1033 constructorDelegationCall.getResultingDescriptor();
1034
1035 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, constructorDelegationCall);
1036 if (!isSameClassConstructor(delegateConstructor)) {
1037 // Initialization happens only for constructors delegating to super
1038 generateClosureInitialization(iv);
1039 generateInitializers(codegen);
1040 }
1041
1042 assert constructor != null;
1043 if (constructor.hasBody()) {
1044 codegen.gen(constructor.getBodyExpression(), Type.VOID_TYPE);
1045 }
1046
1047 iv.visitInsn(RETURN);
1048 }
1049
1050 private static void markLineNumberForConstructor(
1051 @NotNull ClassConstructorDescriptor descriptor,
1052 @Nullable KtConstructor constructor,
1053 @NotNull ExpressionCodegen codegen
1054 ) {
1055 if (constructor == null) {
1056 markLineNumberForDescriptor(descriptor.getContainingDeclaration(), codegen.v);
1057 }
1058 else if (constructor.hasBody() && !(constructor instanceof KtSecondaryConstructor && !((KtSecondaryConstructor) constructor).hasImplicitDelegationCall())) {
1059 KtBlockExpression bodyExpression = constructor.getBodyExpression();
1060 List<KtExpression> statements = bodyExpression != null ? bodyExpression.getStatements() : Collections.<KtExpression>emptyList();
1061 if (!statements.isEmpty()) {
1062 codegen.markStartLineNumber(statements.iterator().next());
1063 }
1064 else {
1065 codegen.markStartLineNumber(bodyExpression != null ? bodyExpression : constructor);
1066 }
1067 }
1068 else {
1069 codegen.markStartLineNumber(constructor);
1070 }
1071 }
1072
1073 private void generateInitializers(@NotNull final ExpressionCodegen codegen) {
1074 generateInitializers(new Function0<ExpressionCodegen>() {
1075 @Override
1076 public ExpressionCodegen invoke() {
1077 return codegen;
1078 }
1079 });
1080 }
1081
1082 private void generateClosureInitialization(@NotNull InstructionAdapter iv) {
1083 MutableClosure closure = context.closure;
1084 if (closure != null) {
1085 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
1086 int k = 1;
1087 for (FieldInfo info : argsFromClosure) {
1088 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
1089 }
1090 }
1091 }
1092
1093 private void genSimpleSuperCall(InstructionAdapter iv) {
1094 iv.load(0, superClassAsmType);
1095 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
1096 iv.load(1, JAVA_STRING_TYPE);
1097 iv.load(2, Type.INT_TYPE);
1098 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
1099 }
1100 else {
1101 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false);
1102 }
1103 }
1104
1105 private class DelegationFieldsInfo {
1106 private class Field {
1107 public final Type type;
1108 public final String name;
1109 public final boolean generateField;
1110
1111 private Field(Type type, String name, boolean generateField) {
1112 this.type = type;
1113 this.name = name;
1114 this.generateField = generateField;
1115 }
1116
1117 @NotNull
1118 public StackValue getStackValue() {
1119 return StackValue.field(type, classAsmType, name, false, StackValue.none());
1120 }
1121 }
1122 private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<KtDelegatedSuperTypeEntry, Field>();
1123
1124 @NotNull
1125 public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
1126 return fields.get(specifier);
1127 }
1128
1129 private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
1130 fields.put(specifier,
1131 new Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false));
1132 }
1133
1134 private void addField(KtDelegatedSuperTypeEntry specifier, Type type, String name) {
1135 fields.put(specifier, new Field(type, name, true));
1136 }
1137 }
1138
1139 @NotNull
1140 private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<KtSuperTypeListEntry> delegationSpecifiers) {
1141 DelegationFieldsInfo result = new DelegationFieldsInfo();
1142 int n = 0;
1143 for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
1144 if (specifier instanceof KtDelegatedSuperTypeEntry) {
1145 KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1146 PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
1147
1148
1149 if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
1150 result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
1151 }
1152 else {
1153 KotlinType expressionType = expression != null ? bindingContext.getType(expression) : null;
1154 Type asmType =
1155 expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(getSuperClass(specifier));
1156 result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
1157 }
1158 n++;
1159 }
1160 }
1161 return result;
1162 }
1163
1164 @NotNull
1165 private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
1166 return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
1167 }
1168
1169 private void genCallToDelegatorByExpressionSpecifier(
1170 InstructionAdapter iv,
1171 ExpressionCodegen codegen,
1172 KtDelegatedSuperTypeEntry specifier,
1173 DelegationFieldsInfo fieldsInfo
1174 ) {
1175 KtExpression expression = specifier.getDelegateExpression();
1176
1177 DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier);
1178 if (fieldInfo.generateField) {
1179 iv.load(0, classAsmType);
1180 fieldInfo.getStackValue().store(codegen.gen(expression), iv);
1181 }
1182 }
1183
1184 private void lookupConstructorExpressionsInClosureIfPresent() {
1185 if (!state.getClassBuilderMode().generateBodies || descriptor.getConstructors().isEmpty()) return;
1186
1187 KtVisitorVoid visitor = new KtVisitorVoid() {
1188 @Override
1189 public void visitKtElement(@NotNull KtElement e) {
1190 e.acceptChildren(this);
1191 }
1192
1193 @Override
1194 public void visitSimpleNameExpression(@NotNull KtSimpleNameExpression expr) {
1195 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
1196
1197 if (isLocalFunction(descriptor)) {
1198 lookupInContext(descriptor);
1199 }
1200 else if (descriptor instanceof CallableMemberDescriptor) {
1201 ResolvedCall<? extends CallableDescriptor> call = CallUtilKt.getResolvedCall(expr, bindingContext);
1202 if (call != null) {
1203 lookupReceivers(call);
1204 }
1205 if (call instanceof VariableAsFunctionResolvedCall) {
1206 lookupReceivers(((VariableAsFunctionResolvedCall) call).getVariableCall());
1207 }
1208 }
1209 else if (descriptor instanceof VariableDescriptor) {
1210 if (descriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
1211 ClassDescriptor classDescriptor =
1212 (ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration();
1213 if (classDescriptor == ImplementationBodyCodegen.this.descriptor) return;
1214 }
1215 lookupInContext(descriptor);
1216 }
1217 }
1218
1219 private void lookupReceivers(@NotNull ResolvedCall<? extends CallableDescriptor> call) {
1220 lookupReceiver(call.getDispatchReceiver());
1221 lookupReceiver(call.getExtensionReceiver());
1222 }
1223
1224 private void lookupReceiver(@Nullable ReceiverValue value) {
1225 if (value instanceof ImplicitReceiver) {
1226 if (value instanceof ExtensionReceiver) {
1227 ReceiverParameterDescriptor parameter =
1228 ((ExtensionReceiver) value).getDeclarationDescriptor().getExtensionReceiverParameter();
1229 assert parameter != null : "Extension receiver should exist: " + ((ExtensionReceiver) value).getDeclarationDescriptor();
1230 lookupInContext(parameter);
1231 }
1232 else {
1233 lookupInContext(((ImplicitReceiver) value).getDeclarationDescriptor());
1234 }
1235 }
1236 }
1237
1238
1239 private void lookupInContext(@NotNull DeclarationDescriptor toLookup) {
1240 ExpressionCodegen.lookupValuaAndLocalVariableMetadata(toLookup, StackValue.LOCAL_0, state, true, context, null);
1241 }
1242
1243 @Override
1244 public void visitThisExpression(@NotNull KtThisExpression expression) {
1245 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
1246 assert descriptor instanceof CallableDescriptor ||
1247 descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor;
1248 if (descriptor instanceof ClassDescriptor) {
1249 lookupInContext(descriptor);
1250 }
1251
1252 if (descriptor instanceof CallableDescriptor) {
1253 ReceiverParameterDescriptor parameter = ((CallableDescriptor) descriptor).getExtensionReceiverParameter();
1254 if (parameter != null) {
1255 lookupInContext(parameter);
1256 }
1257 }
1258 }
1259
1260 @Override
1261 public void visitSuperExpression(@NotNull KtSuperExpression expression) {
1262 lookupInContext(ExpressionCodegen.getSuperCallLabelTarget(context, expression));
1263 }
1264 };
1265
1266 for (KtDeclaration declaration : myClass.getDeclarations()) {
1267 if (declaration instanceof KtProperty) {
1268 KtProperty property = (KtProperty) declaration;
1269 KtExpression initializer = property.getDelegateExpressionOrInitializer();
1270 if (initializer != null) {
1271 initializer.accept(visitor);
1272 }
1273 }
1274 else if (declaration instanceof KtAnonymousInitializer) {
1275 KtAnonymousInitializer initializer = (KtAnonymousInitializer) declaration;
1276 initializer.accept(visitor);
1277 }
1278 else if (declaration instanceof KtSecondaryConstructor) {
1279 KtSecondaryConstructor constructor = (KtSecondaryConstructor) declaration;
1280 constructor.accept(visitor);
1281 }
1282 }
1283
1284 for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
1285 if (specifier instanceof KtDelegatedSuperTypeEntry) {
1286 KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1287 assert delegateExpression != null;
1288 delegateExpression.accept(visitor);
1289 }
1290 else if (specifier instanceof KtSuperTypeCallEntry) {
1291 specifier.accept(visitor);
1292 }
1293 }
1294 }
1295
1296 private void generateTraitMethods() {
1297 if (isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, state)) return;
1298
1299 List<FunctionDescriptor> restrictedInheritance = new ArrayList<FunctionDescriptor>();
1300 for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
1301 FunctionDescriptor interfaceFun = entry.getKey();
1302 //skip java 8 default methods
1303 if (!CodegenUtilKt.isDefinitelyNotDefaultImplsMethod(interfaceFun) && !isJvm8InterfaceWithDefaultsMember(interfaceFun, state)) {
1304 if (state.isJvm8TargetWithDefaults() && !JvmCodegenUtil.isJvm8InterfaceWithDefaults(interfaceFun.getContainingDeclaration(), state)) {
1305 restrictedInheritance.add(interfaceFun);
1306 }
1307 else {
1308 generateDelegationToDefaultImpl(interfaceFun, entry.getValue());
1309 }
1310 }
1311 }
1312
1313 CodegenUtilKt.reportTarget6InheritanceErrorIfNeeded(descriptor, myClass.getPsiOrParent(), restrictedInheritance, state);
1314 }
1315
1316 private void generateDelegationToDefaultImpl(@NotNull final FunctionDescriptor traitFun, @NotNull final FunctionDescriptor inheritedFun) {
1317 functionCodegen.generateMethod(
1318 JvmDeclarationOriginKt.DelegationToDefaultImpls(descriptorToDeclaration(traitFun), traitFun),
1319 inheritedFun,
1320 new FunctionGenerationStrategy.CodegenBased(state) {
1321 @Override
1322 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1323 DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration();
1324 if (!DescriptorUtils.isInterface(containingDeclaration)) return;
1325
1326 DeclarationDescriptor declarationInheritedFun = inheritedFun.getContainingDeclaration();
1327 PsiElement classForInheritedFun = descriptorToDeclaration(declarationInheritedFun);
1328 if (classForInheritedFun instanceof KtDeclaration) {
1329 codegen.markLineNumber((KtElement) classForInheritedFun, false);
1330 }
1331
1332 ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration;
1333 Type traitImplType = typeMapper.mapDefaultImpls(containingTrait);
1334
1335 Method traitMethod = typeMapper.mapAsmMethod(traitFun.getOriginal(), OwnerKind.DEFAULT_IMPLS);
1336
1337 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
1338 Type[] originalArgTypes = traitMethod.getArgumentTypes();
1339 assert originalArgTypes.length == argTypes.length + 1 :
1340 "Invalid trait implementation signature: " + signature + " vs " + traitMethod + " for " + traitFun;
1341
1342 InstructionAdapter iv = codegen.v;
1343 iv.load(0, OBJECT_TYPE);
1344 for (int i = 0, reg = 1; i < argTypes.length; i++) {
1345 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i + 1], iv);
1346 //noinspection AssignmentToForLoopParameter
1347 reg += argTypes[i].getSize();
1348 }
1349
1350 if (KotlinBuiltIns.isCloneable(containingTrait) && traitMethod.getName().equals("clone")) {
1351 // A special hack for Cloneable: there's no kotlin/Cloneable$DefaultImpls class at runtime,
1352 // and its 'clone' method is actually located in java/lang/Object
1353 iv.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false);
1354 }
1355 else {
1356 iv.invokestatic(traitImplType.getInternalName(), traitMethod.getName(), traitMethod.getDescriptor(), false);
1357 }
1358
1359 Type returnType = signature.getReturnType();
1360 StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv);
1361 iv.areturn(returnType);
1362 }
1363 }
1364 );
1365 }
1366
1367 private void generateDelegatorToConstructorCall(
1368 @NotNull InstructionAdapter iv,
1369 @NotNull ExpressionCodegen codegen,
1370 @NotNull ClassConstructorDescriptor constructorDescriptor,
1371 @Nullable ResolvedCall<ConstructorDescriptor> delegationConstructorCall
1372 ) {
1373 if (delegationConstructorCall == null) {
1374 genSimpleSuperCall(iv);
1375 return;
1376 }
1377 iv.load(0, OBJECT_TYPE);
1378 ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(codegen.getConstructorDescriptor(delegationConstructorCall));
1379
1380 CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor, false);
1381 CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor, false);
1382
1383 List<JvmMethodParameterSignature> delegatingParameters = delegateConstructorCallable.getValueParameters();
1384 List<JvmMethodParameterSignature> parameters = callable.getValueParameters();
1385
1386 ArgumentGenerator argumentGenerator;
1387 if (isSameClassConstructor(delegateConstructor)) {
1388 // if it's the same class constructor we should just pass all synthetic parameters
1389 argumentGenerator =
1390 generateThisCallImplicitArguments(iv, codegen, delegateConstructor, delegateConstructorCallable, delegatingParameters,
1391 parameters);
1392 }
1393 else {
1394 argumentGenerator =
1395 generateSuperCallImplicitArguments(iv, codegen, constructorDescriptor, delegateConstructor, delegateConstructorCallable,
1396 delegatingParameters,
1397 parameters);
1398 }
1399
1400 codegen.invokeMethodWithArguments(
1401 delegateConstructorCallable, delegationConstructorCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator);
1402 }
1403
1404 private boolean isSameClassConstructor(@Nullable ConstructorDescriptor delegatingConstructor) {
1405 return delegatingConstructor != null && delegatingConstructor.getContainingDeclaration() == descriptor;
1406 }
1407
1408 @NotNull
1409 private ArgumentGenerator generateSuperCallImplicitArguments(
1410 @NotNull InstructionAdapter iv,
1411 @NotNull ExpressionCodegen codegen,
1412 @NotNull ConstructorDescriptor constructorDescriptor,
1413 @NotNull ConstructorDescriptor superConstructor,
1414 @NotNull CallableMethod superCallable,
1415 @NotNull List<JvmMethodParameterSignature> superParameters,
1416 @NotNull List<JvmMethodParameterSignature> parameters
1417 ) {
1418 int offset = 1;
1419 int superIndex = 0;
1420
1421 // Here we match all the super constructor parameters except those with kind VALUE to the derived constructor parameters, push
1422 // them all onto the stack and update "offset" variable so that in the end it points to the slot of the first VALUE argument
1423 for (JvmMethodParameterSignature parameter : parameters) {
1424 if (superIndex >= superParameters.size()) break;
1425
1426 JvmMethodParameterKind superKind = superParameters.get(superIndex).getKind();
1427 JvmMethodParameterKind kind = parameter.getKind();
1428 Type type = parameter.getAsmType();
1429
1430 if (superKind == JvmMethodParameterKind.VALUE && kind == JvmMethodParameterKind.SUPER_CALL_PARAM) {
1431 // Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below
1432 break;
1433 }
1434
1435 if (superKind == JvmMethodParameterKind.OUTER) {
1436 assert kind == JvmMethodParameterKind.OUTER || kind == JvmMethodParameterKind.SUPER_CALL_PARAM :
1437 String.format("Non-outer parameter incorrectly mapped to outer for %s: %s vs %s",
1438 constructorDescriptor, parameters, superParameters);
1439 // Super constructor requires OUTER parameter, but our OUTER instance may be different from what is expected by the super
1440 // constructor. We need to traverse our outer classes from the bottom up, to find the needed class. See innerExtendsOuter.kt
1441 ClassDescriptor outerForSuper = (ClassDescriptor) superConstructor.getContainingDeclaration().getContainingDeclaration();
1442 StackValue outer = codegen.generateThisOrOuter(outerForSuper, true, true);
1443 outer.put(outer.type, codegen.v);
1444 superIndex++;
1445 }
1446 else if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL) {
1447 iv.load(offset, type);
1448 superIndex++;
1449 }
1450
1451 offset += type.getSize();
1452 }
1453
1454 if (isAnonymousObject(descriptor)) {
1455 List<JvmMethodParameterSignature> superValues = superParameters.subList(superIndex, superParameters.size());
1456 return new ObjectSuperCallArgumentGenerator(superValues, iv, offset);
1457 }
1458 else {
1459 return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(),
1460 superCallable.getValueParameterTypes());
1461 }
1462 }
1463
1464 @NotNull
1465 private static ArgumentGenerator generateThisCallImplicitArguments(
1466 @NotNull InstructionAdapter iv,
1467 @NotNull ExpressionCodegen codegen,
1468 @NotNull ConstructorDescriptor delegatingConstructor,
1469 @NotNull CallableMethod delegatingCallable,
1470 @NotNull List<JvmMethodParameterSignature> delegatingParameters,
1471 @NotNull List<JvmMethodParameterSignature> parameters
1472 ) {
1473 int offset = 1;
1474 int index = 0;
1475 for (; index < delegatingParameters.size(); index++) {
1476 JvmMethodParameterKind delegatingKind = delegatingParameters.get(index).getKind();
1477 if (delegatingKind == JvmMethodParameterKind.VALUE) {
1478 assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE:
1479 "Delegating constructor has not enough implicit parameters";
1480 break;
1481 }
1482 assert index < parameters.size() && parameters.get(index).getKind() == delegatingKind :
1483 "Constructors of the same class should have the same set of implicit arguments";
1484 JvmMethodParameterSignature parameter = parameters.get(index);
1485
1486 iv.load(offset, parameter.getAsmType());
1487 offset += parameter.getAsmType().getSize();
1488 }
1489
1490 assert index == parameters.size() || parameters.get(index).getKind() == JvmMethodParameterKind.VALUE :
1491 "Delegating constructor has not enough parameters";
1492
1493 return new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, delegatingConstructor.getValueParameters(),
1494 delegatingCallable.getValueParameterTypes());
1495 }
1496
1497 private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator {
1498 private final List<JvmMethodParameterSignature> parameters;
1499 private final InstructionAdapter iv;
1500 private int offset;
1501
1502 public ObjectSuperCallArgumentGenerator(
1503 @NotNull List<JvmMethodParameterSignature> superParameters,
1504 @NotNull InstructionAdapter iv,
1505 int firstValueParamOffset
1506 ) {
1507 this.parameters = superParameters;
1508 this.iv = iv;
1509 this.offset = firstValueParamOffset;
1510 }
1511
1512 @Override
1513 public void generateExpression(int i, @NotNull ExpressionValueArgument argument) {
1514 generateSuperCallArgument(i);
1515 }
1516
1517 @Override
1518 public void generateDefault(int i, @NotNull DefaultValueArgument argument) {
1519 Type type = parameters.get(i).getAsmType();
1520 pushDefaultValueOnStack(type, iv);
1521 }
1522
1523 @Override
1524 public void generateVararg(int i, @NotNull VarargValueArgument argument) {
1525 generateSuperCallArgument(i);
1526 }
1527
1528 private void generateSuperCallArgument(int i) {
1529 Type type = parameters.get(i).getAsmType();
1530 iv.load(offset, type);
1531 offset += type.getSize();
1532 }
1533
1534 @Override
1535 protected void reorderArgumentsIfNeeded(@NotNull List<ArgumentAndDeclIndex> args) {
1536
1537 }
1538 }
1539
1540 private void generateEnumEntries() {
1541 if (descriptor.getKind() != ClassKind.ENUM_CLASS) return;
1542
1543 List<KtEnumEntry> enumEntries = CollectionsKt.filterIsInstance(element.getDeclarations(), KtEnumEntry.class);
1544
1545 for (KtEnumEntry enumEntry : enumEntries) {
1546 ClassDescriptor descriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
1547 int isDeprecated = KotlinBuiltIns.isDeprecated(descriptor) ? ACC_DEPRECATED : 0;
1548 FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(enumEntry, descriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL | isDeprecated,
1549 descriptor.getName().asString(), classAsmType.getDescriptor(), null, null);
1550 AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(descriptor, null);
1551 }
1552
1553 initializeEnumConstants(enumEntries);
1554 }
1555
1556 private void initializeEnumConstants(@NotNull List<KtEnumEntry> enumEntries) {
1557 if (!state.getClassBuilderMode().generateBodies) return;
1558
1559 ExpressionCodegen codegen = createOrGetClInitCodegen();
1560 InstructionAdapter iv = codegen.v;
1561
1562 Type arrayAsmType = typeMapper.mapType(DescriptorUtilsKt.getBuiltIns(descriptor).getArrayType(INVARIANT, descriptor.getDefaultType()));
1563 v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
1564 arrayAsmType.getDescriptor(), null, null);
1565
1566 iv.iconst(enumEntries.size());
1567 iv.newarray(classAsmType);
1568
1569 if (!enumEntries.isEmpty()) {
1570 iv.dup();
1571 for (int ordinal = 0, size = enumEntries.size(); ordinal < size; ordinal++) {
1572 initializeEnumConstant(enumEntries, ordinal);
1573 }
1574 }
1575
1576 iv.putstatic(classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, arrayAsmType.getDescriptor());
1577 }
1578
1579 private void initializeEnumConstant(@NotNull List<KtEnumEntry> enumEntries, int ordinal) {
1580 ExpressionCodegen codegen = createOrGetClInitCodegen();
1581 InstructionAdapter iv = codegen.v;
1582 KtEnumEntry enumEntry = enumEntries.get(ordinal);
1583
1584 iv.dup();
1585 iv.iconst(ordinal);
1586
1587 ClassDescriptor classDescriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
1588 Type implClass = typeMapper.mapClass(classDescriptor);
1589
1590 iv.anew(implClass);
1591 iv.dup();
1592
1593 iv.aconst(enumEntry.getName());
1594 iv.iconst(ordinal);
1595
1596 List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
1597 ResolvedCall<?> defaultArgumentsConstructorCall = CallUtilKt.getResolvedCall(enumEntry, bindingContext);
1598 boolean enumEntryHasSubclass = CodegenBinding.enumEntryNeedSubclass(bindingContext, classDescriptor);
1599 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
1600 ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
1601
1602 CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor(), false);
1603
1604 codegen.invokeMethodWithArguments(method, resolvedCall, StackValue.none());
1605 }
1606 else if (defaultArgumentsConstructorCall != null && !enumEntryHasSubclass) {
1607 codegen.invokeFunction(defaultArgumentsConstructorCall, StackValue.none()).put(Type.VOID_TYPE, iv);
1608 }
1609 else {
1610 iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
1611 }
1612
1613 iv.dup();
1614 iv.putstatic(classAsmType.getInternalName(), enumEntry.getName(), classAsmType.getDescriptor());
1615 iv.astore(OBJECT_TYPE);
1616 }
1617
1618 private void generateDelegates(DelegationFieldsInfo delegationFieldsInfo) {
1619 for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
1620 if (specifier instanceof KtDelegatedSuperTypeEntry) {
1621 DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
1622 generateDelegateField(field);
1623 KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
1624 KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
1625 generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
1626 }
1627 }
1628 }
1629
1630 private void generateDelegateField(DelegationFieldsInfo.Field fieldInfo) {
1631 if (!fieldInfo.generateField) return;
1632
1633 v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC,
1634 fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null);
1635 }
1636
1637 private void generateDelegates(
1638 @NotNull ClassDescriptor toInterface,
1639 @Nullable KotlinType delegateExpressionType,
1640 @NotNull DelegationFieldsInfo.Field field
1641 ) {
1642 for (Map.Entry<CallableMemberDescriptor, CallableMemberDescriptor> entry : DelegationResolver.Companion.getDelegates(
1643 descriptor, toInterface, delegateExpressionType).entrySet()
1644 ) {
1645 CallableMemberDescriptor member = entry.getKey();
1646 CallableMemberDescriptor delegateTo = entry.getValue();
1647 if (member instanceof PropertyDescriptor) {
1648 propertyCodegen.genDelegate((PropertyDescriptor) member, (PropertyDescriptor) delegateTo, field.getStackValue());
1649 }
1650 else if (member instanceof FunctionDescriptor) {
1651 functionCodegen.genDelegate((FunctionDescriptor) member, (FunctionDescriptor) delegateTo, field.getStackValue());
1652 }
1653 }
1654 }
1655
1656 public void addCompanionObjectPropertyToCopy(@NotNull PropertyDescriptor descriptor, Object defaultValue) {
1657 if (companionObjectPropertiesToCopy == null) {
1658 companionObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>();
1659 }
1660 companionObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue));
1661 }
1662
1663 @Override
1664 protected void done() {
1665 for (Function2<ImplementationBodyCodegen, ClassBuilder, Unit> task : additionalTasks) {
1666 task.invoke(this, v);
1667 }
1668
1669 super.done();
1670 }
1671
1672 private static class PropertyAndDefaultValue {
1673 public final PropertyDescriptor descriptor;
1674 public final Object defaultValue;
1675
1676 public PropertyAndDefaultValue(@NotNull PropertyDescriptor descriptor, Object defaultValue) {
1677 this.descriptor = descriptor;
1678 this.defaultValue = defaultValue;
1679 }
1680 }
1681
1682 public void addAdditionalTask(Function2<ImplementationBodyCodegen, ClassBuilder, Unit> additionalTask) {
1683 additionalTasks.add(additionalTask);
1684 }
1685 }