Flutter Engine
The Flutter Engine
port.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/port.h"
6
7#include <utility>
8
9#include "include/dart_api.h"
10#include "platform/utils.h"
11#include "vm/dart_api_impl.h"
12#include "vm/dart_entry.h"
13#include "vm/isolate.h"
14#include "vm/lockers.h"
15#include "vm/message_handler.h"
16#include "vm/os_thread.h"
17
18namespace dart {
19
20Mutex* PortMap::mutex_ = nullptr;
21PortSet<PortMap::Entry>* PortMap::ports_ = nullptr;
22Random* PortMap::prng_ = nullptr;
23
24Dart_Port PortMap::AllocatePort() {
26
28
29 // Keep getting new values while we have an illegal port number or the port
30 // number is already in use.
31 do {
32 // Ensure port ids are never valid object pointers so that reinterpreting
33 // an object pointer as a port id never produces a used port id.
34 const Dart_Port kMask2 = 0x3;
35
36 // Ensure port ids are representable in JavaScript for the benefit of
37 // vm-service clients such as Observatory.
38 result = prng_->NextJSInt() | kMask2;
39
40 // The two special marker ports are used for the hashset implementation and
41 // cannot be used as actual ports.
44 continue;
45 }
46
47 ASSERT(!static_cast<ObjectPtr>(static_cast<uword>(result))->IsWellFormed());
48 } while (ports_->Contains(result));
49
50 ASSERT(result != 0);
51 ASSERT(!ports_->Contains(result));
52 return result;
53}
54
56 ASSERT(handler != nullptr);
57 MutexLocker ml(mutex_);
58 if (ports_ == nullptr) {
59 return ILLEGAL_PORT;
60 }
61
62#if defined(DEBUG)
63 handler->CheckAccess();
64#endif
65
66 const Dart_Port port = AllocatePort();
67
68 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
69 // by the [PortMap::mutex_] we already hold.
70 MessageHandler::PortSetEntry isolate_entry;
71 isolate_entry.port = port;
72 handler->ports_.Insert(isolate_entry);
73
74 Entry entry;
75 entry.port = port;
76 entry.handler = handler;
77 ports_->Insert(entry);
78
79 if (FLAG_trace_isolates) {
81 "[+] Opening port: \n"
82 "\thandler: %s\n"
83 "\tport: %" Pd64 "\n",
84 handler->name(), entry.port);
85 }
86
87 return entry.port;
88}
89
91 if (message_handler != nullptr) *message_handler = nullptr;
92
93 MessageHandler* handler = nullptr;
94 {
95 MutexLocker ml(mutex_);
96 if (ports_ == nullptr) {
97 return false;
98 }
99 auto it = ports_->TryLookup(port);
100 if (it == ports_->end()) {
101 return false;
102 }
103 Entry entry = *it;
104 handler = entry.handler;
105 ASSERT(handler != nullptr);
106
107#if defined(DEBUG)
108 handler->CheckAccess();
109#endif
110
111 // Delete the port entry before releasing the lock to avoid holding the lock
112 // while flushing the messages below.
113 it.Delete();
114 ports_->Rebalance();
115
116 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
117 // by the [PortMap::mutex_] we already hold.
118 auto isolate_it = handler->ports_.TryLookup(port);
119 ASSERT(isolate_it != handler->ports_.end());
120 isolate_it.Delete();
121 handler->ports_.Rebalance();
122 }
123 handler->ClosePort(port);
124 if (message_handler != nullptr) *message_handler = handler;
125 return true;
126}
127
129 {
130 MutexLocker ml(mutex_);
131 if (ports_ == nullptr) {
132 return;
133 }
134 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
135 // by the [PortMap::mutex_] we already hold.
136 for (auto isolate_it = handler->ports_.begin();
137 isolate_it != handler->ports_.end(); ++isolate_it) {
138 auto it = ports_->TryLookup((*isolate_it).port);
139 ASSERT(it != ports_->end());
140 Entry entry = *it;
141 ASSERT(entry.port == (*isolate_it).port);
142 ASSERT(entry.handler == handler);
143 it.Delete();
144 isolate_it.Delete();
145 }
146 ASSERT(handler->ports_.IsEmpty());
147 ports_->Rebalance();
148 }
149 handler->CloseAllPorts();
150}
151
152bool PortMap::PostMessage(std::unique_ptr<Message> message,
153 bool before_events) {
154 MutexLocker ml(mutex_);
155 if (ports_ == nullptr) {
156 return false;
157 }
158 auto it = ports_->TryLookup(message->dest_port());
159 if (it == ports_->end()) {
160 // Ownership of external data remains with the poster.
161 message->DropFinalizers();
162 return false;
163 }
164 MessageHandler* handler = (*it).handler;
165 ASSERT(handler != nullptr);
166 handler->PostMessage(std::move(message), before_events);
167 return true;
168}
169
170#if defined(TESTING)
171bool PortMap::PortExists(Dart_Port id) {
172 MutexLocker ml(mutex_);
173 if (ports_ == nullptr) {
174 return false;
175 }
176 auto it = ports_->TryLookup(id);
177 return it != ports_->end();
178}
179#endif // defined(TESTING)
180
182 MutexLocker ml(mutex_);
183 if (ports_ == nullptr) {
184 return nullptr;
185 }
186 auto it = ports_->TryLookup(id);
187 if (it == ports_->end()) {
188 // Port does not exist.
189 return nullptr;
190 }
191
192 MessageHandler* handler = (*it).handler;
193 return handler->isolate();
194}
195
197 MutexLocker ml(mutex_);
198 if (ports_ == nullptr) {
199 return ILLEGAL_PORT;
200 }
201 auto it = ports_->TryLookup(id);
202 if (it == ports_->end()) {
203 // Port does not exist.
204 return ILLEGAL_PORT;
205 }
206
207 MessageHandler* handler = (*it).handler;
208 Isolate* isolate = handler->isolate();
209 if (isolate == nullptr) {
210 // Message handler is a native port instead of an isolate.
211 return ILLEGAL_PORT;
212 }
213 return isolate->origin_id();
214}
215
216#if defined(TESTING)
217bool PortMap::HasPorts(MessageHandler* handler) {
218 MutexLocker ml(mutex_);
219 if (ports_ == nullptr) {
220 return false;
221 }
222 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
223 // by the [PortMap::mutex_] we already hold.
224 return !handler->ports_.IsEmpty();
225}
226#endif
227
230 MutexLocker ml(mutex_);
231 if (ports_ == nullptr) {
232 // Port was closed.
233 return true;
234 }
235 auto it = ports_->TryLookup(receiver);
236 if (it == ports_->end()) {
237 // Port was closed.
238 return true;
239 }
240 auto isolate = (*it).handler->isolate();
241 if (isolate == nullptr) {
242 // Port belongs to a native port instead of an isolate.
243 return false;
244 }
245 return isolate->group() == group;
246}
247
249 if (mutex_ == nullptr) {
250 mutex_ = new Mutex();
251 }
252 ASSERT(mutex_ != nullptr);
253 if (prng_ == nullptr) {
254 prng_ = new Random();
255 }
256 if (ports_ == nullptr) {
257 ports_ = new PortSet<Entry>();
258 }
259}
260
262 ASSERT(ports_ != nullptr);
263 ASSERT(prng_ != nullptr);
264 for (auto it = ports_->begin(); it != ports_->end(); ++it) {
265 const auto& entry = *it;
266 ASSERT(entry.handler != nullptr);
267 delete entry.handler;
268 it.Delete();
269 }
270 ports_->Rebalance();
271
272 // Grab the mutex and delete the port set.
273 MutexLocker ml(mutex_);
274 delete prng_;
275 prng_ = nullptr;
276 delete ports_;
277 ports_ = nullptr;
278}
279
282#ifndef PRODUCT
283 JSONObject jsobj(stream);
284 jsobj.AddProperty("type", "_Ports");
285 Object& msg_handler = Object::Handle();
286 {
287 JSONArray ports(&jsobj, "ports");
288 SafepointMutexLocker ml(mutex_);
289 if (ports_ == nullptr) {
290 return;
291 }
292 for (auto& entry : *ports_) {
293 if (entry.handler == handler) {
294 JSONObject port(&ports);
295 port.AddProperty("type", "_Port");
296 port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", entry.port);
297 msg_handler = DartLibraryCalls::LookupHandler(entry.port);
298 port.AddProperty("handler", msg_handler);
299 }
300 }
301 }
302#endif
303}
304
306 SafepointMutexLocker ml(mutex_);
307 if (ports_ == nullptr) {
308 return;
309 }
310 Object& msg_handler = Object::Handle();
311 for (auto& entry : *ports_) {
312 if (entry.handler == handler) {
313 OS::PrintErr("Port = %" Pd64 "\n", entry.port);
314 msg_handler = DartLibraryCalls::LookupHandler(entry.port);
315 OS::PrintErr("Handler = %s\n", msg_handler.ToCString());
316 }
317 }
318}
319
320} // namespace dart
static ObjectPtr LookupHandler(Dart_Port port_id)
Definition: dart_entry.cc:664
Dart_Port origin_id()
Definition: isolate.cc:1990
void AddProperty(const char *name, bool b) const
Definition: json_stream.h:395
void PostMessage(std::unique_ptr< Message > message, bool before_events=false)
virtual const char * name() const
virtual Isolate * isolate() const
void ClosePort(Dart_Port port)
bool IsOwnedByCurrentThread() const
Definition: os_thread.h:402
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
virtual const char * ToCString() const
Definition: object.h:366
static Object & Handle()
Definition: object.h:407
static Dart_Port GetOriginId(Dart_Port id)
Definition: port.cc:196
static void DebugDumpForMessageHandler(MessageHandler *handler)
Definition: port.cc:305
static bool PostMessage(std::unique_ptr< Message > message, bool before_events=false)
Definition: port.cc:152
static Isolate * GetIsolate(Dart_Port id)
Definition: port.cc:181
static void PrintPortsForMessageHandler(MessageHandler *handler, JSONStream *stream)
Definition: port.cc:280
static bool ClosePort(Dart_Port id, MessageHandler **message_handler=nullptr)
Definition: port.cc:90
static void Init()
Definition: port.cc:248
static bool IsReceiverInThisIsolateGroupOrClosed(Dart_Port receiver, IsolateGroup *group)
Definition: port.cc:228
static void ClosePorts(MessageHandler *handler)
Definition: port.cc:128
static void Cleanup()
Definition: port.cc:261
static Dart_Port CreatePort(MessageHandler *handler)
Definition: port.cc:55
void Insert(const T &entry)
Definition: port_set.h:126
static constexpr Dart_Port kDeletedPort
Definition: port_set.h:20
Iterator TryLookup(Dart_Port port)
Definition: port_set.h:156
DART_FORCE_INLINE Iterator begin()
Definition: port_set.h:114
DART_FORCE_INLINE Iterator end()
Definition: port_set.h:124
void Rebalance()
Definition: port_set.h:165
bool IsEmpty() const
Definition: port_set.h:112
bool Contains(Dart_Port port)
Definition: port_set.h:162
static constexpr Dart_Port kFreePort
Definition: port_set.h:19
uint64_t NextJSInt()
Definition: random.h:37
#define ILLEGAL_PORT
Definition: dart_api.h:1535
int64_t Dart_Port
Definition: dart_api.h:1525
#define ASSERT(E)
GAsyncResult * result
Win32Message message
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
Definition: switches.h:87
#define Pd64
Definition: globals.h:416