diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index bc60b3b006b..7aaca7d066c 100755 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -854,7 +854,9 @@ DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name); * * A snapshot can be used to restore the VM quickly to a saved state * and is useful for fast startup. If snapshot data is provided, the - * isolate will be started using that snapshot data. + * isolate will be started using that snapshot data. Requires a core snapshot or + * an app snapshot created by Dart_CreateSnapshot or + * Dart_CreatePrecompiledSnapshot* from a VM with the same version. * * Requires there to be no current isolate. * @@ -2795,7 +2797,9 @@ DART_EXPORT Dart_Handle Dart_LoadScript(Dart_Handle url, intptr_t col_offset); /** - * Loads the root script for current isolate from a snapshot. + * Loads the root script for current isolate from a script snapshot. The + * snapshot must have been created by Dart_CreateScriptSnapshot from a VM with + * the same version. * * \param buffer A buffer which contains a snapshot of the script. * \param buffer_len Length of the passed in buffer. diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc index 29436f9f181..bf490bfa0ed 100644 --- a/runtime/vm/dart.cc +++ b/runtime/vm/dart.cc @@ -522,8 +522,14 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer, void* data) { const String& message = String::Handle(String::New("Invalid snapshot")); return ApiError::New(message); } + if (snapshot->kind() != snapshot_kind_) { + const String& message = String::Handle( + String::NewFormatted("Invalid snapshot kind: got '%s', expected '%s'", + Snapshot::KindToCString(snapshot->kind()), + Snapshot::KindToCString(snapshot_kind_))); + return ApiError::New(message); + } ASSERT(Snapshot::IsFull(snapshot->kind())); - ASSERT(snapshot->kind() == snapshot_kind_); if (FLAG_trace_isolates) { OS::Print("Size of isolate snapshot = %" Pd "\n", snapshot->length()); } diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc index 8c7b5c28982..6fc90ba4d3b 100644 --- a/runtime/vm/snapshot.cc +++ b/runtime/vm/snapshot.cc @@ -142,6 +142,21 @@ static intptr_t GetTypeIndex(ObjectStore* object_store, } +const char* Snapshot::KindToCString(Kind kind) { + switch (kind) { + case kCore: return "core"; + case kScript: return "script"; + case kMessage: return "message"; + case kAppWithJIT: return "app-jit"; + case kAppNoJIT: return "app-aot"; + case kNone: return "none"; + case kInvalid: + default: + return "invalid"; + } +} + + // TODO(5411462): Temporary setup of snapshot for testing purposes, // the actual creation of a snapshot maybe done differently. const Snapshot* Snapshot::SetupFromBuffer(const void* raw_memory) { diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h index 715df14aa58..7bc946fb050 100644 --- a/runtime/vm/snapshot.h +++ b/runtime/vm/snapshot.h @@ -165,6 +165,7 @@ class Snapshot { kNone, // dart_bootstrap/gen_snapshot kInvalid }; + static const char* KindToCString(Kind kind); static const int kHeaderSize = 2 * sizeof(int64_t); static const int kLengthIndex = 0; diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc index c39d82842dc..cbe7009aaf0 100644 --- a/runtime/vm/snapshot_test.cc +++ b/runtime/vm/snapshot_test.cc @@ -1634,6 +1634,89 @@ UNIT_TEST_CASE(ScriptSnapshot2) { } +UNIT_TEST_CASE(MismatchedSnapshotKinds) { + const char* kScriptChars = + "main() { print('Hello, world!'); }"; + Dart_Handle result; + + uint8_t* buffer; + intptr_t size; + intptr_t vm_isolate_snapshot_size; + uint8_t* isolate_snapshot = NULL; + intptr_t isolate_snapshot_size; + uint8_t* full_snapshot = NULL; + uint8_t* script_snapshot = NULL; + + 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__; + Dart_EnterScope(); // Start a Dart API scope for invoking API functions. + + // Write out the script snapshot. + result = Dart_CreateSnapshot(NULL, + &vm_isolate_snapshot_size, + &isolate_snapshot, + &isolate_snapshot_size); + EXPECT_VALID(result); + full_snapshot = reinterpret_cast(malloc(isolate_snapshot_size)); + memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size); + Dart_ExitScope(); + } + FLAG_concurrent_sweep = saved_concurrent_sweep_mode; + FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode; + + { + // Create an Isolate using the full snapshot, load a script and create + // a script snapshot of the script. + TestCase::CreateTestIsolateFromSnapshot(full_snapshot); + Dart_EnterScope(); // Start a Dart API scope for invoking API functions. + + // Create a test library and Load up a test script in it. + TestCase::LoadTestScript(kScriptChars, NULL); + + EXPECT_VALID(Api::CheckAndFinalizePendingClasses(Thread::Current())); + + // Write out the script snapshot. + result = Dart_CreateScriptSnapshot(&buffer, &size); + EXPECT_VALID(result); + script_snapshot = reinterpret_cast(malloc(size)); + memmove(script_snapshot, buffer, size); + Dart_ExitScope(); + Dart_ShutdownIsolate(); + } + + { + // Use a script snapshot where a full snapshot is expected. + char* error = NULL; + Dart_Isolate isolate = Dart_CreateIsolate("script-uri", "main", + script_snapshot, NULL, NULL, + &error); + EXPECT(isolate == NULL); + EXPECT(error != NULL); + EXPECT_SUBSTRING("got 'script', expected 'core'", error); + } + + { + TestCase::CreateTestIsolateFromSnapshot(full_snapshot); + Dart_EnterScope(); // Start a Dart API scope for invoking API functions. + + // Use a full snapshot where a script snapshot is expected. + Dart_Handle result = Dart_LoadScriptFromSnapshot(full_snapshot, size); + EXPECT_ERROR(result, "Dart_LoadScriptFromSnapshot expects parameter" + " 'buffer' to be a script type snapshot."); + + Dart_ExitScope(); + } + Dart_ShutdownIsolate(); + free(full_snapshot); + free(script_snapshot); +} + + #endif // !PRODUCT