зеркало из https://github.com/mozilla/pjs.git
Merge.
This commit is contained in:
Коммит
004ca3887a
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
144
js/src/jsobj.cpp
144
js/src/jsobj.cpp
|
@ -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, ¬ePool, 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, ¬ePool, 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;
|
||||
}
|
||||
|
|
128
js/src/jsstr.cpp
128
js/src/jsstr.cpp
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче