Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: runtime/vm/bootstrap.cc

Issue 2485993002: VM: Support bootstrapping core libraries from Kernel binaries instead of source. (Closed)
Patch Set: Done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/bootstrap.h" 5 #include "vm/bootstrap.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/bootstrap_natives.h" 9 #include "vm/bootstrap_natives.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
11 #include "vm/compiler.h" 11 #include "vm/compiler.h"
12 #include "vm/dart_api_impl.h" 12 #include "vm/dart_api_impl.h"
13 #include "vm/kernel.h"
14 #include "vm/kernel_reader.h"
13 #include "vm/object.h" 15 #include "vm/object.h"
14 #include "vm/object_store.h" 16 #include "vm/object_store.h"
15 #include "vm/symbols.h" 17 #include "vm/symbols.h"
16 18
17 namespace dart { 19 namespace dart {
18 20
19 #define INIT_LIBRARY(index, name, source, patch) \ 21 struct BootstrapLibProps {
20 { index, \ 22 ObjectStore::BootstrapLibraryId index;
21 "dart:"#name, source, \ 23 const char* uri;
22 "dart:"#name"-patch", patch } \ 24 const char** source_paths;
23 25 const char* patch_uri;
24 typedef struct { 26 const char** patch_paths;
25 ObjectStore::BootstrapLibraryId index_; 27 };
26 const char* uri_;
27 const char** source_paths_;
28 const char* patch_uri_;
29 const char** patch_paths_;
30 } bootstrap_lib_props;
31 28
32 29
33 enum { 30 enum {
34 kPathsUriOffset = 0, 31 kPathsUriOffset = 0,
35 kPathsFileOffset = 1, 32 kPathsFileOffset = 1,
36 kPathsSourceOffset = 2, 33 kPathsSourceOffset = 2,
37 kPathsEntryLength = 3 34 kPathsEntryLength = 3
38 }; 35 };
39 36
40 37
41 static bootstrap_lib_props bootstrap_libraries[] = { 38 const char** Bootstrap::profiler_patch_paths_ = NULL;
42 INIT_LIBRARY(ObjectStore::kCore, 39 const char** Bootstrap::typed_data_patch_paths_ = NULL;
43 core, 40
44 Bootstrap::core_source_paths_, 41
45 Bootstrap::core_patch_paths_), 42 #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
46 INIT_LIBRARY(ObjectStore::kAsync, 43 { ObjectStore::k##CamelName, \
47 async, 44 "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.
48 Bootstrap::async_source_paths_, 45 Bootstrap::hacker_name##_source_paths_, \
49 Bootstrap::async_patch_paths_), 46 "dart:" #hacker_name "-patch", \
50 INIT_LIBRARY(ObjectStore::kConvert, 47 Bootstrap::hacker_name##_patch_paths_ \
51 convert, 48 },
52 Bootstrap::convert_source_paths_, 49
53 Bootstrap::convert_patch_paths_), 50 static BootstrapLibProps bootstrap_libraries[] = {
Florian Schneider 2016/11/08 20:41:39 static const?
Vyacheslav Egorov (Google) 2016/11/09 14:43:16 Done.
54 INIT_LIBRARY(ObjectStore::kCollection, 51 FOR_EACH_BOOTSTRAP_LIBRARY(MAKE_PROPERTIES)
55 collection,
56 Bootstrap::collection_source_paths_,
57 Bootstrap::collection_patch_paths_),
58 INIT_LIBRARY(ObjectStore::kDeveloper,
59 developer,
60 Bootstrap::developer_source_paths_,
61 Bootstrap::developer_patch_paths_),
62 INIT_LIBRARY(ObjectStore::kInternal,
63 _internal,
64 Bootstrap::_internal_source_paths_,
65 Bootstrap::_internal_patch_paths_),
66 INIT_LIBRARY(ObjectStore::kIsolate,
67 isolate,
68 Bootstrap::isolate_source_paths_,
69 Bootstrap::isolate_patch_paths_),
70 INIT_LIBRARY(ObjectStore::kMath,
71 math,
72 Bootstrap::math_source_paths_,
73 Bootstrap::math_patch_paths_),
74 INIT_LIBRARY(ObjectStore::kMirrors,
75 mirrors,
76 Bootstrap::mirrors_source_paths_,
77 Bootstrap::mirrors_patch_paths_),
78 INIT_LIBRARY(ObjectStore::kProfiler,
79 profiler,
80 Bootstrap::profiler_source_paths_,
81 NULL),
82 INIT_LIBRARY(ObjectStore::kTypedData,
83 typed_data,
84 Bootstrap::typed_data_source_paths_,
85 NULL),
86 INIT_LIBRARY(ObjectStore::kVMService,
87 _vmservice,
88 Bootstrap::_vmservice_source_paths_,
89 Bootstrap::_vmservice_patch_paths_),
90 { ObjectStore::kNone, NULL, NULL, NULL, NULL }
91 }; 52 };
92 53
54 #undef MAKE_PROPERTIES
93 55
94 static RawString* GetLibrarySource(const Library& lib, 56
95 const String& uri, 57 static const intptr_t kBootstrapLibraryCount = ARRAY_SIZE(bootstrap_libraries);
96 bool patch) { 58
97 // First check if this is a valid bootstrap library and find it's index 59
98 // in the 'bootstrap_libraries' table above. 60 static RawString* GetLibrarySourceByIndex(intptr_t index,
99 intptr_t index; 61 const String& uri,
100 const String& lib_uri = String::Handle(lib.url()); 62 bool patch) {
101 for (index = 0; 63 ASSERT(index >= 0 && index < kBootstrapLibraryCount);
102 bootstrap_libraries[index].index_ != ObjectStore::kNone;
103 ++index) {
104 if (lib_uri.Equals(bootstrap_libraries[index].uri_)) {
105 break;
106 }
107 }
108 if (bootstrap_libraries[index].index_ == ObjectStore::kNone) {
109 return String::null(); // Library is not a bootstrap library.
110 }
111 64
112 // Try to read the source using the path specified for the uri. 65 // Try to read the source using the path specified for the uri.
113 const char** source_paths = patch ? 66 const char** source_paths = patch ? bootstrap_libraries[index].patch_paths
114 bootstrap_libraries[index].patch_paths_ : 67 : bootstrap_libraries[index].source_paths;
115 bootstrap_libraries[index].source_paths_;
116 if (source_paths == NULL) { 68 if (source_paths == NULL) {
117 return String::null(); // No path mapping information exists for library. 69 return String::null(); // No path mapping information exists for library.
118 } 70 }
119 const char* source_path = NULL; 71 const char* source_path = NULL;
120 const char* source_data = NULL; 72 const char* source_data = NULL;
121 for (intptr_t i = 0; source_paths[i] != NULL; i += kPathsEntryLength) { 73 for (intptr_t i = 0; source_paths[i] != NULL; i += kPathsEntryLength) {
122 if (uri.Equals(source_paths[i + kPathsUriOffset])) { 74 if (uri.Equals(source_paths[i + kPathsUriOffset])) {
123 source_path = source_paths[i + kPathsFileOffset]; 75 source_path = source_paths[i + kPathsFileOffset];
124 source_data = source_paths[i + kPathsSourceOffset]; 76 source_data = source_paths[i + kPathsSourceOffset];
125 break; 77 break;
(...skipping 24 matching lines...) Expand all
150 } else { 102 } else {
151 return String::null(); 103 return String::null();
152 } 104 }
153 } 105 }
154 ASSERT(utf8_array != NULL); 106 ASSERT(utf8_array != NULL);
155 ASSERT(file_length >= 0); 107 ASSERT(file_length >= 0);
156 return String::FromUTF8(utf8_array, file_length); 108 return String::FromUTF8(utf8_array, file_length);
157 } 109 }
158 110
159 111
112 static RawString* GetLibrarySource(const Library& lib,
113 const String& uri,
114 bool patch) {
115 // First check if this is a valid bootstrap library and find its index in
116 // the 'bootstrap_libraries' table above.
117 intptr_t index;
118 const String& lib_uri = String::Handle(lib.url());
119 for (index = 0; index < kBootstrapLibraryCount; ++index) {
120 if (lib_uri.Equals(bootstrap_libraries[index].uri)) {
121 break;
122 }
123 }
124 if (index == kBootstrapLibraryCount) {
125 return String::null(); // The library is not a bootstrap library.
126 }
127
128 return GetLibrarySourceByIndex(index, uri, patch);
129 }
130
131
160 static RawError* Compile(const Library& library, const Script& script) { 132 static RawError* Compile(const Library& library, const Script& script) {
161 bool update_lib_status = (script.kind() == RawScript::kScriptTag || 133 bool update_lib_status = (script.kind() == RawScript::kScriptTag ||
162 script.kind() == RawScript::kLibraryTag); 134 script.kind() == RawScript::kLibraryTag);
163 if (update_lib_status) { 135 if (update_lib_status) {
164 library.SetLoadInProgress(); 136 library.SetLoadInProgress();
165 } 137 }
166 const Error& error = Error::Handle(Compiler::Compile(library, script)); 138 const Error& error = Error::Handle(Compiler::Compile(library, script));
167 if (update_lib_status) { 139 if (update_lib_status) {
168 if (error.IsNull()) { 140 if (error.IsNull()) {
169 library.SetLoaded(); 141 library.SetLoaded();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 return Api::NewError("Invalid import of '%s' in a bootstrap library", 205 return Api::NewError("Invalid import of '%s' in a bootstrap library",
234 uri_str.ToCString()); 206 uri_str.ToCString());
235 } 207 }
236 ASSERT(tag == Dart_kSourceTag); 208 ASSERT(tag == Dart_kSourceTag);
237 const Library& lib = Api::UnwrapLibraryHandle(zone, library); 209 const Library& lib = Api::UnwrapLibraryHandle(zone, library);
238 ASSERT(!lib.IsNull()); 210 ASSERT(!lib.IsNull());
239 return LoadPartSource(thread, lib, uri_str); 211 return LoadPartSource(thread, lib, uri_str);
240 } 212 }
241 213
242 214
243 static RawError* LoadPatchFiles(Zone* zone, 215 static RawError* LoadPatchFiles(Thread* thread,
244 const Library& lib, 216 const Library& lib,
245 const String& patch_uri, 217 intptr_t index) {
246 const char** patch_files) { 218 const char** patch_files = bootstrap_libraries[index].patch_paths;
219 if (patch_files == NULL) return Error::null();
220
221 Zone* zone = thread->zone();
222 String& patch_uri = String::Handle(
223 zone, Symbols::New(thread, bootstrap_libraries[index].patch_uri));
247 String& patch_file_uri = String::Handle(zone); 224 String& patch_file_uri = String::Handle(zone);
248 String& source = String::Handle(zone); 225 String& source = String::Handle(zone);
249 Script& script = Script::Handle(zone); 226 Script& script = Script::Handle(zone);
250 Error& error = Error::Handle(zone); 227 Error& error = Error::Handle(zone);
251 const Array& strings = Array::Handle(zone, Array::New(3)); 228 const Array& strings = Array::Handle(zone, Array::New(3));
252 strings.SetAt(0, patch_uri); 229 strings.SetAt(0, patch_uri);
253 strings.SetAt(1, Symbols::Slash()); 230 strings.SetAt(1, Symbols::Slash());
254 for (intptr_t j = 0; patch_files[j] != NULL; j += kPathsEntryLength) { 231 for (intptr_t j = 0; patch_files[j] != NULL; j += kPathsEntryLength) {
255 patch_file_uri = String::New(patch_files[j + kPathsUriOffset]); 232 patch_file_uri = String::New(patch_files[j + kPathsUriOffset]);
256 source = GetLibrarySource(lib, patch_file_uri, true); 233 source = GetLibrarySourceByIndex(index, patch_file_uri, true);
257 if (source.IsNull()) { 234 if (source.IsNull()) {
258 const String& message = String::Handle( 235 const String& message = String::Handle(
259 String::NewFormatted("Unable to find dart patch source for %s", 236 String::NewFormatted("Unable to find dart patch source for %s",
260 patch_file_uri.ToCString())); 237 patch_file_uri.ToCString()));
261 return ApiError::New(message); 238 return ApiError::New(message);
262 } 239 }
263 // Prepend the patch library URI to form a unique script URI for the patch. 240 // Prepend the patch library URI to form a unique script URI for the patch.
264 strings.SetAt(2, patch_file_uri); 241 strings.SetAt(2, patch_file_uri);
265 patch_file_uri = String::ConcatAll(strings); 242 patch_file_uri = String::ConcatAll(strings);
266 script = Script::New(patch_file_uri, source, RawScript::kPatchTag); 243 script = Script::New(patch_file_uri, source, RawScript::kPatchTag);
267 error = lib.Patch(script); 244 error = lib.Patch(script);
268 if (!error.IsNull()) { 245 if (!error.IsNull()) {
269 return error.raw(); 246 return error.raw();
270 } 247 }
271 } 248 }
272 return Error::null(); 249 return Error::null();
273 } 250 }
274 251
275 252
276 RawError* Bootstrap::LoadandCompileScripts() { 253 static void Finish(Thread* thread, bool from_kernel) {
277 Thread* thread = Thread::Current(); 254 Bootstrap::SetupNativeResolver();
255 if (!ClassFinalizer::ProcessPendingClasses(from_kernel)) {
256 FATAL("Error in class finalization during bootstrapping.");
257 }
258
259 // Eagerly compile the _Closure class as it is the class of all closure
260 // instances. This allows us to just finalize function types without going
261 // through the hoops of trying to compile their scope class.
262 ObjectStore* object_store = thread->isolate()->object_store();
263 Class& cls = Class::Handle(thread->zone(), object_store->closure_class());
264 Compiler::CompileClass(cls);
265 // Eagerly compile Bool class, bool constants are used from within compiler.
266 cls = object_store->bool_class();
267 Compiler::CompileClass(cls);
268 }
269
270
271 static RawError* BootstrapFromSource(Thread* thread) {
278 Isolate* isolate = thread->isolate(); 272 Isolate* isolate = thread->isolate();
279 Zone* zone = thread->zone(); 273 Zone* zone = thread->zone();
280 String& uri = String::Handle(zone); 274 String& uri = String::Handle(zone);
281 String& patch_uri = String::Handle(zone);
282 String& source = String::Handle(zone); 275 String& source = String::Handle(zone);
283 Script& script = Script::Handle(zone); 276 Script& script = Script::Handle(zone);
284 Library& lib = Library::Handle(zone); 277 Library& lib = Library::Handle(zone);
285 Error& error = Error::Handle(zone); 278 Error& error = Error::Handle(zone);
286 Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler();
287 279
288 // Set the library tag handler for the isolate to the bootstrap 280 // Set the library tag handler for the isolate to the bootstrap
289 // library tag handler so that we can load all the bootstrap libraries. 281 // library tag handler so that we can load all the bootstrap libraries.
282 Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler();
290 isolate->set_library_tag_handler(BootstrapLibraryTagHandler); 283 isolate->set_library_tag_handler(BootstrapLibraryTagHandler);
291 284
292 HANDLESCOPE(thread);
293
294 // Create library objects for all the bootstrap libraries.
295 for (intptr_t i = 0;
296 bootstrap_libraries[i].index_ != ObjectStore::kNone;
297 ++i) {
298 #ifdef PRODUCT
299 if (bootstrap_libraries[i].index_ == ObjectStore::kMirrors) {
300 continue;
301 }
302 #endif // !PRODUCT
303 uri = Symbols::New(thread, bootstrap_libraries[i].uri_);
304 lib = Library::LookupLibrary(thread, uri);
305 if (lib.IsNull()) {
306 lib = Library::NewLibraryHelper(uri, false);
307 lib.SetLoadRequested();
308 lib.Register(thread);
309 }
310 isolate->object_store()->set_bootstrap_library(
311 bootstrap_libraries[i].index_, lib);
312 }
313
314 // Load, compile and patch bootstrap libraries. 285 // Load, compile and patch bootstrap libraries.
315 for (intptr_t i = 0; 286 for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
316 bootstrap_libraries[i].index_ != ObjectStore::kNone; 287 ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
317 ++i) { 288 uri = Symbols::New(thread, bootstrap_libraries[i].uri);
318 #ifdef PRODUCT 289 lib = isolate->object_store()->bootstrap_library(id);
319 if (bootstrap_libraries[i].index_ == ObjectStore::kMirrors) {
320 continue;
321 }
322 #endif // PRODUCT
323 uri = Symbols::New(thread, bootstrap_libraries[i].uri_);
324 lib = Library::LookupLibrary(thread, uri);
325 ASSERT(!lib.IsNull()); 290 ASSERT(!lib.IsNull());
326 source = GetLibrarySource(lib, uri, false); 291 ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
292 source = GetLibrarySourceByIndex(i, uri, false);
327 if (source.IsNull()) { 293 if (source.IsNull()) {
328 const String& message = String::Handle( 294 const String& message = String::Handle(
329 String::NewFormatted("Unable to find dart source for %s", 295 String::NewFormatted("Unable to find dart source for %s",
330 uri.ToCString())); 296 uri.ToCString()));
331 error ^= ApiError::New(message); 297 error ^= ApiError::New(message);
332 break; 298 break;
333 } 299 }
334 script = Script::New(uri, source, RawScript::kLibraryTag); 300 script = Script::New(uri, source, RawScript::kLibraryTag);
335 error = Compile(lib, script); 301 error = Compile(lib, script);
336 if (!error.IsNull()) { 302 if (!error.IsNull()) {
337 break; 303 break;
338 } 304 }
339 // If a patch exists, load and patch the script. 305 // If a patch exists, load and patch the script.
340 if (bootstrap_libraries[i].patch_paths_ != NULL) { 306 error = LoadPatchFiles(thread, lib, i);
341 patch_uri = Symbols::New(thread, bootstrap_libraries[i].patch_uri_); 307 if (!error.IsNull()) {
342 error = LoadPatchFiles(zone, 308 break;
343 lib,
344 patch_uri,
345 bootstrap_libraries[i].patch_paths_);
346 if (!error.IsNull()) {
347 break;
348 }
349 } 309 }
350 } 310 }
311
351 if (error.IsNull()) { 312 if (error.IsNull()) {
352 SetupNativeResolver(); 313 Finish(thread, /*from_kernel=*/false);
353 ClassFinalizer::ProcessPendingClasses();
354
355 // Eagerly compile the _Closure class as it is the class of all closure
356 // instances. This allows us to just finalize function types
357 // without going through the hoops of trying to compile their scope class.
358 Class& cls =
359 Class::Handle(zone, isolate->object_store()->closure_class());
360 Compiler::CompileClass(cls);
361 // Eagerly compile Bool class, bool constants are used from within compiler.
362 cls = isolate->object_store()->bool_class();
363 Compiler::CompileClass(cls);
364 } 314 }
365
366 // Restore the library tag handler for the isolate. 315 // Restore the library tag handler for the isolate.
367 isolate->set_library_tag_handler(saved_tag_handler); 316 isolate->set_library_tag_handler(saved_tag_handler);
368 317
369 return error.raw(); 318 return error.raw();
370 } 319 }
371 320
321
322 static RawError* BootstrapFromKernel(Thread* thread,
323 const uint8_t* buffer,
324 intptr_t buffer_size) {
325 Zone* zone = thread->zone();
326 kernel::Program* program =
327 ReadPrecompiledKernelFromBuffer(buffer, buffer_size);
328 if (program == NULL) {
329 const String& message =
330 String::Handle(zone, String::New("Failed to read Kernel file"));
331 return ApiError::New(message);
332 }
333
334 Isolate* isolate = thread->isolate();
335 // Mark the already-pending classes. This mark bit will be used to avoid
336 // adding classes to the list more than once.
337 GrowableObjectArray& pending_classes = GrowableObjectArray::Handle(
338 zone, isolate->object_store()->pending_classes());
339 dart::Class& pending = dart::Class::Handle(zone);
340 for (intptr_t i = 0; i < pending_classes.Length(); ++i) {
341 pending ^= pending_classes.At(i);
342 pending.set_is_marked_for_parsing();
343 }
344
345 Library& library = Library::Handle(zone);
346 String& dart_name = String::Handle(zone);
347 String& kernel_name = String::Handle(zone);
348 kernel::KernelReader reader(NULL, -1, true);
349 for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
350 ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
351 library = isolate->object_store()->bootstrap_library(id);
352 dart_name = library.url();
353 for (intptr_t j = 0; j < program->libraries().length(); ++j) {
354 kernel::Library* kernel_library = program->libraries()[j];
355 kernel::String* uri = kernel_library->import_uri();
356 kernel_name = Symbols::FromUTF8(thread, uri->buffer(), uri->size());
357 if (kernel_name.Equals(dart_name)) {
358 reader.ReadLibrary(kernel_library);
359 library.SetLoaded();
360 break;
361 }
362 }
363 }
364
365 Finish(thread, /*from_kernel=*/true);
366 return Error::null();
367 }
368
369
370 RawError* Bootstrap::DoBootstrapping(const uint8_t* kernel_buffer,
371 intptr_t kernel_buffer_length) {
372 Thread* thread = Thread::Current();
373 Isolate* isolate = thread->isolate();
374 Zone* zone = thread->zone();
375 String& uri = String::Handle(zone);
376 Library& lib = Library::Handle(zone);
377
378 HANDLESCOPE(thread);
379
380 // Ensure there are library objects for all the bootstrap libraries.
381 for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
382 ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
383 uri = Symbols::New(thread, bootstrap_libraries[i].uri);
384 lib = isolate->object_store()->bootstrap_library(id);
385 ASSERT(lib.raw() == Library::LookupLibrary(thread, uri));
386 if (lib.IsNull()) {
387 lib = Library::NewLibraryHelper(uri, false);
388 lib.SetLoadRequested();
389 lib.Register(thread);
390 isolate->object_store()->set_bootstrap_library(id, lib);
391 }
392 }
393
394 return (kernel_buffer == NULL)
395 ? BootstrapFromSource(thread)
396 : BootstrapFromKernel(thread, kernel_buffer, kernel_buffer_length);
397 }
398
372 } // namespace dart 399 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698