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