mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 556187 - encapsulate JSSLOT_ARRAY_* within JSObject. r=brendan.
This commit is contained in:
parent
06c049adbc
commit
4542317997
@ -103,6 +103,7 @@
|
||||
#include "jsvector.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
@ -122,7 +123,7 @@ INDEX_TOO_BIG(jsuint index)
|
||||
#define INDEX_TOO_SPARSE(array, index) \
|
||||
(INDEX_TOO_BIG(index) || \
|
||||
((index) > js_DenseArrayCapacity(array) && (index) >= MIN_SPARSE_INDEX && \
|
||||
(index) > (uint32)((array)->fslots[JSSLOT_ARRAY_COUNT] + 1) * 4))
|
||||
(index) > ((array)->getArrayCount() + 1) * 4))
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
|
||||
|
||||
@ -227,7 +228,7 @@ JSBool
|
||||
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
{
|
||||
if (obj->isArray()) {
|
||||
*lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
*lengthp = obj->getArrayLength();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -497,10 +498,10 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, jsval v)
|
||||
JS_ASSERT(idx + 1 > idx);
|
||||
if (!EnsureCapacity(cx, obj, idx + 1))
|
||||
return JS_FALSE;
|
||||
if (idx >= uint32(obj->fslots[JSSLOT_ARRAY_LENGTH]))
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = idx + 1;
|
||||
if (idx >= obj->getArrayLength())
|
||||
obj->setArrayLength(idx + 1);
|
||||
if (obj->dslots[idx] == JSVAL_HOLE)
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->incArrayCountBy(1);
|
||||
obj->dslots[idx] = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -528,7 +529,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index)
|
||||
jsuint idx = jsuint(index);
|
||||
if (!INDEX_TOO_SPARSE(obj, idx) && idx < js_DenseArrayCapacity(obj)) {
|
||||
if (obj->dslots[idx] != JSVAL_HOLE)
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]--;
|
||||
obj->decArrayCountBy(1);
|
||||
obj->dslots[idx] = JSVAL_HOLE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -619,7 +620,7 @@ array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
do {
|
||||
if (obj->isArray())
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
|
||||
return IndexToValue(cx, obj->getArrayLength(), vp);
|
||||
} while ((obj = obj->getProto()) != NULL);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -639,7 +640,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
newlen = ValueIsLength(cx, vp);
|
||||
if (JSVAL_IS_NULL(*vp))
|
||||
return false;
|
||||
oldlen = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
oldlen = obj->getArrayLength();
|
||||
|
||||
if (oldlen == newlen)
|
||||
return true;
|
||||
@ -648,7 +649,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
return false;
|
||||
|
||||
if (oldlen < newlen) {
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
|
||||
obj->setArrayLength(newlen);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -691,7 +692,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
}
|
||||
}
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
|
||||
obj->setArrayLength(newlen);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -707,7 +708,7 @@ IsDenseArrayId(JSContext *cx, JSObject *obj, jsid id)
|
||||
uint32 i;
|
||||
return id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) ||
|
||||
(js_IdIsIndex(id, &i) &&
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] != 0 &&
|
||||
obj->getArrayLength() != 0 &&
|
||||
i < js_DenseArrayCapacity(obj) &&
|
||||
obj->dslots[i] != JSVAL_HOLE);
|
||||
}
|
||||
@ -750,7 +751,7 @@ js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop,
|
||||
uint32 i;
|
||||
if (!js_IdIsIndex(id, &i)) {
|
||||
JS_ASSERT(id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom));
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
|
||||
return IndexToValue(cx, obj->getArrayLength(), vp);
|
||||
}
|
||||
*vp = obj->dslots[i];
|
||||
return JS_TRUE;
|
||||
@ -762,7 +763,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
uint32 i;
|
||||
|
||||
if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
|
||||
return IndexToValue(cx, obj->getArrayLength(), vp);
|
||||
|
||||
if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) {
|
||||
*vp = OBJECT_TO_JSVAL(obj->getProto());
|
||||
@ -811,9 +812,9 @@ slowarray_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
|
||||
if (!js_IdIsIndex(id, &index))
|
||||
return JS_TRUE;
|
||||
length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
length = obj->getArrayLength();
|
||||
if (index >= length)
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
|
||||
obj->setArrayLength(index + 1);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -867,10 +868,10 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
if (!EnsureCapacity(cx, obj, i + 1))
|
||||
return JS_FALSE;
|
||||
|
||||
if (i >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
|
||||
if (i >= obj->getArrayLength())
|
||||
obj->setArrayLength(i + 1);
|
||||
if (obj->dslots[i] == JSVAL_HOLE)
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->incArrayCountBy(1);
|
||||
obj->dslots[i] = *vp;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -927,9 +928,9 @@ dense_grow(JSContext* cx, JSObject* obj, jsint i, jsval v)
|
||||
if (js_PrototypeHasIndexedProperties(cx, obj))
|
||||
return JS_FALSE;
|
||||
|
||||
if (u >= jsuint(obj->fslots[JSSLOT_ARRAY_LENGTH]))
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = u + 1;
|
||||
++obj->fslots[JSSLOT_ARRAY_COUNT];
|
||||
if (u >= obj->getArrayLength())
|
||||
obj->setArrayLength(u + 1);
|
||||
obj->incArrayCountBy(1);
|
||||
}
|
||||
|
||||
obj->dslots[u] = v;
|
||||
@ -1039,7 +1040,7 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
|
||||
|
||||
if (js_IdIsIndex(id, &i) && i < js_DenseArrayCapacity(obj) &&
|
||||
obj->dslots[i] != JSVAL_HOLE) {
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]--;
|
||||
obj->decArrayCountBy(1);
|
||||
obj->dslots[i] = JSVAL_HOLE;
|
||||
}
|
||||
|
||||
@ -1120,7 +1121,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
JS_ASSERT(obj->isDenseArray());
|
||||
capacity = js_DenseArrayCapacity(obj);
|
||||
if (idp)
|
||||
*idp = INT_TO_JSVAL(obj->fslots[JSSLOT_ARRAY_COUNT]);
|
||||
*idp = INT_TO_JSVAL(obj->getArrayCount());
|
||||
ii = NULL;
|
||||
for (i = 0; i != capacity; ++i) {
|
||||
if (obj->dslots[i] == JSVAL_HOLE) {
|
||||
@ -1338,15 +1339,13 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
/*
|
||||
* Render our formerly-reserved count property GC-safe.
|
||||
* We do not need to make the length slot GC-safe as this slot is private
|
||||
* where the implementation can store an arbitrary value.
|
||||
* Render our formerly-reserved count property GC-safe. We do not need to
|
||||
* make the length slot GC-safe because it is the private slot (this is
|
||||
* statically asserted within JSObject) where the implementation can store
|
||||
* an arbitrary value.
|
||||
*/
|
||||
{
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE);
|
||||
JS_ASSERT(js_SlowArrayClass.flags & JSCLASS_HAS_PRIVATE);
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
|
||||
}
|
||||
JS_ASSERT(js_SlowArrayClass.flags & JSCLASS_HAS_PRIVATE);
|
||||
obj->voidDenseArrayCount();
|
||||
|
||||
/* Make sure we preserve any flags borrowing bits in classword. */
|
||||
obj->classword ^= (jsuword) &js_ArrayClass;
|
||||
@ -1659,8 +1658,8 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva
|
||||
if (!EnsureCapacity(cx, obj, newlen))
|
||||
return JS_FALSE;
|
||||
|
||||
if (newlen > uint32(obj->fslots[JSSLOT_ARRAY_LENGTH]))
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
|
||||
if (newlen > obj->getArrayLength())
|
||||
obj->setArrayLength(newlen);
|
||||
|
||||
JS_ASSERT(count < size_t(-1) / sizeof(jsval));
|
||||
if (targetType == TargetElementsMayContainValues) {
|
||||
@ -1669,19 +1668,19 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva
|
||||
if (obj->dslots[start + i] != JSVAL_HOLE)
|
||||
valueCount++;
|
||||
}
|
||||
JS_ASSERT(uint32(obj->fslots[JSSLOT_ARRAY_COUNT]) >= valueCount);
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] -= valueCount;
|
||||
JS_ASSERT(obj->getArrayCount() >= valueCount);
|
||||
obj->decArrayCountBy(valueCount);
|
||||
}
|
||||
memcpy(obj->dslots + start, vector, sizeof(jsval) * count);
|
||||
if (vectorType == SourceVectorAllValues) {
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] += count;
|
||||
obj->incArrayCountBy(count);
|
||||
} else {
|
||||
jsuint valueCount = 0;
|
||||
for (jsuint i = 0; i < count; i++) {
|
||||
if (obj->dslots[start + i] != JSVAL_HOLE)
|
||||
valueCount++;
|
||||
}
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] += valueCount;
|
||||
obj->incArrayCountBy(valueCount);
|
||||
}
|
||||
JS_ASSERT_IF(count != 0, obj->dslots[newlen - 1] != JSVAL_HOLE);
|
||||
return JS_TRUE;
|
||||
@ -1728,7 +1727,7 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const jsval *vector
|
||||
{
|
||||
JS_ASSERT(obj->isArray());
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
|
||||
obj->setArrayLength(length);
|
||||
|
||||
if (vector) {
|
||||
if (!EnsureCapacity(cx, obj, length))
|
||||
@ -1744,9 +1743,9 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const jsval *vector
|
||||
obj->dslots[i] = vector[i];
|
||||
}
|
||||
}
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = count;
|
||||
obj->setArrayCount(count);
|
||||
} else {
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
|
||||
obj->setArrayCount(0);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -2353,7 +2352,7 @@ array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
|
||||
static JSBool
|
||||
array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
||||
{
|
||||
uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
uint32 length = obj->getArrayLength();
|
||||
if (INDEX_TOO_SPARSE(obj, length)) {
|
||||
if (!js_MakeArraySlow(cx, obj))
|
||||
return JS_FALSE;
|
||||
@ -2362,19 +2361,19 @@ array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
|
||||
|
||||
if (!EnsureCapacity(cx, obj, length + 1))
|
||||
return JS_FALSE;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = length + 1;
|
||||
obj->setArrayLength(length + 1);
|
||||
|
||||
JS_ASSERT(obj->dslots[length] == JSVAL_HOLE);
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->incArrayCountBy(1);
|
||||
obj->dslots[length] = v;
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], rval);
|
||||
return IndexToValue(cx, obj->getArrayLength(), rval);
|
||||
}
|
||||
|
||||
JSBool JS_FASTCALL
|
||||
js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v)
|
||||
{
|
||||
JS_ASSERT(obj->isDenseArray());
|
||||
uint32_t length = (uint32_t) obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
uint32_t length = obj->getArrayLength();
|
||||
JS_ASSERT(length <= js_DenseArrayCapacity(obj));
|
||||
|
||||
if (length == js_DenseArrayCapacity(obj)) {
|
||||
@ -2387,8 +2386,8 @@ js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v)
|
||||
if (!EnsureCapacity(cx, obj, length + 1))
|
||||
return JS_FALSE;
|
||||
}
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = length + 1;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->setArrayLength(length + 1);
|
||||
obj->incArrayCountBy(1);
|
||||
obj->dslots[length] = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -2453,7 +2452,7 @@ array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
jsuint index;
|
||||
JSBool hole;
|
||||
|
||||
index = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
index = obj->getArrayLength();
|
||||
if (index == 0) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
@ -2463,7 +2462,7 @@ array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
|
||||
return JS_FALSE;
|
||||
if (!hole && !DeleteArrayElement(cx, obj, index))
|
||||
return JS_FALSE;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
|
||||
obj->setArrayLength(index);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -2517,7 +2516,7 @@ array_shift(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (*vp == JSVAL_HOLE)
|
||||
*vp = JSVAL_VOID;
|
||||
else
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]--;
|
||||
obj->decArrayCountBy(1);
|
||||
memmove(obj->dslots, obj->dslots + 1, length * sizeof(jsval));
|
||||
obj->dslots[length] = JSVAL_HOLE;
|
||||
} else {
|
||||
@ -2526,7 +2525,7 @@ array_shift(JSContext *cx, uintN argc, jsval *vp)
|
||||
* with an explicitly set non-zero length when shift() is called on
|
||||
* it, but note fallthrough to reduce the length by one.
|
||||
*/
|
||||
JS_ASSERT(obj->fslots[JSSLOT_ARRAY_COUNT] == 0);
|
||||
JS_ASSERT(obj->getArrayCount() == 0);
|
||||
*vp = JSVAL_VOID;
|
||||
}
|
||||
} else {
|
||||
@ -2678,8 +2677,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
|
||||
!js_PrototypeHasIndexedProperties(cx, obj2) &&
|
||||
end <= js_DenseArrayCapacity(obj)) {
|
||||
if (!InitArrayObject(cx, obj2, count, obj->dslots + begin,
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] !=
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH])) {
|
||||
obj->getArrayCount() != obj->getArrayLength())) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
@ -2713,10 +2711,10 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
|
||||
jsval srcval = obj->dslots[last];
|
||||
jsval* dest = &obj->dslots[last + delta];
|
||||
if (*dest == JSVAL_HOLE && srcval != JSVAL_HOLE)
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->incArrayCountBy(1);
|
||||
*dest = srcval;
|
||||
}
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] += delta;
|
||||
obj->setArrayLength(obj->getArrayLength() + delta);
|
||||
} else {
|
||||
/* (uint) end could be 0, so we can't use a vanilla >= test. */
|
||||
while (last-- > end) {
|
||||
@ -2737,7 +2735,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
|
||||
jsval srcval = obj->dslots[last];
|
||||
jsval* dest = &obj->dslots[last - delta];
|
||||
if (*dest == JSVAL_HOLE && srcval != JSVAL_HOLE)
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
obj->incArrayCountBy(1);
|
||||
*dest = srcval;
|
||||
}
|
||||
} else {
|
||||
@ -2788,14 +2786,13 @@ array_concat(JSContext *cx, uintN argc, jsval *vp)
|
||||
* where length is <= capacity, nobj and aobj will have the same
|
||||
* capacity.
|
||||
*/
|
||||
length = aobj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
length = aobj->getArrayLength();
|
||||
jsuint capacity = js_DenseArrayCapacity(aobj);
|
||||
nobj = js_NewArrayObject(cx, JS_MIN(length, capacity), aobj->dslots,
|
||||
aobj->fslots[JSSLOT_ARRAY_COUNT] !=
|
||||
(jsval) length);
|
||||
aobj->getArrayCount() != length);
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
nobj->fslots[JSSLOT_ARRAY_LENGTH] = length;
|
||||
nobj->setArrayLength(length);
|
||||
*vp = OBJECT_TO_JSVAL(nobj);
|
||||
if (argc == 0)
|
||||
return JS_TRUE;
|
||||
@ -2909,8 +2906,7 @@ array_slice(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (obj->isDenseArray() && end <= js_DenseArrayCapacity(obj) &&
|
||||
!js_PrototypeHasIndexedProperties(cx, obj)) {
|
||||
nobj = js_NewArrayObject(cx, end - begin, obj->dslots + begin,
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] !=
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH]);
|
||||
obj->getArrayCount() != obj->getArrayLength());
|
||||
if (!nobj)
|
||||
return JS_FALSE;
|
||||
*vp = OBJECT_TO_JSVAL(nobj);
|
||||
@ -3357,9 +3353,6 @@ js_Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
return InitArrayObject(cx, obj, length, vector);
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
|
||||
|
||||
JSObject* JS_FASTCALL
|
||||
js_NewEmptyArray(JSContext* cx, JSObject* proto)
|
||||
{
|
||||
@ -3375,10 +3368,9 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
|
||||
obj->setProto(proto);
|
||||
obj->setParent(proto->getParent());
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
|
||||
for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
obj->setArrayLength(0);
|
||||
obj->setArrayCount(0);
|
||||
obj->voidArrayUnused();
|
||||
obj->dslots = NULL;
|
||||
return obj;
|
||||
}
|
||||
@ -3394,7 +3386,7 @@ js_NewEmptyArrayWithLength(JSContext* cx, JSObject* proto, int32 len)
|
||||
JSObject *obj = js_NewEmptyArray(cx, proto);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = len;
|
||||
obj->setArrayLength(len);
|
||||
return obj;
|
||||
}
|
||||
#ifdef JS_TRACER
|
||||
@ -3408,7 +3400,7 @@ js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len)
|
||||
JSObject* obj = js_NewEmptyArray(cx, proto);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = len;
|
||||
obj->setArrayLength(len);
|
||||
if (!ResizeSlots(cx, obj, 0, JS_MAX(len, ARRAY_CAPACITY_MIN)))
|
||||
return NULL;
|
||||
return obj;
|
||||
@ -3459,7 +3451,7 @@ js_NewSlowArrayObject(JSContext *cx)
|
||||
{
|
||||
JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL);
|
||||
if (obj)
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
obj->setArrayLength(0);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -3485,10 +3477,10 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
}
|
||||
fprintf(stderr, "%s: %s (len %lu", bytes,
|
||||
array->isDenseArray()) ? "dense" : "sparse",
|
||||
array->fslots[JSSLOT_ARRAY_LENGTH]);
|
||||
array->getArrayLength());
|
||||
if (array->isDenseArray()) {
|
||||
fprintf(stderr, ", count %lu, capacity %lu",
|
||||
array->fslots[JSSLOT_ARRAY_COUNT],
|
||||
array->getArrayCount(),
|
||||
js_DenseArrayCapacity(array));
|
||||
}
|
||||
fputs(")\n", stderr);
|
||||
@ -3507,7 +3499,7 @@ js_CoerceArrayToCanvasImageData(JSObject *obj, jsuint offset, jsuint count,
|
||||
if (!obj || !obj->isDenseArray())
|
||||
return JS_FALSE;
|
||||
|
||||
length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
length = obj->getArrayLength();
|
||||
if (length < offset + count)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -3572,7 +3564,7 @@ js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector)
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = capacity;
|
||||
obj->setArrayCount(capacity);
|
||||
*vector = obj->dslots;
|
||||
return obj;
|
||||
}
|
||||
|
@ -61,10 +61,16 @@ JSObject::isDenseArray() const
|
||||
return getClass() == &js_ArrayClass;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::isSlowArray() const
|
||||
{
|
||||
return getClass() == &js_SlowArrayClass;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::isArray() const
|
||||
{
|
||||
return isDenseArray() || getClass() == &js_SlowArrayClass;
|
||||
return isDenseArray() || isSlowArray();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -115,10 +121,6 @@ js_NewSlowArrayObject(JSContext *cx);
|
||||
extern JSBool
|
||||
js_MakeArraySlow(JSContext *cx, JSObject *obj);
|
||||
|
||||
#define JSSLOT_ARRAY_LENGTH JSSLOT_PRIVATE
|
||||
#define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1)
|
||||
#define JSSLOT_ARRAY_UNUSED (JSSLOT_ARRAY_COUNT + 1)
|
||||
|
||||
static JS_INLINE uint32
|
||||
js_DenseArrayCapacity(JSObject *obj)
|
||||
{
|
||||
|
@ -2071,7 +2071,7 @@ obj_keys(JSContext *cx, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
JS_ASSERT(len <= UINT32_MAX);
|
||||
aobj->fslots[JSSLOT_ARRAY_COUNT] = len;
|
||||
aobj->setArrayCount(len);
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -2513,7 +2513,7 @@ DefinePropertyArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc
|
||||
if (obj->isDenseArray() && !js_MakeArraySlow(cx, obj))
|
||||
return JS_FALSE;
|
||||
|
||||
jsuint oldLen = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
jsuint oldLen = obj->getArrayLength();
|
||||
|
||||
if (desc.id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
|
||||
/*
|
||||
@ -2541,7 +2541,7 @@ DefinePropertyArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc
|
||||
|
||||
if (index >= oldLen) {
|
||||
JS_ASSERT(index != UINT32_MAX);
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
|
||||
obj->setArrayLength(index + 1);
|
||||
}
|
||||
|
||||
*rval = true;
|
||||
@ -6937,8 +6937,7 @@ js_DumpObject(JSObject *obj)
|
||||
fprintf(stderr, "class %p %s\n", (void *)clasp, clasp->name);
|
||||
|
||||
if (obj->isDenseArray()) {
|
||||
slots = JS_MIN((jsuint) obj->fslots[JSSLOT_ARRAY_LENGTH],
|
||||
js_DenseArrayCapacity(obj));
|
||||
slots = JS_MIN(obj->getArrayLength(), js_DenseArrayCapacity(obj));
|
||||
fprintf(stderr, "elements\n");
|
||||
for (i = 0; i < slots; i++) {
|
||||
fprintf(stderr, " %3d: ", i);
|
||||
|
@ -248,6 +248,12 @@ const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
|
||||
* records the number of available slots.
|
||||
*/
|
||||
struct JSObject {
|
||||
/*
|
||||
* TraceRecorder must be a friend because it generates code that
|
||||
* manipulates JSObjects, which requires peeking under any encapsulation.
|
||||
*/
|
||||
friend class js::TraceRecorder;
|
||||
|
||||
JSObjectMap *map; /* property map, see jsscope.h */
|
||||
jsuword classword; /* JSClass ptr | bits, see above */
|
||||
jsval fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
|
||||
@ -378,6 +384,33 @@ struct JSObject {
|
||||
: JSVAL_VOID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Array-specific getters and setters (for both dense and slow arrays).
|
||||
*/
|
||||
|
||||
private:
|
||||
static const uint32 JSSLOT_ARRAY_LENGTH = JSSLOT_PRIVATE;
|
||||
static const uint32 JSSLOT_ARRAY_COUNT = JSSLOT_PRIVATE + 1;
|
||||
static const uint32 JSSLOT_ARRAY_UNUSED = JSSLOT_PRIVATE + 2;
|
||||
|
||||
// This must remain true; see comment in js_MakeArraySlow().
|
||||
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE);
|
||||
|
||||
public:
|
||||
inline uint32 getArrayLength() const;
|
||||
inline uint32 getArrayCount() const;
|
||||
|
||||
inline void setArrayLength(uint32 length);
|
||||
inline void setArrayCount(uint32 count);
|
||||
inline void voidDenseArrayCount();
|
||||
inline void incArrayCountBy(uint32 posDelta);
|
||||
inline void decArrayCountBy(uint32 negDelta);
|
||||
inline void voidArrayUnused();
|
||||
|
||||
/*
|
||||
* Back to generic stuff.
|
||||
*/
|
||||
|
||||
bool isCallable();
|
||||
|
||||
/* The map field is not initialized here and should be set separately. */
|
||||
@ -477,6 +510,7 @@ struct JSObject {
|
||||
inline bool isArguments() const;
|
||||
inline bool isArray() const;
|
||||
inline bool isDenseArray() const;
|
||||
inline bool isSlowArray() const;
|
||||
inline bool isFunction() const;
|
||||
inline bool isRegExp() const;
|
||||
inline bool isXML() const;
|
||||
|
@ -45,7 +45,8 @@
|
||||
#include "jsscope.h"
|
||||
|
||||
inline jsval
|
||||
JSObject::getSlotMT(JSContext *cx, uintN slot) {
|
||||
JSObject::getSlotMT(JSContext *cx, uintN slot)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* If thread-safe, define a getSlotMT() that bypasses, for a native
|
||||
@ -66,7 +67,8 @@ JSObject::getSlotMT(JSContext *cx, uintN slot) {
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value) {
|
||||
JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Thread-safe way to set a slot. */
|
||||
OBJ_CHECK_SLOT(this, slot);
|
||||
@ -79,6 +81,62 @@ JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
inline uint32
|
||||
JSObject::getArrayLength() const
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
return uint32(fslots[JSSLOT_ARRAY_LENGTH]);
|
||||
}
|
||||
|
||||
inline uint32
|
||||
JSObject::getArrayCount() const
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
return uint32(fslots[JSSLOT_ARRAY_COUNT]);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setArrayLength(uint32 length)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_LENGTH] = length;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setArrayCount(uint32 count)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = count;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::voidDenseArrayCount()
|
||||
{
|
||||
JS_ASSERT(isDenseArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::incArrayCountBy(uint32 posDelta)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] += posDelta;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::decArrayCountBy(uint32 negDelta)
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] -= negDelta;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::voidArrayUnused()
|
||||
{
|
||||
JS_ASSERT(isArray());
|
||||
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
|
||||
jsval privateSlotValue)
|
||||
|
@ -1523,12 +1523,7 @@ BEGIN_CASE(JSOP_LENGTH)
|
||||
} else if (!JSVAL_IS_PRIMITIVE(lval)) {
|
||||
obj = JSVAL_TO_OBJECT(lval);
|
||||
if (obj->isArray()) {
|
||||
/*
|
||||
* We know that the array is created with its 'length' private data
|
||||
* in a fixed slot at JSSLOT_ARRAY_LENGTH. See also JSOP_ARRAYPUSH,
|
||||
* far below.
|
||||
*/
|
||||
jsuint length = obj->fslots[JSSLOT_ARRAY_LENGTH];
|
||||
jsuint length = obj->getArrayLength();
|
||||
|
||||
if (length <= JSVAL_INT_MAX)
|
||||
regs.sp[-1] = INT_TO_JSVAL(length);
|
||||
@ -1876,7 +1871,7 @@ BEGIN_CASE(JSOP_GETELEM)
|
||||
if (obj->isDenseArray()) {
|
||||
jsuint idx = jsuint(JSVAL_TO_INT(rval));
|
||||
|
||||
if (idx < jsuint(obj->fslots[JSSLOT_ARRAY_LENGTH]) &&
|
||||
if (idx < obj->getArrayLength() &&
|
||||
idx < js_DenseArrayCapacity(obj)) {
|
||||
rval = obj->dslots[idx];
|
||||
if (rval != JSVAL_HOLE)
|
||||
@ -1948,9 +1943,9 @@ BEGIN_CASE(JSOP_SETELEM)
|
||||
if (obj->dslots[i] == JSVAL_HOLE) {
|
||||
if (js_PrototypeHasIndexedProperties(cx, obj))
|
||||
break;
|
||||
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT]++;
|
||||
if ((jsuint)i >= obj->getArrayLength())
|
||||
obj->setArrayLength(i + 1);
|
||||
obj->incArrayCountBy(1);
|
||||
}
|
||||
obj->dslots[i] = rval;
|
||||
goto end_setelem;
|
||||
|
@ -10448,7 +10448,7 @@ TraceRecorder::newArray(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval)
|
||||
}
|
||||
|
||||
if (argc > 0)
|
||||
stobj_set_fslot(arr_ins, JSSLOT_ARRAY_COUNT, INS_CONST(argc));
|
||||
stobj_set_fslot(arr_ins, JSObject::JSSLOT_ARRAY_COUNT, INS_CONST(argc));
|
||||
}
|
||||
|
||||
set(rval, arr_ins);
|
||||
@ -12584,10 +12584,10 @@ TraceRecorder::record_JSOP_APPLY()
|
||||
*/
|
||||
if (aobj->isDenseArray()) {
|
||||
guardDenseArray(aobj, aobj_ins, MISMATCH_EXIT);
|
||||
length = jsuint(aobj->fslots[JSSLOT_ARRAY_LENGTH]);
|
||||
length = aobj->getArrayLength();
|
||||
guard(true,
|
||||
lir->ins2i(LIR_eq,
|
||||
p2i(stobj_get_fslot(aobj_ins, JSSLOT_ARRAY_LENGTH)),
|
||||
p2i(stobj_get_fslot(aobj_ins, JSObject::JSSLOT_ARRAY_LENGTH)),
|
||||
length),
|
||||
BRANCH_EXIT);
|
||||
} else if (aobj->isArguments()) {
|
||||
@ -12957,7 +12957,7 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
|
||||
/* check that the index is within bounds */
|
||||
LIns* dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots), ACC_OTHER);
|
||||
jsuint capacity = js_DenseArrayCapacity(obj);
|
||||
bool within = (jsuint(idx) < jsuint(obj->fslots[JSSLOT_ARRAY_LENGTH]) && jsuint(idx) < capacity);
|
||||
bool within = (jsuint(idx) < obj->getArrayLength() && jsuint(idx) < capacity);
|
||||
if (!within) {
|
||||
/* If idx < 0, stay on trace (and read value as undefined, since this is a dense array). */
|
||||
LIns* br1 = NULL;
|
||||
@ -12973,7 +12973,7 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
|
||||
LIns* br2 = lir->insBranch(LIR_jf,
|
||||
lir->ins2(LIR_pult,
|
||||
pidx_ins,
|
||||
stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
|
||||
stobj_get_fslot(obj_ins, JSObject::JSSLOT_ARRAY_LENGTH)),
|
||||
NULL);
|
||||
|
||||
/* If dslots is NULL, stay on trace (and read value as undefined). */
|
||||
@ -13013,7 +13013,7 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
|
||||
|
||||
/* Guard array length */
|
||||
guard(true,
|
||||
lir->ins2(LIR_pult, pidx_ins, stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
|
||||
lir->ins2(LIR_pult, pidx_ins, stobj_get_fslot(obj_ins, JSObject::JSSLOT_ARRAY_LENGTH)),
|
||||
exit);
|
||||
|
||||
/* dslots must not be NULL */
|
||||
@ -15026,7 +15026,7 @@ TraceRecorder::record_JSOP_LENGTH()
|
||||
if (!guardClass(obj, obj_ins, &js_SlowArrayClass, snapshot(BRANCH_EXIT), ACC_OTHER))
|
||||
RETURN_STOP_A("can't trace length property access on non-array");
|
||||
}
|
||||
v_ins = lir->ins1(LIR_i2f, p2i(stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)));
|
||||
v_ins = lir->ins1(LIR_i2f, p2i(stobj_get_fslot(obj_ins, JSObject::JSSLOT_ARRAY_LENGTH)));
|
||||
} else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) {
|
||||
// Ensure array is a typed array and is the same type as what was written
|
||||
guardClass(obj, obj_ins, obj->getClass(), snapshot(BRANCH_EXIT), ACC_OTHER);
|
||||
@ -15066,7 +15066,7 @@ TraceRecorder::record_JSOP_NEWARRAY()
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
stobj_set_fslot(v_ins, JSSLOT_ARRAY_COUNT, INS_CONST(count));
|
||||
stobj_set_fslot(v_ins, JSObject::JSSLOT_ARRAY_COUNT, INS_CONST(count));
|
||||
|
||||
stack(-int(len), v_ins);
|
||||
return ARECORD_CONTINUE;
|
||||
|
@ -63,6 +63,8 @@
|
||||
#include "jsvector.h"
|
||||
#include "jstypedarray.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
@ -1014,7 +1016,7 @@ class TypedArrayTemplate
|
||||
NativeType *dest = static_cast<NativeType*>(data);
|
||||
|
||||
if (ar->isDenseArray() && js_DenseArrayCapacity(ar) >= len) {
|
||||
JS_ASSERT(ar->fslots[JSSLOT_ARRAY_LENGTH] == (jsval)len);
|
||||
JS_ASSERT(ar->getArrayLength() == len);
|
||||
|
||||
jsval *src = ar->dslots;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user