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