Browse Source

Merge pull request #1086 from svaarala/put-number-list-fastints

Add fastint check for duk_put_number_list() values
pull/1097/head
Sami Vaarala 8 years ago
committed by GitHub
parent
commit
f77ea3fa4d
  1. 2
      RELEASES.rst
  2. 2
      src-input/duk_api_bytecode.c
  3. 5
      src-input/duk_api_object.c
  4. 4
      src-input/duk_bi_thread.c
  5. 4
      src-input/duk_heaphdr.h
  6. 6
      src-input/duk_js_call.c
  7. 2
      src-input/duk_js_compiler.c
  8. 4
      src-input/duk_js_executor.c
  9. 6
      src-input/duk_tval.c
  10. 51
      src-input/duk_tval.h
  11. 11
      tests/api/test-put-func-num-list.c

2
RELEASES.rst

@ -1959,6 +1959,8 @@ Planned
ES6 and other engines; "\078" is now accepted and is the same as
"\u00078", "\8" and "\9" are accepted as literal "8" and "9" (GH-1057)
* Add a fastint check for duk_put_number_list() values (GH-1086)
* Fix Object.prototype.__proto__ handling to use ToObject() coercion rather
than requiring an object; this matches ES6 requirements and allows e.g.
the expression (123).__proto__ to work (GH-1080)

2
src-input/duk_api_bytecode.c

@ -487,7 +487,7 @@ static duk_uint8_t *duk__load_func(duk_context *ctx, duk_uint8_t *p, duk_uint8_t
duk_double_t val;
DUK__ASSERT_LEFT(8);
val = DUK_RAW_READ_DOUBLE_BE(p);
DUK_TVAL_SET_NUMBER_CHKFAST(&tv_tmp, val);
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(&tv_tmp, val);
duk_push_tval(ctx, &tv_tmp);
break;
}

5
src-input/duk_api_object.c

@ -528,13 +528,16 @@ DUK_EXTERNAL void duk_put_function_list(duk_context *ctx, duk_idx_t obj_idx, con
DUK_EXTERNAL void duk_put_number_list(duk_context *ctx, duk_idx_t obj_idx, const duk_number_list_entry *numbers) {
const duk_number_list_entry *ent = numbers;
duk_tval *tv;
DUK_ASSERT_CTX_VALID(ctx);
obj_idx = duk_require_normalize_index(ctx, obj_idx);
if (ent != NULL) {
while (ent->key != NULL) {
duk_push_number(ctx, ent->value);
tv = ((duk_hthread *) ctx)->valstack_top++;
DUK_ASSERT(DUK_TVAL_IS_UNDEFINED(tv)); /* value stack init policy */
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv, ent->value); /* no need for decref/incref */
duk_put_prop_string(ctx, obj_idx, ent->key);
ent++;
}

4
src-input/duk_bi_thread.c

@ -169,7 +169,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_resume(duk_context *ctx) {
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom + 1 < thr->valstack_top);
DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[1]); /* side effects */
DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;
@ -288,7 +288,7 @@ DUK_INTERNAL duk_ret_t duk_bi_thread_yield(duk_context *ctx) {
/* lj value1: value */
DUK_ASSERT(thr->valstack_bottom < thr->valstack_top);
DUK_TVAL_SET_TVAL_UPDREF(thr, &thr->heap->lj.value1, &thr->valstack_bottom[0]); /* side effects */
DUK_TVAL_CHKFAST_INPLACE(&thr->heap->lj.value1);
DUK_TVAL_CHKFAST_INPLACE_SLOW(&thr->heap->lj.value1);
thr->heap->lj.iserror = is_error;

4
src-input/duk_heaphdr.h

@ -574,7 +574,7 @@ struct duk_heaphdr_string {
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
duk_tval *tv__dst; duk_tval tv__tmp; tv__dst = (tvptr_dst); \
DUK_TVAL_SET_TVAL(&tv__tmp, tv__dst); \
DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
DUK_TVAL_DECREF((thr), &tv__tmp); /* side effects */ \
} while (0)
#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
@ -800,7 +800,7 @@ struct duk_heaphdr_string {
} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF_ALT0(thr,tvptr_dst,newval) do { \
duk_tval *tv__dst; tv__dst = (tvptr_dst); \
DUK_TVAL_SET_NUMBER_CHKFAST(tv__dst, (newval)); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv__dst, (newval)); \
DUK_UNREF((thr)); \
} while (0)
#define DUK_TVAL_SET_DOUBLE_UPDREF_ALT0(thr,tvptr_dst,newval) do { \

6
src-input/duk_js_call.c

@ -1598,7 +1598,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
tv_funret = thr->valstack_top - 1;
#if defined(DUK_USE_FASTINT)
/* Explicit check for fastint downgrade. */
DUK_TVAL_CHKFAST_INPLACE(tv_funret);
DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
#endif
DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
} else {
@ -1663,7 +1663,7 @@ DUK_LOCAL void duk__handle_call_inner(duk_hthread *thr,
tv_funret = thr->valstack_top - 1;
#if defined(DUK_USE_FASTINT)
/* Explicit check for fastint downgrade. */
DUK_TVAL_CHKFAST_INPLACE(tv_funret);
DUK_TVAL_CHKFAST_INPLACE_FAST(tv_funret);
#endif
DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, tv_funret); /* side effects */
}
@ -1787,7 +1787,7 @@ DUK_LOCAL void duk__handle_call_error(duk_hthread *thr,
DUK_TVAL_SET_TVAL_UPDREF(thr, tv_ret, &thr->heap->lj.value1); /* side effects */
#if defined(DUK_USE_FASTINT)
/* Explicit check for fastint downgrade. */
DUK_TVAL_CHKFAST_INPLACE(tv_ret);
DUK_TVAL_CHKFAST_INPLACE_FAST(tv_ret);
#endif
duk_set_top(ctx, idx_func + 1); /* XXX: could be eliminated with valstack adjust */

2
src-input/duk_js_compiler.c

@ -1861,7 +1861,7 @@ DUK_LOCAL duk_regconst_t duk__getconst(duk_compiler_ctx *comp_ctx) {
#if defined(DUK_USE_FASTINT)
/* Explicit check for fastint downgrade. */
DUK_TVAL_CHKFAST_INPLACE(tv1);
DUK_TVAL_CHKFAST_INPLACE_SLOW(tv1);
#endif
/* Sanity workaround for handling functions with a large number of

4
src-input/duk_js_executor.c

@ -547,7 +547,7 @@ DUK_LOCAL DUK__INLINE_PERF void duk__vm_arith_unary_op(duk_hthread *thr, duk_idx
DUK_ASSERT(DUK_DBLUNION_IS_NORMALIZED(&du));
#if defined(DUK_USE_FASTINT)
tv = DUK_GET_TVAL_POSIDX(ctx, idx_dst);
DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d);
DUK_TVAL_SET_NUMBER_CHKFAST_UPDREF(thr, tv, du.d); /* always 'fast', i.e. inlined */
return;
#endif
} else {
@ -1531,7 +1531,7 @@ DUK_LOCAL duk_small_uint_t duk__handle_return(duk_hthread *thr,
DUK_ASSERT(entry_thread != NULL);
DUK_ASSERT(thr->valstack_top - 1 >= thr->valstack_bottom);
tv1 = thr->valstack_top - 1;
DUK_TVAL_CHKFAST_INPLACE(tv1); /* fastint downgrade check for return values */
DUK_TVAL_CHKFAST_INPLACE_FAST(tv1); /* fastint downgrade check for return values */
/*
* Four possible outcomes:

6
src-input/duk_tval.c

@ -19,7 +19,7 @@
* See doc/fastint.rst for details.
*/
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x) {
DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x) {
duk_double_union du;
duk_int64_t i;
duk_small_int_t expt;
@ -62,6 +62,10 @@ DUK_INTERNAL DUK_ALWAYS_INLINE void duk_tval_set_number_chkfast(duk_tval *tv, du
return;
}
DUK_INTERNAL DUK_NOINLINE void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x) {
duk_tval_set_number_chkfast_fast(tv, x);
}
/*
* Manually optimized number-to-double conversion
*/

51
src-input/duk_tval.h

@ -176,15 +176,25 @@ typedef struct {
#define DUK_TVAL_SET_I48(tv,i) DUK__TVAL_SET_I48((tv), (i))
#define DUK_TVAL_SET_I32(tv,i) DUK__TVAL_SET_I32((tv), (i))
#define DUK_TVAL_SET_U32(tv,i) DUK__TVAL_SET_U32((tv), (i))
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) duk_tval_set_number_chkfast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) duk_tval_set_number_chkfast_fast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) duk_tval_set_number_chkfast_slow((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE(tv) do { \
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
} \
} while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
} \
} while (0)
#else /* DUK_USE_FASTINT */
@ -197,9 +207,11 @@ typedef struct {
#define DUK_TVAL_SET_I48(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i)) /* XXX: fast int-to-double */
#define DUK_TVAL_SET_I32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
#define DUK_TVAL_SET_U32(tv,i) DUK_TVAL_SET_DOUBLE((tv), (duk_double_t) (i))
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,d) DUK_TVAL_SET_DOUBLE((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE(tv) do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
#endif /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_FASTINT(tv,i) DUK_TVAL_SET_I48((tv), (i)) /* alias */
@ -395,17 +407,28 @@ typedef struct {
duk__tv->t = DUK_TAG_FASTINT; \
duk__tv->v.fi = (duk_int64_t) (val); \
} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
duk_tval_set_number_chkfast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
duk_tval_set_number_chkfast_fast((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
duk_tval_set_number_chkfast_slow((tv), (d))
#define DUK_TVAL_SET_NUMBER(tv,val) \
DUK_TVAL_SET_DOUBLE((tv), (val))
#define DUK_TVAL_CHKFAST_INPLACE(tv) do { \
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
DUK_TVAL_SET_NUMBER_CHKFAST(duk__tv, duk__d); \
DUK_TVAL_SET_NUMBER_CHKFAST_FAST(duk__tv, duk__d); \
} \
} while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { \
duk_tval *duk__tv; \
duk_double_t duk__d; \
duk__tv = (tv); \
if (DUK_TVAL_IS_DOUBLE(duk__tv)) { \
duk__d = DUK_TVAL_GET_DOUBLE(duk__tv); \
DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(duk__tv, duk__d); \
} \
} while (0)
#else /* DUK_USE_FASTINT */
@ -426,9 +449,12 @@ typedef struct {
duk__tv->t = DUK_TAG_NUMBER; \
duk__tv->v.d = duk__dblval; \
} while (0)
#define DUK_TVAL_SET_NUMBER_CHKFAST(tv,d) \
#define DUK_TVAL_SET_NUMBER_CHKFAST_FAST(tv,d) \
DUK_TVAL_SET_NUMBER((tv), (d))
#define DUK_TVAL_SET_NUMBER_CHKFAST_SLOW(tv,d) \
DUK_TVAL_SET_NUMBER((tv), (d))
#define DUK_TVAL_CHKFAST_INPLACE(tv) do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_FAST(tv) do { } while (0)
#define DUK_TVAL_CHKFAST_INPLACE_SLOW(tv) do { } while (0)
#endif /* DUK_USE_FASTINT */
#define DUK_TVAL_SET_FASTINT(tv,i) \
@ -588,7 +614,8 @@ DUK_INTERNAL_DECL duk_double_t duk_tval_get_number_unpacked_fastint(duk_tval *tv
#define DUK_FASTINT_MAX 0x7fffffffffffLL
#define DUK_FASTINT_BITS 48
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast(duk_tval *tv, duk_double_t x);
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_fast(duk_tval *tv, duk_double_t x);
DUK_INTERNAL_DECL void duk_tval_set_number_chkfast_slow(duk_tval *tv, duk_double_t x);
#endif
#endif /* DUK_TVAL_H_INCLUDED */

11
tests/api/test-put-func-num-list.c

@ -2,7 +2,7 @@
*** test_1 (duk_safe_call)
after definition, top=0
object
tweak,adjust,frobnicate,FLAG_FOO,FLAG_BAR,FLAG_QUUX,meaning
tweak,adjust,frobnicate,FLAG_FOO,FLAG_BAR,FLAG_QUUX,meaning,nonFast
1
2
4
@ -13,6 +13,8 @@ adjust, top=3
4
frobnicate, top=6
5
true
true
final top: 0
==> rc=0, result='undefined'
===*/
@ -50,6 +52,7 @@ static const duk_number_list_entry my_consts[] = {
{ "FLAG_BAR", (duk_double_t) (1 << 1) },
{ "FLAG_QUUX", (duk_double_t) (1 << 2) },
{ "meaning", (duk_double_t) 42.0 },
{ "nonFast", (duk_double_t) 42.1 },
{ NULL, 0.0 }
};
@ -85,6 +88,12 @@ static duk_ret_t test_1(duk_context *ctx, void *udata) {
"print(MyModule.frobnicate(1, 2, 3, 4, 5, 6));\n"
);
/* Fastint compatible values are fastint downgraded. */
duk_eval_string_noresult(ctx,
"print(Duktape.info(MyModule.meaning)[1] === Duktape.info(MyModule.FLAG_FOO)[1])\n" /* match: both are fastints */
"print(Duktape.info(MyModule.meaning)[1] !== Duktape.info(MyModule.nonFast)[1])\n" /* no match: nonFast is not fastint */
);
printf("final top: %ld\n", (long) duk_get_top(ctx));
return 0;
}

Loading…
Cancel
Save