diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index 8263ec44682..f54975cd360 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt @@ -253,6 +253,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xwasm-kclass-fqn", description = "Enable support for FQ names in KClass") var wasmKClassFqn: Boolean by FreezableVar(false) + @Argument(value = "-Xwasm-enable-array-range-checks", description = "Turn on range checks for the array access functions") + var wasmEnableArrayRangeChecks: Boolean by FreezableVar(false) + override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap, Any> { return super.configureAnalysisFlags(collector, languageVersion).also { it[allowFullyQualifiedNameInKClass] = wasm && wasmKClassFqn //Only enabled WASM BE supports this flag diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index 4b265597e04..8aa0d50ba48 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -135,6 +135,8 @@ class K2JsIrCompiler : CLICompiler() { configuration.put(JSConfigurationKeys.PARTIAL_LINKAGE, arguments.partialLinkage) + configuration.put(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS, arguments.wasmEnableArrayRangeChecks) + val commonSourcesArray = arguments.commonSources val commonSources = commonSourcesArray?.toSet() ?: emptySet() for (arg in arguments.freeArgs) { diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt index 8657ffde302..78f9aeb4c1b 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt @@ -156,6 +156,8 @@ class WasmSymbols( val wasmRefCast = getInternalFunction("wasm_ref_cast") + val rangeCheck = getInternalFunction("rangeCheck") + val boxIntrinsic: IrSimpleFunctionSymbol = getInternalFunction("boxIntrinsic") val unboxIntrinsic: IrSimpleFunctionSymbol = getInternalFunction("unboxIntrinsic") diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt index b269e75e3a3..66815144cb6 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.wasm.ir.* class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorVoid { @@ -258,6 +259,13 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV return } + // Range check intrinsic is a special case because it doesn't require arguments on the stack. + if (call.symbol == wasmSymbols.rangeCheck && + backendContext.configuration.getNotNull(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS) == false) { + body.buildGetUnit() + return + } + val function: IrFunction = call.symbol.owner.realOverrideTarget call.dispatchReceiver?.let { generateExpression(it) } diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 8d993c89072..7b87fd07b89 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -39,6 +39,8 @@ where advanced options include: -Xtyped-arrays Translate primitive arrays to JS typed arrays -Xwasm Use experimental WebAssembly compiler backend -Xwasm-debug-info Add debug info to WebAssembly compiled module + -Xwasm-enable-array-range-checks + Turn on range checks for the array access functions -Xwasm-kclass-fqn Enable support for FQ names in KClass -Xwasm-launcher=esm|nodejs|d8 Picks flavor for the wasm launcher. Default is ESM. -Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java index 3877733db44..fdddd23a301 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/config/JSConfigurationKeys.java @@ -99,4 +99,7 @@ public class JSConfigurationKeys { public static final CompilerConfigurationKey PROPERTY_LAZY_INITIALIZATION = CompilerConfigurationKey.create("perform lazy initialization for properties"); + + public static final CompilerConfigurationKey WASM_ENABLE_ARRAY_RANGE_CHECKS = + CompilerConfigurationKey.create("enable array range checks"); } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt index 010bf48a198..d0f062c585d 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/BasicWasmBoxTest.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.facade.TranslationUnit import org.jetbrains.kotlin.js.testOld.engines.ExternalTool @@ -235,6 +236,7 @@ abstract class BasicWasmBoxTest( private fun createConfig(languageVersionSettings: LanguageVersionSettings?): JsConfig { val configuration = environment.configuration.copy() configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE) + configuration.put(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS, false) configuration.languageVersionSettings = languageVersionSettings ?: LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE) return JsConfig(project, configuration, CompilerEnvironment, null, null) diff --git a/libraries/stdlib/wasm/build.gradle.kts b/libraries/stdlib/wasm/build.gradle.kts index 01d2e9aa3a1..6f8569fe72a 100644 --- a/libraries/stdlib/wasm/build.gradle.kts +++ b/libraries/stdlib/wasm/build.gradle.kts @@ -1,4 +1,5 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCompile +import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink plugins { `maven-publish` @@ -139,6 +140,10 @@ val compileTestKotlinWasm by tasks.existing(KotlinCompile::class) { } } +tasks.named("compileTestDevelopmentExecutableKotlinWasm") { + (this as KotlinCompile<*>).kotlinOptions.freeCompilerArgs += "-Xwasm-enable-array-range-checks" +} + val runtimeElements by configurations.creating {} val apiElements by configurations.creating {}