7#ifndef RUNTIME_VM_HEAP_GC_SHARED_H_
8#define RUNTIME_VM_HEAP_GC_SHARED_H_
11#if defined(SHOULD_NOT_INCLUDE_RUNTIME)
12#error "Should not include runtime"
31#define GC_LINKED_LIST(V) \
32 V(WeakProperty, weak_properties) \
33 V(WeakArray, weak_arrays) \
34 V(WeakReference, weak_references) \
35 V(FinalizerEntry, finalizer_entries)
37template <
typename Type,
typename PtrType>
41 ASSERT(ptr->untag()->next_seen_by_gc().IsRawNull());
42 ptr->untag()->next_seen_by_gc_ = head_;
58 to->tail_->untag()->next_seen_by_gc_ = head_;
66 PtrType return_value = head_;
84#define FOREACH(type, var) GCLinkedList<type, type##Ptr> var;
90#define TRACE_FINALIZER(format, ...) \
91 if (FLAG_trace_finalizers) { \
92 THR_Print("%s %p " format "\n", GCVisitorType::kName, visitor, \
96#define TRACE_FINALIZER(format, ...)
106template <
typename GCVisitorType>
108 FinalizerEntryPtr raw_entry,
110 GCVisitorType* visitor) {
111 PointerPtr callback_pointer = raw_finalizer->untag()->callback();
113 callback_pointer->untag()->data());
115 const bool is_detached = token_object == raw_entry;
116 const intptr_t external_size = raw_entry->
untag()->external_size();
119 ASSERT(token_object == raw_entry);
120 ASSERT(external_size == 0);
121 if (FLAG_trace_finalizers) {
122 TRACE_FINALIZER(
"Not running native finalizer %p callback %p, detached",
127 ASSERT(token_object.IsPointer());
128 PointerPtr token =
static_cast<PointerPtr
>(token_object);
129 void* peer =
reinterpret_cast<void*
>(token->untag()->data());
130 if (FLAG_trace_finalizers) {
131 TRACE_FINALIZER(
"Running native finalizer %p callback %p with token %p",
132 raw_finalizer->untag(),
callback, peer);
134 raw_entry.untag()->set_token(raw_entry);
136 if (external_size > 0) {
137 if (FLAG_trace_finalizers) {
139 external_size, before_gc_space == 0 ?
"new" :
"old");
141 visitor->isolate_group()->heap()->FreedExternal(external_size,
143 raw_entry->untag()->set_external_size(0);
161template <
typename GCVisitorType>
163 FinalizerEntryPtr current_entry) {
167 const bool value_collected_this_gc =
168 GCVisitorType::ForwardOrSetNullIfCollected(
169 current_entry, ¤t_entry->untag()->value_);
170 if (!value_collected_this_gc && before_gc_space ==
Heap::kNew) {
173 const intptr_t external_size = current_entry->untag()->external_size_;
175 " bytes from new to old space",
177 visitor->isolate_group()->heap()->PromotedExternal(external_size);
180 GCVisitorType::ForwardOrSetNullIfCollected(current_entry,
181 ¤t_entry->untag()->detach_);
182 GCVisitorType::ForwardOrSetNullIfCollected(
183 current_entry, ¤t_entry->untag()->finalizer_);
187 const bool is_detached = token_object == current_entry;
189 if (!value_collected_this_gc)
return;
190 if (is_detached)
return;
192 FinalizerBasePtr finalizer = current_entry->
untag()->finalizer();
194 if (finalizer.IsRawNull()) {
196 current_entry->untag());
203 current_entry->untag(), finalizer->untag());
205 FinalizerPtr finalizer_dart =
static_cast<FinalizerPtr
>(finalizer);
220 if (finalizer.IsNativeFinalizer()) {
221 NativeFinalizerPtr native_finalizer =
222 static_cast<NativeFinalizerPtr
>(finalizer);
232 FinalizerEntryPtr previous_head =
233 finalizer_dart->untag()->exchange_entries_collected(current_entry);
234 current_entry->untag()->set_next(previous_head);
235 const bool first_entry = previous_head.IsRawNull();
241 if (!first_entry && previous_head->IsNewObject() &&
242 current_entry->IsOldObject()) {
243 TRACE_FINALIZER(
"Entry %p (old) next is %p (new)", current_entry->untag(),
244 previous_head->untag());
250 Isolate* isolate = finalizer->untag()->isolate_;
251 if (isolate ==
nullptr) {
252 TRACE_FINALIZER(
"Not scheduling finalizer %p callback on isolate null",
256 finalizer->untag(), isolate);
269#undef TRACE_FINALIZER
PersistentHandle * AllocatePersistentHandle()
void Enqueue(PtrType ptr)
void FlushInto(GCLinkedList< Type, PtrType > *to)
ApiState * api_state() const
MessageHandler * message_handler() const
IsolateGroup * group() const
void PostMessage(std::unique_ptr< Message > message, bool before_events=false)
static std::unique_ptr< Message > New(Args &&... args)
UntaggedObject * untag() const
void set_ptr(ObjectPtr ref)
static Thread * Current()
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define TRACE_FINALIZER(format,...)
#define GC_LINKED_LIST(V)
#define FOREACH(type, var)
void MournFinalizerEntry(GCVisitorType *visitor, FinalizerEntryPtr current_entry)
Heap::Space SpaceForExternal(FinalizerEntryPtr raw_entry)
void RunNativeFinalizerCallback(NativeFinalizerPtr raw_finalizer, FinalizerEntryPtr raw_entry, Heap::Space before_gc_space, GCVisitorType *visitor)
void FlushInto(GCLinkedLists *to)