// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_INL_H_
#define V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_INL_H_
#include "include/v8-traced-handle.h"
#include "src/base/logging.h"
#include "src/handles/global-handles.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/heap.h"
#include "src/heap/mark-compact.h"
#include "src/heap/marking-worklist-inl.h"
namespace v8 {
namespace internal {
class BasicTracedReferenceExtractor {
public:
static Object GetObjectForMarking(const TracedReferenceBase& ref) {
Address* global_handle_location = const_cast
(
reinterpret_cast(ref.GetSlotThreadSafe()));
// We cannot assume that the reference is non-null as we may get here by
// tracing an ephemeron which doesn't have early bailouts, see
// `cppgc::Visitor::TraceEphemeron()` for non-Member values.
if (!global_handle_location) return Object();
GlobalHandles::MarkTraced(global_handle_location);
return Object(
reinterpret_cast*>(global_handle_location)
->load(std::memory_order_relaxed));
}
};
void UnifiedHeapMarkingState::MarkAndPush(
const TracedReferenceBase& reference) {
// The following code will crash with null pointer derefs when finding a
// non-empty `TracedReferenceBase` when `CppHeap` is in detached mode.
Object object = BasicTracedReferenceExtractor::GetObjectForMarking(reference);
if (!object.IsHeapObject()) {
// The embedder is not aware of whether numbers are materialized as heap
// objects are just passed around as Smis.
return;
}
HeapObject heap_object = HeapObject::cast(object);
if (marking_state_->WhiteToGrey(heap_object)) {
local_marking_worklist_->Push(heap_object);
}
if (V8_UNLIKELY(track_retaining_path_)) {
heap_->AddRetainingRoot(Root::kWrapperTracing, heap_object);
}
}
} // namespace internal
} // namespace v8
#endif // V8_HEAP_CPPGC_JS_UNIFIED_HEAP_MARKING_STATE_INL_H_