From 86430cb46a4228329f92c4a49f7eea067830044f Mon Sep 17 00:00:00 2001 From: Ryan Macnak Date: Tue, 25 Sep 2018 23:44:29 +0000 Subject: [PATCH] [vm] Extend AppJIT capability of gen_snapshot. - Add generation of AppJIT snapshots (from a trace rather than a training run). - Add generation of AppJIT snapshots under the constraint of not generating a new instructions segment. - Remove generation of script snapshots (no longer used by Flutter). Change-Id: I2a7cb4b7cd681fae5d33bc896107b3ea903f35d1 Reviewed-on: https://dart-review.googlesource.com/75390 Commit-Queue: Ryan Macnak Reviewed-by: Stanislav Baranov --- runtime/bin/gen_snapshot.cc | 213 ++++++++++++++++++---------------- runtime/bin/snapshot_utils.cc | 4 +- runtime/include/dart_api.h | 3 +- runtime/vm/dart_api_impl.cc | 12 +- runtime/vm/hash_map.h | 1 + runtime/vm/image_snapshot.cc | 89 +++++++++++++- runtime/vm/image_snapshot.h | 12 +- runtime/vm/object.cc | 3 +- 8 files changed, 225 insertions(+), 112 deletions(-) diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 690cf4d27180b..3f6a71f3d4169 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -60,7 +60,7 @@ static const int kErrorExitCode = 255; } // The core snapshot to use when creating isolates. Normally NULL, but loaded -// from a file when creating script snapshots. +// from a file when creating AppJIT snapshots. const uint8_t* isolate_snapshot_data = NULL; const uint8_t* isolate_snapshot_instructions = NULL; @@ -69,7 +69,7 @@ const uint8_t* isolate_snapshot_instructions = NULL; enum SnapshotKind { kCore, kCoreJIT, - kScript, + kAppJIT, kAppAOTBlobs, kAppAOTAssembly, kVMAOTAssembly, @@ -93,7 +93,7 @@ static bool ProcessEnvironmentOption(const char* arg, static const char* kSnapshotKindNames[] = { "core", "core-jit", - "script", + "app-jit", "app-aot-blobs", "app-aot-assembly", "vm-aot-assembly", @@ -101,12 +101,18 @@ static const char* kSnapshotKindNames[] = { }; #define STRING_OPTIONS_LIST(V) \ + V(load_vm_snapshot_data, load_vm_snapshot_data_filename) \ + V(load_vm_snapshot_instructions, load_vm_snapshot_instructions_filename) \ + V(load_isolate_snapshot_data, load_isolate_snapshot_data_filename) \ + V(load_isolate_snapshot_instructions, \ + load_isolate_snapshot_instructions_filename) \ V(vm_snapshot_data, vm_snapshot_data_filename) \ V(vm_snapshot_instructions, vm_snapshot_instructions_filename) \ V(isolate_snapshot_data, isolate_snapshot_data_filename) \ V(isolate_snapshot_instructions, isolate_snapshot_instructions_filename) \ V(shared_data, shared_data_filename) \ V(shared_instructions, shared_instructions_filename) \ + V(reused_instructions, reused_instructions_filename) \ V(assembly, assembly_filename) \ V(script_snapshot, script_snapshot_filename) \ V(dependencies, dependencies_filename) \ @@ -150,10 +156,6 @@ static bool IsSnapshottingForPrecompilation() { (snapshot_kind == kVMAOTAssembly); } -static bool SnapshotKindAllowedFromKernel() { - return snapshot_kind != kScript; -} - // clang-format off static void PrintUsage() { Log::PrintErr( @@ -305,14 +307,17 @@ static int ParseArguments(int argc, } break; } - case kScript: { - if ((vm_snapshot_data_filename == NULL) || + case kAppJIT: { + if ((load_vm_snapshot_data_filename == NULL) || (isolate_snapshot_data_filename == NULL) || - (script_snapshot_filename == NULL) || (*script_name == NULL)) { + ((isolate_snapshot_instructions_filename == NULL) && + (reused_instructions_filename == NULL))) { Log::PrintErr( - "Building a script snapshot requires specifying input files for " - "--vm_snapshot_data and --isolate_snapshot_data, an output file " - "for --script_snapshot, and a Dart script.\n\n"); + "Building an app JIT snapshot requires specifying input files for " + "--load_vm_snapshot_data and --load_vm_snapshot_instructions, an " + " output file for --isolate_snapshot_data, and either an output " + "file for --isolate_snapshot_instructions or an input file for " + "--reused_instructions.\n\n"); return -1; } break; @@ -564,12 +569,13 @@ class DependenciesFileWriter : public ValueObject { WriteDependenciesWithTarget(vm_snapshot_data_filename); // WriteDependenciesWithTarget(isolate_snapshot_data_filename); break; - case kScript: - WriteDependenciesWithTarget(script_snapshot_filename); - break; case kAppAOTAssembly: WriteDependenciesWithTarget(assembly_filename); break; + case kAppJIT: + WriteDependenciesWithTarget(isolate_snapshot_data_filename); + // WriteDependenciesWithTarget(isolate_snapshot_instructions_filename); + break; case kCoreJIT: case kAppAOTBlobs: WriteDependenciesWithTarget(vm_snapshot_data_filename); @@ -593,21 +599,6 @@ class DependenciesFileWriter : public ValueObject { WritePath(target); Write(": "); - if (snapshot_kind == kScript) { - if (vm_snapshot_data_filename != NULL) { - WritePath(vm_snapshot_data_filename); - } - if (vm_snapshot_instructions_filename != NULL) { - WritePath(vm_snapshot_instructions_filename); - } - if (isolate_snapshot_data_filename != NULL) { - WritePath(isolate_snapshot_data_filename); - } - if (isolate_snapshot_instructions_filename != NULL) { - WritePath(isolate_snapshot_instructions_filename); - } - } - for (intptr_t i = 0; i < dependencies_->length(); i++) { WritePath(dependencies_->At(i)); } @@ -765,7 +756,7 @@ static Dart_Handle LoadGenericSnapshotCreationScript( static void LoadCompilationTrace() { if ((load_compilation_trace_filename != NULL) && - (snapshot_kind == kCoreJIT)) { + ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) { uint8_t* buffer = NULL; intptr_t size = 0; ReadFile(load_compilation_trace_filename, &buffer, &size); @@ -805,6 +796,30 @@ static void CreateAndWriteCoreSnapshot() { } } +static std::unique_ptr MapFile(const char* filename, + File::MapType type, + const uint8_t** buffer) { + File* file = File::Open(NULL, filename, File::kRead); + if (file == NULL) { + Log::PrintErr("Failed to open: %s\n", filename); + exit(kErrorExitCode); + } + RefCntReleaseScope rs(file); + intptr_t length = file->Length(); + if (length == 0) { + // Can't map an empty file. + *buffer = NULL; + return NULL; + } + MappedMemory* mapping = file->Map(type, 0, length); + if (mapping == NULL) { + Log::PrintErr("Failed to read: %s\n", filename); + exit(kErrorExitCode); + } + *buffer = reinterpret_cast(mapping->address()); + return std::unique_ptr(mapping); +} + static void CreateAndWriteCoreJITSnapshot() { ASSERT(snapshot_kind == kCoreJIT); ASSERT(vm_snapshot_data_filename != NULL); @@ -844,18 +859,38 @@ static void CreateAndWriteCoreJITSnapshot() { isolate_snapshot_instructions_size); } -static void CreateAndWriteScriptSnapshot() { - ASSERT(snapshot_kind == kScript); - ASSERT(script_snapshot_filename != NULL); +static void CreateAndWriteAppJITSnapshot() { + ASSERT(snapshot_kind == kAppJIT); + ASSERT(isolate_snapshot_data_filename != NULL); + ASSERT((isolate_snapshot_instructions_filename != NULL) || + (reused_instructions_filename != NULL)); - // First create a snapshot. - uint8_t* buffer = NULL; - intptr_t size = 0; - Dart_Handle result = Dart_CreateScriptSnapshot(&buffer, &size); + const uint8_t* reused_instructions = NULL; + std::unique_ptr mapped_reused_instructions; + if (reused_instructions_filename != NULL) { + mapped_reused_instructions = MapFile(reused_instructions_filename, + File::kReadOnly, &reused_instructions); + } + + Dart_Handle result; + uint8_t* isolate_snapshot_data_buffer = NULL; + intptr_t isolate_snapshot_data_size = 0; + uint8_t* isolate_snapshot_instructions_buffer = NULL; + intptr_t isolate_snapshot_instructions_size = 0; + + result = Dart_CreateAppJITSnapshotAsBlobs( + &isolate_snapshot_data_buffer, &isolate_snapshot_data_size, + &isolate_snapshot_instructions_buffer, + &isolate_snapshot_instructions_size, reused_instructions); CHECK_RESULT(result); - // Now write it out to the specified file. - WriteFile(script_snapshot_filename, buffer, size); + WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer, + isolate_snapshot_data_size); + if (reused_instructions_filename == NULL) { + WriteFile(isolate_snapshot_instructions_filename, + isolate_snapshot_instructions_buffer, + isolate_snapshot_instructions_size); + } } static void StreamingWriteCallback(void* callback_data, @@ -870,30 +905,6 @@ static void StreamingWriteCallback(void* callback_data, } } -static std::unique_ptr MapFile(const char* filename, - File::MapType type, - const uint8_t** buffer) { - File* file = File::Open(NULL, filename, File::kRead); - if (file == NULL) { - Log::PrintErr("Failed to open: %s\n", filename); - exit(kErrorExitCode); - } - RefCntReleaseScope rs(file); - intptr_t length = file->Length(); - if (length == 0) { - // Can't map an empty file. - *buffer = NULL; - return NULL; - } - MappedMemory* mapping = file->Map(type, 0, length); - if (mapping == NULL) { - Log::PrintErr("Failed to read: %s\n", filename); - exit(kErrorExitCode); - } - *buffer = reinterpret_cast(mapping->address()); - return std::unique_ptr(mapping); -} - static void CreateAndWritePrecompiledSnapshot() { ASSERT(IsSnapshottingForPrecompilation()); Dart_Handle result; @@ -1050,8 +1061,6 @@ static Dart_QualifiedFunctionName no_entry_points[] = { static int GenerateSnapshotFromKernel(const uint8_t* kernel_buffer, intptr_t kernel_buffer_size) { - ASSERT(SnapshotKindAllowedFromKernel()); - char* error = NULL; IsolateData* isolate_data = new IsolateData(NULL, commandline_package_root, commandline_packages_file, NULL); @@ -1067,12 +1076,19 @@ static int GenerateSnapshotFromKernel(const uint8_t* kernel_buffer, isolate_flags.entry_points = no_entry_points; } - // We need to capture the vmservice library in the core snapshot, so load it - // in the main isolate as well. - isolate_flags.load_vmservice_library = true; - Dart_Isolate isolate = Dart_CreateIsolateFromKernel( - NULL, NULL, kernel_buffer, kernel_buffer_size, &isolate_flags, - isolate_data, &error); + Dart_Isolate isolate; + if (isolate_snapshot_data == NULL) { + // We need to capture the vmservice library in the core snapshot, so load it + // in the main isolate as well. + isolate_flags.load_vmservice_library = true; + isolate = Dart_CreateIsolateFromKernel(NULL, NULL, kernel_buffer, + kernel_buffer_size, &isolate_flags, + isolate_data, &error); + } else { + isolate = Dart_CreateIsolate(NULL, NULL, isolate_snapshot_data, + isolate_snapshot_instructions, NULL, NULL, + &isolate_flags, isolate_data, &error); + } if (isolate == NULL) { delete isolate_data; Log::PrintErr("%s\n", error); @@ -1125,6 +1141,10 @@ static int GenerateSnapshotFromKernel(const uint8_t* kernel_buffer, LoadCompilationTrace(); CreateAndWriteCoreJITSnapshot(); break; + case kAppJIT: + LoadCompilationTrace(); + CreateAndWriteAppJITSnapshot(); + break; default: UNREACHABLE(); } @@ -1172,13 +1192,6 @@ int main(int argc, char** argv) { dfe.ReadScript(app_script_name, &kernel_buffer, &kernel_buffer_size); } if (kernel_buffer != NULL) { - if (!SnapshotKindAllowedFromKernel()) { - // TODO(sivachandra): Add check for the kernel program format (incremental - // vs batch). - Log::PrintErr( - "Can only generate core or aot snapshots from a kernel file.\n"); - return kErrorExitCode; - } if (dependencies_filename != NULL) { Log::PrintErr("Depfiles are not supported in Dart 2.\n"); return kErrorExitCode; @@ -1205,7 +1218,7 @@ int main(int argc, char** argv) { if (IsSnapshottingForPrecompilation()) { vm_options.AddArgument("--precompilation"); } - if (snapshot_kind == kCoreJIT) { + if (snapshot_kind == kCoreJIT || snapshot_kind == kAppJIT) { vm_options.AddArgument("--fields_may_be_reset"); vm_options.AddArgument("--link_natives_lazily"); #if !defined(PRODUCT) @@ -1246,26 +1259,25 @@ int main(int argc, char** argv) { std::unique_ptr mapped_vm_snapshot_instructions; std::unique_ptr mapped_isolate_snapshot_data; std::unique_ptr mapped_isolate_snapshot_instructions; - if (snapshot_kind == kScript) { + if (load_vm_snapshot_data_filename != NULL) { mapped_vm_snapshot_data = - MapFile(vm_snapshot_data_filename, File::kReadOnly, + MapFile(load_vm_snapshot_data_filename, File::kReadOnly, &init_params.vm_snapshot_data); - - if (vm_snapshot_instructions_filename != NULL) { - mapped_vm_snapshot_instructions = - MapFile(vm_snapshot_instructions_filename, File::kReadExecute, - &init_params.vm_snapshot_instructions); - } - + } + if (load_vm_snapshot_instructions_filename != NULL) { + mapped_vm_snapshot_instructions = + MapFile(load_vm_snapshot_instructions_filename, File::kReadExecute, + &init_params.vm_snapshot_instructions); + } + if (load_isolate_snapshot_data_filename) { mapped_isolate_snapshot_data = - MapFile(isolate_snapshot_data_filename, File::kReadOnly, + MapFile(load_isolate_snapshot_data_filename, File::kReadOnly, &isolate_snapshot_data); - - if (isolate_snapshot_instructions_filename != NULL) { - mapped_isolate_snapshot_instructions = - MapFile(isolate_snapshot_instructions_filename, File::kReadExecute, - &isolate_snapshot_instructions); - } + } + if (load_isolate_snapshot_instructions_filename != NULL) { + mapped_isolate_snapshot_instructions = + MapFile(load_isolate_snapshot_instructions_filename, File::kReadExecute, + &isolate_snapshot_instructions); } error = Dart_Initialize(&init_params); @@ -1391,8 +1403,8 @@ int main(int argc, char** argv) { case kCoreJIT: CreateAndWriteCoreJITSnapshot(); break; - case kScript: - CreateAndWriteScriptSnapshot(); + case kAppJIT: + CreateAndWriteAppJITSnapshot(); break; case kAppAOTBlobs: case kAppAOTAssembly: @@ -1419,6 +1431,9 @@ int main(int argc, char** argv) { case kCoreJIT: CreateAndWriteCoreJITSnapshot(); break; + case kAppJIT: + CreateAndWriteAppJITSnapshot(); + break; default: UNREACHABLE(); break; diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc index 2ff01c2dc40d5..99ee0ec8e0d41 100644 --- a/runtime/bin/snapshot_utils.cc +++ b/runtime/bin/snapshot_utils.cc @@ -368,7 +368,7 @@ void Snapshot::GenerateScript(const char* snapshot_filename) { void Snapshot::GenerateAppJIT(const char* snapshot_filename) { #if defined(TARGET_ARCH_IA32) - // Snapshots with code are not supported on IA32 or DBC. + // Snapshots with code are not supported on IA32. uint8_t* isolate_buffer = NULL; intptr_t isolate_size = 0; @@ -387,7 +387,7 @@ void Snapshot::GenerateAppJIT(const char* snapshot_filename) { intptr_t isolate_instructions_size = 0; Dart_Handle result = Dart_CreateAppJITSnapshotAsBlobs( &isolate_data_buffer, &isolate_data_size, &isolate_instructions_buffer, - &isolate_instructions_size); + &isolate_instructions_size, NULL); if (Dart_IsError(result)) { ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result)); } diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index a8df73240cc4e..a41812c6e0669 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3470,7 +3470,8 @@ DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, intptr_t* isolate_snapshot_data_size, uint8_t** isolate_snapshot_instructions_buffer, - intptr_t* isolate_snapshot_instructions_size); + intptr_t* isolate_snapshot_instructions_size, + const uint8_t* reused_instructions); /** * Like Dart_CreateAppJITSnapshotAsBlobs, but also creates a new VM snapshot. diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 7a079a0fa2a25..1c4c4f59986b6 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -6597,7 +6597,8 @@ DART_EXPORT Dart_Handle Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, intptr_t* isolate_snapshot_data_size, uint8_t** isolate_snapshot_instructions_buffer, - intptr_t* isolate_snapshot_instructions_size) { + intptr_t* isolate_snapshot_instructions_size, + const uint8_t* reused_instructions) { #if defined(TARGET_ARCH_IA32) return Api::NewError("Snapshots with code are not supported on IA32."); #elif defined(DART_PRECOMPILED_RUNTIME) @@ -6621,6 +6622,9 @@ Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, } BackgroundCompiler::Stop(I); + if (reused_instructions) { + DropCodeWithoutReusableInstructions(reused_instructions); + } ProgramVisitor::Dedup(); Symbols::Compact(I); @@ -6628,7 +6632,7 @@ Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, "WriteAppJITSnapshot")); BlobImageWriter isolate_image_writer(isolate_snapshot_instructions_buffer, ApiReallocate, 2 * MB /* initial_size */, - NULL, NULL); + NULL, NULL, reused_instructions); FullSnapshotWriter writer(Snapshot::kFullJIT, NULL, isolate_snapshot_data_buffer, ApiReallocate, NULL, &isolate_image_writer); @@ -6638,6 +6642,10 @@ Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer, *isolate_snapshot_instructions_size = isolate_image_writer.InstructionsBlobSize(); + if (reused_instructions) { + *isolate_snapshot_instructions_buffer = NULL; + } + return Api::Success(); #endif } diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h index fb6ff15ad326b..95194aadeec7e 100644 --- a/runtime/vm/hash_map.h +++ b/runtime/vm/hash_map.h @@ -43,6 +43,7 @@ class BaseDirectChainedHashMap : public B { return Lookup(key) != NULL; } + intptr_t Size() const { return count_; } bool IsEmpty() const { return count_ == 0; } virtual void Clear() { diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc index 28dda6aba8a2d..26dea3aa1daf4 100644 --- a/runtime/vm/image_snapshot.cc +++ b/runtime/vm/image_snapshot.cc @@ -12,6 +12,7 @@ #include "vm/heap/heap.h" #include "vm/json_writer.h" #include "vm/object.h" +#include "vm/program_visitor.h" #include "vm/stub_code.h" #include "vm/timeline.h" #include "vm/type_testing_stubs.h" @@ -30,6 +31,11 @@ DEFINE_FLAG(charp, "Print sizes of all instruction objects to the given file"); #endif +DEFINE_FLAG(bool, + trace_reused_instructions, + false, + "Print code that lacks reusable instructions"); + intptr_t ObjectOffsetTrait::Hashcode(Key key) { RawObject* obj = key; ASSERT(!obj->IsSmi()); @@ -72,11 +78,13 @@ bool ObjectOffsetTrait::IsKeyEqual(Pair pair, Key key) { } ImageWriter::ImageWriter(const void* shared_objects, - const void* shared_instructions) + const void* shared_instructions, + const void* reused_instructions) : next_data_offset_(0), next_text_offset_(0), objects_(), instructions_() { ResetOffsets(); SetupShared(&shared_objects_, shared_objects); SetupShared(&shared_instructions_, shared_instructions); + SetupShared(&reuse_instructions_, reused_instructions); } void ImageWriter::SetupShared(ObjectOffsetMap* map, const void* shared_image) { @@ -100,6 +108,15 @@ void ImageWriter::SetupShared(ObjectOffsetMap* map, const void* shared_image) { int32_t ImageWriter::GetTextOffsetFor(RawInstructions* instructions, RawCode* code) { + if (!reuse_instructions_.IsEmpty()) { + ObjectOffsetPair* pair = reuse_instructions_.Lookup(instructions); + if (pair == NULL) { + // Code should have been removed by DropCodeWithoutReusableInstructions. + FATAL("Expected instructions to reuse\n"); + } + return pair->offset; + } + ObjectOffsetPair* pair = shared_instructions_.Lookup(instructions); if (pair != NULL) { // Negative offsets tell the reader the offset is w/r/t the shared @@ -280,7 +297,7 @@ AssemblyImageWriter::AssemblyImageWriter(Dart_StreamingWriteCallback callback, void* callback_data, const void* shared_objects, const void* shared_instructions) - : ImageWriter(shared_objects, shared_instructions), + : ImageWriter(shared_objects, shared_instructions, NULL), assembly_stream_(512 * KB, callback, callback_data), dwarf_(NULL) { #if defined(DART_PRECOMPILER) @@ -531,8 +548,9 @@ BlobImageWriter::BlobImageWriter(uint8_t** instructions_blob_buffer, ReAlloc alloc, intptr_t initial_size, const void* shared_objects, - const void* shared_instructions) - : ImageWriter(shared_objects, shared_instructions), + const void* shared_instructions, + const void* reused_instructions) + : ImageWriter(shared_objects, shared_instructions, reused_instructions), instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) { } @@ -644,4 +662,67 @@ RawObject* ImageReader::GetSharedObjectAt(uint32_t offset) const { return result; } +void DropCodeWithoutReusableInstructions(const void* reused_instructions) { + class DropCodeVisitor : public FunctionVisitor, public ClassVisitor { + public: + explicit DropCodeVisitor(const void* reused_instructions) + : code_(Code::Handle()), instructions_(Instructions::Handle()) { + ImageWriter::SetupShared(&reused_instructions_, reused_instructions); + if (FLAG_trace_reused_instructions) { + OS::PrintErr("%" Pd " reusable instructions\n", + reused_instructions_.Size()); + } + } + + void Visit(const Class& cls) { + code_ = cls.allocation_stub(); + if (!code_.IsNull() && !IsAvailable(code_)) { + if (FLAG_trace_reused_instructions) { + OS::PrintErr("No reusable instructions for %s\n", cls.ToCString()); + } + cls.DisableAllocationStub(); + } + } + + void Visit(const Function& func) { + if (func.HasCode()) { + code_ = func.CurrentCode(); + if (!IsAvailable(code_)) { + if (FLAG_trace_reused_instructions) { + OS::PrintErr("No reusable instructions for %s\n", func.ToCString()); + } + func.ClearCode(); + func.ClearICDataArray(); + return; + } + } + code_ = func.unoptimized_code(); + if (!code_.IsNull() && !IsAvailable(code_)) { + if (FLAG_trace_reused_instructions) { + OS::PrintErr("No reusable instructions for %s\n", func.ToCString()); + } + func.ClearCode(); + func.ClearICDataArray(); + return; + } + } + + private: + bool IsAvailable(const Code& code) { + ObjectOffsetPair* pair = reused_instructions_.Lookup(code.instructions()); + return pair != NULL; + } + + ObjectOffsetMap reused_instructions_; + Code& code_; + Instructions& instructions_; + + DISALLOW_COPY_AND_ASSIGN(DropCodeVisitor); + }; + + DropCodeVisitor visitor(reused_instructions); + ProgramVisitor::VisitClasses(&visitor); + ProgramVisitor::VisitFunctions(&visitor); +} + } // namespace dart diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h index a4af7e4b62fc3..b5ba9dc640ba0 100644 --- a/runtime/vm/image_snapshot.h +++ b/runtime/vm/image_snapshot.h @@ -96,10 +96,12 @@ typedef DirectChainedHashMap ObjectOffsetMap; class ImageWriter : public ValueObject { public: - ImageWriter(const void* shared_objects, const void* shared_instructions); + ImageWriter(const void* shared_objects, + const void* shared_instructions, + const void* reused_instructions); virtual ~ImageWriter() {} - void SetupShared(ObjectOffsetMap* map, const void* shared_image); + static void SetupShared(ObjectOffsetMap* map, const void* shared_image); void ResetOffsets() { next_data_offset_ = Image::kHeaderSize; next_text_offset_ = Image::kHeaderSize; @@ -156,6 +158,7 @@ class ImageWriter : public ValueObject { GrowableArray instructions_; ObjectOffsetMap shared_objects_; ObjectOffsetMap shared_instructions_; + ObjectOffsetMap reuse_instructions_; private: DISALLOW_COPY_AND_ASSIGN(ImageWriter); @@ -196,7 +199,8 @@ class BlobImageWriter : public ImageWriter { ReAlloc alloc, intptr_t initial_size, const void* shared_objects, - const void* shared_instructions); + const void* shared_instructions, + const void* reused_instructions = NULL); virtual void WriteText(WriteStream* clustered_stream, bool vm); @@ -210,6 +214,8 @@ class BlobImageWriter : public ImageWriter { DISALLOW_COPY_AND_ASSIGN(BlobImageWriter); }; +void DropCodeWithoutReusableInstructions(const void* reused_instructions); + } // namespace dart #endif // RUNTIME_VM_IMAGE_SNAPSHOT_H_ diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 0a4719f618ae7..5a92e02901228 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -1276,7 +1276,8 @@ RawError* Object::Init(Isolate* isolate, "Object::Init");) #if defined(DART_NO_SNAPSHOT) - bool bootstrapping = Dart::vm_snapshot_kind() == Snapshot::kNone; + bool bootstrapping = + (Dart::vm_snapshot_kind() == Snapshot::kNone) || is_kernel; #elif defined(DART_PRECOMPILED_RUNTIME) bool bootstrapping = false; #else