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