blob: bbdf5f990bd66a86cfb8b3d84efc0cb1bed92f65 [file] [log] [blame]
// 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.
#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 OldPage;
class WeakTable;
class FreeList;
class Message {
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,
Dart_Port delivery_failure_port = kIllegalPort);
// Message objects can also carry RawObject pointers 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,
Dart_Port delivery_failure_port = kIllegalPort);
Message(Dart_Port dest_port,
PersistentHandle* handle,
Priority priority,
Dart_Port delivery_failure_port = kIllegalPort);
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 {
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_ != NULL) {
size += finalizable_data_->external_size();
return size;
ObjectPtr raw_obj() const {
return payload_.raw_obj_;
PersistentHandle* persistent_handle() const {
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(); }
// 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;
bool RedirectToDeliveryFailurePort();
void DropFinalizers() {
if (finalizable_data_ != nullptr) {
intptr_t Id() const;
static const char* PriorityAsString(Priority priority);
static intptr_t const kPersistentHandleSnapshotLen = -1;
friend class MessageQueue;
Message* next_ = nullptr;
Dart_Port dest_port_;
Dart_Port delivery_failure_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_;
// There is a message queue per isolate.
class MessageQueue {
void Enqueue(std::unique_ptr<Message> msg, bool before_events);
// Gets the next message from the message queue or NULL if no
// message is available. This function will not block.
std::unique_ptr<Message> Dequeue();
bool IsEmpty() { return head_ == NULL; }
// Clear all messages from the message queue.
void Clear();
// Iterator class.
class Iterator : public ValueObject {
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();
Message* next_;
intptr_t Length() const;
// Returns the message with id or NULL.
Message* FindMessageById(intptr_t id);
void PrintJSON(JSONStream* stream);
Message* head_;
Message* tail_;
} // namespace dart