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

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

Issue 2735823006: Bindings: Manage multiple DOMWrapperWorlds for worklets (Closed)
Patch Set: s/lastUsedWorldId/lastGeneratedWorldId 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
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 22 matching lines...) Expand all
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698