summaryrefslogtreecommitdiff
path: root/vere/pkg/noun/v2/hashtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'vere/pkg/noun/v2/hashtable.c')
-rw-r--r--vere/pkg/noun/v2/hashtable.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/vere/pkg/noun/v2/hashtable.c b/vere/pkg/noun/v2/hashtable.c
new file mode 100644
index 0000000..a4f0291
--- /dev/null
+++ b/vere/pkg/noun/v2/hashtable.c
@@ -0,0 +1,143 @@
+/// @file
+
+#include "../hashtable.h"
+#include "v1/hashtable.h"
+#include "v2/hashtable.h"
+
+#include "../allocate.h"
+#include "v1/allocate.h"
+#include "v2/allocate.h"
+
+/* _ch_v2_popcount(): number of bits set in word. A standard intrinsic.
+** NB: copy of _ch_v2_popcount in pkg/noun/hashtable.c
+*/
+static c3_w
+_ch_v2_popcount(c3_w num_w)
+{
+ return __builtin_popcount(num_w);
+}
+
+/* _ch_v2_free_buck(): free bucket
+** NB: copy of _ch_v2_free_buck in pkg/noun/hashtable.c
+*/
+static void
+_ch_v2_free_buck(u3h_v2_buck* hab_u)
+{
+ c3_w i_w;
+
+ for ( i_w = 0; i_w < hab_u->len_w; i_w++ ) {
+ u3z(u3h_v2_slot_to_noun(hab_u->sot_w[i_w]));
+ }
+ u3a_v2_wfree(hab_u);
+}
+
+/* _ch_v2_free_node(): free node.
+*/
+static void
+_ch_v2_free_node(u3h_v2_node* han_u, c3_w lef_w)
+{
+ c3_w len_w = _ch_v2_popcount(han_u->map_w);
+ c3_w i_w;
+
+ lef_w -= 5;
+
+ for ( i_w = 0; i_w < len_w; i_w++ ) {
+ c3_w sot_w = han_u->sot_w[i_w];
+
+ if ( _(u3h_v2_slot_is_noun(sot_w)) ) {
+ u3z(u3h_v2_slot_to_noun(sot_w));
+ }
+ else {
+ // NB: u3h_v2_slot_to_node()
+ void* hav_v = u3h_v2_slot_to_node(sot_w);
+
+ if ( 0 == lef_w ) {
+ _ch_v2_free_buck(hav_v);
+ } else {
+ _ch_v2_free_node(hav_v, lef_w);
+ }
+ }
+ }
+ u3a_v2_wfree(han_u);
+}
+
+/* _ch_v2_rewrite_buck(): rewrite buck for compaction.
+*/
+void
+_ch_v2_rewrite_buck(u3h_v2_buck* hab_u)
+{
+ if ( c3n == u3a_v2_rewrite_ptr(hab_u) ) return;
+ c3_w i_w;
+
+ for ( i_w = 0; i_w < hab_u->len_w; i_w++ ) {
+ u3_noun som = u3h_v2_slot_to_noun(hab_u->sot_w[i_w]);
+ hab_u->sot_w[i_w] = u3h_v2_noun_to_slot(u3a_v2_rewritten_noun(som));
+ u3a_v2_rewrite_noun(som);
+ }
+}
+
+/* _ch_v2_rewrite_node(): rewrite node for compaction.
+*/
+void
+_ch_v2_rewrite_node(u3h_v2_node* han_u, c3_w lef_w)
+{
+ if ( c3n == u3a_v2_rewrite_ptr(han_u) ) return;
+
+ c3_w len_w = _ch_v2_popcount(han_u->map_w);
+ c3_w i_w;
+
+ lef_w -= 5;
+
+ for ( i_w = 0; i_w < len_w; i_w++ ) {
+ c3_w sot_w = han_u->sot_w[i_w];
+
+ if ( _(u3h_v2_slot_is_noun(sot_w)) ) {
+ u3_noun kev = u3h_v2_slot_to_noun(sot_w);
+ han_u->sot_w[i_w] = u3h_v2_noun_to_slot(u3a_v2_rewritten_noun(kev));
+
+ u3a_v2_rewrite_noun(kev);
+ }
+ else {
+ void* hav_v = u3h_v1_slot_to_node(sot_w);
+ u3h_v2_node* nod_u = u3to(u3h_v2_node, u3a_v2_rewritten(u3of(u3h_v2_node,hav_v)));
+
+ han_u->sot_w[i_w] = u3h_v2_node_to_slot(nod_u);
+
+ if ( 0 == lef_w ) {
+ _ch_v2_rewrite_buck(hav_v);
+ } else {
+ _ch_v2_rewrite_node(hav_v, lef_w);
+ }
+ }
+ }
+}
+
+/* u3h_v2_rewrite(): rewrite pointers during compaction.
+*/
+void
+u3h_v2_rewrite(u3p(u3h_v2_root) har_p)
+{
+ u3h_v2_root* har_u = u3to(u3h_v2_root, har_p);
+ c3_w i_w;
+
+ if ( c3n == u3a_v2_rewrite_ptr(har_u) ) return;
+
+ for ( i_w = 0; i_w < 64; i_w++ ) {
+ c3_w sot_w = har_u->sot_w[i_w];
+
+ if ( _(u3h_v2_slot_is_noun(sot_w)) ) {
+ u3_noun kev = u3h_v2_slot_to_noun(sot_w);
+ har_u->sot_w[i_w] = u3h_v2_noun_to_slot(u3a_v2_rewritten_noun(kev));
+
+ u3a_v2_rewrite_noun(kev);
+ }
+ else if ( _(u3h_v2_slot_is_node(sot_w)) ) {
+ u3h_v2_node* han_u = (u3h_v2_node*) u3h_v1_slot_to_node(sot_w);
+ u3h_v2_node* nod_u = u3to(u3h_v2_node, u3a_v2_rewritten(u3of(u3h_v2_node,han_u)));
+
+ har_u->sot_w[i_w] = u3h_v2_node_to_slot(nod_u);
+
+ _ch_v2_rewrite_node(han_u, 25);
+ }
+ }
+}