// 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 #include #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 static std::unique_ptr New(Args&&... args) { return std::unique_ptr(new Message(std::forward(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 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 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_