[JS IR BE] support CharSequence and String methods
This commit is contained in:
@@ -9,9 +9,12 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.findSingleFunction
|
||||
@@ -219,6 +222,20 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
|
||||
val jsArraySlice = unOp("slice")
|
||||
|
||||
// TODO move to IntrinsifyCallsLowering
|
||||
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getInternalClass("DoNotIntrinsify"))
|
||||
|
||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||
val charSequenceLengthPropertyGetterSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol
|
||||
val charSequenceGetFunctionSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get"}.symbol
|
||||
val charSequenceSubSequenceFunctionSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence"}.symbol
|
||||
|
||||
|
||||
val jsCharSequenceGet = getInternalFunction("charSequenceGet")
|
||||
val jsCharSequenceLength = getInternalFunction("charSequenceLength")
|
||||
val jsCharSequenceSubSequence = getInternalFunction("charSequenceSubSequence")
|
||||
|
||||
// Helpers:
|
||||
|
||||
private fun getInternalFunction(name: String) =
|
||||
|
||||
+11
@@ -162,6 +162,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
}
|
||||
|
||||
add(context.irBuiltIns.stringClass.lengthProperty, context.intrinsics.jsArrayLength, true)
|
||||
add(context.irBuiltIns.stringClass.getFunction, intrinsics.jsCharSequenceGet.owner, true)
|
||||
add(context.irBuiltIns.stringClass.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence"}.symbol,
|
||||
intrinsics.jsCharSequenceSubSequence.owner, true)
|
||||
|
||||
add(intrinsics.charSequenceLengthPropertyGetterSymbol, intrinsics.jsCharSequenceLength.owner, true)
|
||||
add(intrinsics.charSequenceGetFunctionSymbol, intrinsics.jsCharSequenceGet.owner, true)
|
||||
add(intrinsics.charSequenceSubSequenceFunctionSymbol, intrinsics.jsCharSequenceSubSequence.owner, true)
|
||||
}
|
||||
|
||||
memberToTransformer.run {
|
||||
@@ -352,6 +359,10 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
val symbol = call.symbol
|
||||
val declaration = symbol.owner
|
||||
|
||||
if (declaration.annotations.any { it.superQualifierSymbol == intrinsics.doNotIntrinsifyAnnotationSymbol }) {
|
||||
return call
|
||||
}
|
||||
|
||||
if (declaration.isDynamic() || declaration.isEffectivelyExternal()) {
|
||||
when (call.origin) {
|
||||
IrStatementOrigin.GET_PROPERTY -> {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
val cs: CharSequence = "abcd"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
val xs = "abcd"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
val xs = "abcd"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
val xs = "abcd"
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// DONT_RUN_GENERATED_CODE: JS
|
||||
|
||||
fun escapeChar(c : Char) : String? = when (c) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun StringBuilder.first() = this.get(0)
|
||||
|
||||
fun foo() = StringBuilder("foo").first()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
val list = ArrayList<String>()
|
||||
list.add("0")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
val c: Char? = '0'
|
||||
c!!.toInt()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
val s: String? = "abc"
|
||||
val c = s?.get(0)!! - 'b'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
fun foo(i : Int?, a : Any?) {
|
||||
i?.plus(1)
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// Auto-generated by GenerateInRangeExpressionTestData. Do not edit!
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
-3
@@ -1,9 +1,6 @@
|
||||
// TODO: muted automatically, investigate should it be ran for JVM_IR or not
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
// TODO: muted automatically, investigate should it be ran for JS_IR or not
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
// Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT!
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun test(s: CharSequence): Int {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun box(): String {
|
||||
|
||||
-3
@@ -1,9 +1,6 @@
|
||||
// TODO: muted automatically, investigate should it be ran for JVM_IR or not
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
// TODO: muted automatically, investigate should it be ran for JS_IR or not
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
// Auto-generated by org.jetbrains.kotlin.generators.tests.GenerateRangesCodegenTestData. DO NOT EDIT!
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun foo(): Int {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
class Thing(delegate: CharSequence) : CharSequence by delegate
|
||||
|
||||
fun box(): String {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
fun box(): String {
|
||||
val sb = StringBuilder("OK")
|
||||
return "${sb.get(0)}${sb[1]}"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// KT-5956 java.lang.AbstractMethodError: test.Thing.subSequence(II)Ljava/lang/CharSequence
|
||||
|
||||
class Thing(val delegate: CharSequence) : CharSequence {
|
||||
|
||||
+1
-2
@@ -122,8 +122,7 @@ public class GenerateRangesCodegenTestData {
|
||||
private static final List<String> IGNORED_FOR_JS_BACKEND = Collections.emptyList();
|
||||
|
||||
private static final List<String> IGNORED_FOR_JS_IR_BACKEND = Arrays.asList("inexactDownToMinValue.kt",
|
||||
"inexactToMaxValue.kt",
|
||||
"simpleRangeWithNonConstantEnds.kt");
|
||||
"inexactToMaxValue.kt");
|
||||
|
||||
private static final List<String> IGNORED_FOR_NATIVE_BACKEND = Collections.emptyList();
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1230
|
||||
package foo
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1250
|
||||
package foo
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1286
|
||||
package foo
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1284
|
||||
// See KT-8005
|
||||
package foo
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1300
|
||||
/*
|
||||
* Copy of JVM-backend test
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1303
|
||||
/*
|
||||
* Copy of JVM-backend test
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1524
|
||||
package foo
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// EXPECTED_REACHABLE_NODES: 1288
|
||||
var log = ""
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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 kotlin.js
|
||||
|
||||
internal annotation class DoNotIntrinsify
|
||||
|
||||
@PublishedApi
|
||||
@DoNotIntrinsify
|
||||
internal fun charSequenceGet(a: CharSequence, index: Int): Char {
|
||||
return if (a is String) {
|
||||
Char(a.asDynamic().charCodeAt(index).unsafeCast<Int>())
|
||||
} else {
|
||||
a[index]
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@DoNotIntrinsify
|
||||
internal fun charSequenceLength(a: CharSequence): Int {
|
||||
return if (a is String) {
|
||||
a.asDynamic().length.unsafeCast<Int>()
|
||||
} else {
|
||||
a.length
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@DoNotIntrinsify
|
||||
internal fun charSequenceSubSequence(a: CharSequence, startIndex: Int, endIndex: Int): CharSequence {
|
||||
return if (a is String) {
|
||||
a.asDynamic().substring(startIndex, endIndex).unsafeCast<String>()
|
||||
} else {
|
||||
a.subSequence(startIndex, endIndex)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user