This commit is contained in:
Robert Sayre 2010-05-03 12:32:11 -04:00
Родитель c1d5a1b578 e46c240d6f
Коммит 004ca3887a
55 изменённых файлов: 1076 добавлений и 988 удалений

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

@ -715,9 +715,9 @@ _isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook)
JSTrapStatus
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure)
jsval closure)
{
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure));
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(closure);
JSD_ExecutionHookProc hook;
void* hookData;
JSDContext* jsdc;
@ -799,8 +799,8 @@ jsd_SetExecutionHook(JSDContext* jsdc,
jsdhook->callerdata = callerdata;
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, jsd_TrapHandler,
(void*) PRIVATE_TO_JSVAL(jsdhook)) )
(jsbytecode*)pc, jsd_TrapHandler,
PRIVATE_TO_JSVAL(jsdhook)) )
{
free(jsdhook);
JSD_UNLOCK();

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

@ -62,9 +62,11 @@ BEGIN_TEST(testContexts_bug561444)
if (!cx)
return;
JS_BeginRequest(cx);
jsvalRoot v(cx);
if (!JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__, v.addr()))
return;
{
jsvalRoot v(cx);
if (!JS_EvaluateScript(cx, d->obj, d->code, strlen(d->code), __FILE__, __LINE__, v.addr()))
return;
}
JS_DestroyContext(cx);
d->ok = true;
}

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

@ -5,10 +5,11 @@ static int emptyTrapCallCount = 0;
static JSTrapStatus
EmptyTrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure)
jsval closure)
{
JS_GC(cx);
++emptyTrapCallCount;
if (JSVAL_IS_STRING(closure))
++emptyTrapCallCount;
return JSTRAP_CONTINUE;
}
@ -49,8 +50,8 @@ BEGIN_TEST(testTrap_gc)
static const char trapClosureText[] = "some trap closure";
JSString *trapClosure = JS_NewStringCopyZ(cx, trapClosureText);
CHECK(trapClosure);
JS_SetTrap(cx, script, line2, EmptyTrapHandler, trapClosure);
JS_SetTrap(cx, script, line6, EmptyTrapHandler, trapClosure);
JS_SetTrap(cx, script, line2, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
JS_SetTrap(cx, script, line6, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
JS_GC(cx);

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

@ -5507,39 +5507,23 @@ JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
CHECK_REQUEST(cx);
/* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics;
res->clearRoots();
res->input = input;
res->multiline = multiline;
cx->runtime->gcPoke = JS_TRUE;
}
JS_PUBLIC_API(void)
JS_ClearRegExpStatics(JSContext *cx)
{
JSRegExpStatics *res;
/* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics;
res->input = NULL;
res->multiline = JS_FALSE;
res->parenCount = 0;
res->lastMatch = res->lastParen = js_EmptySubString;
res->leftContext = res->rightContext = js_EmptySubString;
if (res->moreParens) {
cx->free(res->moreParens);
res->moreParens = NULL;
}
cx->runtime->gcPoke = JS_TRUE;
cx->regExpStatics.clear();
}
JS_PUBLIC_API(void)
JS_ClearRegExpRoots(JSContext *cx)
{
JSRegExpStatics *res;
/* No locking required, cx is thread-private and input must be live. */
res = &cx->regExpStatics;
res->input = NULL;
cx->runtime->gcPoke = JS_TRUE;
cx->regExpStatics.clearRoots();
}
/* TODO: compile, execute, get/set other statics... */

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

@ -112,7 +112,7 @@ JSVAL_IS_OBJECT(jsval v)
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_INT(jsval v)
{
return v & JSVAL_INT;
return (JSBool)(v & JSVAL_INT);
}
static JS_ALWAYS_INLINE JSBool

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

@ -47,12 +47,17 @@
* &js_ArrayClass, and can then directly manipulate the slots for efficiency.
*
* We track these pieces of metadata for arrays in dense mode:
* - the array's length property as a uint32, accessible with
* {get,set}ArrayLength().
* - the number of indices that are filled (non-holes), accessible with
* {get,set}ArrayCount().
* - the number of element slots (capacity), gettable with
* - The array's length property as a uint32, accessible with
* getArrayLength(), setDenseArrayLength().
* - The number of indices that are filled (non-holes), accessible with
* {get,set}DenseArrayCount().
* - The number of element slots (capacity), gettable with
* getDenseArrayCapacity().
* - The minimum of length and capacity (minLenCap). There are no explicit
* setters, it's updated automatically by setDenseArrayLength() and
* setDenseArrayCapacity(). There are also no explicit getters, the only
* user is TraceRecorder which can access it directly because it's a
* friend.
*
* In dense mode, holes in the array are represented by JSVAL_HOLE. The final
* slot in fslots is unused.
@ -125,7 +130,7 @@ INDEX_TOO_BIG(jsuint index)
#define INDEX_TOO_SPARSE(array, index) \
(INDEX_TOO_BIG(index) || \
((index) > array->getDenseArrayCapacity() && (index) >= MIN_SPARSE_INDEX && \
(index) > ((array)->getArrayCount() + 1) * 4))
(index) > ((array)->getDenseArrayCount() + 1) * 4))
JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
@ -339,7 +344,7 @@ JSObject::resizeDenseArrayElements(JSContext *cx, uint32 oldcap, uint32 newcap,
return false;
dslots = newslots + 1;
dslots[-1] = newcap;
setDenseArrayCapacity(newcap);
if (initializeAllSlots) {
for (uint32 i = oldcap; i < newcap; i++)
@ -497,9 +502,9 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, jsval v)
if (!obj->ensureDenseArrayElements(cx, idx + 1))
return JS_FALSE;
if (idx >= obj->getArrayLength())
obj->setArrayLength(idx + 1);
obj->setDenseArrayLength(idx + 1);
if (obj->getDenseArrayElement(idx) == JSVAL_HOLE)
obj->incArrayCountBy(1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(idx, v);
return JS_TRUE;
}
@ -527,7 +532,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index)
jsuint idx = jsuint(index);
if (!INDEX_TOO_SPARSE(obj, idx) && idx < obj->getDenseArrayCapacity()) {
if (obj->getDenseArrayElement(idx) != JSVAL_HOLE)
obj->decArrayCountBy(1);
obj->decDenseArrayCountBy(1);
obj->setDenseArrayElement(idx, JSVAL_HOLE);
return JS_TRUE;
}
@ -647,7 +652,10 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return false;
if (oldlen < newlen) {
obj->setArrayLength(newlen);
if (obj->isDenseArray())
obj->setDenseArrayLength(newlen);
else
obj->setSlowArrayLength(newlen);
return true;
}
@ -656,12 +664,14 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
jsuint capacity = obj->getDenseArrayCapacity();
if (capacity > newlen && !obj->resizeDenseArrayElements(cx, capacity, newlen))
return false;
obj->setDenseArrayLength(newlen);
} else if (oldlen - newlen < (1 << 24)) {
do {
--oldlen;
if (!JS_CHECK_OPERATION_LIMIT(cx) || !DeleteArrayElement(cx, obj, oldlen))
return false;
} while (oldlen != newlen);
obj->setSlowArrayLength(newlen);
} else {
/*
* We are going to remove a lot of indexes in a presumably sparse
@ -688,9 +698,9 @@ array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return false;
}
}
obj->setSlowArrayLength(newlen);
}
obj->setArrayLength(newlen);
return true;
}
@ -812,7 +822,7 @@ slowarray_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
length = obj->getArrayLength();
if (index >= length)
obj->setArrayLength(index + 1);
obj->setSlowArrayLength(index + 1);
return JS_TRUE;
}
@ -867,9 +877,9 @@ array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
return JS_FALSE;
if (i >= obj->getArrayLength())
obj->setArrayLength(i + 1);
obj->setDenseArrayLength(i + 1);
if (obj->getDenseArrayElement(i) == JSVAL_HOLE)
obj->incArrayCountBy(1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(i, *vp);
return JS_TRUE;
}
@ -927,8 +937,8 @@ dense_grow(JSContext* cx, JSObject* obj, jsint i, jsval v)
return JS_FALSE;
if (u >= obj->getArrayLength())
obj->setArrayLength(u + 1);
obj->incArrayCountBy(1);
obj->setDenseArrayLength(u + 1);
obj->incDenseArrayCountBy(1);
}
obj->setDenseArrayElement(u, v);
@ -1038,7 +1048,7 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
if (js_IdIsIndex(id, &i) && i < obj->getDenseArrayCapacity() &&
obj->getDenseArrayElement(i) != JSVAL_HOLE) {
obj->decArrayCountBy(1);
obj->decDenseArrayCountBy(1);
obj->setDenseArrayElement(i, JSVAL_HOLE);
}
@ -1119,7 +1129,7 @@ array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
JS_ASSERT(obj->isDenseArray());
capacity = obj->getDenseArrayCapacity();
if (idp)
*idp = INT_TO_JSVAL(obj->getArrayCount());
*idp = INT_TO_JSVAL(obj->getDenseArrayCount());
ii = NULL;
for (i = 0; i != capacity; ++i) {
if (obj->getDenseArrayElement(i) == JSVAL_HOLE) {
@ -1263,7 +1273,8 @@ JSClass js_ArrayClass = {
"Array",
JSCLASS_HAS_RESERVED_SLOTS(2) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
JSCLASS_NEW_ENUMERATE,
JSCLASS_NEW_ENUMERATE |
JSCLASS_CONSTRUCT_PROTOTYPE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize,
array_getObjectOps, NULL, NULL, NULL,
@ -1286,7 +1297,7 @@ JSClass js_SlowArrayClass = {
JSBool
js_MakeArraySlow(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->getClass() == &js_ArrayClass);
JS_ASSERT(obj->isDenseArray());
/*
* Create a native scope. All slow arrays other than Array.prototype get
@ -1337,13 +1348,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 because it is the private slot (this is
* statically asserted within JSObject) where the implementation can store
* an arbitrary value.
* Render our formerly-reserved non-private properties 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_ASSERT(js_SlowArrayClass.flags & JSCLASS_HAS_PRIVATE);
obj->voidDenseArrayCount();
obj->voidDenseOnlyArraySlots();
/* Make sure we preserve any flags borrowing bits in classword. */
obj->classword ^= (jsuword) &js_ArrayClass;
@ -1657,7 +1668,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva
return JS_FALSE;
if (newlen > obj->getArrayLength())
obj->setArrayLength(newlen);
obj->setDenseArrayLength(newlen);
JS_ASSERT(count < size_t(-1) / sizeof(jsval));
if (targetType == TargetElementsMayContainValues) {
@ -1666,19 +1677,19 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, jsva
if (obj->getDenseArrayElement(start + i) != JSVAL_HOLE)
valueCount++;
}
JS_ASSERT(obj->getArrayCount() >= valueCount);
obj->decArrayCountBy(valueCount);
JS_ASSERT(obj->getDenseArrayCount() >= valueCount);
obj->decDenseArrayCountBy(valueCount);
}
memcpy(obj->getDenseArrayElements() + start, vector, sizeof(jsval) * count);
if (vectorType == SourceVectorAllValues) {
obj->incArrayCountBy(count);
obj->incDenseArrayCountBy(count);
} else {
jsuint valueCount = 0;
for (jsuint i = 0; i < count; i++) {
if (obj->getDenseArrayElement(start + i) != JSVAL_HOLE)
valueCount++;
}
obj->incArrayCountBy(valueCount);
obj->incDenseArrayCountBy(valueCount);
}
JS_ASSERT_IF(count != 0, obj->getDenseArrayElement(newlen - 1) != JSVAL_HOLE);
return JS_TRUE;
@ -1725,9 +1736,9 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const jsval *vector
{
JS_ASSERT(obj->isArray());
obj->setArrayLength(length);
if (vector) {
JS_ASSERT(obj->isDenseArray());
obj->setDenseArrayLength(length);
if (!obj->ensureDenseArrayElements(cx, length))
return JS_FALSE;
@ -1741,37 +1752,18 @@ InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, const jsval *vector
obj->setDenseArrayElement(i, vector[i]);
}
}
obj->setArrayCount(count);
obj->setDenseArrayCount(count);
} else {
obj->setArrayCount(0);
if (obj->isDenseArray()) {
obj->setDenseArrayLength(length);
obj->setDenseArrayCount(0);
} else {
obj->setSlowArrayLength(length);
}
}
return JS_TRUE;
}
#ifdef JS_TRACER
static JSString* FASTCALL
Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
{
AutoValueRooter tvr(cx);
if (!array_toString_sub(cx, obj, JS_FALSE, str, tvr.addr())) {
SetBuiltinError(cx);
return NULL;
}
return JSVAL_TO_STRING(tvr.value());
}
static JSString* FASTCALL
Array_p_toString(JSContext* cx, JSObject* obj)
{
AutoValueRooter tvr(cx);
if (!array_toString_sub(cx, obj, JS_FALSE, NULL, tvr.addr())) {
SetBuiltinError(cx);
return NULL;
}
return JSVAL_TO_STRING(tvr.value());
}
#endif
/*
* Perl-inspired join, reverse, and sort.
*/
@ -2357,10 +2349,10 @@ array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
if (!obj->ensureDenseArrayElements(cx, length + 1))
return JS_FALSE;
obj->setArrayLength(length + 1);
obj->setDenseArrayLength(length + 1);
JS_ASSERT(obj->getDenseArrayElement(length) == JSVAL_HOLE);
obj->incArrayCountBy(1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(length, v);
return IndexToValue(cx, obj->getArrayLength(), rval);
}
@ -2382,29 +2374,14 @@ js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v)
if (!obj->ensureDenseArrayElements(cx, length + 1))
return JS_FALSE;
}
obj->setArrayLength(length + 1);
obj->incArrayCountBy(1);
obj->setDenseArrayLength(length + 1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(length, v);
return JS_TRUE;
}
JS_DEFINE_CALLINFO_3(extern, BOOL, js_ArrayCompPush, CONTEXT, OBJECT, JSVAL, 0,
nanojit::ACC_STORE_ANY)
#ifdef JS_TRACER
static jsval FASTCALL
Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
{
AutoValueRooter tvr(cx, v);
if (obj->isDenseArray()
? array_push1_dense(cx, obj, v, tvr.addr())
: array_push_slowly(cx, obj, 1, tvr.addr(), tvr.addr())) {
return tvr.value();
}
SetBuiltinError(cx);
return JSVAL_VOID;
}
#endif
static JSBool
array_push(JSContext *cx, uintN argc, jsval *vp)
{
@ -2458,25 +2435,10 @@ array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
return JS_FALSE;
if (!hole && !DeleteArrayElement(cx, obj, index))
return JS_FALSE;
obj->setArrayLength(index);
obj->setDenseArrayLength(index);
return JS_TRUE;
}
#ifdef JS_TRACER
static jsval FASTCALL
Array_p_pop(JSContext* cx, JSObject* obj)
{
AutoValueRooter tvr(cx);
if (obj->isDenseArray()
? array_pop_dense(cx, obj, tvr.addr())
: array_pop_slowly(cx, obj, tvr.addr())) {
return tvr.value();
}
SetBuiltinError(cx);
return JSVAL_VOID;
}
#endif
static JSBool
array_pop(JSContext *cx, uintN argc, jsval *vp)
{
@ -2512,11 +2474,11 @@ array_shift(JSContext *cx, uintN argc, jsval *vp)
if (*vp == JSVAL_HOLE)
*vp = JSVAL_VOID;
else
obj->decArrayCountBy(1);
obj->decDenseArrayCountBy(1);
jsval *elems = obj->getDenseArrayElements();
memmove(elems, elems + 1, length * sizeof(jsval));
obj->setDenseArrayElement(length, JSVAL_HOLE);
obj->setArrayLength(length);
obj->setDenseArrayLength(length);
return JS_TRUE;
}
@ -2666,7 +2628,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
!js_PrototypeHasIndexedProperties(cx, obj2) &&
end <= obj->getDenseArrayCapacity()) {
if (!InitArrayObject(cx, obj2, count, obj->getDenseArrayElements() + begin,
obj->getArrayCount() != obj->getArrayLength())) {
obj->getDenseArrayCount() != obj->getArrayLength())) {
return JS_FALSE;
}
} else {
@ -2700,10 +2662,10 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
jsval srcval = obj->getDenseArrayElement(last);
jsval dest = obj->getDenseArrayElement(last + delta);
if (dest == JSVAL_HOLE && srcval != JSVAL_HOLE)
obj->incArrayCountBy(1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(last + delta, srcval);
}
obj->setArrayLength(obj->getArrayLength() + delta);
obj->setDenseArrayLength(obj->getArrayLength() + delta);
} else {
/* (uint) end could be 0, so we can't use a vanilla >= test. */
while (last-- > end) {
@ -2724,7 +2686,7 @@ array_splice(JSContext *cx, uintN argc, jsval *vp)
jsval srcval = obj->getDenseArrayElement(last);
jsval dest = obj->getDenseArrayElement(last - delta);
if (dest == JSVAL_HOLE && srcval != JSVAL_HOLE)
obj->incArrayCountBy(1);
obj->incDenseArrayCountBy(1);
obj->setDenseArrayElement(last - delta, srcval);
}
} else {
@ -2778,10 +2740,10 @@ array_concat(JSContext *cx, uintN argc, jsval *vp)
length = aobj->getArrayLength();
jsuint capacity = aobj->getDenseArrayCapacity();
nobj = js_NewArrayObject(cx, JS_MIN(length, capacity), aobj->getDenseArrayElements(),
aobj->getArrayCount() != length);
aobj->getDenseArrayCount() != length);
if (!nobj)
return JS_FALSE;
nobj->setArrayLength(length);
nobj->setDenseArrayLength(length);
*vp = OBJECT_TO_JSVAL(nobj);
if (argc == 0)
return JS_TRUE;
@ -2893,7 +2855,7 @@ array_slice(JSContext *cx, uintN argc, jsval *vp)
if (obj->isDenseArray() && end <= obj->getDenseArrayCapacity() &&
!js_PrototypeHasIndexedProperties(cx, obj)) {
nobj = js_NewArrayObject(cx, end - begin, obj->getDenseArrayElements() + begin,
obj->getArrayCount() != obj->getArrayLength());
obj->getDenseArrayCount() != obj->getArrayLength());
if (!nobj)
return JS_FALSE;
*vp = OBJECT_TO_JSVAL(nobj);
@ -3257,28 +3219,19 @@ static JSPropertySpec array_props[] = {
{0,0,0,0,0}
};
JS_DEFINE_TRCINFO_1(array_toString,
(2, (static, STRING_FAIL, Array_p_toString, CONTEXT, THIS, 0, nanojit::ACC_STORE_ANY)))
JS_DEFINE_TRCINFO_1(array_join,
(3, (static, STRING_FAIL, Array_p_join, CONTEXT, THIS, STRING, 0, nanojit::ACC_STORE_ANY)))
JS_DEFINE_TRCINFO_1(array_push,
(3, (static, JSVAL_FAIL, Array_p_push1, CONTEXT, THIS, JSVAL, 0, nanojit::ACC_STORE_ANY)))
JS_DEFINE_TRCINFO_1(array_pop,
(2, (static, JSVAL_FAIL, Array_p_pop, CONTEXT, THIS, 0, nanojit::ACC_STORE_ANY)))
static JSFunctionSpec array_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, array_toSource, 0,0),
#endif
JS_TN(js_toString_str, array_toString, 0,0, &array_toString_trcinfo),
JS_FN(js_toString_str, array_toString, 0,0),
JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
/* Perl-ish methods. */
JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, &array_join_trcinfo),
JS_FN("join", array_join, 1,JSFUN_GENERIC_NATIVE),
JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, &array_push_trcinfo),
JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, &array_pop_trcinfo),
JS_FN("push", array_push, 1,JSFUN_GENERIC_NATIVE),
JS_FN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE),
JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
@ -3352,8 +3305,8 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
obj->init(&js_ArrayClass, proto, proto->getParent(), JSVAL_NULL);
obj->setArrayLength(0);
obj->setArrayCount(0);
obj->setDenseArrayLength(0);
obj->setDenseArrayCount(0);
return obj;
}
#ifdef JS_TRACER
@ -3368,7 +3321,7 @@ js_NewEmptyArrayWithLength(JSContext* cx, JSObject* proto, int32 len)
JSObject *obj = js_NewEmptyArray(cx, proto);
if (!obj)
return NULL;
obj->setArrayLength(len);
obj->setDenseArrayLength(len);
return obj;
}
#ifdef JS_TRACER
@ -3382,7 +3335,7 @@ js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len)
JSObject* obj = js_NewEmptyArray(cx, proto);
if (!obj)
return NULL;
obj->setArrayLength(len);
obj->setDenseArrayLength(len);
if (!obj->resizeDenseArrayElements(cx, 0, JS_MAX(len, ARRAY_CAPACITY_MIN)))
return NULL;
return obj;
@ -3433,7 +3386,7 @@ js_NewSlowArrayObject(JSContext *cx)
{
JSObject *obj = NewObject(cx, &js_SlowArrayClass, NULL, NULL);
if (obj)
obj->setArrayLength(0);
obj->setSlowArrayLength(0);
return obj;
}
@ -3462,7 +3415,7 @@ js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
array->getArrayLength());
if (array->isDenseArray()) {
fprintf(stderr, ", count %lu, capacity %lu",
array->getArrayCount(),
array->getDenseArrayCount(),
array->getDenseArrayCapacity());
}
fputs(")\n", stderr);
@ -3546,7 +3499,7 @@ js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector)
if (!obj)
return NULL;
obj->setArrayCount(capacity);
obj->setDenseArrayCount(capacity);
*vector = obj->getDenseArrayElements();
return obj;
}
@ -3625,8 +3578,8 @@ js_CloneDensePrimitiveArray(JSContext *cx, JSObject *obj, JSObject **clone)
AutoObjectRooter cloneRoot(cx, *clone);
memcpy(buffer, vector.buffer(), jsvalCount * sizeof (jsval));
(*clone)->setArrayLength(length);
(*clone)->setArrayCount(length - holeCount);
(*clone)->setDenseArrayLength(length);
(*clone)->setDenseArrayCount(length - holeCount);
return JS_TRUE;
}

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

@ -102,10 +102,6 @@ js_imod(int32 a, int32 b)
}
JS_DEFINE_CALLINFO_2(extern, INT32, js_imod, INT32, INT32, 1, ACC_NONE)
/* The following boxing/unboxing primitives we can't emit inline because
they either interact with the GC and depend on Spidermonkey's 32-bit
integer representation. */
jsval FASTCALL
js_BoxDouble(JSContext* cx, jsdouble d)
{
@ -115,7 +111,7 @@ js_BoxDouble(JSContext* cx, jsdouble d)
JS_ASSERT(JS_ON_TRACE(cx));
jsval v; /* not rooted but ok here because we know GC won't run */
if (!js_NewDoubleInRootedValue(cx, d, &v))
return JSVAL_ERROR_COOKIE;
return JSVAL_NULL;
return v;
}
JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, ACC_NONE)
@ -129,7 +125,7 @@ js_BoxInt32(JSContext* cx, int32 i)
jsval v; /* not rooted but ok here because we know GC won't run */
jsdouble d = (jsdouble)i;
if (!js_NewDoubleInRootedValue(cx, d, &v))
return JSVAL_ERROR_COOKIE;
return JSVAL_NULL;
return v;
}
JS_DEFINE_CALLINFO_2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, ACC_NONE)

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

@ -48,7 +48,7 @@
#undef THIS
#endif
enum JSTNErrType { INFALLIBLE, FAIL_STATUS, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_COOKIE };
enum JSTNErrType { INFALLIBLE, FAIL_STATUS, FAIL_NULL, FAIL_NEG, FAIL_VOID };
enum { JSTN_ERRTYPE_MASK = 0x07, JSTN_UNBOX_AFTER = 0x08, JSTN_MORE = 0x10,
JSTN_CONSTRUCTOR = 0x20 };
@ -101,14 +101,6 @@ struct JSNativeTraceInfo {
JSSpecializedNative *specializations;
};
/*
* We use a magic boxed pointer value to represent error conditions that
* trigger a side exit. The address is so low that it should never be actually
* in use. If it is, a performance regression occurs, not an actual runtime
* error.
*/
#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((JSObject*)0x10)
/* Macros used by JS_DEFINE_CALLINFOn. */
#ifdef DEBUG
#define _JS_CI_NAME(op) ,#op
@ -160,7 +152,6 @@ struct ClosureVarInfo;
* INT32_RETRY: any negative value
* STRING_RETRY: NULL
* OBJECT_RETRY_NULL: NULL
* JSVAL_RETRY: JSVAL_ERROR_COOKIE
*
* _RETRY function calls are faster than _FAIL calls. Each _RETRY call
* saves two writes to cx->bailExit and a read from state->builtinStatus.
@ -194,7 +185,6 @@ struct ClosureVarInfo;
#define _JS_CTYPE_PC _JS_CTYPE(jsbytecode *, _JS_PTR,"P", "", INFALLIBLE)
#define _JS_CTYPE_JSVALPTR _JS_CTYPE(jsval *, _JS_PTR,"P", "", INFALLIBLE)
#define _JS_CTYPE_JSVAL _JS_JSVAL_CTYPE( _JS_PTR, "","v", INFALLIBLE)
#define _JS_CTYPE_JSVAL_RETRY _JS_JSVAL_CTYPE( _JS_PTR, --, --, FAIL_COOKIE)
#define _JS_CTYPE_JSVAL_FAIL _JS_JSVAL_CTYPE( _JS_PTR, --, --, FAIL_STATUS)
#define _JS_CTYPE_JSID _JS_CTYPE(jsid, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE)

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

@ -180,6 +180,8 @@ JSThreadData::purge(JSContext *cx)
js_DestroyScriptsToGC(cx, this);
js_PurgeCachedNativeEnumerators(cx, this);
dtoaCache.s = NULL;
}
void

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

@ -556,6 +556,17 @@ struct JSThreadData {
/* State used by dtoa.c. */
DtoaState *dtoaState;
/*
* State used to cache some double-to-string conversions. A stupid
* optimization aimed directly at v8-splay.js, which stupidly converts
* many doubles multiple times in a row.
*/
struct {
jsdouble d;
jsint base;
JSString *s; // if s==NULL, d and base are not valid
} dtoaCache;
/*
* Cache of reusable JSNativeEnumerators mapped by shape identifiers (as
* stored in scope->shape). This cache is nulled by the GC and protected
@ -854,7 +865,7 @@ struct JSRuntime {
#ifdef JS_TRACER
/* True if any debug hooks not supported by the JIT are enabled. */
bool debuggerInhibitsJIT() const {
return (globalDebugHooks.interruptHandler ||
return (globalDebugHooks.interruptHook ||
globalDebugHooks.callHook ||
globalDebugHooks.objectHook);
}
@ -1178,9 +1189,27 @@ namespace js {
class AutoGCRooter;
}
struct JSRegExpStatics {
JSContext *cx;
JSString *input; /* input string to match (perl $_, GC root) */
JSBool multiline; /* whether input contains newlines (perl $*) */
JSSubString lastMatch; /* last string matched (perl $&) */
JSSubString lastParen; /* last paren matched (perl $+) */
JSSubString leftContext; /* input to left of last match (perl $`) */
JSSubString rightContext; /* input to right of last match (perl $') */
js::Vector<JSSubString> parens; /* last set of parens matched (perl $1, $2) */
JSRegExpStatics(JSContext *cx) : cx(cx), parens(cx) {}
bool copy(const JSRegExpStatics& other);
void clearRoots();
void clear();
};
struct JSContext
{
explicit JSContext(JSRuntime *rt) : runtime(rt), busyArrays(this) {}
explicit JSContext(JSRuntime *rt) :
runtime(rt), regExpStatics(this), busyArrays(this) {}
/*
* If this flag is set, we were asked to call back the operation callback
@ -1266,7 +1295,7 @@ struct JSContext
/* Storage to root recently allocated GC things and script result. */
JSWeakRoots weakRoots;
/* Regular expression class statics (XXX not shared globally). */
/* Regular expression class statics. */
JSRegExpStatics regExpStatics;
/* State for object and array toSource conversion. */

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

@ -2199,26 +2199,6 @@ date_toString(JSContext *cx, uintN argc, jsval *vp)
return date_format(cx, utctime, FORMATSPEC_FULL, vp);
}
#ifdef JS_TRACER
static jsval FASTCALL
date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
{
JS_ASSERT(JS_InstanceOf(cx, obj, &js_DateClass, NULL));
jsdouble t = *JSVAL_TO_DOUBLE(obj->getDateUTCTime());
JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
jsval v;
if (js_EqualStrings(str, number_str)) {
if (!js_NewNumberInRootedValue(cx, t, &v))
return JSVAL_ERROR_COOKIE;
} else {
if (!date_format(cx, t, FORMATSPEC_FULL, &v))
return JSVAL_ERROR_COOKIE;
}
return v;
}
#endif
static JSBool
date_valueOf(JSContext *cx, uintN argc, jsval *vp)
{
@ -2254,9 +2234,6 @@ static JSFunctionSpec date_static_methods[] = {
JS_FS_END
};
JS_DEFINE_TRCINFO_1(date_valueOf,
(3, (static, JSVAL_RETRY, date_valueOf_tn, CONTEXT, THIS, STRING, 0, nanojit::ACC_STORE_ANY)))
static JSFunctionSpec date_methods[] = {
JS_FN("getTime", date_getTime, 0,0),
JS_FN("getTimezoneOffset", date_getTimezoneOffset, 0,0),
@ -2302,12 +2279,11 @@ static JSFunctionSpec date_methods[] = {
JS_FN("toTimeString", date_toTimeString, 0,0),
JS_FN("toISOString", date_toISOString, 0,0),
JS_FN(js_toJSON_str, date_toISOString, 0,0),
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, date_toSource, 0,0),
#endif
JS_FN(js_toString_str, date_toString, 0,0),
JS_TN(js_valueOf_str, date_valueOf, 0,0, &date_valueOf_trcinfo),
JS_FN(js_valueOf_str, date_valueOf, 0,0),
JS_FS_END
};

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

@ -77,7 +77,7 @@ typedef struct JSTrap {
jsbytecode *pc;
JSOp op;
JSTrapHandler handler;
void *closure;
jsval closure;
} JSTrap;
#define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
@ -142,7 +142,7 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script)
JS_PUBLIC_API(JSBool)
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler handler, void *closure)
JSTrapHandler handler, jsval closure)
{
JSTrap *junk, *trap, *twin;
JSRuntime *rt;
@ -168,7 +168,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
trap = (JSTrap *) cx->malloc(sizeof *trap);
if (!trap)
return JS_FALSE;
trap->closure = NULL;
trap->closure = JSVAL_NULL;
DBG_LOCK(rt);
twin = (rt->debuggerMutations != sample)
? FindTrap(rt, script, pc)
@ -220,7 +220,7 @@ DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
JS_PUBLIC_API(void)
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, void **closurep)
JSTrapHandler *handlerp, jsval *closurep)
{
JSTrap *trap;
@ -229,7 +229,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
if (handlerp)
*handlerp = trap ? trap->handler : NULL;
if (closurep)
*closurep = trap ? trap->closure : NULL;
*closurep = trap ? trap->closure : JSVAL_NULL;
if (trap)
DestroyTrapAndUnlock(cx, trap);
else
@ -295,10 +295,8 @@ js_MarkTraps(JSTracer *trc)
for (JSTrap *trap = (JSTrap *) rt->trapList.next;
&trap->links != &rt->trapList;
trap = (JSTrap *) trap->links.next) {
if (trap->closure) {
JS_SET_TRACING_NAME(trc, "trap->closure");
js_CallValueTracerIfGCThing(trc, (jsval) trap->closure);
}
JS_SET_TRACING_NAME(trc, "trap->closure");
js_CallValueTracerIfGCThing(trc, trap->closure);
}
}
@ -375,15 +373,15 @@ LeaveTraceRT(JSRuntime *rt)
#endif
JS_PUBLIC_API(JSBool)
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook hook, void *closure)
{
#ifdef JS_TRACER
{
AutoLockGC lock(rt);
bool wasInhibited = rt->debuggerInhibitsJIT();
#endif
rt->globalDebugHooks.interruptHandler = handler;
rt->globalDebugHooks.interruptHandlerData = closure;
rt->globalDebugHooks.interruptHook = hook;
rt->globalDebugHooks.interruptHookData = closure;
#ifdef JS_TRACER
JITInhibitingHookChange(rt, wasInhibited);
}
@ -393,18 +391,18 @@ JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
}
JS_PUBLIC_API(JSBool)
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *hoop, void **closurep)
{
#ifdef JS_TRACER
AutoLockGC lock(rt);
bool wasInhibited = rt->debuggerInhibitsJIT();
#endif
if (handlerp)
*handlerp = rt->globalDebugHooks.interruptHandler;
if (hoop)
*hoop = rt->globalDebugHooks.interruptHook;
if (closurep)
*closurep = rt->globalDebugHooks.interruptHandlerData;
rt->globalDebugHooks.interruptHandler = 0;
rt->globalDebugHooks.interruptHandlerData = 0;
*closurep = rt->globalDebugHooks.interruptHookData;
rt->globalDebugHooks.interruptHook = 0;
rt->globalDebugHooks.interruptHookData = 0;
#ifdef JS_TRACER
JITInhibitingHookChange(rt, wasInhibited);
#endif
@ -506,10 +504,8 @@ js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
wp = (JSWatchPoint *)wp->links.next) {
if (wp->object == obj) {
wp->sprop->trace(trc);
if (wp->sprop->hasSetterValue() && wp->setter) {
JS_CALL_OBJECT_TRACER(trc, js_CastAsObject(wp->setter),
"wp->setter");
}
if (wp->sprop->hasSetterValue() && wp->setter)
JS_CALL_OBJECT_TRACER(trc, CastAsObject(wp->setter), "wp->setter");
JS_SET_TRACING_NAME(trc, "wp->closure");
js_CallValueTracerIfGCThing(trc, OBJECT_TO_JSVAL(wp->closure));
}
@ -735,7 +731,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
ok = !wp->setter ||
(sprop->hasSetterValue()
? js_InternalCall(cx, obj,
js_CastAsObjectJSVal(wp->setter),
CastAsObjectJSVal(wp->setter),
1, vp, vp)
: wp->setter(cx, obj, userid, vp));
if (injectFrame) {
@ -774,7 +770,7 @@ IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop)
{
if (sprop->hasSetterValue()) {
JSObject *funobj = sprop->setterObject();
if (!funobj->isFunction())
if (!funobj || !funobj->isFunction())
return false;
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
@ -803,10 +799,10 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
}
wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
setter ? js_CastAsObject(setter)->getParent() : NULL, atom);
setter ? CastAsObject(setter)->getParent() : NULL, atom);
if (!wrapper)
return NULL;
return js_CastAsPropertyOp(FUN_OBJECT(wrapper));
return CastAsPropertyOp(FUN_OBJECT(wrapper));
}
JS_PUBLIC_API(JSBool)
@ -1563,7 +1559,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
/************************************************************************/
JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
{
rt->globalDebugHooks.debuggerHandler = handler;
rt->globalDebugHooks.debuggerHandlerData = closure;
@ -1625,7 +1621,7 @@ JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
}
JS_PUBLIC_API(JSBool)
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
{
rt->globalDebugHooks.throwHook = hook;
rt->globalDebugHooks.throwHookData = closure;

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

@ -57,16 +57,17 @@ JS_BEGIN_EXTERN_C
extern jsbytecode *
js_UntrapScriptCode(JSContext *cx, JSScript *script);
/* The closure argument will be marked. */
extern JS_PUBLIC_API(JSBool)
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler handler, void *closure);
JSTrapHandler handler, jsval closure);
extern JS_PUBLIC_API(JSOp)
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(void)
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, void **closurep);
JSTrapHandler *handlerp, jsval *closurep);
extern JS_PUBLIC_API(void)
JS_ClearScriptTraps(JSContext *cx, JSScript *script);
@ -78,10 +79,10 @@ extern JS_PUBLIC_API(JSTrapStatus)
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
extern JS_PUBLIC_API(JSBool)
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure);
extern JS_PUBLIC_API(JSBool)
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
/************************************************************************/
@ -337,7 +338,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
/************************************************************************/
extern JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler hook, void *closure);
extern JS_PUBLIC_API(JSBool)
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
@ -352,7 +353,7 @@ extern JS_PUBLIC_API(JSBool)
JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure);
extern JS_PUBLIC_API(JSBool)
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure);
JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure);
extern JS_PUBLIC_API(JSBool)
JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure);

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

@ -52,7 +52,7 @@
static char dempty[] = "<null>";
static char *
jsdtrace_fun_classname(JSFunction *fun)
jsdtrace_fun_classname(const JSFunction *fun)
{
return (fun &&
!FUN_INTERPRETED(fun) &&
@ -71,7 +71,7 @@ jsdtrace_filename(JSStackFrame *fp)
}
static int
jsdtrace_fun_linenumber(JSContext *cx, JSFunction *fun)
jsdtrace_fun_linenumber(JSContext *cx, const JSFunction *fun)
{
if (fun && FUN_INTERPRETED(fun))
return (int) JS_GetScriptBaseLineNumber(cx, FUN_SCRIPT(fun));
@ -109,7 +109,7 @@ jsdtrace_frame_linenumber(JSContext *cx, JSStackFrame *fp)
* provide raw (unmasked) jsvals should type info be useful from D scripts.
*/
static void *
jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
jsdtrace_jsvaltovoid(JSContext *cx, const jsval argval)
{
JSType type = TYPEOF(cx, argval);
@ -136,7 +136,7 @@ jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
}
static char *
jsdtrace_fun_name(JSContext *cx, JSFunction *fun)
jsdtrace_fun_name(JSContext *cx, const JSFunction *fun)
{
JSAtom *atom;
char *name;
@ -166,7 +166,7 @@ jsdtrace_fun_name(JSContext *cx, JSFunction *fun)
* a number of usually unused lines of code would cause.
*/
void
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, const JSFunction *fun)
{
JAVASCRIPT_FUNCTION_ENTRY(
jsdtrace_filename(fp),
@ -190,7 +190,8 @@ jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
}
void
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsuint argc, jsval *argv)
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
jsuint argc, jsval *argv)
{
JAVASCRIPT_FUNCTION_ARGS(
jsdtrace_filename(fp),

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

@ -33,7 +33,9 @@
*
* ***** END LICENSE BLOCK ***** */
#ifdef INCLUDE_MOZILLA_DTRACE
#include "javascript-trace.h"
#endif
#include "jspubtd.h"
#include "jsprvtd.h"
@ -43,39 +45,126 @@
JS_BEGIN_EXTERN_C
extern void
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, const JSFunction *fun);
extern void
jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
JSFunction *fun);
const JSFunction *fun);
extern void
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsuint argc, jsval *argv);
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
jsuint argc, jsval *argv);
extern void
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval *rval);
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
jsval rval);
extern void
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, const JSFunction *fun);
extern void
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp);
jsdtrace_object_create_start(JSStackFrame *fp, const JSClass *clasp);
extern void
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp);
jsdtrace_object_create_done(JSStackFrame *fp, const JSClass *clasp);
extern void
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj);
jsdtrace_object_create(JSContext *cx, const JSClass *clasp, const JSObject *obj);
extern void
jsdtrace_object_finalize(JSObject *obj);
jsdtrace_object_finalize(const JSObject *obj);
extern void
jsdtrace_execute_start(JSScript *script);
jsdtrace_execute_start(const JSScript *script);
extern void
jsdtrace_execute_done(JSScript *script);
jsdtrace_execute_done(const JSScript *script);
JS_END_EXTERN_C
namespace js {
class DTrace {
public:
/*
* If |lval| is provided to the enter/exit methods, it is tested to see if
* it is a function as a predicate to the dtrace event emission.
*/
static void enterJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval = NULL);
static void exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
jsval rval, jsval *lval = NULL);
static void finalizeObject(const JSObject *obj);
class ExecutionScope {
const JSScript *script;
void startExecution();
void endExecution();
public:
explicit ExecutionScope(const JSScript *script) : script(script) { startExecution(); }
~ExecutionScope() { endExecution(); }
};
};
inline void
DTrace::enterJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
JSStackFrame *dfp, jsuint argc, jsval *argv, jsval *lval)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, fp, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, fp, dfp, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun, argc, argv);
}
#endif
}
inline void
DTrace::exitJSFun(JSContext *cx, JSStackFrame *fp, const JSFunction *fun,
jsval rval, jsval *lval)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (!lval || VALUE_IS_FUNCTION(cx, *lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fun, rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fun);
}
#endif
}
inline void
DTrace::finalizeObject(const JSObject *obj)
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
jsdtrace_object_finalize(obj);
#endif
}
inline void
DTrace::ExecutionScope::startExecution()
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_EXECUTE_START_ENABLED())
jsdtrace_execute_start(script);
#endif
}
inline void
DTrace::ExecutionScope::endExecution()
{
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
jsdtrace_execute_done(script);
#endif
}
} /* namespace js */
#endif /* _JSDTRACE_H */

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

@ -96,7 +96,8 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser,
spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
arrayCompDepth(0),
emitLevel(0)
emitLevel(0),
constMap(parser->context)
{
flags = TCF_COMPILING;
memset(&prolog, 0, sizeof prolog);
@ -107,6 +108,11 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser,
memset(&upvarMap, 0, sizeof upvarMap);
}
bool JSCodeGenerator::init()
{
return constMap.init();
}
JSCodeGenerator::~JSCodeGenerator()
{
JS_ARENA_RELEASE(codePool, codeMark);
@ -1544,7 +1550,6 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
jsint ival;
JSAtom *valueAtom;
jsval v;
JSAtomListElement *ale;
/* XXX just do numbers for now */
if (pn->pn_type == TOK_NUMBER) {
@ -1562,10 +1567,8 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
return JS_FALSE;
v = ATOM_KEY(valueAtom);
}
ale = cg->constList.add(cg->parser, atom);
if (!ale)
if (!cg->constMap.put(atom, v))
return JS_FALSE;
ALE_SET_VALUE(ale, v);
}
return JS_TRUE;
}
@ -1626,7 +1629,6 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
{
JSBool ok;
JSStmtInfo *stmt;
JSAtomListElement *ale;
JSObject *obj, *objbox;
JSProperty *prop;
uintN attrs;
@ -1644,10 +1646,9 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
if (stmt)
return JS_TRUE;
ale = cg->constList.lookup(atom);
if (ale) {
JS_ASSERT(ALE_VALUE(ale) != JSVAL_HOLE);
*vp = ALE_VALUE(ale);
if (JSCodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) {
JS_ASSERT(p->value != JSVAL_HOLE);
*vp = p->value;
return JS_TRUE;
}
@ -4397,6 +4398,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
new (cg2space) JSCodeGenerator(cg->parser,
cg->codePool, cg->notePool,
pn->pn_pos.begin.lineno);
if (!cg2->init())
return JS_FALSE;
cg2->flags = pn->pn_funbox->tcflags | TCF_IN_FUNCTION;
#if JS_HAS_SHARP_VARS
if (cg2->flags & TCF_HAS_SHARPS) {
@ -6018,25 +6023,32 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return JS_FALSE;
}
/* Emit remainder as a single JSOP_CONCATN. */
for (index = 0; pn2; pn2 = pn2->pn_next, index++) {
if (!pn2)
break;
/*
* Having seen a string literal, we know statically that the rest
* of the additions are string concatenation, so we emit them as a
* single concatn. First, do string conversion on the result of the
* preceding zero or more additions so that any side effects of
* string conversion occur before the next operand begins.
*/
if (pn2 == pn->pn_head) {
index = 0;
} else {
if (!js_Emit1(cx, cg, JSOP_OBJTOSTR))
return JS_FALSE;
index = 1;
}
for (; pn2; pn2 = pn2->pn_next, index++) {
if (!js_EmitTree(cx, cg, pn2))
return JS_FALSE;
if (!pn2->isLiteral() &&
js_Emit1(cx, cg, JSOP_OBJTOSTR) < 0) {
if (!pn2->isLiteral() && js_Emit1(cx, cg, JSOP_OBJTOSTR) < 0)
return JS_FALSE;
}
}
if (index != 0) {
EMIT_UINT16_IMM_OP(JSOP_CONCATN, index);
/* If we had a prefix, we need to be added to it now. */
if (pn->pn_head->pn_type != TOK_STRING &&
js_Emit1(cx, cg, JSOP_ADD) < 0) {
return JS_FALSE;
}
}
EMIT_UINT16_IMM_OP(JSOP_CONCATN, index);
break;
}
case TOK_BITOR:

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

@ -313,6 +313,15 @@ struct JSTreeContext { /* tree context for semantic checks */
*/
#define TCF_FUN_MODULE_PATTERN 0x200000
/*
* Flag to prevent a non-escaping function from being optimized into a null
* closure (i.e., a closure that needs only its global object for free variable
* resolution, thanks to JSOP_{GET,CALL}UPVAR), because this function contains
* a closure that needs one or more scope objects surrounding it (i.e., Call
* object for a heavyweight outer function). See bug 560234.
*/
#define TCF_FUN_ENTRAINS_SCOPES 0x400000
/*
* Flags to check for return; vs. return expr; in a function.
*/
@ -455,7 +464,9 @@ struct JSCodeGenerator : public JSTreeContext
uintN arrayCompDepth; /* stack depth of array in comprehension */
uintN emitLevel; /* js_EmitTree recursion level */
JSAtomList constList; /* compile time constants */
typedef js::HashMap<JSAtom *, jsval> ConstMap;
ConstMap constMap; /* compile time constants */
JSCGObjectList objectList; /* list of emitted objects */
JSCGObjectList regexpList; /* list of emitted regexp that will be
@ -473,6 +484,8 @@ struct JSCodeGenerator : public JSTreeContext
JSArenaPool *codePool, JSArenaPool *notePool,
uintN lineno);
bool init();
/*
* Release cg->codePool, cg->notePool, and parser->context->tempPool to
* marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own

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

@ -137,7 +137,7 @@ js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
JSObject *argsobj = JSVAL_TO_OBJECT(fp->argsobj);
if (arg < fp->argc) {
if (argsobj) {
jsval v = GetArgsSlot(argsobj, arg);
jsval v = argsobj->getArgsElement(arg);
if (v == JSVAL_HOLE)
return argsobj->getProperty(cx, id, vp);
}
@ -197,9 +197,9 @@ PutArguments(JSContext *cx, JSObject *argsobj, jsval *args)
{
uint32 argc = argsobj->getArgsLength();
for (uint32 i = 0; i != argc; ++i) {
jsval v = argsobj->dslots[i];
jsval v = argsobj->getArgsElement(i);
if (v != JSVAL_HOLE)
argsobj->dslots[i] = args[i];
argsobj->setArgsElement(i, args[i]);
}
}
@ -301,7 +301,7 @@ args_delProperty(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
if (JSVAL_IS_INT(idval)) {
uintN arg = uintN(JSVAL_TO_INT(idval));
if (arg < obj->getArgsLength())
SetArgsSlot(obj, arg, JSVAL_HOLE);
obj->setArgsElement(arg, JSVAL_HOLE);
} else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
obj->setArgsLengthOverridden();
} else if (idval == ATOM_KEY(cx->runtime->atomState.calleeAtom)) {
@ -508,7 +508,7 @@ ArgGetter(JSContext *cx, JSObject *obj, jsval idval, jsval *vp)
if (fp) {
*vp = fp->argv[arg];
} else {
jsval v = GetArgsSlot(obj, arg);
jsval v = obj->getArgsElement(arg);
if (v != JSVAL_HOLE)
*vp = v;
}
@ -595,7 +595,7 @@ args_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
jsid id = 0;
if (JSVAL_IS_INT(idval)) {
uint32 arg = uint32(JSVAL_TO_INT(idval));
if (arg < obj->getArgsLength() && GetArgsSlot(obj, arg) != JSVAL_HOLE)
if (arg < obj->getArgsLength() && obj->getArgsElement(arg) != JSVAL_HOLE)
id = INT_JSVAL_TO_JSID(idval);
} else if (idval == ATOM_KEY(cx->runtime->atomState.lengthAtom)) {
if (!obj->isArgsLengthOverridden())
@ -2040,19 +2040,19 @@ js_fun_apply(JSContext *cx, uintN argc, jsval *vp)
/*
* Two cases, two loops: note how in the case of an active stack frame
* backing aobj, even though we copy from fp->argv, we still must check
* aobj->dslots[i] for a hole, to handle a delete on the corresponding
* arguments element. See args_delProperty.
* aobj->getArgsElement(i) for a hole, to handle a delete on the
* corresponding arguments element. See args_delProperty.
*/
JSStackFrame *fp = (JSStackFrame *) aobj->getPrivate();
if (fp) {
memcpy(sp, fp->argv, argc * sizeof(jsval));
for (i = 0; i < argc; i++) {
if (aobj->dslots[i] == JSVAL_HOLE) // suppress deleted element
if (aobj->getArgsElement(i) == JSVAL_HOLE) // suppress deleted element
sp[i] = JSVAL_VOID;
}
} else {
memcpy(sp, aobj->dslots, argc * sizeof(jsval));
for (i = 0; i < argc; i++) {
sp[i] = aobj->getArgsElement(i);
if (sp[i] == JSVAL_HOLE)
sp[i] = JSVAL_VOID;
}

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

@ -429,22 +429,6 @@ const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(24) - 1;
JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
JS_STATIC_ASSERT(jsval((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
namespace js {
inline jsval
GetArgsSlot(JSObject *argsobj, uint32 arg)
{
return argsobj->dslots[arg];
}
inline void
SetArgsSlot(JSObject *argsobj, uint32 arg, jsval v)
{
argsobj->dslots[arg] = v;
}
} /* namespace js */
extern JSBool
js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp);

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

@ -84,10 +84,7 @@
#include "jsxml.h"
#endif
#ifdef INCLUDE_MOZILLA_DTRACE
#include "jsdtracef.h"
#endif
#include "jscntxtinlines.h"
#include "jsobjinlines.h"
@ -2520,10 +2517,7 @@ FinalizeObject(JSContext *cx, JSObject *obj, unsigned thingKind)
if (clasp->finalize)
clasp->finalize(cx, obj);
#ifdef INCLUDE_MOZILLA_DTRACE
if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
jsdtrace_object_finalize(obj);
#endif
DTrace::finalizeObject(obj);
if (JS_LIKELY(obj->isNative())) {
JSScope *scope = obj->scope();
@ -2881,7 +2875,7 @@ SweepDoubles(JSRuntime *rt)
namespace js {
void
JS_FRIEND_API(void)
BackgroundSweepTask::replenishAndFreeLater(void *ptr)
{
JS_ASSERT(freeCursor == freeCursorEnd);
@ -3411,7 +3405,7 @@ FireGCEnd(JSContext *cx, JSGCInvocationKind gckind)
* interlock mechanism here.
*/
if (gckind != GC_SET_SLOT_REQUEST && callback) {
Conditionally<AutoUnlockGC> unlockIf(gckind & GC_LOCK_HELD, rt);
Conditionally<AutoUnlockGC> unlockIf(!!(gckind & GC_LOCK_HELD), rt);
(void) callback(cx, JSGC_END);

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

@ -383,7 +383,8 @@ class BackgroundSweepTask : public JSBackgroundTask {
void **freeCursor;
void **freeCursorEnd;
void replenishAndFreeLater(void *ptr);
JS_FRIEND_API(void)
replenishAndFreeLater(void *ptr);
static void freeElementsAndArray(void **array, void **end) {
JS_ASSERT(array <= end);

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

@ -81,10 +81,7 @@
#include "jsscopeinlines.h"
#include "jsscriptinlines.h"
#include "jsstrinlines.h"
#ifdef INCLUDE_MOZILLA_DTRACE
#include "jsdtracef.h"
#endif
#if JS_HAS_XML_SUPPORT
#include "jsxml.h"
@ -814,15 +811,7 @@ js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
if (hook)
hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function entry, non-inlines */
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, &frame, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, &frame, frame.down, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, &frame, fun, frame.argc, frame.argv);
#endif
DTrace::enterJSFun(cx, &frame, fun, frame.down, frame.argc, frame.argv);
/* Call the function, either a native method or an interpreted script. */
if (native) {
@ -842,13 +831,7 @@ js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
ok = js_Interpret(cx);
}
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function return, non-inlines */
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, &frame, fun, &frame.rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, &frame, fun);
#endif
DTrace::exitJSFun(cx, &frame, fun, frame.rval);
out:
if (hookData) {
@ -948,20 +931,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
LeaveTrace(cx);
#ifdef INCLUDE_MOZILLA_DTRACE
struct JSDNotifyGuard {
JSScript *script;
JSDNotifyGuard(JSScript *s) : script(s) {
if (JAVASCRIPT_EXECUTE_START_ENABLED())
jsdtrace_execute_start(script);
}
~JSDNotifyGuard() {
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
jsdtrace_execute_done(script);
}
} jsdNotifyGuard(script);
#endif
DTrace::ExecutionScope executionScope(script);
JSInterpreterHook hook = cx->debugHooks->executeHook;
void *hookData = NULL;
@ -2549,7 +2519,7 @@ js_Interpret(JSContext *cx)
# define CHECK_INTERRUPT_HANDLER() \
JS_BEGIN_MACRO \
if (cx->debugHooks->interruptHandler) \
if (cx->debugHooks->interruptHook) \
ENABLE_INTERRUPTS(); \
JS_END_MACRO
@ -2709,7 +2679,7 @@ js_Interpret(JSContext *cx)
/* This is an error, not a catchable exception, quit the frame ASAP. */
ok = JS_FALSE;
} else {
JSTrapHandler handler;
JSThrowHook handler;
JSTryNote *tn, *tnlimit;
uint32 offset;

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

@ -885,12 +885,18 @@ js_NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base)
return JSString::unitString(jschar('a' + i - 10));
}
}
JSThreadData *data = JS_THREAD_DATA(cx);
if (data->dtoaCache.s && data->dtoaCache.base == base && data->dtoaCache.d == d)
return data->dtoaCache.s;
numStr = NumberToCString(cx, d, base, buf, sizeof buf);
if (!numStr)
return NULL;
s = JS_NewStringCopyZ(cx, numStr);
if (!(numStr >= buf && numStr < buf + sizeof buf))
js_free(numStr);
data->dtoaCache.base = base;
data->dtoaCache.d = d;
data->dtoaCache.s = s;
return s;
}

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

@ -93,10 +93,7 @@
#include "jsxdrapi.h"
#endif
#ifdef INCLUDE_MOZILLA_DTRACE
#include "jsdtracef.h"
#endif
#include "jsatominlines.h"
#include "jsobjinlines.h"
#include "jsscriptinlines.h"
@ -1012,14 +1009,6 @@ obj_valueOf(JSContext *cx, uintN argc, jsval *vp)
return !JSVAL_IS_NULL(*vp);
}
#ifdef JS_TRACER
static jsval FASTCALL
Object_p_valueOf(JSContext* cx, JSObject* obj, JSString *hint)
{
return OBJECT_TO_JSVAL(obj);
}
#endif
/*
* Check if CSP allows new Function() or eval() to run in the current
* principals.
@ -1633,26 +1622,6 @@ js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
return true;
}
#ifdef JS_TRACER
static JSBool FASTCALL
Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
{
jsid id;
JSObject *pobj;
JSProperty *prop;
if (!js_ValueToStringId(cx, STRING_TO_JSVAL(str), &id) ||
!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &pobj, &prop)) {
SetBuiltinError(cx);
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
}
if (prop)
pobj->dropProperty(cx, prop);
return !!prop;
}
#endif
/* Proposed ECMA 15.2.4.6. */
static JSBool
obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
@ -1681,23 +1650,6 @@ obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
return obj && js_PropertyIsEnumerable(cx, obj, id, vp);
}
#ifdef JS_TRACER
static JSBool FASTCALL
Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
{
jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
jsval v;
if (!js_PropertyIsEnumerable(cx, obj, id, &v)) {
SetBuiltinError(cx);
return JSVAL_TO_BOOLEAN(JSVAL_VOID);
}
JS_ASSERT(JSVAL_IS_BOOLEAN(v));
return JSVAL_TO_BOOLEAN(v);
}
#endif
JSBool
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
@ -1776,7 +1728,7 @@ js_obj_defineGetter(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
*vp = JSVAL_VOID;
return obj->defineProperty(cx, id, JSVAL_VOID,
js_CastAsPropertyOp(JSVAL_TO_OBJECT(fval)), JS_PropertyStub,
CastAsPropertyOp(JSVAL_TO_OBJECT(fval)), JS_PropertyStub,
JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED);
}
@ -1809,7 +1761,7 @@ js_obj_defineSetter(JSContext *cx, uintN argc, jsval *vp)
return JS_FALSE;
*vp = JSVAL_VOID;
return obj->defineProperty(cx, id, JSVAL_VOID,
JS_PropertyStub, js_CastAsPropertyOp(JSVAL_TO_OBJECT(fval)),
JS_PropertyStub, CastAsPropertyOp(JSVAL_TO_OBJECT(fval)),
JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED);
}
@ -2020,7 +1972,7 @@ obj_keys(JSContext *cx, uintN argc, jsval *vp)
}
JS_ASSERT(len <= UINT32_MAX);
aobj->setArrayCount(len);
aobj->setDenseArrayCount(len);
return JS_TRUE;
}
@ -2182,8 +2134,8 @@ Reject(JSContext *cx, JSObject *obj, JSProperty *prop, uintN errorNumber, bool t
}
static JSBool
DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc,
bool throwError, bool *rval)
DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc,
bool throwError, bool *rval)
{
/* 8.12.9 step 1. */
JSProperty *current;
@ -2221,9 +2173,7 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
return JS_FALSE;
return js_DefineProperty(cx, obj, desc.id, JSVAL_VOID,
desc.getterObject() ? desc.getter() : JS_PropertyStub,
desc.setterObject() ? desc.setter() : JS_PropertyStub,
desc.attrs);
desc.getter(), desc.setter(), desc.attrs);
}
/* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
@ -2247,13 +2197,15 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
if (desc.hasGet &&
!js_SameValue(desc.getterValue(),
sprop->hasGetterValue() ? sprop->getterValue() : JSVAL_VOID, cx)) {
sprop->hasGetterValue() ? sprop->getterValue() : JSVAL_VOID,
cx)) {
break;
}
if (desc.hasSet &&
!js_SameValue(desc.setterValue(),
sprop->hasSetterValue() ? sprop->setterValue() : JSVAL_VOID, cx)) {
sprop->hasSetterValue() ? sprop->setterValue() : JSVAL_VOID,
cx)) {
break;
}
} else {
@ -2350,8 +2302,9 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_UNCONFIGURABLE_PROP,
throwError, desc.id, rval);
}
} else if (desc.isDataDescriptor() && sprop->isDataDescriptor()) {
} else if (desc.isDataDescriptor()) {
/* 8.12.9 step 10. */
JS_ASSERT(sprop->isDataDescriptor());
if (!sprop->configurable() && !sprop->writable()) {
if ((desc.hasWritable && desc.writable()) ||
(desc.hasValue && !js_SameValue(desc.value, v, cx))) {
@ -2369,7 +2322,8 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
cx)) ||
(desc.hasGet &&
!js_SameValue(desc.getterValue(),
sprop->hasGetterValue() ? sprop->getterValue() : JSVAL_VOID, cx)))
sprop->hasGetterValue() ? sprop->getterValue() : JSVAL_VOID,
cx)))
{
return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_UNCONFIGURABLE_PROP,
throwError, desc.id, rval);
@ -2429,14 +2383,20 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
changed |= JSPROP_SETTER | JSPROP_SHARED;
attrs = (desc.attrs & changed) | (sprop->attributes() & ~changed);
if (desc.hasGet)
getter = desc.getterObject() ? desc.getter() : JS_PropertyStub;
else
getter = sprop->hasDefaultGetter() ? JS_PropertyStub : sprop->getter();
if (desc.hasSet)
setter = desc.setterObject() ? desc.setter() : JS_PropertyStub;
else
setter = sprop->hasDefaultSetter() ? JS_PropertyStub : sprop->setter();
if (desc.hasGet) {
getter = desc.getter();
} else {
getter = (sprop->hasDefaultGetter() && !sprop->hasGetterValue())
? JS_PropertyStub
: sprop->getter();
}
if (desc.hasSet) {
setter = desc.setter();
} else {
setter = (sprop->hasDefaultSetter() && !sprop->hasSetterValue())
? JS_PropertyStub
: sprop->setter();
}
}
*rval = true;
@ -2445,8 +2405,8 @@ DefinePropertyObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &des
}
static JSBool
DefinePropertyArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc,
bool throwError, bool *rval)
DefinePropertyOnArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc,
bool throwError, bool *rval)
{
/*
* We probably should optimize dense array property definitions where
@ -2479,21 +2439,21 @@ DefinePropertyArray(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc
if (index >= oldLen && lengthPropertyNotWritable())
return ThrowTypeError(cx, JSMSG_CANT_APPEND_PROPERTIES_TO_UNWRITABLE_LENGTH_ARRAY);
*/
if (!DefinePropertyObject(cx, obj, desc, false, rval))
if (!DefinePropertyOnObject(cx, obj, desc, false, rval))
return JS_FALSE;
if (!*rval)
return Reject(cx, JSMSG_CANT_DEFINE_ARRAY_INDEX, throwError, rval);
if (index >= oldLen) {
JS_ASSERT(index != UINT32_MAX);
obj->setArrayLength(index + 1);
obj->setSlowArrayLength(index + 1);
}
*rval = true;
return JS_TRUE;
}
return DefinePropertyObject(cx, obj, desc, throwError, rval);
return DefinePropertyOnObject(cx, obj, desc, throwError, rval);
}
static JSBool
@ -2501,12 +2461,12 @@ DefineProperty(JSContext *cx, JSObject *obj, const PropertyDescriptor &desc, boo
bool *rval)
{
if (obj->isArray())
return DefinePropertyArray(cx, obj, desc, throwError, rval);
return DefinePropertyOnArray(cx, obj, desc, throwError, rval);
if (obj->map->ops->lookupProperty != js_LookupProperty)
return Reject(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
return DefinePropertyObject(cx, obj, desc, throwError, rval);
return DefinePropertyOnObject(cx, obj, desc, throwError, rval);
}
JSBool
@ -2671,30 +2631,20 @@ const char js_hasOwnProperty_str[] = "hasOwnProperty";
const char js_isPrototypeOf_str[] = "isPrototypeOf";
const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
JS_DEFINE_TRCINFO_1(obj_valueOf,
(3, (static, JSVAL, Object_p_valueOf, CONTEXT, THIS, STRING, 0,
nanojit::ACC_STORE_ANY)))
JS_DEFINE_TRCINFO_1(obj_hasOwnProperty,
(3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING, 0,
nanojit::ACC_STORE_ANY)))
JS_DEFINE_TRCINFO_1(obj_propertyIsEnumerable,
(3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0,
nanojit::ACC_STORE_ANY)))
static JSFunctionSpec object_methods[] = {
#if JS_HAS_TOSOURCE
JS_FN(js_toSource_str, obj_toSource, 0,0),
#endif
JS_FN(js_toString_str, obj_toString, 0,0),
JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0),
JS_TN(js_valueOf_str, obj_valueOf, 0,0, &obj_valueOf_trcinfo),
JS_FN(js_valueOf_str, obj_valueOf, 0,0),
#if JS_HAS_OBJ_WATCHPOINT
JS_FN(js_watch_str, obj_watch, 2,0),
JS_FN(js_unwatch_str, obj_unwatch, 1,0),
#endif
JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0, &obj_hasOwnProperty_trcinfo),
JS_FN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0),
JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0, &obj_propertyIsEnumerable_trcinfo),
JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0),
#if OLD_GETTER_SETTER_METHODS
JS_FN(js_defineGetter_str, js_obj_defineGetter, 2,0),
JS_FN(js_defineSetter_str, js_obj_defineSetter, 2,0),
@ -4250,9 +4200,9 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
/* Use the object's class getter and setter by default. */
clasp = obj->getClass();
if (!(defineHow & JSDNP_SET_METHOD)) {
if (!getter)
if (!getter && !(attrs & JSPROP_GETTER))
getter = clasp->getProperty;
if (!setter)
if (!setter && !(attrs & JSPROP_SETTER))
setter = clasp->setProperty;
}
@ -4273,15 +4223,25 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSObject *funobj = JSVAL_TO_OBJECT(value);
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
flags |= JSScopeProperty::METHOD;
getter = js_CastAsPropertyOp(funobj);
getter = CastAsPropertyOp(funobj);
}
}
added = !scope->hasProperty(id);
uint32 oldShape = scope->shape;
sprop = scope->putProperty(cx, id, getter, setter, SPROP_INVALID_SLOT,
attrs, flags, shortid);
if (!sprop)
goto error;
/*
* If sprop is a method, the above call to putProperty suffices to
* update the shape if necessary. But if scope->branded(), the shape
* may not have changed and we may be overwriting a function-valued
* property. See bug 560998.
*/
if (scope->shape == oldShape && scope->branded())
scope->methodWriteBarrier(cx, sprop->slot, value);
}
/* Store value before calling addProperty, in case the latter GC's. */
@ -5140,7 +5100,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
JSObject *funobj = JSVAL_TO_OBJECT(*vp);
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
flags |= JSScopeProperty::METHOD;
getter = js_CastAsPropertyOp(funobj);
getter = CastAsPropertyOp(funobj);
}
}

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

@ -97,10 +97,10 @@ struct PropertyDescriptor {
}
JSObject* getterObject() const {
return get != JSVAL_VOID ? JSVAL_TO_OBJECT(get) : NULL;
return (get != JSVAL_VOID) ? JSVAL_TO_OBJECT(get) : NULL;
}
JSObject* setterObject() const {
return set != JSVAL_VOID ? JSVAL_TO_OBJECT(set) : NULL;
return (set != JSVAL_VOID) ? JSVAL_TO_OBJECT(set) : NULL;
}
jsval getterValue() const {
@ -111,10 +111,10 @@ struct PropertyDescriptor {
}
JSPropertyOp getter() const {
return js_CastAsPropertyOp(getterObject());
return js::CastAsPropertyOp(getterObject());
}
JSPropertyOp setter() const {
return js_CastAsPropertyOp(setterObject());
return js::CastAsPropertyOp(setterObject());
}
static void traceDescriptorArray(JSTracer* trc, JSObject* obj);
@ -292,7 +292,7 @@ struct JSObject {
classword |= jsuword(2);
}
uint32 numSlots(void) {
uint32 numSlots(void) const {
return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS;
}
@ -405,24 +405,32 @@ struct JSObject {
*/
private:
// Used by dense and slow arrays.
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;
// Used only by dense arrays.
static const uint32 JSSLOT_DENSE_ARRAY_COUNT = JSSLOT_PRIVATE + 1;
static const uint32 JSSLOT_DENSE_ARRAY_MINLENCAP = JSSLOT_PRIVATE + 2;
// This assertion must remain true; see comment in js_MakeArraySlow().
// (Nb: This method is never called, it just contains a static assertion.
// The static assertion isn't inline because that doesn't work on Mac.)
inline void staticAssertArrayLengthIsInPrivateSlot();
inline bool isDenseArrayMinLenCapOk() const;
inline uint32 uncheckedGetArrayLength() const;
inline uint32 uncheckedGetDenseArrayCapacity() const;
public:
inline uint32 getArrayLength() const;
inline void setArrayLength(uint32 length);
inline void setDenseArrayLength(uint32 length);
inline void setSlowArrayLength(uint32 length);
inline uint32 getArrayCount() const;
inline void voidDenseArrayCount();
inline void setArrayCount(uint32 count);
inline void incArrayCountBy(uint32 posDelta);
inline void decArrayCountBy(uint32 negDelta);
inline uint32 getDenseArrayCount() const;
inline void setDenseArrayCount(uint32 count);
inline void incDenseArrayCountBy(uint32 posDelta);
inline void decDenseArrayCountBy(uint32 negDelta);
inline uint32 getDenseArrayCapacity() const;
inline void setDenseArrayCapacity(uint32 capacity); // XXX: bug 558263 will remove this
@ -437,6 +445,8 @@ struct JSObject {
bool initializeAllSlots = true);
inline void freeDenseArrayElements(JSContext *cx);
inline void voidDenseOnlyArraySlots(); // used when converting a dense array to a slow array
/*
* Arguments-specific getters and setters.
*/
@ -451,8 +461,8 @@ struct JSObject {
* JSSLOT_ARGS_CALLEE - the arguments.callee value or JSVAL_HOLE if that
* was overwritten.
*
* Argument index i is stored in dslots[i]. But future-proof your code by
* using {Get,Set}ArgsSlot instead of naked dslots references.
* Argument index i is stored in dslots[i], accessible via
* {get,set}ArgsElement().
*/
private:
static const uint32 JSSLOT_ARGS_LENGTH = JSSLOT_PRIVATE + 1;
@ -465,11 +475,14 @@ struct JSObject {
inline uint32 getArgsLength() const;
inline void setArgsLength(uint32 argc);
inline void setArgsLengthOverridden();
inline bool isArgsLengthOverridden();
inline bool isArgsLengthOverridden() const;
inline jsval getArgsCallee() const;
inline void setArgsCallee(jsval callee);
inline jsval getArgsElement(uint32 i) const;
inline void setArgsElement(uint32 i, jsval v);
/*
* Date-specific getters and setters.
*/

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

@ -115,60 +115,85 @@ inline void JSObject::staticAssertArrayLengthIsInPrivateSlot()
JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH == JSSLOT_PRIVATE);
}
inline bool JSObject::isDenseArrayMinLenCapOk() const
{
JS_ASSERT(isDenseArray());
uint32 length = uncheckedGetArrayLength();
uint32 capacity = uncheckedGetDenseArrayCapacity();
uint32 minLenCap = uint32(fslots[JSSLOT_DENSE_ARRAY_MINLENCAP]);
return minLenCap == JS_MIN(length, capacity);
}
inline uint32
JSObject::uncheckedGetArrayLength() const
{
return uint32(fslots[JSSLOT_ARRAY_LENGTH]);
}
inline uint32
JSObject::getArrayLength() const
{
JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_LENGTH]);
JS_ASSERT_IF(isDenseArray(), isDenseArrayMinLenCapOk());
return uncheckedGetArrayLength();
}
inline void
JSObject::setArrayLength(uint32 length)
JSObject::setDenseArrayLength(uint32 length)
{
JS_ASSERT(isArray());
JS_ASSERT(isDenseArray());
fslots[JSSLOT_ARRAY_LENGTH] = length;
uint32 capacity = uncheckedGetDenseArrayCapacity();
fslots[JSSLOT_DENSE_ARRAY_MINLENCAP] = JS_MIN(length, capacity);
}
inline void
JSObject::setSlowArrayLength(uint32 length)
{
JS_ASSERT(isSlowArray());
fslots[JSSLOT_ARRAY_LENGTH] = length;
}
inline uint32
JSObject::getArrayCount() const
{
JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_COUNT]);
}
inline void
JSObject::setArrayCount(uint32 count)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] = count;
}
inline void
JSObject::voidDenseArrayCount()
JSObject::getDenseArrayCount() const
{
JS_ASSERT(isDenseArray());
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
return uint32(fslots[JSSLOT_DENSE_ARRAY_COUNT]);
}
inline void
JSObject::incArrayCountBy(uint32 posDelta)
JSObject::setDenseArrayCount(uint32 count)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] += posDelta;
JS_ASSERT(isDenseArray());
fslots[JSSLOT_DENSE_ARRAY_COUNT] = count;
}
inline void
JSObject::decArrayCountBy(uint32 negDelta)
JSObject::incDenseArrayCountBy(uint32 posDelta)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] -= negDelta;
JS_ASSERT(isDenseArray());
fslots[JSSLOT_DENSE_ARRAY_COUNT] += posDelta;
}
inline void
JSObject::decDenseArrayCountBy(uint32 negDelta)
{
JS_ASSERT(isDenseArray());
fslots[JSSLOT_DENSE_ARRAY_COUNT] -= negDelta;
}
inline uint32
JSObject::uncheckedGetDenseArrayCapacity() const
{
return dslots ? uint32(dslots[-1]) : 0;
}
inline uint32
JSObject::getDenseArrayCapacity() const
{
JS_ASSERT(isDenseArray());
return dslots ? uint32(dslots[-1]) : 0;
JS_ASSERT(isDenseArrayMinLenCapOk());
return uncheckedGetDenseArrayCapacity();
}
inline void
@ -177,6 +202,8 @@ JSObject::setDenseArrayCapacity(uint32 capacity)
JS_ASSERT(isDenseArray());
JS_ASSERT(dslots);
dslots[-1] = capacity;
uint32 length = uncheckedGetArrayLength();
fslots[JSSLOT_DENSE_ARRAY_MINLENCAP] = JS_MIN(length, capacity);
}
inline jsval
@ -205,10 +232,21 @@ JSObject::getDenseArrayElements() const
inline void
JSObject::freeDenseArrayElements(JSContext *cx)
{
JS_ASSERT(isDenseArray());
if (dslots) {
cx->free(dslots - 1);
dslots = NULL;
}
fslots[JSSLOT_DENSE_ARRAY_MINLENCAP] = 0;
JS_ASSERT(isDenseArrayMinLenCapOk());
}
inline void
JSObject::voidDenseOnlyArraySlots()
{
JS_ASSERT(isDenseArray());
fslots[JSSLOT_DENSE_ARRAY_COUNT] = JSVAL_VOID;
fslots[JSSLOT_DENSE_ARRAY_MINLENCAP] = JSVAL_VOID;
}
inline void
@ -240,7 +278,7 @@ JSObject::setArgsLengthOverridden()
}
inline bool
JSObject::isArgsLengthOverridden()
JSObject::isArgsLengthOverridden() const
{
JS_ASSERT(isArguments());
jsval v = fslots[JSSLOT_ARGS_LENGTH];
@ -261,6 +299,22 @@ JSObject::setArgsCallee(jsval callee)
fslots[JSSLOT_ARGS_CALLEE] = callee;
}
inline jsval
JSObject::getArgsElement(uint32 i) const
{
JS_ASSERT(isArguments());
JS_ASSERT(i < numSlots() - JS_INITIAL_NSLOTS);
return dslots[i];
}
inline void
JSObject::setArgsElement(uint32 i, jsval v)
{
JS_ASSERT(isArguments());
JS_ASSERT(i < numSlots() - JS_INITIAL_NSLOTS);
dslots[i] = v;
}
inline jsval
JSObject::getDateLocalTime() const
{

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

@ -48,14 +48,14 @@
#endif /* !JS_THREADED_INTERP */
{
bool moreInterrupts = false;
JSTrapHandler handler = cx->debugHooks->interruptHandler;
if (handler) {
JSInterruptHook hook = cx->debugHooks->interruptHook;
if (hook) {
#ifdef JS_TRACER
if (TRACE_RECORDER(cx))
AbortRecording(cx, "interrupt handler");
AbortRecording(cx, "interrupt hook");
#endif
switch (handler(cx, script, regs.pc, &rval,
cx->debugHooks->interruptHandlerData)) {
switch (hook(cx, script, regs.pc, &rval,
cx->debugHooks->interruptHookData)) {
case JSTRAP_ERROR:
goto error;
case JSTRAP_CONTINUE:
@ -258,13 +258,7 @@ BEGIN_CASE(JSOP_STOP)
*/
fp->putActivationObjects(cx);
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function return, inlines */
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fp->fun, &fp->rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fp->fun);
#endif
DTrace::exitJSFun(cx, fp, fp->fun, fp->rval);
/* Restore context version only if callee hasn't set version. */
if (JS_LIKELY(cx->version == currentVersion)) {
@ -1878,7 +1872,7 @@ BEGIN_CASE(JSOP_GETELEM)
goto end_getelem;
}
rval = GetArgsSlot(obj, arg);
rval = obj->getArgsElement(arg);
if (rval != JSVAL_HOLE)
goto end_getelem;
rval = FETCH_OPND(-1);
@ -1928,8 +1922,8 @@ BEGIN_CASE(JSOP_SETELEM)
if (js_PrototypeHasIndexedProperties(cx, obj))
break;
if ((jsuint)i >= obj->getArrayLength())
obj->setArrayLength(i + 1);
obj->incArrayCountBy(1);
obj->setDenseArrayLength(i + 1);
obj->incDenseArrayCountBy(1);
}
obj->setDenseArrayElement(i, rval);
goto end_setelem;
@ -2163,15 +2157,7 @@ BEGIN_CASE(JSOP_APPLY)
inlineCallCount++;
JS_RUNTIME_METER(rt, inlineCalls);
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function entry, inlines */
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, fp, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, fp, fp->down, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun, fp->argc, fp->argv);
#endif
DTrace::enterJSFun(cx, fp, fun, fp->down, fp->argc, fp->argv);
#ifdef JS_TRACER
if (TraceRecorder *tr = TRACE_RECORDER(cx)) {
@ -2205,30 +2191,13 @@ BEGIN_CASE(JSOP_APPLY)
}
if (fun->flags & JSFUN_FAST_NATIVE) {
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function entry, non-inlines */
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, NULL, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, NULL, fp, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun, argc, vp+2);
}
#endif
DTrace::enterJSFun(cx, NULL, fun, fp, argc, vp + 2, &lval);
JS_ASSERT(fun->u.n.extra == 0);
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
PRIMITIVE_THIS_TEST(fun, vp[1]));
ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
#ifdef INCLUDE_MOZILLA_DTRACE
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, NULL, fun, vp);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, NULL, fun);
}
#endif
DTrace::exitJSFun(cx, NULL, fun, *vp, &lval);
regs.sp = vp + 1;
if (!ok) {
/*
@ -2933,9 +2902,9 @@ BEGIN_CASE(JSOP_DEFFUN)
attrs |= flags | JSPROP_SHARED;
rval = JSVAL_VOID;
if (flags == JSPROP_GETTER)
getter = js_CastAsPropertyOp(obj);
getter = CastAsPropertyOp(obj);
else
setter = js_CastAsPropertyOp(obj);
setter = CastAsPropertyOp(obj);
}
/*
@ -3033,10 +3002,10 @@ BEGIN_CASE(JSOP_DEFFUN_DBGFC)
ok = parent->defineProperty(cx, id, rval,
(flags & JSPROP_GETTER)
? js_CastAsPropertyOp(obj)
? CastAsPropertyOp(obj)
: JS_PropertyStub,
(flags & JSPROP_SETTER)
? js_CastAsPropertyOp(obj)
? CastAsPropertyOp(obj)
: JS_PropertyStub,
attrs);
}
@ -3259,12 +3228,12 @@ BEGIN_CASE(JSOP_SETTER)
goto error;
if (op == JSOP_GETTER) {
getter = js_CastAsPropertyOp(JSVAL_TO_OBJECT(rval));
getter = CastAsPropertyOp(JSVAL_TO_OBJECT(rval));
setter = JS_PropertyStub;
attrs = JSPROP_GETTER;
} else {
getter = JS_PropertyStub;
setter = js_CastAsPropertyOp(JSVAL_TO_OBJECT(rval));
setter = CastAsPropertyOp(JSVAL_TO_OBJECT(rval));
attrs = JSPROP_SETTER;
}
attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
@ -3678,7 +3647,7 @@ END_CASE(JSOP_INSTANCEOF)
#if JS_HAS_DEBUGGER_KEYWORD
BEGIN_CASE(JSOP_DEBUGGER)
{
JSTrapHandler handler = cx->debugHooks->debuggerHandler;
JSDebuggerHandler handler = cx->debugHooks->debuggerHandler;
if (handler) {
switch (handler(cx, script, regs.pc, &rval, cx->debugHooks->debuggerHandlerData)) {
case JSTRAP_ERROR:

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

@ -722,7 +722,6 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle
JSString *source /* = NULL */,
unsigned staticLevel /* = 0 */)
{
Compiler compiler(cx, principals, callerFrame);
JSArenaPool codePool, notePool;
TokenKind tt;
JSParseNode *pn;
@ -742,6 +741,7 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle
JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
JS_ASSERT_IF(staticLevel != 0, callerFrame);
Compiler compiler(cx, principals, callerFrame);
if (!compiler.init(chars, length, file, filename, lineno))
return NULL;
@ -754,6 +754,8 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle
TokenStream &tokenStream = parser.tokenStream;
JSCodeGenerator cg(&parser, &codePool, &notePool, tokenStream.getLineno());
if (!cg.init())
return NULL;
MUST_FLOW_THROUGH("out");
@ -1527,6 +1529,9 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin
TokenStream &tokenStream = parser.tokenStream;
JSCodeGenerator funcg(&parser, &codePool, &notePool, tokenStream.getLineno());
if (!funcg.init())
return NULL;
funcg.flags |= TCF_IN_FUNCTION;
funcg.fun = fun;
if (!GenerateBlockId(&funcg, funcg.bodyid))
@ -1991,6 +1996,14 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags)
*/
if (!afunbox || afunbox->node->isFunArg())
return false;
/*
* Reaching up for dn across a generator also means we can't flatten,
* since the generator iterator does not run until later, in general.
* See bug 563034.
*/
if (afunbox->tcflags & TCF_FUN_IS_GENERATOR)
return false;
}
/*
@ -2081,23 +2094,23 @@ CanFlattenUpvar(JSDefinition *dn, JSFunctionBox *funbox, uint32 tcflags)
static void
FlagHeavyweights(JSDefinition *dn, JSFunctionBox *funbox, uint32& tcflags)
{
JSFunctionBox *afunbox = funbox->parent;
uintN dnLevel = dn->frameLevel();
while (afunbox) {
while ((funbox = funbox->parent) != NULL) {
/*
* Notice that afunbox->level is the static level of the definition or
* expression of the function parsed into afunbox, not the static level
* Notice that funbox->level is the static level of the definition or
* expression of the function parsed into funbox, not the static level
* of its body. Therefore we must add 1 to match dn's level to find the
* afunbox whose body contains the dn definition.
* funbox whose body contains the dn definition.
*/
if (afunbox->level + 1U == dnLevel || (dnLevel == 0 && dn->isLet())) {
afunbox->tcflags |= TCF_FUN_HEAVYWEIGHT;
if (funbox->level + 1U == dnLevel || (dnLevel == 0 && dn->isLet())) {
funbox->tcflags |= TCF_FUN_HEAVYWEIGHT;
break;
}
afunbox = afunbox->parent;
funbox->tcflags |= TCF_FUN_ENTRAINS_SCOPES;
}
if (!afunbox && (tcflags & TCF_IN_FUNCTION))
if (!funbox && (tcflags & TCF_IN_FUNCTION))
tcflags |= TCF_FUN_HEAVYWEIGHT;
}
@ -2172,10 +2185,11 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32& tcflags)
JSFunction *fun = (JSFunction *) funbox->object;
JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED);
FUN_METER(allfun);
if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
FUN_METER(heavy);
JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED);
} else if (pn->pn_type != TOK_UPVARS) {
/*
* No lexical dependencies => null closure, for best performance.
@ -2247,7 +2261,8 @@ Parser::setFunctionKinds(JSFunctionBox *funbox, uint32& tcflags)
if (nupvars == 0) {
FUN_METER(onlyfreevar);
FUN_SET_KIND(fun, JSFUN_NULL_CLOSURE);
} else if (!mutation && !(funbox->tcflags & TCF_FUN_IS_GENERATOR)) {
} else if (!mutation &&
!(funbox->tcflags & (TCF_FUN_IS_GENERATOR | TCF_FUN_ENTRAINS_SCOPES))) {
/*
* Algol-like functions can read upvars using the dynamic
* link (cx->fp/fp->down), optimized using the cx->display

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

@ -91,10 +91,12 @@ typedef uint32 jsatomid;
#ifdef __cplusplus
/* Class and struct forward declarations in namespace js. */
extern "C++" {
namespace js {
struct Parser;
struct Compiler;
}
}
#endif
@ -184,17 +186,18 @@ class DeflatedStringCache;
class PropertyCache;
struct PropertyCacheEntry;
static inline JSPropertyOp
CastAsPropertyOp(JSObject *object)
{
return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
}
} /* namespace js */
/* Common instantiations. */
typedef js::Vector<jschar, 32> JSCharBuffer;
static inline JSPropertyOp
js_CastAsPropertyOp(JSObject *object)
{
return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
}
} /* export "C++" */
#endif /* __cplusplus */
@ -209,7 +212,19 @@ typedef enum JSTrapStatus {
typedef JSTrapStatus
(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
jsval closure);
typedef JSTrapStatus
(* JSInterruptHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSTrapStatus
(* JSDebuggerHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSTrapStatus
(* JSThrowHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSBool
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old,
@ -271,13 +286,13 @@ typedef JSBool
void *closure);
typedef struct JSDebugHooks {
JSTrapHandler interruptHandler;
void *interruptHandlerData;
JSInterruptHook interruptHook;
void *interruptHookData;
JSNewScriptHook newScriptHook;
void *newScriptHookData;
JSDestroyScriptHook destroyScriptHook;
void *destroyScriptHookData;
JSTrapHandler debuggerHandler;
JSDebuggerHandler debuggerHandler;
void *debuggerHandlerData;
JSSourceHandler sourceHandler;
void *sourceHandlerData;
@ -287,7 +302,7 @@ typedef struct JSDebugHooks {
void *callHookData;
JSObjectHook objectHook;
void *objectHookData;
JSTrapHandler throwHook;
JSThrowHook throwHook;
void *throwHookData;
JSDebugErrorHook debugErrorHook;
void *debugErrorHookData;

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

@ -353,6 +353,38 @@ typedef struct REGlobalData {
size_t backTrackLimit; /* upper limit on backtrack states */
} REGlobalData;
void
JSRegExpStatics::clearRoots()
{
input = NULL;
cx->runtime->gcPoke = JS_TRUE;
}
bool
JSRegExpStatics::copy(const JSRegExpStatics& other)
{
clearRoots();
input = other.input;
multiline = other.multiline;
lastMatch = other.lastMatch;
lastParen = other.lastParen;
leftContext = other.leftContext;
rightContext = other.rightContext;
if (!parens.resize(other.parens.length()))
return false;
memcpy(parens.begin(), other.parens.begin(), sizeof(JSSubString) * parens.length());
return true;
}
void
JSRegExpStatics::clear()
{
clearRoots();
multiline = false;
lastMatch = lastParen = leftContext = rightContext = js_EmptySubString;
parens.clear();
}
/*
* 1. If IgnoreCase is false, return ch.
* 2. Let u be ch converted to upper case as if by calling
@ -4865,11 +4897,10 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
const jschar *cp, *ep;
size_t i, length, start;
JSSubString *morepar;
JSBool ok;
JSRegExpStatics *res;
ptrdiff_t matchlen;
uintN num, morenum;
uintN num;
JSString *parstr, *matchstr;
JSObject *obj;
@ -4973,45 +5004,22 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
res = &cx->regExpStatics;
res->input = str;
res->parenCount = uint16(re->parenCount);
if (!res->parens.resize(re->parenCount)) {
ok = JS_FALSE;
goto out;
}
if (re->parenCount == 0) {
res->lastParen = js_EmptySubString;
} else {
for (num = 0; num < re->parenCount; num++) {
JSSubString *sub = &res->parens[num];
parsub = &result->parens[num];
if (num < 9) {
if (parsub->index == -1) {
res->parens[num].chars = NULL;
res->parens[num].length = 0;
} else {
res->parens[num].chars = gData.cpbegin + parsub->index;
res->parens[num].length = parsub->length;
}
if (parsub->index == -1) {
sub->chars = NULL;
sub->length = 0;
} else {
morenum = num - 9;
morepar = res->moreParens;
if (!morepar) {
res->moreLength = 10;
morepar = (JSSubString*)
cx->malloc(10 * sizeof(JSSubString));
} else if (morenum >= res->moreLength) {
res->moreLength += 10;
morepar = (JSSubString*)
cx->realloc(morepar,
res->moreLength * sizeof(JSSubString));
}
if (!morepar) {
ok = JS_FALSE;
goto out;
}
res->moreParens = morepar;
if (parsub->index == -1) {
morepar[morenum].chars = NULL;
morepar[morenum].length = 0;
} else {
morepar[morenum].chars = gData.cpbegin + parsub->index;
morepar[morenum].length = parsub->length;
}
sub->chars = gData.cpbegin + parsub->index;
sub->length = parsub->length;
}
if (test)
continue;
@ -5209,14 +5217,9 @@ JS_FRIEND_API(void)
js_SaveAndClearRegExpStatics(JSContext *cx, JSRegExpStatics *statics,
AutoValueRooter *tvr)
{
*statics = cx->regExpStatics;
statics->copy(cx->regExpStatics);
if (statics->input)
tvr->setString(statics->input);
/*
* Prevent JS_ClearRegExpStatics from freeing moreParens, since we've only
* moved it elsewhere (into statics->moreParens).
*/
cx->regExpStatics.moreParens = NULL;
JS_ClearRegExpStatics(cx);
}
@ -5225,8 +5228,7 @@ js_RestoreRegExpStatics(JSContext *cx, JSRegExpStatics *statics,
AutoValueRooter *tvr)
{
/* Clear/free any new JSRegExpStatics data before clobbering. */
JS_ClearRegExpStatics(cx);
cx->regExpStatics = *statics;
cx->regExpStatics.copy(*statics);
}
void
@ -5278,7 +5280,7 @@ regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
sub = &res->rightContext;
break;
default:
sub = REGEXP_PAREN_SUBSTRING(res, slot);
sub = (size_t(slot) < res->parens.length()) ? &res->parens[slot] : &js_EmptySubString;
break;
}
str = js_NewStringCopyN(cx, sub->chars, sub->length);

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

@ -52,19 +52,6 @@
JS_BEGIN_EXTERN_C
struct JSRegExpStatics {
JSString *input; /* input string to match (perl $_, GC root) */
JSBool multiline; /* whether input contains newlines (perl $*) */
uint16 parenCount; /* number of valid elements in parens[] */
uint16 moreLength; /* number of allocated elements in moreParens */
JSSubString parens[9]; /* last set of parens matched (perl $1, $2) */
JSSubString *moreParens; /* null or realloc'd vector for $10, etc. */
JSSubString lastMatch; /* last string matched (perl $&) */
JSSubString lastParen; /* last paren matched (perl $+) */
JSSubString leftContext; /* input to left of last match (perl $`) */
JSSubString rightContext; /* input to right of last match (perl $') */
};
namespace js { class AutoValueRooter; }
extern JS_FRIEND_API(void)
@ -96,17 +83,6 @@ typedef struct RECharSet {
} u;
} RECharSet;
/*
* This macro is safe because moreParens is guaranteed to be allocated and big
* enough to hold parenCount, or else be null when parenCount is 0.
*/
#define REGEXP_PAREN_SUBSTRING(res, num) \
(((jsuint)(num) < (jsuint)(res)->parenCount) \
? ((jsuint)(num) < 9) \
? &(res)->parens[num] \
: &(res)->moreParens[(num) - 9] \
: &js_EmptySubString)
typedef struct RENode RENode;
struct JSRegExp {

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

@ -768,16 +768,20 @@ NormalizeGetterAndSetter(JSContext *cx, JSScope *scope,
JSPropertyOp &getter,
JSPropertyOp &setter)
{
if (setter == JS_PropertyStub)
if (setter == JS_PropertyStub) {
JS_ASSERT(!(attrs & JSPROP_SETTER));
setter = NULL;
}
if (flags & JSScopeProperty::METHOD) {
/* Here, getter is the method, a function object reference. */
JS_ASSERT(getter);
JS_ASSERT(!setter || setter == js_watch_set);
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
} else {
if (getter == JS_PropertyStub)
if (getter == JS_PropertyStub) {
JS_ASSERT(!(attrs & JSPROP_GETTER));
getter = NULL;
}
}
/*
@ -1158,7 +1162,7 @@ JSScope::deletingShapeChange(JSContext *cx, JSScopeProperty *sprop)
}
bool
JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval)
JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop)
{
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
if (sprop->isMethod()) {
@ -1189,7 +1193,7 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval)
}
bool
JSScope::methodShapeChange(JSContext *cx, uint32 slot, jsval toval)
JSScope::methodShapeChange(JSContext *cx, uint32 slot)
{
if (!hasMethodBarrier()) {
generateOwnShape(cx);
@ -1197,7 +1201,7 @@ JSScope::methodShapeChange(JSContext *cx, uint32 slot, jsval toval)
for (JSScopeProperty *sprop = lastProp; sprop; sprop = sprop->parent) {
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
if (sprop->slot == slot)
return methodShapeChange(cx, sprop, toval);
return methodShapeChange(cx, sprop);
}
}
return true;

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

@ -373,8 +373,8 @@ struct JSScope : public JSObjectMap
void trace(JSTracer *trc);
void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop);
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval);
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop);
bool methodShapeChange(JSContext *cx, uint32 slot);
void protoShapeChange(JSContext *cx);
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
bool globalObjectOwnShapeChange(JSContext *cx);
@ -575,21 +575,23 @@ JSObject::lockedSetSlot(uintN slot, jsval value)
* Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
* and setters.
*/
namespace js {
inline JSObject *
js_CastAsObject(JSPropertyOp op)
CastAsObject(JSPropertyOp op)
{
return JS_FUNC_TO_DATA_PTR(JSObject *, op);
}
inline jsval
js_CastAsObjectJSVal(JSPropertyOp op)
CastAsObjectJSVal(JSPropertyOp op)
{
return OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, op));
}
namespace js {
class PropertyTree;
}
} /* namespace js */
struct JSScopeProperty {
friend struct JSScope;
@ -602,13 +604,17 @@ struct JSScopeProperty {
private:
union {
JSPropertyOp rawGetter; /* getter and setter hooks or objects */
JSPropertyOp rawGetter; /* getter and setter hooks or objects */
JSObject *getterObj; /* user-defined callable "get" object or
null if sprop->hasGetterValue() */
JSScopeProperty *next; /* next node in freelist */
};
union {
JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0
JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0
if sprop->isMethod() */
JSObject *setterObj; /* user-defined callable "set" object or
null if sprop->hasSetterValue() */
JSScopeProperty **prevp; /* pointer to previous node's next, or
pointer to head of freelist */
};
@ -673,10 +679,8 @@ struct JSScopeProperty {
: id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)),
flags(uint8(flags)), shortid(int16(shortid))
{
JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER),
JSVAL_TO_OBJECT(getterValue())->isCallable());
JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER),
JSVAL_TO_OBJECT(setterValue())->isCallable());
JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), getterObj->isCallable());
JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER), setterObj->isCallable());
}
bool marked() const { return (flags & MARK) != 0; }
@ -698,48 +702,34 @@ struct JSScopeProperty {
PUBLIC_FLAGS = ALIAS | HAS_SHORTID | METHOD
};
uintN getFlags() const { return flags & PUBLIC_FLAGS; }
bool isAlias() const { return (flags & ALIAS) != 0; }
uintN getFlags() const { return flags & PUBLIC_FLAGS; }
bool isAlias() const { return (flags & ALIAS) != 0; }
bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
bool isMethod() const { return (flags & METHOD) != 0; }
bool isMethod() const { return (flags & METHOD) != 0; }
JSObject *methodObject() const {
JS_ASSERT(isMethod());
return js_CastAsObject(rawGetter);
}
jsval methodValue() const {
JS_ASSERT(isMethod());
return js_CastAsObjectJSVal(rawGetter);
}
JSObject *methodObject() const { JS_ASSERT(isMethod()); return getterObj; }
jsval methodValue() const { return OBJECT_TO_JSVAL(methodObject()); }
JSPropertyOp getter() const { return rawGetter; }
bool hasDefaultGetter() const { return !rawGetter; }
JSPropertyOp getterOp() const {
JS_ASSERT(!hasGetterValue());
return rawGetter;
}
JSObject *getterObject() const {
JS_ASSERT(hasGetterValue());
return js_CastAsObject(rawGetter);
}
JSPropertyOp getter() const { return rawGetter; }
bool hasDefaultGetter() const { return !rawGetter; }
JSPropertyOp getterOp() const { JS_ASSERT(!hasGetterValue()); return rawGetter; }
JSObject *getterObject() const { JS_ASSERT(hasGetterValue()); return getterObj; }
// Per ES5, decode null getterObj as the undefined value, which encodes as null.
jsval getterValue() const {
JS_ASSERT(hasGetterValue());
return rawGetter ? js_CastAsObjectJSVal(rawGetter) : JSVAL_VOID;
return getterObj ? OBJECT_TO_JSVAL(getterObj) : JSVAL_VOID;
}
JSPropertyOp setter() const { return rawSetter; }
bool hasDefaultSetter() const { return !rawSetter; }
JSPropertyOp setterOp() const {
JS_ASSERT(!hasSetterValue());
return rawSetter;
}
JSObject *setterObject() const {
JS_ASSERT(hasSetterValue() && rawSetter);
return js_CastAsObject(rawSetter);
}
JSPropertyOp setter() const { return rawSetter; }
bool hasDefaultSetter() const { return !rawSetter; }
JSPropertyOp setterOp() const { JS_ASSERT(!hasSetterValue()); return rawSetter; }
JSObject *setterObject() const { JS_ASSERT(hasSetterValue()); return setterObj; }
// Per ES5, decode null setterObj as the undefined value, which encodes as null.
jsval setterValue() const {
JS_ASSERT(hasSetterValue());
return rawSetter ? js_CastAsObjectJSVal(rawSetter) : JSVAL_VOID;
return setterObj ? OBJECT_TO_JSVAL(setterObj) : JSVAL_VOID;
}
inline JSDHashNumber hash() const;

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

@ -140,7 +140,7 @@ JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v)
jsval prev = object->lockedGetSlot(sprop->slot);
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
return methodShapeChange(cx, sprop, v);
return methodShapeChange(cx, sprop);
}
return true;
}
@ -152,7 +152,7 @@ JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, jsval v)
jsval prev = object->lockedGetSlot(slot);
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
return methodShapeChange(cx, slot, v);
return methodShapeChange(cx, slot);
}
return true;
}

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

@ -1123,7 +1123,7 @@ struct ManualCmp {
template <class InnerMatch>
static jsint
Duff(const jschar *text, jsuint textlen, const jschar *pat, jsuint patlen)
UnrolledMatch(const jschar *text, jsuint textlen, const jschar *pat, jsuint patlen)
{
JS_ASSERT(patlen > 0 && textlen > 0);
const jschar *textend = text + textlen - (patlen - 1);
@ -1134,26 +1134,35 @@ Duff(const jschar *text, jsuint textlen, const jschar *pat, jsuint patlen)
const jschar *t = text;
switch ((textend - t) & 7) {
case 0: if (*t++ == p0) { fixup = 8; goto match; }
case 7: if (*t++ == p0) { fixup = 7; goto match; }
case 6: if (*t++ == p0) { fixup = 6; goto match; }
case 5: if (*t++ == p0) { fixup = 5; goto match; }
case 4: if (*t++ == p0) { fixup = 4; goto match; }
case 3: if (*t++ == p0) { fixup = 3; goto match; }
case 2: if (*t++ == p0) { fixup = 2; goto match; }
case 1: if (*t++ == p0) { fixup = 1; goto match; }
}
while (t != textend) {
if (t[0] == p0) { t += 1; fixup = 8; goto match; }
if (t[1] == p0) { t += 2; fixup = 7; goto match; }
if (t[2] == p0) { t += 3; fixup = 6; goto match; }
if (t[3] == p0) { t += 4; fixup = 5; goto match; }
if (t[4] == p0) { t += 5; fixup = 4; goto match; }
if (t[5] == p0) { t += 6; fixup = 3; goto match; }
if (t[6] == p0) { t += 7; fixup = 2; goto match; }
if (t[7] == p0) { t += 8; fixup = 1; goto match; }
t += 8;
continue;
do {
case 0: if (*t++ == p0) { fixup = 8; goto match; }
case 7: if (*t++ == p0) { fixup = 7; goto match; }
case 6: if (*t++ == p0) { fixup = 6; goto match; }
case 5: if (*t++ == p0) { fixup = 5; goto match; }
case 4: if (*t++ == p0) { fixup = 4; goto match; }
case 3: if (*t++ == p0) { fixup = 3; goto match; }
case 2: if (*t++ == p0) { fixup = 2; goto match; }
case 1: if (*t++ == p0) { fixup = 1; goto match; }
continue;
do {
if (*t++ == p0) {
match:
if (!InnerMatch::match(patNext, t, extent))
goto failed_match;
return t - text - 1;
}
failed_match:;
} while (--fixup > 0);
} while(t != textend);
if (*t++ == p0) {
match:
if (!InnerMatch::match(patNext, t, extent))
goto failed_match;
return t - text - 1;
}
failed_match:;
} while (--fixup > 0);
}
return -1;
}
@ -1209,10 +1218,10 @@ StringMatch(const jschar *text, jsuint textlen,
*/
return
#if !defined(__linux__)
patlen > 128 ? Duff<MemCmp>(text, textlen, pat, patlen)
patlen > 128 ? UnrolledMatch<MemCmp>(text, textlen, pat, patlen)
:
#endif
Duff<ManualCmp>(text, textlen, pat, patlen);
UnrolledMatch<ManualCmp>(text, textlen, pat, patlen);
}
static JSBool
@ -1719,13 +1728,13 @@ InterpretDollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData &rdata,
if (JS7_ISDEC(dc)) {
/* ECMA-262 Edition 3: 1-9 or 01-99 */
num = JS7_UNDEC(dc);
if (num > res->parenCount)
if (num > res->parens.length())
return NULL;
cp = dp + 2;
if (cp < ep && (dc = *cp, JS7_ISDEC(dc))) {
tmp = 10 * num + JS7_UNDEC(dc);
if (tmp <= res->parenCount) {
if (tmp <= res->parens.length()) {
cp++;
num = tmp;
}
@ -1736,7 +1745,7 @@ InterpretDollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData &rdata,
/* Adjust num from 1 $n-origin to 0 array-index-origin. */
num--;
*skip = cp - dp;
return REGEXP_PAREN_SUBSTRING(res, num);
return (num < res->parens.length()) ? &res->parens[num] : &js_EmptySubString;
}
*skip = 2;
@ -1769,6 +1778,20 @@ PushRegExpSubstr(JSContext *cx, const JSSubString &sub, jsval *&sp)
return true;
}
class PreserveRegExpStatics {
JSContext *cx;
JSRegExpStatics save;
public:
PreserveRegExpStatics(JSContext *cx) : cx(cx), save(cx) {
save.copy(cx->regExpStatics);
}
~PreserveRegExpStatics() {
cx->regExpStatics.copy(save);
}
};
static bool
FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
{
@ -1780,8 +1803,6 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
lambda = rdata.lambda;
if (lambda) {
uintN i, m, n;
LeaveTrace(cx);
/*
@ -1802,17 +1823,7 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
}
jsval* invokevp = rdata.invokevp;
MUST_FLOW_THROUGH("lambda_out");
bool ok = false;
bool freeMoreParens = false;
/*
* Save the regExpStatics from the current regexp, since they may be
* clobbered by a RegExp usage in the lambda function. Note that all
* members of JSRegExpStatics are JSSubStrings, so not GC roots, save
* input, which is rooted otherwise via vp[1] in str_replace.
*/
JSRegExpStatics save = cx->regExpStatics;
PreserveRegExpStatics save(cx);
/* Push lambda and its 'this' parameter. */
jsval *sp = invokevp;
@ -1821,27 +1832,13 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
/* Push $&, $1, $2, ... */
if (!PushRegExpSubstr(cx, cx->regExpStatics.lastMatch, sp))
goto lambda_out;
return false;
i = 0;
m = cx->regExpStatics.parenCount;
n = JS_MIN(m, 9);
for (uintN j = 0; i < n; i++, j++) {
if (!PushRegExpSubstr(cx, cx->regExpStatics.parens[j], sp))
goto lambda_out;
uintN i = 0;
for (uintN n = cx->regExpStatics.parens.length(); i < n; i++) {
if (!PushRegExpSubstr(cx, cx->regExpStatics.parens[i], sp))
return false;
}
for (uintN j = 0; i < m; i++, j++) {
if (!PushRegExpSubstr(cx, cx->regExpStatics.moreParens[j], sp))
goto lambda_out;
}
/*
* We need to clear moreParens in the top-of-stack cx->regExpStatics
* so it won't be possibly realloc'ed, leaving the bottom-of-stack
* moreParens pointing to freed memory.
*/
cx->regExpStatics.moreParens = NULL;
freeMoreParens = true;
/* Make sure to push undefined for any unmatched parens. */
for (; i < p; i++)
@ -1852,7 +1849,7 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
*sp++ = STRING_TO_JSVAL(rdata.str);
if (!js_Invoke(cx, argc, invokevp, 0))
goto lambda_out;
return false;
/*
* NB: we count on the newborn string root to hold any string
@ -1861,18 +1858,12 @@ FindReplaceLength(JSContext *cx, ReplaceData &rdata, size_t *sizep)
*/
repstr = js_ValueToString(cx, *invokevp);
if (!repstr)
goto lambda_out;
return false;
rdata.repstr = repstr;
*sizep = repstr->length();
ok = true;
lambda_out:
if (freeMoreParens)
cx->free(cx->regExpStatics.moreParens);
cx->regExpStatics = save;
return ok;
return true;
}
repstr = rdata.repstr;
@ -2212,10 +2203,11 @@ str_split(JSContext *cx, uintN argc, jsval *vp)
* substring that was delimited.
*/
if (re && sep->chars) {
for (uintN num = 0; num < cx->regExpStatics.parenCount; num++) {
JSRegExpStatics *res = &cx->regExpStatics;
for (uintN num = 0; num < res->parens.length(); num++) {
if (limited && len >= limit)
break;
JSSubString *parsub = REGEXP_PAREN_SUBSTRING(&cx->regExpStatics, num);
JSSubString *parsub = &res->parens[num];
sub = js_NewStringCopyN(cx, parsub->chars, parsub->length);
if (!sub || !splits.push(sub))
return false;

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

@ -43,6 +43,7 @@ class JSBackgroundTask {
friend class JSBackgroundThread;
JSBackgroundTask* next;
public:
virtual ~JSBackgroundTask() {}
virtual void run() = 0;
};

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

@ -2746,7 +2746,6 @@ NativeToValue(JSContext* cx, jsval& v, TraceType type, double* slot)
switch (type) {
case TT_OBJECT:
v = OBJECT_TO_JSVAL(*(JSObject**)slot);
JS_ASSERT(v != JSVAL_ERROR_COOKIE); /* don't leak JSVAL_ERROR_COOKIE */
debug_only_printf(LC_TMTracer,
"object<%p:%s> ", (void*)JSVAL_TO_OBJECT(v),
JSVAL_IS_NULL(v)
@ -2779,7 +2778,6 @@ NativeToValue(JSContext* cx, jsval& v, TraceType type, double* slot)
case TT_JSVAL:
v = *(jsval*)slot;
JS_ASSERT(v != JSVAL_ERROR_COOKIE); /* don't leak JSVAL_ERROR_COOKIE */
debug_only_printf(LC_TMTracer, "box<%p> ", (void*)v);
break;
@ -9427,8 +9425,7 @@ TraceRecorder::box_jsval(jsval v, LIns* v_ins)
}
LIns* args[] = { v_ins, cx_ins };
v_ins = lir->insCall(&js_BoxDouble_ci, args);
guard(false, lir->ins2(LIR_peq, v_ins, INS_CONSTWORD(JSVAL_ERROR_COOKIE)),
OOM_EXIT);
guard(false, lir->insEqP_0(v_ins), OOM_EXIT);
return v_ins;
}
switch (JSVAL_TAG(v)) {
@ -10546,7 +10543,7 @@ TraceRecorder::newArray(JSObject* ctor, uint32 argc, jsval* argv, jsval* rval)
}
if (argc > 0)
stobj_set_fslot(arr_ins, JSObject::JSSLOT_ARRAY_COUNT, INS_CONST(argc));
stobj_set_fslot(arr_ins, JSObject::JSSLOT_DENSE_ARRAY_COUNT, INS_CONST(argc));
}
set(rval, arr_ins);
@ -10670,9 +10667,6 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[],
case FAIL_VOID:
guard(false, lir->ins2ImmI(LIR_eq, res_ins, JSVAL_TO_SPECIAL(JSVAL_VOID)), OOM_EXIT);
break;
case FAIL_COOKIE:
guard(false, lir->ins2(LIR_peq, res_ins, INS_CONSTWORD(JSVAL_ERROR_COOKIE)), OOM_EXIT);
break;
default:;
}
@ -10681,7 +10675,7 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[],
/*
* The return value will be processed by NativeCallComplete since
* we have to know the actual return value type for calls that return
* jsval (like Array_p_pop).
* jsval.
*/
pendingSpecializedNative = sn;
@ -13127,7 +13121,8 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
VMSideExit* exit = snapshot(BRANCH_EXIT);
/* check that the index is within bounds */
LIns* dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots), ACC_OTHER);
LIns* dslots_ins =
addName(lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots), ACC_OTHER), "dslots");
jsuint capacity = obj->getDenseArrayCapacity();
bool within = (jsuint(idx) < obj->getArrayLength() && jsuint(idx) < capacity);
if (!within) {
@ -13141,32 +13136,18 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
NULL);
}
/* If not idx < length, stay on trace (and read value as undefined). */
LIns* length = stobj_get_fslot(obj_ins, JSObject::JSSLOT_ARRAY_LENGTH);
if (pidx_ins != length) {
LIns* br2 = lir->insBranch(LIR_jf,
lir->ins2(LIR_pult, pidx_ins, length),
NULL);
/* If not idx < min(length, capacity), stay on trace (and read value as undefined). */
LIns* minLenCap =
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
LIns* br2 = lir->insBranch(LIR_jf,
lir->ins2(LIR_pult, pidx_ins, minLenCap),
NULL);
/* If dslots is NULL, stay on trace (and read value as undefined). */
LIns* br3 = lir->insBranch(LIR_jt, lir->insEqP_0(dslots_ins), NULL);
/* If not idx < capacity, stay on trace (and read value as undefined). */
LIns* br4 = lir->insBranch(LIR_jf,
lir->ins2(LIR_pult,
pidx_ins,
lir->insLoad(LIR_ldp, dslots_ins,
-(int)sizeof(jsval), ACC_OTHER)),
NULL);
lir->insGuard(LIR_x, NULL, createGuardRecord(exit));
LIns* label = lir->ins0(LIR_label);
if (br1)
br1->setTarget(label);
br2->setTarget(label);
br3->setTarget(label);
br4->setTarget(label);
}
lir->insGuard(LIR_x, NULL, createGuardRecord(exit));
LIns* label = lir->ins0(LIR_label);
if (br1)
br1->setTarget(label);
br2->setTarget(label);
CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, MISMATCH_EXIT));
@ -13185,21 +13166,11 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
exit);
}
/* Guard array length */
/* Guard array min(length, capacity). */
LIns* minLenCap =
addName(stobj_get_fslot(obj_ins, JSObject::JSSLOT_DENSE_ARRAY_MINLENCAP), "minLenCap");
guard(true,
lir->ins2(LIR_pult, pidx_ins, stobj_get_fslot(obj_ins, JSObject::JSSLOT_ARRAY_LENGTH)),
exit);
/* dslots must not be NULL */
guard(false,
lir->insEqP_0(dslots_ins),
exit);
/* Guard array capacity */
guard(true,
lir->ins2(LIR_pult,
pidx_ins,
lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval), ACC_OTHER)),
lir->ins2(LIR_pult, pidx_ins, minLenCap),
exit);
/* Load the value and guard on its type to unbox it. */
@ -15059,7 +15030,7 @@ CallIteratorNext_tn(JSContext* cx, jsbytecode* pc, JSObject* iterobj)
if (!ok) {
SetBuiltinError(cx);
return JSVAL_ERROR_COOKIE;
return JSVAL_NULL; /* error occured, value doesn't matter. */
}
return tvr.value();
}
@ -15221,7 +15192,7 @@ TraceRecorder::record_JSOP_NEWARRAY()
}
if (count > 0)
stobj_set_fslot(v_ins, JSObject::JSSLOT_ARRAY_COUNT, INS_CONST(count));
stobj_set_fslot(v_ins, JSObject::JSSLOT_DENSE_ARRAY_COUNT, INS_CONST(count));
stack(-int(len), v_ins);
return ARECORD_CONTINUE;

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

@ -5185,9 +5185,8 @@ js_TestXMLEquality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
HasSimpleContent(xml))) {
ok = js_EnterLocalRootScope(cx);
if (ok) {
str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
vstr = js_ValueToString(cx, v);
ok = str && vstr;
ok = (str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj))) &&
(vstr = js_ValueToString(cx, v));
if (ok)
*bp = js_EqualStrings(str, vstr);
js_LeaveLocalRootScope(cx);
@ -5200,9 +5199,8 @@ js_TestXMLEquality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
ok = js_EnterLocalRootScope(cx);
if (ok) {
if (HasSimpleContent(xml)) {
str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
vstr = js_ValueToString(cx, v);
ok = str && vstr;
ok = (str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj))) &&
(vstr = js_ValueToString(cx, v));
if (ok)
*bp = js_EqualStrings(str, vstr);
} else if (JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v)) {

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

@ -1 +1 @@
53522168256873ff92a5cf1668d3ef8e65a87f38
b49dd62330e017769dfdea9c87a74698179c7f45

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

@ -1526,7 +1526,7 @@ namespace nanojit
case LIR_rshuq:
case LIR_rshq:
case LIR_orq:
case LIR_qxor:
case LIR_xorq:
countlir_alu();
ins->oprnd1()->setResultLive();
ins->oprnd2()->setResultLive();

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

@ -1325,7 +1325,7 @@ namespace nanojit
case LIR_xori:
CASE64(LIR_andq:)
CASE64(LIR_orq:)
CASE64(LIR_qxor:)
CASE64(LIR_xorq:)
CASESF(LIR_ii2d:)
case LIR_file:
case LIR_line:
@ -1710,7 +1710,7 @@ namespace nanojit
case LIR_divd:
case LIR_andi: CASE64(LIR_andq:)
case LIR_ori: CASE64(LIR_orq:)
case LIR_xori: CASE64(LIR_qxor:)
case LIR_xori: CASE64(LIR_xorq:)
case LIR_lshi: CASE64(LIR_lshq:)
case LIR_rshi: CASE64(LIR_rshq:)
case LIR_rshui: CASE64(LIR_rshuq:)
@ -2922,7 +2922,7 @@ namespace nanojit
#ifdef NANOJIT_64BIT
case LIR_andq:
case LIR_orq:
case LIR_qxor:
case LIR_xorq:
case LIR_addq:
case LIR_eqq:
case LIR_ltq:

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

@ -58,7 +58,7 @@ better code
- spill gp values to xmm registers?
- prefer xmm registers for copies since gprs are in higher demand?
- stack arg doubles
- stack based LIR_param
- stack based LIR_paramp
tracing
- nFragExit
@ -654,12 +654,12 @@ namespace nanojit
switch (ins->opcode()) {
default:
TODO(asm_shift);
case LIR_qursh: SHRQ(rr); break;
case LIR_qirsh: SARQ(rr); break;
case LIR_qilsh: SHLQ(rr); break;
case LIR_ush: SHR( rr); break;
case LIR_rsh: SAR( rr); break;
case LIR_lsh: SHL( rr); break;
case LIR_rshuq: SHRQ(rr); break;
case LIR_rshq: SARQ(rr); break;
case LIR_lshq: SHLQ(rr); break;
case LIR_rshui: SHR( rr); break;
case LIR_rshi: SAR( rr); break;
case LIR_lshi: SHL( rr); break;
}
if (rr != ra)
MR(rr, ra);
@ -674,12 +674,12 @@ namespace nanojit
int shift = ins->oprnd2()->immI() & 63;
switch (ins->opcode()) {
default: TODO(shiftimm);
case LIR_qursh: SHRQI(rr, shift); break;
case LIR_qirsh: SARQI(rr, shift); break;
case LIR_qilsh: SHLQI(rr, shift); break;
case LIR_ush: SHRI( rr, shift); break;
case LIR_rsh: SARI( rr, shift); break;
case LIR_lsh: SHLI( rr, shift); break;
case LIR_rshuq: SHRQI(rr, shift); break;
case LIR_rshq: SARQI(rr, shift); break;
case LIR_lshq: SHLQI(rr, shift); break;
case LIR_rshui: SHRI( rr, shift); break;
case LIR_rshi: SARI( rr, shift); break;
case LIR_lshi: SHLI( rr, shift); break;
}
if (rr != ra)
MR(rr, ra);
@ -700,7 +700,7 @@ namespace nanojit
int32_t imm = getImm32(b);
LOpcode op = ins->opcode();
Register rr, ra;
if (op == LIR_mul || op == LIR_mulxov) {
if (op == LIR_muli || op == LIR_mulxovi) {
// Special case: imul-by-imm has true 3-addr form. So we don't
// need the MR(rr, ra) after the IMULI.
beginOp1Regs(ins, GpRegs, rr, ra);
@ -713,32 +713,32 @@ namespace nanojit
if (isS8(imm)) {
switch (ins->opcode()) {
default: TODO(arith_imm8);
case LIR_add:
case LIR_addxov: ADDLR8(rr, imm); break; // XXX: bug 547125: could use LEA for LIR_add
case LIR_and: ANDLR8(rr, imm); break;
case LIR_or: ORLR8( rr, imm); break;
case LIR_sub:
case LIR_subxov: SUBLR8(rr, imm); break;
case LIR_xor: XORLR8(rr, imm); break;
case LIR_qiadd: ADDQR8(rr, imm); break;
case LIR_qiand: ANDQR8(rr, imm); break;
case LIR_qior: ORQR8( rr, imm); break;
case LIR_qxor: XORQR8(rr, imm); break;
case LIR_addi:
case LIR_addxovi: ADDLR8(rr, imm); break; // XXX: bug 547125: could use LEA for LIR_addi
case LIR_andi: ANDLR8(rr, imm); break;
case LIR_ori: ORLR8( rr, imm); break;
case LIR_subi:
case LIR_subxovi: SUBLR8(rr, imm); break;
case LIR_xori: XORLR8(rr, imm); break;
case LIR_addq: ADDQR8(rr, imm); break;
case LIR_andq: ANDQR8(rr, imm); break;
case LIR_orq: ORQR8( rr, imm); break;
case LIR_xorq: XORQR8(rr, imm); break;
}
} else {
switch (ins->opcode()) {
default: TODO(arith_imm);
case LIR_add:
case LIR_addxov: ADDLRI(rr, imm); break; // XXX: bug 547125: could use LEA for LIR_add
case LIR_and: ANDLRI(rr, imm); break;
case LIR_or: ORLRI( rr, imm); break;
case LIR_sub:
case LIR_subxov: SUBLRI(rr, imm); break;
case LIR_xor: XORLRI(rr, imm); break;
case LIR_qiadd: ADDQRI(rr, imm); break;
case LIR_qiand: ANDQRI(rr, imm); break;
case LIR_qior: ORQRI( rr, imm); break;
case LIR_qxor: XORQRI(rr, imm); break;
case LIR_addi:
case LIR_addxovi: ADDLRI(rr, imm); break; // XXX: bug 547125: could use LEA for LIR_addi
case LIR_andi: ANDLRI(rr, imm); break;
case LIR_ori: ORLRI( rr, imm); break;
case LIR_subi:
case LIR_subxovi: SUBLRI(rr, imm); break;
case LIR_xori: XORLRI(rr, imm); break;
case LIR_addq: ADDQRI(rr, imm); break;
case LIR_andq: ANDQRI(rr, imm); break;
case LIR_orq: ORQRI( rr, imm); break;
case LIR_xorq: XORQRI(rr, imm); break;
}
}
if (rr != ra)
@ -747,9 +747,9 @@ namespace nanojit
endOpRegs(ins, rr, ra);
}
// Generates code for a LIR_div that doesn't have a subsequent LIR_mod.
// Generates code for a LIR_divi that doesn't have a subsequent LIR_modi.
void Assembler::asm_div(LIns *div) {
NanoAssert(div->isop(LIR_div));
NanoAssert(div->isop(LIR_divi));
LIns *a = div->oprnd1();
LIns *b = div->oprnd2();
@ -772,12 +772,12 @@ namespace nanojit
}
}
// Generates code for a LIR_mod(LIR_div(divL, divR)) sequence.
// Generates code for a LIR_modi(LIR_divi(divL, divR)) sequence.
void Assembler::asm_div_mod(LIns *mod) {
LIns *div = mod->oprnd1();
NanoAssert(mod->isop(LIR_mod));
NanoAssert(div->isop(LIR_div));
NanoAssert(mod->isop(LIR_modi));
NanoAssert(div->isop(LIR_divi));
LIns *divL = div->oprnd1();
LIns *divR = div->oprnd2();
@ -807,15 +807,15 @@ namespace nanojit
Register rr, ra, rb = UnspecifiedReg; // init to shut GCC up
switch (ins->opcode()) {
case LIR_lsh: case LIR_qilsh:
case LIR_rsh: case LIR_qirsh:
case LIR_ush: case LIR_qursh:
case LIR_lshi: case LIR_lshq:
case LIR_rshi: case LIR_rshq:
case LIR_rshui: case LIR_rshuq:
asm_shift(ins);
return;
case LIR_mod:
case LIR_modi:
asm_div_mod(ins);
return;
case LIR_div:
case LIR_divi:
// Nb: if the div feeds into a mod it will be handled by
// asm_div_mod() rather than here.
asm_div(ins);
@ -831,20 +831,20 @@ namespace nanojit
}
beginOp2Regs(ins, GpRegs, rr, ra, rb);
switch (ins->opcode()) {
default: TODO(asm_arith);
case LIR_or: ORLRR(rr, rb); break;
case LIR_sub:
case LIR_subxov: SUBRR(rr, rb); break;
case LIR_add:
case LIR_addxov: ADDRR(rr, rb); break; // XXX: bug 547125: could use LEA for LIR_add
case LIR_and: ANDRR(rr, rb); break;
case LIR_xor: XORRR(rr, rb); break;
case LIR_mul:
case LIR_mulxov: IMUL(rr, rb); break;
case LIR_qxor: XORQRR(rr, rb); break;
case LIR_qior: ORQRR(rr, rb); break;
case LIR_qiand: ANDQRR(rr, rb); break;
case LIR_qiadd: ADDQRR(rr, rb); break;
default: TODO(asm_arith);
case LIR_ori: ORLRR(rr, rb); break;
case LIR_subi:
case LIR_subxovi: SUBRR(rr, rb); break;
case LIR_addi:
case LIR_addxovi: ADDRR(rr, rb); break; // XXX: bug 547125: could use LEA for LIR_addi
case LIR_andi: ANDRR(rr, rb); break;
case LIR_xori: XORRR(rr, rb); break;
case LIR_muli:
case LIR_mulxovi: IMUL(rr, rb); break;
case LIR_xorq: XORQRR(rr, rb); break;
case LIR_orq: ORQRR(rr, rb); break;
case LIR_andq: ANDQRR(rr, rb); break;
case LIR_addq: ADDQRR(rr, rb); break;
}
if (rr != ra)
MR(rr, ra);
@ -858,10 +858,10 @@ namespace nanojit
beginOp2Regs(ins, FpRegs, rr, ra, rb);
switch (ins->opcode()) {
default: TODO(asm_fop);
case LIR_fdiv: DIVSD(rr, rb); break;
case LIR_fmul: MULSD(rr, rb); break;
case LIR_fadd: ADDSD(rr, rb); break;
case LIR_fsub: SUBSD(rr, rb); break;
case LIR_divd: DIVSD(rr, rb); break;
case LIR_muld: MULSD(rr, rb); break;
case LIR_addd: ADDSD(rr, rb); break;
case LIR_subd: SUBSD(rr, rb); break;
}
if (rr != ra) {
asm_nongp_copy(rr, ra);
@ -874,7 +874,7 @@ namespace nanojit
Register rr, ra;
beginOp1Regs(ins, GpRegs, rr, ra);
if (ins->isop(LIR_not))
if (ins->isop(LIR_noti))
NOT(rr);
else
NEG(rr);
@ -885,7 +885,7 @@ namespace nanojit
}
void Assembler::asm_call(LIns *ins) {
Register rr = ( ins->isop(LIR_fcall) ? XMM0 : retRegs[0] );
Register rr = ( ins->isop(LIR_calld) ? XMM0 : retRegs[0] );
prepareResultReg(ins, rmask(rr));
evictScratchRegsExcept(rmask(rr));
@ -1025,7 +1025,7 @@ namespace nanojit
Register rr, ra;
beginOp1Regs(ins, GpRegs, rr, ra);
NanoAssert(IsGpReg(ra));
if (ins->isop(LIR_u2q)) {
if (ins->isop(LIR_ui2uq)) {
MOVLR(rr, ra); // 32bit mov zeros the upper 32bits of the target
} else {
NanoAssert(ins->isop(LIR_i2q));
@ -1077,8 +1077,8 @@ namespace nanojit
LIns* iftrue = ins->oprnd2();
LIns* iffalse = ins->oprnd3();
NanoAssert(cond->isCmp());
NanoAssert((ins->isop(LIR_cmov) && iftrue->isI() && iffalse->isI()) ||
(ins->isop(LIR_qcmov) && iftrue->isQ() && iffalse->isQ()));
NanoAssert((ins->isop(LIR_cmovi) && iftrue->isI() && iffalse->isI()) ||
(ins->isop(LIR_cmovq) && iftrue->isQ() && iffalse->isQ()));
Register rr = prepareResultReg(ins, GpRegs);
@ -1091,30 +1091,30 @@ namespace nanojit
// codes between the MRcc generation here and the asm_cmp() call
// below. See asm_cmp() for more details.
LOpcode condop = cond->opcode();
if (ins->opcode() == LIR_cmov) {
if (ins->opcode() == LIR_cmovi) {
switch (condop) {
case LIR_eq: case LIR_qeq: CMOVNE( rr, rf); break;
case LIR_lt: case LIR_qlt: CMOVNL( rr, rf); break;
case LIR_gt: case LIR_qgt: CMOVNG( rr, rf); break;
case LIR_le: case LIR_qle: CMOVNLE(rr, rf); break;
case LIR_ge: case LIR_qge: CMOVNGE(rr, rf); break;
case LIR_ult: case LIR_qult: CMOVNB( rr, rf); break;
case LIR_ugt: case LIR_qugt: CMOVNA( rr, rf); break;
case LIR_ule: case LIR_qule: CMOVNBE(rr, rf); break;
case LIR_uge: case LIR_quge: CMOVNAE(rr, rf); break;
case LIR_eqi: case LIR_eqq: CMOVNE( rr, rf); break;
case LIR_lti: case LIR_ltq: CMOVNL( rr, rf); break;
case LIR_gti: case LIR_gtq: CMOVNG( rr, rf); break;
case LIR_lei: case LIR_leq: CMOVNLE(rr, rf); break;
case LIR_gei: case LIR_geq: CMOVNGE(rr, rf); break;
case LIR_ltui: case LIR_ltuq: CMOVNB( rr, rf); break;
case LIR_gtui: case LIR_gtuq: CMOVNA( rr, rf); break;
case LIR_leui: case LIR_leuq: CMOVNBE(rr, rf); break;
case LIR_geui: case LIR_geuq: CMOVNAE(rr, rf); break;
default: NanoAssert(0); break;
}
} else {
switch (condop) {
case LIR_eq: case LIR_qeq: CMOVQNE( rr, rf); break;
case LIR_lt: case LIR_qlt: CMOVQNL( rr, rf); break;
case LIR_gt: case LIR_qgt: CMOVQNG( rr, rf); break;
case LIR_le: case LIR_qle: CMOVQNLE(rr, rf); break;
case LIR_ge: case LIR_qge: CMOVQNGE(rr, rf); break;
case LIR_ult: case LIR_qult: CMOVQNB( rr, rf); break;
case LIR_ugt: case LIR_qugt: CMOVQNA( rr, rf); break;
case LIR_ule: case LIR_qule: CMOVQNBE(rr, rf); break;
case LIR_uge: case LIR_quge: CMOVQNAE(rr, rf); break;
case LIR_eqi: case LIR_eqq: CMOVQNE( rr, rf); break;
case LIR_lti: case LIR_ltq: CMOVQNL( rr, rf); break;
case LIR_gti: case LIR_gtq: CMOVQNG( rr, rf); break;
case LIR_lei: case LIR_leq: CMOVQNLE(rr, rf); break;
case LIR_gei: case LIR_geq: CMOVQNGE(rr, rf); break;
case LIR_ltui: case LIR_ltuq: CMOVQNB( rr, rf); break;
case LIR_gtui: case LIR_gtuq: CMOVQNA( rr, rf); break;
case LIR_leui: case LIR_leuq: CMOVQNBE(rr, rf); break;
case LIR_geui: case LIR_geuq: CMOVQNAE(rr, rf); break;
default: NanoAssert(0); break;
}
}
@ -1145,56 +1145,56 @@ namespace nanojit
if (target && isTargetWithinS8(target)) {
if (onFalse) {
switch (condop) {
case LIR_eq: case LIR_qeq: JNE8( 8, target); break;
case LIR_lt: case LIR_qlt: JNL8( 8, target); break;
case LIR_gt: case LIR_qgt: JNG8( 8, target); break;
case LIR_le: case LIR_qle: JNLE8(8, target); break;
case LIR_ge: case LIR_qge: JNGE8(8, target); break;
case LIR_ult: case LIR_qult: JNB8( 8, target); break;
case LIR_ugt: case LIR_qugt: JNA8( 8, target); break;
case LIR_ule: case LIR_qule: JNBE8(8, target); break;
case LIR_uge: case LIR_quge: JNAE8(8, target); break;
case LIR_eqi: case LIR_eqq: JNE8( 8, target); break;
case LIR_lti: case LIR_ltq: JNL8( 8, target); break;
case LIR_gti: case LIR_gtq: JNG8( 8, target); break;
case LIR_lei: case LIR_leq: JNLE8(8, target); break;
case LIR_gei: case LIR_geq: JNGE8(8, target); break;
case LIR_ltui: case LIR_ltuq: JNB8( 8, target); break;
case LIR_gtui: case LIR_gtuq: JNA8( 8, target); break;
case LIR_leui: case LIR_leuq: JNBE8(8, target); break;
case LIR_geui: case LIR_geuq: JNAE8(8, target); break;
default: NanoAssert(0); break;
}
} else {
switch (condop) {
case LIR_eq: case LIR_qeq: JE8( 8, target); break;
case LIR_lt: case LIR_qlt: JL8( 8, target); break;
case LIR_gt: case LIR_qgt: JG8( 8, target); break;
case LIR_le: case LIR_qle: JLE8(8, target); break;
case LIR_ge: case LIR_qge: JGE8(8, target); break;
case LIR_ult: case LIR_qult: JB8( 8, target); break;
case LIR_ugt: case LIR_qugt: JA8( 8, target); break;
case LIR_ule: case LIR_qule: JBE8(8, target); break;
case LIR_uge: case LIR_quge: JAE8(8, target); break;
case LIR_eqi: case LIR_eqq: JE8( 8, target); break;
case LIR_lti: case LIR_ltq: JL8( 8, target); break;
case LIR_gti: case LIR_gtq: JG8( 8, target); break;
case LIR_lei: case LIR_leq: JLE8(8, target); break;
case LIR_gei: case LIR_geq: JGE8(8, target); break;
case LIR_ltui: case LIR_ltuq: JB8( 8, target); break;
case LIR_gtui: case LIR_gtuq: JA8( 8, target); break;
case LIR_leui: case LIR_leuq: JBE8(8, target); break;
case LIR_geui: case LIR_geuq: JAE8(8, target); break;
default: NanoAssert(0); break;
}
}
} else {
if (onFalse) {
switch (condop) {
case LIR_eq: case LIR_qeq: JNE( 8, target); break;
case LIR_lt: case LIR_qlt: JNL( 8, target); break;
case LIR_gt: case LIR_qgt: JNG( 8, target); break;
case LIR_le: case LIR_qle: JNLE(8, target); break;
case LIR_ge: case LIR_qge: JNGE(8, target); break;
case LIR_ult: case LIR_qult: JNB( 8, target); break;
case LIR_ugt: case LIR_qugt: JNA( 8, target); break;
case LIR_ule: case LIR_qule: JNBE(8, target); break;
case LIR_uge: case LIR_quge: JNAE(8, target); break;
case LIR_eqi: case LIR_eqq: JNE( 8, target); break;
case LIR_lti: case LIR_ltq: JNL( 8, target); break;
case LIR_gti: case LIR_gtq: JNG( 8, target); break;
case LIR_lei: case LIR_leq: JNLE(8, target); break;
case LIR_gei: case LIR_geq: JNGE(8, target); break;
case LIR_ltui: case LIR_ltuq: JNB( 8, target); break;
case LIR_gtui: case LIR_gtuq: JNA( 8, target); break;
case LIR_leui: case LIR_leuq: JNBE(8, target); break;
case LIR_geui: case LIR_geuq: JNAE(8, target); break;
default: NanoAssert(0); break;
}
} else {
switch (condop) {
case LIR_eq: case LIR_qeq: JE( 8, target); break;
case LIR_lt: case LIR_qlt: JL( 8, target); break;
case LIR_gt: case LIR_qgt: JG( 8, target); break;
case LIR_le: case LIR_qle: JLE(8, target); break;
case LIR_ge: case LIR_qge: JGE(8, target); break;
case LIR_ult: case LIR_qult: JB( 8, target); break;
case LIR_ugt: case LIR_qugt: JA( 8, target); break;
case LIR_ule: case LIR_qule: JBE(8, target); break;
case LIR_uge: case LIR_quge: JAE(8, target); break;
case LIR_eqi: case LIR_eqq: JE( 8, target); break;
case LIR_lti: case LIR_ltq: JL( 8, target); break;
case LIR_gti: case LIR_gtq: JG( 8, target); break;
case LIR_lei: case LIR_leq: JLE(8, target); break;
case LIR_gei: case LIR_geq: JGE(8, target); break;
case LIR_ltui: case LIR_ltuq: JB( 8, target); break;
case LIR_gtui: case LIR_gtuq: JA( 8, target); break;
case LIR_leui: case LIR_leuq: JBE(8, target); break;
case LIR_geui: case LIR_geuq: JAE(8, target); break;
default: NanoAssert(0); break;
}
}
@ -1287,7 +1287,7 @@ namespace nanojit
NIns *patch;
LIns *a = cond->oprnd1();
LIns *b = cond->oprnd2();
if (condop == LIR_feq) {
if (condop == LIR_eqd) {
if (onFalse) {
// branch if unordered or !=
JP(16, target); // underrun of 12 needed, round up for overhang --> 16
@ -1305,19 +1305,19 @@ namespace nanojit
}
}
else {
if (condop == LIR_flt) {
condop = LIR_fgt;
if (condop == LIR_ltd) {
condop = LIR_gtd;
LIns *t = a; a = b; b = t;
} else if (condop == LIR_fle) {
condop = LIR_fge;
} else if (condop == LIR_led) {
condop = LIR_ged;
LIns *t = a; a = b; b = t;
}
if (condop == LIR_fgt) {
if (condop == LIR_gtd) {
if (onFalse)
JBE(8, target);
else
JA(8, target);
} else { // LIR_fge
} else { // LIR_ged
if (onFalse)
JB(8, target);
else
@ -1333,7 +1333,7 @@ namespace nanojit
LOpcode op = ins->opcode();
LIns *a = ins->oprnd1();
LIns *b = ins->oprnd2();
if (op == LIR_feq) {
if (op == LIR_eqd) {
// result = ZF & !PF, must do logic on flags
// r = al|bl|cl|dl, can only use rh without rex prefix
Register r = prepareResultReg(ins, 1<<RAX|1<<RCX|1<<RDX|1<<RBX);
@ -1342,16 +1342,16 @@ namespace nanojit
X86_SETNP(r); // setnp rh rh = !PF
X86_SETE(r); // sete rl rl = ZF
} else {
if (op == LIR_flt) {
op = LIR_fgt;
if (op == LIR_ltd) {
op = LIR_gtd;
LIns *t = a; a = b; b = t;
} else if (op == LIR_fle) {
op = LIR_fge;
} else if (op == LIR_led) {
op = LIR_ged;
LIns *t = a; a = b; b = t;
}
Register r = prepareResultReg(ins, GpRegs); // x64 can use any GPR as setcc target
MOVZX8(r, r);
if (op == LIR_fgt)
if (op == LIR_gtd)
SETA(r);
else
SETAE(r);
@ -1396,13 +1396,13 @@ namespace nanojit
}
bool Assembler::canRemat(LIns* ins) {
return ins->isImmAny() || ins->isop(LIR_alloc) || canRematLEA(ins);
return ins->isImmAny() || ins->isop(LIR_allocp) || canRematLEA(ins);
}
// WARNING: the code generated by this function must not affect the
// condition codes. See asm_cmp() for details.
void Assembler::asm_restore(LIns *ins, Register r) {
if (ins->isop(LIR_alloc)) {
if (ins->isop(LIR_allocp)) {
int d = arDisp(ins);
LEAQRM(r, d, FP);
}
@ -1448,24 +1448,24 @@ namespace nanojit
switch (op) {
default:
TODO(cond);
case LIR_qeq:
case LIR_eq: SETE(r); break;
case LIR_qlt:
case LIR_lt: SETL(r); break;
case LIR_qle:
case LIR_le: SETLE(r); break;
case LIR_qgt:
case LIR_gt: SETG(r); break;
case LIR_qge:
case LIR_ge: SETGE(r); break;
case LIR_qult:
case LIR_ult: SETB(r); break;
case LIR_qule:
case LIR_ule: SETBE(r); break;
case LIR_qugt:
case LIR_ugt: SETA(r); break;
case LIR_quge:
case LIR_uge: SETAE(r); break;
case LIR_eqq:
case LIR_eqi: SETE(r); break;
case LIR_ltq:
case LIR_lti: SETL(r); break;
case LIR_leq:
case LIR_lei: SETLE(r); break;
case LIR_gtq:
case LIR_gti: SETG(r); break;
case LIR_geq:
case LIR_gei: SETGE(r); break;
case LIR_ltuq:
case LIR_ltui: SETB(r); break;
case LIR_leuq:
case LIR_leui: SETBE(r); break;
case LIR_gtuq:
case LIR_gtui: SETA(r); break;
case LIR_geuq:
case LIR_geui: SETAE(r); break;
}
freeResourcesOf(ins);
@ -1481,7 +1481,7 @@ namespace nanojit
releaseRegisters();
assignSavedRegs();
LIns *value = ins->oprnd1();
Register r = ins->isop(LIR_fret) ? XMM0 : RAX;
Register r = ins->isop(LIR_retd) ? XMM0 : RAX;
findSpecificRegFor(value, r);
}
@ -1521,12 +1521,12 @@ namespace nanojit
NanoAssert(IsGpReg(rr));
MOVQRM(rr, dr, rb); // general 64bit load, 32bit const displacement
break;
case LIR_ldf:
case LIR_ldd:
beginLoadRegs(ins, FpRegs, rr, dr, rb);
NanoAssert(IsFpReg(rr));
MOVSDRM(rr, dr, rb); // load 64bits into XMM
break;
case LIR_ld32f:
case LIR_ldf2d:
beginLoadRegs(ins, FpRegs, rr, dr, rb);
NanoAssert(IsFpReg(rr));
CVTSS2SD(rr, rr);
@ -1546,19 +1546,19 @@ namespace nanojit
beginLoadRegs(ins, GpRegs, r, d, b);
LOpcode op = ins->opcode();
switch (op) {
case LIR_ldzb:
case LIR_lduc2ui:
MOVZX8M( r, d, b);
break;
case LIR_ldzs:
case LIR_ldus2ui:
MOVZX16M(r, d, b);
break;
case LIR_ld:
case LIR_ldi:
MOVLRM( r, d, b);
break;
case LIR_ldsb:
case LIR_ldc2i:
MOVSX8M( r, d, b);
break;
case LIR_ldss:
case LIR_lds2i:
MOVSX16M( r, d, b);
break;
default:
@ -1572,19 +1572,19 @@ namespace nanojit
NanoAssert(value->isQorD());
switch (op) {
case LIR_stqi: {
case LIR_stq: {
Register r, b;
getBaseReg2(GpRegs, value, r, BaseRegs, base, b, d);
MOVQMR(r, d, b); // gpr store
break;
}
case LIR_stfi: {
case LIR_std: {
Register b = getBaseReg(base, d, BaseRegs);
Register r = findRegFor(value, FpRegs);
MOVSDMR(r, d, b); // xmm store
break;
}
case LIR_st32f: {
case LIR_std2f: {
Register b = getBaseReg(base, d, BaseRegs);
Register r = findRegFor(value, FpRegs);
Register t = registerAllocTmp(FpRegs & ~rmask(r));
@ -1604,17 +1604,17 @@ namespace nanojit
// Quirk of x86-64: reg cannot appear to be ah/bh/ch/dh for
// single-byte stores with REX prefix.
const RegisterMask SrcRegs = (op == LIR_stb) ? SingleByteStoreRegs : GpRegs;
const RegisterMask SrcRegs = (op == LIR_sti2c) ? SingleByteStoreRegs : GpRegs;
NanoAssert(value->isI());
Register b = getBaseReg(base, d, BaseRegs);
Register r = findRegFor(value, SrcRegs & ~rmask(b));
switch (op) {
case LIR_stb:
case LIR_sti2c:
MOVBMR(r, d, b);
break;
case LIR_sts:
case LIR_sti2s:
MOVSMR(r, d, b);
break;
case LIR_sti:

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

@ -712,7 +712,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
case 'Z':
if (++i == argc)
return usage();
JS_SetGCZeal(cx, atoi(argv[i]));
JS_SetGCZeal(cx, !!(atoi(argv[i])));
break;
#endif
@ -1457,12 +1457,12 @@ GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
static JSTrapStatus
TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure)
jsval closure)
{
JSString *str;
JSStackFrame *caller;
str = (JSString *) closure;
str = JSVAL_TO_STRING(closure);
caller = JS_GetScriptedCaller(cx, NULL);
if (!JS_EvaluateUCInStackFrame(cx, caller,
JS_GetStringChars(str), JS_GetStringLength(str),
@ -1493,7 +1493,7 @@ Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
argv[argc] = STRING_TO_JSVAL(str);
if (!GetTrapArgs(cx, argc, argv, &script, &i))
return JS_FALSE;
return JS_SetTrap(cx, script, script->code + i, TrapHandler, str);
return JS_SetTrap(cx, script, script->code + i, TrapHandler, STRING_TO_JSVAL(str));
}
static JSBool
@ -3056,7 +3056,7 @@ EvalInFrame(JSContext *cx, uintN argc, jsval *vp)
JSString *str = JSVAL_TO_STRING(argv[1]);
bool saveCurrent = (argc >= 3 && JSVAL_IS_BOOLEAN(argv[2]))
? (bool)JSVAL_TO_SPECIAL(argv[2])
? !!(JSVAL_TO_SPECIAL(argv[2]))
: false;
JS_ASSERT(cx->fp);
@ -3749,7 +3749,8 @@ Parse(JSContext *cx, uintN argc, jsval *vp)
js::Parser parser(cx);
parser.init(JS_GetStringCharsZ(cx, scriptContents), JS_GetStringLength(scriptContents),
NULL, "<string>", 0);
parser.parse(NULL);
if (!parser.parse(NULL))
return JS_FALSE;
JS_SET_RVAL(cx, vp, JSVAL_VOID);
return JS_TRUE;
}

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

@ -178,7 +178,7 @@ script regress-427196-01.js
script regress-427196-02.js
script regress-427196-03.js
script regress-429264.js
skip script regress-429739.js # Bug 520778 - wontfix
script regress-429739.js
script regress-431428.js
skip script regress-432075.js # obsolete test
script regress-434837-01.js

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

@ -53,7 +53,7 @@ function test()
printBugNumber(BUGNUMBER);
printStatus (summary);
expect = 'function anonymous(y) {}';
expect = 'TypeError: o.y is not a constructor';
try
{
@ -65,7 +65,7 @@ function test()
actual = ex + '';
}
compareSource(expect, actual, summary);
reportCompare(expect, actual, summary);
exitFunc ('test');
}

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

@ -12,3 +12,5 @@ script regress-555246-0.js
fails script regress-555246-1.js
script regress-559438.js
script regress-560101.js
script regress-560998-1.js
script regress-560998-2.js

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

@ -0,0 +1,10 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
// Contributor: Jesse Ruderman
for (let j = 0; j < 4; ++j) {
function g() { j; }
g();
}
reportCompare(0, 0, "ok");

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

@ -0,0 +1,10 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
// Contributor: Jason Orendorff <jorendorff@mozilla.com>
var x = {};
for (var i = 0; i < 2; i++) {
Object.defineProperty(x, "y", {configurable: true, value: function () {}});
x.y();
}
reportCompare(0, 0, "ok");

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

@ -0,0 +1,10 @@
function test() {
var a = ['x', '', '', '', '', '', '', 'x'];
var b = '';
for (var i = 0; i < a.length; i++) {
(function() {
a[i].replace(/x/, function() { return b; });
}());
}
}
test(); // should NOT get a ReferenceError for b on trace

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

@ -0,0 +1,12 @@
function f(a) {
function g() {
yield function () a;
}
if (a == 8)
return g();
a = 3;
}
var x;
for (var i = 0; i < 9; i++)
x = f(i);
x.next()(); // ReferenceError: a is not defined.

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

@ -0,0 +1,11 @@
function f(a, b) { return a + " " + b; }
for (var i = 0; i < 10; ++i) {
var s = '';
var a = {toString: function () { s += 'a'; return 'a'; }};
var b = {toString: function () { s += 'b'; return 'b'; }};
f(a, b);
assertEq(s, 'ab');
}
checkStats({ traceTriggered:1 });

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

@ -92,6 +92,8 @@ class Test:
def find_tests(dir, substring = None):
ans = []
for dirpath, dirnames, filenames in os.walk(dir):
dirnames.sort()
filenames.sort()
if dirpath == '.':
continue
for filename in filenames:

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

@ -123,7 +123,7 @@ interface nsIXPCComponents_utils_Sandbox : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(da2267f2-d4cc-448f-9d70-1c7fe134d2fe)]
[scriptable, uuid(c1d616fa-1875-49ba-b7b8-5861dab31a42)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -217,6 +217,16 @@ interface nsIXPCComponents_Utils : nsISupports
* Force an immediate garbage collection cycle.
*/
void forceGC();
/*
* To be called from JS only.
*
* Returns the global object with which the given object is associated.
*
* @param obj The JavaScript object whose parent is to be gotten.
* @return the corresponding global.
*/
void /* JSObject */ getGlobalForObject(/* in JSObject obj */);
};
/**

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

@ -534,7 +534,7 @@ XPC_SJOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
NS_STACK_CLASS class SafeCallGuard {
public:
SafeCallGuard(JSContext *cx, nsIPrincipal *principal)
: cx(cx), tvr(cx) {
: cx(cx), statics(cx), tvr(cx) {
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
if (ssm) {
// Note: We pass null as the target frame pointer because we know that

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

@ -3761,6 +3761,66 @@ nsXPCComponents_Utils::ForceGC()
return NS_OK;
}
/* void getGlobalForObject(); */
NS_IMETHODIMP
nsXPCComponents_Utils::GetGlobalForObject()
{
nsresult rv;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
if(NS_FAILED(rv))
return NS_ERROR_FAILURE;
// get the xpconnect native call context
nsAXPCNativeCallContext *cc = nsnull;
xpc->GetCurrentNativeCallContext(&cc);
if(!cc)
return NS_ERROR_FAILURE;
// Get JSContext of current call
JSContext* cx;
rv = cc->GetJSContext(&cx);
if(NS_FAILED(rv) || !cx)
return NS_ERROR_FAILURE;
// get place for return value
jsval *rval = nsnull;
rv = cc->GetRetValPtr(&rval);
if(NS_FAILED(rv) || !rval)
return NS_ERROR_FAILURE;
// get argc and argv and verify arg count
PRUint32 argc;
rv = cc->GetArgc(&argc);
if(NS_FAILED(rv))
return NS_ERROR_FAILURE;
if(argc != 1)
return NS_ERROR_XPC_NOT_ENOUGH_ARGS;
jsval* argv;
rv = cc->GetArgvPtr(&argv);
if(NS_FAILED(rv) || !argv)
return NS_ERROR_FAILURE;
// first argument must be an object
if(JSVAL_IS_PRIMITIVE(argv[0]))
return NS_ERROR_XPC_BAD_CONVERT_JS;
JSObject *obj = JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(argv[0]));
*rval = OBJECT_TO_JSVAL(obj);
// Outerize if necessary. Embrace the ugliness!
JSClass *clasp = JS_GetClass(cx, obj);
if (clasp->flags & JSCLASS_IS_EXTENDED) {
JSExtendedClass *xclasp = reinterpret_cast<JSExtendedClass *>(clasp);
if (JSObjectOp outerize = xclasp->outerObject)
*rval = OBJECT_TO_JSVAL(outerize(cx, obj));
}
cc->SetReturnValueWasSet(PR_TRUE);
return NS_OK;
}
#ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
/* string canCreateWrapper (in nsIIDPtr iid); */
NS_IMETHODIMP