mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
Re-landing fix for bug 408301 to see if it really was the cause of the orange last time it landed. Make more XPConnect wrappers share their JSObject maps. r=peterv@propagandism.org, sr=brendan@mozilla.org
This commit is contained in:
parent
30fca1fe7c
commit
807c3720ca
@ -1151,6 +1151,7 @@ extern JSClass XPC_WN_NoMods_NoCall_Proto_JSClass;
|
||||
extern JSClass XPC_WN_ModsAllowed_WithCall_Proto_JSClass;
|
||||
extern JSClass XPC_WN_ModsAllowed_NoCall_Proto_JSClass;
|
||||
extern JSClass XPC_WN_Tearoff_JSClass;
|
||||
extern JSClass XPC_WN_NoHelper_Proto_JSClass;
|
||||
|
||||
extern JSObjectOps * JS_DLL_CALLBACK
|
||||
XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz);
|
||||
@ -1158,6 +1159,9 @@ XPC_WN_GetObjectOpsNoCall(JSContext *cx, JSClass *clazz);
|
||||
extern JSObjectOps * JS_DLL_CALLBACK
|
||||
XPC_WN_GetObjectOpsWithCall(JSContext *cx, JSClass *clazz);
|
||||
|
||||
extern JSObjectOps * JS_DLL_CALLBACK
|
||||
XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz);
|
||||
|
||||
extern JSBool JS_DLL_CALLBACK
|
||||
XPC_WN_CallMethod(JSContext *cx, JSObject *obj,
|
||||
uintN argc, jsval *argv, jsval *vp);
|
||||
@ -1215,6 +1219,11 @@ public:
|
||||
JSObject*
|
||||
GetPrototypeJSObject() const {return mPrototypeJSObject;}
|
||||
|
||||
// Getter for the prototype that we use for wrappers that have no
|
||||
// helper.
|
||||
JSObject*
|
||||
GetPrototypeNoHelper(XPCCallContext& ccx);
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
nsIPrincipal*
|
||||
GetPrincipal() const
|
||||
@ -1308,8 +1317,13 @@ private:
|
||||
// unless a PreCreate hook overrides it. Note that this _may_ be null (see
|
||||
// constructor).
|
||||
JSObject* mGlobalJSObject;
|
||||
|
||||
// Cached value of Object.prototype
|
||||
JSObject* mPrototypeJSObject;
|
||||
// Cached value of Function.prototype
|
||||
JSObject* mPrototypeJSFunction;
|
||||
// Prototype to use for wrappers with no helper.
|
||||
JSObject* mPrototypeNoHelper;
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
// The script object principal instance corresponding to our current global
|
||||
|
@ -868,7 +868,11 @@ XPCWrappedNative::Init(XPCCallContext& ccx, JSObject* parent, JSBool isGlobal,
|
||||
|
||||
JSObject* protoJSObject = HasProto() ?
|
||||
GetProto()->GetJSProtoObject() :
|
||||
GetScope()->GetPrototypeJSObject();
|
||||
GetScope()->GetPrototypeNoHelper(ccx);
|
||||
|
||||
if (!protoJSObject) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
mFlatJSObject = xpc_NewSystemInheritingJSObject(ccx, jsclazz, protoJSObject,
|
||||
parent);
|
||||
|
@ -899,7 +899,7 @@ JSExtendedClass XPC_WN_NoHelper_JSClass = {
|
||||
XPC_WN_NoHelper_Finalize, // finalize;
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
nsnull, // getObjectOps;
|
||||
XPC_WN_GetObjectOpsNoCall, // getObjectOps;
|
||||
nsnull, // checkAccess;
|
||||
nsnull, // call;
|
||||
nsnull, // construct;
|
||||
@ -1186,9 +1186,11 @@ JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
XPC_WN_JSOp_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp)
|
||||
{
|
||||
if(!IS_WRAPPER_CLASS(JS_GET_CLASS(cx, obj)))
|
||||
JSClass *clazz = JS_GET_CLASS(cx, obj);
|
||||
if(!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base)
|
||||
{
|
||||
// obj must be a prototype object. Short circuit this call to
|
||||
// obj must be a prototype object or a wrapper w/o a
|
||||
// helper. Short circuit this call to
|
||||
// js_ObjectOps.enumerate().
|
||||
|
||||
return js_ObjectOps.enumerate(cx, obj, enum_op, statep, idp);
|
||||
@ -1633,7 +1635,8 @@ XPC_WN_Proto_GetObjectOps(JSContext *cx, JSClass *clazz)
|
||||
return &XPC_WN_WithCall_JSOps;
|
||||
|
||||
NS_ASSERTION(clazz == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass ||
|
||||
clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass,
|
||||
clazz == &XPC_WN_NoMods_NoCall_Proto_JSClass ||
|
||||
clazz == &XPC_WN_NoHelper_Proto_JSClass,
|
||||
"bad proto");
|
||||
|
||||
return &XPC_WN_NoCall_JSOps;
|
||||
|
@ -119,11 +119,12 @@ XPCWrappedNativeScope::GetNewOrUsed(XPCCallContext& ccx, JSObject* aGlobal)
|
||||
scope = new XPCWrappedNativeScope(ccx, aGlobal);
|
||||
else
|
||||
{
|
||||
// We need to call SetGlobal in order to refresh our cached
|
||||
// mPrototypeJSObject and mPrototypeJSFunction in the case where
|
||||
// the global object is being reused (JS_ClearScope has been
|
||||
// called).
|
||||
// NOTE: We are only called by nsXPConnect::InitClasses.
|
||||
// We need to call SetGlobal in order to refresh our cached
|
||||
// mPrototypeJSObject and mPrototypeJSFunction and to clear
|
||||
// mPrototypeNoHelper (so we get a new one if requested in the
|
||||
// new scope) in the case where the global object is being
|
||||
// reused (JS_ClearScope has been called). NOTE: We are only
|
||||
// called by nsXPConnect::InitClasses.
|
||||
scope->SetGlobal(ccx, aGlobal);
|
||||
}
|
||||
return scope;
|
||||
@ -139,7 +140,8 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx,
|
||||
mNext(nsnull),
|
||||
mGlobalJSObject(nsnull),
|
||||
mPrototypeJSObject(nsnull),
|
||||
mPrototypeJSFunction(nsnull)
|
||||
mPrototypeJSFunction(nsnull),
|
||||
mPrototypeNoHelper(nsnull)
|
||||
{
|
||||
// add ourselves to the scopes list
|
||||
{ // scoped lock
|
||||
@ -181,6 +183,41 @@ XPCWrappedNativeScope::SetComponents(nsXPCComponents* aComponents)
|
||||
mComponents = aComponents;
|
||||
}
|
||||
|
||||
// Dummy JS class to let wrappers w/o an xpc prototype share
|
||||
// scopes. By doing this we avoid allocating a new scope for every
|
||||
// wrapper on creation of the wrapper, and most wrappers won't need
|
||||
// their own scope at all for the lifetime of the wrapper.
|
||||
// JSCLASS_HAS_PRIVATE is key here (even though there's never anything
|
||||
// in the private data slot in these prototypes), as the number of
|
||||
// reserved slots in this class needs to match that of the wrappers
|
||||
// for the JS engine to share scopes.
|
||||
|
||||
JSClass XPC_WN_NoHelper_Proto_JSClass = {
|
||||
"XPC_WN_NoHelper_Proto_JSClass",// name;
|
||||
JSCLASS_HAS_PRIVATE, // flags;
|
||||
|
||||
/* Mandatory non-null function pointer members. */
|
||||
JS_PropertyStub, // addProperty;
|
||||
JS_PropertyStub, // delProperty;
|
||||
JS_PropertyStub, // getProperty;
|
||||
JS_PropertyStub, // setProperty;
|
||||
JS_EnumerateStub, // enumerate;
|
||||
JS_ResolveStub, // resolve;
|
||||
JS_ConvertStub, // convert;
|
||||
JS_FinalizeStub, // finalize;
|
||||
|
||||
/* Optionally non-null members start here. */
|
||||
XPC_WN_Proto_GetObjectOps, // getObjectOps;
|
||||
nsnull, // checkAccess;
|
||||
nsnull, // call;
|
||||
nsnull, // construct;
|
||||
nsnull, // xdrObject;
|
||||
nsnull, // hasInstance;
|
||||
nsnull, // mark/trace;
|
||||
nsnull // spare;
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
|
||||
{
|
||||
@ -191,25 +228,24 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
mScriptObjectPrincipal = nsnull;
|
||||
// Now init our script object principal, if the new global has one
|
||||
if (aGlobal)
|
||||
|
||||
JSContext* cx = ccx.GetJSContext();
|
||||
const JSClass* jsClass = JS_GetClass(cx, aGlobal);
|
||||
if(!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS)))
|
||||
{
|
||||
JSContext* cx = ccx.GetJSContext();
|
||||
const JSClass* jsClass = JS_GetClass(cx, aGlobal);
|
||||
if (jsClass && !(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS)))
|
||||
// Our global has an nsISupports native pointer. Let's
|
||||
// see whether it's what we want.
|
||||
nsISupports* priv = (nsISupports*)JS_GetPrivate(cx, aGlobal);
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> native =
|
||||
do_QueryInterface(priv);
|
||||
if(native)
|
||||
{
|
||||
// Our global has an nsISupports native pointer. Let's
|
||||
// see whether it's what we want.
|
||||
nsISupports* priv = (nsISupports*)JS_GetPrivate(cx, aGlobal);
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> native =
|
||||
do_QueryInterface(priv);
|
||||
if (native)
|
||||
{
|
||||
mScriptObjectPrincipal = do_QueryWrappedNative(native);
|
||||
}
|
||||
if (!mScriptObjectPrincipal) {
|
||||
mScriptObjectPrincipal = do_QueryInterface(priv);
|
||||
}
|
||||
mScriptObjectPrincipal = do_QueryWrappedNative(native);
|
||||
}
|
||||
if(!mScriptObjectPrincipal)
|
||||
{
|
||||
mScriptObjectPrincipal = do_QueryInterface(priv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -247,6 +283,10 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
|
||||
NS_ERROR("Can't get globalObject.Function.prototype");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the no helper wrapper prototype object so that a new one
|
||||
// gets created if needed.
|
||||
mPrototypeNoHelper = nsnull;
|
||||
}
|
||||
|
||||
XPCWrappedNativeScope::~XPCWrappedNativeScope()
|
||||
@ -279,6 +319,25 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope()
|
||||
NS_IF_RELEASE(mComponents);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
XPCWrappedNativeScope::GetPrototypeNoHelper(XPCCallContext& ccx)
|
||||
{
|
||||
// We could create this prototype in SetGlobal(), but all scopes
|
||||
// don't need one, so we save ourselves a bit of space if we
|
||||
// create these when they're needed.
|
||||
if(!mPrototypeNoHelper)
|
||||
{
|
||||
mPrototypeNoHelper =
|
||||
xpc_NewSystemInheritingJSObject(ccx, &XPC_WN_NoHelper_Proto_JSClass,
|
||||
mPrototypeJSObject,
|
||||
mGlobalJSObject);
|
||||
|
||||
NS_ASSERTION(mPrototypeNoHelper,
|
||||
"Failed to create prototype for wrappers w/o a helper");
|
||||
}
|
||||
|
||||
return mPrototypeNoHelper;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
|
||||
WrappedNativeJSGCThingTracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
@ -407,6 +466,11 @@ XPCWrappedNativeScope::FinishedMarkPhaseOfGC(JSContext* cx, XPCJSRuntime* rt)
|
||||
{
|
||||
cur->mPrototypeJSFunction = nsnull;
|
||||
}
|
||||
if(cur->mPrototypeNoHelper &&
|
||||
JS_IsAboutToBeFinalized(cx, cur->mPrototypeNoHelper))
|
||||
{
|
||||
cur->mPrototypeNoHelper = nsnull;
|
||||
}
|
||||
}
|
||||
if(cur)
|
||||
prev = cur;
|
||||
@ -637,11 +701,12 @@ GetScopeOfObject(JSContext* cx, JSObject* obj)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
{
|
||||
if(clazz->flags & JSCLASS_HAS_PRIVATE &&
|
||||
clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)
|
||||
if(!(~clazz->flags & (JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_PRIVATE_IS_NSISUPPORTS)) &&
|
||||
(supports = (nsISupports*) JS_GetPrivate(cx, obj)))
|
||||
{
|
||||
nsCOMPtr<nsIXPConnectWrappedNative> iface =
|
||||
do_QueryInterface((nsISupports*) JS_GetPrivate(cx, obj));
|
||||
do_QueryInterface(supports);
|
||||
|
||||
NS_ASSERTION(!iface, "Uh, how'd this happen?");
|
||||
}
|
||||
@ -861,6 +926,7 @@ XPCWrappedNativeScope::DebugDump(PRInt16 depth)
|
||||
XPC_LOG_ALWAYS(("mGlobalJSObject @ %x", mGlobalJSObject));
|
||||
XPC_LOG_ALWAYS(("mPrototypeJSObject @ %x", mPrototypeJSObject));
|
||||
XPC_LOG_ALWAYS(("mPrototypeJSFunction @ %x", mPrototypeJSFunction));
|
||||
XPC_LOG_ALWAYS(("mPrototypeNoHelper @ %x", mPrototypeNoHelper));
|
||||
|
||||
XPC_LOG_ALWAYS(("mWrappedNativeMap @ %x with %d wrappers(s)", \
|
||||
mWrappedNativeMap, \
|
||||
|
Loading…
Reference in New Issue
Block a user