Index: third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp |
diff --git a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp |
index 4593c3ef2285369cbe2c479171ad9ca9c709cf0f..24b1935d37cb34f49b926bbeab36d1f85585a79e 100644 |
--- a/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp |
+++ b/third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp |
@@ -83,11 +83,25 @@ class DOMObjectHolder : public DOMObjectHolderBase { |
unsigned DOMWrapperWorld::s_numberOfNonMainWorldsInMainThread = 0; |
+using WorldMap = HashMap<int, DOMWrapperWorld*>; |
+ |
+static WorldMap& isolatedWorldMap() { |
+ DCHECK(isMainThread()); |
+ DEFINE_STATIC_LOCAL(WorldMap, map, ()); |
+ return map; |
+} |
+ |
+static WorldMap& worldMap() { |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<WorldMap>, map, |
+ new ThreadSpecific<WorldMap>); |
+ return *map; |
+} |
+ |
PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(v8::Isolate* isolate, |
WorldType worldType) { |
DCHECK_NE(WorldType::Isolated, worldType); |
- return adoptRef( |
- new DOMWrapperWorld(isolate, worldType, getWorldIdForType(worldType))); |
+ return adoptRef(new DOMWrapperWorld(isolate, worldType, |
+ generateWorldIdForType(worldType))); |
} |
DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, |
@@ -97,8 +111,28 @@ DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, |
m_worldId(worldId), |
m_domDataStore( |
WTF::wrapUnique(new DOMDataStore(isolate, isMainWorld()))) { |
- if (isWorkerWorld()) |
- workerWorld() = this; |
+ switch (worldType) { |
+ case WorldType::Main: |
+ // MainWorld is managed separately from worldMap() and isolatedWorldMap(). |
+ // See mainWorld(). |
+ break; |
+ case WorldType::Isolated: { |
+ DCHECK(isMainThread()); |
+ WorldMap& map = isolatedWorldMap(); |
+ DCHECK(!map.contains(worldId)); |
+ map.insert(worldId, this); |
+ break; |
+ } |
+ case WorldType::GarbageCollector: |
+ case WorldType::RegExp: |
+ case WorldType::Testing: |
+ case WorldType::Worker: { |
+ WorldMap& map = worldMap(); |
+ DCHECK(!map.contains(worldId)); |
+ map.insert(worldId, this); |
+ break; |
+ } |
+ } |
if (worldId != WorldId::MainWorldId && isMainThread()) |
s_numberOfNonMainWorldsInMainThread++; |
} |
@@ -111,12 +145,6 @@ DOMWrapperWorld& DOMWrapperWorld::mainWorld() { |
return *cachedMainWorld; |
} |
-DOMWrapperWorld*& DOMWrapperWorld::workerWorld() { |
- DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<DOMWrapperWorld*>, workerWorld, |
- new ThreadSpecific<DOMWrapperWorld*>); |
- return *workerWorld; |
-} |
- |
PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::fromWorldId(v8::Isolate* isolate, |
int worldId) { |
if (worldId == MainWorldId) |
@@ -124,47 +152,40 @@ PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::fromWorldId(v8::Isolate* isolate, |
return ensureIsolatedWorld(isolate, worldId); |
} |
-typedef HashMap<int, DOMWrapperWorld*> WorldMap; |
-static WorldMap& isolatedWorldMap() { |
- ASSERT(isMainThread()); |
- DEFINE_STATIC_LOCAL(WorldMap, map, ()); |
- return map; |
-} |
- |
void DOMWrapperWorld::allWorldsInMainThread( |
Vector<RefPtr<DOMWrapperWorld>>& worlds) { |
ASSERT(isMainThread()); |
worlds.push_back(&mainWorld()); |
- WorldMap& isolatedWorlds = isolatedWorldMap(); |
- for (WorldMap::iterator it = isolatedWorlds.begin(); |
- it != isolatedWorlds.end(); ++it) |
- worlds.push_back(it->value); |
+ for (DOMWrapperWorld* world : worldMap().values()) |
+ worlds.push_back(world); |
+ for (DOMWrapperWorld* world : isolatedWorldMap().values()) |
+ worlds.push_back(world); |
} |
void DOMWrapperWorld::markWrappersInAllWorlds( |
ScriptWrappable* scriptWrappable, |
const ScriptWrappableVisitor* visitor) { |
- // Handle marking in per-worker wrapper worlds. |
- if (!isMainThread()) { |
- DCHECK(ThreadState::current()->isolate()); |
- DOMWrapperWorld* worker = workerWorld(); |
- if (worker) { |
- DOMDataStore& dataStore = worker->domDataStore(); |
- if (dataStore.containsWrapper(scriptWrappable)) { |
- dataStore.markWrapper(scriptWrappable); |
- } |
- } |
- return; |
+ // Marking for worlds other than the main world and the isolated worlds. |
+ DCHECK(ThreadState::current()->isolate()); |
+ for (DOMWrapperWorld* world : worldMap().values()) { |
+ DOMDataStore& dataStore = world->domDataStore(); |
+ if (dataStore.containsWrapper(scriptWrappable)) |
+ dataStore.markWrapper(scriptWrappable); |
} |
+ // The main world and isolated worlds should exist only on the main thread. |
+ if (!isMainThread()) |
+ return; |
+ |
+ // Marking for the main world. |
scriptWrappable->markWrapper(visitor); |
+ |
+ // Marking for the isolated worlds. |
WorldMap& isolatedWorlds = isolatedWorldMap(); |
for (auto& world : isolatedWorlds.values()) { |
DOMDataStore& dataStore = world->domDataStore(); |
- if (dataStore.containsWrapper(scriptWrappable)) { |
- // Marking for the isolated worlds |
+ if (dataStore.containsWrapper(scriptWrappable)) |
dataStore.markWrapper(scriptWrappable); |
- } |
} |
} |
@@ -193,8 +214,7 @@ DOMWrapperWorld::~DOMWrapperWorld() { |
void DOMWrapperWorld::dispose() { |
m_domObjectHolders.clear(); |
m_domDataStore.reset(); |
- if (isWorkerWorld()) |
- workerWorld() = nullptr; |
+ worldMap().remove(m_worldId); |
} |
#if DCHECK_IS_ON() |
@@ -210,16 +230,14 @@ PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld( |
ASSERT(isIsolatedWorldId(worldId)); |
WorldMap& map = isolatedWorldMap(); |
- WorldMap::AddResult result = map.insert(worldId, nullptr); |
- RefPtr<DOMWrapperWorld> world = result.storedValue->value; |
- if (world) { |
- ASSERT(world->worldId() == worldId); |
+ auto it = map.find(worldId); |
+ if (it != map.end()) { |
+ RefPtr<DOMWrapperWorld> world = it->value; |
+ DCHECK_EQ(worldId, world->worldId()); |
return world.release(); |
} |
- world = adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId)); |
- result.storedValue->value = world.get(); |
- return world.release(); |
+ return adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId)); |
} |
typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap; |
@@ -323,7 +341,11 @@ void DOMWrapperWorld::weakCallbackForDOMObjectHolder( |
holderBase->world()->unregisterDOMObjectHolder(holderBase); |
} |
-int DOMWrapperWorld::getWorldIdForType(WorldType worldType) { |
+int DOMWrapperWorld::generateWorldIdForType(WorldType worldType) { |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<int>, s_nextWorldId, |
+ new ThreadSpecific<int>); |
+ if (!s_nextWorldId.isSet()) |
+ *s_nextWorldId = WorldId::UnspecifiedWorldIdStart; |
switch (worldType) { |
case WorldType::Main: |
return MainWorldId; |
@@ -333,17 +355,13 @@ int DOMWrapperWorld::getWorldIdForType(WorldType worldType) { |
NOTREACHED(); |
return InvalidWorldId; |
case WorldType::GarbageCollector: |
- return GarbageCollectorWorldId; |
case WorldType::RegExp: |
- return RegExpWorldId; |
case WorldType::Testing: |
- return TestingWorldId; |
- // Currently, WorldId for a worker/worklet is a fixed value, but this |
- // doesn't work when multiple worklets are created on a thread. |
- // TODO(nhiroki): Expand the identifier space for workers/worklets. |
- // (https://crbug.com/697622) |
case WorldType::Worker: |
- return WorkerWorldId; |
+ int worldId = *s_nextWorldId; |
+ CHECK_GE(worldId, WorldId::UnspecifiedWorldIdStart); |
+ *s_nextWorldId = worldId + 1; |
+ return worldId; |
} |
NOTREACHED(); |
return InvalidWorldId; |