Fix for bug 590612 (Speed up js-wrapping in classinfo when we already have a wrapper). r=bz, a=jst.

This commit is contained in:
Peter Van der Beken 2010-08-28 10:04:25 +02:00
parent 68c6411e7f
commit a6974efb9d
8 changed files with 129 additions and 95 deletions

View File

@ -106,12 +106,6 @@ nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
JSRuntime *nsScriptSecurityManager::sRuntime = 0;
PRBool nsScriptSecurityManager::sStrictFileOriginPolicy = PR_TRUE;
// Info we need about the JSClasses used by XPConnects wrapped
// natives, to avoid having to QI to nsIXPConnectWrappedNative all the
// time when doing security checks.
static JSEqualityOp sXPCWrappedNativeEqualityOps;
///////////////////////////
// Convenience Functions //
///////////////////////////
@ -2414,11 +2408,8 @@ nsScriptSecurityManager::doGetObjectPrincipal(JSObject *aObj
do {
// Note: jsClass is set before this loop, and also at the
// *end* of this loop.
// NOTE: These class and equality hook checks better match
// what IS_WRAPPER_CLASS() does in xpconnect!
if (jsClass->ext.equality == js::Valueify(sXPCWrappedNativeEqualityOps)) {
if (IS_WRAPPER_CLASS(jsClass)) {
result = sXPConnect->GetPrincipal(aObj,
#ifdef DEBUG
aAllowShortCircuit
@ -3423,7 +3414,6 @@ nsresult nsScriptSecurityManager::Init()
JS_SetRuntimeSecurityCallbacks(sRuntime, &securityCallbacks);
NS_ASSERTION(!oldcallbacks, "Someone else set security callbacks!");
sXPConnect->GetXPCWrappedNativeJSClassInfo(&sXPCWrappedNativeEqualityOps);
return NS_OK;
}

View File

@ -5537,6 +5537,11 @@ nsContentUtils::WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
return NS_OK;
}
JSObject *wrapper = xpc_GetCachedSlimWrapper(cache, scope, vp);
if (wrapper) {
return NS_OK;
}
NS_ENSURE_TRUE(sXPConnect && sThreadJSContextStack, NS_ERROR_UNEXPECTED);
// Keep sXPConnect and sThreadJSContextStack alive. If we're on the main

View File

@ -48,6 +48,7 @@
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
#include "nsIScriptGlobalObject.h"
#include "nsContentUtils.h"
#include "xpcpublic.h"
class nsIDOMWindow;
class nsIDOMNSHTMLOptionCollection;
@ -140,8 +141,8 @@ public:
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull)
{
return nsContentUtils::WrapNative(cx, scope, native, aIID, vp, aHolder,
aAllowWrapping);
return WrapNative(cx, scope, native, nsnull, aIID, vp, aHolder,
aAllowWrapping);
}
// Used for cases where PreCreate needs to wrap the native parent, and the
@ -161,8 +162,8 @@ public:
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull)
{
return nsContentUtils::WrapNative(cx, scope, native, vp, aHolder,
aAllowWrapping);
return WrapNative(cx, scope, native, nsnull, nsnull, vp, aHolder,
aAllowWrapping);
}
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, nsWrapperCache *cache,
@ -171,8 +172,8 @@ public:
// while there's a ref to it
nsIXPConnectJSObjectHolder** aHolder = nsnull)
{
return nsContentUtils::WrapNative(cx, scope, native, cache, vp, aHolder,
aAllowWrapping);
return WrapNative(cx, scope, native, cache, nsnull, vp, aHolder,
aAllowWrapping);
}
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
@ -247,6 +248,29 @@ protected:
id == sName_id);
}
static nsresult WrapNative(JSContext *cx, JSObject *scope,
nsISupports *native, nsWrapperCache *cache,
const nsIID* aIID, jsval *vp,
nsIXPConnectJSObjectHolder** aHolder,
PRBool aAllowWrapping)
{
if (!native) {
NS_ASSERTION(!aHolder || !*aHolder, "*aHolder should be null!");
*vp = JSVAL_NULL;
return NS_OK;
}
JSObject *wrapper = xpc_GetCachedSlimWrapper(cache, scope, vp);
if (wrapper) {
return NS_OK;
}
return sXPConnect->WrapNativeToJSVal(cx, scope, native, cache, aIID,
aAllowWrapping, vp, aHolder);
}
static nsIXPConnect *sXPConnect;
static nsIScriptSecurityManager *sSecMan;

View File

@ -40,19 +40,19 @@
#ifndef jstl_h_
#define jstl_h_
/* Gross special case for Gecko, which defines malloc/calloc/free. */
#ifdef mozilla_mozalloc_macro_wrappers_h
# define JS_UNDEFD_MOZALLOC_WRAPPERS
/* The "anti-header" */
# include "mozilla/mozalloc_undef_macro_wrappers.h"
#endif
#include "jsbit.h"
#include "jsstaticcheck.h"
#include <new>
#include <string.h>
/* Gross special case for Gecko, which defines malloc/calloc/free. */
#ifdef mozilla_mozalloc_macro_wrappers_h
# define JSSTL_UNDEFD_MOZALLOC_WRAPPERS
/* The "anti-header" */
# include "mozilla/mozalloc_undef_macro_wrappers.h"
#endif
namespace js {
/* JavaScript Template Library. */
@ -467,4 +467,8 @@ InitConst(const T &t)
} /* namespace js */
#ifdef JSSTL_UNDEFD_MOZALLOC_WRAPPERS
# include "mozilla/mozalloc_macro_wrappers.h"
#endif
#endif /* jstl_h_ */

View File

@ -50,6 +50,12 @@
#pragma warning(disable:4345)
#endif
/* Gross special case for Gecko, which defines malloc/calloc/free. */
#ifdef mozilla_mozalloc_macro_wrappers_h
# define JSVECTOR_UNDEFD_MOZALLOC_WRAPPERS
# include "mozilla/mozalloc_undef_macro_wrappers.h"
#endif
namespace js {
/*
@ -743,4 +749,8 @@ Vector<T,N,AP>::replaceRawBuffer(T *p, size_t length)
#pragma warning(pop)
#endif
#ifdef JSVECTOR_UNDEFD_MOZALLOC_WRAPPERS
# include "mozilla/mozalloc_macro_wrappers.h"
#endif
#endif /* jsvector_h_ */

View File

@ -707,17 +707,8 @@ def writeResultConv(f, type, jsvalPtr, jsvalRef):
return
else:
f.write(" nsWrapperCache* cache = xpc_qsGetWrapperCache(result);\n"
" if (cache) {\n"
" JSObject* wrapper = cache->GetWrapper();\n"
" NS_ASSERTION(cx->compartment == obj->compartment(),\n"
" \"wrong compartment in object or context!\");\n"
" if (wrapper &&\n"
# FIXME: Bug 585786, this check should go away
" IS_SLIM_WRAPPER_OBJECT(wrapper) &&\n"
" cx->compartment == wrapper->compartment()) {\n"
" *%s = OBJECT_TO_JSVAL(wrapper);\n"
" return JS_TRUE;\n"
" }\n"
" if (xpc_GetCachedSlimWrapper(cache, obj, %s)) {\n"
" return JS_TRUE;\n"
" }\n"
" // After this point do not use 'result'!\n"
" qsObjectHelper helper(result, cache);\n"
@ -1259,17 +1250,10 @@ def writeTraceableResultConv(f, type):
"&vp.array[0]);\n")
else:
f.write(" nsWrapperCache* cache = xpc_qsGetWrapperCache(result);\n"
" if (cache) {\n"
" JSObject* wrapper = cache->GetWrapper();\n"
" NS_ASSERTION(cx->compartment == obj->compartment(),\n"
" \"wrong compartment in object or context!\");\n"
" if (wrapper &&\n"
# FIXME: Bug 585786, this check should go away
" IS_SLIM_WRAPPER_OBJECT(wrapper) &&\n"
" cx->compartment == wrapper->compartment()) {\n"
" vp.array[0] = OBJECT_TO_JSVAL(wrapper);\n"
" return wrapper;\n"
" }\n"
" JSObject* wrapper =\n"
" xpc_GetCachedSlimWrapper(cache, obj, &vp.array[0]);\n"
" if (wrapper) {\n"
" return wrapper;\n"
" }\n"
" // After this point do not use 'result'!\n"
" qsObjectHelper helper(result, cache);\n"

View File

@ -50,6 +50,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include "xpcpublic.h"
#include "jsapi.h"
#include "jsdhash.h"
#include "jsprf.h"
@ -1454,46 +1455,6 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JSObject *obj);
(clazz) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass || \
(clazz) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass)
// NOTE!!!
//
// If this ever changes,
// nsScriptSecurityManager::doGetObjectPrincipal() *must* be updated
// also!
//
// NOTE!!!
#define IS_WRAPPER_CLASS(clazz) \
(clazz->ext.equality == js::Valueify(XPC_WN_Equality))
inline JSBool
DebugCheckWrapperClass(JSObject* obj)
{
NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()),
"Forgot to check if this is a wrapper?");
return JS_TRUE;
}
// If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
// a slim wrapper, holding a native in its private slot, or a wrappednative
// wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
// also holds a pointer to its XPCWrappedNativeProto in a reserved slot, we can
// check that slot for a non-void value to distinguish between the two.
// Only use these macros if IS_WRAPPER_CLASS(obj->getClass()) is true.
#define IS_WN_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && \
obj->getSlot(0).isUndefined())
#define IS_SLIM_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && \
!obj->getSlot(0).isUndefined())
// Use these macros if IS_WRAPPER_CLASS(obj->getClass()) might be false.
// Avoid calling them if IS_WRAPPER_CLASS(obj->getClass()) can only be
// true, as we'd do a redundant call to IS_WRAPPER_CLASS.
#define IS_WN_WRAPPER(obj) \
(IS_WRAPPER_CLASS(obj->getClass()) && IS_WN_WRAPPER_OBJECT(obj))
#define IS_SLIM_WRAPPER(obj) \
(IS_WRAPPER_CLASS(obj->getClass()) && IS_SLIM_WRAPPER_OBJECT(obj))
// Comes from xpcwrappednativeops.cpp
extern void
xpc_TraceForValidWrapper(JSTracer *trc, XPCWrappedNative* wrapper);
@ -2463,7 +2424,6 @@ private:
};
void *xpc_GetJSPrivate(JSObject *obj);
inline JSObject *xpc_GetGlobalForObject(JSObject *obj);
/***************************************************************************/
// XPCWrappedNative the wrapper around one instance of a native xpcom object
@ -4457,13 +4417,6 @@ xpc_GetJSPrivate(JSObject *obj)
{
return obj->getPrivate();
}
inline JSObject *
xpc_GetGlobalForObject(JSObject *obj)
{
while(JSObject *parent = obj->getParent())
obj = parent;
return obj;
}
#ifndef XPCONNECT_STANDALONE

View File

@ -41,7 +41,10 @@
#define xpcpublic_h
#include "jsapi.h"
#include "nsISupports.h"
#include "jsobj.h"
#include "nsAString.h"
#include "nsIPrincipal.h"
#include "nsWrapperCache.h"
class nsIPrincipal;
@ -56,4 +59,65 @@ xpc_CreateMTGlobalObject(JSContext *cx, JSClass *clasp,
nsISupports *ptr, JSObject **global,
JSCompartment **compartment);
extern JSBool
XPC_WN_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
#define IS_WRAPPER_CLASS(clazz) \
(clazz->ext.equality == js::Valueify(XPC_WN_Equality))
inline JSBool
DebugCheckWrapperClass(JSObject* obj)
{
NS_ASSERTION(IS_WRAPPER_CLASS(obj->getClass()),
"Forgot to check if this is a wrapper?");
return JS_TRUE;
}
// If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
// a slim wrapper, holding a native in its private slot, or a wrappednative
// wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
// also holds a pointer to its XPCWrappedNativeProto in a reserved slot, we can
// check that slot for a non-void value to distinguish between the two.
// Only use these macros if IS_WRAPPER_CLASS(obj->getClass()) is true.
#define IS_WN_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && obj->getSlot(0).isUndefined())
#define IS_SLIM_WRAPPER_OBJECT(obj) \
(DebugCheckWrapperClass(obj) && !obj->getSlot(0).isUndefined())
// Use these macros if IS_WRAPPER_CLASS(obj->getClass()) might be false.
// Avoid calling them if IS_WRAPPER_CLASS(obj->getClass()) can only be
// true, as we'd do a redundant call to IS_WRAPPER_CLASS.
#define IS_WN_WRAPPER(obj) \
(IS_WRAPPER_CLASS(obj->getClass()) && IS_WN_WRAPPER_OBJECT(obj))
#define IS_SLIM_WRAPPER(obj) \
(IS_WRAPPER_CLASS(obj->getClass()) && IS_SLIM_WRAPPER_OBJECT(obj))
inline JSObject *
xpc_GetGlobalForObject(JSObject *obj)
{
while(JSObject *parent = obj->getParent())
obj = parent;
return obj;
}
inline JSObject*
xpc_GetCachedSlimWrapper(nsWrapperCache *cache, JSObject *scope, jsval *vp)
{
if (cache) {
JSObject* wrapper = cache->GetWrapper();
// FIXME: Bug 585786, the check for IS_SLIM_WRAPPER_OBJECT should go
// away
if (wrapper &&
IS_SLIM_WRAPPER_OBJECT(wrapper) &&
wrapper->getCompartment() == scope->getCompartment()) {
*vp = OBJECT_TO_JSVAL(wrapper);
return wrapper;
}
}
return nsnull;
}
#endif