This is an automated email from the ASF dual-hosted git repository.

junrushao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new 9ac3121  [CPP] Remove static line based object reg in favor of 
ObjectDef (#116)
9ac3121 is described below

commit 9ac312164e75c18e7b26214bba1f142de94913b4
Author: Tianqi Chen <[email protected]>
AuthorDate: Tue Oct 14 12:15:22 2025 -0400

    [CPP] Remove static line based object reg in favor of ObjectDef (#116)
    
    This PR moves static inline registrations of objects in the object reg
    macros.
    
    Rationale: while the static inline based registration is convenient and
    removes the need for explicit registration this can cause extra space
    overhead for every dll that includes the header file even if the class
    is not used.
    
    Given that reflection::ObjectDef<T> already registers the type index and
    static type objects are predefined that we can control, we explicitly
    removes the static inline based reg trigger to we can save up possible
    binary space and reduce init logic.
    
    This does mean that when an Object is not registered through ObjectDef
    the dynamic casting mechanism won't work. But we are OK since
    expectation is most dynamic ObjectRef needs to do so for it to be
    useful.
---
 include/tvm/ffi/error.h      |  2 +-
 include/tvm/ffi/object.h     | 51 +++++++++++++++++++++++++++-----------------
 src/ffi/container.cc         |  1 -
 src/ffi/object.cc            | 25 +++++++++++++++-------
 tests/cpp/test_object.cc     |  4 ++--
 tests/cpp/test_reflection.cc |  2 +-
 6 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/include/tvm/ffi/error.h b/include/tvm/ffi/error.h
index d4f50a3..dd7b923 100644
--- a/include/tvm/ffi/error.h
+++ b/include/tvm/ffi/error.h
@@ -89,7 +89,7 @@ class ErrorObj : public Object, public TVMFFIErrorCell {
  public:
   /// \cond Doxygen_Suppress
   static constexpr const int32_t _type_index = TypeIndex::kTVMFFIError;
-  TVM_FFI_DECLARE_OBJECT_INFO_STATIC("ffi.Error", ErrorObj, Object);
+  TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIError, ErrorObj, 
Object);
   /// \endcond
 };
 
diff --git a/include/tvm/ffi/object.h b/include/tvm/ffi/object.h
index d7834e8..1f0fe4c 100644
--- a/include/tvm/ffi/object.h
+++ b/include/tvm/ffi/object.h
@@ -94,6 +94,8 @@ struct StaticTypeKey {
   static constexpr const char* kTVMFFISmallStr = "ffi.SmallStr";
   /*! \brief The type key for SmallBytes */
   static constexpr const char* kTVMFFISmallBytes = "ffi.SmallBytes";
+  /*! \brief The type key for Error */
+  static constexpr const char* kTVMFFIError = "ffi.Error";
   /*! \brief The type key for Bytes */
   static constexpr const char* kTVMFFIBytes = "ffi.Bytes";
   /*! \brief The type key for String */
@@ -913,8 +915,20 @@ struct ObjectPtrEqual {
   TVM_FFI_INLINE bool operator()(const Variant<V...>& a, const Variant<V...>& 
b) const;
 };
 
-/// \cond Doxygen_Suppress
-#define TVM_FFI_REGISTER_STATIC_TYPE_INFO(TypeName, ParentType)                
               \
+/*!
+ * \brief Helper macro to declare object information with static type index.
+ *
+ * For each custom object, you need to call 
tvm::ffi::reflection::ObjectDef<TypeName>()
+ * once in your cc file to register the type index with the runtime.
+ * Alternatively, you can call TypeName::_GetOrAllocRuntimeTypeIndex() once.
+ *
+ * \param TypeKey The type key of the current type.
+ * \param TypeName The name of the current type.
+ * \param ParentType The name of the ParentType
+ *
+ * \see tvm::ffi::reflection::ObjectDef
+ */
+#define TVM_FFI_DECLARE_OBJECT_INFO_STATIC(TypeKey, TypeName, ParentType)      
               \
   static constexpr int32_t _type_depth = ParentType::_type_depth + 1;          
               \
   static int32_t _GetOrAllocRuntimeTypeIndex() {                               
               \
     static_assert(!ParentType::_type_final, "ParentType marked as final");     
               \
@@ -923,25 +937,13 @@ struct ObjectPtrEqual {
                   "Need to set _type_child_slots when parent specifies it.");  
               \
     TVMFFIByteArray type_key{TypeName::_type_key,                              
               \
                              
std::char_traits<char>::length(TypeName::_type_key)};            \
-    static int32_t tindex = TVMFFITypeGetOrAllocIndex(                         
               \
+    static int32_t tindex [[maybe_unused]] = TVMFFITypeGetOrAllocIndex(        
               \
         &type_key, TypeName::_type_index, TypeName::_type_depth, 
TypeName::_type_child_slots, \
         TypeName::_type_child_slots_can_overflow, 
ParentType::_GetOrAllocRuntimeTypeIndex()); \
-    return tindex;                                                             
               \
+    return TypeName::_type_index;                                              
               \
   }                                                                            
               \
-  static inline int32_t _register_type_index = _GetOrAllocRuntimeTypeIndex()
-/// \endcond
-
-/*!
- * \brief Helper macro to declare object information with static type index.
- *
- * \param TypeKey The type key of the current type.
- * \param TypeName The name of the current type.
- * \param ParentType The name of the ParentType
- */
-#define TVM_FFI_DECLARE_OBJECT_INFO_STATIC(TypeKey, TypeName, ParentType) \
-  static constexpr const char* _type_key = TypeKey;                       \
-  static int32_t RuntimeTypeIndex() { return TypeName::_type_index; }     \
-  TVM_FFI_REGISTER_STATIC_TYPE_INFO(TypeName, ParentType)
+  static int32_t RuntimeTypeIndex() { return TypeName::_type_index; }          
               \
+  static constexpr const char* _type_key = TypeKey
 
 /*!
  * \brief Helper macro to declare object information with type key already 
defined in class.
@@ -963,15 +965,19 @@ struct ObjectPtrEqual {
         TypeName::_type_child_slots_can_overflow, 
ParentType::_GetOrAllocRuntimeTypeIndex()); \
     return tindex;                                                             
               \
   }                                                                            
               \
-  static int32_t RuntimeTypeIndex() { return _GetOrAllocRuntimeTypeIndex(); }  
               \
-  static inline int32_t _type_index = _GetOrAllocRuntimeTypeIndex()
+  static int32_t RuntimeTypeIndex() { return _GetOrAllocRuntimeTypeIndex(); }
 
 /*!
  * \brief Helper macro to declare object information with dynamic type index.
  *
+ * For each custom object, you need to call 
tvm::ffi::reflection::ObjectDef<TypeName>()
+ * once in your cc file to register the type index with the runtime.
+ * Alternatively, you can call TypeName::_GetOrAllocRuntimeTypeIndex() once.
+ *
  * \param TypeKey The type key of the current type.
  * \param TypeName The name of the current type.
  * \param ParentType The name of the ParentType
+ * \sa tvm::ffi::reflection::ObjectDef
  */
 #define TVM_FFI_DECLARE_OBJECT_INFO(TypeKey, TypeName, ParentType) \
   static constexpr const char* _type_key = TypeKey;                \
@@ -980,9 +986,14 @@ struct ObjectPtrEqual {
 /*!
  * \brief Helper macro to declare object information with dynamic type index 
and is final.
  *
+ * For each custom object, you need to call 
tvm::ffi::reflection::ObjectDef<TypeName>()
+ * once in your cc file to register the type index with the runtime.
+ * Alternatively, you can call TypeName::_GetOrAllocRuntimeTypeIndex() once.
+ *
  * \param TypeKey The type key of the current type.
  * \param TypeName The name of the current type.
  * \param ParentType The name of the ParentType
+ * \sa tvm::ffi::reflection::ObjectDef
  */
 #define TVM_FFI_DECLARE_OBJECT_INFO_FINAL(TypeKey, TypeName, ParentType) \
   static const constexpr int _type_child_slots [[maybe_unused]] = 0;     \
diff --git a/src/ffi/container.cc b/src/ffi/container.cc
index ca1ec91..b777dc0 100644
--- a/src/ffi/container.cc
+++ b/src/ffi/container.cc
@@ -22,7 +22,6 @@
  */
 #include <tvm/ffi/container/array.h>
 #include <tvm/ffi/container/map.h>
-#include <tvm/ffi/container/shape.h>
 #include <tvm/ffi/function.h>
 #include <tvm/ffi/reflection/registry.h>
 
diff --git a/src/ffi/object.cc b/src/ffi/object.cc
index b3927fe..b58231a 100644
--- a/src/ffi/object.cc
+++ b/src/ffi/object.cc
@@ -339,20 +339,29 @@ class TypeTable {
                             TypeIndex::kTVMFFIObjectRValueRef);
     ReserveBuiltinTypeIndex(StaticTypeKey::kTVMFFISmallStr, 
TypeIndex::kTVMFFISmallStr);
     ReserveBuiltinTypeIndex(StaticTypeKey::kTVMFFISmallBytes, 
TypeIndex::kTVMFFISmallBytes);
-    // register opaque py whose type depth is 1
-    this->GetOrAllocTypeIndex(StaticTypeKey::kTVMFFIOpaquePyObject,
-                              TypeIndex::kTVMFFIOpaquePyObject,
-                              /*type_depth=*/1,
-                              /*num_child_slots=*/0,
-                              /*child_slots_can_overflow=*/false,
-                              /*parent_type_index=*/TypeIndex::kTVMFFIObject);
-    // no need to reserve for object types as they will be registered
+    // reserved static type indices for depth 1 object types
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIStr, 
TypeIndex::kTVMFFIStr);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIBytes, 
TypeIndex::kTVMFFIBytes);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIError, 
TypeIndex::kTVMFFIError);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIFunction, 
TypeIndex::kTVMFFIFunction);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIShape, 
TypeIndex::kTVMFFIShape);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFITensor, 
TypeIndex::kTVMFFITensor);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIArray, 
TypeIndex::kTVMFFIArray);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIMap, 
TypeIndex::kTVMFFIMap);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIModule, 
TypeIndex::kTVMFFIModule);
+    ReserveDepthOneObjectTypeIndex(StaticTypeKey::kTVMFFIOpaquePyObject,
+                                   TypeIndex::kTVMFFIOpaquePyObject);
   }
 
   void ReserveBuiltinTypeIndex(const char* type_key, int32_t 
static_type_index) {
     this->GetOrAllocTypeIndex(String(type_key), static_type_index, 0, 0, 
false, -1);
   }
 
+  void ReserveDepthOneObjectTypeIndex(const char* type_key, int32_t 
static_type_index) {
+    this->GetOrAllocTypeIndex(String(type_key), static_type_index, 1, 0, false,
+                              TypeIndex::kTVMFFIObject);
+  }
+
   static ObjectPtr<details::StringObj> MakeInplaceString(const char* data, 
size_t length) {
     ObjectPtr<details::StringObj> p =
         make_inplace_array_object<details::StringObj, char>(length + 1);
diff --git a/tests/cpp/test_object.cc b/tests/cpp/test_object.cc
index da22e59..4aeddef 100644
--- a/tests/cpp/test_object.cc
+++ b/tests/cpp/test_object.cc
@@ -55,8 +55,8 @@ TEST(Object, TypeInfo) {
   EXPECT_TRUE(info != nullptr);
   EXPECT_EQ(info->type_index, TIntObj::RuntimeTypeIndex());
   EXPECT_EQ(info->type_depth, 2);
-  EXPECT_EQ(info->type_ancestors[0]->type_index, Object::_type_index);
-  EXPECT_EQ(info->type_ancestors[1]->type_index, TNumberObj::_type_index);
+  EXPECT_EQ(info->type_ancestors[0]->type_index, Object::RuntimeTypeIndex());
+  EXPECT_EQ(info->type_ancestors[1]->type_index, 
TNumberObj::RuntimeTypeIndex());
   EXPECT_GE(info->type_index, TypeIndex::kTVMFFIDynObjectBegin);
 }
 
diff --git a/tests/cpp/test_reflection.cc b/tests/cpp/test_reflection.cc
index acabdec..c81a20b 100644
--- a/tests/cpp/test_reflection.cc
+++ b/tests/cpp/test_reflection.cc
@@ -172,7 +172,7 @@ TEST(Reflection, ForEachFieldInfo) {
 
 TEST(Reflection, TypeAttrColumn) {
   reflection::TypeAttrColumn size_attr("test.size");
-  EXPECT_EQ(size_attr[TIntObj::_type_index].cast<int>(), sizeof(TIntObj));
+  EXPECT_EQ(size_attr[TIntObj::RuntimeTypeIndex()].cast<int>(), 
sizeof(TIntObj));
 }
 
 TVM_FFI_STATIC_INIT_BLOCK() {

Reply via email to