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

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

Issue 2512483002: Support reloading from source on top of a script snapshot. (Closed)
Patch Set: bug fixes 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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/isolate_reload.h" 5 #include "vm/isolate_reload.h"
6 6
7 #include "vm/become.h" 7 #include "vm/become.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 // currently. 347 // currently.
348 const String& a_name = String::Handle(a.Name()); 348 const String& a_name = String::Handle(a.Name());
349 const String& b_name = String::Handle(b.Name()); 349 const String& b_name = String::Handle(b.Name());
350 350
351 if (!a_name.Equals(b_name)) { 351 if (!a_name.Equals(b_name)) {
352 return false; 352 return false;
353 } 353 }
354 354
355 const Library& a_lib = Library::Handle(a.library()); 355 const Library& a_lib = Library::Handle(a.library());
356 const Library& b_lib = Library::Handle(b.library()); 356 const Library& b_lib = Library::Handle(b.library());
357 return IsSameLibrary(a_lib, b_lib); 357
358 if (a_lib.IsNull() || b_lib.IsNull()) {
359 return a_lib.raw() == b_lib.raw();
360 }
361 return (a_lib.private_key() == b_lib.private_key());
358 } 362 }
359 363
360 364
361 bool IsolateReloadContext::IsSameLibrary(const Library& a_lib, 365 bool IsolateReloadContext::IsSameLibrary(const Library& a_lib,
362 const Library& b_lib) { 366 const Library& b_lib) {
363 const String& a_lib_url = 367 const String& a_lib_url =
364 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url()); 368 String::Handle(a_lib.IsNull() ? String::null() : a_lib.url());
365 const String& b_lib_url = 369 const String& b_lib_url =
366 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url()); 370 String::Handle(b_lib.IsNull() ? String::null() : b_lib.url());
367 return a_lib_url.Equals(b_lib_url); 371 return a_lib_url.Equals(b_lib_url);
368 } 372 }
369 373
370 374
371 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js) 375 IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js)
372 : zone_(Thread::Current()->zone()), 376 : zone_(Thread::Current()->zone()),
373 start_time_micros_(OS::GetCurrentMonotonicMicros()), 377 start_time_micros_(OS::GetCurrentMonotonicMicros()),
374 reload_timestamp_(OS::GetCurrentTimeMillis()), 378 reload_timestamp_(OS::GetCurrentTimeMillis()),
375 isolate_(isolate), 379 isolate_(isolate),
376 reload_skipped_(false), 380 reload_skipped_(false),
377 reload_aborted_(false), 381 reload_aborted_(false),
378 reload_finalized_(false), 382 reload_finalized_(false),
379 js_(js), 383 js_(js),
380 saved_num_cids_(-1), 384 saved_num_cids_(-1),
381 saved_class_table_(NULL), 385 saved_class_table_(NULL),
382 num_saved_libs_(-1), 386 num_saved_libs_(-1),
383 instance_morphers_(zone_, 0), 387 instance_morphers_(zone_, 0),
384 reasons_to_cancel_reload_(zone_, 0), 388 reasons_to_cancel_reload_(zone_, 0),
385 cid_mapper_(), 389 cid_mapper_(),
386 modified_libs_(NULL), 390 modified_libs_(NULL),
387 script_uri_(String::null()), 391 script_url_(String::null()),
388 error_(Error::null()), 392 error_(Error::null()),
389 old_classes_set_storage_(Array::null()), 393 old_classes_set_storage_(Array::null()),
390 class_map_storage_(Array::null()), 394 class_map_storage_(Array::null()),
391 old_libraries_set_storage_(Array::null()), 395 old_libraries_set_storage_(Array::null()),
392 library_map_storage_(Array::null()), 396 library_map_storage_(Array::null()),
393 become_map_storage_(Array::null()), 397 become_map_storage_(Array::null()),
394 become_enum_mappings_(GrowableObjectArray::null()), 398 become_enum_mappings_(GrowableObjectArray::null()),
395 saved_root_library_(Library::null()), 399 saved_root_library_(Library::null()),
396 saved_libraries_(GrowableObjectArray::null()) { 400 saved_libraries_(GrowableObjectArray::null()),
401 root_url_prefix_(String::null()),
402 old_root_url_prefix_(String::null()) {
397 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not 403 // NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
398 // associated with the isolate yet and if a GC is triggered here the raw 404 // associated with the isolate yet and if a GC is triggered here the raw
399 // objects will not be properly accounted for. 405 // objects will not be properly accounted for.
400 ASSERT(zone_ != NULL); 406 ASSERT(zone_ != NULL);
401 } 407 }
402 408
403 409
404 IsolateReloadContext::~IsolateReloadContext() {} 410 IsolateReloadContext::~IsolateReloadContext() {}
405 411
406 412
(...skipping 22 matching lines...) Expand all
429 private: 435 private:
430 const Error& error_; 436 const Error& error_;
431 437
432 RawError* ToError() { return error_.raw(); } 438 RawError* ToError() { return error_.raw(); }
433 RawString* ToString() { 439 RawString* ToString() {
434 return String::NewFormatted("%s", error_.ToErrorCString()); 440 return String::NewFormatted("%s", error_.ToErrorCString());
435 } 441 }
436 }; 442 };
437 443
438 444
445 static intptr_t CommonSuffixLength(const char* a, const char* b) {
446 const intptr_t a_length = strlen(a);
447 const intptr_t b_length = strlen(b);
448 intptr_t a_cursor = a_length;
449 intptr_t b_cursor = b_length;
450
451 while ((a_cursor >= 0) && (b_cursor >= 0)) {
452 if (a[a_cursor] != b[b_cursor]) {
453 break;
454 }
455 a_cursor--;
456 b_cursor--;
457 }
458
459 ASSERT((a_length - a_cursor) == (b_length - b_cursor));
460 return (a_length - a_cursor);
461 }
462
463
439 // NOTE: This function returns *after* FinalizeLoading is called. 464 // NOTE: This function returns *after* FinalizeLoading is called.
440 void IsolateReloadContext::Reload(bool force_reload) { 465 void IsolateReloadContext::Reload(bool force_reload,
466 const char* root_script_url,
467 const char* packages_url_) {
441 TIMELINE_SCOPE(Reload); 468 TIMELINE_SCOPE(Reload);
442 Thread* thread = Thread::Current(); 469 Thread* thread = Thread::Current();
443 ASSERT(isolate() == thread->isolate()); 470 ASSERT(isolate() == thread->isolate());
444 471
445 // Grab root library before calling CheckpointBeforeReload. 472 // Grab root library before calling CheckpointBeforeReload.
446 const Library& root_lib = Library::Handle(object_store()->root_library()); 473 const Library& old_root_lib = Library::Handle(object_store()->root_library());
447 ASSERT(!root_lib.IsNull()); 474 ASSERT(!old_root_lib.IsNull());
448 const String& root_lib_url = String::Handle(root_lib.url()); 475 const String& old_root_lib_url = String::Handle(old_root_lib.url());
476 // Root library url.
477 const String& root_lib_url =
478 (root_script_url == NULL) ? old_root_lib_url
479 : String::Handle(String::New(root_script_url));
480
481 // Check to see if the base url of the loaded libraries has moved.
482 if (!old_root_lib_url.Equals(root_lib_url)) {
483 const char* old_root_library_url_c = old_root_lib_url.ToCString();
484 const char* root_library_url_c = root_lib_url.ToCString();
485 const intptr_t common_suffix_length =
486 CommonSuffixLength(root_library_url_c, old_root_library_url_c);
487 root_url_prefix_ = String::SubString(
488 root_lib_url, 0, root_lib_url.Length() - common_suffix_length + 1);
489 old_root_url_prefix_ =
490 String::SubString(old_root_lib_url, 0,
491 old_root_lib_url.Length() - common_suffix_length + 1);
492 }
449 493
450 // Check to see which libraries have been modified. 494 // Check to see which libraries have been modified.
451 modified_libs_ = FindModifiedLibraries(force_reload); 495 modified_libs_ = FindModifiedLibraries(force_reload);
452 if (!modified_libs_->Contains(root_lib.index())) { 496 if (!modified_libs_->Contains(old_root_lib.index())) {
453 ASSERT(modified_libs_->IsEmpty()); 497 ASSERT(modified_libs_->IsEmpty());
454 reload_skipped_ = true; 498 reload_skipped_ = true;
455 ReportOnJSON(js_); 499 ReportOnJSON(js_);
456 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n"); 500 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n");
457 return; 501 return;
458 } 502 }
459 503
460 TIR_Print("---- STARTING RELOAD\n"); 504 TIR_Print("---- STARTING RELOAD\n");
461 505
462 // Preallocate storage for maps. 506 // Preallocate storage for maps.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 // This is where we validate the reload and commit or reject. 541 // This is where we validate the reload and commit or reject.
498 // 5) Dart_FinalizeLoading invokes Dart code related to deferred libraries. 542 // 5) Dart_FinalizeLoading invokes Dart code related to deferred libraries.
499 // 6) The tag handler returns and we move on. 543 // 6) The tag handler returns and we move on.
500 // 544 //
501 // Even after a successful reload the Dart code invoked in (5) can result 545 // Even after a successful reload the Dart code invoked in (5) can result
502 // in an Unwind error or an UnhandledException error. This error will be 546 // in an Unwind error or an UnhandledException error. This error will be
503 // returned by the tag handler. The tag handler can return other errors, 547 // returned by the tag handler. The tag handler can return other errors,
504 // for example, top level parse errors. We want to capture these errors while 548 // for example, top level parse errors. We want to capture these errors while
505 // propagating the UnwindError or an UnhandledException error. 549 // propagating the UnwindError or an UnhandledException error.
506 Object& result = Object::Handle(thread->zone()); 550 Object& result = Object::Handle(thread->zone());
551
552 String& packages_url = String::Handle();
553 if (packages_url_ != NULL) {
554 packages_url = String::New(packages_url_);
555 }
556
557 TIR_Print("---- ENTERING TAG HANDLER\n");
507 { 558 {
508 TransitionVMToNative transition(thread); 559 TransitionVMToNative transition(thread);
509 Api::Scope api_scope(thread); 560 Api::Scope api_scope(thread);
510 561
511 Dart_Handle retval = (I->library_tag_handler())( 562 Dart_Handle retval = (I->library_tag_handler())(
512 Dart_kScriptTag, Api::NewHandle(thread, Library::null()), 563 Dart_kScriptTag, Api::NewHandle(thread, packages_url.raw()),
513 Api::NewHandle(thread, root_lib_url.raw())); 564 Api::NewHandle(thread, root_lib_url.raw()));
514 result = Api::UnwrapHandle(retval); 565 result = Api::UnwrapHandle(retval);
515 } 566 }
516 // 567 //
517 // WEIRD CONTROL FLOW ENDS. 568 // WEIRD CONTROL FLOW ENDS.
569 TIR_Print("---- EXITED TAG HANDLER\n");
518 570
519 BackgroundCompiler::Enable(); 571 BackgroundCompiler::Enable();
520 572
521 if (result.IsUnwindError() || result.IsUnhandledException()) { 573 if (result.IsUnwindError() || result.IsUnhandledException()) {
522 // If the tag handler returns with an UnwindError or an UnhandledException 574 // If the tag handler returns with an UnwindError or an UnhandledException
523 // error, propagate it and give up. 575 // error, propagate it and give up.
524 Exceptions::PropagateError(Error::Cast(result)); 576 Exceptions::PropagateError(Error::Cast(result));
525 UNREACHABLE(); 577 UNREACHABLE();
526 } 578 }
527 579
(...skipping 12 matching lines...) Expand all
540 if (FLAG_identity_reload) { 592 if (FLAG_identity_reload) {
541 TIR_Print("Could not find replacement class for %s\n", 593 TIR_Print("Could not find replacement class for %s\n",
542 new_cls.ToCString()); 594 new_cls.ToCString());
543 UNREACHABLE(); 595 UNREACHABLE();
544 } 596 }
545 597
546 // New class maps to itself. 598 // New class maps to itself.
547 AddClassMapping(new_cls, new_cls); 599 AddClassMapping(new_cls, new_cls);
548 return; 600 return;
549 } 601 }
602 VTIR_Print("Registering class: %s\n", new_cls.ToCString());
550 new_cls.set_id(old_cls.id()); 603 new_cls.set_id(old_cls.id());
551 isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw()); 604 isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw());
552 if (!old_cls.is_enum_class()) { 605 if (!old_cls.is_enum_class()) {
553 new_cls.CopyCanonicalConstants(old_cls); 606 new_cls.CopyCanonicalConstants(old_cls);
554 } 607 }
555 new_cls.CopyCanonicalType(old_cls); 608 new_cls.CopyCanonicalType(old_cls);
556 AddBecomeMapping(old_cls, new_cls); 609 AddBecomeMapping(old_cls, new_cls);
557 AddClassMapping(new_cls, old_cls); 610 AddClassMapping(new_cls, old_cls);
558 } 611 }
559 612
(...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 return cls.raw(); 1618 return cls.raw();
1566 } 1619 }
1567 1620
1568 1621
1569 RawString* IsolateReloadContext::FindLibraryPrivateKey( 1622 RawString* IsolateReloadContext::FindLibraryPrivateKey(
1570 const Library& replacement_or_new) { 1623 const Library& replacement_or_new) {
1571 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new)); 1624 const Library& old = Library::Handle(OldLibraryOrNull(replacement_or_new));
1572 if (old.IsNull()) { 1625 if (old.IsNull()) {
1573 return String::null(); 1626 return String::null();
1574 } 1627 }
1628 #if defined(DEBUG)
1629 VTIR_Print("`%s` is getting `%s`'s private key.\n",
1630 String::Handle(replacement_or_new.url()).ToCString(),
1631 String::Handle(old.url()).ToCString());
1632 #endif
1575 return old.private_key(); 1633 return old.private_key();
1576 } 1634 }
1577 1635
1578 1636
1579 RawLibrary* IsolateReloadContext::OldLibraryOrNull( 1637 RawLibrary* IsolateReloadContext::OldLibraryOrNull(
1580 const Library& replacement_or_new) { 1638 const Library& replacement_or_new) {
1581 UnorderedHashSet<LibraryMapTraits> old_libraries_set( 1639 UnorderedHashSet<LibraryMapTraits> old_libraries_set(
1582 old_libraries_set_storage_); 1640 old_libraries_set_storage_);
1583 Library& lib = Library::Handle(); 1641 Library& lib = Library::Handle();
1584 lib ^= old_libraries_set.GetOrNull(replacement_or_new); 1642 lib ^= old_libraries_set.GetOrNull(replacement_or_new);
1585 old_libraries_set.Release(); 1643 old_libraries_set.Release();
1644 if (lib.IsNull() && (root_url_prefix_ != String::null()) &&
1645 (old_root_url_prefix_ != String::null())) {
1646 return OldLibraryOrNullBaseMoved(replacement_or_new);
1647 }
1586 return lib.raw(); 1648 return lib.raw();
1587 } 1649 }
1588 1650
1589 1651
1652 // Attempt to find the pair to |replacement_or_new| with the knowledge that
1653 // the base url prefix has moved.
1654 RawLibrary* IsolateReloadContext::OldLibraryOrNullBaseMoved(
1655 const Library& replacement_or_new) {
1656 const String& url_prefix = String::Handle(root_url_prefix_);
1657 const String& old_url_prefix = String::Handle(old_root_url_prefix_);
1658 const intptr_t prefix_length = url_prefix.Length();
1659 const intptr_t old_prefix_length = old_url_prefix.Length();
1660 const String& new_url = String::Handle(replacement_or_new.url());
1661 const String& suffix =
1662 String::Handle(String::SubString(new_url, prefix_length));
1663 if (!new_url.StartsWith(url_prefix)) {
1664 return Library::null();
1665 }
1666 Library& old = Library::Handle();
1667 String& old_url = String::Handle();
1668 String& old_suffix = String::Handle();
1669 GrowableObjectArray& saved_libs =
1670 GrowableObjectArray::Handle(saved_libraries());
1671 ASSERT(!saved_libs.IsNull());
1672 for (intptr_t i = 0; i < saved_libs.Length(); i++) {
1673 old = Library::RawCast(saved_libs.At(i));
1674 old_url = old.url();
1675 if (!old_url.StartsWith(old_url_prefix)) {
1676 continue;
1677 }
1678 old_suffix ^= String::SubString(old_url, old_prefix_length);
1679 if (old_suffix.IsNull()) {
1680 continue;
1681 }
1682 if (old_suffix.Equals(suffix)) {
1683 TIR_Print("`%s` is moving to `%s`\n", old_url.ToCString(),
1684 new_url.ToCString());
1685 return old.raw();
1686 }
1687 }
1688 return Library::null();
1689 }
1690
1691
1590 void IsolateReloadContext::BuildLibraryMapping() { 1692 void IsolateReloadContext::BuildLibraryMapping() {
1591 const GrowableObjectArray& libs = 1693 const GrowableObjectArray& libs =
1592 GrowableObjectArray::Handle(object_store()->libraries()); 1694 GrowableObjectArray::Handle(object_store()->libraries());
1593 1695
1594 Library& replacement_or_new = Library::Handle(); 1696 Library& replacement_or_new = Library::Handle();
1595 Library& old = Library::Handle(); 1697 Library& old = Library::Handle();
1596 for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) { 1698 for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
1597 replacement_or_new = Library::RawCast(libs.At(i)); 1699 replacement_or_new = Library::RawCast(libs.At(i));
1598 old ^= OldLibraryOrNull(replacement_or_new); 1700 old ^= OldLibraryOrNull(replacement_or_new);
1599 if (old.IsNull()) { 1701 if (old.IsNull()) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1695 ASSERT(!super_cls.IsNull()); 1797 ASSERT(!super_cls.IsNull());
1696 super_cls.AddDirectSubclass(cls); 1798 super_cls.AddDirectSubclass(cls);
1697 } 1799 }
1698 } 1800 }
1699 } 1801 }
1700 } 1802 }
1701 1803
1702 #endif // !PRODUCT 1804 #endif // !PRODUCT
1703 1805
1704 } // namespace dart 1806 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698