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