From 233376eef00baf119ee1099645a0949f92cefec7 Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Fri, 10 Nov 2017 08:38:18 +0300 Subject: [PATCH] Improve min/max specialization for longs and 3-arg overloads in JS --- .../src/core/generated/_ComparisonsJs.kt | 36 +++++++-------- js/js.libraries/src/core/math.kt | 12 ++--- .../src/templates/Comparables.kt | 45 ++++++++++++++++--- 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/js/js.libraries/src/core/generated/_ComparisonsJs.kt b/js/js.libraries/src/core/generated/_ComparisonsJs.kt index c606e293b23..7e705bec8c3 100644 --- a/js/js.libraries/src/core/generated/_ComparisonsJs.kt +++ b/js/js.libraries/src/core/generated/_ComparisonsJs.kt @@ -26,7 +26,7 @@ public fun > maxOf(a: T, b: T): T { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Byte, b: Byte): Byte { - return Math.max(a.toInt(), b.toInt()).toByte() + return Math.max(a.toInt(), b.toInt()).unsafeCast() } /** @@ -35,7 +35,7 @@ public inline fun maxOf(a: Byte, b: Byte): Byte { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Short, b: Short): Short { - return Math.max(a.toInt(), b.toInt()).toShort() + return Math.max(a.toInt(), b.toInt()).unsafeCast() } /** @@ -51,9 +51,9 @@ public inline fun maxOf(a: Int, b: Int): Int { * Returns the greater of two values. */ @SinceKotlin("1.1") -@kotlin.internal.InlineOnly +@Suppress("NOTHING_TO_INLINE") public inline fun maxOf(a: Long, b: Long): Long { - return Math.max(a, b) + return if (a >= b) a else b } /** @@ -88,7 +88,7 @@ public fun > maxOf(a: T, b: T, c: T): T { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { - return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).toByte() + return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast() } /** @@ -97,7 +97,7 @@ public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Short, b: Short, c: Short): Short { - return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).toShort() + return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast() } /** @@ -106,7 +106,7 @@ public inline fun maxOf(a: Short, b: Short, c: Short): Short { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Int, b: Int, c: Int): Int { - return maxOf(a, maxOf(b, c)) + return Math.max(a, b, c) } /** @@ -124,7 +124,7 @@ public inline fun maxOf(a: Long, b: Long, c: Long): Long { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Float, b: Float, c: Float): Float { - return maxOf(a, maxOf(b, c)) + return Math.max(a, b, c) } /** @@ -133,7 +133,7 @@ public inline fun maxOf(a: Float, b: Float, c: Float): Float { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun maxOf(a: Double, b: Double, c: Double): Double { - return maxOf(a, maxOf(b, c)) + return Math.max(a, b, c) } /** @@ -168,7 +168,7 @@ public fun > minOf(a: T, b: T): T { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Byte, b: Byte): Byte { - return Math.min(a.toInt(), b.toInt()).toByte() + return Math.min(a.toInt(), b.toInt()).unsafeCast() } /** @@ -177,7 +177,7 @@ public inline fun minOf(a: Byte, b: Byte): Byte { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Short, b: Short): Short { - return Math.min(a.toInt(), b.toInt()).toShort() + return Math.min(a.toInt(), b.toInt()).unsafeCast() } /** @@ -193,9 +193,9 @@ public inline fun minOf(a: Int, b: Int): Int { * Returns the smaller of two values. */ @SinceKotlin("1.1") -@kotlin.internal.InlineOnly +@Suppress("NOTHING_TO_INLINE") public inline fun minOf(a: Long, b: Long): Long { - return Math.min(a, b) + return if (a <= b) a else b } /** @@ -230,7 +230,7 @@ public fun > minOf(a: T, b: T, c: T): T { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { - return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).toByte() + return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast() } /** @@ -239,7 +239,7 @@ public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Short, b: Short, c: Short): Short { - return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).toShort() + return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast() } /** @@ -248,7 +248,7 @@ public inline fun minOf(a: Short, b: Short, c: Short): Short { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Int, b: Int, c: Int): Int { - return minOf(a, minOf(b, c)) + return Math.min(a, b, c) } /** @@ -266,7 +266,7 @@ public inline fun minOf(a: Long, b: Long, c: Long): Long { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Float, b: Float, c: Float): Float { - return minOf(a, minOf(b, c)) + return Math.min(a, b, c) } /** @@ -275,7 +275,7 @@ public inline fun minOf(a: Float, b: Float, c: Float): Float { @SinceKotlin("1.1") @kotlin.internal.InlineOnly public inline fun minOf(a: Double, b: Double, c: Double): Double { - return minOf(a, minOf(b, c)) + return Math.min(a, b, c) } /** diff --git a/js/js.libraries/src/core/math.kt b/js/js.libraries/src/core/math.kt index 068aa54824a..5a4caa6213b 100644 --- a/js/js.libraries/src/core/math.kt +++ b/js/js.libraries/src/core/math.kt @@ -1045,14 +1045,14 @@ public fun abs(n: Int): Int = if (n < 0) (-n or 0) else n */ @SinceKotlin("1.2") @InlineOnly -public inline fun min(a: Int, b: Int): Int = minOf(a, b) +public inline fun min(a: Int, b: Int): Int = nativeMath.min(a, b) /** * Returns the greater of two values. */ @SinceKotlin("1.2") @InlineOnly -public inline fun max(a: Int, b: Int): Int = maxOf(a, b) +public inline fun max(a: Int, b: Int): Int = nativeMath.max(a, b) /** * Returns the absolute value of this value. @@ -1096,15 +1096,15 @@ public fun abs(n: Long): Long = if (n < 0) -n else n * Returns the smaller of two values. */ @SinceKotlin("1.2") -@InlineOnly -public inline fun min(a: Long, b: Long): Long = minOf(a, b) +@Suppress("NOTHING_TO_INLINE") +public inline fun min(a: Long, b: Long): Long = if (a <= b) a else b /** * Returns the greater of two values. */ @SinceKotlin("1.2") -@InlineOnly -public inline fun max(a: Long, b: Long): Long = maxOf(a, b) +@Suppress("NOTHING_TO_INLINE") +public inline fun max(a: Long, b: Long): Long = if (a >= b) a else b /** * Returns the absolute value of this value. diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt index 13864f4bda9..1681251390d 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Comparables.kt @@ -150,7 +150,6 @@ object ComparableOps : TemplateGroupBase() { typeParam("T: Comparable") returns("T") receiver("") - specialFor(Primitives) { inlineOnly() } doc { """ Returns the smaller of two values. @@ -159,15 +158,25 @@ object ComparableOps : TemplateGroupBase() { } // TODO: Add a note about NaN propagation for floats. specialFor(Primitives) { + inlineOnly() doc { """Returns the smaller of two values.""" } - // TODO: custom body for JS minOf(Long, Long) + var convertBack = "to$primitive()" + on(Platform.JS) { + convertBack = "unsafeCast<$primitive>()" + } body { "return Math.min(a, b)" } if (primitive in shortIntPrimitives) { - body { "return Math.min(a.toInt(), b.toInt()).to$primitive()" } + body { "return Math.min(a.toInt(), b.toInt()).$convertBack" } + } + on(Platform.JS) { + if (primitive == PrimitiveType.Long) { + inline(suppressWarning = true) + body { "return if (a <= b) a else b" } + } } } body(Generic) { @@ -197,6 +206,14 @@ object ComparableOps : TemplateGroupBase() { specialFor(Primitives) { if (primitive in shortIntPrimitives) { body { "return Math.min(a.toInt(), Math.min(b.toInt(), c.toInt())).to$primitive()" } + on(Platform.JS) { + body { "return Math.min(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" } + } + } + else if (primitive != PrimitiveType.Long) { + on(Platform.JS) { + body { "return Math.min(a, b, c)" } + } } } } @@ -245,7 +262,6 @@ object ComparableOps : TemplateGroupBase() { typeParam("T: Comparable") returns("T") receiver("") - specialFor(Primitives) { inlineOnly() } doc { """ Returns the greater of two values. @@ -254,14 +270,25 @@ object ComparableOps : TemplateGroupBase() { } // TODO: Add a note about NaN propagation for floats. specialFor(Primitives) { + inlineOnly() doc { """Returns the greater of two values.""" } + var convertBack = "to$primitive()" + on(Platform.JS) { + convertBack = "unsafeCast<$primitive>()" + } body { "return Math.max(a, b)" } if (primitive in shortIntPrimitives) { - body { "return Math.max(a.toInt(), b.toInt()).to$primitive()" } + body { "return Math.max(a.toInt(), b.toInt()).$convertBack" } + } + on(Platform.JS) { + if (primitive == PrimitiveType.Long) { + inline(suppressWarning = true) + body { "return if (a >= b) a else b" } + } } } body(Generic) { @@ -291,6 +318,14 @@ object ComparableOps : TemplateGroupBase() { specialFor(Primitives) { if (primitive in shortIntPrimitives) { body { "return Math.max(a.toInt(), Math.max(b.toInt(), c.toInt())).to$primitive()" } + on(Platform.JS) { + body { "return Math.max(a.toInt(), b.toInt(), c.toInt()).unsafeCast<$primitive>()" } + } + } + else if (primitive != PrimitiveType.Long) { + on(Platform.JS) { + body { "return Math.max(a, b, c)" } + } } } }