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