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