Compare commits

..
5 Commits
Author SHA1 Message Date
hyung-hwan 6844dde1b6 nonblock call polishing in pio 2026-08-17 22:48:30 +09:00
hyung-hwan 260318b24c fixed pio flaws 2026-08-17 22:21:41 +09:00
hyung-hwan 6b7873b230 fixed a wrong condition in fix_val_with_raw() in hawk.go 2026-08-05 14:47:30 +09:00
hyung-hwan 5a563d7c15 added hawk_rtx_isimmorstaticval() and fixed the go wrapper to call it to fix a bug of invalid memory reference 2026-08-05 14:36:38 +09:00
hyung-hwan 6dc0dec3e8 added more test cases.
touched up code for stack-based statement execution
2026-08-03 00:54:53 +09:00
9 changed files with 235 additions and 2618 deletions
+4 -3
View File
@@ -701,7 +701,7 @@ func (rtx *Rtx) Exec(args []string) (*Val, error) {
// hawk_rtx_exec...() returns a value with the reference count incremented.
// create a value without going through rtx.make_val()
return rtx.fix_val_with_raw(val), nil
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
//return rtx.make_val(func() *C.hawk_val_t { return val })
}
func (rtx *Rtx) Loop() (*Val, error) {
@@ -711,7 +711,7 @@ func (rtx *Rtx) Loop() (*Val, error) {
// hawk_rtx_loop() returns a value with the reference count incremented.
// create a value without going through rtx.make_val()
return rtx.fix_val_with_raw(val), nil
//return rtx.make_val(func() *C.hawk_val_t { return val })aAAA
//return rtx.make_val(func() *C.hawk_val_t { return val })
}
func (rtx *Rtx) Call(name string, args ...*Val) (*Val, error) {
@@ -1053,7 +1053,8 @@ func (rtx* Rtx) fix_val_with_raw(val *C.hawk_val_t) *Val {
// this function assumes val has the non-zero reference count
// the caller must ensure that the reference count has been incremented properly
var vv *Val
if val.v_refs <= 0 && C.hawk_rtx_isstaticval(rtx.c, val) == 0 { panic("invalid reference count") }
// immediate values or static pointer values must no check the reference count.
if C.hawk_rtx_isimmorstaticval(rtx.c, val) == 0 && val.v_refs <= 0 { panic("invalid reference count") }
vv = &Val{rtx: rtx, c: val}
rtx.chain_val(vv)
return vv
-87
View File
@@ -69,20 +69,6 @@ typedef struct hawk_tree_t hawk_tree_t;
#define HAWK_ENABLE_ATOMIC_SIG
#endif
/* this part is kept for preservation of experiment only.
#if defined(HAVE_UCONTEXT_H)
#include <ucontext.h>
#define HAWK_ENABLE_UCONTEXT
#endif
*/
/* Use iterative (heap-stack) expression evaluation instead of C recursion.
* eval_expression, eval_expression0, and hawk_rtx_evalcall automatically
* route through the xstack variants when this is defined. Comment out to
* revert to the purely recursive implementation. */
/*#define HAWK_ENABLE_XSTACK_EVAL*/
/* ------------------------------------------------------------------------ */
/* private headers. some files are affected by feature macros above */
@@ -462,49 +448,6 @@ struct hawk_exec_stack_t
typedef struct hawk_exec_stack_t hawk_exec_stack_t;
/* expression frame states for eval_expression0_xstack */
enum hawk_ef_state_t
{
HAWK_EF_EVAL = 0, /* dispatch on nde->type */
HAWK_EF_BIN_LEFT, /* binary: awaiting left result */
HAWK_EF_BIN_RIGHT, /* binary: left done (val=left refupped), awaiting right */
HAWK_EF_UNARY, /* unary: awaiting operand result */
HAWK_EF_CND, /* conditional: awaiting test result */
HAWK_EF_ASS_RHS, /* assignment: awaiting RHS result */
HAWK_EF_ASS_LHS, /* compound assign: RHS in val (refupped), awaiting LHS */
HAWK_EF_LAND_LEFT, /* logical AND: awaiting left result */
HAWK_EF_LAND_RIGHT, /* logical AND: left done and true (val=left), awaiting right */
HAWK_EF_LOR_LEFT, /* logical OR: awaiting left result */
HAWK_EF_LOR_RIGHT, /* logical OR: left done and false (val=left), awaiting right */
#if defined(HAWK_ENABLE_XSTACK_EVAL)
HAWK_EF_FNCALL_FUN_AWAIT /* user fn body executing on exec_stack; aux=exec_body_base */
#endif
};
typedef enum hawk_ef_state_t hawk_ef_state_t;
struct hawk_eframe_t
{
hawk_ef_state_t state;
hawk_nde_t* nde; /* composite node being processed */
hawk_val_t* val; /* intermediate value (refcount incremented) */
hawk_oow_t aux; /* FNCALL_FUN_AWAIT: exec_stack size when body frames were pushed */
};
typedef struct hawk_eframe_t hawk_eframe_t;
#if defined(HAWK_ENABLE_XSTACK_EVAL)
/* call frame: saves context for a user-defined function call made from within
* expression evaluation. stored in the call_stack. */
struct hawk_call_frame_t
{
hawk_nde_fncall_t* call; /* call-site node */
hawk_fun_t* fun; /* resolved function */
hawk_oow_t saved_stack_top; /* rtx->stack_top before the call */
hawk_oow_t saved_stack_base;/* rtx->stack_base before the call */
hawk_oow_t nargs; /* actual argument count pushed */
};
typedef struct hawk_call_frame_t hawk_call_frame_t;
#endif
struct hawk_rtx_t
{
HAWK_RTX_HDR;
@@ -524,36 +467,6 @@ struct hawk_rtx_t
hawk_oow_t exec_stack_size;
hawk_oow_t exec_stack_limit;
/* heap-based stack for iterative expression evaluation (xstack variant) */
hawk_eframe_t* eframe_stack;
hawk_oow_t eframe_stack_size;
hawk_oow_t eframe_stack_limit;
#if defined(HAWK_ENABLE_XSTACK_EVAL)
/* heap-based call frame stack: user-defined function calls from eframe evaluation */
hawk_call_frame_t* call_stack;
hawk_oow_t call_stack_size;
hawk_oow_t call_stack_limit;
/* result register: eframe eval result delivered to exec AFTER_EVAL frames */
hawk_val_t* driver_eval_result;
#endif
#if defined(HAWK_ENABLE_UCONTEXT)
/* pool of reusable C stacks for coroutine-based function calls */
struct
{
char* pool[16];
hawk_oow_t pool_size;
/* arguments for the next coroutine invocation */
hawk_nde_blk_t* pending_body;
int* pending_result;
/* depth at which the current C stack segment started */
hawk_oow_t stack_base;
/* nonzero when executing on a heap-allocated coroutine stack */
int in_coroutine;
} co;
#endif
int exit_level;
int init_called;
+16 -6
View File
@@ -1922,14 +1922,12 @@ static HAWK_INLINE void hawk_geterruinf (hawk_t* hawk, hawk_erruinf_t* errinf) {
* it automatically formatted.
*/
#if defined(HAWK_HAVE_INLINE)
static HAWK_INLINE void hawk_clrerror (hawk_t* hawk) { hawk_gem_seterrnum(hawk_getgem(hawk), HAWK_NULL, HAWK_ENOERR); }
static HAWK_INLINE void hawk_seterrnum (hawk_t* hawk, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum(hawk_getgem(hawk), errloc, errnum); }
static HAWK_INLINE void hawk_seterrinf (hawk_t* hawk, const hawk_errinf_t* errinf) { hawk_gem_seterrinf(hawk_getgem(hawk), errinf); }
static HAWK_INLINE void hawk_seterrnum (hawk_t* hawk, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum (hawk_getgem(hawk), errloc, errnum); }
static HAWK_INLINE void hawk_seterrinf (hawk_t* hawk, const hawk_errinf_t* errinf) { hawk_gem_seterrinf (hawk_getgem(hawk), errinf); }
static HAWK_INLINE void hawk_seterror (hawk_t* hawk, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_oocs_t* errarg) { hawk_gem_seterror(hawk_getgem(hawk), errloc, errnum, errarg); }
static HAWK_INLINE const hawk_ooch_t* hawk_backuperrmsg (hawk_t* hawk) { return hawk_gem_backuperrmsg(hawk_getgem(hawk)); }
static HAWK_INLINE void hawk_geterror (hawk_t* hawk, hawk_errnum_t* errnum, const hawk_ooch_t** errmsg, hawk_loc_t* errloc) { return hawk_gem_geterror(hawk_getgem(hawk), errnum, errmsg, errloc); }
#else
#define hawk_clrerror(hawk) hawk_gem_seterrnum(hawk_getgem(hawk), HAWK_NULL, HAWK_ENOERR)
#define hawk_seterrnum(hawk, errloc, errnum) hawk_gem_seterrnum(hawk_getgem(hawk), errloc, errnum)
#define hawk_seterrinf(hawk, errinf) hawk_gem_seterrinf(hawk_getgem(hawk), errinf)
#define hawk_seterror(hawk, errloc, errnum, errarg) hawk_gem_seterror(hawk_getgem(hawk), errloc, errnum, errarg)
@@ -3121,13 +3119,11 @@ static HAWK_INLINE void hawk_rtx_geterror (hawk_rtx_t* rtx, hawk_errnum_t* errnu
* The hawk_rtx_seterrinf() function sets error information.
*/
#if defined(HAWK_HAVE_INLINE)
static HAWK_INLINE void hawk_rtx_clrerror (hawk_rtx_t* rtx) { hawk_gem_seterrnum(hawk_rtx_getgem(rtx), HAWK_NULL, HAWK_ENOERR); }
static HAWK_INLINE void hawk_rtx_seterrnum (hawk_rtx_t* rtx, const hawk_loc_t* errloc, hawk_errnum_t errnum) { hawk_gem_seterrnum (hawk_rtx_getgem(rtx), errloc, errnum); }
static HAWK_INLINE void hawk_rtx_seterrinf (hawk_rtx_t* rtx, const hawk_errinf_t* errinf) { hawk_gem_seterrinf (hawk_rtx_getgem(rtx), errinf); }
static HAWK_INLINE void hawk_rtx_seterror (hawk_rtx_t* rtx, const hawk_loc_t* errloc, hawk_errnum_t errnum, const hawk_oocs_t* errarg) { hawk_gem_seterror(hawk_rtx_getgem(rtx), errloc, errnum, errarg); }
static HAWK_INLINE const hawk_ooch_t* hawk_rtx_backuperrmsg (hawk_rtx_t* rtx) { return hawk_gem_backuperrmsg(hawk_rtx_getgem(rtx)); }
#else
#define hawk_rtx_clrerror(rtx) hawk_gem_seterrnum(hawk_rtx_getgem(rtx), HAWK_NULL, HAWK_ENOERR)
#define hawk_rtx_seterrnum(rtx, errloc, errnum) hawk_gem_seterrnum(hawk_rtx_getgem(rtx), errloc, errnum)
#define hawk_rtx_seterrinf(rtx, errinf) hawk_gem_seterrinf(hawk_rtx_getgem(rtx), errinf)
#define hawk_rtx_seterror(rtx, errloc, errnum, errarg) hawk_gem_seterror(hawk_rtx_getgem(rtx), errloc, errnum, errarg)
@@ -3657,6 +3653,20 @@ HAWK_EXPORT int hawk_rtx_isstaticval (
const hawk_val_t* val /**< value to check */
);
/**
* The hawk_rtx_isimmval() function determines if a value is a immediate value
* encoded using pointer tagging.
*/
HAWK_EXPORT int hawk_rtx_isimmval (
hawk_rtx_t* rtx, /**< runtime context */
const hawk_val_t* val /**< value to check */
);
HAWK_EXPORT int hawk_rtx_isimmorstaticval (
hawk_rtx_t* rtx, /**< runtime context */
const hawk_val_t* val /**< value to check */
);
HAWK_EXPORT int hawk_rtx_getvaltype (
hawk_rtx_t* rtx,
const hawk_val_t* val
+4 -9
View File
@@ -22,15 +22,6 @@
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <hawk-cfg.h>
#if defined(HAVE_ACCEPT4)
/* the runtime library has accept4. but accept4 is usually visiable
* if _GNU_SOURCE is defined */
# if !defined(_GNU_SOURCE)
# define _GNU_SOURCE
# endif
#endif
#include "mod-sys.h"
#include "hawk-prv.h"
#include <hawk-pio.h>
@@ -51,6 +42,10 @@
#elif defined(__DOS__)
# include <dos.h>
#else
# if !defined(_GNU_SOURCE)
# define _GNU_SOURCE
# endif
# include "syscall.h"
# include <sys/utsname.h>
# if defined(HAVE_SYS_EPOLL_H)
+92 -15
View File
@@ -601,9 +601,17 @@ static hawk_pio_pid_t standard_fork_and_exec (hawk_pio_t* pio, int pipes[], para
#endif
#if !defined(__DOS__)
/* not needed on DOS: hawk_pio_init() bails out with HAWK_ENOIMPL there before
* any pipe is ever created, so there is no call site for this. */
static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
{
#if defined(O_NONBLOCK)
#if defined(_WIN32)
/* anonymous pipes created by CreatePipe() cannot be switched to
* non-blocking mode. */
hawk_gem_seterrnum(pio->gem, HAWK_NULL, HAWK_ENOIMPL);
return -1;
#elif defined(O_NONBLOCK)
int flag = HAWK_FCNTL(fd, F_GETFL, 0);
if (flag >= 0) flag = HAWK_FCNTL(fd, F_SETFL, (enabled? (flag | O_NONBLOCK): (flag & ~O_NONBLOCK)));
if (flag <= -1) hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
@@ -613,6 +621,7 @@ static int set_pipe_nonblock (hawk_pio_t* pio, hawk_pio_hnd_t fd, int enabled)
return -1;
#endif
}
#endif
int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int flags, hawk_pio_env_mk_t env_mk, void* env_ctx)
@@ -725,6 +734,12 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
}
}
/* handle[1] is the parent's end and is never inherited by the child,
* so switching it here - before the child exists - is equivalent to
* doing it afterwards, and keeps this failure out of the window in
* which a spawned child would have to be cleaned up. */
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
minidx = 0; maxidx = 1;
}
@@ -750,6 +765,8 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
}
}
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
if (minidx == -1) minidx = 2;
maxidx = 3;
}
@@ -776,6 +793,8 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
}
}
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
if (minidx == -1) minidx = 4;
maxidx = 5;
}
@@ -813,7 +832,7 @@ int hawk_pio_init (hawk_pio_t* pio, hawk_gem_t* gem, const hawk_ooch_t* cmd, int
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startup.hStdOutput = GetStdHandle(STD_ERROR_HANDLE);
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if (startup.hStdInput == INVALID_HANDLE_VALUE ||
startup.hStdOutput == INVALID_HANDLE_VALUE ||
startup.hStdError == INVALID_HANDLE_VALUE)
@@ -1013,6 +1032,12 @@ create_process:
DosQueryFHState (handle[1], &state);
DosSetFHState (handle[1], state | OPEN_FLAGS_NOINHERIT); */
/* handle[1] is the parent's end and is marked NOINHERIT above, so
* switching it before the child exists is equivalent to doing it
* afterwards, and keeps this failure out of the window in which a
* spawned child would have to be cleaned up. */
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
minidx = 0; maxidx = 1;
}
@@ -1035,6 +1060,8 @@ create_process:
goto oops;
}
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
if (minidx == -1) minidx = 2;
maxidx = 3;
}
@@ -1058,6 +1085,8 @@ create_process:
goto oops;
}
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
if (minidx == -1) minidx = 4;
maxidx = 5;
}
@@ -1303,6 +1332,15 @@ create_process:
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
goto oops;
}
/* O_NONBLOCK belongs to the open file description, and handle[1] is
* the parent's end - a different description from the handle[0] the
* child inherits, and one the child closes anyway. so switching it
* here, before the child exists, is equivalent to doing it after the
* spawn, and keeps this failure out of the window in which a spawned
* child would have to be cleaned up. */
if ((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) goto oops;
minidx = 0; maxidx = 1;
}
@@ -1313,6 +1351,9 @@ create_process:
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
goto oops;
}
if ((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) goto oops;
if (minidx == -1) minidx = 2;
maxidx = 3;
}
@@ -1324,6 +1365,9 @@ create_process:
hawk_gem_seterrnum(pio->gem, HAWK_NULL, hawk_syserr_to_errnum(errno));
goto oops;
}
if ((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1) goto oops;
if (minidx == -1) minidx = 4;
maxidx = 5;
}
@@ -1761,13 +1805,6 @@ create_process:
}
#endif
if (((flags & HAWK_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
((flags & HAWK_PIO_OUTNOBLOCK) && set_pipe_nonblock(pio, handle[2], 1) <= -1) ||
((flags & HAWK_PIO_ERRNOBLOCK) && set_pipe_nonblock(pio, handle[4], 1) <= -1))
{
goto oops;
}
/* store back references */
pio->pin[HAWK_PIO_IN].self = pio;
pio->pin[HAWK_PIO_OUT].self = pio;
@@ -1778,7 +1815,6 @@ create_process:
pio->pin[HAWK_PIO_OUT].handle = handle[2];
pio->pin[HAWK_PIO_ERR].handle = handle[4];
if (flags & HAWK_PIO_TEXT)
{
int topt = 0;
@@ -1791,6 +1827,9 @@ create_process:
{
int r;
/* NOTE: the child process has already been spawned.
* jumping to oops for failure below will trigger forced kill of
* a child process at the beginning of the oops part */
tio[i] = hawk_tio_open(pio->gem, HAWK_SIZEOF(&pio->pin[i]), topt);
if (HAWK_UNLIKELY(!tio[i])) goto oops;
@@ -1808,6 +1847,26 @@ create_process:
return 0;
oops:
/* if the child has already been spawned, a failure in a later step must
* not leave it behind: the caller is about to get -1 and will never have
* a handle to reap it with. */
if (pio->child != HAWK_PIO_PID_NIL)
{
hawk_errnum_t err = hawk_gem_geterrnum(pio->gem);
/* SIGKILL, not a bare wait: the child may be long-running, or blocked
* writing to a pipe we still hold - either would hang us here. */
hawk_pio_kill(pio);
/* the caller's WAITNOBLOCK/WAITNORETRY must not stop us reaping */
pio->flags &= ~HAWK_PIO_WAITNOBLOCK;
pio->flags &= ~HAWK_PIO_WAITNORETRY;
hawk_pio_wait(pio); /* reaps and resets child to PID_NIL */
/* kill()/wait() set errnum themselves - restore the real cause */
hawk_gem_seterrnum (pio->gem, HAWK_NULL, err);
}
#if defined(_WIN32)
if (windevnul != INVALID_HANDLE_VALUE) CloseHandle(windevnul);
@@ -1837,12 +1896,21 @@ oops:
}
#if defined(_WIN32)
for (i = minidx; i < maxidx; i++) CloseHandle(handle[i]);
if (minidx >= 0)
{
for (i = minidx; i <= maxidx; i++)
{
if (handle[i] != HAWK_PIO_HND_NIL) CloseHandle(handle[i]);
}
}
#elif defined(__OS2__)
for (i = minidx; i < maxidx; i++)
if (minidx >= 0)
{
for (i = minidx; i <= maxidx; i++)
{
if (handle[i] != HAWK_PIO_HND_NIL) DosClose(handle[i]);
}
}
#elif defined(__DOS__)
/* DOS not multi-processed. can't support pio */
@@ -1852,20 +1920,29 @@ oops:
posix_spawn_file_actions_destroy (&fa);
fa_inited = 0;
}
for (i = minidx; i < maxidx; i++)
if (i >= 0)
{
for (i = minidx; i <= maxidx; i++)
{
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
}
}
#elif defined(HAWK_SYSCALL0) && defined(SYS_vfork)
for (i = minidx; i < maxidx; i++)
if (i >= 0)
{
for (i = minidx; i <= maxidx; i++)
{
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
}
}
#else
for (i = minidx; i < maxidx; i++)
if (i >= 0)
{
for (i = minidx; i <= maxidx; i++)
{
if (handle[i] != HAWK_PIO_HND_NIL) HAWK_CLOSE(handle[i]);
}
}
#endif
return -1;
-13
View File
@@ -30,7 +30,6 @@ enum hawk_assop_type_t
/* if you change this, you have to change assop_str in tree.c.
* synchronize it wit:
* - binop_func in eval_assignment of run.c
* - binop_func in eval_expression0_xstack in run.c
* - assop in assing_to_opcode of parse.c
* - TOK_XXX_ASSN in tok_t in parse.c
* - assop_str in tree.c
@@ -150,18 +149,6 @@ hawk_val_t* hawk_rtx_evalcall (
void* eharg
);
#if 0
hawk_val_t* hawk_rtx_evalcall_xstack (
hawk_rtx_t* rtx,
hawk_nde_fncall_t* call,
hawk_fun_t* fun,
hawk_oow_t(*argpusher)(hawk_rtx_t*,const hawk_loc_t* loc,void*),
void* apdata,
void(*errhandler)(void*),
void* eharg
);
#endif
int hawk_rtx_setsighandler (
hawk_rtx_t* rtx,
int sig,
+75 -2430
View File
File diff suppressed because it is too large Load Diff
-21
View File
@@ -215,18 +215,6 @@ void hawk_rtx_freevalchunk (
);
#if defined(HAWK_HAVE_INLINE)
/* the nocheck versions are defined in case you already know the value
* is a pointer and not a static value */
static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_nocheck_inline (hawk_rtx_t* rtx, hawk_val_t* val)
{
#if defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_ADD)
HAWK_ATOMIC_FETCH_ADD(&val->v_refs, 1, HAWK_ATOMIC_RELAXED);
#else
val->v_refs++;
#endif
}
/* regular refup with pointer check */
static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_inline (hawk_rtx_t* rtx, hawk_val_t* val)
{
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val))
@@ -238,22 +226,13 @@ static HAWK_INLINE_ALWAYS void hawk_rtx_refupval_inline (hawk_rtx_t* rtx, hawk_v
#endif
}
}
#elif defined(HAWK_USE_ATOMIC_REFCNT) && defined(HAWK_ATOMIC_FETCH_ADD)
#define hawk_rtx_refupval_nocheck_inline(rtx, val) do { \
HAWK_ATOMIC_FETCH_ADD(&(val)->v_refs, 1, HAWK_ATOMIC_RELAXED); \
} while(0)
#define hawk_rtx_refupval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) { \
HAWK_ATOMIC_FETCH_ADD(&(val)->v_refs, 1, HAWK_ATOMIC_RELAXED); \
} \
} while(0)
#else
#define hawk_rtx_refupval_nocheck_inline(rtx, val) do { (val)->v_refs++; } while(0)
#define hawk_rtx_refupval_inline(rtx, val) do { \
if (HAWK_VTR_IS_POINTER(val) && !HAWK_IS_STATICVAL(val)) (val)->v_refs++; \
} while(0)
+11 -1
View File
@@ -1572,11 +1572,21 @@ hawk_val_t* hawk_rtx_makebobval (hawk_rtx_t* rtx, const void* ptr, hawk_oow_t le
return (hawk_val_t*)val;
}
int HAWK_INLINE hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
int hawk_rtx_isstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
{
return HAWK_VTR_IS_POINTER(val) && HAWK_IS_STATICVAL(val);
}
int hawk_rtx_isimmval (hawk_rtx_t* rtx, const hawk_val_t* val)
{
return !HAWK_VTR_IS_POINTER(val);
}
int hawk_rtx_isimmorstaticval (hawk_rtx_t* rtx, const hawk_val_t* val)
{
return !HAWK_VTR_IS_POINTER(val) || HAWK_IS_STATICVAL(val);
}
int hawk_rtx_getvaltype (hawk_rtx_t* rtx, const hawk_val_t* val)
{
return HAWK_RTX_GETVALTYPE(rtx, val);