Browse Source

Make resize operations cold/unlikely

The actual resize events (call stack, etc) shouldn't be inlined because they
affect code locality and are very rarely triggered.
pull/1309/head
Sami Vaarala 8 years ago
parent
commit
3ca687a9c0
  1. 59
      src-input/duk_api_stack.c
  2. 2
      src-input/duk_heap_stringtable.c
  3. 73
      src-input/duk_hthread_stacks.c
  4. 2
      src-input/duk_util_bufwriter.c

59
src-input/duk_api_stack.c

@ -686,26 +686,16 @@ DUK_LOCAL duk_bool_t duk__resize_valstack(duk_context *ctx, duk_size_t new_size)
return 1;
}
DUK_INTERNAL
duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
DUK_LOCAL DUK_COLD DUK_NOINLINE duk_bool_t duk__valstack_do_resize(duk_context *ctx,
duk_size_t min_new_size,
duk_small_uint_t flags) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_size_t old_size;
duk_size_t new_size;
duk_bool_t is_shrink = 0;
duk_small_uint_t shrink_flag = (flags & DUK_VSRESIZE_FLAG_SHRINK);
duk_bool_t is_shrink;
duk_small_uint_t compact_flag = (flags & DUK_VSRESIZE_FLAG_COMPACT);
duk_small_uint_t throw_flag = (flags & DUK_VSRESIZE_FLAG_THROW);
DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
"curr_bottom=%ld, shrink=%d, compact=%d, throw=%d",
(unsigned long) min_new_size,
(long) (thr->valstack_end - thr->valstack),
(long) (thr->valstack_top - thr->valstack),
(long) (thr->valstack_bottom - thr->valstack),
(int) shrink_flag, (int) compact_flag, (int) throw_flag));
DUK_ASSERT_CTX_VALID(ctx);
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
@ -721,11 +711,8 @@ duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
if (min_new_size <= old_size) {
is_shrink = 1;
if (!shrink_flag ||
old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD) {
DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
return 1;
}
} else {
is_shrink = 0;
}
new_size = min_new_size;
@ -786,6 +773,44 @@ duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
return 1;
}
DUK_INTERNAL duk_bool_t duk_valstack_resize_raw(duk_context *ctx,
duk_size_t min_new_size,
duk_small_uint_t flags) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_size_t old_size;
DUK_DDD(DUK_DDDPRINT("check valstack resize: min_new_size=%lu, curr_size=%ld, curr_top=%ld, "
"curr_bottom=%ld, flags=%lx",
(unsigned long) min_new_size,
(long) (thr->valstack_end - thr->valstack),
(long) (thr->valstack_top - thr->valstack),
(long) (thr->valstack_bottom - thr->valstack),
(unsigned long) flags));
DUK_ASSERT_CTX_VALID(ctx);
DUK_ASSERT(thr != NULL);
DUK_ASSERT(thr->valstack_bottom >= thr->valstack);
DUK_ASSERT(thr->valstack_top >= thr->valstack_bottom);
DUK_ASSERT(thr->valstack_end >= thr->valstack_top);
#if defined(DUK_USE_PREFER_SIZE)
old_size = (duk_size_t) (thr->valstack_end - thr->valstack);
#else
DUK_ASSERT((duk_size_t) (thr->valstack_end - thr->valstack) == thr->valstack_size);
old_size = thr->valstack_size;
#endif
if (DUK_LIKELY(min_new_size <= old_size)) {
if (DUK_LIKELY((flags & DUK_VSRESIZE_FLAG_SHRINK) == 0 ||
old_size - min_new_size < DUK_VALSTACK_SHRINK_THRESHOLD)) {
DUK_DDD(DUK_DDDPRINT("no need to grow or shrink valstack"));
return 1;
}
}
return duk__valstack_do_resize(ctx, min_new_size, flags);
}
DUK_EXTERNAL duk_bool_t duk_check_stack(duk_context *ctx, duk_idx_t extra) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_size_t min_new_size;

2
src-input/duk_heap_stringtable.c

@ -476,7 +476,7 @@ DUK_LOCAL void duk__strtable_shrink_inplace(duk_heap *heap) {
*/
#if defined(DUK__STRTAB_RESIZE_CHECK)
DUK_LOCAL void duk__strtable_resize_check(duk_heap *heap) {
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__strtable_resize_check(duk_heap *heap) {
duk_uint32_t load_factor; /* fixed point */
DUK_ASSERT(heap != NULL);

73
src-input/duk_hthread_stacks.c

@ -22,8 +22,7 @@
#include "duk_internal.h"
/* check that there is space for at least one new entry */
DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__hthread_do_callstack_grow(duk_hthread *thr) {
duk_activation *new_ptr;
duk_size_t old_size;
duk_size_t new_size;
@ -32,10 +31,6 @@ DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
if (thr->callstack_top < thr->callstack_size) {
return;
}
old_size = thr->callstack_size;
new_size = old_size + DUK_CALLSTACK_GROW_STEP;
@ -63,17 +58,25 @@ DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
/* note: any entries above the callstack top are garbage and not zeroed */
}
DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
duk_size_t new_size;
duk_activation *p;
/* check that there is space for at least one new entry */
DUK_INTERNAL void duk_hthread_callstack_grow(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
if (thr->callstack_size - thr->callstack_top < DUK_CALLSTACK_SHRINK_THRESHOLD) {
if (DUK_LIKELY(thr->callstack_top < thr->callstack_size)) {
return;
}
duk__hthread_do_callstack_grow(thr);
}
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__hthread_do_callstack_shrink(duk_hthread *thr) {
duk_size_t new_size;
duk_activation *p;
DUK_ASSERT(thr != NULL);
DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
new_size = thr->callstack_top + DUK_CALLSTACK_SHRINK_SPARE;
DUK_ASSERT(new_size >= thr->callstack_top);
@ -101,6 +104,18 @@ DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
/* note: any entries above the callstack top are garbage and not zeroed */
}
DUK_INTERNAL void duk_hthread_callstack_shrink_check(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT_DISABLE(thr->callstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->callstack_size >= thr->callstack_top);
if (DUK_LIKELY(thr->callstack_size - thr->callstack_top < DUK_CALLSTACK_SHRINK_THRESHOLD)) {
return;
}
duk__hthread_do_callstack_shrink(thr);
}
DUK_INTERNAL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_top) {
duk_size_t idx;
@ -328,7 +343,7 @@ DUK_INTERNAL void duk_hthread_callstack_unwind(duk_hthread *thr, duk_size_t new_
*/
}
DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__hthread_do_catchstack_grow(duk_hthread *thr) {
duk_catcher *new_ptr;
duk_size_t old_size;
duk_size_t new_size;
@ -337,10 +352,6 @@ DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
DUK_ASSERT_DISABLE(thr->catchstack_top); /* avoid warning (unsigned) */
DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
if (thr->catchstack_top < thr->catchstack_size) {
return;
}
old_size = thr->catchstack_size;
new_size = old_size + DUK_CATCHSTACK_GROW_STEP;
@ -368,7 +379,19 @@ DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
/* note: any entries above the catchstack top are garbage and not zeroed */
}
DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
DUK_INTERNAL void duk_hthread_catchstack_grow(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT_DISABLE(thr->catchstack_top); /* avoid warning (unsigned) */
DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
if (DUK_LIKELY(thr->catchstack_top < thr->catchstack_size)) {
return;
}
duk__hthread_do_catchstack_grow(thr);
}
DUK_LOCAL DUK_COLD DUK_NOINLINE void duk__hthread_do_catchstack_shrink(duk_hthread *thr) {
duk_size_t new_size;
duk_catcher *p;
@ -376,10 +399,6 @@ DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
DUK_ASSERT_DISABLE(thr->catchstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
if (thr->catchstack_size - thr->catchstack_top < DUK_CATCHSTACK_SHRINK_THRESHOLD) {
return;
}
new_size = thr->catchstack_top + DUK_CATCHSTACK_SHRINK_SPARE;
DUK_ASSERT(new_size >= thr->catchstack_top);
@ -406,6 +425,18 @@ DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
/* note: any entries above the catchstack top are garbage and not zeroed */
}
DUK_INTERNAL void duk_hthread_catchstack_shrink_check(duk_hthread *thr) {
DUK_ASSERT(thr != NULL);
DUK_ASSERT_DISABLE(thr->catchstack_top >= 0); /* avoid warning (unsigned) */
DUK_ASSERT(thr->catchstack_size >= thr->catchstack_top);
if (DUK_LIKELY(thr->catchstack_size - thr->catchstack_top < DUK_CATCHSTACK_SHRINK_THRESHOLD)) {
return;
}
duk__hthread_do_catchstack_shrink(thr);
}
DUK_INTERNAL void duk_hthread_catchstack_unwind(duk_hthread *thr, duk_size_t new_top) {
duk_size_t idx;

2
src-input/duk_util_bufwriter.c

@ -63,7 +63,7 @@ DUK_INTERNAL duk_uint8_t *duk_bw_resize(duk_hthread *thr, duk_bufwriter_ctx *bw_
curr_off = (duk_size_t) (bw_ctx->p - bw_ctx->p_base);
add_sz = (curr_off >> DUK_BW_SPARE_SHIFT) + DUK_BW_SPARE_ADD;
new_sz = curr_off + sz + add_sz;
if (new_sz < curr_off) {
if (DUK_UNLIKELY(new_sz < curr_off)) {
/* overflow */
DUK_ERROR_RANGE(thr, DUK_STR_BUFFER_TOO_LONG);
return NULL; /* not reachable */

Loading…
Cancel
Save