| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_VM_MESSAGE_H_ |
| #define RUNTIME_VM_MESSAGE_H_ |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "platform/assert.h" |
| #include "vm/allocation.h" |
| #include "vm/finalizable_data.h" |
| #include "vm/globals.h" |
| #include "vm/tagged_pointer.h" |
| |
| // Duplicated from dart_api.h to avoid including the whole header. |
| typedef int64_t Dart_Port; |
| |
| namespace dart { |
| |
| class JSONStream; |
| class PersistentHandle; |
| |
| class Message { |
| public: |
| typedef enum { |
| kNormalPriority = 0, // Deliver message when idle. |
| kOOBPriority = 1, // Deliver message asap. |
| |
| // Iteration. |
| kFirstPriority = 0, |
| kNumPriorities = 2, |
| } Priority; |
| |
| // Values defining the type of OOB messages. OOB messages can only be |
| // fixed length arrays where the first element is a Smi with one of the |
| // valid values below. |
| typedef enum { |
| kIllegalOOB = 0, |
| kServiceOOBMsg = 1, |
| kIsolateLibOOBMsg = 2, |
| kDelayedIsolateLibOOBMsg = 3, |
| } OOBMsgTag; |
| |
| // A port number which is never used. |
| static const Dart_Port kIllegalPort; |
| |
| // A new message to be sent between two isolates. The data handed to this |
| // message will be disposed by calling free() once the message object is |
| // being destructed (after delivery or when the receiving port is closed). |
| Message(Dart_Port dest_port, |
| uint8_t* snapshot, |
| intptr_t snapshot_length, |
| MessageFinalizableData* finalizable_data, |
| Priority priority); |
| |
| // Message objects can also carry raw ObjectPtr for Smis and objects in |
| // the VM heap. This is indicated by setting the len_ field to 0. |
| Message(Dart_Port dest_port, ObjectPtr raw_obj, Priority priority); |
| |
| // A message sent from SendPort.send or SendPort.sendAndExit where sender and |
| // receiver are in the same isolate group. |
| Message(Dart_Port dest_port, PersistentHandle* handle, Priority priority); |
| |
| // A message sent from GC to run a finalizer. |
| Message(PersistentHandle* handle, Priority priority); |
| |
| ~Message(); |
| |
| template <typename... Args> |
| static std::unique_ptr<Message> New(Args&&... args) { |
| return std::unique_ptr<Message>(new Message(std::forward<Args>(args)...)); |
| } |
| |
| Dart_Port dest_port() const { return dest_port_; } |
| |
| uint8_t* snapshot() const { |
| ASSERT(IsSnapshot()); |
| return payload_.snapshot_; |
| } |
| intptr_t snapshot_length() const { return snapshot_length_; } |
| |
| MessageFinalizableData* finalizable_data() { return finalizable_data_; } |
| |
| intptr_t Size() const { |
| intptr_t size = snapshot_length_; |
| if (finalizable_data_ != nullptr) { |
| size += finalizable_data_->external_size(); |
| } |
| return size; |
| } |
| |
| ObjectPtr raw_obj() const { |
| ASSERT(IsRaw()); |
| return payload_.raw_obj_; |
| } |
| PersistentHandle* persistent_handle() const { |
| ASSERT(IsPersistentHandle() || IsFinalizerInvocationRequest()); |
| return payload_.persistent_handle_; |
| } |
| Priority priority() const { return priority_; } |
| |
| // A message processed at any interrupt point (stack overflow check) instead |
| // of at the top of the message loop. Control messages from dart:isolate or |
| // vm-service requests. |
| bool IsOOB() const { return priority_ == Message::kOOBPriority; } |
| bool IsSnapshot() const { |
| return !IsRaw() && !IsPersistentHandle() && !IsFinalizerInvocationRequest(); |
| } |
| // A message whose object is an immortal object from the vm-isolate's heap. |
| bool IsRaw() const { return snapshot_length_ == 0; } |
| // A message sent from SendPort.send or SendPort.sendAndExit where sender and |
| // receiver are in the same isolate group. |
| bool IsPersistentHandle() const { |
| return snapshot_length_ == kPersistentHandleSnapshotLen; |
| } |
| // A message sent from GC to run a finalizer. |
| bool IsFinalizerInvocationRequest() const { |
| return snapshot_length_ == kFinalizerSnapshotLen; |
| } |
| |
| void DropFinalizers() { |
| if (finalizable_data_ != nullptr) { |
| finalizable_data_->DropFinalizers(); |
| } |
| } |
| |
| intptr_t Id() const; |
| |
| static const char* PriorityAsString(Priority priority); |
| |
| private: |
| static intptr_t const kPersistentHandleSnapshotLen = -1; |
| static intptr_t const kFinalizerSnapshotLen = -2; |
| |
| friend class MessageQueue; |
| |
| Message* next_ = nullptr; |
| Dart_Port dest_port_; |
| union Payload { |
| Payload(uint8_t* snapshot) : snapshot_(snapshot) {} |
| Payload(ObjectPtr raw_obj) : raw_obj_(raw_obj) {} |
| Payload(PersistentHandle* persistent_handle) |
| : persistent_handle_(persistent_handle) {} |
| |
| uint8_t* snapshot_; |
| ObjectPtr raw_obj_; |
| PersistentHandle* persistent_handle_; |
| } payload_; |
| intptr_t snapshot_length_ = 0; |
| MessageFinalizableData* finalizable_data_ = nullptr; |
| Priority priority_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Message); |
| }; |
| |
| // There is a message queue per isolate. |
| class MessageQueue { |
| public: |
| MessageQueue(); |
| ~MessageQueue(); |
| |
| void Enqueue(std::unique_ptr<Message> msg, bool before_events); |
| |
| // Gets the next message from the message queue or nullptr if no |
| // message is available. This function will not block. |
| std::unique_ptr<Message> Dequeue(); |
| |
| bool IsEmpty() { return head_ == nullptr; } |
| |
| // Clear all messages from the message queue. |
| void Clear(); |
| |
| // Iterator class. |
| class Iterator : public ValueObject { |
| public: |
| explicit Iterator(const MessageQueue* queue); |
| virtual ~Iterator(); |
| |
| void Reset(const MessageQueue* queue); |
| |
| // Returns false when there are no more messages left. |
| bool HasNext(); |
| |
| // Returns the current message and moves forward. |
| Message* Next(); |
| |
| private: |
| Message* next_; |
| }; |
| |
| intptr_t Length() const; |
| |
| // Returns the message with id or nullptr. |
| Message* FindMessageById(intptr_t id); |
| |
| void PrintJSON(JSONStream* stream); |
| |
| private: |
| Message* head_; |
| Message* tail_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MessageQueue); |
| }; |
| |
| } // namespace dart |
| |
| #endif // RUNTIME_VM_MESSAGE_H_ |