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