001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.codegen; 018 019 import com.google.common.collect.ImmutableMap; 020 import com.google.common.collect.Sets; 021 import com.google.protobuf.MessageLite; 022 import com.intellij.openapi.util.Pair; 023 import com.intellij.psi.tree.IElementType; 024 import kotlin.Unit; 025 import kotlin.jvm.functions.Function1; 026 import org.jetbrains.annotations.NotNull; 027 import org.jetbrains.annotations.Nullable; 028 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 029 import org.jetbrains.kotlin.builtins.PrimitiveType; 030 import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; 031 import org.jetbrains.kotlin.codegen.context.CodegenContext; 032 import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods; 033 import org.jetbrains.kotlin.codegen.serialization.JvmStringTable; 034 import org.jetbrains.kotlin.codegen.state.GenerationState; 035 import org.jetbrains.kotlin.codegen.state.JetTypeMapper; 036 import org.jetbrains.kotlin.descriptors.*; 037 import org.jetbrains.kotlin.jvm.RuntimeAssertionInfo; 038 import org.jetbrains.kotlin.lexer.KtTokens; 039 import org.jetbrains.kotlin.load.java.JavaVisibilities; 040 import org.jetbrains.kotlin.load.java.JvmAnnotationNames; 041 import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; 042 import org.jetbrains.kotlin.name.FqName; 043 import org.jetbrains.kotlin.resolve.DeprecationUtilKt; 044 import org.jetbrains.kotlin.resolve.DescriptorUtils; 045 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 046 import org.jetbrains.kotlin.resolve.inline.InlineUtil; 047 import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolverKt; 048 import org.jetbrains.kotlin.resolve.jvm.JvmClassName; 049 import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; 050 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; 051 import org.jetbrains.kotlin.serialization.DescriptorSerializer; 052 import org.jetbrains.kotlin.serialization.jvm.BitEncoding; 053 import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; 054 import org.jetbrains.kotlin.types.FlexibleTypesKt; 055 import org.jetbrains.kotlin.types.KotlinType; 056 import org.jetbrains.org.objectweb.asm.*; 057 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 058 import org.jetbrains.org.objectweb.asm.commons.Method; 059 060 import java.util.ArrayList; 061 import java.util.List; 062 import java.util.Map; 063 import java.util.Set; 064 065 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean; 066 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass; 067 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; 068 import static org.jetbrains.kotlin.load.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS; 069 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; 070 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 071 import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation; 072 import static org.jetbrains.kotlin.types.TypeUtils.isNullableType; 073 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 074 075 public class AsmUtil { 076 private static final Set<Type> STRING_BUILDER_OBJECT_APPEND_ARG_TYPES = Sets.newHashSet( 077 getType(String.class), 078 getType(StringBuffer.class), 079 getType(CharSequence.class) 080 ); 081 082 private static final int NO_FLAG_LOCAL = 0; 083 public static final int NO_FLAG_PACKAGE_PRIVATE = 0; 084 085 @NotNull 086 private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder() 087 .put(Visibilities.PRIVATE, ACC_PRIVATE) 088 .put(Visibilities.PRIVATE_TO_THIS, ACC_PRIVATE) 089 .put(Visibilities.PROTECTED, ACC_PROTECTED) 090 .put(JavaVisibilities.PROTECTED_STATIC_VISIBILITY, ACC_PROTECTED) 091 .put(JavaVisibilities.PROTECTED_AND_PACKAGE, ACC_PROTECTED) 092 .put(Visibilities.PUBLIC, ACC_PUBLIC) 093 .put(Visibilities.INTERNAL, ACC_PUBLIC) 094 .put(Visibilities.LOCAL, NO_FLAG_LOCAL) 095 .put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE) 096 .build(); 097 098 public static final String CAPTURED_RECEIVER_FIELD = "receiver$0"; 099 public static final String CAPTURED_THIS_FIELD = "this$0"; 100 101 private static final ImmutableMap<Integer, JvmPrimitiveType> primitiveTypeByAsmSort; 102 private static final ImmutableMap<Type, Type> primitiveTypeByBoxedType; 103 104 static { 105 ImmutableMap.Builder<Integer, JvmPrimitiveType> typeBySortBuilder = ImmutableMap.builder(); 106 ImmutableMap.Builder<Type, Type> typeByWrapperBuilder = ImmutableMap.builder(); 107 for (JvmPrimitiveType primitiveType : JvmPrimitiveType.values()) { 108 Type asmType = Type.getType(primitiveType.getDesc()); 109 typeBySortBuilder.put(asmType.getSort(), primitiveType); 110 typeByWrapperBuilder.put(asmTypeByFqNameWithoutInnerClasses(primitiveType.getWrapperFqName()), asmType); 111 } 112 primitiveTypeByAsmSort = typeBySortBuilder.build(); 113 primitiveTypeByBoxedType = typeByWrapperBuilder.build(); 114 } 115 116 private AsmUtil() { 117 } 118 119 @NotNull 120 public static Type boxType(@NotNull Type type) { 121 JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort()); 122 return jvmPrimitiveType != null ? asmTypeByFqNameWithoutInnerClasses(jvmPrimitiveType.getWrapperFqName()) : type; 123 } 124 125 @NotNull 126 public static Type unboxType(@NotNull Type boxedType) { 127 Type primitiveType = primitiveTypeByBoxedType.get(boxedType); 128 if (primitiveType == null) { 129 throw new UnsupportedOperationException("Unboxing: " + boxedType); 130 } 131 return primitiveType; 132 } 133 134 public static boolean isIntPrimitive(Type type) { 135 return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; 136 } 137 138 public static boolean isNumberPrimitive(Type type) { 139 return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE; 140 } 141 142 public static boolean isPrimitive(Type type) { 143 return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY; 144 } 145 146 public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) { 147 if (!(descriptor instanceof ClassDescriptor)) { 148 return false; 149 } 150 return isPrimitiveClass((ClassDescriptor) descriptor) && !isBoolean((ClassDescriptor) descriptor); 151 } 152 153 public static Type correctElementType(Type type) { 154 String internalName = type.getInternalName(); 155 assert internalName.charAt(0) == '['; 156 return Type.getType(internalName.substring(1)); 157 } 158 159 @Nullable 160 public static PrimitiveType asmPrimitiveTypeToLangPrimitiveType(Type type) { 161 JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort()); 162 return jvmPrimitiveType != null ? jvmPrimitiveType.getPrimitiveType() : null; 163 } 164 165 @NotNull 166 public static Method method(@NotNull String name, @NotNull Type returnType, @NotNull Type... parameterTypes) { 167 return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes)); 168 } 169 170 public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { 171 return (functionDescriptor.getModality() == Modality.ABSTRACT 172 || isJvmInterface(functionDescriptor.getContainingDeclaration())) 173 && !isStaticMethod(kind, functionDescriptor); 174 } 175 176 public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) { 177 return isStaticKind(kind) || 178 JetTypeMapper.isStaticAccessor(functionDescriptor) || 179 AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor); 180 } 181 182 public static boolean isStaticKind(OwnerKind kind) { 183 return kind == OwnerKind.PACKAGE || kind == OwnerKind.DEFAULT_IMPLS; 184 } 185 186 public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) { 187 int flags = getCommonCallableFlags(functionDescriptor); 188 189 for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.METHOD_FLAGS) { 190 if (flagAnnotation.hasAnnotation(functionDescriptor.getOriginal())) { 191 flags |= flagAnnotation.getJvmFlag(); 192 } 193 } 194 195 if (functionDescriptor.getOriginal().isExternal()) { 196 flags |= Opcodes.ACC_NATIVE; 197 } 198 199 if (AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor)) { 200 // Native method will be a member of the class, the companion object method will be delegated to it 201 flags &= ~Opcodes.ACC_NATIVE; 202 } 203 204 if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) { 205 DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); 206 if (!(containingDeclaration instanceof ClassDescriptor) || 207 ((ClassDescriptor) containingDeclaration).getKind() != ClassKind.INTERFACE) { 208 flags |= ACC_FINAL; 209 } 210 } 211 212 if (isStaticMethod(kind, functionDescriptor)) { 213 flags |= ACC_STATIC; 214 } 215 216 if (isAbstractMethod(functionDescriptor, kind)) { 217 flags |= ACC_ABSTRACT; 218 } 219 220 if (JetTypeMapper.isAccessor(functionDescriptor) 221 || AnnotationUtilKt.hasJvmSyntheticAnnotation(functionDescriptor)) { 222 flags |= ACC_SYNTHETIC; 223 } 224 225 return flags; 226 } 227 228 private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) { 229 int flags = getVisibilityAccessFlag(functionDescriptor); 230 flags |= getVarargsFlag(functionDescriptor); 231 flags |= getDeprecatedAccessFlag(functionDescriptor); 232 if (DeprecationUtilKt.isAnnotatedAsHidden(functionDescriptor) 233 || functionDescriptor instanceof PropertyAccessorDescriptor 234 && DeprecationUtilKt.isAnnotatedAsHidden(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) { 235 flags |= ACC_SYNTHETIC; 236 } 237 return flags; 238 } 239 240 //TODO: move mapping logic to front-end java 241 public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) { 242 Integer specialCase = specialCaseVisibility(descriptor); 243 if (specialCase != null) { 244 return specialCase; 245 } 246 return getDefaultVisibilityFlag(descriptor.getVisibility()); 247 } 248 249 public static int getDefaultVisibilityFlag(@NotNull Visibility visibility) { 250 Integer defaultMapping = visibilityToAccessFlag.get(visibility); 251 if (defaultMapping == null) { 252 throw new IllegalStateException(visibility + " is not a valid visibility in backend"); 253 } 254 return defaultMapping; 255 } 256 257 /* 258 Use this method to get visibility flag for class to define it in byte code (v.defineClass method). 259 For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor) 260 Classes in byte code should be public or package private 261 */ 262 public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) { 263 if (DescriptorUtils.isTopLevelDeclaration(descriptor) || 264 descriptor.getVisibility() == Visibilities.PUBLIC || 265 // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes 266 descriptor.getVisibility() == Visibilities.LOCAL || 267 descriptor.getVisibility() == Visibilities.INTERNAL) { 268 return ACC_PUBLIC; 269 } 270 return NO_FLAG_PACKAGE_PRIVATE; 271 } 272 273 public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { 274 return InlineUtil.isInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; 275 } 276 277 public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { 278 int visibility = (innerClass.getVisibility() == Visibilities.LOCAL) ? ACC_PUBLIC : getVisibilityAccessFlag(innerClass); 279 return visibility | 280 innerAccessFlagsForModalityAndKind(innerClass) | 281 (innerClass.isInner() ? 0 : ACC_STATIC); 282 } 283 284 private static int innerAccessFlagsForModalityAndKind(@NotNull ClassDescriptor innerClass) { 285 switch (innerClass.getKind()) { 286 case INTERFACE: 287 return ACC_ABSTRACT | ACC_INTERFACE; 288 case ENUM_CLASS: 289 return ACC_FINAL | ACC_ENUM; 290 case ANNOTATION_CLASS: 291 return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE; 292 default: 293 if (innerClass.getModality() == Modality.FINAL) { 294 return ACC_FINAL; 295 } 296 else if (innerClass.getModality() == Modality.ABSTRACT) { 297 return ACC_ABSTRACT; 298 } 299 } 300 return 0; 301 } 302 303 public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { 304 if (descriptor instanceof PropertyAccessorDescriptor) { 305 if (((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty().isConst()) { 306 return ACC_DEPRECATED; 307 } 308 return KotlinBuiltIns.isDeprecated(descriptor) 309 ? ACC_DEPRECATED 310 : getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); 311 } 312 else if (KotlinBuiltIns.isDeprecated(descriptor)) { 313 return ACC_DEPRECATED; 314 } 315 return 0; 316 } 317 318 private static int getVarargsFlag(FunctionDescriptor functionDescriptor) { 319 if (!functionDescriptor.getValueParameters().isEmpty() 320 && functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1) 321 .getVarargElementType() != null) { 322 return ACC_VARARGS; 323 } 324 return 0; 325 } 326 327 @Nullable 328 private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) { 329 DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); 330 Visibility memberVisibility = memberDescriptor.getVisibility(); 331 if (isJvmInterface(containingDeclaration)) { 332 return memberVisibility == Visibilities.PRIVATE ? NO_FLAG_PACKAGE_PRIVATE : ACC_PUBLIC; 333 } 334 335 if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) { 336 return ACC_PUBLIC; 337 } 338 339 if (isEnumEntry(memberDescriptor)) { 340 return NO_FLAG_PACKAGE_PRIVATE; 341 } 342 343 if (memberDescriptor instanceof ConstructorDescriptor && isAnonymousObject(memberDescriptor.getContainingDeclaration())) { 344 return getVisibilityAccessFlagForAnonymous((ClassDescriptor) memberDescriptor.getContainingDeclaration()); 345 } 346 347 if (memberDescriptor instanceof SyntheticJavaPropertyDescriptor) { 348 return getVisibilityAccessFlag(((SyntheticJavaPropertyDescriptor) memberDescriptor).getGetMethod()); 349 } 350 if (memberDescriptor instanceof PropertyAccessorDescriptor) { 351 PropertyDescriptor property = ((PropertyAccessorDescriptor) memberDescriptor).getCorrespondingProperty(); 352 if (property instanceof SyntheticJavaPropertyDescriptor) { 353 FunctionDescriptor method = memberDescriptor == property.getGetter() 354 ? ((SyntheticJavaPropertyDescriptor) property).getGetMethod() 355 : ((SyntheticJavaPropertyDescriptor) property).getSetMethod(); 356 assert method != null : "No get/set method in SyntheticJavaPropertyDescriptor: " + property; 357 return getVisibilityAccessFlag(method); 358 } 359 } 360 361 if (memberDescriptor instanceof CallableDescriptor && memberVisibility == Visibilities.PROTECTED) { 362 for (CallableDescriptor overridden : DescriptorUtils.getAllOverriddenDescriptors((CallableDescriptor) memberDescriptor)) { 363 if (isJvmInterface(overridden.getContainingDeclaration())) { 364 return ACC_PUBLIC; 365 } 366 } 367 } 368 369 if (!Visibilities.isPrivate(memberVisibility)) { 370 return null; 371 } 372 373 // the following code is only for PRIVATE visibility of member 374 if (memberDescriptor instanceof ConstructorDescriptor) { 375 if (isEnumEntry(containingDeclaration)) { 376 return NO_FLAG_PACKAGE_PRIVATE; 377 } 378 if (isEnumClass(containingDeclaration)) { 379 //TODO: should be ACC_PRIVATE 380 // see http://youtrack.jetbrains.com/issue/KT-2680 381 return ACC_PROTECTED; 382 } 383 } 384 385 if (memberDescriptor instanceof PropertyDescriptor && 386 ((PropertyDescriptor) memberDescriptor).isConst() || hasJvmFieldAnnotation(memberDescriptor)) { 387 return null; 388 } 389 390 return null; 391 } 392 393 public static Type stringValueOfType(Type type) { 394 int sort = type.getSort(); 395 return sort == Type.OBJECT || sort == Type.ARRAY 396 ? OBJECT_TYPE 397 : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type; 398 } 399 400 private static Type stringBuilderAppendType(Type type) { 401 switch (type.getSort()) { 402 case Type.OBJECT: 403 return STRING_BUILDER_OBJECT_APPEND_ARG_TYPES.contains(type) ? type : OBJECT_TYPE; 404 case Type.ARRAY: 405 return OBJECT_TYPE; 406 case Type.BYTE: 407 case Type.SHORT: 408 return Type.INT_TYPE; 409 default: 410 return type; 411 } 412 } 413 414 public static void genThrow(@NotNull InstructionAdapter v, @NotNull String exception, @Nullable String message) { 415 v.anew(Type.getObjectType(exception)); 416 v.dup(); 417 if (message != null) { 418 v.aconst(message); 419 v.invokespecial(exception, "<init>", "(Ljava/lang/String;)V", false); 420 } 421 else { 422 v.invokespecial(exception, "<init>", "()V", false); 423 } 424 v.athrow(); 425 } 426 427 public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) { 428 List<Pair<String, Type>> allFields = new ArrayList<Pair<String, Type>>(); 429 430 ClassifierDescriptor captureThis = closure.getCaptureThis(); 431 if (captureThis != null) { 432 allFields.add(Pair.create(CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis))); 433 } 434 435 KotlinType captureReceiverType = closure.getCaptureReceiverType(); 436 if (captureReceiverType != null) { 437 allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType))); 438 } 439 440 allFields.addAll(closure.getRecordedFields()); 441 genClosureFields(allFields, v); 442 } 443 444 public static void genClosureFields(List<Pair<String, Type>> allFields, ClassBuilder builder) { 445 //noinspection PointlessBitwiseExpression 446 int access = NO_FLAG_PACKAGE_PRIVATE | ACC_SYNTHETIC | ACC_FINAL; 447 for (Pair<String, Type> field : allFields) { 448 builder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, field.first, field.second.getDescriptor(), null, null); 449 } 450 } 451 452 public static List<FieldInfo> transformCapturedParams(List<Pair<String, Type>> allFields, Type owner) { 453 List<FieldInfo> result = new ArrayList<FieldInfo>(); 454 for (Pair<String, Type> field : allFields) { 455 result.add(FieldInfo.createForHiddenField(owner, field.second, field.first)); 456 } 457 return result; 458 } 459 460 public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { 461 assert !info.isStatic(); 462 Type fieldType = info.getFieldType(); 463 iv.load(0, info.getOwnerType());//this 464 iv.load(index, fieldType); //param 465 iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); 466 index += fieldType.getSize(); 467 return index; 468 } 469 470 public static void genStringBuilderConstructor(InstructionAdapter v) { 471 v.visitTypeInsn(NEW, "java/lang/StringBuilder"); 472 v.dup(); 473 v.invokespecial("java/lang/StringBuilder", "<init>", "()V", false); 474 } 475 476 public static void genInvokeAppendMethod(InstructionAdapter v, Type type) { 477 type = stringBuilderAppendType(type); 478 v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;", false); 479 } 480 481 public static StackValue genToString(final StackValue receiver, final Type receiverType) { 482 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 483 @Override 484 public Unit invoke(InstructionAdapter v) { 485 Type type = stringValueOfType(receiverType); 486 receiver.put(type, v); 487 v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false); 488 return null; 489 } 490 }); 491 } 492 493 static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) { 494 if (type.getSort() == Type.ARRAY) { 495 Type elementType = correctElementType(type); 496 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 497 iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I", false); 498 } 499 else { 500 iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I", false); 501 } 502 } 503 else if (type.getSort() == Type.OBJECT) { 504 iv.invokevirtual("java/lang/Object", "hashCode", "()I", false); 505 } 506 else if (type.getSort() == Type.LONG) { 507 genLongHashCode(mv, iv); 508 } 509 else if (type.getSort() == Type.DOUBLE) { 510 iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false); 511 genLongHashCode(mv, iv); 512 } 513 else if (type.getSort() == Type.FLOAT) { 514 iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false); 515 } 516 else if (type.getSort() == Type.BOOLEAN) { 517 Label end = new Label(); 518 iv.dup(); 519 iv.ifeq(end); 520 iv.pop(); 521 iv.iconst(1); 522 iv.mark(end); 523 } 524 else { // byte short char int 525 // do nothing 526 } 527 } 528 529 private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) { 530 iv.dup2(); 531 iv.iconst(32); 532 iv.ushr(Type.LONG_TYPE); 533 iv.xor(Type.LONG_TYPE); 534 mv.visitInsn(L2I); 535 } 536 537 static void genInvertBoolean(InstructionAdapter v) { 538 v.iconst(1); 539 v.xor(Type.INT_TYPE); 540 } 541 542 @NotNull 543 public static StackValue genEqualsForExpressionsOnStack( 544 final @NotNull IElementType opToken, 545 final @NotNull StackValue left, 546 final @NotNull StackValue right 547 ) { 548 final Type leftType = left.type; 549 final Type rightType = right.type; 550 if (isPrimitive(leftType) && leftType == rightType) { 551 return StackValue.cmp(opToken, leftType, left, right); 552 } 553 554 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 555 @Override 556 public Unit invoke(InstructionAdapter v) { 557 left.put(leftType, v); 558 right.put(rightType, v); 559 genAreEqualCall(v); 560 561 if (opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ) { 562 genInvertBoolean(v); 563 } 564 return Unit.INSTANCE$; 565 } 566 }); 567 } 568 569 public static void genAreEqualCall(InstructionAdapter v) { 570 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); 571 } 572 573 public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) { 574 if (expectedType == Type.LONG_TYPE) { 575 v.lconst(myDelta); 576 } 577 else if (expectedType == Type.FLOAT_TYPE) { 578 v.fconst(myDelta); 579 } 580 else if (expectedType == Type.DOUBLE_TYPE) { 581 v.dconst(myDelta); 582 } 583 else { 584 v.iconst(myDelta); 585 v.add(Type.INT_TYPE); 586 StackValue.coerce(Type.INT_TYPE, expectedType, v); 587 return; 588 } 589 v.add(expectedType); 590 } 591 592 public static void swap(InstructionAdapter v, Type stackTop, Type afterTop) { 593 if (stackTop.getSize() == 1) { 594 if (afterTop.getSize() == 1) { 595 v.swap(); 596 } 597 else { 598 v.dupX2(); 599 v.pop(); 600 } 601 } 602 else { 603 if (afterTop.getSize() == 1) { 604 v.dup2X1(); 605 } 606 else { 607 v.dup2X2(); 608 } 609 v.pop2(); 610 } 611 } 612 613 public static void genNotNullAssertionsForParameters( 614 @NotNull InstructionAdapter v, 615 @NotNull GenerationState state, 616 @NotNull FunctionDescriptor descriptor, 617 @NotNull FrameMap frameMap 618 ) { 619 if (!state.isParamAssertionsEnabled()) return; 620 621 // Private method is not accessible from other classes, no assertions needed 622 if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return; 623 624 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 625 if (receiverParameter != null) { 626 genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver"); 627 } 628 629 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) { 630 genParamAssertion(v, state.getTypeMapper(), frameMap, parameter, parameter.getName().asString()); 631 } 632 } 633 634 private static void genParamAssertion( 635 @NotNull InstructionAdapter v, 636 @NotNull JetTypeMapper typeMapper, 637 @NotNull FrameMap frameMap, 638 @NotNull CallableDescriptor parameter, 639 @NotNull String name 640 ) { 641 KotlinType type = parameter.getReturnType(); 642 if (type == null || isNullableType(type)) return; 643 644 int index = frameMap.getIndex(parameter); 645 Type asmType = typeMapper.mapType(type); 646 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 647 v.load(index, asmType); 648 v.visitLdcInsn(name); 649 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull", 650 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 651 } 652 } 653 654 public static boolean genNotNullAssertionForField( 655 @NotNull InstructionAdapter v, 656 @NotNull GenerationState state, 657 @NotNull PropertyDescriptor descriptor 658 ) { 659 return genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull"); 660 } 661 662 private static boolean genNotNullAssertion( 663 @NotNull InstructionAdapter v, 664 @NotNull GenerationState state, 665 @NotNull CallableDescriptor descriptor, 666 @NotNull String assertMethodToCall 667 ) { 668 // Assertions are generated elsewhere for platform types 669 if (JavaDescriptorResolverKt.getPLATFORM_TYPES()) return false; 670 671 if (!state.isCallAssertionsEnabled()) return false; 672 673 if (!isDeclaredInJava(descriptor)) return false; 674 675 KotlinType type = descriptor.getReturnType(); 676 if (type == null || isNullableType(FlexibleTypesKt.lowerIfFlexible(type))) return false; 677 678 Type asmType = state.getTypeMapper().mapReturnType(descriptor); 679 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 680 v.dup(); 681 v.visitLdcInsn(descriptor.getContainingDeclaration().getName().asString()); 682 v.visitLdcInsn(descriptor.getName().asString()); 683 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, assertMethodToCall, 684 "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V", false); 685 return true; 686 } 687 688 return false; 689 } 690 691 @NotNull 692 public static StackValue genNotNullAssertions( 693 @NotNull GenerationState state, 694 @NotNull final StackValue stackValue, 695 @Nullable final RuntimeAssertionInfo runtimeAssertionInfo 696 ) { 697 if (!state.isCallAssertionsEnabled()) return stackValue; 698 if (runtimeAssertionInfo == null || !runtimeAssertionInfo.getNeedNotNullAssertion()) return stackValue; 699 700 return new StackValue(stackValue.type) { 701 702 @Override 703 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 704 stackValue.put(type, v); 705 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 706 v.dup(); 707 v.visitLdcInsn(runtimeAssertionInfo.getMessage()); 708 v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull", 709 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 710 } 711 } 712 }; 713 } 714 715 private static boolean isDeclaredInJava(@NotNull CallableDescriptor callableDescriptor) { 716 CallableDescriptor descriptor = callableDescriptor; 717 while (true) { 718 if (descriptor instanceof JavaCallableMemberDescriptor) { 719 return true; 720 } 721 CallableDescriptor original = descriptor.getOriginal(); 722 if (descriptor == original) break; 723 descriptor = original; 724 } 725 return false; 726 } 727 728 public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 729 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 730 v.aconst(null); 731 } 732 else { 733 pushDefaultPrimitiveValueOnStack(type, v); 734 } 735 } 736 737 public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 738 if (type.getSort() == Type.FLOAT) { 739 v.fconst(0); 740 } 741 else if (type.getSort() == Type.DOUBLE) { 742 v.dconst(0); 743 } 744 else if (type.getSort() == Type.LONG) { 745 v.lconst(0); 746 } 747 else { 748 v.iconst(0); 749 } 750 } 751 752 public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) { 753 if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { 754 return false; 755 } 756 757 DeclarationDescriptor container = propertyDescriptor.getContainingDeclaration(); 758 return isNonCompanionObject(container) || 759 isPropertyWithBackingFieldInOuterClass(propertyDescriptor) || 760 (isCompanionObject(container) && isInterface(container.getContainingDeclaration())); 761 } 762 763 public static boolean isPropertyWithBackingFieldInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 764 return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && 765 isCompanionObjectWithBackingFieldsInOuter(propertyDescriptor.getContainingDeclaration()); 766 } 767 768 public static int getVisibilityForSpecialPropertyBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) { 769 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 770 if (isDelegate || isExtensionProperty) { 771 return ACC_PRIVATE; 772 } 773 else { 774 return areBothAccessorDefault(propertyDescriptor) 775 ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) 776 : ACC_PRIVATE; 777 } 778 } 779 780 private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) { 781 if (!propertyDescriptor.isVar()) { 782 return propertyDescriptor; 783 } 784 else { 785 return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor; 786 } 787 } 788 789 public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 790 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 791 DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration(); 792 return !propertyDescriptor.isVar() 793 && !isExtensionProperty 794 && isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration()) 795 && areBothAccessorDefault(propertyDescriptor) 796 && getVisibilityForSpecialPropertyBackingField(propertyDescriptor, false) == ACC_PUBLIC; 797 } 798 799 public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) { 800 DeclarationDescriptor containingClass = companionObject.getContainingDeclaration(); 801 return isCompanionObject(companionObject) && (isClass(containingClass) || isEnumClass(containingClass)); 802 } 803 804 private static boolean areBothAccessorDefault(@NotNull PropertyDescriptor propertyDescriptor) { 805 return isAccessorWithEmptyBody(propertyDescriptor.getGetter()) 806 && (!propertyDescriptor.isVar() || isAccessorWithEmptyBody(propertyDescriptor.getSetter())); 807 } 808 809 private static boolean isAccessorWithEmptyBody(@Nullable PropertyAccessorDescriptor accessorDescriptor) { 810 return accessorDescriptor == null || !accessorDescriptor.hasBody(); 811 } 812 813 public static Type comparisonOperandType(Type left, Type right) { 814 if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE; 815 if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE; 816 if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE; 817 return Type.INT_TYPE; 818 } 819 820 @NotNull 821 public static Type numberFunctionOperandType(@NotNull Type expectedType) { 822 if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE || expectedType == Type.CHAR_TYPE) { 823 return Type.INT_TYPE; 824 } 825 return expectedType; 826 } 827 828 public static void pop(@NotNull MethodVisitor v, @NotNull Type type) { 829 if (type.getSize() == 2) { 830 v.visitInsn(Opcodes.POP2); 831 } 832 else { 833 v.visitInsn(Opcodes.POP); 834 } 835 } 836 837 public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) { 838 dup(v, type.getSize()); 839 } 840 841 private static void dup(@NotNull InstructionAdapter v, int size) { 842 if (size == 2) { 843 v.dup2(); 844 } 845 else if (size == 1) { 846 v.dup(); 847 } 848 else { 849 throw new UnsupportedOperationException(); 850 } 851 } 852 853 public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) { 854 if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) { 855 return; 856 } 857 858 if (topOfStack.getSize() == 0) { 859 dup(v, afterTop); 860 } 861 else if (afterTop.getSize() == 0) { 862 dup(v, topOfStack); 863 } 864 else if (afterTop.getSize() == 1) { 865 if (topOfStack.getSize() == 1) { 866 dup(v, 2); 867 } 868 else { 869 v.dup2X1(); 870 v.pop2(); 871 v.dupX2(); 872 v.dupX2(); 873 v.pop(); 874 v.dup2X1(); 875 } 876 } 877 else { 878 //Note: it's possible to write dup3 and dup4 879 throw new UnsupportedOperationException("Don't know how generate dup3/dup4 for: " + topOfStack + " and " + afterTop); 880 } 881 } 882 883 public static void writeKotlinSyntheticClassAnnotation(@NotNull ClassBuilder v, @NotNull GenerationState state) { 884 AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), true); 885 JvmCodegenUtil.writeAbiVersion(av); 886 JvmCodegenUtil.writeModuleName(av, state); 887 av.visitEnd(); 888 } 889 890 public static void writeAnnotationData( 891 @NotNull AnnotationVisitor av, 892 @NotNull DescriptorSerializer serializer, 893 @NotNull MessageLite message 894 ) { 895 byte[] bytes = serializer.serialize(message); 896 897 JvmCodegenUtil.writeAbiVersion(av); 898 AnnotationVisitor data = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME); 899 for (String string : BitEncoding.encodeBytes(bytes)) { 900 data.visit(null, string); 901 } 902 data.visitEnd(); 903 AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.STRINGS_FIELD_NAME); 904 for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) { 905 strings.visit(null, string); 906 } 907 strings.visitEnd(); 908 } 909 910 @NotNull 911 public static String asmDescByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 912 return asmTypeByFqNameWithoutInnerClasses(fqName).getDescriptor(); 913 } 914 915 @NotNull 916 public static String shortNameByAsmType(@NotNull Type type) { 917 String internalName = type.getInternalName(); 918 int lastSlash = internalName.lastIndexOf('/'); 919 return lastSlash < 0 ? internalName : internalName.substring(lastSlash + 1); 920 } 921 922 @NotNull 923 public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 924 return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName)); 925 } 926 927 @NotNull 928 public static String internalNameByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 929 return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName(); 930 } 931 932 @NotNull 933 public static String getSimpleInternalName(@NotNull String internalName) { 934 int lastSlash = internalName.lastIndexOf('/'); 935 if (lastSlash >= 0) { 936 return internalName.substring(lastSlash + 1); 937 } 938 else { 939 return internalName; 940 } 941 } 942 943 public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) { 944 if (isPrimitive(type)) { 945 v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;"); 946 } 947 else { 948 v.aconst(type); 949 } 950 } 951 952 public static void wrapJavaClassIntoKClass(@NotNull InstructionAdapter v) { 953 v.invokestatic(REFLECTION, "getOrCreateKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false); 954 } 955 956 public static void wrapJavaClassesIntoKClasses(@NotNull InstructionAdapter v) { 957 v.invokestatic(REFLECTION, "getOrCreateKotlinClasses", Type.getMethodDescriptor(K_CLASS_ARRAY_TYPE, getType(Class[].class)), false); 958 } 959 960 public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) { 961 OwnerKind kind = context.getContextKind(); 962 //Trait always should have this descriptor 963 return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1; 964 } 965 }