%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/objects/
Upload File :
Create Path :
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/objects/js-weak-refs-inl.h

// Copyright 2018 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_OBJECTS_JS_WEAK_REFS_INL_H_
#define V8_OBJECTS_JS_WEAK_REFS_INL_H_

#include "src/api/api-inl.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/js-weak-refs.h"
#include "src/objects/smi-inl.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

#include "torque-generated/src/objects/js-weak-refs-tq-inl.inc"

TQ_OBJECT_CONSTRUCTORS_IMPL(WeakCell)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSWeakRef)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSFinalizationRegistry)

BIT_FIELD_ACCESSORS(JSFinalizationRegistry, flags, scheduled_for_cleanup,
                    JSFinalizationRegistry::ScheduledForCleanupBit)

void JSFinalizationRegistry::RegisterWeakCellWithUnregisterToken(
    Handle<JSFinalizationRegistry> finalization_registry,
    Handle<WeakCell> weak_cell, Isolate* isolate) {
  Handle<SimpleNumberDictionary> key_map;
  if (IsUndefined(finalization_registry->key_map(), isolate)) {
    key_map = SimpleNumberDictionary::New(isolate, 1);
  } else {
    key_map =
        handle(SimpleNumberDictionary::cast(finalization_registry->key_map()),
               isolate);
  }

  // Unregister tokens are held weakly as objects are often their own
  // unregister token. To avoid using an ephemeron map, the map for token
  // lookup is keyed on the token's identity hash instead of the token itself.
  uint32_t key =
      Object::GetOrCreateHash(weak_cell->unregister_token(), isolate).value();
  InternalIndex entry = key_map->FindEntry(isolate, key);
  if (entry.is_found()) {
    Tagged<Object> value = key_map->ValueAt(entry);
    Tagged<WeakCell> existing_weak_cell = WeakCell::cast(value);
    existing_weak_cell->set_key_list_prev(*weak_cell);
    weak_cell->set_key_list_next(existing_weak_cell);
  }
  key_map = SimpleNumberDictionary::Set(isolate, key_map, key, weak_cell);
  finalization_registry->set_key_map(*key_map);
}

bool JSFinalizationRegistry::Unregister(
    Handle<JSFinalizationRegistry> finalization_registry,
    Handle<HeapObject> unregister_token, Isolate* isolate) {
  // Iterate through the doubly linked list of WeakCells associated with the
  // key. Each WeakCell will be in the "active_cells" or "cleared_cells" list of
  // its FinalizationRegistry; remove it from there.
  return finalization_registry->RemoveUnregisterToken(
      *unregister_token, isolate, kRemoveMatchedCellsFromRegistry,
      [](Tagged<HeapObject>, ObjectSlot, Tagged<Object>) {});
}

template <typename GCNotifyUpdatedSlotCallback>
bool JSFinalizationRegistry::RemoveUnregisterToken(
    Tagged<HeapObject> unregister_token, Isolate* isolate,
    RemoveUnregisterTokenMode removal_mode,
    GCNotifyUpdatedSlotCallback gc_notify_updated_slot) {
  // This method is called from both FinalizationRegistry#unregister and for
  // removing weakly-held dead unregister tokens. The latter is during GC so
  // this function cannot GC.
  DisallowGarbageCollection no_gc;
  if (IsUndefined(key_map(), isolate)) {
    return false;
  }

  Tagged<SimpleNumberDictionary> key_map =
      SimpleNumberDictionary::cast(this->key_map());
  // If the token doesn't have a hash, it was not used as a key inside any hash
  // tables.
  Tagged<Object> hash = Object::GetHash(unregister_token);
  if (IsUndefined(hash, isolate)) {
    return false;
  }
  uint32_t key = Smi::ToInt(hash);
  InternalIndex entry = key_map->FindEntry(isolate, key);
  if (entry.is_not_found()) {
    return false;
  }

  Tagged<Object> value = key_map->ValueAt(entry);
  bool was_present = false;
  Tagged<HeapObject> undefined = ReadOnlyRoots(isolate).undefined_value();
  Tagged<HeapObject> new_key_list_head = undefined;
  Tagged<HeapObject> new_key_list_prev = undefined;
  // Compute a new key list that doesn't have unregister_token. Because
  // unregister tokens are held weakly, key_map is keyed using the tokens'
  // identity hashes, and identity hashes may collide.
  while (!IsUndefined(value, isolate)) {
    Tagged<WeakCell> weak_cell = WeakCell::cast(value);
    DCHECK(!ObjectInYoungGeneration(weak_cell));
    value = weak_cell->key_list_next();
    if (weak_cell->unregister_token() == unregister_token) {
      // weak_cell has the same unregister token; remove it from the key list.
      switch (removal_mode) {
        case kRemoveMatchedCellsFromRegistry:
          weak_cell->RemoveFromFinalizationRegistryCells(isolate);
          break;
        case kKeepMatchedCellsInRegistry:
          // Do nothing.
          break;
      }
      // Clear unregister token-related fields.
      weak_cell->set_unregister_token(undefined);
      weak_cell->set_key_list_prev(undefined);
      weak_cell->set_key_list_next(undefined);
      was_present = true;
    } else {
      // weak_cell has a different unregister token with the same key (hash
      // collision); fix up the list.
      weak_cell->set_key_list_prev(new_key_list_prev);
      gc_notify_updated_slot(weak_cell,
                             weak_cell->RawField(WeakCell::kKeyListPrevOffset),
                             new_key_list_prev);
      weak_cell->set_key_list_next(undefined);
      if (IsUndefined(new_key_list_prev, isolate)) {
        new_key_list_head = weak_cell;
      } else {
        DCHECK(IsWeakCell(new_key_list_head));
        Tagged<WeakCell> prev_cell = WeakCell::cast(new_key_list_prev);
        prev_cell->set_key_list_next(weak_cell);
        gc_notify_updated_slot(
            prev_cell, prev_cell->RawField(WeakCell::kKeyListNextOffset),
            weak_cell);
      }
      new_key_list_prev = weak_cell;
    }
  }
  if (IsUndefined(new_key_list_head, isolate)) {
    DCHECK(was_present);
    key_map->ClearEntry(entry);
    key_map->ElementRemoved();
  } else {
    key_map->ValueAtPut(entry, new_key_list_head);
    gc_notify_updated_slot(key_map, key_map->RawFieldOfValueAt(entry),
                           new_key_list_head);
  }
  return was_present;
}

bool JSFinalizationRegistry::NeedsCleanup() const {
  return IsWeakCell(cleared_cells());
}

Tagged<HeapObject> WeakCell::relaxed_target() const {
  return TaggedField<HeapObject>::Relaxed_Load(*this, kTargetOffset);
}

Tagged<HeapObject> WeakCell::relaxed_unregister_token() const {
  return TaggedField<HeapObject>::Relaxed_Load(*this, kUnregisterTokenOffset);
}

template <typename GCNotifyUpdatedSlotCallback>
void WeakCell::Nullify(Isolate* isolate,
                       GCNotifyUpdatedSlotCallback gc_notify_updated_slot) {
  // Remove from the WeakCell from the "active_cells" list of its
  // JSFinalizationRegistry and insert it into the "cleared_cells" list. This is
  // only called for WeakCells which haven't been unregistered yet, so they will
  // be in the active_cells list. (The caller must guard against calling this
  // for unregistered WeakCells by checking that the target is not undefined.)
  DCHECK(Object::CanBeHeldWeakly(target()));
  set_target(ReadOnlyRoots(isolate).undefined_value());

  Tagged<JSFinalizationRegistry> fr =
      JSFinalizationRegistry::cast(finalization_registry());
  if (IsWeakCell(prev())) {
    DCHECK_NE(fr->active_cells(), *this);
    Tagged<WeakCell> prev_cell = WeakCell::cast(prev());
    prev_cell->set_next(next());
    gc_notify_updated_slot(prev_cell,
                           prev_cell->RawField(WeakCell::kNextOffset), next());
  } else {
    DCHECK_EQ(fr->active_cells(), *this);
    fr->set_active_cells(next());
    gc_notify_updated_slot(
        fr, fr->RawField(JSFinalizationRegistry::kActiveCellsOffset), next());
  }
  if (IsWeakCell(next())) {
    Tagged<WeakCell> next_cell = WeakCell::cast(next());
    next_cell->set_prev(prev());
    gc_notify_updated_slot(next_cell,
                           next_cell->RawField(WeakCell::kPrevOffset), prev());
  }

  set_prev(ReadOnlyRoots(isolate).undefined_value());
  Tagged<Object> cleared_head = fr->cleared_cells();
  if (IsWeakCell(cleared_head)) {
    Tagged<WeakCell> cleared_head_cell = WeakCell::cast(cleared_head);
    cleared_head_cell->set_prev(*this);
    gc_notify_updated_slot(cleared_head_cell,
                           cleared_head_cell->RawField(WeakCell::kPrevOffset),
                           *this);
  }
  set_next(fr->cleared_cells());
  gc_notify_updated_slot(*this, RawField(WeakCell::kNextOffset), next());
  fr->set_cleared_cells(*this);
  gc_notify_updated_slot(
      fr, fr->RawField(JSFinalizationRegistry::kClearedCellsOffset), *this);
}

void WeakCell::RemoveFromFinalizationRegistryCells(Isolate* isolate) {
  // Remove the WeakCell from the list it's in (either "active_cells" or
  // "cleared_cells" of its JSFinalizationRegistry).

  // It's important to set_target to undefined here. This guards that we won't
  // call Nullify (which assumes that the WeakCell is in active_cells).
  DCHECK(IsUndefined(target()) || Object::CanBeHeldWeakly(target()));
  set_target(ReadOnlyRoots(isolate).undefined_value());

  Tagged<JSFinalizationRegistry> fr =
      JSFinalizationRegistry::cast(finalization_registry());
  if (fr->active_cells() == *this) {
    DCHECK(IsUndefined(prev(), isolate));
    fr->set_active_cells(next());
  } else if (fr->cleared_cells() == *this) {
    DCHECK(!IsWeakCell(prev()));
    fr->set_cleared_cells(next());
  } else {
    DCHECK(IsWeakCell(prev()));
    Tagged<WeakCell> prev_cell = WeakCell::cast(prev());
    prev_cell->set_next(next());
  }
  if (IsWeakCell(next())) {
    Tagged<WeakCell> next_cell = WeakCell::cast(next());
    next_cell->set_prev(prev());
  }
  set_prev(ReadOnlyRoots(isolate).undefined_value());
  set_next(ReadOnlyRoots(isolate).undefined_value());
}

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_JS_WEAK_REFS_INL_H_

Zerion Mini Shell 1.0