summaryrefslogtreecommitdiff
path: root/vere/pkg/noun/v2/hashtable.c
blob: a4f0291bd1cdf4a4c77c887166c4f871fabbfba2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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);
    }
  }
}