File 4001-erts-add-enif_term_size.patch of Package erlang

From 993282dab4379472692fc10ce804af317f3ad7a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Claes=20N=C3=A4st=C3=A9n?= <pekdon@gmail.com>
Date: Fri, 27 Feb 2026 16:33:10 +0100
Subject: [PATCH] erts: add enif_term_size

---
 erts/doc/references/erl_nif.md                | 12 ++++++++++++
 erts/emulator/beam/erl_nif.c                  |  5 +++++
 erts/emulator/beam/erl_nif.h                  |  2 +-
 erts/emulator/beam/erl_nif_api_funcs.h        |  2 ++
 erts/emulator/test/nif_SUITE.erl              | 15 +++++++++++++--
 erts/emulator/test/nif_SUITE_data/nif_SUITE.c |  7 +++++++
 6 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/erts/doc/references/erl_nif.md b/erts/doc/references/erl_nif.md
index 5c4e4195a5..8beee75545 100644
--- a/erts/doc/references/erl_nif.md
+++ b/erts/doc/references/erl_nif.md
@@ -3910,6 +3910,18 @@ Sets an [`ErlNifPid`](erl_nif.md#ErlNifPid) variable as undefined. See
 
 Available since OTP 22.0
 
+## enif_term_size()
+
+```c
+unsigned enif_term_size(
+        ERL_NIF_TERM term);
+```
+
+Gets the number of bytes used to store term. The size does not include
+ERL_NIF_TERM itself or binary data held by the term.
+
+Available since OTP 29.0
+
 ## enif_sizeof_resource()
 
 ```c
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index 816945fd75..185cd648b9 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -1576,6 +1576,12 @@ ErlNifUInt64 enif_hash(ErlNifHash type, Eterm term, ErlNifUInt64 salt)
     }
 }
 
+__attribute__((externally_visible))
+size_t enif_term_size(Eterm term)
+{
+    return size_object(term) * sizeof(ERL_NIF_TERM);
+}
+
 __attribute__((externally_visible))
 int enif_get_tuple(ErlNifEnv* env, Eterm tpl, int* arity, const Eterm** array)
 {
diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h
index 0c1ef96836..c7535dfcd6 100644
--- a/erts/emulator/beam/erl_nif.h
+++ b/erts/emulator/beam/erl_nif.h
@@ -63,7 +63,7 @@
 **            enif_make_new_atom_len, ERL_NIF_UTF8
 */
 #define ERL_NIF_MAJOR_VERSION 2
-#define ERL_NIF_MINOR_VERSION 17
+#define ERL_NIF_MINOR_VERSION 18
 
 /*
  * WHEN CHANGING INTERFACE VERSION, also replace erts version below with
diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h
index 0e57ef85c5..41400853b7 100644
--- a/erts/emulator/beam/erl_nif_api_funcs.h
+++ b/erts/emulator/beam/erl_nif_api_funcs.h
@@ -225,6 +225,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_get_string_length, (ErlNifEnv *env, ERL_NIF_TERM
 ERL_NIF_API_FUNC_DECL(int, enif_make_new_atom, (ErlNifEnv *env, const char *name, ERL_NIF_TERM *atom, ErlNifCharEncoding encoding));
 ERL_NIF_API_FUNC_DECL(int, enif_make_new_atom_len, (ErlNifEnv *env, const char *name, size_t len, ERL_NIF_TERM *atom, ErlNifCharEncoding encoding));
 ERL_NIF_API_FUNC_DECL(int, enif_set_option, (ErlNifEnv *env, ErlNifOption opt, ...));
+ERL_NIF_API_FUNC_DECL(size_t,enif_term_size,(ERL_NIF_TERM term));
 
 /*
 ** ADD NEW ENTRIES HERE (before this comment) !!!
@@ -419,6 +420,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_set_option, (ErlNifEnv *env, ErlNifOption opt, .
 #  define enif_make_new_atom ERL_NIF_API_FUNC_MACRO(enif_make_new_atom)
 #  define enif_make_new_atom_len ERL_NIF_API_FUNC_MACRO(enif_make_new_atom_len)
 #  define enif_set_option ERL_NIF_API_FUNC_MACRO(enif_set_option)
+#  define enif_term_size ERL_NIF_API_FUNC_MACRO(enif_term_size)
 /*
 ** ADD NEW ENTRIES HERE (before this comment)
 */
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 62774dd94e..649540d54d 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -81,7 +81,8 @@
          match_state_arg/1,
          pid/1,
          id/1,
-         nif_term_type/1
+         nif_term_type/1,
+         nif_term_size/1
 	]).
 
 -export([many_args_100/100]).
@@ -197,6 +198,7 @@
        is_pid_undefined_nif/1,
        compare_pids_nif/2,
        term_type_nif/1,
+       term_size_nif/1,
        dynamic_resource_call/4,
        msa_find_y_nif/1
       ]).
@@ -251,7 +253,8 @@ all() ->
      nif_ioq,
      match_state_arg,
      pid,
-     nif_term_type].
+     nif_term_type,
+     nif_term_size].
 
 init_per_suite(Config) ->
     erts_debug:set_internal_state(available_internal_state, true),
@@ -4533,6 +4536,13 @@ nif_term_type(Config) ->
 
     ok.
 
+nif_term_size(Config) ->
+    ensure_lib_loaded(Config),
+    0 = term_size_nif(atom),
+    0 = term_size_nif(42),
+    true = term_size_nif(<<"binary data">>) > 0,
+    true = term_size_nif({tuple,<<"binary data">>,atom,[list]}) > 0.
+
 %% Verify match state arguments are not passed to declared NIFs.
 match_state_arg(Config) ->
     ensure_lib_loaded(Config),
@@ -4684,6 +4694,7 @@ is_pid_undefined_nif(_) -> ?nif_stub.
 compare_pids_nif(_, _) -> ?nif_stub.
 
 term_type_nif(_) -> ?nif_stub.
+term_size_nif(_) -> ?nif_stub.
 
 dynamic_resource_call(_,_,_,_) -> ?nif_stub.
 
diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
index 1458656e93..37f6eb7bde 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c
@@ -3854,6 +3854,12 @@ static ERL_NIF_TERM term_type_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
     }
 }
 
+static ERL_NIF_TERM term_size_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+    assert(argc == 1);
+    return enif_make_uint64(env, enif_term_size(argv[0]));
+}
+
 static ERL_NIF_TERM msa_find_y_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
     ErlNifBinary bin;
@@ -3986,6 +3992,7 @@ static ErlNifFunc nif_funcs[] =
     {"is_pid_undefined_nif", 1, is_pid_undefined_nif},
     {"compare_pids_nif", 2, compare_pids_nif},
     {"term_type_nif", 1, term_type_nif},
+    {"term_size_nif", 1, term_size_nif},
     {"msa_find_y_nif", 1, msa_find_y_nif}
 };
 
-- 
2.51.0

openSUSE Build Service is sponsored by