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