OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |