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