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