001 /* 002 * Copyright 2010-2014 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.jet.codegen; 018 019 import com.google.common.collect.Lists; 020 import com.intellij.openapi.progress.ProcessCanceledException; 021 import com.intellij.psi.PsiElement; 022 import com.intellij.util.ArrayUtil; 023 import kotlin.*; 024 import org.jetbrains.annotations.NotNull; 025 import org.jetbrains.annotations.Nullable; 026 import org.jetbrains.jet.backend.common.CodegenUtil; 027 import org.jetbrains.jet.backend.common.DataClassMethodGenerator; 028 import org.jetbrains.jet.codegen.binding.MutableClosure; 029 import org.jetbrains.jet.codegen.bridges.BridgesPackage; 030 import org.jetbrains.jet.codegen.context.*; 031 import org.jetbrains.jet.codegen.signature.BothSignatureWriter; 032 import org.jetbrains.jet.codegen.state.GenerationState; 033 import org.jetbrains.jet.codegen.state.JetTypeMapper; 034 import org.jetbrains.jet.descriptors.serialization.BitEncoding; 035 import org.jetbrains.jet.descriptors.serialization.ClassData; 036 import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer; 037 import org.jetbrains.jet.descriptors.serialization.ProtoBuf; 038 import org.jetbrains.jet.lang.descriptors.*; 039 import org.jetbrains.jet.lang.psi.*; 040 import org.jetbrains.jet.lang.resolve.BindingContext; 041 import org.jetbrains.jet.lang.resolve.DeclarationResolver; 042 import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils; 043 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 044 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; 045 import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; 046 import org.jetbrains.jet.lang.resolve.calls.model.DefaultValueArgument; 047 import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument; 048 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 049 import org.jetbrains.jet.lang.resolve.calls.model.VarargValueArgument; 050 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; 051 import org.jetbrains.jet.lang.resolve.java.JvmAbi; 052 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; 053 import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin; 054 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmClassSignature; 055 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterKind; 056 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodParameterSignature; 057 import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; 058 import org.jetbrains.jet.lang.resolve.name.Name; 059 import org.jetbrains.jet.lang.types.*; 060 import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 061 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 062 import org.jetbrains.jet.lexer.JetTokens; 063 import org.jetbrains.org.objectweb.asm.*; 064 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 065 import org.jetbrains.org.objectweb.asm.commons.Method; 066 067 import java.util.*; 068 069 import static org.jetbrains.jet.codegen.AsmUtil.*; 070 import static org.jetbrains.jet.codegen.JvmCodegenUtil.*; 071 import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; 072 import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; 073 import static org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils.descriptorToDeclaration; 074 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 075 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*; 076 import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass; 077 import static org.jetbrains.jet.lang.resolve.java.diagnostics.DiagnosticsPackage.*; 078 import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin.NO_ORIGIN; 079 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 080 081 public class ImplementationBodyCodegen extends ClassBodyCodegen { 082 private static final String ENUM_VALUES_FIELD_NAME = "$VALUES"; 083 private JetDelegatorToSuperCall superCall; 084 private Type superClassAsmType; 085 @Nullable // null means java/lang/Object 086 private JetType superClassType; 087 private final Type classAsmType; 088 089 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy; 090 091 private final List<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>> additionalTasks = 092 new ArrayList<Function2<ImplementationBodyCodegen, ClassBuilder, Unit>>(); 093 094 public ImplementationBodyCodegen( 095 @NotNull JetClassOrObject aClass, 096 @NotNull ClassContext context, 097 @NotNull ClassBuilder v, 098 @NotNull GenerationState state, 099 @Nullable MemberCodegen<?> parentCodegen 100 ) { 101 super(aClass, context, v, state, parentCodegen); 102 this.classAsmType = typeMapper.mapClass(descriptor); 103 } 104 105 @Override 106 protected void generateDeclaration() { 107 getSuperClass(); 108 109 JvmClassSignature signature = signature(); 110 111 boolean isAbstract = false; 112 boolean isInterface = false; 113 boolean isFinal = false; 114 boolean isStatic; 115 boolean isAnnotation = false; 116 boolean isEnum = false; 117 118 if (myClass instanceof JetClass) { 119 JetClass jetClass = (JetClass) myClass; 120 if (jetClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { 121 isAbstract = true; 122 } 123 if (jetClass.isTrait()) { 124 isAbstract = true; 125 isInterface = true; 126 } 127 else if (jetClass.isAnnotation()) { 128 isAbstract = true; 129 isInterface = true; 130 isAnnotation = true; 131 signature.getInterfaces().add("java/lang/annotation/Annotation"); 132 } 133 else if (jetClass.isEnum()) { 134 isAbstract = hasAbstractMembers(descriptor); 135 isEnum = true; 136 } 137 138 if (descriptor.getKind() == ClassKind.OBJECT || descriptor.getKind() == ClassKind.CLASS_OBJECT) { 139 isFinal = true; 140 } 141 142 if (!jetClass.hasModifier(JetTokens.OPEN_KEYWORD) && !isAbstract) { 143 isFinal = true; 144 } 145 isStatic = !jetClass.isInner(); 146 } 147 else { 148 isStatic = myClass.getParent() instanceof JetClassObject; 149 isFinal = true; 150 } 151 152 int access = 0; 153 154 if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES && !DescriptorUtils.isTopLevelDeclaration(descriptor)) { 155 // ClassBuilderMode.LIGHT_CLASSES means we are generating light classes & looking at a nested or inner class 156 // Light class generation is implemented so that Cls-classes only read bare code of classes, 157 // without knowing whether these classes are inner or not (see ClassStubBuilder.EMPTY_STRATEGY) 158 // Thus we must write full accessibility flags on inner classes in this mode 159 access |= getVisibilityAccessFlag(descriptor); 160 // Same for STATIC 161 if (isStatic) { 162 access |= ACC_STATIC; 163 } 164 } 165 else { 166 access |= getVisibilityAccessFlagForClass(descriptor); 167 } 168 if (isAbstract) { 169 access |= ACC_ABSTRACT; 170 } 171 if (isInterface) { 172 access |= ACC_INTERFACE; // ACC_SUPER 173 } 174 else { 175 access |= ACC_SUPER; 176 } 177 if (isFinal) { 178 access |= ACC_FINAL; 179 } 180 if (isAnnotation) { 181 access |= ACC_ANNOTATION; 182 } 183 if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) { 184 access |= ACC_DEPRECATED; 185 } 186 if (isEnum) { 187 for (JetDeclaration declaration : myClass.getDeclarations()) { 188 if (declaration instanceof JetEnumEntry) { 189 if (enumEntryNeedSubclass(state.getBindingContext(), (JetEnumEntry) declaration)) { 190 access &= ~ACC_FINAL; 191 } 192 } 193 } 194 access |= ACC_ENUM; 195 } 196 List<String> interfaces = signature.getInterfaces(); 197 v.defineClass(myClass, V1_6, 198 access, 199 signature.getName(), 200 signature.getJavaGenericSignature(), 201 signature.getSuperclassName(), 202 ArrayUtil.toStringArray(interfaces) 203 ); 204 v.visitSource(myClass.getContainingFile().getName(), null); 205 206 writeEnclosingMethod(); 207 208 writeOuterClasses(); 209 210 writeInnerClasses(); 211 212 AnnotationCodegen.forClass(v.getVisitor(), typeMapper).genAnnotations(descriptor, null); 213 214 generateReflectionObjectFieldIfNeeded(); 215 } 216 217 @Override 218 protected void generateKotlinAnnotation() { 219 if (isAnonymousObject(descriptor)) { 220 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.ANONYMOUS_OBJECT); 221 return; 222 } 223 224 if (!isTopLevelOrInnerClass(descriptor)) { 225 // LOCAL_CLASS is also written to inner classes of local classes 226 writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.LOCAL_CLASS); 227 return; 228 } 229 230 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 231 232 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings())); 233 234 ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); 235 236 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto); 237 238 AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true); 239 //noinspection ConstantConditions 240 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); 241 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); 242 for (String string : BitEncoding.encodeBytes(data.toBytes())) { 243 array.visit(null, string); 244 } 245 array.visitEnd(); 246 av.visitEnd(); 247 } 248 249 private void writeEnclosingMethod() { 250 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class. 251 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); 252 253 boolean isObjectLiteral = DescriptorUtils.isAnonymousObject(descriptor); 254 255 boolean isLocalOrAnonymousClass = isObjectLiteral || 256 !(parentDescriptor instanceof PackageFragmentDescriptor || parentDescriptor instanceof ClassDescriptor); 257 // Do not emit enclosing method in "light-classes mode" since currently we generate local light classes as if they're top level 258 if (isLocalOrAnonymousClass && state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES) { 259 writeOuterClassAndEnclosingMethod(descriptor, descriptor, typeMapper, v); 260 } 261 } 262 263 private void writeInnerClasses() { 264 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor); 265 if (result != null) { 266 for (ClassDescriptor innerClass : result) { 267 writeInnerClass(innerClass); 268 } 269 } 270 } 271 272 private void writeOuterClasses() { 273 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information 274 // for each enclosing class and for each immediate member 275 DeclarationDescriptor inner = descriptor; 276 while (true) { 277 if (inner == null || isTopLevelDeclaration(inner)) { 278 break; 279 } 280 if (inner instanceof ClassDescriptor) { 281 writeInnerClass((ClassDescriptor) inner); 282 } 283 inner = inner.getContainingDeclaration(); 284 } 285 } 286 287 private void writeInnerClass(@NotNull ClassDescriptor innerClass) { 288 DeclarationDescriptor containing = innerClass.getContainingDeclaration(); 289 String outerClassInternalName = 290 containing instanceof ClassDescriptor ? typeMapper.mapClass((ClassDescriptor) containing).getInternalName() : null; 291 292 String innerName = isClassObject(innerClass) 293 ? JvmAbi.CLASS_OBJECT_CLASS_NAME 294 : innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); 295 296 String innerClassInternalName = typeMapper.mapClass(innerClass).getInternalName(); 297 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, calculateInnerClassAccessFlags(innerClass)); 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 List<JetType> interfaceSupertypes = Lists.newArrayList(); 317 boolean explicitKObject = false; 318 319 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 320 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 321 assert superType != null : "No supertype for class: " + myClass.getText(); 322 ClassifierDescriptor classifierDescriptor = superType.getConstructor().getDeclarationDescriptor(); 323 if (classifierDescriptor instanceof ClassDescriptor) { 324 ClassDescriptor superClassDescriptor = (ClassDescriptor) classifierDescriptor; 325 if (isInterface(superClassDescriptor)) { 326 interfaceSupertypes.add(superType); 327 328 if (JvmAbi.K_OBJECT.equalsTo(DescriptorUtils.getFqName(superClassDescriptor))) { 329 explicitKObject = true; 330 } 331 } 332 } 333 } 334 335 LinkedHashSet<String> superInterfaces = new LinkedHashSet<String>(); 336 if (!explicitKObject && !isInterface(descriptor)) { 337 Type kObject = asmTypeByFqNameWithoutInnerClasses(JvmAbi.K_OBJECT); 338 sw.writeInterface(); 339 sw.writeClassBegin(kObject); 340 sw.writeClassEnd(); 341 sw.writeInterfaceEnd(); 342 superInterfaces.add(kObject.getInternalName()); 343 } 344 345 for (JetType supertype : interfaceSupertypes) { 346 sw.writeInterface(); 347 Type jvmName = typeMapper.mapSupertype(supertype, sw); 348 sw.writeInterfaceEnd(); 349 superInterfaces.add(jvmName.getInternalName()); 350 } 351 352 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(), 353 new ArrayList<String>(superInterfaces), 354 sw.makeJavaGenericSignature()); 355 } 356 357 protected void getSuperClass() { 358 superClassAsmType = AsmTypeConstants.OBJECT_TYPE; 359 superClassType = null; 360 361 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); 362 363 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) { 364 return; 365 } 366 367 for (JetDelegationSpecifier specifier : delegationSpecifiers) { 368 if (specifier instanceof JetDelegatorToSuperCall) { 369 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 370 assert superType != null : 371 String.format("No type recorded for \n---\n%s\n---\n", JetPsiUtil.getElementTextWithContext(specifier)); 372 373 ClassifierDescriptor classifierDescriptor = superType.getConstructor().getDeclarationDescriptor(); 374 if (!(classifierDescriptor instanceof ClassDescriptor)) continue; 375 376 ClassDescriptor superClassDescriptor = (ClassDescriptor) classifierDescriptor; 377 if (!isInterface(superClassDescriptor)) { 378 superClassType = superType; 379 superClassAsmType = typeMapper.mapClass(superClassDescriptor); 380 superCall = (JetDelegatorToSuperCall) specifier; 381 } 382 } 383 } 384 385 if (superClassType == null) { 386 if (descriptor.getKind() == ClassKind.ENUM_CLASS) { 387 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType()); 388 superClassAsmType = typeMapper.mapType(superClassType); 389 } 390 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) { 391 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next(); 392 superClassAsmType = typeMapper.mapType(superClassType); 393 } 394 } 395 } 396 397 @Override 398 protected void generateSyntheticParts() { 399 generatePropertyMetadataArrayFieldIfNeeded(classAsmType); 400 401 generateFieldForSingleton(); 402 403 generateClassObjectBackingFieldCopies(); 404 405 DelegationFieldsInfo delegationFieldsInfo = getDelegationFieldsInfo(myClass.getDelegationSpecifiers()); 406 try { 407 generatePrimaryConstructor(delegationFieldsInfo); 408 } 409 catch (CompilationException e) { 410 throw e; 411 } 412 catch (ProcessCanceledException e) { 413 throw e; 414 } 415 catch (RuntimeException e) { 416 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e); 417 } 418 419 generateTraitMethods(); 420 421 generateDelegates(delegationFieldsInfo); 422 423 generateSyntheticAccessors(); 424 425 generateEnumMethodsAndConstInitializers(); 426 427 generateFunctionsForDataClasses(); 428 429 generateBuiltinMethodStubs(); 430 431 generateToArray(); 432 433 genClosureFields(context.closure, v, typeMapper); 434 } 435 436 private void generateReflectionObjectFieldIfNeeded() { 437 if (isAnnotationClass(descriptor)) { 438 // There's a bug in JDK 6 and 7 that prevents us from generating a static field in an annotation class: 439 // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6857918 440 // TODO: make reflection work on annotation classes somehow 441 return; 442 } 443 444 generateReflectionObjectField(state, classAsmType, v, method("kClassFromKotlin", K_CLASS_IMPL_TYPE, getType(Class.class)), 445 JvmAbi.KOTLIN_CLASS_FIELD_NAME, createOrGetClInitCodegen().v); 446 } 447 448 private boolean isGenericToArrayPresent() { 449 Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray")); 450 for (FunctionDescriptor function : functions) { 451 if (CallResolverUtil.isOrOverridesSynthesized(function)) { 452 continue; 453 } 454 455 if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { 456 continue; 457 } 458 459 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(function.getTypeParameters().get(0).getDefaultType()); 460 JetType returnType = function.getReturnType(); 461 assert returnType != null : function.toString(); 462 JetType paramType = function.getValueParameters().get(0).getType(); 463 if (JetTypeChecker.DEFAULT.equalTypes(arrayType, returnType) && JetTypeChecker.DEFAULT.equalTypes(arrayType, paramType)) { 464 return true; 465 } 466 } 467 return false; 468 469 } 470 471 private void generateToArray() { 472 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 473 if (!isSubclass(descriptor, builtIns.getCollection())) return; 474 475 int access = descriptor.getKind() == ClassKind.TRAIT ? 476 ACC_PUBLIC | ACC_ABSTRACT : 477 ACC_PUBLIC; 478 if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) { 479 MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "()[Ljava/lang/Object;", null, null); 480 481 if (descriptor.getKind() != ClassKind.TRAIT) { 482 InstructionAdapter iv = new InstructionAdapter(mv); 483 mv.visitCode(); 484 485 iv.load(0, classAsmType); 486 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false); 487 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 488 489 FunctionCodegen.endVisit(mv, "toArray", myClass); 490 } 491 } 492 493 if (!isGenericToArrayPresent()) { 494 MethodVisitor mv = v.newMethod(NO_ORIGIN, access, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); 495 496 if (descriptor.getKind() != ClassKind.TRAIT) { 497 InstructionAdapter iv = new InstructionAdapter(mv); 498 mv.visitCode(); 499 500 iv.load(0, classAsmType); 501 iv.load(1, Type.getObjectType("[Ljava/lang/Object;")); 502 503 iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", 504 "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false); 505 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 506 507 FunctionCodegen.endVisit(mv, "toArray", myClass); 508 } 509 } 510 } 511 512 private class MethodStubGenerator { 513 private final Set<String> generatedSignatures = new HashSet<String>(); 514 515 public void generate( 516 @NotNull String name, 517 @NotNull String desc, 518 @NotNull ClassifierDescriptor returnedClassifier, 519 @NotNull ClassifierDescriptor... valueParameterClassifiers 520 ) { 521 // avoid generating same signature twice 522 if (!generatedSignatures.add(name + desc)) return; 523 if (CodegenUtil.getDeclaredFunctionByRawSignature( 524 descriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers) == null) { 525 int access = descriptor.getKind() == ClassKind.TRAIT ? 526 ACC_PUBLIC | ACC_ABSTRACT : 527 ACC_PUBLIC; 528 MethodVisitor mv = v.newMethod(NO_ORIGIN, access, name, desc, null, null); 529 if (descriptor.getKind() != ClassKind.TRAIT) { 530 mv.visitCode(); 531 genThrow(new InstructionAdapter(mv), "java/lang/UnsupportedOperationException", "Mutating immutable collection"); 532 FunctionCodegen.endVisit(mv, "built-in stub for " + name + desc, null); 533 } 534 } 535 } 536 } 537 538 private void generateBuiltinMethodStubs() { 539 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 540 MethodStubGenerator methodStubs = new MethodStubGenerator(); 541 if (isSubclass(descriptor, builtIns.getCollection())) { 542 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getCollection(), 0); 543 544 methodStubs.generate("add", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), classifier); 545 methodStubs.generate("remove", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), builtIns.getAny()); 546 methodStubs.generate("addAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 547 methodStubs.generate("removeAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 548 methodStubs.generate("retainAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 549 methodStubs.generate("clear", "()V", builtIns.getUnit()); 550 } 551 552 if (isSubclass(descriptor, builtIns.getList())) { 553 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getList(), 0); 554 555 methodStubs.generate("set", "(ILjava/lang/Object;)Ljava/lang/Object;", classifier, builtIns.getInt(), classifier); 556 methodStubs.generate("add", "(ILjava/lang/Object;)V", builtIns.getUnit(), builtIns.getInt(), classifier); 557 methodStubs.generate("remove", "(I)Ljava/lang/Object;", classifier, builtIns.getInt()); 558 } 559 560 if (isSubclass(descriptor, builtIns.getMap())) { 561 ClassifierDescriptor keyClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 0); 562 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 1); 563 564 methodStubs.generate("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, keyClassifier, 565 valueClassifier); 566 methodStubs.generate("remove", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, builtIns.getAny()); 567 methodStubs.generate("putAll", "(Ljava/util/Map;)V", builtIns.getUnit(), builtIns.getMap()); 568 methodStubs.generate("clear", "()V", builtIns.getUnit()); 569 } 570 571 if (isSubclass(descriptor, builtIns.getMapEntry())) { 572 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMapEntry(), 1); 573 574 methodStubs.generate("setValue", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, valueClassifier); 575 } 576 577 if (isSubclass(descriptor, builtIns.getIterator())) { 578 methodStubs.generate("remove", "()V", builtIns.getUnit()); 579 } 580 } 581 582 @NotNull 583 private ClassifierDescriptor getSubstituteForTypeParameterOf(@NotNull ClassDescriptor trait, int index) { 584 TypeParameterDescriptor listTypeParameter = trait.getTypeConstructor().getParameters().get(index); 585 TypeSubstitutor deepSubstitutor = SubstitutionUtils.buildDeepSubstitutor(descriptor.getDefaultType()); 586 TypeProjection substitute = deepSubstitutor.substitute(new TypeProjectionImpl(listTypeParameter.getDefaultType())); 587 assert substitute != null : "Couldn't substitute: " + descriptor; 588 ClassifierDescriptor classifier = substitute.getType().getConstructor().getDeclarationDescriptor(); 589 assert classifier != null : "No classifier: " + substitute.getType(); 590 return classifier; 591 } 592 593 private void generateFunctionsForDataClasses() { 594 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return; 595 596 new DataClassMethodGeneratorImpl(myClass, bindingContext).generate(); 597 } 598 599 private class DataClassMethodGeneratorImpl extends DataClassMethodGenerator { 600 DataClassMethodGeneratorImpl( 601 JetClassOrObject klass, 602 BindingContext bindingContext 603 ) { 604 super(klass, bindingContext); 605 } 606 607 @Override 608 public void generateEqualsMethod(@NotNull List<PropertyDescriptor> properties) { 609 FunctionDescriptor equalsFunction = CodegenUtil.getDeclaredFunctionByRawSignature( 610 descriptor, Name.identifier(CodegenUtil.EQUALS_METHOD_NAME), 611 KotlinBuiltIns.getInstance().getBoolean(), 612 KotlinBuiltIns.getInstance().getAny() 613 ); 614 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(equalsFunction); 615 MethodVisitor mv = v.newMethod(OtherOrigin(equalsFunction), ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); 616 InstructionAdapter iv = new InstructionAdapter(mv); 617 618 mv.visitCode(); 619 Label eq = new Label(); 620 Label ne = new Label(); 621 622 iv.load(0, OBJECT_TYPE); 623 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 624 iv.ifacmpeq(eq); 625 626 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 627 iv.instanceOf(classAsmType); 628 iv.ifeq(ne); 629 630 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 631 iv.checkcast(classAsmType); 632 iv.store(2, AsmTypeConstants.OBJECT_TYPE); 633 634 for (PropertyDescriptor propertyDescriptor : properties) { 635 Type asmType = typeMapper.mapType(propertyDescriptor); 636 637 genPropertyOnStack(iv, context, propertyDescriptor, 0); 638 genPropertyOnStack(iv, context, propertyDescriptor, 2); 639 640 if (asmType.getSort() == Type.ARRAY) { 641 Type elementType = correctElementType(asmType); 642 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 643 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z", false); 644 } 645 else { 646 iv.invokestatic("java/util/Arrays", "equals", 647 "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z", false); 648 } 649 } 650 else { 651 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType); 652 value.put(Type.BOOLEAN_TYPE, iv); 653 } 654 655 iv.ifeq(ne); 656 } 657 658 iv.mark(eq); 659 iv.iconst(1); 660 iv.areturn(Type.INT_TYPE); 661 662 iv.mark(ne); 663 iv.iconst(0); 664 iv.areturn(Type.INT_TYPE); 665 666 FunctionCodegen.endVisit(mv, "equals", myClass); 667 } 668 669 @Override 670 public void generateHashCodeMethod(@NotNull List<PropertyDescriptor> properties) { 671 FunctionDescriptor hashCodeFunction = CodegenUtil.getDeclaredFunctionByRawSignature( 672 descriptor, Name.identifier(CodegenUtil.HASH_CODE_METHOD_NAME), 673 KotlinBuiltIns.getInstance().getInt() 674 ); 675 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(hashCodeFunction); 676 MethodVisitor mv = v.newMethod(OtherOrigin(hashCodeFunction), ACC_PUBLIC, "hashCode", "()I", null, null); 677 InstructionAdapter iv = new InstructionAdapter(mv); 678 679 mv.visitCode(); 680 boolean first = true; 681 for (PropertyDescriptor propertyDescriptor : properties) { 682 if (!first) { 683 iv.iconst(31); 684 iv.mul(Type.INT_TYPE); 685 } 686 687 genPropertyOnStack(iv, context, propertyDescriptor, 0); 688 689 Label ifNull = null; 690 Type asmType = typeMapper.mapType(propertyDescriptor); 691 if (!isPrimitive(asmType)) { 692 ifNull = new Label(); 693 iv.dup(); 694 iv.ifnull(ifNull); 695 } 696 697 genHashCode(mv, iv, asmType); 698 699 if (ifNull != null) { 700 Label end = new Label(); 701 iv.goTo(end); 702 iv.mark(ifNull); 703 iv.pop(); 704 iv.iconst(0); 705 iv.mark(end); 706 } 707 708 if (first) { 709 first = false; 710 } 711 else { 712 iv.add(Type.INT_TYPE); 713 } 714 } 715 716 mv.visitInsn(IRETURN); 717 718 FunctionCodegen.endVisit(mv, "hashCode", myClass); 719 } 720 721 @Override 722 public void generateToStringMethod(@NotNull List<PropertyDescriptor> properties) { 723 FunctionDescriptor toString = CodegenUtil.getDeclaredFunctionByRawSignature( 724 descriptor, Name.identifier(CodegenUtil.TO_STRING_METHOD_NAME), 725 KotlinBuiltIns.getInstance().getString() 726 ); 727 MethodContext context = ImplementationBodyCodegen.this.context.intoFunction(toString); 728 MethodVisitor mv = v.newMethod(OtherOrigin(toString), ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); 729 InstructionAdapter iv = new InstructionAdapter(mv); 730 731 mv.visitCode(); 732 genStringBuilderConstructor(iv); 733 734 boolean first = true; 735 for (PropertyDescriptor propertyDescriptor : properties) { 736 if (first) { 737 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"="); 738 first = false; 739 } 740 else { 741 iv.aconst(", " + propertyDescriptor.getName().asString() + "="); 742 } 743 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 744 745 Type type = genPropertyOnStack(iv, context, propertyDescriptor, 0); 746 747 if (type.getSort() == Type.ARRAY) { 748 Type elementType = correctElementType(type); 749 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 750 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;", false); 751 type = JAVA_STRING_TYPE; 752 } 753 else { 754 if (elementType.getSort() != Type.CHAR) { 755 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;", false); 756 type = JAVA_STRING_TYPE; 757 } 758 } 759 } 760 genInvokeAppendMethod(iv, type); 761 } 762 763 iv.aconst(")"); 764 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 765 766 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false); 767 iv.areturn(JAVA_STRING_TYPE); 768 769 FunctionCodegen.endVisit(mv, "toString", myClass); 770 } 771 772 private Type genPropertyOnStack(InstructionAdapter iv, MethodContext context, @NotNull PropertyDescriptor propertyDescriptor, int index) { 773 iv.load(index, classAsmType); 774 if (couldUseDirectAccessToProperty(propertyDescriptor, /* forGetter = */ true, /* isDelegated = */ false, context)) { 775 Type type = typeMapper.mapType(propertyDescriptor.getType()); 776 String fieldName = ((FieldOwnerContext) context.getParentContext()).getFieldName(propertyDescriptor, false); 777 iv.getfield(classAsmType.getInternalName(), fieldName, type.getDescriptor()); 778 return type.getReturnType(); 779 } 780 else { 781 //noinspection ConstantConditions 782 Method method = typeMapper.mapSignature(propertyDescriptor.getGetter()).getAsmMethod(); 783 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor(), false); 784 return method.getReturnType(); 785 } 786 } 787 788 @Override 789 public void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) { 790 PsiElement originalElement = DescriptorToSourceUtils.descriptorToDeclaration(parameter); 791 functionCodegen.generateMethod(OtherOrigin(originalElement, function), typeMapper.mapSignature(function), function, new FunctionGenerationStrategy() { 792 @Override 793 public void generateBody( 794 @NotNull MethodVisitor mv, 795 @NotNull FrameMap frameMap, 796 @NotNull JvmMethodSignature signature, 797 @NotNull MethodContext context, 798 @NotNull MemberCodegen<?> parentCodegen 799 ) { 800 Type componentType = signature.getReturnType(); 801 InstructionAdapter iv = new InstructionAdapter(mv); 802 if (!componentType.equals(Type.VOID_TYPE)) { 803 PropertyDescriptor property = 804 bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, descriptorToDeclaration(parameter)); 805 assert property != null : "Property descriptor is not found for primary constructor parameter: " + parameter; 806 807 genPropertyOnStack(iv, context, property, 0); 808 } 809 iv.areturn(componentType); 810 } 811 }); 812 } 813 814 @Override 815 public void generateCopyFunction(@NotNull final FunctionDescriptor function, @NotNull List<JetParameter> constructorParameters) { 816 JvmMethodSignature methodSignature = typeMapper.mapSignature(function); 817 818 final Type thisDescriptorType = typeMapper.mapType(descriptor); 819 820 functionCodegen.generateMethod(OtherOrigin(myClass, function), methodSignature, function, new FunctionGenerationStrategy() { 821 @Override 822 public void generateBody( 823 @NotNull MethodVisitor mv, 824 @NotNull FrameMap frameMap, 825 @NotNull JvmMethodSignature signature, 826 @NotNull MethodContext context, 827 @NotNull MemberCodegen<?> parentCodegen 828 ) { 829 InstructionAdapter iv = new InstructionAdapter(mv); 830 831 iv.anew(thisDescriptorType); 832 iv.dup(); 833 834 ConstructorDescriptor constructor = DeclarationResolver.getConstructorOfDataClass(descriptor); 835 assert function.getValueParameters().size() == constructor.getValueParameters().size() : 836 "Number of parameters of copy function and constructor are different. " + 837 "Copy: " + function.getValueParameters().size() + ", " + 838 "constructor: " + constructor.getValueParameters().size(); 839 840 MutableClosure closure = ImplementationBodyCodegen.this.context.closure; 841 if (closure != null) { 842 ClassDescriptor captureThis = closure.getCaptureThis(); 843 if (captureThis != null) { 844 iv.load(0, classAsmType); 845 Type type = typeMapper.mapType(captureThis); 846 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); 847 } 848 } 849 850 int parameterIndex = 1; // localVariable 0 = this 851 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) { 852 Type type = typeMapper.mapType(parameterDescriptor.getType()); 853 iv.load(parameterIndex, type); 854 parameterIndex += type.getSize(); 855 } 856 857 Method constructorAsmMethod = typeMapper.mapSignature(constructor).getAsmMethod(); 858 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorAsmMethod.getDescriptor(), false); 859 860 iv.areturn(thisDescriptorType); 861 } 862 }); 863 864 functionCodegen.generateDefaultIfNeeded( 865 context.intoFunction(function), methodSignature, function, OwnerKind.IMPLEMENTATION, 866 new DefaultParameterValueLoader() { 867 @Override 868 public void putValueOnStack(ValueParameterDescriptor valueParameter, ExpressionCodegen codegen) { 869 assert KotlinBuiltIns.getInstance().isData((ClassDescriptor) function.getContainingDeclaration()) 870 : "Function container should be annotated with [data]: " + function; 871 PropertyDescriptor property = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameter); 872 assert property != null : "Copy function doesn't correspond to any property: " + function; 873 codegen.v.load(0, thisDescriptorType); 874 Type propertyType = typeMapper.mapType(property); 875 codegen.intermediateValueForProperty(property, false, null).put(propertyType, codegen.v); 876 } 877 }, 878 null 879 ); 880 } 881 } 882 883 private void generateEnumMethodsAndConstInitializers() { 884 if (isEnumClass(descriptor)) { 885 generateEnumValuesMethod(); 886 generateEnumValueOfMethod(); 887 initializeEnumConstants(); 888 } 889 } 890 891 private void generateEnumValuesMethod() { 892 Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); 893 894 FunctionDescriptor valuesFunction = 895 KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUES), new Function1<FunctionDescriptor, Boolean>() { 896 @Override 897 public Boolean invoke(FunctionDescriptor descriptor) { 898 return CodegenUtil.isEnumValuesMethod(descriptor); 899 } 900 }); 901 MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(), 902 "()" + type.getDescriptor(), null, null); 903 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 904 905 mv.visitCode(); 906 mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, type.getDescriptor()); 907 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false); 908 mv.visitTypeInsn(CHECKCAST, type.getInternalName()); 909 mv.visitInsn(ARETURN); 910 FunctionCodegen.endVisit(mv, "values()", myClass); 911 } 912 913 private void generateEnumValueOfMethod() { 914 FunctionDescriptor valueOfFunction = 915 KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUE_OF), new Function1<FunctionDescriptor, Boolean>() { 916 @Override 917 public Boolean invoke(FunctionDescriptor descriptor) { 918 return CodegenUtil.isEnumValueOfMethod(descriptor); 919 } 920 }); 921 MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(), 922 "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null); 923 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 924 925 mv.visitCode(); 926 mv.visitLdcInsn(classAsmType); 927 mv.visitVarInsn(ALOAD, 0); 928 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false); 929 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName()); 930 mv.visitInsn(ARETURN); 931 FunctionCodegen.endVisit(mv, "valueOf()", myClass); 932 } 933 934 protected void generateSyntheticAccessors() { 935 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = ((CodegenContext<?>) context).getAccessors(); 936 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) { 937 generateSyntheticAccessor(entry); 938 } 939 } 940 941 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) { 942 if (entry.getValue() instanceof FunctionDescriptor) { 943 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); 944 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); 945 functionCodegen.generateMethod( 946 Synthetic(null, original), typeMapper.mapSignature(bridge), bridge, 947 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) { 948 @Override 949 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 950 generateMethodCallTo(original, codegen.v); 951 codegen.v.areturn(signature.getReturnType()); 952 } 953 } 954 ); 955 } 956 else if (entry.getValue() instanceof PropertyDescriptor) { 957 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); 958 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); 959 960 class PropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased<PropertyAccessorDescriptor> { 961 public PropertyAccessorStrategy(@NotNull PropertyAccessorDescriptor callableDescriptor) { 962 super(ImplementationBodyCodegen.this.state, callableDescriptor); 963 } 964 965 @Override 966 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 967 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && 968 !isClassObject(bridge.getContainingDeclaration()); 969 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 970 971 InstructionAdapter iv = codegen.v; 972 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 973 for (int i = 0, reg = 0; i < argTypes.length; i++) { 974 Type argType = argTypes[i]; 975 iv.load(reg, argType); 976 //noinspection AssignmentToForLoopParameter 977 reg += argType.getSize(); 978 } 979 980 if (callableDescriptor instanceof PropertyGetterDescriptor) { 981 property.put(property.type, iv); 982 } 983 else { 984 property.store(property.type, iv); 985 } 986 987 iv.areturn(signature.getReturnType()); 988 } 989 } 990 991 PropertyGetterDescriptor getter = bridge.getGetter(); 992 assert getter != null; 993 functionCodegen.generateMethod(Synthetic(null, original.getGetter() != null ? original.getGetter() : original), 994 typeMapper.mapSignature(getter), 995 getter, 996 new PropertyAccessorStrategy(getter)); 997 998 999 if (bridge.isVar()) { 1000 PropertySetterDescriptor setter = bridge.getSetter(); 1001 assert setter != null; 1002 1003 functionCodegen.generateMethod(Synthetic(null, original.getSetter() != null ? original.getSetter() : original), 1004 typeMapper.mapSignature(setter), 1005 setter, 1006 new PropertyAccessorStrategy(setter)); 1007 } 1008 } 1009 else { 1010 throw new UnsupportedOperationException(); 1011 } 1012 } 1013 1014 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) { 1015 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor; 1016 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor); 1017 CallableMethod callableMethod = isConstructor ? 1018 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) : 1019 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context); 1020 1021 int reg = 1; 1022 if (isConstructor) { 1023 iv.anew(callableMethod.getOwner()); 1024 iv.dup(); 1025 reg = 0; 1026 } 1027 else if (callFromAccessor) { 1028 iv.load(0, OBJECT_TYPE); 1029 } 1030 1031 for (Type argType : callableMethod.getAsmMethod().getArgumentTypes()) { 1032 iv.load(reg, argType); 1033 reg += argType.getSize(); 1034 } 1035 callableMethod.invokeWithoutAssertions(iv); 1036 } 1037 1038 private void generateFieldForSingleton() { 1039 if (isEnumEntry(descriptor)) return; 1040 1041 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor(); 1042 ClassDescriptor fieldTypeDescriptor; 1043 JetClassOrObject original; 1044 if (isObject(descriptor)) { 1045 original = myClass; 1046 fieldTypeDescriptor = descriptor; 1047 } 1048 else if (classObjectDescriptor != null) { 1049 JetClassObject classObject = ((JetClass) myClass).getClassObject(); 1050 assert classObject != null : "Class object not found: " + myClass.getText(); 1051 original = classObject.getObjectDeclaration(); 1052 fieldTypeDescriptor = classObjectDescriptor; 1053 } 1054 else { 1055 return; 1056 } 1057 1058 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper); 1059 1060 v.newField(OtherOrigin(original), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); 1061 1062 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 1063 1064 if (isObject(descriptor)) { 1065 // Invoke the object constructor but ignore the result because INSTANCE$ will be initialized in the first line of <init> 1066 InstructionAdapter v = createOrGetClInitCodegen().v; 1067 v.anew(classAsmType); 1068 v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false); 1069 } 1070 else if (!isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) { 1071 generateClassObjectInitializer(fieldTypeDescriptor); 1072 } 1073 } 1074 1075 private void generateClassObjectBackingFieldCopies() { 1076 if (classObjectPropertiesToCopy == null) return; 1077 1078 for (PropertyAndDefaultValue info : classObjectPropertiesToCopy) { 1079 PropertyDescriptor property = info.descriptor; 1080 1081 Type type = typeMapper.mapType(property); 1082 FieldVisitor fv = v.newField(OtherOrigin(property), ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(property, false), 1083 type.getDescriptor(), typeMapper.mapFieldSignature(property.getType()), 1084 info.defaultValue); 1085 1086 AnnotationCodegen.forField(fv, typeMapper).genAnnotations(property, type); 1087 1088 //This field are always static and final so if it has constant initializer don't do anything in clinit, 1089 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 1090 // TODO: test this code 1091 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && info.defaultValue == null) { 1092 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1093 int classObjectIndex = putClassObjectInLocalVar(codegen); 1094 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v); 1095 copyFieldFromClassObject(property); 1096 } 1097 } 1098 } 1099 1100 private int putClassObjectInLocalVar(ExpressionCodegen codegen) { 1101 FrameMap frameMap = codegen.myFrameMap; 1102 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor(); 1103 int classObjectIndex = frameMap.getIndex(classObjectDescriptor); 1104 if (classObjectIndex == -1) { 1105 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE); 1106 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper); 1107 classObject.put(classObject.type, codegen.v); 1108 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v); 1109 } 1110 return classObjectIndex; 1111 } 1112 1113 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) { 1114 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1115 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null); 1116 property.put(property.type, codegen.v); 1117 StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true); 1118 field.store(field.type, codegen.v); 1119 } 1120 1121 private void generateClassObjectInitializer(@NotNull ClassDescriptor classObject) { 1122 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1123 FunctionDescriptor constructor = codegen.accessibleFunctionDescriptor(KotlinPackage.single(classObject.getConstructors())); 1124 generateMethodCallTo(constructor, codegen.v); 1125 StackValue.singleton(classObject, typeMapper).store(typeMapper.mapClass(classObject), codegen.v); 1126 } 1127 1128 private void generatePrimaryConstructor(final DelegationFieldsInfo delegationFieldsInfo) { 1129 if (ignoreIfTraitOrAnnotation()) return; 1130 1131 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); 1132 assert constructorDescriptor != null : "Constructor not found for class: " + descriptor; 1133 1134 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); 1135 1136 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1137 lookupConstructorExpressionsInClosureIfPresent(constructorContext); 1138 } 1139 1140 JvmMethodSignature signature = typeMapper.mapSignature(constructorDescriptor); 1141 1142 functionCodegen.generateMethod(OtherOrigin(myClass, constructorDescriptor), signature, constructorDescriptor, constructorContext, 1143 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) { 1144 @Override 1145 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 1146 generatePrimaryConstructorImpl(callableDescriptor, codegen, delegationFieldsInfo); 1147 } 1148 } 1149 ); 1150 1151 functionCodegen.generateDefaultIfNeeded(constructorContext, signature, constructorDescriptor, OwnerKind.IMPLEMENTATION, 1152 DefaultParameterValueLoader.DEFAULT, null); 1153 1154 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor); 1155 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v); 1156 1157 if (isClassObject(descriptor)) { 1158 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, bindingContext); 1159 } 1160 } 1161 1162 private void generatePrimaryConstructorImpl( 1163 @NotNull ConstructorDescriptor constructorDescriptor, 1164 @NotNull final ExpressionCodegen codegen, 1165 @NotNull DelegationFieldsInfo fieldsInfo 1166 ) { 1167 InstructionAdapter iv = codegen.v; 1168 1169 MutableClosure closure = context.closure; 1170 if (closure != null) { 1171 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType); 1172 int k = 1; 1173 for (FieldInfo info : argsFromClosure) { 1174 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv); 1175 } 1176 } 1177 1178 if (superCall == null) { 1179 genSimpleSuperCall(iv); 1180 } 1181 else { 1182 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor); 1183 } 1184 1185 if (isObject(descriptor)) { 1186 iv.load(0, classAsmType); 1187 StackValue.singleton(descriptor, typeMapper).store(classAsmType, iv); 1188 } 1189 1190 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1191 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1192 genCallToDelegatorByExpressionSpecifier(iv, codegen, (JetDelegatorByExpressionSpecifier) specifier, fieldsInfo); 1193 } 1194 } 1195 1196 int curParam = 0; 1197 List<ValueParameterDescriptor> parameters = constructorDescriptor.getValueParameters(); 1198 for (JetParameter parameter : getPrimaryConstructorParameters()) { 1199 if (parameter.hasValOrVarNode()) { 1200 VariableDescriptor descriptor = parameters.get(curParam); 1201 Type type = typeMapper.mapType(descriptor); 1202 iv.load(0, classAsmType); 1203 iv.load(codegen.myFrameMap.getIndex(descriptor), type); 1204 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 1205 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter; 1206 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor, false), type.getDescriptor()); 1207 } 1208 curParam++; 1209 } 1210 1211 if (isClassObjectWithBackingFieldsInOuter(descriptor)) { 1212 final ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this); 1213 //generate OBJECT$ 1214 parentCodegen.generateClassObjectInitializer(descriptor); 1215 generateInitializers(new Function0<ExpressionCodegen>() { 1216 @Override 1217 public ExpressionCodegen invoke() { 1218 return parentCodegen.createOrGetClInitCodegen(); 1219 } 1220 }); 1221 } 1222 else { 1223 generateInitializers(new Function0<ExpressionCodegen>() { 1224 @Override 1225 public ExpressionCodegen invoke() { 1226 return codegen; 1227 } 1228 }); 1229 } 1230 1231 iv.visitInsn(RETURN); 1232 } 1233 1234 private void genSimpleSuperCall(InstructionAdapter iv) { 1235 iv.load(0, superClassAsmType); 1236 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) { 1237 iv.load(1, JAVA_STRING_TYPE); 1238 iv.load(2, Type.INT_TYPE); 1239 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false); 1240 } 1241 else { 1242 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false); 1243 } 1244 } 1245 1246 private class DelegationFieldsInfo { 1247 private class Field { 1248 public final Type type; 1249 public final String name; 1250 public final boolean generateField; 1251 1252 private Field(Type type, String name, boolean generateField) { 1253 this.type = type; 1254 this.name = name; 1255 this.generateField = generateField; 1256 } 1257 1258 @NotNull 1259 public StackValue getStackValue() { 1260 return StackValue.field(type, classAsmType, name, false); 1261 } 1262 } 1263 private final Map<JetDelegatorByExpressionSpecifier, Field> fields = new HashMap<JetDelegatorByExpressionSpecifier, Field>(); 1264 1265 @NotNull 1266 public Field getInfo(JetDelegatorByExpressionSpecifier specifier) { 1267 return fields.get(specifier); 1268 } 1269 1270 private void addField(JetDelegatorByExpressionSpecifier specifier, PropertyDescriptor propertyDescriptor) { 1271 fields.put(specifier, 1272 new Field(typeMapper.mapType(propertyDescriptor), propertyDescriptor.getName().asString(), false)); 1273 } 1274 1275 private void addField(JetDelegatorByExpressionSpecifier specifier, Type type, String name) { 1276 fields.put(specifier, new Field(type, name, true)); 1277 } 1278 } 1279 1280 @NotNull 1281 private DelegationFieldsInfo getDelegationFieldsInfo(@NotNull List<JetDelegationSpecifier> delegationSpecifiers) { 1282 DelegationFieldsInfo result = new DelegationFieldsInfo(); 1283 int n = 0; 1284 for (JetDelegationSpecifier specifier : delegationSpecifiers) { 1285 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1286 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1287 PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext); 1288 1289 ClassDescriptor superClassDescriptor = getSuperClass(specifier); 1290 1291 if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) { 1292 result.addField((JetDelegatorByExpressionSpecifier) specifier, propertyDescriptor); 1293 } 1294 else { 1295 result.addField((JetDelegatorByExpressionSpecifier) specifier, typeMapper.mapType(superClassDescriptor), "$delegate_" + n); 1296 } 1297 n++; 1298 } 1299 } 1300 return result; 1301 } 1302 1303 @NotNull 1304 private ClassDescriptor getSuperClass(@NotNull JetDelegationSpecifier specifier) { 1305 return CodegenUtil.getSuperClassByDelegationSpecifier(specifier, bindingContext); 1306 } 1307 1308 private void genCallToDelegatorByExpressionSpecifier( 1309 InstructionAdapter iv, 1310 ExpressionCodegen codegen, 1311 JetDelegatorByExpressionSpecifier specifier, 1312 DelegationFieldsInfo fieldsInfo 1313 ) { 1314 JetExpression expression = specifier.getDelegateExpression(); 1315 1316 DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier); 1317 if (fieldInfo.generateField) { 1318 iv.load(0, classAsmType); 1319 codegen.genToJVMStack(expression); 1320 1321 fieldInfo.getStackValue().store(fieldInfo.type, iv); 1322 } 1323 } 1324 1325 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) { 1326 JetVisitorVoid visitor = new JetVisitorVoid() { 1327 @Override 1328 public void visitJetElement(@NotNull JetElement e) { 1329 e.acceptChildren(this); 1330 } 1331 1332 @Override 1333 public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expr) { 1334 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr); 1335 1336 DeclarationDescriptor toLookup; 1337 if (isLocalNamedFun(descriptor)) { 1338 toLookup = descriptor; 1339 } 1340 else if (descriptor instanceof CallableMemberDescriptor) { 1341 toLookup = descriptor.getContainingDeclaration(); 1342 } 1343 else if (descriptor instanceof VariableDescriptor) { 1344 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor(); 1345 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) { 1346 if (descriptor.equals(parameterDescriptor)) return; 1347 } 1348 toLookup = descriptor; 1349 } 1350 else return; 1351 1352 constructorContext.lookupInContext(toLookup, null, state, true); 1353 } 1354 1355 @Override 1356 public void visitThisExpression(@NotNull JetThisExpression expression) { 1357 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 1358 assert descriptor instanceof CallableDescriptor || 1359 descriptor instanceof ClassDescriptor : "'This' reference target should be class or callable descriptor but was " + descriptor; 1360 if (context.getCallableDescriptorWithReceiver() != descriptor) { 1361 context.lookupInContext(descriptor, null, state, true); 1362 } 1363 } 1364 }; 1365 1366 for (JetDeclaration declaration : myClass.getDeclarations()) { 1367 if (declaration instanceof JetProperty) { 1368 JetProperty property = (JetProperty) declaration; 1369 JetExpression initializer = property.getInitializer(); 1370 if (initializer != null) { 1371 initializer.accept(visitor); 1372 } 1373 } 1374 else if (declaration instanceof JetClassInitializer) { 1375 JetClassInitializer initializer = (JetClassInitializer) declaration; 1376 initializer.accept(visitor); 1377 } 1378 } 1379 1380 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1381 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1382 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1383 assert delegateExpression != null; 1384 delegateExpression.accept(visitor); 1385 } 1386 } 1387 1388 if (superCall != null && !isAnonymousObject(descriptor)) { 1389 JetValueArgumentList argumentList = superCall.getValueArgumentList(); 1390 if (argumentList != null) { 1391 argumentList.accept(visitor); 1392 } 1393 } 1394 } 1395 1396 private boolean ignoreIfTraitOrAnnotation() { 1397 if (myClass instanceof JetClass) { 1398 JetClass aClass = (JetClass) myClass; 1399 if (aClass.isTrait()) { 1400 return true; 1401 } 1402 if (aClass.isAnnotation()) { 1403 return true; 1404 } 1405 } 1406 return false; 1407 } 1408 1409 private void generateTraitMethods() { 1410 if (JetPsiUtil.isTrait(myClass)) return; 1411 1412 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1413 if (!(declaration instanceof CallableMemberDescriptor)) continue; 1414 1415 CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration; 1416 CallableMemberDescriptor traitMember = BridgesPackage.findTraitImplementation(inheritedMember); 1417 if (traitMember == null) continue; 1418 1419 assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember; 1420 1421 // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here 1422 // with traitMember's modality 1423 CallableMemberDescriptor copy = 1424 inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, 1425 CallableMemberDescriptor.Kind.DECLARATION, true); 1426 1427 if (traitMember instanceof SimpleFunctionDescriptor) { 1428 generateDelegationToTraitImpl((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); 1429 } 1430 else if (traitMember instanceof PropertyDescriptor) { 1431 for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { 1432 for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { 1433 if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind 1434 generateDelegationToTraitImpl(traitAccessor, inheritedAccessor); 1435 } 1436 } 1437 } 1438 } 1439 } 1440 } 1441 1442 private void generateDelegationToTraitImpl(@NotNull final FunctionDescriptor traitFun, @NotNull FunctionDescriptor inheritedFun) { 1443 functionCodegen.generateMethod( 1444 DelegationToTraitImpl(descriptorToDeclaration(traitFun), traitFun), 1445 typeMapper.mapSignature(inheritedFun), 1446 inheritedFun, 1447 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, inheritedFun) { 1448 @Override 1449 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 1450 DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration(); 1451 if (!DescriptorUtils.isTrait(containingDeclaration)) return; 1452 ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration; 1453 Type traitImplType = typeMapper.mapTraitImpl(containingTrait); 1454 1455 Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal(), OwnerKind.TRAIT_IMPL).getAsmMethod(); 1456 1457 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 1458 Type[] originalArgTypes = traitMethod.getArgumentTypes(); 1459 assert originalArgTypes.length == argTypes.length + 1 : 1460 "Invalid trait implementation signature: " + signature + " vs " + traitMethod + " for " + traitFun; 1461 1462 InstructionAdapter iv = codegen.v; 1463 iv.load(0, OBJECT_TYPE); 1464 for (int i = 0, reg = 1; i < argTypes.length; i++) { 1465 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i + 1], iv); 1466 //noinspection AssignmentToForLoopParameter 1467 reg += argTypes[i].getSize(); 1468 } 1469 1470 if (KotlinBuiltIns.getInstance().isCloneable(containingTrait) && traitMethod.getName().equals("clone")) { 1471 // A special hack for Cloneable: there's no kotlin/Cloneable$$TImpl class at runtime, 1472 // and its 'clone' method is actually located in java/lang/Object 1473 iv.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false); 1474 } 1475 else { 1476 iv.invokestatic(traitImplType.getInternalName(), traitMethod.getName(), traitMethod.getDescriptor(), false); 1477 } 1478 1479 Type returnType = signature.getReturnType(); 1480 StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv); 1481 iv.areturn(returnType); 1482 } 1483 } 1484 ); 1485 } 1486 1487 private void generateDelegatorToConstructorCall( 1488 @NotNull InstructionAdapter iv, 1489 @NotNull ExpressionCodegen codegen, 1490 @NotNull ConstructorDescriptor constructorDescriptor 1491 ) { 1492 iv.load(0, OBJECT_TYPE); 1493 1494 ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(superCall, bindingContext); 1495 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1496 1497 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor); 1498 CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor); 1499 1500 List<JvmMethodParameterSignature> superParameters = superCallable.getValueParameters(); 1501 List<JvmMethodParameterSignature> parameters = callable.getValueParameters(); 1502 1503 int offset = 1; 1504 int superIndex = 0; 1505 1506 // Here we match all the super constructor parameters except those with kind VALUE to the derived constructor parameters, push 1507 // them all onto the stack and update "offset" variable so that in the end it points to the slot of the first VALUE argument 1508 for (JvmMethodParameterSignature parameter : parameters) { 1509 if (superIndex >= superParameters.size()) break; 1510 1511 JvmMethodParameterKind kind = parameter.getKind(); 1512 Type type = parameter.getAsmType(); 1513 1514 // Stop when we reach the actual value parameters present in the code; they will be generated via ResolvedCall below 1515 if (superParameters.get(superIndex).getKind() == JvmMethodParameterKind.VALUE && 1516 kind == JvmMethodParameterKind.SUPER_CALL_PARAM) { 1517 break; 1518 } 1519 1520 if (kind == JvmMethodParameterKind.SUPER_CALL_PARAM || kind == JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL || 1521 (kind == JvmMethodParameterKind.OUTER && superConstructor.getContainingDeclaration().isInner())) { 1522 iv.load(offset, type); 1523 superIndex++; 1524 } 1525 1526 offset += type.getSize(); 1527 } 1528 1529 ArgumentGenerator argumentGenerator; 1530 if (isAnonymousObject(descriptor)) { 1531 List<JvmMethodParameterSignature> superValues = superParameters.subList(superIndex, superParameters.size()); 1532 argumentGenerator = new ObjectSuperCallArgumentGenerator(superValues, iv, offset); 1533 } 1534 else { 1535 argumentGenerator = 1536 new CallBasedArgumentGenerator(codegen, codegen.defaultCallGenerator, superConstructor.getValueParameters(), 1537 superCallable.getValueParameterTypes()); 1538 } 1539 1540 codegen.invokeMethodWithArguments(superCallable, resolvedCall, StackValue.none(), codegen.defaultCallGenerator, argumentGenerator); 1541 } 1542 1543 private static class ObjectSuperCallArgumentGenerator extends ArgumentGenerator { 1544 private final List<JvmMethodParameterSignature> parameters; 1545 private final InstructionAdapter iv; 1546 private int offset; 1547 1548 public ObjectSuperCallArgumentGenerator( 1549 @NotNull List<JvmMethodParameterSignature> superParameters, 1550 @NotNull InstructionAdapter iv, 1551 int firstValueParamOffset 1552 ) { 1553 this.parameters = superParameters; 1554 this.iv = iv; 1555 this.offset = firstValueParamOffset; 1556 } 1557 1558 @Override 1559 public void generateExpression(int i, @NotNull ExpressionValueArgument argument) { 1560 generateSuperCallArgument(i); 1561 } 1562 1563 @Override 1564 public void generateDefault(int i, @NotNull DefaultValueArgument argument) { 1565 pushDefaultValueOnStack(parameters.get(i).getAsmType(), iv); 1566 } 1567 1568 @Override 1569 public void generateVararg(int i, @NotNull VarargValueArgument argument) { 1570 generateSuperCallArgument(i); 1571 } 1572 1573 private void generateSuperCallArgument(int i) { 1574 Type type = parameters.get(i).getAsmType(); 1575 iv.load(offset, type); 1576 offset += type.getSize(); 1577 } 1578 } 1579 1580 @Override 1581 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) { 1582 if (declaration instanceof JetEnumEntry) { 1583 String name = declaration.getName(); 1584 assert name != null : "Enum entry has no name: " + declaration.getText(); 1585 ClassDescriptor entryDescriptor = bindingContext.get(BindingContext.CLASS, declaration); 1586 FieldVisitor fv = v.newField(OtherOrigin(declaration, entryDescriptor), ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, 1587 name, classAsmType.getDescriptor(), null, null); 1588 AnnotationCodegen.forField(fv, typeMapper).genAnnotations(entryDescriptor, null); 1589 myEnumConstants.add((JetEnumEntry) declaration); 1590 } 1591 1592 super.generateDeclaration(propertyCodegen, declaration); 1593 } 1594 1595 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>(); 1596 1597 private void initializeEnumConstants() { 1598 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; 1599 1600 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1601 InstructionAdapter iv = codegen.v; 1602 1603 Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); 1604 v.newField(OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME, 1605 arrayAsmType.getDescriptor(), null, null); 1606 1607 iv.iconst(myEnumConstants.size()); 1608 iv.newarray(classAsmType); 1609 1610 if (!myEnumConstants.isEmpty()) { 1611 iv.dup(); 1612 for (int ordinal = 0, size = myEnumConstants.size(); ordinal < size; ordinal++) { 1613 initializeEnumConstant(codegen, ordinal); 1614 } 1615 } 1616 1617 iv.putstatic(classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, arrayAsmType.getDescriptor()); 1618 } 1619 1620 private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) { 1621 InstructionAdapter iv = codegen.v; 1622 JetEnumEntry enumConstant = myEnumConstants.get(ordinal); 1623 1624 iv.dup(); 1625 iv.iconst(ordinal); 1626 1627 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant); 1628 assert classDescriptor != null; 1629 Type implClass = typeMapper.mapClass(classDescriptor); 1630 1631 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers(); 1632 if (delegationSpecifiers.size() > 1) { 1633 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported"); 1634 } 1635 1636 iv.anew(implClass); 1637 iv.dup(); 1638 1639 iv.aconst(enumConstant.getName()); 1640 iv.iconst(ordinal); 1641 1642 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { 1643 JetDelegationSpecifier specifier = delegationSpecifiers.get(0); 1644 if (!(specifier instanceof JetDelegatorToSuperCall)) { 1645 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); 1646 } 1647 1648 ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(specifier, bindingContext); 1649 1650 CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor()); 1651 1652 codegen.invokeMethodWithArguments(method, resolvedCall, StackValue.none()); 1653 } 1654 else { 1655 iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false); 1656 } 1657 1658 iv.dup(); 1659 iv.putstatic(classAsmType.getInternalName(), enumConstant.getName(), classAsmType.getDescriptor()); 1660 iv.astore(OBJECT_TYPE); 1661 } 1662 1663 private void generateDelegates(DelegationFieldsInfo delegationFieldsInfo) { 1664 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1665 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1666 DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((JetDelegatorByExpressionSpecifier) specifier); 1667 generateDelegateField(field); 1668 generateDelegates(getSuperClass(specifier), field); 1669 } 1670 } 1671 } 1672 1673 private void generateDelegateField(DelegationFieldsInfo.Field fieldInfo) { 1674 if (!fieldInfo.generateField) return; 1675 1676 v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, 1677 fieldInfo.name, fieldInfo.type.getDescriptor(), /*TODO*/null, null); 1678 } 1679 1680 protected void generateDelegates(ClassDescriptor toClass, DelegationFieldsInfo.Field field) { 1681 for (Map.Entry<CallableMemberDescriptor, CallableMemberDescriptor> entry : CodegenUtil.getDelegates(descriptor, toClass).entrySet()) { 1682 CallableMemberDescriptor callableMemberDescriptor = entry.getKey(); 1683 CallableMemberDescriptor overriddenDescriptor = entry.getValue(); 1684 if (callableMemberDescriptor instanceof PropertyDescriptor) { 1685 propertyCodegen 1686 .genDelegate((PropertyDescriptor) callableMemberDescriptor, (PropertyDescriptor) overriddenDescriptor, field.getStackValue()); 1687 } 1688 else if (callableMemberDescriptor instanceof FunctionDescriptor) { 1689 functionCodegen 1690 .genDelegate((FunctionDescriptor) callableMemberDescriptor, (FunctionDescriptor) overriddenDescriptor, field.getStackValue()); 1691 } 1692 } 1693 } 1694 1695 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { 1696 if (classObjectPropertiesToCopy == null) { 1697 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>(); 1698 } 1699 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue)); 1700 } 1701 1702 @Override 1703 protected void done() { 1704 for (Function2<ImplementationBodyCodegen, ClassBuilder, Unit> task : additionalTasks) { 1705 task.invoke(this, v); 1706 } 1707 1708 super.done(); 1709 } 1710 1711 private static class PropertyAndDefaultValue { 1712 public final PropertyDescriptor descriptor; 1713 public final Object defaultValue; 1714 1715 public PropertyAndDefaultValue(PropertyDescriptor descriptor, Object defaultValue) { 1716 this.descriptor = descriptor; 1717 this.defaultValue = defaultValue; 1718 } 1719 } 1720 1721 public void addAdditionalTask(Function2<ImplementationBodyCodegen, ClassBuilder, Unit> additionalTask) { 1722 additionalTasks.add(additionalTask); 1723 } 1724 }