| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/isolate.h" | 5 #include "vm/isolate.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "platform/json.h" | 9 #include "platform/json.h" |
| 10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 Object& obj = Object::Handle(I, message.At(2)); | 195 Object& obj = Object::Handle(I, message.At(2)); |
| 196 if (!I->VerifyPauseCapability(obj)) return true; | 196 if (!I->VerifyPauseCapability(obj)) return true; |
| 197 obj = message.At(3); | 197 obj = message.At(3); |
| 198 if (!obj.IsCapability()) return true; | 198 if (!obj.IsCapability()) return true; |
| 199 if (I->RemoveResumeCapability(Capability::Cast(obj))) { | 199 if (I->RemoveResumeCapability(Capability::Cast(obj))) { |
| 200 decrement_paused(); | 200 decrement_paused(); |
| 201 } | 201 } |
| 202 break; | 202 break; |
| 203 } | 203 } |
| 204 case kPingMsg: { | 204 case kPingMsg: { |
| 205 // [ OOB, kPingMsg, responsePort, priority ] | 205 // [ OOB, kPingMsg, responsePort, priority, response ] |
| 206 if (message.Length() != 4) return true; | 206 if (message.Length() != 5) return true; |
| 207 const Object& obj2 = Object::Handle(I, message.At(2)); | 207 const Object& obj2 = Object::Handle(I, message.At(2)); |
| 208 if (!obj2.IsSendPort()) return true; | 208 if (!obj2.IsSendPort()) return true; |
| 209 const SendPort& send_port = SendPort::Cast(obj2); | 209 const SendPort& send_port = SendPort::Cast(obj2); |
| 210 const Object& obj3 = Object::Handle(I, message.At(3)); | 210 const Object& obj3 = Object::Handle(I, message.At(3)); |
| 211 if (!obj3.IsSmi()) return true; | 211 if (!obj3.IsSmi()) return true; |
| 212 const intptr_t priority = Smi::Cast(obj3).Value(); | 212 const intptr_t priority = Smi::Cast(obj3).Value(); |
| 213 const Object& obj4 = Object::Handle(I, message.At(4)); |
| 214 if (!obj4.IsInstance() && !obj4.IsNull()) return true; |
| 215 const Instance& response = |
| 216 obj4.IsNull() ? Instance::null_instance() : Instance::Cast(obj4); |
| 213 if (priority == kImmediateAction) { | 217 if (priority == kImmediateAction) { |
| 214 uint8_t* data = NULL; | 218 uint8_t* data = NULL; |
| 215 intptr_t len = 0; | 219 intptr_t len = 0; |
| 216 SerializeObject(Object::null_instance(), &data, &len, false); | 220 SerializeObject(response, &data, &len, false); |
| 217 PortMap::PostMessage(new Message(send_port.Id(), | 221 PortMap::PostMessage(new Message(send_port.Id(), |
| 218 data, len, | 222 data, len, |
| 219 Message::kNormalPriority)); | 223 Message::kNormalPriority)); |
| 220 } else { | 224 } else { |
| 221 ASSERT((priority == kBeforeNextEventAction) || | 225 ASSERT((priority == kBeforeNextEventAction) || |
| 222 (priority == kAsEventAction)); | 226 (priority == kAsEventAction)); |
| 223 // Update the message so that it will be handled immediately when it | 227 // Update the message so that it will be handled immediately when it |
| 224 // is picked up from the message queue the next time. | 228 // is picked up from the message queue the next time. |
| 225 message.SetAt( | 229 message.SetAt( |
| 226 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); | 230 0, Smi::Handle(I, Smi::New(Message::kDelayedIsolateLibOOBMsg))); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 Message::kNormalPriority), | 265 Message::kNormalPriority), |
| 262 priority == kBeforeNextEventAction /* at_head */); | 266 priority == kBeforeNextEventAction /* at_head */); |
| 263 } | 267 } |
| 264 break; | 268 break; |
| 265 } | 269 } |
| 266 case kAddExitMsg: | 270 case kAddExitMsg: |
| 267 case kDelExitMsg: | 271 case kDelExitMsg: |
| 268 case kAddErrorMsg: | 272 case kAddErrorMsg: |
| 269 case kDelErrorMsg: { | 273 case kDelErrorMsg: { |
| 270 // [ OOB, msg, listener port ] | 274 // [ OOB, msg, listener port ] |
| 271 if (message.Length() != 3) return true; | 275 if (message.Length() < 3) return true; |
| 272 const Object& obj = Object::Handle(I, message.At(2)); | 276 const Object& obj = Object::Handle(I, message.At(2)); |
| 273 if (!obj.IsSendPort()) return true; | 277 if (!obj.IsSendPort()) return true; |
| 274 const SendPort& listener = SendPort::Cast(obj); | 278 const SendPort& listener = SendPort::Cast(obj); |
| 275 switch (msg_type) { | 279 switch (msg_type) { |
| 276 case kAddExitMsg: | 280 case kAddExitMsg: { |
| 277 I->AddExitListener(listener); | 281 if (message.Length() != 4) return true; |
| 282 // [ OOB, msg, listener port, response object ] |
| 283 const Object& response = Object::Handle(I, message.At(3)); |
| 284 if (!response.IsInstance() && !response.IsNull()) return true; |
| 285 I->AddExitListener(listener, |
| 286 response.IsNull() ? Instance::null_instance() |
| 287 : Instance::Cast(response)); |
| 278 break; | 288 break; |
| 289 } |
| 279 case kDelExitMsg: | 290 case kDelExitMsg: |
| 291 if (message.Length() != 3) return true; |
| 280 I->RemoveExitListener(listener); | 292 I->RemoveExitListener(listener); |
| 281 break; | 293 break; |
| 282 case kAddErrorMsg: | 294 case kAddErrorMsg: |
| 295 if (message.Length() != 3) return true; |
| 283 I->AddErrorListener(listener); | 296 I->AddErrorListener(listener); |
| 284 break; | 297 break; |
| 285 case kDelErrorMsg: | 298 case kDelErrorMsg: |
| 299 if (message.Length() != 3) return true; |
| 286 I->RemoveErrorListener(listener); | 300 I->RemoveErrorListener(listener); |
| 287 break; | 301 break; |
| 288 default: | 302 default: |
| 289 UNREACHABLE(); | 303 UNREACHABLE(); |
| 290 } | 304 } |
| 291 break; | 305 break; |
| 292 } | 306 } |
| 293 case kErrorFatalMsg: { | 307 case kErrorFatalMsg: { |
| 294 // [ OOB, kErrorFatalMsg, terminate capability, val ] | 308 // [ OOB, kErrorFatalMsg, terminate capability, val ] |
| 295 if (message.Length() != 4) return true; | 309 if (message.Length() != 4) return true; |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 caps.SetAt(i, current); | 1009 caps.SetAt(i, current); |
| 996 return true; | 1010 return true; |
| 997 } | 1011 } |
| 998 } | 1012 } |
| 999 return false; | 1013 return false; |
| 1000 } | 1014 } |
| 1001 | 1015 |
| 1002 | 1016 |
| 1003 // TODO(iposva): Remove duplicated code and start using some hash based | 1017 // TODO(iposva): Remove duplicated code and start using some hash based |
| 1004 // structure instead of these linear lookups. | 1018 // structure instead of these linear lookups. |
| 1005 void Isolate::AddExitListener(const SendPort& listener) { | 1019 void Isolate::AddExitListener(const SendPort& listener, |
| 1020 const Instance& response) { |
| 1006 // Ensure a limit for the number of listeners remembered. | 1021 // Ensure a limit for the number of listeners remembered. |
| 1007 static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize); | 1022 static const intptr_t kMaxListeners = kSmiMax / (12 * kWordSize); |
| 1008 | 1023 |
| 1009 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | 1024 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( |
| 1010 this, object_store()->exit_listeners()); | 1025 this, object_store()->exit_listeners()); |
| 1011 SendPort& current = SendPort::Handle(this); | 1026 SendPort& current = SendPort::Handle(this); |
| 1012 intptr_t insertion_index = -1; | 1027 intptr_t insertion_index = -1; |
| 1013 for (intptr_t i = 0; i < listeners.Length(); i++) { | 1028 for (intptr_t i = 0; i < listeners.Length(); i += 2) { |
| 1014 current ^= listeners.At(i); | 1029 current ^= listeners.At(i); |
| 1015 if (current.IsNull()) { | 1030 if (current.IsNull()) { |
| 1016 if (insertion_index < 0) { | 1031 if (insertion_index < 0) { |
| 1017 insertion_index = i; | 1032 insertion_index = i; |
| 1018 } | 1033 } |
| 1019 } else if (current.Id() == listener.Id()) { | 1034 } else if (current.Id() == listener.Id()) { |
| 1035 listeners.SetAt(i + 1, response); |
| 1020 return; | 1036 return; |
| 1021 } | 1037 } |
| 1022 } | 1038 } |
| 1023 if (insertion_index < 0) { | 1039 if (insertion_index < 0) { |
| 1024 if (listeners.Length() >= kMaxListeners) { | 1040 if (listeners.Length() >= kMaxListeners) { |
| 1025 // Cannot grow the array of listeners beyond its max. Additional | 1041 // Cannot grow the array of listeners beyond its max. Additional |
| 1026 // listeners are ignored. In practice will never happen as we will | 1042 // listeners are ignored. In practice will never happen as we will |
| 1027 // run out of memory beforehand. | 1043 // run out of memory beforehand. |
| 1028 return; | 1044 return; |
| 1029 } | 1045 } |
| 1030 listeners.Add(listener); | 1046 listeners.Add(listener); |
| 1047 listeners.Add(response); |
| 1031 } else { | 1048 } else { |
| 1032 listeners.SetAt(insertion_index, listener); | 1049 listeners.SetAt(insertion_index, listener); |
| 1050 listeners.SetAt(insertion_index + 1, response); |
| 1033 } | 1051 } |
| 1034 } | 1052 } |
| 1035 | 1053 |
| 1036 | 1054 |
| 1037 void Isolate::RemoveExitListener(const SendPort& listener) { | 1055 void Isolate::RemoveExitListener(const SendPort& listener) { |
| 1038 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | 1056 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( |
| 1039 this, object_store()->exit_listeners()); | 1057 this, object_store()->exit_listeners()); |
| 1040 SendPort& current = SendPort::Handle(this); | 1058 SendPort& current = SendPort::Handle(this); |
| 1041 for (intptr_t i = 0; i < listeners.Length(); i++) { | 1059 for (intptr_t i = 0; i < listeners.Length(); i += 2) { |
| 1042 current ^= listeners.At(i); | 1060 current ^= listeners.At(i); |
| 1043 if (!current.IsNull() && (current.Id() == listener.Id())) { | 1061 if (!current.IsNull() && (current.Id() == listener.Id())) { |
| 1044 // Remove the matching listener from the list. | 1062 // Remove the matching listener from the list. |
| 1045 current = SendPort::null(); | 1063 current = SendPort::null(); |
| 1046 listeners.SetAt(i, current); | 1064 listeners.SetAt(i, current); |
| 1065 listeners.SetAt(i + 1, Object::null_instance()); |
| 1047 return; | 1066 return; |
| 1048 } | 1067 } |
| 1049 } | 1068 } |
| 1050 } | 1069 } |
| 1051 | 1070 |
| 1052 | 1071 |
| 1053 void Isolate::NotifyExitListeners() { | 1072 void Isolate::NotifyExitListeners() { |
| 1054 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( | 1073 const GrowableObjectArray& listeners = GrowableObjectArray::Handle( |
| 1055 this, this->object_store()->exit_listeners()); | 1074 this, this->object_store()->exit_listeners()); |
| 1056 if (listeners.IsNull()) return; | 1075 if (listeners.IsNull()) return; |
| 1057 | 1076 |
| 1058 SendPort& listener = SendPort::Handle(this); | 1077 SendPort& listener = SendPort::Handle(this); |
| 1059 for (intptr_t i = 0; i < listeners.Length(); i++) { | 1078 Instance& response = Instance::Handle(this); |
| 1079 for (intptr_t i = 0; i < listeners.Length(); i += 2) { |
| 1060 listener ^= listeners.At(i); | 1080 listener ^= listeners.At(i); |
| 1061 if (!listener.IsNull()) { | 1081 if (!listener.IsNull()) { |
| 1062 Dart_Port port_id = listener.Id(); | 1082 Dart_Port port_id = listener.Id(); |
| 1063 uint8_t* data = NULL; | 1083 uint8_t* data = NULL; |
| 1064 intptr_t len = 0; | 1084 intptr_t len = 0; |
| 1065 SerializeObject(Object::null_instance(), &data, &len, false); | 1085 response ^= listeners.At(i + 1); |
| 1086 SerializeObject(response, &data, &len, false); |
| 1066 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); | 1087 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); |
| 1067 PortMap::PostMessage(msg); | 1088 PortMap::PostMessage(msg); |
| 1068 } | 1089 } |
| 1069 } | 1090 } |
| 1070 } | 1091 } |
| 1071 | 1092 |
| 1072 | 1093 |
| 1073 void Isolate::AddErrorListener(const SendPort& listener) { | 1094 void Isolate::AddErrorListener(const SendPort& listener) { |
| 1074 // Ensure a limit for the number of listeners remembered. | 1095 // Ensure a limit for the number of listeners remembered. |
| 1075 static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize); | 1096 static const intptr_t kMaxListeners = kSmiMax / (6 * kWordSize); |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1947 serialized_message_, serialized_message_len_); | 1968 serialized_message_, serialized_message_len_); |
| 1948 } | 1969 } |
| 1949 | 1970 |
| 1950 | 1971 |
| 1951 void IsolateSpawnState::Cleanup() { | 1972 void IsolateSpawnState::Cleanup() { |
| 1952 SwitchIsolateScope switch_scope(I); | 1973 SwitchIsolateScope switch_scope(I); |
| 1953 Dart::ShutdownIsolate(); | 1974 Dart::ShutdownIsolate(); |
| 1954 } | 1975 } |
| 1955 | 1976 |
| 1956 } // namespace dart | 1977 } // namespace dart |
| OLD | NEW |