1 /*
2  *  duk_hthread allocation and freeing.
3  */
4 
5 #include "duk_internal.h"
6 
7 /*
8  *  Allocate initial stacks for a thread.  Note that 'thr' must be reachable
9  *  as a garbage collection may be triggered by the allocation attempts.
10  *  Returns zero (without leaking memory) if init fails.
11  */
12 
duk_hthread_init_stacks(duk_heap * heap,duk_hthread * thr)13 DUK_INTERNAL duk_bool_t duk_hthread_init_stacks(duk_heap *heap, duk_hthread *thr) {
14 	duk_size_t alloc_size;
15 	duk_size_t i;
16 
17 	DUK_ASSERT(heap != NULL);
18 	DUK_ASSERT(thr != NULL);
19 	DUK_ASSERT(thr->valstack == NULL);
20 	DUK_ASSERT(thr->valstack_end == NULL);
21 	DUK_ASSERT(thr->valstack_bottom == NULL);
22 	DUK_ASSERT(thr->valstack_top == NULL);
23 	DUK_ASSERT(thr->callstack == NULL);
24 	DUK_ASSERT(thr->catchstack == NULL);
25 
26 	/* valstack */
27 	alloc_size = sizeof(duk_tval) * DUK_VALSTACK_INITIAL_SIZE;
28 	thr->valstack = (duk_tval *) DUK_ALLOC(heap, alloc_size);
29 	if (!thr->valstack) {
30 		goto fail;
31 	}
32 	DUK_MEMZERO(thr->valstack, alloc_size);
33 	thr->valstack_end = thr->valstack + DUK_VALSTACK_INITIAL_SIZE;
34 #if !defined(DUK_USE_PREFER_SIZE)
35 	thr->valstack_size = DUK_VALSTACK_INITIAL_SIZE;
36 #endif
37 	thr->valstack_bottom = thr->valstack;
38 	thr->valstack_top = thr->valstack;
39 
40 	for (i = 0; i < DUK_VALSTACK_INITIAL_SIZE; i++) {
41 		DUK_TVAL_SET_UNDEFINED(&thr->valstack[i]);
42 	}
43 
44 	/* callstack */
45 	alloc_size = sizeof(duk_activation) * DUK_CALLSTACK_INITIAL_SIZE;
46 	thr->callstack = (duk_activation *) DUK_ALLOC(heap, alloc_size);
47 	if (!thr->callstack) {
48 		goto fail;
49 	}
50 	DUK_MEMZERO(thr->callstack, alloc_size);
51 	thr->callstack_size = DUK_CALLSTACK_INITIAL_SIZE;
52 	DUK_ASSERT(thr->callstack_top == 0);
53 
54 	/* catchstack */
55 	alloc_size = sizeof(duk_catcher) * DUK_CATCHSTACK_INITIAL_SIZE;
56 	thr->catchstack = (duk_catcher *) DUK_ALLOC(heap, alloc_size);
57 	if (!thr->catchstack) {
58 		goto fail;
59 	}
60 	DUK_MEMZERO(thr->catchstack, alloc_size);
61 	thr->catchstack_size = DUK_CATCHSTACK_INITIAL_SIZE;
62 	DUK_ASSERT(thr->catchstack_top == 0);
63 
64 	return 1;
65 
66  fail:
67 	DUK_FREE(heap, thr->valstack);
68 	DUK_FREE(heap, thr->callstack);
69 	DUK_FREE(heap, thr->catchstack);
70 
71 	thr->valstack = NULL;
72 	thr->callstack = NULL;
73 	thr->catchstack = NULL;
74 	return 0;
75 }
76 
77 /* For indirect allocs. */
78 
duk_hthread_get_valstack_ptr(duk_heap * heap,void * ud)79 DUK_INTERNAL void *duk_hthread_get_valstack_ptr(duk_heap *heap, void *ud) {
80 	duk_hthread *thr = (duk_hthread *) ud;
81 	DUK_UNREF(heap);
82 	return (void *) thr->valstack;
83 }
84 
duk_hthread_get_callstack_ptr(duk_heap * heap,void * ud)85 DUK_INTERNAL void *duk_hthread_get_callstack_ptr(duk_heap *heap, void *ud) {
86 	duk_hthread *thr = (duk_hthread *) ud;
87 	DUK_UNREF(heap);
88 	return (void *) thr->callstack;
89 }
90 
duk_hthread_get_catchstack_ptr(duk_heap * heap,void * ud)91 DUK_INTERNAL void *duk_hthread_get_catchstack_ptr(duk_heap *heap, void *ud) {
92 	duk_hthread *thr = (duk_hthread *) ud;
93 	DUK_UNREF(heap);
94 	return (void *) thr->catchstack;
95 }
96