Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/js/src/vm/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 7 kB image not shown  

Quelle  ObjectFuse.cpp

  Sprache: C
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "vm/ObjectFuse.h"

#include "gc/Barrier.h"
#include "gc/StableCellHasher.h"
#include "jit/InvalidationScriptSet.h"
#include "js/SweepingAPI.h"
#include "vm/JSScript.h"
#include "vm/NativeObject.h"
#include "vm/PropertyInfo.h"

#include "gc/StableCellHasher-inl.h"
#include "vm/JSScript-inl.h"

using namespace js;

bool ObjectFuse::ensurePropertyStateLength(uint32_t length) {
  MOZ_ASSERT(length > 0);

  if (length <= propertyStateLength_) {
    MOZ_ASSERT(propertyStateBits_);
    return true;
  }

  if (!propertyStateBits_) {
    propertyStateBits_.reset(js_pod_malloc<uint32_t>(length));
    if (!propertyStateBits_) {
      return false;
    }
  } else {
    uint32_t* bitsNew = js_pod_realloc<uint32_t>(propertyStateBits_.get(),
                                                 propertyStateLength_, length);
    if (!bitsNew) {
      return false;
    }
    (void)propertyStateBits_.release();
    propertyStateBits_.reset(bitsNew);
  }

  // Initialize the new words to 0.
  static_assert(uint32_t(PropertyState::Untracked) == 0);
  std::uninitialized_fill_n(propertyStateBits_.get() + propertyStateLength_,
                            length - propertyStateLength_, 0);
  propertyStateLength_ = length;
  return true;
}

bool ObjectFuse::addDependency(uint32_t propSlot,
                               const jit::IonScriptKey& ionScript) {
  MOZ_ASSERT(getPropertyState(propSlot) == PropertyState::Constant);

  auto p = dependencies_.lookupForAdd(propSlot);
  if (!p) {
    if (!dependencies_.add(p, propSlot, jit::DependentIonScriptSet())) {
      return false;
    }
  }
  return p->value().addToSet(ionScript);
}

void ObjectFuse::invalidateDependentIonScriptsForProperty(JSContext* cx,
                                                          PropertyInfo prop,
                                                          const char* reason) {
  if (auto p = dependencies_.lookup(prop.slot())) {
    p->value().invalidateAndClear(cx, reason);
    dependencies_.remove(p);
  }
}

void ObjectFuse::invalidateAllDependentIonScripts(JSContext* cx,
                                                  const char* reason) {
  for (auto iter = dependencies_.iter(); !iter.done(); iter.next()) {
    iter.get().value().invalidateAndClear(cx, reason);
  }
  dependencies_.clear();
}

bool ObjectFuse::markPropertyConstant(PropertyInfo prop) {
  MOZ_ASSERT(getPropertyState(prop) == PropertyState::Untracked);
  uint32_t index = prop.slot() / NumPropsPerWord;
  if (!ensurePropertyStateLength(index + 1)) {
    return false;
  }
  setPropertyState(prop, PropertyState::Constant);
  return true;
}

bool ObjectFuse::tryOptimizeConstantProperty(PropertyKey key,
                                             PropertyInfo prop) {
  MOZ_RELEASE_ASSERT(ObjectFuse::tracksPropertyKey(key));

  if (MOZ_UNLIKELY(!generation_.isValid())) {
    return false;
  }
  PropertyState state = getPropertyState(prop);
  switch (state) {
    case PropertyState::Untracked:
      if (!markPropertyConstant(prop)) {
        return false;
      }
      MOZ_ASSERT(isConstantProperty(prop));
      return true;
    case PropertyState::Constant:
      return true;
    case PropertyState::NotConstant:
      return false;
  }
  MOZ_CRASH("Unreachable");
}

void ObjectFuse::handlePropertyValueChange(JSContext* cx, PropertyInfo prop) {
  // Custom data properties aren't optimized with object fuses.
  if (!prop.hasSlot()) {
    return;
  }

  PropertyState state = getPropertyState(prop);
  switch (state) {
    case PropertyState::Untracked:
      // Mark the property as Constant. IC code for SetProp operations relies on
      // properties getting marked NotConstant after a few sets, because we can
      // only optimize stores to NotConstant properties. We can ignore OOM here.
      (void)markPropertyConstant(prop);
      break;
    case PropertyState::Constant:
      invalidatedConstantProperty_ = 1;
      setPropertyState(prop, PropertyState::NotConstant);
      invalidateDependentIonScriptsForProperty(cx, prop,
                                               "changed constant property");
      break;
    case PropertyState::NotConstant:
      break;
  }
}

void ObjectFuse::handlePropertyRemove(JSContext* cx, PropertyInfo prop,
                                      bool* wasTrackedProp) {
  if (!prop.hasSlot() || isUntrackedProperty(prop)) {
    MOZ_ASSERT(!*wasTrackedProp);
    return;
  }

  *wasTrackedProp = true;
  bumpGeneration();
  invalidateDependentIonScriptsForProperty(cx, prop, "removed property");

  // Ensure a new property with this slot number will have the correct initial
  // state.
  setPropertyState(prop, PropertyState::Untracked);
}

void ObjectFuse::handleTeleportingShadowedProperty(JSContext* cx,
                                                   PropertyInfo prop) {
  if (!prop.hasSlot() || isUntrackedProperty(prop)) {
    return;
  }
  bumpGeneration();
  invalidateDependentIonScriptsForProperty(cx, prop,
                                           "teleporting shadowed property");
}

void ObjectFuse::handleTeleportingProtoMutation(JSContext* cx) {
  bumpGeneration();
  invalidateAllDependentIonScripts(cx, "proto mutation");
}

void ObjectFuse::handleShadowedGlobalProperty(JSContext* cx,
                                              PropertyInfo prop) {
  if (isUntrackedProperty(prop)) {
    return;
  }
  bumpGeneration();
  invalidateDependentIonScriptsForProperty(cx, prop,
                                           "shadowed global property");
}

const char* ObjectFuse::getPropertyStateString(PropertyInfo prop) const {
  PropertyState state = getPropertyState(prop);
  switch (state) {
    case PropertyState::Untracked:
      return "Untracked";
    case PropertyState::Constant:
      return "Constant";
    case PropertyState::NotConstant:
      return "NotConstant";
  }
  MOZ_CRASH("Unreachable");
}

size_t ObjectFuse::sizeOfIncludingThis(
    mozilla::MallocSizeOf mallocSizeOf) const {
  size_t result = mallocSizeOf(this);
  if (propertyStateBits_) {
    result += mallocSizeOf(propertyStateBits_.get());
  }
  result += dependencies_.shallowSizeOfExcludingThis(mallocSizeOf);
  for (auto iter = dependencies_.iter(); !iter.done(); iter.next()) {
    result += iter.get().value().sizeOfExcludingThis(mallocSizeOf);
  }
  return result;
}

ObjectFuse* ObjectFuseMap::getOrCreate(JSContext* cx, NativeObject* obj) {
  MOZ_ASSERT(obj->hasObjectFuse());
  MOZ_ASSERT(obj->zone() == zone_);
  auto p = objectFuses_.lookupForAdd(obj);
  if (!p) {
    auto fuse = MakeUnique<ObjectFuse>();
    if (!fuse || !objectFuses_.add(p, obj, std::move(fuse))) {
      ReportOutOfMemory(cx);
      return nullptr;
    }
  }
  return p->value().get();
}

ObjectFuse* ObjectFuseMap::get(NativeObject* obj) {
  MOZ_ASSERT(obj->hasObjectFuse());
  auto p = objectFuses_.lookup(obj);
  return p ? p->value().get() : nullptr;
}

size_t ObjectFuseMap::sizeOfExcludingThis(
    mozilla::MallocSizeOf mallocSizeOf) const {
  size_t result = objectFuses_.sizeOfExcludingThis(mallocSizeOf);
  for (auto iter = objectFuses_.iter(); !iter.done(); iter.next()) {
    result += iter.get().value()->sizeOfIncludingThis(mallocSizeOf);
  }
  return result;
}

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet am  2026-08-25) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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.