Add a separate compiler switch for runtime asserts
This commit is contained in:
committed by
Space
parent
c3515cc338
commit
48a2b23b3a
@@ -321,6 +321,15 @@ class K2Native : CLICompiler<K2NativeCompilerArguments>() {
|
||||
true
|
||||
}
|
||||
})
|
||||
put(RUNTIME_ASSERTS_MODE, when (arguments.runtimeAssertsMode) {
|
||||
"ignore" -> RuntimeAssertsMode.IGNORE
|
||||
"log" -> RuntimeAssertsMode.LOG
|
||||
"panic" -> RuntimeAssertsMode.PANIC
|
||||
else -> {
|
||||
configuration.report(ERROR, "Unsupported runtime asserts mode ${arguments.runtimeAssertsMode}")
|
||||
RuntimeAssertsMode.IGNORE
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -321,6 +321,9 @@ class K2NativeCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var checkLldCompatibility: String? = null
|
||||
|
||||
@Argument(value="-Xruntime-asserts-mode", valueDescription = "<mode>", description = "Enable asserts in runtime. Possible values: 'ignore', 'log', 'panic'")
|
||||
var runtimeAssertsMode: String? = "ignore"
|
||||
|
||||
override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> =
|
||||
super.configureAnalysisFlags(collector, languageVersion).also {
|
||||
val useExperimental = it[AnalysisFlags.useExperimental] as List<*>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
// Must match `DestroyRuntimeMode` in Runtime.h
|
||||
// Must match `DestroyRuntimeMode` in CompilerConstants.hpp
|
||||
enum class DestroyRuntimeMode(val value: Int) {
|
||||
LEGACY(0),
|
||||
ON_SHUTDOWN(1),
|
||||
|
||||
+1
@@ -49,6 +49,7 @@ class KonanConfig(val project: Project, val configuration: CompilerConfiguration
|
||||
val destroyRuntimeMode: DestroyRuntimeMode get() = configuration.get(KonanConfigKeys.DESTROY_RUNTIME_MODE)!!
|
||||
val gc: GC get() = configuration.get(KonanConfigKeys.GARBAGE_COLLECTOR)!!
|
||||
val gcAggressive: Boolean get() = configuration.get(KonanConfigKeys.GARBAGE_COLLECTOR_AGRESSIVE)!!
|
||||
val runtimeAssertsMode: RuntimeAssertsMode get() = configuration.get(KonanConfigKeys.RUNTIME_ASSERTS_MODE)!!
|
||||
|
||||
val needVerifyIr: Boolean
|
||||
get() = configuration.get(KonanConfigKeys.VERIFY_IR) == true
|
||||
|
||||
+1
@@ -159,6 +159,7 @@ class KonanConfigKeys {
|
||||
val GARBAGE_COLLECTOR: CompilerConfigurationKey<GC> = CompilerConfigurationKey.create("gc")
|
||||
val GARBAGE_COLLECTOR_AGRESSIVE: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create("turn on agressive GC mode")
|
||||
val CHECK_LLD_COMPATIBILITY: CompilerConfigurationKey<Boolean> = CompilerConfigurationKey.create("check compatibility with LLD")
|
||||
val RUNTIME_ASSERTS_MODE: CompilerConfigurationKey<RuntimeAssertsMode> = CompilerConfigurationKey.create("enable runtime asserts")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.backend.konan
|
||||
|
||||
// Must match `RuntimeAssertsMode` in CompilerConstants.hpp
|
||||
enum class RuntimeAssertsMode(val value: Int) {
|
||||
IGNORE(0),
|
||||
LOG(1),
|
||||
PANIC(2),
|
||||
}
|
||||
+16
-9
@@ -358,7 +358,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
codegen.objCDataGenerator?.finishModule()
|
||||
|
||||
context.coverage.writeRegionInfo()
|
||||
appendDebugSelector()
|
||||
setRuntimeConstGlobals()
|
||||
overrideRuntimeGlobals()
|
||||
appendLlvmUsed("llvm.used", context.llvm.usedFunctions + context.llvm.usedGlobals)
|
||||
appendLlvmUsed("llvm.compiler.used", context.llvm.compilerUsedGlobals)
|
||||
@@ -2417,16 +2417,23 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
LLVMSetSection(llvmUsedGlobal.llvmGlobal, "llvm.metadata")
|
||||
}
|
||||
|
||||
// TODO: Consider migrating `KonanNeedDebugInfo` to the `overrideRuntimeGlobal` mechanism from below.
|
||||
private fun appendDebugSelector() {
|
||||
if (!context.producedLlvmModuleContainsStdlib) return
|
||||
val llvmDebugSelector =
|
||||
context.llvm.staticData.placeGlobal("KonanNeedDebugInfo",
|
||||
Int32(if (context.shouldContainDebugInfo()) 1 else 0))
|
||||
llvmDebugSelector.setConstant(true)
|
||||
llvmDebugSelector.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
// Globals set this way will be const, but can only be built into runtime-containing module. Which
|
||||
// means they are set at stdlib-cache compilation time.
|
||||
private fun setRuntimeConstGlobal(name: String, value: ConstValue) {
|
||||
val global = context.llvm.staticData.placeGlobal(name, value)
|
||||
global.setConstant(true)
|
||||
global.setLinkage(LLVMLinkage.LLVMExternalLinkage)
|
||||
}
|
||||
|
||||
private fun setRuntimeConstGlobals() {
|
||||
if (!context.producedLlvmModuleContainsStdlib)
|
||||
return
|
||||
|
||||
setRuntimeConstGlobal("KonanNeedDebugInfo", Int32(if (context.shouldContainDebugInfo()) 1 else 0))
|
||||
setRuntimeConstGlobal("Kotlin_runtimeAssertsMode", Int32(context.config.runtimeAssertsMode.value))
|
||||
}
|
||||
|
||||
// Globals set this way cannot be const, but are overridable when producing final executable.
|
||||
private fun overrideRuntimeGlobal(name: String, value: ConstValue) {
|
||||
// TODO: A similar mechanism is used in `ObjCExportCodeGenerator`. Consider merging them.
|
||||
if (context.llvmModuleSpecification.importsKotlinDeclarationsFromOtherSharedLibraries()) {
|
||||
|
||||
@@ -117,6 +117,17 @@ if (ext.isExperimentalMM) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: It also makes sense to test -g without asserts, and also to test -opt with asserts.
|
||||
if (project.globalTestArgs.contains("-g")) {
|
||||
tasks.withType(KonanCompileNativeBinary.class).configureEach {
|
||||
extraOpts "-Xruntime-asserts-mode=panic"
|
||||
}
|
||||
|
||||
tasks.withType(RunExternalTestGroup.class).configureEach {
|
||||
flags = (flags ?: []) + "-Xruntime-asserts-mode=panic"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
// Root directories for test output (logs, compiled files, statistics etc). Only single path must be in each set.
|
||||
// backend.native/tests
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "SameThreadMarkAndSweep.hpp"
|
||||
|
||||
#include "CompilerConstants.hpp"
|
||||
#include "GlobalData.hpp"
|
||||
#include "MarkAndSweepUtils.hpp"
|
||||
#include "Memory.h"
|
||||
@@ -111,7 +112,7 @@ void gc::SameThreadMarkAndSweep::ThreadData::SafePointRegular(size_t weight) noe
|
||||
}
|
||||
|
||||
gc::SameThreadMarkAndSweep::SameThreadMarkAndSweep() noexcept {
|
||||
if (Kotlin_getGcAggressive()) {
|
||||
if (compiler::gcAggressive()) {
|
||||
// TODO: Make it even more aggressive and run on a subset of backend.native tests.
|
||||
threshold_ = 1000;
|
||||
allocationThresholdBytes_ = 10000;
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "KAssert.h"
|
||||
#include "Atomic.h"
|
||||
#include "Cleaner.h"
|
||||
#include "CompilerConstants.hpp"
|
||||
#if USE_CYCLIC_GC
|
||||
#include "CyclicCollector.h"
|
||||
#endif // USE_CYCLIC_GC
|
||||
@@ -220,7 +221,7 @@ class CycleDetector : private kotlin::Pinned, public KonanAllocatorAware {
|
||||
}
|
||||
|
||||
static bool canBeACandidate(KRef object) {
|
||||
return KonanNeedDebugInfo &&
|
||||
return kotlin::compiler::shouldContainDebugInfo() &&
|
||||
Kotlin_memoryLeakCheckerEnabled() &&
|
||||
(object->type_info()->flags_ & TF_LEAK_DETECTOR_CANDIDATE) != 0;
|
||||
}
|
||||
@@ -2044,11 +2045,11 @@ MemoryState* initMemory(bool firstRuntime) {
|
||||
memoryState->tls.Init();
|
||||
memoryState->foreignRefManager = ForeignRefManager::create();
|
||||
bool firstMemoryState = atomicAdd(&aliveMemoryStatesCount, 1) == 1;
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
firstRuntime = firstMemoryState;
|
||||
break;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
@@ -2066,11 +2067,11 @@ void deinitMemory(MemoryState* memoryState, bool destroyRuntime) {
|
||||
atomicAdd(&pendingDeinit, 1);
|
||||
#if USE_GC
|
||||
bool lastMemoryState = atomicAdd(&aliveMemoryStatesCount, -1) == 0;
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
destroyRuntime = lastMemoryState;
|
||||
break;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
@@ -3557,7 +3558,7 @@ KBoolean Kotlin_native_internal_GC_getTuneThreshold(KRef) {
|
||||
|
||||
OBJ_GETTER(Kotlin_native_internal_GC_detectCycles, KRef) {
|
||||
#if USE_CYCLE_DETECTOR
|
||||
if (!KonanNeedDebugInfo && !Kotlin_memoryLeakCheckerEnabled()) RETURN_OBJ(nullptr);
|
||||
if (!kotlin::compiler::shouldContainDebugInfo() && !Kotlin_memoryLeakCheckerEnabled()) RETURN_OBJ(nullptr);
|
||||
RETURN_RESULT_OF0(detectCyclicReferences);
|
||||
#else
|
||||
RETURN_OBJ(nullptr);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "CompilerConstants.hpp"
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
// These are defined by overrideRuntimeGlobals in IrToBitcode.kt
|
||||
RUNTIME_WEAK int32_t Kotlin_destroyRuntimeMode = 1;
|
||||
RUNTIME_WEAK int32_t Kotiln_gcAggressive = 0;
|
||||
|
||||
ALWAYS_INLINE compiler::DestroyRuntimeMode compiler::destroyRuntimeMode() noexcept {
|
||||
return static_cast<compiler::DestroyRuntimeMode>(Kotlin_destroyRuntimeMode);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool compiler::gcAggressive() noexcept {
|
||||
return Kotiln_gcAggressive != 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RUNTIME_COMPILER_CONSTANTS_H
|
||||
#define RUNTIME_COMPILER_CONSTANTS_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// Prefer to use getter functions below. These constants are exposed to simplify the job of the inliner.
|
||||
|
||||
// These are defined by setRuntimeConstGlobals in IrToBitcode.kt
|
||||
extern "C" const int32_t KonanNeedDebugInfo;
|
||||
extern "C" const int32_t Kotlin_runtimeAssertsMode;
|
||||
|
||||
namespace kotlin {
|
||||
namespace compiler {
|
||||
|
||||
// Must match DestroyRuntimeMode in DestroyRuntimeMode.kt
|
||||
enum class DestroyRuntimeMode : int32_t {
|
||||
kLegacy = 0,
|
||||
kOnShutdown = 1,
|
||||
};
|
||||
|
||||
// Must match RuntimeAssertsMode in RuntimeAssertsMode.kt
|
||||
enum class RuntimeAssertsMode : int32_t {
|
||||
kIgnore = 0,
|
||||
kLog = 1,
|
||||
kPanic = 2,
|
||||
};
|
||||
|
||||
DestroyRuntimeMode destroyRuntimeMode() noexcept;
|
||||
|
||||
bool gcAggressive() noexcept;
|
||||
|
||||
ALWAYS_INLINE inline bool shouldContainDebugInfo() noexcept {
|
||||
return KonanNeedDebugInfo != 0;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE inline RuntimeAssertsMode runtimeAssertsMode() noexcept {
|
||||
return static_cast<RuntimeAssertsMode>(Kotlin_runtimeAssertsMode);
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace kotlin
|
||||
|
||||
#endif // RUNTIME_COMPILER_CONSTANTS_H
|
||||
@@ -8,14 +8,14 @@
|
||||
#include "Porting.h"
|
||||
#include "StackTrace.hpp"
|
||||
|
||||
using namespace kotlin;
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO: Enable stacktraces for asserts when stacktrace printing is more mature.
|
||||
inline constexpr bool kEnableStacktraces = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* format, ...) {
|
||||
void PrintAssert(const char* location, const char* format, std::va_list args) noexcept {
|
||||
char buf[1024];
|
||||
int written = -1;
|
||||
|
||||
@@ -28,10 +28,7 @@ RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* form
|
||||
|
||||
// Write the message.
|
||||
if (written >= 0 && static_cast<size_t>(written) < sizeof(buf)) {
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
konan::vsnprintf(buf + written, sizeof(buf) - written, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
konan::consoleErrorUtf8(buf, konan::strnlen(buf, sizeof(buf)));
|
||||
@@ -39,18 +36,21 @@ RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* form
|
||||
if constexpr (kEnableStacktraces) {
|
||||
kotlin::PrintStackTraceStderr();
|
||||
}
|
||||
konan::abort();
|
||||
}
|
||||
|
||||
// TODO: this function is not used by runtime, but apparently there are
|
||||
// third-party libraries that use it (despite the fact it is not a public API).
|
||||
// Keeping the function here for now for backward compatibility, to be removed later.
|
||||
RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* message) {
|
||||
char buf[1024];
|
||||
if (location != nullptr)
|
||||
konan::snprintf(buf, sizeof(buf), "%s: runtime assert: %s\n", location, message);
|
||||
else
|
||||
konan::snprintf(buf, sizeof(buf), "runtime assert: %s\n", message);
|
||||
konan::consoleErrorUtf8(buf, konan::strnlen(buf, sizeof(buf)));
|
||||
konan::abort();
|
||||
} // namespace
|
||||
|
||||
void internal::RuntimeAssertFailedLog(const char* location, const char* format, ...) {
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
PrintAssert(location, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
RUNTIME_NORETURN void internal::RuntimeAssertFailedPanic(const char* location, const char* format, ...) {
|
||||
std::va_list args;
|
||||
va_start(args, format);
|
||||
PrintAssert(location, format, args);
|
||||
va_end(args);
|
||||
konan::abort();
|
||||
}
|
||||
|
||||
@@ -18,73 +18,69 @@
|
||||
#define RUNTIME_ASSERT_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// To avoid cluttering optimized code with asserts, they could be turned off.
|
||||
#define KONAN_ENABLE_ASSERT 1
|
||||
#include "CompilerConstants.hpp"
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
#if KONAN_ENABLE_ASSERT
|
||||
#define CURRENT_SOURCE_LOCATION __FILE__ ":" TOSTRING(__LINE__)
|
||||
#else
|
||||
// Do not generate location strings, when asserts are disabled to reduce code size.
|
||||
#define CURRENT_SOURCE_LOCATION nullptr
|
||||
#endif
|
||||
|
||||
RUNTIME_NORETURN void RuntimeAssertFailed(const char* location, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
namespace kotlin {
|
||||
namespace internal {
|
||||
|
||||
void RuntimeAssertFailedLog(const char* location, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
RUNTIME_NORETURN void RuntimeAssertFailedPanic(const char* location, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
inline RUNTIME_NORETURN void TODOImpl(const char* location) {
|
||||
RuntimeAssertFailed(location, "Unimplemented");
|
||||
RuntimeAssertFailedPanic(location, "Unimplemented");
|
||||
}
|
||||
|
||||
// TODO: Support format string when `RuntimeAssertFailed` supports it.
|
||||
inline RUNTIME_NORETURN void TODOImpl(const char* location, const char* message) {
|
||||
RuntimeAssertFailed(location, "%s", message);
|
||||
RuntimeAssertFailedPanic(location, "%s", message);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace kotlin
|
||||
|
||||
// During codegeneration we set this constant to 1 or 0 to allow bitcode optimizer
|
||||
// to get rid of code behind condition.
|
||||
extern "C" const int KonanNeedDebugInfo;
|
||||
|
||||
#if KONAN_ENABLE_ASSERT
|
||||
// Use RuntimeAssert() in internal state checks, which could be ignored in production.
|
||||
#define RuntimeAssert(condition, format, ...) \
|
||||
do { \
|
||||
if (KonanNeedDebugInfo && (!(condition))) { \
|
||||
RuntimeAssertFailed(CURRENT_SOURCE_LOCATION, format, ##__VA_ARGS__); \
|
||||
switch (::kotlin::compiler::runtimeAssertsMode()) { \
|
||||
case ::kotlin::compiler::RuntimeAssertsMode::kIgnore: break; \
|
||||
case ::kotlin::compiler::RuntimeAssertsMode::kLog: \
|
||||
if (!(condition)) { \
|
||||
::kotlin::internal::RuntimeAssertFailedLog(CURRENT_SOURCE_LOCATION, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
break; \
|
||||
case ::kotlin::compiler::RuntimeAssertsMode::kPanic: \
|
||||
if (!(condition)) { \
|
||||
::kotlin::internal::RuntimeAssertFailedPanic(CURRENT_SOURCE_LOCATION, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} while (false)
|
||||
#else
|
||||
#define RuntimeAssert(condition, format, ...) \
|
||||
do { \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
// Use RuntimeCheck() in runtime checks that could fail due to external condition and shall lead
|
||||
// to program termination. Never compiled out.
|
||||
// TODO: Consider using `CURRENT_SOURCE_LOCATION` when `KonanNeedDebugInfo` is `true`.
|
||||
// TODO: Consider using `CURRENT_SOURCE_LOCATION` when `kotlin::compiler::runtimeAssertsMode()` is not `kIgnore`.
|
||||
#define RuntimeCheck(condition, format, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
RuntimeAssertFailed(nullptr, format, ##__VA_ARGS__); \
|
||||
::kotlin::internal::RuntimeAssertFailedPanic(nullptr, format, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
#define TODO(...) \
|
||||
do { \
|
||||
::internal::TODOImpl(CURRENT_SOURCE_LOCATION, ##__VA_ARGS__); \
|
||||
::kotlin::internal::TODOImpl(CURRENT_SOURCE_LOCATION, ##__VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
// Use RuntimeFail() to unconditionally fail, signifying compiler/runtime bug.
|
||||
// TODO: Consider using `CURRENT_SOURCE_LOCATION` when `KonanNeedDebugInfo` is `true`.
|
||||
// TODO: Consider using `CURRENT_SOURCE_LOCATION` when `kotlin::compiler::runtimeAssertsMode()` is not `kIgnore`.
|
||||
#define RuntimeFail(format, ...) \
|
||||
do { \
|
||||
RuntimeAssertFailed(nullptr, format, ##__VA_ARGS__); \
|
||||
::kotlin::internal::RuntimeAssertFailedPanic(nullptr, format, ##__VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
#endif // RUNTIME_ASSERT_H
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <chrono>
|
||||
|
||||
#include "Common.h"
|
||||
#include "CompilerConstants.hpp"
|
||||
#include "Porting.h"
|
||||
#include "KAssert.h"
|
||||
|
||||
@@ -105,13 +106,13 @@ int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) {
|
||||
if (::ReadConsoleW(stdInHandle, buffer, bufferLength, &bufferRead, NULL)) {
|
||||
length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8,
|
||||
maxSizeBytes - 1, NULL, NULL);
|
||||
if (!length && KonanNeedDebugInfo) {
|
||||
if (!length && kotlin::compiler::shouldContainDebugInfo()) {
|
||||
char msg[512];
|
||||
auto errCode = getLastErrorMessage(msg, sizeof(msg));
|
||||
consoleErrorf("UTF-16 to UTF-8 conversion error %d: %s", errCode, msg);
|
||||
}
|
||||
((char*) utf8)[length] = 0;
|
||||
} else if (KonanNeedDebugInfo) {
|
||||
} else if (kotlin::compiler::shouldContainDebugInfo()) {
|
||||
char msg[512];
|
||||
auto errCode = getLastErrorMessage(msg, sizeof(msg));
|
||||
consoleErrorf("Console read failure: %d %s", errCode, msg);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Alloc.h"
|
||||
#include "Atomic.h"
|
||||
#include "Cleaner.h"
|
||||
#include "CompilerConstants.hpp"
|
||||
#include "Exceptions.h"
|
||||
#include "KAssert.h"
|
||||
#include "Memory.h"
|
||||
@@ -31,18 +32,6 @@ struct InitNode {
|
||||
InitNode* next;
|
||||
};
|
||||
|
||||
// These globals are overriden by the compiler.
|
||||
RUNTIME_WEAK DestroyRuntimeMode Kotlin_destroyRuntimeMode = DESTROY_RUNTIME_ON_SHUTDOWN;
|
||||
RUNTIME_WEAK KInt Kotlin_gcAggressive = 0;
|
||||
|
||||
DestroyRuntimeMode Kotlin_getDestroyRuntimeMode() {
|
||||
return Kotlin_destroyRuntimeMode;
|
||||
}
|
||||
|
||||
bool Kotlin_getGcAggressive() {
|
||||
return Kotlin_gcAggressive != 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
InitNode* initHeadNode = nullptr;
|
||||
@@ -108,8 +97,8 @@ RuntimeState* initRuntime() {
|
||||
bool firstRuntime = false;
|
||||
// We set this guard in the `switch` below, after memory initialization.
|
||||
kotlin::ThreadStateGuard stateGuard;
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
compareAndSwap(&globalRuntimeStatus, kGlobalRuntimeUninitialized, kGlobalRuntimeRunning);
|
||||
result->memoryState = InitMemory(false); // The argument will be ignored for legacy DestroyRuntimeMode
|
||||
// Switch thread state because worker and globals inits require the runnable state.
|
||||
@@ -122,7 +111,7 @@ RuntimeState* initRuntime() {
|
||||
konan::abort();
|
||||
}
|
||||
break;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
// First update `aliveRuntimesCount` and then update `globalRuntimeStatus`, for synchronization with
|
||||
// runtime shutdown, which does it the other way around.
|
||||
atomicAdd(&aliveRuntimesCount, 1);
|
||||
@@ -168,11 +157,11 @@ void deinitRuntime(RuntimeState* state, bool destroyRuntime) {
|
||||
::runtimeState = state;
|
||||
RestoreMemory(state->memoryState);
|
||||
bool lastRuntime = atomicAdd(&aliveRuntimesCount, -1) == 0;
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
destroyRuntime = lastRuntime;
|
||||
break;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
@@ -234,11 +223,11 @@ void Kotlin_shutdownRuntime() {
|
||||
RuntimeAssert(runtime != kInvalidRuntime, "Current thread must have Kotlin runtime initialized on it");
|
||||
|
||||
bool needsFullShutdown = false;
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
needsFullShutdown = true;
|
||||
break;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
needsFullShutdown = Kotlin_forceCheckedShutdown() || Kotlin_memoryLeakCheckerEnabled() || Kotlin_cleanersLeakCheckerEnabled();
|
||||
break;
|
||||
}
|
||||
@@ -349,7 +338,7 @@ KInt Konan_Platform_getMemoryModel() {
|
||||
}
|
||||
|
||||
KBoolean Konan_Platform_isDebugBinary() {
|
||||
return KonanNeedDebugInfo ? true : false;
|
||||
return kotlin::compiler::shouldContainDebugInfo();
|
||||
}
|
||||
|
||||
bool Kotlin_memoryLeakCheckerEnabled() {
|
||||
@@ -385,11 +374,11 @@ KBoolean Kotlin_Debugging_getForceCheckedShutdown() {
|
||||
}
|
||||
|
||||
void Kotlin_Debugging_setForceCheckedShutdown(KBoolean value) {
|
||||
switch (Kotlin_getDestroyRuntimeMode()) {
|
||||
case DESTROY_RUNTIME_LEGACY:
|
||||
switch (kotlin::compiler::destroyRuntimeMode()) {
|
||||
case kotlin::compiler::DestroyRuntimeMode::kLegacy:
|
||||
// Only applicable to ON_SHUTDOWN modes.
|
||||
return;
|
||||
case DESTROY_RUNTIME_ON_SHUTDOWN:
|
||||
case kotlin::compiler::DestroyRuntimeMode::kOnShutdown:
|
||||
break;
|
||||
}
|
||||
g_forceCheckedShutdown = value;
|
||||
|
||||
@@ -25,15 +25,6 @@ struct InitNode;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Must match DestroyRuntimeMode in DestroyRuntimeMode.kt
|
||||
enum DestroyRuntimeMode {
|
||||
DESTROY_RUNTIME_LEGACY = 0,
|
||||
DESTROY_RUNTIME_ON_SHUTDOWN = 1,
|
||||
};
|
||||
|
||||
DestroyRuntimeMode Kotlin_getDestroyRuntimeMode();
|
||||
bool Kotlin_getGcAggressive();
|
||||
|
||||
// For experimental MM, if runtime gets initialized, it will be in the native state after this.
|
||||
RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeeded();
|
||||
void Kotlin_deinitRuntimeIfNeeded();
|
||||
|
||||
@@ -56,8 +56,8 @@ testing::StrictMock<testing::MockFunction<void(KInt, bool)>>* shutdownCleanerWor
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Set to 1 to enable runtime assertions.
|
||||
extern const int KonanNeedDebugInfo = 1;
|
||||
extern const int32_t KonanNeedDebugInfo = 1;
|
||||
extern const int32_t Kotlin_runtimeAssertsMode = static_cast<int32_t>(kotlin::compiler::RuntimeAssertsMode::kPanic);
|
||||
|
||||
extern const TypeInfo* theAnyTypeInfo = theAnyTypeInfoHolder.typeInfo();
|
||||
extern const TypeInfo* theArrayTypeInfo = theArrayTypeInfoHolder.typeInfo();
|
||||
|
||||
Reference in New Issue
Block a user