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