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