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