Bug 1417123 - Move barrier function declarations to public/HeapAPI.h r=sfink

This commit is contained in:
Jon Coppeard 2017-11-16 12:21:07 +00:00
parent 97baa05333
commit 08052a293d
23 changed files with 161 additions and 163 deletions

View File

@ -4,6 +4,10 @@
* 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/. */
/*
* High-level interface to the JS garbage collector.
*/
#ifndef js_GCAPI_h
#define js_GCAPI_h
@ -11,10 +15,13 @@
#include "mozilla/Vector.h"
#include "js/GCAnnotations.h"
#include "js/HeapAPI.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
struct JSContext;
class JSObject;
struct JSRuntime;
namespace js {
namespace gc {
class GCRuntime;
@ -51,6 +58,8 @@ typedef enum JSGCInvocationKind {
namespace JS {
struct Zone;
#define GCREASONS(D) \
/* Reasons internal to the JS engine */ \
D(API) \
@ -442,29 +451,6 @@ IsIncrementalGCInProgress(JSContext* cx);
extern JS_PUBLIC_API(bool)
IsIncrementalGCInProgress(JSRuntime* rt);
/*
* Returns true when writes to GC thing pointers (and reads from weak pointers)
* must call an incremental barrier. This is generally only true when running
* mutator code in-between GC slices. At other times, the barrier may be elided
* for performance.
*/
extern JS_PUBLIC_API(bool)
IsIncrementalBarrierNeeded(JSContext* cx);
/*
* Notify the GC that a reference to a JSObject is about to be overwritten.
* This method must be called if IsIncrementalBarrierNeeded.
*/
extern JS_PUBLIC_API(void)
IncrementalPreWriteBarrier(JSObject* obj);
/*
* Notify the GC that a weak reference to a GC thing has been read.
* This method must be called if IsIncrementalBarrierNeeded.
*/
extern JS_PUBLIC_API(void)
IncrementalReadBarrier(GCCellPtr thing);
/**
* Returns true if the most recent GC ran incrementally.
*/
@ -613,88 +599,6 @@ class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoRequireNoGC
} JS_HAZ_GC_INVALIDATED;
#endif
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
* if anything was unmarked.
*/
extern JS_FRIEND_API(bool)
UnmarkGrayGCThingRecursively(GCCellPtr thing);
} /* namespace JS */
namespace js {
namespace gc {
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
// GC things residing in the nursery cannot be gray: they have no mark bits.
// All live objects in the nursery are moved to tenured at the beginning of
// each GC slice, so the gray marker never sees nursery things.
if (IsInsideNursery(thing.asCell()))
return;
// There's nothing to do for permanent GC things that might be owned by
// another runtime.
if (thing.mayBeOwnedByOtherRuntime())
return;
if (IsIncrementalBarrierNeededOnTenuredGCThing(thing))
JS::IncrementalReadBarrier(thing);
else if (js::gc::detail::TenuredCellIsMarkedGray(thing.asCell()))
JS::UnmarkGrayGCThingRecursively(thing);
MOZ_ASSERT(!js::gc::detail::TenuredCellIsMarkedGray(thing.asCell()));
}
template <typename T>
extern JS_PUBLIC_API(bool)
EdgeNeedsSweepUnbarrieredSlow(T* thingp);
static MOZ_ALWAYS_INLINE bool
EdgeNeedsSweepUnbarriered(JSObject** objp)
{
// This function does not handle updating nursery pointers. Raw JSObject
// pointers should be updated separately or replaced with
// JS::Heap<JSObject*> which handles this automatically.
MOZ_ASSERT(!JS::CurrentThreadIsHeapMinorCollecting());
if (IsInsideNursery(reinterpret_cast<Cell*>(*objp)))
return false;
auto zone = JS::shadow::Zone::asShadowZone(detail::GetGCThingZone(uintptr_t(*objp)));
if (!zone->isGCSweepingOrCompacting())
return false;
return EdgeNeedsSweepUnbarrieredSlow(objp);
}
} /* namespace gc */
} /* namespace js */
namespace JS {
/*
* This should be called when an object that is marked gray is exposed to the JS
* engine (by handing it to running JS code or writing it into live JS
* data). During incremental GC, since the gray bits haven't been computed yet,
* we conservatively mark the object black.
*/
static MOZ_ALWAYS_INLINE void
ExposeObjectToActiveJS(JSObject* obj)
{
MOZ_ASSERT(obj);
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarrieredSlow(&obj));
js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
}
static MOZ_ALWAYS_INLINE void
ExposeScriptToActiveJS(JSScript* script)
{
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarrieredSlow(&script));
js::gc::ExposeGCThingToActiveJS(GCCellPtr(script));
}
/*
* Internal to Firefox.
*/
@ -709,4 +613,18 @@ NotifyDidPaint(JSContext* cx);
} /* namespace JS */
namespace js {
namespace gc {
/**
* Create an object providing access to the garbage collector's internal notion
* of the current state of memory (both GC heap memory and GCthing-controlled
* malloc memory.
*/
extern JS_PUBLIC_API(JSObject*)
NewMemoryInfoObject(JSContext* cx);
} /* namespace gc */
} /* namespace js */
#endif /* js_GCAPI_h */

View File

@ -467,7 +467,38 @@ GCThingIsMarkedGray(GCCellPtr thing)
extern JS_PUBLIC_API(JS::TraceKind)
GCThingTraceKind(void* thing);
} /* namespace JS */
/*
* Returns true when writes to GC thing pointers (and reads from weak pointers)
* must call an incremental barrier. This is generally only true when running
* mutator code in-between GC slices. At other times, the barrier may be elided
* for performance.
*/
extern JS_PUBLIC_API(bool)
IsIncrementalBarrierNeeded(JSContext* cx);
/*
* Notify the GC that a reference to a JSObject is about to be overwritten.
* This method must be called if IsIncrementalBarrierNeeded.
*/
extern JS_PUBLIC_API(void)
IncrementalPreWriteBarrier(JSObject* obj);
/*
* Notify the GC that a weak reference to a GC thing has been read.
* This method must be called if IsIncrementalBarrierNeeded.
*/
extern JS_PUBLIC_API(void)
IncrementalReadBarrier(GCCellPtr thing);
/**
* Unsets the gray bit for anything reachable from |thing|. |kind| should not be
* JS::TraceKind::Shape. |thing| should be non-null. The return value indicates
* if anything was unmarked.
*/
extern JS_FRIEND_API(bool)
UnmarkGrayGCThingRecursively(GCCellPtr thing);
} // namespace JS
namespace js {
namespace gc {
@ -487,15 +518,75 @@ IsIncrementalBarrierNeededOnTenuredGCThing(const JS::GCCellPtr thing)
return JS::shadow::Zone::asShadowZone(zone)->needsIncrementalBarrier();
}
/**
* Create an object providing access to the garbage collector's internal notion
* of the current state of memory (both GC heap memory and GCthing-controlled
* malloc memory.
*/
extern JS_PUBLIC_API(JSObject*)
NewMemoryInfoObject(JSContext* cx);
static MOZ_ALWAYS_INLINE void
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
{
// GC things residing in the nursery cannot be gray: they have no mark bits.
// All live objects in the nursery are moved to tenured at the beginning of
// each GC slice, so the gray marker never sees nursery things.
if (IsInsideNursery(thing.asCell()))
return;
} /* namespace gc */
} /* namespace js */
// There's nothing to do for permanent GC things that might be owned by
// another runtime.
if (thing.mayBeOwnedByOtherRuntime())
return;
if (IsIncrementalBarrierNeededOnTenuredGCThing(thing))
JS::IncrementalReadBarrier(thing);
else if (js::gc::detail::TenuredCellIsMarkedGray(thing.asCell()))
JS::UnmarkGrayGCThingRecursively(thing);
MOZ_ASSERT(!js::gc::detail::TenuredCellIsMarkedGray(thing.asCell()));
}
template <typename T>
extern JS_PUBLIC_API(bool)
EdgeNeedsSweepUnbarrieredSlow(T* thingp);
static MOZ_ALWAYS_INLINE bool
EdgeNeedsSweepUnbarriered(JSObject** objp)
{
// This function does not handle updating nursery pointers. Raw JSObject
// pointers should be updated separately or replaced with
// JS::Heap<JSObject*> which handles this automatically.
MOZ_ASSERT(!JS::CurrentThreadIsHeapMinorCollecting());
if (IsInsideNursery(reinterpret_cast<Cell*>(*objp)))
return false;
auto zone = JS::shadow::Zone::asShadowZone(detail::GetGCThingZone(uintptr_t(*objp)));
if (!zone->isGCSweepingOrCompacting())
return false;
return EdgeNeedsSweepUnbarrieredSlow(objp);
}
} // namespace gc
} // namesapce js
namespace JS {
/*
* This should be called when an object that is marked gray is exposed to the JS
* engine (by handing it to running JS code or writing it into live JS
* data). During incremental GC, since the gray bits haven't been computed yet,
* we conservatively mark the object black.
*/
static MOZ_ALWAYS_INLINE void
ExposeObjectToActiveJS(JSObject* obj)
{
MOZ_ASSERT(obj);
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarrieredSlow(&obj));
js::gc::ExposeGCThingToActiveJS(GCCellPtr(obj));
}
static MOZ_ALWAYS_INLINE void
ExposeScriptToActiveJS(JSScript* script)
{
MOZ_ASSERT(!js::gc::EdgeNeedsSweepUnbarrieredSlow(&script));
js::gc::ExposeGCThingToActiveJS(GCCellPtr(script));
}
} /* namespace JS */
#endif /* js_HeapAPI_h */

View File

@ -19,7 +19,6 @@
#include "jspubtd.h"
#include "js/GCAnnotations.h"
#include "js/GCAPI.h"
#include "js/GCPolicyAPI.h"
#include "js/HeapAPI.h"
#include "js/TypeDecls.h"

View File

@ -15,7 +15,6 @@
#include "builtin/SelfHostingDefines.h"
#include "js/Class.h"
#include "js/GCAPI.h"
#include "js/GCHashTable.h"
#include "vm/NativeObject.h"

View File

@ -25,7 +25,6 @@
#include "builtin/TypedObject.h"
#include "jit/AtomicOperations.h"
#include "jit/InlinableNatives.h"
#include "js/GCAPI.h"
#include "js/Value.h"
#include "jsobjinlines.h"

View File

@ -12,7 +12,6 @@
#define gc_ArenaList_h
#include "gc/AllocKind.h"
#include "js/GCAPI.h"
#include "js/SliceBudget.h"
#include "threading/ProtectedData.h"

View File

@ -25,7 +25,6 @@
#include "gc/AllocKind.h"
#include "gc/GCEnum.h"
#include "gc/Memory.h"
#include "js/GCAPI.h"
#include "js/HeapAPI.h"
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"

View File

@ -19,7 +19,6 @@
#include "NamespaceImports.h"
#include "gc/GCEnum.h"
#include "js/GCAPI.h"
#include "js/SliceBudget.h"
#include "js/UniquePtr.h"
#include "js/Vector.h"

View File

@ -17,7 +17,6 @@
#include "gc/GCInternals.h"
#include "gc/Zone.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "jscntxtinlines.h"

View File

@ -46,7 +46,6 @@
#include "jit/mips32/Simulator-mips32.h"
#include "jit/mips64/Simulator-mips64.h"
#include "jit/ProcessExecutableMemory.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@ -76,6 +75,8 @@ extern "C" void sync_instruction_memory(caddr_t v, u_int len);
#include <libkern/OSCacheControl.h>
#endif
struct JSRuntime;
namespace JS {
struct CodeSizes;
} // namespace JS

View File

@ -14,7 +14,6 @@
#include "jsfriendapi.h"
#include "jstypes.h"
#include "js/GCAPI.h"
#include "js/Value.h"
#include "vm/String.h"

View File

@ -21,7 +21,6 @@
#include "jit/Lowering.h"
#include "jit/MIR.h"
#include "js/Conversions.h"
#include "js/GCAPI.h"
#include "vm/TraceLogging.h"
#include "jsobjinlines.h"

View File

@ -5,8 +5,6 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/UniquePtr.h"
#include "js/GCAPI.h"
#include "jsapi-tests/tests.h"
static unsigned gSliceCallbackCount = 0;

View File

@ -19,7 +19,6 @@
#include "js/Class.h"
#include "js/Date.h"
#include "js/Debug.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/HeapAPI.h"
#include "js/Id.h"

View File

@ -71,33 +71,8 @@ class AtomStateEntry
struct AtomHasher
{
struct Lookup
{
union {
const JS::Latin1Char* latin1Chars;
const char16_t* twoByteChars;
};
bool isLatin1;
size_t length;
const JSAtom* atom; /* Optional. */
JS::AutoCheckCannotGC nogc;
HashNumber hash;
MOZ_ALWAYS_INLINE Lookup(const char16_t* chars, size_t length)
: twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
MOZ_ALWAYS_INLINE Lookup(const JS::Latin1Char* chars, size_t length)
: latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
inline explicit Lookup(const JSAtom* atom);
};
static HashNumber hash(const Lookup& l) { return l.hash; }
struct Lookup;
static inline HashNumber hash(const Lookup& l);
static MOZ_ALWAYS_INLINE bool match(const AtomStateEntry& entry, const Lookup& lookup);
static void rekey(AtomStateEntry& k, const AtomStateEntry& newKey) { k = newKey; }
};

View File

@ -35,6 +35,38 @@ js::AtomStateEntry::asPtrUnbarriered() const
namespace js {
struct AtomHasher::Lookup
{
union {
const JS::Latin1Char* latin1Chars;
const char16_t* twoByteChars;
};
bool isLatin1;
size_t length;
const JSAtom* atom; /* Optional. */
JS::AutoCheckCannotGC nogc;
HashNumber hash;
MOZ_ALWAYS_INLINE Lookup(const char16_t* chars, size_t length)
: twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
MOZ_ALWAYS_INLINE Lookup(const JS::Latin1Char* chars, size_t length)
: latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
{
hash = mozilla::HashString(chars, length);
}
inline explicit Lookup(const JSAtom* atom);
};
inline HashNumber
AtomHasher::hash(const Lookup& l)
{
return l.hash;
}
inline jsid
AtomToId(JSAtom* atom)
{

View File

@ -20,7 +20,6 @@
#include "gc/Barrier.h"
#include "js/Conversions.h"
#include "js/GCAPI.h"
#include "js/GCVector.h"
#include "js/HeapAPI.h"
#include "vm/Printer.h"

View File

@ -14,7 +14,6 @@
#include "jsobj.h"
#include "jswrapper.h"
#include "js/GCAPI.h"
#include "vm/GlobalObject.h"
#include "jsobjinlines.h"

View File

@ -75,7 +75,6 @@
#include "jit/JitcodeMap.h"
#include "jit/OptimizationTracking.h"
#include "js/Debug.h"
#include "js/GCAPI.h"
#include "js/GCVector.h"
#include "js/Initialization.h"
#include "js/StructuredClone.h"

View File

@ -27,7 +27,6 @@
#include "jit/BaselineDebugModeOSR.h"
#include "jit/BaselineJIT.h"
#include "js/Date.h"
#include "js/GCAPI.h"
#include "js/UbiNodeBreadthFirst.h"
#include "js/Vector.h"
#include "proxy/ScriptedProxyHandler.h"

View File

@ -14,7 +14,6 @@
#include "jit/BaselineFrame.h"
#include "jit/JitcodeMap.h"
#include "jit/JitCompartment.h"
#include "js/GCAPI.h"
#include "vm/Debugger.h"
#include "vm/Opcodes.h"

View File

@ -14,7 +14,6 @@
#include "mozilla/Unused.h"
#include "gc/Marking.h"
#include "js/GCAPI.h"
#include "js/UbiNode.h"
#include "vm/GeckoProfiler.h"

View File

@ -19,7 +19,6 @@
#include "gc/Heap.h"
#include "gc/Rooting.h"
#include "js/CharacterEncoding.h"
#include "js/GCAPI.h"
#include "js/RootingAPI.h"
#include "vm/Printer.h"