Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.cpp

Issue 2735823006: Bindings: Manage multiple DOMWrapperWorlds for worklets (Closed)
Patch Set: ThreadSpecific Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 76
77 private: 77 private:
78 DOMObjectHolder(v8::Isolate* isolate, T* object, v8::Local<v8::Value> wrapper) 78 DOMObjectHolder(v8::Isolate* isolate, T* object, v8::Local<v8::Value> wrapper)
79 : DOMObjectHolderBase(isolate, wrapper), m_object(object) {} 79 : DOMObjectHolderBase(isolate, wrapper), m_object(object) {}
80 80
81 Persistent<T> m_object; 81 Persistent<T> m_object;
82 }; 82 };
83 83
84 unsigned DOMWrapperWorld::s_numberOfNonMainWorldsInMainThread = 0; 84 unsigned DOMWrapperWorld::s_numberOfNonMainWorldsInMainThread = 0;
85 85
86 using WorldMap = HashMap<int, DOMWrapperWorld*>;
87
88 static WorldMap& isolatedWorldMap() {
89 DCHECK(isMainThread());
90 DEFINE_STATIC_LOCAL(WorldMap, map, ());
91 return map;
92 }
93
94 static WorldMap& worldMap() {
95 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<WorldMap>, map,
96 new ThreadSpecific<WorldMap>);
97 return *map;
98 }
99
86 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(v8::Isolate* isolate, 100 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(v8::Isolate* isolate,
87 WorldType worldType) { 101 WorldType worldType) {
88 DCHECK_NE(WorldType::Isolated, worldType); 102 DCHECK_NE(WorldType::Isolated, worldType);
89 return adoptRef( 103 return adoptRef(new DOMWrapperWorld(isolate, worldType,
90 new DOMWrapperWorld(isolate, worldType, getWorldIdForType(worldType))); 104 generateWorldIdForType(worldType)));
91 } 105 }
92 106
93 DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, 107 DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate,
94 WorldType worldType, 108 WorldType worldType,
95 int worldId) 109 int worldId)
96 : m_worldType(worldType), 110 : m_worldType(worldType),
97 m_worldId(worldId), 111 m_worldId(worldId),
98 m_domDataStore( 112 m_domDataStore(
99 WTF::wrapUnique(new DOMDataStore(isolate, isMainWorld()))) { 113 WTF::wrapUnique(new DOMDataStore(isolate, isMainWorld()))) {
100 if (isWorkerWorld()) 114 switch (worldType) {
101 workerWorld() = this; 115 case WorldType::Main:
116 // MainWorld is managed separately from worldMap() and isolatedWorldMap().
117 // See mainWorld().
118 break;
119 case WorldType::Isolated: {
120 DCHECK(isMainThread());
121 WorldMap& map = isolatedWorldMap();
122 DCHECK(!map.contains(worldId));
123 map.insert(worldId, this);
124 break;
125 }
126 case WorldType::GarbageCollector:
127 case WorldType::RegExp:
128 case WorldType::Testing:
129 case WorldType::Worker: {
130 WorldMap& map = worldMap();
131 DCHECK(!map.contains(worldId));
132 map.insert(worldId, this);
133 break;
134 }
135 }
102 if (worldId != WorldId::MainWorldId && isMainThread()) 136 if (worldId != WorldId::MainWorldId && isMainThread())
103 s_numberOfNonMainWorldsInMainThread++; 137 s_numberOfNonMainWorldsInMainThread++;
104 } 138 }
105 139
106 DOMWrapperWorld& DOMWrapperWorld::mainWorld() { 140 DOMWrapperWorld& DOMWrapperWorld::mainWorld() {
107 ASSERT(isMainThread()); 141 ASSERT(isMainThread());
108 DEFINE_STATIC_REF( 142 DEFINE_STATIC_REF(
109 DOMWrapperWorld, cachedMainWorld, 143 DOMWrapperWorld, cachedMainWorld,
110 (DOMWrapperWorld::create(v8::Isolate::GetCurrent(), WorldType::Main))); 144 (DOMWrapperWorld::create(v8::Isolate::GetCurrent(), WorldType::Main)));
111 return *cachedMainWorld; 145 return *cachedMainWorld;
112 } 146 }
113 147
114 DOMWrapperWorld*& DOMWrapperWorld::workerWorld() {
115 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<DOMWrapperWorld*>, workerWorld,
116 new ThreadSpecific<DOMWrapperWorld*>);
117 return *workerWorld;
118 }
119
120 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::fromWorldId(v8::Isolate* isolate, 148 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::fromWorldId(v8::Isolate* isolate,
121 int worldId) { 149 int worldId) {
122 if (worldId == MainWorldId) 150 if (worldId == MainWorldId)
123 return &mainWorld(); 151 return &mainWorld();
124 return ensureIsolatedWorld(isolate, worldId); 152 return ensureIsolatedWorld(isolate, worldId);
125 } 153 }
126 154
127 typedef HashMap<int, DOMWrapperWorld*> WorldMap;
128 static WorldMap& isolatedWorldMap() {
129 ASSERT(isMainThread());
130 DEFINE_STATIC_LOCAL(WorldMap, map, ());
131 return map;
132 }
133
134 void DOMWrapperWorld::allWorldsInMainThread( 155 void DOMWrapperWorld::allWorldsInMainThread(
135 Vector<RefPtr<DOMWrapperWorld>>& worlds) { 156 Vector<RefPtr<DOMWrapperWorld>>& worlds) {
136 ASSERT(isMainThread()); 157 ASSERT(isMainThread());
137 worlds.push_back(&mainWorld()); 158 worlds.push_back(&mainWorld());
138 WorldMap& isolatedWorlds = isolatedWorldMap(); 159 for (DOMWrapperWorld* world : worldMap().values())
139 for (WorldMap::iterator it = isolatedWorlds.begin(); 160 worlds.push_back(world);
140 it != isolatedWorlds.end(); ++it) 161 for (DOMWrapperWorld* world : isolatedWorldMap().values())
141 worlds.push_back(it->value); 162 worlds.push_back(world);
142 } 163 }
143 164
144 void DOMWrapperWorld::markWrappersInAllWorlds( 165 void DOMWrapperWorld::markWrappersInAllWorlds(
145 ScriptWrappable* scriptWrappable, 166 ScriptWrappable* scriptWrappable,
146 const ScriptWrappableVisitor* visitor) { 167 const ScriptWrappableVisitor* visitor) {
147 // Handle marking in per-worker wrapper worlds. 168 // Marking for worlds other than the main world and the isolated worlds.
148 if (!isMainThread()) { 169 DCHECK(ThreadState::current()->isolate());
149 DCHECK(ThreadState::current()->isolate()); 170 for (DOMWrapperWorld* world : worldMap().values()) {
150 DOMWrapperWorld* worker = workerWorld(); 171 DOMDataStore& dataStore = world->domDataStore();
151 if (worker) { 172 if (dataStore.containsWrapper(scriptWrappable))
152 DOMDataStore& dataStore = worker->domDataStore(); 173 dataStore.markWrapper(scriptWrappable);
153 if (dataStore.containsWrapper(scriptWrappable)) {
154 dataStore.markWrapper(scriptWrappable);
155 }
156 }
157 return;
158 } 174 }
159 175
176 // The main world and isolated worlds should exist only on the main thread.
177 if (!isMainThread())
178 return;
179
180 // Marking for the main world.
160 scriptWrappable->markWrapper(visitor); 181 scriptWrappable->markWrapper(visitor);
182
183 // Marking for the isolated worlds.
161 WorldMap& isolatedWorlds = isolatedWorldMap(); 184 WorldMap& isolatedWorlds = isolatedWorldMap();
162 for (auto& world : isolatedWorlds.values()) { 185 for (auto& world : isolatedWorlds.values()) {
163 DOMDataStore& dataStore = world->domDataStore(); 186 DOMDataStore& dataStore = world->domDataStore();
164 if (dataStore.containsWrapper(scriptWrappable)) { 187 if (dataStore.containsWrapper(scriptWrappable))
165 // Marking for the isolated worlds
166 dataStore.markWrapper(scriptWrappable); 188 dataStore.markWrapper(scriptWrappable);
167 }
168 } 189 }
169 } 190 }
170 191
171 DOMWrapperWorld::~DOMWrapperWorld() { 192 DOMWrapperWorld::~DOMWrapperWorld() {
172 ASSERT(!isMainWorld()); 193 ASSERT(!isMainWorld());
173 194
174 dispose(); 195 dispose();
175 196
176 if (isMainThread()) 197 if (isMainThread())
177 s_numberOfNonMainWorldsInMainThread--; 198 s_numberOfNonMainWorldsInMainThread--;
178 199
179 if (!isIsolatedWorld()) 200 if (!isIsolatedWorld())
180 return; 201 return;
181 202
182 WorldMap& map = isolatedWorldMap(); 203 WorldMap& map = isolatedWorldMap();
183 WorldMap::iterator it = map.find(m_worldId); 204 WorldMap::iterator it = map.find(m_worldId);
184 if (it == map.end()) { 205 if (it == map.end()) {
185 ASSERT_NOT_REACHED(); 206 ASSERT_NOT_REACHED();
186 return; 207 return;
187 } 208 }
188 ASSERT(it->value == this); 209 ASSERT(it->value == this);
189 210
190 map.remove(it); 211 map.remove(it);
191 } 212 }
192 213
193 void DOMWrapperWorld::dispose() { 214 void DOMWrapperWorld::dispose() {
194 m_domObjectHolders.clear(); 215 m_domObjectHolders.clear();
195 m_domDataStore.reset(); 216 m_domDataStore.reset();
196 if (isWorkerWorld()) 217 worldMap().remove(m_worldId);
197 workerWorld() = nullptr;
198 } 218 }
199 219
200 #if DCHECK_IS_ON() 220 #if DCHECK_IS_ON()
201 static bool isIsolatedWorldId(int worldId) { 221 static bool isIsolatedWorldId(int worldId) {
202 return DOMWrapperWorld::MainWorldId < worldId && 222 return DOMWrapperWorld::MainWorldId < worldId &&
203 worldId < DOMWrapperWorld::IsolatedWorldIdLimit; 223 worldId < DOMWrapperWorld::IsolatedWorldIdLimit;
204 } 224 }
205 #endif 225 #endif
206 226
207 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld( 227 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(
208 v8::Isolate* isolate, 228 v8::Isolate* isolate,
209 int worldId) { 229 int worldId) {
210 ASSERT(isIsolatedWorldId(worldId)); 230 ASSERT(isIsolatedWorldId(worldId));
211 231
212 WorldMap& map = isolatedWorldMap(); 232 WorldMap& map = isolatedWorldMap();
213 WorldMap::AddResult result = map.insert(worldId, nullptr); 233 auto it = map.find(worldId);
214 RefPtr<DOMWrapperWorld> world = result.storedValue->value; 234 if (it != map.end()) {
215 if (world) { 235 RefPtr<DOMWrapperWorld> world = it->value;
216 ASSERT(world->worldId() == worldId); 236 DCHECK_EQ(worldId, world->worldId());
217 return world.release(); 237 return world.release();
218 } 238 }
219 239
220 world = adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId)); 240 return adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId));
221 result.storedValue->value = world.get();
222 return world.release();
223 } 241 }
224 242
225 typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap; 243 typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap;
226 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() { 244 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() {
227 ASSERT(isMainThread()); 245 ASSERT(isMainThread());
228 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); 246 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ());
229 return map; 247 return map;
230 } 248 }
231 249
232 SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() { 250 SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 ASSERT(m_domObjectHolders.contains(holderBase)); 334 ASSERT(m_domObjectHolders.contains(holderBase));
317 m_domObjectHolders.erase(holderBase); 335 m_domObjectHolders.erase(holderBase);
318 } 336 }
319 337
320 void DOMWrapperWorld::weakCallbackForDOMObjectHolder( 338 void DOMWrapperWorld::weakCallbackForDOMObjectHolder(
321 const v8::WeakCallbackInfo<DOMObjectHolderBase>& data) { 339 const v8::WeakCallbackInfo<DOMObjectHolderBase>& data) {
322 DOMObjectHolderBase* holderBase = data.GetParameter(); 340 DOMObjectHolderBase* holderBase = data.GetParameter();
323 holderBase->world()->unregisterDOMObjectHolder(holderBase); 341 holderBase->world()->unregisterDOMObjectHolder(holderBase);
324 } 342 }
325 343
326 int DOMWrapperWorld::getWorldIdForType(WorldType worldType) { 344 int DOMWrapperWorld::generateWorldIdForType(WorldType worldType) {
345 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<int>, s_nextWorldId,
346 new ThreadSpecific<int>);
347 if (!s_nextWorldId.isSet())
348 *s_nextWorldId = DOMWrapperWorld::WorldId::UnspecifiedWorldIdStart;
peria 2017/03/14 09:52:46 s/DOMWrapperWorld:://
nhiroki 2017/03/14 10:58:28 Done.
327 switch (worldType) { 349 switch (worldType) {
328 case WorldType::Main: 350 case WorldType::Main:
329 return MainWorldId; 351 return MainWorldId;
330 case WorldType::Isolated: 352 case WorldType::Isolated:
331 // This function should not be called for IsolatedWorld because an 353 // This function should not be called for IsolatedWorld because an
332 // identifier for the world is given from out of DOMWrapperWorld. 354 // identifier for the world is given from out of DOMWrapperWorld.
333 NOTREACHED(); 355 NOTREACHED();
334 return InvalidWorldId; 356 return InvalidWorldId;
335 case WorldType::GarbageCollector: 357 case WorldType::GarbageCollector:
336 return GarbageCollectorWorldId;
337 case WorldType::RegExp: 358 case WorldType::RegExp:
338 return RegExpWorldId;
339 case WorldType::Testing: 359 case WorldType::Testing:
340 return TestingWorldId;
341 // Currently, WorldId for a worker/worklet is a fixed value, but this
342 // doesn't work when multiple worklets are created on a thread.
343 // TODO(nhiroki): Expand the identifier space for workers/worklets.
344 // (https://crbug.com/697622)
345 case WorldType::Worker: 360 case WorldType::Worker:
346 return WorkerWorldId; 361 int worldId = *s_nextWorldId;
362 CHECK_GT(worldId, 0);
peria 2017/03/14 09:52:46 CHECK_GE(worldId, WorldId::UnspecifiedWorldIdStart
nhiroki 2017/03/14 10:58:28 Done.
363 *s_nextWorldId = worldId + 1;
364 return worldId;
347 } 365 }
348 NOTREACHED(); 366 NOTREACHED();
349 return InvalidWorldId; 367 return InvalidWorldId;
350 } 368 }
351 369
352 } // namespace blink 370 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/bindings/core/v8/DOMWrapperWorld.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698