Commit 5565fad0 authored by rafaelw@chromium.org's avatar rafaelw@chromium.org

Use v8 Microtask Queue

V8 now hosts the end-of-microtask work queue. This allows consistent
scheduling of microtask work regardless of where it is implemented (v8 vs blink).

R=adamk@chromium.org

Review URL: https://codereview.chromium.org/167683003

git-svn-id: svn://svn.chromium.org/blink/trunk@169978 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 12a4cf33
...@@ -5,6 +5,7 @@ Set timer for test function. ...@@ -5,6 +5,7 @@ Set timer for test function.
Captured call stacks in no particular order: Captured call stacks in no particular order:
Call stack: Call stack:
0) mutationCallback (async-callstack-mutation-observer.html:21) 0) mutationCallback (async-callstack-mutation-observer.html:21)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) timeout1 (async-callstack-mutation-observer.html:44) 1) timeout1 (async-callstack-mutation-observer.html:44)
...@@ -13,6 +14,7 @@ Call stack: ...@@ -13,6 +14,7 @@ Call stack:
Call stack: Call stack:
0) mutationCallback (async-callstack-mutation-observer.html:21) 0) mutationCallback (async-callstack-mutation-observer.html:21)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations2 (async-callstack-mutation-observer.html:64) 0) doMutations2 (async-callstack-mutation-observer.html:64)
1) timeout2 (async-callstack-mutation-observer.html:57) 1) timeout2 (async-callstack-mutation-observer.html:57)
...@@ -23,9 +25,11 @@ Call stack: ...@@ -23,9 +25,11 @@ Call stack:
Call stack: Call stack:
0) nestedMutationCallback (async-callstack-mutation-observer.html:28) 0) nestedMutationCallback (async-callstack-mutation-observer.html:28)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) mutationCallback (async-callstack-mutation-observer.html:20) 1) mutationCallback (async-callstack-mutation-observer.html:20)
2) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) timeout1 (async-callstack-mutation-observer.html:44) 1) timeout1 (async-callstack-mutation-observer.html:44)
...@@ -34,14 +38,17 @@ Call stack: ...@@ -34,14 +38,17 @@ Call stack:
Call stack: Call stack:
0) nestedMutationCallback (async-callstack-mutation-observer.html:28) 0) nestedMutationCallback (async-callstack-mutation-observer.html:28)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations2 (async-callstack-mutation-observer.html:64) 0) doMutations2 (async-callstack-mutation-observer.html:64)
1) timeoutFromNestedMutation (async-callstack-mutation-observer.html:76) 1) timeoutFromNestedMutation (async-callstack-mutation-observer.html:76)
[setTimeout] [setTimeout]
0) nestedMutationCallback (async-callstack-mutation-observer.html:30) 0) nestedMutationCallback (async-callstack-mutation-observer.html:30)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) mutationCallback (async-callstack-mutation-observer.html:20) 1) mutationCallback (async-callstack-mutation-observer.html:20)
2) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) timeout1 (async-callstack-mutation-observer.html:44) 1) timeout1 (async-callstack-mutation-observer.html:44)
...@@ -50,6 +57,7 @@ Call stack: ...@@ -50,6 +57,7 @@ Call stack:
0) timeoutFromMutation (async-callstack-mutation-observer.html:70) 0) timeoutFromMutation (async-callstack-mutation-observer.html:70)
[setTimeout] [setTimeout]
0) mutationCallback (async-callstack-mutation-observer.html:23) 0) mutationCallback (async-callstack-mutation-observer.html:23)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) timeout1 (async-callstack-mutation-observer.html:44) 1) timeout1 (async-callstack-mutation-observer.html:44)
...@@ -60,9 +68,11 @@ Call stack: ...@@ -60,9 +68,11 @@ Call stack:
0) timeoutFromNestedMutation (async-callstack-mutation-observer.html:75) 0) timeoutFromNestedMutation (async-callstack-mutation-observer.html:75)
[setTimeout] [setTimeout]
0) nestedMutationCallback (async-callstack-mutation-observer.html:30) 0) nestedMutationCallback (async-callstack-mutation-observer.html:30)
1) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) mutationCallback (async-callstack-mutation-observer.html:20) 1) mutationCallback (async-callstack-mutation-observer.html:20)
2) RunMicrotasks ((internal script):(line number))
[Mutation] [Mutation]
0) doMutations1 (async-callstack-mutation-observer.html:50) 0) doMutations1 (async-callstack-mutation-observer.html:50)
1) timeout1 (async-callstack-mutation-observer.html:44) 1) timeout1 (async-callstack-mutation-observer.html:44)
......
...@@ -39,7 +39,7 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit ...@@ -39,7 +39,7 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit
{ {
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureRegexContext()); v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureDomInJSContext());
v8::TryCatch tryCatch; v8::TryCatch tryCatch;
unsigned flags = v8::RegExp::kNone; unsigned flags = v8::RegExp::kNone;
...@@ -69,7 +69,7 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c ...@@ -69,7 +69,7 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c
v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::HandleScope handleScope(isolate); v8::HandleScope handleScope(isolate);
v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureRegexContext()); v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureDomInJSContext());
v8::TryCatch tryCatch; v8::TryCatch tryCatch;
v8::Local<v8::RegExp> regex = m_regex.newLocal(isolate); v8::Local<v8::RegExp> regex = m_regex.newLocal(isolate);
......
...@@ -125,11 +125,11 @@ void V8PerIsolateData::setDOMTemplate(void* domTemplateKey, v8::Handle<v8::Funct ...@@ -125,11 +125,11 @@ void V8PerIsolateData::setDOMTemplate(void* domTemplateKey, v8::Handle<v8::Funct
currentDOMTemplateMap().add(domTemplateKey, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); currentDOMTemplateMap().add(domTemplateKey, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ));
} }
v8::Local<v8::Context> V8PerIsolateData::ensureRegexContext() v8::Local<v8::Context> V8PerIsolateData::ensureDomInJSContext()
{ {
if (!m_perContextDataForRegex) if (!m_domInJSPerContextData)
m_perContextDataForRegex = V8PerContextData::create(v8::Context::New(m_isolate), DOMWrapperWorld::create()); m_domInJSPerContextData = V8PerContextData::create(v8::Context::New(m_isolate), DOMWrapperWorld::create());
return m_perContextDataForRegex->context(); return m_domInJSPerContextData->context();
} }
bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value) bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value)
......
...@@ -97,7 +97,7 @@ public: ...@@ -97,7 +97,7 @@ public:
bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>); bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>);
v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>); v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>);
v8::Local<v8::Context> ensureRegexContext(); v8::Local<v8::Context> ensureDomInJSContext();
const char* previousSamplingState() const { return m_previousSamplingState; } const char* previousSamplingState() const { return m_previousSamplingState; }
void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; } void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; }
...@@ -119,7 +119,7 @@ private: ...@@ -119,7 +119,7 @@ private:
OwnPtr<StringCache> m_stringCache; OwnPtr<StringCache> m_stringCache;
OwnPtr<V8HiddenValue> m_hiddenValue; OwnPtr<V8HiddenValue> m_hiddenValue;
ScopedPersistent<v8::Value> m_liveRoot; ScopedPersistent<v8::Value> m_liveRoot;
OwnPtr<V8PerContextData> m_perContextDataForRegex; OwnPtr<V8PerContextData> m_domInJSPerContextData;
const char* m_previousSamplingState; const char* m_previousSamplingState;
......
...@@ -33,39 +33,48 @@ ...@@ -33,39 +33,48 @@
#include "bindings/v8/V8PerIsolateData.h" #include "bindings/v8/V8PerIsolateData.h"
#include "wtf/Vector.h" #include "wtf/Vector.h"
#include <v8.h>
namespace WebCore { namespace WebCore {
typedef Vector<MicrotaskCallback> MicrotaskQueue;
static MicrotaskQueue& microtaskQueue()
{
DEFINE_STATIC_LOCAL(MicrotaskQueue, microtaskQueue, ());
return microtaskQueue;
}
void Microtask::performCheckpoint() void Microtask::performCheckpoint()
{ {
V8PerIsolateData* isolateData = V8PerIsolateData::current(); v8::Isolate* isolate = v8::Isolate::GetCurrent();
V8PerIsolateData* isolateData = V8PerIsolateData::from(isolate);
ASSERT(isolateData); ASSERT(isolateData);
if (isolateData->recursionLevel() || isolateData->performingMicrotaskCheckpoint()) if (isolateData->recursionLevel() || isolateData->performingMicrotaskCheckpoint())
return; return;
isolateData->setPerformingMicrotaskCheckpoint(true); isolateData->setPerformingMicrotaskCheckpoint(true);
while (!microtaskQueue().isEmpty()) { v8::HandleScope handleScope(isolate);
Vector<MicrotaskCallback> microtasks; v8::Local<v8::Context> context = isolateData->ensureDomInJSContext();
microtasks.swap(microtaskQueue()); v8::Context::Scope scope(context);
for (size_t i = 0; i < microtasks.size(); ++i) { v8::V8::RunMicrotasks(isolate);
microtasks[i]();
}
}
isolateData->setPerformingMicrotaskCheckpoint(false); isolateData->setPerformingMicrotaskCheckpoint(false);
} }
COMPILE_ASSERT(sizeof(void*) == sizeof(MicrotaskCallback), VoidPtrAndFunctionPtrAreSameSize);
static void microtaskFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
{
MicrotaskCallback callback =
reinterpret_cast<MicrotaskCallback>(reinterpret_cast<intptr_t>(
info.Data().As<v8::External>()->Value()));
(*callback)();
}
void Microtask::enqueueMicrotask(MicrotaskCallback callback) void Microtask::enqueueMicrotask(MicrotaskCallback callback)
{ {
microtaskQueue().append(callback); v8::Isolate* isolate = v8::Isolate::GetCurrent();
V8PerIsolateData* isolateData = V8PerIsolateData::from(isolate);
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = isolateData->ensureDomInJSContext();
v8::Context::Scope scope(context);
v8::Local<v8::External> handler =
v8::External::New(isolate,
reinterpret_cast<void*>(reinterpret_cast<intptr_t>(callback)));
v8::V8::EnqueueMicrotask(isolate, v8::Function::New(isolate, &microtaskFunctionCallback, handler));
} }
} // namespace WebCore } // namespace WebCore
...@@ -109,6 +109,7 @@ void initialize(Platform* platform) ...@@ -109,6 +109,7 @@ void initialize(Platform* platform)
v8::V8::SetEntropySource(&generateEntropy); v8::V8::SetEntropySource(&generateEntropy);
v8::V8::SetArrayBufferAllocator(WebCore::v8ArrayBufferAllocator()); v8::V8::SetArrayBufferAllocator(WebCore::v8ArrayBufferAllocator());
v8::V8::Initialize(); v8::V8::Initialize();
v8::V8::SetAutorunMicrotasks(isolate, false);
WebCore::V8PerIsolateData::ensureInitialized(isolate); WebCore::V8PerIsolateData::ensureInitialized(isolate);
s_isolateInterruptor = new WebCore::V8IsolateInterruptor(v8::Isolate::GetCurrent()); s_isolateInterruptor = new WebCore::V8IsolateInterruptor(v8::Isolate::GetCurrent());
......
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