Commit f49851c9 authored by antonm@chromium.org's avatar antonm@chromium.org
Browse files

2010-09-06 Anton Muhin <antonm@chromium.org>

        Reviewed by Adam Barth.

        [v8] Inline hot methods for V8 to WebCore and back conversions
        https://bugs.webkit.org/show_bug.cgi?id=45270

        Inline fast paths of hot functions performing conversions from V8 wrappers
        to WebCore native objects and back.
        That slightly increases the size of binary (within 0.1% for both Ubuntu
        and Windows, but those builds are slightly different from official ones),
        but gives performance boost (3--5% on Windows, up to 8% on Ubuntu).

        * bindings/scripts/CodeGeneratorV8.pm:
        * bindings/v8/V8DOMWindowShell.cpp:
        (WebCore::V8DOMWindowShell::initContextIfNeeded):
        * bindings/v8/V8DOMWindowShell.h:
        * bindings/v8/V8DOMWrapper.cpp:
        (WebCore::V8DOMWrapper::getWrapperSlow):
        * bindings/v8/V8DOMWrapper.h:
        (WebCore::V8DOMWrapper::getWrapper):
        * bindings/v8/custom/V8NodeCustom.cpp:
        (WebCore::toV8Slow):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@66840 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 07e1356e
2010-09-06 Anton Muhin <antonm@chromium.org>
Reviewed by Adam Barth.
[v8] Inline hot methods for V8 to WebCore and back conversions
https://bugs.webkit.org/show_bug.cgi?id=45270
Inline fast paths of hot functions performing conversions from V8 wrappers
to WebCore native objects and back.
That slightly increases the size of binary (within 0.1% for both Ubuntu
and Windows, but those builds are slightly different from official ones),
but gives performance boost (3--5% on Windows, up to 8% on Ubuntu).
* bindings/scripts/CodeGeneratorV8.pm:
* bindings/v8/V8DOMWindowShell.cpp:
(WebCore::V8DOMWindowShell::initContextIfNeeded):
* bindings/v8/V8DOMWindowShell.h:
* bindings/v8/V8DOMWrapper.cpp:
(WebCore::V8DOMWrapper::getWrapperSlow):
* bindings/v8/V8DOMWrapper.h:
(WebCore::V8DOMWrapper::getWrapper):
* bindings/v8/custom/V8NodeCustom.cpp:
(WebCore::toV8Slow):
2010-09-06 Shane Stephens <shanestephens@google.com>
 
Reviewed by Dimitri Glazkov.
......@@ -233,6 +233,7 @@ sub GenerateHeader
$headerIncludes{"$podType.h"} = 1 if $podType and ($podType ne "double" and $podType ne "float" and $podType ne "RGBA32");
$headerIncludes{"wtf/text/StringHash.h"} = 1;
$headerIncludes{"WrapperTypeInfo.h"} = 1;
$headerIncludes{"V8DOMWrapper.h"} = 1;
my $headerClassInclude = GetHeaderClassInclude($implClassName);
$headerIncludes{$headerClassInclude} = 1 if $headerClassInclude ne "";
......@@ -253,15 +254,23 @@ sub GenerateHeader
if ($podType) {
$nativeType = "V8SVGPODTypeWrapper<${nativeType} >";
}
my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
my $forceNewObjectParameter = IsDOMNodeType($interfaceName) ? ", bool forceNewObject = false" : "";
my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
my $forceNewObjectCall = IsDOMNodeType($interfaceName) ? ", forceNewObject" : "";
push(@headerContent, <<END);
public:
static bool HasInstance(v8::Handle<v8::Value> value);
static v8::Persistent<v8::FunctionTemplate> GetRawTemplate();
static v8::Persistent<v8::FunctionTemplate> GetTemplate();
static ${nativeType}* toNative(v8::Handle<v8::Object>);
static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
static ${nativeType}* toNative(v8::Handle<v8::Object> object)
{
return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
}
inline static v8::Handle<v8::Object> wrap(${nativeType}*${forceNewObjectParameter});
static void derefObject(void*);
static WrapperTypeInfo info;
END
......@@ -336,13 +345,72 @@ END
}
push(@headerContent, <<END);
private:
static v8::Handle<v8::Object> wrapSlow(${nativeType}*);
};
END
push(@headerContent, <<END);
v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
{
END
if ($domMapFunction) {
push(@headerContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
my $getWrapper = IsNodeSubType($dataNode) ? "V8DOMWrapper::getWrapper(impl)" : "${domMapFunction}.get(impl)";
push(@headerContent, <<END);
v8::Handle<v8::Object> wrapper = ${getWrapper};
if (!wrapper.IsEmpty())
return wrapper;
END
push(@headerContent, " }\n") if IsDOMNodeType($interfaceName);
}
push(@headerContent, <<END);
return ${className}::wrapSlow(impl);
}
END
if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
push(@headerContent, <<END);
inline v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectParameter})
{
if (!impl)
return v8::Null();
return ${className}::wrap(impl${forceNewObjectCall});
}
END
} elsif ($interfaceName ne 'Node') {
push(@headerContent, <<END);
v8::Handle<v8::Value> toV8(${nativeType}*${forceNewObjectParameter});
END
} else {
push(@headerContent, <<END);
v8::Handle<v8::Value> toV8Slow(Node*, bool);
inline v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject = false)
{
if (!impl)
return v8::Null();
if (!forceNewObject) {
v8::Handle<v8::Value> wrapper = V8DOMWrapper::getWrapper(impl);
if (!wrapper.IsEmpty())
return wrapper;
}
return toV8Slow(impl, forceNewObject);
}
END
}
if (IsRefPtrType($implClassName)) {
push(@headerContent, <<END);
v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} >${forceNewObjectParameter});
inline v8::Handle<v8::Value> toV8(PassRefPtr< ${nativeType} > impl${forceNewObjectParameter})
{
return toV8(impl.get()${forceNewObjectCall});
}
END
}
......@@ -2086,11 +2154,6 @@ v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate()\
return ${className}Cache;
}
${nativeType}* ${className}::toNative(v8::Handle<v8::Object> object)
{
return reinterpret_cast<${nativeType}*>(object->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
}
bool ${className}::HasInstance(v8::Handle<v8::Value> value)
{
return GetRawTemplate()->HasInstance(value);
......@@ -2359,7 +2422,7 @@ sub GenerateToV8Converters
push(@implContent, <<END);
v8::Handle<v8::Object> ${className}::wrap(${nativeType}* impl${forceNewObjectInput})
v8::Handle<v8::Object> ${className}::wrapSlow(${nativeType}* impl)
{
v8::Handle<v8::Object> wrapper;
V8Proxy* proxy = 0;
......@@ -2369,26 +2432,17 @@ END
push(@implContent, <<END);
if (impl->document()) {
proxy = V8Proxy::retrieve(impl->document()->frame());
if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl))
proxy->windowShell()->initContextIfNeeded();
if (proxy && static_cast<Node*>(impl->document()) == static_cast<Node*>(impl)) {
if (proxy->windowShell()->initContextIfNeeded()) {
// initContextIfNeeded may have created a wrapper for the object, retry from the start.
return ${className}::wrap(impl);
}
}
}
END
}
if ($domMapFunction) {
push(@implContent, " if (!forceNewObject) {\n") if IsDOMNodeType($interfaceName);
if (IsNodeSubType($dataNode)) {
push(@implContent, " wrapper = V8DOMWrapper::getWrapper(impl);\n");
} else {
push(@implContent, " wrapper = ${domMapFunction}.get(impl);\n");
}
push(@implContent, <<END);
if (!wrapper.IsEmpty())
return wrapper;
END
push(@implContent, " }\n") if IsDOMNodeType($interfaceName);
}
if (IsNodeSubType($dataNode)) {
push(@implContent, <<END);
......@@ -2445,28 +2499,6 @@ END
return wrapper;
}
END
if (IsRefPtrType($interfaceName)) {
push(@implContent, <<END);
v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl${forceNewObjectInput})
{
return toV8(impl.get()${forceNewObjectCall});
}
END
}
if (!HasCustomToV8Implementation($dataNode, $interfaceName)) {
push(@implContent, <<END);
v8::Handle<v8::Value> toV8(${nativeType}* impl${forceNewObjectInput})
{
if (!impl)
return v8::Null();
return ${className}::wrap(impl${forceNewObjectCall});
}
END
}
}
sub HasCustomToV8Implementation {
......
......@@ -242,11 +242,11 @@ void V8DOMWindowShell::clearForNavigation()
// the frame. However, a new inner window is created for the new page.
// If there are JS code holds a closure to the old inner window,
// it won't be able to reach the outer window via its global object.
void V8DOMWindowShell::initContextIfNeeded()
bool V8DOMWindowShell::initContextIfNeeded()
{
// Bail out if the context has already been initialized.
if (!m_context.IsEmpty())
return;
return false;
// Create a handle scope for all local handles.
v8::HandleScope handleScope;
......@@ -273,7 +273,7 @@ void V8DOMWindowShell::initContextIfNeeded()
m_context = createNewContext(m_global, 0);
if (m_context.IsEmpty())
return;
return false;
v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context);
v8::Context::Scope contextScope(v8Context);
......@@ -284,7 +284,7 @@ void V8DOMWindowShell::initContextIfNeeded()
// Bail out if allocation of the first global objects fails.
if (m_global.IsEmpty()) {
disposeContextHandles();
return;
return false;
}
#ifndef NDEBUG
V8GCController::registerGlobalHandle(PROXY, this, m_global);
......@@ -293,12 +293,12 @@ void V8DOMWindowShell::initContextIfNeeded()
if (!installHiddenObjectPrototype(v8Context)) {
disposeContextHandles();
return;
return false;
}
if (!installDOMWindow(v8Context, m_frame->domWindow())) {
disposeContextHandles();
return;
return false;
}
updateDocument();
......@@ -310,6 +310,8 @@ void V8DOMWindowShell::initContextIfNeeded()
// FIXME: This is wrong. We should actually do this for the proper world once
// we do isolated worlds the WebCore way.
m_frame->loader()->dispatchDidClearWindowObjectInWorld(0);
return true;
}
v8::Persistent<v8::Context> V8DOMWindowShell::createNewContext(v8::Handle<v8::Object> global, int extensionGroup)
......
......@@ -69,7 +69,7 @@ public:
void setContext(v8::Handle<v8::Context>);
static bool installDOMWindow(v8::Handle<v8::Context> context, DOMWindow*);
void initContextIfNeeded();
bool initContextIfNeeded();
void updateDocumentWrapper(v8::Handle<v8::Object> wrapper);
void clearForNavigation();
......
......@@ -329,9 +329,8 @@ bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, WrapperTypeInfo*
return typeInfo == type;
}
v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node)
v8::Handle<v8::Object> V8DOMWrapper::getWrapperSlow(Node* node)
{
ASSERT(WTF::isMainThread());
V8IsolatedContext* context = V8IsolatedContext::getEntered();
if (LIKELY(!context)) {
v8::Persistent<v8::Object>* wrapper = node->wrapper();
......@@ -339,7 +338,6 @@ v8::Handle<v8::Object> V8DOMWrapper::getWrapper(Node* node)
return v8::Handle<v8::Object>();
return *wrapper;
}
DOMNodeMapping& domNodeMap = context->world()->domDataStore()->domNodeMap();
return domNodeMap.get(node);
}
......
......@@ -33,6 +33,7 @@
#include "Document.h"
#include "Event.h"
#include "IsolatedWorld.h"
#include "Node.h"
#include "NodeFilter.h"
#include "PlatformString.h"
......@@ -130,7 +131,19 @@ namespace WebCore {
static v8::Local<v8::Object> instantiateV8Object(V8Proxy* proxy, WrapperTypeInfo*, void* impl);
static v8::Handle<v8::Object> getWrapper(Node*);
static v8::Handle<v8::Object> getWrapper(Node* node)
{
ASSERT(WTF::isMainThread());
if (LIKELY(!IsolatedWorld::count())) {
v8::Persistent<v8::Object>* wrapper = node->wrapper();
if (wrapper)
return *wrapper;
}
return getWrapperSlow(node);
}
private:
static v8::Handle<v8::Object> getWrapperSlow(Node*);
};
}
......
......@@ -130,7 +130,7 @@ v8::Handle<v8::Value> V8Node::appendChildCallback(const v8::Arguments& args)
return v8::Null();
}
v8::Handle<v8::Value> toV8(Node* impl, bool forceNewObject)
v8::Handle<v8::Value> toV8Slow(Node* impl, bool forceNewObject)
{
if (!impl)
return v8::Null();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment