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