Chromium Code Reviews| Index: runtime/vm/bootstrap.cc |
| diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc |
| index ed97340f8e254946e1a2e7c78c499f3319702664..965f40a824510013e808d5d598edf6a39114bd8c 100644 |
| --- a/runtime/vm/bootstrap.cc |
| +++ b/runtime/vm/bootstrap.cc |
| @@ -10,24 +10,21 @@ |
| #include "vm/class_finalizer.h" |
| #include "vm/compiler.h" |
| #include "vm/dart_api_impl.h" |
| +#include "vm/kernel.h" |
| +#include "vm/kernel_reader.h" |
| #include "vm/object.h" |
| #include "vm/object_store.h" |
| #include "vm/symbols.h" |
| namespace dart { |
| -#define INIT_LIBRARY(index, name, source, patch) \ |
| - { index, \ |
| - "dart:"#name, source, \ |
| - "dart:"#name"-patch", patch } \ |
| - |
| -typedef struct { |
| - ObjectStore::BootstrapLibraryId index_; |
| - const char* uri_; |
| - const char** source_paths_; |
| - const char* patch_uri_; |
| - const char** patch_paths_; |
| -} bootstrap_lib_props; |
| +struct BootstrapLibProps { |
| + ObjectStore::BootstrapLibraryId index; |
| + const char* uri; |
| + const char** source_paths; |
| + const char* patch_uri; |
| + const char** patch_paths; |
| +}; |
| enum { |
| @@ -38,81 +35,36 @@ enum { |
| }; |
| -static bootstrap_lib_props bootstrap_libraries[] = { |
| - INIT_LIBRARY(ObjectStore::kCore, |
| - core, |
| - Bootstrap::core_source_paths_, |
| - Bootstrap::core_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kAsync, |
| - async, |
| - Bootstrap::async_source_paths_, |
| - Bootstrap::async_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kConvert, |
| - convert, |
| - Bootstrap::convert_source_paths_, |
| - Bootstrap::convert_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kCollection, |
| - collection, |
| - Bootstrap::collection_source_paths_, |
| - Bootstrap::collection_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kDeveloper, |
| - developer, |
| - Bootstrap::developer_source_paths_, |
| - Bootstrap::developer_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kInternal, |
| - _internal, |
| - Bootstrap::_internal_source_paths_, |
| - Bootstrap::_internal_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kIsolate, |
| - isolate, |
| - Bootstrap::isolate_source_paths_, |
| - Bootstrap::isolate_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kMath, |
| - math, |
| - Bootstrap::math_source_paths_, |
| - Bootstrap::math_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kMirrors, |
| - mirrors, |
| - Bootstrap::mirrors_source_paths_, |
| - Bootstrap::mirrors_patch_paths_), |
| - INIT_LIBRARY(ObjectStore::kProfiler, |
| - profiler, |
| - Bootstrap::profiler_source_paths_, |
| - NULL), |
| - INIT_LIBRARY(ObjectStore::kTypedData, |
| - typed_data, |
| - Bootstrap::typed_data_source_paths_, |
| - NULL), |
| - INIT_LIBRARY(ObjectStore::kVMService, |
| - _vmservice, |
| - Bootstrap::_vmservice_source_paths_, |
| - Bootstrap::_vmservice_patch_paths_), |
| - { ObjectStore::kNone, NULL, NULL, NULL, NULL } |
| +const char** Bootstrap::profiler_patch_paths_ = NULL; |
| +const char** Bootstrap::typed_data_patch_paths_ = NULL; |
| + |
| + |
| +#define MAKE_PROPERTIES(CamelName, hacker_name) \ |
|
Florian Schneider
2016/11/08 20:41:39
I do like reducing boilerplate code, but I don't l
Vyacheslav Egorov (Google)
2016/11/09 14:43:16
Moved to a separate CL: https://codereview.chromiu
|
| + { ObjectStore::k##CamelName, \ |
| + "dart:" #hacker_name, \ |
|
Florian Schneider
2016/11/08 20:41:39
What's a hacker_name? Why not just use "name"?
Vyacheslav Egorov (Google)
2016/11/09 14:43:16
I guess hacker_name is name_with_underscores. Rena
Kevin Millikin (Google)
2016/11/09 15:17:32
Because the other parameter is also a name.
|
| + Bootstrap::hacker_name##_source_paths_, \ |
| + "dart:" #hacker_name "-patch", \ |
| + Bootstrap::hacker_name##_patch_paths_ \ |
| + }, |
| + |
| +static BootstrapLibProps bootstrap_libraries[] = { |
|
Florian Schneider
2016/11/08 20:41:39
static const?
Vyacheslav Egorov (Google)
2016/11/09 14:43:16
Done.
|
| + FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_PROPERTIES) |
| }; |
| +#undef MAKE_PROPERTIES |
| -static RawString* GetLibrarySource(const Library& lib, |
| - const String& uri, |
| - bool patch) { |
| - // First check if this is a valid bootstrap library and find it's index |
| - // in the 'bootstrap_libraries' table above. |
| - intptr_t index; |
| - const String& lib_uri = String::Handle(lib.url()); |
| - for (index = 0; |
| - bootstrap_libraries[index].index_ != ObjectStore::kNone; |
| - ++index) { |
| - if (lib_uri.Equals(bootstrap_libraries[index].uri_)) { |
| - break; |
| - } |
| - } |
| - if (bootstrap_libraries[index].index_ == ObjectStore::kNone) { |
| - return String::null(); // Library is not a bootstrap library. |
| - } |
| + |
| +static const intptr_t kBootstrapLibraryCount = ARRAY_SIZE(bootstrap_libraries); |
| + |
| + |
| +static RawString* GetLibrarySourceByIndex(intptr_t index, |
| + const String& uri, |
| + bool patch) { |
| + ASSERT(index >= 0 && index < kBootstrapLibraryCount); |
| // Try to read the source using the path specified for the uri. |
| - const char** source_paths = patch ? |
| - bootstrap_libraries[index].patch_paths_ : |
| - bootstrap_libraries[index].source_paths_; |
| + const char** source_paths = patch ? bootstrap_libraries[index].patch_paths |
| + : bootstrap_libraries[index].source_paths; |
| if (source_paths == NULL) { |
| return String::null(); // No path mapping information exists for library. |
| } |
| @@ -157,6 +109,26 @@ static RawString* GetLibrarySource(const Library& lib, |
| } |
| +static RawString* GetLibrarySource(const Library& lib, |
| + const String& uri, |
| + bool patch) { |
| + // First check if this is a valid bootstrap library and find its index in |
| + // the 'bootstrap_libraries' table above. |
| + intptr_t index; |
| + const String& lib_uri = String::Handle(lib.url()); |
| + for (index = 0; index < kBootstrapLibraryCount; ++index) { |
| + if (lib_uri.Equals(bootstrap_libraries[index].uri)) { |
| + break; |
| + } |
| + } |
| + if (index == kBootstrapLibraryCount) { |
| + return String::null(); // The library is not a bootstrap library. |
| + } |
| + |
| + return GetLibrarySourceByIndex(index, uri, patch); |
| +} |
| + |
| + |
| static RawError* Compile(const Library& library, const Script& script) { |
| bool update_lib_status = (script.kind() == RawScript::kScriptTag || |
| script.kind() == RawScript::kLibraryTag); |
| @@ -240,10 +212,15 @@ static Dart_Handle BootstrapLibraryTagHandler(Dart_LibraryTag tag, |
| } |
| -static RawError* LoadPatchFiles(Zone* zone, |
| +static RawError* LoadPatchFiles(Thread* thread, |
| const Library& lib, |
| - const String& patch_uri, |
| - const char** patch_files) { |
| + intptr_t index) { |
| + const char** patch_files = bootstrap_libraries[index].patch_paths; |
| + if (patch_files == NULL) return Error::null(); |
| + |
| + Zone* zone = thread->zone(); |
| + String& patch_uri = String::Handle( |
| + zone, Symbols::New(thread, bootstrap_libraries[index].patch_uri)); |
| String& patch_file_uri = String::Handle(zone); |
| String& source = String::Handle(zone); |
| Script& script = Script::Handle(zone); |
| @@ -253,7 +230,7 @@ static RawError* LoadPatchFiles(Zone* zone, |
| strings.SetAt(1, Symbols::Slash()); |
| for (intptr_t j = 0; patch_files[j] != NULL; j += kPathsEntryLength) { |
| patch_file_uri = String::New(patch_files[j + kPathsUriOffset]); |
| - source = GetLibrarySource(lib, patch_file_uri, true); |
| + source = GetLibrarySourceByIndex(index, patch_file_uri, true); |
| if (source.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("Unable to find dart patch source for %s", |
| @@ -273,57 +250,46 @@ static RawError* LoadPatchFiles(Zone* zone, |
| } |
| -RawError* Bootstrap::LoadandCompileScripts() { |
| - Thread* thread = Thread::Current(); |
| +static void Finish(Thread* thread, bool from_kernel) { |
| + Bootstrap::SetupNativeResolver(); |
| + if (!ClassFinalizer::ProcessPendingClasses(from_kernel)) { |
| + FATAL("Error in class finalization during bootstrapping."); |
| + } |
| + |
| + // Eagerly compile the _Closure class as it is the class of all closure |
| + // instances. This allows us to just finalize function types without going |
| + // through the hoops of trying to compile their scope class. |
| + ObjectStore* object_store = thread->isolate()->object_store(); |
| + Class& cls = Class::Handle(thread->zone(), object_store->closure_class()); |
| + Compiler::CompileClass(cls); |
| + // Eagerly compile Bool class, bool constants are used from within compiler. |
| + cls = object_store->bool_class(); |
| + Compiler::CompileClass(cls); |
| +} |
| + |
| + |
| +static RawError* BootstrapFromSource(Thread* thread) { |
| Isolate* isolate = thread->isolate(); |
| Zone* zone = thread->zone(); |
| String& uri = String::Handle(zone); |
| - String& patch_uri = String::Handle(zone); |
| String& source = String::Handle(zone); |
| Script& script = Script::Handle(zone); |
| Library& lib = Library::Handle(zone); |
| Error& error = Error::Handle(zone); |
| - Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler(); |
| // Set the library tag handler for the isolate to the bootstrap |
| // library tag handler so that we can load all the bootstrap libraries. |
| + Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler(); |
| isolate->set_library_tag_handler(BootstrapLibraryTagHandler); |
| - HANDLESCOPE(thread); |
| - |
| - // Create library objects for all the bootstrap libraries. |
| - for (intptr_t i = 0; |
| - bootstrap_libraries[i].index_ != ObjectStore::kNone; |
| - ++i) { |
| -#ifdef PRODUCT |
| - if (bootstrap_libraries[i].index_ == ObjectStore::kMirrors) { |
| - continue; |
| - } |
| -#endif // !PRODUCT |
| - uri = Symbols::New(thread, bootstrap_libraries[i].uri_); |
| - lib = Library::LookupLibrary(thread, uri); |
| - if (lib.IsNull()) { |
| - lib = Library::NewLibraryHelper(uri, false); |
| - lib.SetLoadRequested(); |
| - lib.Register(thread); |
| - } |
| - isolate->object_store()->set_bootstrap_library( |
| - bootstrap_libraries[i].index_, lib); |
| - } |
| - |
| // Load, compile and patch bootstrap libraries. |
| - for (intptr_t i = 0; |
| - bootstrap_libraries[i].index_ != ObjectStore::kNone; |
| - ++i) { |
| -#ifdef PRODUCT |
| - if (bootstrap_libraries[i].index_ == ObjectStore::kMirrors) { |
| - continue; |
| - } |
| -#endif // PRODUCT |
| - uri = Symbols::New(thread, bootstrap_libraries[i].uri_); |
| - lib = Library::LookupLibrary(thread, uri); |
| + for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) { |
| + ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index; |
| + uri = Symbols::New(thread, bootstrap_libraries[i].uri); |
| + lib = isolate->object_store()->bootstrap_library(id); |
| ASSERT(!lib.IsNull()); |
| - source = GetLibrarySource(lib, uri, false); |
| + ASSERT(lib.raw() == Library::LookupLibrary(thread, uri)); |
| + source = GetLibrarySourceByIndex(i, uri, false); |
| if (source.IsNull()) { |
| const String& message = String::Handle( |
| String::NewFormatted("Unable to find dart source for %s", |
| @@ -337,36 +303,97 @@ RawError* Bootstrap::LoadandCompileScripts() { |
| break; |
| } |
| // If a patch exists, load and patch the script. |
| - if (bootstrap_libraries[i].patch_paths_ != NULL) { |
| - patch_uri = Symbols::New(thread, bootstrap_libraries[i].patch_uri_); |
| - error = LoadPatchFiles(zone, |
| - lib, |
| - patch_uri, |
| - bootstrap_libraries[i].patch_paths_); |
| - if (!error.IsNull()) { |
| - break; |
| - } |
| + error = LoadPatchFiles(thread, lib, i); |
| + if (!error.IsNull()) { |
| + break; |
| } |
| } |
| + |
| if (error.IsNull()) { |
| - SetupNativeResolver(); |
| - ClassFinalizer::ProcessPendingClasses(); |
| - |
| - // Eagerly compile the _Closure class as it is the class of all closure |
| - // instances. This allows us to just finalize function types |
| - // without going through the hoops of trying to compile their scope class. |
| - Class& cls = |
| - Class::Handle(zone, isolate->object_store()->closure_class()); |
| - Compiler::CompileClass(cls); |
| - // Eagerly compile Bool class, bool constants are used from within compiler. |
| - cls = isolate->object_store()->bool_class(); |
| - Compiler::CompileClass(cls); |
| + Finish(thread, /*from_kernel=*/false); |
| } |
| - |
| // Restore the library tag handler for the isolate. |
| isolate->set_library_tag_handler(saved_tag_handler); |
| return error.raw(); |
| } |
| + |
| +static RawError* BootstrapFromKernel(Thread* thread, |
| + const uint8_t* buffer, |
| + intptr_t buffer_size) { |
| + Zone* zone = thread->zone(); |
| + kernel::Program* program = |
| + ReadPrecompiledKernelFromBuffer(buffer, buffer_size); |
| + if (program == NULL) { |
| + const String& message = |
| + String::Handle(zone, String::New("Failed to read Kernel file")); |
| + return ApiError::New(message); |
| + } |
| + |
| + Isolate* isolate = thread->isolate(); |
| + // Mark the already-pending classes. This mark bit will be used to avoid |
| + // adding classes to the list more than once. |
| + GrowableObjectArray& pending_classes = GrowableObjectArray::Handle( |
| + zone, isolate->object_store()->pending_classes()); |
| + dart::Class& pending = dart::Class::Handle(zone); |
| + for (intptr_t i = 0; i < pending_classes.Length(); ++i) { |
| + pending ^= pending_classes.At(i); |
| + pending.set_is_marked_for_parsing(); |
| + } |
| + |
| + Library& library = Library::Handle(zone); |
| + String& dart_name = String::Handle(zone); |
| + String& kernel_name = String::Handle(zone); |
| + kernel::KernelReader reader(NULL, -1, true); |
| + for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) { |
| + ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index; |
| + library = isolate->object_store()->bootstrap_library(id); |
| + dart_name = library.url(); |
| + for (intptr_t j = 0; j < program->libraries().length(); ++j) { |
| + kernel::Library* kernel_library = program->libraries()[j]; |
| + kernel::String* uri = kernel_library->import_uri(); |
| + kernel_name = Symbols::FromUTF8(thread, uri->buffer(), uri->size()); |
| + if (kernel_name.Equals(dart_name)) { |
| + reader.ReadLibrary(kernel_library); |
| + library.SetLoaded(); |
| + break; |
| + } |
| + } |
| + } |
| + |
| + Finish(thread, /*from_kernel=*/true); |
| + return Error::null(); |
| +} |
| + |
| + |
| +RawError* Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer, |
| + intptr_t kernel_buffer_length) { |
| + Thread* thread = Thread::Current(); |
| + Isolate* isolate = thread->isolate(); |
| + Zone* zone = thread->zone(); |
| + String& uri = String::Handle(zone); |
| + Library& lib = Library::Handle(zone); |
| + |
| + HANDLESCOPE(thread); |
| + |
| + // Ensure there are library objects for all the bootstrap libraries. |
| + for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) { |
| + ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index; |
| + uri = Symbols::New(thread, bootstrap_libraries[i].uri); |
| + lib = isolate->object_store()->bootstrap_library(id); |
| + ASSERT(lib.raw() == Library::LookupLibrary(thread, uri)); |
| + if (lib.IsNull()) { |
| + lib = Library::NewLibraryHelper(uri, false); |
| + lib.SetLoadRequested(); |
| + lib.Register(thread); |
| + isolate->object_store()->set_bootstrap_library(id, lib); |
| + } |
| + } |
| + |
| + return (kernel_buffer == NULL) |
| + ? BootstrapFromSource(thread) |
| + : BootstrapFromKernel(thread, kernel_buffer, kernel_buffer_length); |
| +} |
| + |
| } // namespace dart |