Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
isolate_reload.h
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_ISOLATE_RELOAD_H_
6#define RUNTIME_VM_ISOLATE_RELOAD_H_
7
8#include <functional>
9#include <memory>
10
12
14#include "vm/globals.h"
15#include "vm/growable_array.h"
16#include "vm/hash_map.h"
17#include "vm/heap/become.h"
18#include "vm/heap/safepoint.h"
19#include "vm/log.h"
20#include "vm/object.h"
21
22DECLARE_FLAG(bool, trace_reload);
23DECLARE_FLAG(bool, trace_reload_verbose);
24
25// 'Trace Isolate Reload' TIR_Print
26#if defined(_MSC_VER)
27#define TIR_Print(format, ...) \
28 if (FLAG_trace_reload) Log::Current()->Print(format, __VA_ARGS__)
29#else
30#define TIR_Print(format, ...) \
31 if (FLAG_trace_reload) Log::Current()->Print(format, ##__VA_ARGS__)
32#endif
33
34// 'Verbose Trace Isolate Reload' VTIR_Print
35#if defined(_MSC_VER)
36#define VTIR_Print(format, ...) \
37 if (FLAG_trace_reload_verbose) Log::Current()->Print(format, __VA_ARGS__)
38#else
39#define VTIR_Print(format, ...) \
40 if (FLAG_trace_reload_verbose) Log::Current()->Print(format, ##__VA_ARGS__)
41#endif
42
43#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
44
45namespace dart {
46
47class BitVector;
48class GrowableObjectArray;
49class Isolate;
50class Library;
51class ObjectLocator;
52class ObjectPointerVisitor;
53class ObjectStore;
54class Script;
55class UpdateClassesVisitor;
56
58 intptr_t offset;
59 intptr_t box_cid; // kIllegalCid if field is boxed
60};
61
64
66 public:
67 // Creates a new [InstanceMorpher] based on the [from]/[to] class
68 // descriptions.
70 ClassTable* class_table,
71 const Class& from,
72 const Class& to);
73
76 const Class& old_class,
77 const Class& new_class,
78 FieldMappingArray* mapping,
79 FieldOffsetArray* new_fields_offsets);
80 virtual ~InstanceMorpher() {}
81
82 // Adds an object to be morphed.
83 void AddObject(ObjectPtr object);
84
85 // Create the morphed objects based on the before() list.
86 void CreateMorphedCopies(Become* become);
87
88 // Append the morper info to JSON array.
89 void AppendTo(JSONArray* array);
90
91 // Returns the cid associated with the from_ and to_ class.
92 intptr_t cid() const { return cid_; }
93
94 // Dumps the field mappings for the [cid()] class.
95 void Dump() const;
96
97 private:
98 Zone* zone_;
99 classid_t cid_;
100 const Class& old_class_;
101 const Class& new_class_;
102 FieldMappingArray* mapping_;
103 FieldOffsetArray* new_fields_offsets_;
104
106};
107
109 public:
110 explicit ReasonForCancelling(Zone* zone) {}
112
113 // Reports a reason for cancelling reload.
114 void Report(IsolateGroupReloadContext* context);
115
116 // Conversion to a VM error object.
117 // Default implementation calls ToString.
118 virtual ErrorPtr ToError();
119
120 // Conversion to a string object.
121 // Default implementation calls ToError.
122 virtual StringPtr ToString();
123
124 // Append the reason to JSON array.
125 virtual void AppendTo(JSONArray* array);
126
127 // Concrete subclasses must override either ToError or ToString.
128};
129
130// Abstract class for also capturing the from_ and to_ class.
132 public:
133 ClassReasonForCancelling(Zone* zone, const Class& from, const Class& to);
134 void AppendTo(JSONArray* array);
135
136 protected:
137 const Class& from_;
138 const Class& to_;
139};
140
142 public:
144 ClassTable* class_table,
145 JSONStream* js);
147
148 // If kernel_buffer is provided, the VM takes ownership when Reload is called.
149 bool Reload(bool force_reload,
150 const char* root_script_url = nullptr,
151 const char* packages_url = nullptr,
152 const uint8_t* kernel_buffer = nullptr,
153 intptr_t kernel_buffer_size = 0);
154
155 // All zone allocated objects must be allocated from this zone.
156 Zone* zone() const { return zone_; }
157
158 IsolateGroup* isolate_group() const { return isolate_group_; }
159 bool reload_aborted() const { return HasReasonsForCancelling(); }
160 bool reload_skipped() const { return reload_skipped_; }
161 ErrorPtr error() const;
162 int64_t start_time_micros() const { return start_time_micros_; }
163 int64_t reload_timestamp() const { return reload_timestamp_; }
164
166 return file_modified_callback_;
167 }
169 file_modified_callback_ = callback;
170 }
171
172 private:
173 // Tells whether there are reasons for cancelling the reload.
174 bool HasReasonsForCancelling() const {
175 return !reasons_to_cancel_reload_.is_empty();
176 }
177
178 // Record problem for this reload.
179 void AddReasonForCancelling(ReasonForCancelling* reason);
180
181 // Reports all reasons for cancelling reload.
182 void ReportReasonsForCancelling();
183
184 // Reports the details of a reload operation.
185 void ReportOnJSON(JSONStream* stream, intptr_t final_library_count);
186
187 // Ensures there is a instance morpher for [cid], if not it will use
188 // [instance_morpher]
189 void EnsureHasInstanceMorpherFor(classid_t cid,
190 InstanceMorpher* instance_morpher);
191
192 // Tells whether instance in the heap must be morphed.
193 bool HasInstanceMorphers() const { return !instance_morphers_.is_empty(); }
194
195 // Called by both FinalizeLoading and FinalizeFailedLoad.
196 void CommonFinalizeTail(intptr_t final_library_count);
197
198 // Report back through the observatory channels.
199 void ReportError(const Error& error);
200 void ReportSuccess();
201
202 void VisitObjectPointers(ObjectPointerVisitor* visitor);
203
204 void GetRootLibUrl(const char* root_script_url);
205 char* CompileToKernel(bool force_reload,
206 const char* packages_url,
207 const uint8_t** kernel_buffer,
208 intptr_t* kernel_buffer_size);
209 void BuildModifiedLibrariesClosure(BitVector* modified_libs);
210 void FindModifiedSources(bool force_reload,
211 Dart_SourceFile** modified_sources,
212 intptr_t* count,
213 const char* packages_url);
214 bool ScriptModifiedSince(const Script& script, int64_t since);
215
216 void MorphInstancesPhase1Allocate(ObjectLocator* locator, Become* become);
217 void MorphInstancesPhase2Become(Become* become);
218
219 void ForEachIsolate(std::function<void(Isolate*)> callback);
220
221 // The zone used for all reload related allocations.
222 Zone* zone_;
223
224 IsolateGroup* isolate_group_;
225 ClassTable* class_table_;
226
227 int64_t start_time_micros_ = -1;
228 int64_t reload_timestamp_ = -1;
229 bool reload_skipped_ = false;
230 bool reload_finalized_ = false;
231 JSONStream* js_;
232 intptr_t num_old_libs_ = -1;
233
234 intptr_t num_received_libs_ = -1;
235 intptr_t bytes_received_libs_ = -1;
236 intptr_t num_received_classes_ = -1;
237 intptr_t num_received_procedures_ = -1;
238 intptr_t num_saved_libs_ = -1;
239
240 // Required trait for the instance_morpher_by_cid_;
241 struct MorpherTrait {
242 typedef InstanceMorpher* Value;
243 typedef intptr_t Key;
244 typedef InstanceMorpher* Pair;
245
246 static Key KeyOf(Pair kv) { return kv->cid(); }
247 static Value ValueOf(Pair kv) { return kv; }
248 static uword Hash(Key key) { return Utils::WordHash(key); }
249 static bool IsKeyEqual(Pair kv, Key key) { return kv->cid() == key; }
250 };
251
252 // Collect the necessary instance transformation for schema changes.
253 GrowableArray<InstanceMorpher*> instance_morphers_;
254
255 // Collects the reasons for cancelling the reload.
256 GrowableArray<ReasonForCancelling*> reasons_to_cancel_reload_;
257
258 // Hash map from cid to InstanceMorpher.
259 DirectChainedHashMap<MorpherTrait> instance_morpher_by_cid_;
260
261 // A bit vector indicating which of the original libraries were modified.
262 BitVector* modified_libs_ = nullptr;
263
264 // A bit vector indicating which of the original libraries were modified,
265 // or where a transitive dependency was modified.
266 BitVector* modified_libs_transitive_ = nullptr;
267
268 // A bit vector indicating which of the saved libraries that transitively
269 // depend on a modified library.
270 BitVector* saved_libs_transitive_updated_ = nullptr;
271
272 String& root_lib_url_;
273 ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&root_url_prefix_); }
274 StringPtr root_url_prefix_;
275 StringPtr old_root_url_prefix_;
276 ObjectPtr* to() {
277 return reinterpret_cast<ObjectPtr*>(&old_root_url_prefix_);
278 }
279
280 friend class Isolate;
281 friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
282 friend class Library;
283 friend class ObjectLocator;
286 friend class IsolateGroup;
287
288 static Dart_FileModifiedCallback file_modified_callback_;
289};
290
292 public:
294 std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
295 IsolateGroup* isolate_group);
297
298 // All zone allocated objects must be allocated from this zone.
299 Zone* zone() const { return zone_; }
300
302 return group_reload_context_.get();
303 }
304
305 static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
306 static bool IsSameClass(const Class& a, const Class& b);
307
308 private:
309 bool IsDirty(const Library& lib);
310
311 void RegisterClass(const Class& new_cls);
312
313 // Finds the library private key for |replacement_or_new| or return null
314 // if |replacement_or_new| is new.
315 StringPtr FindLibraryPrivateKey(const Library& replacement_or_new);
316
317 void VisitObjectPointers(ObjectPointerVisitor* visitor);
318
319 IsolateGroup* isolate_group() { return isolate_group_; }
320 ObjectStore* object_store();
321
322 void EnsuredUnoptimizedCodeForStack();
323 void DeoptimizeDependentCode();
324
325 void ReloadPhase1AllocateStorageMapsAndCheckpoint();
326 void CheckpointClasses();
327 ObjectPtr ReloadPhase2LoadKernel(kernel::Program* program,
328 const String& root_lib_url);
329 void ReloadPhase3FinalizeLoading();
330 void ReloadPhase4CommitPrepare();
331 void ReloadPhase4CommitFinish();
332 void ReloadPhase4Rollback();
333
334 void CheckpointLibraries();
335
336 void RollbackLibraries();
337
338#ifdef DEBUG
339 void VerifyMaps();
340#endif
341
342 void CommitBeforeInstanceMorphing();
343 void CommitAfterInstanceMorphing();
344 void PostCommit();
345
346 void RunInvalidationVisitors();
347 void InvalidateKernelInfos(
348 Zone* zone,
349 const GrowableArray<const KernelProgramInfo*>& kernel_infos);
350 void InvalidateFunctions(Zone* zone,
351 const GrowableArray<const Function*>& functions);
352 void InvalidateSuspendStates(
353 Zone* zone,
354 const GrowableArray<const SuspendState*>& suspend_states);
355 void InvalidateFields(Zone* zone,
356 const GrowableArray<const Field*>& fields,
357 const GrowableArray<const Instance*>& instances);
358 void ResetUnoptimizedICsOnStack();
359 void ResetMegamorphicCaches();
360 void InvalidateWorld();
361
362 struct LibraryInfo {
363 bool dirty;
364 };
365
366 // The zone used for all reload related allocations.
367 Zone* zone_;
368 std::shared_ptr<IsolateGroupReloadContext> group_reload_context_;
369 IsolateGroup* isolate_group_;
370 MallocGrowableArray<LibraryInfo> library_infos_;
371
372 ClassPtr OldClassOrNull(const Class& replacement_or_new);
373 LibraryPtr OldLibraryOrNull(const Library& replacement_or_new);
374 LibraryPtr OldLibraryOrNullBaseMoved(const Library& replacement_or_new);
375
376 void BuildLibraryMapping();
377 void BuildRemovedClassesSet();
378 void ValidateReload();
379
380 void AddClassMapping(const Class& replacement_or_new, const Class& original);
381 void AddLibraryMapping(const Library& replacement_or_new,
382 const Library& original);
383 void AddStaticFieldMapping(const Field& old_field, const Field& new_field);
384 void AddBecomeMapping(const Object& old, const Object& neu);
385 void RebuildDirectSubclasses();
386
387 Become become_;
388
389 ObjectPtr* from() {
390 return reinterpret_cast<ObjectPtr*>(&old_classes_set_storage_);
391 }
392 ArrayPtr old_classes_set_storage_;
393 ArrayPtr class_map_storage_;
394 ArrayPtr removed_class_set_storage_;
395 ArrayPtr old_libraries_set_storage_;
396 ArrayPtr library_map_storage_;
397 LibraryPtr saved_root_library_;
398 GrowableObjectArrayPtr saved_libraries_;
399 ObjectPtr* to() { return reinterpret_cast<ObjectPtr*>(&saved_libraries_); }
400
401 friend class Isolate;
402 friend class IsolateGroup;
403 friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
404 friend class Library;
405 friend class ObjectLocator;
408};
409
411 public:
412 explicit CallSiteResetter(Zone* zone);
413
415 void ResetCaches(const Code& code);
416 void ResetCaches(const ObjectPool& pool);
417 void Reset(const ICData& ic);
418 void ResetSwitchableCalls(const Code& code);
419
420 private:
421 Zone* zone_;
422 Instructions& instrs_;
423 ObjectPool& pool_;
424 Object& object_;
425 String& name_;
426 Class& new_cls_;
427 Library& new_lib_;
428 Function& new_function_;
429 Field& new_field_;
430 Array& entries_;
431 Function& old_target_;
432 Function& new_target_;
433 Function& caller_;
434 Array& args_desc_array_;
435 Array& ic_data_array_;
436 Array& edge_counters_;
437 PcDescriptors& descriptors_;
438 ICData& ic_data_;
439};
440
441// Ensures all other mutators are stopped at a well-defined place where reload
442// is allowed.
443#define RELOAD_OPERATION_SCOPE(thread_expr) \
444 auto _thread_ = (thread_expr); \
445 \
446 /* As the background compiler is a mutator it participates in safepoint */ \
447 /* operations. Though the BG compiler won't check into reload safepoint */ \
448 /* requests - as it's not a well-defined place to do reload. */ \
449 /* So we ensure the background compiler is stopped before we get all */ \
450 /* other mutators to reload safepoints. */ \
451 NoBackgroundCompilerScope _stop_bg_compiler_(_thread_); \
452 \
453 /* This will enable the current thread to perform reload operations (as */ \
454 /* well as check-in with other thread's reload operations). */ \
455 ReloadParticipationScope _allow_reload_(_thread_); \
456 \
457 /* The actual reload operation that will ensure all other mutators are */ \
458 /* stopped at well-defined places where reload can happen. */ \
459 ReloadSafepointOperationScope _safepoint_operation_(_thread_);
460
461} // namespace dart
462
463#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
464
465#endif // RUNTIME_VM_ISOLATE_RELOAD_H_
AutoreleasePool pool
int count
TArray< uint32_t > Key
void ResetCaches(const Code &code)
void ResetSwitchableCalls(const Code &code)
void Reset(const ICData &ic)
void ZeroEdgeCounters(const Function &function)
void AppendTo(JSONArray *array)
intptr_t cid() const
void AddObject(ObjectPtr object)
void AppendTo(JSONArray *array)
static InstanceMorpher * CreateFromClassDescriptors(Zone *zone, ClassTable *class_table, const Class &from, const Class &to)
void CreateMorphedCopies(Become *become)
static Dart_FileModifiedCallback file_modified_callback()
static void SetFileModifiedCallback(Dart_FileModifiedCallback callback)
IsolateGroup * isolate_group() const
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)
static bool IsSameLibrary(const Library &a_lib, const Library &b_lib)
static bool IsSameClass(const Class &a, const Class &b)
IsolateGroupReloadContext * group_reload_context()
virtual ErrorPtr ToError()
virtual void AppendTo(JSONArray *array)
virtual StringPtr ToString()
static uint32_t WordHash(intptr_t key)
Definition utils.cc:217
bool(* Dart_FileModifiedCallback)(const char *url, int64_t since)
static bool b
struct MyStruct a[10]
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define DECLARE_FLAG(type, name)
Definition flags.h:14
Dart_NativeFunction function
Definition fuchsia.cc:51
int32_t classid_t
Definition globals.h:524
uintptr_t uword
Definition globals.h:501
const intptr_t cid