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 22 matching lines...) Expand all Loading... | |
33 #include <memory> | 33 #include <memory> |
34 #include "bindings/core/v8/DOMDataStore.h" | 34 #include "bindings/core/v8/DOMDataStore.h" |
35 #include "bindings/core/v8/ScriptController.h" | 35 #include "bindings/core/v8/ScriptController.h" |
36 #include "bindings/core/v8/V8Binding.h" | 36 #include "bindings/core/v8/V8Binding.h" |
37 #include "bindings/core/v8/V8DOMActivityLogger.h" | 37 #include "bindings/core/v8/V8DOMActivityLogger.h" |
38 #include "bindings/core/v8/V8DOMWrapper.h" | 38 #include "bindings/core/v8/V8DOMWrapper.h" |
39 #include "bindings/core/v8/V8Window.h" | 39 #include "bindings/core/v8/V8Window.h" |
40 #include "bindings/core/v8/WindowProxy.h" | 40 #include "bindings/core/v8/WindowProxy.h" |
41 #include "bindings/core/v8/WrapperTypeInfo.h" | 41 #include "bindings/core/v8/WrapperTypeInfo.h" |
42 #include "core/dom/ExecutionContext.h" | 42 #include "core/dom/ExecutionContext.h" |
43 #include "wtf/Atomics.h" | |
43 #include "wtf/HashTraits.h" | 44 #include "wtf/HashTraits.h" |
44 #include "wtf/PtrUtil.h" | 45 #include "wtf/PtrUtil.h" |
45 #include "wtf/StdLibExtras.h" | 46 #include "wtf/StdLibExtras.h" |
46 | 47 |
47 namespace blink { | 48 namespace blink { |
48 | 49 |
49 class DOMObjectHolderBase { | 50 class DOMObjectHolderBase { |
50 USING_FAST_MALLOC(DOMObjectHolderBase); | 51 USING_FAST_MALLOC(DOMObjectHolderBase); |
51 | 52 |
52 public: | 53 public: |
(...skipping 23 matching lines...) Expand all Loading... | |
76 | 77 |
77 private: | 78 private: |
78 DOMObjectHolder(v8::Isolate* isolate, T* object, v8::Local<v8::Value> wrapper) | 79 DOMObjectHolder(v8::Isolate* isolate, T* object, v8::Local<v8::Value> wrapper) |
79 : DOMObjectHolderBase(isolate, wrapper), m_object(object) {} | 80 : DOMObjectHolderBase(isolate, wrapper), m_object(object) {} |
80 | 81 |
81 Persistent<T> m_object; | 82 Persistent<T> m_object; |
82 }; | 83 }; |
83 | 84 |
84 unsigned DOMWrapperWorld::s_numberOfNonMainWorldsInMainThread = 0; | 85 unsigned DOMWrapperWorld::s_numberOfNonMainWorldsInMainThread = 0; |
85 | 86 |
87 using WorldMap = HashMap<int, DOMWrapperWorld*>; | |
88 | |
89 static WorldMap& isolatedWorldMap() { | |
90 DCHECK(isMainThread()); | |
91 DEFINE_STATIC_LOCAL(WorldMap, map, ()); | |
92 return map; | |
93 } | |
94 | |
95 static WorldMap& worldMap() { | |
96 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<WorldMap>, map, | |
97 new ThreadSpecific<WorldMap>); | |
98 return *map; | |
99 } | |
100 | |
86 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(v8::Isolate* isolate, | 101 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(v8::Isolate* isolate, |
87 WorldType worldType) { | 102 WorldType worldType) { |
88 DCHECK_NE(WorldType::Isolated, worldType); | 103 DCHECK_NE(WorldType::Isolated, worldType); |
89 return adoptRef( | 104 return adoptRef(new DOMWrapperWorld(isolate, worldType, |
90 new DOMWrapperWorld(isolate, worldType, getWorldIdForType(worldType))); | 105 generateWorldIdForType(worldType))); |
91 } | 106 } |
92 | 107 |
93 DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, | 108 DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, |
94 WorldType worldType, | 109 WorldType worldType, |
95 int worldId) | 110 int worldId) |
96 : m_worldType(worldType), | 111 : m_worldType(worldType), |
97 m_worldId(worldId), | 112 m_worldId(worldId), |
98 m_domDataStore( | 113 m_domDataStore( |
99 WTF::wrapUnique(new DOMDataStore(isolate, isMainWorld()))) { | 114 WTF::wrapUnique(new DOMDataStore(isolate, isMainWorld()))) { |
100 if (isWorkerWorld()) | 115 switch (worldType) { |
101 workerWorld() = this; | 116 case WorldType::Main: |
117 // MainWorld is managed separately from worldMap() and isolatedWorldMap(). | |
118 // See mainWorld(). | |
119 break; | |
120 case WorldType::Isolated: { | |
121 DCHECK(isMainThread()); | |
122 WorldMap& map = isolatedWorldMap(); | |
123 DCHECK(!map.contains(worldId)); | |
124 map.insert(worldId, this); | |
125 break; | |
126 } | |
127 case WorldType::GarbageCollector: | |
128 case WorldType::RegExp: | |
129 case WorldType::Testing: | |
130 case WorldType::Worker: { | |
131 WorldMap& map = worldMap(); | |
132 DCHECK(!map.contains(worldId)); | |
133 map.insert(worldId, this); | |
134 break; | |
135 } | |
136 } | |
102 if (worldId != WorldId::MainWorldId && isMainThread()) | 137 if (worldId != WorldId::MainWorldId && isMainThread()) |
103 s_numberOfNonMainWorldsInMainThread++; | 138 s_numberOfNonMainWorldsInMainThread++; |
104 } | 139 } |
105 | 140 |
106 DOMWrapperWorld& DOMWrapperWorld::mainWorld() { | 141 DOMWrapperWorld& DOMWrapperWorld::mainWorld() { |
107 ASSERT(isMainThread()); | 142 ASSERT(isMainThread()); |
108 DEFINE_STATIC_REF( | 143 DEFINE_STATIC_REF( |
109 DOMWrapperWorld, cachedMainWorld, | 144 DOMWrapperWorld, cachedMainWorld, |
110 (DOMWrapperWorld::create(v8::Isolate::GetCurrent(), WorldType::Main))); | 145 (DOMWrapperWorld::create(v8::Isolate::GetCurrent(), WorldType::Main))); |
111 return *cachedMainWorld; | 146 return *cachedMainWorld; |
112 } | 147 } |
113 | 148 |
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, | 149 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::fromWorldId(v8::Isolate* isolate, |
121 int worldId) { | 150 int worldId) { |
122 if (worldId == MainWorldId) | 151 if (worldId == MainWorldId) |
123 return &mainWorld(); | 152 return &mainWorld(); |
124 return ensureIsolatedWorld(isolate, worldId); | 153 return ensureIsolatedWorld(isolate, worldId); |
125 } | 154 } |
126 | 155 |
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( | 156 void DOMWrapperWorld::allWorldsInMainThread( |
135 Vector<RefPtr<DOMWrapperWorld>>& worlds) { | 157 Vector<RefPtr<DOMWrapperWorld>>& worlds) { |
136 ASSERT(isMainThread()); | 158 ASSERT(isMainThread()); |
137 worlds.push_back(&mainWorld()); | 159 worlds.push_back(&mainWorld()); |
138 WorldMap& isolatedWorlds = isolatedWorldMap(); | 160 for (DOMWrapperWorld* world : worldMap().values()) |
139 for (WorldMap::iterator it = isolatedWorlds.begin(); | 161 worlds.push_back(world); |
140 it != isolatedWorlds.end(); ++it) | 162 for (DOMWrapperWorld* world : isolatedWorldMap().values()) |
141 worlds.push_back(it->value); | 163 worlds.push_back(world); |
142 } | 164 } |
143 | 165 |
144 void DOMWrapperWorld::markWrappersInAllWorlds( | 166 void DOMWrapperWorld::markWrappersInAllWorlds( |
145 ScriptWrappable* scriptWrappable, | 167 ScriptWrappable* scriptWrappable, |
146 const ScriptWrappableVisitor* visitor) { | 168 const ScriptWrappableVisitor* visitor) { |
147 // Handle marking in per-worker wrapper worlds. | 169 // Marking for worlds other than the main world and the isolated worlds. |
148 if (!isMainThread()) { | 170 DCHECK(ThreadState::current()->isolate()); |
149 DCHECK(ThreadState::current()->isolate()); | 171 for (DOMWrapperWorld* world : worldMap().values()) { |
150 DOMWrapperWorld* worker = workerWorld(); | 172 DOMDataStore& dataStore = world->domDataStore(); |
151 if (worker) { | 173 if (dataStore.containsWrapper(scriptWrappable)) |
152 DOMDataStore& dataStore = worker->domDataStore(); | 174 dataStore.markWrapper(scriptWrappable); |
153 if (dataStore.containsWrapper(scriptWrappable)) { | |
154 dataStore.markWrapper(scriptWrappable); | |
155 } | |
156 } | |
157 return; | |
158 } | 175 } |
159 | 176 |
177 // The main world and isolated worlds should exist only on the main thread. | |
178 if (!isMainThread()) | |
179 return; | |
180 | |
181 // Marking for the main world. | |
160 scriptWrappable->markWrapper(visitor); | 182 scriptWrappable->markWrapper(visitor); |
183 | |
184 // Marking for the isolated worlds. | |
161 WorldMap& isolatedWorlds = isolatedWorldMap(); | 185 WorldMap& isolatedWorlds = isolatedWorldMap(); |
162 for (auto& world : isolatedWorlds.values()) { | 186 for (auto& world : isolatedWorlds.values()) { |
163 DOMDataStore& dataStore = world->domDataStore(); | 187 DOMDataStore& dataStore = world->domDataStore(); |
164 if (dataStore.containsWrapper(scriptWrappable)) { | 188 if (dataStore.containsWrapper(scriptWrappable)) |
165 // Marking for the isolated worlds | |
166 dataStore.markWrapper(scriptWrappable); | 189 dataStore.markWrapper(scriptWrappable); |
167 } | |
168 } | 190 } |
169 } | 191 } |
170 | 192 |
171 DOMWrapperWorld::~DOMWrapperWorld() { | 193 DOMWrapperWorld::~DOMWrapperWorld() { |
172 ASSERT(!isMainWorld()); | 194 ASSERT(!isMainWorld()); |
173 | 195 |
174 dispose(); | 196 dispose(); |
175 | 197 |
176 if (isMainThread()) | 198 if (isMainThread()) |
177 s_numberOfNonMainWorldsInMainThread--; | 199 s_numberOfNonMainWorldsInMainThread--; |
178 | 200 |
179 if (!isIsolatedWorld()) | 201 if (!isIsolatedWorld()) |
180 return; | 202 return; |
181 | 203 |
182 WorldMap& map = isolatedWorldMap(); | 204 WorldMap& map = isolatedWorldMap(); |
183 WorldMap::iterator it = map.find(m_worldId); | 205 WorldMap::iterator it = map.find(m_worldId); |
184 if (it == map.end()) { | 206 if (it == map.end()) { |
185 ASSERT_NOT_REACHED(); | 207 ASSERT_NOT_REACHED(); |
186 return; | 208 return; |
187 } | 209 } |
188 ASSERT(it->value == this); | 210 ASSERT(it->value == this); |
189 | 211 |
190 map.remove(it); | 212 map.remove(it); |
191 } | 213 } |
192 | 214 |
193 void DOMWrapperWorld::dispose() { | 215 void DOMWrapperWorld::dispose() { |
194 m_domObjectHolders.clear(); | 216 m_domObjectHolders.clear(); |
195 m_domDataStore.reset(); | 217 m_domDataStore.reset(); |
196 if (isWorkerWorld()) | 218 worldMap().remove(m_worldId); |
197 workerWorld() = nullptr; | |
198 } | 219 } |
199 | 220 |
200 #if DCHECK_IS_ON() | 221 #if DCHECK_IS_ON() |
201 static bool isIsolatedWorldId(int worldId) { | 222 static bool isIsolatedWorldId(int worldId) { |
202 return DOMWrapperWorld::MainWorldId < worldId && | 223 return DOMWrapperWorld::MainWorldId < worldId && |
203 worldId < DOMWrapperWorld::IsolatedWorldIdLimit; | 224 worldId < DOMWrapperWorld::IsolatedWorldIdLimit; |
204 } | 225 } |
205 #endif | 226 #endif |
206 | 227 |
207 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld( | 228 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld( |
208 v8::Isolate* isolate, | 229 v8::Isolate* isolate, |
209 int worldId) { | 230 int worldId) { |
210 ASSERT(isIsolatedWorldId(worldId)); | 231 ASSERT(isIsolatedWorldId(worldId)); |
211 | 232 |
212 WorldMap& map = isolatedWorldMap(); | 233 WorldMap& map = isolatedWorldMap(); |
213 WorldMap::AddResult result = map.insert(worldId, nullptr); | 234 auto it = map.find(worldId); |
214 RefPtr<DOMWrapperWorld> world = result.storedValue->value; | 235 if (it != map.end()) { |
215 if (world) { | 236 RefPtr<DOMWrapperWorld> world = it->value; |
216 ASSERT(world->worldId() == worldId); | 237 DCHECK_EQ(worldId, world->worldId()); |
217 return world.release(); | 238 return world.release(); |
218 } | 239 } |
219 | 240 |
220 world = adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId)); | 241 return adoptRef(new DOMWrapperWorld(isolate, WorldType::Isolated, worldId)); |
221 result.storedValue->value = world.get(); | |
222 return world.release(); | |
223 } | 242 } |
224 | 243 |
225 typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap; | 244 typedef HashMap<int, RefPtr<SecurityOrigin>> IsolatedWorldSecurityOriginMap; |
226 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() { | 245 static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() { |
227 ASSERT(isMainThread()); | 246 ASSERT(isMainThread()); |
228 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); | 247 DEFINE_STATIC_LOCAL(IsolatedWorldSecurityOriginMap, map, ()); |
229 return map; | 248 return map; |
230 } | 249 } |
231 | 250 |
232 SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() { | 251 SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
316 ASSERT(m_domObjectHolders.contains(holderBase)); | 335 ASSERT(m_domObjectHolders.contains(holderBase)); |
317 m_domObjectHolders.erase(holderBase); | 336 m_domObjectHolders.erase(holderBase); |
318 } | 337 } |
319 | 338 |
320 void DOMWrapperWorld::weakCallbackForDOMObjectHolder( | 339 void DOMWrapperWorld::weakCallbackForDOMObjectHolder( |
321 const v8::WeakCallbackInfo<DOMObjectHolderBase>& data) { | 340 const v8::WeakCallbackInfo<DOMObjectHolderBase>& data) { |
322 DOMObjectHolderBase* holderBase = data.GetParameter(); | 341 DOMObjectHolderBase* holderBase = data.GetParameter(); |
323 holderBase->world()->unregisterDOMObjectHolder(holderBase); | 342 holderBase->world()->unregisterDOMObjectHolder(holderBase); |
324 } | 343 } |
325 | 344 |
326 int DOMWrapperWorld::getWorldIdForType(WorldType worldType) { | 345 int DOMWrapperWorld::generateWorldIdForType(WorldType worldType) { |
346 DEFINE_THREAD_SAFE_STATIC_LOCAL( | |
347 int, s_lastGeneratedWorldId, | |
348 new int(DOMWrapperWorld::WorldId::IsolatedWorldIdLimit)); | |
haraken
2017/03/14 09:18:20
I think you could just use ThreadSpecific. The wor
nhiroki
2017/03/14 09:39:05
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 = WTF::atomicIncrement(&s_lastGeneratedWorldId); |
362 CHECK_GT(worldId, 0); | |
363 return worldId; | |
347 } | 364 } |
348 NOTREACHED(); | 365 NOTREACHED(); |
349 return InvalidWorldId; | 366 return InvalidWorldId; |
350 } | 367 } |
351 | 368 |
352 } // namespace blink | 369 } // namespace blink |
OLD | NEW |