gemini-code-assist[bot] commented on code in PR #392:
URL: https://github.com/apache/tvm-ffi/pull/392#discussion_r2674262877


##########
docs/concepts/object_and_class.rst:
##########
@@ -0,0 +1,686 @@
+..  Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+..    http://www.apache.org/licenses/LICENSE-2.0
+
+..  Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+Object and Class
+================
+
+TVM-FFI provides a unified object system that enables cross-language 
interoperability
+between C++, Python, and Rust. The object system is built around 
:cpp:class:`tvm::ffi::Object`
+and :cpp:class:`tvm::ffi::ObjectRef`, which together form the foundation for:
+
+- **Type-safe runtime type identification** without relying on C++ RTTI
+- **Intrusive reference counting** for smart memory management
+- **Reflection-based class exposure** across programming languages
+- **Serialization and deserialization** via reflection metadata
+
+This tutorial covers everything you need to know about defining, using, and 
extending
+TVM-FFI objects across languages.
+
+
+Glossary
+--------
+
+:cpp:class:`tvm::ffi::Object`
+  A heap-allocated, reference-counted container.
+  All TVM-FFI objects inherit from this base class and share a common 24-byte 
header
+  that stores reference counts, type index, and a deleter callback.
+
+:cpp:class:`tvm::ffi::ObjectRef`
+  An intrusive pointer that manages an :cpp:class:`~tvm::ffi::Object`'s 
lifetime through reference counting.
+  Its subclasses provide type-safe access to specific object types. In its 
low-level implementation, it is
+  equivalent to a normal C++ pointer to a heap-allocated 
:cpp:class:`~tvm::ffi::Object`.
+
+Type info: type index and type key
+  Type index is an integer that uniquely identifies each object type.
+  Built-in types have statically assigned indices defined in 
:cpp:enum:`TVMFFITypeIndex`,
+  while user-defined types receive indices at startup when first accessed.
+  Type key is a unique string identifier (e.g., ``"my_ext.MyClass"``) that 
names an object type.
+  It is used for registration, serialization, and cross-language mapping.
+
+Common Usage
+------------
+
+Define a Class in C++
+~~~~~~~~~~~~~~~~~~~~~
+
+To define a custom object class in normal C++, inherit it from 
:cpp:class:`tvm::ffi::Object` or its subclasses,
+and then add one of the following macros that declares its metadata:
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO>`
+  Declare an object type that can be subclassed. Type index is assigned 
dynamically.
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO_FINAL>`
+  Declare a final object type (no subclasses). Enables faster type checking.
+
+**Example**. The code below shows a minimal example of defining a TVM-FFI 
object class.
+It declares a class ``MyObjectObj`` that inherits from 
:cpp:class:`~tvm::ffi::Object`.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/tvm_ffi.h>
+
+   namespace ffi = tvm::ffi;
+
+   class MyObjectObj : public ffi::Object {
+    public:
+     // Normal C++ code: Declare fields, methods, constructor, destructor, etc.
+     int64_t value;
+     ffi::String name;
+     MyObjectObj(int64_t value, ffi::String name) : value(value), 
name(std::move(name)) {}
+     int64_t GetValue() const { return value; }
+
+     // Declare object type info
+     TVM_FFI_DECLARE_OBJECT_INFO(
+       /*type_key=*/"my_ext.MyObject",
+       /*type_name=*/MyObjectObj,
+       /*parent_type=*/ffi::Object);
+   };
+
+**Managed reference**. Optionally, a managed reference class can be defined by 
inheriting
+from :cpp:class:`~tvm::ffi::ObjectRef` and using one of the following macros 
to define the methods.
+Define its constructor by wrapping the :cpp:func:`tvm::ffi::make_object` 
function.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE>`
+  Define a nullable reference class.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE>`
+  Define a non-nullable reference class.
+
+
+.. code-block:: cpp
+
+   class MyObject : public ffi::ObjectRef {
+    public:
+     MyObject(int64_t value, ffi::String name) : 
data_(ffi::make_object<MyObjectObj>(value, std::move(name))) {}
+     TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(
+        /*type_name=*/MyObject,
+        /*parent_type=*/ffi::ObjectRef,
+        /*object_name=*/MyObjectObj);
+   };
+
+   // Create a managed object
+   MyObject obj = MyObject(42, "hello");
+
+   // Access fields via operator->
+   std::cout << obj->value << std::endl;  // -> 42
+
+
+Expose an Object Class in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Reflection**. The object's metadata is used for reflection. Use 
:cpp:class:`tvm::ffi::reflection::ObjectDef`
+to register an object's constructor, fields, and methods.
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<MyObjectObj>()
+         // Register constructor with signature
+         .def(refl::init<int64_t, ffi::String>())
+         // Register read-write fields
+         .def_rw("value", &MyObjectObj::value, "The integer value")
+         .def_rw("name", &MyObjectObj::name, "The name string")
+         // Register methods
+         .def("get_value", &MyObjectObj::GetValue, "Returns the value");
+   }
+
+**Python binding**. After registration, the object is automatically available 
in Python. Use
+:py:func:`tvm_ffi.register_object` to bind a Python class to a registered C++ 
type:
+
+.. code-block:: python
+
+   import tvm_ffi
+
+   @tvm_ffi.register_object("my_ext.MyObject")
+   class MyObject(tvm_ffi.Object):
+       # tvm-ffi-stubgen(begin): object/my_ext.MyObject
+       value: int
+       name: str
+
+       if TYPE_CHECKING:
+         def __init__(self, value: int, name: str) -> None: ...
+         def get_value(self) -> int: ...
+       # tvm-ffi-stubgen(end)
+
+   # Create and use objects
+   obj = MyObject(42, "hello")
+   print(obj.value)      # -> 42
+   print(obj.get_value())  # -> 42
+   obj.value = 100       # Mutable field access
+
+The decorator looks up the type key ``"my_ext.MyObject"`` in the C++ type 
registry and binds the Python class to it.
+Fields and methods registered via 
:cpp:class:`~tvm::ffi::reflection::ObjectDef` are automatically available on 
the Python class.
+
+
+Type Checks and Casting
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Type checking**. Use :cpp:func:`Object::IsInstance\<T\>() 
<tvm::ffi::Object::IsInstance>`
+for runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       return true;
+     }
+     return false;
+   }
+
+**Type casting**. Use :cpp:func:`ObjectRef::as\<T\>() 
<tvm::ffi::ObjectRef::as>` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+**Type info**. Type index is available via :cpp:func:`ObjectRef::type_index() 
<tvm::ffi::ObjectRef::type_index>`
+and type key is available via :cpp:func:`ObjectRef::GetTypeKey() 
<tvm::ffi::ObjectRef::GetTypeKey>`. These methods
+can be used to safely identify object types without relying on C++ RTTI 
(``typeid``, ``dynamic_cast``).
+
+.. note::
+  C++ RTTI (e.g. ``typeid``, ``dynamic_cast``) is strictly not useful in 
TVM-FFI-based approaches.
+
+Serialization and Deserialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**C++ APIs**. Use :cpp:func:`tvm::ffi::ToJSONGraph` to serialize an object to 
a JSON value,
+and :cpp:func:`tvm::ffi::FromJSONGraph` to deserialize a JSON value to an 
object.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/extra/serialization.h>
+
+   // Serialize to JSON
+   ffi::Any obj = ...;
+   ffi::json::Value json = ffi::ToJSONGraph(obj);
+
+   // Deserialize from JSON
+   ffi::Any restored = ffi::FromJSONGraph(json);
+
+**Python APIs**. Pickle is overloaded in Python to support TVM-FFI object 
serialization.
+
+.. code-block:: python
+
+   import pickle
+
+   obj = MyObject(42, "test")
+   data = pickle.dumps(obj)
+   restored = pickle.loads(data)
+
+Or explicitly use the :py:func:`tvm_ffi.serialization.to_json_graph_str`
+and :py:func:`tvm_ffi.serialization.from_json_graph_str` to serialize and 
deserialize an object to a JSON string.
+
+
+
+Memory Model
+------------
+
+Reference Counting
+~~~~~~~~~~~~~~~~~~
+
+TVM-FFI uses intrusive reference counting: the reference count is stored 
directly
+in the object header, not in a separate control block. This design:
+
+- Reduces memory overhead (no separate allocation for control block)
+- Improves cache locality
+- Enables efficient cross-language ownership transfer
+
+The :cpp:class:`TVMFFIObject` header stores a 64-bit ``combined_ref_count`` 
that
+packs both strong and weak reference counts:
+
+.. code-block:: cpp
+
+   // Strong ref count: lower 32 bits
+   uint32_t strong_ref_count = combined_ref_count & 0xFFFFFFFF;
+   // Weak ref count: upper 32 bits
+   uint32_t weak_ref_count = (combined_ref_count >> 32) & 0xFFFFFFFF;
+
+.. figure:: 
https://raw.githubusercontent.com/tlc-pack/web-data/main/images/tvm-ffi/stable-c-abi-layout-any.svg
+   :alt: Object header layout
+   :align: center
+
+   Figure 1. The object header stores reference counts, type index, and 
deleter in 24 bytes.
+
+
+ObjectPtr vs ObjectRef
+~~~~~~~~~~~~~~~~~~~~~~
+
+Both :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>` and ``ObjectRef`` 
subclasses
+manage object lifetimes, but serve different purposes:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 25 35 40
+
+   * - Type
+     - Usage
+     - Example
+   * - :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>`
+     - Low-level smart pointer
+     - ``ObjectPtr<MyObjectObj> ptr = make_object<MyObjectObj>(...);``
+   * - ``ObjectRef`` subclass
+     - Type-safe managed reference
+     - ``MyObject obj(make_object<MyObjectObj>(...));``
+
+The key difference is that ``ObjectRef`` subclasses provide a cleaner API with
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS` generating common operations like
+``operator->``, ``get()``, and type casting.
+
+
+Converting Between Pointer Types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use :cpp:func:`GetRef\<T\> <tvm::ffi::GetRef>` to convert a raw ``Object*`` to
+a managed reference:
+
+.. code-block:: cpp
+
+   void ProcessObject(const MyObjectObj* ptr) {
+     // Convert raw pointer to managed reference
+     MyObject ref = ffi::GetRef<MyObject>(ptr);
+     // ref now shares ownership with the original holder
+   }
+
+Use ``ObjectRef::get()`` or ``ObjectPtr::get()`` to obtain a raw pointer 
(non-owning):
+
+.. code-block:: cpp
+
+   MyObject obj = ...;
+   const MyObjectObj* ptr = obj.get();  // Non-owning, valid while obj lives
+
+
+Type System
+-----------
+
+Every object in TVM-FFI carries a runtime type index that enables type-safe
+operations without relying on C++ RTTI (``typeid``, ``dynamic_cast``).
+
+Type Registration
+~~~~~~~~~~~~~~~~~
+
+Types are registered at startup with a unique type key:
+
+- **Built-in types** (String, Array, Map, Tensor, etc.) have statically 
assigned indices
+  defined in :cpp:enum:`TVMFFITypeIndex`.
+- **User-defined types** receive indices dynamically when first accessed via
+  :cpp:func:`TVMFFITypeGetOrAllocIndex`.
+
+The registration happens automatically when you use 
:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO`
+or :c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL`:
+
+.. code-block:: cpp
+
+   // Static type index (built-in types)
+   static constexpr const uint32_t _type_index = TypeIndex::kTVMFFIStr;
+   TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIStr, StringObj, 
Object);
+
+   // Dynamic type index (user-defined types)
+   TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyClass", MyClassObj, Object);
+
+
+Type Checking with IsInstance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :cpp:func:`Object::IsInstance\<T\>() <tvm::ffi::Object::IsInstance>` method
+provides fast runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       const MyObjectObj* ptr = static_cast<const MyObjectObj*>(obj.get());
+       return true;
+     }
+     return false;
+   }
+
+The implementation uses a fast-path optimization for final types and types with
+reserved child slots:
+
+1. **Final types**: Direct index comparison (``object_type_index == 
TargetType::RuntimeTypeIndex()``)
+2. **Types with child slots**: Range check (``type_index ∈ [begin, begin + 
child_slots]``)
+3. **Fallback**: Ancestor chain lookup in the global type table
+
+
+Safe Downcasting
+~~~~~~~~~~~~~~~~
+
+Use ``ObjectRef::as<T>()`` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+
+Type Hierarchy
+~~~~~~~~~~~~~~
+
+TVM-FFI supports single inheritance for object types. Configure inheritance 
behavior
+with these static fields:
+
+.. code-block:: cpp
+
+   class MyBaseObj : public ffi::Object {
+    public:
+     // Reserve slots for up to 10 child types (fast type checking)
+     static constexpr int _type_child_slots = 10;
+     // Allow more children beyond the reserved slots
+     static constexpr bool _type_child_slots_can_overflow = true;
+
+     TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyBase", MyBaseObj, Object);
+   };
+
+   class MyDerivedObj : public MyBaseObj {
+    public:
+     // Final class: no subclasses allowed
+     TVM_FFI_DECLARE_OBJECT_INFO_FINAL("my_ext.MyDerived", MyDerivedObj, 
MyBaseObj);
+   };
+
+
+Reflection System
+-----------------
+
+The reflection system enables cross-language exposure of C++ classes, their 
fields,
+and methods. It is built around :cpp:class:`tvm::ffi::reflection::ObjectDef` 
and
+:cpp:class:`tvm::ffi::reflection::GlobalDef`.
+
+ObjectDef API
+~~~~~~~~~~~~~
+
+:cpp:class:`ObjectDef\<T\> <tvm::ffi::reflection::ObjectDef>` registers 
reflection
+metadata for object type ``T``:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 30 70
+
+   * - Method
+     - Description
+   * - ``.def(init<Args...>())``
+     - Register a constructor with the given argument types
+   * - ``.def_ro("name", &T::field)``
+     - Register a read-only field
+   * - ``.def_rw("name", &T::field)``
+     - Register a read-write field (requires ``_type_mutable = true``)
+   * - ``.def("name", &T::method)``
+     - Register a member method
+   * - ``.def_static("name", &func)``
+     - Register a static method
+
+Example:
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<IntPairObj>()
+         .def(refl::init<int64_t, int64_t>())
+         .def_rw("a", &IntPairObj::a, "the first field")
+         .def_rw("b", &IntPairObj::b, "the second field")
+         .def("sum", &IntPairObj::Sum, "compute a + b");
+   }
+
+
+GlobalDef API
+~~~~~~~~~~~~~
+
+:cpp:class:`GlobalDef <tvm::ffi::reflection::GlobalDef>` registers global 
functions:
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::GlobalDef()
+         .def("my_ext.add_one", [](int x) { return x + 1; })
+         .def("my_ext.greet", [](ffi::String name) {
+           return ffi::String("Hello, " + std::string(name));
+         });
+   }
+
+
+Metadata and Documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add documentation strings and custom metadata to fields and methods:
+
+.. code-block:: cpp
+
+   refl::ObjectDef<MyObjectObj>()
+       .def_rw("value", &MyObjectObj::value,
+               "The numeric value",                    // docstring
+               refl::DefaultValue(0),                  // default value
+               refl::Metadata{{"min", 0}, {"max", 100}})  // custom metadata
+       .def("compute", &MyObjectObj::Compute,
+            "Perform computation");

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   The example uses `MyObjectObj::Compute`, but this method is not defined in 
the `MyObjectObj` class shown earlier in the document. To make the example 
valid and less confusing, please use the existing `GetValue` method instead.
   
   ```suggestion
          .def("get_value", &MyObjectObj::GetValue,
               "Returns the value");
   ```



##########
docs/concepts/object_and_class.rst:
##########
@@ -0,0 +1,686 @@
+..  Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+..    http://www.apache.org/licenses/LICENSE-2.0
+
+..  Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+Object and Class
+================
+
+TVM-FFI provides a unified object system that enables cross-language 
interoperability
+between C++, Python, and Rust. The object system is built around 
:cpp:class:`tvm::ffi::Object`
+and :cpp:class:`tvm::ffi::ObjectRef`, which together form the foundation for:
+
+- **Type-safe runtime type identification** without relying on C++ RTTI
+- **Intrusive reference counting** for smart memory management
+- **Reflection-based class exposure** across programming languages
+- **Serialization and deserialization** via reflection metadata
+
+This tutorial covers everything you need to know about defining, using, and 
extending
+TVM-FFI objects across languages.
+
+
+Glossary
+--------
+
+:cpp:class:`tvm::ffi::Object`
+  A heap-allocated, reference-counted container.
+  All TVM-FFI objects inherit from this base class and share a common 24-byte 
header
+  that stores reference counts, type index, and a deleter callback.
+
+:cpp:class:`tvm::ffi::ObjectRef`
+  An intrusive pointer that manages an :cpp:class:`~tvm::ffi::Object`'s 
lifetime through reference counting.
+  Its subclasses provide type-safe access to specific object types. In its 
low-level implementation, it is
+  equivalent to a normal C++ pointer to a heap-allocated 
:cpp:class:`~tvm::ffi::Object`.
+
+Type info: type index and type key
+  Type index is an integer that uniquely identifies each object type.
+  Built-in types have statically assigned indices defined in 
:cpp:enum:`TVMFFITypeIndex`,
+  while user-defined types receive indices at startup when first accessed.
+  Type key is a unique string identifier (e.g., ``"my_ext.MyClass"``) that 
names an object type.
+  It is used for registration, serialization, and cross-language mapping.
+
+Common Usage
+------------
+
+Define a Class in C++
+~~~~~~~~~~~~~~~~~~~~~
+
+To define a custom object class in normal C++, inherit it from 
:cpp:class:`tvm::ffi::Object` or its subclasses,
+and then add one of the following macros that declares its metadata:
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO>`
+  Declare an object type that can be subclassed. Type index is assigned 
dynamically.
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO_FINAL>`
+  Declare a final object type (no subclasses). Enables faster type checking.
+
+**Example**. The code below shows a minimal example of defining a TVM-FFI 
object class.
+It declares a class ``MyObjectObj`` that inherits from 
:cpp:class:`~tvm::ffi::Object`.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/tvm_ffi.h>
+
+   namespace ffi = tvm::ffi;
+
+   class MyObjectObj : public ffi::Object {
+    public:
+     // Normal C++ code: Declare fields, methods, constructor, destructor, etc.
+     int64_t value;
+     ffi::String name;
+     MyObjectObj(int64_t value, ffi::String name) : value(value), 
name(std::move(name)) {}
+     int64_t GetValue() const { return value; }
+
+     // Declare object type info
+     TVM_FFI_DECLARE_OBJECT_INFO(
+       /*type_key=*/"my_ext.MyObject",
+       /*type_name=*/MyObjectObj,
+       /*parent_type=*/ffi::Object);
+   };
+
+**Managed reference**. Optionally, a managed reference class can be defined by 
inheriting
+from :cpp:class:`~tvm::ffi::ObjectRef` and using one of the following macros 
to define the methods.
+Define its constructor by wrapping the :cpp:func:`tvm::ffi::make_object` 
function.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE>`
+  Define a nullable reference class.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE>`
+  Define a non-nullable reference class.
+
+
+.. code-block:: cpp
+
+   class MyObject : public ffi::ObjectRef {
+    public:
+     MyObject(int64_t value, ffi::String name) : 
data_(ffi::make_object<MyObjectObj>(value, std::move(name))) {}
+     TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(
+        /*type_name=*/MyObject,
+        /*parent_type=*/ffi::ObjectRef,
+        /*object_name=*/MyObjectObj);
+   };
+
+   // Create a managed object
+   MyObject obj = MyObject(42, "hello");
+
+   // Access fields via operator->
+   std::cout << obj->value << std::endl;  // -> 42
+
+
+Expose an Object Class in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Reflection**. The object's metadata is used for reflection. Use 
:cpp:class:`tvm::ffi::reflection::ObjectDef`
+to register an object's constructor, fields, and methods.
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<MyObjectObj>()
+         // Register constructor with signature
+         .def(refl::init<int64_t, ffi::String>())
+         // Register read-write fields
+         .def_rw("value", &MyObjectObj::value, "The integer value")
+         .def_rw("name", &MyObjectObj::name, "The name string")
+         // Register methods
+         .def("get_value", &MyObjectObj::GetValue, "Returns the value");
+   }
+
+**Python binding**. After registration, the object is automatically available 
in Python. Use
+:py:func:`tvm_ffi.register_object` to bind a Python class to a registered C++ 
type:
+
+.. code-block:: python
+
+   import tvm_ffi
+
+   @tvm_ffi.register_object("my_ext.MyObject")
+   class MyObject(tvm_ffi.Object):
+       # tvm-ffi-stubgen(begin): object/my_ext.MyObject
+       value: int
+       name: str
+
+       if TYPE_CHECKING:
+         def __init__(self, value: int, name: str) -> None: ...
+         def get_value(self) -> int: ...
+       # tvm-ffi-stubgen(end)
+
+   # Create and use objects
+   obj = MyObject(42, "hello")
+   print(obj.value)      # -> 42
+   print(obj.get_value())  # -> 42
+   obj.value = 100       # Mutable field access
+
+The decorator looks up the type key ``"my_ext.MyObject"`` in the C++ type 
registry and binds the Python class to it.
+Fields and methods registered via 
:cpp:class:`~tvm::ffi::reflection::ObjectDef` are automatically available on 
the Python class.
+
+
+Type Checks and Casting
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Type checking**. Use :cpp:func:`Object::IsInstance\<T\>() 
<tvm::ffi::Object::IsInstance>`
+for runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       return true;
+     }
+     return false;
+   }
+
+**Type casting**. Use :cpp:func:`ObjectRef::as\<T\>() 
<tvm::ffi::ObjectRef::as>` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+**Type info**. Type index is available via :cpp:func:`ObjectRef::type_index() 
<tvm::ffi::ObjectRef::type_index>`
+and type key is available via :cpp:func:`ObjectRef::GetTypeKey() 
<tvm::ffi::ObjectRef::GetTypeKey>`. These methods
+can be used to safely identify object types without relying on C++ RTTI 
(``typeid``, ``dynamic_cast``).
+
+.. note::
+  C++ RTTI (e.g. ``typeid``, ``dynamic_cast``) is strictly not useful in 
TVM-FFI-based approaches.
+
+Serialization and Deserialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**C++ APIs**. Use :cpp:func:`tvm::ffi::ToJSONGraph` to serialize an object to 
a JSON value,
+and :cpp:func:`tvm::ffi::FromJSONGraph` to deserialize a JSON value to an 
object.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/extra/serialization.h>
+
+   // Serialize to JSON
+   ffi::Any obj = ...;
+   ffi::json::Value json = ffi::ToJSONGraph(obj);
+
+   // Deserialize from JSON
+   ffi::Any restored = ffi::FromJSONGraph(json);
+
+**Python APIs**. Pickle is overloaded in Python to support TVM-FFI object 
serialization.
+
+.. code-block:: python
+
+   import pickle
+
+   obj = MyObject(42, "test")
+   data = pickle.dumps(obj)
+   restored = pickle.loads(data)
+
+Or explicitly use the :py:func:`tvm_ffi.serialization.to_json_graph_str`
+and :py:func:`tvm_ffi.serialization.from_json_graph_str` to serialize and 
deserialize an object to a JSON string.
+
+
+
+Memory Model
+------------
+
+Reference Counting
+~~~~~~~~~~~~~~~~~~
+
+TVM-FFI uses intrusive reference counting: the reference count is stored 
directly
+in the object header, not in a separate control block. This design:
+
+- Reduces memory overhead (no separate allocation for control block)
+- Improves cache locality
+- Enables efficient cross-language ownership transfer
+
+The :cpp:class:`TVMFFIObject` header stores a 64-bit ``combined_ref_count`` 
that
+packs both strong and weak reference counts:
+
+.. code-block:: cpp
+
+   // Strong ref count: lower 32 bits
+   uint32_t strong_ref_count = combined_ref_count & 0xFFFFFFFF;
+   // Weak ref count: upper 32 bits
+   uint32_t weak_ref_count = (combined_ref_count >> 32) & 0xFFFFFFFF;
+
+.. figure:: 
https://raw.githubusercontent.com/tlc-pack/web-data/main/images/tvm-ffi/stable-c-abi-layout-any.svg
+   :alt: Object header layout
+   :align: center
+
+   Figure 1. The object header stores reference counts, type index, and 
deleter in 24 bytes.
+
+
+ObjectPtr vs ObjectRef
+~~~~~~~~~~~~~~~~~~~~~~
+
+Both :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>` and ``ObjectRef`` 
subclasses
+manage object lifetimes, but serve different purposes:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 25 35 40
+
+   * - Type
+     - Usage
+     - Example
+   * - :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>`
+     - Low-level smart pointer
+     - ``ObjectPtr<MyObjectObj> ptr = make_object<MyObjectObj>(...);``
+   * - ``ObjectRef`` subclass
+     - Type-safe managed reference
+     - ``MyObject obj(make_object<MyObjectObj>(...));``

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   The example `MyObject obj(make_object<MyObjectObj>(...));` is a bit 
confusing for a tutorial, as it uses the base class constructor. It would be 
clearer to use the `MyObject` constructor that was defined earlier in the 
document, which is more idiomatic.
   
   ```suggestion
        - ``MyObject obj(42, "hello");``
   ```



##########
docs/concepts/object_and_class.rst:
##########
@@ -0,0 +1,686 @@
+..  Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+..    http://www.apache.org/licenses/LICENSE-2.0
+
+..  Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+Object and Class
+================
+
+TVM-FFI provides a unified object system that enables cross-language 
interoperability
+between C++, Python, and Rust. The object system is built around 
:cpp:class:`tvm::ffi::Object`
+and :cpp:class:`tvm::ffi::ObjectRef`, which together form the foundation for:
+
+- **Type-safe runtime type identification** without relying on C++ RTTI
+- **Intrusive reference counting** for smart memory management
+- **Reflection-based class exposure** across programming languages
+- **Serialization and deserialization** via reflection metadata
+
+This tutorial covers everything you need to know about defining, using, and 
extending
+TVM-FFI objects across languages.
+
+
+Glossary
+--------
+
+:cpp:class:`tvm::ffi::Object`
+  A heap-allocated, reference-counted container.
+  All TVM-FFI objects inherit from this base class and share a common 24-byte 
header
+  that stores reference counts, type index, and a deleter callback.
+
+:cpp:class:`tvm::ffi::ObjectRef`
+  An intrusive pointer that manages an :cpp:class:`~tvm::ffi::Object`'s 
lifetime through reference counting.
+  Its subclasses provide type-safe access to specific object types. In its 
low-level implementation, it is
+  equivalent to a normal C++ pointer to a heap-allocated 
:cpp:class:`~tvm::ffi::Object`.
+
+Type info: type index and type key
+  Type index is an integer that uniquely identifies each object type.
+  Built-in types have statically assigned indices defined in 
:cpp:enum:`TVMFFITypeIndex`,
+  while user-defined types receive indices at startup when first accessed.
+  Type key is a unique string identifier (e.g., ``"my_ext.MyClass"``) that 
names an object type.
+  It is used for registration, serialization, and cross-language mapping.
+
+Common Usage
+------------
+
+Define a Class in C++
+~~~~~~~~~~~~~~~~~~~~~
+
+To define a custom object class in normal C++, inherit it from 
:cpp:class:`tvm::ffi::Object` or its subclasses,
+and then add one of the following macros that declares its metadata:
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO>`
+  Declare an object type that can be subclassed. Type index is assigned 
dynamically.
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO_FINAL>`
+  Declare a final object type (no subclasses). Enables faster type checking.
+
+**Example**. The code below shows a minimal example of defining a TVM-FFI 
object class.
+It declares a class ``MyObjectObj`` that inherits from 
:cpp:class:`~tvm::ffi::Object`.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/tvm_ffi.h>
+
+   namespace ffi = tvm::ffi;
+
+   class MyObjectObj : public ffi::Object {
+    public:
+     // Normal C++ code: Declare fields, methods, constructor, destructor, etc.
+     int64_t value;
+     ffi::String name;
+     MyObjectObj(int64_t value, ffi::String name) : value(value), 
name(std::move(name)) {}
+     int64_t GetValue() const { return value; }
+
+     // Declare object type info
+     TVM_FFI_DECLARE_OBJECT_INFO(
+       /*type_key=*/"my_ext.MyObject",
+       /*type_name=*/MyObjectObj,
+       /*parent_type=*/ffi::Object);
+   };
+
+**Managed reference**. Optionally, a managed reference class can be defined by 
inheriting
+from :cpp:class:`~tvm::ffi::ObjectRef` and using one of the following macros 
to define the methods.
+Define its constructor by wrapping the :cpp:func:`tvm::ffi::make_object` 
function.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE>`
+  Define a nullable reference class.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE>`
+  Define a non-nullable reference class.
+
+
+.. code-block:: cpp
+
+   class MyObject : public ffi::ObjectRef {
+    public:
+     MyObject(int64_t value, ffi::String name) : 
data_(ffi::make_object<MyObjectObj>(value, std::move(name))) {}
+     TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(
+        /*type_name=*/MyObject,
+        /*parent_type=*/ffi::ObjectRef,
+        /*object_name=*/MyObjectObj);
+   };
+
+   // Create a managed object
+   MyObject obj = MyObject(42, "hello");
+
+   // Access fields via operator->
+   std::cout << obj->value << std::endl;  // -> 42
+
+
+Expose an Object Class in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Reflection**. The object's metadata is used for reflection. Use 
:cpp:class:`tvm::ffi::reflection::ObjectDef`
+to register an object's constructor, fields, and methods.
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<MyObjectObj>()
+         // Register constructor with signature
+         .def(refl::init<int64_t, ffi::String>())
+         // Register read-write fields
+         .def_rw("value", &MyObjectObj::value, "The integer value")
+         .def_rw("name", &MyObjectObj::name, "The name string")
+         // Register methods
+         .def("get_value", &MyObjectObj::GetValue, "Returns the value");
+   }
+
+**Python binding**. After registration, the object is automatically available 
in Python. Use
+:py:func:`tvm_ffi.register_object` to bind a Python class to a registered C++ 
type:
+
+.. code-block:: python
+
+   import tvm_ffi
+
+   @tvm_ffi.register_object("my_ext.MyObject")
+   class MyObject(tvm_ffi.Object):
+       # tvm-ffi-stubgen(begin): object/my_ext.MyObject
+       value: int
+       name: str
+
+       if TYPE_CHECKING:
+         def __init__(self, value: int, name: str) -> None: ...
+         def get_value(self) -> int: ...
+       # tvm-ffi-stubgen(end)
+
+   # Create and use objects
+   obj = MyObject(42, "hello")
+   print(obj.value)      # -> 42
+   print(obj.get_value())  # -> 42
+   obj.value = 100       # Mutable field access
+
+The decorator looks up the type key ``"my_ext.MyObject"`` in the C++ type 
registry and binds the Python class to it.
+Fields and methods registered via 
:cpp:class:`~tvm::ffi::reflection::ObjectDef` are automatically available on 
the Python class.
+
+
+Type Checks and Casting
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Type checking**. Use :cpp:func:`Object::IsInstance\<T\>() 
<tvm::ffi::Object::IsInstance>`
+for runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       return true;
+     }
+     return false;
+   }
+
+**Type casting**. Use :cpp:func:`ObjectRef::as\<T\>() 
<tvm::ffi::ObjectRef::as>` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+**Type info**. Type index is available via :cpp:func:`ObjectRef::type_index() 
<tvm::ffi::ObjectRef::type_index>`
+and type key is available via :cpp:func:`ObjectRef::GetTypeKey() 
<tvm::ffi::ObjectRef::GetTypeKey>`. These methods
+can be used to safely identify object types without relying on C++ RTTI 
(``typeid``, ``dynamic_cast``).
+
+.. note::
+  C++ RTTI (e.g. ``typeid``, ``dynamic_cast``) is strictly not useful in 
TVM-FFI-based approaches.
+
+Serialization and Deserialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**C++ APIs**. Use :cpp:func:`tvm::ffi::ToJSONGraph` to serialize an object to 
a JSON value,
+and :cpp:func:`tvm::ffi::FromJSONGraph` to deserialize a JSON value to an 
object.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/extra/serialization.h>
+
+   // Serialize to JSON
+   ffi::Any obj = ...;
+   ffi::json::Value json = ffi::ToJSONGraph(obj);
+
+   // Deserialize from JSON
+   ffi::Any restored = ffi::FromJSONGraph(json);
+
+**Python APIs**. Pickle is overloaded in Python to support TVM-FFI object 
serialization.
+
+.. code-block:: python
+
+   import pickle
+
+   obj = MyObject(42, "test")
+   data = pickle.dumps(obj)
+   restored = pickle.loads(data)
+
+Or explicitly use the :py:func:`tvm_ffi.serialization.to_json_graph_str`
+and :py:func:`tvm_ffi.serialization.from_json_graph_str` to serialize and 
deserialize an object to a JSON string.
+
+
+
+Memory Model
+------------
+
+Reference Counting
+~~~~~~~~~~~~~~~~~~
+
+TVM-FFI uses intrusive reference counting: the reference count is stored 
directly
+in the object header, not in a separate control block. This design:
+
+- Reduces memory overhead (no separate allocation for control block)
+- Improves cache locality
+- Enables efficient cross-language ownership transfer
+
+The :cpp:class:`TVMFFIObject` header stores a 64-bit ``combined_ref_count`` 
that
+packs both strong and weak reference counts:
+
+.. code-block:: cpp
+
+   // Strong ref count: lower 32 bits
+   uint32_t strong_ref_count = combined_ref_count & 0xFFFFFFFF;
+   // Weak ref count: upper 32 bits
+   uint32_t weak_ref_count = (combined_ref_count >> 32) & 0xFFFFFFFF;
+
+.. figure:: 
https://raw.githubusercontent.com/tlc-pack/web-data/main/images/tvm-ffi/stable-c-abi-layout-any.svg
+   :alt: Object header layout
+   :align: center
+
+   Figure 1. The object header stores reference counts, type index, and 
deleter in 24 bytes.
+
+
+ObjectPtr vs ObjectRef
+~~~~~~~~~~~~~~~~~~~~~~
+
+Both :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>` and ``ObjectRef`` 
subclasses
+manage object lifetimes, but serve different purposes:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 25 35 40
+
+   * - Type
+     - Usage
+     - Example
+   * - :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>`
+     - Low-level smart pointer
+     - ``ObjectPtr<MyObjectObj> ptr = make_object<MyObjectObj>(...);``
+   * - ``ObjectRef`` subclass
+     - Type-safe managed reference
+     - ``MyObject obj(make_object<MyObjectObj>(...));``
+
+The key difference is that ``ObjectRef`` subclasses provide a cleaner API with
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS` generating common operations like
+``operator->``, ``get()``, and type casting.
+
+
+Converting Between Pointer Types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use :cpp:func:`GetRef\<T\> <tvm::ffi::GetRef>` to convert a raw ``Object*`` to
+a managed reference:
+
+.. code-block:: cpp
+
+   void ProcessObject(const MyObjectObj* ptr) {
+     // Convert raw pointer to managed reference
+     MyObject ref = ffi::GetRef<MyObject>(ptr);
+     // ref now shares ownership with the original holder
+   }
+
+Use ``ObjectRef::get()`` or ``ObjectPtr::get()`` to obtain a raw pointer 
(non-owning):
+
+.. code-block:: cpp
+
+   MyObject obj = ...;
+   const MyObjectObj* ptr = obj.get();  // Non-owning, valid while obj lives
+
+
+Type System
+-----------
+
+Every object in TVM-FFI carries a runtime type index that enables type-safe
+operations without relying on C++ RTTI (``typeid``, ``dynamic_cast``).
+
+Type Registration
+~~~~~~~~~~~~~~~~~
+
+Types are registered at startup with a unique type key:
+
+- **Built-in types** (String, Array, Map, Tensor, etc.) have statically 
assigned indices
+  defined in :cpp:enum:`TVMFFITypeIndex`.
+- **User-defined types** receive indices dynamically when first accessed via
+  :cpp:func:`TVMFFITypeGetOrAllocIndex`.
+
+The registration happens automatically when you use 
:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO`
+or :c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL`:
+
+.. code-block:: cpp
+
+   // Static type index (built-in types)
+   static constexpr const uint32_t _type_index = TypeIndex::kTVMFFIStr;
+   TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIStr, StringObj, 
Object);
+
+   // Dynamic type index (user-defined types)
+   TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyClass", MyClassObj, Object);
+
+
+Type Checking with IsInstance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :cpp:func:`Object::IsInstance\<T\>() <tvm::ffi::Object::IsInstance>` method
+provides fast runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       const MyObjectObj* ptr = static_cast<const MyObjectObj*>(obj.get());
+       return true;
+     }
+     return false;
+   }
+
+The implementation uses a fast-path optimization for final types and types with
+reserved child slots:
+
+1. **Final types**: Direct index comparison (``object_type_index == 
TargetType::RuntimeTypeIndex()``)
+2. **Types with child slots**: Range check (``type_index ∈ [begin, begin + 
child_slots]``)
+3. **Fallback**: Ancestor chain lookup in the global type table
+
+
+Safe Downcasting
+~~~~~~~~~~~~~~~~
+
+Use ``ObjectRef::as<T>()`` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+
+Type Hierarchy
+~~~~~~~~~~~~~~
+
+TVM-FFI supports single inheritance for object types. Configure inheritance 
behavior
+with these static fields:
+
+.. code-block:: cpp
+
+   class MyBaseObj : public ffi::Object {
+    public:
+     // Reserve slots for up to 10 child types (fast type checking)
+     static constexpr int _type_child_slots = 10;
+     // Allow more children beyond the reserved slots
+     static constexpr bool _type_child_slots_can_overflow = true;
+
+     TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyBase", MyBaseObj, Object);
+   };
+
+   class MyDerivedObj : public MyBaseObj {
+    public:
+     // Final class: no subclasses allowed
+     TVM_FFI_DECLARE_OBJECT_INFO_FINAL("my_ext.MyDerived", MyDerivedObj, 
MyBaseObj);
+   };
+
+
+Reflection System
+-----------------
+
+The reflection system enables cross-language exposure of C++ classes, their 
fields,
+and methods. It is built around :cpp:class:`tvm::ffi::reflection::ObjectDef` 
and
+:cpp:class:`tvm::ffi::reflection::GlobalDef`.
+
+ObjectDef API
+~~~~~~~~~~~~~
+
+:cpp:class:`ObjectDef\<T\> <tvm::ffi::reflection::ObjectDef>` registers 
reflection
+metadata for object type ``T``:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 30 70
+
+   * - Method
+     - Description
+   * - ``.def(init<Args...>())``
+     - Register a constructor with the given argument types
+   * - ``.def_ro("name", &T::field)``
+     - Register a read-only field
+   * - ``.def_rw("name", &T::field)``
+     - Register a read-write field (requires ``_type_mutable = true``)
+   * - ``.def("name", &T::method)``
+     - Register a member method
+   * - ``.def_static("name", &func)``
+     - Register a static method
+
+Example:
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<IntPairObj>()
+         .def(refl::init<int64_t, int64_t>())
+         .def_rw("a", &IntPairObj::a, "the first field")
+         .def_rw("b", &IntPairObj::b, "the second field")
+         .def("sum", &IntPairObj::Sum, "compute a + b");
+   }
+
+
+GlobalDef API
+~~~~~~~~~~~~~
+
+:cpp:class:`GlobalDef <tvm::ffi::reflection::GlobalDef>` registers global 
functions:
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::GlobalDef()
+         .def("my_ext.add_one", [](int x) { return x + 1; })
+         .def("my_ext.greet", [](ffi::String name) {
+           return ffi::String("Hello, " + std::string(name));
+         });
+   }
+
+
+Metadata and Documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Add documentation strings and custom metadata to fields and methods:
+
+.. code-block:: cpp
+
+   refl::ObjectDef<MyObjectObj>()
+       .def_rw("value", &MyObjectObj::value,
+               "The numeric value",                    // docstring
+               refl::DefaultValue(0),                  // default value
+               refl::Metadata{{"min", 0}, {"max", 100}})  // custom metadata
+       .def("compute", &MyObjectObj::Compute,
+            "Perform computation");
+
+
+Python Interoperability
+-----------------------
+
+Object Registration in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use :py:func:`tvm_ffi.register_object` to bind a Python class to a registered 
C++ type:
+
+.. code-block:: python
+
+   import tvm_ffi
+
+   @tvm_ffi.register_object("my_ext.MyObject")
+   class MyObject(tvm_ffi.Object):
+       """Python wrapper for my_ext.MyObject."""
+       value: int
+       name: str
+
+       def __init__(self, value: int, name: str) -> None:
+           self.__ffi_init__(value, name)
+
+       def get_value(self) -> int: ...
+
+The decorator looks up the type key ``"my_ext.MyObject"`` in the C++ type 
registry
+and binds the Python class to it. Fields and methods registered via 
``ObjectDef``
+are automatically available on the Python class.
+
+
+Automatic Fallback Classes
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a C++ object type is returned to Python but no Python class is registered 
for it,
+TVM-FFI automatically generates a fallback class with the registered fields 
and methods:
+
+.. code-block:: python
+
+   # Returns an object of type "my_ext.UnregisteredType"
+   obj = some_ffi_function()
+
+   # Auto-generated class with fields/methods from C++ reflection
+   print(obj.some_field)
+   obj.some_method()
+
+
+Handle and Lifetime
+~~~~~~~~~~~~~~~~~~~
+
+Each Python :py:class:`tvm_ffi.Object` instance holds a C handle (``void*``) 
that
+references the underlying C++ object. The Python wrapper:
+
+- Increments the reference count when constructed
+- Decrements the reference count when garbage collected
+
+.. code-block:: python
+
+   obj = MyObject(42, "test")    # refcount += 1
+   obj2 = obj                    # Python reference, no C++ refcount change
+   del obj                       # Python reference gone, C++ refcount 
unchanged
+   del obj2                      # refcount -= 1, may deallocate
+
+
+Serialization
+-------------
+
+TVM-FFI provides reflection-based serialization via 
:cpp:func:`tvm::ffi::ToJSONGraph`:
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/extra/serialization.h>
+
+   ffi::Any obj = ...;
+   ffi::json::Value json = ffi::ToJSONGraph(obj);
+
+The serialization:
+
+1. Traverses the object graph starting from the root
+2. Assigns each unique object a node index
+3. Serializes each node with its type key and field values
+
+The JSON structure:
+
+.. code-block:: json
+
+   {
+     "root_index": 0,
+     "nodes": [
+       {"type": "my_ext.MyObject", "data": {"value": 42, "name": 1}},
+       {"type": "ffi.Str", "data": "hello"}
+     ]
+   }
+
+Deserialization reconstructs the object graph:
+
+.. code-block:: cpp
+
+   ffi::Any restored = ffi::FromJSONGraph(json);
+
+
+Python Pickle Support
+~~~~~~~~~~~~~~~~~~~~~
+
+Python objects support pickle via ``__getstate__`` / ``__setstate__``:
+
+.. code-block:: python
+
+   import pickle
+
+   obj = MyObject(42, "test")
+   data = pickle.dumps(obj)
+   restored = pickle.loads(data)
+
+
+Object Layout
+-------------
+
+C ABI Header
+~~~~~~~~~~~~
+
+All TVM-FFI objects share a common 24-byte header (:cpp:class:`TVMFFIObject`):
+
+.. code-block:: cpp
+
+   typedef struct {
+     uint64_t combined_ref_count;  // Bytes 0-7: strong + weak ref counts
+     int32_t type_index;           // Bytes 8-11: runtime type identifier
+     uint32_t __padding;           // Bytes 12-15: alignment padding
+     void (*deleter)(void*, int);  // Bytes 16-23: destructor callback
+   } TVMFFIObject;
+
+The ``deleter`` is called when:
+
+- Strong reference count reaches zero (destructor called)
+- Weak reference count reaches zero (memory freed)
+
+
+Object vs ObjectRef Layout
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: cpp
+
+   // Object: header + fields
+   class MyObjectObj : public Object {
+     TVMFFIObject header_;  // 24 bytes (inherited from Object)
+     int64_t value;         // 8 bytes
+     String name;           // 8 bytes (pointer to StringObj)
+   };
+
+   // ObjectRef: just a pointer
+   class MyObject : public ObjectRef {
+     ObjectPtr<Object> data_;  // 8 bytes
+   };

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   This code block illustrating the object layout uses unqualified type names 
like `Object`, `String`, and `ObjectRef`. For clarity and consistency with the 
rest of the document, it would be better to use fully qualified names, e.g., 
`ffi::Object`, `ffi::String`. Also, the comment for `header_` should be updated 
to reflect the inheritance from `ffi::Object`.
   
   ```suggestion
   .. code-block:: cpp
   
      // Object: header + fields
      class MyObjectObj : public ffi::Object {
        TVMFFIObject header_;  // 24 bytes (inherited from ffi::Object)
        int64_t value;         // 8 bytes
        ffi::String name;      // 8 bytes (pointer to StringObj)
      };
   
      // ObjectRef: just a pointer
      class MyObject : public ffi::ObjectRef {
        ObjectPtr<ffi::Object> data_;  // 8 bytes
      };
   ```



##########
docs/concepts/object_and_class.rst:
##########
@@ -0,0 +1,686 @@
+..  Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+..    http://www.apache.org/licenses/LICENSE-2.0
+
+..  Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+Object and Class
+================
+
+TVM-FFI provides a unified object system that enables cross-language 
interoperability
+between C++, Python, and Rust. The object system is built around 
:cpp:class:`tvm::ffi::Object`
+and :cpp:class:`tvm::ffi::ObjectRef`, which together form the foundation for:
+
+- **Type-safe runtime type identification** without relying on C++ RTTI
+- **Intrusive reference counting** for smart memory management
+- **Reflection-based class exposure** across programming languages
+- **Serialization and deserialization** via reflection metadata
+
+This tutorial covers everything you need to know about defining, using, and 
extending
+TVM-FFI objects across languages.
+
+
+Glossary
+--------
+
+:cpp:class:`tvm::ffi::Object`
+  A heap-allocated, reference-counted container.
+  All TVM-FFI objects inherit from this base class and share a common 24-byte 
header
+  that stores reference counts, type index, and a deleter callback.
+
+:cpp:class:`tvm::ffi::ObjectRef`
+  An intrusive pointer that manages an :cpp:class:`~tvm::ffi::Object`'s 
lifetime through reference counting.
+  Its subclasses provide type-safe access to specific object types. In its 
low-level implementation, it is
+  equivalent to a normal C++ pointer to a heap-allocated 
:cpp:class:`~tvm::ffi::Object`.
+
+Type info: type index and type key
+  Type index is an integer that uniquely identifies each object type.
+  Built-in types have statically assigned indices defined in 
:cpp:enum:`TVMFFITypeIndex`,
+  while user-defined types receive indices at startup when first accessed.
+  Type key is a unique string identifier (e.g., ``"my_ext.MyClass"``) that 
names an object type.
+  It is used for registration, serialization, and cross-language mapping.
+
+Common Usage
+------------
+
+Define a Class in C++
+~~~~~~~~~~~~~~~~~~~~~
+
+To define a custom object class in normal C++, inherit it from 
:cpp:class:`tvm::ffi::Object` or its subclasses,
+and then add one of the following macros that declares its metadata:
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO>`
+  Declare an object type that can be subclassed. Type index is assigned 
dynamically.
+
+:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL(TypeKey, TypeName, ParentType) 
<TVM_FFI_DECLARE_OBJECT_INFO_FINAL>`
+  Declare a final object type (no subclasses). Enables faster type checking.
+
+**Example**. The code below shows a minimal example of defining a TVM-FFI 
object class.
+It declares a class ``MyObjectObj`` that inherits from 
:cpp:class:`~tvm::ffi::Object`.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/tvm_ffi.h>
+
+   namespace ffi = tvm::ffi;
+
+   class MyObjectObj : public ffi::Object {
+    public:
+     // Normal C++ code: Declare fields, methods, constructor, destructor, etc.
+     int64_t value;
+     ffi::String name;
+     MyObjectObj(int64_t value, ffi::String name) : value(value), 
name(std::move(name)) {}
+     int64_t GetValue() const { return value; }
+
+     // Declare object type info
+     TVM_FFI_DECLARE_OBJECT_INFO(
+       /*type_key=*/"my_ext.MyObject",
+       /*type_name=*/MyObjectObj,
+       /*parent_type=*/ffi::Object);
+   };
+
+**Managed reference**. Optionally, a managed reference class can be defined by 
inheriting
+from :cpp:class:`~tvm::ffi::ObjectRef` and using one of the following macros 
to define the methods.
+Define its constructor by wrapping the :cpp:func:`tvm::ffi::make_object` 
function.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE>`
+  Define a nullable reference class.
+
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(TypeName, ParentType, 
ObjectName) <TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE>`
+  Define a non-nullable reference class.
+
+
+.. code-block:: cpp
+
+   class MyObject : public ffi::ObjectRef {
+    public:
+     MyObject(int64_t value, ffi::String name) : 
data_(ffi::make_object<MyObjectObj>(value, std::move(name))) {}
+     TVM_FFI_DEFINE_OBJECT_REF_METHODS_NOTNULLABLE(
+        /*type_name=*/MyObject,
+        /*parent_type=*/ffi::ObjectRef,
+        /*object_name=*/MyObjectObj);
+   };
+
+   // Create a managed object
+   MyObject obj = MyObject(42, "hello");
+
+   // Access fields via operator->
+   std::cout << obj->value << std::endl;  // -> 42
+
+
+Expose an Object Class in Python
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Reflection**. The object's metadata is used for reflection. Use 
:cpp:class:`tvm::ffi::reflection::ObjectDef`
+to register an object's constructor, fields, and methods.
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<MyObjectObj>()
+         // Register constructor with signature
+         .def(refl::init<int64_t, ffi::String>())
+         // Register read-write fields
+         .def_rw("value", &MyObjectObj::value, "The integer value")
+         .def_rw("name", &MyObjectObj::name, "The name string")
+         // Register methods
+         .def("get_value", &MyObjectObj::GetValue, "Returns the value");
+   }
+
+**Python binding**. After registration, the object is automatically available 
in Python. Use
+:py:func:`tvm_ffi.register_object` to bind a Python class to a registered C++ 
type:
+
+.. code-block:: python
+
+   import tvm_ffi
+
+   @tvm_ffi.register_object("my_ext.MyObject")
+   class MyObject(tvm_ffi.Object):
+       # tvm-ffi-stubgen(begin): object/my_ext.MyObject
+       value: int
+       name: str
+
+       if TYPE_CHECKING:
+         def __init__(self, value: int, name: str) -> None: ...
+         def get_value(self) -> int: ...
+       # tvm-ffi-stubgen(end)
+
+   # Create and use objects
+   obj = MyObject(42, "hello")
+   print(obj.value)      # -> 42
+   print(obj.get_value())  # -> 42
+   obj.value = 100       # Mutable field access
+
+The decorator looks up the type key ``"my_ext.MyObject"`` in the C++ type 
registry and binds the Python class to it.
+Fields and methods registered via 
:cpp:class:`~tvm::ffi::reflection::ObjectDef` are automatically available on 
the Python class.
+
+
+Type Checks and Casting
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Type checking**. Use :cpp:func:`Object::IsInstance\<T\>() 
<tvm::ffi::Object::IsInstance>`
+for runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       return true;
+     }
+     return false;
+   }
+
+**Type casting**. Use :cpp:func:`ObjectRef::as\<T\>() 
<tvm::ffi::ObjectRef::as>` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+**Type info**. Type index is available via :cpp:func:`ObjectRef::type_index() 
<tvm::ffi::ObjectRef::type_index>`
+and type key is available via :cpp:func:`ObjectRef::GetTypeKey() 
<tvm::ffi::ObjectRef::GetTypeKey>`. These methods
+can be used to safely identify object types without relying on C++ RTTI 
(``typeid``, ``dynamic_cast``).
+
+.. note::
+  C++ RTTI (e.g. ``typeid``, ``dynamic_cast``) is strictly not useful in 
TVM-FFI-based approaches.
+
+Serialization and Deserialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**C++ APIs**. Use :cpp:func:`tvm::ffi::ToJSONGraph` to serialize an object to 
a JSON value,
+and :cpp:func:`tvm::ffi::FromJSONGraph` to deserialize a JSON value to an 
object.
+
+.. code-block:: cpp
+
+   #include <tvm/ffi/extra/serialization.h>
+
+   // Serialize to JSON
+   ffi::Any obj = ...;
+   ffi::json::Value json = ffi::ToJSONGraph(obj);
+
+   // Deserialize from JSON
+   ffi::Any restored = ffi::FromJSONGraph(json);
+
+**Python APIs**. Pickle is overloaded in Python to support TVM-FFI object 
serialization.
+
+.. code-block:: python
+
+   import pickle
+
+   obj = MyObject(42, "test")
+   data = pickle.dumps(obj)
+   restored = pickle.loads(data)
+
+Or explicitly use the :py:func:`tvm_ffi.serialization.to_json_graph_str`
+and :py:func:`tvm_ffi.serialization.from_json_graph_str` to serialize and 
deserialize an object to a JSON string.
+
+
+
+Memory Model
+------------
+
+Reference Counting
+~~~~~~~~~~~~~~~~~~
+
+TVM-FFI uses intrusive reference counting: the reference count is stored 
directly
+in the object header, not in a separate control block. This design:
+
+- Reduces memory overhead (no separate allocation for control block)
+- Improves cache locality
+- Enables efficient cross-language ownership transfer
+
+The :cpp:class:`TVMFFIObject` header stores a 64-bit ``combined_ref_count`` 
that
+packs both strong and weak reference counts:
+
+.. code-block:: cpp
+
+   // Strong ref count: lower 32 bits
+   uint32_t strong_ref_count = combined_ref_count & 0xFFFFFFFF;
+   // Weak ref count: upper 32 bits
+   uint32_t weak_ref_count = (combined_ref_count >> 32) & 0xFFFFFFFF;
+
+.. figure:: 
https://raw.githubusercontent.com/tlc-pack/web-data/main/images/tvm-ffi/stable-c-abi-layout-any.svg
+   :alt: Object header layout
+   :align: center
+
+   Figure 1. The object header stores reference counts, type index, and 
deleter in 24 bytes.
+
+
+ObjectPtr vs ObjectRef
+~~~~~~~~~~~~~~~~~~~~~~
+
+Both :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>` and ``ObjectRef`` 
subclasses
+manage object lifetimes, but serve different purposes:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 25 35 40
+
+   * - Type
+     - Usage
+     - Example
+   * - :cpp:class:`ObjectPtr\<T\> <tvm::ffi::ObjectPtr>`
+     - Low-level smart pointer
+     - ``ObjectPtr<MyObjectObj> ptr = make_object<MyObjectObj>(...);``
+   * - ``ObjectRef`` subclass
+     - Type-safe managed reference
+     - ``MyObject obj(make_object<MyObjectObj>(...));``
+
+The key difference is that ``ObjectRef`` subclasses provide a cleaner API with
+:c:macro:`TVM_FFI_DEFINE_OBJECT_REF_METHODS` generating common operations like
+``operator->``, ``get()``, and type casting.
+
+
+Converting Between Pointer Types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use :cpp:func:`GetRef\<T\> <tvm::ffi::GetRef>` to convert a raw ``Object*`` to
+a managed reference:
+
+.. code-block:: cpp
+
+   void ProcessObject(const MyObjectObj* ptr) {
+     // Convert raw pointer to managed reference
+     MyObject ref = ffi::GetRef<MyObject>(ptr);
+     // ref now shares ownership with the original holder
+   }
+
+Use ``ObjectRef::get()`` or ``ObjectPtr::get()`` to obtain a raw pointer 
(non-owning):
+
+.. code-block:: cpp
+
+   MyObject obj = ...;
+   const MyObjectObj* ptr = obj.get();  // Non-owning, valid while obj lives
+
+
+Type System
+-----------
+
+Every object in TVM-FFI carries a runtime type index that enables type-safe
+operations without relying on C++ RTTI (``typeid``, ``dynamic_cast``).
+
+Type Registration
+~~~~~~~~~~~~~~~~~
+
+Types are registered at startup with a unique type key:
+
+- **Built-in types** (String, Array, Map, Tensor, etc.) have statically 
assigned indices
+  defined in :cpp:enum:`TVMFFITypeIndex`.
+- **User-defined types** receive indices dynamically when first accessed via
+  :cpp:func:`TVMFFITypeGetOrAllocIndex`.
+
+The registration happens automatically when you use 
:c:macro:`TVM_FFI_DECLARE_OBJECT_INFO`
+or :c:macro:`TVM_FFI_DECLARE_OBJECT_INFO_FINAL`:
+
+.. code-block:: cpp
+
+   // Static type index (built-in types)
+   static constexpr const uint32_t _type_index = TypeIndex::kTVMFFIStr;
+   TVM_FFI_DECLARE_OBJECT_INFO_STATIC(StaticTypeKey::kTVMFFIStr, StringObj, 
Object);
+
+   // Dynamic type index (user-defined types)
+   TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyClass", MyClassObj, Object);
+
+
+Type Checking with IsInstance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The :cpp:func:`Object::IsInstance\<T\>() <tvm::ffi::Object::IsInstance>` method
+provides fast runtime type checking:
+
+.. code-block:: cpp
+
+   bool CheckType(const ffi::ObjectRef& obj) {
+     if (obj->IsInstance<MyObjectObj>()) {
+       // obj is a MyObjectObj or subclass
+       const MyObjectObj* ptr = static_cast<const MyObjectObj*>(obj.get());
+       return true;
+     }
+     return false;
+   }
+
+The implementation uses a fast-path optimization for final types and types with
+reserved child slots:
+
+1. **Final types**: Direct index comparison (``object_type_index == 
TargetType::RuntimeTypeIndex()``)
+2. **Types with child slots**: Range check (``type_index ∈ [begin, begin + 
child_slots]``)
+3. **Fallback**: Ancestor chain lookup in the global type table
+
+
+Safe Downcasting
+~~~~~~~~~~~~~~~~
+
+Use ``ObjectRef::as<T>()`` for safe downcasting:
+
+.. code-block:: cpp
+
+   ffi::ObjectRef obj = ...;
+
+   // as<ObjectType>() returns a pointer (nullptr if type doesn't match)
+   if (const MyObjectObj* ptr = obj.as<MyObjectObj>()) {
+     std::cout << ptr->value << std::endl;
+   }
+
+   // as<ObjectRefType>() returns std::optional
+   if (auto opt = obj.as<MyObject>()) {
+     std::cout << opt->get()->value << std::endl;
+   }
+
+
+Type Hierarchy
+~~~~~~~~~~~~~~
+
+TVM-FFI supports single inheritance for object types. Configure inheritance 
behavior
+with these static fields:
+
+.. code-block:: cpp
+
+   class MyBaseObj : public ffi::Object {
+    public:
+     // Reserve slots for up to 10 child types (fast type checking)
+     static constexpr int _type_child_slots = 10;
+     // Allow more children beyond the reserved slots
+     static constexpr bool _type_child_slots_can_overflow = true;
+
+     TVM_FFI_DECLARE_OBJECT_INFO("my_ext.MyBase", MyBaseObj, Object);
+   };
+
+   class MyDerivedObj : public MyBaseObj {
+    public:
+     // Final class: no subclasses allowed
+     TVM_FFI_DECLARE_OBJECT_INFO_FINAL("my_ext.MyDerived", MyDerivedObj, 
MyBaseObj);
+   };
+
+
+Reflection System
+-----------------
+
+The reflection system enables cross-language exposure of C++ classes, their 
fields,
+and methods. It is built around :cpp:class:`tvm::ffi::reflection::ObjectDef` 
and
+:cpp:class:`tvm::ffi::reflection::GlobalDef`.
+
+ObjectDef API
+~~~~~~~~~~~~~
+
+:cpp:class:`ObjectDef\<T\> <tvm::ffi::reflection::ObjectDef>` registers 
reflection
+metadata for object type ``T``:
+
+.. list-table::
+   :header-rows: 1
+   :widths: 30 70
+
+   * - Method
+     - Description
+   * - ``.def(init<Args...>())``
+     - Register a constructor with the given argument types
+   * - ``.def_ro("name", &T::field)``
+     - Register a read-only field
+   * - ``.def_rw("name", &T::field)``
+     - Register a read-write field (requires ``_type_mutable = true``)
+   * - ``.def("name", &T::method)``
+     - Register a member method
+   * - ``.def_static("name", &func)``
+     - Register a static method
+
+Example:
+
+.. code-block:: cpp
+
+   TVM_FFI_STATIC_INIT_BLOCK() {
+     namespace refl = tvm::ffi::reflection;
+     refl::ObjectDef<IntPairObj>()
+         .def(refl::init<int64_t, int64_t>())
+         .def_rw("a", &IntPairObj::a, "the first field")
+         .def_rw("b", &IntPairObj::b, "the second field")
+         .def("sum", &IntPairObj::Sum, "compute a + b");
+   }

Review Comment:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   The example uses `IntPairObj`, but this class is not defined anywhere in 
this document. This can be confusing for readers. Please consider defining 
`IntPairObj` before its use to make the example self-contained and 
understandable.
   
   ```suggestion
   .. code-block:: cpp
   
      class IntPairObj : public ffi::Object {
       public:
        int64_t a;
        int64_t b;
        IntPairObj(int64_t a, int64_t b) : a(a), b(b) {}
        int64_t Sum() const { return a + b; }
   
        TVM_FFI_DECLARE_OBJECT_INFO_FINAL("my_ext.IntPair", IntPairObj, 
ffi::Object);
      };
   
      TVM_FFI_STATIC_INIT_BLOCK() {
        namespace refl = tvm::ffi::reflection;
        refl::ObjectDef<IntPairObj>()
            .def(refl::init<int64_t, int64_t>())
            .def_rw("a", &IntPairObj::a, "the first field")
            .def_rw("b", &IntPairObj::b, "the second field")
            .def("sum", &IntPairObj::Sum, "compute a + b");
      }
   ```



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

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to