001 /*
002 * Copyright 2010-2013 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.google.common.collect.Sets;
021 import com.intellij.openapi.progress.ProcessCanceledException;
022 import com.intellij.openapi.util.Pair;
023 import com.intellij.psi.PsiElement;
024 import com.intellij.util.ArrayUtil;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.asm4.AnnotationVisitor;
028 import org.jetbrains.asm4.Label;
029 import org.jetbrains.asm4.MethodVisitor;
030 import org.jetbrains.asm4.Type;
031 import org.jetbrains.asm4.commons.InstructionAdapter;
032 import org.jetbrains.asm4.commons.Method;
033 import org.jetbrains.jet.codegen.binding.CalculatedClosure;
034 import org.jetbrains.jet.codegen.binding.CodegenBinding;
035 import org.jetbrains.jet.codegen.binding.MutableClosure;
036 import org.jetbrains.jet.codegen.context.ClassContext;
037 import org.jetbrains.jet.codegen.context.ConstructorContext;
038 import org.jetbrains.jet.codegen.context.MethodContext;
039 import org.jetbrains.jet.codegen.signature.*;
040 import org.jetbrains.jet.codegen.signature.kotlin.JetMethodAnnotationWriter;
041 import org.jetbrains.jet.codegen.state.GenerationState;
042 import org.jetbrains.jet.codegen.state.JetTypeMapper;
043 import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
044 import org.jetbrains.jet.lang.descriptors.*;
045 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
046 import org.jetbrains.jet.lang.psi.*;
047 import org.jetbrains.jet.lang.resolve.BindingContext;
048 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
049 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
050 import org.jetbrains.jet.lang.resolve.OverridingUtil;
051 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
052 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
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.JvmClassName;
056 import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
057 import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
058 import org.jetbrains.jet.lang.resolve.name.Name;
059 import org.jetbrains.jet.lang.types.JetType;
060 import org.jetbrains.jet.lang.types.TypeUtils;
061 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
062 import org.jetbrains.jet.lexer.JetTokens;
063
064 import java.util.*;
065
066 import static org.jetbrains.asm4.Opcodes.*;
067 import static org.jetbrains.jet.codegen.AsmUtil.*;
068 import static org.jetbrains.jet.codegen.CodegenUtil.*;
069 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*;
070 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration;
071 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
072 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
073 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isKindOf;
074 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
075 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
076
077 public class ImplementationBodyCodegen extends ClassBodyCodegen {
078 private static final String VALUES = "$VALUES";
079 private JetDelegationSpecifier superCall;
080 private Type superClassAsmType;
081 @Nullable // null means java/lang/Object
082 private JetType superClassType;
083 private final Type classAsmType;
084
085 private final FunctionCodegen functionCodegen;
086 private final PropertyCodegen propertyCodegen;
087
088 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy;
089
090 public ImplementationBodyCodegen(
091 @NotNull JetClassOrObject aClass,
092 @NotNull ClassContext context,
093 @NotNull ClassBuilder v,
094 @NotNull GenerationState state,
095 @Nullable MemberCodegen parentCodegen
096 ) {
097 super(aClass, context, v, state, parentCodegen);
098 this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL);
099 this.functionCodegen = new FunctionCodegen(context, v, state);
100 this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this);
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.SIGNATURES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
153 // ClassBuilderMode.SIGNATURES 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);
211
212 writeClassSignatureIfNeeded(signature);
213 }
214
215 private void writeEnclosingMethod() {
216 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
217 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
218
219 boolean isObjectLiteral = DescriptorUtils.isAnonymous(descriptor);
220
221 boolean isLocalOrAnonymousClass = isObjectLiteral ||
222 !(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor);
223 if (isLocalOrAnonymousClass) {
224 String outerClassName = getOuterClassName(descriptor, typeMapper);
225 FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class);
226
227 if (function != null) {
228 Method method = typeMapper.mapSignature(function).getAsmMethod();
229 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor());
230 }
231 else {
232 assert isObjectLiteral
233 : "Function descriptor could be null only for object literal in package namespace: " + descriptor.getName();
234 v.visitOuterClass(outerClassName, null, null);
235 }
236 }
237 }
238
239 @NotNull
240 private static String getOuterClassName(
241 @NotNull ClassDescriptor classDescriptor,
242 @NotNull JetTypeMapper typeMapper
243 ) {
244 ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
245 if (container != null) {
246 return typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
247 }
248 else {
249 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), classDescriptor);
250 assert containingFile != null : "Containing file should be present for " + classDescriptor;
251 return NamespaceCodegen.getNamespacePartInternalName(containingFile);
252 }
253 }
254
255 private void writeInnerClasses() {
256 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor);
257 if (result != null) {
258 for (ClassDescriptor innerClass : result) {
259 writeInnerClass(innerClass);
260 }
261 }
262 }
263
264 private void writeOuterClasses() {
265 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
266 // for each enclosing class and for each immediate member
267 DeclarationDescriptor inner = descriptor;
268 while (true) {
269 if (inner == null || isTopLevelDeclaration(inner)) {
270 break;
271 }
272 if (inner instanceof ClassDescriptor && !isEnumClassObject(inner)) {
273 writeInnerClass((ClassDescriptor) inner);
274 }
275 inner = inner.getContainingDeclaration();
276 }
277 }
278
279 private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
280 // TODO: proper access
281 int innerClassAccess = getVisibilityAccessFlag(innerClass);
282 if (innerClass.getModality() == Modality.FINAL) {
283 innerClassAccess |= ACC_FINAL;
284 }
285 else if (innerClass.getModality() == Modality.ABSTRACT) {
286 innerClassAccess |= ACC_ABSTRACT;
287 }
288
289 if (innerClass.getKind() == ClassKind.TRAIT) {
290 innerClassAccess |= ACC_INTERFACE;
291 }
292 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) {
293 innerClassAccess |= ACC_ENUM;
294 }
295
296 if (!innerClass.isInner()) {
297 innerClassAccess |= ACC_STATIC;
298 }
299
300 // TODO: cache internal names
301 DeclarationDescriptor containing = innerClass.getContainingDeclaration();
302 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null;
303
304 String innerClassInternalName;
305 String innerName;
306
307 if (isClassObject(innerClass)) {
308 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME;
309 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX;
310 }
311 else {
312 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString();
313 innerClassInternalName = getInternalNameForImpl(innerClass);
314 }
315
316 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess);
317 }
318
319 @NotNull
320 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) {
321 return typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
322 }
323
324 private void writeClassSignatureIfNeeded(JvmClassSignature signature) {
325 AnnotationVisitor annotationVisitor = v.newAnnotation(JvmStdlibNames.JET_CLASS.getDescriptor(), true);
326 annotationVisitor.visit(JvmStdlibNames.JET_CLASS_SIGNATURE, signature.getKotlinGenericSignature());
327 int flags = getFlagsForVisibility(descriptor.getVisibility()) | getFlagsForClassKind(descriptor);
328 if (JvmStdlibNames.FLAGS_DEFAULT_VALUE != flags) {
329 annotationVisitor.visit(JvmStdlibNames.JET_FLAGS_FIELD, flags);
330 }
331 annotationVisitor.visit(JvmStdlibNames.ABI_VERSION_NAME, JvmAbi.VERSION);
332 annotationVisitor.visitEnd();
333
334 if (descriptor.getKind() == ClassKind.CLASS_OBJECT) {
335 AnnotationVisitor classObjectVisitor = v.newAnnotation(JvmStdlibNames.JET_CLASS_OBJECT.getDescriptor(), true);
336 classObjectVisitor.visitEnd();
337 }
338 }
339
340 private JvmClassSignature signature() {
341 List<String> superInterfaces;
342
343 LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>();
344
345 // TODO: generics signature is not always needed
346 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true);
347
348
349 { // type parameters
350 List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
351 typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor);
352 }
353
354 signatureVisitor.writeSupersStart();
355
356 { // superclass
357 signatureVisitor.writeSuperclass();
358 if (superClassType == null) {
359 signatureVisitor.writeClassBegin(superClassAsmType.getInternalName(), false, false);
360 signatureVisitor.writeClassEnd();
361 }
362 else {
363 typeMapper.mapType(superClassType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
364 }
365 signatureVisitor.writeSuperclassEnd();
366 }
367
368
369 { // superinterfaces
370 superInterfacesLinkedHashSet.add(JvmStdlibNames.JET_OBJECT.getInternalName());
371
372 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
373 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
374 assert superType != null;
375 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
376 if (isInterface(superClassDescriptor)) {
377 signatureVisitor.writeInterface();
378 Type jvmName = typeMapper.mapType(superType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER);
379 signatureVisitor.writeInterfaceEnd();
380 superInterfacesLinkedHashSet.add(jvmName.getInternalName());
381 }
382 }
383
384 superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet);
385 }
386
387 signatureVisitor.writeSupersEnd();
388
389 return new JvmClassSignature(jvmName(), superClassAsmType.getInternalName(), superInterfaces, signatureVisitor.makeJavaGenericSignature(),
390 signatureVisitor.makeKotlinClassSignature());
391 }
392
393 private String jvmName() {
394 if (kind != OwnerKind.IMPLEMENTATION) {
395 throw new IllegalStateException("must not call this method with kind " + kind);
396 }
397 return classAsmType.getInternalName();
398 }
399
400 protected void getSuperClass() {
401 superClassAsmType = AsmTypeConstants.OBJECT_TYPE;
402 superClassType = null;
403
404 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
405
406 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) {
407 return;
408 }
409
410 if (kind != OwnerKind.IMPLEMENTATION) {
411 throw new IllegalStateException("must be impl to reach this code: " + kind);
412 }
413
414 for (JetDelegationSpecifier specifier : delegationSpecifiers) {
415 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
416 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
417 assert superType != null;
418 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
419 assert superClassDescriptor != null;
420 if (!isInterface(superClassDescriptor)) {
421 superClassType = superType;
422 superClassAsmType = typeMapper.mapType(superClassDescriptor.getDefaultType(), JetTypeMapperMode.IMPL);
423 superCall = specifier;
424 }
425 }
426 }
427
428 if (superClassType == null) {
429 if (descriptor.getKind() == ClassKind.ENUM_CLASS) {
430 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType());
431 superClassAsmType = typeMapper.mapType(superClassType);
432 }
433 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) {
434 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next();
435 superClassAsmType = typeMapper.mapType(superClassType);
436 }
437 }
438 }
439
440 @Override
441 protected void generateSyntheticParts() {
442 generateFieldForSingleton();
443
444 generateClassObjectBackingFieldCopies();
445
446 try {
447 generatePrimaryConstructor();
448 }
449 catch (CompilationException e) {
450 throw e;
451 }
452 catch (ProcessCanceledException e) {
453 throw e;
454 }
455 catch (RuntimeException e) {
456 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
457 }
458
459 generateTraitMethods();
460
461 generateSyntheticAccessors();
462
463 generateEnumMethodsAndConstInitializers();
464
465 generateFunctionsForDataClasses();
466
467 genClosureFields(context.closure, v, state.getTypeMapper());
468 }
469
470 private List<PropertyDescriptor> getDataProperties() {
471 ArrayList<PropertyDescriptor> result = Lists.newArrayList();
472 for (JetParameter parameter : getPrimaryConstructorParameters()) {
473 if (parameter.getValOrVarNode() == null) continue;
474
475 PropertyDescriptor propertyDescriptor = DescriptorUtils.getPropertyDescriptor(parameter, bindingContext);
476
477 result.add(propertyDescriptor);
478 }
479 return result;
480 }
481
482 private void generateFunctionsForDataClasses() {
483 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return;
484
485 generateComponentFunctionsForDataClasses();
486 generateCopyFunctionForDataClasses();
487
488 List<PropertyDescriptor> properties = getDataProperties();
489 if (!properties.isEmpty()) {
490 generateDataClassToStringIfNeeded(properties);
491 generateDataClassHashCodeIfNeeded(properties);
492 generateDataClassEqualsIfNeeded(properties);
493 }
494 }
495
496 private void generateCopyFunctionForDataClasses() {
497 FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, descriptor);
498 if (copyFunction != null) {
499 generateCopyFunction(copyFunction);
500 }
501 }
502
503 private void generateDataClassToStringIfNeeded(List<PropertyDescriptor> properties) {
504 ClassDescriptor stringClass = KotlinBuiltIns.getInstance().getString();
505 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toString"), stringClass) == null) {
506 generateDataClassToStringMethod(properties);
507 }
508 }
509
510 private void generateDataClassHashCodeIfNeeded(List<PropertyDescriptor> properties) {
511 ClassDescriptor intClass = KotlinBuiltIns.getInstance().getInt();
512 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("hashCode"), intClass) == null) {
513 generateDataClassHashCodeMethod(properties);
514 }
515 }
516
517 private void generateDataClassEqualsIfNeeded(List<PropertyDescriptor> properties) {
518 ClassDescriptor booleanClass = KotlinBuiltIns.getInstance().getBoolean();
519 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny();
520 FunctionDescriptor equalsFunction = getDeclaredFunctionByRawSignature(descriptor, Name.identifier("equals"), booleanClass, anyClass);
521 if (equalsFunction == null) {
522 generateDataClassEqualsMethod(properties);
523 }
524 }
525
526 private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) {
527 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
528 InstructionAdapter iv = new InstructionAdapter(mv);
529
530 mv.visitCode();
531 Label eq = new Label();
532 Label ne = new Label();
533
534 iv.load(0, OBJECT_TYPE);
535 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
536 iv.ifacmpeq(eq);
537
538 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
539 iv.instanceOf(classAsmType);
540 iv.ifeq(ne);
541
542 iv.load(1, AsmTypeConstants.OBJECT_TYPE);
543 iv.checkcast(classAsmType);
544 iv.store(2, AsmTypeConstants.OBJECT_TYPE);
545
546 for (PropertyDescriptor propertyDescriptor : properties) {
547 Type asmType = typeMapper.mapType(propertyDescriptor.getType());
548
549 genPropertyOnStack(iv, propertyDescriptor, 0);
550 genPropertyOnStack(iv, propertyDescriptor, 2);
551
552 if (asmType.getSort() == Type.ARRAY) {
553 Type elementType = correctElementType(asmType);
554 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
555 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
556 }
557 else {
558 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z");
559 }
560 }
561 else {
562 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType);
563 value.put(Type.BOOLEAN_TYPE, iv);
564 }
565
566 iv.ifeq(ne);
567 }
568
569 iv.mark(eq);
570 iv.iconst(1);
571 iv.areturn(Type.INT_TYPE);
572
573 iv.mark(ne);
574 iv.iconst(0);
575 iv.areturn(Type.INT_TYPE);
576
577 FunctionCodegen.endVisit(mv, "equals", myClass);
578 }
579
580 private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) {
581 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null);
582 InstructionAdapter iv = new InstructionAdapter(mv);
583
584 mv.visitCode();
585 boolean first = true;
586 for (PropertyDescriptor propertyDescriptor : properties) {
587 if (!first) {
588 iv.iconst(31);
589 iv.mul(Type.INT_TYPE);
590 }
591
592 genPropertyOnStack(iv, propertyDescriptor, 0);
593
594 Label ifNull = null;
595 Type asmType = typeMapper.mapType(propertyDescriptor.getType());
596 if (!isPrimitive(asmType)) {
597 ifNull = new Label();
598 iv.dup();
599 iv.ifnull(ifNull);
600 }
601
602 genHashCode(mv, iv, asmType);
603
604 if (ifNull != null) {
605 Label end = new Label();
606 iv.goTo(end);
607 iv.mark(ifNull);
608 iv.pop();
609 iv.iconst(0);
610 iv.mark(end);
611 }
612
613 if (first) {
614 first = false;
615 }
616 else {
617 iv.add(Type.INT_TYPE);
618 }
619 }
620
621 mv.visitInsn(IRETURN);
622
623 FunctionCodegen.endVisit(mv, "hashCode", myClass);
624 }
625
626 private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) {
627 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);
628 InstructionAdapter iv = new InstructionAdapter(mv);
629
630 mv.visitCode();
631 genStringBuilderConstructor(iv);
632
633 boolean first = true;
634 for (PropertyDescriptor propertyDescriptor : properties) {
635 if (first) {
636 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"=");
637 first = false;
638 }
639 else {
640 iv.aconst(", " + propertyDescriptor.getName().asString()+"=");
641 }
642 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
643
644 Type type = genPropertyOnStack(iv, propertyDescriptor, 0);
645
646 if (type.getSort() == Type.ARRAY) {
647 Type elementType = correctElementType(type);
648 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) {
649 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;");
650 type = JAVA_STRING_TYPE;
651 }
652 else {
653 if (elementType.getSort() != Type.CHAR) {
654 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;");
655 type = JAVA_STRING_TYPE;
656 }
657 }
658 }
659 genInvokeAppendMethod(iv, type);
660 }
661
662 iv.aconst(")");
663 genInvokeAppendMethod(iv, JAVA_STRING_TYPE);
664
665 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
666 iv.areturn(JAVA_STRING_TYPE);
667
668 FunctionCodegen.endVisit(mv, "toString", myClass);
669 }
670
671 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) {
672 iv.load(index, classAsmType);
673 Method
674 method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod();
675
676 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor());
677 return method.getReturnType();
678 }
679
680 private void generateComponentFunctionsForDataClasses() {
681 if (!myClass.hasPrimaryConstructor() || !KotlinBuiltIns.getInstance().isData(descriptor)) return;
682
683 ConstructorDescriptor constructor = descriptor.getConstructors().iterator().next();
684
685 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) {
686 FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter);
687 if (function != null) {
688 generateComponentFunction(function, parameter);
689 }
690 }
691 }
692
693 private void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) {
694 JetType returnType = function.getReturnType();
695 assert returnType != null : "Return type of component function should not be null: " + function;
696 final Type componentType = typeMapper.mapReturnType(returnType);
697
698 JvmMethodSignature signature = typeMapper.mapSignature(function);
699
700 FunctionCodegen fc = new FunctionCodegen(context, v, state);
701 fc.generateMethod(myClass, signature, true, function, new FunctionGenerationStrategy() {
702 @Override
703 public void generateBody(
704 @NotNull MethodVisitor mv,
705 @NotNull JvmMethodSignature signature,
706 @NotNull MethodContext context
707 ) {
708 InstructionAdapter iv = new InstructionAdapter(mv);
709 if (!componentType.equals(Type.VOID_TYPE)) {
710 iv.load(0, classAsmType);
711 String desc = "()" + componentType.getDescriptor();
712 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc);
713 }
714 iv.areturn(componentType);
715 }
716 });
717 }
718
719 private void generateCopyFunction(@NotNull final FunctionDescriptor function) {
720 JvmMethodSignature methodSignature = typeMapper.mapSignature(function);
721
722 final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType());
723
724 FunctionCodegen fc = new FunctionCodegen(context, v, state);
725 fc.generateMethod(myClass, methodSignature, true, function, new FunctionGenerationStrategy() {
726 @Override
727 public void generateBody(
728 @NotNull MethodVisitor mv,
729 @NotNull JvmMethodSignature signature,
730 @NotNull MethodContext context
731 ) {
732 InstructionAdapter iv = new InstructionAdapter(mv);
733
734 iv.anew(thisDescriptorType);
735 iv.dup();
736
737 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor);
738 assert function.getValueParameters().size() == constructor.getValueParameters().size() :
739 "Number of parameters of copy function and constructor are different. " +
740 "Copy: " + function.getValueParameters().size() + ", " +
741 "constructor: " + constructor.getValueParameters().size();
742
743 MutableClosure closure = ImplementationBodyCodegen.this.context.closure;
744 if (closure != null && closure.getCaptureThis() != null) {
745 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor));
746 iv.load(0, classAsmType);
747 iv.getfield(JvmClassName.byType(classAsmType).getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor());
748 }
749
750 int parameterIndex = 1; // localVariable 0 = this
751 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) {
752 Type type = typeMapper.mapType(parameterDescriptor.getType());
753 iv.load(parameterIndex, type);
754 parameterIndex += type.getSize();
755 }
756
757 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor();
758 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor);
759
760 iv.areturn(thisDescriptorType);
761 }
762 });
763
764 MethodContext functionContext = context.intoFunction(function);
765 FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION,
766 new DefaultParameterValueLoader() {
767 @Override
768 public void putValueOnStack(
769 ValueParameterDescriptor descriptor,
770 ExpressionCodegen codegen
771 ) {
772 assert (KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration()))
773 : "Trying to create function with default arguments for function that isn't presented in code for class without data annotation";
774 PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get(
775 BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor);
776 assert propertyDescriptor != null
777 : "Trying to generate default value for parameter of copy function that doesn't correspond to any property";
778 codegen.v.load(0, thisDescriptorType);
779 Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType());
780 codegen.intermediateValueForProperty(propertyDescriptor, false, null).put(propertyType, codegen.v);
781 }
782 });
783 }
784
785 private void generateEnumMethodsAndConstInitializers() {
786 if (!myEnumConstants.isEmpty()) {
787 generateEnumMethods();
788
789 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
790 initializeEnumConstants(createOrGetClInitCodegen());
791 }
792 }
793 }
794
795 private void generateEnumMethods() {
796 if (myEnumConstants.size() > 0) {
797 {
798 Type type =
799 typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()),
800 JetTypeMapperMode.IMPL);
801
802 MethodVisitor mv =
803 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null);
804 mv.visitCode();
805 mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor).getInternalName(),
806 VALUES,
807 type.getDescriptor());
808 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;");
809 mv.visitTypeInsn(CHECKCAST, type.getInternalName());
810 mv.visitInsn(ARETURN);
811 FunctionCodegen.endVisit(mv, "values()", myClass);
812 }
813 {
814
815 MethodVisitor mv =
816 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null,
817 null);
818 mv.visitCode();
819 mv.visitLdcInsn(classAsmType);
820 mv.visitVarInsn(ALOAD, 0);
821 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;");
822 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName());
823 mv.visitInsn(ARETURN);
824 FunctionCodegen.endVisit(mv, "values()", myClass);
825 }
826 }
827 }
828
829 protected void generateSyntheticAccessors() {
830 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors();
831 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
832 generateSyntheticAccessor(entry);
833 }
834 }
835
836 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
837 if (entry.getValue() instanceof FunctionDescriptor) {
838 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
839 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
840 functionCodegen.generateMethod(null, typeMapper.mapSignature(bridge), false, bridge,
841 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) {
842 @Override
843 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
844 generateMethodCallTo(original, codegen.v);
845
846 codegen.v.areturn(signature.getAsmMethod().getReturnType());
847 }
848 });
849 }
850 else if (entry.getValue() instanceof PropertyDescriptor) {
851 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue();
852 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey();
853
854
855 PropertyGetterDescriptor getter = bridge.getGetter();
856 assert getter != null;
857 functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, getter,
858 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) {
859 @Override
860 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
861 InstructionAdapter iv = codegen.v;
862 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
863 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
864 if (!forceField) {
865 iv.load(0, OBJECT_TYPE);
866 }
867 property.put(property.type, iv);
868 iv.areturn(signature.getAsmMethod().getReturnType());
869 }
870 });
871
872
873 if (bridge.isVar()) {
874 PropertySetterDescriptor setter = bridge.getSetter();
875 assert setter != null;
876
877 functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), false, setter,
878 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) {
879 @Override
880 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
881 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration());
882 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR);
883 InstructionAdapter iv = codegen.v;
884
885 Type[] argTypes = signature.getAsmMethod().getArgumentTypes();
886 for (int i = 0, reg = 0; i < argTypes.length; i++) {
887 Type argType = argTypes[i];
888 iv.load(reg, argType);
889 //noinspection AssignmentToForLoopParameter
890 reg += argType.getSize();
891 }
892 property.store(property.type, iv);
893
894 iv.areturn(signature.getAsmMethod().getReturnType());
895 }
896 });
897 }
898 }
899 else {
900 throw new UnsupportedOperationException();
901 }
902 }
903
904 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) {
905 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
906 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor);
907 CallableMethod callableMethod = isConstructor ?
908 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
909 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor,
910 isCallInsideSameClassAsDeclared(functionDescriptor, context),
911 isCallInsideSameModuleAsDeclared(functionDescriptor, context),
912 context.getContextKind());
913
914 Method method = callableMethod.getSignature().getAsmMethod();
915 Type[] argTypes = method.getArgumentTypes();
916
917 int reg = 1;
918 if (isConstructor) {
919 iv.anew(callableMethod.getOwner().getAsmType());
920 iv.dup();
921 reg = 0;
922 }
923 else if (callFromAccessor) {
924 iv.load(0, OBJECT_TYPE);
925 }
926
927 for (int paramIndex = 0; paramIndex < argTypes.length; paramIndex++) {
928 Type argType = argTypes[paramIndex];
929 iv.load(reg, argType);
930 //noinspection AssignmentToForLoopParameter
931 reg += argType.getSize();
932 }
933 callableMethod.invokeWithoutAssertions(iv);
934 }
935
936 private void generateFieldForSingleton() {
937 boolean hasClassObject = descriptor.getClassObjectDescriptor() != null;
938 boolean isEnumClass = DescriptorUtils.isEnumClass(descriptor);
939
940 if (!(isNonLiteralObject(myClass) || hasClassObject) || isEnumClass) return;
941
942 ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor;
943 assert fieldTypeDescriptor != null;
944 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper);
945 JetClassOrObject original;
946 if (hasClassObject) {
947 JetClassObject classObject = ((JetClass) myClass).getClassObject();
948 assert classObject != null : myClass.getText();
949 original = classObject.getObjectDeclaration();
950 }
951 else {
952 original = myClass;
953 }
954
955 v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
956
957 if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) {
958 genInitSingleton(fieldTypeDescriptor, field);
959 }
960 }
961
962 private void generateClassObjectBackingFieldCopies() {
963 if (classObjectPropertiesToCopy != null) {
964 for (PropertyAndDefaultValue propertyInfo : classObjectPropertiesToCopy) {
965 PropertyDescriptor propertyDescriptor = propertyInfo.propertyDescriptor;
966
967 v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(propertyDescriptor),
968 typeMapper.mapType(propertyDescriptor).getDescriptor(), null, propertyInfo.defaultValue);
969
970 //This field are always static and final so if it has constant initializer don't do anything in clinit,
971 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4
972 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && propertyInfo.defaultValue == null) {
973 ExpressionCodegen codegen = createOrGetClInitCodegen();
974 int classObjectIndex = putClassObjectInLocalVar(codegen);
975 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v);
976 copyFieldFromClassObject(propertyDescriptor);
977 }
978 }
979 }
980 }
981
982 private int putClassObjectInLocalVar(ExpressionCodegen codegen) {
983 FrameMap frameMap = codegen.myFrameMap;
984 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor();
985 int classObjectIndex = frameMap.getIndex(classObjectDescriptor);
986 if (classObjectIndex == -1) {
987 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE);
988 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper);
989 classObject.put(classObject.type, codegen.v);
990 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v);
991 }
992 return classObjectIndex;
993 }
994
995 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) {
996 ExpressionCodegen codegen = createOrGetClInitCodegen();
997 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null);
998 property.put(property.type, codegen.v);
999 StackValue.Field field = StackValue.field(property.type, JvmClassName.byClassDescriptor(descriptor),
1000 propertyDescriptor.getName().asString(), true);
1001 field.store(field.type, codegen.v);
1002 }
1003
1004 protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
1005 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1006 ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor);
1007 ExpressionCodegen codegen = createOrGetClInitCodegen();
1008 FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor);
1009 generateMethodCallTo(fd, codegen.v);
1010 field.store(field.type, codegen.v);
1011 }
1012 }
1013
1014 protected void generatePrimaryConstructor() {
1015 if (ignoreIfTraitOrAnnotation()) return;
1016
1017 if (kind != OwnerKind.IMPLEMENTATION) {
1018 throw new IllegalStateException("incorrect kind for primary constructor: " + kind);
1019 }
1020
1021 final MutableClosure closure = context.closure;
1022 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
1023
1024 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
1025
1026 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1027 lookupConstructorExpressionsInClosureIfPresent(constructorContext);
1028 }
1029
1030 assert constructorDescriptor != null;
1031 final JvmMethodSignature constructorSignature = typeMapper.mapConstructorSignature(constructorDescriptor, closure);
1032
1033 functionCodegen.generateMethod(null, constructorSignature, true, constructorDescriptor, constructorContext,
1034 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) {
1035
1036 @NotNull
1037 @Override
1038 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) {
1039 return new ConstructorFrameMap(constructorSignature);
1040 }
1041
1042 @Override
1043 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
1044 generatePrimaryConstructorImpl(callableDescriptor, codegen, closure);
1045 }
1046 }
1047 );
1048
1049 FunctionCodegen.generateDefaultIfNeeded(constructorContext, state, v, constructorSignature, constructorDescriptor,
1050 OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT);
1051
1052 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, closure);
1053 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v);
1054
1055 if (isClassObject(descriptor)) {
1056 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, typeMapper);
1057 }
1058 }
1059
1060 private void generatePrimaryConstructorImpl(
1061 @Nullable ConstructorDescriptor constructorDescriptor,
1062 @NotNull ExpressionCodegen codegen,
1063 @Nullable MutableClosure closure
1064 ) {
1065 List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
1066 ? constructorDescriptor.getValueParameters()
1067 : Collections.<ValueParameterDescriptor>emptyList();
1068
1069 InstructionAdapter iv = codegen.v;
1070
1071 JvmClassName className = JvmClassName.byType(classAsmType);
1072
1073 if (superCall == null) {
1074 genSimpleSuperCall(iv);
1075 }
1076 else if (superCall instanceof JetDelegatorToSuperClass) {
1077 genSuperCallToDelegatorToSuperClass(iv);
1078 }
1079 else {
1080 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor);
1081 }
1082
1083 if (closure != null) {
1084 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType);
1085 int k = 1;
1086 for (FieldInfo info : argsFromClosure) {
1087 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv);
1088 }
1089 }
1090
1091 int n = 0;
1092 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1093 if (specifier == superCall) {
1094 continue;
1095 }
1096
1097 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1098 genCallToDelegatorByExpressionSpecifier(iv, codegen, classAsmType, className, n++, specifier);
1099 }
1100 }
1101
1102 int curParam = 0;
1103 List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
1104 for (JetParameter parameter : constructorParameters) {
1105 if (parameter.getValOrVarNode() != null) {
1106 VariableDescriptor descriptor = paramDescrs.get(curParam);
1107 Type type = typeMapper.mapType(descriptor);
1108 iv.load(0, classAsmType);
1109 iv.load(codegen.myFrameMap.getIndex(descriptor), type);
1110 iv.putfield(classAsmType.getInternalName(),
1111 context.getFieldName(DescriptorUtils.getPropertyDescriptor(parameter, bindingContext)),
1112 type.getDescriptor());
1113 }
1114 curParam++;
1115 }
1116
1117 boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor);
1118 if (generateInitializerInOuter) {
1119 ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this);
1120 //generate object$
1121 parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper));
1122 parentCodegen.generateInitializers(parentCodegen.createOrGetClInitCodegen(),
1123 myClass.getDeclarations(), bindingContext, state);
1124 } else {
1125 generateInitializers(codegen, myClass.getDeclarations(), bindingContext, state);
1126 }
1127
1128
1129 iv.visitInsn(RETURN);
1130 }
1131
1132 private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) {
1133 iv.load(0, superClassAsmType);
1134 JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference());
1135 List<Type> parameterTypes = new ArrayList<Type>();
1136 assert superType != null;
1137 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1138 if (CodegenBinding.hasThis0(bindingContext, superClassDescriptor)) {
1139 iv.load(1, OBJECT_TYPE);
1140 parameterTypes.add(typeMapper.mapType(
1141 enclosingClassDescriptor(bindingContext, descriptor)));
1142 }
1143 Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
1144 //noinspection ConstantConditions
1145 iv.invokespecial(typeMapper.mapType(superClassDescriptor).getInternalName(), "<init>",
1146 superCallMethod.getDescriptor());
1147 }
1148
1149 private void genSimpleSuperCall(InstructionAdapter iv) {
1150 iv.load(0, superClassAsmType);
1151 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) {
1152 iv.load(1, JAVA_STRING_TYPE);
1153 iv.load(2, Type.INT_TYPE);
1154 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V");
1155 }
1156 else {
1157 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V");
1158 }
1159 }
1160
1161 private void genCallToDelegatorByExpressionSpecifier(
1162 InstructionAdapter iv,
1163 ExpressionCodegen codegen,
1164 Type classType,
1165 JvmClassName className,
1166 int n,
1167 JetDelegationSpecifier specifier
1168 ) {
1169 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1170 PropertyDescriptor propertyDescriptor = null;
1171 if (expression instanceof JetSimpleNameExpression) {
1172 ResolvedCall<? extends CallableDescriptor> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression);
1173 if (call != null) {
1174 CallableDescriptor callResultingDescriptor = call.getResultingDescriptor();
1175 if (callResultingDescriptor instanceof ValueParameterDescriptor) {
1176 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor;
1177 // constructor parameter
1178 if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) {
1179 // constructor of my class
1180 if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == descriptor) {
1181 propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor);
1182 }
1183 }
1184 }
1185
1186 // todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier
1187 }
1188 }
1189
1190 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
1191 assert superType != null;
1192
1193 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
1194 assert superClassDescriptor != null;
1195
1196 StackValue field;
1197 if (propertyDescriptor != null &&
1198 !propertyDescriptor.isVar() &&
1199 Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) {
1200 // final property with backing field
1201 field = StackValue.field(typeMapper.mapType(propertyDescriptor.getType()), className,
1202 propertyDescriptor.getName().asString(), false);
1203 }
1204 else {
1205 iv.load(0, classType);
1206 codegen.genToJVMStack(expression);
1207
1208 String delegateField = "$delegate_" + n;
1209 Type fieldType = typeMapper.mapType(superClassDescriptor);
1210 String fieldDesc = fieldType.getDescriptor();
1211
1212 v.newField(specifier, ACC_PRIVATE|ACC_FINAL|ACC_SYNTHETIC, delegateField, fieldDesc, /*TODO*/null, null);
1213
1214 field = StackValue.field(fieldType, className, delegateField, false);
1215 field.store(fieldType, iv);
1216 }
1217
1218 generateDelegates(superClassDescriptor, field);
1219 }
1220
1221 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) {
1222 JetVisitorVoid visitor = new JetVisitorVoid() {
1223 @Override
1224 public void visitJetElement(JetElement e) {
1225 e.acceptChildren(this);
1226 }
1227
1228 @Override
1229 public void visitSimpleNameExpression(JetSimpleNameExpression expr) {
1230 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr);
1231 if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) {
1232 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor();
1233 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) {
1234 //noinspection ConstantConditions
1235 if (descriptor.equals(parameterDescriptor)) {
1236 return;
1237 }
1238 }
1239 constructorContext.lookupInContext(descriptor, null, state, true);
1240 } else if (isLocalNamedFun(descriptor)) {
1241 assert descriptor != null;
1242 MutableClassDescriptor classDescriptor =
1243 (MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor();
1244
1245 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getAllCallableMembers()) {
1246 if (descriptor.equals(memberDescriptor)) {
1247 return;
1248 }
1249 }
1250 constructorContext.lookupInContext(descriptor, null, state, true);
1251 }
1252 }
1253
1254 @Override
1255 public void visitThisExpression(JetThisExpression expression) {
1256 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
1257 if (descriptor instanceof ClassDescriptor) {
1258 // @todo for now all our classes are inner so no need to lookup this. change it when we have real inners
1259 }
1260 else {
1261 assert descriptor instanceof CallableDescriptor;
1262 if (context.getCallableDescriptorWithReceiver() != descriptor) {
1263 context.lookupInContext(descriptor, null, state, false);
1264 }
1265 }
1266 }
1267 };
1268
1269 for (JetDeclaration declaration : myClass.getDeclarations()) {
1270 if (declaration instanceof JetProperty) {
1271 JetProperty property = (JetProperty) declaration;
1272 JetExpression initializer = property.getInitializer();
1273 if (initializer != null) {
1274 initializer.accept(visitor);
1275 }
1276 }
1277 else if (declaration instanceof JetClassInitializer) {
1278 JetClassInitializer initializer = (JetClassInitializer) declaration;
1279 initializer.accept(visitor);
1280 }
1281 }
1282
1283 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
1284 if (specifier != superCall) {
1285 if (specifier instanceof JetDelegatorByExpressionSpecifier) {
1286 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression();
1287 assert delegateExpression != null;
1288 delegateExpression.accept(visitor);
1289 }
1290 }
1291 else {
1292 if (superCall instanceof JetDelegatorToSuperCall) {
1293 JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList();
1294 if (argumentList != null) {
1295 argumentList.accept(visitor);
1296 }
1297 }
1298 }
1299 }
1300 }
1301
1302 private boolean ignoreIfTraitOrAnnotation() {
1303 if (myClass instanceof JetClass) {
1304 JetClass aClass = (JetClass) myClass;
1305 if (aClass.isTrait()) {
1306 return true;
1307 }
1308 if (aClass.isAnnotation()) {
1309 return true;
1310 }
1311 }
1312 return false;
1313 }
1314
1315 private void generateTraitMethods() {
1316 if (JetPsiUtil.isTrait(myClass)) {
1317 return;
1318 }
1319
1320 for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) {
1321 if (needDelegates.second instanceof SimpleFunctionDescriptor) {
1322 generateDelegationToTraitImpl((FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first);
1323 }
1324 else if (needDelegates.second instanceof PropertyDescriptor) {
1325 PropertyDescriptor property = (PropertyDescriptor) needDelegates.second;
1326 List<PropertyAccessorDescriptor> inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors();
1327 for (PropertyAccessorDescriptor accessor : property.getAccessors()) {
1328 for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) {
1329 if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind
1330 generateDelegationToTraitImpl(accessor, inheritedAccessor);
1331 }
1332 }
1333 }
1334 }
1335 }
1336 }
1337
1338
1339 private void generateDelegationToTraitImpl(final @NotNull FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) {
1340 DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
1341 if (!(containingDeclaration instanceof ClassDescriptor)) {
1342 return;
1343 }
1344
1345 ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration;
1346 if (containingClass.getKind() != ClassKind.TRAIT) {
1347 return;
1348 }
1349
1350 int flags = ACC_PUBLIC; // TODO.
1351
1352 TraitImplDelegateInfo delegateInfo = getTraitImplDelegateInfo(fun);
1353 Method methodToGenerate = delegateInfo.methodToGenerate;
1354 Method methodInTrait = delegateInfo.methodInTrait;
1355
1356 PsiElement origin = descriptorToDeclaration(bindingContext, fun);
1357 MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null, null);
1358 AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(fun);
1359
1360 if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
1361 genStubCode(mv);
1362 }
1363 else if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
1364 writeAnnotationForDelegateToTraitImpl(fun, inheritedFun, mv);
1365
1366 Type returnType = methodToGenerate.getReturnType();
1367
1368 mv.visitCode();
1369 FrameMap frameMap = context.prepareFrame(typeMapper);
1370 ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state);
1371 codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it?
1372
1373 Type[] argTypes = methodToGenerate.getArgumentTypes();
1374 Type[] originalArgTypes = methodInTrait.getArgumentTypes();
1375
1376 InstructionAdapter iv = new InstructionAdapter(mv);
1377 iv.load(0, OBJECT_TYPE);
1378 for (int i = 0, reg = 1; i < argTypes.length; i++) {
1379 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
1380 //noinspection AssignmentToForLoopParameter
1381 reg += argTypes[i].getSize();
1382 }
1383
1384 Type type = getTraitImplThisParameterType(containingClass, typeMapper);
1385 String functionDescriptor = methodInTrait.getDescriptor().replace("(", "(" + type.getDescriptor());
1386
1387 Type tImplType = typeMapper.mapType(containingClass.getDefaultType(), JetTypeMapperMode.TRAIT_IMPL);
1388
1389 iv.invokestatic(tImplType.getInternalName(), methodToGenerate.getName(), functionDescriptor);
1390 StackValue.onStack(methodInTrait.getReturnType()).put(returnType, iv);
1391 iv.areturn(returnType);
1392
1393 FunctionCodegen.endVisit(iv, "trait method", callableDescriptorToDeclaration(bindingContext, fun));
1394 }
1395
1396 FunctionCodegen.generateBridgeIfNeeded(context, state, v, methodToGenerate, fun);
1397 }
1398
1399 private static class TraitImplDelegateInfo {
1400 private final Method methodToGenerate;
1401 private final Method methodInTrait;
1402
1403 private TraitImplDelegateInfo(@NotNull Method methodToGenerate, @NotNull Method methodInTrait) {
1404 this.methodToGenerate = methodToGenerate;
1405 this.methodInTrait = methodInTrait;
1406 }
1407 }
1408
1409 @NotNull
1410 private TraitImplDelegateInfo getTraitImplDelegateInfo(@NotNull FunctionDescriptor fun) {
1411 if (fun instanceof PropertyAccessorDescriptor) {
1412 PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty();
1413 PropertyDescriptor original = property.getOriginal();
1414 if (fun instanceof PropertyGetterDescriptor) {
1415 JvmPropertyAccessorSignature toGenerate = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION);
1416 JvmPropertyAccessorSignature inTrait = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION);
1417 return new TraitImplDelegateInfo(
1418 toGenerate.getAsmMethod(), inTrait.getAsmMethod());
1419 }
1420 else if (fun instanceof PropertySetterDescriptor) {
1421 JvmPropertyAccessorSignature toGenerate = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION);
1422 JvmPropertyAccessorSignature inTrait = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION);
1423 return new TraitImplDelegateInfo(
1424 toGenerate.getAsmMethod(), inTrait.getAsmMethod());
1425 }
1426 else {
1427 throw new IllegalStateException("Accessor is neither getter, nor setter, what is it? " + fun);
1428 }
1429 }
1430 else {
1431 Method function = typeMapper.mapSignature(fun).getAsmMethod();
1432 Method functionOriginal = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod();
1433 return new TraitImplDelegateInfo(function, functionOriginal);
1434 }
1435 }
1436
1437 private void writeAnnotationForDelegateToTraitImpl(
1438 @NotNull FunctionDescriptor fun,
1439 @NotNull FunctionDescriptor inheritedFun,
1440 @NotNull MethodVisitor mv
1441 ) {
1442 JvmMethodSignature jvmSignature = typeMapper.mapSignature(inheritedFun, true, OwnerKind.IMPLEMENTATION);
1443 JetMethodAnnotationWriter aw = JetMethodAnnotationWriter.visitAnnotation(mv);
1444 int kotlinFlags = getFlagsForVisibility(fun.getVisibility());
1445 if (fun instanceof PropertyAccessorDescriptor) {
1446 kotlinFlags |= JvmStdlibNames.FLAG_PROPERTY_BIT;
1447 aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
1448 aw.writePropertyType(jvmSignature.getKotlinReturnType());
1449 }
1450 else {
1451 aw.writeTypeParameters(jvmSignature.getKotlinTypeParameter());
1452 aw.writeReturnType(jvmSignature.getKotlinReturnType());
1453 }
1454 kotlinFlags |= DescriptorKindUtils.kindToFlags(inheritedFun.getKind());
1455 aw.writeFlags(kotlinFlags);
1456 aw.visitEnd();
1457 }
1458
1459 private void generateDelegatorToConstructorCall(
1460 InstructionAdapter iv, ExpressionCodegen codegen,
1461 ConstructorDescriptor constructorDescriptor
1462 ) {
1463 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
1464
1465 iv.load(0, OBJECT_TYPE);
1466
1467 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) {
1468 iv.load(1, OBJECT_TYPE);
1469 iv.load(2, Type.INT_TYPE);
1470 }
1471
1472 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure);
1473
1474 ResolvedCall<? extends CallableDescriptor> resolvedCall =
1475 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression());
1476 assert resolvedCall != null;
1477 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
1478
1479 //noinspection SuspiciousMethodCalls
1480 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration());
1481 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper);
1482
1483 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) {
1484 iv.load(((ConstructorFrameMap)codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE);
1485 }
1486
1487 if (myClass instanceof JetObjectDeclaration &&
1488 superCall instanceof JetDelegatorToSuperCall &&
1489 ((JetObjectDeclaration) myClass).isObjectLiteral()) {
1490 int nextVar = findFirstSuperArgument(method);
1491 for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
1492 iv.load(nextVar, t);
1493 nextVar += t.getSize();
1494 }
1495 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall);
1496 }
1497 else {
1498 codegen.invokeMethodWithArguments(superCallable, resolvedCall, null, StackValue.none());
1499 }
1500 }
1501
1502 private static int findFirstSuperArgument(CallableMethod method) {
1503 List<JvmMethodParameterSignature> types = method.getSignature().getKotlinParameterTypes();
1504 int i = 0;
1505 for (JvmMethodParameterSignature type : types) {
1506 if (type.getKind() == JvmMethodParameterKind.SUPER_CALL_PARAM) {
1507 return i + 1; // because of this
1508 }
1509 i += type.getAsmType().getSize();
1510 }
1511 return -1;
1512 }
1513
1514 @Override
1515 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) {
1516 if (declaration instanceof JetEnumEntry) {
1517 String name = declaration.getName();
1518 String desc = "L" + classAsmType.getInternalName() + ";";
1519 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
1520 myEnumConstants.add((JetEnumEntry) declaration);
1521 }
1522
1523 super.generateDeclaration(propertyCodegen, declaration);
1524 }
1525
1526 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
1527
1528 private void initializeEnumConstants(ExpressionCodegen codegen) {
1529 InstructionAdapter iv = codegen.v;
1530 int ordinal = -1;
1531 JetType myType = descriptor.getDefaultType();
1532 Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL);
1533
1534 assert myEnumConstants.size() > 0;
1535 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(myType);
1536 Type arrayAsmType = typeMapper.mapType(arrayType, JetTypeMapperMode.IMPL);
1537 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$VALUES", arrayAsmType.getDescriptor(), null, null);
1538
1539 iv.iconst(myEnumConstants.size());
1540 iv.newarray(myAsmType);
1541 iv.dup();
1542
1543 for (JetEnumEntry enumConstant : myEnumConstants) {
1544 ordinal++;
1545
1546 iv.dup();
1547 iv.iconst(ordinal);
1548
1549 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant);
1550 assert classDescriptor != null;
1551 String implClass = typeMapper.mapType(classDescriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
1552
1553 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
1554 if (delegationSpecifiers.size() > 1) {
1555 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
1556 }
1557
1558 iv.anew(Type.getObjectType(implClass));
1559 iv.dup();
1560
1561 iv.aconst(enumConstant.getName());
1562 iv.iconst(ordinal);
1563
1564 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) {
1565 JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
1566 if (specifier instanceof JetDelegatorToSuperCall) {
1567 ResolvedCall<? extends CallableDescriptor> resolvedCall =
1568 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression());
1569 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText();
1570
1571 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
1572 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor);
1573
1574 codegen.invokeMethodWithArguments(method, resolvedCall, null, StackValue.none());
1575 }
1576 else {
1577 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
1578 }
1579 }
1580 else {
1581 iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V");
1582 }
1583 iv.dup();
1584 iv.putstatic(myAsmType.getInternalName(), enumConstant.getName(), "L" + myAsmType.getInternalName() + ";");
1585 iv.astore(OBJECT_TYPE);
1586 }
1587 iv.putstatic(myAsmType.getInternalName(), "$VALUES", arrayAsmType.getDescriptor());
1588 }
1589
1590 public static void generateInitializers(
1591 @NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations,
1592 @NotNull BindingContext bindingContext, @NotNull GenerationState state
1593 ) {
1594 JetTypeMapper typeMapper = state.getTypeMapper();
1595 for (JetDeclaration declaration : declarations) {
1596 if (declaration instanceof JetProperty) {
1597 if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
1598 initializeProperty(codegen, bindingContext, (JetProperty) declaration);
1599 }
1600 }
1601 else if (declaration instanceof JetClassInitializer) {
1602 codegen.gen(((JetClassInitializer) declaration).getBody(), Type.VOID_TYPE);
1603 }
1604 }
1605 }
1606
1607
1608 public static void initializeProperty(
1609 @NotNull ExpressionCodegen codegen,
1610 @NotNull BindingContext bindingContext,
1611 @NotNull JetProperty property
1612 ) {
1613
1614 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property);
1615 assert propertyDescriptor != null;
1616
1617 JetExpression initializer = property.getDelegateExpressionOrInitializer();
1618 assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
1619
1620 JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor);
1621
1622 StackValue.StackValueWithSimpleReceiver propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER);
1623
1624 if (!propValue.isStatic) {
1625 codegen.v.load(0, OBJECT_TYPE);
1626 }
1627
1628 Type type = codegen.expressionType(initializer);
1629 if (jetType.isNullable()) {
1630 type = boxType(type);
1631 }
1632 codegen.gen(initializer, type);
1633
1634 propValue.store(type, codegen.v);
1635 }
1636
1637 public static boolean shouldWriteFieldInitializer(PropertyDescriptor descriptor, JetTypeMapper mapper) {
1638 //final field of primitive or String type
1639 if (!descriptor.isVar()) {
1640 Type type = mapper.mapType(descriptor.getType());
1641 return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName());
1642 }
1643 return false;
1644 }
1645
1646 public static boolean shouldInitializeProperty(
1647 @NotNull JetProperty property,
1648 @NotNull JetTypeMapper typeMapper
1649 ) {
1650 JetExpression initializer = property.getDelegateExpressionOrInitializer();
1651 if (initializer == null) return false;
1652
1653 CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
1654 if (compileTimeValue == null) return true;
1655
1656 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) typeMapper.getBindingContext().get(BindingContext.VARIABLE, property);
1657 assert propertyDescriptor != null;
1658
1659 //TODO: OPTIMIZATION: don't initialize static final fields
1660
1661 Object value = compileTimeValue.getValue();
1662 JetType jetType = getPropertyOrDelegateType(typeMapper.getBindingContext(), property, propertyDescriptor);
1663 Type type = typeMapper.mapType(jetType);
1664 return !skipDefaultValue(propertyDescriptor, value, type);
1665 }
1666
1667 @NotNull
1668 private static JetType getPropertyOrDelegateType(@NotNull BindingContext bindingContext, @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) {
1669 JetExpression delegateExpression = property.getDelegateExpression();
1670 if (delegateExpression != null) {
1671 JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression);
1672 assert delegateType != null : "Type of delegate expression should be recorded";
1673 return delegateType;
1674 }
1675 return descriptor.getType();
1676 }
1677
1678 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) {
1679 if (isPrimitive(type)) {
1680 if (!propertyDescriptor.getType().isNullable() && value instanceof Number) {
1681 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) {
1682 return true;
1683 }
1684 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) {
1685 return true;
1686 }
1687 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) {
1688 return true;
1689 }
1690 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) {
1691 return true;
1692 }
1693 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) {
1694 return true;
1695 }
1696 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) {
1697 return true;
1698 }
1699 }
1700 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) {
1701 return true;
1702 }
1703 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) {
1704 return true;
1705 }
1706 }
1707 else {
1708 if (value == null) {
1709 return true;
1710 }
1711 }
1712 return false;
1713 }
1714
1715 protected void generateDelegates(ClassDescriptor toClass, StackValue field) {
1716 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1717 if (declaration instanceof CallableMemberDescriptor) {
1718 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration;
1719 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) {
1720 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors();
1721 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) {
1722 if (overriddenDescriptor.getContainingDeclaration() == toClass) {
1723 if (declaration instanceof PropertyDescriptor) {
1724 propertyCodegen
1725 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field);
1726 }
1727 else if (declaration instanceof FunctionDescriptor) {
1728 functionCodegen
1729 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field);
1730 }
1731 }
1732 }
1733 }
1734 }
1735 }
1736 }
1737
1738
1739 /**
1740 * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait,
1741 * second is member of trait that contain implementation.
1742 */
1743 private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) {
1744 List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList();
1745
1746 for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
1747 if (!(decl instanceof CallableMemberDescriptor)) {
1748 continue;
1749 }
1750
1751 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl;
1752 if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
1753 continue;
1754 }
1755
1756 Collection<CallableMemberDescriptor> overriddenDeclarations =
1757 OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor);
1758
1759 Collection<CallableMemberDescriptor> filteredOverriddenDeclarations =
1760 OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations));
1761
1762 int count = 0;
1763 CallableMemberDescriptor candidate = null;
1764
1765 for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) {
1766 if (isKindOf(overriddenDeclaration.getContainingDeclaration(), ClassKind.TRAIT) &&
1767 overriddenDeclaration.getModality() != Modality.ABSTRACT) {
1768 candidate = overriddenDeclaration;
1769 count++;
1770 }
1771 }
1772 if (candidate == null) {
1773 continue;
1774 }
1775
1776 assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName();
1777
1778
1779 Collection<JetType> superTypesOfSuperClass =
1780 superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>emptySet();
1781 ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject();
1782 assert expectedThisObject != null;
1783 JetType candidateType = expectedThisObject.getType();
1784 boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType);
1785
1786 if (!implementedInSuperClass) {
1787 r.add(Pair.create(callableMemberDescriptor, candidate));
1788 }
1789 }
1790 return r;
1791 }
1792
1793 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) {
1794 if (classObjectPropertiesToCopy == null) {
1795 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>();
1796 }
1797 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue));
1798 }
1799
1800 static class PropertyAndDefaultValue {
1801
1802 PropertyAndDefaultValue(PropertyDescriptor propertyDescriptor, Object defaultValue) {
1803 this.propertyDescriptor = propertyDescriptor;
1804 this.defaultValue = defaultValue;
1805 }
1806
1807 private PropertyDescriptor propertyDescriptor;
1808
1809 private Object defaultValue;
1810
1811
1812 }
1813
1814 }