Browse Source

Add duk_{xcopy,xmove}_top(), remove duk_xmove()

Note: If 'count' exceeds valstack_max, an "invalid count" message is thrown
(same goes for a negative count).  Use the same message also for the case
where 'count' exceeds the source stack depth just a little.  Previously the
code would use a different error message for this case.
v1.0-maintenance
Sami Vaarala 10 years ago
parent
commit
399fd412a8
  1. 7
      src/duk_api_public.h.in
  2. 63
      src/duk_api_stack.c
  3. 2
      src/duk_strings.c
  4. 4
      src/duk_strings.h

7
src/duk_api_public.h.in

@ -299,8 +299,11 @@ void duk_insert(duk_context *ctx, duk_idx_t to_index);
void duk_replace(duk_context *ctx, duk_idx_t to_index);
void duk_copy(duk_context *ctx, duk_idx_t from_index, duk_idx_t to_index);
void duk_remove(duk_context *ctx, duk_idx_t index);
/* FIXME: undocumented */
void duk_xmove(duk_context *from_ctx, duk_context *to_ctx, duk_idx_t count);
void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy);
#define duk_xmove_top(to_ctx,from_ctx,count) \
duk_xcopymove_raw((to_ctx), (from_ctx), (count), 0 /*is_copy*/)
#define duk_xcopy_top(to_ctx,from_ctx,count) \
duk_xcopymove_raw((to_ctx), (from_ctx), (count), 1 /*is_copy*/)
/*
* Push operations

63
src/duk_api_stack.c

@ -315,6 +315,9 @@ void duk_set_top(duk_context *ctx, duk_idx_t index) {
DUK_TVAL_SET_TVAL(&tv_tmp, tv);
DUK_TVAL_SET_UNDEFINED_UNUSED(tv);
DUK_TVAL_DECREF(thr, &tv_tmp); /* side effects */
/* XXX: fast primitive to set a bunch of values to UNDEFINED_UNUSED */
}
}
return;
@ -869,20 +872,27 @@ void duk_remove(duk_context *ctx, duk_idx_t index) {
* Stack slice primitives
*/
void duk_xmove(duk_context *ctx, duk_context *from_ctx, duk_idx_t count) {
duk_hthread *thr = (duk_hthread *) ctx;
void duk_xcopymove_raw(duk_context *to_ctx, duk_context *from_ctx, duk_idx_t count, duk_bool_t is_copy) {
duk_hthread *to_thr = (duk_hthread *) to_ctx;
duk_hthread *from_thr = (duk_hthread *) from_ctx;
void *src;
duk_size_t nbytes;
duk_tval *p;
duk_tval *q;
DUK_ASSERT(ctx != NULL);
/* XXX: several pointer comparison issues here */
DUK_ASSERT(to_ctx != NULL);
DUK_ASSERT(from_ctx != NULL);
if (to_ctx == from_ctx) {
DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_CONTEXT);
return;
}
if ((count < 0) ||
(count > (duk_idx_t) thr->valstack_max)) {
(count > (duk_idx_t) to_thr->valstack_max)) {
/* Maximum value check ensures 'nbytes' won't wrap below. */
DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
return;
}
@ -890,25 +900,44 @@ void duk_xmove(duk_context *ctx, duk_context *from_ctx, duk_idx_t count) {
if (nbytes == 0) {
return;
}
DUK_ASSERT(thr->valstack_top <= thr->valstack_end);
if ((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack_top) < nbytes) {
DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
DUK_ASSERT(to_thr->valstack_top <= to_thr->valstack_end);
if ((duk_size_t) ((duk_uint8_t *) to_thr->valstack_end - (duk_uint8_t *) to_thr->valstack_top) < nbytes) {
DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_PUSH_BEYOND_ALLOC_STACK);
}
src = (void *) ((duk_uint8_t *) from_thr->valstack_top - nbytes);
if (src < (void *) from_thr->valstack_bottom) {
DUK_ERROR(thr, DUK_ERR_API_ERROR, DUK_STR_SRC_STACK_NOT_ENOUGH);
DUK_ERROR(to_thr, DUK_ERR_API_ERROR, DUK_STR_INVALID_COUNT);
}
/* copy values (no overlap even if ctx == from_ctx) */
/* copy values (no overlap even if to_ctx == from_ctx; that's not
* allowed now anyway)
*/
DUK_ASSERT(nbytes > 0);
DUK_MEMCPY((void *) thr->valstack_top, src, nbytes);
DUK_MEMCPY((void *) to_thr->valstack_top, src, nbytes);
/* incref them */
p = thr->valstack_top;
thr->valstack_top = (duk_tval *) (((duk_uint8_t *) thr->valstack_top) + nbytes);
while (p < thr->valstack_top) {
DUK_TVAL_INCREF(thr, p); /* no side effects */
p++;
p = to_thr->valstack_top;
to_thr->valstack_top = (duk_tval *) (((duk_uint8_t *) p) + nbytes);
if (is_copy) {
/* incref copies, keep originals */
q = to_thr->valstack_top;
while (p < q) {
DUK_TVAL_INCREF(to_thr, p); /* no side effects */
p++;
}
} else {
/* no net refcount change */
p = from_thr->valstack_top;
q = (duk_tval *) (((duk_uint8_t *) p) - nbytes);
from_thr->valstack_top = q;
/* elements above stack top are kept UNUSED */
while (p > q) {
p--;
DUK_TVAL_SET_UNDEFINED_UNUSED(p);
/* XXX: fast primitive to set a bunch of values to UNDEFINED_UNUSED */
}
}
}

2
src/duk_strings.c

@ -17,9 +17,9 @@ const char *duk_str_not_extensible = "not extensible";
const char *duk_str_not_writable = "not writable";
const char *duk_str_not_configurable = "not configurable";
const char *duk_str_invalid_context = "invalid context";
const char *duk_str_invalid_index = "invalid index";
const char *duk_str_push_beyond_alloc_stack = "attempt to push beyond currently allocated stack";
const char *duk_str_src_stack_not_enough = "source stack does not contain enough elements";
const char *duk_str_not_undefined = "not undefined";
const char *duk_str_not_null = "not null";
const char *duk_str_not_boolean = "not boolean";

4
src/duk_strings.h

@ -39,9 +39,9 @@ extern const char *duk_str_not_extensible;
extern const char *duk_str_not_writable;
extern const char *duk_str_not_configurable;
#define DUK_STR_INVALID_CONTEXT duk_str_invalid_context
#define DUK_STR_INVALID_INDEX duk_str_invalid_index
#define DUK_STR_PUSH_BEYOND_ALLOC_STACK duk_str_push_beyond_alloc_stack
#define DUK_STR_SRC_STACK_NOT_ENOUGH duk_str_src_stack_not_enough
#define DUK_STR_NOT_UNDEFINED duk_str_not_undefined
#define DUK_STR_NOT_NULL duk_str_not_null
#define DUK_STR_NOT_BOOLEAN duk_str_not_boolean
@ -76,9 +76,9 @@ extern const char *duk_str_not_configurable;
#define DUK_STR_UNIMPLEMENTED duk_str_unimplemented
#define DUK_STR_ARRAY_LENGTH_OVER_2G duk_str_array_length_over_2g
extern const char *duk_str_invalid_context;
extern const char *duk_str_invalid_index;
extern const char *duk_str_push_beyond_alloc_stack;
extern const char *duk_str_src_stack_not_enough;
extern const char *duk_str_not_undefined;
extern const char *duk_str_not_null;
extern const char *duk_str_not_boolean;

Loading…
Cancel
Save