Chromium Code Reviews| 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/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
| 11 #include "vm/hash_table.h" | 11 #include "vm/hash_table.h" |
| 12 #include "vm/isolate.h" | 12 #include "vm/isolate.h" |
| 13 #include "vm/kernel_reader.h" | |
| 13 #include "vm/log.h" | 14 #include "vm/log.h" |
| 14 #include "vm/object.h" | 15 #include "vm/object.h" |
| 15 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 16 #include "vm/parser.h" | 17 #include "vm/parser.h" |
| 17 #include "vm/runtime_entry.h" | 18 #include "vm/runtime_entry.h" |
| 18 #include "vm/safepoint.h" | 19 #include "vm/safepoint.h" |
| 19 #include "vm/service_event.h" | 20 #include "vm/service_event.h" |
| 20 #include "vm/stack_frame.h" | 21 #include "vm/stack_frame.h" |
| 21 #include "vm/thread.h" | 22 #include "vm/thread.h" |
| 22 #include "vm/timeline.h" | 23 #include "vm/timeline.h" |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 | 479 |
| 479 private: | 480 private: |
| 480 const Error& error_; | 481 const Error& error_; |
| 481 | 482 |
| 482 RawError* ToError() { return error_.raw(); } | 483 RawError* ToError() { return error_.raw(); } |
| 483 RawString* ToString() { | 484 RawString* ToString() { |
| 484 return String::NewFormatted("%s", error_.ToErrorCString()); | 485 return String::NewFormatted("%s", error_.ToErrorCString()); |
| 485 } | 486 } |
| 486 }; | 487 }; |
| 487 | 488 |
| 489 #if !defined(DART_PRECOMPILED_RUNTIME) | |
| 488 static intptr_t CommonSuffixLength(const char* a, const char* b) { | 490 static intptr_t CommonSuffixLength(const char* a, const char* b) { |
| 489 const intptr_t a_length = strlen(a); | 491 const intptr_t a_length = strlen(a); |
| 490 const intptr_t b_length = strlen(b); | 492 const intptr_t b_length = strlen(b); |
| 491 intptr_t a_cursor = a_length; | 493 intptr_t a_cursor = a_length; |
| 492 intptr_t b_cursor = b_length; | 494 intptr_t b_cursor = b_length; |
| 493 | 495 |
| 494 while ((a_cursor >= 0) && (b_cursor >= 0)) { | 496 while ((a_cursor >= 0) && (b_cursor >= 0)) { |
| 495 if (a[a_cursor] != b[b_cursor]) { | 497 if (a[a_cursor] != b[b_cursor]) { |
| 496 break; | 498 break; |
| 497 } | 499 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 526 const char* root_library_url_c = root_lib_url.ToCString(); | 528 const char* root_library_url_c = root_lib_url.ToCString(); |
| 527 const intptr_t common_suffix_length = | 529 const intptr_t common_suffix_length = |
| 528 CommonSuffixLength(root_library_url_c, old_root_library_url_c); | 530 CommonSuffixLength(root_library_url_c, old_root_library_url_c); |
| 529 root_url_prefix_ = String::SubString( | 531 root_url_prefix_ = String::SubString( |
| 530 root_lib_url, 0, root_lib_url.Length() - common_suffix_length + 1); | 532 root_lib_url, 0, root_lib_url.Length() - common_suffix_length + 1); |
| 531 old_root_url_prefix_ = | 533 old_root_url_prefix_ = |
| 532 String::SubString(old_root_lib_url, 0, | 534 String::SubString(old_root_lib_url, 0, |
| 533 old_root_lib_url.Length() - common_suffix_length + 1); | 535 old_root_lib_url.Length() - common_suffix_length + 1); |
| 534 } | 536 } |
| 535 | 537 |
| 536 // Check to see which libraries have been modified. | 538 Object& result = Object::Handle(thread->zone()); |
| 537 modified_libs_ = FindModifiedLibraries(force_reload); | 539 kernel::Program* kernel_program = NULL; |
| 540 String& packages_url = String::Handle(); | |
| 541 if (packages_url_ != NULL) { | |
| 542 packages_url = String::New(packages_url_); | |
| 543 } | |
| 544 if (isolate()->use_dart_frontend()) { | |
| 545 // Load the kernel program and figure out the modified libraries. | |
| 546 const GrowableObjectArray& libs = | |
| 547 GrowableObjectArray::Handle(object_store()->libraries()); | |
| 548 intptr_t num_libs = libs.Length(); | |
| 549 modified_libs_ = new (Z) BitVector(Z, num_libs); | |
| 550 TIR_Print("---- ENTERING TAG HANDLER\n"); | |
| 551 { | |
| 552 TransitionVMToNative transition(thread); | |
| 553 Api::Scope api_scope(thread); | |
| 554 Dart_Handle retval = (I->library_tag_handler())( | |
| 555 Dart_kKernelTag, Api::NewHandle(thread, packages_url.raw()), | |
| 556 Api::NewHandle(thread, root_lib_url.raw())); | |
| 557 if (Dart_IsError(retval)) { | |
| 558 // Compilation of the new sources failed, abort reload and report | |
| 559 // error. | |
| 560 result = Api::UnwrapHandle(retval); | |
| 561 } else { | |
| 562 uint64_t data; | |
| 563 intptr_t data_len = 0; | |
| 564 Dart_TypedData_Type data_type; | |
| 565 ASSERT(Dart_IsTypedData(retval)); | |
| 566 Dart_Handle val = Dart_TypedDataAcquireData( | |
| 567 retval, &data_type, reinterpret_cast<void**>(&data), &data_len); | |
| 568 ASSERT(!Dart_IsError(val)); | |
| 569 ASSERT(data_type == Dart_TypedData_kUint64); | |
| 570 ASSERT(data_len == 1); | |
| 571 kernel_program = reinterpret_cast<kernel::Program*>(data); | |
| 572 Dart_TypedDataReleaseData(retval); | |
| 573 kernel::KernelReader reader(kernel_program); | |
| 574 reader.FindModifiedLibraries(I, modified_libs_, force_reload); | |
| 575 } | |
| 576 } | |
| 577 if (result.IsError()) { | |
|
aam
2017/08/18 16:04:20
Can this section be moved up to line 560?
IOTW, is
siva
2017/08/18 17:17:51
The reason it is outside is because we need to run
| |
| 578 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n"); | |
| 579 AddReasonForCancelling(new Aborted(zone_, ApiError::Cast(result))); | |
| 580 ReportReasonsForCancelling(); | |
| 581 CommonFinalizeTail(); | |
| 582 return; | |
| 583 } | |
| 584 TIR_Print("---- EXITED TAG HANDLER\n"); | |
| 585 } else { | |
| 586 // Check to see which libraries have been modified. | |
| 587 modified_libs_ = FindModifiedLibraries(force_reload); | |
| 588 } | |
| 538 if (!modified_libs_->Contains(old_root_lib.index())) { | 589 if (!modified_libs_->Contains(old_root_lib.index())) { |
| 539 ASSERT(modified_libs_->IsEmpty()); | 590 ASSERT(modified_libs_->IsEmpty()); |
| 540 reload_skipped_ = true; | 591 reload_skipped_ = true; |
| 541 ReportOnJSON(js_); | 592 ReportOnJSON(js_); |
| 542 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n"); | 593 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n"); |
| 543 return; | 594 return; |
| 544 } | 595 } |
| 545 | 596 |
| 546 TIR_Print("---- STARTING RELOAD\n"); | 597 TIR_Print("---- STARTING RELOAD\n"); |
| 547 | 598 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 582 // and we are temporarily back in control. | 633 // and we are temporarily back in control. |
| 583 // This is where we validate the reload and commit or reject. | 634 // This is where we validate the reload and commit or reject. |
| 584 // 5) Dart_FinalizeLoading invokes Dart code related to deferred libraries. | 635 // 5) Dart_FinalizeLoading invokes Dart code related to deferred libraries. |
| 585 // 6) The tag handler returns and we move on. | 636 // 6) The tag handler returns and we move on. |
| 586 // | 637 // |
| 587 // Even after a successful reload the Dart code invoked in (5) can result | 638 // Even after a successful reload the Dart code invoked in (5) can result |
| 588 // in an Unwind error or an UnhandledException error. This error will be | 639 // in an Unwind error or an UnhandledException error. This error will be |
| 589 // returned by the tag handler. The tag handler can return other errors, | 640 // returned by the tag handler. The tag handler can return other errors, |
| 590 // for example, top level parse errors. We want to capture these errors while | 641 // for example, top level parse errors. We want to capture these errors while |
| 591 // propagating the UnwindError or an UnhandledException error. | 642 // propagating the UnwindError or an UnhandledException error. |
| 592 Object& result = Object::Handle(thread->zone()); | |
| 593 | 643 |
| 594 String& packages_url = String::Handle(); | 644 if (isolate()->use_dart_frontend()) { |
| 595 if (packages_url_ != NULL) { | 645 // Read the kernel program. |
| 596 packages_url = String::New(packages_url_); | 646 kernel::KernelReader reader(kernel_program); |
| 597 } | 647 const Object& tmp = reader.ReadProgram(); |
| 598 | 648 if (!tmp.IsError()) { |
| 599 TIR_Print("---- ENTERING TAG HANDLER\n"); | 649 Library& lib = Library::Handle(thread->zone()); |
| 600 { | 650 lib ^= tmp.raw(); |
| 651 isolate()->object_store()->set_root_library(lib); | |
| 652 FinalizeLoading(); | |
| 653 result = Object::null(); | |
| 654 } else { | |
| 655 result = tmp.raw(); | |
| 656 } | |
| 657 } else { | |
| 658 TIR_Print("---- ENTERING TAG HANDLER\n"); | |
| 601 TransitionVMToNative transition(thread); | 659 TransitionVMToNative transition(thread); |
| 602 Api::Scope api_scope(thread); | 660 Api::Scope api_scope(thread); |
| 603 | 661 |
| 604 Dart_Handle retval = (I->library_tag_handler())( | 662 Dart_Handle retval = (I->library_tag_handler())( |
| 605 Dart_kScriptTag, Api::NewHandle(thread, packages_url.raw()), | 663 Dart_kScriptTag, Api::NewHandle(thread, packages_url.raw()), |
| 606 Api::NewHandle(thread, root_lib_url.raw())); | 664 Api::NewHandle(thread, root_lib_url.raw())); |
| 607 result = Api::UnwrapHandle(retval); | 665 result = Api::UnwrapHandle(retval); |
| 666 TIR_Print("---- EXITED TAG HANDLER\n"); | |
| 608 } | 667 } |
| 609 // | 668 // |
| 610 // WEIRD CONTROL FLOW ENDS. | 669 // WEIRD CONTROL FLOW ENDS. |
| 611 TIR_Print("---- EXITED TAG HANDLER\n"); | |
| 612 | 670 |
| 613 // Re-enable the background compiler. Do this before propagating any errors. | 671 // Re-enable the background compiler. Do this before propagating any errors. |
| 614 BackgroundCompiler::Enable(); | 672 BackgroundCompiler::Enable(); |
| 615 | 673 |
| 616 if (result.IsUnwindError()) { | 674 if (result.IsUnwindError()) { |
| 617 if (thread->top_exit_frame_info() == 0) { | 675 if (thread->top_exit_frame_info() == 0) { |
| 618 // We can only propagate errors when there are Dart frames on the stack. | 676 // We can only propagate errors when there are Dart frames on the stack. |
| 619 // In this case there are no Dart frames on the stack and we set the | 677 // In this case there are no Dart frames on the stack and we set the |
| 620 // thread's sticky error. This error will be returned to the message | 678 // thread's sticky error. This error will be returned to the message |
| 621 // handler. | 679 // handler. |
| 622 thread->set_sticky_error(Error::Cast(result)); | 680 thread->set_sticky_error(Error::Cast(result)); |
| 623 } else { | 681 } else { |
| 624 // If the tag handler returns with an UnwindError error, propagate it and | 682 // If the tag handler returns with an UnwindError error, propagate it and |
| 625 // give up. | 683 // give up. |
| 626 Exceptions::PropagateError(Error::Cast(result)); | 684 Exceptions::PropagateError(Error::Cast(result)); |
| 627 UNREACHABLE(); | 685 UNREACHABLE(); |
| 628 } | 686 } |
| 629 } | 687 } |
| 630 | 688 |
| 631 // Other errors (e.g. a parse error) are captured by the reload system. | 689 // Other errors (e.g. a parse error) are captured by the reload system. |
| 632 if (result.IsError()) { | 690 if (result.IsError()) { |
| 633 FinalizeFailedLoad(Error::Cast(result)); | 691 FinalizeFailedLoad(Error::Cast(result)); |
| 634 } | 692 } |
| 635 } | 693 } |
| 694 #else | |
| 695 // NOTE: This function returns *after* FinalizeLoading is called. | |
| 696 void IsolateReloadContext::Reload(bool force_reload, | |
| 697 const char* root_script_url, | |
| 698 const char* packages_url_) {} | |
| 699 #endif // !defined(DART_PRECOMPILED_RUNTIME) | |
| 636 | 700 |
| 637 void IsolateReloadContext::RegisterClass(const Class& new_cls) { | 701 void IsolateReloadContext::RegisterClass(const Class& new_cls) { |
| 638 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); | 702 const Class& old_cls = Class::Handle(OldClassOrNull(new_cls)); |
| 639 if (old_cls.IsNull()) { | 703 if (old_cls.IsNull()) { |
| 640 I->class_table()->Register(new_cls); | 704 I->class_table()->Register(new_cls); |
| 641 | 705 |
| 642 if (FLAG_identity_reload) { | 706 if (FLAG_identity_reload) { |
| 643 TIR_Print("Could not find replacement class for %s\n", | 707 TIR_Print("Could not find replacement class for %s\n", |
| 644 new_cls.ToCString()); | 708 new_cls.ToCString()); |
| 645 UNREACHABLE(); | 709 UNREACHABLE(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 656 new_cls.CopyCanonicalConstants(old_cls); | 720 new_cls.CopyCanonicalConstants(old_cls); |
| 657 } | 721 } |
| 658 new_cls.CopyCanonicalType(old_cls); | 722 new_cls.CopyCanonicalType(old_cls); |
| 659 AddBecomeMapping(old_cls, new_cls); | 723 AddBecomeMapping(old_cls, new_cls); |
| 660 AddClassMapping(new_cls, old_cls); | 724 AddClassMapping(new_cls, old_cls); |
| 661 } | 725 } |
| 662 | 726 |
| 663 // FinalizeLoading will be called *before* Reload() returns but will not be | 727 // FinalizeLoading will be called *before* Reload() returns but will not be |
| 664 // called if the embedder fails to load sources. | 728 // called if the embedder fails to load sources. |
| 665 void IsolateReloadContext::FinalizeLoading() { | 729 void IsolateReloadContext::FinalizeLoading() { |
| 666 if (reload_skipped_) { | 730 if (reload_skipped_ || reload_finalized_) { |
|
aam
2017/08/18 16:04:20
Do we want to return when reload_finalized_ == tru
siva
2017/08/18 17:17:51
It was asserting that reload_finalized_ should be
| |
| 667 return; | 731 return; |
| 668 } | 732 } |
| 669 ASSERT(!reload_finalized_); | |
| 670 BuildLibraryMapping(); | 733 BuildLibraryMapping(); |
| 671 TIR_Print("---- LOAD SUCCEEDED\n"); | 734 TIR_Print("---- LOAD SUCCEEDED\n"); |
| 672 if (ValidateReload()) { | 735 if (ValidateReload()) { |
| 673 Commit(); | 736 Commit(); |
| 674 PostCommit(); | 737 PostCommit(); |
| 675 isolate()->set_last_reload_timestamp(reload_timestamp_); | 738 isolate()->set_last_reload_timestamp(reload_timestamp_); |
| 676 } else { | 739 } else { |
| 677 ReportReasonsForCancelling(); | 740 ReportReasonsForCancelling(); |
| 678 Rollback(); | 741 Rollback(); |
| 679 } | 742 } |
| (...skipping 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1825 ASSERT(!super_cls.IsNull()); | 1888 ASSERT(!super_cls.IsNull()); |
| 1826 super_cls.AddDirectSubclass(cls); | 1889 super_cls.AddDirectSubclass(cls); |
| 1827 } | 1890 } |
| 1828 } | 1891 } |
| 1829 } | 1892 } |
| 1830 } | 1893 } |
| 1831 | 1894 |
| 1832 #endif // !PRODUCT | 1895 #endif // !PRODUCT |
| 1833 | 1896 |
| 1834 } // namespace dart | 1897 } // namespace dart |
| OLD | NEW |