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