diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 1aaf1925f69..9ce1b2c4473 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -516,7 +516,7 @@ static void SetupForGenericSnapshotCreation() { int main(int argc, char** argv) { - const int EXTRA_VM_ARGUMENTS = 1; + const int EXTRA_VM_ARGUMENTS = 2; CommandLineOptions vm_options(argc + EXTRA_VM_ARGUMENTS); // Initialize the URL mapping array. @@ -536,7 +536,9 @@ int main(int argc, char** argv) { DartUtils::SetOriginalWorkingDirectory(); vm_options.AddArgument("--load_deferred_eagerly"); - + // Workaround until issue 21620 is fixed. + // (https://github.com/dart-lang/sdk/issues/21620) + vm_options.AddArgument("--no-concurrent_sweep"); Dart_SetVMFlags(vm_options.count(), vm_options.arguments()); // Initialize the Dart VM. diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc index c3c152b8abf..46f3f4dcbaa 100644 --- a/runtime/vm/class_finalizer.cc +++ b/runtime/vm/class_finalizer.cc @@ -2332,6 +2332,9 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { if (cls.is_finalized()) { return; } + if (FLAG_trace_class_finalization) { + OS::Print("Finalize %s\n", cls.ToCString()); + } if (cls.is_patch()) { // The fields and functions of a patch class are copied to the // patched class after parsing. There is nothing to finalize. @@ -2340,9 +2343,6 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { cls.set_is_finalized(); return; } - if (FLAG_trace_class_finalization) { - OS::Print("Finalize %s\n", cls.ToCString()); - } if (cls.IsMixinApplication()) { // Copy instance methods and fields from the mixin class. // This has to happen before the check whether the methods of diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc index dfe2c697d1d..80902546206 100644 --- a/runtime/vm/compiler.cc +++ b/runtime/vm/compiler.cc @@ -344,6 +344,12 @@ RawError* Compiler::CompileClass(const Class& cls) { ClassFinalizer::FinalizeClass(parse_class); parse_class.reset_is_marked_for_parsing(); } + for (intptr_t i = (patch_list.Length() - 1); i >=0 ; i--) { + parse_class ^= patch_list.At(i); + ASSERT(!parse_class.IsNull()); + ClassFinalizer::FinalizeClass(parse_class); + parse_class.reset_is_marked_for_parsing(); + } return Error::null(); } else { diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 9562941a55c..cb5d584d94d 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -71,6 +71,46 @@ const char* CanonicalFunction(const char* func) { } +#if defined(DEBUG) +// An object visitor which will iterate over all the function objects in the +// heap and check if the result type and parameter types are canonicalized +// or not. An assertion is raised if a type is not canonicalized. +class FunctionVisitor : public ObjectVisitor { + public: + explicit FunctionVisitor(Isolate* isolate) : + ObjectVisitor(isolate), + classHandle_(Class::Handle(isolate)), + funcHandle_(Function::Handle(isolate)), + typeHandle_(AbstractType::Handle(isolate)) {} + + void VisitObject(RawObject* obj) { + if (obj->IsFunction()) { + funcHandle_ ^= obj; + classHandle_ ^= funcHandle_.Owner(); + // Verify that the result type of a function is canonical or a + // TypeParameter. + typeHandle_ ^= funcHandle_.result_type(); + ASSERT(typeHandle_.IsNull() || + typeHandle_.IsTypeParameter() || + typeHandle_.IsCanonical()); + // Verify that the types in the function signature are all canonical or + // a TypeParameter. + const intptr_t num_parameters = funcHandle_.NumParameters(); + for (intptr_t i = 0; i < num_parameters; i++) { + typeHandle_ = funcHandle_.ParameterTypeAt(i); + ASSERT(typeHandle_.IsTypeParameter() || typeHandle_.IsCanonical()); + } + } + } + + private: + Class& classHandle_; + Function& funcHandle_; + AbstractType& typeHandle_; +}; +#endif // #if defined(DEBUG). + + static RawInstance* GetListInstance(Isolate* isolate, const Object& obj) { if (obj.IsInstance()) { const Library& core_lib = Library::Handle(Library::CoreLibrary()); @@ -1463,6 +1503,12 @@ DART_EXPORT Dart_Handle Dart_CreateSnapshot( if (::Dart_IsError(state)) { return state; } + isolate->heap()->CollectAllGarbage(); +#if defined(DEBUG) + FunctionVisitor check_canonical(isolate); + isolate->heap()->VisitObjects(&check_canonical); +#endif // #if defined(DEBUG). + // Since this is only a snapshot the root library should not be set. isolate->object_store()->set_root_library(Library::Handle(isolate)); FullSnapshotWriter writer(vm_isolate_snapshot_buffer, diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 57aca2be4a0..0c69b39f82d 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -393,6 +393,9 @@ class RawObject { bool IsScript() { return ((GetClassId() == kScriptCid)); } + bool IsFunction() { + return ((GetClassId() == kFunctionCid)); + } intptr_t Size() const { uword tags = ptr()->tags_; diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc index 5c9a28a5d3c..e4f682946d0 100644 --- a/runtime/vm/snapshot_test.cc +++ b/runtime/vm/snapshot_test.cc @@ -20,6 +20,7 @@ namespace dart { DECLARE_FLAG(bool, enable_type_checks); DECLARE_FLAG(bool, load_deferred_eagerly); +DECLARE_FLAG(bool, concurrent_sweep); // Check if serialized and deserialized objects are equal. static bool Equals(const Object& expected, const Object& actual) { @@ -1235,7 +1236,10 @@ UNIT_TEST_CASE(ScriptSnapshot) { bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly; FLAG_load_deferred_eagerly = true; - + // Workaround until issue 21620 is fixed. + // (https://github.com/dart-lang/sdk/issues/21620) + bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep; + FLAG_concurrent_sweep = false; { // Start an Isolate, and create a full snapshot of it. TestIsolateScope __test_isolate__; @@ -1251,8 +1255,8 @@ UNIT_TEST_CASE(ScriptSnapshot) { memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size); Dart_ExitScope(); } - FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode; + FLAG_concurrent_sweep = saved_concurrent_sweep_mode; // Test for Dart_CreateScriptSnapshot. { @@ -1379,6 +1383,8 @@ UNIT_TEST_CASE(ScriptSnapshot1) { bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly; FLAG_load_deferred_eagerly = true; + bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep; + FLAG_concurrent_sweep = false; { // Start an Isolate, and create a full snapshot of it. TestIsolateScope __test_isolate__; @@ -1394,6 +1400,7 @@ UNIT_TEST_CASE(ScriptSnapshot1) { memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size); Dart_ExitScope(); } + FLAG_concurrent_sweep = saved_concurrent_sweep_mode; { // Create an Isolate using the full snapshot, load a script and create @@ -1469,7 +1476,8 @@ UNIT_TEST_CASE(ScriptSnapshot2) { FLAG_enable_type_checks = false; bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly; FLAG_load_deferred_eagerly = true; - + bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep; + FLAG_concurrent_sweep = false; { // Start an Isolate, and create a full snapshot of it. TestIsolateScope __test_isolate__; @@ -1485,6 +1493,7 @@ UNIT_TEST_CASE(ScriptSnapshot2) { memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size); Dart_ExitScope(); } + FLAG_concurrent_sweep = saved_concurrent_sweep_mode; { // Create an Isolate using the full snapshot, load a script and create