Merge from tracemonkey to jsdbg2.

This commit is contained in:
Jason Orendorff
2011-07-01 19:02:40 -05:00
2899 changed files with 57983 additions and 94820 deletions

View File

@@ -179,40 +179,6 @@ js_StringIsIndex(JSLinearString *str, jsuint *indexp)
return false;
}
static bool
ValueToLength(JSContext *cx, Value* vp, jsuint* plength)
{
if (vp->isInt32()) {
int32_t i = vp->toInt32();
if (i < 0)
goto error;
*plength = (jsuint)(i);
return true;
}
jsdouble d;
if (!ValueToNumber(cx, *vp, &d))
goto error;
if (JSDOUBLE_IS_NaN(d))
goto error;
jsuint length;
length = (jsuint) d;
if (d != (jsdouble) length)
goto error;
*plength = length;
return true;
error:
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_ARRAY_LENGTH);
return false;
}
JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{
@@ -582,23 +548,6 @@ js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length)
return obj->setProperty(cx, id, &v, false);
}
JSBool
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{
JSErrorReporter older = JS_SetErrorReporter(cx, NULL);
AutoValueRooter tvr(cx);
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
JSBool ok = obj->getProperty(cx, id, tvr.addr());
JS_SetErrorReporter(cx, older);
if (!ok)
return false;
if (!ValueToLength(cx, tvr.addr(), lengthp))
return false;
return true;
}
/*
* Since SpiderMonkey supports cross-class prototype-based delegation, we have
* to be careful about the length getter and setter being called on an object
@@ -621,20 +570,26 @@ array_length_getter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
static JSBool
array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
{
jsuint newlen, oldlen, gap, index;
Value junk;
if (!obj->isArray()) {
jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
return obj->defineProperty(cx, lengthId, *vp, NULL, NULL, JSPROP_ENUMERATE);
}
if (!ValueToLength(cx, vp, &newlen))
uint32 newlen;
if (!ValueToECMAUint32(cx, *vp, &newlen))
return false;
oldlen = obj->getArrayLength();
jsdouble d;
if (!ValueToNumber(cx, *vp, &d))
return false;
if (d != newlen) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
uint32 oldlen = obj->getArrayLength();
if (oldlen == newlen)
return true;
@@ -684,12 +639,14 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
/* Protect iter against GC under JSObject::deleteProperty. */
AutoObjectRooter tvr(cx, iter);
gap = oldlen - newlen;
jsuint gap = oldlen - newlen;
for (;;) {
if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id))
return false;
if (JSID_IS_VOID(id))
break;
jsuint index;
Value junk;
if (js_IdIsIndex(id, &index) && index - newlen < gap &&
!obj->deleteProperty(cx, id, &junk, false)) {
return false;
@@ -2130,8 +2087,10 @@ array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
}
JS_ALWAYS_INLINE JSBool
ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
NewbornArrayPushImpl(JSContext *cx, JSObject *obj, const Value &v)
{
JS_ASSERT(!v.isMagic());
uint32 length = obj->getArrayLength();
if (obj->isSlowArray()) {
/* This can happen in one evil case. See bug 630377. */
@@ -2143,45 +2102,34 @@ ArrayCompPushImpl(JSContext *cx, JSObject *obj, const Value &v)
JS_ASSERT(obj->isDenseArray());
JS_ASSERT(length <= obj->getDenseArrayCapacity());
if (length == obj->getDenseArrayCapacity()) {
if (length > JS_ARGS_LENGTH_MAX) {
JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
JSMSG_ARRAY_INIT_TOO_BIG);
return false;
}
if (length == obj->getDenseArrayCapacity() && !obj->ensureSlots(cx, length + 1))
return false;
/*
* An array comprehension cannot add holes to the array. So we can use
* ensureSlots instead of ensureDenseArrayElements.
*/
if (!obj->ensureSlots(cx, length + 1))
return false;
}
obj->setArrayLength(length + 1);
obj->setDenseArrayElement(length, v);
return true;
}
JSBool
js_ArrayCompPush(JSContext *cx, JSObject *obj, const Value &vp)
js_NewbornArrayPush(JSContext *cx, JSObject *obj, const Value &vp)
{
return ArrayCompPushImpl(cx, obj, vp);
return NewbornArrayPushImpl(cx, obj, vp);
}
#ifdef JS_TRACER
JSBool JS_FASTCALL
js_ArrayCompPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
js_NewbornArrayPush_tn(JSContext *cx, JSObject *obj, ValueArgType v)
{
TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
if (!ArrayCompPushImpl(cx, obj, ValueArgToConstRef(v))) {
if (!NewbornArrayPushImpl(cx, obj, ValueArgToConstRef(v))) {
SetBuiltinError(tm);
return JS_FALSE;
}
return WasBuiltinSuccessful(tm);
}
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_ArrayCompPush_tn, CONTEXT, OBJECT,
JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_NewbornArrayPush_tn, CONTEXT, OBJECT,
VALUE, 0, nanojit::ACCSET_STORE_ANY)
#endif
@@ -2573,8 +2521,6 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
length = 0;
}
AutoValueRooter tvr(cx);
/* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
for (uintN i = 0; i <= argc; i++) {
if (!JS_CHECK_OPERATION_LIMIT(cx))
@@ -2582,29 +2528,22 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
const Value &v = p[i];
if (v.isObject()) {
aobj = &v.toObject();
if (aobj->isArray() ||
(aobj->isWrapper() && aobj->unwrap()->isArray())) {
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
if (!aobj->getProperty(cx, id, tvr.addr()))
return false;
if (aobj->isArray() || (aobj->isWrapper() && aobj->unwrap()->isArray())) {
jsuint alength;
if (!ValueToLength(cx, tvr.addr(), &alength))
if (!js_GetLengthProperty(cx, aobj, &alength))
return false;
for (jsuint slot = 0; slot < alength; slot++) {
for (uint32 slot = 0; slot < alength; slot++) {
JSBool hole;
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!GetElement(cx, aobj, slot, &hole, tvr.addr())) {
Value tmp;
if (!JS_CHECK_OPERATION_LIMIT(cx) || !GetElement(cx, aobj, slot, &hole, &tmp))
return false;
}
/*
* Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
* properties.
*/
if (!hole &&
!SetArrayElement(cx, nobj, length+slot, tvr.value())) {
if (!hole && !SetArrayElement(cx, nobj, length + slot, tmp))
return false;
}
}
length += alength;
continue;
@@ -2832,7 +2771,8 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
newlen = 0;
newarr = NULL;
#endif
jsint start = 0, end = length, step = 1;
jsuint start = 0, end = length;
jsint step = 1;
switch (mode) {
case REDUCE_RIGHT:
@@ -2901,7 +2841,7 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
Value objv = ObjectValue(*obj);
AutoValueRooter tvr(cx);
for (jsint i = start; i != end; i += step) {
for (jsuint i = start; i != end; i += step) {
JSBool hole;
ok = JS_CHECK_OPERATION_LIMIT(cx) &&
GetElement(cx, obj, i, &hole, tvr.addr());
@@ -3071,29 +3011,42 @@ static JSFunctionSpec array_static_methods[] = {
JS_FS_END
};
/* ES5 15.4.2 */
JSBool
js_Array(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
if (argc == 0) {
obj = NewDenseEmptyArray(cx);
} else if (argc > 1) {
obj = NewDenseCopiedArray(cx, argc, vp + 2);
} else if (!vp[2].isNumber()) {
obj = NewDenseCopiedArray(cx, 1, vp + 2);
} else {
jsuint length;
if (!ValueToLength(cx, vp + 2, &length))
return JS_FALSE;
obj = NewDenseUnallocatedArray(cx, length);
if (argc != 1 || !vp[2].isNumber()) {
JSObject *obj = (argc == 0)
? NewDenseEmptyArray(cx)
: NewDenseCopiedArray(cx, argc, vp + 2);
if (!obj)
return false;
vp->setObject(*obj);
return true;
}
if (!obj)
return JS_FALSE;
vp->setObject(*obj);
uint32 length;
if (vp[2].isInt32()) {
int32_t i = vp[2].toInt32();
if (i < 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
length = uint32(i);
} else {
jsdouble d = vp[2].toDouble();
length = js_DoubleToECMAUint32(d);
if (d != jsdouble(length)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
}
return JS_TRUE;
JSObject *obj = NewDenseUnallocatedArray(cx, length);
if (!obj)
return false;
vp->setObject(*obj);
return true;
}
JSObject *
@@ -3230,73 +3183,3 @@ js_ArrayInfo(JSContext *cx, uintN argc, jsval *vp)
return true;
}
#endif
JS_FRIEND_API(JSBool)
js_IsDensePrimitiveArray(JSObject *obj)
{
if (!obj || !obj->isDenseArray())
return JS_FALSE;
jsuint capacity = obj->getDenseArrayCapacity();
for (jsuint i = 0; i < capacity; i++) {
if (obj->getDenseArrayElement(i).isObject())
return JS_FALSE;
}
return JS_TRUE;
}
JS_FRIEND_API(JSBool)
js_CloneDensePrimitiveArray(JSContext *cx, JSObject *obj, JSObject **clone)
{
JS_ASSERT(obj);
if (!obj->isDenseArray()) {
/*
* This wasn't a dense array. Return JS_TRUE but a NULL clone to signal
* that no exception was encountered.
*/
*clone = NULL;
return JS_TRUE;
}
jsuint length = obj->getArrayLength();
/*
* Must use the minimum of original array's length and capacity, to handle
* |a = [1,2,3]; a.length = 10000| "dense" cases efficiently. In the normal
* case where length is <= capacity, the clone and original array will have
* the same capacity.
*/
jsuint jsvalCount = JS_MIN(obj->getDenseArrayCapacity(), length);
AutoValueVector vector(cx);
if (!vector.reserve(jsvalCount))
return JS_FALSE;
for (jsuint i = 0; i < jsvalCount; i++) {
const Value &val = obj->getDenseArrayElement(i);
if (val.isString()) {
// Strings must be made immutable before being copied to a clone.
if (!val.toString()->ensureFixed(cx))
return JS_FALSE;
} else if (val.isObject()) {
/*
* This wasn't an array of primitives. Return JS_TRUE but a null
* clone to signal that no exception was encountered.
*/
*clone = NULL;
return JS_TRUE;
}
vector.infallibleAppend(val);
}
*clone = NewDenseCopiedArray(cx, jsvalCount, vector.begin());
if (!*clone)
return JS_FALSE;
/* The length will be set to the JS_MIN, above, but length might be larger. */
(*clone)->setArrayLength(length);
return JS_TRUE;
}