shithub: libmujs

Download patch

ref: 9f181651fb03b9d951ae60ae7ef51589efe69015
parent: 9ded251f9ba34702dbc0d434b7be9727c5ce2072
author: Tor Andersson <tor.andersson@artifex.com>
date: Fri Nov 7 11:00:45 EST 2014

Track array sparseness to be smarter in jsV_resizearray.

--- a/jsproperty.c
+++ b/jsproperty.c
@@ -27,7 +27,7 @@
 	NULL, NULL
 };
 
-static js_Property *newproperty(js_State *J, const char *name)
+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);
@@ -40,6 +40,7 @@
 	node->value.u.number = 0;
 	node->getter = NULL;
 	node->setter = NULL;
+	++obj->count;
 	return node;
 }
 
@@ -80,14 +81,14 @@
 	return node;
 }
 
-static js_Property *insert(js_State *J, js_Property *node, const char *name, js_Property **result)
+static js_Property *insert(js_State *J, js_Object *obj, js_Property *node, const char *name, js_Property **result)
 {
 	if (node != &sentinel) {
 		int c = strcmp(name, node->name);
 		if (c < 0)
-			node->left = insert(J, node->left, name, result);
+			node->left = insert(J, obj, node->left, name, result);
 		else if (c > 0)
-			node->right = insert(J, node->right, name, result);
+			node->right = insert(J, obj, node->right, name, result);
 		else
 			return *result = node;
 		node = skew(node);
@@ -94,7 +95,7 @@
 		node = split(node);
 		return node;
 	}
-	return *result = newproperty(J, name);
+	return *result = newproperty(J, obj, name);
 }
 
 static void freeproperty(js_State *J, js_Object *obj, js_Property *node)
@@ -105,6 +106,7 @@
 		obj->tailp = node->prevp;
 	*node->prevp = node->next;
 	js_free(J, node);
+	--obj->count;
 }
 
 static js_Property *delete(js_State *J, js_Object *obj, js_Property *node, const char *name)
@@ -207,7 +209,7 @@
 	if (!obj->extensible)
 		return lookup(obj->properties, name);
 
-	obj->properties = insert(J, obj->properties, name, &result);
+	obj->properties = insert(J, obj, obj->properties, name, &result);
 	if (!result->prevp) {
 		result->prevp = obj->tailp;
 		*obj->tailp = result;
@@ -315,11 +317,19 @@
 	const char *s;
 	unsigned int k;
 	if (newlen < obj->u.a.length) {
-		js_Object *it = jsV_newiterator(J, obj, 1);
-		while ((s = jsV_nextiterator(J, it))) {
-			k = jsV_numbertouint32(jsV_stringtonumber(J, s));
-			if (k >= newlen && !strcmp(s, jsV_numbertostring(J, k)))
-				jsV_delproperty(J, obj, s);
+		if (obj->u.a.length > obj->count * 2) {
+			js_Object *it = jsV_newiterator(J, obj, 1);
+			while ((s = jsV_nextiterator(J, it))) {
+				k = jsV_numbertouint32(jsV_stringtonumber(J, s));
+				if (k >= newlen && !strcmp(s, jsV_numbertostring(J, k)))
+					jsV_delproperty(J, obj, s);
+			}
+		} else {
+			for (k = newlen; k < obj->u.a.length; ++k) {
+				char buf[32];
+				sprintf(buf, "%u", k);
+				jsV_delproperty(J, obj, buf);
+			}
 		}
 	}
 	obj->u.a.length = newlen;
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -63,6 +63,7 @@
 	int extensible;
 	js_Property *properties;
 	js_Property *head, **tailp; /* for enumeration */
+	unsigned int count; /* number of properties, for array sparseness check */
 	js_Object *prototype;
 	union {
 		int boolean;