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