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