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