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