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 = 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 |
OLD | NEW |