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) AC_DEFINE(GC_LEAK_DETECTOR)
fi 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 ========================================================
dnl = Enable trace malloc dnl = Enable trace malloc
dnl ======================================================== dnl ========================================================

View File

@ -2828,19 +2828,7 @@ JS_PUBLIC_API(JSBool)
JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto) JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
JS_ASSERT(obj != proto); return js_SetProtoOrParent(cx, obj, JSSLOT_PROTO, proto, JS_FALSE);
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;
} }
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)
@ -2858,9 +2846,7 @@ JS_PUBLIC_API(JSBool)
JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent) JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
{ {
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
JS_ASSERT(obj != parent); return js_SetProtoOrParent(cx, obj, JSSLOT_PARENT, parent, JS_FALSE);
OBJ_SET_PARENT(cx, obj, parent);
return JS_TRUE;
} }
JS_PUBLIC_API(JSObject *) JS_PUBLIC_API(JSObject *)

View File

@ -336,7 +336,7 @@ struct JSSetSlotRequest {
JSObject *obj; /* object containing slot to set */ JSObject *obj; /* object containing slot to set */
JSObject *pobj; /* new proto or parent reference */ JSObject *pobj; /* new proto or parent reference */
uint16 slot; /* which to set, proto or parent */ 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 */ JSSetSlotRequest *next; /* next request in GC worklist */
}; };

View File

@ -3200,76 +3200,26 @@ js_TriggerGC(JSContext *cx, JSBool gcLocked)
static void static void
ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr) ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
{ {
JSObject *obj, *pobj; JSObject *obj = ssr->obj;
uint32 slot; JSObject *pobj = ssr->pobj;
uint32 slot = ssr->slot;
obj = ssr->obj;
pobj = ssr->pobj;
slot = ssr->slot;
while (pobj) { while (pobj) {
pobj = js_GetWrappedObject(cx, pobj); pobj = js_GetWrappedObject(cx, pobj);
if (pobj == obj) { if (pobj == obj) {
ssr->errnum = JSMSG_CYCLIC_VALUE; ssr->cycle = true;
return; return;
} }
pobj = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(pobj, slot)); pobj = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(pobj, slot));
} }
pobj = ssr->pobj; pobj = ssr->pobj;
if (slot == JSSLOT_PROTO) {
if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) { STOBJ_SET_PROTO(obj, pobj);
JSScope *scope, *newscope; } else {
JSObject *oldproto; JS_ASSERT(slot == JSSLOT_PARENT);
STOBJ_SET_PARENT(obj, pobj);
/* 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);
}
} }
/* Finally, do the deed. */
STOBJ_SET_SLOT(obj, slot, OBJECT_TO_JSVAL(pobj));
STOBJ_SET_DELEGATE(pobj);
} }
void void

View File

@ -240,7 +240,7 @@ obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_FALSE; return JS_FALSE;
} }
return js_SetProtoOrParent(cx, obj, slot, pobj); return js_SetProtoOrParent(cx, obj, slot, pobj, JS_TRUE);
} }
static JSBool static JSBool
@ -279,45 +279,66 @@ out:
#endif /* !JS_HAS_OBJ_PROTO_PROP */ #endif /* !JS_HAS_OBJ_PROTO_PROP */
JSBool 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; JS_ASSERT(slot == JSSLOT_PARENT || slot == JSSLOT_PROTO);
JSRuntime *rt; JS_ASSERT_IF(!checkForCycles, obj != pobj);
/* Optimize the null case to avoid the unnecessary overhead of js_GC. */ if (slot == JSSLOT_PROTO) {
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);
JS_UNLOCK_OBJ(cx, obj); 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; if (!pobj || !checkForCycles) {
ssr.pobj = pobj; if (slot == JSSLOT_PROTO)
ssr.slot = (uint16) slot; STOBJ_SET_PROTO(obj, pobj);
ssr.errnum = (uint16) JSMSG_NOT_AN_ERROR; 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; 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); 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.cycle) {
if (ssr.errnum == JSMSG_OUT_OF_MEMORY) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JS_ReportOutOfMemory(cx); JSMSG_CYCLIC_VALUE,
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, ssr.errnum,
#if JS_HAS_OBJ_PROTO_PROP #if JS_HAS_OBJ_PROTO_PROP
object_props[slot].name object_props[slot].name
#else #else
@ -325,8 +346,8 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
: js_parent_str : js_parent_str
#endif #endif
); );
return JS_FALSE;
} }
return JS_FALSE;
} }
return JS_TRUE; return JS_TRUE;
} }

View File

@ -776,7 +776,8 @@ extern JSBool
js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
extern JSBool 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 extern JSBool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); 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); bool wasInImacro = (cx->fp->imacpc != NULL);
#endif #endif
switch (op) { switch (op) {
default: goto stop_recording; default:
status = JSRS_ERROR;
goto stop_recording;
# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \ # define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
case x: \ case x: \
status = tr->record_##x(); \ status = tr->record_##x(); \