5 #include "duk_internal.h"
7 DUK_INTERNAL
void duk_hthread_terminate(duk_hthread
*thr
) {
8 DUK_ASSERT(thr
!= NULL
);
10 /* Order of unwinding is important */
12 duk_hthread_catchstack_unwind(thr
, 0);
14 duk_hthread_callstack_unwind(thr
, 0); /* side effects, possibly errors */
16 thr
->valstack_bottom
= thr
->valstack
;
17 duk_set_top((duk_context
*) thr
, 0); /* unwinds valstack, updating refcounts */
19 thr
->state
= DUK_HTHREAD_STATE_TERMINATED
;
21 /* Here we could remove references to built-ins, but it may not be
22 * worth the effort because built-ins are quite likely to be shared
23 * with another (unterminated) thread, and terminated threads are also
24 * usually garbage collected quite quickly. Also, doing DECREFs
25 * could trigger finalization, which would run on the current thread
26 * and have access to only some of the built-ins. Garbage collection
27 * deals with this correctly already.
30 /* XXX: Shrink the stacks to minimize memory usage? May not
31 * be worth the effort because terminated threads are usually
32 * garbage collected quite soon.
36 DUK_INTERNAL duk_activation
*duk_hthread_get_current_activation(duk_hthread
*thr
) {
37 DUK_ASSERT(thr
!= NULL
);
39 if (thr
->callstack_top
> 0) {
40 return thr
->callstack
+ thr
->callstack_top
- 1;
46 #if defined(DUK_USE_DEBUGGER_SUPPORT)
47 DUK_INTERNAL duk_uint_fast32_t
duk_hthread_get_act_curr_pc(duk_hthread
*thr
, duk_activation
*act
) {
50 DUK_ASSERT(thr
!= NULL
);
51 DUK_ASSERT(act
!= NULL
);
54 /* XXX: store 'bcode' pointer to activation for faster lookup? */
55 if (act
->func
&& DUK_HOBJECT_IS_COMPILEDFUNCTION(act
->func
)) {
56 bcode
= DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr
->heap
, (duk_hcompiledfunction
*) (act
->func
));
57 return (duk_uint_fast32_t
) (act
->curr_pc
- bcode
);
61 #endif /* DUK_USE_DEBUGGER_SUPPORT */
63 DUK_INTERNAL duk_uint_fast32_t
duk_hthread_get_act_prev_pc(duk_hthread
*thr
, duk_activation
*act
) {
65 duk_uint_fast32_t ret
;
67 DUK_ASSERT(thr
!= NULL
);
68 DUK_ASSERT(act
!= NULL
);
71 if (act
->func
&& DUK_HOBJECT_IS_COMPILEDFUNCTION(act
->func
)) {
72 bcode
= DUK_HCOMPILEDFUNCTION_GET_CODE_BASE(thr
->heap
, (duk_hcompiledfunction
*) (act
->func
));
73 ret
= (duk_uint_fast32_t
) (act
->curr_pc
- bcode
);
82 /* Write bytecode executor's curr_pc back to topmost activation (if any). */
83 DUK_INTERNAL
void duk_hthread_sync_currpc(duk_hthread
*thr
) {
86 DUK_ASSERT(thr
!= NULL
);
88 if (thr
->ptr_curr_pc
!= NULL
) {
89 /* ptr_curr_pc != NULL only when bytecode executor is active. */
90 DUK_ASSERT(thr
->callstack_top
> 0);
91 act
= thr
->callstack
+ thr
->callstack_top
- 1;
92 act
->curr_pc
= *thr
->ptr_curr_pc
;
96 DUK_INTERNAL
void duk_hthread_sync_and_null_currpc(duk_hthread
*thr
) {
99 DUK_ASSERT(thr
!= NULL
);
101 if (thr
->ptr_curr_pc
!= NULL
) {
102 /* ptr_curr_pc != NULL only when bytecode executor is active. */
103 DUK_ASSERT(thr
->callstack_top
> 0);
104 act
= thr
->callstack
+ thr
->callstack_top
- 1;
105 act
->curr_pc
= *thr
->ptr_curr_pc
;
106 thr
->ptr_curr_pc
= NULL
;