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 (state.getClassBuilderMode() != ClassBuilderMode.FULL) { 218 return; 219 } 220 221 if (!isTopLevelOrInnerClass(descriptor)) return; 222 223 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getMemberMap())); 224 225 ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); 226 227 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto); 228 229 AnnotationVisitor av = v.getVisitor().visitAnnotation(JvmAnnotationNames.KOTLIN_CLASS.getDescriptor(), true); 230 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); 231 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); 232 for (String string : JavaProtoBufUtil.encodeBytes(data.toBytes())) { 233 array.visit(null, string); 234 } 235 array.visitEnd(); 236 av.visitEnd(); 237 } 238 239 private void writeEnclosingMethod() { 240 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class. 241 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); 242 243 boolean isObjectLiteral = DescriptorUtils.isAnonymous(descriptor); 244 245 boolean isLocalOrAnonymousClass = isObjectLiteral || 246 !(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor); 247 if (isLocalOrAnonymousClass) { 248 String outerClassName = getOuterClassName(descriptor, typeMapper); 249 FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class); 250 251 if (function != null) { 252 Method method = typeMapper.mapSignature(function).getAsmMethod(); 253 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor()); 254 } 255 else { 256 assert isObjectLiteral 257 : "Function descriptor could be null only for object literal in package namespace: " + descriptor.getName(); 258 v.visitOuterClass(outerClassName, null, null); 259 } 260 } 261 } 262 263 @NotNull 264 private static String getOuterClassName( 265 @NotNull ClassDescriptor classDescriptor, 266 @NotNull JetTypeMapper typeMapper 267 ) { 268 ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class); 269 if (container != null) { 270 return typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 271 } 272 else { 273 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), classDescriptor); 274 assert containingFile != null : "Containing file should be present for " + classDescriptor; 275 return NamespaceCodegen.getNamespacePartInternalName(containingFile); 276 } 277 } 278 279 private void writeInnerClasses() { 280 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor); 281 if (result != null) { 282 for (ClassDescriptor innerClass : result) { 283 writeInnerClass(innerClass); 284 } 285 } 286 } 287 288 private void writeOuterClasses() { 289 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information 290 // for each enclosing class and for each immediate member 291 DeclarationDescriptor inner = descriptor; 292 while (true) { 293 if (inner == null || isTopLevelDeclaration(inner)) { 294 break; 295 } 296 if (inner instanceof ClassDescriptor && !isEnumClassObject(inner)) { 297 writeInnerClass((ClassDescriptor) inner); 298 } 299 inner = inner.getContainingDeclaration(); 300 } 301 } 302 303 private void writeInnerClass(@NotNull ClassDescriptor innerClass) { 304 // TODO: proper access 305 int innerClassAccess = getVisibilityAccessFlag(innerClass); 306 if (innerClass.getModality() == Modality.FINAL) { 307 innerClassAccess |= ACC_FINAL; 308 } 309 else if (innerClass.getModality() == Modality.ABSTRACT) { 310 innerClassAccess |= ACC_ABSTRACT; 311 } 312 313 if (innerClass.getKind() == ClassKind.TRAIT) { 314 innerClassAccess |= ACC_INTERFACE; 315 } 316 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) { 317 innerClassAccess |= ACC_ENUM; 318 } 319 320 if (!innerClass.isInner()) { 321 innerClassAccess |= ACC_STATIC; 322 } 323 324 // TODO: cache internal names 325 DeclarationDescriptor containing = innerClass.getContainingDeclaration(); 326 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null; 327 328 String innerClassInternalName; 329 String innerName; 330 331 if (isClassObject(innerClass)) { 332 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME; 333 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX; 334 } 335 else { 336 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); 337 innerClassInternalName = getInternalNameForImpl(innerClass); 338 } 339 340 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess); 341 } 342 343 @NotNull 344 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) { 345 return typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 346 } 347 348 private JvmClassSignature signature() { 349 List<String> superInterfaces; 350 351 LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>(); 352 353 // TODO: generics signature is not always needed 354 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true); 355 356 357 { // type parameters 358 List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters(); 359 typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor); 360 } 361 362 { // superclass 363 signatureVisitor.writeSuperclass(); 364 if (superClassType == null) { 365 signatureVisitor.writeClassBegin(superClassAsmType); 366 signatureVisitor.writeClassEnd(); 367 } 368 else { 369 typeMapper.mapType(superClassType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 370 } 371 signatureVisitor.writeSuperclassEnd(); 372 } 373 374 375 { // superinterfaces 376 superInterfacesLinkedHashSet.add(JvmAbi.JET_OBJECT.getInternalName()); 377 378 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 379 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 380 assert superType != null; 381 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 382 if (isInterface(superClassDescriptor)) { 383 signatureVisitor.writeInterface(); 384 Type jvmName = typeMapper.mapType(superType, signatureVisitor, JetTypeMapperMode.TYPE_PARAMETER); 385 signatureVisitor.writeInterfaceEnd(); 386 superInterfacesLinkedHashSet.add(jvmName.getInternalName()); 387 } 388 } 389 390 superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet); 391 } 392 393 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(), superInterfaces, 394 signatureVisitor.makeJavaGenericSignature()); 395 } 396 397 protected void getSuperClass() { 398 superClassAsmType = AsmTypeConstants.OBJECT_TYPE; 399 superClassType = null; 400 401 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); 402 403 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) { 404 return; 405 } 406 407 if (kind != OwnerKind.IMPLEMENTATION) { 408 throw new IllegalStateException("must be impl to reach this code: " + kind); 409 } 410 411 for (JetDelegationSpecifier specifier : delegationSpecifiers) { 412 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) { 413 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 414 assert superType != null; 415 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 416 assert superClassDescriptor != null; 417 if (!isInterface(superClassDescriptor)) { 418 superClassType = superType; 419 superClassAsmType = typeMapper.mapType(superClassDescriptor.getDefaultType(), JetTypeMapperMode.IMPL); 420 superCall = specifier; 421 } 422 } 423 } 424 425 if (superClassType == null) { 426 if (descriptor.getKind() == ClassKind.ENUM_CLASS) { 427 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType()); 428 superClassAsmType = typeMapper.mapType(superClassType); 429 } 430 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) { 431 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next(); 432 superClassAsmType = typeMapper.mapType(superClassType); 433 } 434 } 435 } 436 437 @Override 438 protected void generateSyntheticParts() { 439 generateFieldForSingleton(); 440 441 generateClassObjectBackingFieldCopies(); 442 443 try { 444 generatePrimaryConstructor(); 445 } 446 catch (CompilationException e) { 447 throw e; 448 } 449 catch (ProcessCanceledException e) { 450 throw e; 451 } 452 catch (RuntimeException e) { 453 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e); 454 } 455 456 generateTraitMethods(); 457 458 generateSyntheticAccessors(); 459 460 generateEnumMethodsAndConstInitializers(); 461 462 generateFunctionsForDataClasses(); 463 464 genClosureFields(context.closure, v, state.getTypeMapper()); 465 } 466 467 private List<PropertyDescriptor> getDataProperties() { 468 ArrayList<PropertyDescriptor> result = Lists.newArrayList(); 469 for (JetParameter parameter : getPrimaryConstructorParameters()) { 470 if (parameter.getValOrVarNode() == null) continue; 471 472 PropertyDescriptor propertyDescriptor = DescriptorUtils.getPropertyDescriptor(parameter, bindingContext); 473 474 result.add(propertyDescriptor); 475 } 476 return result; 477 } 478 479 private void generateFunctionsForDataClasses() { 480 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return; 481 482 generateComponentFunctionsForDataClasses(); 483 generateCopyFunctionForDataClasses(); 484 485 List<PropertyDescriptor> properties = getDataProperties(); 486 if (!properties.isEmpty()) { 487 generateDataClassToStringIfNeeded(properties); 488 generateDataClassHashCodeIfNeeded(properties); 489 generateDataClassEqualsIfNeeded(properties); 490 } 491 } 492 493 private void generateCopyFunctionForDataClasses() { 494 FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, descriptor); 495 if (copyFunction != null) { 496 generateCopyFunction(copyFunction); 497 } 498 } 499 500 private void generateDataClassToStringIfNeeded(List<PropertyDescriptor> properties) { 501 ClassDescriptor stringClass = KotlinBuiltIns.getInstance().getString(); 502 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toString"), stringClass) == null) { 503 generateDataClassToStringMethod(properties); 504 } 505 } 506 507 private void generateDataClassHashCodeIfNeeded(List<PropertyDescriptor> properties) { 508 ClassDescriptor intClass = KotlinBuiltIns.getInstance().getInt(); 509 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("hashCode"), intClass) == null) { 510 generateDataClassHashCodeMethod(properties); 511 } 512 } 513 514 private void generateDataClassEqualsIfNeeded(List<PropertyDescriptor> properties) { 515 ClassDescriptor booleanClass = KotlinBuiltIns.getInstance().getBoolean(); 516 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny(); 517 FunctionDescriptor equalsFunction = getDeclaredFunctionByRawSignature(descriptor, Name.identifier("equals"), booleanClass, anyClass); 518 if (equalsFunction == null) { 519 generateDataClassEqualsMethod(properties); 520 } 521 } 522 523 private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) { 524 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); 525 InstructionAdapter iv = new InstructionAdapter(mv); 526 527 mv.visitCode(); 528 Label eq = new Label(); 529 Label ne = new Label(); 530 531 iv.load(0, OBJECT_TYPE); 532 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 533 iv.ifacmpeq(eq); 534 535 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 536 iv.instanceOf(classAsmType); 537 iv.ifeq(ne); 538 539 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 540 iv.checkcast(classAsmType); 541 iv.store(2, AsmTypeConstants.OBJECT_TYPE); 542 543 for (PropertyDescriptor propertyDescriptor : properties) { 544 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 545 546 genPropertyOnStack(iv, propertyDescriptor, 0); 547 genPropertyOnStack(iv, propertyDescriptor, 2); 548 549 if (asmType.getSort() == Type.ARRAY) { 550 Type elementType = correctElementType(asmType); 551 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 552 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z"); 553 } 554 else { 555 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z"); 556 } 557 } 558 else { 559 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType); 560 value.put(Type.BOOLEAN_TYPE, iv); 561 } 562 563 iv.ifeq(ne); 564 } 565 566 iv.mark(eq); 567 iv.iconst(1); 568 iv.areturn(Type.INT_TYPE); 569 570 iv.mark(ne); 571 iv.iconst(0); 572 iv.areturn(Type.INT_TYPE); 573 574 FunctionCodegen.endVisit(mv, "equals", myClass); 575 } 576 577 private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) { 578 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null); 579 InstructionAdapter iv = new InstructionAdapter(mv); 580 581 mv.visitCode(); 582 boolean first = true; 583 for (PropertyDescriptor propertyDescriptor : properties) { 584 if (!first) { 585 iv.iconst(31); 586 iv.mul(Type.INT_TYPE); 587 } 588 589 genPropertyOnStack(iv, propertyDescriptor, 0); 590 591 Label ifNull = null; 592 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 593 if (!isPrimitive(asmType)) { 594 ifNull = new Label(); 595 iv.dup(); 596 iv.ifnull(ifNull); 597 } 598 599 genHashCode(mv, iv, asmType); 600 601 if (ifNull != null) { 602 Label end = new Label(); 603 iv.goTo(end); 604 iv.mark(ifNull); 605 iv.pop(); 606 iv.iconst(0); 607 iv.mark(end); 608 } 609 610 if (first) { 611 first = false; 612 } 613 else { 614 iv.add(Type.INT_TYPE); 615 } 616 } 617 618 mv.visitInsn(IRETURN); 619 620 FunctionCodegen.endVisit(mv, "hashCode", myClass); 621 } 622 623 private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) { 624 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); 625 InstructionAdapter iv = new InstructionAdapter(mv); 626 627 mv.visitCode(); 628 genStringBuilderConstructor(iv); 629 630 boolean first = true; 631 for (PropertyDescriptor propertyDescriptor : properties) { 632 if (first) { 633 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"="); 634 first = false; 635 } 636 else { 637 iv.aconst(", " + propertyDescriptor.getName().asString()+"="); 638 } 639 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 640 641 Type type = genPropertyOnStack(iv, propertyDescriptor, 0); 642 643 if (type.getSort() == Type.ARRAY) { 644 Type elementType = correctElementType(type); 645 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 646 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;"); 647 type = JAVA_STRING_TYPE; 648 } 649 else { 650 if (elementType.getSort() != Type.CHAR) { 651 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;"); 652 type = JAVA_STRING_TYPE; 653 } 654 } 655 } 656 genInvokeAppendMethod(iv, type); 657 } 658 659 iv.aconst(")"); 660 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 661 662 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); 663 iv.areturn(JAVA_STRING_TYPE); 664 665 FunctionCodegen.endVisit(mv, "toString", myClass); 666 } 667 668 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) { 669 iv.load(index, classAsmType); 670 Method 671 method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod(); 672 673 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor()); 674 return method.getReturnType(); 675 } 676 677 private void generateComponentFunctionsForDataClasses() { 678 if (!myClass.hasPrimaryConstructor() || !KotlinBuiltIns.getInstance().isData(descriptor)) return; 679 680 ConstructorDescriptor constructor = descriptor.getConstructors().iterator().next(); 681 682 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) { 683 FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter); 684 if (function != null) { 685 generateComponentFunction(function, parameter); 686 } 687 } 688 } 689 690 private void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) { 691 JetType returnType = function.getReturnType(); 692 assert returnType != null : "Return type of component function should not be null: " + function; 693 final Type componentType = typeMapper.mapReturnType(returnType); 694 695 JvmMethodSignature signature = typeMapper.mapSignature(function); 696 697 FunctionCodegen fc = new FunctionCodegen(context, v, state); 698 fc.generateMethod(myClass, signature, function, new FunctionGenerationStrategy() { 699 @Override 700 public void generateBody( 701 @NotNull MethodVisitor mv, 702 @NotNull JvmMethodSignature signature, 703 @NotNull MethodContext context 704 ) { 705 InstructionAdapter iv = new InstructionAdapter(mv); 706 if (!componentType.equals(Type.VOID_TYPE)) { 707 iv.load(0, classAsmType); 708 String desc = "()" + componentType.getDescriptor(); 709 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc); 710 } 711 iv.areturn(componentType); 712 } 713 }); 714 } 715 716 private void generateCopyFunction(@NotNull final FunctionDescriptor function) { 717 JvmMethodSignature methodSignature = typeMapper.mapSignature(function); 718 719 final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); 720 721 FunctionCodegen fc = new FunctionCodegen(context, v, state); 722 fc.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() { 723 @Override 724 public void generateBody( 725 @NotNull MethodVisitor mv, 726 @NotNull JvmMethodSignature signature, 727 @NotNull MethodContext context 728 ) { 729 InstructionAdapter iv = new InstructionAdapter(mv); 730 731 iv.anew(thisDescriptorType); 732 iv.dup(); 733 734 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor); 735 assert function.getValueParameters().size() == constructor.getValueParameters().size() : 736 "Number of parameters of copy function and constructor are different. " + 737 "Copy: " + function.getValueParameters().size() + ", " + 738 "constructor: " + constructor.getValueParameters().size(); 739 740 MutableClosure closure = ImplementationBodyCodegen.this.context.closure; 741 if (closure != null && closure.getCaptureThis() != null) { 742 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor)); 743 iv.load(0, classAsmType); 744 iv.getfield(JvmClassName.byType(classAsmType).getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); 745 } 746 747 int parameterIndex = 1; // localVariable 0 = this 748 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) { 749 Type type = typeMapper.mapType(parameterDescriptor.getType()); 750 iv.load(parameterIndex, type); 751 parameterIndex += type.getSize(); 752 } 753 754 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor(); 755 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor); 756 757 iv.areturn(thisDescriptorType); 758 } 759 }); 760 761 MethodContext functionContext = context.intoFunction(function); 762 FunctionCodegen.generateDefaultIfNeeded(functionContext, state, v, methodSignature, function, OwnerKind.IMPLEMENTATION, 763 new DefaultParameterValueLoader() { 764 @Override 765 public void putValueOnStack( 766 ValueParameterDescriptor descriptor, 767 ExpressionCodegen codegen 768 ) { 769 assert (KotlinBuiltIns.getInstance() 770 .isData((ClassDescriptor) function.getContainingDeclaration())) 771 : "Trying to create function with default arguments for function that isn't presented in code for class without data annotation"; 772 PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get( 773 BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor); 774 assert propertyDescriptor != null 775 : "Trying to generate default value for parameter of copy function that doesn't correspond to any property"; 776 codegen.v.load(0, thisDescriptorType); 777 Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType()); 778 codegen.intermediateValueForProperty(propertyDescriptor, false, null) 779 .put(propertyType, codegen.v); 780 } 781 }); 782 } 783 784 private void generateEnumMethodsAndConstInitializers() { 785 if (!myEnumConstants.isEmpty()) { 786 generateEnumMethods(); 787 788 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 789 initializeEnumConstants(createOrGetClInitCodegen()); 790 } 791 } 792 } 793 794 private void generateEnumMethods() { 795 if (myEnumConstants.size() > 0) { 796 { 797 Type type = 798 typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()), 799 JetTypeMapperMode.IMPL); 800 801 MethodVisitor mv = 802 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null); 803 mv.visitCode(); 804 mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor).getInternalName(), 805 VALUES, 806 type.getDescriptor()); 807 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;"); 808 mv.visitTypeInsn(CHECKCAST, type.getInternalName()); 809 mv.visitInsn(ARETURN); 810 FunctionCodegen.endVisit(mv, "values()", myClass); 811 } 812 { 813 814 MethodVisitor mv = 815 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, 816 null); 817 mv.visitCode(); 818 mv.visitLdcInsn(classAsmType); 819 mv.visitVarInsn(ALOAD, 0); 820 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;"); 821 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName()); 822 mv.visitInsn(ARETURN); 823 FunctionCodegen.endVisit(mv, "values()", myClass); 824 } 825 } 826 } 827 828 protected void generateSyntheticAccessors() { 829 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors(); 830 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) { 831 generateSyntheticAccessor(entry); 832 } 833 } 834 835 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) { 836 if (entry.getValue() instanceof FunctionDescriptor) { 837 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); 838 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); 839 functionCodegen.generateMethod(null, typeMapper.mapSignature(bridge), bridge, 840 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) { 841 @Override 842 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 843 generateMethodCallTo(original, codegen.v); 844 845 codegen.v.areturn(signature.getAsmMethod().getReturnType()); 846 } 847 }); 848 } 849 else if (entry.getValue() instanceof PropertyDescriptor) { 850 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); 851 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); 852 853 854 PropertyGetterDescriptor getter = bridge.getGetter(); 855 assert getter != null; 856 functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), getter, 857 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) { 858 @Override 859 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 860 InstructionAdapter iv = codegen.v; 861 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 862 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 863 if (!forceField) { 864 iv.load(0, OBJECT_TYPE); 865 } 866 property.put(property.type, iv); 867 iv.areturn(signature.getAsmMethod().getReturnType()); 868 } 869 }); 870 871 872 if (bridge.isVar()) { 873 PropertySetterDescriptor setter = bridge.getSetter(); 874 assert setter != null; 875 876 functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), setter, 877 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) { 878 @Override 879 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 880 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 881 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 882 InstructionAdapter iv = codegen.v; 883 884 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 885 for (int i = 0, reg = 0; i < argTypes.length; i++) { 886 Type argType = argTypes[i]; 887 iv.load(reg, argType); 888 //noinspection AssignmentToForLoopParameter 889 reg += argType.getSize(); 890 } 891 property.store(property.type, iv); 892 893 iv.areturn(signature.getAsmMethod().getReturnType()); 894 } 895 }); 896 } 897 } 898 else { 899 throw new UnsupportedOperationException(); 900 } 901 } 902 903 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) { 904 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor; 905 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor); 906 CallableMethod callableMethod = isConstructor ? 907 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) : 908 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, 909 isCallInsideSameClassAsDeclared(functionDescriptor, context), 910 isCallInsideSameModuleAsDeclared(functionDescriptor, context), 911 context.getContextKind()); 912 913 Method method = callableMethod.getSignature().getAsmMethod(); 914 Type[] argTypes = method.getArgumentTypes(); 915 916 int reg = 1; 917 if (isConstructor) { 918 iv.anew(callableMethod.getOwner().getAsmType()); 919 iv.dup(); 920 reg = 0; 921 } 922 else if (callFromAccessor) { 923 iv.load(0, OBJECT_TYPE); 924 } 925 926 for (int paramIndex = 0; paramIndex < argTypes.length; paramIndex++) { 927 Type argType = argTypes[paramIndex]; 928 iv.load(reg, argType); 929 //noinspection AssignmentToForLoopParameter 930 reg += argType.getSize(); 931 } 932 callableMethod.invokeWithoutAssertions(iv); 933 } 934 935 private void generateFieldForSingleton() { 936 boolean hasClassObject = descriptor.getClassObjectDescriptor() != null; 937 boolean isEnumClass = DescriptorUtils.isEnumClass(descriptor); 938 boolean isObjectDeclaration = descriptor.getKind() == ClassKind.OBJECT && isNonLiteralObject(myClass) ; 939 940 if (!isObjectDeclaration && !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, 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 Type returnType = methodToGenerate.getReturnType(); 1365 1366 mv.visitCode(); 1367 FrameMap frameMap = context.prepareFrame(typeMapper); 1368 ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state); 1369 codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it? 1370 1371 Type[] argTypes = methodToGenerate.getArgumentTypes(); 1372 Type[] originalArgTypes = methodInTrait.getArgumentTypes(); 1373 1374 InstructionAdapter iv = new InstructionAdapter(mv); 1375 iv.load(0, OBJECT_TYPE); 1376 for (int i = 0, reg = 1; i < argTypes.length; i++) { 1377 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); 1378 //noinspection AssignmentToForLoopParameter 1379 reg += argTypes[i].getSize(); 1380 } 1381 1382 Type type = getTraitImplThisParameterType(containingClass, typeMapper); 1383 String functionDescriptor = methodInTrait.getDescriptor().replace("(", "(" + type.getDescriptor()); 1384 1385 Type tImplType = typeMapper.mapType(containingClass.getDefaultType(), JetTypeMapperMode.TRAIT_IMPL); 1386 1387 iv.invokestatic(tImplType.getInternalName(), methodToGenerate.getName(), functionDescriptor); 1388 StackValue.onStack(methodInTrait.getReturnType()).put(returnType, iv); 1389 iv.areturn(returnType); 1390 1391 FunctionCodegen.endVisit(iv, "trait method", callableDescriptorToDeclaration(bindingContext, fun)); 1392 } 1393 1394 FunctionCodegen.generateBridgeIfNeeded(context, state, v, methodToGenerate, fun); 1395 } 1396 1397 private static class TraitImplDelegateInfo { 1398 private final Method methodToGenerate; 1399 private final Method methodInTrait; 1400 1401 private TraitImplDelegateInfo(@NotNull Method methodToGenerate, @NotNull Method methodInTrait) { 1402 this.methodToGenerate = methodToGenerate; 1403 this.methodInTrait = methodInTrait; 1404 } 1405 } 1406 1407 @NotNull 1408 private TraitImplDelegateInfo getTraitImplDelegateInfo(@NotNull FunctionDescriptor fun) { 1409 if (fun instanceof PropertyAccessorDescriptor) { 1410 PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty(); 1411 PropertyDescriptor original = property.getOriginal(); 1412 if (fun instanceof PropertyGetterDescriptor) { 1413 JvmMethodSignature toGenerate = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION); 1414 JvmMethodSignature inTrait = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); 1415 return new TraitImplDelegateInfo( 1416 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1417 } 1418 else if (fun instanceof PropertySetterDescriptor) { 1419 JvmMethodSignature toGenerate = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION); 1420 JvmMethodSignature inTrait = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); 1421 return new TraitImplDelegateInfo( 1422 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1423 } 1424 else { 1425 throw new IllegalStateException("Accessor is neither getter, nor setter, what is it? " + fun); 1426 } 1427 } 1428 else { 1429 Method function = typeMapper.mapSignature(fun).getAsmMethod(); 1430 Method functionOriginal = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod(); 1431 return new TraitImplDelegateInfo(function, functionOriginal); 1432 } 1433 } 1434 1435 private void generateDelegatorToConstructorCall( 1436 InstructionAdapter iv, ExpressionCodegen codegen, 1437 ConstructorDescriptor constructorDescriptor 1438 ) { 1439 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); 1440 1441 iv.load(0, OBJECT_TYPE); 1442 1443 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) { 1444 iv.load(1, OBJECT_TYPE); 1445 iv.load(2, Type.INT_TYPE); 1446 } 1447 1448 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure); 1449 1450 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1451 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression()); 1452 assert resolvedCall != null; 1453 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1454 1455 //noinspection SuspiciousMethodCalls 1456 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration()); 1457 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper); 1458 1459 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { 1460 iv.load(((ConstructorFrameMap)codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE); 1461 } 1462 1463 if (myClass instanceof JetObjectDeclaration && 1464 superCall instanceof JetDelegatorToSuperCall && 1465 ((JetObjectDeclaration) myClass).isObjectLiteral()) { 1466 int nextVar = findFirstSuperArgument(method); 1467 for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { 1468 iv.load(nextVar, t); 1469 nextVar += t.getSize(); 1470 } 1471 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall); 1472 } 1473 else { 1474 codegen.invokeMethodWithArguments(superCallable, resolvedCall, null, StackValue.none()); 1475 } 1476 } 1477 1478 private static int findFirstSuperArgument(CallableMethod method) { 1479 List<JvmMethodParameterSignature> types = method.getSignature().getKotlinParameterTypes(); 1480 int i = 0; 1481 for (JvmMethodParameterSignature type : types) { 1482 if (type.getKind() == JvmMethodParameterKind.SUPER_CALL_PARAM) { 1483 return i + 1; // because of this 1484 } 1485 i += type.getAsmType().getSize(); 1486 } 1487 return -1; 1488 } 1489 1490 @Override 1491 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) { 1492 if (declaration instanceof JetEnumEntry) { 1493 String name = declaration.getName(); 1494 assert name != null : "Enum entry has no name: " + declaration.getText(); 1495 String desc = "L" + classAsmType.getInternalName() + ";"; 1496 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null); 1497 myEnumConstants.add((JetEnumEntry) declaration); 1498 } 1499 1500 super.generateDeclaration(propertyCodegen, declaration); 1501 } 1502 1503 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>(); 1504 1505 private void initializeEnumConstants(ExpressionCodegen codegen) { 1506 InstructionAdapter iv = codegen.v; 1507 int ordinal = -1; 1508 JetType myType = descriptor.getDefaultType(); 1509 Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL); 1510 1511 assert myEnumConstants.size() > 0; 1512 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(myType); 1513 Type arrayAsmType = typeMapper.mapType(arrayType, JetTypeMapperMode.IMPL); 1514 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$VALUES", arrayAsmType.getDescriptor(), null, null); 1515 1516 iv.iconst(myEnumConstants.size()); 1517 iv.newarray(myAsmType); 1518 iv.dup(); 1519 1520 for (JetEnumEntry enumConstant : myEnumConstants) { 1521 ordinal++; 1522 1523 iv.dup(); 1524 iv.iconst(ordinal); 1525 1526 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant); 1527 assert classDescriptor != null; 1528 String implClass = typeMapper.mapType(classDescriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 1529 1530 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers(); 1531 if (delegationSpecifiers.size() > 1) { 1532 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported"); 1533 } 1534 1535 iv.anew(Type.getObjectType(implClass)); 1536 iv.dup(); 1537 1538 iv.aconst(enumConstant.getName()); 1539 iv.iconst(ordinal); 1540 1541 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { 1542 JetDelegationSpecifier specifier = delegationSpecifiers.get(0); 1543 if (specifier instanceof JetDelegatorToSuperCall) { 1544 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1545 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression()); 1546 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText(); 1547 1548 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1549 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor); 1550 1551 codegen.invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 1552 } 1553 else { 1554 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); 1555 } 1556 } 1557 else { 1558 iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V"); 1559 } 1560 iv.dup(); 1561 iv.putstatic(myAsmType.getInternalName(), enumConstant.getName(), "L" + myAsmType.getInternalName() + ";"); 1562 iv.astore(OBJECT_TYPE); 1563 } 1564 iv.putstatic(myAsmType.getInternalName(), "$VALUES", arrayAsmType.getDescriptor()); 1565 } 1566 1567 public static void generateInitializers( 1568 @NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations, 1569 @NotNull BindingContext bindingContext, @NotNull GenerationState state 1570 ) { 1571 JetTypeMapper typeMapper = state.getTypeMapper(); 1572 for (JetDeclaration declaration : declarations) { 1573 if (declaration instanceof JetProperty) { 1574 if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) { 1575 initializeProperty(codegen, bindingContext, (JetProperty) declaration); 1576 } 1577 } 1578 else if (declaration instanceof JetClassInitializer) { 1579 codegen.gen(((JetClassInitializer) declaration).getBody(), Type.VOID_TYPE); 1580 } 1581 } 1582 } 1583 1584 1585 public static void initializeProperty( 1586 @NotNull ExpressionCodegen codegen, 1587 @NotNull BindingContext bindingContext, 1588 @NotNull JetProperty property 1589 ) { 1590 1591 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property); 1592 assert propertyDescriptor != null; 1593 1594 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1595 assert initializer != null : "shouldInitializeProperty must return false if initializer is null"; 1596 1597 JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor); 1598 1599 StackValue.StackValueWithSimpleReceiver propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER); 1600 1601 if (!propValue.isStatic) { 1602 codegen.v.load(0, OBJECT_TYPE); 1603 } 1604 1605 Type type = codegen.expressionType(initializer); 1606 if (jetType.isNullable()) { 1607 type = boxType(type); 1608 } 1609 codegen.gen(initializer, type); 1610 1611 propValue.store(type, codegen.v); 1612 } 1613 1614 public static boolean shouldWriteFieldInitializer(PropertyDescriptor descriptor, JetTypeMapper mapper) { 1615 //final field of primitive or String type 1616 if (!descriptor.isVar()) { 1617 Type type = mapper.mapType(descriptor.getType()); 1618 return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName()); 1619 } 1620 return false; 1621 } 1622 1623 public static boolean shouldInitializeProperty( 1624 @NotNull JetProperty property, 1625 @NotNull JetTypeMapper typeMapper 1626 ) { 1627 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1628 if (initializer == null) return false; 1629 1630 CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); 1631 if (compileTimeValue == null) return true; 1632 1633 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) typeMapper.getBindingContext().get(BindingContext.VARIABLE, property); 1634 assert propertyDescriptor != null; 1635 1636 //TODO: OPTIMIZATION: don't initialize static final fields 1637 1638 Object value = compileTimeValue.getValue(); 1639 JetType jetType = getPropertyOrDelegateType(typeMapper.getBindingContext(), property, propertyDescriptor); 1640 Type type = typeMapper.mapType(jetType); 1641 return !skipDefaultValue(propertyDescriptor, value, type); 1642 } 1643 1644 @NotNull 1645 private static JetType getPropertyOrDelegateType(@NotNull BindingContext bindingContext, @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { 1646 JetExpression delegateExpression = property.getDelegateExpression(); 1647 if (delegateExpression != null) { 1648 JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression); 1649 assert delegateType != null : "Type of delegate expression should be recorded"; 1650 return delegateType; 1651 } 1652 return descriptor.getType(); 1653 } 1654 1655 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) { 1656 if (isPrimitive(type)) { 1657 if (!propertyDescriptor.getType().isNullable() && value instanceof Number) { 1658 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) { 1659 return true; 1660 } 1661 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) { 1662 return true; 1663 } 1664 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) { 1665 return true; 1666 } 1667 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) { 1668 return true; 1669 } 1670 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) { 1671 return true; 1672 } 1673 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) { 1674 return true; 1675 } 1676 } 1677 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) { 1678 return true; 1679 } 1680 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) { 1681 return true; 1682 } 1683 } 1684 else { 1685 if (value == null) { 1686 return true; 1687 } 1688 } 1689 return false; 1690 } 1691 1692 protected void generateDelegates(ClassDescriptor toClass, StackValue field) { 1693 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1694 if (declaration instanceof CallableMemberDescriptor) { 1695 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; 1696 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) { 1697 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors(); 1698 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) { 1699 if (overriddenDescriptor.getContainingDeclaration() == toClass) { 1700 if (declaration instanceof PropertyDescriptor) { 1701 propertyCodegen 1702 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field); 1703 } 1704 else if (declaration instanceof FunctionDescriptor) { 1705 functionCodegen 1706 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field); 1707 } 1708 } 1709 } 1710 } 1711 } 1712 } 1713 } 1714 1715 1716 /** 1717 * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, 1718 * second is member of trait that contain implementation. 1719 */ 1720 private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { 1721 List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList(); 1722 1723 for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1724 if (!(decl instanceof CallableMemberDescriptor)) { 1725 continue; 1726 } 1727 1728 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl; 1729 if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 1730 continue; 1731 } 1732 1733 Collection<CallableMemberDescriptor> overriddenDeclarations = 1734 OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor); 1735 1736 Collection<CallableMemberDescriptor> filteredOverriddenDeclarations = 1737 OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations)); 1738 1739 int count = 0; 1740 CallableMemberDescriptor candidate = null; 1741 1742 for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { 1743 if (isKindOf(overriddenDeclaration.getContainingDeclaration(), ClassKind.TRAIT) && 1744 overriddenDeclaration.getModality() != Modality.ABSTRACT) { 1745 candidate = overriddenDeclaration; 1746 count++; 1747 } 1748 } 1749 if (candidate == null) { 1750 continue; 1751 } 1752 1753 assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName(); 1754 1755 1756 Collection<JetType> superTypesOfSuperClass = 1757 superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>emptySet(); 1758 ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject(); 1759 assert expectedThisObject != null; 1760 JetType candidateType = expectedThisObject.getType(); 1761 boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType); 1762 1763 if (!implementedInSuperClass) { 1764 r.add(Pair.create(callableMemberDescriptor, candidate)); 1765 } 1766 } 1767 return r; 1768 } 1769 1770 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { 1771 if (classObjectPropertiesToCopy == null) { 1772 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>(); 1773 } 1774 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue)); 1775 } 1776 1777 static class PropertyAndDefaultValue { 1778 1779 PropertyAndDefaultValue(PropertyDescriptor propertyDescriptor, Object defaultValue) { 1780 this.propertyDescriptor = propertyDescriptor; 1781 this.defaultValue = defaultValue; 1782 } 1783 1784 private PropertyDescriptor propertyDescriptor; 1785 1786 private Object defaultValue; 1787 1788 1789 } 1790 }