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