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