OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/port.h" | 5 #include "vm/port.h" |
6 | 6 |
7 #include "vm/dart_entry.h" | |
8 #include "platform/utils.h" | 7 #include "platform/utils.h" |
9 #include "vm/dart_api_impl.h" | 8 #include "vm/dart_api_impl.h" |
| 9 #include "vm/dart_entry.h" |
10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
11 #include "vm/lockers.h" | 11 #include "vm/lockers.h" |
12 #include "vm/message_handler.h" | 12 #include "vm/message_handler.h" |
13 #include "vm/os_thread.h" | 13 #include "vm/os_thread.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 Mutex* PortMap::mutex_ = NULL; | 17 Mutex* PortMap::mutex_ = NULL; |
18 PortMap::Entry* PortMap::map_ = NULL; | 18 PortMap::Entry* PortMap::map_ = NULL; |
19 MessageHandler* PortMap::deleted_entry_ = reinterpret_cast<MessageHandler*>(1); | 19 MessageHandler* PortMap::deleted_entry_ = reinterpret_cast<MessageHandler*>(1); |
20 intptr_t PortMap::capacity_ = 0; | 20 intptr_t PortMap::capacity_ = 0; |
21 intptr_t PortMap::used_ = 0; | 21 intptr_t PortMap::used_ = 0; |
22 intptr_t PortMap::deleted_ = 0; | 22 intptr_t PortMap::deleted_ = 0; |
23 Random* PortMap::prng_ = NULL; | 23 Random* PortMap::prng_ = NULL; |
24 | 24 |
25 | |
26 intptr_t PortMap::FindPort(Dart_Port port) { | 25 intptr_t PortMap::FindPort(Dart_Port port) { |
27 // ILLEGAL_PORT (0) is used as a sentinel value in Entry.port. The loop below | 26 // ILLEGAL_PORT (0) is used as a sentinel value in Entry.port. The loop below |
28 // could return the index to a deleted port when we are searching for | 27 // could return the index to a deleted port when we are searching for |
29 // port id ILLEGAL_PORT. Return -1 immediately to indicate the port | 28 // port id ILLEGAL_PORT. Return -1 immediately to indicate the port |
30 // does not exist. | 29 // does not exist. |
31 if (port == ILLEGAL_PORT) { | 30 if (port == ILLEGAL_PORT) { |
32 return -1; | 31 return -1; |
33 } | 32 } |
34 ASSERT(port != ILLEGAL_PORT); | 33 ASSERT(port != ILLEGAL_PORT); |
35 intptr_t index = port % capacity_; | 34 intptr_t index = port % capacity_; |
36 intptr_t start_index = index; | 35 intptr_t start_index = index; |
37 Entry entry = map_[index]; | 36 Entry entry = map_[index]; |
38 while (entry.handler != NULL) { | 37 while (entry.handler != NULL) { |
39 if (entry.port == port) { | 38 if (entry.port == port) { |
40 return index; | 39 return index; |
41 } | 40 } |
42 index = (index + 1) % capacity_; | 41 index = (index + 1) % capacity_; |
43 // Prevent endless loops. | 42 // Prevent endless loops. |
44 ASSERT(index != start_index); | 43 ASSERT(index != start_index); |
45 entry = map_[index]; | 44 entry = map_[index]; |
46 } | 45 } |
47 return -1; | 46 return -1; |
48 } | 47 } |
49 | 48 |
50 | |
51 void PortMap::Rehash(intptr_t new_capacity) { | 49 void PortMap::Rehash(intptr_t new_capacity) { |
52 Entry* new_ports = new Entry[new_capacity]; | 50 Entry* new_ports = new Entry[new_capacity]; |
53 memset(new_ports, 0, new_capacity * sizeof(Entry)); | 51 memset(new_ports, 0, new_capacity * sizeof(Entry)); |
54 | 52 |
55 for (intptr_t i = 0; i < capacity_; i++) { | 53 for (intptr_t i = 0; i < capacity_; i++) { |
56 Entry entry = map_[i]; | 54 Entry entry = map_[i]; |
57 // Skip free and deleted entries. | 55 // Skip free and deleted entries. |
58 if (entry.port != 0) { | 56 if (entry.port != 0) { |
59 intptr_t new_index = entry.port % new_capacity; | 57 intptr_t new_index = entry.port % new_capacity; |
60 while (new_ports[new_index].port != 0) { | 58 while (new_ports[new_index].port != 0) { |
61 new_index = (new_index + 1) % new_capacity; | 59 new_index = (new_index + 1) % new_capacity; |
62 } | 60 } |
63 new_ports[new_index] = entry; | 61 new_ports[new_index] = entry; |
64 } | 62 } |
65 } | 63 } |
66 delete[] map_; | 64 delete[] map_; |
67 map_ = new_ports; | 65 map_ = new_ports; |
68 capacity_ = new_capacity; | 66 capacity_ = new_capacity; |
69 deleted_ = 0; | 67 deleted_ = 0; |
70 } | 68 } |
71 | 69 |
72 | |
73 const char* PortMap::PortStateString(PortState kind) { | 70 const char* PortMap::PortStateString(PortState kind) { |
74 switch (kind) { | 71 switch (kind) { |
75 case kNewPort: | 72 case kNewPort: |
76 return "new"; | 73 return "new"; |
77 case kLivePort: | 74 case kLivePort: |
78 return "live"; | 75 return "live"; |
79 case kControlPort: | 76 case kControlPort: |
80 return "control"; | 77 return "control"; |
81 default: | 78 default: |
82 UNREACHABLE(); | 79 UNREACHABLE(); |
83 return "UNKNOWN"; | 80 return "UNKNOWN"; |
84 } | 81 } |
85 } | 82 } |
86 | 83 |
87 | |
88 Dart_Port PortMap::AllocatePort() { | 84 Dart_Port PortMap::AllocatePort() { |
89 const Dart_Port kMASK = 0x3fffffff; | 85 const Dart_Port kMASK = 0x3fffffff; |
90 Dart_Port result = prng_->NextUInt32() & kMASK; | 86 Dart_Port result = prng_->NextUInt32() & kMASK; |
91 | 87 |
92 // Keep getting new values while we have an illegal port number or the port | 88 // Keep getting new values while we have an illegal port number or the port |
93 // number is already in use. | 89 // number is already in use. |
94 while ((result == 0) || (FindPort(result) >= 0)) { | 90 while ((result == 0) || (FindPort(result) >= 0)) { |
95 result = prng_->NextUInt32() & kMASK; | 91 result = prng_->NextUInt32() & kMASK; |
96 } | 92 } |
97 | 93 |
98 ASSERT(result != 0); | 94 ASSERT(result != 0); |
99 ASSERT(FindPort(result) < 0); | 95 ASSERT(FindPort(result) < 0); |
100 return result; | 96 return result; |
101 } | 97 } |
102 | 98 |
103 | |
104 void PortMap::SetPortState(Dart_Port port, PortState state) { | 99 void PortMap::SetPortState(Dart_Port port, PortState state) { |
105 MutexLocker ml(mutex_); | 100 MutexLocker ml(mutex_); |
106 intptr_t index = FindPort(port); | 101 intptr_t index = FindPort(port); |
107 ASSERT(index >= 0); | 102 ASSERT(index >= 0); |
108 PortState old_state = map_[index].state; | 103 PortState old_state = map_[index].state; |
109 ASSERT(old_state == kNewPort); | 104 ASSERT(old_state == kNewPort); |
110 map_[index].state = state; | 105 map_[index].state = state; |
111 if (state == kLivePort) { | 106 if (state == kLivePort) { |
112 map_[index].handler->increment_live_ports(); | 107 map_[index].handler->increment_live_ports(); |
113 } | 108 } |
114 if (FLAG_trace_isolates) { | 109 if (FLAG_trace_isolates) { |
115 OS::Print( | 110 OS::Print( |
116 "[^] Port (%s) -> (%s): \n" | 111 "[^] Port (%s) -> (%s): \n" |
117 "\thandler: %s\n" | 112 "\thandler: %s\n" |
118 "\tport: %" Pd64 "\n", | 113 "\tport: %" Pd64 "\n", |
119 PortStateString(old_state), PortStateString(state), | 114 PortStateString(old_state), PortStateString(state), |
120 map_[index].handler->name(), port); | 115 map_[index].handler->name(), port); |
121 } | 116 } |
122 } | 117 } |
123 | 118 |
124 | |
125 void PortMap::MaintainInvariants() { | 119 void PortMap::MaintainInvariants() { |
126 intptr_t empty = capacity_ - used_ - deleted_; | 120 intptr_t empty = capacity_ - used_ - deleted_; |
127 if (used_ > ((capacity_ / 4) * 3)) { | 121 if (used_ > ((capacity_ / 4) * 3)) { |
128 // Grow the port map. | 122 // Grow the port map. |
129 Rehash(capacity_ * 2); | 123 Rehash(capacity_ * 2); |
130 } else if (empty < deleted_) { | 124 } else if (empty < deleted_) { |
131 // Rehash without growing the table to flush the deleted slots out of the | 125 // Rehash without growing the table to flush the deleted slots out of the |
132 // map. | 126 // map. |
133 Rehash(capacity_); | 127 Rehash(capacity_); |
134 } | 128 } |
135 } | 129 } |
136 | 130 |
137 | |
138 Dart_Port PortMap::CreatePort(MessageHandler* handler) { | 131 Dart_Port PortMap::CreatePort(MessageHandler* handler) { |
139 ASSERT(handler != NULL); | 132 ASSERT(handler != NULL); |
140 MutexLocker ml(mutex_); | 133 MutexLocker ml(mutex_); |
141 #if defined(DEBUG) | 134 #if defined(DEBUG) |
142 handler->CheckAccess(); | 135 handler->CheckAccess(); |
143 #endif | 136 #endif |
144 | 137 |
145 Entry entry; | 138 Entry entry; |
146 entry.port = AllocatePort(); | 139 entry.port = AllocatePort(); |
147 entry.handler = handler; | 140 entry.handler = handler; |
(...skipping 30 matching lines...) Expand all Loading... |
178 OS::Print( | 171 OS::Print( |
179 "[+] Opening port: \n" | 172 "[+] Opening port: \n" |
180 "\thandler: %s\n" | 173 "\thandler: %s\n" |
181 "\tport: %" Pd64 "\n", | 174 "\tport: %" Pd64 "\n", |
182 handler->name(), entry.port); | 175 handler->name(), entry.port); |
183 } | 176 } |
184 | 177 |
185 return entry.port; | 178 return entry.port; |
186 } | 179 } |
187 | 180 |
188 | |
189 bool PortMap::ClosePort(Dart_Port port) { | 181 bool PortMap::ClosePort(Dart_Port port) { |
190 MessageHandler* handler = NULL; | 182 MessageHandler* handler = NULL; |
191 { | 183 { |
192 MutexLocker ml(mutex_); | 184 MutexLocker ml(mutex_); |
193 intptr_t index = FindPort(port); | 185 intptr_t index = FindPort(port); |
194 if (index < 0) { | 186 if (index < 0) { |
195 return false; | 187 return false; |
196 } | 188 } |
197 ASSERT(index < capacity_); | 189 ASSERT(index < capacity_); |
198 ASSERT(map_[index].port != 0); | 190 ASSERT(map_[index].port != 0); |
(...skipping 18 matching lines...) Expand all Loading... |
217 MaintainInvariants(); | 209 MaintainInvariants(); |
218 } | 210 } |
219 handler->ClosePort(port); | 211 handler->ClosePort(port); |
220 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) { | 212 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) { |
221 // Delete handler as soon as it isn't busy with a task. | 213 // Delete handler as soon as it isn't busy with a task. |
222 handler->RequestDeletion(); | 214 handler->RequestDeletion(); |
223 } | 215 } |
224 return true; | 216 return true; |
225 } | 217 } |
226 | 218 |
227 | |
228 void PortMap::ClosePorts(MessageHandler* handler) { | 219 void PortMap::ClosePorts(MessageHandler* handler) { |
229 { | 220 { |
230 MutexLocker ml(mutex_); | 221 MutexLocker ml(mutex_); |
231 for (intptr_t i = 0; i < capacity_; i++) { | 222 for (intptr_t i = 0; i < capacity_; i++) { |
232 if (map_[i].handler == handler) { | 223 if (map_[i].handler == handler) { |
233 // Mark the slot as deleted. | 224 // Mark the slot as deleted. |
234 map_[i].port = 0; | 225 map_[i].port = 0; |
235 map_[i].handler = deleted_entry_; | 226 map_[i].handler = deleted_entry_; |
236 if (map_[i].state == kLivePort) { | 227 if (map_[i].state == kLivePort) { |
237 handler->decrement_live_ports(); | 228 handler->decrement_live_ports(); |
238 } | 229 } |
239 used_--; | 230 used_--; |
240 deleted_++; | 231 deleted_++; |
241 } | 232 } |
242 } | 233 } |
243 MaintainInvariants(); | 234 MaintainInvariants(); |
244 } | 235 } |
245 handler->CloseAllPorts(); | 236 handler->CloseAllPorts(); |
246 } | 237 } |
247 | 238 |
248 | |
249 bool PortMap::PostMessage(Message* message) { | 239 bool PortMap::PostMessage(Message* message) { |
250 MutexLocker ml(mutex_); | 240 MutexLocker ml(mutex_); |
251 intptr_t index = FindPort(message->dest_port()); | 241 intptr_t index = FindPort(message->dest_port()); |
252 if (index < 0) { | 242 if (index < 0) { |
253 delete message; | 243 delete message; |
254 return false; | 244 return false; |
255 } | 245 } |
256 ASSERT(index >= 0); | 246 ASSERT(index >= 0); |
257 ASSERT(index < capacity_); | 247 ASSERT(index < capacity_); |
258 MessageHandler* handler = map_[index].handler; | 248 MessageHandler* handler = map_[index].handler; |
259 ASSERT(map_[index].port != 0); | 249 ASSERT(map_[index].port != 0); |
260 ASSERT((handler != NULL) && (handler != deleted_entry_)); | 250 ASSERT((handler != NULL) && (handler != deleted_entry_)); |
261 handler->PostMessage(message); | 251 handler->PostMessage(message); |
262 return true; | 252 return true; |
263 } | 253 } |
264 | 254 |
265 | |
266 bool PortMap::IsLocalPort(Dart_Port id) { | 255 bool PortMap::IsLocalPort(Dart_Port id) { |
267 MutexLocker ml(mutex_); | 256 MutexLocker ml(mutex_); |
268 intptr_t index = FindPort(id); | 257 intptr_t index = FindPort(id); |
269 if (index < 0) { | 258 if (index < 0) { |
270 // Port does not exist. | 259 // Port does not exist. |
271 return false; | 260 return false; |
272 } | 261 } |
273 | 262 |
274 MessageHandler* handler = map_[index].handler; | 263 MessageHandler* handler = map_[index].handler; |
275 return handler->IsCurrentIsolate(); | 264 return handler->IsCurrentIsolate(); |
276 } | 265 } |
277 | 266 |
278 | |
279 Isolate* PortMap::GetIsolate(Dart_Port id) { | 267 Isolate* PortMap::GetIsolate(Dart_Port id) { |
280 MutexLocker ml(mutex_); | 268 MutexLocker ml(mutex_); |
281 intptr_t index = FindPort(id); | 269 intptr_t index = FindPort(id); |
282 if (index < 0) { | 270 if (index < 0) { |
283 // Port does not exist. | 271 // Port does not exist. |
284 return NULL; | 272 return NULL; |
285 } | 273 } |
286 | 274 |
287 MessageHandler* handler = map_[index].handler; | 275 MessageHandler* handler = map_[index].handler; |
288 return handler->isolate(); | 276 return handler->isolate(); |
289 } | 277 } |
290 | 278 |
291 | |
292 void PortMap::InitOnce() { | 279 void PortMap::InitOnce() { |
293 mutex_ = new Mutex(); | 280 mutex_ = new Mutex(); |
294 prng_ = new Random(); | 281 prng_ = new Random(); |
295 | 282 |
296 static const intptr_t kInitialCapacity = 8; | 283 static const intptr_t kInitialCapacity = 8; |
297 // TODO(iposva): Verify whether we want to keep exponentially growing. | 284 // TODO(iposva): Verify whether we want to keep exponentially growing. |
298 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); | 285 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); |
299 map_ = new Entry[kInitialCapacity]; | 286 map_ = new Entry[kInitialCapacity]; |
300 memset(map_, 0, kInitialCapacity * sizeof(Entry)); | 287 memset(map_, 0, kInitialCapacity * sizeof(Entry)); |
301 capacity_ = kInitialCapacity; | 288 capacity_ = kInitialCapacity; |
302 used_ = 0; | 289 used_ = 0; |
303 deleted_ = 0; | 290 deleted_ = 0; |
304 } | 291 } |
305 | 292 |
306 | |
307 void PortMap::PrintPortsForMessageHandler(MessageHandler* handler, | 293 void PortMap::PrintPortsForMessageHandler(MessageHandler* handler, |
308 JSONStream* stream) { | 294 JSONStream* stream) { |
309 #ifndef PRODUCT | 295 #ifndef PRODUCT |
310 if (!FLAG_support_service) { | 296 if (!FLAG_support_service) { |
311 return; | 297 return; |
312 } | 298 } |
313 JSONObject jsobj(stream); | 299 JSONObject jsobj(stream); |
314 jsobj.AddProperty("type", "_Ports"); | 300 jsobj.AddProperty("type", "_Ports"); |
315 Object& msg_handler = Object::Handle(); | 301 Object& msg_handler = Object::Handle(); |
316 { | 302 { |
317 JSONArray ports(&jsobj, "ports"); | 303 JSONArray ports(&jsobj, "ports"); |
318 SafepointMutexLocker ml(mutex_); | 304 SafepointMutexLocker ml(mutex_); |
319 for (intptr_t i = 0; i < capacity_; i++) { | 305 for (intptr_t i = 0; i < capacity_; i++) { |
320 if (map_[i].handler == handler) { | 306 if (map_[i].handler == handler) { |
321 if (map_[i].state == kLivePort) { | 307 if (map_[i].state == kLivePort) { |
322 JSONObject port(&ports); | 308 JSONObject port(&ports); |
323 port.AddProperty("type", "_Port"); | 309 port.AddProperty("type", "_Port"); |
324 port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", map_[i].port); | 310 port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", map_[i].port); |
325 msg_handler = DartLibraryCalls::LookupHandler(map_[i].port); | 311 msg_handler = DartLibraryCalls::LookupHandler(map_[i].port); |
326 port.AddProperty("handler", msg_handler); | 312 port.AddProperty("handler", msg_handler); |
327 } | 313 } |
328 } | 314 } |
329 } | 315 } |
330 } | 316 } |
331 #endif | 317 #endif |
332 } | 318 } |
333 | 319 |
334 | |
335 void PortMap::DebugDumpForMessageHandler(MessageHandler* handler) { | 320 void PortMap::DebugDumpForMessageHandler(MessageHandler* handler) { |
336 SafepointMutexLocker ml(mutex_); | 321 SafepointMutexLocker ml(mutex_); |
337 Object& msg_handler = Object::Handle(); | 322 Object& msg_handler = Object::Handle(); |
338 for (intptr_t i = 0; i < capacity_; i++) { | 323 for (intptr_t i = 0; i < capacity_; i++) { |
339 if (map_[i].handler == handler) { | 324 if (map_[i].handler == handler) { |
340 if (map_[i].state == kLivePort) { | 325 if (map_[i].state == kLivePort) { |
341 OS::Print("Live Port = %" Pd64 "\n", map_[i].port); | 326 OS::Print("Live Port = %" Pd64 "\n", map_[i].port); |
342 msg_handler = DartLibraryCalls::LookupHandler(map_[i].port); | 327 msg_handler = DartLibraryCalls::LookupHandler(map_[i].port); |
343 OS::Print("Handler = %s\n", msg_handler.ToCString()); | 328 OS::Print("Handler = %s\n", msg_handler.ToCString()); |
344 } | 329 } |
345 } | 330 } |
346 } | 331 } |
347 } | 332 } |
348 | 333 |
349 | |
350 } // namespace dart | 334 } // namespace dart |
OLD | NEW |