| // 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 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 Isolate.exit 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 Isolate.exit 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(); | |
| } | |
| } | |
| 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; | |
| private: | |
| Message* head_; | |
| Message* tail_; | |
| DISALLOW_COPY_AND_ASSIGN(MessageQueue); | |
| }; | |
| } // namespace dart | |
| #endif // RUNTIME_VM_MESSAGE_H_ |