Merge tracemonkey to mozilla-central

This commit is contained in:
Robert Sayre 2009-05-05 11:36:48 -07:00
commit d819a61312
7 changed files with 82 additions and 111 deletions

View File

@ -4105,6 +4105,17 @@ if test -n "$GC_LEAK_DETECTOR"; then
AC_DEFINE(GC_LEAK_DETECTOR)
fi
dnl ========================================================
dnl Enable Narcissus
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(narcissus,
[ --enable-narcissus Build with Narcissus code enabled],
NARCISSUS=1,
NARCISSUS= )
if test -n "$NARCISSUS"; then
AC_DEFINE(NARCISSUS)
fi
dnl ========================================================
dnl = Enable trace malloc
dnl ========================================================

View File

@ -2828,19 +2828,7 @@ JS_PUBLIC_API(JSBool)
JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
{
CHECK_REQUEST(cx);
JS_ASSERT(obj != proto);
if (OBJ_IS_NATIVE(obj)) {
JS_LOCK_OBJ(cx, obj);
if (!js_GetMutableScope(cx, obj)) {
JS_UNLOCK_OBJ(cx, obj);
return JS_FALSE;
}
LOCKED_OBJ_SET_PROTO(obj, proto);
JS_UNLOCK_OBJ(cx, obj);
return JS_TRUE;
}
OBJ_SET_PROTO(cx, obj, proto);
return JS_TRUE;
return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, proto, JS_FALSE);
}
JS_PUBLIC_API(JSObject *)
@ -2858,9 +2846,7 @@ JS_PUBLIC_API(JSBool)
JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
{
CHECK_REQUEST(cx);
JS_ASSERT(obj != parent);
OBJ_SET_PARENT(cx, obj, parent);
return JS_TRUE;
return js_SetProtoOrParent(cx, obj, JSSLOT_PARENT, parent, JS_FALSE);
}
JS_PUBLIC_API(JSObject *)

View File

@ -336,7 +336,7 @@ struct JSSetSlotRequest {
JSObject *obj; /* object containing slot to set */
JSObject *pobj; /* new proto or parent reference */
uint16 slot; /* which to set, proto or parent */
uint16 errnum; /* JSMSG_NO_ERROR or error result */
JSPackedBool cycle; /* true if a cycle was detected */
JSSetSlotRequest *next; /* next request in GC worklist */
};

View File

@ -3200,76 +3200,26 @@ js_TriggerGC(JSContext *cx, JSBool gcLocked)
static void
ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
{
JSObject *obj, *pobj;
uint32 slot;
obj = ssr->obj;
pobj = ssr->pobj;
slot = ssr->slot;
JSObject *obj = ssr->obj;
JSObject *pobj = ssr->pobj;
uint32 slot = ssr->slot;
while (pobj) {
pobj = js_GetWrappedObject(cx, pobj);
if (pobj == obj) {
ssr->errnum = JSMSG_CYCLIC_VALUE;
ssr->cycle = true;
return;
}
pobj = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(pobj, slot));
}
pobj = ssr->pobj;
if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) {
JSScope *scope, *newscope;
JSObject *oldproto;
/* Check to see whether obj shares its prototype's scope. */
scope = OBJ_SCOPE(obj);
oldproto = STOBJ_GET_PROTO(obj);
if (oldproto && OBJ_SCOPE(oldproto) == scope) {
/* Either obj needs a new empty scope, or it should share pobj's. */
if (!pobj ||
!OBJ_IS_NATIVE(pobj) ||
OBJ_GET_CLASS(cx, pobj) != STOBJ_GET_CLASS(oldproto)) {
/*
* With no proto and no scope of its own, obj is truly empty.
*
* If pobj is not native, obj needs its own empty scope -- it
* should not continue to share oldproto's scope once oldproto
* is not on obj's prototype chain. That would put properties
* from oldproto's scope ahead of properties defined by pobj,
* in lookup order.
*
* If pobj's class differs from oldproto's, we may need a new
* scope to handle differences in private and reserved slots,
* so we suboptimally but safely make one.
*/
if (!js_GetMutableScope(cx, obj)) {
ssr->errnum = JSMSG_OUT_OF_MEMORY;
return;
}
} else if (OBJ_SCOPE(pobj) != scope) {
newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map);
obj->map = &newscope->map;
js_DropObjectMap(cx, &scope->map, obj);
JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
}
}
/*
* Regenerate property cache shape ids for all of the scopes along the
* old prototype chain, in case any property cache entries were filled
* by looking up starting from obj.
*/
while (oldproto && OBJ_IS_NATIVE(oldproto)) {
scope = OBJ_SCOPE(oldproto);
js_MakeScopeShapeUnique(cx, scope);
oldproto = STOBJ_GET_PROTO(scope->object);
}
if (slot == JSSLOT_PROTO) {
STOBJ_SET_PROTO(obj, pobj);
} else {
JS_ASSERT(slot == JSSLOT_PARENT);
STOBJ_SET_PARENT(obj, pobj);
}
/* Finally, do the deed. */
STOBJ_SET_SLOT(obj, slot, OBJECT_TO_JSVAL(pobj));
STOBJ_SET_DELEGATE(pobj);
}
void

View File

@ -240,7 +240,7 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_FALSE;
}
return js_SetProtoOrParent(cx, obj, slot, pobj);
return js_SetProtoOrParent(cx, obj, slot, pobj, JS_TRUE);
}
static JSBool
@ -279,45 +279,66 @@ out:
#endif /* !JS_HAS_OBJ_PROTO_PROP */
JSBool
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
JSBool checkForCycles)
{
JSSetSlotRequest ssr;
JSRuntime *rt;
JS_ASSERT(slot == JSSLOT_PARENT || slot == JSSLOT_PROTO);
JS_ASSERT_IF(!checkForCycles, obj != pobj);
/* Optimize the null case to avoid the unnecessary overhead of js_GC. */
if (!pobj) {
JS_LOCK_OBJ(cx, obj);
if (slot == JSSLOT_PROTO && !js_GetMutableScope(cx, obj)) {
JS_UNLOCK_OBJ(cx, obj);
return JS_FALSE;
}
LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_NULL);
if (slot == JSSLOT_PROTO) {
JS_UNLOCK_OBJ(cx, obj);
return JS_TRUE;
bool ok = !!js_GetMutableScope(cx, obj);
JS_UNLOCK_OBJ(cx, obj);
if (!ok)
return JS_FALSE;
/*
* Regenerate property cache shape ids for all of the scopes along the
* old prototype chain to invalidate their property cache entries, in
* case any entries were filled by looking up starting from obj.
*/
JSObject *oldproto = STOBJ_GET_PROTO(obj);
while (oldproto && OBJ_IS_NATIVE(oldproto)) {
JS_LOCK_OBJ(cx, oldproto);
JSScope *scope = OBJ_SCOPE(oldproto);
js_MakeScopeShapeUnique(cx, scope);
JSObject *tmp = STOBJ_GET_PROTO(scope->object);
JS_UNLOCK_OBJ(cx, oldproto);
oldproto = tmp;
}
}
ssr.obj = obj;
ssr.pobj = pobj;
ssr.slot = (uint16) slot;
ssr.errnum = (uint16) JSMSG_NOT_AN_ERROR;
if (!pobj || !checkForCycles) {
if (slot == JSSLOT_PROTO)
STOBJ_SET_PROTO(obj, pobj);
else
STOBJ_SET_PARENT(obj, pobj);
} else {
/*
* Use the GC machinery to serialize access to all objects on the
* prototype or parent chain.
*/
JSSetSlotRequest ssr;
ssr.obj = obj;
ssr.pobj = pobj;
ssr.slot = (uint16) slot;
ssr.cycle = false;
rt = cx->runtime;
JS_LOCK_GC(rt);
ssr.next = rt->setSlotRequests;
rt->setSlotRequests = &ssr;
for (;;) {
js_GC(cx, GC_SET_SLOT_REQUEST);
JS_UNLOCK_GC(rt);
if (!rt->setSlotRequests)
break;
JSRuntime *rt = cx->runtime;
JS_LOCK_GC(rt);
}
ssr.next = rt->setSlotRequests;
rt->setSlotRequests = &ssr;
for (;;) {
js_GC(cx, GC_SET_SLOT_REQUEST);
JS_UNLOCK_GC(rt);
if (!rt->setSlotRequests)
break;
JS_LOCK_GC(rt);
}
if (ssr.errnum != JSMSG_NOT_AN_ERROR) {
if (ssr.errnum == JSMSG_OUT_OF_MEMORY) {
JS_ReportOutOfMemory(cx);
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, ssr.errnum,
if (ssr.cycle) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CYCLIC_VALUE,
#if JS_HAS_OBJ_PROTO_PROP
object_props[slot].name
#else
@ -325,8 +346,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
: js_parent_str
#endif
);
return JS_FALSE;
}
return JS_FALSE;
}
return JS_TRUE;
}

View File

@ -776,7 +776,8 @@ extern JSBool
js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
extern JSBool
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj);
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
JSBool checkForCycles);
extern JSBool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);

View File

@ -4587,7 +4587,9 @@ TraceRecorder::monitorRecording(JSContext* cx, TraceRecorder* tr, JSOp op)
bool wasInImacro = (cx->fp->imacpc != NULL);
#endif
switch (op) {
default: goto stop_recording;
default:
status = JSRS_ERROR;
goto stop_recording;
# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
case x: \
status = tr->record_##x(); \