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