@@ -498,6 +498,68 @@ void IncrementalMarking::UpdateMarkingWorklistAfterScavenge() {
498498 weak_objects_->UpdateAfterScavenge ();
499499}
500500
501+ void IncrementalMarking::UpdateExternalPointerTableAfterScavenge () {
502+ #ifdef V8_COMPRESS_POINTERS
503+ if (!IsMajorMarking ()) return ;
504+ DCHECK (!v8_flags.separate_gc_phases );
505+
506+ heap_->isolate ()->external_pointer_table ().UpdateAllEvacuationEntries (
507+ heap_->young_external_pointer_space (), [](Address old_handle_location) {
508+ // 1) Resolve object start from the marking bitmap. Note that it's safe
509+ // since there is no black allocation for the young space (and hence
510+ // no range or page marking).
511+ // 2) Get a relocated object from the forwaring reference stored in the
512+ // map.
513+ // 3) Compute offset from the original object start to the handle
514+ // location.
515+ // 4) Compute and return the new handle location.
516+ //
517+ // Please note that instead of updating the evacuation entries, we
518+ // could simply clobber them all, which would still work, but limit
519+ // compaction to some extent. We can reconsider this in the future, if
520+ // relying on the marking bitmap becomes an issue (e.g. with inlined
521+ // mark-bits).
522+ const MemoryChunk* chunk =
523+ MemoryChunk::FromAddress (old_handle_location);
524+ if (!chunk->InYoungGeneration ()) {
525+ return old_handle_location;
526+ }
527+ // TODO(358485426): Check that the page is not black.
528+
529+ Address base = MarkingBitmap::FindPreviousValidObject (
530+ static_cast <const PageMetadata*>(chunk->Metadata ()),
531+ old_handle_location);
532+ Tagged<HeapObject> object (HeapObject::FromAddress (base));
533+
534+ MapWord map_word = object->map_word (kRelaxedLoad );
535+ if (!map_word.IsForwardingAddress ()) {
536+ // There may be objects in the EPT that do not exist anymore. If these
537+ // objects are dead at scavenging time, their marking deque entries will
538+ // not point to forwarding addresses. Hence, we can discard them.
539+ #if DEBUG
540+ // Check that the handle did reside inside the original dead object.
541+ const int object_size = object->Size ();
542+ // Map slots can never contain external pointers.
543+ DCHECK_LT (object.address (), old_handle_location);
544+ DCHECK_LT (old_handle_location, object.address () + object_size);
545+ #endif // DEBUG
546+ return kNullAddress ;
547+ }
548+
549+ Tagged<HeapObject> moved_object = map_word.ToForwardingAddress (object);
550+ #if DEBUG
551+ const int object_size = moved_object->Size ();
552+ // Map slots can never contain external pointers.
553+ DCHECK_LT (object.address (), old_handle_location);
554+ DCHECK_LT (old_handle_location, object.address () + object_size);
555+ #endif // DEBUG
556+
557+ const ptrdiff_t handle_offset = old_handle_location - base;
558+ return moved_object.address () + handle_offset;
559+ });
560+ #endif // V8_COMPRESS_POINTERS
561+ }
562+
501563void IncrementalMarking::UpdateMarkedBytesAfterScavenge (
502564 size_t dead_bytes_in_new_space) {
503565 if (!IsMajorMarking ()) return ;
0 commit comments