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