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 3ab87a6bebce441ddf9dfc2541690779fdcaee5a
Author: Nick Vatamaniuc <[email protected]>
AuthorDate: Thu Apr 9 20:34:16 2026 -0400

    No more FLTO
    
    Instead enable the equivalent optimization in compiler using includes and
    static inline functions.
    
    We had bunch of logic to enable FLTO and some issues around it not working
    sometimes. There was snippet even to do a test compile something to see if 
it
    can be enabled at all in the rebar script. Since it provided enough benefit
    that folks wanted it, let's just have an effective LTO all the time. Let's 
put
    the hot-path utilities like utf8 and bump-reductions into a header and use
    `static inline` functions. These will let the compiler do 
the-right-thing(tm)
    and optimize whole compilation unit and will eliminate the need for messing
    around to FLTO linker and compiler options.
---
 c_src/decoder.c                |  1 +
 c_src/encoder.c                |  1 +
 c_src/jiffy.h                  | 24 ++++++------
 c_src/{utf8.c => jiffy_utf8.h} | 87 ++++++++++++++++++++++--------------------
 c_src/util.c                   | 18 ---------
 rebar.config                   |  8 +---
 rebar.config.script            | 25 +-----------
 7 files changed, 64 insertions(+), 100 deletions(-)

diff --git a/c_src/decoder.c b/c_src/decoder.c
index fd2e406..46abfec 100644
--- a/c_src/decoder.c
+++ b/c_src/decoder.c
@@ -9,6 +9,7 @@
 
 #include "erl_nif.h"
 #include "jiffy.h"
+#include "jiffy_utf8.h"
 
 #define STACK_SIZE_INC 64
 #define NUM_BUF_LEN 32
diff --git a/c_src/encoder.c b/c_src/encoder.c
index d952652..c8243fa 100644
--- a/c_src/encoder.c
+++ b/c_src/encoder.c
@@ -6,6 +6,7 @@
 #include <string.h>
 
 #include "jiffy.h"
+#include "jiffy_utf8.h"
 #include "ryu/ryu.h"
 
 #define BIN_INC_SIZE 2048
diff --git a/c_src/jiffy.h b/c_src/jiffy.h
index daf4bd2..252d2fc 100644
--- a/c_src/jiffy.h
+++ b/c_src/jiffy.h
@@ -63,7 +63,19 @@ int get_null_term(ErlNifEnv* env, ERL_NIF_TERM val, 
ERL_NIF_TERM *null_term);
 static inline size_t yield_threshold(size_t bytes_per_red) {
     return bytes_per_red * DEFAULT_ERLANG_REDUCTION_COUNT;
 }
-void bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red);
+
+static inline void
+bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red)
+{
+    size_t reds_used = used / bytes_per_red;
+    size_t pct_used = 100 * reds_used / DEFAULT_ERLANG_REDUCTION_COUNT;
+    if(pct_used > 0) {
+        if(pct_used > 100) {
+            pct_used = 100;
+        }
+        enif_consume_timeslice(env, pct_used);
+    }
+}
 
 ERL_NIF_TERM decode_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 ERL_NIF_TERM decode_iter(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -76,14 +88,4 @@ void enc_destroy(ErlNifEnv* env, void* obj);
 int make_object(ErlNifEnv* env, ERL_NIF_TERM pairs, ERL_NIF_TERM* out,
         int ret_map, int dedupe_keys);
 
-int int_from_hex(const unsigned char* p);
-int int_to_hex(int val, unsigned char* p);
-int utf8_len(int c);
-int utf8_esc_len(int c);
-size_t utf8_validate(unsigned char* data, size_t size);
-int utf8_to_unicode(unsigned char* buf, size_t size);
-int unicode_to_utf8(int c, unsigned char* buf);
-int unicode_from_pair(int hi, int lo);
-int unicode_uescape(int c, unsigned char* buf);
-
 #endif // Included JIFFY_H
diff --git a/c_src/utf8.c b/c_src/jiffy_utf8.h
similarity index 96%
rename from c_src/utf8.c
rename to c_src/jiffy_utf8.h
index 6f8d3bd..b75b9ad 100644
--- a/c_src/utf8.c
+++ b/c_src/jiffy_utf8.h
@@ -1,7 +1,10 @@
 // This file is part of Jiffy released under the MIT license.
 // See the LICENSE file for more information.
-#include "jiffy.h"
-#include <stdio.h>
+
+#ifndef JIFFY_UTF8_H
+#define JIFFY_UTF8_H
+
+#include <string.h>
 
 static const unsigned char hexvals[256] = {
     255, 255, 255, 255, 255, 255, 255, 255,
@@ -46,7 +49,7 @@ static const char hexdigits[16] = {
     'C', 'D', 'E', 'F'
 };
 
-int
+static inline int
 int_from_hex(const unsigned char* p)
 {
     unsigned char* h = (unsigned char*) p;
@@ -65,7 +68,7 @@ int_from_hex(const unsigned char* p)
     return ret;
 }
 
-int
+static inline int
 int_to_hex(int val, unsigned char* p)
 {
     if(val < 0 || val > 65535)
@@ -79,7 +82,7 @@ int_to_hex(int val, unsigned char* p)
     return 1;
 }
 
-int
+static inline int
 utf8_len(int c)
 {
     if(c < 128) {
@@ -99,7 +102,7 @@ utf8_len(int c)
     }
 }
 
-int
+static inline int
 utf8_esc_len(int c)
 {
     if(c < 0x10000) {
@@ -111,7 +114,38 @@ utf8_esc_len(int c)
     }
 }
 
-size_t
+static inline int
+utf8_to_unicode(unsigned char* buf, size_t size)
+{
+    int ret;
+    if((buf[0] & 0x80) == 0x00) {
+        // 0xxxxxxx
+        ret = buf[0];
+    } else if((buf[0] & 0xE0) == 0xC0 && size >= 2) {
+        // 110xxxxy 10yyyyyy
+        ret = ((buf[0] & 0x1F) << 6)
+            | ((buf[1] & 0x3F));
+    } else if((buf[0] & 0xF0) == 0xE0 && size >= 3) {
+        // 1110xxxx 10xyyyyy 10yyyyyy
+        ret = ((buf[0] & 0x0F) << 12)
+            | ((buf[1] & 0x3F) << 6)
+            | ((buf[2] & 0x3F));
+        if(ret >= 0xD800 && ret <= 0xDFFF) {
+            ret = -1;
+        }
+    } else if((buf[0] & 0xF8) == 0xF0 && size >= 4) {
+        // 11110xxx 10xxyyyy 10yyyyyy 10yyyyyy
+        ret = ((buf[0] & 0x07) << 18)
+            | ((buf[1] & 0x3F) << 12)
+            | ((buf[2] & 0x3F) << 6)
+            | ((buf[3] & 0x3F));
+    } else {
+        ret = -1;
+    }
+    return ret;
+}
+
+static inline size_t
 utf8_validate(unsigned char* data, size_t size)
 {
     size_t ulen = 0;
@@ -175,38 +209,7 @@ utf8_validate(unsigned char* data, size_t size)
     return ulen;
 }
 
-int
-utf8_to_unicode(unsigned char* buf, size_t size)
-{
-    int ret;
-    if((buf[0] & 0x80) == 0x00) {
-        // 0xxxxxxx
-        ret = buf[0];
-    } else if((buf[0] & 0xE0) == 0xC0 && size >= 2) {
-        // 110xxxxy 10yyyyyy
-        ret = ((buf[0] & 0x1F) << 6)
-            | ((buf[1] & 0x3F));
-    } else if((buf[0] & 0xF0) == 0xE0 && size >= 3) {
-        // 1110xxxx 10xyyyyy 10yyyyyy
-        ret = ((buf[0] & 0x0F) << 12)
-            | ((buf[1] & 0x3F) << 6)
-            | ((buf[2] & 0x3F));
-        if(ret >= 0xD800 && ret <= 0xDFFF) {
-            ret = -1;
-        }
-    } else if((buf[0] & 0xF8) == 0xF0 && size >= 4) {
-        // 11110xxx 10xxyyyy 10yyyyyy 10yyyyyy
-        ret = ((buf[0] & 0x07) << 18)
-            | ((buf[1] & 0x3F) << 12)
-            | ((buf[2] & 0x3F) << 6)
-            | ((buf[3] & 0x3F));
-    } else {
-        ret = -1;
-    }
-    return ret;
-}
-
-int
+static inline int
 unicode_to_utf8(int c, unsigned char* buf)
 {
     if(c < 0x80) {
@@ -235,7 +238,7 @@ unicode_to_utf8(int c, unsigned char* buf)
     return -1;
 }
 
-int
+static inline int
 unicode_from_pair(int hi, int lo)
 {
     if(hi < 0xD800 || hi >= 0xDC00) return -1;
@@ -243,7 +246,7 @@ unicode_from_pair(int hi, int lo)
     return ((hi & 0x3FF) << 10) + (lo & 0x3FF) + 0x10000;
 }
 
-int
+static inline int
 unicode_uescape(int val, unsigned char* p)
 {
     int n;
@@ -270,3 +273,5 @@ unicode_uescape(int val, unsigned char* p)
     }
     return -1;
 }
+
+#endif // JIFFY_UTF8_H
diff --git a/c_src/util.c b/c_src/util.c
index b1a0242..cc23a15 100644
--- a/c_src/util.c
+++ b/c_src/util.c
@@ -100,21 +100,3 @@ get_null_term(ErlNifEnv* env, ERL_NIF_TERM val, 
ERL_NIF_TERM *null_term)
 
     return 1;
 }
-
-void
-bump_used_reds(ErlNifEnv* env, size_t used, size_t bytes_per_red)
-{
-    size_t reds_used;
-    size_t pct_used;
-
-    reds_used = used / bytes_per_red;
-    pct_used = 100 * reds_used / DEFAULT_ERLANG_REDUCTION_COUNT;
-
-    if(pct_used > 0) {
-        if(pct_used > 100) {
-            pct_used = 100;
-        }
-
-        enif_consume_timeslice(env, pct_used);
-    }
-}
diff --git a/rebar.config b/rebar.config
index 960b5ba..f98a95c 100644
--- a/rebar.config
+++ b/rebar.config
@@ -11,14 +11,8 @@
     % Drop -lerl_interface
     {"ERL_LDFLAGS", " -L$ERL_EI_LIBDIR -lei"},
     {"win32", "ERL_LDFLAGS", " /LIBPATH:$ERL_EI_LIBDIR ei.lib"},
-
-    {".*", "FLTO_FLAG", ""},
-
-    {"(linux|solaris|freebsd|netbsd|openbsd|dragonfly|darwin|gnu)",
-        "CFLAGS", "$CFLAGS -Ic_src/ -g -Wall $FLTO_FLAG -Werror -O3 
-fvisibility=hidden"},
-
     {"(linux|solaris|freebsd|netbsd|openbsd|dragonfly|darwin|gnu)",
-        "LDFLAGS", "$LDFLAGS $FLTO_FLAG"}
+        "CFLAGS", "$CFLAGS -Ic_src/ -g -Wall -Werror -O3 -fvisibility=hidden"}
 ]}.
 
 {eunit_opts, [
diff --git a/rebar.config.script b/rebar.config.script
index 604f4de..375ef6f 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -27,27 +27,6 @@ Config1 = case lists:keyfind(erl_opts, 1, CONFIG) of
         CONFIG ++ [{erl_opts, ErlOpts}]
 end,
 
-Config2 = case os:type() of
-    {unix, _} ->
-        CC = case os:getenv("CC") of
-            false -> "cc";
-            Else -> Else
-        end,
-        FLTO_CHECK = "echo 'int main(int argc, char *argv[]) {return 0;}' | "
-                ++ CC ++ " -c -x c -o /dev/null -flto -",
-        case os:cmd(FLTO_CHECK) of
-            [] ->
-                {port_env, PortEnv} = lists:keyfind(port_env, 1, Config1),
-                NewFlag = {".*", "FLTO_FLAG", "-flto"},
-                NewPortEnv = lists:keyreplace("FLTO_FLAG", 2, PortEnv, 
NewFlag),
-                lists:keyreplace(port_env, 1, Config1, {port_env, NewPortEnv});
-            _ ->
-                Config1
-        end;
-    _ ->
-        Config1
-end,
-
 IsRebar2 = case lists:keyfind(rebar, 1, application:loaded_applications()) of
     {rebar, _Desc, Vsn} ->
         case string:split(Vsn, ".") of
@@ -60,9 +39,9 @@ end,
 
 case IsRebar2 of
     true ->
-        Config2;
+        Config1;
     false ->
-        Config2 ++ [
+        Config1 ++ [
             {plugins, [{pc, "~> 1.15"}]},
             case os:type() of
                 {win32, _} -> {artifacts, ["priv/jiffy.dll"]};

Reply via email to