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