diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2022-11-01 13:34:29 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2022-11-07 16:25:09 +0100 |
commit | c067e1299c83e7df24a89cbea36679aefad43bb0 (patch) | |
tree | e35fe7626abfa1b5cf60e0fcf8fd632b8b553bb7 | |
parent | 0e611cdc0c81a90dabfcb2ab96992acca95b886d (diff) |
Avoid using the string interning table.
Make a copy of the property name in the same allocation as the property slot.
Make a copy of the internal string value of String objects.
-rw-r--r-- | jsgc.c | 4 | ||||
-rw-r--r-- | jsobject.c | 4 | ||||
-rw-r--r-- | jsproperty.c | 58 | ||||
-rw-r--r-- | jsrun.c | 2 | ||||
-rw-r--r-- | jsstring.c | 7 | ||||
-rw-r--r-- | jsvalue.c | 8 | ||||
-rw-r--r-- | jsvalue.h | 9 |
7 files changed, 52 insertions, 40 deletions
@@ -42,6 +42,10 @@ static void jsG_freeobject(js_State *J, js_Object *obj) js_free(J, obj->u.r.source); js_regfreex(J->alloc, J->actx, obj->u.r.prog); } + if (obj->type == JS_CSTRING) { + if (obj->u.s.string != obj->u.s.shrstr) + js_free(J, obj->u.s.string); + } if (obj->type == JS_CARRAY && obj->u.a.simple) js_free(J, obj->u.a.array); if (obj->type == JS_CITERATOR) @@ -160,7 +160,7 @@ static int O_getOwnPropertyNames_walk(js_State *J, js_Property *ref, int i) { if (ref->left->level) i = O_getOwnPropertyNames_walk(J, ref->left, i); - js_pushliteral(J, ref->name); + js_pushstring(J, ref->name); js_setindex(J, -2, i++); if (ref->right->level) i = O_getOwnPropertyNames_walk(J, ref->right, i); @@ -352,7 +352,7 @@ static int O_keys_walk(js_State *J, js_Property *ref, int i) if (ref->left->level) i = O_keys_walk(J, ref->left, i); if (!(ref->atts & JS_DONTENUM)) { - js_pushliteral(J, ref->name); + js_pushstring(J, ref->name); js_setindex(J, -2, i++); } if (ref->right->level) diff --git a/jsproperty.c b/jsproperty.c index f2e23b7..5e136fb 100644 --- a/jsproperty.c +++ b/jsproperty.c @@ -21,17 +21,16 @@ */ static js_Property sentinel = { - "", &sentinel, &sentinel, 0, 0, { {0}, {0}, JS_TUNDEFINED }, - NULL, NULL + NULL, NULL, "" }; static js_Property *newproperty(js_State *J, js_Object *obj, const char *name) { - js_Property *node = js_malloc(J, sizeof *node); - node->name = js_intern(J, name); + int n = strlen(name) + 1; + js_Property *node = js_malloc(J, offsetof(js_Property, name) + n); node->left = node->right = &sentinel; node->level = 1; node->atts = 0; @@ -39,6 +38,7 @@ static js_Property *newproperty(js_State *J, js_Object *obj, const char *name) node->value.u.number = 0; node->getter = NULL; node->setter = NULL; + memcpy(node->name, name, n); ++obj->count; ++J->gccounter; return node; @@ -104,33 +104,31 @@ static void freeproperty(js_State *J, js_Object *obj, js_Property *node) --obj->count; } -static js_Property *delete(js_State *J, js_Object *obj, js_Property *node, const char *name) +static js_Property *unlink(js_State *J, js_Object *obj, js_Property *node, const char *name, js_Property **garbage) { js_Property *temp, *succ; if (node != &sentinel) { int c = strcmp(name, node->name); if (c < 0) { - node->left = delete(J, obj, node->left, name); + node->left = unlink(J, obj, node->left, name, garbage); } else if (c > 0) { - node->right = delete(J, obj, node->right, name); + node->right = unlink(J, obj, node->right, name, garbage); } else { if (node->left == &sentinel) { - temp = node; + *garbage = node; node = node->right; - freeproperty(J, obj, temp); } else if (node->right == &sentinel) { - temp = node; + *garbage = node; node = node->left; - freeproperty(J, obj, temp); } else { + *garbage = node; succ = node->right; while (succ->left != &sentinel) succ = succ->left; - node->name = succ->name; - node->atts = succ->atts; - node->value = succ->value; - node->right = delete(J, obj, node->right, succ->name); + succ->right = unlink(J, obj, node->right, succ->name, &temp); + succ->left = node->left; + node = succ; } } @@ -149,6 +147,15 @@ static js_Property *delete(js_State *J, js_Object *obj, js_Property *node, const return node; } +static js_Property *delete(js_State *J, js_Object *obj, js_Property *tree, const char *name) +{ + js_Property *garbage = NULL; + tree = unlink(J, obj, tree, name, &garbage); + if (garbage != NULL) + freeproperty(J, obj, garbage); + return tree; +} + js_Object *jsV_newobject(js_State *J, enum js_Class type, js_Object *prototype) { js_Object *obj = js_malloc(J, sizeof *obj); @@ -229,9 +236,10 @@ void jsV_delproperty(js_State *J, js_Object *obj, const char *name) /* Flatten hierarchy of enumerable properties into an iterator object */ static js_Iterator *itnewnode(js_State *J, const char *name, js_Iterator *next) { - js_Iterator *node = js_malloc(J, sizeof(js_Iterator)); - node->name = name; + int n = strlen(name) + 1; + js_Iterator *node = js_malloc(J, offsetof(js_Iterator, name) + n); node->next = next; + memcpy(node->name, name, n); return node; } @@ -272,6 +280,7 @@ js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own) } else { io->u.iter.head = itflatten(J, obj); } + io->u.iter.current = io->u.iter.head; if (obj->type == JS_CSTRING) io->u.iter.n = obj->u.s.length; @@ -284,7 +293,6 @@ js_Object *jsV_newiterator(js_State *J, js_Object *obj, int own) const char *jsV_nextiterator(js_State *J, js_Object *io) { - int k; if (io->type != JS_CITERATOR) js_typeerror(J, "not an iterator"); if (io->u.iter.i < io->u.iter.n) { @@ -292,19 +300,11 @@ const char *jsV_nextiterator(js_State *J, js_Object *io) io->u.iter.i++; return J->scratch; } - while (io->u.iter.head) { - js_Iterator *next = io->u.iter.head->next; - const char *name = io->u.iter.head->name; - js_free(J, io->u.iter.head); - io->u.iter.head = next; + while (io->u.iter.current) { + const char *name = io->u.iter.current->name; + io->u.iter.current = io->u.iter.current->next; if (jsV_getproperty(J, io->u.iter.target, name)) return name; - if (io->u.iter.target->type == JS_CSTRING) - if (js_isarrayindex(J, name, &k) && k < io->u.iter.target->u.s.length) - return name; - if (io->u.iter.target->type == JS_CARRAY && io->u.iter.target->u.a.simple) - if (js_isarrayindex(J, name, &k) && k < io->u.iter.target->u.a.length) - return name; } return NULL; } @@ -1736,7 +1736,7 @@ static void jsR_run(js_State *J, js_Function *F) obj = js_toobject(J, -1); str = jsV_nextiterator(J, obj); if (str) { - js_pushliteral(J, str); + js_pushstring(J, str); js_pushboolean(J, 1); } else { js_pop(J, 1); @@ -77,14 +77,14 @@ static void Sp_toString(js_State *J) { js_Object *self = js_toobject(J, 0); if (self->type != JS_CSTRING) js_typeerror(J, "not a string"); - js_pushliteral(J, self->u.s.string); + js_pushstring(J, self->u.s.string); } static void Sp_valueOf(js_State *J) { js_Object *self = js_toobject(J, 0); if (self->type != JS_CSTRING) js_typeerror(J, "not a string"); - js_pushliteral(J, self->u.s.string); + js_pushstring(J, self->u.s.string); } static void Sp_charAt(js_State *J) @@ -688,7 +688,8 @@ static void Sp_split(js_State *J) void jsB_initstring(js_State *J) { - J->String_prototype->u.s.string = ""; + J->String_prototype->u.s.shrstr[0] = 0; + J->String_prototype->u.s.string = J->String_prototype->u.s.shrstr; J->String_prototype->u.s.length = 0; js_pushobject(J, J->String_prototype); @@ -377,7 +377,13 @@ static js_Object *jsV_newnumber(js_State *J, double v) static js_Object *jsV_newstring(js_State *J, const char *v) { js_Object *obj = jsV_newobject(J, JS_CSTRING, J->String_prototype); - obj->u.s.string = js_intern(J, v); /* TODO: js_String */ + size_t n = strlen(v); + if (n < sizeof(obj->u.s.shrstr) - 1) { + obj->u.s.string = obj->u.s.shrstr; + memcpy(obj->u.s.shrstr, v, n + 1); + } else { + obj->u.s.string = js_strdup(J, v); + } obj->u.s.length = utflen(v); return obj; } @@ -88,8 +88,9 @@ struct js_Object int boolean; double number; struct { - const char *string; int length; + char *string; + char shrstr[16]; } s; struct { int length; @@ -113,7 +114,7 @@ struct js_Object struct { js_Object *target; int i, n; /* for array part */ - js_Iterator *head; /* for object part */ + js_Iterator *head, *current; /* for object part */ } iter; struct { const char *tag; @@ -131,19 +132,19 @@ struct js_Object struct js_Property { - const char *name; js_Property *left, *right; int level; int atts; js_Value value; js_Object *getter; js_Object *setter; + char name[1]; }; struct js_Iterator { - const char *name; js_Iterator *next; + char name[1]; }; /* jsrun.c */ |