Shaver's huge patch for 419152 (Huge, I say; r=me).

This commit is contained in:
brendan%mozilla.org 2008-02-26 00:59:37 +00:00
Родитель edabe7a07b
Коммит 5c6901f9e8
4 изменённых файлов: 126 добавлений и 71 удалений

Просмотреть файл

@ -102,16 +102,8 @@
#define MAXINDEX 4294967295u #define MAXINDEX 4294967295u
#define MAXSTR "4294967295" #define MAXSTR "4294967295"
#define ARRAY_SET_LENGTH(obj, len) \ #define ARRAY_SET_DENSE_LENGTH(obj, max) \
STOBJ_SET_SLOT((obj), JSSLOT_ARRAY_LENGTH, (uint32)len)
#define ARRAY_LENGTH(obj) (uint32)STOBJ_GET_SLOT((obj), JSSLOT_ARRAY_LENGTH)
#define ARRAY_SET_COUNT(obj, count) \
STOBJ_SET_SLOT((obj), JSSLOT_ARRAY_COUNT, (jsval)(count))
#define ARRAY_COUNT(obj) (uint32)(STOBJ_GET_SLOT((obj), JSSLOT_ARRAY_COUNT))
#define ARRAY_SET_DENSELEN(obj, max) \
(JS_ASSERT((obj)->dslots), (obj)->dslots[-1] = (jsval)(max)) (JS_ASSERT((obj)->dslots), (obj)->dslots[-1] = (jsval)(max))
#define ARRAY_DENSELEN(obj) ((obj)->dslots ? (uint32)(obj)->dslots[-1] : 0)
/* Small arrays are dense, no matter what. */ /* Small arrays are dense, no matter what. */
#define MIN_SPARSE_INDEX 32 #define MIN_SPARSE_INDEX 32
@ -119,8 +111,8 @@
#define INDEX_TOO_BIG(index) ((index) > JS_BIT(29) - 1) #define INDEX_TOO_BIG(index) ((index) > JS_BIT(29) - 1)
#define INDEX_TOO_SPARSE(array, index) \ #define INDEX_TOO_SPARSE(array, index) \
(INDEX_TOO_BIG(index) || \ (INDEX_TOO_BIG(index) || \
((index) > ARRAY_DENSELEN(array) && (index) >= MIN_SPARSE_INDEX && \ ((index) > ARRAY_DENSE_LENGTH(array) && (index) >= MIN_SPARSE_INDEX && \
(index) > (ARRAY_COUNT(array) + 1) * 4)) (index) > (uint32)((array)->fslots[JSSLOT_ARRAY_COUNT] + 1) * 4))
JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval)); JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
@ -234,7 +226,7 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
jsint i; jsint i;
if (OBJ_IS_ARRAY(cx, obj)) { if (OBJ_IS_ARRAY(cx, obj)) {
*lengthp = ARRAY_LENGTH(obj); *lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH];
return JS_TRUE; return JS_TRUE;
} }
@ -336,7 +328,7 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldlen, uint32 len)
return JS_FALSE; return JS_FALSE;
obj->dslots = newslots + 1; obj->dslots = newslots + 1;
ARRAY_SET_DENSELEN(obj, len); ARRAY_SET_DENSE_LENGTH(obj, len);
for (slots = obj->dslots + oldlen; slots < obj->dslots + len; slots++) for (slots = obj->dslots + oldlen; slots < obj->dslots + len; slots++)
*slots = JSVAL_HOLE; *slots = JSVAL_HOLE;
@ -349,7 +341,7 @@ ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldlen, uint32 len)
static JSBool static JSBool
EnsureLength(JSContext *cx, JSObject *obj, uint32 len) EnsureLength(JSContext *cx, JSObject *obj, uint32 len)
{ {
uint32 oldlen = ARRAY_DENSELEN(obj); uint32 oldlen = ARRAY_DENSE_LENGTH(obj);
if (len > oldlen) { if (len > oldlen) {
return ResizeSlots(cx, obj, oldlen, return ResizeSlots(cx, obj, oldlen,
@ -373,7 +365,7 @@ GetArrayElement(JSContext *cx, JSObject *obj, jsuint index, JSBool *hole,
JSProperty *prop; JSProperty *prop;
if (OBJ_IS_DENSE_ARRAY(cx, obj)) { if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
if (index >= ARRAY_DENSELEN(obj)) { if (index >= ARRAY_DENSE_LENGTH(obj)) {
*vp = JSVAL_VOID; *vp = JSVAL_VOID;
*hole = JS_TRUE; *hole = JS_TRUE;
return JS_TRUE; return JS_TRUE;
@ -431,10 +423,10 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsuint index, jsval v)
if (!EnsureLength(cx, obj, index + 1)) if (!EnsureLength(cx, obj, index + 1))
return JS_FALSE; return JS_FALSE;
if (index >= ARRAY_LENGTH(obj)) if (index >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
ARRAY_SET_LENGTH(obj, index + 1); obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
if (obj->dslots[index] == JSVAL_HOLE) if (obj->dslots[index] == JSVAL_HOLE)
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) + 1); obj->fslots[JSSLOT_ARRAY_COUNT]++;
obj->dslots[index] = v; obj->dslots[index] = v;
return JS_TRUE; return JS_TRUE;
} }
@ -457,9 +449,9 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index)
jsval junk; jsval junk;
if (OBJ_IS_DENSE_ARRAY(cx, obj)) { if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
if (index < ARRAY_DENSELEN(obj)) { if (index < ARRAY_DENSE_LENGTH(obj)) {
if (obj->dslots[index] != JSVAL_HOLE) if (obj->dslots[index] != JSVAL_HOLE)
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) - 1); obj->fslots[JSSLOT_ARRAY_COUNT]--;
obj->dslots[index] = JSVAL_HOLE; obj->dslots[index] = JSVAL_HOLE;
} }
return JS_TRUE; return JS_TRUE;
@ -554,7 +546,7 @@ array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{ {
do { do {
if (OBJ_IS_ARRAY(cx, obj)) if (OBJ_IS_ARRAY(cx, obj))
return IndexToValue(cx, ARRAY_LENGTH(obj), vp); return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
} while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL); } while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL);
return JS_TRUE; return JS_TRUE;
} }
@ -577,7 +569,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (!ValueIsLength(cx, *vp, &newlen)) if (!ValueIsLength(cx, *vp, &newlen))
return JS_FALSE; return JS_FALSE;
oldlen = ARRAY_LENGTH(obj); oldlen = obj->fslots[JSSLOT_ARRAY_LENGTH];
if (oldlen == newlen) if (oldlen == newlen)
return JS_TRUE; return JS_TRUE;
@ -586,12 +578,12 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_FALSE; return JS_FALSE;
if (oldlen < newlen) { if (oldlen < newlen) {
ARRAY_SET_LENGTH(obj, newlen); obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
return JS_TRUE; return JS_TRUE;
} }
if (OBJ_IS_DENSE_ARRAY(cx, obj)) { if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
if (ARRAY_DENSELEN(obj) && !ResizeSlots(cx, obj, oldlen, newlen)) if (ARRAY_DENSE_LENGTH(obj) && !ResizeSlots(cx, obj, oldlen, newlen))
return JS_FALSE; return JS_FALSE;
} else if (oldlen - newlen < (1 << 24)) { } else if (oldlen - newlen < (1 << 24)) {
do { do {
@ -634,7 +626,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_FALSE; return JS_FALSE;
} }
ARRAY_SET_LENGTH(obj, newlen); obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
return JS_TRUE; return JS_TRUE;
} }
@ -653,8 +645,10 @@ array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
*/ */
if ((!js_IdIsIndex(id, &i) && if ((!js_IdIsIndex(id, &i) &&
id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) || id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) ||
ARRAY_LENGTH(obj) == 0 || i >= ARRAY_DENSELEN(obj) || obj->fslots[JSSLOT_ARRAY_LENGTH] == 0 ||
obj->dslots[i] == JSVAL_HOLE) { i >= ARRAY_DENSE_LENGTH(obj) ||
obj->dslots[i] == JSVAL_HOLE)
{
JSObject *proto = STOBJ_GET_PROTO(obj); JSObject *proto = STOBJ_GET_PROTO(obj);
if (!proto) { if (!proto) {
@ -692,7 +686,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
uint32 i; uint32 i;
if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
return IndexToValue(cx, ARRAY_LENGTH(obj), vp); return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) { if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) {
*vp = STOBJ_GET_SLOT(obj, JSSLOT_PROTO); *vp = STOBJ_GET_SLOT(obj, JSSLOT_PROTO);
@ -702,7 +696,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
if (!OBJ_IS_DENSE_ARRAY(cx, obj)) if (!OBJ_IS_DENSE_ARRAY(cx, obj))
return js_GetProperty(cx, obj, id, vp); return js_GetProperty(cx, obj, id, vp);
if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= ARRAY_DENSELEN(obj) || if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= ARRAY_DENSE_LENGTH(obj) ||
obj->dslots[i] == JSVAL_HOLE) { obj->dslots[i] == JSVAL_HOLE) {
JSObject *proto = STOBJ_GET_PROTO(obj); JSObject *proto = STOBJ_GET_PROTO(obj);
if (!proto) { if (!proto) {
@ -724,16 +718,16 @@ slowarray_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
if (!js_IdIsIndex(id, &index)) if (!js_IdIsIndex(id, &index))
return JS_TRUE; return JS_TRUE;
length = ARRAY_LENGTH(obj); length = obj->fslots[JSSLOT_ARRAY_LENGTH];
if (index >= length) if (index >= length)
ARRAY_SET_LENGTH(obj, index + 1); obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
return JS_TRUE; return JS_TRUE;
} }
static void static void
slowarray_trace(JSTracer *trc, JSObject *obj) slowarray_trace(JSTracer *trc, JSObject *obj)
{ {
uint32 length = ARRAY_LENGTH(obj); uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_SlowArrayClass); JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_SlowArrayClass);
@ -741,9 +735,9 @@ slowarray_trace(JSTracer *trc, JSObject *obj)
* Move JSSLOT_ARRAY_LENGTH aside to prevent the GC from treating * Move JSSLOT_ARRAY_LENGTH aside to prevent the GC from treating
* untagged integer values as objects or strings. * untagged integer values as objects or strings.
*/ */
STOBJ_SET_SLOT(obj, JSSLOT_ARRAY_LENGTH, JSVAL_VOID); obj->fslots[JSSLOT_ARRAY_LENGTH] = JSVAL_VOID;
js_TraceObject(trc, obj); js_TraceObject(trc, obj);
STOBJ_SET_SLOT(obj, JSSLOT_ARRAY_LENGTH, length); obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
} }
static JSObjectOps js_SlowArrayObjectOps; static JSObjectOps js_SlowArrayObjectOps;
@ -774,10 +768,10 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
if (!EnsureLength(cx, obj, i + 1)) if (!EnsureLength(cx, obj, i + 1))
return JS_FALSE; return JS_FALSE;
if (i >= ARRAY_LENGTH(obj)) if (i >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
ARRAY_SET_LENGTH(obj, i + 1); obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
if (obj->dslots[i] == JSVAL_HOLE) if (obj->dslots[i] == JSVAL_HOLE)
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) + 1); obj->fslots[JSSLOT_ARRAY_COUNT]++;
obj->dslots[i] = *vp; obj->dslots[i] = *vp;
return JS_TRUE; return JS_TRUE;
} }
@ -833,9 +827,9 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
return JS_TRUE; return JS_TRUE;
} }
if (js_IdIsIndex(id, &i) && i < ARRAY_DENSELEN(obj) && if (js_IdIsIndex(id, &i) && i < ARRAY_DENSE_LENGTH(obj) &&
obj->dslots[i] != JSVAL_HOLE) { obj->dslots[i] != JSVAL_HOLE) {
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) - 1); obj->fslots[JSSLOT_ARRAY_COUNT]--;
obj->dslots[i] = JSVAL_HOLE; obj->dslots[i] = JSVAL_HOLE;
} }
@ -896,7 +890,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
return JS_TRUE; return JS_TRUE;
} }
length = ARRAY_DENSELEN(obj); length = ARRAY_DENSE_LENGTH(obj);
if (*statep == OBJECT_TO_JSVAL(obj)) { if (*statep == OBJECT_TO_JSVAL(obj)) {
if (length == 0) { if (length == 0) {
*statep = JSVAL_NULL; *statep = JSVAL_NULL;
@ -944,7 +938,7 @@ array_trace(JSTracer *trc, JSObject *obj)
JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)); JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
length = ARRAY_DENSELEN(obj); length = ARRAY_DENSE_LENGTH(obj);
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
v = obj->dslots[i]; v = obj->dslots[i];
if (JSVAL_IS_TRACEABLE(v)) { if (JSVAL_IS_TRACEABLE(v)) {
@ -1046,7 +1040,7 @@ MakeArraySlow(JSContext *cx, JSObject *obj)
if (!map) if (!map)
return JS_FALSE; return JS_FALSE;
length = ARRAY_DENSELEN(obj); length = ARRAY_DENSE_LENGTH(obj);
if (length) { if (length) {
map->freeslot = STOBJ_NSLOTS(obj) + JS_INITIAL_NSLOTS; map->freeslot = STOBJ_NSLOTS(obj) + JS_INITIAL_NSLOTS;
obj->dslots[-1] = JS_INITIAL_NSLOTS + length; obj->dslots[-1] = JS_INITIAL_NSLOTS + length;
@ -1201,7 +1195,7 @@ array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
/* Use rval to locally root each element value as we loop and convert. */ /* Use rval to locally root each element value as we loop and convert. */
for (index = 0; index < length; index++) { for (index = 0; index < length; index++) {
if (OBJ_IS_DENSE_ARRAY(cx, obj) && index < ARRAY_DENSELEN(obj)) { if (OBJ_IS_DENSE_ARRAY(cx, obj) && index < ARRAY_DENSE_LENGTH(obj)) {
*rval = obj->dslots[index]; *rval = obj->dslots[index];
hole = (*rval == JSVAL_HOLE); hole = (*rval == JSVAL_HOLE);
ok = JS_TRUE; ok = JS_TRUE;
@ -1373,8 +1367,8 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint end,
if (!EnsureLength(cx, obj, end)) if (!EnsureLength(cx, obj, end))
return JS_FALSE; return JS_FALSE;
if (end > ARRAY_LENGTH(obj)) if (end > (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
ARRAY_SET_LENGTH(obj, end); obj->fslots[JSSLOT_ARRAY_LENGTH] = end;
memcpy(obj->dslots + start, vector, sizeof(jsval) * (end - start)); memcpy(obj->dslots + start, vector, sizeof(jsval) * (end - start));
return JS_TRUE; return JS_TRUE;
@ -1394,15 +1388,15 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector)
{ {
JS_ASSERT(OBJ_IS_ARRAY(cx, obj)); JS_ASSERT(OBJ_IS_ARRAY(cx, obj));
ARRAY_SET_LENGTH(obj, length); obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
if (vector) { if (vector) {
if (!EnsureLength(cx, obj, length)) if (!EnsureLength(cx, obj, length))
return JS_FALSE; return JS_FALSE;
memcpy(obj->dslots, vector, length * sizeof (jsval)); memcpy(obj->dslots, vector, length * sizeof (jsval));
ARRAY_SET_COUNT(obj, length); obj->fslots[JSSLOT_ARRAY_COUNT] = length;
} else { } else {
ARRAY_SET_COUNT(obj, 0); obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
} }
return JS_TRUE; return JS_TRUE;
} }
@ -1964,7 +1958,7 @@ static JSBool
array_push(JSContext *cx, uintN argc, jsval *vp) array_push(JSContext *cx, uintN argc, jsval *vp)
{ {
JSObject *obj; JSObject *obj;
uint32 len; uint32 length;
/* Insist on one argument and obj of the expected class. */ /* Insist on one argument and obj of the expected class. */
obj = JS_THIS_OBJECT(cx, vp); obj = JS_THIS_OBJECT(cx, vp);
@ -1973,21 +1967,21 @@ array_push(JSContext *cx, uintN argc, jsval *vp)
if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj)) if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
return array_push_slowly(cx, obj, argc, vp); return array_push_slowly(cx, obj, argc, vp);
len = ARRAY_LENGTH(obj); length = obj->fslots[JSSLOT_ARRAY_LENGTH];
if (INDEX_TOO_SPARSE(obj, len)) { if (INDEX_TOO_SPARSE(obj, length)) {
if (!MakeArraySlow(cx, obj)) if (!MakeArraySlow(cx, obj))
return JS_FALSE; return JS_FALSE;
return array_push_slowly(cx, obj, argc, vp); return array_push_slowly(cx, obj, argc, vp);
} }
if (!EnsureLength(cx, obj, len + 1)) if (!EnsureLength(cx, obj, length + 1))
return JS_FALSE; return JS_FALSE;
ARRAY_SET_LENGTH(obj, len + 1); obj->fslots[JSSLOT_ARRAY_LENGTH] = length + 1;
JS_ASSERT(obj->dslots[len] == JSVAL_HOLE); JS_ASSERT(obj->dslots[length] == JSVAL_HOLE);
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) + 1); obj->fslots[JSSLOT_ARRAY_COUNT]++;
obj->dslots[len] = vp[2]; obj->dslots[length] = vp[2];
return IndexToValue(cx, ARRAY_LENGTH(obj), vp); return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
} }
JSBool JSBool
@ -2002,23 +1996,23 @@ array_pop(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE; return JS_FALSE;
if (OBJ_IS_DENSE_ARRAY(cx, obj)) { if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
*vp = JSVAL_VOID; *vp = JSVAL_VOID;
index = ARRAY_LENGTH(obj); index = obj->fslots[JSSLOT_ARRAY_LENGTH];
if (index == 0) if (index == 0)
return JS_TRUE; return JS_TRUE;
index--; index--;
if (index < ARRAY_DENSELEN(obj)) { if (index < ARRAY_DENSE_LENGTH(obj)) {
*vp = obj->dslots[index]; *vp = obj->dslots[index];
JS_ASSERT(*vp != JSVAL_HOLE); JS_ASSERT(*vp != JSVAL_HOLE);
if (index == 0) { if (index == 0) {
JS_free(cx, obj->dslots - 1); JS_free(cx, obj->dslots - 1);
obj->dslots = NULL; obj->dslots = NULL;
} else { } else {
ARRAY_SET_DENSELEN(obj, index); ARRAY_SET_DENSE_LENGTH(obj, index);
} }
ARRAY_SET_COUNT(obj, ARRAY_COUNT(obj) - 1); obj->fslots[JSSLOT_ARRAY_COUNT]--;
} }
ARRAY_SET_LENGTH(obj, index); obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
return JS_TRUE; return JS_TRUE;
} }
@ -2273,11 +2267,11 @@ array_concat(JSContext *cx, uintN argc, jsval *vp)
/* Create a new Array object and root it using *vp. */ /* Create a new Array object and root it using *vp. */
aobj = JS_THIS_OBJECT(cx, vp); aobj = JS_THIS_OBJECT(cx, vp);
if (OBJ_IS_DENSE_ARRAY(cx, aobj)) { if (OBJ_IS_DENSE_ARRAY(cx, aobj)) {
nobj = js_NewArrayObject(cx, ARRAY_DENSELEN(aobj), aobj->dslots); nobj = js_NewArrayObject(cx, ARRAY_DENSE_LENGTH(aobj), aobj->dslots);
if (!nobj) if (!nobj)
return JS_FALSE; return JS_FALSE;
length = ARRAY_LENGTH(aobj); length = aobj->fslots[JSSLOT_ARRAY_LENGTH];
ARRAY_SET_LENGTH(nobj, length); nobj->fslots[JSSLOT_ARRAY_LENGTH] = length;
*vp = OBJECT_TO_JSVAL(nobj); *vp = OBJECT_TO_JSVAL(nobj);
if (argc == 0) if (argc == 0)
return JS_TRUE; return JS_TRUE;
@ -2865,7 +2859,7 @@ js_NewSlowArrayObject(JSContext *cx)
{ {
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL); JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
if (obj) if (obj)
ARRAY_SET_LENGTH(obj, 0); obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
return obj; return obj;
} }
@ -2891,10 +2885,11 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
} }
fprintf(stderr, "%s: %s (len %lu", bytes, fprintf(stderr, "%s: %s (len %lu", bytes,
OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse", OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse",
ARRAY_LENGTH(array)); array->fslots[JSSLOT_ARRAY_LENGTH]);
if (OBJ_IS_DENSE_ARRAY(cx, array)) { if (OBJ_IS_DENSE_ARRAY(cx, array)) {
fprintf(stderr, ", count %lu, denselen %lu", fprintf(stderr, ", count %lu, denselen %lu",
ARRAY_COUNT(array), ARRAY_DENSELEN(array)); array->fslots[JSSLOT_ARRAY_COUNT],
ARRAY_DENSE_LENGTH(array));
} }
fputs(")\n", stderr); fputs(")\n", stderr);
JS_free(cx, bytes); JS_free(cx, bytes);

Просмотреть файл

@ -74,6 +74,10 @@ js_NewSlowArrayObject(JSContext *cx);
#define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1) #define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1)
#define JSSLOT_ARRAY_LOOKUP_HOLDER (JSSLOT_ARRAY_COUNT + 1) #define JSSLOT_ARRAY_LOOKUP_HOLDER (JSSLOT_ARRAY_COUNT + 1)
#define ARRAY_DENSE_LENGTH(obj) \
(JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)), \
(obj)->dslots ? (uint32)(obj)->dslots[-1] : 0)
extern JSBool extern JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);

Просмотреть файл

@ -4381,7 +4381,43 @@ interrupt:
END_CASE(JSOP_SETPROP) END_CASE(JSOP_SETPROP)
BEGIN_CASE(JSOP_GETELEM) BEGIN_CASE(JSOP_GETELEM)
ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval)); /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */
SAVE_SP_AND_PC(fp);
lval = FETCH_OPND(-2);
rval = FETCH_OPND(-1);
if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(rval)) {
str = JSVAL_TO_STRING(lval);
i = JSVAL_TO_INT(rval);
if ((size_t)i < JSSTRING_LENGTH(str)) {
str = js_GetUnitString(cx, JSSTRING_CHARS(str)[i]);
if (!str)
goto error;
rval = STRING_TO_JSVAL(str);
goto end_getelem;
}
}
VALUE_TO_OBJECT(cx, -2, lval, obj);
if (JSVAL_IS_INT(rval)) {
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
jsuint length;
length = ARRAY_DENSE_LENGTH(obj);
i = JSVAL_TO_INT(rval);
if ((jsuint)i < length &&
i < obj->fslots[JSSLOT_ARRAY_LENGTH]) {
rval = obj->dslots[i];
if (rval != JSVAL_HOLE)
goto end_getelem;
}
}
id = INT_JSVAL_TO_JSID(rval);
} else {
if (!InternNonIntElementId(cx, obj, rval, &id))
goto error;
}
if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
goto error;
end_getelem:
sp--; sp--;
STORE_OPND(-1, rval); STORE_OPND(-1, rval);
END_CASE(JSOP_GETELEM) END_CASE(JSOP_GETELEM)
@ -4398,7 +4434,27 @@ interrupt:
BEGIN_CASE(JSOP_SETELEM) BEGIN_CASE(JSOP_SETELEM)
rval = FETCH_OPND(-1); rval = FETCH_OPND(-1);
ELEMENT_OP(-2, OBJ_SET_PROPERTY(cx, obj, id, &rval)); SAVE_SP_AND_PC(fp);
FETCH_OBJECT(cx, -3, lval, obj);
FETCH_ELEMENT_ID(obj, -2, id);
if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) {
jsuint length;
length = ARRAY_DENSE_LENGTH(obj);
i = JSID_TO_INT(id);
if ((jsuint)i < length) {
if (obj->dslots[i] == JSVAL_HOLE) {
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
obj->fslots[JSSLOT_ARRAY_COUNT]++;
}
obj->dslots[i] = rval;
goto end_setelem;
}
}
if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
goto error;
end_setelem:
sp -= 2; sp -= 2;
STORE_OPND(-1, rval); STORE_OPND(-1, rval);
END_CASE(JSOP_SETELEM) END_CASE(JSOP_SETELEM)

Просмотреть файл

@ -583,7 +583,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
slot = JSVAL_TO_INT(id); slot = JSVAL_TO_INT(id);
if ((size_t)slot < JSSTRING_LENGTH(str)) { if ((size_t)slot < JSSTRING_LENGTH(str)) {
str1 = js_NewDependentString(cx, str, (size_t)slot, 1); str1 = js_GetUnitString(cx, JSSTRING_CHARS(str)[slot]);
if (!str1) if (!str1)
return JS_FALSE; return JS_FALSE;
if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(slot), if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(slot),