Add a new API function to sniff a snapshot to determine if the

snapshot is a Dart2 snapshot or a Dart1 snapshot.
This will be used by the flutter engine to initialize itself
correctly based on the snapshot provided.

Change-Id: I06adaac74b350f96aa6ebb55887e4a81f09fbd14
Reviewed-on: https://dart-review.googlesource.com/41082
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
asiva 2018-02-14 23:27:38 +00:00 committed by commit-bot@chromium.org
parent 4436877ab2
commit 9884447cc5
8 changed files with 96 additions and 14 deletions

View file

@ -1029,6 +1029,18 @@ DART_EXPORT Dart_Handle
Dart_CreateScriptSnapshot(uint8_t** script_snapshot_buffer,
intptr_t* script_snapshot_size);
/**
* Returns true if snapshot_buffer contains a Dart2 snapshot.
*
* \param snapshot_buffer Pointer to a buffer that contains the snapshot
* that needs to be checked.
* \param snapshot_size Size of the buffer.
*
* \returns true if the snapshot is a Dart2 snapshot, false otherwise.
*/
DART_EXPORT bool Dart_IsDart2Snapshot(uint8_t* snapshot_buffer,
intptr_t snapshot_size);
/**
* Schedules an interrupt for the specified isolate.
*

View file

@ -4846,14 +4846,14 @@ RawObject* Serializer::ParentOf(const Object& object) {
}
#endif // SNAPSHOT_BACKTRACE
void Serializer::WriteVersionAndFeatures() {
void Serializer::WriteVersionAndFeatures(bool is_vm_snapshot) {
const char* expected_version = Version::SnapshotString();
ASSERT(expected_version != NULL);
const intptr_t version_len = strlen(expected_version);
WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
const char* expected_features =
Dart::FeaturesString(Isolate::Current(), kind_);
Dart::FeaturesString(Isolate::Current(), is_vm_snapshot, kind_);
ASSERT(expected_features != NULL);
const intptr_t features_len = strlen(expected_features);
WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
@ -5303,7 +5303,8 @@ RawApiError* Deserializer::VerifyVersionAndFeatures(Isolate* isolate) {
}
Advance(version_len);
const char* expected_features = Dart::FeaturesString(isolate, kind_);
const char* expected_features =
Dart::FeaturesString(isolate, (isolate == NULL), kind_);
ASSERT(expected_features != NULL);
const intptr_t expected_len = strlen(expected_features);
@ -5717,7 +5718,7 @@ intptr_t FullSnapshotWriter::WriteVMSnapshot() {
kInitialSize, vm_image_writer_);
serializer.ReserveHeader();
serializer.WriteVersionAndFeatures();
serializer.WriteVersionAndFeatures(true);
// VM snapshot roots are:
// - the symbol table
// - all the token streams
@ -5749,7 +5750,7 @@ void FullSnapshotWriter::WriteIsolateSnapshot(intptr_t num_base_objects) {
ASSERT(object_store != NULL);
serializer.ReserveHeader();
serializer.WriteVersionAndFeatures();
serializer.WriteVersionAndFeatures(false);
// Isolate snapshot roots are:
// - the object store
serializer.WriteIsolateSnapshot(num_base_objects, object_store);

View file

@ -195,7 +195,7 @@ class Serializer : public StackResource {
data[Snapshot::kSnapshotFlagIndex] = kind;
}
void WriteVersionAndFeatures();
void WriteVersionAndFeatures(bool is_vm_snapshot);
void Serialize();
WriteStream* stream() { return &stream_; }

View file

@ -636,7 +636,9 @@ RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data,
return Error::null();
}
const char* Dart::FeaturesString(Isolate* isolate, Snapshot::Kind kind) {
const char* Dart::FeaturesString(Isolate* isolate,
bool is_vm_isolate,
Snapshot::Kind kind) {
TextBuffer buffer(64);
// Different fields are included for DEBUG/RELEASE/PRODUCT.
@ -648,16 +650,24 @@ const char* Dart::FeaturesString(Isolate* isolate, Snapshot::Kind kind) {
buffer.AddString("release");
#endif
if (Snapshot::IncludesCode(kind)) {
// Checked mode affects deopt ids.
#define ADD_FLAG(name, isolate_flag, flag) \
do { \
const bool name = (isolate != NULL) ? isolate->name() : flag; \
buffer.AddString(name ? (" " #name) : (" no-" #name)); \
} while (0);
// We don't write the strong flag into the features list for the VM isolate
// snapshot as the implementation is in an intermediate state where the VM
// isolate is always initialized from a vm_snapshot generated in non strong
// mode.
if (!is_vm_isolate) {
ADD_FLAG(strong, strong, FLAG_strong);
}
if (Snapshot::IncludesCode(kind)) {
// Checked mode affects deopt ids.
ADD_FLAG(type_checks, enable_type_checks, FLAG_enable_type_checks);
ADD_FLAG(asserts, enable_asserts, FLAG_enable_asserts);
ADD_FLAG(strong, strong, FLAG_strong);
ADD_FLAG(error_on_bad_type, enable_error_on_bad_type,
FLAG_error_on_bad_type);
ADD_FLAG(error_on_bad_override, enable_error_on_bad_override,
@ -666,7 +676,6 @@ const char* Dart::FeaturesString(Isolate* isolate, Snapshot::Kind kind) {
ADD_FLAG(use_field_guards, use_field_guards, FLAG_use_field_guards);
ADD_FLAG(use_osr, use_osr, FLAG_use_osr);
}
#undef ADD_FLAG
// Generated code must match the host architecture and ABI.
#if defined(TARGET_ARCH_ARM)
@ -697,6 +706,7 @@ const char* Dart::FeaturesString(Isolate* isolate, Snapshot::Kind kind) {
if (FLAG_precompiled_mode && FLAG_dwarf_stack_traces) {
buffer.AddString(" dwarf-stack-traces");
}
#undef ADD_FLAG
return buffer.Steal();
}

View file

@ -74,7 +74,9 @@ class Dart : public AllStatic {
static uword AllocateReadOnlyHandle();
static bool IsReadOnlyHandle(uword address);
static const char* FeaturesString(Isolate* isolate, Snapshot::Kind kind);
static const char* FeaturesString(Isolate* isolate,
bool is_vm_snapshot,
Snapshot::Kind kind);
static Snapshot::Kind vm_snapshot_kind() { return vm_snapshot_kind_; }
static const uint8_t* vm_snapshot_instructions() {
return vm_snapshot_instructions_;

View file

@ -1551,6 +1551,37 @@ Dart_CreateScriptSnapshot(uint8_t** script_snapshot_buffer,
return Api::Success();
}
DART_EXPORT bool Dart_IsDart2Snapshot(uint8_t* snapshot_buffer,
intptr_t snapshot_size) {
const char* expected_version = Version::SnapshotString();
ASSERT(expected_version != NULL);
const intptr_t version_len = strlen(expected_version);
if (snapshot_size < version_len) {
return false;
}
const char* version = reinterpret_cast<const char*>(snapshot_buffer);
ASSERT(version != NULL);
if (strncmp(version, expected_version, version_len)) {
return false;
}
const char* features =
reinterpret_cast<const char*>(snapshot_buffer) + version_len;
ASSERT(features != NULL);
intptr_t pending_len = snapshot_size - version_len;
intptr_t buffer_len = OS::StrNLen(features, pending_len);
// if buffer_len is less than pending_len it means we have a null terminated
// string and we can safely execute 'strstr' on it.
if ((buffer_len < pending_len)) {
if (strstr(features, "no-strong")) {
return false;
} else if (strstr(features, "strong")) {
return true;
}
}
return false;
}
DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate) {
if (isolate == NULL) {
FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);

View file

@ -662,7 +662,7 @@ RawApiError* SnapshotReader::VerifyVersionAndFeatures(Isolate* isolate) {
}
Advance(version_len);
const char* expected_features = Dart::FeaturesString(isolate, kind_);
const char* expected_features = Dart::FeaturesString(isolate, false, kind_);
ASSERT(expected_features != NULL);
const intptr_t expected_len = strlen(expected_features);
@ -1535,7 +1535,7 @@ void SnapshotWriter::WriteVersionAndFeatures() {
WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
const char* expected_features =
Dart::FeaturesString(Isolate::Current(), kind_);
Dart::FeaturesString(Isolate::Current(), false, kind_);
ASSERT(expected_features != NULL);
const intptr_t features_len = strlen(expected_features);
WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),

View file

@ -1791,6 +1791,32 @@ VM_UNIT_TEST_CASE(MismatchedSnapshotKinds) {
free(script_snapshot);
}
VM_UNIT_TEST_CASE(CheckKernelSnapshot) {
intptr_t vm_isolate_snapshot_size;
uint8_t* isolate_snapshot = NULL;
intptr_t isolate_snapshot_size;
uint8_t* full_snapshot = NULL;
bool saved_load_deferred_eagerly_mode = FLAG_load_deferred_eagerly;
FLAG_load_deferred_eagerly = true;
{
// 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.
Dart_Handle result =
Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size, &isolate_snapshot,
&isolate_snapshot_size);
EXPECT_VALID(result);
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
}
FLAG_load_deferred_eagerly = saved_load_deferred_eagerly_mode;
bool is_kernel = Dart_IsDart2Snapshot(full_snapshot, isolate_snapshot_size);
EXPECT_EQ(FLAG_strong, is_kernel);
}
#endif // !PRODUCT
// Helper function to call a top level Dart function and serialize the result.