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