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