Fixing one more part of the DOM performance bug 118933. Cache the properties 'document' and 'window' on the global object in JS to avoid needing to go through XPConnect every time these are accessed. 2x speedup on some DOM testcases where the bulk of the time we spend is in the JS engine and XPConnect. r=peterv@netscape.com, sr=vidur@netscape.com

This commit is contained in:
jst%netscape.com 2002-04-27 00:03:47 +00:00
Родитель d7ab4fab24
Коммит 5909fbe828
3 изменённых файлов: 93 добавлений и 10 удалений

Просмотреть файл

@ -839,6 +839,8 @@ JSString *nsDOMClassInfo::sOpen_id = nsnull;
JSString *nsDOMClassInfo::sItem_id = nsnull; JSString *nsDOMClassInfo::sItem_id = nsnull;
JSString *nsDOMClassInfo::sEnumerate_id = nsnull; JSString *nsDOMClassInfo::sEnumerate_id = nsnull;
JSString *nsDOMClassInfo::sNavigator_id = nsnull; JSString *nsDOMClassInfo::sNavigator_id = nsnull;
JSString *nsDOMClassInfo::sDocument_id = nsnull;
JSString *nsDOMClassInfo::sWindow_id = nsnull;
const JSClass *nsDOMClassInfo::sObjectClass = nsnull; const JSClass *nsDOMClassInfo::sObjectClass = nsnull;
@ -913,6 +915,8 @@ nsDOMClassInfo::DefineStaticJSStrings(JSContext *cx)
sItem_id = ::JS_InternString(cx, "item"); sItem_id = ::JS_InternString(cx, "item");
sEnumerate_id = ::JS_InternString(cx, "enumerateProperties"); sEnumerate_id = ::JS_InternString(cx, "enumerateProperties");
sNavigator_id = ::JS_InternString(cx, "navigator"); sNavigator_id = ::JS_InternString(cx, "navigator");
sDocument_id = ::JS_InternString(cx, "document");
sWindow_id = ::JS_InternString(cx, "window");
return NS_OK; return NS_OK;
} }
@ -2666,6 +2670,8 @@ nsDOMClassInfo::ShutDown()
sItem_id = jsnullstring; sItem_id = jsnullstring;
sEnumerate_id = jsnullstring; sEnumerate_id = jsnullstring;
sNavigator_id = jsnullstring; sNavigator_id = jsnullstring;
sDocument_id = jsnullstring;
sWindow_id = jsnullstring;
NS_IF_RELEASE(sXPConnect); NS_IF_RELEASE(sXPConnect);
NS_IF_RELEASE(sSecMan); NS_IF_RELEASE(sSecMan);
@ -2769,10 +2775,13 @@ nsWindowSH::doCheckPropertyAccess(JSContext *cx, JSObject *obj, jsval id,
return NS_OK; return NS_OK;
} }
// Don't check when getting the Components property, // Don't check when getting the document, window, or Components
// since we check its properties anyway. This will help performance. // property, since we check its properties anyway. This will help
// performance.
if (accessMode == nsIXPCSecurityManager::ACCESS_GET_PROPERTY && if (accessMode == nsIXPCSecurityManager::ACCESS_GET_PROPERTY &&
id == STRING_TO_JSVAL(sComponents_id)) { (id == STRING_TO_JSVAL(sDocument_id) ||
id == STRING_TO_JSVAL(sWindow_id) ||
id == STRING_TO_JSVAL(sComponents_id))) {
return NS_OK; return NS_OK;
} }
@ -2977,7 +2986,8 @@ nsWindowSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK; return NS_OK;
} }
nsresult rv = doCheckPropertyAccess(cx, obj, id, wrapper, nsresult rv =
doCheckPropertyAccess(cx, obj, id, wrapper,
nsIXPCSecurityManager::ACCESS_SET_PROPERTY); nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -2996,7 +3006,8 @@ nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
PRBool *_retval) PRBool *_retval)
{ {
nsresult rv = doCheckPropertyAccess(cx, obj, id, wrapper, nsresult rv =
doCheckPropertyAccess(cx, obj, id, wrapper,
nsIXPCSecurityManager::ACCESS_SET_PROPERTY); nsIXPCSecurityManager::ACCESS_SET_PROPERTY);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
@ -3565,6 +3576,31 @@ nsWindowSH::GlobalResolve(nsISupports *native, JSContext *cx, JSObject *obj,
return rv; return rv;
} }
// static
nsresult
nsWindowSH::CacheDocumentProperty(JSContext *cx, JSObject *obj,
nsIDOMWindow *window)
{
nsCOMPtr<nsIDOMDocument> document;
nsresult rv = window->GetDocument(getter_AddRefs(document));
NS_ENSURE_SUCCESS(rv, rv);
jsval v;
rv = WrapNative(cx, obj, document, NS_GET_IID(nsIDOMDocument), &v);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_STRING(doc_str, "document");
if (!::JS_DefineUCProperty(cx, obj, NS_REINTERPRET_CAST(const jschar *,
doc_str.get()),
doc_str.Length(), v, nsnull,
nsnull, JSPROP_READONLY)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsval id, PRUint32 flags, JSObject *obj, jsval id, PRUint32 flags,
@ -3777,6 +3813,34 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK; return NS_OK;
} }
if (str == sDocument_id) {
nsCOMPtr<nsIDOMWindowInternal> window(do_QueryInterface(native));
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
rv = CacheDocumentProperty(cx, obj, window);
NS_ENSURE_SUCCESS(rv, rv);
*objp = obj;
return NS_OK;
}
if (str == sWindow_id) {
jsval v;
rv = WrapNative(cx, obj, native, NS_GET_IID(nsIDOMWindow), &v);
NS_ENSURE_SUCCESS(rv, rv);
if (!::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
::JS_GetStringLength(str), v, nsnull,
nsnull, JSPROP_READONLY)) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
} }
return nsEventRecieverSH::NewResolve(wrapper, cx, obj, id, flags, objp, return nsEventRecieverSH::NewResolve(wrapper, cx, obj, id, flags, objp,

Просмотреть файл

@ -45,6 +45,7 @@
#include "jsapi.h" #include "jsapi.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
class nsIDOMWindow;
class nsIDOMNSHTMLOptionCollection; class nsIDOMNSHTMLOptionCollection;
class nsIPluginInstance; class nsIPluginInstance;
class nsIForm; class nsIForm;
@ -233,6 +234,8 @@ protected:
static JSString *sItem_id; static JSString *sItem_id;
static JSString *sEnumerate_id; static JSString *sEnumerate_id;
static JSString *sNavigator_id; static JSString *sNavigator_id;
static JSString *sDocument_id;
static JSString *sWindow_id;
static const JSClass *sObjectClass; static const JSClass *sObjectClass;
@ -323,6 +326,9 @@ public:
NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx, NS_IMETHOD Finalize(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj); JSObject *obj);
static nsresult CacheDocumentProperty(JSContext *cx, JSObject *obj,
nsIDOMWindow *window);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData) static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{ {
return new nsWindowSH(aData); return new nsWindowSH(aData);

Просмотреть файл

@ -479,7 +479,9 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
// not doing this unless there's a new document prevents a closed window's // not doing this unless there's a new document prevents a closed window's
// JS properties from going away (that's good) and causes everything, // JS properties from going away (that's good) and causes everything,
// and I mean everything, to be leaked (that's bad) // and I mean everything, to be leaked (that's bad)
::JS_ClearScope((JSContext *)mContext->GetNativeContext(), mJSObject);
::JS_ClearScope((JSContext *)mContext->GetNativeContext(),
mJSObject);
mIsScopeClear = PR_TRUE; mIsScopeClear = PR_TRUE;
} }
@ -498,8 +500,19 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument* aDocument,
mDocument = aDocument; mDocument = aDocument;
if (mDocument && mContext && mIsScopeClear) { if (mDocument && mContext) {
if (mIsScopeClear) {
mContext->InitContext(this); mContext->InitContext(this);
} else if (mJSObject) {
// If we didn't clear the scope (i.e. the old document was
// about:blank) then we need to update the cached document
// property on the window to reflect the new document and not
// the old one.
JSContext *cx = (JSContext *)mContext->GetNativeContext();
nsWindowSH::CacheDocumentProperty(cx, mJSObject, this);
}
} }
// Clear our mutation bitfield. // Clear our mutation bitfield.