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