001 /* 002 * Copyright 2010-2013 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.google.common.collect.Sets; 021 import com.intellij.openapi.progress.ProcessCanceledException; 022 import com.intellij.openapi.util.Pair; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.util.ArrayUtil; 025 import org.jetbrains.annotations.NotNull; 026 import org.jetbrains.annotations.Nullable; 027 import org.jetbrains.asm4.AnnotationVisitor; 028 import org.jetbrains.asm4.Label; 029 import org.jetbrains.asm4.MethodVisitor; 030 import org.jetbrains.asm4.Type; 031 import org.jetbrains.asm4.commons.InstructionAdapter; 032 import org.jetbrains.asm4.commons.Method; 033 import org.jetbrains.jet.codegen.binding.CalculatedClosure; 034 import org.jetbrains.jet.codegen.binding.CodegenBinding; 035 import org.jetbrains.jet.codegen.binding.MutableClosure; 036 import org.jetbrains.jet.codegen.context.ClassContext; 037 import org.jetbrains.jet.codegen.context.ConstructorContext; 038 import org.jetbrains.jet.codegen.context.MethodContext; 039 import org.jetbrains.jet.codegen.signature.*; 040 import org.jetbrains.jet.codegen.state.GenerationState; 041 import org.jetbrains.jet.codegen.state.JetTypeMapper; 042 import org.jetbrains.jet.codegen.state.JetTypeMapperMode; 043 import org.jetbrains.jet.descriptors.serialization.BitEncoding; 044 import org.jetbrains.jet.descriptors.serialization.ClassData; 045 import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer; 046 import org.jetbrains.jet.descriptors.serialization.ProtoBuf; 047 import org.jetbrains.jet.lang.descriptors.*; 048 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 049 import org.jetbrains.jet.lang.psi.*; 050 import org.jetbrains.jet.lang.resolve.BindingContext; 051 import org.jetbrains.jet.lang.resolve.BindingContextUtils; 052 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 053 import org.jetbrains.jet.lang.resolve.OverridingUtil; 054 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; 055 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 056 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; 057 import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants; 058 import org.jetbrains.jet.lang.resolve.java.JvmAbi; 059 import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; 060 import org.jetbrains.jet.lang.resolve.name.Name; 061 import org.jetbrains.jet.lang.types.*; 062 import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 063 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 064 import org.jetbrains.jet.lexer.JetTokens; 065 066 import java.util.*; 067 068 import static org.jetbrains.asm4.Opcodes.*; 069 import static org.jetbrains.jet.codegen.AsmUtil.*; 070 import static org.jetbrains.jet.codegen.CodegenUtil.*; 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.BindingContextUtils.callableDescriptorToDeclaration; 074 import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; 075 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; 076 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; 077 import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; 078 079 public class ImplementationBodyCodegen extends ClassBodyCodegen { 080 private static final String VALUES = "$VALUES"; 081 private JetDelegationSpecifier superCall; 082 private Type superClassAsmType; 083 @Nullable // null means java/lang/Object 084 private JetType superClassType; 085 private final Type classAsmType; 086 087 private final FunctionCodegen functionCodegen; 088 private final PropertyCodegen propertyCodegen; 089 090 private List<PropertyAndDefaultValue> classObjectPropertiesToCopy; 091 092 public ImplementationBodyCodegen( 093 @NotNull JetClassOrObject aClass, 094 @NotNull ClassContext context, 095 @NotNull ClassBuilder v, 096 @NotNull GenerationState state, 097 @Nullable MemberCodegen parentCodegen 098 ) { 099 super(aClass, context, v, state, parentCodegen); 100 this.classAsmType = typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL); 101 this.functionCodegen = new FunctionCodegen(context, v, state, this); 102 this.propertyCodegen = new PropertyCodegen(context, v, this.functionCodegen, this); 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); 213 } 214 215 @Override 216 protected void generateKotlinAnnotation() { 217 if (state.getClassBuilderMode() != ClassBuilderMode.FULL) { 218 return; 219 } 220 221 if (!isTopLevelOrInnerClass(descriptor)) return; 222 223 DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getMemberMap())); 224 225 ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); 226 227 ClassData data = new ClassData(createNameResolver(serializer.getNameTable()), classProto); 228 229 AnnotationVisitor av = v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_CLASS), true); 230 av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); 231 AnnotationVisitor array = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); 232 for (String string : BitEncoding.encodeBytes(data.toBytes())) { 233 array.visit(null, string); 234 } 235 array.visitEnd(); 236 av.visitEnd(); 237 } 238 239 private void writeEnclosingMethod() { 240 //JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class. 241 DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration(); 242 243 boolean isObjectLiteral = DescriptorUtils.isAnonymous(descriptor); 244 245 boolean isLocalOrAnonymousClass = isObjectLiteral || 246 !(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor); 247 if (isLocalOrAnonymousClass) { 248 String outerClassName = getOuterClassName(descriptor, typeMapper); 249 FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class); 250 251 if (function != null) { 252 Method method = typeMapper.mapSignature(function).getAsmMethod(); 253 v.visitOuterClass(outerClassName, method.getName(), method.getDescriptor()); 254 } 255 else { 256 assert isObjectLiteral 257 : "Function descriptor could be null only for object literal in package namespace: " + descriptor.getName(); 258 v.visitOuterClass(outerClassName, null, null); 259 } 260 } 261 } 262 263 @NotNull 264 private static String getOuterClassName( 265 @NotNull ClassDescriptor classDescriptor, 266 @NotNull JetTypeMapper typeMapper 267 ) { 268 ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class); 269 if (container != null) { 270 return typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 271 } 272 else { 273 JetFile containingFile = BindingContextUtils.getContainingFile(typeMapper.getBindingContext(), classDescriptor); 274 assert containingFile != null : "Containing file should be present for " + classDescriptor; 275 return NamespaceCodegen.getNamespacePartInternalName(containingFile); 276 } 277 } 278 279 private void writeInnerClasses() { 280 Collection<ClassDescriptor> result = bindingContext.get(INNER_CLASSES, descriptor); 281 if (result != null) { 282 for (ClassDescriptor innerClass : result) { 283 writeInnerClass(innerClass); 284 } 285 } 286 } 287 288 private void writeOuterClasses() { 289 // JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information 290 // for each enclosing class and for each immediate member 291 DeclarationDescriptor inner = descriptor; 292 while (true) { 293 if (inner == null || isTopLevelDeclaration(inner)) { 294 break; 295 } 296 if (inner instanceof ClassDescriptor && !isEnumClassObject(inner)) { 297 writeInnerClass((ClassDescriptor) inner); 298 } 299 inner = inner.getContainingDeclaration(); 300 } 301 } 302 303 private void writeInnerClass(@NotNull ClassDescriptor innerClass) { 304 // TODO: proper access 305 int innerClassAccess = getVisibilityAccessFlag(innerClass); 306 if (innerClass.getModality() == Modality.FINAL) { 307 innerClassAccess |= ACC_FINAL; 308 } 309 else if (innerClass.getModality() == Modality.ABSTRACT) { 310 innerClassAccess |= ACC_ABSTRACT; 311 } 312 313 if (innerClass.getKind() == ClassKind.TRAIT) { 314 innerClassAccess |= ACC_INTERFACE; 315 } 316 else if (innerClass.getKind() == ClassKind.ENUM_CLASS) { 317 innerClassAccess |= ACC_ENUM; 318 } 319 320 if (!innerClass.isInner()) { 321 innerClassAccess |= ACC_STATIC; 322 } 323 324 // TODO: cache internal names 325 DeclarationDescriptor containing = innerClass.getContainingDeclaration(); 326 String outerClassInternalName = containing instanceof ClassDescriptor ? getInternalNameForImpl((ClassDescriptor) containing) : null; 327 328 String innerClassInternalName; 329 String innerName; 330 331 if (isClassObject(innerClass)) { 332 innerName = JvmAbi.CLASS_OBJECT_CLASS_NAME; 333 innerClassInternalName = outerClassInternalName + JvmAbi.CLASS_OBJECT_SUFFIX; 334 } 335 else { 336 innerName = innerClass.getName().isSpecial() ? null : innerClass.getName().asString(); 337 innerClassInternalName = getInternalNameForImpl(innerClass); 338 } 339 340 v.visitInnerClass(innerClassInternalName, outerClassInternalName, innerName, innerClassAccess); 341 } 342 343 @NotNull 344 private String getInternalNameForImpl(@NotNull ClassDescriptor descriptor) { 345 return typeMapper.mapType(descriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 346 } 347 348 private JvmClassSignature signature() { 349 List<String> superInterfaces; 350 351 LinkedHashSet<String> superInterfacesLinkedHashSet = new LinkedHashSet<String>(); 352 353 // TODO: generics signature is not always needed 354 BothSignatureWriter signatureVisitor = new BothSignatureWriter(BothSignatureWriter.Mode.CLASS, true); 355 356 357 { // type parameters 358 List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters(); 359 typeMapper.writeFormalTypeParameters(typeParameters, signatureVisitor); 360 } 361 362 { // superclass 363 signatureVisitor.writeSuperclass(); 364 if (superClassType == null) { 365 signatureVisitor.writeClassBegin(superClassAsmType); 366 signatureVisitor.writeClassEnd(); 367 } 368 else { 369 typeMapper.mapType(superClassType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE); 370 } 371 signatureVisitor.writeSuperclassEnd(); 372 } 373 374 375 { // superinterfaces 376 superInterfacesLinkedHashSet.add(JvmAbi.JET_OBJECT.getInternalName()); 377 378 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 379 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 380 assert superType != null; 381 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 382 if (isInterface(superClassDescriptor)) { 383 signatureVisitor.writeInterface(); 384 Type jvmName = typeMapper.mapType(superType, signatureVisitor, JetTypeMapperMode.SUPER_TYPE); 385 signatureVisitor.writeInterfaceEnd(); 386 superInterfacesLinkedHashSet.add(jvmName.getInternalName()); 387 } 388 } 389 390 superInterfaces = new ArrayList<String>(superInterfacesLinkedHashSet); 391 } 392 393 return new JvmClassSignature(classAsmType.getInternalName(), superClassAsmType.getInternalName(), superInterfaces, 394 signatureVisitor.makeJavaGenericSignature()); 395 } 396 397 protected void getSuperClass() { 398 superClassAsmType = AsmTypeConstants.OBJECT_TYPE; 399 superClassType = null; 400 401 List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); 402 403 if (myClass instanceof JetClass && ((JetClass) myClass).isTrait()) { 404 return; 405 } 406 407 if (kind != OwnerKind.IMPLEMENTATION) { 408 throw new IllegalStateException("must be impl to reach this code: " + kind); 409 } 410 411 for (JetDelegationSpecifier specifier : delegationSpecifiers) { 412 if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) { 413 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 414 assert superType != null; 415 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 416 assert superClassDescriptor != null; 417 if (!isInterface(superClassDescriptor)) { 418 superClassType = superType; 419 superClassAsmType = typeMapper.mapType(superClassDescriptor.getDefaultType(), JetTypeMapperMode.IMPL); 420 superCall = specifier; 421 } 422 } 423 } 424 425 if (superClassType == null) { 426 if (descriptor.getKind() == ClassKind.ENUM_CLASS) { 427 superClassType = KotlinBuiltIns.getInstance().getEnumType(descriptor.getDefaultType()); 428 superClassAsmType = typeMapper.mapType(superClassType); 429 } 430 if (descriptor.getKind() == ClassKind.ENUM_ENTRY) { 431 superClassType = descriptor.getTypeConstructor().getSupertypes().iterator().next(); 432 superClassAsmType = typeMapper.mapType(superClassType); 433 } 434 } 435 } 436 437 @Override 438 protected void generateSyntheticParts() { 439 generateFieldForSingleton(); 440 441 generateClassObjectBackingFieldCopies(); 442 443 try { 444 generatePrimaryConstructor(); 445 } 446 catch (CompilationException e) { 447 throw e; 448 } 449 catch (ProcessCanceledException e) { 450 throw e; 451 } 452 catch (RuntimeException e) { 453 throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e); 454 } 455 456 generateTraitMethods(); 457 458 generateSyntheticAccessors(); 459 460 generateEnumMethodsAndConstInitializers(); 461 462 generateFunctionsForDataClasses(); 463 464 generateBuiltinMethodStubs(); 465 466 generateToArray(); 467 468 genClosureFields(context.closure, v, state.getTypeMapper()); 469 } 470 471 private boolean isGenericToArrayPresent() { 472 Collection<FunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getFunctions(Name.identifier("toArray")); 473 for (FunctionDescriptor function : functions) { 474 if (CallResolverUtil.isOrOverridesSynthesized(function)) { 475 continue; 476 } 477 478 if (function.getValueParameters().size() != 1 || function.getTypeParameters().size() != 1) { 479 continue; 480 } 481 482 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(function.getTypeParameters().get(0).getDefaultType()); 483 JetType returnType = function.getReturnType(); 484 assert returnType != null : function.toString(); 485 JetType paramType = function.getValueParameters().get(0).getType(); 486 if (JetTypeChecker.INSTANCE.equalTypes(arrayType, returnType) && JetTypeChecker.INSTANCE.equalTypes(arrayType, paramType)) { 487 return true; 488 } 489 } 490 return false; 491 492 } 493 494 private void generateToArray() { 495 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 496 if (isSubclass(descriptor, builtIns.getCollection())) { 497 if (CodegenUtil.getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toArray"), builtIns.getArray()) == null) { 498 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null); 499 InstructionAdapter iv = new InstructionAdapter(mv); 500 501 mv.visitCode(); 502 503 iv.load(0, classAsmType); 504 iv.invokestatic("jet/runtime/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;"); 505 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 506 507 FunctionCodegen.endVisit(mv, "toArray", myClass); 508 } 509 510 if (!isGenericToArrayPresent()) { 511 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", null, null); 512 InstructionAdapter iv = new InstructionAdapter(mv); 513 514 mv.visitCode(); 515 516 iv.load(0, classAsmType); 517 iv.load(1, Type.getObjectType("[Ljava/lang/Object;")); 518 519 iv.invokestatic("jet/runtime/CollectionToArray", "toArray", "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;"); 520 iv.areturn(Type.getObjectType("[Ljava/lang/Object;")); 521 522 FunctionCodegen.endVisit(mv, "toArray", myClass); 523 } 524 } 525 } 526 527 private void generateMethodStub( 528 @NotNull String name, 529 @NotNull String desc, 530 @NotNull ClassifierDescriptor returnedClassifier, 531 @NotNull ClassifierDescriptor... valueParameterClassifiers 532 ) { 533 if (CodegenUtil.getDeclaredFunctionByRawSignature( 534 descriptor, Name.identifier(name), returnedClassifier, valueParameterClassifiers) == null) { 535 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, name, desc, null, null); 536 AsmUtil.genMethodThrow(mv, "java/lang/UnsupportedOperationException", "Mutating immutable collection"); 537 } 538 } 539 540 private void generateBuiltinMethodStubs() { 541 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); 542 if (isSubclass(descriptor, builtIns.getCollection())) { 543 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getCollection(), 0); 544 545 generateMethodStub("add", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), classifier); 546 generateMethodStub("remove", "(Ljava/lang/Object;)Z", builtIns.getBoolean(), builtIns.getAny()); 547 generateMethodStub("addAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 548 generateMethodStub("removeAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 549 generateMethodStub("retainAll", "(Ljava/util/Collection;)Z", builtIns.getBoolean(), builtIns.getCollection()); 550 generateMethodStub("clear", "()V", builtIns.getUnit()); 551 } 552 553 if (isSubclass(descriptor, builtIns.getList())) { 554 ClassifierDescriptor classifier = getSubstituteForTypeParameterOf(builtIns.getList(), 0); 555 556 generateMethodStub("set", "(ILjava/lang/Object;)Ljava/lang/Object;", classifier, builtIns.getInt(), classifier); 557 generateMethodStub("add", "(ILjava/lang/Object;)V", builtIns.getUnit(), builtIns.getInt(), classifier); 558 generateMethodStub("remove", "(I)Ljava/lang/Object;", classifier, builtIns.getInt()); 559 } 560 561 if (isSubclass(descriptor, builtIns.getMap())) { 562 ClassifierDescriptor keyClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 0); 563 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMap(), 1); 564 565 generateMethodStub("put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, keyClassifier, 566 valueClassifier); 567 generateMethodStub("remove", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, builtIns.getAny()); 568 generateMethodStub("putAll", "(Ljava/util/Map;)V", builtIns.getUnit(), builtIns.getMap()); 569 generateMethodStub("clear", "()V", builtIns.getUnit()); 570 } 571 572 if (isSubclass(descriptor, builtIns.getMapEntry())) { 573 ClassifierDescriptor valueClassifier = getSubstituteForTypeParameterOf(builtIns.getMapEntry(), 1); 574 575 generateMethodStub("setValue", "(Ljava/lang/Object;)Ljava/lang/Object;", valueClassifier, valueClassifier); 576 } 577 578 if (isSubclass(descriptor, builtIns.getIterator())) { 579 generateMethodStub("remove", "()V", builtIns.getUnit()); 580 } 581 } 582 583 @NotNull 584 private ClassifierDescriptor getSubstituteForTypeParameterOf(@NotNull ClassDescriptor trait, int index) { 585 TypeParameterDescriptor listTypeParameter = trait.getTypeConstructor().getParameters().get(index); 586 TypeSubstitutor deepSubstitutor = SubstitutionUtils.buildDeepSubstitutor(descriptor.getDefaultType()); 587 TypeProjection substitute = deepSubstitutor.substitute(new TypeProjection(listTypeParameter.getDefaultType())); 588 assert substitute != null : "Couldn't substitute: " + descriptor; 589 ClassifierDescriptor classifier = substitute.getType().getConstructor().getDeclarationDescriptor(); 590 assert classifier != null : "No classifier: " + substitute.getType(); 591 return classifier; 592 } 593 594 private List<PropertyDescriptor> getDataProperties() { 595 ArrayList<PropertyDescriptor> result = Lists.newArrayList(); 596 for (JetParameter parameter : getPrimaryConstructorParameters()) { 597 if (parameter.getValOrVarNode() != null) { 598 result.add(bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter)); 599 } 600 } 601 return result; 602 } 603 604 private void generateFunctionsForDataClasses() { 605 if (!KotlinBuiltIns.getInstance().isData(descriptor)) return; 606 607 generateComponentFunctionsForDataClasses(); 608 generateCopyFunctionForDataClasses(); 609 610 List<PropertyDescriptor> properties = getDataProperties(); 611 if (!properties.isEmpty()) { 612 generateDataClassToStringIfNeeded(properties); 613 generateDataClassHashCodeIfNeeded(properties); 614 generateDataClassEqualsIfNeeded(properties); 615 } 616 } 617 618 private void generateCopyFunctionForDataClasses() { 619 FunctionDescriptor copyFunction = bindingContext.get(BindingContext.DATA_CLASS_COPY_FUNCTION, descriptor); 620 if (copyFunction != null) { 621 generateCopyFunction(copyFunction); 622 } 623 } 624 625 private void generateDataClassToStringIfNeeded(List<PropertyDescriptor> properties) { 626 ClassDescriptor stringClass = KotlinBuiltIns.getInstance().getString(); 627 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("toString"), stringClass) == null) { 628 generateDataClassToStringMethod(properties); 629 } 630 } 631 632 private void generateDataClassHashCodeIfNeeded(List<PropertyDescriptor> properties) { 633 ClassDescriptor intClass = KotlinBuiltIns.getInstance().getInt(); 634 if (getDeclaredFunctionByRawSignature(descriptor, Name.identifier("hashCode"), intClass) == null) { 635 generateDataClassHashCodeMethod(properties); 636 } 637 } 638 639 private void generateDataClassEqualsIfNeeded(List<PropertyDescriptor> properties) { 640 ClassDescriptor booleanClass = KotlinBuiltIns.getInstance().getBoolean(); 641 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny(); 642 FunctionDescriptor equalsFunction = getDeclaredFunctionByRawSignature(descriptor, Name.identifier("equals"), booleanClass, anyClass); 643 if (equalsFunction == null) { 644 generateDataClassEqualsMethod(properties); 645 } 646 } 647 648 private void generateDataClassEqualsMethod(List<PropertyDescriptor> properties) { 649 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null); 650 InstructionAdapter iv = new InstructionAdapter(mv); 651 652 mv.visitCode(); 653 Label eq = new Label(); 654 Label ne = new Label(); 655 656 iv.load(0, OBJECT_TYPE); 657 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 658 iv.ifacmpeq(eq); 659 660 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 661 iv.instanceOf(classAsmType); 662 iv.ifeq(ne); 663 664 iv.load(1, AsmTypeConstants.OBJECT_TYPE); 665 iv.checkcast(classAsmType); 666 iv.store(2, AsmTypeConstants.OBJECT_TYPE); 667 668 for (PropertyDescriptor propertyDescriptor : properties) { 669 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 670 671 genPropertyOnStack(iv, propertyDescriptor, 0); 672 genPropertyOnStack(iv, propertyDescriptor, 2); 673 674 if (asmType.getSort() == Type.ARRAY) { 675 Type elementType = correctElementType(asmType); 676 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 677 iv.invokestatic("java/util/Arrays", "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z"); 678 } 679 else { 680 iv.invokestatic("java/util/Arrays", "equals", "([" + elementType.getDescriptor() + "[" + elementType.getDescriptor() + ")Z"); 681 } 682 } 683 else { 684 StackValue value = genEqualsForExpressionsOnStack(iv, JetTokens.EQEQ, asmType, asmType); 685 value.put(Type.BOOLEAN_TYPE, iv); 686 } 687 688 iv.ifeq(ne); 689 } 690 691 iv.mark(eq); 692 iv.iconst(1); 693 iv.areturn(Type.INT_TYPE); 694 695 iv.mark(ne); 696 iv.iconst(0); 697 iv.areturn(Type.INT_TYPE); 698 699 FunctionCodegen.endVisit(mv, "equals", myClass); 700 } 701 702 private void generateDataClassHashCodeMethod(List<PropertyDescriptor> properties) { 703 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "hashCode", "()I", null, null); 704 InstructionAdapter iv = new InstructionAdapter(mv); 705 706 mv.visitCode(); 707 boolean first = true; 708 for (PropertyDescriptor propertyDescriptor : properties) { 709 if (!first) { 710 iv.iconst(31); 711 iv.mul(Type.INT_TYPE); 712 } 713 714 genPropertyOnStack(iv, propertyDescriptor, 0); 715 716 Label ifNull = null; 717 Type asmType = typeMapper.mapType(propertyDescriptor.getType()); 718 if (!isPrimitive(asmType)) { 719 ifNull = new Label(); 720 iv.dup(); 721 iv.ifnull(ifNull); 722 } 723 724 genHashCode(mv, iv, asmType); 725 726 if (ifNull != null) { 727 Label end = new Label(); 728 iv.goTo(end); 729 iv.mark(ifNull); 730 iv.pop(); 731 iv.iconst(0); 732 iv.mark(end); 733 } 734 735 if (first) { 736 first = false; 737 } 738 else { 739 iv.add(Type.INT_TYPE); 740 } 741 } 742 743 mv.visitInsn(IRETURN); 744 745 FunctionCodegen.endVisit(mv, "hashCode", myClass); 746 } 747 748 private void generateDataClassToStringMethod(List<PropertyDescriptor> properties) { 749 MethodVisitor mv = v.getVisitor().visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null); 750 InstructionAdapter iv = new InstructionAdapter(mv); 751 752 mv.visitCode(); 753 genStringBuilderConstructor(iv); 754 755 boolean first = true; 756 for (PropertyDescriptor propertyDescriptor : properties) { 757 if (first) { 758 iv.aconst(descriptor.getName() + "(" + propertyDescriptor.getName().asString()+"="); 759 first = false; 760 } 761 else { 762 iv.aconst(", " + propertyDescriptor.getName().asString()+"="); 763 } 764 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 765 766 Type type = genPropertyOnStack(iv, propertyDescriptor, 0); 767 768 if (type.getSort() == Type.ARRAY) { 769 Type elementType = correctElementType(type); 770 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 771 iv.invokestatic("java/util/Arrays", "toString", "([Ljava/lang/Object;)Ljava/lang/String;"); 772 type = JAVA_STRING_TYPE; 773 } 774 else { 775 if (elementType.getSort() != Type.CHAR) { 776 iv.invokestatic("java/util/Arrays", "toString", "(" + type.getDescriptor() + ")Ljava/lang/String;"); 777 type = JAVA_STRING_TYPE; 778 } 779 } 780 } 781 genInvokeAppendMethod(iv, type); 782 } 783 784 iv.aconst(")"); 785 genInvokeAppendMethod(iv, JAVA_STRING_TYPE); 786 787 iv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;"); 788 iv.areturn(JAVA_STRING_TYPE); 789 790 FunctionCodegen.endVisit(mv, "toString", myClass); 791 } 792 793 private Type genPropertyOnStack(InstructionAdapter iv, PropertyDescriptor propertyDescriptor, int index) { 794 iv.load(index, classAsmType); 795 Method 796 method = typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION).getAsmMethod(); 797 798 iv.invokevirtual(classAsmType.getInternalName(), method.getName(), method.getDescriptor()); 799 return method.getReturnType(); 800 } 801 802 private void generateComponentFunctionsForDataClasses() { 803 if (!myClass.hasPrimaryConstructor() || !KotlinBuiltIns.getInstance().isData(descriptor)) return; 804 805 ConstructorDescriptor constructor = descriptor.getConstructors().iterator().next(); 806 807 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) { 808 FunctionDescriptor function = bindingContext.get(BindingContext.DATA_CLASS_COMPONENT_FUNCTION, parameter); 809 if (function != null) { 810 generateComponentFunction(function, parameter); 811 } 812 } 813 } 814 815 private void generateComponentFunction(@NotNull FunctionDescriptor function, @NotNull final ValueParameterDescriptor parameter) { 816 JetType returnType = function.getReturnType(); 817 assert returnType != null : "Return type of component function should not be null: " + function; 818 final Type componentType = typeMapper.mapReturnType(returnType); 819 820 JvmMethodSignature signature = typeMapper.mapSignature(function); 821 822 functionCodegen.generateMethod(myClass, signature, function, new FunctionGenerationStrategy() { 823 @Override 824 public void generateBody( 825 @NotNull MethodVisitor mv, 826 @NotNull JvmMethodSignature signature, 827 @NotNull MethodContext context, 828 @Nullable MemberCodegen parentCodegen 829 ) { 830 InstructionAdapter iv = new InstructionAdapter(mv); 831 if (!componentType.equals(Type.VOID_TYPE)) { 832 iv.load(0, classAsmType); 833 String desc = "()" + componentType.getDescriptor(); 834 iv.invokevirtual(classAsmType.getInternalName(), PropertyCodegen.getterName(parameter.getName()), desc); 835 } 836 iv.areturn(componentType); 837 } 838 }); 839 } 840 841 private void generateCopyFunction(@NotNull final FunctionDescriptor function) { 842 JvmMethodSignature methodSignature = typeMapper.mapSignature(function); 843 844 final Type thisDescriptorType = typeMapper.mapType(descriptor.getDefaultType()); 845 846 functionCodegen.generateMethod(myClass, methodSignature, function, new FunctionGenerationStrategy() { 847 @Override 848 public void generateBody( 849 @NotNull MethodVisitor mv, 850 @NotNull JvmMethodSignature signature, 851 @NotNull MethodContext context, 852 @Nullable MemberCodegen parentCodegen 853 ) { 854 InstructionAdapter iv = new InstructionAdapter(mv); 855 856 iv.anew(thisDescriptorType); 857 iv.dup(); 858 859 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor); 860 assert function.getValueParameters().size() == constructor.getValueParameters().size() : 861 "Number of parameters of copy function and constructor are different. " + 862 "Copy: " + function.getValueParameters().size() + ", " + 863 "constructor: " + constructor.getValueParameters().size(); 864 865 MutableClosure closure = ImplementationBodyCodegen.this.context.closure; 866 if (closure != null && closure.getCaptureThis() != null) { 867 Type type = typeMapper.mapType(enclosingClassDescriptor(bindingContext, descriptor)); 868 iv.load(0, classAsmType); 869 iv.getfield(classAsmType.getInternalName(), CAPTURED_THIS_FIELD, type.getDescriptor()); 870 } 871 872 int parameterIndex = 1; // localVariable 0 = this 873 for (ValueParameterDescriptor parameterDescriptor : function.getValueParameters()) { 874 Type type = typeMapper.mapType(parameterDescriptor.getType()); 875 iv.load(parameterIndex, type); 876 parameterIndex += type.getSize(); 877 } 878 879 String constructorJvmDescriptor = typeMapper.mapToCallableMethod(constructor).getSignature().getAsmMethod().getDescriptor(); 880 iv.invokespecial(thisDescriptorType.getInternalName(), "<init>", constructorJvmDescriptor); 881 882 iv.areturn(thisDescriptorType); 883 } 884 }); 885 886 MethodContext functionContext = context.intoFunction(function); 887 888 functionCodegen.generateDefaultIfNeeded(functionContext, methodSignature, function, OwnerKind.IMPLEMENTATION, 889 new DefaultParameterValueLoader() { 890 @Override 891 public void putValueOnStack( 892 ValueParameterDescriptor descriptor, 893 ExpressionCodegen codegen 894 ) { 895 assert (KotlinBuiltIns.getInstance() 896 .isData((ClassDescriptor) function.getContainingDeclaration())) 897 : "Trying to create function with default arguments for function that isn't presented in code for class without data annotation"; 898 PropertyDescriptor propertyDescriptor = codegen.getBindingContext().get( 899 BindingContext.VALUE_PARAMETER_AS_PROPERTY, descriptor); 900 assert propertyDescriptor != null 901 : "Trying to generate default value for parameter of copy function that doesn't correspond to any property"; 902 codegen.v.load(0, thisDescriptorType); 903 Type propertyType = codegen.typeMapper.mapType(propertyDescriptor.getType()); 904 codegen.intermediateValueForProperty(propertyDescriptor, false, null) 905 .put(propertyType, codegen.v); 906 } 907 }); 908 909 } 910 911 private void generateEnumMethodsAndConstInitializers() { 912 if (!myEnumConstants.isEmpty()) { 913 generateEnumMethods(); 914 915 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 916 initializeEnumConstants(createOrGetClInitCodegen()); 917 } 918 } 919 } 920 921 private void generateEnumMethods() { 922 if (myEnumConstants.size() > 0) { 923 { 924 Type type = 925 typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()), 926 JetTypeMapperMode.IMPL); 927 928 MethodVisitor mv = 929 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null); 930 mv.visitCode(); 931 mv.visitFieldInsn(GETSTATIC, typeMapper.mapType(descriptor).getInternalName(), 932 VALUES, 933 type.getDescriptor()); 934 mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;"); 935 mv.visitTypeInsn(CHECKCAST, type.getInternalName()); 936 mv.visitInsn(ARETURN); 937 FunctionCodegen.endVisit(mv, "values()", myClass); 938 } 939 { 940 941 MethodVisitor mv = 942 v.newMethod(myClass, ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, 943 null); 944 mv.visitCode(); 945 mv.visitLdcInsn(classAsmType); 946 mv.visitVarInsn(ALOAD, 0); 947 mv.visitMethodInsn(INVOKESTATIC, "java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;"); 948 mv.visitTypeInsn(CHECKCAST, classAsmType.getInternalName()); 949 mv.visitInsn(ARETURN); 950 FunctionCodegen.endVisit(mv, "values()", myClass); 951 } 952 } 953 } 954 955 protected void generateSyntheticAccessors() { 956 Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors(); 957 for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) { 958 generateSyntheticAccessor(entry); 959 } 960 } 961 962 private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) { 963 if (entry.getValue() instanceof FunctionDescriptor) { 964 FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue(); 965 final FunctionDescriptor original = (FunctionDescriptor) entry.getKey(); 966 functionCodegen.generateMethod(null, typeMapper.mapSignature(bridge), bridge, 967 new FunctionGenerationStrategy.CodegenBased<FunctionDescriptor>(state, bridge) { 968 @Override 969 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 970 generateMethodCallTo(original, codegen.v); 971 972 codegen.v.areturn(signature.getAsmMethod().getReturnType()); 973 } 974 }); 975 } 976 else if (entry.getValue() instanceof PropertyDescriptor) { 977 final PropertyDescriptor bridge = (PropertyDescriptor) entry.getValue(); 978 final PropertyDescriptor original = (PropertyDescriptor) entry.getKey(); 979 980 981 PropertyGetterDescriptor getter = bridge.getGetter(); 982 assert getter != null; 983 functionCodegen.generateMethod(null, typeMapper.mapGetterSignature(bridge, OwnerKind.IMPLEMENTATION), getter, 984 new FunctionGenerationStrategy.CodegenBased<PropertyGetterDescriptor>(state, getter) { 985 @Override 986 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 987 InstructionAdapter iv = codegen.v; 988 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 989 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 990 if (!forceField) { 991 iv.load(0, OBJECT_TYPE); 992 } 993 property.put(property.type, iv); 994 iv.areturn(signature.getAsmMethod().getReturnType()); 995 } 996 }); 997 998 999 if (bridge.isVar()) { 1000 PropertySetterDescriptor setter = bridge.getSetter(); 1001 assert setter != null; 1002 1003 functionCodegen.generateMethod(null, typeMapper.mapSetterSignature(bridge, OwnerKind.IMPLEMENTATION), setter, 1004 new FunctionGenerationStrategy.CodegenBased<PropertySetterDescriptor>(state, setter) { 1005 @Override 1006 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 1007 boolean forceField = AsmUtil.isPropertyWithBackingFieldInOuterClass(original) && !isClassObject(bridge.getContainingDeclaration()); 1008 StackValue property = codegen.intermediateValueForProperty(original, forceField, null, MethodKind.SYNTHETIC_ACCESSOR); 1009 InstructionAdapter iv = codegen.v; 1010 1011 Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); 1012 for (int i = 0, reg = 0; i < argTypes.length; i++) { 1013 Type argType = argTypes[i]; 1014 iv.load(reg, argType); 1015 //noinspection AssignmentToForLoopParameter 1016 reg += argType.getSize(); 1017 } 1018 property.store(property.type, iv); 1019 1020 iv.areturn(signature.getAsmMethod().getReturnType()); 1021 } 1022 }); 1023 } 1024 } 1025 else { 1026 throw new UnsupportedOperationException(); 1027 } 1028 } 1029 1030 private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) { 1031 boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor; 1032 boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor); 1033 CallableMethod callableMethod = isConstructor ? 1034 typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) : 1035 typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, 1036 isCallInsideSameClassAsDeclared(functionDescriptor, context), 1037 isCallInsideSameModuleAsDeclared(functionDescriptor, context), 1038 context.getContextKind()); 1039 1040 Method method = callableMethod.getSignature().getAsmMethod(); 1041 Type[] argTypes = method.getArgumentTypes(); 1042 1043 int reg = 1; 1044 if (isConstructor) { 1045 iv.anew(callableMethod.getOwner()); 1046 iv.dup(); 1047 reg = 0; 1048 } 1049 else if (callFromAccessor) { 1050 iv.load(0, OBJECT_TYPE); 1051 } 1052 1053 for (int paramIndex = 0; paramIndex < argTypes.length; paramIndex++) { 1054 Type argType = argTypes[paramIndex]; 1055 iv.load(reg, argType); 1056 //noinspection AssignmentToForLoopParameter 1057 reg += argType.getSize(); 1058 } 1059 callableMethod.invokeWithoutAssertions(iv); 1060 } 1061 1062 private void generateFieldForSingleton() { 1063 boolean hasClassObject = descriptor.getClassObjectDescriptor() != null; 1064 boolean isEnumClass = DescriptorUtils.isEnumClass(descriptor); 1065 boolean isObjectDeclaration = descriptor.getKind() == ClassKind.OBJECT && isNonLiteralObject(myClass) ; 1066 1067 if (!isObjectDeclaration && !hasClassObject || isEnumClass) return; 1068 1069 ClassDescriptor fieldTypeDescriptor = hasClassObject ? descriptor.getClassObjectDescriptor() : descriptor; 1070 assert fieldTypeDescriptor != null; 1071 StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper); 1072 JetClassOrObject original; 1073 if (hasClassObject) { 1074 JetClassObject classObject = ((JetClass) myClass).getClassObject(); 1075 assert classObject != null : myClass.getText(); 1076 original = classObject.getObjectDeclaration(); 1077 } 1078 else { 1079 original = myClass; 1080 } 1081 1082 v.newField(original, ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); 1083 1084 if (!AsmUtil.isClassObjectWithBackingFieldsInOuter(fieldTypeDescriptor)) { 1085 genInitSingleton(fieldTypeDescriptor, field); 1086 } 1087 } 1088 1089 private void generateClassObjectBackingFieldCopies() { 1090 if (classObjectPropertiesToCopy != null) { 1091 for (PropertyAndDefaultValue propertyInfo : classObjectPropertiesToCopy) { 1092 PropertyDescriptor propertyDescriptor = propertyInfo.propertyDescriptor; 1093 1094 v.newField(null, ACC_STATIC | ACC_FINAL | ACC_PUBLIC, context.getFieldName(propertyDescriptor), 1095 typeMapper.mapType(propertyDescriptor).getDescriptor(), null, propertyInfo.defaultValue); 1096 1097 //This field are always static and final so if it has constant initializer don't do anything in clinit, 1098 //field would be initialized via default value in v.newField(...) - see JVM SPEC Ch.4 1099 // TODO: test this code 1100 if (state.getClassBuilderMode() == ClassBuilderMode.FULL && propertyInfo.defaultValue == null) { 1101 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1102 int classObjectIndex = putClassObjectInLocalVar(codegen); 1103 StackValue.local(classObjectIndex, OBJECT_TYPE).put(OBJECT_TYPE, codegen.v); 1104 copyFieldFromClassObject(propertyDescriptor); 1105 } 1106 } 1107 } 1108 } 1109 1110 private int putClassObjectInLocalVar(ExpressionCodegen codegen) { 1111 FrameMap frameMap = codegen.myFrameMap; 1112 ClassDescriptor classObjectDescriptor = descriptor.getClassObjectDescriptor(); 1113 int classObjectIndex = frameMap.getIndex(classObjectDescriptor); 1114 if (classObjectIndex == -1) { 1115 classObjectIndex = frameMap.enter(classObjectDescriptor, OBJECT_TYPE); 1116 StackValue classObject = StackValue.singleton(classObjectDescriptor, typeMapper); 1117 classObject.put(classObject.type, codegen.v); 1118 StackValue.local(classObjectIndex, classObject.type).store(classObject.type, codegen.v); 1119 } 1120 return classObjectIndex; 1121 } 1122 1123 private void copyFieldFromClassObject(PropertyDescriptor propertyDescriptor) { 1124 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1125 StackValue property = codegen.intermediateValueForProperty(propertyDescriptor, false, null); 1126 property.put(property.type, codegen.v); 1127 StackValue.Field field = StackValue.field(property.type, classAsmType, propertyDescriptor.getName().asString(), true); 1128 field.store(field.type, codegen.v); 1129 } 1130 1131 protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) { 1132 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1133 ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor); 1134 ExpressionCodegen codegen = createOrGetClInitCodegen(); 1135 FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor); 1136 generateMethodCallTo(fd, codegen.v); 1137 field.store(field.type, codegen.v); 1138 } 1139 } 1140 1141 protected void generatePrimaryConstructor() { 1142 if (ignoreIfTraitOrAnnotation()) return; 1143 1144 if (kind != OwnerKind.IMPLEMENTATION) { 1145 throw new IllegalStateException("incorrect kind for primary constructor: " + kind); 1146 } 1147 1148 final MutableClosure closure = context.closure; 1149 ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); 1150 1151 ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor); 1152 1153 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1154 lookupConstructorExpressionsInClosureIfPresent(constructorContext); 1155 } 1156 1157 assert constructorDescriptor != null; 1158 final JvmMethodSignature constructorSignature = typeMapper.mapConstructorSignature(constructorDescriptor, closure); 1159 1160 functionCodegen.generateMethod(null, constructorSignature, constructorDescriptor, constructorContext, 1161 new FunctionGenerationStrategy.CodegenBased<ConstructorDescriptor>(state, constructorDescriptor) { 1162 1163 @NotNull 1164 @Override 1165 protected FrameMap createFrameMap(@NotNull JetTypeMapper typeMapper, @NotNull MethodContext context) { 1166 return new ConstructorFrameMap(constructorSignature); 1167 } 1168 1169 @Override 1170 public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { 1171 generatePrimaryConstructorImpl(callableDescriptor, codegen, closure); 1172 } 1173 } 1174 ); 1175 1176 functionCodegen.generateDefaultIfNeeded(constructorContext, constructorSignature, constructorDescriptor, 1177 OwnerKind.IMPLEMENTATION, DefaultParameterValueLoader.DEFAULT); 1178 1179 CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, closure); 1180 FunctionCodegen.generateConstructorWithoutParametersIfNeeded(state, callableMethod, constructorDescriptor, v); 1181 1182 if (isClassObject(descriptor)) { 1183 context.recordSyntheticAccessorIfNeeded(constructorDescriptor, typeMapper); 1184 } 1185 } 1186 1187 private void generatePrimaryConstructorImpl( 1188 @Nullable ConstructorDescriptor constructorDescriptor, 1189 @NotNull ExpressionCodegen codegen, 1190 @Nullable MutableClosure closure 1191 ) { 1192 List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null 1193 ? constructorDescriptor.getValueParameters() 1194 : Collections.<ValueParameterDescriptor>emptyList(); 1195 1196 InstructionAdapter iv = codegen.v; 1197 1198 if (superCall == null) { 1199 genSimpleSuperCall(iv); 1200 } 1201 else if (superCall instanceof JetDelegatorToSuperClass) { 1202 genSuperCallToDelegatorToSuperClass(iv); 1203 } 1204 else { 1205 generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor); 1206 } 1207 1208 if (closure != null) { 1209 List<FieldInfo> argsFromClosure = ClosureCodegen.calculateConstructorParameters(typeMapper, closure, classAsmType); 1210 int k = 1; 1211 for (FieldInfo info : argsFromClosure) { 1212 k = AsmUtil.genAssignInstanceFieldFromParam(info, k, iv); 1213 } 1214 } 1215 1216 int n = 0; 1217 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1218 if (specifier == superCall) { 1219 continue; 1220 } 1221 1222 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1223 genCallToDelegatorByExpressionSpecifier(iv, codegen, n++, specifier); 1224 } 1225 } 1226 1227 int curParam = 0; 1228 List<JetParameter> constructorParameters = getPrimaryConstructorParameters(); 1229 for (JetParameter parameter : constructorParameters) { 1230 if (parameter.getValOrVarNode() != null) { 1231 VariableDescriptor descriptor = paramDescrs.get(curParam); 1232 Type type = typeMapper.mapType(descriptor); 1233 iv.load(0, classAsmType); 1234 iv.load(codegen.myFrameMap.getIndex(descriptor), type); 1235 PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 1236 assert propertyDescriptor != null : "Property descriptor is not found for primary constructor parameter: " + parameter; 1237 iv.putfield(classAsmType.getInternalName(), context.getFieldName(propertyDescriptor), type.getDescriptor()); 1238 } 1239 curParam++; 1240 } 1241 1242 boolean generateInitializerInOuter = isClassObjectWithBackingFieldsInOuter(descriptor); 1243 if (generateInitializerInOuter) { 1244 ImplementationBodyCodegen parentCodegen = getParentBodyCodegen(this); 1245 //generate object$ 1246 parentCodegen.genInitSingleton(descriptor, StackValue.singleton(descriptor, typeMapper)); 1247 parentCodegen.generateInitializers(parentCodegen.createOrGetClInitCodegen(), 1248 myClass.getDeclarations(), bindingContext, state); 1249 } else { 1250 generateInitializers(codegen, myClass.getDeclarations(), bindingContext, state); 1251 } 1252 1253 1254 iv.visitInsn(RETURN); 1255 } 1256 1257 private void genSuperCallToDelegatorToSuperClass(InstructionAdapter iv) { 1258 iv.load(0, superClassAsmType); 1259 JetType superType = bindingContext.get(BindingContext.TYPE, superCall.getTypeReference()); 1260 List<Type> parameterTypes = new ArrayList<Type>(); 1261 assert superType != null; 1262 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 1263 if (CodegenBinding.hasThis0(bindingContext, superClassDescriptor)) { 1264 iv.load(1, OBJECT_TYPE); 1265 parameterTypes.add(typeMapper.mapType( 1266 enclosingClassDescriptor(bindingContext, descriptor))); 1267 } 1268 Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); 1269 //noinspection ConstantConditions 1270 iv.invokespecial(typeMapper.mapType(superClassDescriptor).getInternalName(), "<init>", 1271 superCallMethod.getDescriptor()); 1272 } 1273 1274 private void genSimpleSuperCall(InstructionAdapter iv) { 1275 iv.load(0, superClassAsmType); 1276 if (descriptor.getKind() == ClassKind.ENUM_CLASS || descriptor.getKind() == ClassKind.ENUM_ENTRY) { 1277 iv.load(1, JAVA_STRING_TYPE); 1278 iv.load(2, Type.INT_TYPE); 1279 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(Ljava/lang/String;I)V"); 1280 } 1281 else { 1282 iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V"); 1283 } 1284 } 1285 1286 private void genCallToDelegatorByExpressionSpecifier( 1287 InstructionAdapter iv, 1288 ExpressionCodegen codegen, 1289 int n, 1290 JetDelegationSpecifier specifier 1291 ) { 1292 JetExpression expression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1293 PropertyDescriptor propertyDescriptor = null; 1294 if (expression instanceof JetSimpleNameExpression) { 1295 ResolvedCall<? extends CallableDescriptor> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression); 1296 if (call != null) { 1297 CallableDescriptor callResultingDescriptor = call.getResultingDescriptor(); 1298 if (callResultingDescriptor instanceof ValueParameterDescriptor) { 1299 ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) callResultingDescriptor; 1300 // constructor parameter 1301 if (valueParameterDescriptor.getContainingDeclaration() instanceof ConstructorDescriptor) { 1302 // constructor of my class 1303 if (valueParameterDescriptor.getContainingDeclaration().getContainingDeclaration() == descriptor) { 1304 propertyDescriptor = bindingContext.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, valueParameterDescriptor); 1305 } 1306 } 1307 } 1308 1309 // todo: when and if frontend will allow properties defined not as constructor parameters to be used in delegation specifier 1310 } 1311 } 1312 1313 JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference()); 1314 assert superType != null; 1315 1316 ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 1317 assert superClassDescriptor != null; 1318 1319 StackValue field; 1320 if (propertyDescriptor != null && 1321 !propertyDescriptor.isVar() && 1322 Boolean.TRUE.equals(bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor))) { 1323 // final property with backing field 1324 field = StackValue.field(typeMapper.mapType(propertyDescriptor.getType()), classAsmType, 1325 propertyDescriptor.getName().asString(), false); 1326 } 1327 else { 1328 iv.load(0, classAsmType); 1329 codegen.genToJVMStack(expression); 1330 1331 String delegateField = "$delegate_" + n; 1332 Type fieldType = typeMapper.mapType(superClassDescriptor); 1333 String fieldDesc = fieldType.getDescriptor(); 1334 1335 v.newField(specifier, ACC_PRIVATE | ACC_FINAL | ACC_SYNTHETIC, delegateField, fieldDesc, /*TODO*/null, null); 1336 1337 field = StackValue.field(fieldType, classAsmType, delegateField, false); 1338 field.store(fieldType, iv); 1339 } 1340 1341 generateDelegates(superClassDescriptor, field); 1342 } 1343 1344 private void lookupConstructorExpressionsInClosureIfPresent(final ConstructorContext constructorContext) { 1345 JetVisitorVoid visitor = new JetVisitorVoid() { 1346 @Override 1347 public void visitJetElement(JetElement e) { 1348 e.acceptChildren(this); 1349 } 1350 1351 @Override 1352 public void visitSimpleNameExpression(JetSimpleNameExpression expr) { 1353 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expr); 1354 if (descriptor instanceof VariableDescriptor && !(descriptor instanceof PropertyDescriptor)) { 1355 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) constructorContext.getContextDescriptor(); 1356 for (ValueParameterDescriptor parameterDescriptor : constructorDescriptor.getValueParameters()) { 1357 //noinspection ConstantConditions 1358 if (descriptor.equals(parameterDescriptor)) { 1359 return; 1360 } 1361 } 1362 constructorContext.lookupInContext(descriptor, null, state, true); 1363 } else if (isLocalNamedFun(descriptor)) { 1364 assert descriptor != null; 1365 MutableClassDescriptor classDescriptor = 1366 (MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor(); 1367 1368 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getAllCallableMembers()) { 1369 if (descriptor.equals(memberDescriptor)) { 1370 return; 1371 } 1372 } 1373 constructorContext.lookupInContext(descriptor, null, state, true); 1374 } 1375 } 1376 1377 @Override 1378 public void visitThisExpression(JetThisExpression expression) { 1379 DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference()); 1380 if (descriptor instanceof ClassDescriptor) { 1381 // @todo for now all our classes are inner so no need to lookup this. change it when we have real inners 1382 } 1383 else { 1384 assert descriptor instanceof CallableDescriptor; 1385 if (context.getCallableDescriptorWithReceiver() != descriptor) { 1386 context.lookupInContext(descriptor, null, state, true); 1387 } 1388 } 1389 } 1390 }; 1391 1392 for (JetDeclaration declaration : myClass.getDeclarations()) { 1393 if (declaration instanceof JetProperty) { 1394 JetProperty property = (JetProperty) declaration; 1395 JetExpression initializer = property.getInitializer(); 1396 if (initializer != null) { 1397 initializer.accept(visitor); 1398 } 1399 } 1400 else if (declaration instanceof JetClassInitializer) { 1401 JetClassInitializer initializer = (JetClassInitializer) declaration; 1402 initializer.accept(visitor); 1403 } 1404 } 1405 1406 for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) { 1407 if (specifier != superCall) { 1408 if (specifier instanceof JetDelegatorByExpressionSpecifier) { 1409 JetExpression delegateExpression = ((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression(); 1410 assert delegateExpression != null; 1411 delegateExpression.accept(visitor); 1412 } 1413 } 1414 else { 1415 if (superCall instanceof JetDelegatorToSuperCall) { 1416 JetValueArgumentList argumentList = ((JetDelegatorToSuperCall) superCall).getValueArgumentList(); 1417 if (argumentList != null) { 1418 argumentList.accept(visitor); 1419 } 1420 } 1421 } 1422 } 1423 } 1424 1425 private boolean ignoreIfTraitOrAnnotation() { 1426 if (myClass instanceof JetClass) { 1427 JetClass aClass = (JetClass) myClass; 1428 if (aClass.isTrait()) { 1429 return true; 1430 } 1431 if (aClass.isAnnotation()) { 1432 return true; 1433 } 1434 } 1435 return false; 1436 } 1437 1438 private void generateTraitMethods() { 1439 if (JetPsiUtil.isTrait(myClass)) { 1440 return; 1441 } 1442 1443 for (Pair<CallableMemberDescriptor, CallableMemberDescriptor> needDelegates : getTraitImplementations(descriptor)) { 1444 if (needDelegates.second instanceof SimpleFunctionDescriptor) { 1445 generateDelegationToTraitImpl((FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first); 1446 } 1447 else if (needDelegates.second instanceof PropertyDescriptor) { 1448 PropertyDescriptor property = (PropertyDescriptor) needDelegates.second; 1449 List<PropertyAccessorDescriptor> inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors(); 1450 for (PropertyAccessorDescriptor accessor : property.getAccessors()) { 1451 for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) { 1452 if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind 1453 generateDelegationToTraitImpl(accessor, inheritedAccessor); 1454 } 1455 } 1456 } 1457 } 1458 } 1459 } 1460 1461 1462 private void generateDelegationToTraitImpl(final @NotNull FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) { 1463 DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); 1464 if (!(containingDeclaration instanceof ClassDescriptor)) { 1465 return; 1466 } 1467 1468 ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration; 1469 if (containingClass.getKind() != ClassKind.TRAIT) { 1470 return; 1471 } 1472 1473 int flags = ACC_PUBLIC; // TODO. 1474 1475 TraitImplDelegateInfo delegateInfo = getTraitImplDelegateInfo(fun); 1476 Method methodToGenerate = delegateInfo.methodToGenerate; 1477 Method methodInTrait = delegateInfo.methodInTrait; 1478 1479 PsiElement origin = descriptorToDeclaration(bindingContext, fun); 1480 MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null, null); 1481 AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(fun); 1482 1483 if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { 1484 Type returnType = methodToGenerate.getReturnType(); 1485 1486 mv.visitCode(); 1487 FrameMap frameMap = context.prepareFrame(typeMapper); 1488 ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state, this); 1489 codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it? 1490 1491 Type[] argTypes = methodToGenerate.getArgumentTypes(); 1492 Type[] originalArgTypes = methodInTrait.getArgumentTypes(); 1493 1494 InstructionAdapter iv = new InstructionAdapter(mv); 1495 iv.load(0, OBJECT_TYPE); 1496 for (int i = 0, reg = 1; i < argTypes.length; i++) { 1497 StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); 1498 //noinspection AssignmentToForLoopParameter 1499 reg += argTypes[i].getSize(); 1500 } 1501 1502 Type type = getTraitImplThisParameterType(containingClass, typeMapper); 1503 String functionDescriptor = methodInTrait.getDescriptor().replace("(", "(" + type.getDescriptor()); 1504 1505 Type tImplType = typeMapper.mapType(containingClass.getDefaultType(), JetTypeMapperMode.TRAIT_IMPL); 1506 1507 iv.invokestatic(tImplType.getInternalName(), methodToGenerate.getName(), functionDescriptor); 1508 StackValue.onStack(methodInTrait.getReturnType()).put(returnType, iv); 1509 iv.areturn(returnType); 1510 1511 FunctionCodegen.endVisit(iv, "trait method", callableDescriptorToDeclaration(bindingContext, fun)); 1512 } 1513 1514 FunctionCodegen.generateBridgeIfNeeded(context, state, v, methodToGenerate, fun); 1515 } 1516 1517 private static class TraitImplDelegateInfo { 1518 private final Method methodToGenerate; 1519 private final Method methodInTrait; 1520 1521 private TraitImplDelegateInfo(@NotNull Method methodToGenerate, @NotNull Method methodInTrait) { 1522 this.methodToGenerate = methodToGenerate; 1523 this.methodInTrait = methodInTrait; 1524 } 1525 } 1526 1527 @NotNull 1528 private TraitImplDelegateInfo getTraitImplDelegateInfo(@NotNull FunctionDescriptor fun) { 1529 if (fun instanceof PropertyAccessorDescriptor) { 1530 PropertyDescriptor property = ((PropertyAccessorDescriptor) fun).getCorrespondingProperty(); 1531 PropertyDescriptor original = property.getOriginal(); 1532 if (fun instanceof PropertyGetterDescriptor) { 1533 JvmMethodSignature toGenerate = typeMapper.mapGetterSignature(property, OwnerKind.IMPLEMENTATION); 1534 JvmMethodSignature inTrait = typeMapper.mapGetterSignature(original, OwnerKind.IMPLEMENTATION); 1535 return new TraitImplDelegateInfo( 1536 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1537 } 1538 else if (fun instanceof PropertySetterDescriptor) { 1539 JvmMethodSignature toGenerate = typeMapper.mapSetterSignature(property, OwnerKind.IMPLEMENTATION); 1540 JvmMethodSignature inTrait = typeMapper.mapSetterSignature(original, OwnerKind.IMPLEMENTATION); 1541 return new TraitImplDelegateInfo( 1542 toGenerate.getAsmMethod(), inTrait.getAsmMethod()); 1543 } 1544 else { 1545 throw new IllegalStateException("Accessor is neither getter, nor setter, what is it? " + fun); 1546 } 1547 } 1548 else { 1549 Method function = typeMapper.mapSignature(fun).getAsmMethod(); 1550 Method functionOriginal = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod(); 1551 return new TraitImplDelegateInfo(function, functionOriginal); 1552 } 1553 } 1554 1555 private void generateDelegatorToConstructorCall( 1556 InstructionAdapter iv, ExpressionCodegen codegen, 1557 ConstructorDescriptor constructorDescriptor 1558 ) { 1559 ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration(); 1560 1561 iv.load(0, OBJECT_TYPE); 1562 1563 if (classDecl.getKind() == ClassKind.ENUM_CLASS || classDecl.getKind() == ClassKind.ENUM_ENTRY) { 1564 iv.load(1, OBJECT_TYPE); 1565 iv.load(2, Type.INT_TYPE); 1566 } 1567 1568 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, context.closure); 1569 1570 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1571 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetCallElement) superCall).getCalleeExpression()); 1572 assert resolvedCall != null; 1573 ConstructorDescriptor superConstructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1574 1575 //noinspection SuspiciousMethodCalls 1576 CalculatedClosure closureForSuper = bindingContext.get(CLOSURE, superConstructor.getContainingDeclaration()); 1577 CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, closureForSuper); 1578 1579 if (closureForSuper != null && closureForSuper.getCaptureThis() != null) { 1580 iv.load(((ConstructorFrameMap)codegen.myFrameMap).getOuterThisIndex(), OBJECT_TYPE); 1581 } 1582 1583 if (myClass instanceof JetObjectDeclaration && 1584 superCall instanceof JetDelegatorToSuperCall && 1585 ((JetObjectDeclaration) myClass).isObjectLiteral()) { 1586 int nextVar = findFirstSuperArgument(method); 1587 for (Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { 1588 iv.load(nextVar, t); 1589 nextVar += t.getSize(); 1590 } 1591 superCallable.invokeWithNotNullAssertion(codegen.v, state, resolvedCall); 1592 } 1593 else { 1594 codegen.invokeMethodWithArguments(superCallable, resolvedCall, null, StackValue.none()); 1595 } 1596 } 1597 1598 private static int findFirstSuperArgument(CallableMethod method) { 1599 List<JvmMethodParameterSignature> types = method.getSignature().getKotlinParameterTypes(); 1600 int i = 0; 1601 for (JvmMethodParameterSignature type : types) { 1602 if (type.getKind() == JvmMethodParameterKind.SUPER_CALL_PARAM) { 1603 return i + 1; // because of this 1604 } 1605 i += type.getAsmType().getSize(); 1606 } 1607 return -1; 1608 } 1609 1610 @Override 1611 protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration) { 1612 if (declaration instanceof JetEnumEntry) { 1613 String name = declaration.getName(); 1614 assert name != null : "Enum entry has no name: " + declaration.getText(); 1615 String desc = "L" + classAsmType.getInternalName() + ";"; 1616 v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null); 1617 myEnumConstants.add((JetEnumEntry) declaration); 1618 } 1619 1620 super.generateDeclaration(propertyCodegen, declaration); 1621 } 1622 1623 private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>(); 1624 1625 private void initializeEnumConstants(ExpressionCodegen codegen) { 1626 InstructionAdapter iv = codegen.v; 1627 int ordinal = -1; 1628 JetType myType = descriptor.getDefaultType(); 1629 Type myAsmType = typeMapper.mapType(myType, JetTypeMapperMode.IMPL); 1630 1631 assert myEnumConstants.size() > 0; 1632 JetType arrayType = KotlinBuiltIns.getInstance().getArrayType(myType); 1633 Type arrayAsmType = typeMapper.mapType(arrayType, JetTypeMapperMode.IMPL); 1634 v.newField(myClass, ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, "$VALUES", arrayAsmType.getDescriptor(), null, null); 1635 1636 iv.iconst(myEnumConstants.size()); 1637 iv.newarray(myAsmType); 1638 iv.dup(); 1639 1640 for (JetEnumEntry enumConstant : myEnumConstants) { 1641 ordinal++; 1642 1643 iv.dup(); 1644 iv.iconst(ordinal); 1645 1646 ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, enumConstant); 1647 assert classDescriptor != null; 1648 String implClass = typeMapper.mapType(classDescriptor.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(); 1649 1650 List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers(); 1651 if (delegationSpecifiers.size() > 1) { 1652 throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported"); 1653 } 1654 1655 iv.anew(Type.getObjectType(implClass)); 1656 iv.dup(); 1657 1658 iv.aconst(enumConstant.getName()); 1659 iv.iconst(ordinal); 1660 1661 if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(state.getBindingContext(), enumConstant)) { 1662 JetDelegationSpecifier specifier = delegationSpecifiers.get(0); 1663 if (specifier instanceof JetDelegatorToSuperCall) { 1664 ResolvedCall<? extends CallableDescriptor> resolvedCall = 1665 bindingContext.get(BindingContext.RESOLVED_CALL, ((JetDelegatorToSuperCall) specifier).getCalleeExpression()); 1666 assert resolvedCall != null : "Enum entry delegation specifier is unresolved: " + specifier.getText(); 1667 1668 ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor(); 1669 CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor); 1670 1671 codegen.invokeMethodWithArguments(method, resolvedCall, null, StackValue.none()); 1672 } 1673 else { 1674 throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); 1675 } 1676 } 1677 else { 1678 iv.invokespecial(implClass, "<init>", "(Ljava/lang/String;I)V"); 1679 } 1680 iv.dup(); 1681 iv.putstatic(myAsmType.getInternalName(), enumConstant.getName(), "L" + myAsmType.getInternalName() + ";"); 1682 iv.astore(OBJECT_TYPE); 1683 } 1684 iv.putstatic(myAsmType.getInternalName(), "$VALUES", arrayAsmType.getDescriptor()); 1685 } 1686 1687 public static void generateInitializers( 1688 @NotNull ExpressionCodegen codegen, @NotNull List<JetDeclaration> declarations, 1689 @NotNull BindingContext bindingContext, @NotNull GenerationState state 1690 ) { 1691 JetTypeMapper typeMapper = state.getTypeMapper(); 1692 for (JetDeclaration declaration : declarations) { 1693 if (declaration instanceof JetProperty) { 1694 if (shouldInitializeProperty((JetProperty) declaration, typeMapper)) { 1695 initializeProperty(codegen, bindingContext, (JetProperty) declaration); 1696 } 1697 } 1698 else if (declaration instanceof JetClassInitializer) { 1699 codegen.gen(((JetClassInitializer) declaration).getBody(), Type.VOID_TYPE); 1700 } 1701 } 1702 } 1703 1704 1705 public static void initializeProperty( 1706 @NotNull ExpressionCodegen codegen, 1707 @NotNull BindingContext bindingContext, 1708 @NotNull JetProperty property 1709 ) { 1710 1711 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(BindingContext.VARIABLE, property); 1712 assert propertyDescriptor != null; 1713 1714 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1715 assert initializer != null : "shouldInitializeProperty must return false if initializer is null"; 1716 1717 JetType jetType = getPropertyOrDelegateType(bindingContext, property, propertyDescriptor); 1718 1719 StackValue.StackValueWithSimpleReceiver propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, null, MethodKind.INITIALIZER); 1720 1721 if (!propValue.isStatic) { 1722 codegen.v.load(0, OBJECT_TYPE); 1723 } 1724 1725 Type type = codegen.expressionType(initializer); 1726 if (jetType.isNullable()) { 1727 type = boxType(type); 1728 } 1729 codegen.gen(initializer, type); 1730 1731 propValue.store(type, codegen.v); 1732 } 1733 1734 public static boolean shouldWriteFieldInitializer(PropertyDescriptor descriptor, JetTypeMapper mapper) { 1735 //final field of primitive or String type 1736 if (!descriptor.isVar()) { 1737 Type type = mapper.mapType(descriptor.getType()); 1738 return AsmUtil.isPrimitive(type) || "java.lang.String".equals(type.getClassName()); 1739 } 1740 return false; 1741 } 1742 1743 public static boolean shouldInitializeProperty( 1744 @NotNull JetProperty property, 1745 @NotNull JetTypeMapper typeMapper 1746 ) { 1747 JetExpression initializer = property.getDelegateExpressionOrInitializer(); 1748 if (initializer == null) return false; 1749 1750 CompileTimeConstant<?> compileTimeValue = typeMapper.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); 1751 if (compileTimeValue == null) return true; 1752 1753 PropertyDescriptor propertyDescriptor = (PropertyDescriptor) typeMapper.getBindingContext().get(BindingContext.VARIABLE, property); 1754 assert propertyDescriptor != null; 1755 1756 //TODO: OPTIMIZATION: don't initialize static final fields 1757 1758 Object value = compileTimeValue.getValue(); 1759 JetType jetType = getPropertyOrDelegateType(typeMapper.getBindingContext(), property, propertyDescriptor); 1760 Type type = typeMapper.mapType(jetType); 1761 return !skipDefaultValue(propertyDescriptor, value, type); 1762 } 1763 1764 @NotNull 1765 private static JetType getPropertyOrDelegateType(@NotNull BindingContext bindingContext, @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { 1766 JetExpression delegateExpression = property.getDelegateExpression(); 1767 if (delegateExpression != null) { 1768 JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression); 1769 assert delegateType != null : "Type of delegate expression should be recorded"; 1770 return delegateType; 1771 } 1772 return descriptor.getType(); 1773 } 1774 1775 private static boolean skipDefaultValue(@NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) { 1776 if (isPrimitive(type)) { 1777 if (!propertyDescriptor.getType().isNullable() && value instanceof Number) { 1778 if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) { 1779 return true; 1780 } 1781 if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) { 1782 return true; 1783 } 1784 if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) { 1785 return true; 1786 } 1787 if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) { 1788 return true; 1789 } 1790 if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) { 1791 return true; 1792 } 1793 if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) { 1794 return true; 1795 } 1796 } 1797 if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) { 1798 return true; 1799 } 1800 if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) { 1801 return true; 1802 } 1803 } 1804 else { 1805 if (value == null) { 1806 return true; 1807 } 1808 } 1809 return false; 1810 } 1811 1812 protected void generateDelegates(ClassDescriptor toClass, StackValue field) { 1813 for (DeclarationDescriptor declaration : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1814 if (declaration instanceof CallableMemberDescriptor) { 1815 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) declaration; 1816 if (callableMemberDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION) { 1817 Set<? extends CallableMemberDescriptor> overriddenDescriptors = callableMemberDescriptor.getOverriddenDescriptors(); 1818 for (CallableMemberDescriptor overriddenDescriptor : overriddenDescriptors) { 1819 if (overriddenDescriptor.getContainingDeclaration() == toClass) { 1820 if (declaration instanceof PropertyDescriptor) { 1821 propertyCodegen 1822 .genDelegate((PropertyDescriptor) declaration, (PropertyDescriptor) overriddenDescriptor, field); 1823 } 1824 else if (declaration instanceof FunctionDescriptor) { 1825 functionCodegen 1826 .genDelegate((FunctionDescriptor) declaration, (FunctionDescriptor) overriddenDescriptor, field); 1827 } 1828 } 1829 } 1830 } 1831 } 1832 } 1833 } 1834 1835 1836 /** 1837 * Return pairs of descriptors. First is member of this that should be implemented by delegating to trait, 1838 * second is member of trait that contain implementation. 1839 */ 1840 private List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> getTraitImplementations(@NotNull ClassDescriptor classDescriptor) { 1841 List<Pair<CallableMemberDescriptor, CallableMemberDescriptor>> r = Lists.newArrayList(); 1842 1843 for (DeclarationDescriptor decl : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) { 1844 if (!(decl instanceof CallableMemberDescriptor)) { 1845 continue; 1846 } 1847 1848 CallableMemberDescriptor callableMemberDescriptor = (CallableMemberDescriptor) decl; 1849 if (callableMemberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 1850 continue; 1851 } 1852 1853 Collection<CallableMemberDescriptor> overriddenDeclarations = 1854 OverridingUtil.getOverriddenDeclarations(callableMemberDescriptor); 1855 1856 Collection<CallableMemberDescriptor> filteredOverriddenDeclarations = 1857 OverridingUtil.filterOverrides(Sets.newLinkedHashSet(overriddenDeclarations)); 1858 1859 int count = 0; 1860 CallableMemberDescriptor candidate = null; 1861 1862 for (CallableMemberDescriptor overriddenDeclaration : filteredOverriddenDeclarations) { 1863 if (isTrait(overriddenDeclaration.getContainingDeclaration()) && 1864 overriddenDeclaration.getModality() != Modality.ABSTRACT) { 1865 candidate = overriddenDeclaration; 1866 count++; 1867 } 1868 } 1869 if (candidate == null) { 1870 continue; 1871 } 1872 1873 assert count == 1 : "Ambiguous overridden declaration: " + callableMemberDescriptor.getName(); 1874 1875 1876 Collection<JetType> superTypesOfSuperClass = 1877 superClassType != null ? TypeUtils.getAllSupertypes(superClassType) : Collections.<JetType>emptySet(); 1878 ReceiverParameterDescriptor expectedThisObject = candidate.getExpectedThisObject(); 1879 assert expectedThisObject != null; 1880 JetType candidateType = expectedThisObject.getType(); 1881 boolean implementedInSuperClass = superTypesOfSuperClass.contains(candidateType); 1882 1883 if (!implementedInSuperClass) { 1884 r.add(Pair.create(callableMemberDescriptor, candidate)); 1885 } 1886 } 1887 return r; 1888 } 1889 1890 public void addClassObjectPropertyToCopy(PropertyDescriptor descriptor, Object defaultValue) { 1891 if (classObjectPropertiesToCopy == null) { 1892 classObjectPropertiesToCopy = new ArrayList<PropertyAndDefaultValue>(); 1893 } 1894 classObjectPropertiesToCopy.add(new PropertyAndDefaultValue(descriptor, defaultValue)); 1895 } 1896 1897 static class PropertyAndDefaultValue { 1898 1899 PropertyAndDefaultValue(PropertyDescriptor propertyDescriptor, Object defaultValue) { 1900 this.propertyDescriptor = propertyDescriptor; 1901 this.defaultValue = defaultValue; 1902 } 1903 1904 private PropertyDescriptor propertyDescriptor; 1905 1906 private Object defaultValue; 1907 1908 1909 } 1910 }