1 /*
2     Ypsilon Scheme System
3     Copyright (c) 2004-2008 Y.FUJITA / LittleWing Company Limited.
4     See license.txt for terms and conditions of use
5 */
6 
7 #include "core.h"
8 #include "hash.h"
9 #include "heap.h"
10 #include "list.h"
11 #include "arith.h"
12 #include "port.h"
13 #include "socket.h"
14 
swap(T & lhs,T & rhs)15 template <typename T> void swap(T& lhs, T& rhs) { T tmp = lhs; lhs = rhs; rhs = tmp; }
16 
17 scm_symbol_t
make_symbol(object_heap_t * heap,const char * name,int len)18 make_symbol(object_heap_t* heap, const char *name, int len)
19 {
20 #if USE_PARALLEL_VM
21     heap->m_symbol.lock();
22     scm_symbol_t obj = (scm_symbol_t)heap->m_symbol.get(name, len);
23     if (obj == scm_undef) {
24         if (heap != heap->m_primordial) {
25             heap->m_primordial->m_symbol.lock();
26             obj = (scm_symbol_t)heap->m_primordial->m_symbol.get(name, len);
27             heap->m_primordial->m_symbol.unlock();
28             if (obj != scm_undef) {
29                 heap->m_symbol.unlock();
30                 return obj;
31             }
32         }
33         int bytes = sizeof(scm_symbol_rec_t) + len + 1;
34         if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
35             obj = (scm_symbol_t)heap->allocate_collectible(bytes);
36             obj->name = (char*)((uintptr_t)obj + sizeof(scm_symbol_rec_t));
37         } else {
38             obj = (scm_symbol_t)heap->allocate_collectible(sizeof(scm_symbol_rec_t));
39             obj->name = (char*)heap->allocate_private(len + 1);
40         }
41         obj->hdr = scm_hdr_symbol | MAKEBITS(len, HDR_SYMBOL_SIZE_SHIFT) ;
42         memcpy(obj->name, name, len);
43         obj->name[len] = 0;
44         heap->m_symbol.put(obj);
45     }
46     heap->m_symbol.unlock();
47     return obj;
48 #else
49     heap->m_symbol.lock();
50     scm_symbol_t obj = (scm_symbol_t)heap->m_symbol.get(name, len);
51     if (obj == scm_undef) {
52         int bytes = sizeof(scm_symbol_rec_t) + len + 1;
53         if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
54             obj = (scm_symbol_t)heap->allocate_collectible(bytes);
55             obj->name = (char*)((uintptr_t)obj + sizeof(scm_symbol_rec_t));
56         } else {
57             obj = (scm_symbol_t)heap->allocate_collectible(sizeof(scm_symbol_rec_t));
58             obj->name = (char*)heap->allocate_private(len + 1);
59         }
60         obj->hdr = scm_hdr_symbol | MAKEBITS(len, HDR_SYMBOL_SIZE_SHIFT) ;
61         memcpy(obj->name, name, len);
62         obj->name[len] = 0;
63         heap->m_symbol.put(obj);
64     }
65     heap->m_symbol.unlock();
66     return obj;
67 #endif
68 }
69 
70 scm_symbol_t
make_symbol_uninterned(object_heap_t * heap,const char * name,int len)71 make_symbol_uninterned(object_heap_t* heap, const char *name, int len)
72 {
73     scm_symbol_t obj;
74     int bytes = sizeof(scm_symbol_rec_t) + len + 2;
75     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
76         obj = (scm_symbol_t)heap->allocate_collectible(bytes);
77         obj->name = (char*)((uintptr_t)obj + sizeof(scm_symbol_rec_t));
78     } else {
79         obj = (scm_symbol_t)heap->allocate_collectible(sizeof(scm_symbol_rec_t));
80         obj->name = (char*)heap->allocate_private(len + 2);
81     }
82     obj->hdr = scm_hdr_symbol | MAKEBITS(len, HDR_SYMBOL_SIZE_SHIFT) | HDR_SYMBOL_UNINTERNED_BIT;
83     memcpy(obj->name, name, len);
84     obj->name[len] = 0;
85     obj->name[len + 1] = len;
86     return obj;
87 }
88 
89 scm_symbol_t
make_symbol_uninterned(object_heap_t * heap,const char * name,int len,int prefix)90 make_symbol_uninterned(object_heap_t* heap, const char *name, int len, int prefix)
91 {
92     scm_symbol_t obj;
93     int bytes = sizeof(scm_symbol_rec_t) + len + 2;
94     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
95         obj = (scm_symbol_t)heap->allocate_collectible(bytes);
96         obj->name = (char*)((uintptr_t)obj + sizeof(scm_symbol_rec_t));
97     } else {
98         obj = (scm_symbol_t)heap->allocate_collectible(sizeof(scm_symbol_rec_t));
99         obj->name = (char*)heap->allocate_private(len + 2);
100     }
101     obj->hdr = scm_hdr_symbol | MAKEBITS(len, HDR_SYMBOL_SIZE_SHIFT) | HDR_SYMBOL_UNINTERNED_BIT;
102     memcpy(obj->name, name, len);
103     obj->name[len] = 0;
104     obj->name[len + 1] = prefix;
105     return obj;
106 }
107 
108 scm_symbol_t
make_symbol(object_heap_t * heap,const char * name)109 make_symbol(object_heap_t* heap, const char *name)
110 {
111     return make_symbol(heap, name, strlen(name));
112 }
113 
114 scm_symbol_t
make_symbol_inherent(object_heap_t * heap,const char * name,int code)115 make_symbol_inherent(object_heap_t* heap, const char* name, int code)
116 {
117     assert(code < 256);
118     assert(code < INHERENT_TOTAL_COUNT);
119     assert(heap->m_inherents[code] == scm_undef);
120     scm_symbol_t obj = (scm_symbol_t)heap->allocate_collectible(sizeof(scm_symbol_rec_t));
121     int len = strlen(name);
122     obj->hdr = scm_hdr_symbol
123                 | MAKEBITS(len, HDR_SYMBOL_SIZE_SHIFT)
124                 | MAKEBITS(code, HDR_SYMBOL_CODE_SHIFT)
125                 | HDR_SYMBOL_INHERENT_BIT;
126     obj->name = (char*)heap->allocate_private(len + 1);
127     strcpy(obj->name, name);
128     heap->m_inherents[code] = obj;
129     heap->m_symbol.lock();
130     assert(heap->m_symbol.get(name, len) == scm_undef);
131     heap->m_symbol.put(obj);
132     heap->m_symbol.unlock();
133     return obj;
134 }
135 
136 scm_string_t
make_string(object_heap_t * heap,const char * name,int len)137 make_string(object_heap_t* heap, const char *name, int len)
138 {
139     if (len == 0) return (scm_string_t)heap->m_inherents[NIL_STRING];
140     scm_string_t obj;
141     int bytes = sizeof(scm_string_rec_t) + len + 1;
142     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
143         obj = (scm_string_t)heap->allocate_collectible(bytes);
144         obj->name = (char*)((uintptr_t)obj + sizeof(scm_string_rec_t));
145     } else {
146         obj = (scm_string_t)heap->allocate_collectible(sizeof(scm_string_rec_t));
147         obj->name = (char*)heap->allocate_private(len + 1);
148     }
149     obj->hdr = scm_hdr_string;
150     obj->size = len;
151     memcpy(obj->name, name, len);
152     obj->name[len] = 0;
153     return obj;
154 }
155 
156 scm_string_t
make_string(object_heap_t * heap,const char * name)157 make_string(object_heap_t* heap, const char *name)
158 {
159     return make_string(heap, name, strlen(name));
160 }
161 
162 scm_string_t
make_string_literal(object_heap_t * heap,const char * name,int len)163 make_string_literal(object_heap_t* heap, const char* name, int len)
164 {
165     heap->m_string.lock();
166     scm_string_t obj = (scm_string_t)heap->m_string.get(name, len);
167     if (obj == scm_undef) {
168         int bytes = sizeof(scm_string_rec_t) + len + 1;
169         if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
170             obj = (scm_string_t)heap->allocate_collectible(bytes);
171             obj->name = (char*)((uintptr_t)obj + sizeof(scm_string_rec_t));
172         } else {
173             obj = (scm_string_t)heap->allocate_collectible(sizeof(scm_string_rec_t));
174             obj->name = (char*)heap->allocate_private(len + 1);
175         }
176         obj->hdr = scm_hdr_string | MAKEBITS(1, HDR_STRING_LITERAL_SHIFT);
177         obj->size = len;
178         memcpy(obj->name, name, len);
179         obj->name[len] = 0;
180         heap->m_string.put(obj);
181     }
182     heap->m_string.unlock();
183     return obj;
184 }
185 
186 scm_string_t
make_string_literal(object_heap_t * heap,const char * name)187 make_string_literal(object_heap_t* heap, const char *name)
188 {
189     return make_string_literal(heap, name, strlen(name));
190 }
191 
192 scm_string_t
make_string(object_heap_t * heap,int n,char c)193 make_string(object_heap_t* heap, int n, char c)
194 {
195     if (n == 0) return (scm_string_t)heap->m_inherents[NIL_STRING];
196     scm_string_t obj = (scm_string_t)heap->allocate_collectible(sizeof(scm_string_rec_t));
197     obj->hdr = scm_hdr_string;
198     obj->size = n;
199     obj->name = (char*)heap->allocate_private(n + 1);
200     memset(obj->name, c, n);
201     obj->name[n] = 0;
202     return obj;
203 }
204 
205 scm_vector_t
make_vector(object_heap_t * heap,scm_obj_t lst)206 make_vector(object_heap_t* heap, scm_obj_t lst)
207 {
208     if (lst == scm_nil) return (scm_vector_t)heap->m_inherents[NIL_VECTOR];
209     int n = list_length(lst);
210     int bytes = sizeof(scm_vector_rec_t) + sizeof(scm_obj_t) * n;
211     scm_vector_t obj;
212     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
213         obj = (scm_vector_t)heap->allocate_collectible(bytes);
214         obj->hdr = scm_hdr_vector;
215         obj->count = n;
216         obj->elts = (scm_obj_t*)((uintptr_t)obj + sizeof(scm_vector_rec_t));
217     } else {
218         obj = (scm_vector_t)heap->allocate_collectible(sizeof(scm_vector_rec_t));
219         obj->hdr = scm_hdr_vector;
220         obj->count = n;
221         obj->elts = (scm_obj_t*)heap->allocate_private(sizeof(scm_obj_t) * n);
222     }
223     for (int i = 0; i < n; i++) {
224         obj->elts[i] = CAR(lst);
225         lst = CDR(lst);
226     }
227     return obj;
228 }
229 
230 scm_vector_t
make_vector(object_heap_t * heap,int n,scm_obj_t elt)231 make_vector(object_heap_t* heap, int n, scm_obj_t elt)
232 {
233     if (n == 0) return (scm_vector_t)heap->m_inherents[NIL_VECTOR];
234     int bytes = sizeof(scm_vector_rec_t) + sizeof(scm_obj_t) * n;
235     scm_vector_t obj;
236     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
237         obj = (scm_vector_t)heap->allocate_collectible(bytes);
238         obj->hdr = scm_hdr_vector;
239         obj->count = n;
240         obj->elts = (scm_obj_t*)((uintptr_t)obj + sizeof(scm_vector_rec_t));
241     } else {
242         obj = (scm_vector_t)heap->allocate_collectible(sizeof(scm_vector_rec_t));
243         obj->hdr = scm_hdr_vector;
244         obj->count = n;
245         obj->elts = (scm_obj_t*)heap->allocate_private(sizeof(scm_obj_t) * n);
246     }
247     for (int i = 0; i < n; i++) obj->elts[i] = elt;
248     return obj;
249 }
250 
251 scm_bvector_t
make_bvector(object_heap_t * heap,int n)252 make_bvector(object_heap_t* heap, int n)
253 {
254     if (n == 0) return (scm_bvector_t)heap->m_inherents[NIL_BVECTOR];
255     scm_bvector_t obj = (scm_bvector_t)heap->allocate_collectible(sizeof(scm_bvector_rec_t));
256     obj->hdr = scm_hdr_bvector;
257     obj->count = n;
258     obj->elts = (uint8_t*)heap->allocate_private(n);
259     memset(obj->elts, 0, n);
260     return obj;
261 }
262 
263 scm_bvector_t
make_bvector_mapping(object_heap_t * heap,void * p,int n)264 make_bvector_mapping(object_heap_t* heap, void* p, int n)
265 {
266     scm_bvector_t obj = (scm_bvector_t)heap->allocate_collectible(sizeof(scm_bvector_rec_t));
267     obj->hdr = scm_hdr_bvector | MAKEBITS(1, HDR_BVECTOR_MAPPING_SHIFT);
268     obj->count = n;
269     obj->elts = (uint8_t*)p;
270     return obj;
271 }
272 
273 scm_port_t
make_temp_file_port(object_heap_t * heap,scm_obj_t name,int buffer_mode,scm_obj_t transcoder)274 make_temp_file_port(object_heap_t* heap, scm_obj_t name, int buffer_mode, scm_obj_t transcoder)
275 {
276     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
277     memset(obj, 0, sizeof(scm_port_rec_t));
278     obj->hdr = scm_hdr_port;
279     obj->lock.init(true);
280     scoped_lock lock(obj->lock);
281     port_open_temp_file(obj, name, buffer_mode, transcoder);
282     return obj;
283 }
284 
285 scm_port_t
make_std_port(object_heap_t * heap,fd_t fd,scm_obj_t name,int direction,int file_options,int buffer_mode,scm_obj_t transcoder)286 make_std_port(object_heap_t* heap, fd_t fd, scm_obj_t name, int direction, int file_options, int buffer_mode, scm_obj_t transcoder)
287 {
288     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
289     memset(obj, 0, sizeof(scm_port_rec_t));
290     obj->hdr = scm_hdr_port;
291     obj->lock.init(true);
292     scoped_lock lock(obj->lock);
293     port_open_std(obj, fd, name, direction, file_options, buffer_mode, transcoder);
294     return obj;
295 }
296 
297 scm_port_t
make_file_port(object_heap_t * heap,scm_obj_t name,int direction,int file_options,int buffer_mode,scm_obj_t transcoder)298 make_file_port(object_heap_t* heap, scm_obj_t name, int direction, int file_options, int buffer_mode, scm_obj_t transcoder)
299 {
300     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
301     memset(obj, 0, sizeof(scm_port_rec_t));
302     obj->hdr = scm_hdr_port;
303     obj->lock.init(true);
304     scoped_lock lock(obj->lock);
305     port_open_file(obj, name, direction, file_options, buffer_mode, transcoder);
306     return obj;
307 }
308 
309 scm_port_t
make_bytevector_port(object_heap_t * heap,scm_obj_t name,int direction,scm_obj_t bytes,scm_obj_t transcoder)310 make_bytevector_port(object_heap_t* heap, scm_obj_t name, int direction, scm_obj_t bytes, scm_obj_t transcoder)
311 {
312     assert(SYMBOLP(name));
313     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
314     memset(obj, 0, sizeof(scm_port_rec_t));
315     obj->hdr = scm_hdr_port;
316     obj->lock.init(true);
317     scoped_lock lock(obj->lock);
318     port_open_bytevector(obj, name, direction, bytes, transcoder);
319     return obj;
320 }
321 
322 scm_port_t
make_custom_port(object_heap_t * heap,scm_obj_t name,int direction,scm_obj_t handlers,scm_obj_t transcoder)323 make_custom_port(object_heap_t* heap, scm_obj_t name, int direction, scm_obj_t handlers, scm_obj_t transcoder)
324 {
325     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
326     memset(obj, 0, sizeof(scm_port_rec_t));
327     obj->hdr = scm_hdr_port;
328     obj->lock.init(true);
329     scoped_lock lock(obj->lock);
330     port_make_custom_port(obj, name, direction, handlers, transcoder);
331     return obj;
332 }
333 
334 scm_port_t
make_socket_port(object_heap_t * heap,scm_socket_t socket,scm_obj_t transcoder)335 make_socket_port(object_heap_t* heap, scm_socket_t socket, scm_obj_t transcoder)
336 {
337     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
338     memset(obj, 0, sizeof(scm_port_rec_t));
339     obj->hdr = scm_hdr_port;
340     obj->lock.init(true);
341     scoped_lock lock(obj->lock);
342     port_make_socket_port(obj, socket, transcoder);
343     return obj;
344 }
345 
346 scm_port_t
make_transcoded_port(object_heap_t * heap,scm_obj_t name,scm_port_t port,scm_bvector_t transcoder)347 make_transcoded_port(object_heap_t* heap, scm_obj_t name, scm_port_t port, scm_bvector_t transcoder)
348 {
349     port->lock.verify_locked();
350     scm_port_t obj = (scm_port_t)heap->allocate_collectible(sizeof(scm_port_rec_t));
351     memset(obj, 0, sizeof(scm_port_rec_t));
352     obj->hdr = scm_hdr_port;
353     obj->lock.init(true);
354     scoped_lock lock(obj->lock);
355     port_make_transcoded_port(name, port, obj, transcoder);
356     return obj;
357 }
358 
359 scm_values_t
make_values(object_heap_t * heap,int n)360 make_values(object_heap_t* heap, int n)
361 {
362     int bytes = sizeof(scm_values_rec_t) + sizeof(scm_obj_t) * n;
363     scm_values_t obj;
364     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
365         obj = (scm_values_t)heap->allocate_collectible(bytes);
366         obj->hdr = scm_hdr_values | MAKEBITS(n, HDR_VALUES_COUNT_SHIFT);
367         obj->elts = (scm_obj_t*)((uintptr_t)obj + sizeof(scm_values_rec_t));
368     } else {
369         obj = (scm_values_t)heap->allocate_collectible(sizeof(scm_values_rec_t));
370         obj->hdr = scm_hdr_values | MAKEBITS(n, HDR_VALUES_COUNT_SHIFT);
371         obj->elts = (scm_obj_t*)heap->allocate_private(sizeof(scm_obj_t) * n);
372     }
373     for (int i = 0; i < n; i++) obj->elts[i] = scm_unspecified;
374     return obj;
375 }
376 
377 scm_cont_t
make_cont(object_heap_t * heap,scm_obj_t rec,void * lnk)378 make_cont(object_heap_t* heap, scm_obj_t rec, void* lnk)
379 {
380     scm_cont_t obj = (scm_cont_t)heap->allocate_collectible(sizeof(scm_cont_rec_t));
381     obj->hdr = scm_hdr_cont;
382     obj->wind_rec = rec;
383     obj->cont = lnk;
384     return obj;
385 }
386 
387 scm_hashtable_t
make_hashtable(object_heap_t * heap,int type,int n)388 make_hashtable(object_heap_t* heap, int type, int n)
389 {
390     assert(n > 0);
391     scm_hashtable_t obj = (scm_hashtable_t)heap->allocate_collectible(sizeof(scm_hashtable_rec_t));
392     int datum_size = sizeof(hashtable_rec_t) + sizeof(scm_obj_t) * ((n + n) - 1);
393     hashtable_rec_t* ht_datum = (hashtable_rec_t*)heap->allocate_private(datum_size);
394     ht_datum->capacity = n;
395     ht_datum->live = 0;
396     ht_datum->used = 0;
397     for (int i = 0; i < (n + n); i++) ht_datum->elts[i] = scm_hash_free;
398     switch (type) {
399     case SCM_HASHTABLE_TYPE_EQ:
400         obj->hash = NULL;
401         obj->equiv = NULL;
402         break;
403     case SCM_HASHTABLE_TYPE_EQV:
404         obj->hash = eqv_hash;
405         obj->equiv = eqv_hash_equiv;
406         break;
407     case SCM_HASHTABLE_TYPE_EQUAL:
408         obj->hash = equal_hash;
409         obj->equiv = equal_hash_equiv;
410         break;
411     case SCM_HASHTABLE_TYPE_STRING:
412         obj->hash = string_hash;
413         obj->equiv = string_hash_equiv;
414         break;
415     default:
416         assert(false);
417     }
418     obj->hdr = scm_hdr_hashtable;
419     obj->type = type;
420     obj->handlers = scm_false;
421     obj->datum = ht_datum;
422     obj->lock.init();
423     return obj;
424 }
425 
426 scm_hashtable_t
make_shared_hashtable(object_heap_t * heap,int type,int n)427 make_shared_hashtable(object_heap_t* heap, int type, int n)
428 {
429     scm_hashtable_t ht = make_hashtable(heap, type, n);
430     ht->hdr |= MAKEBITS(1, HDR_HASHTABLE_SHARED_SHIFT);
431     return ht;
432 }
433 
434 scm_hashtable_t
make_generic_hashtable(object_heap_t * heap,scm_vector_t handlers)435 make_generic_hashtable(object_heap_t* heap, scm_vector_t handlers)
436 {
437     assert(VECTORP(handlers));
438     scm_hashtable_t obj = (scm_hashtable_t)heap->allocate_collectible(sizeof(scm_hashtable_rec_t));
439     obj->hdr = scm_hdr_hashtable;
440     obj->type = SCM_HASHTABLE_TYPE_GENERIC;
441     obj->handlers = handlers;
442     obj->hash = NULL;
443     obj->equiv = NULL;
444     obj->datum = NULL;
445     obj->lock.init();
446     return obj;
447 }
448 
449 scm_environment_t
make_environment(object_heap_t * heap,const char * name)450 make_environment(object_heap_t* heap, const char* name)
451 {
452     scm_environment_t obj = (scm_environment_t)heap->allocate_collectible(sizeof(scm_environment_rec_t));
453     obj->hdr = scm_hdr_environment;
454     obj->variable = make_hashtable(heap, SCM_HASHTABLE_TYPE_EQ, lookup_mutable_hashtable_size(0));
455     obj->macro = make_hashtable(heap, SCM_HASHTABLE_TYPE_EQ, lookup_mutable_hashtable_size(0));
456     if (name) {
457         obj->name = make_string_literal(heap, name);
458     } else {
459         char buf[32];
460         snprintf(buf, sizeof(buf), "0x%p", obj);
461         obj->name = make_string_literal(heap, buf);
462     }
463     return obj;
464 }
465 
466 scm_subr_t
make_subr(object_heap_t * heap,subr_proc_t adrs,scm_obj_t doc)467 make_subr(object_heap_t* heap, subr_proc_t adrs, scm_obj_t doc)
468 {
469     scm_subr_t obj = (scm_subr_t)heap->allocate_collectible(sizeof(scm_subr_rec_t));
470     obj->hdr = scm_hdr_subr;
471     obj->adrs = adrs;
472     obj->doc = doc;
473 #if PROFILE_SUBR
474     obj->c_push = 0;
475     obj->c_load = 0;
476     obj->c_apply = 0;
477 #endif
478     return obj;
479 }
480 
481 scm_closure_t
make_closure(object_heap_t * heap,int argc,int rest,void * env,scm_obj_t code,scm_obj_t doc)482 make_closure(object_heap_t* heap, int argc, int rest, void* env, scm_obj_t code, scm_obj_t doc)
483 {
484     int args = rest ? (- 1 - argc) : argc;
485     scm_closure_t obj = (scm_closure_t)heap->allocate_collectible(sizeof(scm_closure_rec_t));
486     obj->hdr = scm_hdr_closure | MAKEBITS(args, HDR_CLOSURE_ARGS_SHIFT);
487     obj->env = env;
488     obj->code = code;
489     obj->doc = doc;
490     return obj;
491 }
492 
493 scm_closure_t
make_closure(object_heap_t * heap,scm_closure_t tmpl,void * env)494 make_closure(object_heap_t* heap, scm_closure_t tmpl, void* env)
495 {
496     if (env) {
497         scm_closure_t obj = (scm_closure_t)heap->allocate_collectible(sizeof(scm_closure_rec_t));
498         obj->hdr = tmpl->hdr;
499         obj->env = env;
500         obj->code = tmpl->code;
501         obj->doc = tmpl->doc;
502         return obj;
503     }
504     return tmpl;
505 }
506 
507 scm_flonum_t
make_flonum(object_heap_t * heap,double num)508 make_flonum(object_heap_t* heap, double num)
509 {
510 #if USE_FLONUM_CONST
511     if (num == 0.0) {
512         union { double f64; int64_t i64; } datum;
513         datum.f64 = num;
514         if (datum.i64 < 0) {
515             return (scm_flonum_t)heap->m_inherents[FL_NEGATIVE_ZERO];
516         } else {
517             return (scm_flonum_t)heap->m_inherents[FL_POSITIVE_ZERO];
518         }
519     }
520     if (isnan(num)) return (scm_flonum_t)heap->m_inherents[FL_NAN];
521 #endif
522     scm_flonum_t obj = heap->allocate_flonum();
523     obj->hdr = scm_hdr_flonum;
524     obj->value = num;
525     return obj;
526 }
527 
528 scm_flonum_t
make_flonum_32bit(object_heap_t * heap,double num)529 make_flonum_32bit(object_heap_t* heap, double num)
530 {
531     scm_flonum_t obj = heap->allocate_flonum();
532     obj->hdr = scm_hdr_flonum  | MAKEBITS(1, HDR_FLONUM_32BIT_SHIFT);
533     obj->value = num;
534     return obj;
535 }
536 
537 scm_bignum_t
make_bignum(object_heap_t * heap,scm_bignum_t bn)538 make_bignum(object_heap_t* heap, scm_bignum_t bn)
539 {
540     int count = HDR_BIGNUM_COUNT(bn->hdr);
541     scm_bignum_t obj = make_bignum(heap, count);
542     obj->hdr = bn->hdr;
543     memcpy(obj->elts, bn->elts, sizeof(digit_t) * count);
544     return obj;
545 }
546 
547 scm_bignum_t
make_bignum(object_heap_t * heap,int n)548 make_bignum(object_heap_t* heap, int n)
549 {
550     int bytes = sizeof(scm_bignum_rec_t) + sizeof(digit_t) * n;
551     scm_bignum_t obj;
552     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
553         obj = (scm_bignum_t)heap->allocate_collectible(bytes);
554         obj->hdr = scm_hdr_bignum | MAKEBITS(n, HDR_BIGNUM_COUNT_SHIFT);
555         if (n) obj->elts = (digit_t*)((uintptr_t)obj + sizeof(scm_bignum_rec_t));
556         else obj->elts = NULL;
557     } else {
558         obj = (scm_bignum_t)heap->allocate_collectible(sizeof(scm_bignum_rec_t));
559         obj->hdr = scm_hdr_bignum | MAKEBITS(n, HDR_BIGNUM_COUNT_SHIFT);
560         if (n) obj->elts = (digit_t*)heap->allocate_private(sizeof(digit_t) * n);
561         else obj->elts = NULL;
562     }
563     return obj;
564 }
565 
566 scm_complex_t
make_complex(object_heap_t * heap,double real,double imag)567 make_complex(object_heap_t* heap, double real, double imag)
568 {
569     scm_complex_t obj = (scm_complex_t)heap->allocate_collectible(sizeof(scm_complex_rec_t));
570     obj->hdr = scm_hdr_complex;
571     obj->real = make_flonum(heap, real);
572     obj->imag = make_flonum(heap, imag);
573     return obj;
574 }
575 
576 scm_complex_t
make_complex(object_heap_t * heap,scm_obj_t real,scm_obj_t imag)577 make_complex(object_heap_t* heap, scm_obj_t real, scm_obj_t imag)
578 {
579     assert(!COMPLEXP(real));
580     assert(!COMPLEXP(imag));
581     scm_complex_t obj = (scm_complex_t)heap->allocate_collectible(sizeof(scm_complex_rec_t));
582     obj->hdr = scm_hdr_complex;
583     obj->real = real;
584     obj->imag = imag;
585     return obj;
586 }
587 
588 scm_rational_t
make_rational(object_heap_t * heap,scm_obj_t numerator,scm_obj_t denominator)589 make_rational(object_heap_t* heap, scm_obj_t numerator, scm_obj_t denominator)
590 {
591     assert(n_negative_pred(denominator) == false);
592     assert(n_exact_pred(numerator));
593     assert(n_exact_pred(denominator));
594     scm_rational_t obj = (scm_rational_t)heap->allocate_collectible(sizeof(scm_rational_rec_t));
595     obj->hdr = scm_hdr_rational;
596     obj->nume = numerator;
597     obj->deno = denominator;
598     return obj;
599 }
600 
601 scm_gloc_t
make_gloc(object_heap_t * heap,scm_environment_t environment,scm_symbol_t symbol)602 make_gloc(object_heap_t* heap, scm_environment_t environment, scm_symbol_t symbol)
603 {
604     scm_gloc_t obj = (scm_gloc_t)heap->allocate_collectible(sizeof(scm_gloc_rec_t));
605     obj->hdr = scm_hdr_gloc;
606     obj->variable = symbol;
607   #if GLOC_DEBUG_INFO
608     obj->environment = environment->name;
609   #endif
610     obj->value = scm_undef;
611     return obj;
612 }
613 
614 scm_tuple_t
make_tuple(object_heap_t * heap,int n,scm_obj_t elt)615 make_tuple(object_heap_t* heap, int n, scm_obj_t elt)
616 {
617     if (n == 0) return (scm_tuple_t)heap->m_inherents[NIL_TUPLE];
618     int bytes = sizeof(scm_tuple_rec_t) + sizeof(scm_obj_t) * n;
619     scm_tuple_t obj;
620     if (bytes <= INTERNAL_PRIVATE_THRESHOLD) {
621         obj = (scm_tuple_t)heap->allocate_collectible(bytes);
622         obj->hdr = scm_hdr_tuple | MAKEBITS(n, HDR_TUPLE_COUNT_SHIFT);
623         obj->elts = (scm_obj_t*)((uintptr_t)obj + sizeof(scm_tuple_rec_t));
624     } else {
625         obj = (scm_tuple_t)heap->allocate_collectible(sizeof(scm_tuple_rec_t));
626         obj->hdr = scm_hdr_tuple | MAKEBITS(n, HDR_TUPLE_COUNT_SHIFT);
627         obj->elts = (scm_obj_t*)heap->allocate_private(sizeof(scm_obj_t) * n);
628     }
629     for (int i = 0; i < n; i++) obj->elts[i] = elt;
630     return obj;
631 }
632 
633 scm_tuple_t
make_tuple(object_heap_t * heap,int len,...)634 make_tuple(object_heap_t* heap, int len, ...)
635 {
636     va_list ap;
637     va_start(ap, len);
638     scm_tuple_t tuple = make_tuple(heap, len, scm_unspecified);
639     for (int i = 0; i < len; i++) tuple->elts[i] = va_arg(ap, scm_obj_t);
640     va_end(ap);
641     return tuple;
642 }
643 
644 scm_weakmapping_t
make_weakmapping(object_heap_t * heap,scm_obj_t key,scm_obj_t value)645 make_weakmapping(object_heap_t* heap, scm_obj_t key, scm_obj_t value)
646 {
647     scm_weakmapping_t obj = (scm_weakmapping_t)heap->allocate_weakmapping();
648     obj->hdr = scm_hdr_weakmapping;
649     obj->key = key;
650     obj->value = value;
651     return obj;
652 }
653 
654 scm_weakhashtable_t
make_weakhashtable(object_heap_t * heap,int n)655 make_weakhashtable(object_heap_t* heap, int n)
656 {
657     assert(n > 0);
658     scm_weakhashtable_t obj = (scm_weakhashtable_t)heap->allocate_collectible(sizeof(scm_weakhashtable_rec_t));
659     int datum_size = sizeof(weakhashtable_rec_t) + sizeof(scm_obj_t) * (n - 1);
660     weakhashtable_rec_t* ht_datum = (weakhashtable_rec_t*)heap->allocate_private(datum_size);
661     ht_datum->capacity = n;
662     ht_datum->live = 0;
663     ht_datum->used = 0;
664     for (int i = 0; i < n; i++) ht_datum->elts[i] = scm_hash_free;
665     obj->hdr = scm_hdr_weakhashtable;
666     obj->datum = ht_datum;
667     obj->lock.init();
668     return obj;
669 }
670 
671 scm_weakhashtable_t
make_shared_weakhashtable(object_heap_t * heap,int n)672 make_shared_weakhashtable(object_heap_t* heap, int n)
673 {
674     scm_weakhashtable_t ht = make_weakhashtable(heap, n);
675     ht->hdr |= MAKEBITS(1, HDR_WEAKHASHTABLE_SHARED_SHIFT);
676     return ht;
677 }
678 
679 scm_socket_t
make_socket(object_heap_t * heap,const char * node,const char * service,int family,int type,int protocol,int flags)680 make_socket(object_heap_t* heap, const char* node, const char* service, int family, int type, int protocol, int flags)
681 {
682     scm_socket_t obj = (scm_socket_t)heap->allocate_collectible(sizeof(scm_socket_rec_t));
683     memset(obj, 0 , sizeof(scm_socket_rec_t));
684     obj->hdr = scm_hdr_socket;
685     obj->fd = INVALID_SOCKET;
686     obj->lock.init(true);
687     scoped_lock lock(obj->lock);
688     socket_open(obj, node, service, family, type, protocol, flags);
689     return obj;
690 }
691 
692 scm_socket_t
make_socket(object_heap_t * heap)693 make_socket(object_heap_t* heap)
694 {
695     scm_socket_t obj = (scm_socket_t)heap->allocate_collectible(sizeof(scm_socket_rec_t));
696     memset(obj, 0 , sizeof(scm_socket_rec_t));
697     obj->hdr = scm_hdr_socket;
698     obj->fd = INVALID_SOCKET;
699     obj->lock.init(true);
700     return obj;
701 }
702 
703 scm_sharedqueue_t
make_sharedqueue(object_heap_t * heap,int n)704 make_sharedqueue(object_heap_t* heap, int n)
705 {
706     assert(n);
707     scm_sharedqueue_t obj = (scm_sharedqueue_t)heap->allocate_collectible(sizeof(scm_sharedqueue_rec_t));
708     obj->hdr = scm_hdr_sharedqueue;
709     obj->buf.init(n + MAX_VIRTUAL_MACHINE);
710     obj->queue.init(n);
711     return obj;
712 }
713 
714 scm_sharedbag_t
make_sharedbag(object_heap_t * heap,int depth)715 make_sharedbag(object_heap_t* heap, int depth)
716 {
717     scm_sharedbag_t obj = (scm_sharedbag_t)heap->allocate_collectible(sizeof(scm_sharedbag_rec_t));
718     sharedbag_slot_t** datum = (sharedbag_slot_t**)malloc(sizeof(sharedbag_slot_t*) * MAX_VIRTUAL_MACHINE);
719     for (int i = 0; i < MAX_VIRTUAL_MACHINE; i++) {
720         datum[i] = (sharedbag_slot_t*)malloc(sizeof(sharedbag_slot_t));
721         datum[i]->key = NULL;
722         datum[i]->buf.init(depth + MAX_VIRTUAL_MACHINE);
723         datum[i]->queue.init(depth);
724     }
725     obj->hdr = scm_hdr_sharedbag;
726     obj->capacity = MAX_VIRTUAL_MACHINE;
727     obj->depth = depth;
728     obj->datum = datum;
729     obj->lock.init();
730     return obj;
731 }
732 
733 scm_obj_t
make_list(object_heap_t * heap,int len,...)734 make_list(object_heap_t* heap, int len, ...)
735 {
736     va_list ap;
737     va_start(ap, len);
738     if (len == 0) return scm_nil;
739     scm_obj_t obj = make_pair(heap, va_arg(ap, scm_obj_t), scm_nil);
740     scm_obj_t tail = obj;
741     for (int i = 1; i < len; i++) {
742         scm_obj_t e = make_pair(heap, va_arg(ap, scm_obj_t), scm_nil);
743         CDR(tail) = e;
744         tail = e;
745     }
746     va_end(ap);
747     return obj;
748 }
749 
750 void
rehash_hashtable(object_heap_t * heap,scm_hashtable_t ht,int nsize)751 rehash_hashtable(object_heap_t* heap, scm_hashtable_t ht, int nsize)
752 {
753     assert(HASHTABLEP(ht));
754     ht->lock.verify_locked();
755     hashtable_rec_t* ht_datum = ht->datum;
756     int nelts = ht_datum->capacity;
757     assert(HASH_DENSE_THRESHOLD(nsize) > ht_datum->live);
758     scm_hashtable_t ht2 = make_hashtable(heap, ht->type, nsize);
759     scoped_lock lock(ht2->lock);
760     for (int i = 0; i < nelts; i++) {
761         if (ht_datum->elts[i] == scm_hash_free) continue;
762         if (ht_datum->elts[i] == scm_hash_deleted) continue;
763         put_hashtable(ht2, ht_datum->elts[i], ht_datum->elts[i + nelts]);
764     }
765     swap(ht->datum, ht2->datum);
766 }
767 
768 void
inplace_rehash_hashtable(object_heap_t * heap,scm_hashtable_t ht)769 inplace_rehash_hashtable(object_heap_t* heap, scm_hashtable_t ht)
770 {
771     assert(HASHTABLEP(ht));
772     ht->lock.verify_locked();
773     hashtable_rec_t* ht_datum = ht->datum;
774     int nelts = ht_datum->capacity;
775     int datum_size = sizeof(hashtable_rec_t) + sizeof(scm_obj_t) * ((nelts + nelts) - 1);
776     hashtable_rec_t* save_datum = (hashtable_rec_t*)malloc(datum_size);
777     memcpy(save_datum, ht_datum, datum_size);
778     clear_volatile_hashtable(ht);
779     for (int i = 0; i < nelts; i++) {
780         if (save_datum->elts[i] == scm_hash_free) continue;
781         if (save_datum->elts[i] == scm_hash_deleted) continue;
782         put_hashtable(ht, save_datum->elts[i], save_datum->elts[i + nelts]);
783     }
784     free(save_datum);
785 }
786 
787 void
rehash_weakhashtable(object_heap_t * heap,scm_weakhashtable_t ht,int nsize)788 rehash_weakhashtable(object_heap_t* heap, scm_weakhashtable_t ht, int nsize)
789 {
790     assert(WEAKHASHTABLEP(ht));
791     ht->lock.verify_locked();
792     weakhashtable_rec_t* ht_datum = ht->datum;
793     int nelts = ht_datum->capacity;
794     assert(HASH_DENSE_THRESHOLD(nsize) > ht_datum->live);
795     scm_weakhashtable_t ht2 = make_weakhashtable(heap, nsize);
796     scoped_lock lock(ht2->lock);
797     for (int i = 0; i < nelts; i++) {
798         scm_obj_t obj = ht_datum->elts[i];
799         if (obj == scm_hash_free) continue;
800         if (obj == scm_hash_deleted) continue;
801         assert(WEAKMAPPINGP(obj));
802         if (((scm_weakmapping_t)obj)->key == scm_false) continue;
803         put_weakhashtable(ht2, (scm_weakmapping_t)obj);
804     }
805     swap(ht->datum, ht2->datum);
806 }
807 
808 void
inplace_rehash_weakhashtable(object_heap_t * heap,scm_weakhashtable_t ht)809 inplace_rehash_weakhashtable(object_heap_t* heap, scm_weakhashtable_t ht)
810 {
811     assert(WEAKHASHTABLEP(ht));
812     ht->lock.verify_locked();
813     weakhashtable_rec_t* ht_datum = ht->datum;
814     int nelts = ht_datum->capacity;
815     int datum_size = sizeof(weakhashtable_rec_t) + sizeof(scm_obj_t) * (nelts - 1);
816     weakhashtable_rec_t* save_datum = (weakhashtable_rec_t*)malloc(datum_size);
817     memcpy(save_datum, ht_datum, datum_size);
818     clear_volatile_weakhashtable(ht);
819     for (int i = 0; i < nelts; i++) {
820         scm_obj_t obj = save_datum->elts[i];
821         if (obj == scm_hash_free) continue;
822         if (obj == scm_hash_deleted) continue;
823         assert(WEAKMAPPINGP(obj));
824         if (((scm_weakmapping_t)obj)->key == scm_false) continue;
825         put_weakhashtable(ht, (scm_weakmapping_t)obj);
826     }
827     free(save_datum);
828 }
829 
830 scm_hashtable_t
copy_hashtable(object_heap_t * heap,scm_hashtable_t ht,bool immutable)831 copy_hashtable(object_heap_t* heap, scm_hashtable_t ht, bool immutable)
832 {
833     assert(HASHTABLEP(ht));
834     ht->lock.verify_locked();
835     hashtable_rec_t* ht_datum = ht->datum;
836     int nelts = ht_datum->capacity;
837     scm_hashtable_t ht2 = make_hashtable(heap, ht->type, lookup_immutable_hashtable_size(HASH_IMMUTABLE_SIZE(ht_datum->live)));
838     scoped_lock lock(ht2->lock);
839     for (int i = 0; i < nelts; i++) {
840         if (ht_datum->elts[i] == scm_hash_free) continue;
841         if (ht_datum->elts[i] == scm_hash_deleted) continue;
842         put_hashtable(ht2, ht_datum->elts[i], ht_datum->elts[i + nelts]);
843     }
844     if (HDR_HASHTABLE_SHARED(ht->hdr)) ht2->hdr |= MAKEBITS(1, HDR_HASHTABLE_SHARED_SHIFT);
845     if (immutable) ht2->hdr |= MAKEBITS(1, HDR_HASHTABLE_IMMUTABLE_SHIFT);
846     return ht2;
847 }
848 
849 scm_weakhashtable_t
copy_weakhashtable(object_heap_t * heap,scm_weakhashtable_t ht,bool immutable)850 copy_weakhashtable(object_heap_t* heap, scm_weakhashtable_t ht, bool immutable)
851 {
852     assert(WEAKHASHTABLEP(ht));
853     ht->lock.verify_locked();
854     weakhashtable_rec_t* ht_datum = ht->datum;
855     int nelts = ht_datum->capacity;
856     scm_weakhashtable_t ht2 = make_weakhashtable(heap, lookup_immutable_hashtable_size(HASH_IMMUTABLE_SIZE(ht_datum->live)));
857     scoped_lock lock(ht2->lock);
858     for (int i = 0; i < nelts; i++) {
859         scm_obj_t obj = ht_datum->elts[i];
860         if (obj == scm_hash_free) continue;
861         if (obj == scm_hash_deleted) continue;
862         assert(WEAKMAPPINGP(obj));
863         if (((scm_weakmapping_t)obj)->key == scm_false) continue;
864         put_weakhashtable(ht2, (scm_weakmapping_t)obj);
865     }
866     if (HDR_WEAKHASHTABLE_SHARED(ht->hdr)) ht2->hdr |= MAKEBITS(1, HDR_WEAKHASHTABLE_SHARED_SHIFT);
867     if (immutable) ht2->hdr |= MAKEBITS(1, HDR_WEAKHASHTABLE_IMMUTABLE_SHIFT);
868     return ht2;
869 }
870 
871 scm_weakhashtable_t
clone_weakhashtable(object_heap_t * heap,scm_weakhashtable_t ht,bool immutable)872 clone_weakhashtable(object_heap_t* heap, scm_weakhashtable_t ht, bool immutable)
873 {
874     assert(WEAKHASHTABLEP(ht));
875     ht->lock.verify_locked();
876     weakhashtable_rec_t* ht_datum = ht->datum;
877     int nelts = ht_datum->capacity;
878     scm_weakhashtable_t ht2 = make_weakhashtable(heap, lookup_immutable_hashtable_size(HASH_IMMUTABLE_SIZE(ht_datum->live)));
879     scoped_lock lock(ht2->lock);
880     for (int i = 0; i < nelts; i++) {
881         scm_obj_t obj = ht_datum->elts[i];
882         if (obj == scm_hash_free) continue;
883         if (obj == scm_hash_deleted) continue;
884         assert(WEAKMAPPINGP(obj));
885         scm_weakmapping_t wmap = (scm_weakmapping_t)obj;
886         if (wmap->key == scm_false) continue;
887         put_weakhashtable(ht2, make_weakmapping(heap, wmap->key, wmap->value));
888     }
889     if (HDR_WEAKHASHTABLE_SHARED(ht->hdr)) ht2->hdr |= MAKEBITS(1, HDR_WEAKHASHTABLE_SHARED_SHIFT);
890     if (immutable) ht2->hdr |= MAKEBITS(1, HDR_WEAKHASHTABLE_IMMUTABLE_SHIFT);
891     return ht2;
892 }
893 
894 void
clear_hashtable(object_heap_t * heap,scm_hashtable_t ht,int n)895 clear_hashtable(object_heap_t* heap, scm_hashtable_t ht, int n)
896 {
897     assert(HASHTABLEP(ht));
898     ht->lock.verify_locked();
899     scm_hashtable_t ht2 = make_hashtable(heap, ht->type, n);
900     swap(ht->datum, ht2->datum);
901 }
902 
903 void
clear_weakhashtable(object_heap_t * heap,scm_weakhashtable_t ht,int n)904 clear_weakhashtable(object_heap_t* heap, scm_weakhashtable_t ht, int n)
905 {
906     assert(WEAKHASHTABLEP(ht));
907     ht->lock.verify_locked();
908     scm_weakhashtable_t ht2 = make_weakhashtable(heap, n);
909     swap(ht->datum, ht2->datum);
910 }
911 
912 void
clear_volatile_hashtable(scm_hashtable_t ht)913 clear_volatile_hashtable(scm_hashtable_t ht)
914 {
915     assert(HASHTABLEP(ht));
916     ht->lock.verify_locked();
917     hashtable_rec_t* ht_datum = ht->datum;
918     int n = ht_datum->capacity;
919     ht_datum->live = 0;
920     ht_datum->used = 0;
921     for (int i = 0; i < (n + n); i++) ht_datum->elts[i] = scm_hash_free;
922 }
923 
924 void
clear_volatile_weakhashtable(scm_weakhashtable_t ht)925 clear_volatile_weakhashtable(scm_weakhashtable_t ht)
926 {
927     assert(WEAKHASHTABLEP(ht));
928     ht->lock.verify_locked();
929     weakhashtable_rec_t* ht_datum = ht->datum;
930     int n = ht_datum->capacity;
931     ht_datum->live = 0;
932     ht_datum->used = 0;
933     for (int i = 0; i < n; i++) ht_datum->elts[i] = scm_hash_free;
934 }
935 
936 void
finalize(object_heap_t * heap,void * obj)937 finalize(object_heap_t* heap, void* obj)
938 {
939     // do not access shared object during finalize, it may collected.
940     assert(heap->is_collectible(obj));
941     if (PAIRP(obj)) {
942         assert(false);
943     }
944     if (FLONUMP(obj)) {
945         assert(false);
946     }
947 
948     int tc = HDR_TC(HDR(obj));
949     assert(tc >= 0);
950     assert(tc <= TC_MASKBITS);
951     switch (tc) {
952         case TC_BIGNUM: {
953             scm_bignum_t bignum = (scm_bignum_t)obj;
954             if (bignum->elts != (digit_t*)((uintptr_t)bignum + sizeof(scm_bignum_rec_t))) {
955                 heap->deallocate_private(bignum->elts);
956             }
957             break;
958         }
959         case TC_SYMBOL: {
960             scm_symbol_t symbol = (scm_symbol_t)obj;
961             if (symbol->name != (char*)((uintptr_t)symbol + sizeof(scm_symbol_rec_t))) {
962                 heap->deallocate_private(symbol->name);
963             }
964             break;
965         }
966         case TC_STRING: {
967             scm_string_t string = (scm_string_t)obj;
968             if (string->name != (char*)((uintptr_t)string + sizeof(scm_string_rec_t))) {
969                 heap->deallocate_private(string->name);
970             }
971             break;
972         }
973         case TC_VECTOR: {
974             scm_vector_t vector = (scm_vector_t)obj;
975             if (vector->elts != (scm_obj_t*)((uintptr_t)vector + sizeof(scm_vector_rec_t))) {
976                 heap->deallocate_private(vector->elts);
977             }
978             break;
979         }
980         case TC_BVECTOR: {
981             scm_bvector_t bvector = (scm_bvector_t)obj;
982             if (HDR_BVECTOR_MAPPING(bvector->hdr) == 0) heap->deallocate_private(bvector->elts);
983             break;
984         }
985         case TC_TUPLE: {
986             scm_tuple_t tuple = (scm_tuple_t)obj;
987             if (tuple->elts != (scm_obj_t*)((uintptr_t)tuple + sizeof(scm_tuple_rec_t))) {
988                 heap->deallocate_private(tuple->elts);
989             }
990             break;
991         }
992         case TC_VALUES: {
993             scm_values_t values = (scm_values_t)obj;
994             if (values->elts != (scm_obj_t*)((uintptr_t)values + sizeof(scm_values_rec_t))) {
995                 heap->deallocate_private(values->elts);
996             }
997             break;
998         }
999         case TC_HASHTABLE: {
1000             scm_hashtable_t ht = (scm_hashtable_t)obj;
1001             heap->deallocate_private(ht->datum);
1002             ht->lock.destroy();
1003             break;
1004         }
1005         case TC_WEAKHASHTABLE: {
1006             scm_weakhashtable_t ht = (scm_weakhashtable_t)obj;
1007             heap->deallocate_private(ht->datum);
1008             ht->lock.destroy();
1009             break;
1010         }
1011         case TC_PORT: {
1012             scm_port_t port = (scm_port_t)obj;
1013             {
1014                 scoped_lock lock(port->lock);
1015                 if (port->type != SCM_PORT_TYPE_CUSTOM) port_close(port);
1016                 // todo: finalizer for custom port
1017             }
1018             port->lock.destroy();
1019             break;
1020         }
1021         case TC_SOCKET: {
1022             scm_socket_t socket = (scm_socket_t)obj;
1023             {
1024                 scoped_lock lock(socket->lock);
1025                 socket_close(socket);
1026             }
1027             socket->lock.destroy();
1028             break;
1029         }
1030         case TC_SHAREDQUEUE: {
1031             scm_sharedqueue_t queue = (scm_sharedqueue_t)obj;
1032             queue->buf.destroy();
1033             queue->queue.destroy();
1034             break;
1035         }
1036         case TC_SHAREDBAG: {
1037             scm_sharedbag_t bag = (scm_sharedbag_t)obj;
1038             for (int i = 0; i < bag->capacity; i++) {
1039                 bag->datum[i]->buf.destroy();
1040                 bag->datum[i]->queue.destroy();
1041                 free(bag->datum[i]->key);
1042                 free(bag->datum[i]);
1043             }
1044             free(bag->datum);
1045             bag->lock.destroy();
1046             break;
1047         }
1048     }
1049 }
1050 
1051 void
renounce(void * obj,int size,void * refcon)1052 renounce(void* obj, int size, void* refcon)
1053 {
1054     if (PAIRP(obj)) return;
1055     int tc = HDR_TC(HDR(obj));
1056     assert(tc >= 0);
1057     assert(tc <= TC_MASKBITS);
1058     switch (tc) {
1059         case TC_HASHTABLE: {
1060             scm_hashtable_t ht = (scm_hashtable_t)obj;
1061             ht->lock.destroy();
1062             break;
1063         }
1064         case TC_WEAKHASHTABLE: {
1065             scm_weakhashtable_t ht = (scm_weakhashtable_t)obj;
1066             ht->lock.destroy();
1067             break;
1068         }
1069         case TC_PORT: {
1070             scm_port_t port = (scm_port_t)obj;
1071             {
1072                 scoped_lock lock(port->lock);
1073                 if (port->type != SCM_PORT_TYPE_CUSTOM) port_close(port);
1074             }
1075             port->lock.destroy();
1076             break;
1077         }
1078         case TC_SOCKET: {
1079             scm_socket_t socket = (scm_socket_t)obj;
1080             {
1081                 scoped_lock lock(socket->lock);
1082                 socket_close(socket);
1083             }
1084             socket->lock.destroy();
1085             break;
1086         }
1087         case TC_SHAREDQUEUE: {
1088             scm_sharedqueue_t queue = (scm_sharedqueue_t)obj;
1089             queue->buf.destroy();
1090             queue->queue.destroy();
1091             break;
1092         }
1093         case TC_SHAREDBAG: {
1094             scm_sharedbag_t bag = (scm_sharedbag_t)obj;
1095             for (int i = 0; i < bag->capacity; i++) {
1096                 bag->datum[i]->buf.destroy();
1097                 bag->datum[i]->queue.destroy();
1098                 free(bag->datum[i]->key);
1099                 free(bag->datum[i]);
1100             }
1101             free(bag->datum);
1102             bag->lock.destroy();
1103             break;
1104         }
1105     }
1106 }
1107