[vm] Move writing snapshot magic value from embedder to VM.

Add Dart_IsSnapshot and Dart_IsKernel to the embedding API.

Change-Id: I7d4e1d145557e8f11dbc3c143767ad38b3615a4a
Reviewed-on: https://dart-review.googlesource.com/46360
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Ryan Macnak 2018-03-19 17:47:55 +00:00 committed by commit-bot@chromium.org
parent a81bc639b5
commit 3989d09c95
12 changed files with 115 additions and 59 deletions

View file

@ -413,19 +413,6 @@ DartUtils::MagicNumber DartUtils::SniffForMagicNumber(const uint8_t* buffer,
return kUnknownMagicNumber;
}
void DartUtils::WriteSnapshotMagicNumber(File* file) {
// Write a magic number and version information into the snapshot file.
bool bytes_written = file->WriteFully(snapshot_magic_number.bytes,
snapshot_magic_number.length);
ASSERT(bytes_written);
}
void DartUtils::SkipSnapshotMagicNumber(const uint8_t** buffer,
intptr_t* buffer_length) {
*buffer += snapshot_magic_number.length;
*buffer_length -= snapshot_magic_number.length;
}
Dart_Handle DartUtils::PrepareBuiltinLibrary(Dart_Handle builtin_lib,
Dart_Handle internal_lib,
bool is_service_isolate,

View file

@ -217,10 +217,6 @@ class DartUtils {
static MagicNumber SniffForMagicNumber(const uint8_t* text_buffer,
intptr_t buffer_len);
// Write a magic number to indicate a script snapshot file.
static void WriteSnapshotMagicNumber(File* file);
static void SkipSnapshotMagicNumber(const uint8_t** buffer, intptr_t* length);
// Global state that stores the original working directory..
static const char* original_working_directory;

View file

@ -110,10 +110,12 @@ void DFE::Init() {
// platform_dill is not NULL implies that platform_strong_dill is also
// not NULL.
if (platform_program_ == NULL) {
ASSERT(Dart_IsKernel(platform_dill, platform_dill_size));
platform_program_ =
Dart_ReadKernelBinary(platform_dill, platform_dill_size, NoopRelease);
}
if (platform_strong_program_ == NULL) {
ASSERT(Dart_IsKernel(platform_strong_dill, platform_strong_dill_size));
platform_strong_program_ = Dart_ReadKernelBinary(
platform_strong_dill, platform_strong_dill_size, NoopRelease);
}

View file

@ -450,7 +450,6 @@ bool Loader::ProcessResultLocked(Loader* loader, Loader::IOResult* result) {
} break;
case Dart_kScriptTag:
if (payload_type == DartUtils::kSnapshotMagicNumber) {
DartUtils::SkipSnapshotMagicNumber(&payload, &payload_length);
dart_result = Dart_LoadScriptFromSnapshot(payload, payload_length);
reload_extensions = true;
} else if (payload_type == DartUtils::kKernelMagicNumber) {

View file

@ -179,7 +179,6 @@ static Dart_Isolate CreateIsolateAndSetup(const char* script_uri,
bin::DartUtils::ReadFile(&payload, &payload_length, file);
bin::DartUtils::CloseFile(file);
bin::DartUtils::SkipSnapshotMagicNumber(&payload, &payload_length);
Dart_Handle result = Dart_LoadScriptFromSnapshot(payload, payload_length);
CHECK_RESULT(result);
}

View file

@ -246,7 +246,6 @@ AppSnapshot* Snapshot::TryReadAppSnapshot(const char* script_name) {
}
static void WriteSnapshotFile(const char* filename,
bool write_magic_number,
const uint8_t* buffer,
const intptr_t size) {
File* file = File::Open(NULL, filename, File::kWriteTruncate);
@ -255,11 +254,6 @@ static void WriteSnapshotFile(const char* filename,
filename);
}
if (write_magic_number) {
// Write the magic number to indicate file is a script snapshot.
DartUtils::WriteSnapshotMagicNumber(file);
}
if (!file->WriteFully(buffer, size)) {
ErrorExit(kErrorExitCode, "Unable to write file %s for writing snapshot\n",
filename);
@ -332,7 +326,7 @@ void Snapshot::GenerateScript(const char* snapshot_filename) {
ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
}
WriteSnapshotFile(snapshot_filename, true, buffer, size);
WriteSnapshotFile(snapshot_filename, buffer, size);
}
void Snapshot::GenerateAppJIT(const char* snapshot_filename) {

View file

@ -1026,6 +1026,27 @@ DART_EXPORT Dart_Handle
Dart_CreateScriptSnapshot(uint8_t** script_snapshot_buffer,
intptr_t* script_snapshot_size);
/**
* Returns whether the buffer contains a snapshot created by
* Dart_Create*Snapshot.
*
* \param buffer Pointer to a buffer that might contain a snapshot.
* \param buffer_size Size of the buffer.
*
* \return Whether the buffer contains a snapshot (core, app or script).
*/
DART_EXPORT bool Dart_IsSnapshot(const uint8_t* buffer, intptr_t buffer_size);
/**
* Returns whether the buffer contains a kernel file.
*
* \param buffer Pointer to a buffer that might contain a kernel binary.
* \param buffer_size Size of the buffer.
*
* \return Whether the buffer contains a kernel binary (full or partial).
*/
DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size);
/**
* Returns true if snapshot_buffer contains a Dart2 snapshot.
*

View file

@ -190,9 +190,10 @@ class Serializer : public StackResource {
}
void FillHeader(Snapshot::Kind kind) {
int64_t* data = reinterpret_cast<int64_t*>(stream_.buffer());
data[Snapshot::kLengthIndex] = stream_.bytes_written();
data[Snapshot::kSnapshotFlagIndex] = kind;
Snapshot* header = reinterpret_cast<Snapshot*>(stream_.buffer());
header->set_magic();
header->set_length(stream_.bytes_written());
header->set_kind(kind);
}
void WriteVersionAndFeatures(bool is_vm_snapshot);

View file

@ -1532,6 +1532,21 @@ Dart_CreateScriptSnapshot(uint8_t** script_snapshot_buffer,
return Api::Success();
}
DART_EXPORT bool Dart_IsSnapshot(const uint8_t* buffer, intptr_t buffer_size) {
if (buffer_size < Snapshot::kHeaderSize) {
return false;
}
return Snapshot::SetupFromBuffer(buffer) != NULL;
}
DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size) {
if (buffer_size < 4) {
return false;
}
return (buffer[0] == 0x90) && (buffer[1] == 0xab) && (buffer[2] == 0xcd) &&
(buffer[3] == 0xef);
}
DART_EXPORT bool Dart_IsDart2Snapshot(const uint8_t* snapshot_buffer) {
if (snapshot_buffer == NULL) {
return false;

View file

@ -152,19 +152,16 @@ const char* Snapshot::KindToCString(Kind kind) {
}
}
// 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) {
ASSERT(raw_memory != NULL);
ASSERT(kHeaderSize == sizeof(Snapshot));
ASSERT(kLengthIndex == length_offset());
ASSERT((kSnapshotFlagIndex * sizeof(int64_t)) == kind_offset());
ASSERT((kHeapObjectTag & kInlined));
const Snapshot* snapshot = reinterpret_cast<const Snapshot*>(raw_memory);
if (!snapshot->check_magic()) {
return NULL;
}
// If the raw length is negative or greater than what the local machine can
// handle, then signal an error.
int64_t snapshot_length = ReadUnaligned(&snapshot->unaligned_length_);
if ((snapshot_length < 0) || (snapshot_length > kIntptrMax)) {
int64_t length = snapshot->large_length();
if ((length < 0) || (length > kIntptrMax)) {
return NULL;
}
return snapshot;

View file

@ -161,19 +161,36 @@ class Snapshot {
};
static const char* KindToCString(Kind kind);
static const int kHeaderSize = 2 * sizeof(int64_t);
static const int kLengthIndex = 0;
static const int kSnapshotFlagIndex = 1;
static const Snapshot* SetupFromBuffer(const void* raw_memory);
// Getters.
const uint8_t* content() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
intptr_t length() const {
return static_cast<intptr_t>(ReadUnaligned(&unaligned_length_));
static const int32_t kMagicValue = 0xdcdcf5f5;
static const intptr_t kMagicOffset = 0;
static const intptr_t kMagicSize = sizeof(int32_t);
static const intptr_t kLengthOffset = kMagicOffset + kMagicSize;
static const intptr_t kLengthSize = sizeof(int64_t);
static const intptr_t kKindOffset = kLengthOffset + kLengthSize;
static const intptr_t kKindSize = sizeof(int64_t);
static const intptr_t kHeaderSize = kKindOffset + kKindSize;
// Accessors.
bool check_magic() const {
return Read<int32_t>(kMagicOffset) == kMagicValue;
}
Kind kind() const {
return static_cast<Kind>(ReadUnaligned(&unaligned_kind_));
void set_magic() { return Write<int32_t>(kMagicOffset, kMagicValue); }
// Excluding the magic value from the size written in the buffer is needed
// so we give a proper version mismatch error for snapshots create before
// magic value was written by the VM instead of the embedder.
int64_t large_length() const {
return Read<int64_t>(kLengthOffset) + kMagicSize;
}
intptr_t length() const { return static_cast<intptr_t>(large_length()); }
void set_length(intptr_t value) {
return Write<int64_t>(kLengthOffset, value - kMagicSize);
}
Kind kind() const { return static_cast<Kind>(Read<int64_t>(kKindOffset)); }
void set_kind(Kind value) { return Write<int64_t>(kKindOffset, value); }
const uint8_t* content() const {
return reinterpret_cast<const uint8_t*>(this) + kHeaderSize;
}
static bool IsFull(Kind kind) {
@ -185,20 +202,21 @@ class Snapshot {
const uint8_t* Addr() const { return reinterpret_cast<const uint8_t*>(this); }
static intptr_t length_offset() {
return OFFSET_OF(Snapshot, unaligned_length_);
}
static intptr_t kind_offset() { return OFFSET_OF(Snapshot, unaligned_kind_); }
private:
// Prevent Snapshot from ever being allocated directly.
Snapshot();
// The following fields are potentially unaligned.
int64_t unaligned_length_; // Stream length.
int64_t unaligned_kind_; // Kind of snapshot.
template <typename T>
T Read(intptr_t offset) const {
return ReadUnaligned(
reinterpret_cast<const T*>(reinterpret_cast<uword>(this) + offset));
}
// Variable length data follows here.
template <typename T>
void Write(intptr_t offset, T value) {
return StoreUnaligned(
reinterpret_cast<T*>(reinterpret_cast<uword>(this) + offset), value);
}
DISALLOW_COPY_AND_ASSIGN(Snapshot);
};
@ -570,9 +588,10 @@ class BaseWriter : public StackResource {
}
void FillHeader(Snapshot::Kind kind) {
int64_t* data = reinterpret_cast<int64_t*>(stream_.buffer());
data[Snapshot::kLengthIndex] = stream_.bytes_written();
data[Snapshot::kSnapshotFlagIndex] = kind;
Snapshot* header = reinterpret_cast<Snapshot*>(stream_.buffer());
header->set_magic();
header->set_length(stream_.bytes_written());
header->set_kind(kind);
}
void FreeBuffer() {

View file

@ -1029,6 +1029,7 @@ VM_UNIT_TEST_CASE(CanonicalizationInScriptSnapshots) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1067,6 +1068,7 @@ VM_UNIT_TEST_CASE(CanonicalizationInScriptSnapshots) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -1139,6 +1141,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshotsUpdateSubclasses) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1176,6 +1179,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshotsUpdateSubclasses) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -1452,6 +1456,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1486,6 +1491,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -1550,6 +1556,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot1) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1568,6 +1575,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot1) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -1641,6 +1649,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot2) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1669,6 +1678,7 @@ VM_UNIT_TEST_CASE(ScriptSnapshot2) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -1733,6 +1743,7 @@ VM_UNIT_TEST_CASE(MismatchedSnapshotKinds) {
result = Dart_CreateSnapshot(NULL, &vm_isolate_snapshot_size,
&isolate_snapshot, &isolate_snapshot_size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(isolate_snapshot, isolate_snapshot_size));
full_snapshot = reinterpret_cast<uint8_t*>(malloc(isolate_snapshot_size));
memmove(full_snapshot, isolate_snapshot, isolate_snapshot_size);
Dart_ExitScope();
@ -1754,6 +1765,7 @@ VM_UNIT_TEST_CASE(MismatchedSnapshotKinds) {
// Write out the script snapshot.
result = Dart_CreateScriptSnapshot(&buffer, &size);
EXPECT_VALID(result);
EXPECT(Dart_IsSnapshot(buffer, size));
script_snapshot = reinterpret_cast<uint8_t*>(malloc(size));
memmove(script_snapshot, buffer, size);
Dart_ExitScope();
@ -3145,4 +3157,18 @@ TEST_CASE(OmittedObjectEncodingLength) {
free(writer.buffer());
}
TEST_CASE(IsSnapshotNegative) {
EXPECT(!Dart_IsSnapshot(NULL, 0));
uint8_t buffer[4] = {0, 0, 0, 0};
EXPECT(!Dart_IsSnapshot(buffer, ARRAY_SIZE(buffer)));
}
TEST_CASE(IsKernelNegative) {
EXPECT(!Dart_IsKernel(NULL, 0));
uint8_t buffer[4] = {0, 0, 0, 0};
EXPECT(!Dart_IsKernel(buffer, ARRAY_SIZE(buffer)));
}
} // namespace dart