| 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 |