Browse Source

Add external strings support

pull/92/head
Sami Vaarala 10 years ago
parent
commit
ab58bb4c2b
  1. 15
      src/duk_features.h.in
  2. 2
      src/duk_forwdecl.h
  3. 1
      src/duk_heap_alloc.c
  4. 57
      src/duk_heap_stringtable.c
  5. 29
      src/duk_hstring.h

15
src/duk_features.h.in

@ -2512,6 +2512,21 @@ typedef FILE duk_file;
#define DUK_USE_USER_INITJS (DUK_OPT_USER_INITJS)
#endif
/*
* External string data support
*
* Allow duk_hstrings to store data also behind an external pointer (see
* duk_hstring_external). This increases code size slightly but is useful
* in low memory environments where memory is more limited than flash.
*/
#undef DUK_USE_HSTRING_EXTDATA
#undef DUK_USE_EXT_STR_CHECK
#if defined(DUK_OPT_EXT_STR_CHECK)
#define DUK_USE_HSTRING_EXTDATA
#define DUK_USE_EXT_STR_CHECK(ptr,len) DUK_OPT_EXT_STR_CHECK((ptr), (len))
#endif
/*
* Lightweight functions
*/

2
src/duk_forwdecl.h

@ -15,6 +15,7 @@ struct duk_jmpbuf;
struct duk_heaphdr;
struct duk_heaphdr_string;
struct duk_hstring;
struct duk_hstring_external;
struct duk_hobject;
struct duk_hcompiledfunction;
struct duk_hnativefunction;
@ -59,6 +60,7 @@ typedef struct duk_jmpbuf duk_jmpbuf;
typedef struct duk_heaphdr duk_heaphdr;
typedef struct duk_heaphdr_string duk_heaphdr_string;
typedef struct duk_hstring duk_hstring;
typedef struct duk_hstring_external duk_hstring_external;
typedef struct duk_hobject duk_hobject;
typedef struct duk_hcompiledfunction duk_hcompiledfunction;
typedef struct duk_hnativefunction duk_hnativefunction;

1
src/duk_heap_alloc.c

@ -516,6 +516,7 @@ DUK_LOCAL void duk__dump_type_sizes(void) {
DUK__DUMPSZ(duk_heaphdr);
DUK__DUMPSZ(duk_heaphdr_string);
DUK__DUMPSZ(duk_hstring);
DUK__DUMPSZ(duk_hstring_external);
DUK__DUMPSZ(duk_hobject);
DUK__DUMPSZ(duk_hcompiledfunction);
DUK__DUMPSZ(duk_hnativefunction);

57
src/duk_heap_stringtable.c

@ -21,7 +21,8 @@ DUK_LOCAL
duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
duk_uint8_t *str,
duk_uint32_t blen,
duk_uint32_t strhash) {
duk_uint32_t strhash,
const duk_uint8_t *extdata) {
duk_hstring *res = NULL;
duk_uint8_t *data;
duk_size_t alloc_size;
@ -36,19 +37,36 @@ duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
}
#endif
/* NUL terminate for convenient C access */
alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
if (!res) {
goto alloc_error;
}
if (extdata) {
alloc_size = (duk_size_t) sizeof(duk_hstring_external);
res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
if (!res) {
goto alloc_error;
}
DUK_MEMZERO(res, sizeof(duk_hstring_external));
#ifdef DUK_USE_EXPLICIT_NULL_INIT
DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA);
DUK_MEMZERO(res, sizeof(duk_hstring));
((duk_hstring_external *) res)->extdata = extdata;
} else {
/* NUL terminate for convenient C access */
alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
if (!res) {
goto alloc_error;
}
DUK_MEMZERO(res, sizeof(duk_hstring));
#ifdef DUK_USE_EXPLICIT_NULL_INIT
DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr);
#endif
DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0);
data = (duk_uint8_t *) (res + 1);
DUK_MEMCPY(data, str, blen);
data[blen] = (duk_uint8_t) 0;
}
if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
DUK_HSTRING_SET_ARRIDX(res);
@ -71,15 +89,12 @@ duk_hstring *duk__alloc_init_hstring(duk_heap *heap,
DUK_ASSERT(clen <= blen);
DUK_HSTRING_SET_CHARLEN(res, clen);
data = (duk_uint8_t *) (res + 1);
DUK_MEMCPY(data, str, blen);
data[blen] = (duk_uint8_t) 0;
DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld",
DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
(unsigned long) DUK_HSTRING_GET_HASH(res),
(long) DUK_HSTRING_GET_BYTELEN(res),
(long) DUK_HSTRING_GET_CHARLEN(res),
(long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0));
(long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0,
(long) DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0));
return res;
@ -451,6 +466,7 @@ DUK_LOCAL duk_bool_t duk__recheck_strtab_size(duk_heap *heap, duk_uint32_t new_u
DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) {
duk_hstring *res;
const duk_uint8_t *extdata;
if (duk__recheck_strtab_size(heap, heap->st_used + 1)) {
return NULL;
@ -473,7 +489,12 @@ DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint
}
#endif
res = duk__alloc_init_hstring(heap, str, blen, strhash);
#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXT_STR_CHECK)
extdata = (const duk_uint8_t *) DUK_USE_EXT_STR_CHECK((void *) str, (duk_size_t) blen);
#else
extdata = (const duk_uint8_t *) NULL;
#endif
res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
if (!res) {
return NULL;
}

29
src/duk_hstring.h

@ -43,24 +43,28 @@
#define DUK_HSTRING_FLAG_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(2) /* string is a reserved word (non-strict) */
#define DUK_HSTRING_FLAG_STRICT_RESERVED_WORD DUK_HEAPHDR_USER_FLAG(3) /* string is a reserved word (strict) */
#define DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS DUK_HEAPHDR_USER_FLAG(4) /* string is 'eval' or 'arguments' */
#define DUK_HSTRING_FLAG_EXTDATA DUK_HEAPHDR_USER_FLAG(5) /* string data is external (duk_hstring_external) */
#define DUK_HSTRING_HAS_ARRIDX(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_HAS_INTERNAL(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
#define DUK_HSTRING_HAS_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_HAS_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_HAS_EXTDATA(x) DUK_HEAPHDR_CHECK_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_SET_ARRIDX(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_SET_INTERNAL(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
#define DUK_HSTRING_SET_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_SET_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_SET_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_SET_EXTDATA(x) DUK_HEAPHDR_SET_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_CLEAR_ARRIDX(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_ARRIDX)
#define DUK_HSTRING_CLEAR_INTERNAL(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_INTERNAL)
#define DUK_HSTRING_CLEAR_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_RESERVED_WORD)
#define DUK_HSTRING_CLEAR_STRICT_RESERVED_WORD(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_STRICT_RESERVED_WORD)
#define DUK_HSTRING_CLEAR_EVAL_OR_ARGUMENTS(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EVAL_OR_ARGUMENTS)
#define DUK_HSTRING_CLEAR_EXTDATA(x) DUK_HEAPHDR_CLEAR_FLAG_BITS(&(x)->hdr, DUK_HSTRING_FLAG_EXTDATA)
#define DUK_HSTRING_IS_ASCII(x) (DUK_HSTRING_GET_BYTELEN((x)) == DUK_HSTRING_GET_CHARLEN((x)))
#define DUK_HSTRING_IS_EMPTY(x) (DUK_HSTRING_GET_BYTELEN((x)) == 0)
@ -97,8 +101,16 @@
} while (0)
#endif
#define DUK_HSTRING_GET_DATA(x) ((duk_uint8_t *) ((x) + 1))
#define DUK_HSTRING_GET_DATA_END(x) (((duk_uint8_t *) ((x) + 1)) + ((x)->blen))
#if defined(DUK_USE_HSTRING_EXTDATA)
#define DUK_HSTRING_GET_DATA(x) \
(DUK_HSTRING_HAS_EXTDATA((x)) ? ((duk_hstring_external *) (x))->extdata : ((duk_uint8_t *) ((x) + 1)))
#else
#define DUK_HSTRING_GET_DATA(x) \
((duk_uint8_t *) ((x) + 1))
#endif
#define DUK_HSTRING_GET_DATA_END(x) \
(DUK_HSTRING_GET_DATA((x)) + (x)->blen)
/* marker value; in E5 2^32-1 is not a valid array index (2^32-2 is highest valid) */
#define DUK_HSTRING_NO_ARRAY_INDEX (0xffffffffUL)
@ -158,6 +170,19 @@ struct duk_hstring {
*/
};
/* The external string struct is defined even when the feature is inactive. */
struct duk_hstring_external {
duk_hstring str;
/*
* For an external string, the NUL-terminated string data is stored
* externally. The user must guarantee that data behind this pointer
* doesn't change while it's used.
*/
const duk_uint8_t *extdata;
};
/*
* Prototypes
*/

Loading…
Cancel
Save