This is an automated email from the ASF dual-hosted git repository. nickva pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/couchdb-jiffy.git
commit 5ba849569f27cb607eb0ae1289e4db43d327b072 Author: Nick Vatamaniuc <[email protected]> AuthorDate: Tue Mar 31 00:05:17 2026 -0400 Clean up unused code paths. Make OTP 20 the official minimum version These are based on the new coverage reports * `make_ok()` function is not used anywhere * `CONSUME_TIMESLICE_PRESENT` and SCHEDULE_NIF_PRESENT features are always present * `ERROR()` and `U()` macros are not used. The most "interesting" change is finding out `enif_alloc_resource()` cannot return `NULL` [1][2], and so `dec_new()` and its callers don't have to handle `NULL`s. Which, in turn, eliminated a bunch of `make_error()` calls. With some `make_error()`s removed, it doesn't have to be utility function, so can be moved to the encoder only. When moving `make_error()` to the encoder, noticed those functions along with others should really be static if they are not used from other modules. Since we removed checks for CONSUME_TIMESLICE_PRESENT, which is present since OTP 17 onwards, and to avoid users getting surprises later during C during compilation, make OTP 20 the official minimum OTP version (so far it's been unofficial only). [1] https://www.erlang.org/doc/apps/erts/erl_nif.html#enif_alloc_resource [2] - In [beam/erl_nif.c](https://github.com/erlang/otp/blob/639c85d7400d34c82df962547561cc1dc0a42755/erts/emulator/beam/erl_nif.c#L3121) it calls `bin = erts_create_magic_binary_x()` - In [beam/erl_binary.h](https://github.com/erlang/otp/blob/639c85d7400d34c82df962547561cc1dc0a42755/erts/emulator/beam/erl_binary.h#L407) if the magic binary allocation fails it calls `erts_alloc_n_enomem()` - In [beam/erl_alloc.c](https://github.com/erlang/otp/blob/639c85d7400d34c82df962547561cc1dc0a42755/erts/emulator/beam/erl_alloc.c#L2108) `erts_alloc_n_enomem()` calls `erts_alc_fatal_error()` which calls `erts_exit()` after a bunch of logging and debug dumps. --- c_src/decoder.c | 24 ++++++------------------ c_src/encoder.c | 41 ++++++++++++++++++++++++----------------- c_src/jiffy.h | 10 ---------- c_src/util.c | 26 -------------------------- rebar.config | 2 ++ 5 files changed, 32 insertions(+), 71 deletions(-) diff --git a/c_src/decoder.c b/c_src/decoder.c index 6a1a7fd..f3fcc7f 100644 --- a/c_src/decoder.c +++ b/c_src/decoder.c @@ -10,9 +10,6 @@ #include "erl_nif.h" #include "jiffy.h" -#define U(c) ((unsigned char) (c)) -#define ERROR(i, msg) make_error(st, env, msg) - #define STACK_SIZE_INC 64 #define NUM_BUF_LEN 32 @@ -66,17 +63,17 @@ typedef struct { int st_top; } Decoder; +// Returns an allocated resource or crashes the VM. No need to +// check return pointer for NULL Decoder* dec_new(ErlNifEnv* env) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); + // If enif_alloc_resource cannot allocate it crashes the VM Decoder* d = enif_alloc_resource(st->res_dec, sizeof(Decoder)); + assert(d != NULL); int i; - if(d == NULL) { - return NULL; - } - d->atoms = st; d->bytes_per_red = DEFAULT_BYTES_PER_REDUCTION; @@ -654,10 +651,9 @@ decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) return enif_make_badarg(env); } + // If allocation fails VM will crash. d = dec_new(env); - if(d == NULL) { - return make_error(st, env, "internal_error"); - } + assert(d != NULL); tmp_argv[0] = argv[0]; tmp_argv[1] = enif_make_resource(env, d); @@ -746,7 +742,6 @@ decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) bump_used_reds(env, bytes_processed, d->bytes_per_red); -#if SCHEDULE_NIF_PRESENT return enif_schedule_nif( env, "nif_decode_iter", @@ -755,13 +750,6 @@ decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 5, tmp_argv ); -#else - return enif_make_tuple2( - env, - st->atom_iter, - enif_make_tuple_from_array(env, tmp_argv, 5) - ); -#endif } switch(dec_curr(d)) { diff --git a/c_src/encoder.c b/c_src/encoder.c index 4a68c74..29ff860 100644 --- a/c_src/encoder.c +++ b/c_src/encoder.c @@ -66,7 +66,7 @@ static char* shifts[NUM_SHIFTS] = { }; -Encoder* +static Encoder* enc_new(ErlNifEnv* env) { jiffy_st* st = (jiffy_st*) enif_priv_data(env); @@ -99,7 +99,7 @@ enc_new(ErlNifEnv* env) return e; } -int +static int enc_init(Encoder* e, ErlNifEnv* env) { e->env = env; @@ -116,20 +116,34 @@ enc_destroy(ErlNifEnv* env, void* obj) } } -ERL_NIF_TERM +static ERL_NIF_TERM +make_error(jiffy_st* st, ErlNifEnv* env, const char* error) +{ + return enif_make_tuple2(env, st->atom_error, make_atom(env, error)); +} + +static ERL_NIF_TERM enc_error(Encoder* e, const char* msg) { //assert(0 && msg); return make_error(e->atoms, e->env, msg); } -ERL_NIF_TERM +static ERL_NIF_TERM +make_obj_error(jiffy_st* st, ErlNifEnv* env, + const char* error, ERL_NIF_TERM obj) +{ + ERL_NIF_TERM reason = enif_make_tuple2(env, make_atom(env, error), obj); + return enif_make_tuple2(env, st->atom_error, reason); +} + +static ERL_NIF_TERM enc_obj_error(Encoder* e, const char* msg, ERL_NIF_TERM obj) { return make_obj_error(e->atoms, e->env, msg, obj); } -int +static int enc_flush(Encoder* e) { ERL_NIF_TERM bin; @@ -411,7 +425,7 @@ enc_object_key(ErlNifEnv *env, Encoder* e, ERL_NIF_TERM val) #define P11 100000000000L #define P12 1000000000000L -int +static inline int digits10(ErlNifUInt64 v) { if (v < P01) return 1; @@ -435,7 +449,7 @@ digits10(ErlNifUInt64 v) return 12 + digits10(v / P12); } -unsigned int +static inline unsigned int u64ToAsciiTable(unsigned char *dst, ErlNifUInt64 value) { static const char digits[201] = @@ -464,7 +478,7 @@ u64ToAsciiTable(unsigned char *dst, ErlNifUInt64 value) return length; } -unsigned +static inline unsigned i64ToAsciiTable(unsigned char *dst, ErlNifSInt64 value) { if (value < 0) { @@ -595,7 +609,7 @@ enc_comma(Encoder* e) return 1; } -int +static int enc_map_to_ejson(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM* out) { ErlNifMapIterator iter; @@ -743,7 +757,6 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) termstack_destroy(&stack); bump_used_reds(env, bytes_processed, e->bytes_per_red); -#if SCHEDULE_NIF_PRESENT return enif_schedule_nif( env, "nif_encode_iter", @@ -752,13 +765,7 @@ encode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) 3, tmp_argv ); -#else - return enif_make_tuple2( - env, - st->atom_iter, - enif_make_tuple_from_array(env, tmp_argv, 3) - ); -#endif + } curr = termstack_pop(&stack); diff --git a/c_src/jiffy.h b/c_src/jiffy.h index 351749f..af755da 100644 --- a/c_src/jiffy.h +++ b/c_src/jiffy.h @@ -9,12 +9,6 @@ #define DEFAULT_BYTES_PER_REDUCTION 20 #define DEFAULT_ERLANG_REDUCTION_COUNT 2000 -#define CONSUME_TIMESLICE_PRESENT \ - ((ERL_NIF_MAJOR_VERSION >= 2 && ERL_NIF_MINOR_VERSION >= 4)) - -#define SCHEDULE_NIF_PRESENT \ - ((ERL_NIF_MAJOR_VERSION >= 2 && ERL_NIF_MINOR_VERSION >= 7)) - typedef struct { ERL_NIF_TERM atom_ok; ERL_NIF_TERM atom_error; @@ -49,10 +43,6 @@ typedef struct { } jiffy_st; ERL_NIF_TERM make_atom(ErlNifEnv* env, const char* name); -ERL_NIF_TERM make_ok(jiffy_st* st, ErlNifEnv* env, ERL_NIF_TERM data); -ERL_NIF_TERM make_error(jiffy_st* st, ErlNifEnv* env, const char* error); -ERL_NIF_TERM make_obj_error(jiffy_st* st, ErlNifEnv* env, const char* error, - ERL_NIF_TERM obj); int get_bytes_per_iter(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi); int get_bytes_per_red(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpr); int get_null_term(ErlNifEnv* env, ERL_NIF_TERM val, ERL_NIF_TERM *null_term); diff --git a/c_src/util.c b/c_src/util.c index f6dcb68..5df4fde 100644 --- a/c_src/util.c +++ b/c_src/util.c @@ -14,26 +14,6 @@ make_atom(ErlNifEnv* env, const char* name) return enif_make_atom(env, name); } -ERL_NIF_TERM -make_ok(jiffy_st* st, ErlNifEnv* env, ERL_NIF_TERM value) -{ - return enif_make_tuple2(env, st->atom_ok, value); -} - -ERL_NIF_TERM -make_error(jiffy_st* st, ErlNifEnv* env, const char* error) -{ - return enif_make_tuple2(env, st->atom_error, make_atom(env, error)); -} - -ERL_NIF_TERM -make_obj_error(jiffy_st* st, ErlNifEnv* env, - const char* error, ERL_NIF_TERM obj) -{ - ERL_NIF_TERM reason = enif_make_tuple2(env, make_atom(env, error), obj); - return enif_make_tuple2(env, st->atom_error, reason); -} - int get_bytes_per_iter(ErlNifEnv* env, ERL_NIF_TERM val, size_t* bpi) { @@ -130,7 +110,6 @@ should_yield(size_t used, size_t bytes_per_red) void bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red) { -#if CONSUME_TIMESLICE_PRESENT size_t reds_used; size_t pct_used; @@ -144,9 +123,4 @@ bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red) enif_consume_timeslice(env, pct_used); } -#endif - - (void) env; - (void) used; - (void) bytes_per_red; } diff --git a/rebar.config b/rebar.config index 6ab52c2..2cd6b3b 100644 --- a/rebar.config +++ b/rebar.config @@ -1,3 +1,5 @@ +{require_min_otp_vsn, "20"}. + {port_specs, [ {"priv/jiffy.so", [ "c_src/*.c",
