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