Commit 36104935 authored by Jon Coppeard's avatar Jon Coppeard
Browse files

Bug 1900050 - Optimize CycleCollectedRuntime's sweeping of nursery wrappers a little r=sfink,mccr8

This adds js::gc::InCollectedNurseryRegion which is fully inlinable and makes
JSObjectsTenured call the finalizers directly.

I don't think this makes a massive difference but it's still probably worth
doing.

Differential Revision: https://phabricator.services.mozilla.com/D212290
parent 27245e0d
Loading
Loading
Loading
Loading
+6 −13
Original line number Diff line number Diff line
@@ -510,7 +510,7 @@ typedef bool (*JSGrayRootsTracer)(JSTracer* trc, js::SliceBudget& budget,

typedef enum JSGCStatus { JSGC_BEGIN, JSGC_END } JSGCStatus;

typedef void (*JSObjectsTenuredCallback)(JSContext* cx, void* data);
typedef void (*JSObjectsTenuredCallback)(JS::GCContext* gcx, void* data);

typedef enum JSFinalizeStatus {
  /**
@@ -1373,20 +1373,13 @@ namespace gc {
extern JS_PUBLIC_API JSObject* NewMemoryInfoObject(JSContext* cx);

/*
 * Return whether |obj| is a dead nursery object during a minor GC.
 */
JS_PUBLIC_API bool IsDeadNurseryObject(JSObject* obj);

/*
 * Run the finalizer of a nursery-allocated JSObject that is known to be dead.
 *
 * This is a dangerous operation - only use this if you know what you're doing!
 * Get the GCContext for the current context.
 *
 * This is used by the browser to implement nursery-allocated wrapper cached
 * wrappers.
 * This is here to allow the browser to call finalizers for dead nursery
 * objects. This is a dangerous operation - only use this if you know what
 * you're doing!
 */
extern JS_PUBLIC_API void FinalizeDeadNurseryObject(JSContext* cx,
                                                    JSObject* obj);
extern JS_PUBLIC_API JS::GCContext* GetGCContext(JSContext* cx);

} /* namespace gc */
} /* namespace js */
+11 −0
Original line number Diff line number Diff line
@@ -648,6 +648,14 @@ MOZ_ALWAYS_INLINE bool IsInsideNursery(const TenuredCell* cell) {
  return false;
}

// Return whether |cell| is in the region of the nursery currently being
// collected.
MOZ_ALWAYS_INLINE bool InCollectedNurseryRegion(const Cell* cell) {
  MOZ_ASSERT(cell);
  return detail::GetCellChunkBase(cell)->getKind() ==
         ChunkKind::NurseryFromSpace;
}

// Allow use before the compiler knows the derivation of JSObject, JSString, and
// JS::BigInt.
MOZ_ALWAYS_INLINE bool IsInsideNursery(const JSObject* obj) {
@@ -659,6 +667,9 @@ MOZ_ALWAYS_INLINE bool IsInsideNursery(const JSString* str) {
MOZ_ALWAYS_INLINE bool IsInsideNursery(const JS::BigInt* bi) {
  return IsInsideNursery(reinterpret_cast<const Cell*>(bi));
}
MOZ_ALWAYS_INLINE bool InCollectedNurseryRegion(const JSObject* obj) {
  return InCollectedNurseryRegion(reinterpret_cast<const Cell*>(obj));
}

MOZ_ALWAYS_INLINE bool IsCellPointerValid(const void* ptr) {
  auto addr = uintptr_t(ptr);
+1 −1
Original line number Diff line number Diff line
@@ -1597,7 +1597,7 @@ void GCRuntime::callObjectsTenuredCallback() {
  JS::AutoSuppressGCAnalysis nogc;
  const auto& callback = tenuredCallback.ref();
  if (callback.op) {
    callback.op(rt->mainContextFromOwnThread(), callback.data);
    callback.op(&mainThreadContext.ref(), callback.data);
  }
}

+2 −19
Original line number Diff line number Diff line
@@ -792,26 +792,9 @@ const char* CellColorName(CellColor color) {
} /* namespace gc */
} /* namespace js */

JS_PUBLIC_API bool js::gc::IsDeadNurseryObject(JSObject* obj) {
  MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting());
  MOZ_ASSERT(obj);
  MOZ_ASSERT(IsInsideNursery(obj));
  MOZ_ASSERT(!IsForwarded(obj));

  return obj->runtimeFromMainThread()->gc.nursery().inCollectedRegion(obj);
}

JS_PUBLIC_API void js::gc::FinalizeDeadNurseryObject(JSContext* cx,
                                                     JSObject* obj) {
JS_PUBLIC_API JS::GCContext* js::gc::GetGCContext(JSContext* cx) {
  CHECK_THREAD(cx);
  MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting());

  MOZ_ASSERT(obj);
  MOZ_ASSERT(IsInsideNursery(obj));
  MOZ_ASSERT(!IsForwarded(obj));

  const JSClass* jsClass = JS::GetClass(obj);
  jsClass->doFinalize(cx->gcContext(), obj);
  return cx->gcContext();
}

JS_PUBLIC_API void js::gc::SetPerformanceHint(JSContext* cx,
+1 −2
Original line number Diff line number Diff line
@@ -40,8 +40,7 @@ inline bool js::Nursery::shouldTenure(gc::Cell* cell) {
}

inline bool js::Nursery::inCollectedRegion(gc::Cell* cell) const {
  gc::ChunkBase* chunk = gc::detail::GetCellChunkBase(cell);
  return chunk->getKind() == gc::ChunkKind::NurseryFromSpace;
  return gc::InCollectedNurseryRegion(cell);
}

inline bool js::Nursery::inCollectedRegion(void* ptr) const {
Loading