@@ -35,7 +35,7 @@ struct HNode
3535 struct HNode * next ;
3636 term key ;
3737 term entry ;
38- Heap * heap ;
38+ Heap heap ;
3939};
4040
4141static uint32_t hash_term (term t , GlobalContext * global );
@@ -53,14 +53,26 @@ struct EtsHashTable *ets_hashtable_new()
5353 return htable ;
5454}
5555
56+ static void ets_hashtable_free_node (struct HNode * node , GlobalContext * global )
57+ {
58+ memory_destroy_heap (& node -> heap , global );
59+ free (node );
60+ }
61+
62+ void ets_hashtable_free_node_array (struct HNode * * allocated , size_t size , GlobalContext * global )
63+ {
64+ for (size_t i = 0 ; i < size ; ++ i ) {
65+ ets_hashtable_free_node (allocated [i ], global );
66+ }
67+ }
68+
5669void ets_hashtable_destroy (struct EtsHashTable * hash_table , GlobalContext * global )
5770{
5871 for (size_t i = 0 ; i < hash_table -> capacity ; ++ i ) {
5972 struct HNode * node = hash_table -> buckets [i ];
60- while (node != 0 ) {
61- memory_destroy_heap (node -> heap , global );
73+ while (node != NULL ) {
6274 struct HNode * next_node = node -> next ;
63- free (node );
75+ ets_hashtable_free_node (node , global );
6476 node = next_node ;
6577 }
6678 }
@@ -82,8 +94,33 @@ static void print_info(struct EtsHashTable *hash_table)
8294}
8395#endif
8496
85- EtsHashtableErrorCode ets_hashtable_insert ( struct EtsHashTable * hash_table , term key , term entry , EtsHashtableOptions opts , Heap * heap , GlobalContext * global )
97+ struct HNode * ets_hashtable_new_node ( term entry , int keypos , GlobalContext * global )
8698{
99+ struct Heap heap ;
100+ size_t size = (size_t ) memory_estimate_usage (entry );
101+ if (memory_init_heap (& heap , size ) != MEMORY_GC_OK ) {
102+ return NULL ;
103+ }
104+
105+ term new_entry = memory_copy_term_tree (& heap , entry );
106+ struct HNode * new_node = malloc (sizeof (struct HNode ));
107+ if (IS_NULL_PTR (new_node )) {
108+ memory_destroy_heap (& heap , global );
109+ return NULL ;
110+ }
111+ term key = term_get_tuple_element (new_entry , keypos );
112+
113+ new_node -> next = NULL ;
114+ new_node -> key = key ;
115+ new_node -> entry = new_entry ;
116+ new_node -> heap = heap ;
117+
118+ return new_node ;
119+ }
120+
121+ EtsHashtableErrorCode ets_hashtable_insert (struct EtsHashTable * hash_table , struct HNode * new_node , EtsHashtableOptions opts , GlobalContext * global )
122+ {
123+ term key = new_node -> key ;
87124 uint32_t hash = hash_term (key , global );
88125 uint32_t index = hash % hash_table -> capacity ;
89126
@@ -94,38 +131,30 @@ EtsHashtableErrorCode ets_hashtable_insert(struct EtsHashTable *hash_table, term
94131#endif
95132
96133 struct HNode * node = hash_table -> buckets [index ];
97- if (node ) {
98- while (1 ) {
99- if (term_compare (key , node -> key , TermCompareExact , global ) == TermEquals ) {
100- if (opts & EtsHashtableAllowOverwrite ) {
101- node -> entry = entry ;
102- memory_destroy_heap (node -> heap , global );
103- node -> heap = heap ;
104- return EtsHashtableOk ;
134+ struct HNode * last_node = NULL ;
135+ while (node ) {
136+ if (term_compare (key , node -> key , TermCompareExact , global ) == TermEquals ) {
137+ if (opts & EtsHashtableAllowOverwrite ) {
138+ if (IS_NULL_PTR (last_node )) {
139+ new_node -> next = node -> next ;
140+ hash_table -> buckets [index ] = new_node ;
105141 } else {
106- return EtsHashtableFailure ;
142+ last_node -> next = new_node ;
143+ new_node -> next = node -> next ;
107144 }
108- }
109-
110- if (node -> next ) {
111- node = node -> next ;
145+ ets_hashtable_free_node (node , global );
146+ return EtsHashtableOk ;
112147 } else {
113- break ;
148+ ets_hashtable_free_node (new_node , global );
149+ return EtsHashtableFailure ;
114150 }
115151 }
152+ last_node = node ;
153+ node = node -> next ;
116154 }
117155
118- struct HNode * new_node = malloc (sizeof (struct HNode ));
119- if (IS_NULL_PTR (new_node )) {
120- return EtsHashtableError ;
121- }
122- new_node -> next = NULL ;
123- new_node -> key = key ;
124- new_node -> entry = entry ;
125- new_node -> heap = heap ;
126-
127- if (node ) {
128- node -> next = new_node ;
156+ if (last_node ) {
157+ last_node -> next = new_node ;
129158 } else {
130159 hash_table -> buckets [index ] = new_node ;
131160 }
@@ -165,7 +194,7 @@ bool ets_hashtable_remove(struct EtsHashTable *hash_table, term key, size_t keyp
165194 term key_to_compare = term_get_tuple_element (node -> entry , keypos );
166195 if (term_compare (key , key_to_compare , TermCompareExact , global ) == TermEquals ) {
167196
168- memory_destroy_heap (node -> heap , global );
197+ memory_destroy_heap (& node -> heap , global );
169198 struct HNode * next_node = node -> next ;
170199 free (node );
171200
0 commit comments