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