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(ClassDescriptor descriptor) { 259 if (descriptor.getVisibility() == Visibilities.PUBLIC || 260 // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes 261 descriptor.getVisibility() == Visibilities.LOCAL || 262 descriptor.getVisibility() == Visibilities.INTERNAL) { 263 return ACC_PUBLIC; 264 } 265 return NO_FLAG_PACKAGE_PRIVATE; 266 } 267 268 public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { 269 return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; 270 } 271 272 public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { 273 int visibility = (innerClass.getVisibility() == Visibilities.LOCAL) ? ACC_PUBLIC : getVisibilityAccessFlag(innerClass); 274 return visibility | 275 innerAccessFlagsForModalityAndKind(innerClass) | 276 (innerClass.isInner() ? 0 : ACC_STATIC); 277 } 278 279 private static int innerAccessFlagsForModalityAndKind(@NotNull ClassDescriptor innerClass) { 280 switch (innerClass.getKind()) { 281 case INTERFACE: 282 return ACC_ABSTRACT | ACC_INTERFACE; 283 case ENUM_CLASS: 284 return ACC_FINAL | ACC_ENUM; 285 case ANNOTATION_CLASS: 286 return ACC_ABSTRACT | ACC_ANNOTATION | ACC_INTERFACE; 287 default: 288 if (innerClass.getModality() == Modality.FINAL) { 289 return ACC_FINAL; 290 } 291 else if (innerClass.getModality() == Modality.ABSTRACT) { 292 return ACC_ABSTRACT; 293 } 294 } 295 return 0; 296 } 297 298 public static int getDeprecatedAccessFlag(@NotNull MemberDescriptor descriptor) { 299 if (descriptor instanceof PropertyAccessorDescriptor) { 300 return KotlinBuiltIns.isDeprecated(descriptor) 301 ? ACC_DEPRECATED 302 : getDeprecatedAccessFlag(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty()); 303 } 304 else if (KotlinBuiltIns.isDeprecated(descriptor)) { 305 return ACC_DEPRECATED; 306 } 307 return 0; 308 } 309 310 private static int getVarargsFlag(FunctionDescriptor functionDescriptor) { 311 if (!functionDescriptor.getValueParameters().isEmpty() 312 && functionDescriptor.getValueParameters().get(functionDescriptor.getValueParameters().size() - 1) 313 .getVarargElementType() != null) { 314 return ACC_VARARGS; 315 } 316 return 0; 317 } 318 319 @Nullable 320 private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) { 321 DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); 322 Visibility memberVisibility = memberDescriptor.getVisibility(); 323 324 if (AnnotationUtilKt.isInlineOnly(memberDescriptor)) return ACC_PRIVATE; 325 326 if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) { 327 return ACC_PUBLIC; 328 } 329 330 if (isEnumEntry(memberDescriptor)) { 331 return NO_FLAG_PACKAGE_PRIVATE; 332 } 333 334 if (memberDescriptor instanceof ConstructorDescriptor && isAnonymousObject(memberDescriptor.getContainingDeclaration())) { 335 return getVisibilityAccessFlagForAnonymous((ClassDescriptor) memberDescriptor.getContainingDeclaration()); 336 } 337 338 if (memberDescriptor instanceof SyntheticJavaPropertyDescriptor) { 339 return getVisibilityAccessFlag(((SyntheticJavaPropertyDescriptor) memberDescriptor).getGetMethod()); 340 } 341 if (memberDescriptor instanceof PropertyAccessorDescriptor) { 342 PropertyDescriptor property = ((PropertyAccessorDescriptor) memberDescriptor).getCorrespondingProperty(); 343 if (property instanceof SyntheticJavaPropertyDescriptor) { 344 FunctionDescriptor method = memberDescriptor == property.getGetter() 345 ? ((SyntheticJavaPropertyDescriptor) property).getGetMethod() 346 : ((SyntheticJavaPropertyDescriptor) property).getSetMethod(); 347 assert method != null : "No get/set method in SyntheticJavaPropertyDescriptor: " + property; 348 return getVisibilityAccessFlag(method); 349 } 350 } 351 352 if (memberDescriptor instanceof CallableDescriptor && memberVisibility == Visibilities.PROTECTED) { 353 for (CallableDescriptor overridden : DescriptorUtils.getAllOverriddenDescriptors((CallableDescriptor) memberDescriptor)) { 354 if (isJvmInterface(overridden.getContainingDeclaration())) { 355 return ACC_PUBLIC; 356 } 357 } 358 } 359 360 if (!Visibilities.isPrivate(memberVisibility)) { 361 return null; 362 } 363 364 // the following code is only for PRIVATE visibility of member 365 if (memberDescriptor instanceof ConstructorDescriptor) { 366 if (isEnumEntry(containingDeclaration)) { 367 return NO_FLAG_PACKAGE_PRIVATE; 368 } 369 if (isEnumClass(containingDeclaration)) { 370 //TODO: should be ACC_PRIVATE 371 // see http://youtrack.jetbrains.com/issue/KT-2680 372 return ACC_PROTECTED; 373 } 374 } 375 376 return null; 377 } 378 379 public static Type stringValueOfType(Type type) { 380 int sort = type.getSort(); 381 return sort == Type.OBJECT || sort == Type.ARRAY 382 ? OBJECT_TYPE 383 : sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : type; 384 } 385 386 private static Type stringBuilderAppendType(Type type) { 387 switch (type.getSort()) { 388 case Type.OBJECT: 389 return STRING_BUILDER_OBJECT_APPEND_ARG_TYPES.contains(type) ? type : OBJECT_TYPE; 390 case Type.ARRAY: 391 return OBJECT_TYPE; 392 case Type.BYTE: 393 case Type.SHORT: 394 return Type.INT_TYPE; 395 default: 396 return type; 397 } 398 } 399 400 public static void genThrow(@NotNull InstructionAdapter v, @NotNull String exception, @Nullable String message) { 401 v.anew(Type.getObjectType(exception)); 402 v.dup(); 403 if (message != null) { 404 v.aconst(message); 405 v.invokespecial(exception, "<init>", "(Ljava/lang/String;)V", false); 406 } 407 else { 408 v.invokespecial(exception, "<init>", "()V", false); 409 } 410 v.athrow(); 411 } 412 413 public static void genClosureFields(CalculatedClosure closure, ClassBuilder v, JetTypeMapper typeMapper) { 414 List<Pair<String, Type>> allFields = new ArrayList<Pair<String, Type>>(); 415 416 ClassifierDescriptor captureThis = closure.getCaptureThis(); 417 if (captureThis != null) { 418 allFields.add(Pair.create(CAPTURED_THIS_FIELD, typeMapper.mapType(captureThis))); 419 } 420 421 KotlinType captureReceiverType = closure.getCaptureReceiverType(); 422 if (captureReceiverType != null) { 423 allFields.add(Pair.create(CAPTURED_RECEIVER_FIELD, typeMapper.mapType(captureReceiverType))); 424 } 425 426 allFields.addAll(closure.getRecordedFields()); 427 genClosureFields(allFields, v); 428 } 429 430 public static void genClosureFields(List<Pair<String, Type>> allFields, ClassBuilder builder) { 431 //noinspection PointlessBitwiseExpression 432 int access = NO_FLAG_PACKAGE_PRIVATE | ACC_SYNTHETIC | ACC_FINAL; 433 for (Pair<String, Type> field : allFields) { 434 builder.newField(JvmDeclarationOrigin.NO_ORIGIN, access, field.first, field.second.getDescriptor(), null, null); 435 } 436 } 437 438 public static int genAssignInstanceFieldFromParam(FieldInfo info, int index, InstructionAdapter iv) { 439 assert !info.isStatic(); 440 Type fieldType = info.getFieldType(); 441 iv.load(0, info.getOwnerType());//this 442 iv.load(index, fieldType); //param 443 iv.visitFieldInsn(PUTFIELD, info.getOwnerInternalName(), info.getFieldName(), fieldType.getDescriptor()); 444 index += fieldType.getSize(); 445 return index; 446 } 447 448 public static void genStringBuilderConstructor(InstructionAdapter v) { 449 v.visitTypeInsn(NEW, "java/lang/StringBuilder"); 450 v.dup(); 451 v.invokespecial("java/lang/StringBuilder", "<init>", "()V", false); 452 } 453 454 public static void genInvokeAppendMethod(InstructionAdapter v, Type type) { 455 type = stringBuilderAppendType(type); 456 v.invokevirtual("java/lang/StringBuilder", "append", "(" + type.getDescriptor() + ")Ljava/lang/StringBuilder;", false); 457 } 458 459 public static StackValue genToString(final StackValue receiver, final Type receiverType) { 460 return StackValue.operation(JAVA_STRING_TYPE, new Function1<InstructionAdapter, Unit>() { 461 @Override 462 public Unit invoke(InstructionAdapter v) { 463 Type type = stringValueOfType(receiverType); 464 receiver.put(type, v); 465 v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;", false); 466 return null; 467 } 468 }); 469 } 470 471 static void genHashCode(MethodVisitor mv, InstructionAdapter iv, Type type) { 472 if (type.getSort() == Type.ARRAY) { 473 Type elementType = correctElementType(type); 474 if (elementType.getSort() == Type.OBJECT || elementType.getSort() == Type.ARRAY) { 475 iv.invokestatic("java/util/Arrays", "hashCode", "([Ljava/lang/Object;)I", false); 476 } 477 else { 478 iv.invokestatic("java/util/Arrays", "hashCode", "(" + type.getDescriptor() + ")I", false); 479 } 480 } 481 else if (type.getSort() == Type.OBJECT) { 482 iv.invokevirtual("java/lang/Object", "hashCode", "()I", false); 483 } 484 else if (type.getSort() == Type.LONG) { 485 genLongHashCode(mv, iv); 486 } 487 else if (type.getSort() == Type.DOUBLE) { 488 iv.invokestatic("java/lang/Double", "doubleToLongBits", "(D)J", false); 489 genLongHashCode(mv, iv); 490 } 491 else if (type.getSort() == Type.FLOAT) { 492 iv.invokestatic("java/lang/Float", "floatToIntBits", "(F)I", false); 493 } 494 else if (type.getSort() == Type.BOOLEAN) { 495 Label end = new Label(); 496 iv.dup(); 497 iv.ifeq(end); 498 iv.pop(); 499 iv.iconst(1); 500 iv.mark(end); 501 } 502 else { // byte short char int 503 // do nothing 504 } 505 } 506 507 private static void genLongHashCode(MethodVisitor mv, InstructionAdapter iv) { 508 iv.dup2(); 509 iv.iconst(32); 510 iv.ushr(Type.LONG_TYPE); 511 iv.xor(Type.LONG_TYPE); 512 mv.visitInsn(L2I); 513 } 514 515 static void genInvertBoolean(InstructionAdapter v) { 516 v.iconst(1); 517 v.xor(Type.INT_TYPE); 518 } 519 520 @NotNull 521 public static StackValue genEqualsForExpressionsOnStack( 522 final @NotNull IElementType opToken, 523 final @NotNull StackValue left, 524 final @NotNull StackValue right 525 ) { 526 final Type leftType = left.type; 527 final Type rightType = right.type; 528 if (isPrimitive(leftType) && leftType == rightType) { 529 return StackValue.cmp(opToken, leftType, left, right); 530 } 531 532 return StackValue.operation(Type.BOOLEAN_TYPE, new Function1<InstructionAdapter, Unit>() { 533 @Override 534 public Unit invoke(InstructionAdapter v) { 535 left.put(leftType, v); 536 right.put(rightType, v); 537 genAreEqualCall(v); 538 539 if (opToken == KtTokens.EXCLEQ || opToken == KtTokens.EXCLEQEQEQ) { 540 genInvertBoolean(v); 541 } 542 return Unit.INSTANCE; 543 } 544 }); 545 } 546 547 public static void genAreEqualCall(InstructionAdapter v) { 548 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false); 549 } 550 551 public static void genIncrement(Type expectedType, int myDelta, InstructionAdapter v) { 552 if (expectedType == Type.LONG_TYPE) { 553 v.lconst(myDelta); 554 } 555 else if (expectedType == Type.FLOAT_TYPE) { 556 v.fconst(myDelta); 557 } 558 else if (expectedType == Type.DOUBLE_TYPE) { 559 v.dconst(myDelta); 560 } 561 else { 562 v.iconst(myDelta); 563 v.add(Type.INT_TYPE); 564 StackValue.coerce(Type.INT_TYPE, expectedType, v); 565 return; 566 } 567 v.add(expectedType); 568 } 569 570 public static void swap(InstructionAdapter v, Type stackTop, Type afterTop) { 571 if (stackTop.getSize() == 1) { 572 if (afterTop.getSize() == 1) { 573 v.swap(); 574 } 575 else { 576 v.dupX2(); 577 v.pop(); 578 } 579 } 580 else { 581 if (afterTop.getSize() == 1) { 582 v.dup2X1(); 583 } 584 else { 585 v.dup2X2(); 586 } 587 v.pop2(); 588 } 589 } 590 591 public static void genNotNullAssertionsForParameters( 592 @NotNull InstructionAdapter v, 593 @NotNull GenerationState state, 594 @NotNull FunctionDescriptor descriptor, 595 @NotNull FrameMap frameMap 596 ) { 597 if (!state.isParamAssertionsEnabled()) return; 598 599 // Private method is not accessible from other classes, no assertions needed 600 if (getVisibilityAccessFlag(descriptor) == ACC_PRIVATE) return; 601 602 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 603 if (receiverParameter != null) { 604 genParamAssertion(v, state.getTypeMapper(), frameMap, receiverParameter, "$receiver"); 605 } 606 607 for (ValueParameterDescriptor parameter : descriptor.getValueParameters()) { 608 genParamAssertion(v, state.getTypeMapper(), frameMap, parameter, parameter.getName().asString()); 609 } 610 } 611 612 private static void genParamAssertion( 613 @NotNull InstructionAdapter v, 614 @NotNull JetTypeMapper typeMapper, 615 @NotNull FrameMap frameMap, 616 @NotNull CallableDescriptor parameter, 617 @NotNull String name 618 ) { 619 KotlinType type = parameter.getReturnType(); 620 if (type == null || isNullableType(type)) return; 621 622 int index = frameMap.getIndex(parameter); 623 Type asmType = typeMapper.mapType(type); 624 if (asmType.getSort() == Type.OBJECT || asmType.getSort() == Type.ARRAY) { 625 v.load(index, asmType); 626 v.visitLdcInsn(name); 627 v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkParameterIsNotNull", 628 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 629 } 630 } 631 632 @NotNull 633 public static StackValue genNotNullAssertions( 634 @NotNull GenerationState state, 635 @NotNull final StackValue stackValue, 636 @Nullable final RuntimeAssertionInfo runtimeAssertionInfo 637 ) { 638 if (!state.isCallAssertionsEnabled()) return stackValue; 639 if (runtimeAssertionInfo == null || !runtimeAssertionInfo.getNeedNotNullAssertion()) return stackValue; 640 641 return new StackValue(stackValue.type) { 642 643 @Override 644 public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) { 645 stackValue.put(type, v); 646 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 647 v.dup(); 648 v.visitLdcInsn(runtimeAssertionInfo.getMessage()); 649 v.invokestatic("kotlin/jvm/internal/Intrinsics", "checkExpressionValueIsNotNull", 650 "(Ljava/lang/Object;Ljava/lang/String;)V", false); 651 } 652 } 653 }; 654 } 655 656 public static void pushDefaultValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 657 if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { 658 v.aconst(null); 659 } 660 else { 661 pushDefaultPrimitiveValueOnStack(type, v); 662 } 663 } 664 665 public static void pushDefaultPrimitiveValueOnStack(@NotNull Type type, @NotNull InstructionAdapter v) { 666 if (type.getSort() == Type.FLOAT) { 667 v.fconst(0); 668 } 669 else if (type.getSort() == Type.DOUBLE) { 670 v.dconst(0); 671 } 672 else if (type.getSort() == Type.LONG) { 673 v.lconst(0); 674 } 675 else { 676 v.iconst(0); 677 } 678 } 679 680 public static boolean isInstancePropertyWithStaticBackingField(@NotNull PropertyDescriptor propertyDescriptor) { 681 return propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && 682 isObject(propertyDescriptor.getContainingDeclaration()); 683 } 684 685 public static int getVisibilityForBackingField(@NotNull PropertyDescriptor propertyDescriptor, boolean isDelegate) { 686 boolean isExtensionProperty = propertyDescriptor.getExtensionReceiverParameter() != null; 687 if (isDelegate || isExtensionProperty) { 688 return ACC_PRIVATE; 689 } 690 else { 691 return propertyDescriptor.isLateInit() || isConstOrHasJvmFieldAnnotation(propertyDescriptor) 692 ? getVisibilityAccessFlag(descriptorForVisibility(propertyDescriptor)) 693 : ACC_PRIVATE; 694 } 695 } 696 697 private static MemberDescriptor descriptorForVisibility(@NotNull PropertyDescriptor propertyDescriptor) { 698 if (!propertyDescriptor.isVar()) { 699 return propertyDescriptor; 700 } 701 else { 702 return propertyDescriptor.getSetter() != null ? propertyDescriptor.getSetter() : propertyDescriptor; 703 } 704 } 705 706 public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) { 707 DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration(); 708 return propertyDescriptor.isConst() 709 && isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration()) 710 && getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC; 711 } 712 713 public static Type comparisonOperandType(Type left, Type right) { 714 if (left == Type.DOUBLE_TYPE || right == Type.DOUBLE_TYPE) return Type.DOUBLE_TYPE; 715 if (left == Type.FLOAT_TYPE || right == Type.FLOAT_TYPE) return Type.FLOAT_TYPE; 716 if (left == Type.LONG_TYPE || right == Type.LONG_TYPE) return Type.LONG_TYPE; 717 return Type.INT_TYPE; 718 } 719 720 @NotNull 721 public static Type numberFunctionOperandType(@NotNull Type expectedType) { 722 if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE || expectedType == Type.CHAR_TYPE) { 723 return Type.INT_TYPE; 724 } 725 return expectedType; 726 } 727 728 public static void pop(@NotNull MethodVisitor v, @NotNull Type type) { 729 if (type.getSize() == 2) { 730 v.visitInsn(Opcodes.POP2); 731 } 732 else { 733 v.visitInsn(Opcodes.POP); 734 } 735 } 736 737 public static void dup(@NotNull InstructionAdapter v, @NotNull Type type) { 738 dup(v, type.getSize()); 739 } 740 741 private static void dup(@NotNull InstructionAdapter v, int size) { 742 if (size == 2) { 743 v.dup2(); 744 } 745 else if (size == 1) { 746 v.dup(); 747 } 748 else { 749 throw new UnsupportedOperationException(); 750 } 751 } 752 753 public static void dup(@NotNull InstructionAdapter v, @NotNull Type topOfStack, @NotNull Type afterTop) { 754 if (topOfStack.getSize() == 0 && afterTop.getSize() == 0) { 755 return; 756 } 757 758 if (topOfStack.getSize() == 0) { 759 dup(v, afterTop); 760 } 761 else if (afterTop.getSize() == 0) { 762 dup(v, topOfStack); 763 } 764 else if (afterTop.getSize() == 1) { 765 if (topOfStack.getSize() == 1) { 766 dup(v, 2); 767 } 768 else { 769 v.dup2X1(); 770 v.pop2(); 771 v.dupX2(); 772 v.dupX2(); 773 v.pop(); 774 v.dup2X1(); 775 } 776 } 777 else { 778 //Note: it's possible to write dup3 and dup4 779 throw new UnsupportedOperationException("Don't know how generate dup3/dup4 for: " + topOfStack + " and " + afterTop); 780 } 781 } 782 783 public static void writeAnnotationData( 784 @NotNull AnnotationVisitor av, 785 @NotNull DescriptorSerializer serializer, 786 @NotNull MessageLite message 787 ) { 788 byte[] bytes = serializer.serialize(message); 789 790 AnnotationVisitor data = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME); 791 for (String string : BitEncoding.encodeBytes(bytes)) { 792 data.visit(null, string); 793 } 794 data.visitEnd(); 795 796 AnnotationVisitor strings = av.visitArray(JvmAnnotationNames.METADATA_STRINGS_FIELD_NAME); 797 for (String string : ((JvmStringTable) serializer.getStringTable()).getStrings()) { 798 strings.visit(null, string); 799 } 800 strings.visitEnd(); 801 } 802 803 @NotNull 804 public static Type asmTypeByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 805 return Type.getObjectType(internalNameByFqNameWithoutInnerClasses(fqName)); 806 } 807 808 @NotNull 809 public static String internalNameByFqNameWithoutInnerClasses(@NotNull FqName fqName) { 810 return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName(); 811 } 812 813 @NotNull 814 public static String getSimpleInternalName(@NotNull String internalName) { 815 int lastSlash = internalName.lastIndexOf('/'); 816 if (lastSlash >= 0) { 817 return internalName.substring(lastSlash + 1); 818 } 819 else { 820 return internalName; 821 } 822 } 823 824 public static void putJavaLangClassInstance(@NotNull InstructionAdapter v, @NotNull Type type) { 825 if (isPrimitive(type)) { 826 v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;"); 827 } 828 else { 829 v.aconst(type); 830 } 831 } 832 833 public static void wrapJavaClassIntoKClass(@NotNull InstructionAdapter v) { 834 v.invokestatic(REFLECTION, "getOrCreateKotlinClass", Type.getMethodDescriptor(K_CLASS_TYPE, getType(Class.class)), false); 835 } 836 837 public static void wrapJavaClassesIntoKClasses(@NotNull InstructionAdapter v) { 838 v.invokestatic(REFLECTION, "getOrCreateKotlinClasses", Type.getMethodDescriptor(K_CLASS_ARRAY_TYPE, getType(Class[].class)), false); 839 } 840 841 public static int getReceiverIndex(@NotNull CodegenContext context, @NotNull CallableMemberDescriptor descriptor) { 842 OwnerKind kind = context.getContextKind(); 843 //Trait always should have this descriptor 844 return kind != OwnerKind.DEFAULT_IMPLS && isStaticMethod(kind, descriptor) ? 0 : 1; 845 } 846 }