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