001 /*
002 * Copyright 2010-2014 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.jet.codegen;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.progress.ProcessCanceledException;
021 import com.intellij.util.ArrayUtil;
022 import kotlin.Function0;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.backend.common.DataClassMethodGenerator;
026 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
027 import org.jetbrains.jet.codegen.binding.CodegenBinding;
028 import org.jetbrains.jet.codegen.binding.MutableClosure;
029 import org.jetbrains.jet.codegen.bridges.BridgesPackage;
030 import org.jetbrains.jet.codegen.context.ClassContext;
031 import org.jetbrains.jet.codegen.context.ConstructorContext;
032 import org.jetbrains.jet.codegen.context.MethodContext;
033 import org.jetbrains.jet.codegen.signature.*;
034 import org.jetbrains.jet.codegen.state.GenerationState;
035 import org.jetbrains.jet.codegen.state.JetTypeMapper;
036 import org.jetbrains.jet.descriptors.serialization.BitEncoding;
037 import org.jetbrains.jet.descriptors.serialization.ClassData;
038 import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer;
039 import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
040 import org.jetbrains.jet.lang.descriptors.*;
041 import org.jetbrains.jet.lang.psi.*;
042 import org.jetbrains.jet.lang.resolve.BindingContext;
043 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
044 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
045 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
046 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
047 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
048 import org.jetbrains.jet.lang.resolve.java.JvmAbi;
049 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
050 import org.jetbrains.jet.lang.resolve.name.Name;
051 import org.jetbrains.jet.lang.types.*;
052 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
053 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
054 import org.jetbrains.jet.lexer.JetTokens;
055 import org.jetbrains.org.objectweb.asm.*;
056 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
057 import org.jetbrains.org.objectweb.asm.commons.Method;
058
059 import java.util.*;
060
061 import static org.jetbrains.jet.codegen.AsmUtil.*;
062 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*;
063 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
064 import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver;
065 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
066 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
067 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
068 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
069 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
070 import static org.jetbrains.org.objectweb.asm.Opcodes.*;
071
072 public class ImplementationBodyCodegen extends ClassBodyCodegen {
073 private static final String VALUES = "$VALUES";
074 private JetDelegationSpecifier superCall;
075 private Type superClassAsmType;
076 @Nullable // null means java/lang/Object
077 private JetType superClassType;
078 private final Type classAsmType;
079
080 private final FunctionCodegen functionCodegen;
081 private final PropertyCodegen propertyCodegen;
082
083 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy;
084
085 public ImplementationBodyCodegen(
086 @NotNull JetClassOrObject aClass,
087 @NotNull ClassContext context,
088 @NotNull ClassBuilder v,
089 @NotNull GenerationState state,
090 @Nullable MemberCodegen<?> parentCodegen
091 ) {
092 super(aClass, context, v, state, parentCodegen);
093 this.classAsmType = typeMapper.mapClass(descriptor);
094 this.functionCodegen = new FunctionCodegen(context, v, state, this);
095 this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this);
096 }
097
098 @Override
099 protected void generateDeclaration() {
100 getSuperClass();
101
102 JvmClassSignature signature = signature();
103
104 boolean isAbstract = false;
105 boolean isInterface = false;
106 boolean isFinal = false;
107 boolean isStatic;
108 boolean isAnnotation = false;
109 boolean isEnum = false;
110
111 if (myClass instanceof JetClass) {
112 JetClass jetClass = (JetClass) myClass;
113 if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) {
114 isAbstract = true;
115 }
116 if (jetClass.isTrait()) {
117 isAbstract = true;
118 isInterface = true;
119 }
120 else if (jetClass.isAnnotation()) {
121 isAbstract = true;
122 isInterface = true;
123 isAnnotation = true;
124 signature.getInterfaces().add("java/lang/annotation/Annotation");
125 }
126 else if (jetClass.isEnum()) {
127 isAbstract = hasAbstractMembers(descriptor);
128 isEnum = true;
129 }
130
131 if (descriptor.getKind() == ClassKind.OBJECT || descriptor.getKind() == ClassKind.CLASS_OBJECT) {
132 isFinal = true;
133 }
134
135 if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) {
136 isFinal = true;
137 }
138 isStatic = !jetClass.isInner();
139 }
140 else {
141 isStatic = myClass.getParent() instanceof JetClassObject;
142 isFinal = true;
143 }
144
145 int access = 0;
146
147 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
148 // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class
149 // Light class generation is implemented so that Cls-classes only read bare code of classes,
150 // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY)
151 // Thus we must write full accessibility flags on inner classes in this mode
152 access |= getVisibilityAccessFlag(descriptor);
153 // Same for STATIC
154 if (isStatic) {
155 access |= ACC_STATIC;
156 }
157 }
158 else {
159 access |= getVisibilityAccessFlagForClass(descriptor);
160 }
161 if (isAbstract) {
162 access |= ACC_ABSTRACT;
163 }
164 if (isInterface) {
165 access |= ACC_INTERFACE; // ACC_SUPER
166 }
167 else {
168 access |= ACC_SUPER;
169 }
170 if (isFinal) {
171 access |= ACC_FINAL;
172 }
173 if (isAnnotation) {
174 access |= ACC_ANNOTATION;
175 }
176 if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) {
177 access |= ACC_DEPRECATED;
178 }
179 if (isEnum) {
180 for (JetDeclaration declaration : myClass.getDeclarations()) {
181 if (declaration instanceof JetEnumEntry) {
182 if (enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) {
183 access &= ~ACC_FINAL;
184 }
185 }
186 }
187 access |= ACC_ENUM;
188 }
189 List<String> interfaces = signature.getInterfaces();
190 v.defineClass(myClass, V1_6,
191 access,
192 signature.getName(),
193 signature.getJavaGenericSignature(),
194 signature.getSuperclassName(),
195 ArrayUtil.toStringArray(interfaces)
196 );
197 v.visitSource(myClass.getContainingFile().getName(), null);
198
199 writeEnclosingMethod();
200
201 writeOuterClasses();
202
203 writeInnerClasses();
204
205 AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor);
206 }
207
208 @Override
209 protected void generateKotlinAnnotation() {
210 if (isAnonymousObject(descriptor)) {
211 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.ANONYMOUS_OBJECT);
212 return;
213 }
214
215 if (!isTopLevelOrInnerClass(descriptor)) {
216 // LOCAL_CLASS is also written to inner classes of local classes
217 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.LOCAL_CLASS);
218 return;
219 }
220
221 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
222
223 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings()));
224
225 ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
226
227 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto);
228
229 AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true);
230 //noinspection ConstantConditions
231 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
232 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME);
233 for (String string : BitEncoding.encodeBytes(data.toBytes())) {
234 array.visit(null, string);
235 }
236 array.visitEnd();
237 av.visitEnd();
238 }
239
240 private void writeEnclosingMethod() {
241 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
242 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
243
244 boolean isObjectLiteral = DescriptorUtils.isAnonymousObject(descriptor);
245
246 boolean isLocalOrAnonymousClass = isObjectLiteral ||
247 !(parentDescriptor instanceof PackageFragmentDescriptor || parentDescriptor instanceof ClassDescriptor);
248 // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level
249 if (isLocalOrAnonymousClass && state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) {
250 String outerClassName = getOuterClassName(descriptor, typeMapper);
251 FunctionDescriptor function = AsmUtil.isDeclarationInsideInlineFunction(descriptor)
252 ? null
253 : DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class);
254
255 if (function != null) {
256 Method method = typeMapper.mapSignature(function).getAsmMethod();
257 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor());
258 }
259 else {
260 v.visitOuterClass(outerClassName, null, null);
261 }
262 }
263 }
264
265 @NotNull
266 private static String getOuterClassName(@NotNull ClassDescriptor classDescriptor, @NotNull JetTypeMapper typeMapper) {
267 ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
268 if (container != null) {
269 return typeMapper.mapClass(container).getInternalName();
270 }
271
272 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), classDescriptor);
273 assert containingFile != null : "Containing file should be present for " + classDescriptor;
274 return PackageCodegen.getPackagePartInternalName(containingFile);
275 }
276
277 private void writeInnerClasses() {
278 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor);
279 if (result != null) {
280 for (ClassDescriptor innerClass : result) {
281 writeInnerClass(innerClass);
282 }
283 }
284 }
285
286 private void writeOuterClasses() {
287 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
288 // for each enclosing class and for each immediate member
289 DeclarationDescriptor inner = descriptor;
290 while (true) {
291 if (inner == null || isTopLevelDeclaration(inner)) {
292 break;
293 }
294 if (inner instanceof ClassDescriptor) {
295 writeInnerClass((ClassDescriptor) inner);
296 }
297 inner = inner.getContainingDeclaration();
298 }
299 }
300
301 private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
302 // TODO: proper access
303 int innerClassAccess = getVisibilityAccessFlag(innerClass);
304 if (innerClass.getModality() == Modality.FINAL) {
305 innerClassAccess |= ACC_FINAL;
306 }
307 else if (innerClass.getModality() == Modality.ABSTRACT) {
308 innerClassAccess |= ACC_ABSTRACT;
309 }
310
311 if (innerClass.getKind() == ClassKind.TRAIT) {
312 innerClassAccess |= ACC_INTERFACE;
313 }
314 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) {
315 innerClassAccess |= ACC_ENUM;
316 }
317
318 if (!innerClass.isInner()) {
319 innerClassAccess |= ACC_STATIC;
320 }
321
322 // TODO: cache internal names
323 DeclarationDescriptor containing = innerClass.getContainingDeclaration();
324 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null;
325
326 String innerClassInternalName;
327 String innerName;
328
329 if (isClassObject(innerClass)) {
330 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME;
331 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
332 }
333 else {
334 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
335 innerClassInternalName = getInternalNameForImpl(innerClass);
336 }
337
338 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess);
339 }
340
341 @NotNull
342 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) {
343 return typeMapper.mapClass(descriptor).getInternalName();
344 }
345
346 @NotNull
347 private JvmClassSignature signature() {
348 BothSignatureWriter sw = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS);
349
350 typeMapper.writeFormalTypeParameters(descriptor.getTypeConstructor().getParameters(), sw);
351
352 sw.writeSuperclass();
353 if (superClassType == null) {
354 sw.writeClassBegin(superClassAsmType);
355 sw.writeClassEnd();
356 }
357 else {
358 typeMapper.mapSupertype(superClassType, sw);
359 }
360 sw.writeSuperclassEnd();
361
362 List<JetType> interfaceSupertypes = Lists.newArrayList();
363 boolean explicitKObject = false;
364
365 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
366 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
367 assert superType != null : "No supertype for class: " + myClass.getText();
368 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
369 if (isInterface(superClassDescriptor)) {
370 interfaceSupertypes.add(superType);
371
372 assert superClassDescriptor != null : "should be already checked by isInterface()";
373 if (JvmAbi.K_OBJECT.equalsTo(DescriptorUtils.getFqName(superClassDescriptor))) {
374 explicitKObject = true;
375 }
376 }
377 }
378
379 LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>();
380 if (!explicitKObject) {
381 Type kObject = asmTypeByFqNameWithoutInnerClasses(JvmAbi.K_OBJECT);
382 sw.writeInterface();
383 sw.writeClassBegin(kObject);
384 sw.writeClassEnd();
385 sw.writeInterfaceEnd();
386 superInterfaces.add(kObject.getInternalName());
387 }
388
389 for (JetType supertype : interfaceSupertypes) {
390 sw.writeInterface();
391 Type jvmName = typeMapper.mapSupertype(supertype, sw);
392 sw.writeInterfaceEnd();
393 superInterfaces.add(jvmName.getInternalName());
394 }
395
396 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(),
397 new ArrayList<String>(superInterfaces),
398 sw.makeJavaGenericSignature());
399 }
400
401 protected void getSuperClass() {
402 superClassAsmType = AsmTypeConstants.OBJECT_TYPE;
403 superClassType = null;
404
405 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
406
407 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
408 return;
409 }
410
411 if (kind != OwnerKind.IMPLEMENTATION) {
412 throw new IllegalStateException("must be impl to reach this code: " + kind);
413 }
414
415 for (JetDelegationSpecifier specifier : delegationSpecifiers) {
416 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
417 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
418 assert superType != null :
419 String.format("No type recorded for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier));
420
421 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
422 assert superClassDescriptor != null;
423 if (!isInterface(superClassDescriptor)) {
424 superClassType = superType;
425 superClassAsmType = typeMapper.mapClass(superClassDescriptor);
426 superCall = specifier;
427 }
428 }
429 }
430
431 if (superClassType == null) {
432 if (descriptor.getKind() == ClassKind.ENUM_CLASS) {
433 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType());
434 superClassAsmType = typeMapper.mapType(superClassType);
435 }
436 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
437 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next();
438 superClassAsmType = typeMapper.mapType(superClassType);
439 }
440 }
441 }
442
443 @Override
444 protected void generateSyntheticParts() {
445 generateDelegatedPropertyMetadataArray();
446
447 generateFieldForSingleton();
448
449 generateClassObjectBackingFieldCopies();
450
451 try {
452 generatePrimaryConstructor();
453 }
454 catch (CompilationException e) {
455 throw e;
456 }
457 catch (ProcessCanceledException e) {
458 throw e;
459 }
460 catch (RuntimeException e) {
461 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
462 }
463
464 generateTraitMethods();
465
466 generateSyntheticAccessors();
467
468 generateEnumMethodsAndConstInitializers();
469
470 generateFunctionsForDataClasses();
471
472 generateBuiltinMethodStubs();
473
474 generateToArray();
475
476 genClosureFields(context.closure, v, state.getTypeMapper());
477 }
478
479 private void generateDelegatedPropertyMetadataArray() {
480 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
481 generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
482 }
483 }
484
485 private boolean isGenericToArrayPresent() {
486 Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray"));
487 for (FunctionDescriptor function : functions) {
488 if (CallResolverUtil.isOrOverridesSynthesized(function)) {
489 continue;
490 }
491
492 if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) {
493 continue;
494 }
495
496 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(function.getTypeParameters().get(0).getDefaultType());
497 JetType returnType = function.getReturnType();
498 assert returnType != null : function.toString();
499 JetType paramType = function.getValueParameters().get(0).getType();
500 if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) {
501 return true;
502 }
503 }
504 return false;
505
506 }
507
508 private void generateToArray() {
509 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
510 if (!isSubclass(descriptor, builtIns.getCollection())) return;
511
512 int access = descriptor.getKind() == ClassKind.TRAIT ?
513 ACC_PUBLIC | ACC_ABSTRACT :
514 ACC_PUBLIC;
515 if (JvmCodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) {
516 MethodVisitor mv = v.getVisitor().visitMethod(access, "toArray", "()[Ljava/lang/Object;", null, null);
517
518 if (descriptor.getKind() != ClassKind.TRAIT) {
519 InstructionAdapter iv = new InstructionAdapter(mv);
520 mv.visitCode();
521
522 iv.load(0, classAsmType);
523 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;");
524 iv.areturn(Type.getObjectType("[Ljava/lang/Object;"));
525
526 FunctionCodegen.endVisit(mv, "toArray", myClass);
527 }
528 }
529
530 if (!isGenericToArrayPresent()) {
531 MethodVisitor mv = v.getVisitor().visitMethod(access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null);
532
533 if (descriptor.getKind() != ClassKind.TRAIT) {
534 InstructionAdapter iv = new InstructionAdapter(mv);
535 mv.visitCode();
536
537 iv.load(0, classAsmType);
538 iv.load(1, Type.getObjectType("[Ljava/lang/Object;"));
539
540 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;");
541 iv.areturn(Type.getObjectType("[Ljava/lang/Object;"));
542
543 FunctionCodegen.endVisit(mv, "toArray", myClass);
544 }
545 }
546 }
547
548 private void generateMethodStub(
549 @NotNull String name,
550 @NotNull String desc,
551 @NotNull ClassifierDescriptor returnedClassifier,
552 @NotNull ClassifierDescriptor... valueParameterClassifiers
553 ) {
554 if (JvmCodegenUtil.getDeclaredFunctionByRawSignature(
555 descriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers) == null) {
556 int access = descriptor.getKind() == ClassKind.TRAIT ?
557 ACC_PUBLIC | ACC_ABSTRACT :
558 ACC_PUBLIC;
559 MethodVisitor mv = v.getVisitor().visitMethod(access, name, desc, null, null);
560 if (descriptor.getKind() != ClassKind.TRAIT) {
561 mv.visitCode();
562 genThrow(mv, "java/lang/UnsupportedOperationException", "Mutating immutable collection");
563 FunctionCodegen.endVisit(mv, "built-in stub for " + name + desc, null);
564 }
565 }
566 }
567
568 private void generateBuiltinMethodStubs() {
569 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
570 if (isSubclass(descriptor, builtIns.getCollection())) {
571 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getCollection(), 0);
572
573 generateMethodStub("add", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), classifier);
574 generateMethodStub("remove", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), builtIns.getAny());
575 generateMethodStub("addAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
576 generateMethodStub("removeAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
577 generateMethodStub("retainAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection());
578 generateMethodStub("clear", "()V", builtIns.getUnit());
579 }
580
581 if (isSubclass(descriptor, builtIns.getList())) {
582 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getList(), 0);
583
584 generateMethodStub("set", "(ILjava/lang/Object;)Ljava/lang/Object;", classifier, builtIns.getInt(), classifier);
585 generateMethodStub("add", "(ILjava/lang/Object;)V", builtIns.getUnit(), builtIns.getInt(), classifier);
586 generateMethodStub("remove", "(I)Ljava/lang/Object;", classifier, builtIns.getInt());
587 }
588
589 if (isSubclass(descriptor, builtIns.getMap())) {
590 ClassifierDescriptor keyClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 0);
591 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 1);
592
593 generateMethodStub("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, keyClassifier,
594 valueClassifier);
595 generateMethodStub("remove", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, builtIns.getAny());
596 generateMethodStub("putAll", "(Ljava/util/Map;)V", builtIns.getUnit(), builtIns.getMap());
597 generateMethodStub("clear", "()V", builtIns.getUnit());
598 }
599
600 if (isSubclass(descriptor, builtIns.getMapEntry())) {
601 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMapEntry(), 1);
602
603 generateMethodStub("setValue", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, valueClassifier);
604 }
605
606 if (isSubclass(descriptor, builtIns.getIterator())) {
607 generateMethodStub("remove", "()V", builtIns.getUnit());
608 }
609 }
610
611 @NotNull
612 private ClassifierDescriptor getSubstituteForTypeParameterOf(@NotNull ClassDescriptor trait, int index) {
613 TypeParameterDescriptor listTypeParameter = trait.getTypeConstructor().getParameters().get(index);
614 TypeSubstitutor deepSubstitutor = SubstitutionUtils.buildDeepSubstitutor(descriptor.getDefaultType());
615 TypeProjection substitute = deepSubstitutor.substitute(new TypeProjectionImpl(listTypeParameter.getDefaultType()));
616 assert substitute != null : "Couldn't substitute: " + descriptor;
617 ClassifierDescriptor classifier = substitute.getType().getConstructor().getDeclarationDescriptor();
618 assert classifier != null : "No classifier: " + substitute.getType();
619 return classifier;
620 }
621
622 private void generateFunctionsForDataClasses() {
623 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return;
624
625 new DataClassMethodGeneratorImpl(myClass, bindingContext).generate();
626 }
627
628 private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator {
629 DataClassMethodGeneratorImpl(
630 JetClassOrObject klass,
631 BindingContext bindingContext
632 ) {
633 super(klass, bindingContext);
634 }
635
636 @Override
637 public void generateEqualsMethod(@NotNull List<PropertyDescriptor> properties) {
638 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
639 InstructionAdapter iv = new InstructionAdapter(mv);
640
641 mv.visitCode();
642 Label eq = new Label();
643 Label ne = new Label();
644
645 iv.load(0, OBJECT_TYPE);
646 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
647 iv.ifacmpeq(eq);
648
649 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
650 iv.instanceOf(classAsmType);
651 iv.ifeq(ne);
652
653 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
654 iv.checkcast(classAsmType);
655 iv.store(2, AsmTypeConstants.OBJECT_TYPE);
656
657 for (PropertyDescriptor propertyDescriptor : properties) {
658 Type asmType = typeMapper.mapType(propertyDescriptor);
659
660 genPropertyOnStack(iv, propertyDescriptor, 0);
661 genPropertyOnStack(iv, propertyDescriptor, 2);
662
663 if (asmType.getSort() == Type.ARRAY) {
664 Type elementType = correctElementType(asmType);
665 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
666 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
667 }
668 else {
669 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z");
670 }
671 }
672 else {
673 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType);
674 value.put(Type.BOOLEAN_TYPE, iv);
675 }
676
677 iv.ifeq(ne);
678 }
679
680 iv.mark(eq);
681 iv.iconst(1);
682 iv.areturn(Type.INT_TYPE);
683
684 iv.mark(ne);
685 iv.iconst(0);
686 iv.areturn(Type.INT_TYPE);
687
688 FunctionCodegen.endVisit(mv, "equals", myClass);
689 }
690
691 @Override
692 public void generateHashCodeMethod(@NotNull List<PropertyDescriptor> properties) {
693 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
694 InstructionAdapter iv = new InstructionAdapter(mv);
695
696 mv.visitCode();
697 boolean first = true;
698 for (PropertyDescriptor propertyDescriptor : properties) {
699 if (!first) {
700 iv.iconst(31);
701 iv.mul(Type.INT_TYPE);
702 }
703
704 genPropertyOnStack(iv, propertyDescriptor, 0);
705
706 Label ifNull = null;
707 Type asmType = typeMapper.mapType(propertyDescriptor);
708 if (!isPrimitive(asmType)) {
709 ifNull = new Label();
710 iv.dup();
711 iv.ifnull(ifNull);
712 }
713
714 genHashCode(mv, iv, asmType);
715
716 if (ifNull != null) {
717 Label end = new Label();
718 iv.goTo(end);
719 iv.mark(ifNull);
720 iv.pop();
721 iv.iconst(0);
722 iv.mark(end);
723 }
724
725 if (first) {
726 first = false;
727 }
728 else {
729 iv.add(Type.INT_TYPE);
730 }
731 }
732
733 mv.visitInsn(IRETURN);
734
735 FunctionCodegen.endVisit(mv, "hashCode", myClass);
736 }
737
738 @Override
739 public void generateToStringMethod(@NotNull List<PropertyDescriptor> properties) {
740 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
741 InstructionAdapter iv = new InstructionAdapter(mv);
742
743 mv.visitCode();
744 genStringBuilderConstructor(iv);
745
746 boolean first = true;
747 for (PropertyDescriptor propertyDescriptor : properties) {
748 if (first) {
749 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"=");
750 first = false;
751 }
752 else {
753 iv.aconst(", " + propertyDescriptor.getName().asString()+"=");
754 }
755 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
756
757 Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
758
759 if (type.getSort() == Type.ARRAY) {
760 Type elementType = correctElementType(type);
761 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
762 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;");
763 type = JAVA_STRING_TYPE;
764 }
765 else {
766 if (elementType.getSort() != Type.CHAR) {
767 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;");
768 type = JAVA_STRING_TYPE;
769 }
770 }
771 }
772 genInvokeAppendMethod(iv, type);
773 }
774
775 iv.aconst(")");
776 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
777
778 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
779 iv.areturn(JAVA_STRING_TYPE);
780
781 FunctionCodegen.endVisit(mv, "toString", myClass);
782 }
783
784 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) {
785 iv.load(index, classAsmType);
786 //noinspection ConstantConditions
787 Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod();
788
789 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor());
790 return method.getReturnType();
791 }
792
793 @Override
794 public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
795 functionCodegen.generateMethod(myClass, typeMapper.mapSignature(function), function, new FunctionGenerationStrategy() {
796 @Override
797 public void generateBody(
798 @NotNull MethodVisitor mv,
799 @NotNull JvmMethodSignature signature,
800 @NotNull MethodContext context,
801 @Nullable MemberCodegen<?> parentCodegen
802 ) {
803 Type componentType = signature.getReturnType();
804 InstructionAdapter iv = new InstructionAdapter(mv);
805 if (!componentType.equals(Type.VOID_TYPE)) {
806 iv.load(0, classAsmType);
807 String desc = "()" + componentType.getDescriptor();
808 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc);
809 }
810 iv.areturn(componentType);
811 }
812 });
813 }
814
815 @Override
816 public void generateCopyFunction(@NotNull final FunctionDescriptor function, @NotNull List<JetParameter> constructorParameters) {
817 JvmMethodSignature methodSignature = typeMapper.mapSignature(function);
818
819 final Type thisDescriptorType = typeMapper.mapType(descriptor);
820
821 functionCodegen.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() {
822 @Override
823 public void generateBody(
824 @NotNull MethodVisitor mv,
825 @NotNull JvmMethodSignature signature,
826 @NotNull MethodContext context,
827 @Nullable MemberCodegen<?> parentCodegen
828 ) {
829 InstructionAdapter iv = new InstructionAdapter(mv);
830
831 iv.anew(thisDescriptorType);
832 iv.dup();
833
834 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor);
835 assert function.getValueParameters().size() == constructor.getValueParameters().size() :
836 "Number of parameters of copy function and constructor are different. " +
837 "Copy: " + function.getValueParameters().size() + ", " +
838 "constructor: " + constructor.getValueParameters().size();
839
840 MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
841 if (closure != null && closure.getCaptureThis() != null) {
842 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor));
843 iv.load(0, classAsmType);
844 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
845 }
846
847 int parameterIndex = 1; // localVariable 0 = this
848 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
849 Type type = typeMapper.mapType(parameterDescriptor.getType());
850 iv.load(parameterIndex, type);
851 parameterIndex += type.getSize();
852 }
853
854 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getAsmMethod().getDescriptor();
855 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor);
856
857 iv.areturn(thisDescriptorType);
858 }
859 });
860
861 functionCodegen.generateDefaultIfNeeded(
862 context.intoFunction(function), methodSignature, function, OwnerKind.IMPLEMENTATION,
863 new DefaultParameterValueLoader() {
864 @Override
865 public void putValueOnStack(ValueParameterDescriptor valueParameter, ExpressionCodegen codegen) {
866 assert KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration())
867 : "Function container should be annotated with [data]: " + function;
868 PropertyDescriptor property = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter);
869 assert property != null : "Copy function doesn't correspond to any property: " + function;
870 codegen.v.load(0, thisDescriptorType);
871 Type propertyType = typeMapper.mapType(property);
872 codegen.intermediateValueForProperty(property, false, null).put(propertyType, codegen.v);
873 }
874 }
875 );
876 }
877 }
878
879 private void generateEnumMethodsAndConstInitializers() {
880 if (isEnumClass(descriptor)) {
881 generateEnumValuesMethod();
882 generateEnumValueOfMethod();
883 initializeEnumConstants();
884 }
885 }
886
887 private void generateEnumValuesMethod() {
888 Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
889
890 MethodVisitor mv = v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null);
891 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
892
893 mv.visitCode();
894 mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), VALUES, type.getDescriptor());
895 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false);
896 mv.visitTypeInsn(CHECKCAST, type.getInternalName());
897 mv.visitInsn(ARETURN);
898 FunctionCodegen.endVisit(mv, "values()", myClass);
899 }
900
901 private void generateEnumValueOfMethod() {
902 MethodVisitor mv =
903 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
904 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
905
906 mv.visitCode();
907 mv.visitLdcInsn(classAsmType);
908 mv.visitVarInsn(ALOAD, 0);
909 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
910 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName());
911 mv.visitInsn(ARETURN);
912 FunctionCodegen.endVisit(mv, "valueOf()", myClass);
913 }
914
915 protected void generateSyntheticAccessors() {
916 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors();
917 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
918 generateSyntheticAccessor(entry);
919 }
920 }
921
922 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
923 if (entry.getValue() instanceof FunctionDescriptor) {
924 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
925 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
926 functionCodegen.generateMethod(
927 null, typeMapper.mapSignature(bridge), bridge,
928 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) {
929 @Override
930 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
931 generateMethodCallTo(original, codegen.v);
932 codegen.v.areturn(signature.getReturnType());
933 }
934 }
935 );
936 }
937 else if (entry.getValue() instanceof PropertyDescriptor) {
938 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
939 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
940
941 PropertyGetterDescriptor getter = bridge.getGetter();
942 assert getter != null;
943 functionCodegen.generateMethod(null, typeMapper.mapSignature(getter), getter,
944 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
945 @Override
946 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
947 InstructionAdapter iv = codegen.v;
948 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
949 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
950
951 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
952 for (int i = 0, reg = 0; i < argTypes.length; i++) {
953 Type argType = argTypes[i];
954 iv.load(reg, argType);
955 //noinspection AssignmentToForLoopParameter
956 reg += argType.getSize();
957 }
958
959 property.put(property.type, iv);
960 iv.areturn(signature.getReturnType());
961 }
962 });
963
964
965 if (bridge.isVar()) {
966 PropertySetterDescriptor setter = bridge.getSetter();
967 assert setter != null;
968
969 functionCodegen.generateMethod(null, typeMapper.mapSignature(setter), setter,
970 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
971 @Override
972 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
973 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
974 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
975 InstructionAdapter iv = codegen.v;
976
977 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
978 for (int i = 0, reg = 0; i < argTypes.length; i++) {
979 Type argType = argTypes[i];
980 iv.load(reg, argType);
981 //noinspection AssignmentToForLoopParameter
982 reg += argType.getSize();
983 }
984 property.store(property.type, iv);
985
986 iv.areturn(signature.getReturnType());
987 }
988 });
989 }
990 }
991 else {
992 throw new UnsupportedOperationException();
993 }
994 }
995
996 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) {
997 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
998 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor);
999 CallableMethod callableMethod = isConstructor ?
1000 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
1001 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context);
1002
1003 int reg = 1;
1004 if (isConstructor) {
1005 iv.anew(callableMethod.getOwner());
1006 iv.dup();
1007 reg = 0;
1008 }
1009 else if (callFromAccessor) {
1010 iv.load(0, OBJECT_TYPE);
1011 }
1012
1013 for (Type argType : callableMethod.getAsmMethod().getArgumentTypes()) {
1014 iv.load(reg, argType);
1015 reg += argType.getSize();
1016 }
1017 callableMethod.invokeWithoutAssertions(iv);
1018 }
1019
1020 private void generateFieldForSingleton() {
1021 if (isEnumClass(descriptor) || isEnumEntry(descriptor)) return;
1022
1023 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
1024 ClassDescriptor fieldTypeDescriptor;
1025 JetClassOrObject original;
1026 if (isObject(descriptor)) {
1027 original = myClass;
1028 fieldTypeDescriptor = descriptor;
1029 }
1030 else if (classObjectDescriptor != null) {
1031 JetClassObject classObject = ((JetClass) myClass).getClassObject();
1032 assert classObject != null : "Class object not found: " + myClass.getText();
1033 original = classObject.getObjectDeclaration();
1034 fieldTypeDescriptor = classObjectDescriptor;
1035 }
1036 else {
1037 return;
1038 }
1039
1040 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
1041
1042 v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
1043
1044 if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
1045 genInitSingleton(fieldTypeDescriptor, field);
1046 }
1047 }
1048
1049 private void generateClassObjectBackingFieldCopies() {
1050 if (classObjectPropertiesToCopy == null) return;
1051
1052 for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) {
1053 PropertyDescriptor property = info.descriptor;
1054
1055 FieldVisitor fv = v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property),
1056 typeMapper.mapType(property).getDescriptor(), null, info.defaultValue);
1057
1058 AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property);
1059
1060 //This field are always static and final so if it has constant initializer don't do anything in clinit,
1061 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
1062 // TODO: test this code
1063 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && info.defaultValue == null) {
1064 ExpressionCodegen codegen = createOrGetClInitCodegen();
1065 int classObjectIndex = putClassObjectInLocalVar(codegen);
1066 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
1067 copyFieldFromClassObject(property);
1068 }
1069 }
1070 }
1071
1072 private int putClassObjectInLocalVar(ExpressionCodegen codegen) {
1073 FrameMap frameMap = codegen.myFrameMap;
1074 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
1075 int classObjectIndex = frameMap.getIndex(classObjectDescriptor);
1076 if (classObjectIndex == -1) {
1077 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
1078 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
1079 classObject.put(classObject.type, codegen.v);
1080 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
1081 }
1082 return classObjectIndex;
1083 }
1084
1085 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
1086 ExpressionCodegen codegen = createOrGetClInitCodegen();
1087 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
1088 property.put(property.type, codegen.v);
1089 StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true);
1090 field.store(field.type, codegen.v);
1091 }
1092
1093 protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
1094 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1095 ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
1096 ExpressionCodegen codegen = createOrGetClInitCodegen();
1097 FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor);
1098 generateMethodCallTo(fd, codegen.v);
1099 field.store(field.type, codegen.v);
1100 }
1101 }
1102
1103 protected void generatePrimaryConstructor() {
1104 if (ignoreIfTraitOrAnnotation()) return;
1105
1106 if (kind != OwnerKind.IMPLEMENTATION) {
1107 throw new IllegalStateException("incorrect kind for primary constructor: " + kind);
1108 }
1109
1110 final MutableClosure closure = context.closure;
1111 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
1112
1113 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, closure);
1114
1115 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1116 lookupConstructorExpressionsInClosureIfPresent(constructorContext);
1117 }
1118
1119 assert constructorDescriptor != null : "Constructor not found for class: " + descriptor;
1120 final JvmMethodSignature constructorSignature = typeMapper.mapSignature(constructorDescriptor);
1121
1122 functionCodegen.generateMethod(myClass, constructorSignature, constructorDescriptor, constructorContext,
1123 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
1124 @NotNull
1125 @Override
1126 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
1127 return new ConstructorFrameMap(constructorSignature);
1128 }
1129
1130 @Override
1131 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1132 generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
1133 }
1134 }
1135 );
1136
1137 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorSignature, constructorDescriptor,
1138 OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
1139
1140 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor);
1141 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
1142
1143 if (isClassObject(descriptor)) {
1144 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext);
1145 }
1146 }
1147
1148 private void generatePrimaryConstructorImpl(
1149 @Nullable ConstructorDescriptor constructorDescriptor,
1150 @NotNull final ExpressionCodegen codegen,
1151 @Nullable MutableClosure closure
1152 ) {
1153 List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
1154 ? constructorDescriptor.getValueParameters()
1155 : Collections.<ValueParameterDescriptor>emptyList();
1156
1157 InstructionAdapter iv = codegen.v;
1158
1159 if (closure != null) {
1160 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
1161 int k = 1;
1162 for (FieldInfo info : argsFromClosure) {
1163 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
1164 }
1165 }
1166
1167 if (superCall == null) {
1168 genSimpleSuperCall(iv);
1169 }
1170 else if (superCall instanceof JetDelegatorToSuperClass) {
1171 genSuperCallToDelegatorToSuperClass(iv);
1172 }
1173 else {
1174 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
1175 }
1176
1177 int n = 0;
1178 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1179 if (specifier == superCall) {
1180 continue;
1181 }
1182
1183 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1184 genCallToDelegatorByExpressionSpecifier(iv, codegen, n++, specifier);
1185 }
1186 }
1187
1188 int curParam = 0;
1189 List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
1190 for (JetParameter parameter : constructorParameters) {
1191 if (parameter.getValOrVarNode() != null) {
1192 VariableDescriptor descriptor = paramDescrs.get(curParam);
1193 Type type = typeMapper.mapType(descriptor);
1194 iv.load(0, classAsmType);
1195 iv.load(codegen.myFrameMap.getIndex(descriptor), type);
1196 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
1197 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter;
1198 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor), type.getDescriptor());
1199 }
1200 curParam++;
1201 }
1202
1203 boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor);
1204 if (generateInitializerInOuter) {
1205 final ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this);
1206 //generate object$
1207 parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper));
1208 generateInitializers(new Function0<ExpressionCodegen>() {
1209 @Override
1210 public ExpressionCodegen invoke() {
1211 return parentCodegen.createOrGetClInitCodegen();
1212 }
1213 });
1214 } else {
1215 generateInitializers(new Function0<ExpressionCodegen>() {
1216 @Override
1217 public ExpressionCodegen invoke() {
1218 return codegen;
1219 }
1220 });
1221 }
1222
1223 iv.visitInsn(RETURN);
1224 }
1225
1226 private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) {
1227 iv.load(0, superClassAsmType);
1228 JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
1229 List<Type> parameterTypes = new ArrayList<Type>();
1230 assert superType != null;
1231 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1232 if (CodegenBinding.hasThis0(bindingContext, superClassDescriptor)) {
1233 iv.load(1, OBJECT_TYPE);
1234 parameterTypes.add(typeMapper.mapType(
1235 enclosingClassDescriptor(bindingContext, descriptor)));
1236 }
1237 Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
1238 //noinspection ConstantConditions
1239 iv.invokespecial(typeMapper.mapType(superClassDescriptor).getInternalName(), "<init>",
1240 superCallMethod.getDescriptor());
1241 }
1242
1243 private void genSimpleSuperCall(InstructionAdapter iv) {
1244 iv.load(0, superClassAsmType);
1245 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
1246 iv.load(1, JAVA_STRING_TYPE);
1247 iv.load(2, Type.INT_TYPE);
1248 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V");
1249 }
1250 else {
1251 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V");
1252 }
1253 }
1254
1255 private void genCallToDelegatorByExpressionSpecifier(
1256 InstructionAdapter iv,
1257 ExpressionCodegen codegen,
1258 int n,
1259 JetDelegationSpecifier specifier
1260 ) {
1261 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1262 PropertyDescriptor propertyDescriptor = null;
1263 if (expression instanceof JetSimpleNameExpression) {
1264 ResolvedCall<?> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression);
1265 if (call != null) {
1266 CallableDescriptor callResultingDescriptor = call.getResultingDescriptor();
1267 if (callResultingDescriptor instanceof ValueParameterDescriptor) {
1268 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor;
1269 // constructor parameter
1270 if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
1271 // constructor of my class
1272 if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == descriptor) {
1273 propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor);
1274 }
1275 }
1276 }
1277
1278 // todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier
1279 }
1280 }
1281
1282 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
1283 assert superType != null;
1284
1285 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1286 assert superClassDescriptor != null;
1287
1288 StackValue field;
1289 if (propertyDescriptor != null &&
1290 !propertyDescriptor.isVar() &&
1291 Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) {
1292 // final property with backing field
1293 field = StackValue.field(typeMapper.mapType(propertyDescriptor), classAsmType, propertyDescriptor.getName().asString(), false);
1294 }
1295 else {
1296 iv.load(0, classAsmType);
1297 codegen.genToJVMStack(expression);
1298
1299 String delegateField = "$delegate_" + n;
1300 Type fieldType = typeMapper.mapType(superClassDescriptor);
1301 String fieldDesc = fieldType.getDescriptor();
1302
1303 v.newField(specifier, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, delegateField, fieldDesc, /*TODO*/null, null);
1304
1305 field = StackValue.field(fieldType, classAsmType, delegateField, false);
1306 field.store(fieldType, iv);
1307 }
1308
1309 generateDelegates(superClassDescriptor, field);
1310 }
1311
1312 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) {
1313 JetVisitorVoid visitor = new JetVisitorVoid() {
1314 @Override
1315 public void visitJetElement(@NotNull JetElement e) {
1316 e.acceptChildren(this);
1317 }
1318
1319 @Override
1320 public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expr) {
1321 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
1322
1323 DeclarationDescriptor toLookup;
1324 if (isLocalNamedFun(descriptor)) {
1325 toLookup = descriptor;
1326 }
1327 else if (descriptor instanceof CallableMemberDescriptor) {
1328 toLookup = descriptor.getContainingDeclaration();
1329 }
1330 else if (descriptor instanceof VariableDescriptor) {
1331 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor();
1332 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
1333 if (descriptor.equals(parameterDescriptor)) return;
1334 }
1335 toLookup = descriptor;
1336 }
1337 else return;
1338
1339 constructorContext.lookupInContext(toLookup, null, state, true);
1340 }
1341
1342 @Override
1343 public void visitThisExpression(@NotNull JetThisExpression expression) {
1344 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
1345 assert descriptor instanceof CallableDescriptor ||
1346 descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor;
1347 if (context.getCallableDescriptorWithReceiver() != descriptor) {
1348 context.lookupInContext(descriptor, null, state, true);
1349 }
1350 }
1351 };
1352
1353 for (JetDeclaration declaration : myClass.getDeclarations()) {
1354 if (declaration instanceof JetProperty) {
1355 JetProperty property = (JetProperty) declaration;
1356 JetExpression initializer = property.getInitializer();
1357 if (initializer != null) {
1358 initializer.accept(visitor);
1359 }
1360 }
1361 else if (declaration instanceof JetClassInitializer) {
1362 JetClassInitializer initializer = (JetClassInitializer) declaration;
1363 initializer.accept(visitor);
1364 }
1365 }
1366
1367 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1368 if (specifier != superCall) {
1369 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1370 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1371 assert delegateExpression != null;
1372 delegateExpression.accept(visitor);
1373 }
1374 }
1375 else {
1376 if (superCall instanceof JetDelegatorToSuperCall) {
1377 JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList();
1378 if (argumentList != null) {
1379 argumentList.accept(visitor);
1380 }
1381 }
1382 }
1383 }
1384 }
1385
1386 private boolean ignoreIfTraitOrAnnotation() {
1387 if (myClass instanceof JetClass) {
1388 JetClass aClass = (JetClass) myClass;
1389 if (aClass.isTrait()) {
1390 return true;
1391 }
1392 if (aClass.isAnnotation()) {
1393 return true;
1394 }
1395 }
1396 return false;
1397 }
1398
1399 private void generateTraitMethods() {
1400 if (JetPsiUtil.isTrait(myClass)) return;
1401
1402 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1403 if (!(declaration instanceof CallableMemberDescriptor)) continue;
1404
1405 CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
1406 CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember);
1407 if (traitMember == null) continue;
1408
1409 assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
1410
1411 // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here
1412 // with traitMember's modality
1413 CallableMemberDescriptor copy =
1414 inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC,
1415 CallableMemberDescriptor.Kind.DECLARATION, true);
1416
1417 if (traitMember instanceof SimpleFunctionDescriptor) {
1418 generateDelegationToTraitImpl((FunctionDescriptor) traitMember, (FunctionDescriptor) copy);
1419 }
1420 else if (traitMember instanceof PropertyDescriptor) {
1421 for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) {
1422 for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) {
1423 if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind
1424 generateDelegationToTraitImpl(traitAccessor, inheritedAccessor);
1425 }
1426 }
1427 }
1428 }
1429 }
1430 }
1431
1432 private void generateDelegationToTraitImpl(@NotNull final FunctionDescriptor traitFun, @NotNull FunctionDescriptor inheritedFun) {
1433 functionCodegen.generateMethod(
1434 descriptorToDeclaration(bindingContext, traitFun),
1435 typeMapper.mapSignature(inheritedFun),
1436 inheritedFun,
1437 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, inheritedFun) {
1438 @Override
1439 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1440 DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration();
1441 if (!(containingDeclaration instanceof ClassDescriptor)) return;
1442 ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration;
1443 if (containingTrait.getKind() != ClassKind.TRAIT) return;
1444
1445 Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal()).getAsmMethod();
1446
1447 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
1448 Type[] originalArgTypes = traitMethod.getArgumentTypes();
1449
1450 InstructionAdapter iv = codegen.v;
1451 iv.load(0, OBJECT_TYPE);
1452 for (int i = 0, reg = 1; i < argTypes.length; i++) {
1453 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
1454 //noinspection AssignmentToForLoopParameter
1455 reg += argTypes[i].getSize();
1456 }
1457
1458 Type type = getTraitImplThisParameterType(containingTrait, typeMapper);
1459 String desc = traitMethod.getDescriptor().replace("(", "(" + type.getDescriptor());
1460
1461 iv.invokestatic(typeMapper.mapTraitImpl(containingTrait).getInternalName(), traitMethod.getName(), desc);
1462
1463 Type returnType = signature.getReturnType();
1464 StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv);
1465 iv.areturn(returnType);
1466 }
1467 }
1468 );
1469 }
1470
1471 private void generateDelegatorToConstructorCall(
1472 InstructionAdapter iv, ExpressionCodegen codegen,
1473 ConstructorDescriptor constructorDescriptor
1474 ) {
1475 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
1476
1477 iv.load(0, OBJECT_TYPE);
1478
1479 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
1480 iv.load(1, OBJECT_TYPE);
1481 iv.load(2, Type.INT_TYPE);
1482 }
1483
1484 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor);
1485
1486 ResolvedCall<?> resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression());
1487 assert resolvedCall != null;
1488 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
1489
1490 //noinspection SuspiciousMethodCalls
1491 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration());
1492 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) {
1493 iv.load(((ConstructorFrameMap) codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE);
1494 }
1495
1496 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor);
1497
1498 if (isAnonymousObject(descriptor) && superCall instanceof JetDelegatorToSuperCall) {
1499 int nextVar = findFirstSuperArgument(method);
1500 for (Type t : superCallable.getAsmMethod().getArgumentTypes()) {
1501 iv.load(nextVar, t);
1502 nextVar += t.getSize();
1503 }
1504 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall);
1505 }
1506 else {
1507 codegen.invokeMethodWithArguments(null, superCallable, resolvedCall, StackValue.none());
1508 }
1509 }
1510
1511 private static int findFirstSuperArgument(@NotNull CallableMethod method) {
1512 int i = 0;
1513 for (JvmMethodParameterSignature type : method.getValueParameters()) {
1514 if (type.getKind() == JvmMethodParameterKind.SUPER_OF_ANONYMOUS_CALL_PARAM) {
1515 return i + 1; // because of this
1516 }
1517 i += type.getAsmType().getSize();
1518 }
1519 return -1;
1520 }
1521
1522 @Override
1523 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
1524 if (declaration instanceof JetEnumEntry) {
1525 String name = declaration.getName();
1526 assert name != null : "Enum entry has no name: " + declaration.getText();
1527 String desc = "L" + classAsmType.getInternalName() + ";";
1528 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
1529 myEnumConstants.add((JetEnumEntry) declaration);
1530 }
1531
1532 super.generateDeclaration(propertyCodegen, declaration);
1533 }
1534
1535 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
1536
1537 private void initializeEnumConstants() {
1538 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
1539
1540 ExpressionCodegen codegen = createOrGetClInitCodegen();
1541 InstructionAdapter iv = codegen.v;
1542
1543 Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
1544 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, VALUES, arrayAsmType.getDescriptor(), null, null);
1545
1546 iv.iconst(myEnumConstants.size());
1547 iv.newarray(classAsmType);
1548
1549 if (!myEnumConstants.isEmpty()) {
1550 iv.dup();
1551 for (int ordinal = 0, size = myEnumConstants.size(); ordinal < size; ordinal++) {
1552 initializeEnumConstant(codegen, ordinal);
1553 }
1554 }
1555
1556 iv.putstatic(classAsmType.getInternalName(), VALUES, arrayAsmType.getDescriptor());
1557 }
1558
1559 private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) {
1560 InstructionAdapter iv = codegen.v;
1561 JetEnumEntry enumConstant = myEnumConstants.get(ordinal);
1562
1563 iv.dup();
1564 iv.iconst(ordinal);
1565
1566 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant);
1567 assert classDescriptor != null;
1568 Type implClass = typeMapper.mapClass(classDescriptor);
1569
1570 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
1571 if (delegationSpecifiers.size() > 1) {
1572 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
1573 }
1574
1575 iv.anew(implClass);
1576 iv.dup();
1577
1578 iv.aconst(enumConstant.getName());
1579 iv.iconst(ordinal);
1580
1581 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) {
1582 JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
1583 if (!(specifier instanceof JetDelegatorToSuperCall)) {
1584 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
1585 }
1586
1587 ResolvedCall<?> resolvedCall =
1588 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression());
1589 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText();
1590
1591 CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor());
1592
1593 codegen.invokeMethodWithArguments(null, method, resolvedCall, StackValue.none());
1594 }
1595 else {
1596 iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V");
1597 }
1598
1599 iv.dup();
1600 iv.putstatic(classAsmType.getInternalName(), enumConstant.getName(), classAsmType.getDescriptor());
1601 iv.astore(OBJECT_TYPE);
1602 }
1603
1604 protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
1605 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1606 if (declaration instanceof CallableMemberDescriptor) {
1607 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
1608 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
1609 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
1610 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
1611 if (overriddenDescriptor.getContainingDeclaration() == toClass) {
1612 if (declaration instanceof PropertyDescriptor) {
1613 propertyCodegen
1614 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
1615 }
1616 else if (declaration instanceof FunctionDescriptor) {
1617 functionCodegen
1618 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field);
1619 }
1620 }
1621 }
1622 }
1623 }
1624 }
1625 }
1626
1627 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) {
1628 if (classObjectPropertiesToCopy == null) {
1629 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>();
1630 }
1631 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue));
1632 }
1633
1634 private static class PropertyAndDefaultValue {
1635 public final PropertyDescriptor descriptor;
1636 public final Object defaultValue;
1637
1638 public PropertyAndDefaultValue(PropertyDescriptor descriptor, Object defaultValue) {
1639 this.descriptor = descriptor;
1640 this.defaultValue = defaultValue;
1641 }
1642 }
1643 }