From 1197b8453f255ba2c05f186de627b292b65265bd Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Mon, 5 Dec 2016 14:01:24 +0300 Subject: [PATCH] Create C++ static initializer for use in global objects. (#115) --- runtime/src/launcher/cpp/launcher.cpp | 4 ++-- runtime/src/main/cpp/Exceptions.cpp | 2 +- runtime/src/main/cpp/Memory.cpp | 32 ++++++++++++++++++++++++++- runtime/src/main/cpp/Memory.h | 6 ++++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/runtime/src/launcher/cpp/launcher.cpp b/runtime/src/launcher/cpp/launcher.cpp index f94039f1084..4a5dba16add 100644 --- a/runtime/src/launcher/cpp/launcher.cpp +++ b/runtime/src/launcher/cpp/launcher.cpp @@ -9,7 +9,8 @@ ArrayHeader* setupArgs(int argc, char** argv) { ArrayHeader* args = AllocArrayInstance(theArrayTypeInfo, SCOPE_GLOBAL, argc-1); for (int i = 0; i < argc-1; i++) { - Kotlin_Array_set(args, i, AllocStringInstance( argv[i+1], strlen(argv[i+1]) )); + Kotlin_Array_set(args, i, AllocStringInstance( + SCOPE_GLOBAL, argv[i+1], strlen(argv[i+1]) )); } return args; @@ -27,4 +28,3 @@ int main(int argc, char** argv) { // Yes, we have to follow Java convention and return zero. return 0; } - diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index 752ec13f447..f972fec81b0 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -36,7 +36,7 @@ class AutoFree { // TODO: this method ignores the encoding KString CreateKotlinStringFromCString(const char* str) { - return AllocStringInstance(str, strlen(str)); + return AllocStringInstance(SCOPE_GLOBAL, str, strlen(str)); } #ifdef __cplusplus diff --git a/runtime/src/main/cpp/Memory.cpp b/runtime/src/main/cpp/Memory.cpp index 2c90ad9bd45..9bfe0894921 100644 --- a/runtime/src/main/cpp/Memory.cpp +++ b/runtime/src/main/cpp/Memory.cpp @@ -89,7 +89,8 @@ ArrayHeader* AllocArrayInstance( return ArrayContainer(type_info, elements).GetPlace(); } -ArrayHeader* AllocStringInstance(const char* data, uint32_t length) { +ArrayHeader* AllocStringInstance( + PlacementHint hint, const char* data, uint32_t length) { ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace(); memcpy( ByteArrayAddressOfElementAt(result, 0), @@ -97,6 +98,35 @@ ArrayHeader* AllocStringInstance(const char* data, uint32_t length) { length); return result; } + +ObjHeader* InitInstance( + ObjHeader** location, const TypeInfo* type_info, PlacementHint hint, + void (*ctor)(ObjHeader*)) { + ObjHeader* sentinel = reinterpret_cast(1); + ObjHeader* value; + // Wait until other initializers. + while ((value = __sync_val_compare_and_swap( + location, nullptr, sentinel)) == sentinel) { + // TODO: consider yielding. + } + + if (value != nullptr) { + // OK'ish, inited by someone else. + return value; + } + + ObjHeader* instance = AllocInstance(type_info, hint); + try { + ctor(instance); + __sync_val_compare_and_swap(location, sentinel, instance); + return instance; + } catch (...) { + Release(instance->container()); + __sync_val_compare_and_swap(location, sentinel, nullptr); + return nullptr; + } +} + #ifdef __cplusplus } #endif diff --git a/runtime/src/main/cpp/Memory.h b/runtime/src/main/cpp/Memory.h index f45b8f38379..fb52d9c0ac2 100644 --- a/runtime/src/main/cpp/Memory.h +++ b/runtime/src/main/cpp/Memory.h @@ -254,7 +254,11 @@ void InitMemory(); ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint); ArrayHeader* AllocArrayInstance( const TypeInfo* type_info, PlacementHint hint, uint32_t elements); -ArrayHeader* AllocStringInstance(const char* data, uint32_t length); +ArrayHeader* AllocStringInstance(PlacementHint hint, + const char* data, uint32_t length); +ObjHeader* InitInstance( + ObjHeader** location, const TypeInfo* type_info, PlacementHint hint, + void (*ctor)(ObjHeader*)); #ifdef __cplusplus }