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