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