KT-65949: Bridge intrinsics
Merge-request: KT-MR-14767 Merged-by: Gleb Lukianets <Gleb.Lukianets@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
7c4c6d2cd9
commit
b46ffc35f1
@@ -605,4 +605,11 @@ RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processObjectInMark(void* s
|
|||||||
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processArrayInMark(void* state, ObjHeader* object);
|
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processArrayInMark(void* state, ObjHeader* object);
|
||||||
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processEmptyObjectInMark(void* state, ObjHeader* object);
|
RUNTIME_NOTHROW ALWAYS_INLINE extern "C" void Kotlin_processEmptyObjectInMark(void* state, ObjHeader* object);
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" OBJ_GETTER(Kotlin_Interop_derefSpecialRef, kotlin::mm::RawSpecialRef *ref);
|
||||||
|
RUNTIME_NOTHROW extern "C" kotlin::mm::RawSpecialRef *Kotlin_Interop_createSpecialRef(ObjHeader *object);
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_disposeSpecialRef(kotlin::mm::RawSpecialRef *ref);
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_retainSpecialRef(kotlin::mm::RawSpecialRef *ref);
|
||||||
|
RUNTIME_NOTHROW extern "C" bool Kotlin_Interop_tryRetainSpecialRef(kotlin::mm::RawSpecialRef *ref);
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_releaseSpecialRef(kotlin::mm::RawSpecialRef *ref);
|
||||||
|
|
||||||
#endif // RUNTIME_MEMORY_H
|
#endif // RUNTIME_MEMORY_H
|
||||||
|
|||||||
@@ -12,6 +12,31 @@ import kotlin.internal.getProgressionLastElement
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.concurrent.AtomicReference
|
import kotlin.concurrent.AtomicReference
|
||||||
import kotlinx.cinterop.*
|
import kotlinx.cinterop.*
|
||||||
|
import kotlinx.cinterop.NativePtr
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_derefSpecialRef")
|
||||||
|
public external fun dereferenceSpecialRef(ref: COpaquePointer?): Any?
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_createSpecialRef")
|
||||||
|
public external fun createSpecialRef(ref: Any?): COpaquePointer?
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_disposeSpecialRef")
|
||||||
|
public external fun disposeSpecialRef(ref: COpaquePointer?)
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_retainSpecialRef")
|
||||||
|
public external fun retainSpecialRef(ref: COpaquePointer?)
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_tryRetainSpecialRef")
|
||||||
|
public external fun tryRetainSpecialRef(ref: COpaquePointer?): Boolean
|
||||||
|
|
||||||
|
@ExperimentalNativeApi
|
||||||
|
@GCUnsafeCall("Kotlin_Interop_releaseSpecialRef")
|
||||||
|
public external fun releaseSpecialRef(ref: COpaquePointer?)
|
||||||
|
|
||||||
@ExportForCppRuntime
|
@ExportForCppRuntime
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
|
|||||||
@@ -14,11 +14,13 @@
|
|||||||
#include "GlobalsRegistry.hpp"
|
#include "GlobalsRegistry.hpp"
|
||||||
#include "KAssert.h"
|
#include "KAssert.h"
|
||||||
#include "Natives.h"
|
#include "Natives.h"
|
||||||
|
#include "ObjCBackRef.hpp"
|
||||||
#include "ObjectOps.hpp"
|
#include "ObjectOps.hpp"
|
||||||
#include "Porting.h"
|
#include "Porting.h"
|
||||||
#include "ReferenceOps.hpp"
|
#include "ReferenceOps.hpp"
|
||||||
#include "Runtime.h"
|
#include "Runtime.h"
|
||||||
#include "SafePoint.hpp"
|
#include "SafePoint.hpp"
|
||||||
|
#include "SpecialRefRegistry.hpp"
|
||||||
#include "StableRef.hpp"
|
#include "StableRef.hpp"
|
||||||
#include "ThreadData.hpp"
|
#include "ThreadData.hpp"
|
||||||
#include "ThreadRegistry.hpp"
|
#include "ThreadRegistry.hpp"
|
||||||
@@ -664,3 +666,33 @@ void kotlin::initObjectPool() noexcept {
|
|||||||
void kotlin::compactObjectPoolInCurrentThread() noexcept {
|
void kotlin::compactObjectPoolInCurrentThread() noexcept {
|
||||||
alloc::compactObjectPoolInCurrentThread();
|
alloc::compactObjectPoolInCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" OBJ_GETTER(Kotlin_Interop_derefSpecialRef, mm::RawSpecialRef *ref) {
|
||||||
|
RETURN_OBJ(ref ? *mm::ObjCBackRef(ref) : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" mm::RawSpecialRef *Kotlin_Interop_createSpecialRef(ObjHeader *object) {
|
||||||
|
return object ? static_cast<mm::RawSpecialRef *>(mm::ObjCBackRef::create(object)) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_disposeSpecialRef(mm::RawSpecialRef *ref) {
|
||||||
|
if (ref) {
|
||||||
|
mm::ObjCBackRef(ref).dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_retainSpecialRef(mm::RawSpecialRef *ref) {
|
||||||
|
if (ref) {
|
||||||
|
mm::ObjCBackRef(ref).retain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" bool Kotlin_Interop_tryRetainSpecialRef(mm::RawSpecialRef *ref) {
|
||||||
|
return ref ? mm::ObjCBackRef(ref).tryRetain() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RUNTIME_NOTHROW extern "C" void Kotlin_Interop_releaseSpecialRef(mm::RawSpecialRef *ref) {
|
||||||
|
if (ref) {
|
||||||
|
mm::ObjCBackRef(ref).release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uintptr_t get_null();
|
||||||
|
uintptr_t get_singleton_object();
|
||||||
|
uintptr_t get_static_object();
|
||||||
|
uintptr_t get_array();
|
||||||
|
uintptr_t get_local_object();
|
||||||
|
uintptr_t dispose_object(uintptr_t);
|
||||||
|
|
||||||
|
_Bool compare_identities(uintptr_t, uintptr_t);
|
||||||
|
_Bool compare_objects(uintptr_t, uintptr_t);
|
||||||
|
_Bool compare_arrays(uintptr_t, uintptr_t);
|
||||||
|
|
||||||
|
void retain_object(uintptr_t);
|
||||||
|
void release_object(uintptr_t);
|
||||||
|
|
||||||
|
void test(uintptr_t obj1, uintptr_t obj2, _Bool (*comparator)(uintptr_t, uintptr_t), int code) {
|
||||||
|
if (!comparator(obj1, obj2)) {
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_object(obj1);
|
||||||
|
dispose_object(obj2);
|
||||||
|
|
||||||
|
release_object(obj1);
|
||||||
|
dispose_object(obj2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test(get_singleton_object(), get_singleton_object(), compare_identities, -1);
|
||||||
|
test(get_static_object(), get_static_object(), compare_identities, -2);
|
||||||
|
test(get_local_object(), get_local_object(), compare_objects, -3);
|
||||||
|
test(get_null(), get_null(), compare_identities, -4);
|
||||||
|
test(get_array(), get_array(), compare_arrays, -5);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import kotlin.native.internal.ExportedBridge
|
||||||
|
import kotlin.native.internal.*
|
||||||
|
import kotlinx.cinterop.ExperimentalForeignApi
|
||||||
|
import kotlinx.cinterop.COpaquePointer
|
||||||
|
|
||||||
|
data object MyObject
|
||||||
|
const val string = "Hello, world!"
|
||||||
|
data class Data(var data: Unit = Unit)
|
||||||
|
|
||||||
|
@ExportedBridge("get_null")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun getNull(): COpaquePointer? = createSpecialRef(null)
|
||||||
|
|
||||||
|
@ExportedBridge("get_singleton_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun getSingletonObject(): COpaquePointer? = createSpecialRef(MyObject)
|
||||||
|
|
||||||
|
@ExportedBridge("get_static_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun getStaticObject(): COpaquePointer? = createSpecialRef(string)
|
||||||
|
|
||||||
|
@ExportedBridge("get_local_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun getLocalObject(): COpaquePointer? = createSpecialRef(Data())
|
||||||
|
|
||||||
|
@ExportedBridge("get_array")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun getArray(): COpaquePointer? = createSpecialRef(arrayOf(Data(), Data()))
|
||||||
|
|
||||||
|
@ExportedBridge("compare_identities")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun compareIdentities(obj1: COpaquePointer?, obj2: COpaquePointer?): Boolean = dereferenceSpecialRef(obj1) === dereferenceSpecialRef(obj2)
|
||||||
|
|
||||||
|
@ExportedBridge("compare_objects")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun compareObjects(obj1: COpaquePointer?, obj2: COpaquePointer?): Boolean = dereferenceSpecialRef(obj1) == dereferenceSpecialRef(obj2)
|
||||||
|
|
||||||
|
@ExportedBridge("compare_arrays")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun compareArrays(obj1: COpaquePointer?, obj2: COpaquePointer?): Boolean = (dereferenceSpecialRef(obj1) as? Array<Any>) contentEquals (dereferenceSpecialRef(obj2) as? Array<Any>)
|
||||||
|
|
||||||
|
@ExportedBridge("dispose_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun disposeObject(obj: COpaquePointer?): Unit = disposeSpecialRef(obj)
|
||||||
|
|
||||||
|
@ExportedBridge("retain_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun retainObject(ref: COpaquePointer?) = retainSpecialRef(ref)
|
||||||
|
|
||||||
|
@ExportedBridge("release_object")
|
||||||
|
@OptIn(ExperimentalForeignApi::class)
|
||||||
|
fun releaseObject(ref: COpaquePointer?) = releaseSpecialRef(ref)
|
||||||
+6
@@ -27,6 +27,12 @@ public class CExportDynamicInterfaceNoneTestGenerated extends AbstractNativeCExp
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nativeRefs")
|
||||||
|
public void testNativeRefs() {
|
||||||
|
runTest("native/native.tests/testData/CExport/InterfaceNone/nativeRefs/");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("primitiveTypes")
|
@TestMetadata("primitiveTypes")
|
||||||
public void testPrimitiveTypes() {
|
public void testPrimitiveTypes() {
|
||||||
|
|||||||
+6
@@ -27,6 +27,12 @@ public class CExportStaticInterfaceNoneTestGenerated extends AbstractNativeCExpo
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nativeRefs")
|
||||||
|
public void testNativeRefs() {
|
||||||
|
runTest("native/native.tests/testData/CExport/InterfaceNone/nativeRefs/");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("primitiveTypes")
|
@TestMetadata("primitiveTypes")
|
||||||
public void testPrimitiveTypes() {
|
public void testPrimitiveTypes() {
|
||||||
|
|||||||
+6
@@ -31,6 +31,12 @@ public class FirCExportDynamicInterfaceNoneTestGenerated extends AbstractNativeC
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nativeRefs")
|
||||||
|
public void testNativeRefs() {
|
||||||
|
runTest("native/native.tests/testData/CExport/InterfaceNone/nativeRefs/");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("primitiveTypes")
|
@TestMetadata("primitiveTypes")
|
||||||
public void testPrimitiveTypes() {
|
public void testPrimitiveTypes() {
|
||||||
|
|||||||
+6
@@ -31,6 +31,12 @@ public class FirCExportStaticInterfaceNoneTestGenerated extends AbstractNativeCE
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("native/native.tests/testData/CExport/InterfaceNone"), Pattern.compile("^([^_](.+))$"), null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("nativeRefs")
|
||||||
|
public void testNativeRefs() {
|
||||||
|
runTest("native/native.tests/testData/CExport/InterfaceNone/nativeRefs/");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("primitiveTypes")
|
@TestMetadata("primitiveTypes")
|
||||||
public void testPrimitiveTypes() {
|
public void testPrimitiveTypes() {
|
||||||
|
|||||||
Reference in New Issue
Block a user