Experimental wasm support

This commit is contained in:
2024-03-30 16:20:55 -07:00
parent 348ebf016a
commit 215865a462
3 changed files with 73 additions and 45 deletions

View File

@@ -42,10 +42,25 @@ else()
add_link_options(-Wl,--gc-sections) add_link_options(-Wl,--gc-sections)
endif() endif()
if(EMSCRIPTEN)
# https://github.com/emscripten-core/emscripten/issues/15377#issuecomment-1285167486
add_link_options(-lnodefs.js -lnoderawfs.js)
endif()
include(CheckIncludeFileCXX) include(CheckIncludeFileCXX)
include(CMakePushCheckState) include(CMakePushCheckState)
if(NOT USE_SIMD_FALLBACK) if(NOT USE_SIMD_FALLBACK)
cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_FLAGS -msimd128)
check_include_file_cxx("wasm_simd128.h" HAS_WASM_SIMD)
if(HAS_WASM_SIMD)
# https://emscripten.org/docs/porting/simd.html#using-simd-with-webassembly
add_compile_options(-msimd128)
add_compile_definitions(HAS_WASM_SIMD)
endif()
cmake_pop_check_state()
cmake_push_check_state() cmake_push_check_state()
list(APPEND CMAKE_REQUIRED_FLAGS -mavx) list(APPEND CMAKE_REQUIRED_FLAGS -mavx)
check_include_file_cxx("immintrin.h" HAS_AVX) check_include_file_cxx("immintrin.h" HAS_AVX)
@@ -105,30 +120,50 @@ include(CTest)
if(BUILD_TESTING) if(BUILD_TESTING)
# Shared library version of FoundationDB's skip list implementation # corpus tests, which are test
add_library(skip_list SHARED SkipList.cpp)
target_compile_options(skip_list PRIVATE -fPIC -fno-exceptions
-fvisibility=hidden)
target_include_directories(skip_list PUBLIC ${CMAKE_SOURCE_DIR}/include)
set_target_properties(skip_list PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/skip_list")
set_target_properties(skip_list PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(skip_list PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR})
# Shared library version of a std::unordered_map-based conflict set (point file(GLOB CORPUS_TESTS ${CMAKE_SOURCE_DIR}/corpus/*)
# queries only)
add_library(hash_table SHARED HashTable.cpp)
target_compile_options(hash_table PRIVATE -fPIC -fno-exceptions
-fvisibility=hidden)
target_include_directories(hash_table PUBLIC ${CMAKE_SOURCE_DIR}/include)
set_target_properties(hash_table PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/hash_table")
set_target_properties(hash_table PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
hash_table PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
# extra testing that relies on shared libraries, which aren't available with
# emscripten
if(NOT EMSCRIPTEN)
# Shared library version of FoundationDB's skip list implementation
add_library(skip_list SHARED SkipList.cpp)
target_compile_options(skip_list PRIVATE -fPIC -fno-exceptions
-fvisibility=hidden)
target_include_directories(skip_list PUBLIC ${CMAKE_SOURCE_DIR}/include)
set_target_properties(skip_list PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/skip_list")
set_target_properties(skip_list PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
skip_list PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
# Shared library version of a std::unordered_map-based conflict set (point
# queries only)
add_library(hash_table SHARED HashTable.cpp)
target_compile_options(hash_table PRIVATE -fPIC -fno-exceptions
-fvisibility=hidden)
target_include_directories(hash_table PUBLIC ${CMAKE_SOURCE_DIR}/include)
set_target_properties(
hash_table PROPERTIES LIBRARY_OUTPUT_DIRECTORY
"${CMAKE_BINARY_DIR}/hash_table")
set_target_properties(hash_table PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
set_target_properties(
hash_table PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION
${PROJECT_VERSION_MAJOR})
add_executable(driver_skip_list TestDriver.cpp)
target_compile_options(driver_skip_list PRIVATE ${TEST_FLAGS})
target_link_libraries(driver_skip_list PRIVATE skip_list)
foreach(TEST ${CORPUS_TESTS})
get_filename_component(hash ${TEST} NAME)
add_test(NAME skip_list_${hash} COMMAND driver_skip_list ${TEST})
endforeach()
endif()
# ad hoc testing
add_executable(conflict_set_main ConflictSet.cpp) add_executable(conflict_set_main ConflictSet.cpp)
target_include_directories(conflict_set_main target_include_directories(conflict_set_main
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
@@ -155,10 +190,7 @@ if(BUILD_TESTING)
endif() endif()
endif() endif()
# corpus tests # fuzz/whitebox tests
file(GLOB CORPUS_TESTS ${CMAKE_SOURCE_DIR}/corpus/*)
add_executable(fuzz_driver ConflictSet.cpp FuzzTestDriver.cpp) add_executable(fuzz_driver ConflictSet.cpp FuzzTestDriver.cpp)
target_compile_options(fuzz_driver PRIVATE ${TEST_FLAGS}) target_compile_options(fuzz_driver PRIVATE ${TEST_FLAGS})
if(NOT CMAKE_CROSSCOMPILING) if(NOT CMAKE_CROSSCOMPILING)
@@ -173,8 +205,7 @@ if(BUILD_TESTING)
add_test(NAME conflict_set_fuzz_${hash} COMMAND fuzz_driver ${TEST}) add_test(NAME conflict_set_fuzz_${hash} COMMAND fuzz_driver ${TEST})
endforeach() endforeach()
# tsan # tsan tests
if(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_BUILD_TYPE STREQUAL Debug) if(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_BUILD_TYPE STREQUAL Debug)
add_executable(tsan_driver ConflictSet.cpp FuzzTestDriver.cpp) add_executable(tsan_driver ConflictSet.cpp FuzzTestDriver.cpp)
target_compile_options(tsan_driver PRIVATE ${TEST_FLAGS} -fsanitize=thread) target_compile_options(tsan_driver PRIVATE ${TEST_FLAGS} -fsanitize=thread)
@@ -188,9 +219,14 @@ if(BUILD_TESTING)
endforeach() endforeach()
endif() endif()
# blackbox tests
add_executable(driver TestDriver.cpp) add_executable(driver TestDriver.cpp)
target_compile_options(driver PRIVATE ${TEST_FLAGS}) target_compile_options(driver PRIVATE ${TEST_FLAGS})
target_link_libraries(driver PRIVATE ${PROJECT_NAME}) target_link_libraries(driver PRIVATE ${PROJECT_NAME})
foreach(TEST ${CORPUS_TESTS})
get_filename_component(hash ${TEST} NAME)
add_test(NAME conflict_set_blackbox_${hash} COMMAND driver ${TEST})
endforeach()
add_executable(script_test ScriptTest.cpp) add_executable(script_test ScriptTest.cpp)
target_compile_options(script_test PRIVATE ${TEST_FLAGS}) target_compile_options(script_test PRIVATE ${TEST_FLAGS})
@@ -202,10 +238,6 @@ if(BUILD_TESTING)
add_test(NAME conflict_set_script_${name} COMMAND script_test ${TEST}) add_test(NAME conflict_set_script_${name} COMMAND script_test ${TEST})
endforeach() endforeach()
add_executable(driver_skip_list TestDriver.cpp)
target_compile_options(driver_skip_list PRIVATE ${TEST_FLAGS})
target_link_libraries(driver_skip_list PRIVATE skip_list)
find_program(VALGRIND_EXE valgrind) find_program(VALGRIND_EXE valgrind)
if(VALGRIND_EXE AND NOT CMAKE_CROSSCOMPILING) if(VALGRIND_EXE AND NOT CMAKE_CROSSCOMPILING)
add_test(NAME conflict_set_blackbox_valgrind add_test(NAME conflict_set_blackbox_valgrind
@@ -213,12 +245,6 @@ if(BUILD_TESTING)
$<TARGET_FILE:driver> ${CORPUS_TESTS}) $<TARGET_FILE:driver> ${CORPUS_TESTS})
endif() endif()
foreach(TEST ${CORPUS_TESTS})
get_filename_component(hash ${TEST} NAME)
add_test(NAME conflict_set_blackbox_${hash} COMMAND driver ${TEST})
add_test(NAME skip_list_${hash} COMMAND driver_skip_list ${TEST})
endforeach()
# api smoke tests # api smoke tests
# c90 # c90
@@ -239,7 +265,9 @@ if(BUILD_TESTING)
PROPERTIES CXX_STANDARD_REQUIRED ON) PROPERTIES CXX_STANDARD_REQUIRED ON)
add_test(NAME conflict_set_cxx_api_test COMMAND conflict_set_cxx_api_test) add_test(NAME conflict_set_cxx_api_test COMMAND conflict_set_cxx_api_test)
if(NOT APPLE AND NOT CMAKE_BUILD_TYPE STREQUAL Debug) if(NOT EMSCRIPTEN
AND NOT APPLE
AND NOT CMAKE_BUILD_TYPE STREQUAL Debug)
add_test( add_test(
NAME conflict_set_shared_symbols NAME conflict_set_shared_symbols
COMMAND ${CMAKE_SOURCE_DIR}/test_symbols.sh COMMAND ${CMAKE_SOURCE_DIR}/test_symbols.sh

View File

@@ -177,12 +177,10 @@ struct Arena::ArenaImpl {
uint8_t *begin() { return reinterpret_cast<uint8_t *>(this + 1); } uint8_t *begin() { return reinterpret_cast<uint8_t *>(this + 1); }
}; };
static_assert(sizeof(Arena::ArenaImpl) == 16);
static_assert(alignof(Arena::ArenaImpl) == 8);
inline Arena::Arena(int initialSize) : impl(nullptr) { inline Arena::Arena(int initialSize) : impl(nullptr) {
if (initialSize > 0) { if (initialSize > 0) {
auto allocationSize = align_up(initialSize + sizeof(ArenaImpl), 16); auto allocationSize =
align_up(initialSize + sizeof(ArenaImpl), sizeof(ArenaImpl));
impl = (Arena::ArenaImpl *)safe_malloc(allocationSize); impl = (Arena::ArenaImpl *)safe_malloc(allocationSize);
impl->prev = nullptr; impl->prev = nullptr;
impl->capacity = allocationSize - sizeof(ArenaImpl); impl->capacity = allocationSize - sizeof(ArenaImpl);
@@ -218,7 +216,7 @@ inline void *operator new(size_t size, std::align_val_t align, Arena &arena) {
(arena.impl ? std::max<int>(sizeof(Arena::ArenaImpl), (arena.impl ? std::max<int>(sizeof(Arena::ArenaImpl),
arena.impl->capacity * 2) arena.impl->capacity * 2)
: 0)), : 0)),
16); sizeof(Arena::ArenaImpl));
auto *impl = (Arena::ArenaImpl *)safe_malloc(allocationSize); auto *impl = (Arena::ArenaImpl *)safe_malloc(allocationSize);
impl->prev = arena.impl; impl->prev = arena.impl;
impl->capacity = allocationSize - sizeof(Arena::ArenaImpl); impl->capacity = allocationSize - sizeof(Arena::ArenaImpl);

View File

@@ -1,8 +1,10 @@
#include <ConflictSet.h> #include <ConflictSet.h>
#include <chrono> #include <chrono>
#include <cstdio>
#include <cstring> #include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <string_view>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@@ -131,4 +133,4 @@ int main(int argc, const char **argv) {
checkTime, checkBytes / checkTime * 1e-6, addTime, checkTime, checkBytes / checkTime * 1e-6, addTime,
addBytes / addTime * 1e-6, gcTime / (gcTime + addTime) * 1e2, addBytes / addTime * 1e-6, gcTime / (gcTime + addTime) * 1e2,
double(peakMemory)); double(peakMemory));
} }