[JS IR BE] Copy type metadata for Boolean, Char and Long varargs

This commit is contained in:
Svyatoslav Kuzmich
2019-05-19 20:04:17 +03:00
parent 59617c97b4
commit b8bbcb3f93
6 changed files with 69 additions and 3 deletions
@@ -245,6 +245,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val arrayConcat = getInternalWithoutPackage("arrayConcat")
val primitiveArrayConcat = getInternalWithoutPackage("primitiveArrayConcat")
val taggedArrayCopy = getInternalWithoutPackage("taggedArrayCopy")
val jsArraySlice = defineJsSliceIntrinsic().symbol
@@ -15,8 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -139,11 +138,18 @@ private class VarargTransformer(
if (segments.size == 1) {
val segment = segments.first()
val argument = if (expression.elements.any { it is IrSpreadElement }) {
val elementType = arrayInfo.primitiveElementType
val copyFunction =
if (elementType.isChar() || elementType.isBoolean() || elementType.isLong())
context.intrinsics.taggedArrayCopy
else
context.intrinsics.jsArraySlice
IrCallImpl(
expression.startOffset,
expression.endOffset,
arrayInfo.primitiveArrayType,
context.intrinsics.jsArraySlice
copyFunction
).apply {
putTypeArgument(0, arrayInfo.primitiveArrayType)
putValueArgument(0, segment)
@@ -6795,6 +6795,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
public void testEmptyVarargInConstructorCall() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/emptyVarargInConstructorCall.kt");
}
@TestMetadata("taggedArrayCopy.kt")
public void testTaggedArrayCopy() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/taggedArrayCopy.kt");
}
}
}
@@ -6830,6 +6830,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
public void testEmptyVarargInConstructorCall() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/emptyVarargInConstructorCall.kt");
}
@TestMetadata("taggedArrayCopy.kt")
public void testTaggedArrayCopy() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/taggedArrayCopy.kt");
}
}
}
@@ -0,0 +1,43 @@
// IGNORE_BACKEND: JS
// KJS_WITH_FULL_RUNTIME
// EXPECTED_REACHABLE_NODES: 1281
package foo
fun checkBooleanVararg(vararg xs: Boolean) {
assertTrue(xs is BooleanArray)
}
fun checkLongVararg(vararg xs: Long) {
assertTrue(xs is LongArray)
}
fun checkCharVararg(vararg xs: Char) {
assertTrue(xs is CharArray)
}
fun box(): String {
checkBooleanVararg()
checkBooleanVararg(true)
checkBooleanVararg(true, false)
checkBooleanVararg(*booleanArrayOf())
checkBooleanVararg(*booleanArrayOf(true, false))
checkBooleanVararg(true, *booleanArrayOf(false), false, *booleanArrayOf())
checkLongVararg()
checkLongVararg(1L)
checkLongVararg(2L, 3L)
checkLongVararg(*longArrayOf())
checkLongVararg(*longArrayOf(4L, 5L))
checkLongVararg(*longArrayOf(4L, 5L), 10L, 20L, 30L)
checkCharVararg()
checkCharVararg('a')
checkCharVararg('b', 'c')
checkCharVararg(*charArrayOf())
checkCharVararg(*charArrayOf('d', 'e'))
checkCharVararg(*charArrayOf(), *charArrayOf(), *charArrayOf())
checkCharVararg('e', *charArrayOf(), 'f', *charArrayOf(), 'x', *charArrayOf(), 'd')
return "OK"
}
@@ -44,6 +44,12 @@ internal fun <T> primitiveArrayConcat(vararg args: T): T {
return result.unsafeCast<T>()
}
internal fun <T> taggedArrayCopy(array: dynamic): T {
val res = array.slice()
res.`$type$` = array.`$type$`
return res.unsafeCast<T>()
}
@PublishedApi
internal inline fun withType(type: String, array: dynamic): dynamic {
array.`$type$` = type