Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | Friends | List of all members
dart::IsolateGroupReloadContext Class Reference

#include <isolate_reload.h>

Public Member Functions

 IsolateGroupReloadContext (IsolateGroup *isolate, ClassTable *class_table, JSONStream *js)
 
 ~IsolateGroupReloadContext ()
 
bool Reload (bool force_reload, const char *root_script_url=nullptr, const char *packages_url=nullptr, const uint8_t *kernel_buffer=nullptr, intptr_t kernel_buffer_size=0)
 
Zonezone () const
 
IsolateGroupisolate_group () const
 
bool reload_aborted () const
 
bool reload_skipped () const
 
ErrorPtr error () const
 
int64_t start_time_micros () const
 
int64_t reload_timestamp () const
 

Static Public Member Functions

static Dart_FileModifiedCallback file_modified_callback ()
 
static void SetFileModifiedCallback (Dart_FileModifiedCallback callback)
 

Friends

class Isolate
 
class Class
 
class Library
 
class ObjectLocator
 
class ReasonForCancelling
 
class ProgramReloadContext
 
class IsolateGroup
 

Detailed Description

Definition at line 141 of file isolate_reload.h.

Constructor & Destructor Documentation

◆ IsolateGroupReloadContext()

dart::IsolateGroupReloadContext::IsolateGroupReloadContext ( IsolateGroup isolate,
ClassTable class_table,
JSONStream js 
)

Definition at line 546 of file isolate_reload.cc.

550 : zone_(Thread::Current()->zone()),
551 isolate_group_(isolate_group),
552 class_table_(class_table),
553 start_time_micros_(OS::GetCurrentMonotonicMicros()),
554 reload_timestamp_(OS::GetCurrentTimeMillis()),
555 js_(js),
556 instance_morphers_(zone_, 0),
557 reasons_to_cancel_reload_(zone_, 0),
558 instance_morpher_by_cid_(zone_),
559 root_lib_url_(String::Handle(Z, String::null())),
560 root_url_prefix_(String::null()),
561 old_root_url_prefix_(String::null()) {}
IsolateGroup * isolate_group() const
static int64_t GetCurrentTimeMillis()
static int64_t GetCurrentMonotonicMicros()
static ObjectPtr null()
Definition: object.h:433
static Object & Handle()
Definition: object.h:407
static Thread * Current()
Definition: thread.h:362
#define Z

◆ ~IsolateGroupReloadContext()

dart::IsolateGroupReloadContext::~IsolateGroupReloadContext ( )

Definition at line 562 of file isolate_reload.cc.

562{}

Member Function Documentation

◆ error()

ErrorPtr dart::IsolateGroupReloadContext::error ( ) const

Definition at line 454 of file isolate_reload.cc.

454 {
455 ASSERT(!reasons_to_cancel_reload_.is_empty());
456 // Report the first error to the surroundings.
457 return reasons_to_cancel_reload_.At(0)->ToError();
458}
#define ASSERT(E)

◆ file_modified_callback()

static Dart_FileModifiedCallback dart::IsolateGroupReloadContext::file_modified_callback ( )
inlinestatic

Definition at line 165 of file isolate_reload.h.

165 {
166 return file_modified_callback_;
167 }

◆ isolate_group()

IsolateGroup * dart::IsolateGroupReloadContext::isolate_group ( ) const
inline

Definition at line 158 of file isolate_reload.h.

158{ return isolate_group_; }

◆ Reload()

bool dart::IsolateGroupReloadContext::Reload ( bool  force_reload,
const char *  root_script_url = nullptr,
const char *  packages_url = nullptr,
const uint8_t *  kernel_buffer = nullptr,
intptr_t  kernel_buffer_size = 0 
)

Definition at line 686 of file isolate_reload.cc.

690 {
692
693 Thread* thread = Thread::Current();
694 ASSERT(thread->OwnsReloadSafepoint());
695
696 Heap* heap = IG->heap();
697 num_old_libs_ =
698 GrowableObjectArray::Handle(Z, IG->object_store()->libraries()).Length();
699
700 // Grab root library before calling CheckpointBeforeReload.
701 GetRootLibUrl(root_script_url);
702
703 std::unique_ptr<kernel::Program> kernel_program;
704
705 // Reset stats.
706 num_received_libs_ = 0;
707 bytes_received_libs_ = 0;
708 num_received_classes_ = 0;
709 num_received_procedures_ = 0;
710
711 bool did_kernel_compilation = false;
712 bool skip_reload = false;
713 {
714 // Load the kernel program and figure out the modified libraries.
715 intptr_t* p_num_received_classes = nullptr;
716 intptr_t* p_num_received_procedures = nullptr;
717
718 // ReadKernelFromFile checks to see if the file at
719 // root_script_url is a valid .dill file. If that's the case, a Program*
720 // is returned. Otherwise, this is likely a source file that needs to be
721 // compiled, so ReadKernelFromFile returns nullptr.
722 kernel_program = kernel::Program::ReadFromFile(root_script_url);
723 if (kernel_program != nullptr) {
724 num_received_libs_ = kernel_program->library_count();
725 bytes_received_libs_ = kernel_program->binary().LengthInBytes();
726 p_num_received_classes = &num_received_classes_;
727 p_num_received_procedures = &num_received_procedures_;
728 } else {
729 if (kernel_buffer == nullptr || kernel_buffer_size == 0) {
730 char* error = CompileToKernel(force_reload, packages_url,
731 &kernel_buffer, &kernel_buffer_size);
732 did_kernel_compilation = true;
733 if (error != nullptr) {
734 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
735 const auto& error_str = String::Handle(Z, String::New(error));
736 free(error);
737 const ApiError& error = ApiError::Handle(Z, ApiError::New(error_str));
738 AddReasonForCancelling(new Aborted(Z, error));
739 ReportReasonsForCancelling();
740 CommonFinalizeTail(num_old_libs_);
741
742 RejectCompilation(thread);
743 return false;
744 }
745 }
746 const auto& typed_data = ExternalTypedData::Handle(
748 const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size));
749 kernel_program = kernel::Program::ReadFromTypedData(typed_data);
750 }
751
752 NoActiveIsolateScope no_active_isolate_scope;
753
754 IsolateGroupSource* source = IsolateGroup::Current()->source();
755 source->add_loaded_blob(Z,
756 ExternalTypedData::Cast(kernel_program->binary()));
757
758 modified_libs_ = new (Z) BitVector(Z, num_old_libs_);
760 kernel_program.get(), IG, modified_libs_, force_reload, &skip_reload,
761 p_num_received_classes, p_num_received_procedures);
762 modified_libs_transitive_ = new (Z) BitVector(Z, num_old_libs_);
763 BuildModifiedLibrariesClosure(modified_libs_);
764
765 ASSERT(num_saved_libs_ == -1);
766 num_saved_libs_ = 0;
767 for (intptr_t i = 0; i < modified_libs_->length(); i++) {
768 if (!modified_libs_->Contains(i)) {
769 num_saved_libs_++;
770 }
771 }
772 }
773
774 NoActiveIsolateScope no_active_isolate_scope;
775
776 if (skip_reload) {
777 ASSERT(modified_libs_->IsEmpty());
778 reload_skipped_ = true;
779 ReportOnJSON(js_, num_old_libs_);
780
781 // If we use the CFE and performed a compilation, we need to notify that
782 // we have accepted the compilation to clear some state in the incremental
783 // compiler.
784 if (did_kernel_compilation) {
785 const auto& result = Object::Handle(Z, AcceptCompilation(thread));
786 if (result.IsError()) {
787 const auto& error = Error::Cast(result);
788 AddReasonForCancelling(new Aborted(Z, error));
789 ReportReasonsForCancelling();
790 CommonFinalizeTail(num_old_libs_);
791 return false;
792 }
793 }
794 TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n");
795 return false;
796 }
797
798 TIR_Print("---- STARTING RELOAD\n");
799
800 intptr_t number_of_isolates = 0;
801 isolate_group_->ForEachIsolate(
802 [&](Isolate* isolate) { number_of_isolates++; });
803
804 // Wait for any concurrent marking tasks to finish and turn off the
805 // concurrent marker during reload as we might be allocating new instances
806 // (constants) when loading the new kernel file and this could cause
807 // inconsistency between the saved class table and the new class table.
808 const bool old_concurrent_mark_flag =
809 heap->old_space()->enable_concurrent_mark();
810 if (old_concurrent_mark_flag) {
811 heap->WaitForMarkerTasks(thread);
812 heap->old_space()->set_enable_concurrent_mark(false);
813 }
814
815 // Ensure all functions on the stack have unoptimized code.
816 // Deoptimize all code that had optimizing decisions that are dependent on
817 // assumptions from field guards or CHA or deferred library prefixes.
818 // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
819 // is paranoid. This likely can be moved to the commit phase.
820 IG->program_reload_context()->EnsuredUnoptimizedCodeForStack();
821 IG->program_reload_context()->DeoptimizeDependentCode();
822 IG->program_reload_context()->ReloadPhase1AllocateStorageMapsAndCheckpoint();
823
824 // Renumbering the libraries has invalidated this.
825 modified_libs_ = nullptr;
826 modified_libs_transitive_ = nullptr;
827
828 if (FLAG_gc_during_reload) {
829 // We force the GC to compact, which is more likely to discover untracked
830 // pointers (and other issues, like incorrect class table).
831 heap->CollectAllGarbage(GCReason::kDebugging, /*compact=*/true);
832 }
833
834 // Clone the class table.
835 {
836 TIMELINE_SCOPE(CheckpointClasses);
837 IG->program_reload_context()->CheckpointClasses();
838 }
839
840 if (FLAG_gc_during_reload) {
841 // We force the GC to compact, which is more likely to discover untracked
842 // pointers (and other issues, like incorrect class table).
843 heap->CollectAllGarbage(GCReason::kDebugging, /*compact=*/true);
844 }
845
846 // We synchronously load the hot-reload kernel diff (which includes changed
847 // libraries and any libraries transitively depending on them).
848 //
849 // If loading the hot-reload diff succeeded we'll finalize the loading, which
850 // will either commit or reject the reload request.
851 const auto& result =
852 Object::Handle(Z, IG->program_reload_context()->ReloadPhase2LoadKernel(
853 kernel_program.get(), root_lib_url_));
854
855 if (result.IsError()) {
856 TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
857
858 const auto& error = Error::Cast(result);
859 AddReasonForCancelling(new Aborted(Z, error));
860
861 IG->program_reload_context()->ReloadPhase4Rollback();
862 CommonFinalizeTail(num_old_libs_);
863 } else {
864 ASSERT(!reload_skipped_ && !reload_finalized_);
865 TIR_Print("---- LOAD SUCCEEDED\n");
866
867 IG->program_reload_context()->ReloadPhase3FinalizeLoading();
868
869 if (FLAG_gc_during_reload) {
870 // We force the GC to compact, which is more likely to discover untracked
871 // pointers (and other issues, like incorrect class table).
872 heap->CollectAllGarbage(GCReason::kDebugging, /*compact=*/true);
873 }
874
875 // If we use the CFE and performed a compilation, we need to notify that
876 // we have accepted the compilation to clear some state in the incremental
877 // compiler.
878 if (did_kernel_compilation) {
880 const auto& result = Object::Handle(Z, AcceptCompilation(thread));
881 if (result.IsError()) {
882 const auto& error = Error::Cast(result);
883 AddReasonForCancelling(new Aborted(Z, error));
884 }
885 }
886
887 if (!FLAG_reload_force_rollback && !HasReasonsForCancelling()) {
888 TIR_Print("---- COMMITTING RELOAD\n");
889 isolate_group_->program_reload_context()->ReloadPhase4CommitPrepare();
890 bool discard_class_tables = true;
891 if (HasInstanceMorphers()) {
892 // Find all objects that need to be morphed (reallocated to a new
893 // layout).
894 ObjectLocator locator(this);
895 {
896 TIMELINE_SCOPE(CollectInstances);
897 HeapIterationScope iteration(thread);
898 iteration.IterateObjects(&locator);
899 }
900
901 // We are still using the old class table at this point.
902 if (FLAG_gc_during_reload) {
903 // We force the GC to compact, which is more likely to discover
904 // untracked pointers (and other issues, like incorrect class table).
905 heap->CollectAllGarbage(GCReason::kDebugging, /*compact=*/true);
906 }
907 const intptr_t count = locator.count();
908 if (count > 0) {
909 TIMELINE_SCOPE(MorphInstances);
910
911 // While we are reallocating instances to their new layout, the heap
912 // will contain a mix of instances with the old and new layouts that
913 // have the same cid. This makes the heap unwalkable until the
914 // "become" operation below replaces all the instances of the old
915 // layout with forwarding corpses. Force heap growth to prevent layout
916 // confusion during this period.
917 ForceGrowthScope force_growth(thread);
918 // The HeapIterationScope above ensures no other GC tasks can be
919 // active.
920 ASSERT(HasNoTasks(heap));
921
922 MorphInstancesPhase1Allocate(&locator, IG->become());
923 {
924 // Apply the new class table before "become". Become will replace
925 // all the instances of the old layout with forwarding corpses, then
926 // perform a heap walk to fix references to the forwarding corpses.
927 // During this heap walk, it will encounter instances of the new
928 // layout, so it requires the new class table.
929 ASSERT(HasNoTasks(heap));
930
931 // We accepted the hot-reload and morphed instances. So now we can
932 // commit to the changed class table and deleted the saved one.
933 IG->DropOriginalClassTable();
934 }
935 MorphInstancesPhase2Become(IG->become());
936
937 discard_class_tables = false;
938 }
939 // We are using the new class table now.
940 if (FLAG_gc_during_reload) {
941 // We force the GC to compact, which is more likely to discover
942 // untracked pointers (and other issues, like incorrect class table).
943 heap->CollectAllGarbage(GCReason::kDebugging, /*compact=*/true);
944 }
945 }
946 if (FLAG_identity_reload) {
947 if (!discard_class_tables) {
948 TIR_Print("Identity reload failed! Some instances were morphed\n");
949 }
950 if (IG->heap_walk_class_table()->NumCids() !=
951 IG->class_table()->NumCids()) {
952 TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n",
953 IG->heap_walk_class_table()->NumCids(),
954 IG->class_table()->NumCids());
955 }
956 if (IG->heap_walk_class_table()->NumTopLevelCids() !=
957 IG->class_table()->NumTopLevelCids()) {
958 TIR_Print("Identity reload failed! B#TLC=%" Pd " A#TLC=%" Pd "\n",
959 IG->heap_walk_class_table()->NumTopLevelCids(),
960 IG->class_table()->NumTopLevelCids());
961 }
962 }
963 if (discard_class_tables) {
964 IG->DropOriginalClassTable();
965 }
966 isolate_group_->program_reload_context()->ReloadPhase4CommitFinish();
967 TIR_Print("---- DONE COMMIT\n");
968 isolate_group_->set_last_reload_timestamp(reload_timestamp_);
969 } else {
970 TIR_Print("---- ROLLING BACK");
971 isolate_group_->program_reload_context()->ReloadPhase4Rollback();
972 }
973
974 // ValidateReload mutates the direct subclass information and does
975 // not remove dead subclasses. Rebuild the direct subclass
976 // information from scratch.
977 {
978 SafepointWriteRwLocker ml(thread, IG->program_lock());
979 IG->program_reload_context()->RebuildDirectSubclasses();
980 }
981 const intptr_t final_library_count =
982 GrowableObjectArray::Handle(Z, IG->object_store()->libraries())
983 .Length();
984 CommonFinalizeTail(final_library_count);
985 }
986
987 // Reenable concurrent marking if it was initially on.
988 if (old_concurrent_mark_flag) {
989 heap->old_space()->set_enable_concurrent_mark(true);
990 }
991
992 bool success;
993 if (!result.IsError() || HasReasonsForCancelling()) {
994 ReportSuccess();
995 success = true;
996 } else {
997 ReportReasonsForCancelling();
998 success = false;
999 }
1000
1001 Array& null_array = Array::Handle(Z);
1002 // Invalidate the URI mapping caches.
1003 IG->object_store()->set_uri_to_resolved_uri_map(null_array);
1004 IG->object_store()->set_resolved_uri_to_uri_map(null_array);
1005
1006 // Re-queue any shutdown requests so they can inform each isolate's own thread
1007 // to shut down.
1008 if (result.IsUnwindError()) {
1009 const auto& error = UnwindError::Cast(result);
1010 ForEachIsolate([&](Isolate* isolate) {
1011 Isolate::KillIfExists(isolate, error.is_user_initiated()
1014 });
1015 }
1016
1017 return success;
1018}
int count
Definition: FontMgrTest.cpp:50
bool IsEmpty() const
Definition: bit_vector.cc:100
intptr_t length() const
Definition: bit_vector.h:117
bool Contains(intptr_t i) const
Definition: bit_vector.h:91
static ExternalTypedDataPtr NewFinalizeWithFree(uint8_t *data, intptr_t len)
Definition: object.cc:25649
bool Reload(bool force_reload, const char *root_script_url=nullptr, const char *packages_url=nullptr, const uint8_t *kernel_buffer=nullptr, intptr_t kernel_buffer_size=0)
void ForEachIsolate(std::function< void(Isolate *isolate)> function, bool at_safepoint=false)
Definition: isolate.cc:2841
static IsolateGroup * Current()
Definition: isolate.h:539
void set_last_reload_timestamp(int64_t value)
Definition: isolate.h:651
IsolateGroupSource * source() const
Definition: isolate.h:286
ProgramReloadContext * program_reload_context()
Definition: isolate.h:659
@ kInternalKillMsg
Definition: isolate.h:973
static void KillIfExists(Isolate *isolate, LibMsgId msg_id)
Definition: isolate.cc:3706
static StringPtr New(const char *cstr, Heap::Space space=Heap::kNew)
Definition: object.cc:23698
static void FindModifiedLibraries(Program *program, IsolateGroup *isolate_group, BitVector *modified_libs, bool force_reload, bool *is_empty_program, intptr_t *p_num_classes, intptr_t *p_num_procedures)
static std::unique_ptr< Program > ReadFromTypedData(const ExternalTypedData &typed_data, const char **error=nullptr)
static std::unique_ptr< Program > ReadFromFile(const char *script_uri, const char **error=nullptr)
SkBitmap source
Definition: examples.cpp:28
GAsyncResult * result
#define IG
#define TIMELINE_SCOPE(name)
#define TIR_Print(format,...)
static ObjectPtr RejectCompilation(Thread *thread)
static ObjectPtr AcceptCompilation(Thread *thread)
static bool HasNoTasks(Heap *heap)
@ ApiError
The Dart error code for an API error.
#define Pd
Definition: globals.h:408

◆ reload_aborted()

bool dart::IsolateGroupReloadContext::reload_aborted ( ) const
inline

Definition at line 159 of file isolate_reload.h.

159{ return HasReasonsForCancelling(); }

◆ reload_skipped()

bool dart::IsolateGroupReloadContext::reload_skipped ( ) const
inline

Definition at line 160 of file isolate_reload.h.

160{ return reload_skipped_; }

◆ reload_timestamp()

int64_t dart::IsolateGroupReloadContext::reload_timestamp ( ) const
inline

Definition at line 163 of file isolate_reload.h.

163{ return reload_timestamp_; }

◆ SetFileModifiedCallback()

static void dart::IsolateGroupReloadContext::SetFileModifiedCallback ( Dart_FileModifiedCallback  callback)
inlinestatic

Definition at line 168 of file isolate_reload.h.

168 {
169 file_modified_callback_ = callback;
170 }
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback

◆ start_time_micros()

int64_t dart::IsolateGroupReloadContext::start_time_micros ( ) const
inline

Definition at line 162 of file isolate_reload.h.

162{ return start_time_micros_; }

◆ zone()

Zone * dart::IsolateGroupReloadContext::zone ( ) const
inline

Definition at line 156 of file isolate_reload.h.

156{ return zone_; }

Friends And Related Function Documentation

◆ Class

friend class Class
friend

Definition at line 281 of file isolate_reload.h.

◆ Isolate

friend class Isolate
friend

Definition at line 280 of file isolate_reload.h.

◆ IsolateGroup

friend class IsolateGroup
friend

Definition at line 286 of file isolate_reload.h.

◆ Library

friend class Library
friend

Definition at line 282 of file isolate_reload.h.

◆ ObjectLocator

friend class ObjectLocator
friend

Definition at line 283 of file isolate_reload.h.

◆ ProgramReloadContext

friend class ProgramReloadContext
friend

Definition at line 285 of file isolate_reload.h.

◆ ReasonForCancelling

friend class ReasonForCancelling
friend

Definition at line 284 of file isolate_reload.h.


The documentation for this class was generated from the following files: