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