Call initRuntimeIfNeeded before EnterFrame in interop adapters. (#4672)

This commit is contained in:
Alexander Shabalin
2021-02-02 18:48:54 +03:00
committed by Vasily Levchenko
parent 99dc9e8e0c
commit f312315346
5 changed files with 13 additions and 6 deletions
@@ -361,8 +361,8 @@ private class ExportedElement(val kind: ElementKind,
| |
|extern "C" KObjHeader* ${cname}_instance(KObjHeader**); |extern "C" KObjHeader* ${cname}_instance(KObjHeader**);
|static $objectClassC ${cname}_instance_impl(void) { |static $objectClassC ${cname}_instance_impl(void) {
| KObjHolder result_holder;
| Kotlin_initRuntimeIfNeeded(); | Kotlin_initRuntimeIfNeeded();
| KObjHolder result_holder;
| KObjHeader* result = ${cname}_instance(result_holder.slot()); | KObjHeader* result = ${cname}_instance(result_holder.slot());
| return $objectClassC { .pinned = CreateStablePointer(result)}; | return $objectClassC { .pinned = CreateStablePointer(result)};
|} |}
@@ -379,8 +379,8 @@ private class ExportedElement(val kind: ElementKind,
return """ return """
|extern "C" KObjHeader* $cname(KObjHeader**); |extern "C" KObjHeader* $cname(KObjHeader**);
|static $enumClassC ${cname}_impl(void) { |static $enumClassC ${cname}_impl(void) {
| KObjHolder result_holder;
| Kotlin_initRuntimeIfNeeded(); | Kotlin_initRuntimeIfNeeded();
| KObjHolder result_holder;
| KObjHeader* result = $cname(result_holder.slot()); | KObjHeader* result = $cname(result_holder.slot());
| return $enumClassC { .pinned = CreateStablePointer(result)}; | return $enumClassC { .pinned = CreateStablePointer(result)};
|} |}
@@ -996,8 +996,8 @@ internal class CAdapterGenerator(val context: Context) : DeclarationDescriptorVi
val argument = if (needArgument) "value, " else "" val argument = if (needArgument) "value, " else ""
output("extern \"C\" KObjHeader* Kotlin_box${it.shortNameForPredefinedType}($parameter$maybeComma KObjHeader**);") output("extern \"C\" KObjHeader* Kotlin_box${it.shortNameForPredefinedType}($parameter$maybeComma KObjHeader**);")
output("static ${translateType(nullableIt)} ${it.createNullableNameForPredefinedType}Impl($parameter) {") output("static ${translateType(nullableIt)} ${it.createNullableNameForPredefinedType}Impl($parameter) {")
output("KObjHolder result_holder;", 1)
output("Kotlin_initRuntimeIfNeeded();", 1) output("Kotlin_initRuntimeIfNeeded();", 1)
output("KObjHolder result_holder;", 1)
output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1) output("KObjHeader* result = Kotlin_box${it.shortNameForPredefinedType}($argument result_holder.slot());", 1)
output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1) output("return ${translateType(nullableIt)} { .pinned = CreateStablePointer(result) };", 1)
output("}") output("}")
@@ -341,6 +341,10 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
*/ */
var forwardingForeignExceptionsTerminatedWith: LLVMValueRef? = null var forwardingForeignExceptionsTerminatedWith: LLVMValueRef? = null
// Whether the generating function needs to initialize Kotlin runtime before execution. Useful for interop bridges,
// for example.
var needsRuntimeInit = false
init { init {
irFunction?.let { irFunction?.let {
if (!irFunction.isExported()) { if (!irFunction.isExported()) {
@@ -1207,6 +1211,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
internal fun epilogue() { internal fun epilogue() {
appendingTo(prologueBb) { appendingTo(prologueBb) {
if (needsRuntimeInit) {
call(context.llvm.initRuntimeIfNeeded, emptyList())
}
val slots = if (needSlotsPhi) val slots = if (needSlotsPhi)
LLVMBuildArrayAlloca(builder, kObjHeaderPtr, Int32(slotCount).llvm, "")!! LLVMBuildArrayAlloca(builder, kObjHeaderPtr, Int32(slotCount).llvm, "")!!
else else
@@ -208,7 +208,7 @@ internal class ObjCExportCodeGenerator(
} }
fun FunctionGenerationContext.initRuntimeIfNeeded() { fun FunctionGenerationContext.initRuntimeIfNeeded() {
callFromBridge(context.llvm.initRuntimeIfNeeded, emptyList()) this.needsRuntimeInit = true
} }
inline fun FunctionGenerationContext.convertKotlin( inline fun FunctionGenerationContext.convertKotlin(
@@ -189,7 +189,7 @@ void AppendToInitializersTail(InitNode *next) {
initTailNode = next; initTailNode = next;
} }
void Kotlin_initRuntimeIfNeeded() { RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeeded() {
if (!isValidRuntime()) { if (!isValidRuntime()) {
initRuntime(); initRuntime();
// Register runtime deinit function at thread cleanup. // Register runtime deinit function at thread cleanup.
+1 -1
View File
@@ -33,7 +33,7 @@ enum DestroyRuntimeMode {
DestroyRuntimeMode Kotlin_getDestroyRuntimeMode(); DestroyRuntimeMode Kotlin_getDestroyRuntimeMode();
void Kotlin_initRuntimeIfNeeded(); RUNTIME_NOTHROW void Kotlin_initRuntimeIfNeeded();
void Kotlin_deinitRuntimeIfNeeded(); void Kotlin_deinitRuntimeIfNeeded();
// Can only be called once. // Can only be called once.