diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index b6ca06e7320..2de15aa5bb4 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -6,6 +6,7 @@ import org.jetbrains.kotlin.backend.common.IrValidatorConfig import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.phaser.* import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer +import org.jetbrains.kotlin.backend.konan.MemoryModel import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport @@ -454,6 +455,8 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) { disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) disableUnless(escapeAnalysisPhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) + // TODO: Support escape analysis with experimental MM. + disableIf(escapeAnalysisPhase, config.memoryModel == MemoryModel.EXPERIMENTAL) // Inline accessors only in optimized builds due to separate compilation and possibility to get broken // debug information. disableUnless(propertyAccessorInlinePhase, getBoolean(KonanConfigKeys.OPTIMIZATION)) diff --git a/kotlin-native/backend.native/tests/build.gradle b/kotlin-native/backend.native/tests/build.gradle index d69ec5fd5f6..6d6ecb376b8 100644 --- a/kotlin-native/backend.native/tests/build.gradle +++ b/kotlin-native/backend.native/tests/build.gradle @@ -2601,24 +2601,21 @@ standaloneTest("args0") { } standaloneTest("devirtualization_lateinitInterface") { - disabled = (cacheTesting != null) || // Cache is not compatible with -opt. - isExperimentalMM // Experimental MM does not support -opt yet. + disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "42\n" flags = ["-opt"] source = "codegen/devirtualization/lateinitInterface.kt" } standaloneTest("devirtualization_getter_looking_as_box_function") { - disabled = (cacheTesting != null) || // Cache is not compatible with -opt. - isExperimentalMM // Experimental MM does not support -opt yet. + disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "box\n" flags = ["-opt"] source = "codegen/devirtualization/getter_looking_as_box_function.kt" } standaloneTest("devirtualization_anonymousObject") { - disabled = (cacheTesting != null) || // Cache is not compatible with -opt. - isExperimentalMM // Experimental MM does not support -opt yet. + disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "zzz\n" flags = ["-opt"] source = "codegen/devirtualization/anonymousObject.kt" @@ -2857,6 +2854,14 @@ task codegen_escapeAnalysis_recursion(type: KonanLocalTest) { source = "codegen/escapeAnalysis/recursion.kt" } +standaloneTest("codegen_escapeAnalysis_stackAllocated") { + disabled = (cacheTesting != null) || // Cache is not compatible with -opt. + project.globalTestArgs.contains('-g') || // -g and -opt are incompatible + isExperimentalMM // TODO: Experimental MM doesn't support stack-allocated objects yet. + flags = ['-opt', '-tr', '-Xopt-in=kotlin.native.internal.InternalForKotlinNative'] + source = "codegen/escapeAnalysis/stackAllocated.kt" +} + task memory_var1(type: KonanLocalTest) { source = "runtime/memory/var1.kt" } @@ -3598,8 +3603,7 @@ tasks.register("driver0", KonanDriverTest) { } tasks.register("driver_opt", KonanDriverTest) { - disabled = (cacheTesting != null) || // Cache is not compatible with -opt. - isExperimentalMM // Experimental MM does not support -opt yet. + disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "Hello, world!\n" source = "runtime/basic/driver0.kt" flags = ["-opt"] @@ -4158,7 +4162,8 @@ interopTest("interop_threadStates") { interopTest("interop_threadStates_callbacksWithExceptions") { disabled = (project.testTarget == 'wasm32') || // No interop for wasm yet. - !isExperimentalMM // No thread state switching in the legacy MM. + !isExperimentalMM || // No thread state switching in the legacy MM. + project.globalTestArgs.contains('-opt') // TODO: Fix this test for -opt. source = "interop/threadStates/callbacksWithExceptions.kt" interop = "threadStates" } @@ -5135,8 +5140,7 @@ tasks.register("metadata_compare_unable_to_import", MetadataComparisonTest) { } standaloneTest("local_ea_arraysfieldwrite") { - disabled = (cacheTesting != null) || // Cache is not compatible with -opt. - isExperimentalMM // Experimental MM does not support -opt yet. + disabled = (cacheTesting != null) // Cache is not compatible with -opt. goldValue = "Array (constructor init):\nSize: 2\nContents: [1, 2]\n" + "Array (constructor init):\nSize: 2\nContents: [3, 4]\n" + "Array (default value init):\nSize: 2\nContents: [1, 2]\n" + diff --git a/kotlin-native/backend.native/tests/codegen/escapeAnalysis/stackAllocated.kt b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/stackAllocated.kt new file mode 100644 index 00000000000..1faeb8d0776 --- /dev/null +++ b/kotlin-native/backend.native/tests/codegen/escapeAnalysis/stackAllocated.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package codegen.escapeAnalysis.stackAllocated + +import kotlin.test.* +import kotlin.native.internal.* + +class A { + fun f(x: Int) = x + 13 +} + +fun f(x: Int): Int { + val a = A() + assertTrue(a.isLocal()) + return a.f(x) +} + +@Test fun runTest() { + assertEquals(f(42), 55) +} diff --git a/kotlin-native/runtime/src/main/cpp/Runtime.cpp b/kotlin-native/runtime/src/main/cpp/Runtime.cpp index 5cc5a404024..751c4de44a8 100644 --- a/kotlin-native/runtime/src/main/cpp/Runtime.cpp +++ b/kotlin-native/runtime/src/main/cpp/Runtime.cpp @@ -389,6 +389,10 @@ KBoolean Kotlin_Debugging_isPermanent(KRef obj) { return obj->permanent(); } +RUNTIME_NOTHROW KBoolean Kotlin_Debugging_isLocal(KRef obj) { + return obj->local(); +} + RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeededFromKotlin() { switch (CurrentMemoryModel) { case MemoryModel::kExperimental: diff --git a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Debugging.kt b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Debugging.kt index 4f6d501cb73..cbce0d9b0d6 100644 --- a/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Debugging.kt +++ b/kotlin-native/runtime/src/main/kotlin/kotlin/native/internal/Debugging.kt @@ -20,6 +20,10 @@ public object Debugging { @InternalForKotlinNative public external fun Any.isPermanent() : Boolean +@GCUnsafeCall("Kotlin_Debugging_isLocal") +@InternalForKotlinNative +public external fun Any.isLocal() : Boolean + @GCUnsafeCall("Kotlin_Debugging_getForceCheckedShutdown") private external fun Debugging_getForceCheckedShutdown(): Boolean