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

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


The following commit(s) were added to refs/heads/main by this push:
     new 1382707e8f [FFI][IR] Route JSON serialization through tvm-ffi (#19662)
1382707e8f is described below

commit 1382707e8fde785872283d517c5790d1e9f5cfcb
Author: Tianqi Chen <[email protected]>
AuthorDate: Wed Jun 3 15:58:07 2026 -0400

    [FFI][IR] Route JSON serialization through tvm-ffi (#19662)
    
    TVM can rely on tvm-ffi's JSON graph serialization helpers directly
    instead of routing through TVM-side `node.SaveJSON`/`node.LoadJSON`
    registry entries.
    
    This changes `tvm.ir` save/load to call `tvm_ffi.serialization` with
    `tvm_version` metadata, removes the C++ registry wrapper, and moves the
    disco debug object path to `ffi::ToJSONGraph`/`ffi::FromJSONGraph` plus
    JSON parse/stringify.
    
    The disco Python wrappers now declare Python attribute storage
    explicitly for `DRef` and `Session` so `DPackedFunc`/`DModule` and
    method caches continue to work with the current tvm-ffi object model.
    The socket address helper also normalizes `localhost` consistently
    across constructors so the disco socket debug round-trip can bind an
    IPv4 socket when `localhost` resolves to IPv6 first.
    
    Validated locally in an isolated worktree build with `ninja -C build
    tvm_compiler tvm_runtime_extra`, targeted IR/target tests,
    `tests/python/disco/test_session.py::test_string_obj`, import smoke, and
    touched-file pre-commit.
---
 python/tvm/ir/base.py                   |  8 +++---
 src/ir/serialization.cc                 | 47 ---------------------------------
 src/runtime/extra/disco/protocol.h      | 12 +++------
 tests/python/ir/test_node_reflection.py |  8 ++++++
 4 files changed, 17 insertions(+), 58 deletions(-)

diff --git a/python/tvm/ir/base.py b/python/tvm/ir/base.py
index cff43bb8c1..ceccb401f4 100644
--- a/python/tvm/ir/base.py
+++ b/python/tvm/ir/base.py
@@ -18,9 +18,11 @@
 
 import tvm_ffi
 from tvm_ffi import get_global_func, register_object
+from tvm_ffi.serialization import from_json_graph_str, to_json_graph_str
 
-from tvm.runtime import Object, _ffi_node_api
+from tvm.runtime import Object
 
+from ..base import __version__
 from . import _ffi_api, json_compact
 
 
@@ -141,7 +143,7 @@ def load_json(json_str) -> Object:
     """
 
     json_str = json_compact.upgrade_json(json_str)
-    return _ffi_node_api.LoadJSON(json_str)
+    return from_json_graph_str(json_str)
 
 
 def save_json(node) -> str:
@@ -157,7 +159,7 @@ def save_json(node) -> str:
     json_str : str
         Saved json string.
     """
-    return _ffi_node_api.SaveJSON(node)
+    return to_json_graph_str(node, {"tvm_version": __version__})
 
 
 def structural_equal(lhs, rhs, map_free_vars=False):
diff --git a/src/ir/serialization.cc b/src/ir/serialization.cc
deleted file mode 100644
index fc080802a3..0000000000
--- a/src/ir/serialization.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-/*!
- * \file src/ir/serialization.cc
- * \brief Utilities to serialize TVM AST/IR objects.
- */
-#include <tvm/ffi/extra/json.h>
-#include <tvm/ffi/extra/serialization.h>
-#include <tvm/ffi/reflection/registry.h>
-#include <tvm/runtime/base.h>
-
-namespace tvm {
-
-static std::string SaveJSON(ffi::Any n) {
-  int indent = 2;
-  ffi::json::Object metadata{{"tvm_version", TVM_VERSION}};
-  ffi::json::Value jgraph = ffi::ToJSONGraph(n, metadata);
-  return ffi::json::Stringify(jgraph, indent);
-}
-
-static ffi::Any LoadJSON(std::string json_str) {
-  ffi::json::Value jgraph = ffi::json::Parse(json_str);
-  return ffi::FromJSONGraph(jgraph);
-}
-
-TVM_FFI_STATIC_INIT_BLOCK() {
-  namespace refl = tvm::ffi::reflection;
-  refl::GlobalDef().def("node.SaveJSON", SaveJSON).def("node.LoadJSON", 
LoadJSON);
-}
-}  // namespace tvm
diff --git a/src/runtime/extra/disco/protocol.h 
b/src/runtime/extra/disco/protocol.h
index 89905b7ce1..25662051dc 100644
--- a/src/runtime/extra/disco/protocol.h
+++ b/src/runtime/extra/disco/protocol.h
@@ -19,7 +19,8 @@
 #ifndef TVM_RUNTIME_DISCO_PROTOCOL_H_
 #define TVM_RUNTIME_DISCO_PROTOCOL_H_
 
-#include <tvm/ffi/function.h>
+#include <tvm/ffi/extra/json.h>
+#include <tvm/ffi/extra/serialization.h>
 #include <tvm/runtime/base.h>
 #include <tvm/runtime/disco/session.h>
 #include <tvm/support/io.h>
@@ -233,10 +234,7 @@ inline std::string DiscoDebugObject::SaveToStr() const {
     return result;
   } else if (auto opt_obj = this->data.as<ffi::ObjectRef>()) {
     ffi::ObjectRef obj = opt_obj.value();
-    const auto f = tvm::ffi::Function::GetGlobal("node.SaveJSON");
-    TVM_FFI_CHECK(f.has_value(), ValueError)
-        << "Cannot serialize object in non-debugging mode: " << 
obj->GetTypeKey();
-    std::string result = (*f)(obj).cast<std::string>();
+    std::string result = ffi::json::Stringify(ffi::ToJSONGraph(obj));
     result.push_back('0');
     return result;
   }
@@ -251,9 +249,7 @@ inline ffi::ObjectPtr<DiscoDebugObject> 
DiscoDebugObject::LoadFromStr(std::strin
   json_str.pop_back();
   ffi::ObjectPtr<DiscoDebugObject> result = 
ffi::make_object<DiscoDebugObject>();
   if (control_bit == '0') {
-    const auto f = tvm::ffi::Function::GetGlobal("node.LoadJSON");
-    TVM_FFI_CHECK(f.has_value(), ValueError) << "Cannot deserialize object in 
non-debugging mode";
-    result->data = (*f)(json_str);
+    result->data = ffi::FromJSONGraph(ffi::json::Parse(json_str));
   } else if (control_bit == '1') {
     support::BytesInStream mstrm(json_str);
     support::Base64InStream b64strm(&mstrm);
diff --git a/tests/python/ir/test_node_reflection.py 
b/tests/python/ir/test_node_reflection.py
index 6cfff9d184..dce3fbffeb 100644
--- a/tests/python/ir/test_node_reflection.py
+++ b/tests/python/ir/test_node_reflection.py
@@ -15,6 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 # ruff: noqa: E712, F401, F841
+import json
 import sys
 
 import numpy as np
@@ -37,6 +38,13 @@ def test_const_saveload_json():
     tvm.ir.assert_structural_equal(zz, z, map_free_vars=True)
 
 
+def test_save_json_metadata_version():
+    obj = tvm.runtime.convert([1, 2])
+    json_str = tvm.ir.save_json(obj)
+    assert json.loads(json_str)["metadata"]["tvm_version"] == tvm.__version__
+    assert list(tvm.ir.load_json(json_str)) == [1, 2]
+
+
 def _test_infinity_value(value, dtype):
     x = tvm.tirx.const(value, dtype)
     json_str = tvm.ir.save_json(x)

Reply via email to