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