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.KotlinTypeMapper; 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.name.FqName; 042 import org.jetbrains.kotlin.resolve.DeprecationUtilKt; 043 import org.jetbrains.kotlin.resolve.DescriptorUtils; 044 import org.jetbrains.kotlin.resolve.annotations.AnnotationUtilKt; 045 import org.jetbrains.kotlin.resolve.inline.InlineUtil; 046 import org.jetbrains.kotlin.resolve.jvm.JvmClassName; 047 import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; 048 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; 049 import org.jetbrains.kotlin.serialization.DescriptorSerializer; 050 import org.jetbrains.kotlin.serialization.jvm.BitEncoding; 051 import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor; 052 import org.jetbrains.kotlin.types.KotlinType; 053 import org.jetbrains.org.objectweb.asm.*; 054 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; 055 import org.jetbrains.org.objectweb.asm.commons.Method; 056 057 import java.util.ArrayList; 058 import java.util.List; 059 import java.util.Map; 060 import java.util.Set; 061 062 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean; 063 import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass; 064 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation; 065 import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; 066 import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; 067 import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*; 068 import static org.jetbrains.kotlin.types.TypeUtils.isNullableType; 069 import static org.jetbrains.org.objectweb.asm.Opcodes.*; 070 071 public class AsmUtil { 072 private static final Set<Type> STRING_BUILDER_OBJECT_APPEND_ARG_TYPES = Sets.newHashSet( 073 getType(String.class), 074 getType(StringBuffer.class), 075 getType(CharSequence.class) 076 ); 077 078 private static final int NO_FLAG_LOCAL = 0; 079 public static final int NO_FLAG_PACKAGE_PRIVATE = 0; 080 081 @NotNull 082 private static final Map<Visibility, Integer> visibilityToAccessFlag = ImmutableMap.<Visibility, Integer>builder() 083 .put(Visibilities.PRIVATE, ACC_PRIVATE) 084 .put(Visibilities.PRIVATE_TO_THIS, ACC_PRIVATE) 085 .put(Visibilities.PROTECTED, ACC_PROTECTED) 086 .put(JavaVisibilities.PROTECTED_STATIC_VISIBILITY, ACC_PROTECTED) 087 .put(JavaVisibilities.PROTECTED_AND_PACKAGE, ACC_PROTECTED) 088 .put(Visibilities.PUBLIC, ACC_PUBLIC) 089 .put(Visibilities.INTERNAL, ACC_PUBLIC) 090 .put(Visibilities.LOCAL, NO_FLAG_LOCAL) 091 .put(JavaVisibilities.PACKAGE_VISIBILITY, NO_FLAG_PACKAGE_PRIVATE) 092 .build(); 093 094 public static final String CAPTURED_RECEIVER_FIELD = "receiver$0"; 095 public static final String CAPTURED_THIS_FIELD = "this$0"; 096 097 private static final ImmutableMap<Integer, JvmPrimitiveType> primitiveTypeByAsmSort; 098 private static final ImmutableMap<Type, Type> primitiveTypeByBoxedType; 099 100 static { 101 ImmutableMap.Builder<Integer, JvmPrimitiveType> typeBySortBuilder = ImmutableMap.builder(); 102 ImmutableMap.Builder<Type, Type> typeByWrapperBuilder = ImmutableMap.builder(); 103 for (JvmPrimitiveType primitiveType : JvmPrimitiveType.values()) { 104 Type asmType = Type.getType(primitiveType.getDesc()); 105 typeBySortBuilder.put(asmType.getSort(), primitiveType); 106 typeByWrapperBuilder.put(asmTypeByFqNameWithoutInnerClasses(primitiveType.getWrapperFqName()), asmType); 107 } 108 primitiveTypeByAsmSort = typeBySortBuilder.build(); 109 primitiveTypeByBoxedType = typeByWrapperBuilder.build(); 110 } 111 112 private AsmUtil() { 113 } 114 115 @NotNull 116 public static Type boxType(@NotNull Type type) { 117 JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort()); 118 return jvmPrimitiveType != null ? asmTypeByFqNameWithoutInnerClasses(jvmPrimitiveType.getWrapperFqName()) : type; 119 } 120 121 @NotNull 122 public static Type unboxType(@NotNull Type boxedType) { 123 Type primitiveType = unboxPrimitiveTypeOrNull(boxedType); 124 if (primitiveType == null) { 125 throw new UnsupportedOperationException("Unboxing: " + boxedType); 126 } 127 return primitiveType; 128 } 129 130 @Nullable 131 public static Type unboxPrimitiveTypeOrNull(@NotNull Type boxedType) { 132 return primitiveTypeByBoxedType.get(boxedType); 133 } 134 135 public static boolean isIntPrimitive(Type type) { 136 return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE; 137 } 138 139 public static boolean isNumberPrimitive(Type type) { 140 return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE; 141 } 142 143 public static boolean isPrimitive(Type type) { 144 return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY; 145 } 146 147 public static boolean isPrimitiveNumberClassDescriptor(DeclarationDescriptor descriptor) { 148 if (!(descriptor instanceof ClassDescriptor)) { 149 return false; 150 } 151 return isPrimitiveClass((ClassDescriptor) descriptor) && !isBoolean((ClassDescriptor) descriptor); 152 } 153 154 public static Type correctElementType(Type type) { 155 String internalName = type.getInternalName(); 156 assert internalName.charAt(0) == '['; 157 return Type.getType(internalName.substring(1)); 158 } 159 160 @Nullable 161 public static PrimitiveType asmPrimitiveTypeToLangPrimitiveType(Type type) { 162 JvmPrimitiveType jvmPrimitiveType = primitiveTypeByAsmSort.get(type.getSort()); 163 return jvmPrimitiveType != null ? jvmPrimitiveType.getPrimitiveType() : null; 164 } 165 166 @NotNull 167 public static Method method(@NotNull String name, @NotNull Type returnType, @NotNull Type... parameterTypes) { 168 return new Method(name, Type.getMethodDescriptor(returnType, parameterTypes)); 169 } 170 171 public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { 172 return (functionDescriptor.getModality() == Modality.ABSTRACT 173 || isJvmInterface(functionDescriptor.getContainingDeclaration())) 174 && !isStaticMethod(kind, functionDescriptor); 175 } 176 177 public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) { 178 return isStaticKind(kind) || 179 KotlinTypeMapper.isStaticAccessor(functionDescriptor) || 180 AnnotationUtilKt.isPlatformStaticInObjectOrClass(functionDescriptor); 181 } 182 183 public static boolean isStaticKind(OwnerKind kind) { 184 return kind == OwnerKind.PACKAGE || kind == OwnerKind.DEFAULT_IMPLS; 185 } 186 187 public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) { 188 int flags = getCommonCallableFlags(functionDescriptor); 189 190 for (AnnotationCodegen.JvmFlagAnnotation flagAnnotation : AnnotationCodegen.METHOD_FLAGS) { 191 if (flagAnnotation.hasAnnotation(functionDescriptor.getOriginal())) { 192 flags |= flagAnnotation.getJvmFlag(); 193 } 194 } 195 196 if (functionDescriptor.getOriginal().isExternal()) { 197 flags |= Opcodes.ACC_NATIVE; 198 } 199 200 if (AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor)) { 201 // Native method will be a member of the class, the companion object method will be delegated to it 202 flags &= ~Opcodes.ACC_NATIVE; 203 } 204 205 if (functionDescriptor.getModality() == Modality.FINAL && !(functionDescriptor instanceof ConstructorDescriptor)) { 206 DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); 207 if (!(containingDeclaration instanceof ClassDescriptor) || 208 ((ClassDescriptor) containingDeclaration).getKind() != ClassKind.INTERFACE) { 209 flags |= ACC_FINAL; 210 } 211 } 212 213 if (isStaticMethod(kind, functionDescriptor)) { 214 flags |= ACC_STATIC; 215 } 216 217 if (isAbstractMethod(functionDescriptor, kind)) { 218 flags |= ACC_ABSTRACT; 219 } 220 221 if (KotlinTypeMapper.isAccessor(functionDescriptor) 222 || AnnotationUtilKt.hasJvmSyntheticAnnotation(functionDescriptor)) { 223 flags |= ACC_SYNTHETIC; 224 } 225 226 return flags; 227 } 228 229 private static int getCommonCallableFlags(FunctionDescriptor functionDescriptor) { 230 int flags = getVisibilityAccessFlag(functionDescriptor); 231 flags |= getVarargsFlag(functionDescriptor); 232 flags |= getDeprecatedAccessFlag(functionDescriptor); 233 if (DeprecationUtilKt.isHiddenInResolution(functionDescriptor) 234 || functionDescriptor instanceof PropertyAccessorDescriptor 235 && DeprecationUtilKt.isHiddenInResolution(((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty())) { 236 flags |= ACC_SYNTHETIC; 237 } 238 return flags; 239 } 240 241 //TODO: move mapping logic to front-end java 242 public static int getVisibilityAccessFlag(@NotNull MemberDescriptor descriptor) { 243 Integer specialCase = specialCaseVisibility(descriptor); 244 if (specialCase != null) { 245 return specialCase; 246 } 247 return getDefaultVisibilityFlag(descriptor.getVisibility()); 248 } 249 250 public static int getDefaultVisibilityFlag(@NotNull Visibility visibility) { 251 Integer defaultMapping = visibilityToAccessFlag.get(visibility); 252 if (defaultMapping == null) { 253 throw new IllegalStateException(visibility + " is not a valid visibility in backend"); 254 } 255 return defaultMapping; 256 } 257 258 /* 259 Use this method to get visibility flag for class to define it in byte code (v.defineClass method). 260 For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor) 261 Classes in byte code should be public or package private 262 */ 263 public static int getVisibilityAccessFlagForClass(@NotNull ClassDescriptor descriptor) { 264 if (descriptor instanceof SyntheticClassDescriptorForLambda) { 265 return getVisibilityAccessFlagForAnonymous(descriptor); 266 } 267 if (descriptor.getVisibility() == Visibilities.PUBLIC || 268 descriptor.getVisibility() == Visibilities.PROTECTED || 269 // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes 270 descriptor.getVisibility() == Visibilities.LOCAL || 271 descriptor.getVisibility() == Visibilities.INTERNAL) { 272 return ACC_PUBLIC; 273 } 274 return NO_FLAG_PACKAGE_PRIVATE; 275 } 276 277 private static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { 278 return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; 279 } 280 281 public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { 282 int visibility = 283 innerClass instanceof SyntheticClassDescriptorForLambda 284 ? getVisibilityAccessFlagForAnonymous(innerClass) 285 : innerClass.getVisibility() == Visibilities.LOCAL 286 ? ACC_PUBLIC 287 : getVisibilityAccessFlag(innerClass); 288 return visibility | 289 innerAccessFlagsForModalityAndKind(innerClass) | 290 (innerClass.isInner() ? 0 : ACC_STATIC); 291 } 292 293 private static int innerAccessFlagsForModalityAndKind(@NotNull ClassDescriptor innerClass) { 294 switch (innerClass.getKind()) { 295 case INTERFACE: 296 return ACC_ABSTRACT | ACC_INTERFACE; 297 case ENUM_CLASS: 298 return ACC_FINAL | ACC_ENUM; 299 case ANNOTATION_CLASS: 300 return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE; 301 default: 302 if (innerClass.getModality() == Modality.FINAL) { 303 return ACC_FINAL; 304 } 305 else if (innerClass.getModality() == Modality.ABSTRACT) { 306 return ACC_ABSTRACT; 307 } 308 } 309 return 0; 310 } 311 312 public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { 313 if (descriptor instanceof PropertyAccessorDescriptor) { 314 return KotlinBuiltIns.isDeprecated(descriptor) 315 ? ACC_DEPRECATED 316 : getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); 317 } 318 else if (KotlinBuiltIns.isDeprecated(descriptor)) { 319 return ACC_DEPRECATED; 320 } 321 return 0; 322 } 323 324 private static int getVarargsFlag(FunctionDescriptor functionDescriptor) { 325 if (!functionDescriptor.getValueParameters().isEmpty() 326 && functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1) 327 .getVarargElementType() != null) { 328 return ACC_VARARGS; 329 } 330 return 0; 331 } 332 333 @Nullable 334 private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) { 335 DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); 336 Visibility memberVisibility = memberDescriptor.getVisibility(); 337 338 if (AnnotationUtilKt.isInlineOnlyOrReified(memberDescriptor)) return ACC_PRIVATE; 339 340 if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) { 341 return ACC_PUBLIC; 342 } 343 344 if (isEnumEntry(memberDescriptor)) { 345 return NO_FLAG_PACKAGE_PRIVATE; 346 } 347 348 if (memberDescriptor instanceof ConstructorDescriptor && isAnonymousObject(memberDescriptor.getContainingDeclaration())) { 349 return getVisibilityAccessFlagForAnonymous((ClassDescriptor) memberDescriptor.getContainingDeclaration()); 350 } 351 352 if (memberDescriptor instanceof SyntheticJavaPropertyDescriptor) { 353 return getVisibilityAccessFlag(((SyntheticJavaPropertyDescriptor) memberDescriptor).getGetMethod()); 354 } 355 if (memberDescriptor instanceof PropertyAccessorDescriptor) { 356 PropertyDescriptor property = ((PropertyAccessorDescriptor) memberDescriptor).getCorrespondingProperty(); 357 if (property instanceof SyntheticJavaPropertyDescriptor) { 358 FunctionDescriptor method = memberDescriptor == property.getGetter() 359 ? ((SyntheticJavaPropertyDescriptor) property).getGetMethod() 360 : ((SyntheticJavaPropertyDescriptor) property).getSetMethod(); 361 assert method != null : "No get/set method in SyntheticJavaPropertyDescriptor: " + property; 362 return getVisibilityAccessFlag(method); 363 } 364 } 365 366 if (memberDescriptor instanceof CallableDescriptor && memberVisibility == Visibilities.PROTECTED) { 367 for (CallableDescriptor overridden : DescriptorUtils.getAllOverriddenDescriptors((CallableDescriptor) memberDescriptor)) { 368 if (isJvmInterface(overridden.getContainingDeclaration())) { 369 return ACC_PUBLIC; 370 } 371 } 372 } 373 374 if (!Visibilities.isPrivate(memberVisibility)) { 375 return null; 376 } 377 378 // the following code is only for PRIVATE visibility of member 379 if (memberDescriptor instanceof ConstructorDescriptor) { 380 if (isEnumEntry(containingDeclaration)) { 381 return NO_FLAG_PACKAGE_PRIVATE; 382 } 383 if (isEnumClass(containingDeclaration)) { 384 //TODO: should be ACC_PRIVATE 385 // see http://youtrack.jetbrains.com/issue/KT-2680 386 return ACC_PROTECTED; 387 } 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, KotlinTypeMapper 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 int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { 453 assert !info.isStatic(); 454 Type fieldType = info.getFieldType(); 455 iv.load(0, info.getOwnerType());//this 456 iv.load(index, fieldType); //param 457 iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); 458 index += fieldType.getSize(); 459 return index; 460 } 461 462 public static void genStringBuilderConstructor(InstructionAdapter v) { 463 v.visitTypeInsn(NEW, "java/lang/StringBuilder"); 464 v.dup(); 465 v.invokespecial("java/lang/StringBuilder", "<init>", "()V", false); 466 } 467 468 public static void genInvokeAppendMethod(InstructionAdapter v, Type type) { 469 type = stringBuilderAppendType(type); 470 v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;", false); 471 } 472 473 public static StackValue genToString(final StackValue receiver, final Type receiverType) { 474 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 475 @Override 476 public Unit invoke(InstructionAdapter v) { 477 Type type = stringValueOfType(receiverType); 478 receiver.put(type, v); 479 v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false); 480 return null; 481 } 482 }); 483 } 484 485 static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) { 486 if (type.getSort() == Type.ARRAY) { 487 Type elementType = correctElementType(type); 488 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 489 iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I", false); 490 } 491 else { 492 iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I", false); 493 } 494 } 495 else if (type.getSort() == Type.OBJECT) { 496 iv.invokevirtual("java/lang/Object", "hashCode", "()I", false); 497 } 498 else if (type.getSort() == Type.LONG) { 499 genLongHashCode(mv, iv); 500 } 501 else if (type.getSort() == Type.DOUBLE) { 502 iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false); 503 genLongHashCode(mv, iv); 504 } 505 else if (type.getSort() == Type.FLOAT) { 506 iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false); 507 } 508 else if (type.getSort() == Type.BOOLEAN) { 509 Label end = new Label(); 510 iv.dup(); 511 iv.ifeq(end); 512 iv.pop(); 513 iv.iconst(1); 514 iv.mark(end); 515 } 516 else { // byte short char int 517 // do nothing 518 } 519 } 520 521 private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) { 522 iv.dup2(); 523 iv.iconst(32); 524 iv.ushr(Type.LONG_TYPE); 525 iv.xor(Type.LONG_TYPE); 526 mv.visitInsn(L2I); 527 } 528 529 static void genInvertBoolean(InstructionAdapter v) { 530 v.iconst(1); 531 v.xor(Type.INT_TYPE); 532 } 533 534 @NotNull 535 public static StackValue genEqualsForExpressionsOnStack( 536 final @NotNull IElementType opToken, 537 final @NotNull StackValue left, 538 final @NotNull StackValue right 539 ) { 540 final Type leftType = left.type; 541 final Type rightType = right.type; 542 if (isPrimitive(leftType) && leftType == rightType) { 543 return StackValue.cmp(opToken, leftType, left, right); 544 } 545 546 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 547 @Override 548 public Unit invoke(InstructionAdapter v) { 549 left.put(leftType, v); 550 right.put(rightType, v); 551 genAreEqualCall(v); 552 553 if (opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ) { 554 genInvertBoolean(v); 555 } 556 return Unit.INSTANCE; 557 } 558 }); 559 } 560 561 public static void genAreEqualCall(InstructionAdapter v) { 562 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); 563 } 564 565 public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) { 566 numConst(myDelta, expectedType, v); 567 v.add(expectedType); 568 } 569 570 public static void numConst(int value, Type type, InstructionAdapter v) { 571 if (type == Type.FLOAT_TYPE) { 572 v.fconst(value); 573 } 574 else if (type == Type.DOUBLE_TYPE) { 575 v.dconst(value); 576 } 577 else if (type == Type.LONG_TYPE) { 578 v.lconst(value); 579 } 580 else if (type == Type.CHAR_TYPE || type == Type.BYTE_TYPE || type == Type.SHORT_TYPE || type == Type.INT_TYPE) { 581 v.iconst(value); 582 } 583 else { 584 throw new IllegalArgumentException("Primitive numeric type expected, got: " + type); 585 } 586 } 587 588 public static void genIncrement(Type expectedType, Type baseType, int myDelta, InstructionAdapter v) { 589 genIncrement(baseType, myDelta, v); 590 StackValue.coerce(baseType, expectedType, v); 591 } 592 593 public static void swap(InstructionAdapter v, Type stackTop, Type afterTop) { 594 if (stackTop.getSize() == 1) { 595 if (afterTop.getSize() == 1) { 596 v.swap(); 597 } 598 else { 599 v.dupX2(); 600 v.pop(); 601 } 602 } 603 else { 604 if (afterTop.getSize() == 1) { 605 v.dup2X1(); 606 } 607 else { 608 v.dup2X2(); 609 } 610 v.pop2(); 611 } 612 } 613 614 public static void genNotNullAssertionsForParameters( 615 @NotNull InstructionAdapter v, 616 @NotNull GenerationState state, 617 @NotNull FunctionDescriptor descriptor, 618 @NotNull FrameMap frameMap 619 ) { 620 if (!state.isParamAssertionsEnabled()) return; 621 622 // Private method is not accessible from other classes, no assertions needed 623 if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return; 624 625 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 626 if (receiverParameter != null) { 627 genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver"); 628 } 629 630 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) { 631 genParamAssertion(v, state.getTypeMapper(), frameMap, parameter, parameter.getName().asString()); 632 } 633 } 634 635 private static void genParamAssertion( 636 @NotNull InstructionAdapter v, 637 @NotNull KotlinTypeMapper typeMapper, 638 @NotNull FrameMap frameMap, 639 @NotNull CallableDescriptor parameter, 640 @NotNull String name 641 ) { 642 KotlinType type = parameter.getReturnType(); 643 if (type == null || isNullableType(type)) return; 644 645 int index = frameMap.getIndex(parameter); 646 Type asmType = typeMapper.mapType(type); 647 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 648 v.load(index, asmType); 649 v.visitLdcInsn(name); 650 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull", 651 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 652 } 653 } 654 655 @NotNull 656 public static StackValue genNotNullAssertions( 657 @NotNull GenerationState state, 658 @NotNull final StackValue stackValue, 659 @Nullable final RuntimeAssertionInfo runtimeAssertionInfo 660 ) { 661 if (!state.isCallAssertionsEnabled()) return stackValue; 662 if (runtimeAssertionInfo == null || !runtimeAssertionInfo.getNeedNotNullAssertion()) return stackValue; 663 664 return new StackValue(stackValue.type) { 665 666 @Override 667 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 668 stackValue.put(type, v); 669 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 670 v.dup(); 671 v.visitLdcInsn(runtimeAssertionInfo.getMessage()); 672 v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull", 673 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 674 } 675 } 676 }; 677 } 678 679 public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 680 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 681 v.aconst(null); 682 } 683 else { 684 pushDefaultPrimitiveValueOnStack(type, v); 685 } 686 } 687 688 public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 689 if (type.getSort() == Type.FLOAT) { 690 v.fconst(0); 691 } 692 else if (type.getSort() == Type.DOUBLE) { 693 v.dconst(0); 694 } 695 else if (type.getSort() == Type.LONG) { 696 v.lconst(0); 697 } 698 else { 699 v.iconst(0); 700 } 701 } 702 703 public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) { 704 return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && 705 isObject(propertyDescriptor.getContainingDeclaration()); 706 } 707 708 public static int getVisibilityForBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) { 709 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 710 if (isDelegate || isExtensionProperty) { 711 return ACC_PRIVATE; 712 } 713 else { 714 return propertyDescriptor.isLateInit() || isConstOrHasJvmFieldAnnotation(propertyDescriptor) 715 ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) 716 : ACC_PRIVATE; 717 } 718 } 719 720 private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) { 721 if (!propertyDescriptor.isVar()) { 722 return propertyDescriptor; 723 } 724 else { 725 return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor; 726 } 727 } 728 729 public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 730 DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration(); 731 return propertyDescriptor.isConst() 732 && isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration()) 733 && getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC; 734 } 735 736 public static Type comparisonOperandType(Type left, Type right) { 737 if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE; 738 if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE; 739 if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE; 740 return Type.INT_TYPE; 741 } 742 743 @NotNull 744 public static Type numberFunctionOperandType(@NotNull Type expectedType) { 745 if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE || expectedType == Type.CHAR_TYPE) { 746 return Type.INT_TYPE; 747 } 748 return expectedType; 749 } 750 751 public static void pop(@NotNull MethodVisitor v, @NotNull Type type) { 752 if (type.getSize() == 2) { 753 v.visitInsn(Opcodes.POP2); 754 } 755 else { 756 v.visitInsn(Opcodes.POP); 757 } 758 } 759 760 public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) { 761 dup(v, type.getSize()); 762 } 763 764 private static void dup(@NotNull InstructionAdapter v, int size) { 765 if (size == 2) { 766 v.dup2(); 767 } 768 else if (size == 1) { 769 v.dup(); 770 } 771 else { 772 throw new UnsupportedOperationException(); 773 } 774 } 775 776 public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) { 777 if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) { 778 return; 779 } 780 781 if (topOfStack.getSize() == 0) { 782 dup(v, afterTop); 783 } 784 else if (afterTop.getSize() == 0) { 785 dup(v, topOfStack); 786 } 787 else if (afterTop.getSize() == 1) { 788 if (topOfStack.getSize() == 1) { 789 dup(v, 2); 790 } 791 else { 792 v.dup2X1(); 793 v.pop2(); 794 v.dupX2(); 795 v.dupX2(); 796 v.pop(); 797 v.dup2X1(); 798 } 799 } 800 else { 801 //Note: it's possible to write dup3 and dup4 802 throw new UnsupportedOperationException("Don't know how generate dup3/dup4 for: " + topOfStack + " and " + afterTop); 803 } 804 } 805 806 public static void writeAnnotationData( 807 @NotNull AnnotationVisitor av, 808 @NotNull DescriptorSerializer serializer, 809 @NotNull MessageLite message 810 ) { 811 byte[] bytes = serializer.serialize(message); 812 813 AnnotationVisitor data = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME); 814 for (String string : BitEncoding.encodeBytes(bytes)) { 815 data.visit(null, string); 816 } 817 data.visitEnd(); 818 819 AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME); 820 for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) { 821 strings.visit(null, string); 822 } 823 strings.visitEnd(); 824 } 825 826 @NotNull 827 public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 828 return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName)); 829 } 830 831 @NotNull 832 public static String internalNameByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 833 return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName(); 834 } 835 836 @NotNull 837 public static String getSimpleInternalName(@NotNull String internalName) { 838 int lastSlash = internalName.lastIndexOf('/'); 839 if (lastSlash >= 0) { 840 return internalName.substring(lastSlash + 1); 841 } 842 else { 843 return internalName; 844 } 845 } 846 847 public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) { 848 if (isPrimitive(type)) { 849 v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;"); 850 } 851 else { 852 v.aconst(type); 853 } 854 } 855 856 public static void wrapJavaClassIntoKClass(@NotNull InstructionAdapter v) { 857 v.invokestatic(REFLECTION, "getOrCreateKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false); 858 } 859 860 public static void wrapJavaClassesIntoKClasses(@NotNull InstructionAdapter v) { 861 v.invokestatic(REFLECTION, "getOrCreateKotlinClasses", Type.getMethodDescriptor(K_CLASS_ARRAY_TYPE, getType(Class[].class)), false); 862 } 863 864 public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) { 865 OwnerKind kind = context.getContextKind(); 866 //Trait always should have this descriptor 867 return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1; 868 } 869 }