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