aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/index.c')
-rw-r--r--erts/emulator/beam/index.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c
new file mode 100644
index 0000000000..a4a3007f93
--- /dev/null
+++ b/erts/emulator/beam/index.c
@@ -0,0 +1,137 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1996-2009. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "sys.h"
+#include "erl_vm.h"
+#include "global.h"
+#include "index.h"
+
+void index_info(int to, void *arg, IndexTable *t)
+{
+ hash_info(to, arg, &t->htable);
+ erts_print(to, arg, "=index_table:%s\n", t->htable.name);
+ erts_print(to, arg, "size: %d\n", t->size);
+ erts_print(to, arg, "limit: %d\n", t->limit);
+ erts_print(to, arg, "entries: %d\n",t->entries);
+}
+
+
+/*
+ * Returns size of table in bytes. Stored objects not included.
+ */
+int
+index_table_sz(IndexTable *t)
+{
+ return (sizeof(IndexTable)
+ - sizeof(Hash)
+ + t->size*sizeof(IndexSlot*)
+ + hash_table_sz(&(t->htable)));
+}
+
+
+/*
+** init a pre allocated or static hash structure
+** and allocate buckets.
+*/
+IndexTable*
+erts_index_init(ErtsAlcType_t type, IndexTable* t, char* name,
+ int size, int limit, HashFunctions fun)
+{
+ Uint base_size = ((limit+INDEX_PAGE_SIZE-1)/INDEX_PAGE_SIZE)*sizeof(IndexSlot*);
+ hash_init(type, &t->htable, name, 3*size/4, fun);
+
+ t->size = 0;
+ t->limit = limit;
+ t->entries = 0;
+ t->type = type;
+ t->seg_table = (IndexSlot***) erts_alloc(type, base_size);
+ return t;
+}
+
+int
+index_put(IndexTable* t, void* tmpl)
+{
+ int ix;
+ IndexSlot* p = (IndexSlot*) hash_put(&t->htable, tmpl);
+
+ if (p->index >= 0) {
+ return p->index;
+ }
+
+ ix = t->entries;
+ if (ix >= t->size) {
+ Uint sz;
+ if (ix >= t->limit) {
+ erl_exit(1, "no more index entries in %s (max=%d)\n",
+ t->htable.name, t->limit);
+ }
+ sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*);
+ t->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(t->type, sz);
+ t->size += INDEX_PAGE_SIZE;
+ }
+ t->entries++;
+ p->index = ix;
+ t->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p;
+ return ix;
+}
+
+int index_get(IndexTable* t, void* tmpl)
+{
+ IndexSlot* p = (IndexSlot*) hash_get(&t->htable, tmpl);
+
+ if (p != NULL) {
+ return p->index;
+ }
+ return -1;
+}
+
+void erts_index_merge(Hash* src, IndexTable* dst)
+{
+ int limit = src->size;
+ HashBucket** bucket = src->bucket;
+ int i;
+
+ for (i = 0; i < limit; i++) {
+ HashBucket* b = bucket[i];
+ IndexSlot* p;
+ int ix;
+
+ while (b) {
+ Uint sz;
+ ix = dst->entries++;
+ if (ix >= dst->size) {
+ if (ix >= dst->limit) {
+ erl_exit(1, "no more index entries in %s (max=%d)\n",
+ dst->htable.name, dst->limit);
+ }
+ sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*);
+ dst->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(dst->type, sz);
+ dst->size += INDEX_PAGE_SIZE;
+ }
+ p = (IndexSlot*) b;
+ p->index = ix;
+ dst->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p;
+ b = b->next;
+ }
+ }
+}