Use java.lang.Long.divideUnsigned/remainderUnsigned in Java 1.8+

#KT-24876
This commit is contained in:
Dmitry Petrov
2019-01-11 17:32:12 +03:00
parent a344feff5c
commit 9973d59643
19 changed files with 361 additions and 2 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.Callable;
import org.jetbrains.kotlin.codegen.CallableMethod;
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
@@ -36,6 +37,10 @@ public abstract class IntrinsicMethod {
return toCallable(codegen.getState().getTypeMapper().mapToCallableMethod(fd, false), isSuper, resolvedCall);
}
public boolean isApplicableToOverload(@NotNull CallableMemberDescriptor descriptor) {
return true;
}
@NotNull
protected Callable toCallable(@NotNull CallableMethod method, boolean isSuper, @NotNull ResolvedCall resolvedCall) {
return toCallable(method, isSuper);
@@ -41,6 +41,8 @@ public class IntrinsicMethods {
private static final FqName KOTLIN_JVM = new FqName("kotlin.jvm");
/* package */ static final FqNameUnsafe RECEIVER_PARAMETER_FQ_NAME = new FqNameUnsafe("T");
private static final FqNameUnsafe KOTLIN_ULONG = new FqNameUnsafe("kotlin.ULong");
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus();
private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
@@ -153,6 +155,16 @@ public class IntrinsicMethods {
}
declareArrayMethods();
if (jvmTarget.compareTo(JvmTarget.JVM_1_8) >= 0) {
Java8ULongDivide java8ULongDivide = new Java8ULongDivide();
Java8ULongRemainder java8ULongRemainder = new Java8ULongRemainder();
intrinsicsMap.registerIntrinsic(KOTLIN_ULONG.toSafe(), null, "div", 1, java8ULongDivide);
intrinsicsMap.registerIntrinsic(KOTLIN_ULONG.toSafe(), null, "rem", 1, java8ULongRemainder);
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "ulongDivide", 2, java8ULongDivide);
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "ulongRemainder", 2, java8ULongRemainder);
}
}
private void declareArrayMethods() {
@@ -56,12 +56,15 @@ internal class IntrinsicsMap {
}
fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? =
intrinsicsMap[Key(
intrinsicsMap[getKey(descriptor)]?.takeIf { it.isApplicableToOverload(descriptor.original) }
private fun getKey(descriptor: CallableMemberDescriptor): Key =
Key(
DescriptorUtils.getFqName(descriptor.containingDeclaration),
getReceiverParameterFqName(descriptor),
descriptor.name.asString(),
valueParameterCountForKey(descriptor)
)]
)
private fun getReceiverParameterFqName(descriptor: CallableMemberDescriptor): FqNameUnsafe? {
val receiverParameter = descriptor.extensionReceiverParameter ?: return null
@@ -72,4 +75,6 @@ internal class IntrinsicsMap {
else
DescriptorUtils.getFqName(classifier)
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
abstract class UnsignedLongDivisionIntrinsic : IntrinsicMethod() {
override fun isApplicableToOverload(descriptor: CallableMemberDescriptor): Boolean {
if (descriptor.containingDeclaration is PackageFragmentDescriptor) return true
val singleValueParameterTypeDescriptor = descriptor.valueParameters.single().type.constructor.declarationDescriptor
?: throw AssertionError("Unexpected descriptor for unsigned long division intrinsic: $descriptor")
return singleValueParameterTypeDescriptor.name.asString() == "ULong"
}
}
class Java8ULongDivide : UnsignedLongDivisionIntrinsic() {
override fun toCallable(method: CallableMethod): Callable =
createIntrinsicCallable(method) {
it.invokestatic("java/lang/Long", "divideUnsigned", "(JJ)J", false)
}
}
class Java8ULongRemainder : UnsignedLongDivisionIntrinsic() {
override fun toCallable(method: CallableMethod): Callable =
createIntrinsicCallable(method) {
it.invokestatic("java/lang/Long", "remainderUnsigned", "(JJ)J", false)
}
}