src/util/copybytes.h
src/util/exhaust.h
src/util/fatbit.h
- src/util/fatbit.c
src/util/join.h
src/util/masked_move.h
src/util/multibit.h
src/util/determinise.h
src/util/dump_mask.cpp
src/util/dump_mask.h
+ src/util/fatbit_build.cpp
+ src/util/fatbit_build.h
src/util/graph.h
src/util/hash.h
src/util/multibit_build.cpp
#include "util/graph.h"
#include "util/make_unique.h"
#include "util/multibit_build.h"
-#include "util/multibit_internal.h"
#include "util/report_manager.h"
#include "util/ue2_containers.h"
#include "util/verify_types.h"
#include "shufticompile.h"
#include "trufflecompile.h"
#include "util/alloc.h"
-#include "util/multibit_internal.h"
+#include "util/multibit_build.h"
#include "util/order_check.h"
#include "util/report_manager.h"
#include "util/verify_types.h"
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2015-2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
#include "util/charreach.h"
#include "util/depth.h"
#include "util/dump_charclass.h"
-#include "util/multibit_internal.h"
+#include "util/multibit_build.h"
#include "util/verify_types.h"
#include <algorithm>
#include "util/compile_context.h"
#include "util/compile_error.h"
#include "util/container.h"
+#include "util/fatbit_build.h"
#include "util/graph_range.h"
#include "util/make_unique.h"
#include "util/multibit_build.h"
engine->ekeyCount = rm.numEkeys();
engine->dkeyCount = rm.numDkeys();
+ engine->dkeyLogSize = fatbit_size(engine->dkeyCount);
engine->invDkeyOffset = dkeyOffset;
copy_bytes(ptr + dkeyOffset, rm.getDkeyToReportTable());
engine->somHorizon = ssm.somPrecision();
engine->somLocationCount = ssm.numSomSlots();
+ engine->somLocationFatbitSize = fatbit_size(engine->somLocationCount);
engine->needsCatchup = bc.needs_catchup ? 1 : 0;
engine->activeArrayCount = activeArrayCount;
engine->activeLeftCount = activeLeftCount;
engine->queueCount = queue_count;
+ engine->activeQueueArraySize = fatbit_size(queue_count);
engine->eagerIterOffset = eagerIterOffset;
engine->handledKeyCount = bc.handledKeys.size();
+ engine->handledKeyFatbitSize = fatbit_size(engine->handledKeyCount);
engine->rolesWithStateCount = bc.numStates;
engine->lastByteHistoryIterOffset = lastByteOffset;
- u32 delay_count = verify_u32(final_id_to_literal.size() - delay_base_id);
- engine->delay_count = delay_count;
+ engine->delay_count =
+ verify_u32(final_id_to_literal.size() - delay_base_id);
+ engine->delay_fatbit_size = fatbit_size(engine->delay_count);
engine->delay_base_id = delay_base_id;
engine->anchored_base_id = anchored_base_id;
engine->anchored_count = delay_base_id - anchored_base_id;
+ engine->anchored_fatbit_size = fatbit_size(engine->anchored_count);
engine->rosePrefixCount = rosePrefixCount;
#include "nfa/nfa_internal.h"
#include "nfa/nfa_kind.h"
#include "util/dump_charclass.h"
-#include "util/multibit_internal.h"
+#include "util/multibit_build.h"
#include "util/multibit.h"
#include <algorithm>
DUMP_U32(t, historyRequired);
DUMP_U32(t, ekeyCount);
DUMP_U32(t, dkeyCount);
+ DUMP_U32(t, dkeyLogSize);
DUMP_U32(t, invDkeyOffset);
DUMP_U32(t, somLocationCount);
+ DUMP_U32(t, somLocationFatbitSize);
DUMP_U32(t, rolesWithStateCount);
DUMP_U32(t, stateSize);
DUMP_U32(t, anchorStateSize);
DUMP_U32(t, activeArrayCount);
DUMP_U32(t, activeLeftCount);
DUMP_U32(t, queueCount);
+ DUMP_U32(t, activeQueueArraySize);
DUMP_U32(t, eagerIterOffset);
DUMP_U32(t, handledKeyCount);
+ DUMP_U32(t, handledKeyFatbitSize);
DUMP_U32(t, leftOffset);
DUMP_U32(t, roseCount);
DUMP_U32(t, lookaroundTableOffset);
DUMP_U64(t, floating_group_mask);
DUMP_U32(t, size);
DUMP_U32(t, delay_count);
+ DUMP_U32(t, delay_fatbit_size);
DUMP_U32(t, delay_base_id);
DUMP_U32(t, anchored_count);
+ DUMP_U32(t, anchored_fatbit_size);
DUMP_U32(t, anchored_base_id);
DUMP_U32(t, maxFloatingDelayedMatch);
DUMP_U32(t, delayRebuildLength);
u32 historyRequired; /**< max amount of history required for streaming */
u32 ekeyCount; /**< number of exhaustion keys */
u32 dkeyCount; /**< number of dedupe keys */
+ u32 dkeyLogSize; /**< size of fatbit for storing dkey log (bytes) */
u32 invDkeyOffset; /**< offset to table mapping from dkeys to the external
* report ids */
u32 somLocationCount; /**< number of som locations required */
+ u32 somLocationFatbitSize; /**< size of SOM location fatbit (bytes) */
u32 rolesWithStateCount; // number of roles with entries in state bitset
u32 stateSize; /* size of the state bitset
* WARNING: not the size of the rose state */
u32 activeArrayCount; //number of nfas tracked in the active array
u32 activeLeftCount; //number of nfas tracked in the active rose array
u32 queueCount; /**< number of nfa queues */
+ u32 activeQueueArraySize; //!< size of fatbit for active queues (bytes)
u32 eagerIterOffset; /**< offset to sparse iter for eager prefixes or 0 if
* none */
/** \brief Number of keys used by CHECK_SET_HANDLED instructions in role
- * programs. Used to size the handled_roles fatbit in scratch. */
+ * programs. */
u32 handledKeyCount;
+ /** \brief Size of the handled keys fatbit in scratch (bytes). */
+ u32 handledKeyFatbitSize;
+
u32 leftOffset;
u32 roseCount;
u32 lookaroundTableOffset; //!< base of lookaround offset list (of s8 values)
rose_group floating_group_mask; /* groups that are used by the ftable */
u32 size; // (bytes)
u32 delay_count; /* number of delayed literal ids. */
+ u32 delay_fatbit_size; //!< size of each delay fatbit in scratch (bytes)
u32 delay_base_id; /* literal id of the first delayed literal.
* delayed literal ids are contiguous */
u32 anchored_count; /* number of anchored literal ids */
+ u32 anchored_fatbit_size; //!< size of each anch fatbit in scratch (bytes)
u32 anchored_base_id; /* literal id of the first literal in the A table.
* anchored literal ids are contiguous */
u32 maxFloatingDelayedMatch; /* max offset that a delayed literal can
#include "state.h"
#include "ue2common.h"
#include "util/exhaust.h"
-#include "util/fatbit.h"
#include "util/multibit.h"
static really_inline
#include "nfa/nfa_api_queue.h"
#include "rose/rose_internal.h"
#include "util/fatbit.h"
-#include "util/multibit.h"
/**
* Determine the space required for a correctly aligned array of fatbit
* structure, laid out as:
*
* - an array of num_entries pointers, each to a fatbit.
- * - an array of fatbit structures, each of size fatbit_size(num_keys).
+ * - an array of fatbit structures, each of size fatbit_len.
+ *
+ * fatbit_len should have been determined at compile time, via the
+ * fatbit_size() call.
*/
static
-size_t fatbit_array_size(u32 num_entries, u32 num_keys) {
+size_t fatbit_array_size(u32 num_entries, u32 fatbit_len) {
size_t len = 0;
// Array of pointers to each fatbit entry.
// Fatbit entries themselves.
len = ROUNDUP_N(len, alignof(struct fatbit));
- len += (size_t)fatbit_size(num_keys) * num_entries;
+ len += (size_t)fatbit_len * num_entries;
return ROUNDUP_N(len, 8); // Round up for potential padding.
}
static
hs_error_t alloc_scratch(const hs_scratch_t *proto, hs_scratch_t **scratch) {
u32 queueCount = proto->queueCount;
- u32 deduperCount = proto->deduper.log_size;
+ u32 activeQueueArraySize = proto->activeQueueArraySize;
+ u32 deduperCount = proto->deduper.dkey_count;
+ u32 deduperLogSize = proto->deduper.log_size;
u32 bStateSize = proto->bStateSize;
u32 tStateSize = proto->tStateSize;
u32 fullStateSize = proto->fullStateSize;
u32 anchored_literal_region_len = proto->anchored_literal_region_len;
- u32 anchored_literal_region_width = proto->anchored_literal_count;
+ u32 anchored_literal_fatbit_size = proto->anchored_literal_fatbit_size;
u32 som_store_size = proto->som_store_count * sizeof(u64a);
u32 som_attempted_store_size = proto->som_store_count * sizeof(u64a);
- u32 som_now_size = fatbit_size(proto->som_store_count);
- u32 som_attempted_size = fatbit_size(proto->som_store_count);
+ u32 som_now_size = proto->som_fatbit_size;
+ u32 som_attempted_size = proto->som_fatbit_size;
struct hs_scratch *s;
struct hs_scratch *s_tmp;
assert(anchored_literal_region_len < 8 * sizeof(s->al_log_sum));
size_t anchored_literal_region_size = fatbit_array_size(
- anchored_literal_region_len, anchored_literal_region_width);
+ anchored_literal_region_len, proto->anchored_literal_fatbit_size);
size_t delay_region_size =
- fatbit_array_size(DELAY_SLOT_COUNT, proto->delay_count);
+ fatbit_array_size(DELAY_SLOT_COUNT, proto->delay_fatbit_size);
// the size is all the allocated stuff, not including the struct itself
size_t size = queue_size + 63
+ bStateSize + tStateSize
+ fullStateSize + 63 /* cacheline padding */
- + fatbit_size(proto->handledKeyCount) /* handled roles */
- + fatbit_size(queueCount) /* active queue array */
- + 2 * fatbit_size(deduperCount) /* need odd and even logs */
- + 2 * fatbit_size(deduperCount) /* ditto som logs */
+ + proto->handledKeyFatbitSize /* handled roles */
+ + activeQueueArraySize /* active queue array */
+ + 2 * deduperLogSize /* need odd and even logs */
+ + 2 * deduperLogSize /* ditto som logs */
+ 2 * sizeof(u64a) * deduperCount /* start offsets for som */
+ anchored_literal_region_size + qmpq_size
+ delay_region_size
for (u32 i = 0; i < DELAY_SLOT_COUNT; i++) {
s->delay_slots[i] = (struct fatbit *)current;
assert(ISALIGNED(s->delay_slots[i]));
- current += fatbit_size(proto->delay_count);
+ current += proto->delay_fatbit_size;
}
current = ROUNDUP_PTR(current, alignof(struct fatbit *));
for (u32 i = 0; i < anchored_literal_region_len; i++) {
s->al_log[i] = (struct fatbit *)current;
assert(ISALIGNED(s->al_log[i]));
- current += fatbit_size(anchored_literal_region_width);
+ current += anchored_literal_fatbit_size;
}
current = ROUNDUP_PTR(current, 8);
assert(ISALIGNED_N(current, 8));
s->aqa = (struct fatbit *)current;
- current += fatbit_size(queueCount);
+ current += activeQueueArraySize;
s->handled_roles = (struct fatbit *)current;
- current += fatbit_size(proto->handledKeyCount);
+ current += proto->handledKeyFatbitSize;
s->deduper.log[0] = (struct fatbit *)current;
- current += fatbit_size(deduperCount);
+ current += deduperLogSize;
s->deduper.log[1] = (struct fatbit *)current;
- current += fatbit_size(deduperCount);
+ current += deduperLogSize;
s->deduper.som_log[0] = (struct fatbit *)current;
- current += fatbit_size(deduperCount);
+ current += deduperLogSize;
s->deduper.som_log[1] = (struct fatbit *)current;
- current += fatbit_size(deduperCount);
+ current += deduperLogSize;
s->som_set_now = (struct fatbit *)current;
current += som_now_size;
proto->anchored_literal_region_len = rose->anchoredDistance;
}
- if (rose->anchored_count > proto->anchored_literal_count) {
+ if (rose->anchored_fatbit_size > proto->anchored_literal_fatbit_size) {
resize = 1;
- proto->anchored_literal_count = rose->anchored_count;
+ proto->anchored_literal_fatbit_size = rose->anchored_fatbit_size;
}
- if (rose->delay_count > proto->delay_count) {
+ if (rose->delay_fatbit_size > proto->delay_fatbit_size) {
resize = 1;
- proto->delay_count = rose->delay_count;
+ proto->delay_fatbit_size = rose->delay_fatbit_size;
}
- if (rose->handledKeyCount > proto->handledKeyCount) {
+ if (rose->handledKeyFatbitSize > proto->handledKeyFatbitSize) {
resize = 1;
- proto->handledKeyCount = rose->handledKeyCount;
+ proto->handledKeyFatbitSize = rose->handledKeyFatbitSize;
}
if (rose->tStateSize > proto->tStateSize) {
proto->som_store_count = som_store_count;
}
+ if (rose->somLocationFatbitSize > proto->som_fatbit_size) {
+ resize = 1;
+ proto->som_fatbit_size = rose->somLocationFatbitSize;
+ }
+
u32 queueCount = rose->queueCount;
if (queueCount > proto->queueCount) {
resize = 1;
proto->queueCount = queueCount;
}
+ if (rose->activeQueueArraySize > proto->activeQueueArraySize) {
+ resize = 1;
+ proto->activeQueueArraySize = rose->activeQueueArraySize;
+ }
+
u32 bStateSize = 0;
if (rose->mode == HS_MODE_BLOCK) {
bStateSize = rose->stateOffsets.end;
proto->fullStateSize = fullStateSize;
}
- if (rose->dkeyCount > proto->deduper.log_size) {
+ if (rose->dkeyCount > proto->deduper.dkey_count) {
resize = 1;
- proto->deduper.log_size = rose->dkeyCount;
+ proto->deduper.dkey_count = rose->dkeyCount;
+ proto->deduper.log_size = rose->dkeyLogSize;
}
if (resize) {
struct fatbit *log[2]; /**< even, odd logs */
struct fatbit *som_log[2]; /**< even, odd fatbit logs for som */
u64a *som_start_log[2]; /**< even, odd start offset logs for som */
+ u32 dkey_count;
u32 log_size;
u64a current_report_offset;
u8 som_log_dirty;
u32 magic;
u8 in_use; /**< non-zero when being used by an API call. */
u32 queueCount;
+ u32 activeQueueArraySize; /**< size of active queue array fatbit in bytes */
u32 bStateSize; /**< sizeof block mode states */
u32 tStateSize; /**< sizeof transient rose states */
u32 fullStateSize; /**< size of uncompressed nfa state */
struct core_info core_info;
struct match_deduper deduper;
u32 anchored_literal_region_len;
- u32 anchored_literal_count;
+ u32 anchored_literal_fatbit_size; /**< size of each anch fatbit in bytes */
struct fatbit *handled_roles; /**< fatbit of ROLES (not states) already
* handled by this literal */
u64a *som_store; /**< array of som locations */
* location had been writable */
u64a som_set_now_offset; /**< offset at which som_set_now represents */
u32 som_store_count;
- u32 handledKeyCount;
- u32 delay_count;
+ u32 som_fatbit_size; /**< size of som location fatbit structures in bytes */
+ u32 handledKeyFatbitSize; /**< size of handled_keys fatbit in bytes */
+ u32 delay_fatbit_size; /**< size of each delay fatbit in bytes */
u32 scratchSize;
char *scratch_alloc; /* user allocated scratch object */
u8 ALIGN_DIRECTIVE fdr_temp_buf[FDR_TEMP_BUF_SIZE];
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2015-2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
#include "scratch_dump.h"
#include "hs_internal.h"
#include "ue2common.h"
-#include "util/multibit_internal.h"
+#include "util/multibit_build.h"
#include "nfa/nfa_api_queue.h"
#include "rose/rose_internal.h"
fprintf(f, " queues : %zu bytes\n",
s->queueCount * sizeof(struct mq));
fprintf(f, " bStateSize : %u bytes\n", s->bStateSize);
- fprintf(f, " active queue array : %u bytes\n",
- mmbit_size(s->queueCount));
+ fprintf(f, " active queue array : %u bytes\n", s->activeQueueArraySize);
fprintf(f, " qmpq : %zu bytes\n",
s->queueCount * sizeof(struct queue_match));
fprintf(f, " delay info : %u bytes\n",
- mmbit_size(s->delay_count) * DELAY_SLOT_COUNT);
+ s->delay_fatbit_size * DELAY_SLOT_COUNT);
}
} // namespace ue2
#include "multibit.h"
#include "ue2common.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define MIN_FAT_SIZE 32
struct fatbit {
return mmbit_iterate(bits->fb_int.raw, total_bits, it_in);
}
-/** \brief Return the size in bytes of a fatbit that can store the given
- * number of bits.
- *
- * Not for use in performance-critical code, implementation is in fatbit.c.
- */
-u32 fatbit_size(u32 total_bits);
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include "fatbit_build.h"
+
#include "fatbit.h"
-#include "multibit.h"
+#include "multibit_build.h"
+
+#include <algorithm>
+
+using namespace std;
+
+namespace ue2 {
u32 fatbit_size(u32 total_bits) {
- return MAX(sizeof(struct fatbit), mmbit_size(total_bits));
+ return max(u32{sizeof(struct fatbit)}, mmbit_size(total_bits));
}
+
+} // namespace ue2
--- /dev/null
+/*
+ * Copyright (c) 2016, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file
+ * \brief Fatbit: build code
+ */
+
+#ifndef FATBIT_BUILD_H
+#define FATBIT_BUILD_H
+
+#include "ue2common.h"
+
+namespace ue2 {
+
+/**
+ * \brief Return the size in bytes of a fatbit that can store the given
+ * number of bits.
+ */
+u32 fatbit_size(u32 total_bits);
+
+} // namespace ue2
+
+#endif // FATBIT_BUILD_H
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2015-2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
1 + (1 << MMB_KEY_SHIFT) + (1 << MMB_KEY_SHIFT * 2) + (1 << MMB_KEY_SHIFT * 3) + (1 << MMB_KEY_SHIFT * 4),
1 + (1 << MMB_KEY_SHIFT) + (1 << MMB_KEY_SHIFT * 2) + (1 << MMB_KEY_SHIFT * 3) + (1 << MMB_KEY_SHIFT * 4) + (1 << MMB_KEY_SHIFT * 5),
};
-
-u32 mmbit_size(u32 total_bits) {
- MDEBUG_PRINTF("%u\n", total_bits);
-
- // Flat model multibit structures are just stored as a bit vector.
- if (total_bits <= MMB_FLAT_MAX_BITS) {
- return ROUNDUP_N(total_bits, 8) / 8;
- }
-
- u64a current_level = 1; // Number of blocks on current level.
- u64a total = 0; // Total number of blocks.
- while (current_level * MMB_KEY_BITS < total_bits) {
- total += current_level;
- current_level <<= MMB_KEY_SHIFT;
- }
-
- // Last level is a one-for-one bit vector. It needs room for total_bits
- // elements, rounded up to the nearest block.
- u64a last_level = ((u64a)total_bits + MMB_KEY_BITS - 1) / MMB_KEY_BITS;
- total += last_level;
-
- assert(total * sizeof(MMB_TYPE) <= UINT32_MAX);
- return (u32)(total * sizeof(MMB_TYPE));
-}
-
-#ifdef DUMP_SUPPORT
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/** \brief Dump a sparse iterator's keys to stdout. */
-void mmbit_sparse_iter_dump(const struct mmbit_sparse_iter *it,
- u32 total_bits) {
- // Expediency and future-proofing: create a temporary multibit of the right
- // size with all the bits on, then walk it with this sparse iterator.
- size_t bytes = mmbit_size(total_bits);
- u8 *bits = malloc(bytes);
- if (!bits) {
- printf("Failed to alloc %zu bytes for temp multibit", bytes);
- return;
- }
- for (u32 i = 0; i < total_bits; i++) {
- mmbit_set_i(bits, total_bits, i);
- }
-
- struct mmbit_sparse_state s[MAX_SPARSE_ITER_STATES];
- u32 idx = 0;
- for (u32 i = mmbit_sparse_iter_begin(bits, total_bits, &idx, it, s);
- i != MMB_INVALID;
- i = mmbit_sparse_iter_next(bits, total_bits, i, &idx, it, s)) {
- printf("%u ", i);
- }
-
- printf("(%u keys)", idx + 1);
-
- free(bits);
-}
-
-#endif // DUMP_SUPPORT
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2015-2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
#include "scatter.h"
#include "ue2common.h"
#include "rose/rose_build_scatter.h"
+#include "util/compile_error.h"
#include <cassert>
#include <cstring> // for memset
namespace ue2 {
+u32 mmbit_size(u32 total_bits) {
+ if (total_bits > MMB_MAX_BITS) {
+ throw ResourceLimitError();
+ }
+
+ // Flat model multibit structures are just stored as a bit vector.
+ if (total_bits <= MMB_FLAT_MAX_BITS) {
+ return ROUNDUP_N(total_bits, 8) / 8;
+ }
+
+ u64a current_level = 1; // Number of blocks on current level.
+ u64a total = 0; // Total number of blocks.
+ while (current_level * MMB_KEY_BITS < total_bits) {
+ total += current_level;
+ current_level <<= MMB_KEY_SHIFT;
+ }
+
+ // Last level is a one-for-one bit vector. It needs room for total_bits
+ // elements, rounded up to the nearest block.
+ u64a last_level = ((u64a)total_bits + MMB_KEY_BITS - 1) / MMB_KEY_BITS;
+ total += last_level;
+
+ assert(total * sizeof(MMB_TYPE) <= UINT32_MAX);
+ return (u32)(total * sizeof(MMB_TYPE));
+}
+
namespace {
struct TreeNode {
MMB_TYPE mask = 0;
assert(out.empty());
assert(!bits.empty());
assert(total_bits > 0);
+ assert(total_bits <= MMB_MAX_BITS);
DEBUG_PRINTF("building sparse iter for %zu of %u bits\n",
bits.size(), total_bits);
namespace ue2 {
+/**
+ * \brief Return the size in bytes of a multibit that can store the given
+ * number of bits.
+ *
+ * This will throw a resource limit assertion if the requested mmbit is too
+ * large.
+ */
+u32 mmbit_size(u32 total_bits);
+
/** \brief Construct a sparse iterator over the values in \a bits for a
* multibit of size \a total_bits. */
void mmbBuildSparseIterator(std::vector<mmbit_sparse_iter> &out,
/*
- * Copyright (c) 2015, Intel Corporation
+ * Copyright (c) 2015-2016, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
typedef u64a MMB_TYPE; /**< Basic block type for mmbit operations. */
#define MMB_MAX_LEVEL 6 /**< Maximum level in the mmbit pyramid. */
+/** \brief Maximum number of keys (bits) in a multibit. */
+#define MMB_MAX_BITS (1U << 31)
+
/** \brief Sparse iterator record type.
*
* A sparse iterator is a tree of these records, where val identifies the
/** \brief Maximum number of \ref mmbit_sparse_state that could be needed. */
#define MAX_SPARSE_ITER_STATES (6 + 1)
-/** \brief Return the size in bytes of a multibit that can store the given
- * number of bits.
- *
- * Not for use in performance-critical code, implementation is in multibit.c.
- */
-u32 mmbit_size(u32 total_bits);
-
#ifdef __cplusplus
} // extern "C"
#endif
#include "gtest/gtest.h"
#include "ue2common.h"
+#include "util/compile_error.h"
#include "util/make_unique.h"
#include "util/multibit.h"
#include "util/multibit_build.h"
-#include "util/target_info.h"
#include <algorithm>
#include <memory>
{ 1U << 29, 24413 },
{ 1U << 30, 50377 },
{ 1U << 31, 104729 },
-
- // { UINT32_MAX, 104729 }, // Very slow
};
INSTANTIATE_TEST_CASE_P(MultiBit, MultiBitTest, ValuesIn(multibitTests));
+TEST(MultiBit, SizeTooBig) {
+ ASSERT_NO_THROW(mmbit_size(MMB_MAX_BITS));
+ ASSERT_THROW(mmbit_size(MMB_MAX_BITS + 1), ResourceLimitError);
+}