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