File 4951-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/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 5c4e4195a5..8beee75545 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -3687,6 +3687,16 @@ if (retval & ERL_NIF_SELECT_STOP_CAL
</func>
<func>
+ <name since="OTP 29.0"><ret>unsigned</ret>
+ <nametext>enif_term_size(ERL_NIF_TERM term)</nametext></name>
+ <fsummary>enif_term_size()</fsummary>
+ <desc>
+ <p>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.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>unsigned</ret>
<nametext>enif_sizeof_resource(void* obj)</nametext></name>
<fsummary>Get the byte size of a resource object.</fsummary>
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