Commit 6e720dd4 authored by commit-queue@webkit.org's avatar commit-queue@webkit.org
Browse files

Remove V8DOMWindowShell::getEntered

https://bugs.webkit.org/show_bug.cgi?id=96637

Patch by Dan Carney <dcarney@google.com> on 2012-09-14
Reviewed by Adam Barth.

V8DOMWindowShell::getEntered was refactored so that the window shell
no longer has to be kept alive by a v8 context but rather a smaller
object.

No new tests. No change in functionality.

* bindings/v8/DOMData.cpp:
(WebCore::DOMData::getCurrentStore):
* bindings/v8/ScopedPersistent.h:
(WebCore::ScopedPersistent::leakHandle):
(ScopedPersistent):
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::resetIsolatedWorlds):
(WebCore::ScriptController::evaluateInIsolatedWorld):
(WebCore::ScriptController::currentWorldContext):
* bindings/v8/V8Binding.cpp:
(WebCore::perContextDataForCurrentWorld):
* bindings/v8/V8DOMWindowShell.cpp:
(WebCore::setIsolatedWorldField):
(WebCore::V8DOMWindowShell::toIsolatedContextData):
(WebCore::isolatedContextWeakCallback):
(WebCore::V8DOMWindowShell::disposeContext):
(WebCore::V8DOMWindowShell::clearIsolatedShell):
(WebCore):
(WebCore::V8DOMWindowShell::initializeIfNeeded):
(WebCore::V8DOMWindowShell::setIsolatedWorldSecurityOrigin):
* bindings/v8/V8DOMWindowShell.h:
(V8DOMWindowShell):
(IsolatedContextData):
(WebCore::V8DOMWindowShell::IsolatedContextData::create):
(WebCore::V8DOMWindowShell::IsolatedContextData::world):
(WebCore::V8DOMWindowShell::IsolatedContextData::perContextData):
(WebCore::V8DOMWindowShell::IsolatedContextData::setSecurityOrigin):
(WebCore::V8DOMWindowShell::IsolatedContextData::securityOrigin):
(WebCore::V8DOMWindowShell::IsolatedContextData::IsolatedContextData):
(WebCore::V8DOMWindowShell::enteredIsolatedContext):
(WebCore::V8DOMWindowShell::enteredIsolatedContextData):
* bindings/v8/V8DOMWrapper.h:
(WebCore::V8DOMWrapper::getCachedWrapper):
* bindings/v8/WorldContextHandle.cpp:
(WebCore::WorldContextHandle::WorldContextHandle):
* bindings/v8/custom/V8DocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8HTMLDocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8SVGDocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8XMLHttpRequestConstructor.cpp:
(WebCore::V8XMLHttpRequest::constructorCallback):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@128669 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a978e2b2
2012-09-14 Dan Carney <dcarney@google.com>
Remove V8DOMWindowShell::getEntered
https://bugs.webkit.org/show_bug.cgi?id=96637
Reviewed by Adam Barth.
V8DOMWindowShell::getEntered was refactored so that the window shell
no longer has to be kept alive by a v8 context but rather a smaller
object.
No new tests. No change in functionality.
* bindings/v8/DOMData.cpp:
(WebCore::DOMData::getCurrentStore):
* bindings/v8/ScopedPersistent.h:
(WebCore::ScopedPersistent::leakHandle):
(ScopedPersistent):
* bindings/v8/ScriptController.cpp:
(WebCore::ScriptController::resetIsolatedWorlds):
(WebCore::ScriptController::evaluateInIsolatedWorld):
(WebCore::ScriptController::currentWorldContext):
* bindings/v8/V8Binding.cpp:
(WebCore::perContextDataForCurrentWorld):
* bindings/v8/V8DOMWindowShell.cpp:
(WebCore::setIsolatedWorldField):
(WebCore::V8DOMWindowShell::toIsolatedContextData):
(WebCore::isolatedContextWeakCallback):
(WebCore::V8DOMWindowShell::disposeContext):
(WebCore::V8DOMWindowShell::clearIsolatedShell):
(WebCore):
(WebCore::V8DOMWindowShell::initializeIfNeeded):
(WebCore::V8DOMWindowShell::setIsolatedWorldSecurityOrigin):
* bindings/v8/V8DOMWindowShell.h:
(V8DOMWindowShell):
(IsolatedContextData):
(WebCore::V8DOMWindowShell::IsolatedContextData::create):
(WebCore::V8DOMWindowShell::IsolatedContextData::world):
(WebCore::V8DOMWindowShell::IsolatedContextData::perContextData):
(WebCore::V8DOMWindowShell::IsolatedContextData::setSecurityOrigin):
(WebCore::V8DOMWindowShell::IsolatedContextData::securityOrigin):
(WebCore::V8DOMWindowShell::IsolatedContextData::IsolatedContextData):
(WebCore::V8DOMWindowShell::enteredIsolatedContext):
(WebCore::V8DOMWindowShell::enteredIsolatedContextData):
* bindings/v8/V8DOMWrapper.h:
(WebCore::V8DOMWrapper::getCachedWrapper):
* bindings/v8/WorldContextHandle.cpp:
(WebCore::WorldContextHandle::WorldContextHandle):
* bindings/v8/custom/V8DocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8HTMLDocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8SVGDocumentCustom.cpp:
(WebCore::toV8):
* bindings/v8/custom/V8XMLHttpRequestConstructor.cpp:
(WebCore::V8XMLHttpRequest::constructorCallback):
2012-09-14 Michelangelo De Simone <michelangelo@webkit.org>
 
[CSS Shaders] u_textureSize uniform should be set to the size of the texture.
......@@ -43,9 +43,9 @@ DOMDataStore& DOMData::getCurrentStore(v8::Isolate* isolate)
V8PerIsolateData* data = V8PerIsolateData::current(isolate);
if (UNLIKELY(data->domDataStore() != 0))
return *data->domDataStore();
V8DOMWindowShell* context = V8DOMWindowShell::getEntered();
if (UNLIKELY(context != 0))
return *context->world()->domDataStore();
V8DOMWindowShell::IsolatedContextData* isolatedData = V8DOMWindowShell::enteredIsolatedContextData();
if (UNLIKELY(!!isolatedData))
return *isolatedData->world()->domDataStore();
return defaultStore;
}
......
......@@ -78,6 +78,13 @@ public:
m_handle.Clear();
}
v8::Persistent<T> leakHandle()
{
v8::Persistent<T> handle = m_handle;
m_handle.Clear();
return handle;
}
private:
v8::Persistent<T> m_handle;
};
......
......@@ -146,7 +146,8 @@ void ScriptController::resetIsolatedWorlds()
{
for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin();
iter != m_isolatedWorlds.end(); ++iter) {
iter->second->destroyIsolatedShell();
iter->second->clearIsolatedShell();
delete iter->second;
}
m_isolatedWorlds.clear();
m_isolatedWorldSecurityOrigins.clear();
......@@ -389,11 +390,12 @@ void ScriptController::evaluateInIsolatedWorld(int worldID, const Vector<ScriptS
resultArray->Set(i, evaluationResult);
}
// Mark temporary shell for weak destruction.
// Destroy temporary world.
if (worldID == DOMWrapperWorld::uninitializedWorldId) {
int actualWorldId = isolatedWorldShell->world()->worldId();
m_isolatedWorlds.remove(actualWorldId);
isolatedWorldShell->destroyIsolatedShell();
isolatedWorldShell->clearIsolatedShell();
delete isolatedWorldShell;
}
v8Results = evaluateHandleScope.Close(resultArray);
......@@ -428,11 +430,11 @@ void ScriptController::finishedWithEvent(Event* event)
v8::Local<v8::Context> ScriptController::currentWorldContext()
{
if (V8DOMWindowShell* isolatedShell = V8DOMWindowShell::getEntered()) {
v8::Persistent<v8::Context> context = isolatedShell->context();
if (context.IsEmpty() || m_frame != toFrameIfNotDetached(context))
v8::Local<v8::Context> isolatedContext = V8DOMWindowShell::enteredIsolatedContext();
if (UNLIKELY(!isolatedContext.IsEmpty())) {
if (m_frame != toFrameIfNotDetached(isolatedContext))
return v8::Local<v8::Context>();
return v8::Local<v8::Context>::New(context);
return v8::Local<v8::Context>::New(isolatedContext);
}
windowShell()->initializeIfNeeded();
return v8::Local<v8::Context>::New(windowShell()->context());
......
......@@ -310,9 +310,9 @@ v8::Local<v8::Context> toV8Context(ScriptExecutionContext* context, const WorldC
V8PerContextData* perContextDataForCurrentWorld(Frame* frame)
{
V8DOMWindowShell* isolatedShell;
if (UNLIKELY(!!(isolatedShell = V8DOMWindowShell::getEntered())))
return isolatedShell->perContextData();
V8DOMWindowShell::IsolatedContextData* isolatedShellData;
if (UNLIKELY(!!(isolatedShellData = V8DOMWindowShell::enteredIsolatedContextData())))
return isolatedShellData->perContextData();
return frame->script()->windowShell()->perContextData();
}
......
......@@ -171,14 +171,14 @@ static void checkDocumentWrapper(v8::Handle<v8::Object> wrapper, Document* docum
ASSERT(!document->isHTMLDocument() || (V8Document::toNative(v8::Handle<v8::Object>::Cast(wrapper->GetPrototype())) == document));
}
static void setIsolatedWorldField(V8DOMWindowShell* shell, v8::Local<v8::Context> context)
static void setIsolatedWorldField(V8DOMWindowShell::IsolatedContextData* data, v8::Handle<v8::Context> context)
{
toInnerGlobalObject(context)->SetPointerInInternalField(V8DOMWindow::enteredIsolatedWorldIndex, shell);
toInnerGlobalObject(context)->SetPointerInInternalField(V8DOMWindow::enteredIsolatedWorldIndex, data);
}
V8DOMWindowShell* V8DOMWindowShell::enteredIsolatedWorldContext()
V8DOMWindowShell::IsolatedContextData* V8DOMWindowShell::toIsolatedContextData(v8::Handle<v8::Context> context)
{
return static_cast<V8DOMWindowShell*>(toInnerGlobalObject(v8::Context::GetEntered())->GetPointerFromInternalField(V8DOMWindow::enteredIsolatedWorldIndex));
return static_cast<IsolatedContextData*>(toInnerGlobalObject(context)->GetPointerFromInternalField(V8DOMWindow::enteredIsolatedWorldIndex));
}
static void setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContext, int debugId)
......@@ -208,20 +208,14 @@ bool V8DOMWindowShell::isContextInitialized()
return !m_context.isEmpty();
}
void V8DOMWindowShell::destroyIsolatedShell()
{
disposeContext(true);
}
static void isolatedContextWeakCallback(v8::Persistent<v8::Value> object, void* parameter)
{
// Handle will be disposed in delete.
delete static_cast<V8DOMWindowShell*>(parameter);
object.Dispose();
delete static_cast<V8DOMWindowShell::IsolatedContextData*>(parameter);
}
void V8DOMWindowShell::disposeContext(bool weak)
void V8DOMWindowShell::disposeContext()
{
ASSERT(!m_context.get().IsWeak());
m_perContextData.clear();
if (m_context.isEmpty())
......@@ -229,14 +223,14 @@ void V8DOMWindowShell::disposeContext(bool weak)
m_frame->loader()->client()->willReleaseScriptContext(m_context.get(), m_world->worldId());
if (!weak)
m_context.clear();
else {
if (m_isolatedContextData) {
ASSERT(!m_world->isMainWorld());
destroyGlobal();
m_frame = 0;
m_context.get().MakeWeak(this, isolatedContextWeakCallback);
}
// Here we must intentionally leak the per context data pointer as it gets deleted in isolatedContextWeakCallback.
m_context.leakHandle().MakeWeak(m_isolatedContextData.leakPtr(), isolatedContextWeakCallback);
// The global handle keeps a reference to the context, so it must be removed.
m_global.clear();
} else
m_context.clear();
// It's likely that disposing the context has created a lot of
// garbage. Notify V8 about this so it'll have a chance of cleaning
......@@ -252,6 +246,11 @@ void V8DOMWindowShell::destroyGlobal()
m_global.clear();
}
void V8DOMWindowShell::clearIsolatedShell()
{
disposeContext();
}
void V8DOMWindowShell::clearForClose()
{
if (m_context.isEmpty())
......@@ -346,19 +345,20 @@ bool V8DOMWindowShell::initializeIfNeeded()
}
}
m_perContextData = V8PerContextData::create(m_context.get());
if (!m_perContextData->init()) {
disposeContext();
return false;
}
// Flag context as isolated.
if (!isMainWorld) {
V8DOMWindowShell* mainWindow = m_frame->script()->windowShell();
mainWindow->initializeIfNeeded();
if (!mainWindow->context().IsEmpty())
setInjectedScriptContextDebugId(m_context.get(), m_frame->script()->contextDebugId(mainWindow->context()));
setIsolatedWorldField(this, context);
}
m_perContextData = V8PerContextData::create(m_context.get());
if (!m_perContextData->init()) {
disposeContext();
return false;
m_isolatedContextData = IsolatedContextData::create(m_world, m_perContextData.release(), m_isolatedWorldShellSecurityOrigin);
setIsolatedWorldField(m_isolatedContextData.get(), context);
}
if (!installDOMWindow()) {
......@@ -618,6 +618,8 @@ void V8DOMWindowShell::setIsolatedWorldSecurityOrigin(PassRefPtr<SecurityOrigin>
InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, securityOrigin.get());
}
m_isolatedWorldShellSecurityOrigin = securityOrigin;
if (m_isolatedContextData)
m_isolatedContextData->setSecurityOrigin(m_isolatedWorldShellSecurityOrigin);
}
} // WebCore
......@@ -53,6 +53,34 @@ class HTMLDocument;
// persist between navigations.
class V8DOMWindowShell {
public:
// This class holds all the data that is accessible from a context for an isolated shell.
// It survives until the context is deleted.
class IsolatedContextData {
WTF_MAKE_NONCOPYABLE(IsolatedContextData);
public:
static PassOwnPtr<IsolatedContextData> create(PassRefPtr<DOMWrapperWorld> world, PassOwnPtr<V8PerContextData> perContextData,
PassRefPtr<SecurityOrigin> securityOrigin)
{
return adoptPtr(new IsolatedContextData(world, perContextData, securityOrigin));
}
DOMWrapperWorld* world() { return m_world.get(); }
V8PerContextData* perContextData() { return m_perContextData.get(); }
void setSecurityOrigin(PassRefPtr<SecurityOrigin> origin) { m_securityOrigin = origin; }
SecurityOrigin* securityOrigin() { return m_securityOrigin.get(); }
private:
IsolatedContextData(PassRefPtr<DOMWrapperWorld> world, PassOwnPtr<V8PerContextData> perContextData, PassRefPtr<SecurityOrigin> securityOrigin)
: m_world(world)
, m_perContextData(perContextData)
, m_securityOrigin(securityOrigin)
{ }
RefPtr<DOMWrapperWorld> m_world;
OwnPtr<V8PerContextData> m_perContextData;
RefPtr<SecurityOrigin> m_securityOrigin;
};
static PassOwnPtr<V8DOMWindowShell> create(Frame*, PassRefPtr<DOMWrapperWorld>);
v8::Persistent<v8::Context> context() const { return m_context.get(); }
......@@ -76,6 +104,7 @@ public:
void clearForNavigation();
void clearForClose();
void clearIsolatedShell();
void destroyGlobal();
......@@ -90,29 +119,36 @@ public:
return m_isolatedWorldShellSecurityOrigin.get();
};
// Returns the isolated world associated with
// v8::Context::GetEntered(). Because worlds are isolated, the entire
// JavaScript call stack should be from the same isolated world.
// Returns 0 if the entered context is from the main world.
//
// FIXME: Consider edge cases with DOM mutation events that might
// violate this invariant.
//
// FIXME: This is poorly named after the deletion of isolated contexts.
static V8DOMWindowShell* getEntered()
inline static v8::Local<v8::Context> enteredIsolatedContext()
{
if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist()))
return v8::Local<v8::Context>();
if (!v8::Context::InContext())
return v8::Local<v8::Context>();
v8::Local<v8::Context> context = v8::Context::GetEntered();
IsolatedContextData* isolatedContextData = toIsolatedContextData(context);
if (LIKELY(!isolatedContextData))
return v8::Local<v8::Context>();
return context;
}
inline static IsolatedContextData* enteredIsolatedContextData()
{
if (!DOMWrapperWorld::isolatedWorldsExist())
if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist()))
return 0;
if (!v8::Context::InContext())
return 0;
return enteredIsolatedWorldContext();
v8::Local<v8::Context> context = v8::Context::GetEntered();
IsolatedContextData* isolatedContextData = toIsolatedContextData(context);
if (LIKELY(!isolatedContextData))
return 0;
return isolatedContextData;
}
void destroyIsolatedShell();
private:
V8DOMWindowShell(Frame*, PassRefPtr<DOMWrapperWorld>);
void disposeContext(bool weak = false);
void disposeContext();
void setSecurityToken();
......@@ -126,12 +162,13 @@ private:
void createContext();
bool installDOMWindow();
static V8DOMWindowShell* enteredIsolatedWorldContext();
static IsolatedContextData* toIsolatedContextData(v8::Handle<v8::Context>);
Frame* m_frame;
RefPtr<DOMWrapperWorld> m_world;
OwnPtr<V8PerContextData> m_perContextData;
OwnPtr<IsolatedContextData> m_isolatedContextData;
ScopedPersistent<v8::Context> m_context;
ScopedPersistent<v8::Object> m_global;
......
......@@ -118,14 +118,14 @@ namespace WebCore {
return *wrapper;
}
V8DOMWindowShell* context = V8DOMWindowShell::getEntered();
if (LIKELY(!context)) {
V8DOMWindowShell::IsolatedContextData* isolatedData = V8DOMWindowShell::enteredIsolatedContextData();
if (LIKELY(!isolatedData)) {
v8::Persistent<v8::Object>* wrapper = node->wrapper();
if (!wrapper)
return v8::Handle<v8::Object>();
return *wrapper;
}
DOMDataStore* store = context->world()->domDataStore();
DOMDataStore* store = isolatedData->world()->domDataStore();
DOMNodeMapping& domNodeMap = node->isActiveNode() ? store->activeDomNodeMap() : store->domNodeMap();
return domNodeMap.get(node);
}
......
......@@ -57,14 +57,13 @@ WorldContextHandle::WorldContextHandle(WorldToUse worldToUse)
}
#endif
V8DOMWindowShell* shell = V8DOMWindowShell::getEntered();
if (LIKELY(!shell)) {
v8::Local<v8::Context> isolatedContext = V8DOMWindowShell::enteredIsolatedContext();
if (LIKELY(isolatedContext.IsEmpty())) {
m_worldToUse = UseMainWorld;
return;
}
ASSERT(!shell->context().IsEmpty());
m_context = SharedPersistent<v8::Context>::create(shell->context());
m_context = SharedPersistent<v8::Context>::create(isolatedContext);
}
v8::Local<v8::Context> WorldContextHandle::adjustedContext(ScriptController* script) const
......
......@@ -108,7 +108,7 @@ v8::Handle<v8::Value> toV8(Document* impl, v8::Handle<v8::Object> creationContex
v8::Handle<v8::Object> wrapper = V8Document::wrap(impl, creationContext, isolate, forceNewObject);
if (wrapper.IsEmpty())
return wrapper;
if (!V8DOMWindowShell::getEntered()) {
if (V8DOMWindowShell::enteredIsolatedContext().IsEmpty()) {
if (Frame* frame = impl->frame())
frame->script()->windowShell()->updateDocumentWrapper(wrapper);
}
......
......@@ -183,7 +183,7 @@ v8::Handle<v8::Value> toV8(HTMLDocument* impl, v8::Handle<v8::Object> creationCo
v8::Handle<v8::Object> wrapper = V8HTMLDocument::wrap(impl, creationContext, isolate, forceNewObject);
if (wrapper.IsEmpty())
return wrapper;
if (!V8DOMWindowShell::getEntered()) {
if (V8DOMWindowShell::enteredIsolatedContext().IsEmpty()) {
if (Frame* frame = impl->frame())
frame->script()->windowShell()->updateDocumentWrapper(wrapper);
}
......
......@@ -45,7 +45,7 @@ v8::Handle<v8::Value> toV8(SVGDocument* impl, v8::Handle<v8::Object> creationCon
v8::Handle<v8::Object> wrapper = V8SVGDocument::wrap(impl, creationContext, isolate, forceNewObject);
if (wrapper.IsEmpty())
return wrapper;
if (!V8DOMWindowShell::getEntered()) {
if (V8DOMWindowShell::enteredIsolatedContext().IsEmpty()) {
if (Frame* frame = impl->frame())
frame->script()->windowShell()->updateDocumentWrapper(wrapper);
}
......
......@@ -55,8 +55,8 @@ v8::Handle<v8::Value> V8XMLHttpRequest::constructorCallback(const v8::Arguments&
ScriptExecutionContext* context = getScriptExecutionContext();
RefPtr<SecurityOrigin> securityOrigin;
if (V8DOMWindowShell* isolatedWorldShell = V8DOMWindowShell::getEntered())
securityOrigin = isolatedWorldShell->isolatedWorldSecurityOrigin();
if (V8DOMWindowShell::IsolatedContextData* isolatedContextData = V8DOMWindowShell::enteredIsolatedContextData())
securityOrigin = isolatedContextData->securityOrigin();
RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin);
......
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