OLD | NEW |
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 Loading... |
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 Loading... |
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 = WorldId::UnspecifiedWorldIdStart; |
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_GE(worldId, WorldId::UnspecifiedWorldIdStart); |
| 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 |
OLD | NEW |