1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 09:20:04 +00:00

[vm] Remove 'dynamic' from 'dart:core'; add missing accessors to the embedding API for dynamic, void and Never.

Fix crash when create type errors involving Never.

Bug: https://github.com/dart-lang/sdk/issues/12478
Bug: https://github.com/dart-lang/sdk/issues/40176
Change-Id: I8cff7042850717d02da36ad935cf0a49ace80c3d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134886
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ryan Macnak 2020-02-07 23:47:50 +00:00 committed by commit-bot@chromium.org
parent a6d792797c
commit d71b1e5b04
9 changed files with 117 additions and 71 deletions

View File

@ -28,6 +28,9 @@ used (see Issue [39627][]).
### Dart VM
* Added `Dart_TypeDynamic`, `Dart_TypeVoid` and `Dart_TypeNever`. Type dynamic
can no longer by reached by `Dart_GetType(dart:core, dynamic)`.
### Tools
#### Dart Dev Compiler (DDC)

View File

@ -1487,6 +1487,11 @@ DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size);
*/
DART_EXPORT Dart_Handle Dart_Null();
/**
* Is this object null?
*/
DART_EXPORT bool Dart_IsNull(Dart_Handle object);
/**
* Returns the empty string object.
*
@ -1495,9 +1500,14 @@ DART_EXPORT Dart_Handle Dart_Null();
DART_EXPORT Dart_Handle Dart_EmptyString();
/**
* Is this object null?
* Returns types that are not classes, and which therefore cannot be looked up
* as library members by Dart_GetType.
*
* \return A handle to the dynamic, void or Never type.
*/
DART_EXPORT bool Dart_IsNull(Dart_Handle object);
DART_EXPORT Dart_Handle Dart_TypeDynamic();
DART_EXPORT Dart_Handle Dart_TypeVoid();
DART_EXPORT Dart_Handle Dart_TypeNever();
/**
* Checks if the two objects are equal.

View File

@ -1179,18 +1179,18 @@ DEFINE_NATIVE_ENTRY(LibraryMirror_members, 0, 2) {
entry = entries.GetNext();
if (entry.IsClass()) {
const Class& klass = Class::Cast(entry);
ASSERT(!klass.IsVoidClass() && !klass.IsNeverClass());
if (!klass.IsDynamicClass()) {
error = klass.EnsureIsFinalized(thread);
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
type = klass.DeclarationType();
member_mirror = CreateClassMirror(klass, type,
Bool::True(), // is_declaration
owner_mirror);
member_mirrors.Add(member_mirror);
ASSERT(!klass.IsDynamicClass());
ASSERT(!klass.IsVoidClass());
ASSERT(!klass.IsNeverClass());
error = klass.EnsureIsFinalized(thread);
if (!error.IsNull()) {
Exceptions::PropagateError(error);
}
type = klass.DeclarationType();
member_mirror = CreateClassMirror(klass, type,
Bool::True(), // is_declaration
owner_mirror);
member_mirrors.Add(member_mirror);
} else if (entry.IsField()) {
const Field& field = Field::Cast(entry);
if (field.is_reflectable()) {

View File

@ -1378,9 +1378,6 @@ void Precompiler::CollectDynamicFunctionNames() {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
functions = cls.functions();
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
@ -1458,10 +1455,6 @@ void Precompiler::TraceForRetainedFunctions() {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
functions = cls.functions();
for (intptr_t j = 0; j < functions.Length(); j++) {
function ^= functions.At(j);
@ -1517,10 +1510,6 @@ void Precompiler::DropFunctions() {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
functions = cls.functions();
retained_functions = GrowableObjectArray::New();
for (intptr_t j = 0; j < functions.Length(); j++) {
@ -1581,10 +1570,6 @@ void Precompiler::DropFields() {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
fields = cls.fields();
retained_fields = GrowableObjectArray::New();
for (intptr_t j = 0; j < fields.Length(); j++) {
@ -1780,9 +1765,6 @@ void Precompiler::TraceTypesFromRetainedClasses() {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
// The subclasses/implementors array is only needed for CHA.
cls.ClearDirectSubclasses();

View File

@ -1016,12 +1016,6 @@ RawError* Compiler::CompileAllFunctions(const Class& cls) {
Object& result = Object::Handle(zone);
Array& functions = Array::Handle(zone, cls.functions());
Function& func = Function::Handle(zone);
// Class dynamic lives in the vm isolate. Its array fields cannot be set to
// an empty array.
if (functions.IsNull()) {
ASSERT(cls.IsDynamicClass());
return Error::null();
}
// Compile all the regular functions.
for (int i = 0; i < functions.Length(); i++) {
func ^= functions.At(i);
@ -1046,12 +1040,6 @@ RawError* Compiler::ReadAllBytecode(const Class& cls) {
ASSERT(error.IsNull());
Array& functions = Array::Handle(zone, cls.functions());
Function& func = Function::Handle(zone);
// Class dynamic lives in the vm isolate. Its array fields cannot be set to
// an empty array.
if (functions.IsNull()) {
ASSERT(cls.IsDynamicClass());
return Error::null();
}
// Compile all the regular functions.
for (int i = 0; i < functions.Length(); i++) {
func ^= functions.At(i);

View File

@ -1981,14 +1981,35 @@ DART_EXPORT Dart_Handle Dart_Null() {
return Api::Null();
}
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
TransitionNativeToVM transition(Thread::Current());
return Api::UnwrapHandle(object) == Object::null();
}
DART_EXPORT Dart_Handle Dart_EmptyString() {
ASSERT(Isolate::Current() != NULL);
return Api::EmptyString();
}
DART_EXPORT bool Dart_IsNull(Dart_Handle object) {
TransitionNativeToVM transition(Thread::Current());
return Api::UnwrapHandle(object) == Object::null();
DART_EXPORT Dart_Handle Dart_TypeDynamic() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::DynamicType());
}
DART_EXPORT Dart_Handle Dart_TypeVoid() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::VoidType());
}
DART_EXPORT Dart_Handle Dart_TypeNever() {
DARTSCOPE(Thread::Current());
CHECK_CALLBACK_STATE(T);
API_TIMELINE_DURATION(T);
return Api::NewHandle(T, Type::NeverType());
}
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
@ -2268,7 +2289,8 @@ DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
#if defined(DEBUG)
const Library& lib = Library::Handle(Z, owner.library());
if (lib.IsNull()) {
ASSERT(owner.IsDynamicClass() || owner.IsVoidClass());
ASSERT(owner.IsDynamicClass() || owner.IsVoidClass() ||
owner.IsNeverClass());
}
#endif
return Api::NewHandle(T, owner.library());

View File

@ -798,6 +798,46 @@ TEST_CASE(DartAPI_EmptyString) {
Dart_Handle empty = Dart_EmptyString();
EXPECT_VALID(empty);
EXPECT(!Dart_IsNull(empty));
EXPECT(Dart_IsString(empty));
intptr_t length = -1;
EXPECT_VALID(Dart_StringLength(empty, &length));
EXPECT_EQ(0, length);
}
TEST_CASE(DartAPI_TypeDynamic) {
Dart_Handle type = Dart_TypeDynamic();
EXPECT_VALID(type);
EXPECT(Dart_IsType(type));
Dart_Handle str = Dart_ToString(type);
EXPECT_VALID(str);
const char* cstr = nullptr;
EXPECT_VALID(Dart_StringToCString(str, &cstr));
EXPECT_STREQ("dynamic", cstr);
}
TEST_CASE(DartAPI_TypeVoid) {
Dart_Handle type = Dart_TypeVoid();
EXPECT_VALID(type);
EXPECT(Dart_IsType(type));
Dart_Handle str = Dart_ToString(type);
EXPECT_VALID(str);
const char* cstr = nullptr;
EXPECT_VALID(Dart_StringToCString(str, &cstr));
EXPECT_STREQ("void", cstr);
}
TEST_CASE(DartAPI_TypeNever) {
Dart_Handle type = Dart_TypeNever();
EXPECT_VALID(type);
EXPECT(Dart_IsType(type));
Dart_Handle str = Dart_ToString(type);
EXPECT_VALID(str);
const char* cstr = nullptr;
EXPECT_VALID(Dart_StringToCString(str, &cstr));
EXPECT_STREQ("Never", cstr);
}
TEST_CASE(DartAPI_IdentityEquals) {
@ -1142,11 +1182,6 @@ TEST_CASE(DartAPI_ClassLibrary) {
const char* str = NULL;
Dart_StringToCString(lib_url, &str);
EXPECT_STREQ("dart:core", str);
// Case with no library.
type = Dart_GetType(lib, NewString("dynamic"), 0, NULL);
EXPECT_VALID(type);
EXPECT(Dart_IsNull(Dart_ClassLibrary(type)));
}
TEST_CASE(DartAPI_BooleanValues) {
@ -5051,7 +5086,9 @@ TEST_CASE(DartAPI_NewListOfType) {
" ChannelReadResult(this.handles);\n"
"}\n"
"void expectListOfString(List<String> _) {}\n"
"void expectListOfDynamic(List<dynamic> _) {}\n";
"void expectListOfDynamic(List<dynamic> _) {}\n"
"void expectListOfVoid(List<void> _) {}\n"
"void expectListOfNever(List<Never> _) {}\n";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_Handle zxhandle_type = Dart_GetType(lib, NewString("ZXHandle"), 0, NULL);
@ -5093,14 +5130,28 @@ TEST_CASE(DartAPI_NewListOfType) {
EXPECT_VALID(
Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args));
Dart_Handle dynamic_type =
Dart_GetType(dart_core, NewString("dynamic"), 0, NULL);
Dart_Handle dynamic_type = Dart_TypeDynamic();
EXPECT_VALID(dynamic_type);
Dart_Handle dynamic_list = Dart_NewListOfType(string_type, 0);
Dart_Handle dynamic_list = Dart_NewListOfType(dynamic_type, 0);
EXPECT_VALID(dynamic_list);
args[0] = dynamic_list;
EXPECT_VALID(
Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args));
Dart_Handle void_type = Dart_TypeVoid();
EXPECT_VALID(void_type);
Dart_Handle void_list = Dart_NewListOfType(void_type, 0);
EXPECT_VALID(void_list);
args[0] = void_list;
EXPECT_VALID(Dart_Invoke(lib, NewString("expectListOfVoid"), kNumArgs, args));
Dart_Handle never_type = Dart_TypeNever();
EXPECT_VALID(never_type);
Dart_Handle never_list = Dart_NewListOfType(never_type, 0);
EXPECT_VALID(never_list);
args[0] = never_list;
EXPECT_VALID(
Dart_Invoke(lib, NewString("expectListOfNever"), kNumArgs, args));
}
static Dart_Handle PrivateLibName(Dart_Handle lib, const char* str) {

View File

@ -11832,12 +11832,6 @@ void Library::InitCoreLibrary(Isolate* isolate) {
core_lib.Register(thread);
isolate->object_store()->set_bootstrap_library(ObjectStore::kCore, core_lib);
isolate->object_store()->set_root_library(Library::Handle());
// Hook up predefined classes without setting their library pointers. These
// classes are coming from the VM isolate, and are shared between multiple
// isolates so setting their library pointers would be wrong.
const Class& cls = Class::Handle(zone, Object::dynamic_class());
core_lib.AddObject(cls, String::Handle(zone, cls.Name()));
}
// Invoke the function, or noSuchMethod if it is null.
@ -19210,7 +19204,9 @@ bool Type::CheckIsCanonical(Thread* thread) const {
#endif // DEBUG
void Type::EnumerateURIs(URIs* uris) const {
if (IsDynamicType() || IsVoidType()) {
// N.B. Not all types with kNeverCid answer true to IsNeverType, but none of
// them have a URI.
if (IsDynamicType() || IsVoidType() || (type_class_id() == kNeverCid)) {
return;
}
Thread* thread = Thread::Current();
@ -19451,7 +19447,8 @@ void TypeRef::EnumerateURIs(URIs* uris) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const AbstractType& ref_type = AbstractType::Handle(zone, type());
ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType());
ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType() &&
!ref_type.IsNeverType());
const Class& cls = Class::Handle(zone, ref_type.type_class());
const String& name = String::Handle(zone, cls.UserVisibleName());
const Library& library = Library::Handle(zone, cls.library());

View File

@ -29,9 +29,6 @@ void ProgramVisitor::VisitClasses(ClassVisitor* visitor) {
ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsDynamicClass()) {
continue; // class 'dynamic' is in the read-only VM isolate.
}
visitor->Visit(cls);
}
patches = lib.used_scripts();
@ -55,10 +52,6 @@ class ClassFunctionVisitor : public ClassVisitor {
field_(Field::Handle(zone)) {}
void Visit(const Class& cls) {
if (cls.IsDynamicClass()) {
return; // class 'dynamic' is in the read-only VM isolate.
}
functions_ = cls.functions();
for (intptr_t j = 0; j < functions_.Length(); j++) {
function_ ^= functions_.At(j);