Skip to content

Commit

Permalink
feature: dynamically enable the STRHASHCRC32 optimization.
Browse files Browse the repository at this point in the history
  • Loading branch information
thibaultcha committed Jan 14, 2020
1 parent 8872ce4 commit 5d3d960
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 45 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ before_install:
- export CXX=g++-5

install:
- if [[ "$(uname -m)" == "x86_64" ]]; then XCFLAGS="$XCFLAGS -msse4.2"; fi
- if [[ "$(uname -m)" == "aarch64" ]]; then XCFLAGS="$XCFLAGS -march=armv8-a+crc"; fi
- make -j$JOBS CCDEBUG=-g Q= PREFIX=$PREFIX XCFLAGS="$XCFLAGS" >build.log 2>&1 || (cat build.log && exit 1)
- make install PREFIX=$PREFIX >build.log 2>&1 || (cat build.log && exit 1)
- export PATH="$PREFIX/bin:$PATH"
Expand Down
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,8 @@ local newstate = jit.prngstate(123456)
**syntax:** *ok = jit.crc32()*

Returns a boolean value indicating if the current architecture supports a CRC32
instruction set.

CRC32 support will be checked at runtime if LuaJIT was compiled with `-msse4.2`
on x64 architectures, or `-march=armv8-a+crc` on ARM64.
instruction set. CRC32 support will be checked at runtime on x64 and ARM64
platforms.

CRC32 support allows for this branch to use an optimized string hashing
algorithm. See the [String hashing](#string-hashing) section for details on
Expand Down Expand Up @@ -285,10 +283,8 @@ but makes hash collision attacks harder for strings up to 127 bytes of size
(see `lj_str_new()`).

This optimization is only available for x64 and ARM64 architectures, and will
be enabled if:

1. LuaJIT is compiled with `-msse4.2` on x64, or `-march=armv8-a+crc` on ARM64.
2. A CRC32 instruction set is detected at runtime (see [jit.crc32](#jitcrc32)).
be enabled if a CRC32 instruction set is detected at runtime (see
[jit.crc32](#jitcrc32)).

**Note:** This optimization can be disabled by compiling LuaJIT with
`-DLJ_OR_DISABLE_STRHASHCRC32`.
Expand Down
13 changes: 11 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,15 @@ ALL_GEN= $(LJVM_S) $(ALL_HDRGEN) $(LIB_VMDEFP)
WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
ALL_RM= $(ALL_T) $(ALL_GEN) *.o host/*.o $(WIN_RM)

ifeq (x64,$(TARGET_LJARCH))
lj_str_hash-CFLAGS = -msse4.2
endif
ifeq (arm64,$(TARGET_LJARCH))
lj_str_hash-CFLAGS = -march=armv8-a+crc
endif

F_CFLAGS = $($(patsubst %.c,%-CFLAGS,$<))

##############################################################################
# Build mode handling.
##############################################################################
Expand Down Expand Up @@ -685,8 +694,8 @@ lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c

%.o: %.c
$(E) "CC $@"
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) -c -o $(@:.o=_dyn.o) $<
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) $(F_CFLAGS) -c -o $(@:.o=_dyn.o) $<
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) $(F_CFLAGS) -c -o $@ $<

%.o: %.S
$(E) "ASM $@"
Expand Down
4 changes: 0 additions & 4 deletions src/lib_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,7 @@ LJLIB_CF(jit_prngstate)

LJLIB_CF(jit_crc32)
{
#if LJ_OR_STRHASHCRC32
setboolV(L->top++, lj_check_crc32_support());
#else
setboolV(L->top++, 0);
#endif
return 1;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lj_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
#endif

/* Optimized string hashing, added by OpenResty. */
#if (LUAJIT_TARGET == LUAJIT_ARCH_X64 && defined(__SSE4_2__) || LUAJIT_TARGET == LUAJIT_ARCH_ARM64 && __ARM_FEATURE_CRC32) && defined(__GNUC__)
#if defined(__GNUC__) && (LUAJIT_TARGET == LUAJIT_ARCH_X64 || LUAJIT_TARGET == LUAJIT_ARCH_ARM64)
#ifndef LJ_OR_DISABLE_STRHASHCRC32
#define LJ_OR_STRHASHCRC32 1
#endif
Expand Down
56 changes: 30 additions & 26 deletions src/lj_str_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,39 @@

#include "lj_str_hash.h"

#if LJ_OR_STRHASHCRC32
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
#include "lj_vm.h"

#ifndef F_CPU_SSE4_2
#define F_CPU_SSE4_2 (1 << 20)
#endif

#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
#include <sys/auxv.h>
#include <errno.h>

#ifndef HWCAP_CRC32
#define HWCAP_CRC32 (1 << 7)
#endif
#endif

#if LJ_OR_STRHASHCRC32
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include "lj_vm.h"

#if LUAJIT_TARGET == LUAJIT_ARCH_X64
#include <smmintrin.h>

#define lj_crc32_u32 _mm_crc32_u32
#define lj_crc32_u64 _mm_crc32_u64

#ifndef F_CPU_SSE4_2
#define F_CPU_SSE4_2 (1 << 20)
#endif

#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
#include <sys/auxv.h>
#include <arm_acle.h>
#include <errno.h>

#define lj_crc32_u32 __crc32cw
#define lj_crc32_u64 __crc32cd

#ifndef HWCAP_CRC32
#define HWCAP_CRC32 (1 << 7)
#endif

#else
#error "LJ_OR_STRHASHCRC32 not supported on this architecture"
#endif
Expand Down Expand Up @@ -288,20 +292,6 @@ static void lj_str_hash_init_random(void)

#undef POW2_MASK

LJ_FUNC unsigned char lj_check_crc32_support()
{
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
uint32_t features[4];
if (lj_vm_cpuid(1, features))
return (features[2] & F_CPU_SSE4_2) != 0;
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
uint32_t hwcap = getauxval(AT_HWCAP);
if (hwcap != ENOENT)
return (hwcap & HWCAP_CRC32) != 0;
#endif
return 0;
}

LJ_FUNC void lj_init_strhashfn(global_State *g)
{
static StrHashFunction strhashfn;
Expand All @@ -318,6 +308,20 @@ LJ_FUNC void lj_init_strhashfn(global_State *g)

#endif

LJ_FUNC unsigned char lj_check_crc32_support()
{
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
uint32_t features[4];
if (lj_vm_cpuid(1, features))
return (features[2] & F_CPU_SSE4_2) != 0;
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
uint32_t hwcap = getauxval(AT_HWCAP);
if (hwcap != ENOENT)
return (hwcap & HWCAP_CRC32) != 0;
#endif
return 0;
}

LJ_FUNC MSize lj_str_hash_orig(const char *str, size_t lenx)
{
MSize len = (MSize)lenx;
Expand Down
2 changes: 1 addition & 1 deletion src/lj_str_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
#include "lj_obj.h"

LJ_FUNC MSize lj_str_hash_orig(const char *str, size_t lenx);
LJ_FUNC unsigned char lj_check_crc32_support();

#if LJ_OR_STRHASHCRC32
LJ_FUNC unsigned char lj_check_crc32_support();
LJ_FUNC void lj_init_strhashfn(global_State *g);
#endif

Expand Down
4 changes: 3 additions & 1 deletion t/strhashcrc32.t
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ __DATA__
--- lua
jit.off()
if jit.crc32() then
if os.getenv("NO_STRHASHCRC32") == "1" then
assert(jit.strhashcrc32() == false, "strhashcrc32 should be disabled (LJ_OR_DISABLE_STRHASHCRC32)")
elseif jit.crc32() then
assert(jit.strhashcrc32() == true, "strhashcrc32 should be enabled")
else
assert(jit.strhashcrc32() == false, "strhashcrc32 should be disabled")
Expand Down

0 comments on commit 5d3d960

Please sign in to comment.