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