mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:39:38 +00:00
[vm] Stricter checks when sending isolate messages between groups.
- Check against sending arbitrary classes via types.
- Stop allowing any object from dart:core, dart:collection, dart:typed_data (effectively reverts 807eacae30
).
`SendPort.send` does not require such objects are sendable, and there is no guarantee the receiving isolate can represent them.
TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/50243
Change-Id: I7e9b0e9d83080d44a98b257cd8f2a58da5443a87
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264725
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
parent
ce591144b0
commit
a8fe399c79
|
@ -966,7 +966,7 @@ bool AotCallSpecializer::TryExpandCallThroughGetter(const Class& receiver_class,
|
||||||
|
|
||||||
// Ignore callsites like f.call() for now. Those need to be handled
|
// Ignore callsites like f.call() for now. Those need to be handled
|
||||||
// specially if f is a closure.
|
// specially if f is a closure.
|
||||||
if (call->function_name().ptr() == Symbols::Call().ptr()) {
|
if (call->function_name().ptr() == Symbols::call().ptr()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,7 +1017,7 @@ bool AotCallSpecializer::TryExpandCallThroughGetter(const Class& receiver_class,
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceCallInstr* invoke_call = new (Z) InstanceCallInstr(
|
InstanceCallInstr* invoke_call = new (Z) InstanceCallInstr(
|
||||||
call->source(), Symbols::Call(), Token::kILLEGAL,
|
call->source(), Symbols::call(), Token::kILLEGAL,
|
||||||
std::move(call_arguments), call->type_args_len(), call->argument_names(),
|
std::move(call_arguments), call->type_args_len(), call->argument_names(),
|
||||||
/*checked_argument_count=*/1,
|
/*checked_argument_count=*/1,
|
||||||
thread()->compiler_state().GetNextDeoptId());
|
thread()->compiler_state().GetNextDeoptId());
|
||||||
|
|
|
@ -733,7 +733,7 @@ void Precompiler::PrecompileConstructors() {
|
||||||
void Precompiler::AddRoots() {
|
void Precompiler::AddRoots() {
|
||||||
HANDLESCOPE(T);
|
HANDLESCOPE(T);
|
||||||
AddSelector(Symbols::NoSuchMethod());
|
AddSelector(Symbols::NoSuchMethod());
|
||||||
AddSelector(Symbols::Call()); // For speed, not correctness.
|
AddSelector(Symbols::call()); // For speed, not correctness.
|
||||||
|
|
||||||
// Add main as an entry point.
|
// Add main as an entry point.
|
||||||
const Library& lib = Library::Handle(IG->object_store()->root_library());
|
const Library& lib = Library::Handle(IG->object_store()->root_library());
|
||||||
|
@ -990,7 +990,7 @@ void Precompiler::AddCalleesOf(const Function& function, intptr_t gop_offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsPotentialClosureCall(const String& selector) {
|
static bool IsPotentialClosureCall(const String& selector) {
|
||||||
return selector.ptr() == Symbols::Call().ptr() ||
|
return selector.ptr() == Symbols::call().ptr() ||
|
||||||
selector.ptr() == Symbols::DynamicCall().ptr();
|
selector.ptr() == Symbols::DynamicCall().ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1379,7 +1379,7 @@ const char* Precompiler::MustRetainFunction(const Function& function) {
|
||||||
|
|
||||||
// Use the same check for _Closure.call as in stack_trace.{h|cc}.
|
// Use the same check for _Closure.call as in stack_trace.{h|cc}.
|
||||||
const auto& selector = String::Handle(Z, function.name());
|
const auto& selector = String::Handle(Z, function.name());
|
||||||
if (selector.ptr() == Symbols::Call().ptr()) {
|
if (selector.ptr() == Symbols::call().ptr()) {
|
||||||
const auto& name = String::Handle(Z, function.QualifiedScrubbedName());
|
const auto& name = String::Handle(Z, function.QualifiedScrubbedName());
|
||||||
if (name.Equals(Symbols::_ClosureCall())) {
|
if (name.Equals(Symbols::_ClosureCall())) {
|
||||||
return "_Closure.call";
|
return "_Closure.call";
|
||||||
|
@ -2462,10 +2462,7 @@ static bool IsUserDefinedClass(Zone* zone,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UntaggedClass* untagged_cls = cls.untag();
|
return true;
|
||||||
return ((untagged_cls->library() != object_store->core_library()) &&
|
|
||||||
(untagged_cls->library() != object_store->collection_library()) &&
|
|
||||||
(untagged_cls->library() != object_store->typed_data_library()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates |visited| weak table with information about whether object
|
/// Updates |visited| weak table with information about whether object
|
||||||
|
|
|
@ -3141,7 +3141,7 @@ Fragment StreamingFlowGraphBuilder::BuildFunctionInvocation(TokenPosition* p) {
|
||||||
SkipDartType(); // read function_type.
|
SkipDartType(); // read function_type.
|
||||||
|
|
||||||
if (is_unchecked_closure_call) {
|
if (is_unchecked_closure_call) {
|
||||||
instructions += CheckNull(position, receiver_temp, Symbols::Call(),
|
instructions += CheckNull(position, receiver_temp, Symbols::call(),
|
||||||
/*clear_temp=*/false);
|
/*clear_temp=*/false);
|
||||||
// Lookup the function in the closure.
|
// Lookup the function in the closure.
|
||||||
instructions += LoadLocal(receiver_temp);
|
instructions += LoadLocal(receiver_temp);
|
||||||
|
|
|
@ -3245,7 +3245,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher(
|
||||||
const Class& closure_class =
|
const Class& closure_class =
|
||||||
Class::Handle(Z, IG->object_store()->closure_class());
|
Class::Handle(Z, IG->object_store()->closure_class());
|
||||||
const bool is_closure_call = (owner.ptr() == closure_class.ptr()) &&
|
const bool is_closure_call = (owner.ptr() == closure_class.ptr()) &&
|
||||||
field_name.Equals(Symbols::Call());
|
field_name.Equals(Symbols::call());
|
||||||
|
|
||||||
graph_entry_ =
|
graph_entry_ =
|
||||||
new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
|
new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
|
||||||
|
@ -3326,7 +3326,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher(
|
||||||
const intptr_t kNumArgsChecked = 1;
|
const intptr_t kNumArgsChecked = 1;
|
||||||
body +=
|
body +=
|
||||||
InstanceCall(TokenPosition::kMinSource,
|
InstanceCall(TokenPosition::kMinSource,
|
||||||
is_dynamic_call ? Symbols::DynamicCall() : Symbols::Call(),
|
is_dynamic_call ? Symbols::DynamicCall() : Symbols::call(),
|
||||||
Token::kILLEGAL, descriptor.TypeArgsLen(),
|
Token::kILLEGAL, descriptor.TypeArgsLen(),
|
||||||
descriptor.Count(), *argument_names, kNumArgsChecked);
|
descriptor.Count(), *argument_names, kNumArgsChecked);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -275,7 +275,7 @@ ObjectPtr DartEntry::InvokeCallable(Thread* thread,
|
||||||
auto& instance =
|
auto& instance =
|
||||||
Instance::CheckedHandle(zone, arguments.At(args_desc.FirstArgIndex()));
|
Instance::CheckedHandle(zone, arguments.At(args_desc.FirstArgIndex()));
|
||||||
// For closures, use the name of the closure, not 'call'.
|
// For closures, use the name of the closure, not 'call'.
|
||||||
const String* target_name = &Symbols::Call();
|
const String* target_name = &Symbols::call();
|
||||||
if (instance.IsClosure()) {
|
if (instance.IsClosure()) {
|
||||||
auto const& function =
|
auto const& function =
|
||||||
Function::Handle(zone, Closure::Cast(instance).function());
|
Function::Handle(zone, Closure::Cast(instance).function());
|
||||||
|
|
|
@ -831,7 +831,7 @@ const Context& ActivationFrame::GetSavedCurrentContext() {
|
||||||
const auto variable_index = VariableIndex(var_info.index());
|
const auto variable_index = VariableIndex(var_info.index());
|
||||||
obj = GetStackVar(variable_index);
|
obj = GetStackVar(variable_index);
|
||||||
if (obj.IsClosure()) {
|
if (obj.IsClosure()) {
|
||||||
ASSERT(function().name() == Symbols::Call().ptr());
|
ASSERT(function().name() == Symbols::call().ptr());
|
||||||
ASSERT(function().IsInvokeFieldDispatcher());
|
ASSERT(function().IsInvokeFieldDispatcher());
|
||||||
// Closure.call frames.
|
// Closure.call frames.
|
||||||
ctx_ = Closure::Cast(obj).context();
|
ctx_ = Closure::Cast(obj).context();
|
||||||
|
|
|
@ -87,7 +87,6 @@ class MessageSerializer;
|
||||||
class MessageDeserializer;
|
class MessageDeserializer;
|
||||||
class ApiMessageSerializer;
|
class ApiMessageSerializer;
|
||||||
class ApiMessageDeserializer;
|
class ApiMessageDeserializer;
|
||||||
class WeakPropertyMessageSerializationCluster;
|
|
||||||
|
|
||||||
class MessageSerializationCluster : public ZoneAllocated {
|
class MessageSerializationCluster : public ZoneAllocated {
|
||||||
public:
|
public:
|
||||||
|
@ -208,7 +207,6 @@ class BaseSerializer : public StackResource {
|
||||||
MallocWriteStream stream_;
|
MallocWriteStream stream_;
|
||||||
MessageFinalizableData* finalizable_data_;
|
MessageFinalizableData* finalizable_data_;
|
||||||
GrowableArray<MessageSerializationCluster*> clusters_;
|
GrowableArray<MessageSerializationCluster*> clusters_;
|
||||||
WeakPropertyMessageSerializationCluster* ephemeron_cluster_;
|
|
||||||
intptr_t num_base_objects_;
|
intptr_t num_base_objects_;
|
||||||
intptr_t num_written_objects_;
|
intptr_t num_written_objects_;
|
||||||
intptr_t next_ref_index_;
|
intptr_t next_ref_index_;
|
||||||
|
@ -717,260 +715,6 @@ class TypeArgumentsMessageDeserializationCluster
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionMessageSerializationCluster : public MessageSerializationCluster {
|
|
||||||
public:
|
|
||||||
FunctionMessageSerializationCluster()
|
|
||||||
: MessageSerializationCluster("Function",
|
|
||||||
MessagePhase::kBeforeTypes,
|
|
||||||
kFunctionCid) {}
|
|
||||||
~FunctionMessageSerializationCluster() {}
|
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
|
||||||
Function* func = static_cast<Function*>(object);
|
|
||||||
objects_.Add(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
s->WriteUnsigned(count);
|
|
||||||
Library& lib = Library::Handle(s->zone());
|
|
||||||
Class& cls = Class::Handle(s->zone());
|
|
||||||
String& str = String::Handle(s->zone());
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
Function* func = objects_[i];
|
|
||||||
s->AssignRef(func);
|
|
||||||
cls ^= func->Owner();
|
|
||||||
lib = cls.library();
|
|
||||||
str = lib.url();
|
|
||||||
s->WriteAscii(str);
|
|
||||||
str = cls.Name();
|
|
||||||
s->WriteAscii(str);
|
|
||||||
str = func->name();
|
|
||||||
s->WriteAscii(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GrowableArray<Function*> objects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FunctionMessageDeserializationCluster
|
|
||||||
: public MessageDeserializationCluster {
|
|
||||||
public:
|
|
||||||
FunctionMessageDeserializationCluster()
|
|
||||||
: MessageDeserializationCluster("Function") {}
|
|
||||||
~FunctionMessageDeserializationCluster() {}
|
|
||||||
|
|
||||||
void ReadNodes(MessageDeserializer* d) {
|
|
||||||
const intptr_t count = d->ReadUnsigned();
|
|
||||||
String& uri = String::Handle(d->zone());
|
|
||||||
Library& lib = Library::Handle(d->zone());
|
|
||||||
String& cname = String::Handle(d->zone());
|
|
||||||
Class& cls = Class::Handle(d->zone());
|
|
||||||
String& fname = String::Handle(d->zone());
|
|
||||||
Function& func = Function::Handle(d->zone());
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
uri = String::New(d->ReadAscii()); // Library URI.
|
|
||||||
cname = String::New(d->ReadAscii()); // Class name.
|
|
||||||
fname = String::New(d->ReadAscii()); // Function name.
|
|
||||||
lib = Library::LookupLibrary(d->thread(), uri);
|
|
||||||
if (UNLIKELY(lib.IsNull())) {
|
|
||||||
FATAL("Not found: %s %s %s", uri.ToCString(), cname.ToCString(),
|
|
||||||
fname.ToCString());
|
|
||||||
}
|
|
||||||
if (cname.Equals(Symbols::TopLevel())) {
|
|
||||||
cls = lib.toplevel_class();
|
|
||||||
} else {
|
|
||||||
cls = lib.LookupClass(cname);
|
|
||||||
}
|
|
||||||
if (UNLIKELY(cls.IsNull())) {
|
|
||||||
FATAL("Not found: %s %s %s", uri.ToCString(), cname.ToCString(),
|
|
||||||
fname.ToCString());
|
|
||||||
}
|
|
||||||
cls.EnsureIsFinalized(d->thread());
|
|
||||||
func = cls.LookupStaticFunction(fname);
|
|
||||||
if (UNLIKELY(func.IsNull())) {
|
|
||||||
FATAL("Not found: %s %s %s", uri.ToCString(), cname.ToCString(),
|
|
||||||
fname.ToCString());
|
|
||||||
}
|
|
||||||
d->AssignRef(func.ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstanceMessageSerializationCluster : public MessageSerializationCluster {
|
|
||||||
public:
|
|
||||||
InstanceMessageSerializationCluster(bool is_canonical, intptr_t cid)
|
|
||||||
: MessageSerializationCluster("Instance",
|
|
||||||
is_canonical
|
|
||||||
? MessagePhase::kCanonicalInstances
|
|
||||||
: MessagePhase::kNonCanonicalInstances,
|
|
||||||
cid,
|
|
||||||
is_canonical),
|
|
||||||
cls_(Class::Handle()) {
|
|
||||||
cls_ = IsolateGroup::Current()->class_table()->At(cid);
|
|
||||||
next_field_offset_ = cls_.host_next_field_offset();
|
|
||||||
}
|
|
||||||
~InstanceMessageSerializationCluster() {}
|
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
|
||||||
Instance* instance = static_cast<Instance*>(object);
|
|
||||||
objects_.Add(instance);
|
|
||||||
|
|
||||||
const intptr_t next_field_offset = next_field_offset_;
|
|
||||||
const auto unboxed_fields_bitmap =
|
|
||||||
s->isolate_group()->class_table()->GetUnboxedFieldsMapAt(cid_);
|
|
||||||
for (intptr_t offset = Instance::NextFieldOffset();
|
|
||||||
offset < next_field_offset; offset += kCompressedWordSize) {
|
|
||||||
if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
s->Push(reinterpret_cast<CompressedObjectPtr*>(
|
|
||||||
reinterpret_cast<uword>(instance->untag()) + offset)
|
|
||||||
->Decompress(instance->untag()->heap_base()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
|
||||||
s->WriteRef(cls_.ptr());
|
|
||||||
|
|
||||||
intptr_t count = objects_.length();
|
|
||||||
s->WriteUnsigned(count);
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
Instance* instance = objects_[i];
|
|
||||||
s->AssignRef(instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteEdges(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
Instance* instance = objects_[i];
|
|
||||||
|
|
||||||
const intptr_t next_field_offset = next_field_offset_;
|
|
||||||
const auto unboxed_fields_bitmap =
|
|
||||||
s->isolate_group()->class_table()->GetUnboxedFieldsMapAt(cid_);
|
|
||||||
for (intptr_t offset = Instance::NextFieldOffset();
|
|
||||||
offset < next_field_offset; offset += kCompressedWordSize) {
|
|
||||||
if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
|
|
||||||
// Writes 32 bits of the unboxed value at a time
|
|
||||||
const uword value = *reinterpret_cast<compressed_uword*>(
|
|
||||||
reinterpret_cast<uword>(instance->untag()) + offset);
|
|
||||||
s->WriteWordWith32BitWrites(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
|
|
||||||
reinterpret_cast<uword>(instance->untag()) + offset)
|
|
||||||
->Decompress(instance->untag()->heap_base()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Class& cls_;
|
|
||||||
intptr_t next_field_offset_;
|
|
||||||
GrowableArray<Instance*> objects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstanceMessageDeserializationCluster
|
|
||||||
: public MessageDeserializationCluster {
|
|
||||||
public:
|
|
||||||
explicit InstanceMessageDeserializationCluster(bool is_canonical)
|
|
||||||
: MessageDeserializationCluster("Instance", is_canonical),
|
|
||||||
cls_(Class::Handle()),
|
|
||||||
field_stores_(GrowableObjectArray::Handle(GrowableObjectArray::New())) {
|
|
||||||
}
|
|
||||||
~InstanceMessageDeserializationCluster() {}
|
|
||||||
|
|
||||||
void ReadNodes(MessageDeserializer* d) {
|
|
||||||
cls_ ^= d->ReadRef();
|
|
||||||
|
|
||||||
intptr_t count = d->ReadUnsigned();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
d->AssignRef(Instance::New(cls_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadEdges(MessageDeserializer* d) {
|
|
||||||
const intptr_t next_field_offset = cls_.host_next_field_offset();
|
|
||||||
const auto unboxed_fields_bitmap =
|
|
||||||
d->isolate_group()->class_table()->GetUnboxedFieldsMapAt(cls_.id());
|
|
||||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
||||||
const intptr_t type_argument_field_offset =
|
|
||||||
cls_.host_type_arguments_field_offset();
|
|
||||||
const bool use_field_guards = d->isolate_group()->use_field_guards();
|
|
||||||
const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap());
|
|
||||||
Field& field = Field::Handle(d->zone());
|
|
||||||
#endif
|
|
||||||
Instance& instance = Instance::Handle(d->zone());
|
|
||||||
Object& value = Object::Handle(d->zone());
|
|
||||||
|
|
||||||
for (intptr_t id = start_index_; id < stop_index_; id++) {
|
|
||||||
instance ^= d->Ref(id);
|
|
||||||
for (intptr_t offset = Instance::NextFieldOffset();
|
|
||||||
offset < next_field_offset; offset += kCompressedWordSize) {
|
|
||||||
if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
|
|
||||||
compressed_uword* p = reinterpret_cast<compressed_uword*>(
|
|
||||||
reinterpret_cast<uword>(instance.untag()) + offset);
|
|
||||||
// Reads 32 bits of the unboxed value at a time
|
|
||||||
*p = d->ReadWordWith32BitReads();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
value = d->ReadRef();
|
|
||||||
instance.SetFieldAtOffset(offset, value);
|
|
||||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
||||||
if (use_field_guards && (offset != type_argument_field_offset) &&
|
|
||||||
(value.ptr() != Object::sentinel().ptr())) {
|
|
||||||
field ^= field_map.At(offset >> kCompressedWordSizeLog2);
|
|
||||||
ASSERT(!field.IsNull());
|
|
||||||
ASSERT(field.HostOffset() == offset);
|
|
||||||
field_stores_.Add(field);
|
|
||||||
field_stores_.Add(value);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectPtr PostLoad(MessageDeserializer* d) {
|
|
||||||
if (is_canonical()) {
|
|
||||||
SafepointMutexLocker ml(
|
|
||||||
d->isolate_group()->constant_canonicalization_mutex());
|
|
||||||
Instance& instance = Instance::Handle(d->zone());
|
|
||||||
for (intptr_t i = start_index_; i < stop_index_; i++) {
|
|
||||||
instance ^= d->Ref(i);
|
|
||||||
instance = instance.CanonicalizeLocked(d->thread());
|
|
||||||
d->UpdateRef(i, instance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cls_.ptr() == d->isolate_group()->object_store()->expando_class()) {
|
|
||||||
const auto& expandos =
|
|
||||||
Array::Handle(d->zone(), Array::New(stop_index_ - start_index_));
|
|
||||||
auto& instance = Instance::Handle(d->zone());
|
|
||||||
for (intptr_t i = start_index_, j = 0; i < stop_index_; i++, j++) {
|
|
||||||
instance ^= d->Ref(i);
|
|
||||||
expandos.SetAt(j, instance);
|
|
||||||
}
|
|
||||||
return DartLibraryCalls::RehashObjectsInDartCore(d->thread(), expandos);
|
|
||||||
}
|
|
||||||
|
|
||||||
Field& field = Field::Handle(d->zone());
|
|
||||||
Object& value = Object::Handle(d->zone());
|
|
||||||
for (int i = 0; i < field_stores_.Length(); i += 2) {
|
|
||||||
field ^= field_stores_.At(i);
|
|
||||||
value = field_stores_.At(i + 1);
|
|
||||||
field.RecordStore(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Class& cls_;
|
|
||||||
GrowableObjectArray& field_stores_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TypeMessageSerializationCluster : public MessageSerializationCluster {
|
class TypeMessageSerializationCluster : public MessageSerializationCluster {
|
||||||
public:
|
public:
|
||||||
explicit TypeMessageSerializationCluster(bool is_canonical)
|
explicit TypeMessageSerializationCluster(bool is_canonical)
|
||||||
|
@ -982,6 +726,11 @@ class TypeMessageSerializationCluster : public MessageSerializationCluster {
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
void Trace(MessageSerializer* s, Object* object) {
|
||||||
Type* type = static_cast<Type*>(object);
|
Type* type = static_cast<Type*>(object);
|
||||||
|
|
||||||
|
if (!type->IsTypeClassAllowedBySpawnUri()) {
|
||||||
|
s->IllegalObject(*object, "is a Type");
|
||||||
|
}
|
||||||
|
|
||||||
objects_.Add(type);
|
objects_.Add(type);
|
||||||
|
|
||||||
s->Push(type->type_class());
|
s->Push(type->type_class());
|
||||||
|
@ -1382,7 +1131,15 @@ class GrowableObjectArrayMessageSerializationCluster
|
||||||
GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object);
|
GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object);
|
||||||
objects_.Add(array);
|
objects_.Add(array);
|
||||||
|
|
||||||
s->Push(array->GetTypeArguments());
|
// Compensation for bogus type prefix optimization.
|
||||||
|
TypeArguments& args =
|
||||||
|
TypeArguments::Handle(s->zone(), array->untag()->type_arguments());
|
||||||
|
if (!args.IsNull() && (args.Length() != 1)) {
|
||||||
|
args = args.TruncatedTo(1);
|
||||||
|
array->untag()->set_type_arguments(args.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
s->Push(array->untag()->type_arguments());
|
||||||
for (intptr_t i = 0, n = array->Length(); i < n; i++) {
|
for (intptr_t i = 0, n = array->Length(); i < n; i++) {
|
||||||
s->Push(array->At(i));
|
s->Push(array->At(i));
|
||||||
}
|
}
|
||||||
|
@ -1402,7 +1159,7 @@ class GrowableObjectArrayMessageSerializationCluster
|
||||||
const intptr_t count = objects_.length();
|
const intptr_t count = objects_.length();
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
for (intptr_t i = 0; i < count; i++) {
|
||||||
GrowableObjectArray* array = objects_[i];
|
GrowableObjectArray* array = objects_[i];
|
||||||
s->WriteRef(array->GetTypeArguments());
|
s->WriteRef(array->untag()->type_arguments());
|
||||||
for (intptr_t i = 0, n = array->Length(); i < n; i++) {
|
for (intptr_t i = 0, n = array->Length(); i < n; i++) {
|
||||||
s->WriteRef(array->At(i));
|
s->WriteRef(array->At(i));
|
||||||
}
|
}
|
||||||
|
@ -2284,64 +2041,6 @@ class Simd128MessageDeserializationCluster
|
||||||
const intptr_t cid_;
|
const intptr_t cid_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegExpMessageSerializationCluster : public MessageSerializationCluster {
|
|
||||||
public:
|
|
||||||
RegExpMessageSerializationCluster()
|
|
||||||
: MessageSerializationCluster("RegExp",
|
|
||||||
MessagePhase::kNonCanonicalInstances,
|
|
||||||
kRegExpCid) {}
|
|
||||||
~RegExpMessageSerializationCluster() {}
|
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
|
||||||
RegExp* regexp = static_cast<RegExp*>(object);
|
|
||||||
objects_.Add(regexp);
|
|
||||||
|
|
||||||
s->Push(regexp->capture_name_map());
|
|
||||||
s->Push(regexp->pattern());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
s->WriteUnsigned(count);
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
RegExp* regexp = objects_[i];
|
|
||||||
s->AssignRef(regexp);
|
|
||||||
s->WriteRef(regexp->capture_name_map());
|
|
||||||
s->WriteRef(regexp->pattern());
|
|
||||||
s->Write<int32_t>(regexp->num_bracket_expressions());
|
|
||||||
s->Write<int32_t>(regexp->num_registers(true));
|
|
||||||
s->Write<int32_t>(regexp->num_registers(false));
|
|
||||||
s->Write<int>(regexp->flags().value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GrowableArray<RegExp*> objects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class RegExpMessageDeserializationCluster
|
|
||||||
: public MessageDeserializationCluster {
|
|
||||||
public:
|
|
||||||
RegExpMessageDeserializationCluster()
|
|
||||||
: MessageDeserializationCluster("RegExp") {}
|
|
||||||
~RegExpMessageDeserializationCluster() {}
|
|
||||||
|
|
||||||
void ReadNodes(MessageDeserializer* d) {
|
|
||||||
RegExp& regexp = RegExp::Handle(d->zone());
|
|
||||||
intptr_t count = d->ReadUnsigned();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
regexp = RegExp::New(d->zone());
|
|
||||||
d->AssignRef(regexp.ptr());
|
|
||||||
regexp.untag()->set_capture_name_map(static_cast<ArrayPtr>(d->ReadRef()));
|
|
||||||
regexp.untag()->set_pattern(static_cast<StringPtr>(d->ReadRef()));
|
|
||||||
regexp.set_num_bracket_expressions(d->Read<int32_t>());
|
|
||||||
regexp.set_num_registers(true, d->Read<int32_t>());
|
|
||||||
regexp.set_num_registers(false, d->Read<int32_t>());
|
|
||||||
regexp.set_flags(RegExpFlags(d->Read<int>()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SendPortMessageSerializationCluster : public MessageSerializationCluster {
|
class SendPortMessageSerializationCluster : public MessageSerializationCluster {
|
||||||
public:
|
public:
|
||||||
explicit SendPortMessageSerializationCluster(Zone* zone)
|
explicit SendPortMessageSerializationCluster(Zone* zone)
|
||||||
|
@ -2481,147 +2180,6 @@ class CapabilityMessageDeserializationCluster
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class WeakPropertyMessageSerializationCluster
|
|
||||||
: public MessageSerializationCluster {
|
|
||||||
public:
|
|
||||||
WeakPropertyMessageSerializationCluster()
|
|
||||||
: MessageSerializationCluster("WeakProperty",
|
|
||||||
MessagePhase::kNonCanonicalInstances,
|
|
||||||
kWeakPropertyCid) {}
|
|
||||||
~WeakPropertyMessageSerializationCluster() {}
|
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
|
||||||
WeakProperty* property = static_cast<WeakProperty*>(object);
|
|
||||||
objects_.Add(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RetraceEphemerons(MessageSerializer* s) {
|
|
||||||
for (intptr_t i = 0; i < objects_.length(); i++) {
|
|
||||||
WeakProperty* property = objects_[i];
|
|
||||||
if (s->HasRef(property->untag()->key())) {
|
|
||||||
s->Push(property->untag()->value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
s->WriteUnsigned(count);
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
WeakProperty* property = objects_[i];
|
|
||||||
s->AssignRef(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteEdges(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
WeakProperty* property = objects_[i];
|
|
||||||
if (s->HasRef(property->untag()->key())) {
|
|
||||||
s->WriteRef(property->untag()->key());
|
|
||||||
s->WriteRef(property->untag()->value());
|
|
||||||
} else {
|
|
||||||
s->WriteRef(Object::null());
|
|
||||||
s->WriteRef(Object::null());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GrowableArray<WeakProperty*> objects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WeakPropertyMessageDeserializationCluster
|
|
||||||
: public MessageDeserializationCluster {
|
|
||||||
public:
|
|
||||||
WeakPropertyMessageDeserializationCluster()
|
|
||||||
: MessageDeserializationCluster("WeakProperty") {}
|
|
||||||
~WeakPropertyMessageDeserializationCluster() {}
|
|
||||||
|
|
||||||
void ReadNodes(MessageDeserializer* d) {
|
|
||||||
const intptr_t count = d->ReadUnsigned();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
d->AssignRef(WeakProperty::New());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadEdges(MessageDeserializer* d) {
|
|
||||||
ASSERT(!is_canonical()); // Never canonical.
|
|
||||||
for (intptr_t id = start_index_; id < stop_index_; id++) {
|
|
||||||
WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
|
|
||||||
property->untag()->set_key(d->ReadRef());
|
|
||||||
property->untag()->set_value(d->ReadRef());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class WeakReferenceMessageSerializationCluster
|
|
||||||
: public MessageSerializationCluster {
|
|
||||||
public:
|
|
||||||
WeakReferenceMessageSerializationCluster()
|
|
||||||
: MessageSerializationCluster("WeakReference",
|
|
||||||
MessagePhase::kNonCanonicalInstances,
|
|
||||||
kWeakReferenceCid) {}
|
|
||||||
~WeakReferenceMessageSerializationCluster() {}
|
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
|
||||||
WeakReference* reference = static_cast<WeakReference*>(object);
|
|
||||||
objects_.Add(reference);
|
|
||||||
|
|
||||||
s->Push(reference->untag()->type_arguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
s->WriteUnsigned(count);
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
WeakReference* reference = objects_[i];
|
|
||||||
s->AssignRef(reference);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteEdges(MessageSerializer* s) {
|
|
||||||
const intptr_t count = objects_.length();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
WeakReference* reference = objects_[i];
|
|
||||||
if (s->HasRef(reference->untag()->target())) {
|
|
||||||
s->WriteRef(reference->untag()->target());
|
|
||||||
} else {
|
|
||||||
s->WriteRef(Object::null());
|
|
||||||
}
|
|
||||||
s->WriteRef(reference->untag()->type_arguments());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
GrowableArray<WeakReference*> objects_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WeakReferenceMessageDeserializationCluster
|
|
||||||
: public MessageDeserializationCluster {
|
|
||||||
public:
|
|
||||||
WeakReferenceMessageDeserializationCluster()
|
|
||||||
: MessageDeserializationCluster("WeakReference") {}
|
|
||||||
~WeakReferenceMessageDeserializationCluster() {}
|
|
||||||
|
|
||||||
void ReadNodes(MessageDeserializer* d) {
|
|
||||||
const intptr_t count = d->ReadUnsigned();
|
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
|
||||||
d->AssignRef(WeakReference::New());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadEdges(MessageDeserializer* d) {
|
|
||||||
ASSERT(!is_canonical()); // Never canonical.
|
|
||||||
for (intptr_t id = start_index_; id < stop_index_; id++) {
|
|
||||||
WeakReferencePtr reference = static_cast<WeakReferencePtr>(d->Ref(id));
|
|
||||||
reference->untag()->set_target(d->ReadRef());
|
|
||||||
reference->untag()->set_type_arguments(
|
|
||||||
static_cast<TypeArgumentsPtr>(d->ReadRef()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class LinkedHashMapMessageSerializationCluster
|
class LinkedHashMapMessageSerializationCluster
|
||||||
: public MessageSerializationCluster {
|
: public MessageSerializationCluster {
|
||||||
public:
|
public:
|
||||||
|
@ -2641,6 +2199,14 @@ class LinkedHashMapMessageSerializationCluster
|
||||||
LinkedHashMap* map = static_cast<LinkedHashMap*>(object);
|
LinkedHashMap* map = static_cast<LinkedHashMap*>(object);
|
||||||
objects_.Add(map);
|
objects_.Add(map);
|
||||||
|
|
||||||
|
// Compensation for bogus type prefix optimization.
|
||||||
|
TypeArguments& args =
|
||||||
|
TypeArguments::Handle(s->zone(), map->untag()->type_arguments());
|
||||||
|
if (!args.IsNull() && (args.Length() != 2)) {
|
||||||
|
args = args.TruncatedTo(2);
|
||||||
|
map->untag()->set_type_arguments(args.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
s->Push(map->untag()->type_arguments());
|
s->Push(map->untag()->type_arguments());
|
||||||
s->Push(map->untag()->data());
|
s->Push(map->untag()->data());
|
||||||
s->Push(map->untag()->used_data());
|
s->Push(map->untag()->used_data());
|
||||||
|
@ -2734,30 +2300,38 @@ class LinkedHashSetMessageSerializationCluster
|
||||||
~LinkedHashSetMessageSerializationCluster() {}
|
~LinkedHashSetMessageSerializationCluster() {}
|
||||||
|
|
||||||
void Trace(MessageSerializer* s, Object* object) {
|
void Trace(MessageSerializer* s, Object* object) {
|
||||||
LinkedHashSet* map = static_cast<LinkedHashSet*>(object);
|
LinkedHashSet* set = static_cast<LinkedHashSet*>(object);
|
||||||
objects_.Add(map);
|
objects_.Add(set);
|
||||||
|
|
||||||
s->Push(map->untag()->type_arguments());
|
// Compensation for bogus type prefix optimization.
|
||||||
s->Push(map->untag()->data());
|
TypeArguments& args =
|
||||||
s->Push(map->untag()->used_data());
|
TypeArguments::Handle(s->zone(), set->untag()->type_arguments());
|
||||||
|
if (!args.IsNull() && (args.Length() != 1)) {
|
||||||
|
args = args.TruncatedTo(1);
|
||||||
|
set->untag()->set_type_arguments(args.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
s->Push(set->untag()->type_arguments());
|
||||||
|
s->Push(set->untag()->data());
|
||||||
|
s->Push(set->untag()->used_data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteNodes(MessageSerializer* s) {
|
void WriteNodes(MessageSerializer* s) {
|
||||||
const intptr_t count = objects_.length();
|
const intptr_t count = objects_.length();
|
||||||
s->WriteUnsigned(count);
|
s->WriteUnsigned(count);
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
for (intptr_t i = 0; i < count; i++) {
|
||||||
LinkedHashSet* map = objects_[i];
|
LinkedHashSet* set = objects_[i];
|
||||||
s->AssignRef(map);
|
s->AssignRef(set);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteEdges(MessageSerializer* s) {
|
void WriteEdges(MessageSerializer* s) {
|
||||||
const intptr_t count = objects_.length();
|
const intptr_t count = objects_.length();
|
||||||
for (intptr_t i = 0; i < count; i++) {
|
for (intptr_t i = 0; i < count; i++) {
|
||||||
LinkedHashSet* map = objects_[i];
|
LinkedHashSet* set = objects_[i];
|
||||||
s->WriteRef(map->untag()->type_arguments());
|
s->WriteRef(set->untag()->type_arguments());
|
||||||
s->WriteRef(map->untag()->data());
|
s->WriteRef(set->untag()->data());
|
||||||
s->WriteRef(map->untag()->used_data());
|
s->WriteRef(set->untag()->used_data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2830,6 +2404,14 @@ class ArrayMessageSerializationCluster : public MessageSerializationCluster {
|
||||||
Array* array = static_cast<Array*>(object);
|
Array* array = static_cast<Array*>(object);
|
||||||
objects_.Add(array);
|
objects_.Add(array);
|
||||||
|
|
||||||
|
// Compensation for bogus type prefix optimization.
|
||||||
|
TypeArguments& args =
|
||||||
|
TypeArguments::Handle(s->zone(), array->untag()->type_arguments());
|
||||||
|
if (!args.IsNull() && (args.Length() != 1)) {
|
||||||
|
args = args.TruncatedTo(1);
|
||||||
|
array->untag()->set_type_arguments(args.ptr());
|
||||||
|
}
|
||||||
|
|
||||||
s->Push(array->untag()->type_arguments());
|
s->Push(array->untag()->type_arguments());
|
||||||
intptr_t length = Smi::Value(array->untag()->length());
|
intptr_t length = Smi::Value(array->untag()->length());
|
||||||
for (intptr_t i = 0; i < length; i++) {
|
for (intptr_t i = 0; i < length; i++) {
|
||||||
|
@ -3201,7 +2783,6 @@ BaseSerializer::BaseSerializer(Thread* thread, Zone* zone)
|
||||||
stream_(100),
|
stream_(100),
|
||||||
finalizable_data_(new MessageFinalizableData()),
|
finalizable_data_(new MessageFinalizableData()),
|
||||||
clusters_(zone, 0),
|
clusters_(zone, 0),
|
||||||
ephemeron_cluster_(nullptr),
|
|
||||||
num_base_objects_(0),
|
num_base_objects_(0),
|
||||||
num_written_objects_(0),
|
num_written_objects_(0),
|
||||||
next_ref_index_(kFirstReference) {}
|
next_ref_index_(kFirstReference) {}
|
||||||
|
@ -3263,18 +2844,8 @@ void MessageSerializer::Trace(Object* object) {
|
||||||
}
|
}
|
||||||
if (cluster == nullptr) {
|
if (cluster == nullptr) {
|
||||||
if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
|
if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
|
||||||
const Class& clazz =
|
|
||||||
Class::Handle(zone(), isolate_group()->class_table()->At(cid));
|
|
||||||
ObjectStore* object_store = isolate_group()->object_store();
|
|
||||||
if ((clazz.library() != object_store->core_library()) &&
|
|
||||||
(clazz.library() != object_store->collection_library()) &&
|
|
||||||
(clazz.library() != object_store->typed_data_library())) {
|
|
||||||
IllegalObject(*object, "is a regular instance");
|
IllegalObject(*object, "is a regular instance");
|
||||||
}
|
}
|
||||||
if (clazz.num_native_fields() != 0) {
|
|
||||||
IllegalObject(*object, "is a NativeWrapper");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep the list in sync with the one in lib/isolate.cc
|
// Keep the list in sync with the one in lib/isolate.cc
|
||||||
#define ILLEGAL(type) \
|
#define ILLEGAL(type) \
|
||||||
|
@ -3283,16 +2854,23 @@ void MessageSerializer::Trace(Object* object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ILLEGAL(Closure)
|
ILLEGAL(Closure)
|
||||||
|
ILLEGAL(Finalizer)
|
||||||
|
ILLEGAL(FinalizerEntry)
|
||||||
ILLEGAL(FunctionType)
|
ILLEGAL(FunctionType)
|
||||||
ILLEGAL(MirrorReference)
|
ILLEGAL(MirrorReference)
|
||||||
|
ILLEGAL(NativeFinalizer)
|
||||||
ILLEGAL(ReceivePort)
|
ILLEGAL(ReceivePort)
|
||||||
|
ILLEGAL(RegExp)
|
||||||
ILLEGAL(StackTrace)
|
ILLEGAL(StackTrace)
|
||||||
ILLEGAL(SuspendState)
|
ILLEGAL(SuspendState)
|
||||||
ILLEGAL(UserTag)
|
ILLEGAL(UserTag)
|
||||||
|
ILLEGAL(WeakProperty)
|
||||||
|
ILLEGAL(WeakReference)
|
||||||
|
|
||||||
// TODO(dartbug.com/49719): allow sending records as long as their
|
// TODO(dartbug.com/49719): allow sending records as long as their
|
||||||
// elements are objects that can be sent.
|
// elements are objects that can be sent.
|
||||||
ILLEGAL(RecordType)
|
ILLEGAL(RecordType)
|
||||||
|
ILLEGAL(Record)
|
||||||
|
|
||||||
// From "dart:ffi" we handle only Pointer/DynamicLibrary specially, since
|
// From "dart:ffi" we handle only Pointer/DynamicLibrary specially, since
|
||||||
// those are the only non-abstract classes (so we avoid checking more cids
|
// those are the only non-abstract classes (so we avoid checking more cids
|
||||||
|
@ -3302,10 +2880,6 @@ void MessageSerializer::Trace(Object* object) {
|
||||||
|
|
||||||
#undef ILLEGAL
|
#undef ILLEGAL
|
||||||
|
|
||||||
if (cid >= kNumPredefinedCids || cid == kInstanceCid ||
|
|
||||||
cid == kByteBufferCid) {
|
|
||||||
Push(isolate_group()->class_table()->At(cid));
|
|
||||||
}
|
|
||||||
cluster = NewClusterForClass(cid, is_canonical);
|
cluster = NewClusterForClass(cid, is_canonical);
|
||||||
clusters_.Add(cluster);
|
clusters_.Add(cluster);
|
||||||
}
|
}
|
||||||
|
@ -3567,10 +3141,6 @@ MessageSerializationCluster* BaseSerializer::NewClusterForClass(
|
||||||
intptr_t cid,
|
intptr_t cid,
|
||||||
bool is_canonical) {
|
bool is_canonical) {
|
||||||
Zone* Z = zone_;
|
Zone* Z = zone_;
|
||||||
if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
|
|
||||||
(cid == kByteBufferCid)) {
|
|
||||||
return new (Z) InstanceMessageSerializationCluster(is_canonical, cid);
|
|
||||||
}
|
|
||||||
if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid ||
|
if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid ||
|
||||||
IsUnmodifiableTypedDataViewClassId(cid) ||
|
IsUnmodifiableTypedDataViewClassId(cid) ||
|
||||||
cid == kUnmodifiableByteDataViewCid) {
|
cid == kUnmodifiableByteDataViewCid) {
|
||||||
|
@ -3590,8 +3160,6 @@ MessageSerializationCluster* BaseSerializer::NewClusterForClass(
|
||||||
return new (Z) ClassMessageSerializationCluster();
|
return new (Z) ClassMessageSerializationCluster();
|
||||||
case kTypeArgumentsCid:
|
case kTypeArgumentsCid:
|
||||||
return new (Z) TypeArgumentsMessageSerializationCluster(is_canonical);
|
return new (Z) TypeArgumentsMessageSerializationCluster(is_canonical);
|
||||||
case kFunctionCid:
|
|
||||||
return new (Z) FunctionMessageSerializationCluster();
|
|
||||||
case kTypeCid:
|
case kTypeCid:
|
||||||
return new (Z) TypeMessageSerializationCluster(is_canonical);
|
return new (Z) TypeMessageSerializationCluster(is_canonical);
|
||||||
case kTypeRefCid:
|
case kTypeRefCid:
|
||||||
|
@ -3604,19 +3172,12 @@ MessageSerializationCluster* BaseSerializer::NewClusterForClass(
|
||||||
return new (Z) DoubleMessageSerializationCluster(Z, is_canonical);
|
return new (Z) DoubleMessageSerializationCluster(Z, is_canonical);
|
||||||
case kGrowableObjectArrayCid:
|
case kGrowableObjectArrayCid:
|
||||||
return new (Z) GrowableObjectArrayMessageSerializationCluster();
|
return new (Z) GrowableObjectArrayMessageSerializationCluster();
|
||||||
case kRegExpCid:
|
|
||||||
return new (Z) RegExpMessageSerializationCluster();
|
|
||||||
case kSendPortCid:
|
case kSendPortCid:
|
||||||
return new (Z) SendPortMessageSerializationCluster(Z);
|
return new (Z) SendPortMessageSerializationCluster(Z);
|
||||||
case kCapabilityCid:
|
case kCapabilityCid:
|
||||||
return new (Z) CapabilityMessageSerializationCluster(Z);
|
return new (Z) CapabilityMessageSerializationCluster(Z);
|
||||||
case kTransferableTypedDataCid:
|
case kTransferableTypedDataCid:
|
||||||
return new (Z) TransferableTypedDataMessageSerializationCluster();
|
return new (Z) TransferableTypedDataMessageSerializationCluster();
|
||||||
case kWeakPropertyCid:
|
|
||||||
ephemeron_cluster_ = new (Z) WeakPropertyMessageSerializationCluster();
|
|
||||||
return ephemeron_cluster_;
|
|
||||||
case kWeakReferenceCid:
|
|
||||||
return new (Z) WeakReferenceMessageSerializationCluster();
|
|
||||||
case kLinkedHashMapCid:
|
case kLinkedHashMapCid:
|
||||||
case kImmutableLinkedHashMapCid:
|
case kImmutableLinkedHashMapCid:
|
||||||
return new (Z)
|
return new (Z)
|
||||||
|
@ -3656,10 +3217,6 @@ MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
|
||||||
const bool is_canonical = (cid_and_canonical & 0x1) == 0x1;
|
const bool is_canonical = (cid_and_canonical & 0x1) == 0x1;
|
||||||
|
|
||||||
Zone* Z = zone_;
|
Zone* Z = zone_;
|
||||||
if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
|
|
||||||
(cid == kByteBufferCid)) {
|
|
||||||
return new (Z) InstanceMessageDeserializationCluster(is_canonical);
|
|
||||||
}
|
|
||||||
if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid ||
|
if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid ||
|
||||||
IsUnmodifiableTypedDataViewClassId(cid) ||
|
IsUnmodifiableTypedDataViewClassId(cid) ||
|
||||||
cid == kUnmodifiableByteDataViewCid) {
|
cid == kUnmodifiableByteDataViewCid) {
|
||||||
|
@ -3684,9 +3241,6 @@ MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
|
||||||
return new (Z) ClassMessageDeserializationCluster();
|
return new (Z) ClassMessageDeserializationCluster();
|
||||||
case kTypeArgumentsCid:
|
case kTypeArgumentsCid:
|
||||||
return new (Z) TypeArgumentsMessageDeserializationCluster(is_canonical);
|
return new (Z) TypeArgumentsMessageDeserializationCluster(is_canonical);
|
||||||
case kFunctionCid:
|
|
||||||
ASSERT(!is_canonical);
|
|
||||||
return new (Z) FunctionMessageDeserializationCluster();
|
|
||||||
case kTypeCid:
|
case kTypeCid:
|
||||||
return new (Z) TypeMessageDeserializationCluster(is_canonical);
|
return new (Z) TypeMessageDeserializationCluster(is_canonical);
|
||||||
case kTypeRefCid:
|
case kTypeRefCid:
|
||||||
|
@ -3701,9 +3255,6 @@ MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
|
||||||
case kGrowableObjectArrayCid:
|
case kGrowableObjectArrayCid:
|
||||||
ASSERT(!is_canonical);
|
ASSERT(!is_canonical);
|
||||||
return new (Z) GrowableObjectArrayMessageDeserializationCluster();
|
return new (Z) GrowableObjectArrayMessageDeserializationCluster();
|
||||||
case kRegExpCid:
|
|
||||||
ASSERT(!is_canonical);
|
|
||||||
return new (Z) RegExpMessageDeserializationCluster();
|
|
||||||
case kSendPortCid:
|
case kSendPortCid:
|
||||||
ASSERT(!is_canonical);
|
ASSERT(!is_canonical);
|
||||||
return new (Z) SendPortMessageDeserializationCluster();
|
return new (Z) SendPortMessageDeserializationCluster();
|
||||||
|
@ -3713,12 +3264,6 @@ MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
|
||||||
case kTransferableTypedDataCid:
|
case kTransferableTypedDataCid:
|
||||||
ASSERT(!is_canonical);
|
ASSERT(!is_canonical);
|
||||||
return new (Z) TransferableTypedDataMessageDeserializationCluster();
|
return new (Z) TransferableTypedDataMessageDeserializationCluster();
|
||||||
case kWeakPropertyCid:
|
|
||||||
ASSERT(!is_canonical);
|
|
||||||
return new (Z) WeakPropertyMessageDeserializationCluster();
|
|
||||||
case kWeakReferenceCid:
|
|
||||||
ASSERT(!is_canonical);
|
|
||||||
return new (Z) WeakReferenceMessageDeserializationCluster();
|
|
||||||
case kLinkedHashMapCid:
|
case kLinkedHashMapCid:
|
||||||
case kImmutableLinkedHashMapCid:
|
case kImmutableLinkedHashMapCid:
|
||||||
return new (Z)
|
return new (Z)
|
||||||
|
@ -3804,18 +3349,10 @@ void MessageSerializer::Serialize(const Object& root) {
|
||||||
|
|
||||||
Push(root.ptr());
|
Push(root.ptr());
|
||||||
|
|
||||||
while (stack_.length() > 0) {
|
|
||||||
// Strong references.
|
|
||||||
while (stack_.length() > 0) {
|
while (stack_.length() > 0) {
|
||||||
Trace(stack_.RemoveLast());
|
Trace(stack_.RemoveLast());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ephemeron references.
|
|
||||||
if (ephemeron_cluster_ != nullptr) {
|
|
||||||
ephemeron_cluster_->RetraceEphemerons(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t num_objects = num_base_objects_ + num_written_objects_;
|
intptr_t num_objects = num_base_objects_ + num_written_objects_;
|
||||||
WriteUnsigned(num_base_objects_);
|
WriteUnsigned(num_base_objects_);
|
||||||
WriteUnsigned(num_objects);
|
WriteUnsigned(num_objects);
|
||||||
|
|
|
@ -6962,6 +6962,19 @@ bool TypeArguments::CanShareFunctionTypeArguments(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeArgumentsPtr TypeArguments::TruncatedTo(intptr_t length) const {
|
||||||
|
Thread* thread = Thread::Current();
|
||||||
|
Zone* zone = thread->zone();
|
||||||
|
const TypeArguments& result =
|
||||||
|
TypeArguments::Handle(zone, TypeArguments::New(length));
|
||||||
|
AbstractType& type = AbstractType::Handle(zone);
|
||||||
|
for (intptr_t i = 0; i < length; i++) {
|
||||||
|
type = TypeAt(i);
|
||||||
|
result.SetTypeAt(i, type);
|
||||||
|
}
|
||||||
|
return result.Canonicalize(thread);
|
||||||
|
}
|
||||||
|
|
||||||
bool TypeArguments::IsFinalized() const {
|
bool TypeArguments::IsFinalized() const {
|
||||||
ASSERT(!IsNull());
|
ASSERT(!IsNull());
|
||||||
AbstractType& type = AbstractType::Handle();
|
AbstractType& type = AbstractType::Handle();
|
||||||
|
@ -10400,7 +10413,7 @@ bool Function::HasDynamicCallers(Zone* zone) const {
|
||||||
// Issue(dartbug.com/42719):
|
// Issue(dartbug.com/42719):
|
||||||
// Right now the metadata of _Closure.call says there are no dynamic callers -
|
// Right now the metadata of _Closure.call says there are no dynamic callers -
|
||||||
// even though there can be. To be conservative we return true.
|
// even though there can be. To be conservative we return true.
|
||||||
if ((name() == Symbols::GetCall().ptr() || name() == Symbols::Call().ptr()) &&
|
if ((name() == Symbols::GetCall().ptr() || name() == Symbols::call().ptr()) &&
|
||||||
Class::IsClosureClass(Owner())) {
|
Class::IsClosureClass(Owner())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -20053,7 +20066,7 @@ bool Instance::IsCallable(Function* function) const {
|
||||||
// Try to resolve a "call" method.
|
// Try to resolve a "call" method.
|
||||||
Zone* zone = Thread::Current()->zone();
|
Zone* zone = Thread::Current()->zone();
|
||||||
Function& call_function = Function::Handle(
|
Function& call_function = Function::Handle(
|
||||||
zone, Resolver::ResolveDynamicAnyArgs(zone, cls, Symbols::Call(),
|
zone, Resolver::ResolveDynamicAnyArgs(zone, cls, Symbols::call(),
|
||||||
/*allow_add=*/false));
|
/*allow_add=*/false));
|
||||||
if (call_function.IsNull()) {
|
if (call_function.IsNull()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -20724,6 +20737,48 @@ bool AbstractType::IsFfiPointerType() const {
|
||||||
return HasTypeClass() && type_class_id() == kPointerCid;
|
return HasTypeClass() && type_class_id() == kPointerCid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AbstractType::IsTypeClassAllowedBySpawnUri() const {
|
||||||
|
if (!HasTypeClass()) return false;
|
||||||
|
|
||||||
|
intptr_t cid = type_class_id();
|
||||||
|
|
||||||
|
if (cid == kBoolCid) return true;
|
||||||
|
if (cid == kDynamicCid) return true;
|
||||||
|
if (cid == kInstanceCid) return true; // Object.
|
||||||
|
if (cid == kNeverCid) return true;
|
||||||
|
if (cid == kNullCid) return true;
|
||||||
|
if (cid == kVoidCid) return true;
|
||||||
|
|
||||||
|
// These are not constant CID checks because kDoubleCid refers to _Double
|
||||||
|
// not double, etc.
|
||||||
|
ObjectStore* object_store = IsolateGroup::Current()->object_store();
|
||||||
|
Type& candidate_type = Type::Handle();
|
||||||
|
candidate_type = object_store->int_type();
|
||||||
|
if (cid == candidate_type.type_class_id()) return true;
|
||||||
|
candidate_type = object_store->double_type();
|
||||||
|
if (cid == candidate_type.type_class_id()) return true;
|
||||||
|
candidate_type = object_store->number_type();
|
||||||
|
if (cid == candidate_type.type_class_id()) return true;
|
||||||
|
candidate_type = object_store->string_type();
|
||||||
|
if (cid == candidate_type.type_class_id()) return true;
|
||||||
|
|
||||||
|
Class& candidate_cls = Class::Handle();
|
||||||
|
candidate_cls = object_store->list_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
candidate_cls = object_store->map_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
candidate_cls = object_store->set_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
candidate_cls = object_store->capability_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
candidate_cls = object_store->send_port_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
candidate_cls = object_store->transferable_class();
|
||||||
|
if (cid == candidate_cls.id()) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AbstractTypePtr AbstractType::UnwrapFutureOr() const {
|
AbstractTypePtr AbstractType::UnwrapFutureOr() const {
|
||||||
// Works properly for a TypeRef without dereferencing it.
|
// Works properly for a TypeRef without dereferencing it.
|
||||||
if (!IsFutureOrType()) {
|
if (!IsFutureOrType()) {
|
||||||
|
@ -27035,13 +27090,13 @@ EntryPointPragma FindEntryPointPragma(IsolateGroup* IG,
|
||||||
return EntryPointPragma::kAlways;
|
return EntryPointPragma::kAlways;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pragma->ptr() == Symbols::Get().ptr()) {
|
if (pragma->ptr() == Symbols::get().ptr()) {
|
||||||
return EntryPointPragma::kGetterOnly;
|
return EntryPointPragma::kGetterOnly;
|
||||||
}
|
}
|
||||||
if (pragma->ptr() == Symbols::Set().ptr()) {
|
if (pragma->ptr() == Symbols::set().ptr()) {
|
||||||
return EntryPointPragma::kSetterOnly;
|
return EntryPointPragma::kSetterOnly;
|
||||||
}
|
}
|
||||||
if (pragma->ptr() == Symbols::Call().ptr()) {
|
if (pragma->ptr() == Symbols::call().ptr()) {
|
||||||
return EntryPointPragma::kCallOnly;
|
return EntryPointPragma::kCallOnly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8067,6 +8067,7 @@ class TypeArguments : public Instance {
|
||||||
bool* with_runtime_check = nullptr) const;
|
bool* with_runtime_check = nullptr) const;
|
||||||
bool CanShareFunctionTypeArguments(const Function& function,
|
bool CanShareFunctionTypeArguments(const Function& function,
|
||||||
bool* with_runtime_check = nullptr) const;
|
bool* with_runtime_check = nullptr) const;
|
||||||
|
TypeArgumentsPtr TruncatedTo(intptr_t length) const;
|
||||||
|
|
||||||
// Return true if all types of this vector are finalized.
|
// Return true if all types of this vector are finalized.
|
||||||
bool IsFinalized() const;
|
bool IsFinalized() const;
|
||||||
|
@ -8435,6 +8436,11 @@ class AbstractType : public Instance {
|
||||||
// non-nullable Object is also a catch-all type.
|
// non-nullable Object is also a catch-all type.
|
||||||
bool IsCatchAllType() const { return IsDynamicType() || IsObjectType(); }
|
bool IsCatchAllType() const { return IsDynamicType() || IsObjectType(); }
|
||||||
|
|
||||||
|
// Returns true if this type has a type class permitted by SendPort.send for
|
||||||
|
// messages between isolates in different groups. Does not recursively visit
|
||||||
|
// type arguments.
|
||||||
|
bool IsTypeClassAllowedBySpawnUri() const;
|
||||||
|
|
||||||
// Check the subtype relationship.
|
// Check the subtype relationship.
|
||||||
bool IsSubtypeOf(const AbstractType& other,
|
bool IsSubtypeOf(const AbstractType& other,
|
||||||
Heap::Space space,
|
Heap::Space space,
|
||||||
|
|
|
@ -446,9 +446,15 @@ void ObjectStore::LazyInitCoreMembers() {
|
||||||
|
|
||||||
cls = core_lib.LookupClass(Symbols::Map());
|
cls = core_lib.LookupClass(Symbols::Map());
|
||||||
ASSERT(!cls.IsNull());
|
ASSERT(!cls.IsNull());
|
||||||
|
map_class_.store(cls.ptr());
|
||||||
|
|
||||||
type ^= cls.RareType();
|
type ^= cls.RareType();
|
||||||
non_nullable_map_rare_type_.store(type.ptr());
|
non_nullable_map_rare_type_.store(type.ptr());
|
||||||
|
|
||||||
|
cls = core_lib.LookupClass(Symbols::Set());
|
||||||
|
ASSERT(!cls.IsNull());
|
||||||
|
set_class_.store(cls.ptr());
|
||||||
|
|
||||||
auto& field = Field::Handle(zone);
|
auto& field = Field::Handle(zone);
|
||||||
|
|
||||||
cls = core_lib.LookupClassAllowPrivate(Symbols::_Enum());
|
cls = core_lib.LookupClassAllowPrivate(Symbols::_Enum());
|
||||||
|
@ -563,6 +569,18 @@ void ObjectStore::LazyInitIsolateMembers() {
|
||||||
auto& cls = Class::Handle(zone);
|
auto& cls = Class::Handle(zone);
|
||||||
auto& function = Function::Handle(zone);
|
auto& function = Function::Handle(zone);
|
||||||
|
|
||||||
|
cls = isolate_lib.LookupClass(Symbols::Capability());
|
||||||
|
ASSERT(!cls.IsNull());
|
||||||
|
capability_class_.store(cls.ptr());
|
||||||
|
|
||||||
|
cls = isolate_lib.LookupClass(Symbols::SendPort());
|
||||||
|
ASSERT(!cls.IsNull());
|
||||||
|
send_port_class_.store(cls.ptr());
|
||||||
|
|
||||||
|
cls = isolate_lib.LookupClass(Symbols::TransferableTypedData());
|
||||||
|
ASSERT(!cls.IsNull());
|
||||||
|
transferable_class_.store(cls.ptr());
|
||||||
|
|
||||||
cls = isolate_lib.LookupClassAllowPrivate(Symbols::_RawReceivePortImpl());
|
cls = isolate_lib.LookupClassAllowPrivate(Symbols::_RawReceivePortImpl());
|
||||||
ASSERT(!cls.IsNull());
|
ASSERT(!cls.IsNull());
|
||||||
const auto& error = cls.EnsureIsFinalized(thread);
|
const auto& error = cls.EnsureIsFinalized(thread);
|
||||||
|
|
|
@ -46,6 +46,8 @@ class ObjectPointerVisitor;
|
||||||
LAZY_ASYNC, LAZY_ISOLATE, LAZY_INTERNAL, \
|
LAZY_ASYNC, LAZY_ISOLATE, LAZY_INTERNAL, \
|
||||||
LAZY_FFI) \
|
LAZY_FFI) \
|
||||||
LAZY_CORE(Class, list_class) \
|
LAZY_CORE(Class, list_class) \
|
||||||
|
LAZY_CORE(Class, map_class) \
|
||||||
|
LAZY_CORE(Class, set_class) \
|
||||||
LAZY_CORE(Type, non_nullable_list_rare_type) \
|
LAZY_CORE(Type, non_nullable_list_rare_type) \
|
||||||
LAZY_CORE(Type, non_nullable_map_rare_type) \
|
LAZY_CORE(Type, non_nullable_map_rare_type) \
|
||||||
LAZY_CORE(Field, enum_index_field) \
|
LAZY_CORE(Field, enum_index_field) \
|
||||||
|
@ -60,6 +62,9 @@ class ObjectPointerVisitor;
|
||||||
LAZY_ASYNC(Type, non_nullable_future_rare_type) \
|
LAZY_ASYNC(Type, non_nullable_future_rare_type) \
|
||||||
LAZY_ASYNC(Type, non_nullable_future_never_type) \
|
LAZY_ASYNC(Type, non_nullable_future_never_type) \
|
||||||
LAZY_ASYNC(Type, nullable_future_null_type) \
|
LAZY_ASYNC(Type, nullable_future_null_type) \
|
||||||
|
LAZY_ISOLATE(Class, send_port_class) \
|
||||||
|
LAZY_ISOLATE(Class, capability_class) \
|
||||||
|
LAZY_ISOLATE(Class, transferable_class) \
|
||||||
LAZY_ISOLATE(Function, lookup_port_handler) \
|
LAZY_ISOLATE(Function, lookup_port_handler) \
|
||||||
LAZY_ISOLATE(Function, lookup_open_ports) \
|
LAZY_ISOLATE(Function, lookup_open_ports) \
|
||||||
LAZY_ISOLATE(Function, handle_message_function) \
|
LAZY_ISOLATE(Function, handle_message_function) \
|
||||||
|
|
|
@ -2636,7 +2636,7 @@ static ObjectPtr InvokeCallThroughGetterOrNoSuchMethod(
|
||||||
// o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
|
// o.foo(...) failed, invoke noSuchMethod is foo exists but has the wrong
|
||||||
// number of arguments, or try (o.foo).call(...)
|
// number of arguments, or try (o.foo).call(...)
|
||||||
|
|
||||||
if ((target_name.ptr() == Symbols::Call().ptr()) && receiver.IsClosure()) {
|
if ((target_name.ptr() == Symbols::call().ptr()) && receiver.IsClosure()) {
|
||||||
// Special case: closures are implemented with a call getter instead of a
|
// Special case: closures are implemented with a call getter instead of a
|
||||||
// call method and with lazy dispatchers the field-invocation-dispatcher
|
// call method and with lazy dispatchers the field-invocation-dispatcher
|
||||||
// would perform the closure call.
|
// would perform the closure call.
|
||||||
|
|
|
@ -31,7 +31,7 @@ class ObjectPointerVisitor;
|
||||||
V(BooleanExpression, "boolean expression") \
|
V(BooleanExpression, "boolean expression") \
|
||||||
V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation") \
|
V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation") \
|
||||||
V(ByteData, "ByteData") \
|
V(ByteData, "ByteData") \
|
||||||
V(Call, "call") \
|
V(Capability, "Capability") \
|
||||||
V(CastError, "_CastError") \
|
V(CastError, "_CastError") \
|
||||||
V(CheckLoaded, "_checkLoaded") \
|
V(CheckLoaded, "_checkLoaded") \
|
||||||
V(Class, "Class") \
|
V(Class, "Class") \
|
||||||
|
@ -73,8 +73,8 @@ class ObjectPointerVisitor;
|
||||||
V(Default, "Default") \
|
V(Default, "Default") \
|
||||||
V(DefaultLabel, ":L") \
|
V(DefaultLabel, ":L") \
|
||||||
V(DotCreate, "._create") \
|
V(DotCreate, "._create") \
|
||||||
V(DotFieldNI, ".fieldNI") \
|
|
||||||
V(DotFieldADI, ".fieldADI") \
|
V(DotFieldADI, ".fieldADI") \
|
||||||
|
V(DotFieldNI, ".fieldNI") \
|
||||||
V(DotRange, ".range") \
|
V(DotRange, ".range") \
|
||||||
V(DotUnder, "._") \
|
V(DotUnder, "._") \
|
||||||
V(DotValue, ".value") \
|
V(DotValue, ".value") \
|
||||||
|
@ -82,8 +82,8 @@ class ObjectPointerVisitor;
|
||||||
V(Double, "double") \
|
V(Double, "double") \
|
||||||
V(Dynamic, "dynamic") \
|
V(Dynamic, "dynamic") \
|
||||||
V(DynamicCall, "dyn:call") \
|
V(DynamicCall, "dyn:call") \
|
||||||
V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed") \
|
|
||||||
V(DynamicCallCurrentFunctionVar, ":dyn_call_current_function") \
|
V(DynamicCallCurrentFunctionVar, ":dyn_call_current_function") \
|
||||||
|
V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed") \
|
||||||
V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index") \
|
V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index") \
|
||||||
V(DynamicCallCurrentTypeParamVar, ":dyn_call_current_type_param") \
|
V(DynamicCallCurrentTypeParamVar, ":dyn_call_current_type_param") \
|
||||||
V(DynamicCallFunctionTypeArgsVar, ":dyn_call_function_type_args") \
|
V(DynamicCallFunctionTypeArgsVar, ":dyn_call_function_type_args") \
|
||||||
|
@ -110,6 +110,7 @@ class ObjectPointerVisitor;
|
||||||
V(FfiFieldPacking, "packing") \
|
V(FfiFieldPacking, "packing") \
|
||||||
V(FfiFieldTypes, "fieldTypes") \
|
V(FfiFieldTypes, "fieldTypes") \
|
||||||
V(FfiFloat, "Float") \
|
V(FfiFloat, "Float") \
|
||||||
|
V(FfiHandle, "Handle") \
|
||||||
V(FfiInt16, "Int16") \
|
V(FfiInt16, "Int16") \
|
||||||
V(FfiInt32, "Int32") \
|
V(FfiInt32, "Int32") \
|
||||||
V(FfiInt64, "Int64") \
|
V(FfiInt64, "Int64") \
|
||||||
|
@ -127,7 +128,6 @@ class ObjectPointerVisitor;
|
||||||
V(FfiUint64, "Uint64") \
|
V(FfiUint64, "Uint64") \
|
||||||
V(FfiUint8, "Uint8") \
|
V(FfiUint8, "Uint8") \
|
||||||
V(FfiVoid, "Void") \
|
V(FfiVoid, "Void") \
|
||||||
V(FfiHandle, "Handle") \
|
|
||||||
V(Field, "Field") \
|
V(Field, "Field") \
|
||||||
V(Finalizable, "Finalizable") \
|
V(Finalizable, "Finalizable") \
|
||||||
V(FinalizerBase, "FinalizerBase") \
|
V(FinalizerBase, "FinalizerBase") \
|
||||||
|
@ -150,7 +150,6 @@ class ObjectPointerVisitor;
|
||||||
V(FutureImpl, "_Future") \
|
V(FutureImpl, "_Future") \
|
||||||
V(FutureOr, "FutureOr") \
|
V(FutureOr, "FutureOr") \
|
||||||
V(FutureValue, "Future.value") \
|
V(FutureValue, "Future.value") \
|
||||||
V(Get, "get") \
|
|
||||||
V(GetCall, "get:call") \
|
V(GetCall, "get:call") \
|
||||||
V(GetLength, "get:length") \
|
V(GetLength, "get:length") \
|
||||||
V(GetRuntimeType, "get:runtimeType") \
|
V(GetRuntimeType, "get:runtimeType") \
|
||||||
|
@ -193,6 +192,7 @@ class ObjectPointerVisitor;
|
||||||
V(ListFactory, "List.") \
|
V(ListFactory, "List.") \
|
||||||
V(ListFilledFactory, "List.filled") \
|
V(ListFilledFactory, "List.filled") \
|
||||||
V(LoadLibrary, "_loadLibrary") \
|
V(LoadLibrary, "_loadLibrary") \
|
||||||
|
V(LoadingUnit, "LoadingUnit") \
|
||||||
V(LocalVarDescriptors, "LocalVarDescriptors") \
|
V(LocalVarDescriptors, "LocalVarDescriptors") \
|
||||||
V(Map, "Map") \
|
V(Map, "Map") \
|
||||||
V(MapLiteralFactory, "Map._fromLiteral") \
|
V(MapLiteralFactory, "Map._fromLiteral") \
|
||||||
|
@ -226,8 +226,9 @@ class ObjectPointerVisitor;
|
||||||
V(SavedTryContextVar, ":saved_try_context_var") \
|
V(SavedTryContextVar, ":saved_try_context_var") \
|
||||||
V(Script, "Script") \
|
V(Script, "Script") \
|
||||||
V(SecondArg, "y") \
|
V(SecondArg, "y") \
|
||||||
|
V(SendPort, "SendPort") \
|
||||||
V(Sentinel, "Sentinel") \
|
V(Sentinel, "Sentinel") \
|
||||||
V(Set, "set") \
|
V(Set, "Set") \
|
||||||
V(SetterPrefix, "set:") \
|
V(SetterPrefix, "set:") \
|
||||||
V(SingleTargetCache, "SingleTargetCache") \
|
V(SingleTargetCache, "SingleTargetCache") \
|
||||||
V(SpaceIsFromSpace, " is from ") \
|
V(SpaceIsFromSpace, " is from ") \
|
||||||
|
@ -239,13 +240,13 @@ class ObjectPointerVisitor;
|
||||||
V(Struct, "Struct") \
|
V(Struct, "Struct") \
|
||||||
V(SubtypeTestCache, "SubtypeTestCache") \
|
V(SubtypeTestCache, "SubtypeTestCache") \
|
||||||
V(SuspendStateVar, ":suspend_state_var") \
|
V(SuspendStateVar, ":suspend_state_var") \
|
||||||
V(LoadingUnit, "LoadingUnit") \
|
|
||||||
V(SwitchExpr, ":switch_expr") \
|
V(SwitchExpr, ":switch_expr") \
|
||||||
V(Symbol, "Symbol") \
|
V(Symbol, "Symbol") \
|
||||||
V(ThrowNew, "_throwNew") \
|
V(ThrowNew, "_throwNew") \
|
||||||
V(ThrowNewInvocation, "_throwNewInvocation") \
|
V(ThrowNewInvocation, "_throwNewInvocation") \
|
||||||
V(ThrowNewNullAssertion, "_throwNewNullAssertion") \
|
V(ThrowNewNullAssertion, "_throwNewNullAssertion") \
|
||||||
V(TopLevel, "::") \
|
V(TopLevel, "::") \
|
||||||
|
V(TransferableTypedData, "TransferableTypedData") \
|
||||||
V(TruncDivOperator, "~/") \
|
V(TruncDivOperator, "~/") \
|
||||||
V(TryFinallyReturnValue, ":try_finally_return_value") \
|
V(TryFinallyReturnValue, ":try_finally_return_value") \
|
||||||
V(TwoByteString, "_TwoByteString") \
|
V(TwoByteString, "_TwoByteString") \
|
||||||
|
@ -262,11 +263,11 @@ class ObjectPointerVisitor;
|
||||||
V(Uint8ClampedList, "Uint8ClampedList") \
|
V(Uint8ClampedList, "Uint8ClampedList") \
|
||||||
V(Uint8List, "Uint8List") \
|
V(Uint8List, "Uint8List") \
|
||||||
V(UnaryMinus, "unary-") \
|
V(UnaryMinus, "unary-") \
|
||||||
V(Union, "Union") \
|
|
||||||
V(UnsignedRightShiftOperator, ">>>") \
|
|
||||||
V(UnhandledException, "UnhandledException") \
|
V(UnhandledException, "UnhandledException") \
|
||||||
|
V(Union, "Union") \
|
||||||
V(UnlinkedCall, "UnlinkedCall") \
|
V(UnlinkedCall, "UnlinkedCall") \
|
||||||
V(UnsafeCast, "unsafeCast") \
|
V(UnsafeCast, "unsafeCast") \
|
||||||
|
V(UnsignedRightShiftOperator, ">>>") \
|
||||||
V(UnsupportedError, "UnsupportedError") \
|
V(UnsupportedError, "UnsupportedError") \
|
||||||
V(UnwindError, "UnwindError") \
|
V(UnwindError, "UnwindError") \
|
||||||
V(Value, "value") \
|
V(Value, "value") \
|
||||||
|
@ -277,7 +278,6 @@ class ObjectPointerVisitor;
|
||||||
V(_ByteBuffer, "_ByteBuffer") \
|
V(_ByteBuffer, "_ByteBuffer") \
|
||||||
V(_ByteBufferDot_New, "_ByteBuffer._New") \
|
V(_ByteBufferDot_New, "_ByteBuffer._New") \
|
||||||
V(_ByteDataView, "_ByteDataView") \
|
V(_ByteDataView, "_ByteDataView") \
|
||||||
V(_UnmodifiableByteDataView, "_UnmodifiableByteDataView") \
|
|
||||||
V(_CapabilityImpl, "_CapabilityImpl") \
|
V(_CapabilityImpl, "_CapabilityImpl") \
|
||||||
V(_ClassMirror, "_ClassMirror") \
|
V(_ClassMirror, "_ClassMirror") \
|
||||||
V(_Closure, "_Closure") \
|
V(_Closure, "_Closure") \
|
||||||
|
@ -304,21 +304,6 @@ class ObjectPointerVisitor;
|
||||||
V(_ExternalUint8Array, "_ExternalUint8Array") \
|
V(_ExternalUint8Array, "_ExternalUint8Array") \
|
||||||
V(_ExternalUint8ClampedArray, "_ExternalUint8ClampedArray") \
|
V(_ExternalUint8ClampedArray, "_ExternalUint8ClampedArray") \
|
||||||
V(_FinalizerImpl, "_FinalizerImpl") \
|
V(_FinalizerImpl, "_FinalizerImpl") \
|
||||||
V(_NativeFinalizer, "_NativeFinalizer") \
|
|
||||||
V(_UnmodifiableInt8ArrayView, "_UnmodifiableInt8ArrayView") \
|
|
||||||
V(_UnmodifiableInt16ArrayView, "_UnmodifiableInt16ArrayView") \
|
|
||||||
V(_UnmodifiableInt32ArrayView, "_UnmodifiableInt32ArrayView") \
|
|
||||||
V(_UnmodifiableInt64ArrayView, "_UnmodifiableInt64ArrayView") \
|
|
||||||
V(_UnmodifiableUint8ClampedArrayView, "_UnmodifiableUint8ClampedArrayView") \
|
|
||||||
V(_UnmodifiableUint8ArrayView, "_UnmodifiableUint8ArrayView") \
|
|
||||||
V(_UnmodifiableUint16ArrayView, "_UnmodifiableUint16ArrayView") \
|
|
||||||
V(_UnmodifiableUint32ArrayView, "_UnmodifiableUint32ArrayView") \
|
|
||||||
V(_UnmodifiableUint64ArrayView, "_UnmodifiableUint64ArrayView") \
|
|
||||||
V(_UnmodifiableFloat32ArrayView, "_UnmodifiableFloat32ArrayView") \
|
|
||||||
V(_UnmodifiableFloat64ArrayView, "_UnmodifiableFloat64ArrayView") \
|
|
||||||
V(_UnmodifiableInt32x4ArrayView, "_UnmodifiableInt32x4ArrayView") \
|
|
||||||
V(_UnmodifiableFloat32x4ArrayView, "_UnmodifiableFloat32x4ArrayView") \
|
|
||||||
V(_UnmodifiableFloat64x2ArrayView, "_UnmodifiableFloat64x2ArrayView") \
|
|
||||||
V(_Float32ArrayFactory, "Float32List.") \
|
V(_Float32ArrayFactory, "Float32List.") \
|
||||||
V(_Float32ArrayView, "_Float32ArrayView") \
|
V(_Float32ArrayView, "_Float32ArrayView") \
|
||||||
V(_Float32List, "_Float32List") \
|
V(_Float32List, "_Float32List") \
|
||||||
|
@ -333,6 +318,7 @@ class ObjectPointerVisitor;
|
||||||
V(_Float64x2ArrayFactory, "Float64x2List.") \
|
V(_Float64x2ArrayFactory, "Float64x2List.") \
|
||||||
V(_Float64x2ArrayView, "_Float64x2ArrayView") \
|
V(_Float64x2ArrayView, "_Float64x2ArrayView") \
|
||||||
V(_Float64x2List, "_Float64x2List") \
|
V(_Float64x2List, "_Float64x2List") \
|
||||||
|
V(_FunctionType, "_FunctionType") \
|
||||||
V(_FunctionTypeMirror, "_FunctionTypeMirror") \
|
V(_FunctionTypeMirror, "_FunctionTypeMirror") \
|
||||||
V(_FutureListener, "_FutureListener") \
|
V(_FutureListener, "_FutureListener") \
|
||||||
V(_GrowableList, "_GrowableList") \
|
V(_GrowableList, "_GrowableList") \
|
||||||
|
@ -374,6 +360,7 @@ class ObjectPointerVisitor;
|
||||||
V(_MethodMirror, "_MethodMirror") \
|
V(_MethodMirror, "_MethodMirror") \
|
||||||
V(_Mint, "_Mint") \
|
V(_Mint, "_Mint") \
|
||||||
V(_MirrorReference, "_MirrorReference") \
|
V(_MirrorReference, "_MirrorReference") \
|
||||||
|
V(_NativeFinalizer, "_NativeFinalizer") \
|
||||||
V(_ParameterMirror, "_ParameterMirror") \
|
V(_ParameterMirror, "_ParameterMirror") \
|
||||||
V(_Random, "_Random") \
|
V(_Random, "_Random") \
|
||||||
V(_RawReceivePortImpl, "_RawReceivePortImpl") \
|
V(_RawReceivePortImpl, "_RawReceivePortImpl") \
|
||||||
|
@ -393,7 +380,6 @@ class ObjectPointerVisitor;
|
||||||
V(_SyncStreamController, "_SyncStreamController") \
|
V(_SyncStreamController, "_SyncStreamController") \
|
||||||
V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl") \
|
V(_TransferableTypedDataImpl, "_TransferableTypedDataImpl") \
|
||||||
V(_Type, "_Type") \
|
V(_Type, "_Type") \
|
||||||
V(_FunctionType, "_FunctionType") \
|
|
||||||
V(_TypeParameter, "_TypeParameter") \
|
V(_TypeParameter, "_TypeParameter") \
|
||||||
V(_TypeRef, "_TypeRef") \
|
V(_TypeRef, "_TypeRef") \
|
||||||
V(_TypeVariableMirror, "_TypeVariableMirror") \
|
V(_TypeVariableMirror, "_TypeVariableMirror") \
|
||||||
|
@ -412,20 +398,34 @@ class ObjectPointerVisitor;
|
||||||
V(_Uint8ClampedArrayView, "_Uint8ClampedArrayView") \
|
V(_Uint8ClampedArrayView, "_Uint8ClampedArrayView") \
|
||||||
V(_Uint8ClampedList, "_Uint8ClampedList") \
|
V(_Uint8ClampedList, "_Uint8ClampedList") \
|
||||||
V(_Uint8List, "_Uint8List") \
|
V(_Uint8List, "_Uint8List") \
|
||||||
|
V(_UnmodifiableByteDataView, "_UnmodifiableByteDataView") \
|
||||||
|
V(_UnmodifiableFloat32ArrayView, "_UnmodifiableFloat32ArrayView") \
|
||||||
|
V(_UnmodifiableFloat32x4ArrayView, "_UnmodifiableFloat32x4ArrayView") \
|
||||||
|
V(_UnmodifiableFloat64ArrayView, "_UnmodifiableFloat64ArrayView") \
|
||||||
|
V(_UnmodifiableFloat64x2ArrayView, "_UnmodifiableFloat64x2ArrayView") \
|
||||||
|
V(_UnmodifiableInt16ArrayView, "_UnmodifiableInt16ArrayView") \
|
||||||
|
V(_UnmodifiableInt32ArrayView, "_UnmodifiableInt32ArrayView") \
|
||||||
|
V(_UnmodifiableInt32x4ArrayView, "_UnmodifiableInt32x4ArrayView") \
|
||||||
|
V(_UnmodifiableInt64ArrayView, "_UnmodifiableInt64ArrayView") \
|
||||||
|
V(_UnmodifiableInt8ArrayView, "_UnmodifiableInt8ArrayView") \
|
||||||
|
V(_UnmodifiableUint16ArrayView, "_UnmodifiableUint16ArrayView") \
|
||||||
|
V(_UnmodifiableUint32ArrayView, "_UnmodifiableUint32ArrayView") \
|
||||||
|
V(_UnmodifiableUint64ArrayView, "_UnmodifiableUint64ArrayView") \
|
||||||
|
V(_UnmodifiableUint8ArrayView, "_UnmodifiableUint8ArrayView") \
|
||||||
|
V(_UnmodifiableUint8ClampedArrayView, "_UnmodifiableUint8ClampedArrayView") \
|
||||||
V(_UserTag, "_UserTag") \
|
V(_UserTag, "_UserTag") \
|
||||||
V(_Utf8Decoder, "_Utf8Decoder") \
|
V(_Utf8Decoder, "_Utf8Decoder") \
|
||||||
V(_VariableMirror, "_VariableMirror") \
|
V(_VariableMirror, "_VariableMirror") \
|
||||||
V(_WeakProperty, "_WeakProperty") \
|
V(_WeakProperty, "_WeakProperty") \
|
||||||
V(_WeakReferenceImpl, "_WeakReferenceImpl") \
|
V(_WeakReferenceImpl, "_WeakReferenceImpl") \
|
||||||
V(_typedDataBase, "_typedDataBase") \
|
|
||||||
V(_await, "_await") \
|
V(_await, "_await") \
|
||||||
V(_classRangeCheck, "_classRangeCheck") \
|
V(_classRangeCheck, "_classRangeCheck") \
|
||||||
V(_current, "_current") \
|
V(_current, "_current") \
|
||||||
V(_ensureScheduleImmediate, "_ensureScheduleImmediate") \
|
V(_ensureScheduleImmediate, "_ensureScheduleImmediate") \
|
||||||
V(_future, "_future") \
|
V(_future, "_future") \
|
||||||
V(_handleException, "_handleException") \
|
V(_handleException, "_handleException") \
|
||||||
V(_handleMessage, "_handleMessage") \
|
|
||||||
V(_handleFinalizerMessage, "_handleFinalizerMessage") \
|
V(_handleFinalizerMessage, "_handleFinalizerMessage") \
|
||||||
|
V(_handleMessage, "_handleMessage") \
|
||||||
V(_handleNativeFinalizerMessage, "_handleNativeFinalizerMessage") \
|
V(_handleNativeFinalizerMessage, "_handleNativeFinalizerMessage") \
|
||||||
V(_hasValue, "_hasValue") \
|
V(_hasValue, "_hasValue") \
|
||||||
V(_initAsync, "_initAsync") \
|
V(_initAsync, "_initAsync") \
|
||||||
|
@ -462,6 +462,7 @@ class ObjectPointerVisitor;
|
||||||
V(_stateData, "_stateData") \
|
V(_stateData, "_stateData") \
|
||||||
V(_suspendSyncStarAtStart, "_suspendSyncStarAtStart") \
|
V(_suspendSyncStarAtStart, "_suspendSyncStarAtStart") \
|
||||||
V(_toString, "_toString") \
|
V(_toString, "_toString") \
|
||||||
|
V(_typedDataBase, "_typedDataBase") \
|
||||||
V(_varData, "_varData") \
|
V(_varData, "_varData") \
|
||||||
V(_wordCharacterMap, "_wordCharacterMap") \
|
V(_wordCharacterMap, "_wordCharacterMap") \
|
||||||
V(_yieldAsyncStar, "_yieldAsyncStar") \
|
V(_yieldAsyncStar, "_yieldAsyncStar") \
|
||||||
|
@ -470,6 +471,8 @@ class ObjectPointerVisitor;
|
||||||
V(add, "add") \
|
V(add, "add") \
|
||||||
V(addStream, "addStream") \
|
V(addStream, "addStream") \
|
||||||
V(asyncStarBody, "asyncStarBody") \
|
V(asyncStarBody, "asyncStarBody") \
|
||||||
|
V(c_result, ":result") \
|
||||||
|
V(call, "call") \
|
||||||
V(callback, "callback") \
|
V(callback, "callback") \
|
||||||
V(capture_length, ":capture_length") \
|
V(capture_length, ":capture_length") \
|
||||||
V(capture_start_index, ":capture_start_index") \
|
V(capture_start_index, ":capture_start_index") \
|
||||||
|
@ -480,6 +483,7 @@ class ObjectPointerVisitor;
|
||||||
V(current_position, ":current_position") \
|
V(current_position, ":current_position") \
|
||||||
V(dynamic_assert_assignable_stc_check, \
|
V(dynamic_assert_assignable_stc_check, \
|
||||||
":dynamic_assert_assignable_stc_check") \
|
":dynamic_assert_assignable_stc_check") \
|
||||||
|
V(get, "get") \
|
||||||
V(index_temp, ":index_temp") \
|
V(index_temp, ":index_temp") \
|
||||||
V(isPaused, "isPaused") \
|
V(isPaused, "isPaused") \
|
||||||
V(match_end_index, ":match_end_index") \
|
V(match_end_index, ":match_end_index") \
|
||||||
|
@ -489,8 +493,8 @@ class ObjectPointerVisitor;
|
||||||
V(options, "options") \
|
V(options, "options") \
|
||||||
V(position_registers, ":position_registers") \
|
V(position_registers, ":position_registers") \
|
||||||
V(print, "print") \
|
V(print, "print") \
|
||||||
V(c_result, ":result") \
|
|
||||||
V(result, "result") \
|
V(result, "result") \
|
||||||
|
V(set, "set") \
|
||||||
V(stack, ":stack") \
|
V(stack, ":stack") \
|
||||||
V(stack_pointer, ":stack_pointer") \
|
V(stack_pointer, ":stack_pointer") \
|
||||||
V(start_index_param, ":start_index_param") \
|
V(start_index_param, ":start_index_param") \
|
||||||
|
|
|
@ -7,6 +7,7 @@ part of "core_patch.dart";
|
||||||
// VM implementation of double.
|
// VM implementation of double.
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@pragma("vm:entry-point")
|
||||||
class double {
|
class double {
|
||||||
@pragma("vm:external-name", "Double_parse")
|
@pragma("vm:external-name", "Double_parse")
|
||||||
external static double? _nativeParse(String str, int start, int end);
|
external static double? _nativeParse(String str, int start, int end);
|
||||||
|
|
|
@ -31,6 +31,7 @@ class ReceivePort {
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@pragma("vm:entry-point")
|
||||||
class Capability {
|
class Capability {
|
||||||
@patch
|
@patch
|
||||||
factory Capability() => new _CapabilityImpl();
|
factory Capability() => new _CapabilityImpl();
|
||||||
|
@ -684,6 +685,7 @@ class Isolate {
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@pragma("vm:entry-point")
|
||||||
abstract class TransferableTypedData {
|
abstract class TransferableTypedData {
|
||||||
@patch
|
@patch
|
||||||
factory TransferableTypedData.fromList(List<TypedData> chunks) {
|
factory TransferableTypedData.fromList(List<TypedData> chunks) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ const int _maxUtf16 = 0xffff;
|
||||||
const int _maxUnicode = 0x10ffff;
|
const int _maxUnicode = 0x10ffff;
|
||||||
|
|
||||||
@patch
|
@patch
|
||||||
|
@pragma("vm:entry-point")
|
||||||
class String {
|
class String {
|
||||||
@patch
|
@patch
|
||||||
factory String.fromCharCodes(Iterable<int> charCodes,
|
factory String.fromCharCodes(Iterable<int> charCodes,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import "dart:typed_data" show Int64List;
|
||||||
|
|
||||||
/// VM implementation of int.
|
/// VM implementation of int.
|
||||||
@patch
|
@patch
|
||||||
|
@pragma("vm:entry-point")
|
||||||
class int {
|
class int {
|
||||||
@patch
|
@patch
|
||||||
@pragma("vm:external-name", "Integer_fromEnvironment")
|
@pragma("vm:external-name", "Integer_fromEnvironment")
|
||||||
|
|
|
@ -702,6 +702,7 @@ class Isolate {
|
||||||
///
|
///
|
||||||
/// [SendPort]s can be transmitted to other isolates, and they preserve equality
|
/// [SendPort]s can be transmitted to other isolates, and they preserve equality
|
||||||
/// when sent.
|
/// when sent.
|
||||||
|
@pragma("vm:entry-point")
|
||||||
abstract class SendPort implements Capability {
|
abstract class SendPort implements Capability {
|
||||||
/// Sends an asynchronous [message] through this send port, to its
|
/// Sends an asynchronous [message] through this send port, to its
|
||||||
/// corresponding [ReceivePort].
|
/// corresponding [ReceivePort].
|
||||||
|
@ -713,10 +714,11 @@ abstract class SendPort implements Capability {
|
||||||
/// - [int]
|
/// - [int]
|
||||||
/// - [double]
|
/// - [double]
|
||||||
/// - [String]
|
/// - [String]
|
||||||
/// - [List] or [Map] (whose elements are any of these)
|
/// - [List], [Map] or [Set] (whose elements are any of these)
|
||||||
/// - [TransferableTypedData]
|
/// - [TransferableTypedData]
|
||||||
/// - [SendPort]
|
/// - [SendPort]
|
||||||
/// - [Capability]
|
/// - [Capability]
|
||||||
|
/// - [Type] representing one of these types, Object, dynamic, void or Never
|
||||||
///
|
///
|
||||||
/// If the sender and receiver isolate share the same code (e.g. isolates
|
/// If the sender and receiver isolate share the same code (e.g. isolates
|
||||||
/// created via [Isolate.spawn]), the transitive object graph of [message] can
|
/// created via [Isolate.spawn]), the transitive object graph of [message] can
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright (c) 2015, 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.
|
|
||||||
|
|
||||||
import 'dart:collection';
|
|
||||||
import 'dart:isolate';
|
|
||||||
|
|
||||||
main(List<String> args, message) {
|
|
||||||
var sendPort = message;
|
|
||||||
try {
|
|
||||||
var map0 = new LinkedHashMap<int, String>();
|
|
||||||
map0[1] = 'one';
|
|
||||||
map0[2] = 'two';
|
|
||||||
map0[3] = 'three';
|
|
||||||
var map1 = new LinkedHashMap<int, String>();
|
|
||||||
map1[4] = 'four';
|
|
||||||
map1[5] = 'five';
|
|
||||||
map1[6] = 'size';
|
|
||||||
var map2 = new LinkedHashMap<int, String>();
|
|
||||||
map2[7] = 'seven';
|
|
||||||
map2[8] = 'eight';
|
|
||||||
map2[9] = 'nine';
|
|
||||||
|
|
||||||
var map = new Map<int, LinkedHashMap<int, String>>.from(
|
|
||||||
{0: map0, 1: map1, 2: map2});
|
|
||||||
sendPort.send(map);
|
|
||||||
} catch (error) {
|
|
||||||
sendPort.send("Invalid Argument(s).");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -45,32 +45,4 @@ main() {
|
||||||
receive2.close();
|
receive2.close();
|
||||||
}, onError: (e) => print('$e'));
|
}, onError: (e) => print('$e'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now spawn an isolate using spawnURI and have it
|
|
||||||
// send back a "literal" like LinkedHashMap object.
|
|
||||||
var receive3 = new ReceivePort();
|
|
||||||
Isolate.spawnUri(
|
|
||||||
Uri.parse('issue_24243_child3_isolate.dart'), [], receive3.sendPort)
|
|
||||||
.then((isolate) {
|
|
||||||
receive3.listen((msg) {
|
|
||||||
var map0 = new LinkedHashMap<int, String>();
|
|
||||||
map0[1] = 'one';
|
|
||||||
map0[2] = 'two';
|
|
||||||
map0[3] = 'three';
|
|
||||||
var map1 = new LinkedHashMap<int, String>();
|
|
||||||
map1[4] = 'four';
|
|
||||||
map1[5] = 'five';
|
|
||||||
map1[6] = 'size';
|
|
||||||
var map2 = new LinkedHashMap<int, String>();
|
|
||||||
map2[7] = 'seven';
|
|
||||||
map2[8] = 'eight';
|
|
||||||
map2[9] = 'nine';
|
|
||||||
Expect.isTrue(msg is Map<int, LinkedHashMap<int, String>>);
|
|
||||||
Expect.mapEquals(msg[0], map0);
|
|
||||||
Expect.mapEquals(msg[1], map1);
|
|
||||||
Expect.mapEquals(msg[2], map2);
|
|
||||||
Expect.throws(() => msg[0] = "throw an exception");
|
|
||||||
receive3.close();
|
|
||||||
}, onError: (e) => print('$e'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ testBadResolvePackage(port) async {
|
||||||
print("Spawned isolate's package config flag: $packageConfigStr");
|
print("Spawned isolate's package config flag: $packageConfigStr");
|
||||||
print("Spawned isolate's loaded package config: $packageConfig");
|
print("Spawned isolate's loaded package config: $packageConfig");
|
||||||
print("Spawned isolate's resolved package path: $resolvedPkg");
|
print("Spawned isolate's resolved package path: $resolvedPkg");
|
||||||
port.send([resolvedPkg]);
|
port.send([resolvedPkg?.toString()]);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
port.send("$e\n$s\n");
|
port.send("$e\n$s\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
|
||||||
|
import "dart:async";
|
||||||
|
import "dart:io";
|
||||||
|
import "dart:isolate";
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
class Unsendable {}
|
||||||
|
|
||||||
|
Future<void> main(args, message) async {
|
||||||
|
if (args.contains("child")) {
|
||||||
|
var sendPort = message as SendPort;
|
||||||
|
|
||||||
|
var bad = <String, Unsendable?>{"a": null, "b": null};
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(bad));
|
||||||
|
|
||||||
|
var good = bad.keys.toList();
|
||||||
|
sendPort.send(good);
|
||||||
|
|
||||||
|
sendPort.send("done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final receivePort = RawReceivePort();
|
||||||
|
receivePort.handler = (msg) {
|
||||||
|
if (msg == "done") receivePort.close();
|
||||||
|
};
|
||||||
|
await Isolate.spawnUri(
|
||||||
|
Platform.script, <String>["child"], receivePort.sendPort,
|
||||||
|
errorsAreFatal: true);
|
||||||
|
}
|
57
tests/lib/isolate/spawn_uri_types_test.dart
Normal file
57
tests/lib/isolate/spawn_uri_types_test.dart
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
|
||||||
|
import "dart:async";
|
||||||
|
import "dart:io";
|
||||||
|
import "dart:isolate";
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
class Foo {}
|
||||||
|
|
||||||
|
Type getType<T>() => T;
|
||||||
|
|
||||||
|
Future<void> main(args, message) async {
|
||||||
|
if (args.contains("child")) {
|
||||||
|
var sendPort = message as SendPort;
|
||||||
|
|
||||||
|
sendPort.send(getType<void>());
|
||||||
|
sendPort.send(Never);
|
||||||
|
sendPort.send(Object);
|
||||||
|
sendPort.send(dynamic);
|
||||||
|
|
||||||
|
sendPort.send(Null);
|
||||||
|
sendPort.send(bool);
|
||||||
|
|
||||||
|
sendPort.send(int);
|
||||||
|
sendPort.send(double);
|
||||||
|
sendPort.send(num);
|
||||||
|
|
||||||
|
sendPort.send(String);
|
||||||
|
|
||||||
|
sendPort.send(List);
|
||||||
|
sendPort.send(Map);
|
||||||
|
sendPort.send(Set);
|
||||||
|
|
||||||
|
sendPort.send(SendPort);
|
||||||
|
sendPort.send(Capability);
|
||||||
|
|
||||||
|
sendPort.send(TransferableTypedData);
|
||||||
|
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(Foo));
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(Socket));
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(getType<List<Foo>>()));
|
||||||
|
|
||||||
|
sendPort.send("done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final receivePort = RawReceivePort();
|
||||||
|
receivePort.handler = (msg) {
|
||||||
|
if (msg == "done") receivePort.close();
|
||||||
|
};
|
||||||
|
await Isolate.spawnUri(
|
||||||
|
Platform.script, <String>["child"], receivePort.sendPort,
|
||||||
|
errorsAreFatal: true);
|
||||||
|
}
|
|
@ -2,29 +2,19 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// 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.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// VMOptions=--enable_fast_object_copy=true
|
||||||
|
// VMOptions=--enable_fast_object_copy=false
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import "dart:isolate";
|
import "dart:isolate";
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
void main(List<String> arguments, Object? message) async {
|
main() async {
|
||||||
if (arguments.length == 1) {
|
|
||||||
assert(arguments[0] == 'helper');
|
|
||||||
await runHelper(message as SendPort);
|
|
||||||
} else {
|
|
||||||
await runTest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> runTest() async {
|
|
||||||
final port = ReceivePort();
|
final port = ReceivePort();
|
||||||
// By spawning the isolate from an uri the newly isolate will run in it's own
|
await Isolate.spawn(
|
||||||
// isolate group. This way we can test the message snapshot serialization
|
runHelper,
|
||||||
// code.
|
|
||||||
await Isolate.spawnUri(
|
|
||||||
Platform.script,
|
|
||||||
['helper'],
|
|
||||||
port.sendPort,
|
port.sendPort,
|
||||||
);
|
);
|
||||||
final message = await port.first;
|
final message = await port.first;
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright (c) 2015, 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.
|
|
||||||
|
|
||||||
// @dart = 2.9
|
|
||||||
|
|
||||||
import 'dart:collection';
|
|
||||||
import 'dart:isolate';
|
|
||||||
|
|
||||||
main(List<String> args, message) {
|
|
||||||
var sendPort = message;
|
|
||||||
try {
|
|
||||||
var map0 = new LinkedHashMap<int, String>();
|
|
||||||
map0[1] = 'one';
|
|
||||||
map0[2] = 'two';
|
|
||||||
map0[3] = 'three';
|
|
||||||
var map1 = new LinkedHashMap<int, String>();
|
|
||||||
map1[4] = 'four';
|
|
||||||
map1[5] = 'five';
|
|
||||||
map1[6] = 'size';
|
|
||||||
var map2 = new LinkedHashMap<int, String>();
|
|
||||||
map2[7] = 'seven';
|
|
||||||
map2[8] = 'eight';
|
|
||||||
map2[9] = 'nine';
|
|
||||||
|
|
||||||
var map = new Map<int, LinkedHashMap<int, String>>.from(
|
|
||||||
{0: map0, 1: map1, 2: map2});
|
|
||||||
sendPort.send(map);
|
|
||||||
} catch (error) {
|
|
||||||
sendPort.send("Invalid Argument(s).");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -49,33 +49,4 @@ main() {
|
||||||
receive2.close();
|
receive2.close();
|
||||||
}, onError: (e) => print('$e'));
|
}, onError: (e) => print('$e'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now spawn an isolate using spawnURI and have it
|
|
||||||
// send back a "literal" like LinkedHashMap object.
|
|
||||||
var receive3 = new ReceivePort();
|
|
||||||
Isolate
|
|
||||||
.spawnUri(
|
|
||||||
Uri.parse('issue_24243_child3_isolate.dart'), [], receive3.sendPort)
|
|
||||||
.then((isolate) {
|
|
||||||
receive3.listen((msg) {
|
|
||||||
var map0 = new LinkedHashMap<int, String>();
|
|
||||||
map0[1] = 'one';
|
|
||||||
map0[2] = 'two';
|
|
||||||
map0[3] = 'three';
|
|
||||||
var map1 = new LinkedHashMap<int, String>();
|
|
||||||
map1[4] = 'four';
|
|
||||||
map1[5] = 'five';
|
|
||||||
map1[6] = 'size';
|
|
||||||
var map2 = new LinkedHashMap<int, String>();
|
|
||||||
map2[7] = 'seven';
|
|
||||||
map2[8] = 'eight';
|
|
||||||
map2[9] = 'nine';
|
|
||||||
Expect.isTrue(msg is Map<int, LinkedHashMap<int, String>>);
|
|
||||||
Expect.mapEquals(msg[0], map0);
|
|
||||||
Expect.mapEquals(msg[1], map1);
|
|
||||||
Expect.mapEquals(msg[2], map2);
|
|
||||||
Expect.throws(() => msg[0] = "throw an exception");
|
|
||||||
receive3.close();
|
|
||||||
}, onError: (e) => print('$e'));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ testBadResolvePackage(port) async {
|
||||||
print("Spawned isolate's package config flag: $packageConfigStr");
|
print("Spawned isolate's package config flag: $packageConfigStr");
|
||||||
print("Spawned isolate's loaded package config: $packageConfig");
|
print("Spawned isolate's loaded package config: $packageConfig");
|
||||||
print("Spawned isolate's resolved package path: $resolvedPkg");
|
print("Spawned isolate's resolved package path: $resolvedPkg");
|
||||||
port.send([resolvedPkg]);
|
port.send([resolvedPkg?.toString()]);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
port.send("$e\n$s\n");
|
port.send("$e\n$s\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
|
||||||
|
// @dart = 2.9
|
||||||
|
|
||||||
|
import "dart:async";
|
||||||
|
import "dart:io";
|
||||||
|
import "dart:isolate";
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
class Unsendable {}
|
||||||
|
|
||||||
|
Future<void> main(args, message) async {
|
||||||
|
if (args.contains("child")) {
|
||||||
|
var sendPort = message as SendPort;
|
||||||
|
|
||||||
|
var bad = <String, Unsendable>{"a": null, "b": null};
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(bad));
|
||||||
|
|
||||||
|
var good = bad.keys.toList();
|
||||||
|
sendPort.send(good);
|
||||||
|
|
||||||
|
sendPort.send("done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final receivePort = RawReceivePort();
|
||||||
|
receivePort.handler = (msg) {
|
||||||
|
if (msg == "done") receivePort.close();
|
||||||
|
};
|
||||||
|
await Isolate.spawnUri(
|
||||||
|
Platform.script, <String>["child"], receivePort.sendPort,
|
||||||
|
errorsAreFatal: true);
|
||||||
|
}
|
59
tests/lib_2/isolate/spawn_uri_types_test.dart
Normal file
59
tests/lib_2/isolate/spawn_uri_types_test.dart
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
|
||||||
|
// @dart = 2.9
|
||||||
|
|
||||||
|
import "dart:async";
|
||||||
|
import "dart:io";
|
||||||
|
import "dart:isolate";
|
||||||
|
|
||||||
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
|
class Foo {}
|
||||||
|
|
||||||
|
Type getType<T>() => T;
|
||||||
|
|
||||||
|
Future<void> main(args, message) async {
|
||||||
|
if (args.contains("child")) {
|
||||||
|
var sendPort = message as SendPort;
|
||||||
|
|
||||||
|
sendPort.send(getType<void>());
|
||||||
|
sendPort.send(Never);
|
||||||
|
sendPort.send(Object);
|
||||||
|
sendPort.send(dynamic);
|
||||||
|
|
||||||
|
sendPort.send(Null);
|
||||||
|
sendPort.send(bool);
|
||||||
|
|
||||||
|
sendPort.send(int);
|
||||||
|
sendPort.send(double);
|
||||||
|
sendPort.send(num);
|
||||||
|
|
||||||
|
sendPort.send(String);
|
||||||
|
|
||||||
|
sendPort.send(List);
|
||||||
|
sendPort.send(Map);
|
||||||
|
sendPort.send(Set);
|
||||||
|
|
||||||
|
sendPort.send(SendPort);
|
||||||
|
sendPort.send(Capability);
|
||||||
|
|
||||||
|
sendPort.send(TransferableTypedData);
|
||||||
|
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(Foo));
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(Socket));
|
||||||
|
Expect.throwsArgumentError(() => sendPort.send(getType<List<Foo>>()));
|
||||||
|
|
||||||
|
sendPort.send("done");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final receivePort = RawReceivePort();
|
||||||
|
receivePort.handler = (msg) {
|
||||||
|
if (msg == "done") receivePort.close();
|
||||||
|
};
|
||||||
|
await Isolate.spawnUri(
|
||||||
|
Platform.script, <String>["child"], receivePort.sendPort,
|
||||||
|
errorsAreFatal: true);
|
||||||
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
// for details. All rights reserved. Use of this source code is governed by a
|
// 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.
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// VMOptions=--enable_fast_object_copy=true
|
||||||
|
// VMOptions=--enable_fast_object_copy=false
|
||||||
|
|
||||||
// @dart = 2.9
|
// @dart = 2.9
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
@ -10,23 +13,10 @@ import 'dart:typed_data';
|
||||||
|
|
||||||
import "package:expect/expect.dart";
|
import "package:expect/expect.dart";
|
||||||
|
|
||||||
void main(List<String> arguments, Object message) async {
|
main() async {
|
||||||
if (arguments.length == 1) {
|
|
||||||
assert(arguments[0] == 'helper');
|
|
||||||
await runHelper(message as SendPort);
|
|
||||||
} else {
|
|
||||||
await runTest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> runTest() async {
|
|
||||||
final port = ReceivePort();
|
final port = ReceivePort();
|
||||||
// By spawning the isolate from an uri the newly isolate will run in it's own
|
await Isolate.spawn(
|
||||||
// isolate group. This way we can test the message snapshot serialization
|
runHelper,
|
||||||
// code.
|
|
||||||
await Isolate.spawnUri(
|
|
||||||
Platform.script,
|
|
||||||
['helper'],
|
|
||||||
port.sendPort,
|
port.sendPort,
|
||||||
);
|
);
|
||||||
final message = await port.first;
|
final message = await port.first;
|
||||||
|
|
Loading…
Reference in a new issue