diff --git a/source/quickjs.c b/source/quickjs.c index 30c528cf..017dc834 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -320,10 +320,6 @@ typedef enum { typedef enum OPCodeEnum OPCodeEnum; -/* Forward declarations for stone arena */ -struct StoneArenaPage; -struct JSText; - /* ============================================================ Buddy Allocator for Actor Memory Blocks ============================================================ */ @@ -523,12 +519,6 @@ typedef strut JSCode { uint8_t *bytecode; }; -static inline uint32_t mist_string_get (const JSText *t, int idx) { - int word_idx = idx / 2; - int shift = (1 - (idx % 2)) * 32; /* high 32 (idx%2==0) then low 32 (idx%2==1) */ - return (uint32_t)(t->packed[word_idx] >> shift); -} - /* ============================================================ Record key helpers (JSValue keys) ============================================================ */ @@ -643,7 +633,7 @@ static JS_BOOL JSText_equal_ascii (const JSText *text, JSValue imm) { int len = MIST_GetImmediateASCIILen (imm); if (len != JSText_len (text)) return FALSE; for (int i = 0; i < len; i++) { - uint32_t c = mist_string_get (text, i); + uint32_t c = string_get (text, i); if (c >= 0x80) return FALSE; if ((uint8_t)c != (uint8_t)MIST_GetImmediateASCIIChar (imm, i)) return FALSE; @@ -1044,7 +1034,7 @@ static JS_BOOL js_key_equal_str (JSValue a, const char *str) { /* Compare character by character (UTF-32 vs ASCII) */ for (size_t i = 0; i < len; i++) { - if (mist_string_get (ta, i) != (uint32_t)(unsigned char)str[i]) + if (string_get (ta, i) != (uint32_t)(unsigned char)str[i]) return FALSE; } return TRUE; @@ -1146,8 +1136,7 @@ static int rec_resize (JSContext *ctx, JSRecord *rec, uint64_t new_mask) { } /* Set own property on record, returns 0 on success, -1 on error */ -static int rec_set_own (JSContext *ctx, JSRecord *rec, JSValue k, - JSValue val) { +static int rec_set_own (JSContext *ctx, JSRecord *rec, JSValue k, JSValue val) { if (rec_key_is_empty (k) || rec_key_is_tomb (k)) { JS_FreeValue (ctx, val); return -1; @@ -1498,15 +1487,11 @@ static JSValue JS_EvalObject (JSContext *ctx, JSValue this_obj, JSValue val, int JS_DeleteProperty (JSContext *ctx, JSValue obj, JSValue prop); JSValue __attribute__ ((format (printf, 2, 3))) JS_ThrowInternalError (JSContext *ctx, const char *fmt, ...); -static __maybe_unused void JS_DumpString (JSRuntime *rt, const JSString *p); -static __maybe_unused void JS_DumpObjectHeader (JSRuntime *rt); -static __maybe_unused void JS_DumpObject (JSRuntime *rt, JSRecord *rec); -static __maybe_unused void JS_DumpGCObject (JSRuntime *rt, - JSGCObjectHeader *p); -static __maybe_unused void JS_DumpValueRT (JSRuntime *rt, const char *str, - JSValue val); -static __maybe_unused void JS_DumpValue (JSContext *ctx, const char *str, - JSValue val); +static __maybe_unused void JS_DumpString (JSText *text); +static __maybe_unused void JS_DumpObjectHeader (JSContext *ctx); +static __maybe_unused void JS_DumpObject (JSContext *ctx, JSRecord *rec); +static __maybe_unused void JS_DumpGCObject (objhdr_t *objhdr); +static __maybe_unused void JS_DumpValue (JSValue val); static void js_dump_value_write (void *opaque, const char *buf, size_t len); static JSValue js_function_apply (JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic); @@ -1568,8 +1553,6 @@ static JSValue js_cell_pop (JSContext *ctx, JSValue this_val, int argc, static JSValue js_cell_array_find (JSContext *ctx, JSValue this_val, int argc, JSValue *argv); JSValue JS_ThrowOutOfMemory (JSContext *ctx); -static int js_string_memcmp (const JSString *p1, int pos1, const JSString *p2, - int pos2, int len); static JSVarRef *get_var_ref (JSContext *ctx, JSStackFrame *sf, int var_idx, BOOL is_arg); static JSValue JS_EvalInternal (JSContext *ctx, JSValue this_obj, @@ -1578,8 +1561,8 @@ static JSValue JS_EvalInternal (JSContext *ctx, JSValue this_obj, int scope_idx); static void free_var_ref (JSRuntime *rt, JSVarRef *var_ref); -static int js_string_compare (JSContext *ctx, const JSString *p1, - const JSString *p2); +static int js_string_compare (JSContext *ctx, const JSText *p1, + const JSText *p2); static JSValue JS_ToNumber (JSContext *ctx, JSValue val); static int JS_SetPropertyValue (JSContext *ctx, JSValue this_obj, JSValue prop, JSValue val); @@ -1610,21 +1593,8 @@ static JSValue js_error_toString (JSContext *ctx, JSValue this_val, int argc, JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT; -static void js_trigger_gc (JSRuntime *rt, size_t size) { - BOOL force_gc; -#ifdef FORCE_GC_AT_MALLOC - force_gc = TRUE; -#else - force_gc = ((rt->malloc_state.malloc_size + size) > rt->malloc_gc_threshold); -#endif - if (force_gc) { -#ifdef DUMP_GC - printf ("GC: size=%" PRIu64 "\n", (uint64_t)rt->malloc_state.malloc_size); -#endif - JS_RunGC (rt); - rt->malloc_gc_threshold - = rt->malloc_state.malloc_size + (rt->malloc_state.malloc_size >> 1); - } +static void js_trigger_gc (JSContext *ctx, size_t size) { + } static size_t js_malloc_usable_size_unknown (const void *ptr) { return 0; } @@ -1744,25 +1714,25 @@ static inline void js_dbuf_init (JSContext *ctx, DynBuf *s) { static inline int is_digit (int c) { return c >= '0' && c <= '9'; } -static inline int string_get (const JSString *p, int idx) { +static inline int string_get (const JSText *p, int idx) { int word_idx = idx >> 1; int shift = (1 - (idx & 1)) * 32; - return (uint32_t)((p->u[word_idx] >> shift) & 0xFFFFFFFF); + return (uint32_t)((p->packed[word_idx] >> shift) & 0xFFFFFFFF); } -static inline void string_put (JSString *p, int idx, uint32_t c) { +static inline void string_put (JSText *p, int idx, uint32_t c) { int word_idx = idx >> 1; int shift = (1 - (idx & 1)) * 32; uint64_t mask = 0xFFFFFFFFULL << shift; p->u[word_idx] = (p->u[word_idx] & ~mask) | ((uint64_t)c << shift); } -/* Get character from any string value (immediate ASCII or JSString) */ +/* Get character from any string value (immediate ASCII or JSText) */ static inline uint32_t js_string_value_get (JSValue v, int idx) { if (MIST_IsImmediateASCII (v)) { return MIST_GetImmediateASCIIChar (v, idx); } else { - JSString *s = JS_VALUE_GET_STRING (v); + JSText *s = JS_VALUE_GET_PTR (v); return string_get (s, idx); } } @@ -1772,8 +1742,7 @@ static inline int js_string_value_len (JSValue v) { if (MIST_IsImmediateASCII (v)) { return MIST_GetImmediateASCIILen (v); } else { - JSString *s = JS_VALUE_GET_STRING (v); - return s->len; + return JSText_len(JS_VALUE_GET_PTR(v)); } } @@ -1785,8 +1754,8 @@ static JSValue js_key_from_string (JSContext *ctx, JSValue val) { return val; /* Immediates can be used directly as keys */ } if (JS_IsText (val)) { - JSString *p = JS_VALUE_GET_STRING (val); - int64_t len = p->len; + JSText *p = JS_VALUE_GET_PTR (val); + int64_t len = p->length; /* Extract UTF-32 characters and intern */ uint32_t *utf32_buf = alloca (len * sizeof (uint32_t)); for (int64_t i = 0; i < len; i++) { @@ -2027,9 +1996,9 @@ static size_t gc_object_size(void *ptr) { return sizeof(JSArray) + values_size; } case OBJ_TEXT: { - /* JSString: header + pad + hdr + length + packed chars */ + /* JSText: header + pad + hdr + length + packed chars */ size_t word_count = (cap + 1) / 2; - return sizeof(JSString) + word_count * sizeof(uint64_t); + return sizeof(JSText) + word_count * sizeof(uint64_t); } case OBJ_RECORD: { /* JSRecord + inline tab. Cap is mask, so tab size is mask+1 entries. */ @@ -2400,104 +2369,11 @@ void JS_SetRuntimeInfo (JSRuntime *rt, const char *s) { } void JS_FreeRuntime (JSRuntime *rt) { - struct list_head *el, *el1; - int i; - - JS_FreeValueRT (rt, rt->current_exception); - - JS_RunGCInternal (rt); - -#ifdef DUMP_LEAKS - /* leaking objects */ - { - BOOL header_done; - JSGCObjectHeader *p; - int count; - - /* remove the internal refcounts to display only the object - referenced externally */ - list_for_each (el, &rt->gc_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - p->mark = 0; - } - gc_decref (rt); - - header_done = FALSE; - list_for_each (el, &rt->gc_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - if (p->ref_count != 0) { - if (!header_done) { - printf ("Object leaks:\n"); - JS_DumpObjectHeader (rt); - header_done = TRUE; - } - JS_DumpGCObject (rt, p); - } - } - - count = 0; - list_for_each (el, &rt->gc_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - if (p->ref_count == 0) { count++; } - } - if (count != 0) printf ("Secondary object leaks: %d\n", count); - } -#endif - // if (!list_empty(&rt->gc_obj_list)) - // printf("Object leaks!\n"); - // assert(list_empty(&rt->gc_obj_list)); - /* free the classes */ js_free_rt (rt, rt->class_array); -#ifdef DUMP_LEAKS - if (!list_empty (&rt->string_list)) { - if (rt->rt_info) { - printf ("%s:1: string leakage:", rt->rt_info); - } else { - printf ("String leaks:\n" - " %6s %s\n", - "REFCNT", "VALUE"); - } - list_for_each_safe (el, el1, &rt->string_list) { - JSString *str = list_entry (el, JSString, link); - if (rt->rt_info) { - printf (" "); - } else { - printf (" %6u ", str->header.ref_count); - } - JS_DumpString (rt, str); - if (rt->rt_info) { - printf (":%u", str->header.ref_count); - } else { - printf ("\n"); - } - list_del (&str->link); - js_free_rt (rt, str); - } - if (rt->rt_info) printf ("\n"); - } - { - JSMallocState *s = &rt->malloc_state; - if (s->malloc_count > 1) { - if (rt->rt_info) printf ("%s:1: ", rt->rt_info); - printf ("Memory leak: %" PRIu64 " bytes lost in %" PRIu64 " block%s\n", - (uint64_t)(s->malloc_size - sizeof (JSRuntime)), - (uint64_t)(s->malloc_count - 1), &"s"[s->malloc_count == 2]); - } - } -#endif - - /* Stone text tables and arena are now per-context, freed in JS_FreeContext - */ - /* Destroy buddy allocator */ buddy_destroy(&rt->buddy); - - { - JSMallocState ms = rt->malloc_state; - rt->mf.js_free (&ms, rt); - } } JSContext *JS_NewContextRaw (JSRuntime *rt) { @@ -2736,12 +2612,12 @@ void JS_UpdateStackTop (JSRuntime *rt) { update_stack_limit (rt); } -static JSString *js_alloc_string (JSContext *ctx, int max_len); +static JSText *js_alloc_string (JSContext *ctx, int max_len); static inline int is_num (int c) { return c >= '0' && c <= '9'; } /* return TRUE if the string is a number n with 0 <= n <= 2^32-1 */ -static inline BOOL is_num_string (uint32_t *pval, const JSString *p) { +static inline BOOL is_num_string (uint32_t *pval, const JSText *p) { uint32_t n; uint64_t n64; int c, i, len; @@ -2784,7 +2660,7 @@ static __maybe_unused void JS_DumpChar (FILE *fo, int c, int sep) { } } -static __maybe_unused void JS_DumpString (JSRuntime *rt, const JSString *p) { +static __maybe_unused void JS_DumpString (JSRuntime *rt, const JSText *p) { int i, sep; if (p == NULL) { @@ -2801,8 +2677,7 @@ static __maybe_unused void JS_DumpString (JSRuntime *rt, const JSString *p) { } static inline BOOL JS_IsEmptyString (JSValue v) { - return JS_VALUE_GET_TAG (v) == JS_TAG_STRING - && JS_VALUE_GET_STRING (v)->len == 0; + return v == JS_EMPTY_TEXT; } /* JSClass support */ @@ -2883,7 +2758,7 @@ int JS_NewClass (JSRuntime *rt, JSClassID class_id, } static JSValue js_new_string8_len (JSContext *ctx, const char *buf, int len) { - JSString *str; + JSText *str; int i; /* Empty string - return immediate empty */ @@ -2908,9 +2783,8 @@ static JSValue js_new_string8 (JSContext *ctx, const char *buf) { return js_new_string8_len (ctx, buf, strlen (buf)); } -static JSValue js_new_string16_len (JSContext *ctx, const uint16_t *buf, - int len) { - JSString *str; +static JSValue js_new_string16_len (JSContext *ctx, const uint16_t *buf, int len) { + JSText *str; int i; str = js_alloc_string (ctx, len); if (!str) return JS_EXCEPTION; @@ -2919,25 +2793,21 @@ static JSValue js_new_string16_len (JSContext *ctx, const uint16_t *buf, return JS_MKPTR(str); } -static JSValue js_sub_string (JSContext *ctx, JSString *p, int start, - int end) { +static JSValue js_sub_string (JSContext *ctx, JSText *p, int start, int end) { int i; int len = end - start; if (start == 0 && end == p->len) { return JS_DupValue (ctx, JS_MKPTR(p)); } - JSString *str = js_alloc_string (ctx, len); + JSText *str = js_alloc_string (ctx, len); if (!str) return JS_EXCEPTION; for (i = 0; i < len; i++) string_put (str, i, string_get (p, start + i)); return JS_MKPTR(str); } -/* string_buffer_widen removed */ - -static no_inline int string_buffer_realloc (StringBuffer *s, int new_len, - int c) { - JSString *new_str; +static no_inline JSText *pretext_realloc (JSText *s, int new_len, int c) { + JSText *new_str; int new_size; size_t new_size_bytes, slack; @@ -2949,9 +2819,9 @@ static no_inline int string_buffer_realloc (StringBuffer *s, int new_len, } new_size = min_int (max_int (new_len, s->size * 3 / 2), JS_STRING_LEN_MAX); - /* JSString stores UTF-32 packed into uint64_t (2 chars per word). */ + /* JSText stores UTF-32 packed into uint64_t (2 chars per word). */ new_size_bytes - = sizeof (JSString) + ((new_size + 1) / 2) * sizeof (uint64_t); + = sizeof (JSText) + ((new_size + 1) / 2) * sizeof (uint64_t); new_str = js_realloc2 (s->ctx, s->str, new_size_bytes, &slack); if (!new_str) return string_buffer_set_error (s); new_size @@ -3010,7 +2880,7 @@ static int string_buffer_write32 (StringBuffer *s, const uint32_t *p, return 0; } -static int string_getc (const JSString *p, int *pidx) { +static int string_getc (const JSText *p, int *pidx) { int idx, c, c1; idx = *pidx; c = string_get (p, idx++); @@ -3025,7 +2895,7 @@ static int string_getc (const JSString *p, int *pidx) { return c; } -static int string_buffer_write8 (StringBuffer *s, const uint8_t *p, int len) { +static JSText *pretext_write8 (JSText *s, const uint8_t *p, int len) { int i; if (s->len + len > s->size) { @@ -3057,7 +2927,7 @@ static int string_buffer_puts8 (StringBuffer *s, const char *str) { return string_buffer_write8 (s, (const uint8_t *)str, strlen (str)); } -static int string_buffer_concat (StringBuffer *s, const JSString *p, +static int string_buffer_concat (StringBuffer *s, const JSText *p, uint32_t from, uint32_t to) { if (to <= from) return 0; int len = (int)(to - from); @@ -3071,7 +2941,7 @@ static int string_buffer_concat (StringBuffer *s, const JSString *p, return 0; } -static int string_buffer_concat_value (StringBuffer *s, JSValue v) { +static JSText *string_buffer_concat_value (JSText *s, JSValue v) { if (MIST_IsImmediateASCII (v)) { int len = MIST_GetImmediateASCIILen (v); char buf[8]; @@ -3080,8 +2950,8 @@ static int string_buffer_concat_value (StringBuffer *s, JSValue v) { return string_buffer_write8 (s, (const uint8_t *)buf, len); } if (JS_IsText (v)) { - JSString *p = JS_VALUE_GET_STRING (v); - return string_buffer_concat (s, p, 0, p->len); + JSText *p = JS_VALUE_GET_PTR (v); + return string_buffer_concat (s, p, 0, p->length); } JSValue v1 = JS_ToString (s->ctx, v); if (JS_IsException (v1)) return string_buffer_set_error (s); @@ -3096,7 +2966,7 @@ static int string_buffer_concat_value (StringBuffer *s, JSValue v) { return res; } - JSString *p = JS_VALUE_GET_STRING (v1); + JSText *p = JS_VALUE_GET_STRING (v1); int res = string_buffer_concat (s, p, 0, p->len); JS_FreeValue (s->ctx, v1); return res; @@ -3169,7 +3039,7 @@ static JSText *text_concat(JSContext *ctx, JSText *text, JSValue v) } static int string_buffer_concat_value_free (StringBuffer *s, JSValue v) { - JSString *p; + JSText *p; int res; if (s->error_status) { @@ -3196,7 +3066,7 @@ static JSValue text_concat_end(JSText *text) { } static JSValue string_buffer_end (StringBuffer *s) { - JSString *str; + JSText *str; str = s->str; if (s->error_status) return JS_EXCEPTION; if (s->len == 0) { @@ -3209,7 +3079,7 @@ static JSValue string_buffer_end (StringBuffer *s) { /* XXX: should add some slack to avoid unnecessary calls */ /* XXX: might need to use malloc+free to ensure smaller size */ str = js_realloc_rt (s->ctx->rt, str, - sizeof (JSString) + (s->len + 1) * sizeof (uint32_t)); + sizeof (JSText) + (s->len + 1) * sizeof (uint32_t)); if (str == NULL) str = s->str; s->str = str; } @@ -3251,7 +3121,7 @@ static JSValue JS_ConcatString3 (JSContext *ctx, const char *str1, JSValue str2, const char *str3) { StringBuffer b_s, *b = &b_s; int len1, len3; - JSString *p; + JSText *p; if (unlikely (JS_VALUE_GET_TAG (str2) != JS_TAG_STRING)) { str2 = JS_ToStringFree (ctx, str2); @@ -3276,13 +3146,13 @@ fail: } /* return (NULL, 0) if exception. */ -/* return pointer into a JSString with a live ref_count */ +/* return pointer into a JSText with a live ref_count */ /* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 * sequences */ const char *JS_ToCStringLen2 (JSContext *ctx, size_t *plen, JSValue val1, BOOL cesu8) { JSValue val; - JSString *str; + JSText *str; char *q, *ret; size_t size; int i, len; @@ -3337,8 +3207,8 @@ void JS_FreeCString (JSContext *ctx, const char *ptr) { } /* return < 0, 0 or > 0 */ -static int js_string_compare (JSContext *ctx, const JSString *p1, - const JSString *p2) { +static int js_string_compare (JSContext *ctx, const JSText *p1, + const JSText *p2) { int res, len, i; len = min_int (p1->len, p2->len); for (i = 0; i < len; i++) { @@ -3350,9 +3220,9 @@ static int js_string_compare (JSContext *ctx, const JSString *p1, return p1->len < p2->len ? -1 : 1; } -static JSValue JS_ConcatString1 (JSContext *ctx, const JSString *p1, - const JSString *p2) { - JSString *p; +static JSValue JS_ConcatString1 (JSContext *ctx, const JSText *p1, + const JSText *p2) { + JSText *p; uint32_t len; len = p1->len + p2->len; @@ -3371,10 +3241,10 @@ static JSValue JS_ConcatString1 (JSContext *ctx, const JSString *p1, return JS_MKPTR(p); } -static BOOL JS_ConcatStringInPlace (JSContext *ctx, JSString *p1, +static BOOL JS_ConcatStringInPlace (JSContext *ctx, JSText *p1, JSValue op2) { if (JS_VALUE_GET_TAG (op2) == JS_TAG_STRING) { - JSString *p2 = JS_VALUE_GET_STRING (op2); + JSText *p2 = JS_VALUE_GET_STRING (op2); size_t size1; int64_t new_len; size_t words_needed; @@ -3401,7 +3271,7 @@ static BOOL JS_ConcatStringInPlace (JSContext *ctx, JSString *p1, static JSValue JS_ConcatString2 (JSContext *ctx, JSValue op1, JSValue op2) { JSValue ret; - JSString *p1, *p2; + JSText *p1, *p2; p1 = JS_VALUE_GET_STRING (op1); if (JS_ConcatStringInPlace (ctx, p1, op2)) { JS_FreeValue (ctx, op2); @@ -3480,7 +3350,7 @@ static JSValue JS_ConcatString (JSContext *ctx, JSValue op1, JSValue op2) { } if (JS_IsNull (ret_val)) { - JSString *p = js_alloc_string (ctx, new_len); + JSText *p = js_alloc_string (ctx, new_len); if (!p) { JS_FreeValue (ctx, op1); JS_FreeValue (ctx, op2); @@ -3919,403 +3789,6 @@ static void free_zero_refcount (JSRuntime *rt) { rt->gc_phase = JS_GC_PHASE_NONE; } -/* called with the ref_count of 'v' reaches zero. */ -void __JS_FreeValueRT (JSRuntime *rt, JSValue v) { -#ifdef DUMP_FREE - { - printf ("Freeing "); - if (js_is_record (v)) { - JS_DumpObject (rt, JS_VALUE_GET_RECORD (v)); - } else { - JS_DumpValueShort (rt, v); - printf ("\n"); - } - } -#endif - - /* New tag system: JS_TAG_PTR for all pointer types */ - if (JS_IsPtr (v)) { - void *ptr = JS_VALUE_GET_PTR (v); - - /* Check objhdr_t at offset 8 to determine type. - Both strings (JSText/JSString) and GC objects have objhdr_t at offset 8. */ - objhdr_t hdr = *((objhdr_t *)((char *)ptr + 8)); - uint8_t type = objhdr_type (hdr); - - /* Handle heap strings - type is OBJ_TEXT */ - if (type == OBJ_TEXT) { - /* Check if this is a stone-allocated JSText (don't free) or - a heap-allocated JSString (do free) */ - if (objhdr_s (hdr)) { - /* Stone-allocated JSText - don't free (lives in stone arena) */ - return; - } - /* Heap-allocated JSString - free it */ - JSString *str = (JSString *)ptr; -#ifdef DUMP_LEAKS - list_del (&str->link); -#endif - js_free_rt (rt, str); - return; - } - - /* GC objects: record, array, function, function_bytecode, var_ref, etc. */ - JSGCObjectHeader *p = (JSGCObjectHeader *)ptr; - if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) { - list_del (&p->link); - list_add (&p->link, &rt->gc_zero_ref_count_list); - p->mark = 1; /* indicate that the object is about to be freed */ - if (rt->gc_phase == JS_GC_PHASE_NONE) { free_zero_refcount (rt); } - } - return; - } - - /* Non-pointer values that shouldn't reach here (except immediate strings) */ - uint32_t tag = JS_VALUE_GET_TAG (v); - if (tag == JS_TAG_STRING_IMM) { - /* Immediate strings do not need freeing */ - return; - } - - /* Unexpected value type */ - abort (); -} - -void __JS_FreeValue (JSContext *ctx, JSValue v) { - __JS_FreeValueRT (ctx->rt, v); -} - -/* garbage collection */ - -static void add_gc_object (JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type) { - h->mark = 0; - h->gc_obj_type = type; - list_add_tail (&h->link, &rt->gc_obj_list); -} - -static void remove_gc_object (JSGCObjectHeader *h) { list_del (&h->link); } - -void JS_MarkValue (JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) { - if (JS_IsPtr (val)) { - void *ptr = JS_VALUE_GET_PTR (val); - /* Check objhdr_t at offset 8 to determine type */ - objhdr_t hdr = *((objhdr_t *)((char *)ptr + 8)); - uint8_t type = objhdr_type (hdr); - /* Only mark GC objects (not OBJ_TEXT strings) */ - if (type != OBJ_TEXT) { - mark_func (rt, (JSGCObjectHeader *)ptr); - } - } -} - -static void mark_children (JSRuntime *rt, JSGCObjectHeader *gp, - JS_MarkFunc *mark_func) { - switch (gp->gc_obj_type) { - case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: - /* the template objects can be part of a cycle */ - { - JSFunctionBytecode *b = (JSFunctionBytecode *)gp; - int i; - for (i = 0; i < b->cpool_count; i++) { - JS_MarkValue (rt, b->cpool[i], mark_func); - } - if (b->realm) mark_func (rt, &b->realm->header); - } - break; - case JS_GC_OBJ_TYPE_FUNCTION: { - JSFunction *func = (JSFunction *)gp; - mark_function_children (rt, func, mark_func); - } break; - case JS_GC_OBJ_TYPE_VAR_REF: { - JSVarRef *var_ref = (JSVarRef *)gp; - if (var_ref->is_detached) { - JS_MarkValue (rt, *var_ref->pvalue, mark_func); - } - } break; - /* JS_GC_OBJ_TYPE_SHAPE removed - shapes no longer used */ - case JS_GC_OBJ_TYPE_JS_CONTEXT: { - JSContext *ctx = (JSContext *)gp; - JS_MarkContext (rt, ctx, mark_func); - } break; - case JS_GC_OBJ_TYPE_ARRAY: { - JSArray *arr = (JSArray *)gp; - uint32_t i; - for (i = 0; i < arr->len; i++) { - JS_MarkValue (rt, arr->values[i], mark_func); - } - } break; - case JS_GC_OBJ_TYPE_RECORD: { - JSRecord *rec = (JSRecord *)gp; - /* Class-specific marking */ - if (rec->class_id != JS_CLASS_OBJECT && rec->class_id < rt->class_count) { - JSClassGCMark *gc_mark = rt->class_array[rec->class_id].gc_mark; - if (gc_mark) gc_mark (rt, JS_MKPTR(rec), mark_func); - } - /* Mark hash table entries */ - uint32_t mask = (uint32_t)objhdr_cap56 (rec->mist_hdr); - uint32_t i; - for (i = 1; i <= mask; i++) { - JSValue k = rec->tab[i].key; - if (!rec_key_is_empty (k) && !rec_key_is_tomb (k)) { - JS_MarkValue (rt, k, mark_func); - JS_MarkValue (rt, rec->tab[i].val, mark_func); - } - } - if (rec->proto) { mark_func (rt, &rec->proto->header); } - } break; - default: - abort (); - } -} - -static void gc_decref_child (JSRuntime *rt, JSGCObjectHeader *p) { - assert (p->ref_count > 0); - RC_GC_DEC (p); - if (p->ref_count == 0 && p->mark == 1) { - list_del (&p->link); - list_add_tail (&p->link, &rt->tmp_obj_list); - } -} - -static inline int32_t gc_parent_class_id (JSGCObjectHeader *parent) { - if (parent && parent->gc_obj_type == JS_GC_OBJ_TYPE_RECORD) { - return ((JSRecord *)parent)->class_id; - } - return -1; -} - -static inline void JS_MarkValueEdgeEx (JSRuntime *rt, JSValue val, - JSGCObjectHeader *parent, - const char *edge, uint32_t atom, - int32_t prop_index) { - if (!JS_IsPtr (val)) { return; } - - void *ptr = JS_VALUE_GET_PTR (val); - /* Check objhdr_t at offset 8 to determine type */ - objhdr_t hdr = *((objhdr_t *)((char *)ptr + 8)); - uint8_t type = objhdr_type (hdr); - /* Only mark GC objects (not OBJ_TEXT strings) */ - if (type != OBJ_TEXT) { - JSGCObjectHeader *child = (JSGCObjectHeader *)ptr; - gc_decref_child (rt, child); - } -} - -static void JS_MarkContextDecref (JSRuntime *rt, JSContext *ctx) { - int i; - - JS_MarkValueEdge (rt, ctx->global_obj, &ctx->header, "ctx.global_obj"); - JS_MarkValueEdge (rt, ctx->global_var_obj, &ctx->header, - "ctx.global_var_obj"); - - JS_MarkValueEdge (rt, ctx->throw_type_error, &ctx->header, - "ctx.throw_type_error"); - JS_MarkValueEdge (rt, ctx->eval_obj, &ctx->header, "ctx.eval_obj"); - - JS_MarkValueEdge (rt, ctx->array_proto_values, &ctx->header, - "ctx.array_proto_values"); - for (i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { - JS_MarkValueEdge (rt, ctx->native_error_proto[i], &ctx->header, - "ctx.native_error_proto"); - } - for (i = 0; i < rt->class_count; i++) { - JS_MarkValueEdge (rt, ctx->class_proto[i], &ctx->header, - "ctx.class_proto"); - } - JS_MarkValueEdge (rt, ctx->array_ctor, &ctx->header, "ctx.array_ctor"); - JS_MarkValueEdge (rt, ctx->regexp_ctor, &ctx->header, "ctx.regexp_ctor"); -} - -static void mark_children_decref (JSRuntime *rt, JSGCObjectHeader *gp) { - switch (gp->gc_obj_type) { - case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: { - JSFunctionBytecode *b = (JSFunctionBytecode *)gp; - int i; - for (i = 0; i < b->cpool_count; i++) { - JS_MarkValueEdge (rt, b->cpool[i], gp, "bytecode.cpool"); - } - if (b->realm) { - gc_decref_child (rt, &b->realm->header); - } - } break; - case JS_GC_OBJ_TYPE_FUNCTION: { - JSFunction *func = (JSFunction *)gp; - mark_function_children_decref (rt, func); - } break; - case JS_GC_OBJ_TYPE_VAR_REF: { - JSVarRef *var_ref = (JSVarRef *)gp; - if (var_ref->is_detached) { - JS_MarkValueEdge (rt, *var_ref->pvalue, gp, "var_ref.value"); - } - } break; - /* JS_GC_OBJ_TYPE_SHAPE removed - shapes no longer used */ - case JS_GC_OBJ_TYPE_JS_CONTEXT: { - JSContext *ctx = (JSContext *)gp; - JS_MarkContextDecref (rt, ctx); - } break; - case JS_GC_OBJ_TYPE_ARRAY: { - JSArray *arr = (JSArray *)gp; - uint32_t i; - for (i = 0; i < arr->len; i++) { - JS_MarkValueEdge (rt, arr->values[i], gp, "array.elem"); - } - } break; - case JS_GC_OBJ_TYPE_RECORD: { - JSRecord *rec = (JSRecord *)gp; - /* Class-specific decref */ - if (rec->class_id != JS_CLASS_OBJECT && rec->class_id < rt->class_count) { - JSClassGCMark *gc_mark = rt->class_array[rec->class_id].gc_mark; - if (gc_mark) { - gc_mark (rt, JS_MKPTR(rec), gc_decref_child); - } - } - /* Mark hash table entries */ - uint32_t mask = (uint32_t)objhdr_cap56 (rec->mist_hdr); - uint32_t i; - for (i = 1; i <= mask; i++) { - JSValue k = rec->tab[i].key; - if (!rec_key_is_empty (k) && !rec_key_is_tomb (k)) { - JS_MarkValueEdge (rt, k, gp, "record.key"); - JS_MarkValueEdge (rt, rec->tab[i].val, gp, "record.val"); - } - } - if (rec->proto) { gc_decref_child (rt, &rec->proto->header); } - } break; - default: - abort (); - } -} - -static void gc_decref (JSRuntime *rt) { - struct list_head *el, *el1; - JSGCObjectHeader *p; - - init_list_head (&rt->tmp_obj_list); - - /* decrement the refcount of all the children of all the GC - objects and move the GC objects with zero refcount to - tmp_obj_list */ - list_for_each_safe (el, el1, &rt->gc_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - assert (p->mark == 0); - mark_children_decref (rt, p); - p->mark = 1; - if (p->ref_count == 0) { - list_del (&p->link); - list_add_tail (&p->link, &rt->tmp_obj_list); - } - } -} - -static void gc_scan_incref_child (JSRuntime *rt, JSGCObjectHeader *p) { - RC_GC_INC (p); - if (p->ref_count == 1) { - /* ref_count was 0: remove from tmp_obj_list and add at the - end of gc_obj_list */ - list_del (&p->link); - list_add_tail (&p->link, &rt->gc_obj_list); - p->mark = 0; /* reset the mark for the next GC call */ - } -} - -static void gc_scan_incref_child2 (JSRuntime *rt, JSGCObjectHeader *p) { - RC_GC_INC (p); -} - -static void gc_scan (JSRuntime *rt) { - struct list_head *el; - JSGCObjectHeader *p; - - /* keep the objects with a refcount > 0 and their children. */ - list_for_each (el, &rt->gc_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - assert (p->ref_count > 0); - p->mark = 0; /* reset the mark for the next GC call */ - mark_children (rt, p, gc_scan_incref_child); - } - - /* restore the refcount of the objects to be deleted. */ - list_for_each (el, &rt->tmp_obj_list) { - p = list_entry (el, JSGCObjectHeader, link); - mark_children (rt, p, gc_scan_incref_child2); - } -} - -static void gc_free_cycles (JSRuntime *rt) { - struct list_head *el, *el1; - JSGCObjectHeader *p; -#ifdef DUMP_GC_FREE - BOOL header_done = FALSE; -#endif - - rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES; - - for (;;) { - el = rt->tmp_obj_list.next; - if (el == &rt->tmp_obj_list) break; - p = list_entry (el, JSGCObjectHeader, link); - /* Only need to free the GC object associated with JS values - or async functions. The rest will be automatically removed - because they must be referenced by them. */ - switch (p->gc_obj_type) { - case JS_GC_OBJ_TYPE_RECORD: - case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: - case JS_GC_OBJ_TYPE_ARRAY: - case JS_GC_OBJ_TYPE_FUNCTION: -#ifdef DUMP_GC_FREE - if (!header_done) { - printf ("Freeing cycles:\n"); - JS_DumpObjectHeader (rt); - header_done = TRUE; - } - JS_DumpGCObject (rt, p); -#endif - free_gc_object (rt, p); - break; - default: - list_del (&p->link); - list_add_tail (&p->link, &rt->gc_zero_ref_count_list); - break; - } - } - rt->gc_phase = JS_GC_PHASE_NONE; - - list_for_each_safe (el, el1, &rt->gc_zero_ref_count_list) { - p = list_entry (el, JSGCObjectHeader, link); - assert (p->gc_obj_type == JS_GC_OBJ_TYPE_RECORD - || p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE - || p->gc_obj_type == JS_GC_OBJ_TYPE_ARRAY - || p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION); - js_free_rt (rt, p); - } - - init_list_head (&rt->gc_zero_ref_count_list); -} - -static void JS_RunGCInternal (JSRuntime *rt) { - /* decrement the reference of the children of each object. mark = - 1 after this pass. */ - gc_decref (rt); - - /* keep the GC objects with a non zero refcount and their childs */ - gc_scan (rt); - - /* free the GC objects in a cycle */ - gc_free_cycles (rt); -} - -void JS_RunGC (JSRuntime *rt) { JS_RunGCInternal (rt); } - -/* Return false if not an object or if the object has already been - freed (zombie objects are visible in finalizers when freeing - cycles). */ -BOOL JS_IsLiveObject (JSRuntime *rt, JSValue obj) { - JSRecord *p; - if (!JS_IsObject (obj)) return FALSE; - p = JS_VALUE_GET_OBJ (obj); - return !p->free_mark; -} - /* Compute memory used by various object types */ /* XXX: poor man's approach to handling multiply referenced objects */ typedef struct JSMemoryUsage_helper { @@ -4331,7 +3804,7 @@ typedef struct JSMemoryUsage_helper { static void compute_value_size (JSValue val, JSMemoryUsage_helper *hp); -static void compute_jsstring_size (JSString *str, JSMemoryUsage_helper *hp) { +static void compute_JSText_size (JSText *str, JSMemoryUsage_helper *hp) { /* UTF-32 packs 2 chars per 64-bit word */ double s_ref_count = str->header.ref_count; size_t data_words = (str->len + 1) / 2; @@ -4382,7 +3855,7 @@ static void compute_bytecode_size (JSFunctionBytecode *b, static void compute_value_size (JSValue val, JSMemoryUsage_helper *hp) { switch (JS_VALUE_GET_TAG (val)) { case JS_TAG_STRING: - compute_jsstring_size (JS_VALUE_GET_STRING (val), hp); + compute_JSText_size (JS_VALUE_GET_STRING (val), hp); break; } } @@ -4427,8 +3900,8 @@ void JS_ComputeMemoryUsage (JSRuntime *rt, JSMemoryUsage *s) { /* Class-specific stats */ switch (rec->class_id) { case JS_CLASS_REGEXP: /* u.regexp */ - compute_jsstring_size (rec->u.regexp.pattern, hp); - compute_jsstring_size (rec->u.regexp.bytecode, hp); + compute_JSText_size (rec->u.regexp.pattern, hp); + compute_JSText_size (rec->u.regexp.bytecode, hp); break; default: /* XXX: class definition should have an opaque block size */ @@ -4472,7 +3945,7 @@ void JS_DumpMemoryUsage (FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) { { "JSRuntime", sizeof (JSRuntime) }, { "JSContext", sizeof (JSContext) }, { "JSRecord", sizeof (JSRecord) }, - { "JSString", sizeof (JSString) }, + { "JSText", sizeof (JSText) }, { "JSFunctionBytecode", sizeof (JSFunctionBytecode) }, }; int i, usage_size_ok = 0; @@ -5153,7 +4626,7 @@ static uint32_t js_string_get_length (JSValue val) { /* Check objhdr_t at offset 8 for type */ objhdr_t hdr = *((objhdr_t *)((char *)ptr + 8)); if (objhdr_type (hdr) == OBJ_TEXT) { - /* String (JSString or JSText) */ + /* String (JSText or JSText) */ return (uint32_t)objhdr_cap56 (hdr); } return 0; @@ -5530,7 +5003,7 @@ static BOOL js_object_has_name (JSContext *ctx, JSValue obj) { if (slot <= 0) return FALSE; JSValue val = rec->tab[slot].val; if (JS_VALUE_GET_TAG (val) != JS_TAG_STRING) return TRUE; - JSString *p = JS_VALUE_GET_STRING (val); + JSText *p = JS_VALUE_GET_STRING (val); return (p->len != 0); } @@ -5837,7 +5310,7 @@ static int JS_ToBoolFree (JSContext *ctx, JSValue val) { /* Check objhdr_t at offset 8 for type */ objhdr_t hdr = *((objhdr_t *)((char *)ptr + 8)); if (objhdr_type (hdr) == OBJ_TEXT) { - /* String (JSString or JSText) - truthy if non-empty */ + /* String (JSText or JSText) - truthy if non-empty */ BOOL ret = objhdr_cap56 (hdr) != 0; JS_FreeValue (ctx, val); return ret; @@ -6552,7 +6025,7 @@ static JSValue JS_ToStringCheckObject (JSContext *ctx, JSValue val) { static JSValue JS_ToQuotedString (JSContext *ctx, JSValue val1) { JSValue val; - JSString *p; + JSText *p; int i; uint32_t c; StringBuffer b_s, *b = &b_s; @@ -6666,7 +6139,7 @@ static void js_dump_char (JSPrintValueState *s, int c, int sep) { static void js_print_string_rec (JSPrintValueState *s, JSValue val, int sep, uint32_t pos) { if (JS_VALUE_GET_TAG (val) == JS_TAG_STRING) { - JSString *p = JS_VALUE_GET_STRING (val); + JSText *p = JS_VALUE_GET_STRING (val); uint32_t i, len; if (pos < s->options.max_string_length) { len = min_uint32 (p->len, s->options.max_string_length - pos); @@ -6691,7 +6164,7 @@ static void js_print_string_rec (JSPrintValueState *s, JSValue val, int sep, static void js_print_string (JSPrintValueState *s, JSValue val) { int sep; if (s->options.raw_dump && JS_VALUE_GET_TAG (val) == JS_TAG_STRING) { - JSString *p = JS_VALUE_GET_STRING (val); + JSText *p = JS_VALUE_GET_STRING (val); js_printf (s, "%d", p->header.ref_count); sep = (p->header.ref_count == 1) ? '\"' : '\''; } else { @@ -6722,7 +6195,7 @@ static void js_print_raw_string (JSPrintValueState *s, JSValue val) { js_print_raw_string2 (s, val, FALSE); } -static BOOL is_ascii_ident (const JSString *p) { +static BOOL is_ascii_ident (const JSText *p) { int i, c; if (p->len == 0) return FALSE; @@ -6839,7 +6312,7 @@ static void js_print_value (JSPrintValueState *s, JSValue val) { uint8_t mist_type = objhdr_type (hdr); if (mist_type == OBJ_TEXT) { - /* String (JSString or JSText) */ + /* String (JSText or JSText) */ js_print_string (s, val); return; } @@ -7011,13 +6484,6 @@ static __maybe_unused void JS_DumpValue (JSContext *ctx, const char *str, printf ("\n"); } -static __maybe_unused void JS_DumpValueRT (JSRuntime *rt, const char *str, - JSValue val) { - printf ("%s=", str); - JS_PrintValueRT (rt, js_dump_value_write, stdout, val, NULL); - printf ("\n"); -} - static __maybe_unused void JS_DumpObjectHeader (JSRuntime *rt) { printf ("%14s %4s %4s %14s %s\n", "ADDRESS", "REFS", "SHRF", "PROTO", "CONTENT"); @@ -12495,7 +11961,7 @@ static __exception int js_parse_template (JSParseState *s, int call, return -1; } } else { - JSString *str; + JSText *str; /* re-parse the string with escape sequences and throw a syntax error if it contains invalid sequences */ @@ -19412,7 +18878,7 @@ static int bc_put_key (BCWriterState *s, JSValue key) { return 0; } - JSString *p = JS_VALUE_GET_STRING (key); + JSText *p = JS_VALUE_GET_STRING (key); /* Write as UTF-8 */ uint32_t len = p->len; /* Calculate UTF-8 size */ @@ -19535,7 +19001,7 @@ fail: return -1; } -static void JS_WriteString (BCWriterState *s, JSString *p) { +static void JS_WriteString (BCWriterState *s, JSText *p) { int i; /* UTF-32: write length, then each character as 32-bit value */ bc_put_leb128 (s, (uint32_t)p->len); @@ -19685,7 +19151,7 @@ static int JS_WriteObjectRec (BCWriterState *s, JSValue obj) { bc_put_u64 (s, u.u64); } break; case JS_TAG_STRING: { - JSString *p = JS_VALUE_GET_STRING (obj); + JSText *p = JS_VALUE_GET_STRING (obj); bc_put_u8 (s, BC_TAG_STRING); JS_WriteString (s, p); } break; @@ -19696,7 +19162,7 @@ static int JS_WriteObjectRec (BCWriterState *s, JSValue obj) { buf[i] = MIST_GetImmediateASCIIChar (obj, i); JSValue tmp = js_new_string8_len (s->ctx, buf, len); if (JS_IsException (tmp)) goto fail; - JSString *p = JS_VALUE_GET_STRING (tmp); + JSText *p = JS_VALUE_GET_STRING (tmp); JS_WriteString (s, p); JS_FreeValue (s->ctx, tmp); } break; @@ -19989,10 +19455,10 @@ static int bc_get_key (BCReaderState *s, JSValue *pkey) { return JS_IsNull (*pkey) ? -1 : 0; } -static JSString *JS_ReadString (BCReaderState *s) { +static JSText *JS_ReadString (BCReaderState *s) { uint32_t len; size_t size; - JSString *p; + JSText *p; uint32_t i; if (bc_get_leb128 (s, &len)) return NULL; @@ -20273,7 +19739,7 @@ static JSValue JS_ReadObjectTag (BCReaderState *s) { if (bc_get_key (s, &key)) goto fail; #ifdef DUMP_READ_OBJECT bc_read_trace (s, "propname: "); - JS_DumpValue (s->ctx->rt, key); + JS_DumpValue (key); printf ("\n"); #endif val = JS_ReadObjectRec (s); @@ -20382,7 +19848,7 @@ static JSValue JS_ReadObjectRec (BCReaderState *s) { obj = __JS_NewFloat64 (ctx, u.d); } break; case BC_TAG_STRING: { - JSString *p; + JSText *p; p = JS_ReadString (s); if (!p) return JS_EXCEPTION; obj = JS_MKPTR(p); @@ -20613,7 +20079,7 @@ static __exception int js_get_length32 (JSContext *ctx, uint32_t *pres, } if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_IMM) { - JSString *p = JS_VALUE_GET_STRING (obj); + JSText *p = JS_VALUE_GET_STRING (obj); *pres = p->len; return 0; } @@ -20820,7 +20286,7 @@ static JSValue js_array_includes (JSContext *ctx, JSValue this_val, int argc, return JS_NewBool (ctx, TRUE); } -static int string_cmp (JSString *p1, JSString *p2, int x1, int x2, int len) { +static int string_cmp (JSText *p1, JSText *p2, int x1, int x2, int len) { int i, c1, c2; for (i = 0; i < len; i++) { if ((c1 = string_get (p1, x1 + i)) != (c2 = string_get (p2, x2 + i))) @@ -21117,10 +20583,10 @@ void *lre_realloc (void *opaque, void *ptr, size_t size) { return js_realloc_rt (ctx->rt, ptr, size); } -/* Convert UTF-32 JSString to UTF-16 buffer for regex engine. +/* Convert UTF-32 JSText to UTF-16 buffer for regex engine. Returns allocated uint16_t buffer that must be freed by caller. Sets *out_len to number of uint16 code units. */ -static uint16_t *js_string_to_utf16 (JSContext *ctx, JSString *str, +static uint16_t *js_string_to_utf16 (JSContext *ctx, JSText *str, int *out_len) { int len = str->len; /* Worst case: each UTF-32 char becomes 2 UTF-16 surrogates */ @@ -21146,7 +20612,7 @@ static uint16_t *js_string_to_utf16 (JSContext *ctx, JSString *str, static JSValue js_regexp_exec (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { JSRegExp *re = js_get_regexp (ctx, this_val, TRUE); - JSString *str; + JSText *str; JSValue ret, str_val, res, val, groups, captures_arr, match0; uint8_t *re_bytecode; uint8_t **capture, *str_buf; @@ -21333,7 +20799,7 @@ fail: static JSValue JS_RegExpDelete (JSContext *ctx, JSValue this_val, JSValue arg) { JSRegExp *re = js_get_regexp (ctx, this_val, TRUE); - JSString *str; + JSText *str; JSValue str_val, val; uint8_t *re_bytecode; int ret; @@ -21997,7 +21463,7 @@ JSValue JS_JSONStringify (JSContext *ctx, JSValue obj, JSValue replacer, if (JS_ToInt32Clamp (ctx, &n, space, 0, 10, 0)) goto exception; jsc->gap = js_new_string8_len (ctx, " ", n); } else if (JS_IsText (space)) { - JSString *p = JS_VALUE_GET_STRING (space); + JSText *p = JS_VALUE_GET_STRING (space); jsc->gap = js_sub_string (ctx, p, 0, min_int (p->len, 10)); } else { jsc->gap = JS_DupValue (ctx, jsc->empty); @@ -22755,7 +22221,7 @@ static JSValue js_cell_character (JSContext *ctx, JSValue this_val, int argc, /* Handle string - return first character */ if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_IMM) { - JSString *p = JS_VALUE_GET_STRING (arg); + JSText *p = JS_VALUE_GET_STRING (arg); if (p->len == 0) return JS_NewString (ctx, ""); /* UTF-32: each element is a full code point, no surrogate handling needed @@ -22832,7 +22298,7 @@ static JSValue js_cell_text (JSContext *ctx, JSValue this_val, int argc, if (argc == 1) return str; - JSString *p = JS_VALUE_GET_STRING (str); + JSText *p = JS_VALUE_GET_STRING (str); int len = p->len; if (argc >= 2) { @@ -23089,7 +22555,7 @@ static JSValue js_cell_text_lower (JSContext *ctx, JSValue this_val, int argc, if (argc < 1) return JS_NULL; if (!JS_VALUE_IS_TEXT (argv[0])) return JS_NULL; - JSString *p = JS_VALUE_GET_STRING (argv[0]); + JSText *p = JS_VALUE_GET_STRING (argv[0]); StringBuffer b_s, *b = &b_s; string_buffer_init (ctx, b, p->len); @@ -23111,7 +22577,7 @@ static JSValue js_cell_text_upper (JSContext *ctx, JSValue this_val, int argc, if (argc < 1) return JS_NULL; if (!JS_VALUE_IS_TEXT (argv[0])) return JS_NULL; - JSString *p = JS_VALUE_GET_STRING (argv[0]); + JSText *p = JS_VALUE_GET_STRING (argv[0]); StringBuffer b_s, *b = &b_s; string_buffer_init (ctx, b, p->len); @@ -23137,7 +22603,7 @@ static JSValue js_cell_text_trim (JSContext *ctx, JSValue this_val, int argc, JSValue str = JS_ToString (ctx, argv[0]); if (JS_IsException (str)) return str; - JSString *p = JS_VALUE_GET_STRING (str); + JSText *p = JS_VALUE_GET_STRING (str); int start = 0; int end = p->len; @@ -23198,7 +22664,7 @@ static JSValue js_cell_text_codepoint (JSContext *ctx, JSValue this_val, JSValue str = JS_ToString (ctx, argv[0]); if (JS_IsException (str)) return str; - JSString *p = JS_VALUE_GET_STRING (str); + JSText *p = JS_VALUE_GET_STRING (str); if (p->len == 0) { /* str removed - arg not owned */ return JS_NULL; @@ -23307,7 +22773,7 @@ static JSValue js_cell_text_replace (JSContext *ctx, JSValue this_val, if (!JS_VALUE_IS_TEXT (argv[0])) return JS_ThrowInternalError (ctx, "Replace must have text in arg0."); - JSString *sp = JS_VALUE_GET_STRING (argv[0]); + JSText *sp = JS_VALUE_GET_STRING (argv[0]); int len = (int)sp->len; int32_t limit = -1; @@ -23324,7 +22790,7 @@ static JSValue js_cell_text_replace (JSContext *ctx, JSValue this_val, return JS_ThrowInternalError ( ctx, "Second arg of replace must be pattern or text."); - JSString *tp = JS_VALUE_GET_STRING (argv[1]); + JSText *tp = JS_VALUE_GET_STRING (argv[1]); int t_len = (int)tp->len; if (t_len == 0) { @@ -23550,7 +23016,7 @@ static JSValue js_cell_text_search (JSContext *ctx, JSValue this_val, int argc, JSValue str = JS_ToString (ctx, argv[0]); if (JS_IsException (str)) return str; - JSString *p = JS_VALUE_GET_STRING (str); + JSText *p = JS_VALUE_GET_STRING (str); int len = (int)p->len; int from = 0; @@ -23574,7 +23040,7 @@ static JSValue js_cell_text_search (JSContext *ctx, JSValue this_val, int argc, return target; } - JSString *t = JS_VALUE_GET_STRING (target); + JSText *t = JS_VALUE_GET_STRING (target); int t_len = (int)t->len; int result = -1; @@ -23653,12 +23119,12 @@ fail_rx_search: /* str removed - arg not owned */ return JS_EXCEPTION; } -static inline uint32_t js_str_get (JSString *s, int idx) { +static inline uint32_t js_str_get (JSText *s, int idx) { return string_get (s, idx); } -static int js_str_find_range (JSString *hay, int from, int to, - JSString *needle) { +static int js_str_find_range (JSText *hay, int from, int to, + JSText *needle) { int nlen = (int)needle->len; int hlen = (int)hay->len; @@ -23696,7 +23162,7 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, JSValue str = JS_ToString (ctx, argv[0]); if (JS_IsException (str)) return JS_EXCEPTION; - JSString *p = JS_VALUE_GET_STRING (str); + JSText *p = JS_VALUE_GET_STRING (str); int len = (int)p->len; int from = 0; @@ -23812,7 +23278,7 @@ static JSValue js_cell_text_extract (JSContext *ctx, JSValue this_val, JSValue needle_val = JS_ToString (ctx, argv[1]); if (JS_IsException (needle_val)) return JS_EXCEPTION; - JSString *needle = JS_VALUE_GET_STRING (needle_val); + JSText *needle = JS_VALUE_GET_STRING (needle_val); int needle_len = (int)needle->len; int pos = js_str_find_range (p, from, to, needle); @@ -24062,7 +23528,7 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc, /* array(text, separator) - split by separator */ /* array(text, length) - dice into chunks */ if (JS_VALUE_IS_TEXT (arg)) { - JSString *p = JS_VALUE_GET_STRING (arg); + JSText *p = JS_VALUE_GET_STRING (arg); int len = p->len; if (argc < 2 || JS_IsNull (argv[1])) { @@ -25949,7 +25415,7 @@ static JSValue js_cell_length (JSContext *ctx, JSValue this_val, int argc, /* Strings return codepoint count */ if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_IMM) { - JSString *p = JS_VALUE_GET_STRING (val); + JSText *p = JS_VALUE_GET_STRING (val); return JS_NewInt32 (ctx, p->len); }