Files
sdk/runtime/vm/message.cc
T
Slava Egorov 53ac68e2dd [vm_service] Deprecate Stack.messages
Make VM always return empty array in the response.

Current implementation for this field comes with a bunch of complexity
because it locks message handler and then invokes Dart code which
makes it difficult to reason about various invariants. This code is 
furthermore demonstrated to cause deadlocks. Given that nobody uses 
it - it is simpler to remove this code altogether.

Fixes https://github.com/flutter/flutter/issues/185156

TEST=ci

Change-Id: I497210e0f1542860caa0d765d634f8ec6a6a6964
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/496340
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
2026-04-20 10:28:01 -07:00

182 lines
4.7 KiB
C++

// 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 "vm/message.h"
#include <utility>
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/object.h"
#include "vm/port.h"
namespace dart {
const Dart_Port Message::kIllegalPort = 0;
Message::Message(Dart_Port dest_port,
uint8_t* snapshot,
intptr_t snapshot_length,
MessageFinalizableData* finalizable_data,
Priority priority)
: dest_port_(dest_port),
payload_(snapshot),
snapshot_length_(snapshot_length),
finalizable_data_(finalizable_data),
priority_(priority) {
ASSERT(IsSnapshot());
}
Message::Message(Dart_Port dest_port, ObjectPtr raw_obj, Priority priority)
: dest_port_(dest_port), payload_(raw_obj), priority_(priority) {
ASSERT(!raw_obj->IsHeapObject());
ASSERT(IsRaw());
}
Message::Message(Dart_Port dest_port,
PersistentHandle* handle,
Priority priority)
: dest_port_(dest_port),
payload_(handle),
snapshot_length_(kPersistentHandleSnapshotLen),
priority_(priority) {
ASSERT(IsPersistentHandle());
}
Message::Message(PersistentHandle* handle, Priority priority)
: dest_port_(ILLEGAL_PORT),
payload_(handle),
snapshot_length_(kFinalizerSnapshotLen),
priority_(priority) {
ASSERT(IsFinalizerInvocationRequest());
}
Message::~Message() {
if (IsSnapshot()) {
free(payload_.snapshot_);
}
delete finalizable_data_;
if (IsPersistentHandle() || IsFinalizerInvocationRequest()) {
auto isolate_group = IsolateGroup::Current();
isolate_group->api_state()->FreePersistentHandle(
payload_.persistent_handle_);
}
}
MessageQueue::MessageQueue() {
head_ = nullptr;
tail_ = nullptr;
}
MessageQueue::~MessageQueue() {
// Ensure that all pending messages have been released.
Clear();
ASSERT(head_ == nullptr);
}
void MessageQueue::Enqueue(std::unique_ptr<Message> msg0, bool before_events) {
// TODO(mdempsky): Use unique_ptr internally?
Message* msg = msg0.release();
// Make sure messages are not reused.
ASSERT(msg->next_ == nullptr);
if (head_ == nullptr) {
// Only element in the queue.
ASSERT(tail_ == nullptr);
head_ = msg;
tail_ = msg;
} else {
ASSERT(tail_ != nullptr);
if (!before_events) {
// Append at the tail.
tail_->next_ = msg;
tail_ = msg;
} else {
ASSERT(msg->dest_port() == Message::kIllegalPort);
if (head_->dest_port() != Message::kIllegalPort) {
msg->next_ = head_;
head_ = msg;
} else {
Message* cur = head_;
while (cur->next_ != nullptr) {
if (cur->next_->dest_port() != Message::kIllegalPort) {
// Splice in the new message at the break.
msg->next_ = cur->next_;
cur->next_ = msg;
return;
}
cur = cur->next_;
}
// All pending messages are isolate library control messages. Append at
// the tail.
ASSERT(tail_ == cur);
ASSERT(tail_->dest_port() == Message::kIllegalPort);
tail_->next_ = msg;
tail_ = msg;
}
}
}
}
std::unique_ptr<Message> MessageQueue::Dequeue() {
Message* result = head_;
if (result != nullptr) {
head_ = result->next_;
// The following update to tail_ is not strictly needed.
if (head_ == nullptr) {
tail_ = nullptr;
}
#if defined(DEBUG)
result->next_ = result; // Make sure to trigger ASSERT in Enqueue.
#endif // DEBUG
return std::unique_ptr<Message>(result);
}
return nullptr;
}
void MessageQueue::Clear() {
std::unique_ptr<Message> cur(head_);
head_ = nullptr;
tail_ = nullptr;
while (cur != nullptr) {
std::unique_ptr<Message> next(cur->next_);
cur = std::move(next);
}
}
MessageQueue::Iterator::Iterator(const MessageQueue* queue) : next_(nullptr) {
Reset(queue);
}
MessageQueue::Iterator::~Iterator() {}
void MessageQueue::Iterator::Reset(const MessageQueue* queue) {
ASSERT(queue != nullptr);
next_ = queue->head_;
}
// returns false when there are no more messages left.
bool MessageQueue::Iterator::HasNext() {
return next_ != nullptr;
}
// Returns the current message and moves forward.
Message* MessageQueue::Iterator::Next() {
Message* current = next_;
next_ = next_->next_;
return current;
}
intptr_t MessageQueue::Length() const {
MessageQueue::Iterator it(this);
intptr_t length = 0;
while (it.HasNext()) {
it.Next();
length++;
}
return length;
}
} // namespace dart