mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[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:
parent
a81bc639b5
commit
3989d09c95
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue