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