tvm-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [incubator-tvm] binarybana commented on a change in pull request #5328: [Rust][Runtime] Add basic object system support.
Date Mon, 20 Apr 2020 03:23:35 GMT

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



##########
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:
       My understanding was that for both Rust and C++, their atomic int types are laid out
in memory identical to their non atomic counterparts, but I guess this is not the same as
guaranteeing ABI compatibility...




----------------------------------------------------------------
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



Mime
View raw message