Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
6df2ffc
Checkpoint dn_simdhash
kg Mar 27, 2024
2f41984
Checkpoint
kg Mar 27, 2024
059705b
Checkpoint
kg Mar 27, 2024
0017d53
Checkpoint
kg Mar 28, 2024
2cc6a91
Checkpoint
kg Mar 28, 2024
6cf488d
Checkpoint
kg Mar 28, 2024
368c076
Checkpoint
kg Mar 28, 2024
ebc7b97
Checkpoint
kg Mar 28, 2024
335b32e
Checkpoint
kg Mar 28, 2024
12487c8
Checkpoint
kg Mar 28, 2024
9bfc7b6
Add missing files
kg Mar 28, 2024
5b8fec5
Checkpoint
kg Mar 28, 2024
5408f27
Add missing header
kg Mar 28, 2024
8cbf1db
Cleanups and more comments
kg Mar 28, 2024
a3d8622
Checkpoint
kg Mar 28, 2024
53ef795
Fix insertion
kg Mar 28, 2024
0d57f12
Remove generic add and get, they complicate everything for no reason
kg Mar 28, 2024
4a194da
Build fix
kg Mar 28, 2024
e6e29ef
Build fixes
kg Mar 28, 2024
406614b
Cleanup
kg Mar 28, 2024
9c1ed15
When cascading, wrap around to the first bucket when we reach the end…
kg Mar 28, 2024
69cd351
Simplify declaring specializations
kg Mar 28, 2024
58045c1
Cleanup
kg Mar 28, 2024
f354798
Convert spaces to tabs
kg Mar 28, 2024
4fa00c8
Rearrange things so that find_first_matching_suffix gets inlined
kg Mar 28, 2024
48faef8
Basic removal implementation
kg Mar 28, 2024
ab63d5f
Expand tests
kg Mar 28, 2024
ee87e52
Build fixes
kg Mar 28, 2024
bcf8be0
Cleanup
kg Mar 28, 2024
f9db166
MSVC doesn't support warning preprocessor command so use pragma message
kg Mar 28, 2024
8c3efe5
Fix build
kg Mar 28, 2024
ece1efe
Fix build
kg Mar 28, 2024
65862c1
Fix linker problem by defining string comparison and hasher inline
kg Mar 28, 2024
0aaffc2
Match semantics of ghashtable better
kg Mar 28, 2024
24cf824
Checkpoint
kg Mar 28, 2024
5a1af2e
dn_allocator allocations aren't zeroed :)
kg Mar 28, 2024
ff3678a
Cleanup
kg Mar 28, 2024
66b8a19
Use dn_simdhash_string_ptr for namespace lookup cache
kg Mar 28, 2024
9f15f25
Fix build
kg Mar 28, 2024
5011da6
Allow hiding the default specializations of a simdhash so you can wra…
kg Mar 28, 2024
0eb125e
Cache the hashcode of keys in string_ptr since it makes natural cache…
kg Mar 28, 2024
fde9544
Rearrange things to fix C4505
kg Mar 28, 2024
4949c53
Prohibit declaring multiple specializations in one .c file since it w…
kg Mar 28, 2024
c5ce9b2
Maybe fix duplicate include
kg Mar 28, 2024
f99f2cc
Fix use of base foreach for string_ptr hashtable
kg Mar 28, 2024
c848322
Annotate fallthrough in murmurhash for clang
kg Mar 28, 2024
c1a8001
Manually unroll the murmurhash3 duff's device to satisfy clang
kg Mar 28, 2024
d4031a1
Oops
kg Mar 28, 2024
b00cd4a
Fix leaked dn_simdhash_t instance
kg Mar 28, 2024
24d4b84
Cleanup
kg Mar 28, 2024
df8d8f4
Fix truncation warning with 64-bit strlen
kg Mar 29, 2024
e13f48e
Workaround linux x64 linker problem
kg Mar 29, 2024
cb2eb95
Fix GCC build parse error
kg Mar 29, 2024
ef9a132
Cleanup & rearrange things; attempt to fix GCC build
kg Mar 29, 2024
5923050
Updates so test suite works again; verified on linux x64 gcc
kg Mar 29, 2024
099a953
Fix indentation
kg Mar 29, 2024
d6f2bb7
Cleanup
kg Mar 29, 2024
6504f19
Fix foreaches
kg Mar 29, 2024
a47fea2
Split architecture-specific stuff into its own header
kg Mar 29, 2024
8fb0a5a
Specializing foreach means key_is_pointer/value_is_pointer aren't needed
kg Mar 29, 2024
e86c5c4
Cleanup
kg Mar 29, 2024
7b2c15d
Simplify preprocessor token gluing
kg Mar 29, 2024
c22b3d7
Cleanup and improve comments
kg Mar 29, 2024
9708bfa
Align the address of the first bucket
kg Mar 29, 2024
e11fa7d
Comment out neon for now
kg Mar 29, 2024
5525995
Cleanup
kg Mar 29, 2024
3f84231
Alignment and arch-specific pointer size fixes
kg Mar 29, 2024
441079a
Fix ARM clang/gcc build
kg Mar 29, 2024
480432f
Maybe fix CI-specific build issue
kg Mar 29, 2024
ffbfd0f
MSVC docs were wrong :(
kg Mar 29, 2024
1ca0206
Cleanup
kg Mar 29, 2024
4685237
Silence MSVC warnings again
kg Mar 29, 2024
6548031
Rework string_ptr to avoid pre-computing string length, and use a str…
kg Mar 30, 2024
14155c8
Cleanup
kg Mar 30, 2024
dbad5d6
Add dn_simdhash_u32_ptr and use it in mono_image_init_name_cache
kg Mar 30, 2024
6ffe793
Add missing file
kg Mar 30, 2024
c3ea833
Fix type mismatch
kg Apr 1, 2024
4169252
No need to eagerly load the suffixes, and doing so makes scalar fallb…
kg Apr 2, 2024
338b23c
Optimize scalar fallback
kg Apr 2, 2024
f17bd49
Migrate all simdhash fixes and changes from simdhash-2 into simdhash …
kg Apr 3, 2024
d62c7c2
Enable ARM NEON support in simdhash since we have system headers now
kg Apr 4, 2024
31eb0ba
Update utils header from successor branch
kg Apr 8, 2024
4d0150f
Dedupe + improve 64-bit pointer hash
kg Apr 8, 2024
18806f3
Fix windows build
kg Apr 8, 2024
27ac09f
Address PR feedback
kg Apr 10, 2024
39747d0
Broken attempt at configurable assertions
kg Apr 11, 2024
c11823d
Migrate updates from simdhash-2 to simdhash-1
kg Apr 11, 2024
e08be1b
Refactor search vectors
kg Apr 11, 2024
391a5d8
Update assertions
kg Apr 11, 2024
0a1936e
Optimize out unaligned 16-byte copy in scalar wasm find_value
kg Apr 11, 2024
e388a1d
Workaround for weird msimd128 codegen
kg Apr 11, 2024
b4d07d7
Update comments
kg Apr 11, 2024
703a607
Simplify assertions
kg Apr 12, 2024
73c505d
Benchmark harness
kg Apr 12, 2024
97a3b25
Checkpoint
kg Apr 12, 2024
391fdeb
Checkpoint
kg Apr 12, 2024
ae69695
Better missing key measurement
kg Apr 12, 2024
f543c20
Fix sequential/random measurements being meaningfully different
kg Apr 12, 2024
07c398b
Adjustment based on benchmarking
kg Apr 12, 2024
44a7bd3
Add a baseline measurement
kg Apr 12, 2024
9572863
Basic ghashtable comparison measurements
kg Apr 12, 2024
bf03cca
Update makefile
kg Apr 12, 2024
57e6aa2
Check in missing changes; fix mono link error
kg Apr 12, 2024
9107045
Add missing license headers
kg Apr 12, 2024
3d066cc
Partially unroll scalar search for better wasm performance
kg Apr 12, 2024
06efeeb
Fully unroll
kg Apr 13, 2024
8d798f8
Cleanup whitespace / add comment
kg Apr 13, 2024
253d920
Only type-check simdhash instances in debug builds
kg Apr 13, 2024
d90828a
Update makefile switches
kg Apr 13, 2024
5f49036
Fix and add comments
kg Apr 15, 2024
1f2b89f
Make test support windows
kg Apr 15, 2024
5083f40
Make it possible to build benchmark suite using MSVC
kg Apr 15, 2024
af63c5c
Improve MSVC codegen
kg Apr 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Address PR feedback
Do some calculations using uint64_t and bounds check before converting back to uint32_t
Do some key calculations using size_t
Introduce dn_simdhash_assert and use it instead of assert
  • Loading branch information
kg committed Apr 15, 2024
commit 27ac09fabe58f7b7d71bff1ddec4163b8fe6e67e
32 changes: 11 additions & 21 deletions src/native/containers/dn-simdhash-specialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#endif

#include "dn-simdhash.h"
#include "dn-simdhash-utils.h"
#include "dn-simdhash-arch.h"

#ifndef DN_SIMDHASH_T
Expand Down Expand Up @@ -78,26 +79,17 @@ static_assert(DN_SIMDHASH_BUCKET_CAPACITY > 1, "Bucket capacity too low");
// We use memcpy to do an unaligned load when reading dn_simdhash_suffixes, but it's
// still ideal to align instances of bucket_t to match the vector width, so that
// loads are less likely to span two cache lines.
#ifdef _MSC_VER
typedef struct __declspec(align(DN_SIMDHASH_VECTOR_WIDTH)) bucket_t {
#else
typedef struct bucket_t {
#endif
dn_simdhash_suffixes suffixes;
_Alignas(DN_SIMDHASH_VECTOR_WIDTH) dn_simdhash_suffixes suffixes;
DN_SIMDHASH_KEY_T keys[DN_SIMDHASH_BUCKET_CAPACITY];
}
#if defined(__clang__) || defined(__GNUC__)
__attribute__((__aligned__(DN_SIMDHASH_VECTOR_WIDTH))) bucket_t;
#else
bucket_t;
#endif
} bucket_t;

static_assert((sizeof (bucket_t) % DN_SIMDHASH_VECTOR_WIDTH) == 0, "Bucket size is not vector aligned");


// While we've inlined these constants into the specialized code we're generating,
// the generic code in dn-simdhash.c needs them, so we put them in this meta header
// that lives inside every hash instance. (TODO: Store it by-reference?)
// that is referenced by every hash instance.
dn_simdhash_meta_t DN_SIMDHASH_T_META = {
DN_SIMDHASH_BUCKET_CAPACITY,
sizeof(bucket_t),
Expand All @@ -114,7 +106,7 @@ check_self (DN_SIMDHASH_T_PTR self)
// what it should be. This detects passing the wrong kind of simdhash_t pointer
// to one of the APIs, since C doesn't have fully type-safe pointers.
uint8_t ok = self && (self->meta == &DN_SIMDHASH_T_META);
assert(ok);
dn_simdhash_assert(ok);
return ok;
}

Expand Down Expand Up @@ -202,10 +194,10 @@ adjust_cascaded_counts (dn_simdhash_buffers_t buffers, uint32_t first_bucket_ind
if (cascaded_count < 255) {
if (increase)
dn_simdhash_bucket_set_cascaded_count(bucket_address->suffixes, cascaded_count + 1);
else if (cascaded_count < 0)
assert(0);
else
else {
dn_simdhash_assert(cascaded_count > 0);
dn_simdhash_bucket_set_cascaded_count(bucket_address->suffixes, cascaded_count - 1);
}
}
END_SCAN_BUCKETS(first_bucket_index, bucket_index, bucket_address)
}
Expand Down Expand Up @@ -294,8 +286,7 @@ DN_SIMDHASH_REHASH_INTERNAL (DN_SIMDHASH_T_PTR hash, dn_simdhash_buffers_t old_b
0
);
// FIXME: Why doesn't assert(ok) work here? Clang says it's unused
if (ok != DN_SIMDHASH_INSERT_OK)
assert(0);
dn_simdhash_assert(ok == DN_SIMDHASH_INSERT_OK);
END_SCAN_PAIRS(old_buffers, key_address, value_address)
}

Expand Down Expand Up @@ -371,7 +362,7 @@ DN_SIMDHASH_TRY_ADD_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key, ui
case DN_SIMDHASH_INSERT_NEED_TO_GROW:
// We should always have enough space after growing once.
default:
assert(0);
dn_simdhash_assert(0);
return 0;
}
}
Expand Down Expand Up @@ -497,7 +488,6 @@ DN_SIMDHASH_TRY_REPLACE_WITH_HASH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_KEY_T key
{
check_self(hash);

assert(hash);
DN_SIMDHASH_VALUE_T *value_ptr = DN_SIMDHASH_FIND_VALUE_INTERNAL(hash, key, key_hash);
if (!value_ptr)
return 0;
Expand All @@ -515,7 +505,7 @@ void
DN_SIMDHASH_FOREACH (DN_SIMDHASH_T_PTR hash, DN_SIMDHASH_FOREACH_FUNC func, void *user_data)
{
check_self(hash);
assert(func);
dn_simdhash_assert(func);

dn_simdhash_buffers_t buffers = hash->buffers;
BEGIN_SCAN_PAIRS(buffers, key_address, value_address)
Expand Down
53 changes: 40 additions & 13 deletions src/native/containers/dn-simdhash-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@
#define __DN_SIMDHASH_UTILS_H__

#include <stdint.h>
#include <assert.h>

#if defined(__clang__) || defined (__GNUC__)
static DN_FORCEINLINE(uint32_t)
next_power_of_two (uint32_t value) {
if (value < 2)
return 1;
return 1u << (32 - __builtin_clz (value - 1));
}
#else // __clang__ || __GNUC__
static DN_FORCEINLINE(uint32_t)
next_power_of_two (uint32_t value) {
if (value < 2)
return 1;
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}
#endif // __clang__ || __GNUC__

// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
Expand Down Expand Up @@ -61,7 +85,7 @@ MurmurHash3_32_ptr (const void *ptr, uint32_t seed)
// for a presumed 8-byte alignment of addresses (the dlmalloc default).
const uint32_t alignment_shift = 3;
// Compute this outside of the if to suppress msvc build warning
const uint8_t is_64_bit = sizeof(void*) == sizeof(uint32_t);
const uint8_t is_64_bit = sizeof(void*) == sizeof(uint64_t);
union {
uint32_t u32;
uint64_t u64;
Expand All @@ -86,14 +110,6 @@ MurmurHash3_32_ptr (const void *ptr, uint32_t seed)

// end of murmurhash

#if defined(__clang__) || defined (__GNUC__)
#define unlikely(expr) __builtin_expect(!!(expr), 0)
#define likely(expr) __builtin_expect(!!(expr), 1)
#else
#define unlikely(expr) (expr)
#define likely(expr) (expr)
#endif

// FNV has bad properties for simdhash even though it's a fairly fast/good hash,
// but the overhead of having to do strlen() first before passing a string key to
// MurmurHash3 is significant and annoying. This is an attempt to reformulate the
Expand All @@ -119,7 +135,7 @@ murmur3_scan_forward (const uint8_t *ptr)
// I tried to get a loop to auto-unroll, but GCC only unrolls at O3 and MSVC never does.
#define SCAN_1(i) \
result.result.bytes[i] = ptr[i]; \
if (unlikely(!result.result.bytes[i])) \
if (DN_UNLIKELY(!result.result.bytes[i])) \
return result;

SCAN_1(0);
Expand Down Expand Up @@ -147,7 +163,7 @@ MurmurHash3_32_streaming (const uint8_t *key, uint32_t seed)
MURMUR3_HASH_BLOCK(block.result.u32);

// If the scan found a null byte next will be 0, so we stop scanning
if (!block.next)
if (DN_UNLIKELY(!block.next))
break;
block = murmur3_scan_forward(block.next);
}
Expand All @@ -163,7 +179,18 @@ MurmurHash3_32_streaming (const uint8_t *key, uint32_t seed)

// end of reformulated murmur3-32

#undef unlikely
#undef likely
#if defined(__clang__) && !defined(NDEBUG)
#define dn_simdhash_assert(expr) \
if (DN_UNLIKELY(!(expr))) { \
__assert_fail(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
}
#else

#define dn_simdhash_assert(expr) \
if (DN_UNLIKELY(!(expr))) { \
abort(); \
}

#endif

#endif // __DN_SIMDHASH_UTILS_H__
75 changes: 34 additions & 41 deletions src/native/containers/dn-simdhash.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.

#include "dn-simdhash.h"
#include "dn-simdhash-utils.h"

#if defined(__clang__) || defined (__GNUC__)
static DN_FORCEINLINE(uint32_t)
next_power_of_two (uint32_t value) {
if (value < 2)
return 1;
return 1u << (32 - __builtin_clz (value - 1));
}
#else // __clang__ || __GNUC__
static DN_FORCEINLINE(uint32_t)
next_power_of_two (uint32_t value) {
if (value < 2)
return 1;
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
static uint32_t
compute_adjusted_capacity (uint32_t requested_capacity)
{
uint64_t _capacity = requested_capacity;
_capacity *= DN_SIMDHASH_SIZING_PERCENTAGE;
_capacity /= 100;
dn_simdhash_assert(_capacity <= UINT32_MAX);
return (uint32_t)_capacity;
}
#endif // __clang__ || __GNUC__

dn_simdhash_t *
dn_simdhash_new_internal (dn_simdhash_meta_t *meta, dn_simdhash_vtable_t vtable, uint32_t capacity, dn_allocator_t *allocator)
Expand All @@ -33,24 +21,23 @@ dn_simdhash_new_internal (dn_simdhash_meta_t *meta, dn_simdhash_vtable_t vtable,
dn_simdhash_t *result = (dn_simdhash_t *)dn_allocator_alloc(allocator, size);
memset(result, 0, size);

assert(meta);
assert((meta->bucket_capacity > 1) && (meta->bucket_capacity <= DN_SIMDHASH_MAX_BUCKET_CAPACITY));
assert(meta->key_size > 0);
assert(meta->bucket_size_bytes >= (DN_SIMDHASH_VECTOR_WIDTH + (meta->bucket_capacity * meta->key_size)));
dn_simdhash_assert(meta);
dn_simdhash_assert((meta->bucket_capacity > 1) && (meta->bucket_capacity <= DN_SIMDHASH_MAX_BUCKET_CAPACITY));
dn_simdhash_assert(meta->key_size > 0);
dn_simdhash_assert(meta->bucket_size_bytes >= (DN_SIMDHASH_VECTOR_WIDTH + (meta->bucket_capacity * meta->key_size)));
result->meta = meta;
result->vtable = vtable;
result->buffers.allocator = allocator;

capacity = capacity * DN_SIMDHASH_SIZING_PERCENTAGE / 100;
dn_simdhash_ensure_capacity_internal(result, capacity);
dn_simdhash_ensure_capacity_internal(result, compute_adjusted_capacity(capacity));

return result;
}

void
dn_simdhash_free (dn_simdhash_t *hash)
{
assert(hash);
dn_simdhash_assert(hash);
if (hash->vtable.destroy_all)
hash->vtable.destroy_all(hash);
dn_simdhash_buffers_t buffers = hash->buffers;
Expand All @@ -71,18 +58,20 @@ dn_simdhash_free_buffers (dn_simdhash_buffers_t buffers)
dn_simdhash_buffers_t
dn_simdhash_ensure_capacity_internal (dn_simdhash_t *hash, uint32_t capacity)
{
assert(hash);
uint32_t bucket_count = (capacity + hash->meta->bucket_capacity - 1) / hash->meta->bucket_capacity;
dn_simdhash_assert(hash);
size_t bucket_count = (capacity + hash->meta->bucket_capacity - 1) / hash->meta->bucket_capacity;
// FIXME: Only apply this when capacity == 0?
if (bucket_count < DN_SIMDHASH_MIN_BUCKET_COUNT)
bucket_count = DN_SIMDHASH_MIN_BUCKET_COUNT;
dn_simdhash_assert(bucket_count < UINT32_MAX);
// Bucket count must be a power of two (this enables more efficient hashcode -> bucket mapping)
bucket_count = next_power_of_two(bucket_count);
uint32_t value_count = bucket_count * hash->meta->bucket_capacity;
bucket_count = next_power_of_two((uint32_t)bucket_count);
size_t value_count = bucket_count * hash->meta->bucket_capacity;
dn_simdhash_assert(value_count <= UINT32_MAX);

dn_simdhash_buffers_t result = { 0, };
if (bucket_count <= hash->buffers.buckets_length) {
assert(value_count <= hash->buffers.values_length);
dn_simdhash_assert(value_count <= hash->buffers.values_length);
return result;
}

Expand All @@ -96,12 +85,15 @@ dn_simdhash_ensure_capacity_internal (dn_simdhash_t *hash, uint32_t capacity)
// Store old buffers so caller can rehash and then free them
result = hash->buffers;

hash->grow_at_count = value_count * 100 / DN_SIMDHASH_SIZING_PERCENTAGE;
hash->buffers.buckets_length = bucket_count;
hash->buffers.values_length = value_count;
size_t grow_at_count = value_count;
grow_at_count *= 100;
grow_at_count /= DN_SIMDHASH_SIZING_PERCENTAGE;
hash->grow_at_count = (uint32_t)grow_at_count;
hash->buffers.buckets_length = (uint32_t)bucket_count;
hash->buffers.values_length = (uint32_t)value_count;

// pad buckets allocation by the width of one vector so we can align it
uint32_t buckets_size_bytes = (bucket_count * hash->meta->bucket_size_bytes) + DN_SIMDHASH_VECTOR_WIDTH,
size_t buckets_size_bytes = (bucket_count * hash->meta->bucket_size_bytes) + DN_SIMDHASH_VECTOR_WIDTH,
values_size_bytes = value_count * hash->meta->value_size;

hash->buffers.buckets = dn_allocator_alloc(hash->buffers.allocator, buckets_size_bytes);
Expand All @@ -122,7 +114,7 @@ dn_simdhash_ensure_capacity_internal (dn_simdhash_t *hash, uint32_t capacity)
void
dn_simdhash_clear (dn_simdhash_t *hash)
{
assert(hash);
dn_simdhash_assert(hash);
if (hash->vtable.destroy_all)
hash->vtable.destroy_all(hash);
hash->count = 0;
Expand All @@ -134,21 +126,22 @@ dn_simdhash_clear (dn_simdhash_t *hash)
uint32_t
dn_simdhash_capacity (dn_simdhash_t *hash)
{
assert(hash);
dn_simdhash_assert(hash);
return hash->buffers.buckets_length * hash->meta->bucket_capacity;
}

uint32_t
dn_simdhash_count (dn_simdhash_t *hash)
{
assert(hash);
dn_simdhash_assert(hash);
return hash->count;
}

void
dn_simdhash_ensure_capacity (dn_simdhash_t *hash, uint32_t capacity)
{
capacity = capacity * DN_SIMDHASH_SIZING_PERCENTAGE / 100;
dn_simdhash_assert(hash);
capacity = compute_adjusted_capacity(capacity);
dn_simdhash_buffers_t old_buffers = dn_simdhash_ensure_capacity_internal(hash, capacity);
if (old_buffers.buckets) {
hash->vtable.rehash(hash, old_buffers);
Expand Down
6 changes: 0 additions & 6 deletions src/native/containers/dn-simdhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@
// to maintain an ideal load factor. FIXME: 120 isn't right
#define DN_SIMDHASH_SIZING_PERCENTAGE 120

#ifdef _MSC_VER
#define DN_FORCEINLINE(RET_TYPE) __forceinline RET_TYPE
#else
#define DN_FORCEINLINE(RET_TYPE) inline RET_TYPE __attribute__((always_inline))
#endif

typedef struct dn_simdhash_void_data_t {
// HACK: Empty struct or 0-element array produce a MSVC warning and break the build.
uint8_t data[1];
Expand Down
10 changes: 8 additions & 2 deletions src/native/containers/dn-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#define DN_CALLBACK_CALLTYPE
#endif

#if defined(__GNUC__) && (__GNUC__ > 2)
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
#define DN_LIKELY(expr) (__builtin_expect ((expr) != 0, 1))
#define DN_UNLIKELY(expr) (__builtin_expect ((expr) != 0, 0))
#else
Expand All @@ -51,14 +51,20 @@

#define _DN_STATIC_ASSERT(expr) static_assert(expr, "")

#ifdef _MSC_VER
#define DN_FORCEINLINE(RET_TYPE) __forceinline RET_TYPE
#else
#define DN_FORCEINLINE(RET_TYPE) inline RET_TYPE __attribute__((always_inline))
#endif

static inline bool
dn_safe_size_t_multiply (size_t lhs, size_t rhs, size_t *result)
{
if (lhs == 0 || rhs == 0) {
*result = 0;
return true;
}

if (((size_t)(~(size_t)0) / lhs) < rhs)
return false;

Expand Down