1// Copyright (c) 2011, 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#ifndef RUNTIME_VM_MESSAGE_H_
6#define RUNTIME_VM_MESSAGE_H_
7
8#include <memory>
9#include <utility>
10
11#include "platform/assert.h"
12#include "vm/allocation.h"
13#include "vm/finalizable_data.h"
14#include "vm/globals.h"
15#include "vm/tagged_pointer.h"
16
17// Duplicated from dart_api.h to avoid including the whole header.
18typedef int64_t Dart_Port;
19
20namespace dart {
21
22class Bequest;
23class JSONStream;
24class PersistentHandle;
25class OldPage;
26class WeakTable;
27class FreeList;
28
29class Message {
30 public:
31 typedef enum {
32 kNormalPriority = 0, // Deliver message when idle.
33 kOOBPriority = 1, // Deliver message asap.
34
35 // Iteration.
36 kFirstPriority = 0,
37 kNumPriorities = 2,
38 } Priority;
39
40 // Values defining the type of OOB messages. OOB messages can only be
41 // fixed length arrays where the first element is a Smi with one of the
42 // valid values below.
43 typedef enum {
44 kIllegalOOB = 0,
45 kServiceOOBMsg = 1,
46 kIsolateLibOOBMsg = 2,
47 kDelayedIsolateLibOOBMsg = 3,
48 } OOBMsgTag;
49
50 // A port number which is never used.
51 static const Dart_Port kIllegalPort;
52
53 // A new message to be sent between two isolates. The data handed to this
54 // message will be disposed by calling free() once the message object is
55 // being destructed (after delivery or when the receiving port is closed).
56 Message(Dart_Port dest_port,
57 uint8_t* snapshot,
58 intptr_t snapshot_length,
59 MessageFinalizableData* finalizable_data,
60 Priority priority,
61 Dart_Port delivery_failure_port = kIllegalPort);
62
63 // Message objects can also carry RawObject pointers for Smis and objects in
64 // the VM heap. This is indicated by setting the len_ field to 0.
65 Message(Dart_Port dest_port,
66 ObjectPtr raw_obj,
67 Priority priority,
68 Dart_Port delivery_failure_port = kIllegalPort);
69
70 Message(Dart_Port dest_port,
71 Bequest* bequest,
72 Priority priority,
73 Dart_Port delivery_failure_port = kIllegalPort);
74
75 ~Message();
76
77 template <typename... Args>
78 static std::unique_ptr<Message> New(Args&&... args) {
79 return std::unique_ptr<Message>(new Message(std::forward<Args>(args)...));
80 }
81
82 Dart_Port dest_port() const { return dest_port_; }
83
84 uint8_t* snapshot() const {
85 ASSERT(IsSnapshot());
86 return payload_.snapshot_;
87 }
88 intptr_t snapshot_length() const { return snapshot_length_; }
89
90 MessageFinalizableData* finalizable_data() { return finalizable_data_; }
91
92 intptr_t Size() const {
93 intptr_t size = snapshot_length_;
94 if (finalizable_data_ != NULL) {
95 size += finalizable_data_->external_size();
96 }
97 return size;
98 }
99
100 ObjectPtr raw_obj() const {
101 ASSERT(IsRaw());
102 return payload_.raw_obj_;
103 }
104 Bequest* bequest() const {
105 ASSERT(IsBequest());
106 return payload_.bequest_;
107 }
108 Priority priority() const { return priority_; }
109
110 // A message processed at any interrupt point (stack overflow check) instead
111 // of at the top of the message loop. Control messages from dart:isolate or
112 // vm-service requests.
113 bool IsOOB() const { return priority_ == Message::kOOBPriority; }
114 bool IsSnapshot() const { return !IsRaw() && !IsBequest(); }
115 // A message whose object is an immortal object from the vm-isolate's heap.
116 bool IsRaw() const { return snapshot_length_ == 0; }
117 // A message sent from sendAndExit.
118 bool IsBequest() const { return snapshot_length_ == -1; }
119
120 bool RedirectToDeliveryFailurePort();
121
122 void DropFinalizers() {
123 if (finalizable_data_ != nullptr) {
124 finalizable_data_->DropFinalizers();
125 }
126 }
127
128 intptr_t Id() const;
129
130 static const char* PriorityAsString(Priority priority);
131
132 private:
133 friend class MessageQueue;
134
135 Message* next_;
136 Dart_Port dest_port_;
137 Dart_Port delivery_failure_port_;
138 union Payload {
139 Payload(uint8_t* snapshot) : snapshot_(snapshot) {}
140 Payload(ObjectPtr raw_obj) : raw_obj_(raw_obj) {}
141 Payload(Bequest* bequest) : bequest_(bequest) {}
142
143 uint8_t* snapshot_;
144 ObjectPtr raw_obj_;
145 Bequest* bequest_;
146 } payload_;
147 intptr_t snapshot_length_;
148 MessageFinalizableData* finalizable_data_;
149 Priority priority_;
150
151 DISALLOW_COPY_AND_ASSIGN(Message);
152};
153
154// There is a message queue per isolate.
155class MessageQueue {
156 public:
157 MessageQueue();
158 ~MessageQueue();
159
160 void Enqueue(std::unique_ptr<Message> msg, bool before_events);
161
162 // Gets the next message from the message queue or NULL if no
163 // message is available. This function will not block.
164 std::unique_ptr<Message> Dequeue();
165
166 bool IsEmpty() { return head_ == NULL; }
167
168 // Clear all messages from the message queue.
169 void Clear();
170
171 // Iterator class.
172 class Iterator : public ValueObject {
173 public:
174 explicit Iterator(const MessageQueue* queue);
175 virtual ~Iterator();
176
177 void Reset(const MessageQueue* queue);
178
179 // Returns false when there are no more messages left.
180 bool HasNext();
181
182 // Returns the current message and moves forward.
183 Message* Next();
184
185 private:
186 Message* next_;
187 };
188
189 intptr_t Length() const;
190
191 // Returns the message with id or NULL.
192 Message* FindMessageById(intptr_t id);
193
194 void PrintJSON(JSONStream* stream);
195
196 private:
197 Message* head_;
198 Message* tail_;
199
200 DISALLOW_COPY_AND_ASSIGN(MessageQueue);
201};
202
203} // namespace dart
204
205#endif // RUNTIME_VM_MESSAGE_H_
206