[vm] Rewrite isolate message serialization.

TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/25559
Bug: https://github.com/dart-lang/sdk/issues/27285
Bug: https://github.com/flutter/flutter/issues/84691
Change-Id: I04608c5d337144195748d5f3509a29eb3116585d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/207865
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2021-07-29 16:55:55 +00:00 committed by commit-bot@chromium.org
parent 7a2f1adebe
commit bbefc05748
50 changed files with 4251 additions and 6159 deletions

View file

@ -19,6 +19,7 @@
#include "vm/lockers.h"
#include "vm/longjump.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object.h"
#include "vm/object_graph_copy.h"
#include "vm/object_store.h"
@ -123,10 +124,10 @@ DEFINE_NATIVE_ENTRY(SendPortImpl_sendInternal_, 0, 2) {
new Message(destination_port_id, handle, Message::kNormalPriority));
PortMap::PostMessage(std::move(message));
} else {
MessageWriter writer(can_send_any_object);
// TODO(turnidge): Throw an exception when the return value is false?
PortMap::PostMessage(writer.WriteMessage(obj, destination_port_id,
Message::kNormalPriority));
PortMap::PostMessage(WriteMessage(can_send_any_object, obj,
destination_port_id,
Message::kNormalPriority));
}
}
return Object::null();
@ -572,8 +573,7 @@ static InstancePtr DeserializeMessage(Thread* thread, Message* message) {
if (message->IsRaw()) {
return Instance::RawCast(message->raw_obj());
} else {
MessageSnapshotReader reader(message, thread);
const Object& obj = Object::Handle(zone, reader.ReadObject());
const Object& obj = Object::Handle(zone, ReadMessage(thread, message));
ASSERT(!obj.IsError());
return Instance::RawCast(obj.ptr());
}
@ -792,10 +792,10 @@ class SpawnIsolateTask : public ThreadPool::Task {
isolate->message_handler()->increment_paused();
}
{
MessageWriter writer(/*can_send_any_object=*/false);
// If parent isolate died, we ignore the fact that we cannot notify it.
PortMap::PostMessage(writer.WriteMessage(message, state_->parent_port(),
Message::kNormalPriority));
PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
message, state_->parent_port(),
Message::kNormalPriority));
}
return true;
@ -866,9 +866,9 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 0, 11) {
// serializable this will throw an exception.
SerializedObjectBuffer message_buffer;
{
MessageWriter writer(/* can_send_any_object = */ true);
message_buffer.set_message(writer.WriteMessage(
message, ILLEGAL_PORT, Message::kNormalPriority));
message_buffer.set_message(WriteMessage(
/* can_send_any_object */ true, message, ILLEGAL_PORT,
Message::kNormalPriority));
}
const char* utf8_package_config =
@ -951,14 +951,14 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 0, 12) {
SerializedObjectBuffer arguments_buffer;
SerializedObjectBuffer message_buffer;
{
MessageWriter writer(/* can_send_any_object = */ false);
arguments_buffer.set_message(
writer.WriteMessage(args, ILLEGAL_PORT, Message::kNormalPriority));
arguments_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
args, ILLEGAL_PORT,
Message::kNormalPriority));
}
{
MessageWriter writer(/* can_send_any_object = */ false);
message_buffer.set_message(
writer.WriteMessage(message, ILLEGAL_PORT, Message::kNormalPriority));
message_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
message, ILLEGAL_PORT,
Message::kNormalPriority));
}
// Canonicalize the uri with respect to the current isolate.
@ -1031,9 +1031,8 @@ DEFINE_NATIVE_ENTRY(Isolate_sendOOB, 0, 2) {
// Ensure message writer (and it's resources, e.g. forwarding tables) are
// cleaned up before handling interrupts.
{
MessageWriter writer(false);
PortMap::PostMessage(
writer.WriteMessage(msg, port.Id(), Message::kOOBPriority));
PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
port.Id(), Message::kOOBPriority));
}
// Drain interrupts before running so any IMMEDIATE operations on the current

View file

@ -6,6 +6,7 @@
#include "lib/invocation_mirror.h"
#include "vm/code_patcher.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/heap/heap.h"
#include "vm/native_entry.h"

View file

@ -11,6 +11,7 @@
#include "vm/kernel_isolate.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/port.h"
@ -59,10 +60,10 @@ DEFINE_NATIVE_ENTRY(VMService_SendIsolateServiceMessage, 0, 2) {
Smi::Handle(thread->zone(), Smi::New(Message::kServiceOOBMsg)));
// Serialize message.
MessageWriter writer(false);
// TODO(turnidge): Throw an exception when the return value is false?
bool result = PortMap::PostMessage(
writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
bool result = PortMap::PostMessage(WriteMessage(
/* can_send_any_object */ false, message, sp.Id(),
Message::kOOBPriority));
return Bool::Get(result).ptr();
#else
return Object::null();

View file

@ -24,7 +24,6 @@ void* ZoneAllocated::operator new(uword size) {
}
void* ZoneAllocated::operator new(uword size, Zone* zone) {
ASSERT(Thread::Current()->ZoneIsOwnedByThread(zone));
return Allocate(size, zone);
}

View file

@ -18,6 +18,7 @@
#include "vm/clustered_snapshot.h"
#include "vm/dart_api_impl.h"
#include "vm/datastream.h"
#include "vm/message_snapshot.h"
#include "vm/stack_frame.h"
#include "vm/timer.h"
@ -517,13 +518,12 @@ BENCHMARK(SerializeNull) {
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
MessageWriter writer(true);
std::unique_ptr<Message> message = writer.WriteMessage(
null_object, ILLEGAL_PORT, Message::kNormalPriority);
std::unique_ptr<Message> message =
WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
reader.ReadObject();
ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@ -540,13 +540,12 @@ BENCHMARK(SerializeSmi) {
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, smi_object, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
reader.ReadObject();
ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@ -565,13 +564,12 @@ BENCHMARK(SimpleMessage) {
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
MessageWriter writer(true);
std::unique_ptr<Message> message = writer.WriteMessage(
array_object, ILLEGAL_PORT, Message::kNormalPriority);
std::unique_ptr<Message> message = WriteMessage(
/* can_send_any_object */ true, array_object, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
reader.ReadObject();
ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@ -599,13 +597,12 @@ BENCHMARK(LargeMap) {
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, map, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
reader.ReadObject();
ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();

View file

@ -16,6 +16,7 @@
#include "vm/compiler/api/print_filter.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/dart.h"
#include "vm/dart_entry.h"
#include "vm/dispatch_table.h"
#include "vm/flag_list.h"
#include "vm/growable_array.h"

View file

@ -24,6 +24,7 @@
#include "vm/compiler/ffi/native_location.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/compiler/method_recognizer.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/native_entry.h"

View file

@ -8,6 +8,7 @@
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
#include "vm/allocation.h"
#include "vm/isolate.h"
#include "vm/snapshot.h"
namespace dart {

View file

@ -32,6 +32,7 @@
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
@ -2161,17 +2162,10 @@ DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
return false;
}
// Smis and null can be sent without serialization.
ObjectPtr raw_obj = Api::UnwrapHandle(handle);
if (ApiObjectConverter::CanConvert(raw_obj)) {
return PortMap::PostMessage(
Message::New(port_id, raw_obj, Message::kNormalPriority));
}
const Object& object = Object::Handle(Z, raw_obj);
MessageWriter writer(false);
return PortMap::PostMessage(
writer.WriteMessage(object, port_id, Message::kNormalPriority));
const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
object, port_id,
Message::kNormalPriority));
}
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {

File diff suppressed because it is too large Load diff

View file

@ -15,185 +15,6 @@
namespace dart {
// Use this C structure for reading internal objects in the serialized
// data. These are objects that we need to process in order to
// generate the Dart_CObject graph but that we don't want to expose in
// that graph.
struct Dart_CObject_Internal : public Dart_CObject {
enum Type {
kTypeArguments = Dart_CObject_kNumberOfTypes,
kDynamicType,
kClass,
kView,
kUninitialized,
};
struct Dart_CObject_Internal* cls;
union {
struct {
struct _Dart_CObject* library_url;
struct _Dart_CObject* class_name;
} as_class;
struct {
struct _Dart_CObject* buffer;
int offset_in_bytes;
int length;
} as_view;
} internal;
};
// Reads a message snapshot into a C structure.
class ApiMessageReader : public BaseReader {
public:
// The ApiMessageReader object must be enclosed by an ApiNativeScope.
// Allocation of all C Heap objects is done in the zone associated with
// the enclosing ApiNativeScope.
explicit ApiMessageReader(Message* message);
~ApiMessageReader();
Dart_CObject* ReadMessage();
private:
class BackRefNode {
public:
BackRefNode(Dart_CObject* reference, DeserializeState state)
: reference_(reference), state_(state) {}
Dart_CObject* reference() const { return reference_; }
void set_reference(Dart_CObject* reference) { reference_ = reference; }
bool is_deserialized() const { return state_ == kIsDeserialized; }
void set_state(DeserializeState value) { state_ = value; }
private:
Dart_CObject* reference_;
DeserializeState state_;
DISALLOW_COPY_AND_ASSIGN(BackRefNode);
};
// Allocates a Dart_CObject object.
Dart_CObject* AllocateDartCObject();
// Allocates a Dart_CObject object with the specified type.
Dart_CObject* AllocateDartCObject(Dart_CObject_Type type);
// Allocates a Dart_CObject object representing an unsupported
// object in the API message.
Dart_CObject* AllocateDartCObjectUnsupported();
// Allocates a Dart_CObject object for the null object.
Dart_CObject* AllocateDartCObjectNull();
// Allocates a Dart_CObject object for a boolean object.
Dart_CObject* AllocateDartCObjectBool(bool value);
// Allocates a Dart_CObject object for for a 32-bit integer.
Dart_CObject* AllocateDartCObjectInt32(int32_t value);
// Allocates a Dart_CObject object for for a 64-bit integer.
Dart_CObject* AllocateDartCObjectInt64(int64_t value);
// Allocates a Dart_CObject object for a double.
Dart_CObject* AllocateDartCObjectDouble(double value);
// Allocates a Dart_CObject object for string data.
Dart_CObject* AllocateDartCObjectString(intptr_t length);
// Allocates a C Dart_CObject object for a typed data.
Dart_CObject* AllocateDartCObjectTypedData(Dart_TypedData_Type type,
intptr_t length);
// Allocates a C array of Dart_CObject objects.
Dart_CObject* AllocateDartCObjectArray(intptr_t length);
// Allocate a C Dart_CObject object for a VM isolate object.
Dart_CObject* AllocateDartCObjectVmIsolateObj(intptr_t id);
// Allocates a Dart_CObject_Internal object with the specified type.
Dart_CObject_Internal* AllocateDartCObjectInternal(
Dart_CObject_Internal::Type type);
// Allocates a Dart_CObject_Internal object for a class object.
Dart_CObject_Internal* AllocateDartCObjectClass();
// Allocates a backwards reference node.
BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
void Init();
intptr_t LookupInternalClass(intptr_t class_header);
Dart_CObject* ReadVMIsolateObject(intptr_t value);
Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
Dart_CObject* ReadInlinedObject(intptr_t object_id);
Dart_CObject* ReadObjectImpl();
Dart_CObject* ReadIndexedObject(intptr_t object_id);
Dart_CObject* ReadPredefinedSymbol(intptr_t object_id);
Dart_CObject* ReadObjectRef();
Dart_CObject* ReadObject();
// Add object to backward references.
void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
// Get an object from the backward references list.
Dart_CObject* GetBackRef(intptr_t id);
intptr_t NextAvailableObjectId() const;
Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
ASSERT(object->type >= Dart_CObject_kNumberOfTypes);
return reinterpret_cast<Dart_CObject_Internal*>(object);
}
ObjectPtr VmIsolateSnapshotObject(intptr_t index) const {
return Object::vm_isolate_snapshot_object_table().At(index);
}
Dart_CObject* CreateDartCObjectString(ObjectPtr raw);
Dart_CObject* GetCanonicalMintObject(Dart_CObject_Type type, int64_t value64);
uint8_t* allocator(intptr_t size) {
return zone_->Realloc<uint8_t>(NULL, 0, size);
}
Zone* zone_; // Zone in which C heap objects are allocated.
ApiGrowableArray<BackRefNode*> backward_references_;
ApiGrowableArray<Dart_CObject*> vm_isolate_references_;
Dart_CObject** vm_symbol_references_;
Dart_CObject type_arguments_marker;
Dart_CObject dynamic_type_marker;
MessageFinalizableData* finalizable_data_;
};
class ApiMessageWriter : public BaseWriter {
public:
static const intptr_t kInitialSize = 512;
ApiMessageWriter();
~ApiMessageWriter();
// Writes a message with a single object.
std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
Dart_Port dest_port,
Message::Priority priority);
private:
static const intptr_t kDartCObjectTypeBits = 4;
static const intptr_t kDartCObjectTypeMask = (1 << kDartCObjectTypeBits) - 1;
static const intptr_t kDartCObjectMarkMask = ~kDartCObjectTypeMask;
static const intptr_t kDartCObjectMarkOffset = 1;
void MarkCObject(Dart_CObject* object, intptr_t object_id);
void UnmarkCObject(Dart_CObject* object);
bool IsCObjectMarked(Dart_CObject* object);
intptr_t GetMarkedCObjectMark(Dart_CObject* object);
void UnmarkAllCObjects(Dart_CObject* object);
void AddToForwardList(Dart_CObject* object);
void WriteSmi(int64_t value);
void WriteNullObject();
void WriteMint(Dart_CObject* object, int64_t value);
void WriteInt32(Dart_CObject* object);
void WriteInt64(Dart_CObject* object);
void WriteInlinedHeader(Dart_CObject* object);
bool WriteCObject(Dart_CObject* object);
bool WriteCObjectRef(Dart_CObject* object);
bool WriteForwardedCObject(Dart_CObject* object);
bool WriteCObjectInlined(Dart_CObject* object, Dart_CObject_Type type);
intptr_t object_id_;
Dart_CObject** forward_list_;
intptr_t forward_list_length_;
intptr_t forward_id_;
MessageFinalizableData* finalizable_data_;
DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
};
// This class handles translation of certain RawObjects to CObjects for
// NativeMessageHandlers.
//

View file

@ -180,8 +180,6 @@ class ArgumentsDescriptor : public ValueObject {
// A cache of VM heap allocated arguments descriptors.
static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount];
friend class SnapshotReader;
friend class SnapshotWriter;
friend class Serializer;
friend class Deserializer;
friend class Simulator;

View file

@ -100,6 +100,13 @@ class Handles {
return scoped_blocks_->AllocateHandle();
}
bool IsEmpty() const {
if (zone_blocks_ != nullptr) return false;
if (first_scoped_block_.HandleCount() != 0) return false;
if (scoped_blocks_ != &first_scoped_block_) return false;
return true;
}
protected:
// Returns a count of active handles (used for testing purposes).
int CountScopedHandles() const;

View file

@ -16,6 +16,7 @@
#include "vm/heap/become.h"
#include "vm/heap/heap.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object_graph.h"
#include "vm/port.h"
#include "vm/symbols.h"
@ -544,8 +545,7 @@ class SendAndExitMessagesHandler : public MessageHandler {
isolate()->group()->api_state()->FreePersistentHandle(handle);
} else {
Thread* thread = Thread::Current();
MessageSnapshotReader reader(message.get(), thread);
response_obj = reader.ReadObject();
response_obj = ReadMessage(thread, message.get());
}
if (response_obj.IsString()) {
String& response = String::Handle();

View file

@ -12,6 +12,7 @@
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/heap/spaces.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/raw_object.h"
#include "vm/ring_buffer.h"

View file

@ -30,7 +30,7 @@ intptr_t WeakTable::SizeFor(intptr_t count, intptr_t size) {
}
void WeakTable::SetValueExclusive(ObjectPtr key, intptr_t val) {
intptr_t mask = size() - 1;
const intptr_t mask = size() - 1;
intptr_t idx = Hash(key) & mask;
intptr_t empty_idx = -1;
ObjectPtr obj = ObjectAtExclusive(idx);
@ -74,6 +74,46 @@ void WeakTable::SetValueExclusive(ObjectPtr key, intptr_t val) {
}
}
bool WeakTable::MarkValueExclusive(ObjectPtr key, intptr_t val) {
const intptr_t mask = size() - 1;
intptr_t idx = Hash(key) & mask;
intptr_t empty_idx = -1;
ObjectPtr obj = ObjectAtExclusive(idx);
while (obj != static_cast<ObjectPtr>(kNoEntry)) {
if (obj == key) {
return false;
} else if ((empty_idx < 0) &&
(static_cast<intptr_t>(obj) == kDeletedEntry)) {
empty_idx = idx; // Insert at this location if not found.
}
idx = (idx + 1) & mask;
obj = ObjectAtExclusive(idx);
}
ASSERT(val != 0);
if (empty_idx >= 0) {
// We will be reusing a slot below.
set_used(used() - 1);
idx = empty_idx;
}
ASSERT(!IsValidEntryAtExclusive(idx));
// Set the key and value.
SetObjectAt(idx, key);
SetValueAt(idx, val);
// Update the counts.
set_used(used() + 1);
set_count(count() + 1);
// Rehash if needed to ensure that there are empty slots available.
if (used_ >= limit()) {
Rehash();
}
return true;
}
void WeakTable::Reset() {
intptr_t* old_data = data_;
used_ = 0;

View file

@ -104,6 +104,7 @@ class WeakTable {
}
void SetValueExclusive(ObjectPtr key, intptr_t val);
bool MarkValueExclusive(ObjectPtr key, intptr_t val);
intptr_t GetValueExclusive(ObjectPtr key) const {
intptr_t mask = size() - 1;
@ -203,7 +204,9 @@ class WeakTable {
void Rehash();
static uword Hash(ObjectPtr key) { return static_cast<uword>(key) * 92821; }
static uword Hash(ObjectPtr key) {
return (static_cast<uword>(key) * 92821) ^ (static_cast<uword>(key) >> 8);
}
Mutex mutex_;

View file

@ -31,6 +31,7 @@
#include "vm/lockers.h"
#include "vm/log.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
@ -123,18 +124,14 @@ class VerifyOriginId : public IsolateVisitor {
static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
const Instance& obj) {
if (ApiObjectConverter::CanConvert(obj.ptr())) {
return Message::New(dest_port, obj.ptr(), Message::kNormalPriority);
} else {
MessageWriter writer(false);
return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
}
return WriteMessage(/* can_send_any_object */ false, obj, dest_port,
Message::kNormalPriority);
}
static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
static std::unique_ptr<Message> SerializeMessage(Zone* zone,
Dart_Port dest_port,
Dart_CObject* obj) {
ApiMessageWriter writer;
return writer.WriteCMessage(obj, dest_port, Message::kNormalPriority);
return WriteApiMessage(zone, obj, dest_port, Message::kNormalPriority);
}
void IsolateGroupSource::add_loaded_blob(
@ -1008,9 +1005,8 @@ void Isolate::SendInternalLibMessage(LibMsgId msg_id, uint64_t capability) {
element = Capability::New(capability);
msg.SetAt(2, element);
MessageWriter writer(false);
PortMap::PostMessage(
writer.WriteMessage(msg, main_port(), Message::kOOBPriority));
PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
main_port(), Message::kOOBPriority));
}
void IsolateGroup::set_object_store(ObjectStore* object_store) {
@ -1330,11 +1326,7 @@ MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
// Parse the message.
Object& msg_obj = Object::Handle(zone);
if (message->IsRaw()) {
msg_obj = message->raw_obj();
// We should only be sending RawObjects that can be converted to CObjects.
ASSERT(ApiObjectConverter::CanConvert(msg_obj.ptr()));
} else if (message->IsPersistentHandle()) {
if (message->IsPersistentHandle()) {
// msg_array = [<message>, <object-in-message-to-rehash>]
const auto& msg_array = Array::Handle(
zone, Array::RawCast(message->persistent_handle()->ptr()));
@ -1348,8 +1340,7 @@ MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
}
}
} else {
MessageSnapshotReader reader(message.get(), thread);
msg_obj = reader.ReadObject();
msg_obj = ReadMessage(thread, message.get());
}
if (msg_obj.IsError()) {
// An error occurred while reading the message.
@ -2360,7 +2351,7 @@ bool Isolate::NotifyErrorListeners(const char* message,
listener ^= listeners.At(i);
if (!listener.IsNull()) {
Dart_Port port_id = listener.Id();
PortMap::PostMessage(SerializeMessage(port_id, &arr));
PortMap::PostMessage(SerializeMessage(current_zone(), port_id, &arr));
}
}
return listeners.Length() > 0;
@ -3297,9 +3288,9 @@ void Isolate::AppendServiceExtensionCall(const Instance& closure,
msg.SetAt(1, element);
element = Smi::New(Isolate::kBeforeNextEventAction);
msg.SetAt(2, element);
MessageWriter writer(false);
std::unique_ptr<Message> message =
writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
std::unique_ptr<Message> message = WriteMessage(
/* can_send_any_object */ false, msg, main_port(),
Message::kOOBPriority);
bool posted = PortMap::PostMessage(std::move(message));
ASSERT(posted);
}
@ -3543,9 +3534,9 @@ void Isolate::KillLocked(LibMsgId msg_id) {
list_values[3] = &imm;
{
ApiMessageWriter writer;
std::unique_ptr<Message> message =
writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
AllocOnlyStackZone zone;
std::unique_ptr<Message> message = WriteApiMessage(
zone.GetZone(), &kill_msg, main_port(), Message::kOOBPriority);
ASSERT(message != nullptr);
// Post the message at the given port.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
// Copyright (c) 2021, 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_SNAPSHOT_H_
#define RUNTIME_VM_MESSAGE_SNAPSHOT_H_
#include <memory>
#include "include/dart_native_api.h"
#include "vm/message.h"
#include "vm/object.h"
namespace dart {
std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
const Object& obj,
Dart_Port dest_port,
Message::Priority priority);
std::unique_ptr<Message> WriteApiMessage(Zone* zone,
Dart_CObject* obj,
Dart_Port dest_port,
Message::Priority priority);
ObjectPtr ReadMessage(Thread* thread, Message* message);
Dart_CObject* ReadApiMessage(Zone* zone, Message* message);
} // namespace dart
#endif // RUNTIME_VM_MESSAGE_SNAPSHOT_H_

View file

@ -12,6 +12,7 @@
#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/message.h"
#include "vm/message_snapshot.h"
#include "vm/native_message_handler.h"
#include "vm/port.h"
#include "vm/service_isolate.h"
@ -43,9 +44,9 @@ class IsolateLeaveScope {
};
static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
ApiMessageWriter writer;
std::unique_ptr<Message> msg =
writer.WriteCMessage(message, port_id, Message::kNormalPriority);
AllocOnlyStackZone zone;
std::unique_ptr<Message> msg = WriteApiMessage(
zone.GetZone(), message, port_id, Message::kNormalPriority);
if (msg == nullptr) {
return false;

View file

@ -9,6 +9,7 @@
#include "vm/dart_api_message.h"
#include "vm/isolate.h"
#include "vm/message.h"
#include "vm/message_snapshot.h"
#include "vm/snapshot.h"
namespace dart {
@ -37,9 +38,7 @@ MessageHandler::MessageStatus NativeMessageHandler::HandleMessage(
// All allocation of objects for decoding the message is done in the
// zone associated with this scope.
ApiNativeScope scope;
Dart_CObject* object;
ApiMessageReader reader(message.get());
object = reader.ReadMessage();
Dart_CObject* object = ReadApiMessage(scope.zone(), message.get());
(*func())(message->dest_port(), object);
return kOK;
}

View file

@ -11610,14 +11610,14 @@ bool Field::UpdateGuardedExactnessState(const Object& value) const {
void Field::RecordStore(const Object& value) const {
ASSERT(IsOriginal());
if (!IsolateGroup::Current()->use_field_guards()) {
Thread* const thread = Thread::Current();
if (!thread->isolate_group()->use_field_guards()) {
return;
}
// We should never try to record a sentinel.
ASSERT(value.ptr() != Object::sentinel().ptr());
Thread* const thread = Thread::Current();
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
if ((guarded_cid() == kDynamicCid) ||
(is_nullable() && value.ptr() == Object::null())) {

View file

@ -215,11 +215,9 @@ class BaseTextBuffer;
#define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
#endif // !PRODUCT
#define SNAPSHOT_READER_SUPPORT(object) \
static object##Ptr ReadFrom(SnapshotReader* reader, intptr_t object_id, \
intptr_t tags, Snapshot::Kind, \
bool as_reference); \
friend class SnapshotReader;
#define SNAPSHOT_SUPPORT(object) \
friend class object##MessageSerializationCluster; \
friend class object##MessageDeserializationCluster;
#define OBJECT_IMPLEMENTATION(object, super) \
public: /* NOLINT */ \
@ -243,7 +241,7 @@ class BaseTextBuffer;
ASSERT(ptr() != null()); \
return const_cast<Untagged##object*>(ptr()->untag()); \
} \
SNAPSHOT_READER_SUPPORT(object) \
SNAPSHOT_SUPPORT(object) \
friend class StackFrame; \
friend class Thread;
@ -268,7 +266,7 @@ class BaseTextBuffer;
return const_cast<Untagged##object*>(ptr()->untag()); \
} \
static intptr_t NextFieldOffset() { return -kWordSize; } \
SNAPSHOT_READER_SUPPORT(rettype) \
SNAPSHOT_SUPPORT(rettype) \
friend class Object; \
friend class StackFrame; \
friend class Thread;
@ -860,7 +858,6 @@ class Object {
friend void ClassTable::Register(const Class& cls);
friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
friend class Closure;
friend class SnapshotReader;
friend class InstanceDeserializationCluster;
friend class OneByteString;
friend class TwoByteString;
@ -2482,7 +2479,6 @@ class ICData : public CallSiteData {
friend class VMDeserializationRoots;
friend class ICDataTestTask;
friend class VMSerializationRoots;
friend class SnapshotWriter;
};
// Often used constants for number of free function type parameters.
@ -3805,7 +3801,6 @@ class Function : public Object {
FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
friend class Class;
friend class SnapshotWriter;
friend class Parser; // For set_eval_script.
// UntaggedFunction::VisitFunctionPointers accesses the private constructor of
// Function.
@ -3849,7 +3844,6 @@ class ClosureData : public Object {
FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
friend class Class;
friend class Function;
friend class HeapProfiler;
friend class Precompiler; // To wrap parent functions in WSRs.
};
@ -3890,7 +3884,6 @@ class FfiTrampolineData : public Object {
FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
friend class Class;
friend class Function;
friend class HeapProfiler;
};
class Field : public Object {
@ -4451,7 +4444,6 @@ class Field : public Object {
FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
friend class Class;
friend class HeapProfiler;
friend class UntaggedField;
friend class FieldSerializationCluster;
friend class FieldDeserializationCluster;
@ -6703,7 +6695,6 @@ class Code : public Object {
FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
friend class Class;
friend class CodeTestHelper;
friend class SnapshotWriter;
friend class StubCode; // for set_object_pool
friend class Precompiler; // for set_object_pool
friend class FunctionSerializationCluster;
@ -7495,7 +7486,6 @@ class Instance : public Object {
friend class Pointer;
friend class DeferredObject;
friend class RegExp;
friend class SnapshotWriter;
friend class StubCode;
friend class TypedDataView;
friend class InstanceSerializationCluster;
@ -9079,6 +9069,7 @@ class Mint : public Integer {
protected:
// Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
friend class Integer;
friend class MintMessageDeserializationCluster;
static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
@ -9489,14 +9480,6 @@ class String : public Instance {
ASSERT(hash_set == value);
}
template <typename HandleType, typename ElementType, typename CallbackType>
static void ReadFromImpl(SnapshotReader* reader,
String* str_obj,
intptr_t len,
intptr_t tags,
CallbackType new_symbol,
Snapshot::Kind kind);
FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
friend class Class;
@ -9666,20 +9649,14 @@ class OneByteString : public AllStatic {
return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
}
static OneByteStringPtr ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference);
friend class Class;
friend class ExternalOneByteString;
friend class ImageWriter;
friend class SnapshotReader;
friend class String;
friend class StringHasher;
friend class Symbols;
friend class Utf8;
friend class OneByteStringMessageSerializationCluster;
};
class TwoByteString : public AllStatic {
@ -9792,18 +9769,12 @@ class TwoByteString : public AllStatic {
return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
}
static TwoByteStringPtr ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference);
friend class Class;
friend class ImageWriter;
friend class SnapshotReader;
friend class String;
friend class StringHasher;
friend class Symbols;
friend class TwoByteStringMessageSerializationCluster;
};
class ExternalOneByteString : public AllStatic {
@ -9887,12 +9858,6 @@ class ExternalOneByteString : public AllStatic {
Dart_WeakPersistentHandle handle,
void* peer);
static ExternalOneByteStringPtr ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference);
static intptr_t NextFieldOffset() {
// Indicates this class cannot be extended by dart code.
return -kWordSize;
@ -9901,7 +9866,6 @@ class ExternalOneByteString : public AllStatic {
friend class Class;
friend class String;
friend class StringHasher;
friend class SnapshotReader;
friend class Symbols;
friend class Utf8;
};
@ -9983,12 +9947,6 @@ class ExternalTwoByteString : public AllStatic {
Dart_WeakPersistentHandle handle,
void* peer);
static ExternalTwoByteStringPtr ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference);
static intptr_t NextFieldOffset() {
// Indicates this class cannot be extended by dart code.
return -kWordSize;
@ -9997,7 +9955,6 @@ class ExternalTwoByteString : public AllStatic {
friend class Class;
friend class String;
friend class StringHasher;
friend class SnapshotReader;
friend class Symbols;
};
@ -10233,6 +10190,7 @@ class Array : public Instance {
friend class ImmutableArray;
friend class Object;
friend class String;
friend class MessageDeserializer;
};
class ImmutableArray : public AllStatic {
@ -10243,12 +10201,6 @@ class ImmutableArray : public AllStatic {
static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
static ImmutableArrayPtr ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind,
bool as_reference);
static const ClassId kClassId = kImmutableArrayCid;
static intptr_t InstanceSize() { return Array::InstanceSize(); }

View file

@ -6,6 +6,7 @@
#include "platform/unaligned.h"
#include "vm/code_patcher.h"
#include "vm/dart_entry.h"
#include "vm/hash_table.h"
#include "vm/isolate_reload.h"
#include "vm/log.h"

View file

@ -307,6 +307,10 @@ void ObjectStore::InitKnownObjects() {
ASSERT(!cls.IsNull());
set_error_class(cls);
cls = core_lib.LookupClassAllowPrivate(Symbols::Expando());
ASSERT(!cls.IsNull());
set_expando_class(cls);
// Cache the core private functions used for fast instance of checks.
simple_instance_of_function_ =
PrivateObjectLookup(Symbols::_simpleInstanceOf());

View file

@ -141,6 +141,7 @@ class ObjectPointerVisitor;
RW(Class, int32x4_class) \
RW(Class, float64x2_class) \
RW(Class, error_class) \
RW(Class, expando_class) \
RW(Class, weak_property_class) \
ARW_AR(Array, symbol_table) \
RW(Array, canonical_types) \
@ -535,7 +536,6 @@ class ObjectStore {
case Snapshot::kFullJIT:
case Snapshot::kFullAOT:
return reinterpret_cast<ObjectPtr*>(&slow_tts_stub_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;

View file

@ -18,8 +18,10 @@
#include "vm/pointer_tagging.h"
#include "vm/snapshot.h"
#include "vm/tagged_pointer.h"
#include "vm/thread.h"
#include "vm/token.h"
#include "vm/token_position.h"
#include "vm/visitor.h"
// Currently we have two different axes for offset generation:
//
@ -118,17 +120,10 @@ enum TypedDataElementType {
#undef V
};
#define SNAPSHOT_WRITER_SUPPORT() \
void WriteTo(SnapshotWriter* writer, intptr_t object_id, \
Snapshot::Kind kind, bool as_reference); \
friend class SnapshotWriter;
#define VISITOR_SUPPORT(object) \
static intptr_t Visit##object##Pointers(object##Ptr raw_obj, \
ObjectPointerVisitor* visitor);
#define HEAP_PROFILER_SUPPORT() friend class HeapProfiler;
#define RAW_OBJECT_IMPLEMENTATION(object) \
private: /* NOLINT */ \
VISITOR_SUPPORT(object) \
@ -144,10 +139,10 @@ enum TypedDataElementType {
#define RAW_HEAP_OBJECT_IMPLEMENTATION(object) \
private: \
RAW_OBJECT_IMPLEMENTATION(object); \
SNAPSHOT_WRITER_SUPPORT() \
HEAP_PROFILER_SUPPORT() \
friend class object##SerializationCluster; \
friend class object##DeserializationCluster; \
friend class object##MessageSerializationCluster; \
friend class object##MessageDeserializationCluster; \
friend class Serializer; \
friend class Deserializer; \
template <typename Base> \
@ -547,6 +542,8 @@ class UntaggedObject {
}
}
friend class MessageDeserializer; // bogus
template <typename type,
typename compressed_type,
std::memory_order order = std::memory_order_relaxed>
@ -760,9 +757,7 @@ class UntaggedObject {
friend class ImageWriter;
friend class AssemblyImageWriter;
friend class BlobImageWriter;
friend class SnapshotReader;
friend class Deserializer;
friend class SnapshotWriter;
friend class String;
friend class WeakProperty; // StorePointer
friend class Instance; // StorePointer
@ -840,8 +835,8 @@ inline intptr_t ObjectPtr::GetClassId() const {
} \
template <std::memory_order order = std::memory_order_relaxed> \
void set_##name(type value) { \
StoreArrayPointer<Compressed##type, order>(&name##_, \
Compressed##type(value)); \
StoreCompressedArrayPointer<type, Compressed##type, order>(&name##_, \
value); \
} \
\
protected: \
@ -1015,7 +1010,6 @@ class UntaggedClass : public UntaggedObject {
#if !defined(DART_PRECOMPILED_RUNTIME)
return reinterpret_cast<CompressedObjectPtr*>(&dependent_code_);
#endif
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1062,7 +1056,7 @@ class UntaggedClass : public UntaggedObject {
friend class UntaggedInstance;
friend class UntaggedInstructions;
friend class UntaggedTypeArguments;
friend class SnapshotReader;
friend class MessageSerializer;
friend class InstanceSerializationCluster;
friend class TypeSerializationCluster;
friend class CidRewriteVisitor;
@ -1088,7 +1082,6 @@ class UntaggedPatchClass : public UntaggedObject {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&library_kernel_data_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1272,7 +1265,6 @@ class UntaggedFunction : public UntaggedObject {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&data_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1417,7 +1409,6 @@ class UntaggedField : public UntaggedObject {
case Snapshot::kFullJIT:
case Snapshot::kFullAOT:
return reinterpret_cast<CompressedObjectPtr*>(&initializer_function_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1491,7 +1482,6 @@ class alignas(8) UntaggedScript : public UntaggedObject {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&kernel_program_info_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1583,7 +1573,6 @@ class UntaggedLibrary : public UntaggedObject {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&kernel_data_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -1636,7 +1625,6 @@ class UntaggedNamespace : public UntaggedObject {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&owner_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -2191,7 +2179,6 @@ class UntaggedContext : public UntaggedObject {
VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
friend class Object;
friend class SnapshotReader;
};
class UntaggedContextScope : public UntaggedObject {
@ -2267,7 +2254,6 @@ class UntaggedContextScope : public UntaggedObject {
friend class Object;
friend class UntaggedClosureData;
friend class SnapshotReader;
};
class UntaggedSentinel : public UntaggedObject {
@ -2333,7 +2319,6 @@ class UntaggedICData : public UntaggedCallSiteData {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return to();
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -2428,7 +2413,6 @@ class UntaggedUnwindError : public UntaggedError {
class UntaggedInstance : public UntaggedObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
friend class Object;
friend class SnapshotReader;
public:
#if defined(DART_COMPRESSED_POINTERS)
@ -2457,7 +2441,6 @@ class UntaggedLibraryPrefix : public UntaggedInstance {
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&importer_);
case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@ -2484,7 +2467,6 @@ class UntaggedTypeArguments : public UntaggedInstance {
COMPRESSED_VARIABLE_POINTER_FIELDS(AbstractTypePtr, element, types)
friend class Object;
friend class SnapshotReader;
};
class UntaggedTypeParameters : public UntaggedObject {
@ -2503,7 +2485,6 @@ class UntaggedTypeParameters : public UntaggedObject {
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Object;
friend class SnapshotReader;
};
class UntaggedAbstractType : public UntaggedInstance {
@ -2715,7 +2696,6 @@ class UntaggedMint : public UntaggedInteger {
friend class Api;
friend class Class;
friend class Integer;
friend class SnapshotReader;
};
COMPILE_ASSERT(sizeof(UntaggedMint) == 16);
@ -2726,7 +2706,6 @@ class UntaggedDouble : public UntaggedNumber {
ALIGN8 double value_;
friend class Api;
friend class SnapshotReader;
friend class Class;
};
COMPILE_ASSERT(sizeof(UntaggedDouble) == 16);
@ -2762,9 +2741,7 @@ class UntaggedOneByteString : public UntaggedString {
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
friend class ApiMessageReader;
friend class RODataSerializationCluster;
friend class SnapshotReader;
friend class String;
};
@ -2777,7 +2754,6 @@ class UntaggedTwoByteString : public UntaggedString {
const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
friend class RODataSerializationCluster;
friend class SnapshotReader;
friend class String;
};
@ -2861,7 +2837,6 @@ class UntaggedTypedData : public UntaggedTypedDataBase {
friend class ObjectPoolDeserializationCluster;
friend class ObjectPoolSerializationCluster;
friend class UntaggedObjectPool;
friend class SnapshotReader;
};
// All _*ArrayView/_ByteDataView classes share the same layout.
@ -2925,7 +2900,6 @@ class UntaggedTypedDataView : public UntaggedTypedDataBase {
friend class GCCompactor;
template <bool>
friend class ScavengerVisitorBase;
friend class SnapshotReader;
};
class UntaggedExternalOneByteString : public UntaggedString {
@ -2971,7 +2945,6 @@ class UntaggedArray : public UntaggedInstance {
friend class Deserializer;
friend class UntaggedCode;
friend class UntaggedImmutableArray;
friend class SnapshotReader;
friend class GrowableObjectArray;
friend class LinkedHashMap;
friend class UntaggedLinkedHashMap;
@ -2988,8 +2961,6 @@ class UntaggedArray : public UntaggedInstance {
class UntaggedImmutableArray : public UntaggedArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
friend class SnapshotReader;
};
class UntaggedGrowableObjectArray : public UntaggedInstance {
@ -3002,7 +2973,6 @@ class UntaggedGrowableObjectArray : public UntaggedInstance {
VISIT_TO(data)
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class SnapshotReader;
friend class ReversePc;
};
@ -3026,14 +2996,10 @@ class UntaggedLinkedHashBase : public UntaggedInstance {
class UntaggedLinkedHashMap : public UntaggedLinkedHashBase {
RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
friend class SnapshotReader;
};
class UntaggedLinkedHashSet : public UntaggedLinkedHashBase {
RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet);
friend class SnapshotReader;
};
class UntaggedFloat32x4 : public UntaggedInstance {
@ -3042,7 +3008,6 @@ class UntaggedFloat32x4 : public UntaggedInstance {
ALIGN8 float value_[4];
friend class SnapshotReader;
friend class Class;
public:
@ -3059,7 +3024,6 @@ class UntaggedInt32x4 : public UntaggedInstance {
ALIGN8 int32_t value_[4];
friend class SnapshotReader;
public:
int32_t x() const { return value_[0]; }
@ -3075,7 +3039,6 @@ class UntaggedFloat64x2 : public UntaggedInstance {
ALIGN8 double value_[2];
friend class SnapshotReader;
friend class Class;
public:
@ -3264,7 +3227,6 @@ class UntaggedUserTag : public UntaggedInstance {
// Isolate unique tag.
uword tag_;
friend class SnapshotReader;
friend class Object;
public:
@ -3277,8 +3239,6 @@ class UntaggedFutureOr : public UntaggedInstance {
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
VISIT_FROM(type_arguments)
VISIT_TO(type_arguments)
friend class SnapshotReader;
};
#undef WSR_COMPRESSED_POINTER_FIELD

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,7 @@
#include "vm/malloc_hooks.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
@ -1018,9 +1019,9 @@ void Service::SendEvent(const char* stream_id,
message.value.as_array.length = 2;
message.value.as_array.values = elements;
ApiMessageWriter writer;
std::unique_ptr<Message> msg = writer.WriteCMessage(
&message, ServiceIsolate::Port(), Message::kNormalPriority);
std::unique_ptr<Message> msg =
WriteApiMessage(thread->zone(), &message, ServiceIsolate::Port(),
Message::kNormalPriority);
if (msg == nullptr) {
result = false;
} else {
@ -1188,9 +1189,10 @@ void Service::PostEvent(Isolate* isolate,
json_cobj.value.as_string = const_cast<char*>(event->ToCString());
list_values[1] = &json_cobj;
ApiMessageWriter writer;
std::unique_ptr<Message> msg = writer.WriteCMessage(
&list_cobj, ServiceIsolate::Port(), Message::kNormalPriority);
AllocOnlyStackZone zone;
std::unique_ptr<Message> msg =
WriteApiMessage(zone.GetZone(), &list_cobj, ServiceIsolate::Port(),
Message::kNormalPriority);
if (msg != nullptr) {
PortMap::PostMessage(std::move(msg));
}
@ -2017,8 +2019,7 @@ static ObjectPtr LookupHeapObjectMessage(Thread* thread,
if (message->IsRaw()) {
return message->raw_obj();
} else {
MessageSnapshotReader reader(message, thread);
return reader.ReadObject();
return ReadMessage(thread, message);
}
}

View file

@ -12,6 +12,7 @@
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
@ -91,9 +92,8 @@ void ServiceIsolate::RequestServerInfo(const SendPort& sp) {
sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
Bool::Handle() /* ignored */));
ASSERT(!message.IsNull());
MessageWriter writer(false);
PortMap::PostMessage(
writer.WriteMessage(message, port_, Message::kNormalPriority));
PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
port_, Message::kNormalPriority));
}
void ServiceIsolate::ControlWebServer(const SendPort& sp,
@ -102,9 +102,8 @@ void ServiceIsolate::ControlWebServer(const SendPort& sp,
const Array& message = Array::Handle(MakeServerControlMessage(
sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
ASSERT(!message.IsNull());
MessageWriter writer(false);
PortMap::PostMessage(
writer.WriteMessage(message, port_, Message::kNormalPriority));
PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
port_, Message::kNormalPriority));
}
void ServiceIsolate::SetServerAddress(const char* address) {
@ -223,14 +222,13 @@ bool ServiceIsolate::SendIsolateStartupMessage() {
const Array& list = Array::Handle(MakeServiceControlMessage(
Dart_GetMainPortId(), VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, name));
ASSERT(!list.IsNull());
MessageWriter writer(false);
if (FLAG_trace_service) {
OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
" registered.\n",
name.ToCString(), Dart_GetMainPortId());
}
return PortMap::PostMessage(
writer.WriteMessage(list, port_, Message::kNormalPriority));
return PortMap::PostMessage(WriteMessage(
/* can_send_any_object */ false, list, port_, Message::kNormalPriority));
}
bool ServiceIsolate::SendIsolateShutdownMessage() {
@ -249,14 +247,13 @@ bool ServiceIsolate::SendIsolateShutdownMessage() {
const Array& list = Array::Handle(MakeServiceControlMessage(
Dart_GetMainPortId(), VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, name));
ASSERT(!list.IsNull());
MessageWriter writer(false);
if (FLAG_trace_service) {
OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
" deregistered.\n",
name.ToCString(), Dart_GetMainPortId());
}
return PortMap::PostMessage(
writer.WriteMessage(list, port_, Message::kNormalPriority));
return PortMap::PostMessage(WriteMessage(
/* can_send_any_object */ false, list, port_, Message::kNormalPriority));
}
void ServiceIsolate::SendServiceExitMessage() {
@ -278,9 +275,9 @@ void ServiceIsolate::SendServiceExitMessage() {
message.value.as_array.length = 1;
message.value.as_array.values = values;
ApiMessageWriter writer;
PortMap::PostMessage(
writer.WriteCMessage(&message, port_, Message::kNormalPriority));
AllocOnlyStackZone zone;
PortMap::PostMessage(WriteApiMessage(zone.GetZone(), &message, port_,
Message::kNormalPriority));
}
void ServiceIsolate::SetServicePort(Dart_Port port) {

View file

@ -14,6 +14,7 @@
#include "vm/globals.h"
#include "vm/heap/safepoint.h"
#include "vm/message_handler.h"
#include "vm/message_snapshot.h"
#include "vm/object_id_ring.h"
#include "vm/os.h"
#include "vm/port.h"
@ -50,8 +51,7 @@ class ServiceTestMessageHandler : public MessageHandler {
response_obj = message->raw_obj();
} else {
Thread* thread = Thread::Current();
MessageSnapshotReader reader(message.get(), thread);
response_obj = reader.ReadObject();
response_obj = ReadMessage(thread, message.get());
}
if (response_obj.IsString()) {
String& response = String::Handle();

File diff suppressed because it is too large Load diff

View file

@ -9,83 +9,14 @@
#include <utility>
#include "platform/assert.h"
#include "platform/unaligned.h"
#include "vm/allocation.h"
#include "vm/bitfield.h"
#include "vm/datastream.h"
#include "vm/finalizable_data.h"
#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/message.h"
#include "vm/visitor.h"
#include "vm/thread.h"
namespace dart {
// Forward declarations.
class AbstractType;
class Array;
class Class;
class ClassTable;
class Closure;
class Code;
class ExternalTypedData;
class TypedDataBase;
class GrowableObjectArray;
class Heap;
class Instance;
class Instructions;
class LanguageError;
class Library;
class LinkedHashMap;
class Object;
class PassiveObject;
class ObjectStore;
class MegamorphicCache;
class PageSpace;
class TypedDataView;
class String;
class TypeArguments;
class TypedData;
class UnhandledException;
// Serialized object header encoding is as follows:
// - Smi: the Smi value is written as is (last bit is not tagged).
// - VM object (from VM isolate): (object id in vm isolate | 0x3)
// This value is serialized as a negative number.
// (note VM objects are never serialized, they are expected to be found
// using ths unique ID assigned to them).
// - Reference to object that has already been written: (object id | 0x3)
// This valus is serialized as a positive number.
// - Object that is seen for the first time (inlined in the stream):
// (a unique id for this object | 0x1)
enum SerializedHeaderType {
kInlined = 0x1,
kObjectId = 0x3,
};
static const int8_t kHeaderTagBits = 2;
static const int8_t kObjectIdBits = (kBitsPerInt32 - (kHeaderTagBits + 1));
static const intptr_t kMaxObjectId = (kMaxUint32 >> (kHeaderTagBits + 1));
static const bool kAsReference = true;
static const bool kAsInlinedObject = false;
static const intptr_t kInvalidPatchIndex = -1;
class SerializedHeaderTag
: public BitField<intptr_t, enum SerializedHeaderType, 0, kHeaderTagBits> {
};
class SerializedHeaderData
: public BitField<intptr_t, intptr_t, kHeaderTagBits, kObjectIdBits> {};
enum DeserializeState {
kIsDeserialized = 0,
kIsNotDeserialized = 1,
};
enum SerializeState {
kIsSerialized = 0,
kIsNotSerialized = 1,
};
// Structure capturing the raw snapshot.
//
class Snapshot {
@ -95,7 +26,6 @@ class Snapshot {
kFullCore, // Full snapshot of core libraries. Agnostic to null safety.
kFullJIT, // Full + JIT code
kFullAOT, // Full + AOT code
kMessage, // A partial snapshot used only for isolate messaging.
kNone, // gen_snapshot
kInvalid
};
@ -185,555 +115,6 @@ inline static bool IsSnapshotCompatible(Snapshot::Kind vm_kind,
return Snapshot::IsFull(isolate_kind);
}
class BaseReader {
public:
BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
// Reads raw data (for basic types).
// sizeof(T) must be in {1,2,4,8}.
template <typename T>
T Read() {
return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
}
classid_t ReadClassIDValue() {
uint32_t value = Read<uint32_t>();
return static_cast<classid_t>(value);
}
COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
double ReadDouble() {
double result;
stream_.ReadBytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
return result;
}
intptr_t ReadTags() {
const intptr_t tags = static_cast<intptr_t>(Read<int8_t>()) & 0xff;
return tags;
}
const uint8_t* CurrentBufferAddress() const {
return stream_.AddressOfCurrentPosition();
}
void Align(intptr_t value) { stream_.Align(value); }
void Advance(intptr_t value) { stream_.Advance(value); }
intptr_t PendingBytes() const { return stream_.PendingBytes(); }
SmiPtr ReadAsSmi();
intptr_t ReadSmiValue();
// Negative header value indicates VM isolate object id.
bool IsVMIsolateObject(intptr_t header_value) { return (header_value < 0); }
intptr_t GetVMIsolateObjectId(intptr_t header_val) {
ASSERT(IsVMIsolateObject(header_val));
intptr_t value = -header_val; // Header is negative for VM isolate objects.
ASSERT(SerializedHeaderTag::decode(value) == kObjectId);
return SerializedHeaderData::decode(value);
}
uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
private:
ReadStream stream_; // input stream.
};
class BackRefNode : public ValueObject {
public:
BackRefNode(Object* reference, DeserializeState state)
: reference_(reference), state_(state) {}
Object* reference() const { return reference_; }
bool is_deserialized() const { return state_ == kIsDeserialized; }
void set_state(DeserializeState state) { state_ = state; }
BackRefNode& operator=(const BackRefNode& other) {
reference_ = other.reference_;
state_ = other.state_;
return *this;
}
private:
Object* reference_;
DeserializeState state_;
};
// Reads a snapshot into objects.
class SnapshotReader : public BaseReader {
public:
Thread* thread() const { return thread_; }
Zone* zone() const { return zone_; }
Isolate* isolate() const { return thread_->isolate(); }
IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
Heap* heap() const { return heap_; }
ObjectStore* object_store() const { return isolate_group()->object_store(); }
ClassTable* class_table() const { return isolate_group()->class_table(); }
PassiveObject* PassiveObjectHandle() { return &pobj_; }
Array* ArrayHandle() { return &array_; }
Class* ClassHandle() { return &cls_; }
Code* CodeHandle() { return &code_; }
Instance* InstanceHandle() { return &instance_; }
Instructions* InstructionsHandle() { return &instructions_; }
String* StringHandle() { return &str_; }
AbstractType* TypeHandle() { return &type_; }
TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
GrowableObjectArray* TokensHandle() { return &tokens_; }
ExternalTypedData* DataHandle() { return &data_; }
TypedDataBase* TypedDataBaseHandle() { return &typed_data_base_; }
TypedData* TypedDataHandle() { return &typed_data_; }
TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
Function* FunctionHandle() { return &function_; }
Smi* SmiHandle() { return &smi_; }
Snapshot::Kind kind() const { return kind_; }
// Reads an object.
ObjectPtr ReadObject();
// Add object to backward references.
void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
// Get an object from the backward references list.
Object* GetBackRef(intptr_t id);
// Read version number of snapshot and verify.
ApiErrorPtr VerifyVersionAndFeatures(IsolateGroup* isolate_group);
ObjectPtr NewInteger(int64_t value);
protected:
SnapshotReader(const uint8_t* buffer,
intptr_t size,
Snapshot::Kind kind,
ZoneGrowableArray<BackRefNode>* backward_references,
Thread* thread);
~SnapshotReader() {}
ZoneGrowableArray<BackRefNode>* GetBackwardReferenceTable() const {
return backward_references_;
}
void ResetBackwardReferenceTable() { backward_references_ = NULL; }
PageSpace* old_space() const { return old_space_; }
private:
void EnqueueTypePostprocessing(const AbstractType& type);
void RunDelayedTypePostprocessing();
void EnqueueRehashingOfMap(const LinkedHashMap& map);
void EnqueueRehashingOfSet(const LinkedHashSet& set);
ObjectPtr RunDelayedRehashingOfMapsAndSets();
ClassPtr ReadClassId(intptr_t object_id);
ObjectPtr ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
// Implementation to read an object.
ObjectPtr ReadObjectImpl(bool as_reference);
ObjectPtr ReadObjectImpl(intptr_t header, bool as_reference);
// Read a Dart Instance object.
ObjectPtr ReadInstance(intptr_t object_id, intptr_t tags, bool as_reference);
// Read a VM isolate object that was serialized as an Id.
ObjectPtr ReadVMIsolateObject(intptr_t object_id);
// Read an object that was serialized as an Id (singleton in object store,
// or an object that was already serialized before).
ObjectPtr ReadIndexedObject(intptr_t object_id);
// Decode class id from the header field.
intptr_t LookupInternalClass(intptr_t class_header);
void ArrayReadFrom(intptr_t object_id,
const Array& result,
intptr_t len,
intptr_t tags);
void MapReadFrom(intptr_t object_id,
const LinkedHashMap& result,
intptr_t tags);
void SetReadFrom(intptr_t object_id,
const LinkedHashSet& result,
intptr_t tags);
intptr_t NextAvailableObjectId() const;
void SetReadException(const char* msg);
ObjectPtr VmIsolateSnapshotObject(intptr_t index) const;
bool is_vm_isolate() const;
Snapshot::Kind kind_; // Indicates type of the snapshot.
Thread* thread_; // Current thread.
Zone* zone_; // Zone for allocations while reading.
Heap* heap_; // Heap of the current isolate.
PageSpace* old_space_; // Old space of the current isolate.
Class& cls_; // Temporary Class handle.
Code& code_; // Temporary Code handle.
Instance& instance_; // Temporary Instance handle
Instructions& instructions_; // Temporary Instructions handle
Object& obj_; // Temporary Object handle.
PassiveObject& pobj_; // Temporary PassiveObject handle.
Array& array_; // Temporary Array handle.
Field& field_; // Temporary Field handle.
String& str_; // Temporary String handle.
Library& library_; // Temporary library handle.
AbstractType& type_; // Temporary type handle.
TypeArguments& type_arguments_; // Temporary type argument handle.
GrowableObjectArray& tokens_; // Temporary tokens handle.
ExternalTypedData& data_; // Temporary stream data handle.
TypedDataBase& typed_data_base_; // Temporary typed data base handle.
TypedData& typed_data_; // Temporary typed data handle.
TypedDataView& typed_data_view_; // Temporary typed data view handle.
Function& function_; // Temporary function handle.
Smi& smi_; // Temporary Smi handle.
UnhandledException& error_; // Error handle.
const Class& set_class_; // The LinkedHashSet class.
intptr_t max_vm_isolate_object_id_;
ZoneGrowableArray<BackRefNode>* backward_references_;
GrowableObjectArray& types_to_postprocess_;
GrowableObjectArray& objects_to_rehash_;
friend class ApiError;
friend class Array;
friend class Class;
friend class Closure;
friend class ClosureData;
friend class Context;
friend class ContextScope;
friend class ExceptionHandlers;
friend class Field;
friend class Function;
friend class GrowableObjectArray;
friend class ICData;
friend class ImmutableArray;
friend class KernelProgramInfo;
friend class LanguageError;
friend class Library;
friend class LibraryPrefix;
friend class LinkedHashMap;
friend class LinkedHashSet;
friend class MirrorReference;
friend class Namespace;
friend class PatchClass;
friend class RegExp;
friend class Script;
friend class SubtypeTestCache;
friend class TransferableTypedData;
friend class Type;
friend class FunctionType;
friend class TypedDataView;
friend class TypeParameters;
friend class TypeArguments;
friend class TypeParameter;
friend class TypeRef;
friend class UnhandledException;
friend class WeakProperty;
friend class WeakSerializationReference;
DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
};
class MessageSnapshotReader : public SnapshotReader {
public:
MessageSnapshotReader(Message* message, Thread* thread);
~MessageSnapshotReader();
MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
private:
MessageFinalizableData* finalizable_data_;
DISALLOW_COPY_AND_ASSIGN(MessageSnapshotReader);
};
class BaseWriter : public StackResource {
public:
uint8_t* Steal(intptr_t* length) { return stream_.Steal(length); }
intptr_t BytesWritten() const { return stream_.bytes_written(); }
// Writes raw data to the stream (basic type).
// sizeof(T) must be in {1,2,4,8}.
template <typename T>
void Write(T value) {
MallocWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
}
void WriteClassIDValue(classid_t value) { Write<uint32_t>(value); }
COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
// Write an object that is serialized as an Id (singleton in object store,
// or an object that was already serialized before).
void WriteIndexedObject(intptr_t object_id) {
ASSERT(object_id <= kMaxObjectId);
intptr_t value = 0;
value = SerializedHeaderTag::update(kObjectId, value);
value = SerializedHeaderData::update(object_id, value);
Write<int32_t>(value);
}
// Write a VM Isolateobject that is serialized as an Id.
void WriteVMIsolateObject(intptr_t object_id) {
ASSERT(object_id <= kMaxObjectId);
intptr_t value = 0;
value = SerializedHeaderTag::update(kObjectId, value);
value = SerializedHeaderData::update(object_id, value);
Write<int32_t>(-value); // Write as a negative value.
}
// Write serialization header information for an object.
void WriteInlinedObjectHeader(intptr_t id) {
ASSERT(id <= kMaxObjectId);
intptr_t value = 0;
value = SerializedHeaderTag::update(kInlined, value);
value = SerializedHeaderData::update(id, value);
Write<int32_t>(value);
}
void WriteTags(intptr_t tags) {
const intptr_t flags = tags & 0xff;
Write<int8_t>(static_cast<int8_t>(flags));
}
void Align(intptr_t value) { stream_.Align(value); }
// Write out a buffer of bytes.
void WriteBytes(const uint8_t* addr, intptr_t len) {
stream_.WriteBytes(addr, len);
}
void WriteDouble(double value) {
stream_.WriteBytes(reinterpret_cast<const uint8_t*>(&value), sizeof(value));
}
void WriteWordWith32BitWrites(uword value) {
stream_.WriteWordWith32BitWrites(value);
}
protected:
explicit BaseWriter(intptr_t initial_size)
: StackResource(Thread::Current()), stream_(initial_size) {}
~BaseWriter() {}
void ReserveHeader() {
// Make room for recording snapshot buffer size.
stream_.SetPosition(Snapshot::kHeaderSize);
}
void FillHeader(Snapshot::Kind kind) {
intptr_t length;
Snapshot* header = reinterpret_cast<Snapshot*>(Steal(&length));
header->set_magic();
header->set_length(length);
header->set_kind(kind);
}
void FreeBuffer() {
intptr_t unused;
free(Steal(&unused));
}
private:
MallocWriteStream stream_;
DISALLOW_IMPLICIT_CONSTRUCTORS(BaseWriter);
};
class ForwardList {
public:
explicit ForwardList(Thread* thread, intptr_t first_object_id);
~ForwardList();
class Node : public ZoneAllocated {
public:
Node(const Object* obj, SerializeState state) : obj_(obj), state_(state) {}
const Object* obj() const { return obj_; }
bool is_serialized() const { return state_ == kIsSerialized; }
private:
// Private to ensure the invariant of first_unprocessed_object_id_.
void set_state(SerializeState value) { state_ = value; }
const Object* obj_;
SerializeState state_;
friend class ForwardList;
DISALLOW_COPY_AND_ASSIGN(Node);
};
Node* NodeForObjectId(intptr_t object_id) const {
return nodes_[object_id - first_object_id_];
}
// Returns the id for the added object.
intptr_t AddObject(Zone* zone, ObjectPtr raw, SerializeState state);
// Returns the id for the object it it exists in the list.
intptr_t FindObject(ObjectPtr raw);
// Exhaustively processes all unserialized objects in this list. 'writer' may
// concurrently add more objects.
void SerializeAll(ObjectVisitor* writer);
// Set state of object in forward list.
void SetState(intptr_t object_id, SerializeState state) {
NodeForObjectId(object_id)->set_state(state);
}
private:
intptr_t first_object_id() const { return first_object_id_; }
intptr_t next_object_id() const { return nodes_.length() + first_object_id_; }
Isolate* isolate() const { return thread_->isolate(); }
Thread* thread_;
const intptr_t first_object_id_;
GrowableArray<Node*> nodes_;
intptr_t first_unprocessed_object_id_;
void SetObjectId(ObjectPtr object, intptr_t id);
intptr_t GetObjectId(ObjectPtr object);
DISALLOW_COPY_AND_ASSIGN(ForwardList);
};
class SnapshotWriter : public BaseWriter {
protected:
SnapshotWriter(Thread* thread,
Snapshot::Kind kind,
intptr_t initial_size,
ForwardList* forward_list,
bool can_send_any_object);
public:
// Snapshot kind.
Snapshot::Kind kind() const { return kind_; }
Thread* thread() const { return thread_; }
Zone* zone() const { return thread_->zone(); }
Isolate* isolate() const { return thread_->isolate(); }
IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
Heap* heap() const { return isolate_group()->heap(); }
// Serialize an object into the buffer.
void WriteObject(ObjectPtr raw);
static uint32_t GetObjectTags(ObjectPtr raw);
static uint32_t GetObjectTags(UntaggedObject* raw);
static uword GetObjectTagsAndHash(ObjectPtr raw);
Exceptions::ExceptionType exception_type() const { return exception_type_; }
void set_exception_type(Exceptions::ExceptionType type) {
exception_type_ = type;
}
const char* exception_msg() const { return exception_msg_; }
void set_exception_msg(const char* msg) { exception_msg_ = msg; }
bool can_send_any_object() const { return can_send_any_object_; }
void ThrowException(Exceptions::ExceptionType type, const char* msg);
// Write a version string for the snapshot.
void WriteVersionAndFeatures();
FunctionPtr IsSerializableClosure(ClosurePtr closure);
void WriteStaticImplicitClosure(intptr_t object_id,
FunctionPtr func,
intptr_t tags,
TypeArgumentsPtr delayed_type_arguments);
protected:
bool CheckAndWritePredefinedObject(ObjectPtr raw);
bool HandleVMIsolateObject(ObjectPtr raw);
void WriteClassId(UntaggedClass* cls);
void WriteObjectImpl(ObjectPtr raw, bool as_reference);
void WriteMarkedObjectImpl(ObjectPtr raw,
intptr_t tags,
intptr_t object_id,
bool as_reference);
void WriteForwardedObjects();
void ArrayWriteTo(intptr_t object_id,
intptr_t array_kind,
intptr_t tags,
SmiPtr length,
TypeArgumentsPtr type_arguments,
CompressedObjectPtr data[],
bool as_reference);
void MapWriteTo(intptr_t object_id,
intptr_t class_id,
intptr_t tags,
TypeArgumentsPtr type_arguments,
SmiPtr used_data_smi,
SmiPtr deleted_keys_smi,
ArrayPtr data,
bool as_reference);
void SetWriteTo(intptr_t object_id,
intptr_t class_id,
intptr_t tags,
TypeArgumentsPtr type_arguments,
SmiPtr used_data_smi,
SmiPtr deleted_keys_smi,
ArrayPtr data,
bool as_reference);
ClassPtr GetFunctionOwner(FunctionPtr func);
void CheckForNativeFields(ClassPtr cls);
void SetWriteException(Exceptions::ExceptionType type, const char* msg);
void WriteInstance(ObjectPtr raw,
ClassPtr cls,
intptr_t tags,
intptr_t object_id,
bool as_reference);
bool AllowObjectsInDartLibrary(LibraryPtr library);
intptr_t FindVmSnapshotObject(ObjectPtr rawobj);
ObjectStore* object_store() const { return object_store_; }
private:
Thread* thread_;
Snapshot::Kind kind_;
ObjectStore* object_store_; // Object store for common classes.
ClassTable* class_table_; // Class table for the class index to class lookup.
ForwardList* forward_list_;
Exceptions::ExceptionType exception_type_; // Exception type.
const char* exception_msg_; // Message associated with exception.
bool can_send_any_object_; // True if any Dart instance can be sent.
friend class UntaggedArray;
friend class UntaggedClass;
friend class UntaggedCode;
friend class UntaggedContextScope;
friend class UntaggedDynamicLibrary;
friend class UntaggedExceptionHandlers;
friend class UntaggedField;
friend class UntaggedFunction;
friend class UntaggedFunctionType;
friend class UntaggedGrowableObjectArray;
friend class UntaggedImmutableArray;
friend class UntaggedInstructions;
friend class UntaggedLibrary;
friend class UntaggedLinkedHashMap;
friend class UntaggedLinkedHashSet;
friend class UntaggedLocalVarDescriptors;
friend class UntaggedMirrorReference;
friend class UntaggedObjectPool;
friend class UntaggedPointer;
friend class UntaggedReceivePort;
friend class UntaggedRegExp;
friend class UntaggedScript;
friend class UntaggedStackTrace;
friend class UntaggedSubtypeTestCache;
friend class UntaggedTransferableTypedData;
friend class UntaggedType;
friend class UntaggedTypeArguments;
friend class UntaggedTypeParameter;
friend class UntaggedTypeRef;
friend class UntaggedTypedDataView;
friend class UntaggedUserTag;
friend class UntaggedWeakSerializationReference;
friend class SnapshotWriterVisitor;
friend class WriteInlinedObjectVisitor;
DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
};
class SerializedObjectBuffer : public StackResource {
public:
SerializedObjectBuffer()
@ -749,46 +130,6 @@ class SerializedObjectBuffer : public StackResource {
std::unique_ptr<Message> message_;
};
class MessageWriter : public SnapshotWriter {
public:
static const intptr_t kInitialSize = 512;
explicit MessageWriter(bool can_send_any_object);
~MessageWriter();
std::unique_ptr<Message> WriteMessage(const Object& obj,
Dart_Port dest_port,
Message::Priority priority);
MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
private:
ForwardList forward_list_;
MessageFinalizableData* finalizable_data_;
DISALLOW_COPY_AND_ASSIGN(MessageWriter);
};
// An object pointer visitor implementation which writes out
// objects to a snapshot.
class SnapshotWriterVisitor : public ObjectPointerVisitor {
public:
SnapshotWriterVisitor(SnapshotWriter* writer, bool as_references)
: ObjectPointerVisitor(Isolate::Current()->group()),
writer_(writer),
as_references_(as_references) {}
void VisitPointers(ObjectPtr* first, ObjectPtr* last);
void VisitCompressedPointers(uword heap_base,
CompressedObjectPtr* first,
CompressedObjectPtr* last);
private:
SnapshotWriter* writer_;
bool as_references_;
DISALLOW_COPY_AND_ASSIGN(SnapshotWriterVisitor);
};
} // namespace dart
#endif // RUNTIME_VM_SNAPSHOT_H_

View file

@ -1,98 +0,0 @@
// Copyright (c) 2012, 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_SNAPSHOT_IDS_H_
#define RUNTIME_VM_SNAPSHOT_IDS_H_
#include "vm/dart_entry.h"
#include "vm/raw_object.h"
namespace dart {
// Index for predefined singleton objects used in a snapshot.
enum {
kNullObject = 0,
kSentinelObject,
kTransitionSentinelObject,
kEmptyArrayObject,
kZeroArrayObject,
kTrueValue,
kFalseValue,
// Marker for special encoding of double objects in message snapshots.
kDoubleObject,
// Object id has been optimized away; reader should use next available id.
kOmittedObjectId,
kClassIdsOffset = kOmittedObjectId,
// The class ids of predefined classes are included in this list
// at an offset of kClassIdsOffset.
kFirstTypeSnapshotId = (kNumPredefinedCids + kClassIdsOffset),
kLegacyObjectType = kFirstTypeSnapshotId,
kNullableObjectType,
kNullType,
kDynamicType,
kVoidType,
kNeverType,
kLegacyFunctionType,
kLegacyNumberType,
kLegacySmiType,
kLegacyMintType,
kLegacyDoubleType,
kLegacyIntType,
kLegacyBoolType,
kLegacyStringType,
kLegacyArrayType,
kNonNullableObjectType,
kNonNullableFunctionType,
kNonNullableNumberType,
kNonNullableSmiType,
kNonNullableMintType,
kNonNullableDoubleType,
kNonNullableIntType,
kNonNullableBoolType,
kNonNullableStringType,
kNonNullableArrayType,
kLastTypeSnapshotId = kNonNullableArrayType,
kFirstTypeArgumentsSnapshotId = kLastTypeSnapshotId + 1,
kLegacyIntTypeArguments = kFirstTypeArgumentsSnapshotId,
kLegacyDoubleTypeArguments,
kLegacyStringTypeArguments,
kLegacyStringDynamicTypeArguments,
kLegacyStringLegacyStringTypeArguments,
kNonNullableIntTypeArguments,
kNonNullableDoubleTypeArguments,
kNonNullableStringTypeArguments,
kNonNullableStringDynamicTypeArguments,
kNonNullableStringNonNullableStringTypeArguments,
kEmptyTypeArguments,
kLastTypeArgumentsSnapshotId = kEmptyTypeArguments,
kExtractorParameterTypes,
kExtractorParameterNames,
kEmptyContextScopeObject,
kImplicitClosureScopeObject,
kEmptyObjectPool,
kEmptyDescriptors,
kEmptyVarDescriptors,
kEmptyExceptionHandlers,
kCachedArgumentsDescriptor0,
kCachedArgumentsDescriptorN =
(kCachedArgumentsDescriptor0 +
ArgumentsDescriptor::kCachedDescriptorCount - 1),
kCachedICDataArray0,
kCachedICDataArrayN =
(kCachedICDataArray0 + ICData::kCachedICDataArrayCount - 1),
kInstanceObjectId,
kStaticImplicitClosureObjectId,
kMaxPredefinedObjectIds,
kInvalidIndex = -1,
};
} // namespace dart
#endif // RUNTIME_VM_SNAPSHOT_IDS_H_

View file

@ -15,6 +15,7 @@
#include "vm/debugger_api_impl_test.h"
#include "vm/flags.h"
#include "vm/malloc_hooks.h"
#include "vm/message_snapshot.h"
#include "vm/snapshot.h"
#include "vm/symbols.h"
#include "vm/timer.h"
@ -59,7 +60,6 @@ static void CompareDartCObjects(Dart_CObject* first, Dart_CObject* second) {
// Return immediately if entering a cycle.
if (second->type == Dart_CObject_kNumberOfTypes) return;
EXPECT_NE(first, second);
EXPECT_EQ(first->type, second->type);
switch (first->type) {
case Dart_CObject_kNull:
@ -106,23 +106,20 @@ static void CompareDartCObjects(Dart_CObject* first, Dart_CObject* second) {
}
}
static void CheckEncodeDecodeMessage(Dart_CObject* root) {
static void CheckEncodeDecodeMessage(Zone* zone, Dart_CObject* root) {
// Encode and decode the message.
ApiMessageWriter writer;
std::unique_ptr<Message> message =
writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
ApiMessageReader api_reader(message.get());
Dart_CObject* new_root = api_reader.ReadMessage();
Dart_CObject* new_root = ReadApiMessage(zone, message.get());
// Check that the two messages are the same.
CompareDartCObjects(root, new_root);
}
static void ExpectEncodeFail(Dart_CObject* root) {
ApiMessageWriter writer;
static void ExpectEncodeFail(Zone* zone, Dart_CObject* root) {
std::unique_ptr<Message> message =
writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
EXPECT(message == nullptr);
}
@ -131,22 +128,21 @@ ISOLATE_UNIT_TEST_CASE(SerializeNull) {
// Write snapshot with object content.
const Object& null_object = Object::Handle();
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(null_object, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(null_object, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kNull, root->type);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
@ -154,23 +150,22 @@ ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(124));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(smi, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(smi.Value(), root->value.as_int32);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
@ -178,46 +173,44 @@ ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(-1));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(smi, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(smi.Value(), root->value.as_int32);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
Dart_CObject* SerializeAndDeserializeMint(const Mint& mint) {
Dart_CObject* SerializeAndDeserializeMint(Zone* zone, const Mint& mint) {
// Write snapshot with object content.
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(mint, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, mint, ILLEGAL_PORT,
Message::kNormalPriority);
{
// Switch to a regular zone, where VM handle allocation is allowed.
Thread* thread = Thread::Current();
StackZone zone(thread);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(serialized_object.IsMint());
}
// Read object back from the snapshot into a C structure.
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(zone, message.get());
EXPECT_NOTNULL(root);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(zone, root);
return root;
}
@ -227,7 +220,8 @@ void CheckMint(int64_t value) {
Mint& mint = Mint::Handle();
mint ^= Integer::New(value);
Dart_CObject* mint_cobject = SerializeAndDeserializeMint(mint);
Dart_CObject* mint_cobject =
SerializeAndDeserializeMint(zone.GetZone(), mint);
// On 64-bit platforms mints always require 64-bits as the smi range
// here covers most of the 64-bit range. On 32-bit platforms the smi
// range covers most of the 32-bit range and values outside that
@ -270,23 +264,22 @@ ISOLATE_UNIT_TEST_CASE(SerializeDouble) {
// Write snapshot with object content.
const Double& dbl = Double::Handle(Double::New(101.29));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(dbl, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, dbl, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(dbl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kDouble, root->type);
EXPECT_EQ(dbl.value(), root->value.as_double);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
@ -294,25 +287,24 @@ ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
// Write snapshot with true object.
const Bool& bl = Bool::True();
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
std::unique_ptr<Message> message = WriteMessage(
/* can_send_any_object */ true, bl, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
EXPECT(Equals(bl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kBool, root->type);
EXPECT_EQ(true, root->value.as_bool);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
@ -320,57 +312,55 @@ ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
// Write snapshot with false object.
const Bool& bl = Bool::False();
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
std::unique_ptr<Message> message = WriteMessage(
/* can_send_any_object */ true, bl, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
const Object& serialized_object =
Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(bl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kBool, root->type);
EXPECT_EQ(false, root->value.as_bool);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
// Write snapshot with object content.
const Capability& capability = Capability::Handle(Capability::New(12345));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(capability, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, capability, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
Capability& obj = Capability::Handle();
obj ^= reader.ReadObject();
obj ^= ReadMessage(thread, message.get());
EXPECT_EQ(static_cast<uint64_t>(12345), obj.Id());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kCapability, root->type);
int64_t id = root->value.as_capability.id;
EXPECT_EQ(12345, id);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
#define TEST_ROUND_TRIP_IDENTICAL(object) \
{ \
MessageWriter writer(true); \
std::unique_ptr<Message> message = writer.WriteMessage( \
Object::Handle(object), ILLEGAL_PORT, Message::kNormalPriority); \
MessageSnapshotReader reader(message.get(), thread); \
EXPECT(reader.ReadObject() == object); \
const Object& before = Object::Handle(object); \
std::unique_ptr<Message> message = \
WriteMessage(/* can_send_any_object */ true, before, ILLEGAL_PORT, \
Message::kNormalPriority); \
const Object& after = Object::Handle(ReadMessage(thread, message.get())); \
EXPECT(before.ptr() == after.ptr()); \
}
ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
@ -393,23 +383,21 @@ static void TestString(const char* cstr) {
EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
// Write snapshot with object content.
String& str = String::Handle(String::New(cstr));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, str, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
String& serialized_str = String::Handle();
serialized_str ^= reader.ReadObject();
serialized_str ^= ReadMessage(thread, message.get());
EXPECT(str.Equals(serialized_str));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kString, root->type);
EXPECT_STREQ(cstr, root->value.as_string);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeString) {
@ -436,20 +424,18 @@ ISOLATE_UNIT_TEST_CASE(SerializeArray) {
smi ^= Smi::New(i);
array.SetAt(i, smi);
}
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
serialized_array ^= reader.ReadObject();
serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
@ -457,7 +443,7 @@ ISOLATE_UNIT_TEST_CASE(SerializeArray) {
EXPECT_EQ(Dart_CObject_kInt32, element->type);
EXPECT_EQ(i, element->value.as_int32);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
@ -471,20 +457,18 @@ ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
smi ^= Smi::New(i);
array.SetAt(i, smi);
}
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
serialized_array ^= reader.ReadObject();
serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
@ -492,7 +476,7 @@ ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
EXPECT_EQ(Dart_CObject_kInt32, element->type);
EXPECT_EQ(i, element->value.as_int32);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
TEST_CASE(FailSerializeLargeArray) {
@ -500,7 +484,8 @@ TEST_CASE(FailSerializeLargeArray) {
root.type = Dart_CObject_kArray;
root.value.as_array.length = Array::kMaxElements + 1;
root.value.as_array.values = NULL;
ExpectEncodeFail(&root);
ApiNativeScope scope;
ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeNestedArray) {
@ -513,7 +498,8 @@ TEST_CASE(FailSerializeLargeNestedArray) {
parent.value.as_array.values = values;
child.type = Dart_CObject_kArray;
child.value.as_array.length = Array::kMaxElements + 1;
ExpectEncodeFail(&parent);
ApiNativeScope scope;
ExpectEncodeFail(scope.zone(), &parent);
}
TEST_CASE(FailSerializeLargeTypedDataInt8) {
@ -522,7 +508,8 @@ TEST_CASE(FailSerializeLargeTypedDataInt8) {
root.value.as_typed_data.type = Dart_TypedData_kInt8;
root.value.as_typed_data.length =
TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
ExpectEncodeFail(&root);
ApiNativeScope scope;
ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeTypedDataUint8) {
@ -531,39 +518,40 @@ TEST_CASE(FailSerializeLargeTypedDataUint8) {
root.value.as_typed_data.type = Dart_TypedData_kUint8;
root.value.as_typed_data.length =
TypedData::MaxElements(kTypedDataUint8ArrayCid) + 1;
ExpectEncodeFail(&root);
ApiNativeScope scope;
ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeExternalTypedData) {
Dart_CObject root;
root.type = Dart_CObject_kExternalTypedData;
root.value.as_typed_data.length =
root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
root.value.as_external_typed_data.length =
ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
ExpectEncodeFail(&root);
ApiNativeScope scope;
ExpectEncodeFail(scope.zone(), &root);
}
ISOLATE_UNIT_TEST_CASE(SerializeEmptyArray) {
// Write snapshot with object content.
const int kArrayLength = 0;
Array& array = Array::Handle(Array::New(kArrayLength));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
serialized_array ^= reader.ReadObject();
serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
EXPECT(root->value.as_array.values == NULL);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
@ -574,26 +562,24 @@ ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
for (int i = 0; i < kTypedDataLength; i++) {
typed_data.SetUint8(i, i);
}
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
TypedData& serialized_typed_data = TypedData::Handle();
serialized_typed_data ^= reader.ReadObject();
serialized_typed_data ^= ReadMessage(thread, message.get());
EXPECT(serialized_typed_data.IsTypedData());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kTypedData, root->type);
EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
for (int i = 0; i < kTypedDataLength; i++) {
EXPECT(root->value.as_typed_data.values[i] == i);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
#define TEST_TYPED_ARRAY(darttype, ctype) \
@ -606,12 +592,11 @@ ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
for (int i = 0; i < kArrayLength; i++) { \
array.Set##darttype((i * scale), i); \
} \
MessageWriter writer(true); \
std::unique_ptr<Message> message = \
writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority); \
MessageSnapshotReader reader(message.get(), thread); \
WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT, \
Message::kNormalPriority); \
TypedData& serialized_array = TypedData::Handle(); \
serialized_array ^= reader.ReadObject(); \
serialized_array ^= ReadMessage(thread, message.get()); \
for (int i = 0; i < kArrayLength; i++) { \
EXPECT_EQ(static_cast<ctype>(i), \
serialized_array.Get##darttype(i* scale)); \
@ -627,12 +612,11 @@ ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
reinterpret_cast<uint8_t*>(data), length)); \
intptr_t scale = array.ElementSizeInBytes(); \
MessageWriter writer(true); \
std::unique_ptr<Message> message = \
writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority); \
MessageSnapshotReader reader(message.get(), thread); \
WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT, \
Message::kNormalPriority); \
ExternalTypedData& serialized_array = ExternalTypedData::Handle(); \
serialized_array ^= reader.ReadObject(); \
serialized_array ^= ReadMessage(thread, message.get()); \
for (int i = 0; i < length; i++) { \
EXPECT_EQ(static_cast<ctype>(data[i]), \
serialized_array.Get##darttype(i* scale)); \
@ -670,25 +654,23 @@ ISOLATE_UNIT_TEST_CASE(SerializeEmptyByteArray) {
const int kTypedDataLength = 0;
TypedData& typed_data = TypedData::Handle(
TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
MessageWriter writer(true);
std::unique_ptr<Message> message =
writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot.
MessageSnapshotReader reader(message.get(), thread);
TypedData& serialized_typed_data = TypedData::Handle();
serialized_typed_data ^= reader.ReadObject();
serialized_typed_data ^= ReadMessage(thread, message.get());
EXPECT(serialized_typed_data.IsTypedData());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kTypedData, root->type);
EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
EXPECT(root->value.as_typed_data.values == NULL);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
VM_UNIT_TEST_CASE(FullSnapshot) {
@ -790,47 +772,38 @@ static std::unique_ptr<Message> GetSerialized(Dart_Handle lib,
Object& obj = Object::Handle(Api::UnwrapHandle(result));
// Serialize the object into a message.
MessageWriter writer(false);
return writer.WriteMessage(obj, ILLEGAL_PORT, Message::kNormalPriority);
}
// Helper function to deserialize the result into a Dart_CObject structure.
static Dart_CObject* GetDeserialized(Message* message) {
// Read object back from the snapshot into a C structure.
ApiMessageReader api_reader(message);
return api_reader.ReadMessage();
return WriteMessage(/* can_send_any_object */ false, obj, ILLEGAL_PORT,
Message::kNormalPriority);
}
static void CheckString(Dart_Handle dart_string, const char* expected) {
StackZone zone(Thread::Current());
String& str = String::Handle();
str ^= Api::UnwrapHandle(dart_string);
MessageWriter writer(false);
std::unique_ptr<Message> message =
writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kString, root->type);
EXPECT_STREQ(expected, root->value.as_string);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(zone.GetZone(), root);
}
static void CheckStringInvalid(Dart_Handle dart_string) {
StackZone zone(Thread::Current());
String& str = String::Handle();
str ^= Api::UnwrapHandle(dart_string);
MessageWriter writer(false);
std::unique_ptr<Message> message =
writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
}
@ -928,18 +901,17 @@ VM_UNIT_TEST_CASE(DartGeneratedMessages) {
StackZone zone(thread);
Smi& smi = Smi::Handle();
smi ^= Api::UnwrapHandle(smi_result);
MessageWriter writer(false);
std::unique_ptr<Message> message =
writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
WriteMessage(/* can_send_any_object */ false, smi, ILLEGAL_PORT,
Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
ApiMessageReader api_reader(message.get());
Dart_CObject* root = api_reader.ReadMessage();
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(42, root->value.as_int32);
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
CheckString(ascii_string_result, "Hello, world!");
CheckString(non_ascii_string_result, "Blåbærgrød");
@ -1000,20 +972,20 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessages) {
// Generate a list of nulls from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1021,13 +993,13 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessages) {
EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1042,7 +1014,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessages) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1124,20 +1096,20 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
// Generate a list of nulls from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1145,13 +1117,13 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
}
CheckEncodeDecodeMessage(root);
CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1166,7 +1138,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
// Generate a list of lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1185,7 +1157,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessages) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1357,7 +1329,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1372,7 +1344,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of medium ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1387,7 +1359,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of doubles from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1396,8 +1368,6 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
EXPECT_EQ(3.14, element->value.as_double);
for (int i = 1; i < kArrayLength; i++) {
element = root->value.as_array.values[i];
// Double values are expected to not be canonicalized in messages.
EXPECT_NE(root->value.as_array.values[0], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
}
@ -1406,7 +1376,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1423,7 +1393,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1441,7 +1411,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1458,8 +1428,6 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
EXPECT_EQ(Dart_CObject_kString, element->type);
EXPECT_STREQ("A", element->value.as_string);
} else {
// Double values are expected to not be canonicalized in messages.
EXPECT_NE(root->value.as_array.values[1], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(2.72, element->value.as_double);
}
@ -1469,7 +1437,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1560,7 +1528,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1575,7 +1543,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of medium ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1590,18 +1558,15 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of doubles from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
Dart_CObject* element = root->value.as_array.values[0];
// Double values are expected to not be canonicalized in messages.
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
for (int i = 1; i < kArrayLength; i++) {
element = root->value.as_array.values[i];
// Double values are expected to not be canonicalized in messages.
EXPECT_NE(root->value.as_array.values[0], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
}
@ -1610,7 +1575,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1627,7 +1592,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1645,7 +1610,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1662,8 +1627,6 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
EXPECT_EQ(Dart_CObject_kString, element->type);
EXPECT_STREQ(".", element->value.as_string);
} else {
// Double values are expected to not be canonicalized in messages.
EXPECT_NE(root->value.as_array.values[1], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(2.72, element->value.as_double);
}
@ -1673,7 +1636,7 @@ VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@ -1806,7 +1769,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithTypedData) {
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@ -1834,7 +1797,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithTypedData) {
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@ -1882,7 +1845,7 @@ VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithTypedData) {
std::unique_ptr<Message> message =
GetSerialized(lib, "getMultipleTypedDataViewList");
ApiNativeScope scope;
Dart_CObject* root = GetDeserialized(message.get());
Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@ -2009,15 +1972,6 @@ VM_UNIT_TEST_CASE(PostCObject) {
Dart_ExitScope();
}
ISOLATE_UNIT_TEST_CASE(OmittedObjectEncodingLength) {
StackZone zone(Thread::Current());
MessageWriter writer(true);
writer.WriteInlinedObjectHeader(kOmittedObjectId);
// For performance, we'd like single-byte headers when ids are omitted.
// If this starts failing, consider renumbering the snapshot ids.
EXPECT_EQ(1, writer.BytesWritten());
}
TEST_CASE(IsKernelNegative) {
EXPECT(!Dart_IsKernel(NULL, 0));

View file

@ -21,8 +21,6 @@ namespace dart {
class Code;
class Isolate;
class ObjectPointerVisitor;
class SnapshotReader;
class SnapshotWriter;
DECLARE_FLAG(bool, disassemble_stubs);

View file

@ -14,7 +14,6 @@
#include "vm/object_store.h"
#include "vm/raw_object.h"
#include "vm/reusable_handles.h"
#include "vm/snapshot_ids.h"
#include "vm/visitor.h"
namespace dart {
@ -514,22 +513,4 @@ void Symbols::DumpTable(IsolateGroup* isolate_group) {
table.Release();
}
intptr_t Symbols::LookupPredefinedSymbol(ObjectPtr obj) {
for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
if (symbol_handles_[i]->ptr() == obj) {
return (i + kMaxPredefinedObjectIds);
}
}
return kInvalidIndex;
}
ObjectPtr Symbols::GetPredefinedSymbol(intptr_t object_id) {
ASSERT(IsPredefinedSymbolId(object_id));
intptr_t i = (object_id - kMaxPredefinedObjectIds);
if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
return symbol_handles_[i]->ptr();
}
return Object::null();
}
} // namespace dart

View file

@ -7,7 +7,6 @@
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/snapshot_ids.h"
namespace dart {
@ -105,6 +104,7 @@ class ObjectPointerVisitor;
V(ExceptionHandlers, "ExceptionHandlers") \
V(ExceptionParameter, ":exception") \
V(ExceptionVar, ":exception_var") \
V(Expando, "Expando") \
V(ExprTemp, ":expr_temp") \
V(ExternalName, "ExternalName") \
V(ExternalOneByteString, "_ExternalOneByteString") \
@ -415,6 +415,7 @@ class ObjectPointerVisitor;
V(_objectNoSuchMethod, "_objectNoSuchMethod") \
V(_objectToString, "_objectToString") \
V(_onData, "_onData") \
V(_rehash, "_rehash") \
V(_rehashObjects, "_rehashObjects") \
V(_resultOrListeners, "_resultOrListeners") \
V(_runExtension, "_runExtension") \
@ -698,13 +699,6 @@ class Symbols : public AllStatic {
template <typename StringType>
static StringPtr NewSymbol(Thread* thread, const StringType& str);
static intptr_t LookupPredefinedSymbol(ObjectPtr obj);
static ObjectPtr GetPredefinedSymbol(intptr_t object_id);
static bool IsPredefinedSymbolId(intptr_t object_id) {
return (object_id >= kMaxPredefinedObjectIds &&
object_id < (kMaxPredefinedObjectIds + kMaxPredefinedId));
}
// List of Latin1 characters stored in the vm isolate as symbols
// in order to make Symbols::FromCharCode fast. This structure is
// used in generated dart code for direct access to these objects.
@ -715,11 +709,8 @@ class Symbols : public AllStatic {
friend class Dart;
friend class String;
friend class SnapshotReader;
friend class SnapshotWriter;
friend class Serializer;
friend class Deserializer;
friend class ApiMessageReader;
DISALLOW_COPY_AND_ASSIGN(Symbols);
};

View file

@ -70,7 +70,6 @@ vm_sources = [
"dart.cc",
"dart.h",
"dart_api_impl.h",
"dart_api_message.cc",
"dart_api_message.h",
"dart_api_state.cc",
"dart_api_state.h",
@ -169,6 +168,8 @@ vm_sources = [
"message.h",
"message_handler.cc",
"message_handler.h",
"message_snapshot.cc",
"message_snapshot.h",
"metrics.cc",
"metrics.h",
"native_arguments.h",
@ -235,7 +236,6 @@ vm_sources = [
"raw_object.h",
"raw_object_fields.cc",
"raw_object_fields.h",
"raw_object_snapshot.cc",
"regexp.cc",
"regexp.h",
"regexp_assembler.cc",
@ -289,7 +289,6 @@ vm_sources = [
"simulator_arm64.h",
"snapshot.cc",
"snapshot.h",
"snapshot_ids.h",
"source_report.cc",
"source_report.h",
"stack_frame.cc",

View file

@ -177,6 +177,7 @@ class Zone {
friend class StackZone;
friend class ApiZone;
friend class AllocOnlyStackZone;
template <typename T, typename B, typename Allocator>
friend class BaseGrowableArray;
template <typename T, typename B, typename Allocator>
@ -212,6 +213,23 @@ class StackZone : public StackResource {
DISALLOW_IMPLICIT_CONSTRUCTORS(StackZone);
};
class AllocOnlyStackZone : public ValueObject {
public:
AllocOnlyStackZone() : zone_() {}
~AllocOnlyStackZone() {
// This zone is not linked into the thread, so any handles would not be
// visited.
ASSERT(zone_.handles()->IsEmpty());
}
Zone* GetZone() { return &zone_; }
private:
Zone zone_;
DISALLOW_COPY_AND_ASSIGN(AllocOnlyStackZone);
};
inline uword Zone::AllocUnsafe(intptr_t size) {
ASSERT(size >= 0);
// Round up the requested size to fit the alignment.

View file

@ -5,11 +5,12 @@
// part of "core_patch.dart";
@patch
@pragma("vm:entry-point")
class Expando<T> {
@patch
Expando([String? name])
: name = name,
_data = new List.filled(_minSize, null),
_data = new List<_WeakProperty?>.filled(_minSize, null),
_used = 0;
static const _minSize = 8;
@ -95,6 +96,7 @@ class Expando<T> {
this[object] = value; // Recursively add the value.
}
@pragma("vm:entry-point", "call")
_rehash() {
// Determine the population count of the map to allocate an appropriately
// sized map below.
@ -119,7 +121,7 @@ class Expando<T> {
// Reset the mappings to empty so that we can just add the existing
// valid entries.
_data = new List.filled(new_size, null);
_data = new List<_WeakProperty?>.filled(new_size, null);
_used = 0;
for (var i = 0; i < old_data.length; i++) {
@ -149,9 +151,9 @@ class Expando<T> {
}
}
get _size => _data.length;
get _limit => (3 * (_size ~/ 4));
int get _size => _data.length;
int get _limit => (3 * (_size ~/ 4));
List _data;
List<_WeakProperty?> _data;
int _used; // Number of used (active and deleted) slots.
}

View file

@ -567,10 +567,16 @@ abstract class SendPort implements Capability {
/// Sends an asynchronous [message] through this send port, to its
/// corresponding `ReceivePort`.
///
/// The content of [message] can be: primitive values
/// (null, num, bool, double, String), instances of [SendPort],
/// and lists and maps whose elements are any of these.
/// List and maps are also allowed to contain cyclic references.
/// The content of [message] can be:
/// - [Null]
/// - [bool]
/// - [int]
/// - [double]
/// - [String]
/// - [List] or [Map] (whose elements are any of these)
/// - [TransferableTypedData]
/// - [SendPort]
/// - [Capability]
///
/// In the special circumstances when two isolates share the same code and are
/// running in the same process (e.g. isolates created via [Isolate.spawn]),

View file

@ -0,0 +1,31 @@
// Copyright (c) 2021, 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.
// See https://github.com/flutter/flutter/issues/84691
import "dart:async";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
class B<T> {}
class D<S> extends B<D> {}
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var list = message as List<D<String>>;
var element = list[0] as D<String>;
port.close();
asyncEnd();
});
var list = <D<String>>[ new D() ];
port.sendPort.send(list);
}

View file

@ -0,0 +1,48 @@
// Copyright (c) 2021, 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.
// See https://github.com/dart-lang/sdk/issues/25559
import "dart:async";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var expando1 = message[0] as Expando;
var expando2 = message[1] as Expando;
var expando3 = message[2] as Expando;
var key1 = message[3];
var key2 = expando1[key1!];
Expect.isNotNull(key2);
var key3 = expando2[key2!];
Expect.isNotNull(key3);
var value = expando3[key3!];
Expect.equals(value, "value");
port.close();
asyncEnd();
});
var key1 = new Object();
var key2 = new Object();
var key3 = new Object();
var expando1 = new Expando();
var expando2 = new Expando();
var expando3 = new Expando();
expando1[key1] = key2;
expando2[key2] = key3;
expando3[key3] = "value";
// key1 is placed after expando1 so that its reachability is uncertain when
// expando1 is first encountered.
var message = <dynamic>[expando1, expando2, expando3, key1];
port.sendPort.send(message);
}

View file

@ -0,0 +1,34 @@
// Copyright (c) 2021, 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.
// See https://github.com/dart-lang/sdk/issues/25559
import "dart:async";
import "dart:developer";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var expando = message as Expando;
// Sent and received without error.
port.close();
asyncEnd();
});
var unwrittenKey = new Object();
var expando = new Expando();
expando[unwrittenKey] = new UserTag("cant send this");
port.sendPort.send(expando);
print(unwrittenKey); // Ensure [unwrittenKey] is live during [send].
}

View file

@ -0,0 +1,33 @@
// Copyright (c) 2021, 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.
// See https://github.com/flutter/flutter/issues/84691
// @dart = 2.9
import "dart:async";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
class B<T> {}
class D<S> extends B<D> {}
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var list = message as List<D<String>>;
var element = list[0] as D<String>;
port.close();
asyncEnd();
});
var list = <D<String>>[ new D() ];
port.sendPort.send(list);
}

View file

@ -0,0 +1,50 @@
// Copyright (c) 2021, 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.
// See https://github.com/dart-lang/sdk/issues/25559
// @dart = 2.9
import "dart:async";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var expando1 = message[0] as Expando;
var expando2 = message[1] as Expando;
var expando3 = message[2] as Expando;
var key1 = message[3];
var key2 = expando1[key1];
Expect.isNotNull(key2);
var key3 = expando2[key2];
Expect.isNotNull(key3);
var value = expando3[key3];
Expect.equals(value, "value");
port.close();
asyncEnd();
});
var key1 = new Object();
var key2 = new Object();
var key3 = new Object();
var expando1 = new Expando();
var expando2 = new Expando();
var expando3 = new Expando();
expando1[key1] = key2;
expando2[key2] = key3;
expando3[key3] = "value";
// key1 is placed after expando1 so that its reachability is uncertain when
// expando1 is first encountered.
var message = <dynamic>[expando1, expando2, expando3, key1];
port.sendPort.send(message);
}

View file

@ -0,0 +1,36 @@
// Copyright (c) 2021, 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.
// See https://github.com/dart-lang/sdk/issues/25559
// @dart = 2.9
import "dart:async";
import "dart:developer";
import "dart:isolate";
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
main() {
asyncStart();
var port;
port = new RawReceivePort((message) {
var expando = message as Expando;
// Sent and received without error.
port.close();
asyncEnd();
});
var unwrittenKey = new Object();
var expando = new Expando();
expando[unwrittenKey] = new UserTag("cant send this");
port.sendPort.send(expando);
print(unwrittenKey); // Ensure [unwrittenKey] is live during [send].
}

View file

@ -23,7 +23,6 @@ VM_SNAPSHOT_FILES = [
'object.h',
'raw_object.h',
'snapshot.h',
'snapshot_ids.h',
'symbols.h',
# Source files.
'clustered_snapshot.cc',
@ -32,7 +31,6 @@ VM_SNAPSHOT_FILES = [
'image_snapshot.cc',
'object.cc',
'raw_object.cc',
'raw_object_snapshot.cc',
'snapshot.cc',
'symbols.cc',
]