mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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:
parent
7a2f1adebe
commit
bbefc05748
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
@ -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.
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
3616
runtime/vm/message_snapshot.cc
Normal file
3616
runtime/vm/message_snapshot.cc
Normal file
File diff suppressed because it is too large
Load diff
32
runtime/vm/message_snapshot.h
Normal file
32
runtime/vm/message_snapshot.h
Normal 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_
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
@ -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_
|
||||
|
|
|
@ -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_
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@ namespace dart {
|
|||
class Code;
|
||||
class Isolate;
|
||||
class ObjectPointerVisitor;
|
||||
class SnapshotReader;
|
||||
class SnapshotWriter;
|
||||
|
||||
DECLARE_FLAG(bool, disassemble_stubs);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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]),
|
||||
|
|
31
tests/lib/isolate/type_ref_message_test.dart
Normal file
31
tests/lib/isolate/type_ref_message_test.dart
Normal 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);
|
||||
}
|
48
tests/lib/isolate/weak_property_message_1_test.dart
Normal file
48
tests/lib/isolate/weak_property_message_1_test.dart
Normal 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);
|
||||
}
|
34
tests/lib/isolate/weak_property_message_2_test.dart
Normal file
34
tests/lib/isolate/weak_property_message_2_test.dart
Normal 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].
|
||||
}
|
33
tests/lib_2/isolate/type_ref_message_test.dart
Normal file
33
tests/lib_2/isolate/type_ref_message_test.dart
Normal 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);
|
||||
}
|
50
tests/lib_2/isolate/weak_property_message_1_test.dart
Normal file
50
tests/lib_2/isolate/weak_property_message_1_test.dart
Normal 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);
|
||||
}
|
36
tests/lib_2/isolate/weak_property_message_2_test.dart
Normal file
36
tests/lib_2/isolate/weak_property_message_2_test.dart
Normal 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].
|
||||
}
|
|
@ -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',
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue