Native: switch to "Native" thread state for some Obj-C runtime calls

A lot of calls to Objective-C runtime are potentially blocking. This
commit adds a number of thread state switches to ensure these Obj-C
runtime calls happen in "Native" thread state.

Also, remove a bunch of such functions from CallsChecker exclude list.
This commit is contained in:
Svyatoslav Scherbina
2022-07-27 12:14:48 +02:00
committed by Space
parent 2e8c25aeff
commit ad1b10cdb0
4 changed files with 15 additions and 14 deletions
@@ -135,6 +135,9 @@ void DisposeCString(char* cstring) {
} }
ObjHeader* CreatePermanentStringFromCString(const char* nullTerminatedUTF8) { ObjHeader* CreatePermanentStringFromCString(const char* nullTerminatedUTF8) {
// Note: this function can be called in "Native" thread state. But this is fine:
// while it indeed manipulates Kotlin objects, it doesn't in fact access _Kotlin heap_,
// because the accessed object is off-heap, imitating permanent static objects.
const char* end = nullTerminatedUTF8 + strlen(nullTerminatedUTF8); const char* end = nullTerminatedUTF8 + strlen(nullTerminatedUTF8);
size_t count = utf8::with_replacement::utf16_length(nullTerminatedUTF8, end); size_t count = utf8::with_replacement::utf16_length(nullTerminatedUTF8, end);
size_t headerSize = alignUp(sizeof(ArrayHeader), alignof(char16_t)); size_t headerSize = alignUp(sizeof(ArrayHeader), alignof(char16_t));
@@ -121,6 +121,8 @@ extern "C" const TypeInfo* Kotlin_ObjCExport_getAssociatedTypeInfo(Class clazz)
} }
static void setAssociatedTypeInfo(Class clazz, const TypeInfo* typeInfo) { static void setAssociatedTypeInfo(Class clazz, const TypeInfo* typeInfo) {
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
// Note: [NSValue valueWithPointer:] uses autorelease (without possibility to eliminate this at the call site), // Note: [NSValue valueWithPointer:] uses autorelease (without possibility to eliminate this at the call site),
// so using alloc-init sequence to avoid this. // so using alloc-init sequence to avoid this.
NSValue* value = [[NSValue alloc] initWithBytes:&typeInfo objCType:@encode(void*)]; NSValue* value = [[NSValue alloc] initWithBytes:&typeInfo objCType:@encode(void*)];
@@ -315,6 +317,8 @@ extern "C" void Kotlin_ObjCExport_initializeClass(Class clazz) {
return; return;
} }
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
const TypeInfo* typeInfo = typeAdapter->kotlinTypeInfo; const TypeInfo* typeInfo = typeAdapter->kotlinTypeInfo;
bool isClassForPackage = typeInfo == nullptr; bool isClassForPackage = typeInfo == nullptr;
if (!isClassForPackage) { if (!isClassForPackage) {
@@ -379,6 +383,8 @@ static void Kotlin_ObjCExport_initializeImpl() {
RuntimeCheck(Kotlin_ObjCExport_toKotlinSelector != nullptr, "unexpected initialization order"); RuntimeCheck(Kotlin_ObjCExport_toKotlinSelector != nullptr, "unexpected initialization order");
RuntimeCheck(Kotlin_ObjCExport_releaseAsAssociatedObjectSelector != nullptr, "unexpected initialization order"); RuntimeCheck(Kotlin_ObjCExport_releaseAsAssociatedObjectSelector != nullptr, "unexpected initialization order");
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
initTypeAdapters(); initTypeAdapters();
SEL toKotlinSelector = Kotlin_ObjCExport_toKotlinSelector; SEL toKotlinSelector = Kotlin_ObjCExport_toKotlinSelector;
@@ -865,6 +871,8 @@ static void throwIfCantBeOverridden(Class clazz, const KotlinToObjCMethodAdapter
} }
static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, const TypeInfo* fieldsInfo) { static const TypeInfo* createTypeInfo(Class clazz, const TypeInfo* superType, const TypeInfo* fieldsInfo) {
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
std_support::unordered_set<SEL> definedSelectors; std_support::unordered_set<SEL> definedSelectors;
addDefinedSelectors(clazz, definedSelectors); addDefinedSelectors(clazz, definedSelectors);
@@ -1053,6 +1061,8 @@ static void addVirtualAdapters(Class clazz, const ObjCTypeAdapter* typeAdapter)
static Class createClass(const TypeInfo* typeInfo, Class superClass) { static Class createClass(const TypeInfo* typeInfo, Class superClass) {
RuntimeAssert(typeInfo->superType_ != nullptr, ""); RuntimeAssert(typeInfo->superType_ != nullptr, "");
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
int classIndex = (anonymousClassNextId++); int classIndex = (anonymousClassNextId++);
std_support::string className = Kotlin_ObjCInterop_getUniquePrefix(); std_support::string className = Kotlin_ObjCInterop_getUniquePrefix();
className += "_kobjcc"; className += "_kobjcc";
@@ -298,6 +298,8 @@ void* CreateKotlinObjCClass(const KotlinObjCClassInfo* info) {
return createdClass; return createdClass;
} }
kotlin::NativeOrUnregisteredThreadGuard threadStateGuard(/* reentrant = */ true);
Class newClass = allocateClass(info); Class newClass = allocateClass(info);
RuntimeAssert(newClass != nullptr, "Failed to allocate Objective-C class"); RuntimeAssert(newClass != nullptr, "Failed to allocate Objective-C class");
@@ -189,14 +189,6 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = {
"CFStringGetCharacters", "CFStringGetCharacters",
"CFStringGetLength", "CFStringGetLength",
"_Block_object_assign", "_Block_object_assign",
"class_addIvar",
"class_addMethod",
"class_addProtocol",
"class_copyMethodList",
"class_copyProtocolList",
"class_getClassMethod",
"class_getInstanceMethod",
"class_getInstanceVariable",
"class_getName", "class_getName",
"class_getSuperclass", "class_getSuperclass",
"class_isMetaClass", "class_isMetaClass",
@@ -205,7 +197,6 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = {
"method_getTypeEncoding", "method_getTypeEncoding",
"objc_alloc", "objc_alloc",
"objc_alloc_init", "objc_alloc_init",
"objc_allocateClassPair",
"objc_autorelease", "objc_autorelease",
"objc_autoreleasePoolPush", "objc_autoreleasePoolPush",
"objc_autoreleaseReturnValue", "objc_autoreleaseReturnValue",
@@ -213,18 +204,13 @@ extern "C" const char* Kotlin_callsCheckerGoodFunctionNames[] = {
"objc_getClass", "objc_getClass",
"objc_getProtocol", "objc_getProtocol",
"objc_lookUpClass", "objc_lookUpClass",
"objc_registerClassPair",
"objc_retain", "objc_retain",
"objc_retainAutoreleaseReturnValue", "objc_retainAutoreleaseReturnValue",
"objc_retainBlock", "objc_retainBlock",
"objc_setAssociatedObject",
"objc_storeWeak", "objc_storeWeak",
"object_getClass", "object_getClass",
"object_isClass", "object_isClass",
"protocol_copyProtocolList",
"protocol_getMethodDescription",
"protocol_getName", "protocol_getName",
"sel_registerName",
"llvm.assume", "llvm.assume",
"llvm.ceil.*", "llvm.ceil.*",