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