You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2020/04/23 03:44:19 UTC

[GitHub] [incubator-tvm] tqchen commented on a change in pull request #5328: [Rust][Runtime] Add basic object system support.

tqchen commented on a change in pull request #5328:
URL: https://github.com/apache/incubator-tvm/pull/5328#discussion_r413486451



##########
File path: rust/tvm-rt/src/object.rs
##########
@@ -0,0 +1,268 @@
+use std::convert::TryFrom;
+use std::convert::TryInto;
+use std::ffi::CString;
+use std::ptr::NonNull;
+use tvm_sys::ffi::{self, TVMObjectFree, TVMObjectRetain, TVMObjectTypeKey2Index};
+use tvm_sys::{TVMArgValue, TVMRetValue};
+
+type Deleter<T> = unsafe extern "C" fn(object: *mut T) -> ();
+
+#[derive(Debug)]
+#[repr(C)]
+pub struct Object {
+    pub type_index: u32,
+    pub ref_count: i32,
+    pub fdeleter: Deleter<Object>,
+}
+
+unsafe extern "C" fn delete<T: IsObject>(object: *mut Object) {
+    let typed_object: *mut T = std::mem::transmute(object);
+    T::typed_delete(typed_object);
+}
+
+fn derived_from(child_type_index: u32, parent_type_index: u32) -> bool {
+    let mut is_derived = 0;
+    crate::check_call!(ffi::TVMObjectDerivedFrom(
+        child_type_index,
+        parent_type_index,
+        &mut is_derived
+    ));
+    if is_derived == 0 {
+        false
+    } else {
+        true
+    }
+}
+
+impl Object {
+    fn new(type_index: u32, deleter: Deleter<Object>) -> Object {
+        Object {
+            type_index,
+            // Note: do not touch this field directly again, this is
+            // a critical section, we write a 1 to the atomic which will now
+            // be managed by the C++ atomics.
+            // In the future we should probably use C-atomcis.
+            ref_count: 1,
+            fdeleter: deleter,
+        }
+    }
+
+    fn get_type_index<T: IsObject>() -> u32 {
+        let type_key = T::TYPE_KEY;
+        let cstring = CString::new(type_key).expect("type key must not contain null characters");
+        if type_key == "Object" {
+            return 0;
+        } else {
+            let mut index = 0;
+            unsafe {
+                let index_ptr = std::mem::transmute(&mut index);
+                if TVMObjectTypeKey2Index(cstring.as_ptr(), index_ptr) != 0 {
+                    panic!(crate::get_last_error())
+                }
+            }
+            return index;
+        }
+    }
+
+    pub fn base_object<T: IsObject>() -> Object {
+        let index = Object::get_type_index::<T>();
+        Object::new(index, delete::<T>)
+    }
+}
+
+pub unsafe trait IsObject {
+    const TYPE_KEY: &'static str;
+
+    fn as_object<'s>(&'s self) -> &'s Object;
+
+    unsafe extern "C" fn typed_delete(object: *mut Self) {
+        // let object = Box::from_raw(object);
+        // drop(object)
+    }
+}
+
+unsafe impl IsObject for Object {
+    const TYPE_KEY: &'static str = "Object";
+
+    fn as_object<'s>(&'s self) -> &'s Object {
+        self
+    }
+}
+
+// unsafe impl<T: IsObject> IsObject for ObjectPtr<T> {
+//     fn as_object<'s>(&'s self) -> &'s Object {
+//         unsafe { self.ptr.as_ref().as_object() }
+//     }
+// }
+
+#[repr(C)]
+pub struct ObjectPtr<T> {
+    ptr: NonNull<T>,
+}
+
+impl ObjectPtr<Object> {
+    fn from_raw(object_ptr: *mut Object) -> Option<ObjectPtr<Object>> {
+        let non_null = NonNull::new(object_ptr);
+        non_null.map(|ptr| ObjectPtr { ptr })
+    }
+}
+
+impl<T> Clone for ObjectPtr<T> {
+    fn clone(&self) -> Self {
+        unsafe {
+            let raw_ptr = std::mem::transmute(self.ptr);
+            assert_eq!(TVMObjectRetain(raw_ptr), 0);
+            ObjectPtr { ptr: self.ptr }
+        }
+    }
+}
+
+impl<T> Drop for ObjectPtr<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let raw_ptr = std::mem::transmute(self.ptr);
+            assert_eq!(TVMObjectFree(raw_ptr), 0)
+        }
+    }
+}
+
+impl<T: IsObject> ObjectPtr<T> {
+    pub fn new(object: T) -> ObjectPtr<T> {
+        let object_ptr = Box::new(object);
+        let ptr = NonNull::from(Box::leak(object_ptr));
+        ObjectPtr { ptr }
+    }
+
+    pub fn count(&self) -> i32 {
+        // need to do atomic read in C++
+        // ABI compatible atomics is funky/hard.

Review comment:
       we might be able to get some guarantees via https://itanium-cxx-abi.github.io/cxx-abi/abi.html




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org