template <typename T> bool JvmtiWeakTable<T>::GetTagSlowPath(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, T* result) { // Under concurrent GC, there is a window between moving objects and sweeping of system // weaks in which mutators are active. We may receive a to-space object pointer in obj, // but still have from-space pointers in the table. Explicitly update the table once. // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
UpdateTableWithReadBarrier(); return GetTagLocked(self, obj, result);
}
template <typename T> bool JvmtiWeakTable<T>::RemoveLocked(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, T* tag) { auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj)); if (it != tagged_objects_.end()) { if (tag != nullptr) {
*tag = it->second;
}
tagged_objects_.erase(it); returntrue;
}
if (art::gUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) { // Under concurrent GC, there is a window between moving objects and sweeping of system // weaks in which mutators are active. We may receive a to-space object pointer in obj, // but still have from-space pointers in the table. Explicitly update the table once. // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
// Update the table.
UpdateTableWithReadBarrier();
// And try again. return RemoveLocked(self, obj, tag);
}
template <typename T> bool JvmtiWeakTable<T>::SetLocked(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, T new_tag) { auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj)); if (it != tagged_objects_.end()) {
it->second = new_tag; returntrue;
}
if (art::gUseReadBarrier && self->GetIsGcMarking() && !update_since_last_sweep_) { // Under concurrent GC, there is a window between moving objects and sweeping of system // weaks in which mutators are active. We may receive a to-space object pointer in obj, // but still have from-space pointers in the table. Explicitly update the table once. // Note: this will keep *all* objects in the table live, but should be a rare occurrence.
// Update the table.
UpdateTableWithReadBarrier();
// And try again. return SetLocked(self, obj, new_tag);
}
// New element. auto insert_it = tagged_objects_.emplace(art::GcRoot<art::mirror::Object>(obj), new_tag);
DCHECK(insert_it.second); returnfalse;
}
// Under concurrent GC, there is a window between moving objects and sweeping of system // weaks in which mutators are active. We may receive a to-space object pointer in obj, // but still have from-space pointers in the table. We explicitly update the table then // to ensure we compare against to-space pointers. But we want to do this only once. Once // sweeping is done, we know all objects are to-space pointers until the next GC cycle, // so we re-enable the explicit update for the next marking.
update_since_last_sweep_ = false;
}
template <typename T> template <typename Updater, typename JvmtiWeakTable<T>::TableUpdateNullTarget kTargetNull>
ALWAYS_INLINE inlinevoid JvmtiWeakTable<T>::UpdateTableWith(Updater& updater) { // We can't emplace within the map as a to-space reference could be the same as some // from-space object reference in the map, causing correctness issues. The problem // doesn't arise if all updated <K,V> pairs are inserted after the loop as by then such // from-space object references would also have been taken care of.
// Side vector to hold node handles of entries which are updated.
std::vector<typename TagMap::node_type> updated_node_handles;
for (auto it = tagged_objects_.begin(); it != tagged_objects_.end();) {
DCHECK(!it->first.IsNull());
art::mirror::Object* original_obj = it->first.template Read<art::kWithoutReadBarrier>();
art::mirror::Object* target_obj = updater(it->first, original_obj); if (original_obj != target_obj) { if (kTargetNull == kIgnoreNull && target_obj == nullptr) { // Ignore null target, don't do anything.
} else { auto nh = tagged_objects_.extract(it++);
DCHECK(!nh.empty()); if (target_obj != nullptr) {
nh.key() = art::GcRoot<art::mirror::Object>(target_obj);
updated_node_handles.push_back(std::move(nh));
} elseif (kTargetNull == kCallHandleNull) {
HandleNullSweep(nh.mapped());
} continue; // Iterator already updated above.
}
}
it++;
} while (!updated_node_handles.empty()) { auto ret = tagged_objects_.insert(std::move(updated_node_handles.back()));
DCHECK(ret.inserted);
updated_node_handles.pop_back();
}
}
template <typename T> template <typename Storage, class Allocator> struct JvmtiWeakTable<T>::ReleasableContainer { using allocator_type = Allocator;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.