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