зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 5 changesets (bug 1664810
) for build bustages on TestingFunctions.cpp. CLOSED TREE
Backed out changeset 8342bb37c478 (bug1664810
) Backed out changeset 0cf50c9c75d9 (bug1664810
) Backed out changeset b85512fd99e1 (bug1664810
) Backed out changeset 99bd2cab97c8 (bug1664810
) Backed out changeset 0d5cd8372bcb (bug1664810
)
This commit is contained in:
Родитель
07362aeaa4
Коммит
dd1efa8650
|
@ -22,7 +22,6 @@
|
|||
#include "js/GCAnnotations.h"
|
||||
#include "js/GCPolicyAPI.h"
|
||||
#include "js/GCTypeMacros.h" // JS_FOR_EACH_PUBLIC_{,TAGGED_}GC_POINTER_TYPE
|
||||
#include "js/HashTable.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/ProfilingStack.h"
|
||||
#include "js/Realm.h"
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Value.h"
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#ifndef js_TracingAPI_h
|
||||
#define js_TracingAPI_h
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/GCTypeMacros.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/TraceKind.h"
|
||||
|
||||
|
@ -444,6 +446,20 @@ JS_DECLARE_UNSAFE_TRACE_ROOT(js::SavedFrame*)
|
|||
|
||||
extern JS_PUBLIC_API void TraceChildren(JSTracer* trc, GCCellPtr thing);
|
||||
|
||||
using ZoneSet =
|
||||
js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy>;
|
||||
using CompartmentSet =
|
||||
js::HashSet<JS::Compartment*, js::DefaultHasher<JS::Compartment*>,
|
||||
js::SystemAllocPolicy>;
|
||||
|
||||
/**
|
||||
* Trace every value within |compartments| that is wrapped by a
|
||||
* cross-compartment wrapper from a compartment that is not an element of
|
||||
* |compartments|.
|
||||
*/
|
||||
extern JS_PUBLIC_API void TraceIncomingCCWs(
|
||||
JSTracer* trc, const JS::CompartmentSet& compartments);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
extern JS_PUBLIC_API void JS_GetTraceThingInfo(char* buf, size_t bufsize,
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
@ -164,25 +163,23 @@
|
|||
// structure of the snapshot file, the analyses should be prepared for ubi::Node
|
||||
// graphs constructed from snapshots to be even more bizarre.
|
||||
|
||||
namespace js {
|
||||
class BaseScript;
|
||||
} // namespace js
|
||||
|
||||
namespace JS {
|
||||
|
||||
using ZoneSet =
|
||||
js::HashSet<Zone*, js::DefaultHasher<Zone*>, js::SystemAllocPolicy>;
|
||||
|
||||
using CompartmentSet =
|
||||
js::HashSet<Compartment*, js::DefaultHasher<Compartment*>,
|
||||
js::SystemAllocPolicy>;
|
||||
|
||||
namespace ubi {
|
||||
|
||||
class Edge;
|
||||
class EdgeRange;
|
||||
class StackFrame;
|
||||
|
||||
} // namespace ubi
|
||||
} // namespace JS
|
||||
|
||||
namespace js {
|
||||
class BaseScript;
|
||||
} // namespace js
|
||||
|
||||
namespace JS {
|
||||
namespace ubi {
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::RangedPtr;
|
||||
using mozilla::Variant;
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/Iteration.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "gc/Tracer.h" // for TraceManuallyBarrieredCrossCompartmentEdge
|
||||
#include "js/HeapAPI.h" // for IsInsideNursery
|
||||
#include "vm/Compartment.h" // for Compartment
|
||||
#include "vm/EnvironmentObject.h" // for JSObject::is, DebugEnvironmentProxy
|
||||
#include "vm/JSAtom.h" // for Atomize, PinAtom
|
||||
#include "vm/JSContext.h" // for JSContext
|
||||
#include "vm/JSFunction.h" // for JSFunction
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "js/HeapAPI.h" // for IsInsideNursery
|
||||
#include "js/Promise.h" // for PromiseState
|
||||
#include "js/Proxy.h" // for PropertyDescriptor
|
||||
#include "js/SourceText.h" // for SourceText
|
||||
#include "js/StableStringChars.h" // for AutoStableStringChars
|
||||
#include "js/String.h" // for JS::StringHasLatin1Chars
|
||||
#include "proxy/ScriptedProxyHandler.h" // for ScriptedProxyHandler
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "js/CompilationAndEvaluation.h" // for Compile
|
||||
#include "js/experimental/TypedData.h" // for JS_NewUint8Array
|
||||
#include "js/friend/ErrorMessages.h" // for GetErrorMessage, JSMSG_*
|
||||
#include "js/SourceText.h" // for JS::SourceOwnership
|
||||
#include "vm/BytecodeUtil.h" // for JSDVG_SEARCH_STACK
|
||||
#include "vm/JSContext.h" // for JSContext (ptr only)
|
||||
#include "vm/JSObject.h" // for JSObject, RequireObject
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "vm/FunctionFlags.h" // FunctionFlags
|
||||
#include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/HelperThreadState.h" // ParseTask
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSScript.h"
|
||||
#include "vm/ModuleBuilder.h" // js::ModuleBuilder
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include <type_traits>
|
||||
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/SymbolType.h"
|
||||
|
||||
#include "gc/Heap-inl.h"
|
||||
|
||||
|
@ -83,14 +82,6 @@ MOZ_ALWAYS_INLINE bool AtomMarkingRuntime::inlinedMarkAtomInternal(
|
|||
return true;
|
||||
}
|
||||
|
||||
void AtomMarkingRuntime::markChildren(JSContext* cx, JSAtom*) {}
|
||||
|
||||
void AtomMarkingRuntime::markChildren(JSContext* cx, JS::Symbol* symbol) {
|
||||
if (JSAtom* description = symbol->description()) {
|
||||
markAtom(cx, description);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MOZ_ALWAYS_INLINE void AtomMarkingRuntime::inlinedMarkAtom(JSContext* cx,
|
||||
T* thing) {
|
||||
|
|
|
@ -10,11 +10,9 @@
|
|||
#include "NamespaceImports.h"
|
||||
#include "ds/Bitmap.h"
|
||||
#include "threading/ProtectedData.h"
|
||||
#include "vm/SymbolType.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoLockGC;
|
||||
|
||||
namespace gc {
|
||||
|
||||
class Arena;
|
||||
|
@ -25,8 +23,13 @@ class AtomMarkingRuntime {
|
|||
// Unused arena atom bitmap indexes. Protected by the GC lock.
|
||||
js::GCLockData<Vector<size_t, 0, SystemAllocPolicy>> freeArenaIndexes;
|
||||
|
||||
inline void markChildren(JSContext* cx, JSAtom*);
|
||||
inline void markChildren(JSContext* cx, JS::Symbol* symbol);
|
||||
void markChildren(JSContext* cx, JSAtom*) {}
|
||||
|
||||
void markChildren(JSContext* cx, JS::Symbol* symbol) {
|
||||
if (JSAtom* description = symbol->description()) {
|
||||
markAtom(cx, description);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
// The extent of all allocated and free words in atom mark bitmaps.
|
||||
|
|
|
@ -227,6 +227,7 @@
|
|||
#include "jit/JitCode.h"
|
||||
#include "jit/JitcodeMap.h"
|
||||
#include "jit/JitRealm.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "js/Object.h" // JS::GetClass
|
||||
#include "js/SliceBudget.h"
|
||||
#include "proxy/DeadObjectProxy.h"
|
||||
|
@ -234,7 +235,6 @@
|
|||
#include "util/Windows.h"
|
||||
#include "vm/BigIntType.h"
|
||||
#include "vm/GeckoProfiler.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSObject.h"
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "ds/OrderedHashTable.h"
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "gc/ParallelWork.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#include "jsfriendapi.h" // For PerformanceHint
|
||||
|
||||
#include "gc/ArenaList.h"
|
||||
#include "gc/AtomMarking.h"
|
||||
#include "gc/GCMarker.h"
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/BigIntType.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/RegExpShared.h"
|
||||
#include "vm/Scope.h"
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "jit/JitRealm.h"
|
||||
#include "util/Poison.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#if defined(DEBUG)
|
||||
# include "vm/EnvironmentObject.h"
|
||||
#endif
|
||||
#include "vm/JSONPrinter.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/Time.h"
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "gc/GCParallelTask.h"
|
||||
#include "gc/Heap.h"
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/TracingAPI.h"
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "gc/GC.h"
|
||||
#include "gc/GCParallelTask.h"
|
||||
#include "gc/GCRuntime.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
|
||||
|
@ -114,7 +113,7 @@ class MOZ_RAII AutoRunParallelWork {
|
|||
}
|
||||
|
||||
~AutoRunParallelWork() {
|
||||
MOZ_ASSERT(gHelperThreadLock.ownedByCurrentThread());
|
||||
MOZ_ASSERT(HelperThreadState().isLockedByCurrentThread());
|
||||
|
||||
for (size_t i = 0; i < tasksStarted; i++) {
|
||||
gc->joinTask(*tasks[i], phaseKind, lock);
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
#include "gc/ClearEdgesTracer.h"
|
||||
#include "gc/GCInternals.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/ValueArray.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSONParser.h"
|
||||
|
||||
|
|
|
@ -104,8 +104,8 @@ void js::TraceChildren(JSTracer* trc, void* thing, JS::TraceKind kind) {
|
|||
});
|
||||
}
|
||||
|
||||
void js::gc::TraceIncomingCCWs(JSTracer* trc,
|
||||
const JS::CompartmentSet& compartments) {
|
||||
JS_PUBLIC_API void JS::TraceIncomingCCWs(
|
||||
JSTracer* trc, const JS::CompartmentSet& compartments) {
|
||||
for (CompartmentsIter source(trc->runtime()); !source.done(); source.next()) {
|
||||
if (compartments.has(source)) {
|
||||
continue;
|
||||
|
|
|
@ -7,14 +7,9 @@
|
|||
#ifndef js_Tracer_h
|
||||
#define js_Tracer_h
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
namespace JS {
|
||||
using CompartmentSet =
|
||||
js::HashSet<Compartment*, js::DefaultHasher<Compartment*>,
|
||||
js::SystemAllocPolicy>;
|
||||
} // namespace JS
|
||||
#include "gc/Barrier.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
@ -311,13 +306,6 @@ namespace gc {
|
|||
void TraceCycleCollectorChildren(JS::CallbackTracer* trc, Shape* shape);
|
||||
void TraceCycleCollectorChildren(JS::CallbackTracer* trc, ObjectGroup* group);
|
||||
|
||||
/**
|
||||
* Trace every value within |compartments| that is wrapped by a
|
||||
* cross-compartment wrapper from a compartment that is not an element of
|
||||
* |compartments|.
|
||||
*/
|
||||
void TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments);
|
||||
|
||||
} // namespace gc
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -501,7 +501,7 @@ void js::gc::MarkingValidator::nonIncrementalMark(AutoGCSession& session) {
|
|||
MOZ_ASSERT(!gcmarker->isWeakMarking());
|
||||
|
||||
/* Wait for off-thread parsing which can allocate. */
|
||||
WaitForAllHelperThreads();
|
||||
HelperThreadState().waitForAllThreads();
|
||||
|
||||
gc->waitBackgroundAllocEnd();
|
||||
gc->waitBackgroundSweepEnd();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "gdb-tests.h"
|
||||
#include "jsapi.h" // sundry symbols not moved to more-specific headers yet
|
||||
#include "jsfriendapi.h" // JSFunctionSpecWithHelp
|
||||
|
||||
#include "jit/JitOptions.h" // js::jit::JitOptions
|
||||
#include "js/CallArgs.h" // JS::CallArgs, JS::CallArgsFromVp
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "debugger/DebugAPI.h"
|
||||
#include "jit/arm/Simulator-arm.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "jit/BaselineFrame.h"
|
||||
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/Realm.h"
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
#include "jit/BaselineFrame.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/FixedList.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/SharedICRegisters.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
struct BytecodeInfo;
|
||||
class MacroAssembler;
|
||||
|
||||
// [SMDOC] Baseline FrameInfo overview.
|
||||
//
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "vm/ArrayObject.h"
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
#include "vm/Realm.h"
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "jit/JitCode.h"
|
||||
#include "jit/shared/Assembler-shared.h"
|
||||
#include "util/TrailingArray.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "builtin/DataViewObject.h"
|
||||
#include "builtin/MapObject.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "jit/BaselineCacheIRCompiler.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/CacheIRSpewer.h"
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "gc/Rooting.h"
|
||||
#include "jit/CacheIROpsGenerated.h"
|
||||
#include "jit/CompactBuffer.h"
|
||||
#include "jit/ICState.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/Simulator.h"
|
||||
#include "js/friend/XrayJitInfo.h" // JS::XrayJitInfo
|
||||
#include "js/ScalarType.h" // js::Scalar::Type
|
||||
|
@ -30,10 +30,6 @@ namespace jit {
|
|||
enum class BaselineCacheIRStubKind;
|
||||
enum class InlinableNative : uint16_t;
|
||||
|
||||
class ICStub;
|
||||
class Label;
|
||||
class MacroAssembler;
|
||||
|
||||
// [SMDOC] CacheIR
|
||||
//
|
||||
// CacheIR is an (extremely simple) linear IR language for inline caches.
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class ICEntry;
|
||||
|
||||
// [SMDOC] CacheIR Health Rating
|
||||
//
|
||||
// The goal of CacheIR health rating is to make the costlier
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "jit/JitAllocPolicy.h"
|
||||
#include "jit/JitFrames.h"
|
||||
#include "jit/Registers.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSFunction.h"
|
||||
|
||||
namespace js {
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#include "js/UniquePtr.h"
|
||||
#include "util/Memory.h"
|
||||
#include "util/Windows.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
#ifdef MOZ_VTUNE
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "frontend/SourceNotes.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
|
@ -32,6 +31,7 @@
|
|||
#include "vm/BytecodeIterator.h"
|
||||
#include "vm/BytecodeLocation.h"
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/Instrumentation.h"
|
||||
#include "vm/Opcodes.h"
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "jit/CodeGenerator.h"
|
||||
#include "jit/JitScript.h"
|
||||
#include "jit/WarpSnapshot.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/JSScript.h"
|
||||
|
||||
#include "vm/JSScript-inl.h"
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define jit_IonIC_h
|
||||
|
||||
#include "jit/CacheIR.h"
|
||||
#include "jit/shared/Assembler-shared.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/BaselineDebugModeOSR.h"
|
||||
#include "jit/BaselineFrame.h"
|
||||
|
@ -21,6 +20,7 @@
|
|||
#include "jit/JitcodeMap.h"
|
||||
#include "jit/JitRealm.h"
|
||||
#include "jit/JitSpewer.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/PcScriptCache.h"
|
||||
#include "jit/Recover.h"
|
||||
#include "jit/Safepoints.h"
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "jit/TrialInlining.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "util/TrailingArray.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/TypeInference.h"
|
||||
|
||||
class JS_PUBLIC_API JSScript;
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class MacroAssembler;
|
||||
|
||||
class Linker {
|
||||
MacroAssembler& masm;
|
||||
mozilla::Maybe<AutoWritableJitCodeFallible> awjcf;
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "jit/AtomicOp.h"
|
||||
#include "jit/BaselineIC.h"
|
||||
#include "jit/FixedList.h"
|
||||
#include "jit/InlineList.h"
|
||||
#include "jit/JitAllocPolicy.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/MOpcodesGenerated.h"
|
||||
#include "jit/TIOracle.h"
|
||||
#include "jit/TypePolicy.h"
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
# include "jit/x86/MacroAssembler-x86-inl.h"
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "vm/Realm.h"
|
||||
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
# include "jit/x86/MacroAssembler-x86.h"
|
||||
#elif defined(JS_CODEGEN_X64)
|
||||
|
@ -37,6 +39,9 @@
|
|||
#include "jit/VMFunctions.h"
|
||||
#include "js/ScalarType.h" // js::Scalar::Type
|
||||
#include "util/Memory.h"
|
||||
#include "vm/ProxyObject.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
|
||||
// [SMDOC] MacroAssembler multi-platform overview
|
||||
//
|
||||
|
@ -204,9 +209,6 @@
|
|||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
class TypedArrayObject;
|
||||
|
||||
namespace jit {
|
||||
|
||||
// Defined in JitFrames.h
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#ifdef JS_ION_PERF
|
||||
# include <stdio.h>
|
||||
# include "jit/MacroAssembler.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -12,13 +12,11 @@
|
|||
#include "jit/JitFrames.h"
|
||||
#include "jit/JSJitFrameIter.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSFunction.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class CallObject;
|
||||
|
||||
namespace jit {
|
||||
|
||||
// RematerializedFrame: An optimized frame that has been rematerialized with
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define jit_TrialInlining_h
|
||||
|
||||
#include "jit/CacheIR.h"
|
||||
#include "jit/ICStubSpace.h"
|
||||
#include "vm/BytecodeLocation.h"
|
||||
|
||||
/*
|
||||
|
@ -36,9 +35,6 @@
|
|||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
class ICEntry;
|
||||
class ICScript;
|
||||
|
||||
/*
|
||||
* An InliningRoot is owned by a JitScript. In turn, it owns the set
|
||||
* of ICScripts that are candidates for being inlined in that JitScript.
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define jit_VMFunctionList_inl_h
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "builtin/ModuleObject.h" // js::GetOrCreateModuleMetaObject
|
||||
#include "builtin/Promise.h" // js::AsyncFunctionAwait
|
||||
#include "builtin/RegExp.h"
|
||||
#include "builtin/String.h"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "vm/BuiltinObjectKind.h"
|
||||
#include "vm/BytecodeIterator.h"
|
||||
#include "vm/BytecodeLocation.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/Instrumentation.h"
|
||||
#include "vm/Opcodes.h"
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "gc/Policy.h"
|
||||
#include "jit/JitAllocPolicy.h"
|
||||
#include "jit/JitContext.h"
|
||||
|
|
|
@ -130,7 +130,7 @@ BEGIN_TEST(testTracingIncomingCCWs) {
|
|||
|
||||
void* thing = wrappee.get();
|
||||
CCWTestTracer trc(cx, &thing, JS::TraceKind::Object);
|
||||
js::gc::TraceIncomingCCWs(&trc, compartments);
|
||||
JS::TraceIncomingCCWs(&trc, compartments);
|
||||
CHECK(trc.numberOfThingsTraced == 1);
|
||||
CHECK(trc.okay);
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "NamespaceImports.h"
|
||||
|
||||
#include "js/Conversions.h"
|
||||
#include "js/friend/ErrorMessages.h"
|
||||
|
||||
#include "vm/StringType.h"
|
||||
|
||||
|
|
|
@ -4761,7 +4761,7 @@ static bool SetJitCompilerOption(JSContext* cx, unsigned argc, Value* vp) {
|
|||
|
||||
// JIT compiler options are process-wide, so we have to stop off-thread
|
||||
// compilations for all runtimes to avoid races.
|
||||
WaitForAllHelperThreads();
|
||||
HelperThreadState().waitForAllThreads();
|
||||
|
||||
// Only release JIT code for the current runtime because there's no good
|
||||
// way to discard code for other runtimes.
|
||||
|
|
|
@ -107,7 +107,7 @@ void CheckGlobalLock<Lock, Helper>::check() const {
|
|||
TlsContext.get()->runtime()->currentThreadHasScriptDataAccess());
|
||||
break;
|
||||
case GlobalLock::HelperThreadLock:
|
||||
MOZ_ASSERT(gHelperThreadLock.ownedByCurrentThread());
|
||||
MOZ_ASSERT(HelperThreadState().isLockedByCurrentThread());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ void FailureSimulator::simulateFailureAfter(Kind kind, uint64_t checks,
|
|||
Maybe<AutoLockHelperThreadState> lock;
|
||||
if (IsHelperThreadType(targetThread_) || IsHelperThreadType(thread)) {
|
||||
lock.emplace();
|
||||
WaitForAllHelperThreads(lock.ref());
|
||||
HelperThreadState().waitForAllThreadsLocked(lock.ref());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(counter_ + checks > counter_);
|
||||
|
@ -66,7 +66,7 @@ void FailureSimulator::reset() {
|
|||
Maybe<AutoLockHelperThreadState> lock;
|
||||
if (IsHelperThreadType(targetThread_)) {
|
||||
lock.emplace();
|
||||
WaitForAllHelperThreads(lock.ref());
|
||||
HelperThreadState().waitForAllThreadsLocked(lock.ref());
|
||||
}
|
||||
|
||||
targetThread_ = THREAD_TYPE_NONE;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include "ds/LifoAlloc.h"
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h"
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
|
||||
#include <type_traits>
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "frontend/NameAnalysisTypes.h"
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/WeakMap.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSObject.h"
|
||||
|
@ -22,10 +24,7 @@
|
|||
|
||||
namespace js {
|
||||
|
||||
class AbstractGeneratorObject;
|
||||
class IndirectBindingMap;
|
||||
class ModuleObject;
|
||||
|
||||
using HandleModuleObject = Handle<ModuleObject*>;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,680 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sts=2 et sw=2 tw=80:
|
||||
* 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/. */
|
||||
|
||||
/*
|
||||
* Definitions for managing off-thread work using a process wide list of
|
||||
* worklist items and pool of threads. Worklist items are engine internal, and
|
||||
* are distinct from e.g. web workers.
|
||||
*/
|
||||
|
||||
#ifndef vm_HelperThreadState_h
|
||||
#define vm_HelperThreadState_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "ds/Fifo.h"
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "threading/ConditionVariable.h"
|
||||
#include "threading/Thread.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/HelperThreadTask.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseTask
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoLockHelperThreadState;
|
||||
class AutoUnlockHelperThreadState;
|
||||
class CompileError;
|
||||
struct ParseTask;
|
||||
struct PromiseHelperTask;
|
||||
class PromiseObject;
|
||||
|
||||
namespace jit {
|
||||
class IonCompileTask;
|
||||
class IonFreeTask;
|
||||
} // namespace jit
|
||||
|
||||
namespace frontend {
|
||||
struct CompilationInfo;
|
||||
} // namespace frontend
|
||||
|
||||
namespace wasm {
|
||||
struct Tier2GeneratorTask;
|
||||
} // namespace wasm
|
||||
|
||||
enum class ParseTaskKind { Script, Module, ScriptDecode, MultiScriptsDecode };
|
||||
enum class StartEncoding { No, Yes };
|
||||
|
||||
namespace wasm {
|
||||
|
||||
struct CompileTask;
|
||||
typedef Fifo<CompileTask*, 0, SystemAllocPolicy> CompileTaskPtrFifo;
|
||||
|
||||
struct Tier2GeneratorTask : public HelperThreadTask {
|
||||
virtual ~Tier2GeneratorTask() = default;
|
||||
virtual void cancel() = 0;
|
||||
};
|
||||
|
||||
using UniqueTier2GeneratorTask = UniquePtr<Tier2GeneratorTask>;
|
||||
typedef Vector<Tier2GeneratorTask*, 0, SystemAllocPolicy>
|
||||
Tier2GeneratorTaskPtrVector;
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
// Per-process state for off thread work items.
|
||||
class GlobalHelperThreadState {
|
||||
friend class AutoLockHelperThreadState;
|
||||
friend class AutoUnlockHelperThreadState;
|
||||
|
||||
public:
|
||||
// A single tier-2 ModuleGenerator job spawns many compilation jobs, and we
|
||||
// do not want to allow more than one such ModuleGenerator to run at a time.
|
||||
static const size_t MaxTier2GeneratorTasks = 1;
|
||||
|
||||
// Number of CPUs to treat this machine as having when creating threads.
|
||||
// May be accessed without locking.
|
||||
size_t cpuCount;
|
||||
|
||||
// Number of threads to create. May be accessed without locking.
|
||||
size_t threadCount;
|
||||
|
||||
typedef Vector<jit::IonCompileTask*, 0, SystemAllocPolicy>
|
||||
IonCompileTaskVector;
|
||||
using IonFreeTaskVector =
|
||||
Vector<js::UniquePtr<jit::IonFreeTask>, 0, SystemAllocPolicy>;
|
||||
typedef Vector<UniquePtr<ParseTask>, 0, SystemAllocPolicy> ParseTaskVector;
|
||||
using ParseTaskList = mozilla::LinkedList<ParseTask>;
|
||||
typedef Vector<UniquePtr<SourceCompressionTask>, 0, SystemAllocPolicy>
|
||||
SourceCompressionTaskVector;
|
||||
using GCParallelTaskList = mozilla::LinkedList<GCParallelTask>;
|
||||
typedef Vector<PromiseHelperTask*, 0, SystemAllocPolicy>
|
||||
PromiseHelperTaskVector;
|
||||
typedef Vector<JSContext*, 0, SystemAllocPolicy> ContextVector;
|
||||
using HelperThreadVector =
|
||||
Vector<UniquePtr<HelperThread>, 0, SystemAllocPolicy>;
|
||||
|
||||
// Count of running task by each threadType.
|
||||
mozilla::EnumeratedArray<ThreadType, ThreadType::THREAD_TYPE_MAX, size_t>
|
||||
runningTaskCount;
|
||||
size_t totalCountRunningTasks;
|
||||
|
||||
WriteOnceData<JS::RegisterThreadCallback> registerThread;
|
||||
WriteOnceData<JS::UnregisterThreadCallback> unregisterThread;
|
||||
|
||||
private:
|
||||
// The lists below are all protected by |lock|.
|
||||
|
||||
// List of available helper threads.
|
||||
HelperThreadVector threads_;
|
||||
|
||||
// Ion compilation worklist and finished jobs.
|
||||
IonCompileTaskVector ionWorklist_, ionFinishedList_;
|
||||
IonFreeTaskVector ionFreeList_;
|
||||
|
||||
// wasm worklists.
|
||||
wasm::CompileTaskPtrFifo wasmWorklist_tier1_;
|
||||
wasm::CompileTaskPtrFifo wasmWorklist_tier2_;
|
||||
wasm::Tier2GeneratorTaskPtrVector wasmTier2GeneratorWorklist_;
|
||||
|
||||
// Count of finished Tier2Generator tasks.
|
||||
uint32_t wasmTier2GeneratorsFinished_;
|
||||
|
||||
// Async tasks that, upon completion, are dispatched back to the JSContext's
|
||||
// owner thread via embedding callbacks instead of a finished list.
|
||||
PromiseHelperTaskVector promiseHelperTasks_;
|
||||
|
||||
// Script parsing/emitting worklist and finished jobs.
|
||||
ParseTaskVector parseWorklist_;
|
||||
ParseTaskList parseFinishedList_;
|
||||
|
||||
// Parse tasks waiting for an atoms-zone GC to complete.
|
||||
ParseTaskVector parseWaitingOnGC_;
|
||||
|
||||
// Source compression worklist of tasks that we do not yet know can start.
|
||||
SourceCompressionTaskVector compressionPendingList_;
|
||||
|
||||
// Source compression worklist of tasks that can start.
|
||||
SourceCompressionTaskVector compressionWorklist_;
|
||||
|
||||
// Finished source compression tasks.
|
||||
SourceCompressionTaskVector compressionFinishedList_;
|
||||
|
||||
// GC tasks needing to be done in parallel.
|
||||
GCParallelTaskList gcParallelWorklist_;
|
||||
size_t gcParallelThreadCount;
|
||||
|
||||
// Global list of JSContext for GlobalHelperThreadState to use.
|
||||
ContextVector helperContexts_;
|
||||
|
||||
using HelperThreadTaskVector =
|
||||
Vector<HelperThreadTask*, 0, SystemAllocPolicy>;
|
||||
// Vector of running HelperThreadTask.
|
||||
// This is used to get the HelperThreadTask that are currently running.
|
||||
HelperThreadTaskVector helperTasks_;
|
||||
|
||||
ParseTask* removeFinishedParseTask(ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
|
||||
public:
|
||||
void addSizeOfIncludingThis(JS::GlobalStats* stats,
|
||||
AutoLockHelperThreadState& lock) const;
|
||||
|
||||
size_t maxIonCompilationThreads() const;
|
||||
size_t maxWasmCompilationThreads() const;
|
||||
size_t maxWasmTier2GeneratorThreads() const;
|
||||
size_t maxPromiseHelperThreads() const;
|
||||
size_t maxParseThreads() const;
|
||||
size_t maxCompressionThreads() const;
|
||||
size_t maxGCParallelThreads(const AutoLockHelperThreadState& lock) const;
|
||||
|
||||
GlobalHelperThreadState();
|
||||
|
||||
HelperThreadVector& threads(const AutoLockHelperThreadState& lock) {
|
||||
return threads_;
|
||||
}
|
||||
const HelperThreadVector& threads(
|
||||
const AutoLockHelperThreadState& lock) const {
|
||||
return threads_;
|
||||
}
|
||||
|
||||
bool ensureInitialized();
|
||||
bool ensureThreadCount(size_t count);
|
||||
void finish();
|
||||
void finishThreads();
|
||||
|
||||
MOZ_MUST_USE bool ensureContextList(size_t count);
|
||||
JSContext* getFirstUnusedContext(AutoLockHelperThreadState& locked);
|
||||
void destroyHelperContexts(AutoLockHelperThreadState& lock);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isLockedByCurrentThread() const;
|
||||
#endif
|
||||
|
||||
enum CondVar {
|
||||
// For notifying threads waiting for work that they may be able to make
|
||||
// progress, ie, a work item has been completed by a helper thread and
|
||||
// the thread that created the work item can now consume it.
|
||||
CONSUMER,
|
||||
|
||||
// For notifying helper threads doing the work that they may be able to
|
||||
// make progress, ie, a work item has been enqueued and an idle helper
|
||||
// thread may pick up up the work item and perform it.
|
||||
PRODUCER,
|
||||
};
|
||||
|
||||
void wait(AutoLockHelperThreadState& locked, CondVar which,
|
||||
mozilla::TimeDuration timeout = mozilla::TimeDuration::Forever());
|
||||
void notifyAll(CondVar which, const AutoLockHelperThreadState&);
|
||||
|
||||
private:
|
||||
void notifyOne(CondVar which, const AutoLockHelperThreadState&);
|
||||
|
||||
public:
|
||||
// Helper method for removing items from the vectors below while iterating
|
||||
// over them.
|
||||
template <typename T>
|
||||
void remove(T& vector, size_t* index) {
|
||||
// Self-moving is undefined behavior.
|
||||
if (*index != vector.length() - 1) {
|
||||
vector[*index] = std::move(vector.back());
|
||||
}
|
||||
(*index)--;
|
||||
vector.popBack();
|
||||
}
|
||||
|
||||
IonCompileTaskVector& ionWorklist(const AutoLockHelperThreadState&) {
|
||||
return ionWorklist_;
|
||||
}
|
||||
IonCompileTaskVector& ionFinishedList(const AutoLockHelperThreadState&) {
|
||||
return ionFinishedList_;
|
||||
}
|
||||
IonFreeTaskVector& ionFreeList(const AutoLockHelperThreadState&) {
|
||||
return ionFreeList_;
|
||||
}
|
||||
|
||||
wasm::CompileTaskPtrFifo& wasmWorklist(const AutoLockHelperThreadState&,
|
||||
wasm::CompileMode m) {
|
||||
switch (m) {
|
||||
case wasm::CompileMode::Once:
|
||||
case wasm::CompileMode::Tier1:
|
||||
return wasmWorklist_tier1_;
|
||||
case wasm::CompileMode::Tier2:
|
||||
return wasmWorklist_tier2_;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
wasm::Tier2GeneratorTaskPtrVector& wasmTier2GeneratorWorklist(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return wasmTier2GeneratorWorklist_;
|
||||
}
|
||||
|
||||
void incWasmTier2GeneratorsFinished(const AutoLockHelperThreadState&) {
|
||||
wasmTier2GeneratorsFinished_++;
|
||||
}
|
||||
|
||||
uint32_t wasmTier2GeneratorsFinished(const AutoLockHelperThreadState&) const {
|
||||
return wasmTier2GeneratorsFinished_;
|
||||
}
|
||||
|
||||
PromiseHelperTaskVector& promiseHelperTasks(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return promiseHelperTasks_;
|
||||
}
|
||||
|
||||
ParseTaskVector& parseWorklist(const AutoLockHelperThreadState&) {
|
||||
return parseWorklist_;
|
||||
}
|
||||
ParseTaskList& parseFinishedList(const AutoLockHelperThreadState&) {
|
||||
return parseFinishedList_;
|
||||
}
|
||||
ParseTaskVector& parseWaitingOnGC(const AutoLockHelperThreadState&) {
|
||||
return parseWaitingOnGC_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionPendingList(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionPendingList_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionWorklist(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionWorklist_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionFinishedList(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionFinishedList_;
|
||||
}
|
||||
|
||||
GCParallelTaskList& gcParallelWorklist(const AutoLockHelperThreadState&) {
|
||||
return gcParallelWorklist_;
|
||||
}
|
||||
|
||||
void setGCParallelThreadCount(size_t count,
|
||||
const AutoLockHelperThreadState&) {
|
||||
MOZ_ASSERT(count >= 1);
|
||||
MOZ_ASSERT(count <= threadCount);
|
||||
gcParallelThreadCount = count;
|
||||
}
|
||||
|
||||
HelperThreadTaskVector& helperTasks(const AutoLockHelperThreadState&) {
|
||||
return helperTasks_;
|
||||
}
|
||||
|
||||
HelperThreadTask* maybeGetWasmCompile(const AutoLockHelperThreadState& lock,
|
||||
wasm::CompileMode mode);
|
||||
|
||||
HelperThreadTask* maybeGetWasmTier1CompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetWasmTier2CompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetWasmTier2GeneratorTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetPromiseHelperTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetIonCompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetIonFreeTask(const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetParseTask(const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetCompressionTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetGCParallelTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
|
||||
enum class ScheduleCompressionTask { GC, API };
|
||||
|
||||
// Used by a major GC to signal processing enqueued compression tasks.
|
||||
void startHandlingCompressionTasks(const AutoLockHelperThreadState&,
|
||||
ScheduleCompressionTask schedule);
|
||||
|
||||
jit::IonCompileTask* highestPriorityPendingIonCompile(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
|
||||
private:
|
||||
void scheduleCompressionTasks(const AutoLockHelperThreadState&,
|
||||
ScheduleCompressionTask schedule);
|
||||
|
||||
UniquePtr<ParseTask> finishParseTaskCommon(JSContext* cx, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
|
||||
JSScript* finishSingleParseTask(
|
||||
JSContext* cx, ParseTaskKind kind, JS::OffThreadToken* token,
|
||||
StartEncoding startEncoding = StartEncoding::No);
|
||||
bool generateLCovSources(JSContext* cx, ParseTask* parseTask);
|
||||
bool finishMultiParseTask(JSContext* cx, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token,
|
||||
MutableHandle<ScriptVector> scripts);
|
||||
|
||||
void mergeParseTaskRealm(JSContext* cx, ParseTask* parseTask,
|
||||
JS::Realm* dest);
|
||||
|
||||
public:
|
||||
void cancelParseTask(JSRuntime* rt, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
void destroyParseTask(JSRuntime* rt, ParseTask* parseTask);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
JSScript* finishScriptParseTask(
|
||||
JSContext* cx, JS::OffThreadToken* token,
|
||||
StartEncoding startEncoding = StartEncoding::No);
|
||||
JSScript* finishScriptDecodeTask(JSContext* cx, JS::OffThreadToken* token);
|
||||
bool finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token,
|
||||
MutableHandle<ScriptVector> scripts);
|
||||
JSObject* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
|
||||
|
||||
bool hasActiveThreads(const AutoLockHelperThreadState&);
|
||||
void waitForAllThreads();
|
||||
void waitForAllThreadsLocked(AutoLockHelperThreadState&);
|
||||
|
||||
bool checkTaskThreadLimit(ThreadType threadType, size_t maxThreads,
|
||||
bool isMaster,
|
||||
const AutoLockHelperThreadState& lock) const;
|
||||
bool checkTaskThreadLimit(ThreadType threadType, size_t maxThreads,
|
||||
const AutoLockHelperThreadState& lock) const {
|
||||
return checkTaskThreadLimit(threadType, maxThreads, /* isMaster */ false,
|
||||
lock);
|
||||
}
|
||||
|
||||
void triggerFreeUnusedMemory();
|
||||
|
||||
private:
|
||||
/* Condvars for threads waiting/notifying each other. */
|
||||
js::ConditionVariable consumerWakeup;
|
||||
js::ConditionVariable producerWakeup;
|
||||
|
||||
js::ConditionVariable& whichWakeup(CondVar which) {
|
||||
switch (which) {
|
||||
case CONSUMER:
|
||||
return consumerWakeup;
|
||||
case PRODUCER:
|
||||
return producerWakeup;
|
||||
default:
|
||||
MOZ_CRASH("Invalid CondVar in |whichWakeup|");
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch(const AutoLockHelperThreadState& locked);
|
||||
|
||||
public:
|
||||
bool submitTask(wasm::UniqueTier2GeneratorTask task);
|
||||
bool submitTask(wasm::CompileTask* task, wasm::CompileMode mode);
|
||||
bool submitTask(UniquePtr<jit::IonFreeTask> task,
|
||||
const AutoLockHelperThreadState& lock);
|
||||
bool submitTask(jit::IonCompileTask* task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(UniquePtr<SourceCompressionTask> task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(JSRuntime* rt, UniquePtr<ParseTask> task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(PromiseHelperTask* task);
|
||||
bool submitTask(GCParallelTask* task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
void runTaskLocked(HelperThreadTask* task, AutoLockHelperThreadState& lock);
|
||||
};
|
||||
|
||||
static inline GlobalHelperThreadState& HelperThreadState() {
|
||||
extern GlobalHelperThreadState* gHelperThreadState;
|
||||
|
||||
MOZ_ASSERT(gHelperThreadState);
|
||||
return *gHelperThreadState;
|
||||
}
|
||||
|
||||
/* Individual helper thread, one allocated per core. */
|
||||
class HelperThread {
|
||||
Thread thread;
|
||||
|
||||
/*
|
||||
* The profiling thread for this helper thread, which can be used to push
|
||||
* and pop label frames.
|
||||
* This field being non-null indicates that this thread has been registered
|
||||
* and needs to be unregistered at shutdown.
|
||||
*/
|
||||
ProfilingStack* profilingStack = nullptr;
|
||||
|
||||
/*
|
||||
* Indicate to a thread that it should terminate itself. This is only read
|
||||
* or written with the helper thread state lock held.
|
||||
*/
|
||||
bool terminate = false;
|
||||
|
||||
public:
|
||||
HelperThread();
|
||||
MOZ_MUST_USE bool init();
|
||||
|
||||
ThreadId threadId() { return thread.get_id(); }
|
||||
|
||||
void setTerminate(const AutoLockHelperThreadState& lock);
|
||||
void join();
|
||||
|
||||
static void ThreadMain(void* arg);
|
||||
void threadLoop();
|
||||
|
||||
void ensureRegisteredWithProfiler();
|
||||
void unregisterWithProfilerIfNeeded();
|
||||
|
||||
private:
|
||||
struct AutoProfilerLabel {
|
||||
AutoProfilerLabel(HelperThread* helperThread, const char* label,
|
||||
JS::ProfilingCategoryPair categoryPair);
|
||||
~AutoProfilerLabel();
|
||||
|
||||
private:
|
||||
ProfilingStack* profilingStack;
|
||||
};
|
||||
|
||||
using Selector = HelperThreadTask* (
|
||||
GlobalHelperThreadState::*)(const AutoLockHelperThreadState&);
|
||||
static const Selector selectors[];
|
||||
|
||||
HelperThreadTask* findHighestPriorityTask(
|
||||
const AutoLockHelperThreadState& locked);
|
||||
};
|
||||
|
||||
struct MOZ_RAII AutoSetHelperThreadContext {
|
||||
JSContext* cx;
|
||||
explicit AutoSetHelperThreadContext();
|
||||
~AutoSetHelperThreadContext() {
|
||||
AutoLockHelperThreadState lock;
|
||||
cx->tempLifoAlloc().releaseAll();
|
||||
if (cx->shouldFreeUnusedMemory()) {
|
||||
cx->tempLifoAlloc().freeAll();
|
||||
cx->setFreeUnusedMemory(false);
|
||||
}
|
||||
cx->clearHelperThread(lock);
|
||||
cx = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct MOZ_RAII AutoSetContextRuntime {
|
||||
explicit AutoSetContextRuntime(JSRuntime* rt) {
|
||||
TlsContext.get()->setRuntime(rt);
|
||||
}
|
||||
~AutoSetContextRuntime() { TlsContext.get()->setRuntime(nullptr); }
|
||||
};
|
||||
|
||||
struct ParseTask : public mozilla::LinkedListElement<ParseTask>,
|
||||
public JS::OffThreadToken,
|
||||
public HelperThreadTask {
|
||||
ParseTaskKind kind;
|
||||
JS::OwningCompileOptions options;
|
||||
|
||||
// HelperThreads are shared between all runtimes in the process so explicitly
|
||||
// track which one we are associated with.
|
||||
JSRuntime* runtime = nullptr;
|
||||
|
||||
// The global object to use while parsing.
|
||||
JSObject* parseGlobal;
|
||||
|
||||
// Callback invoked off thread when the parse finishes.
|
||||
JS::OffThreadCompileCallback callback;
|
||||
void* callbackData;
|
||||
|
||||
// Holds the final scripts between the invocation of the callback and the
|
||||
// point where FinishOffThreadScript is called, which will destroy the
|
||||
// ParseTask.
|
||||
GCVector<JSScript*, 1, SystemAllocPolicy> scripts;
|
||||
|
||||
// Holds the ScriptSourceObjects generated for the script compilation.
|
||||
GCVector<ScriptSourceObject*, 1, SystemAllocPolicy> sourceObjects;
|
||||
|
||||
// Holds the CompilationInfo generated for the script compilation.
|
||||
UniquePtr<frontend::CompilationInfo> compilationInfo_;
|
||||
|
||||
// Any errors or warnings produced during compilation. These are reported
|
||||
// when finishing the script.
|
||||
Vector<UniquePtr<CompileError>, 0, SystemAllocPolicy> errors;
|
||||
bool overRecursed;
|
||||
bool outOfMemory;
|
||||
|
||||
ParseTask(ParseTaskKind kind, JSContext* cx,
|
||||
JS::OffThreadCompileCallback callback, void* callbackData);
|
||||
virtual ~ParseTask();
|
||||
|
||||
bool init(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
|
||||
JSObject* global);
|
||||
|
||||
void activate(JSRuntime* rt);
|
||||
virtual void parse(JSContext* cx) = 0;
|
||||
bool instantiateStencils(JSContext* cx);
|
||||
|
||||
bool runtimeMatches(JSRuntime* rt) { return runtime == rt; }
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
void runTask();
|
||||
ThreadType threadType() override { return ThreadType::THREAD_TYPE_PARSE; }
|
||||
};
|
||||
|
||||
struct ScriptDecodeTask : public ParseTask {
|
||||
const JS::TranscodeRange range;
|
||||
|
||||
ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range,
|
||||
JS::OffThreadCompileCallback callback, void* callbackData);
|
||||
void parse(JSContext* cx) override;
|
||||
};
|
||||
|
||||
struct MultiScriptsDecodeTask : public ParseTask {
|
||||
JS::TranscodeSources* sources;
|
||||
|
||||
MultiScriptsDecodeTask(JSContext* cx, JS::TranscodeSources& sources,
|
||||
JS::OffThreadCompileCallback callback,
|
||||
void* callbackData);
|
||||
void parse(JSContext* cx) override;
|
||||
};
|
||||
|
||||
// It is not desirable to eagerly compress: if lazy functions that are tied to
|
||||
// the ScriptSource were to be executed relatively soon after parsing, they
|
||||
// would need to block on decompression, which hurts responsiveness.
|
||||
//
|
||||
// To this end, compression tasks are heap allocated and enqueued in a pending
|
||||
// list by ScriptSource::setSourceCopy. When a major GC occurs, we schedule
|
||||
// pending compression tasks and move the ones that are ready to be compressed
|
||||
// to the worklist. Currently, a compression task is considered ready 2 major
|
||||
// GCs after being enqueued. Completed tasks are handled during the sweeping
|
||||
// phase by AttachCompressedSourcesTask, which runs in parallel with other GC
|
||||
// sweeping tasks.
|
||||
class SourceCompressionTask : public HelperThreadTask {
|
||||
friend class HelperThread;
|
||||
friend class ScriptSource;
|
||||
|
||||
// The runtime that the ScriptSource is associated with, in the sense that
|
||||
// it uses the runtime's immutable string cache.
|
||||
JSRuntime* runtime_;
|
||||
|
||||
// The major GC number of the runtime when the task was enqueued.
|
||||
uint64_t majorGCNumber_;
|
||||
|
||||
// The source to be compressed.
|
||||
ScriptSourceHolder sourceHolder_;
|
||||
|
||||
// The resultant compressed string. If the compressed string is larger
|
||||
// than the original, or we OOM'd during compression, or nothing else
|
||||
// except the task is holding the ScriptSource alive when scheduled to
|
||||
// compress, this will remain None upon completion.
|
||||
mozilla::Maybe<SharedImmutableString> resultString_;
|
||||
|
||||
public:
|
||||
// The majorGCNumber is used for scheduling tasks.
|
||||
SourceCompressionTask(JSRuntime* rt, ScriptSource* source)
|
||||
: runtime_(rt),
|
||||
majorGCNumber_(rt->gc.majorGCCount()),
|
||||
sourceHolder_(source) {}
|
||||
virtual ~SourceCompressionTask() = default;
|
||||
|
||||
bool runtimeMatches(JSRuntime* runtime) const { return runtime == runtime_; }
|
||||
bool shouldStart() const {
|
||||
// We wait 2 major GCs to start compressing, in order to avoid
|
||||
// immediate compression.
|
||||
return runtime_->gc.majorGCCount() > majorGCNumber_ + 1;
|
||||
}
|
||||
|
||||
bool shouldCancel() const {
|
||||
// If the refcount is exactly 1, then nothing else is holding on to the
|
||||
// ScriptSource, so no reason to compress it and we should cancel the task.
|
||||
return sourceHolder_.get()->refs == 1;
|
||||
}
|
||||
|
||||
void runTask();
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
void complete();
|
||||
|
||||
ThreadType threadType() override { return ThreadType::THREAD_TYPE_COMPRESS; }
|
||||
|
||||
private:
|
||||
struct PerformTaskWork;
|
||||
friend struct PerformTaskWork;
|
||||
|
||||
// The work algorithm, aware whether it's compressing one-byte UTF-8 source
|
||||
// text or UTF-16, for CharT either Utf8Unit or char16_t. Invoked by
|
||||
// work() after doing a type-test of the ScriptSource*.
|
||||
template <typename CharT>
|
||||
void workEncodingSpecific();
|
||||
};
|
||||
|
||||
// A PromiseHelperTask is an OffThreadPromiseTask that executes a single job on
|
||||
// a helper thread. Call js::StartOffThreadPromiseHelperTask to submit a
|
||||
// PromiseHelperTask for execution.
|
||||
//
|
||||
// Concrete subclasses must implement execute and OffThreadPromiseTask::resolve.
|
||||
// The helper thread will call execute() to do the main work. Then, the thread
|
||||
// of the JSContext used to create the PromiseHelperTask will call resolve() to
|
||||
// resolve promise according to those results.
|
||||
struct PromiseHelperTask : OffThreadPromiseTask, public HelperThreadTask {
|
||||
PromiseHelperTask(JSContext* cx, Handle<PromiseObject*> promise)
|
||||
: OffThreadPromiseTask(cx, promise) {}
|
||||
|
||||
// To be called on a helper thread and implemented by the derived class.
|
||||
virtual void execute() = 0;
|
||||
|
||||
// May be called in the absence of helper threads or off-thread promise
|
||||
// support to synchronously execute and resolve a PromiseTask.
|
||||
//
|
||||
// Warning: After this function returns, 'this' can be deleted at any time, so
|
||||
// the caller must immediately return from the stream callback.
|
||||
void executeAndResolveAndDestroy(JSContext* cx);
|
||||
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
ThreadType threadType() override { return THREAD_TYPE_PROMISE_TASK; }
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* vm_HelperThreadState_h */
|
|
@ -26,8 +26,6 @@
|
|||
#include "threading/CpuCount.h"
|
||||
#include "util/NativeStack.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/MutexIDs.h"
|
||||
#include "vm/SharedImmutableStringsCache.h"
|
||||
#include "vm/Time.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
@ -55,7 +53,6 @@ using JS::ReadOnlyCompileOptions;
|
|||
|
||||
namespace js {
|
||||
|
||||
Mutex gHelperThreadLock(mutexid::GlobalHelperThreadState);
|
||||
GlobalHelperThreadState* gHelperThreadState = nullptr;
|
||||
|
||||
} // namespace js
|
||||
|
@ -150,16 +147,6 @@ bool GlobalHelperThreadState::submitTask(wasm::CompileTask* task,
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t js::RemovePendingWasmCompileTasks(
|
||||
const wasm::CompileTaskState& taskState, wasm::CompileMode mode,
|
||||
const AutoLockHelperThreadState& lock) {
|
||||
wasm::CompileTaskPtrFifo& worklist =
|
||||
HelperThreadState().wasmWorklist(lock, mode);
|
||||
return worklist.eraseIf([&taskState](wasm::CompileTask* task) {
|
||||
return &task->state == &taskState;
|
||||
});
|
||||
}
|
||||
|
||||
void js::StartOffThreadWasmTier2Generator(wasm::UniqueTier2GeneratorTask task) {
|
||||
Unused << HelperThreadState().submitTask(std::move(task));
|
||||
}
|
||||
|
@ -1250,7 +1237,8 @@ GlobalHelperThreadState::GlobalHelperThreadState()
|
|||
totalCountRunningTasks(0),
|
||||
registerThread(nullptr),
|
||||
unregisterThread(nullptr),
|
||||
wasmTier2GeneratorsFinished_(0) {
|
||||
wasmTier2GeneratorsFinished_(0),
|
||||
helperLock(mutexid::GlobalHelperThreadState) {
|
||||
cpuCount = ClampDefaultCPUCount(GetCPUCount());
|
||||
threadCount = ThreadCountForCPUCount(cpuCount);
|
||||
gcParallelThreadCount = threadCount;
|
||||
|
@ -1339,7 +1327,7 @@ void GlobalHelperThreadState::destroyHelperContexts(
|
|||
|
||||
#ifdef DEBUG
|
||||
bool GlobalHelperThreadState::isLockedByCurrentThread() const {
|
||||
return gHelperThreadLock.ownedByCurrentThread();
|
||||
return helperLock.ownedByCurrentThread();
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
|
@ -1369,12 +1357,6 @@ bool GlobalHelperThreadState::hasActiveThreads(
|
|||
return !helperTasks(lock).empty();
|
||||
}
|
||||
|
||||
void js::WaitForAllHelperThreads() { HelperThreadState().waitForAllThreads(); }
|
||||
|
||||
void js::WaitForAllHelperThreads(AutoLockHelperThreadState& lock) {
|
||||
HelperThreadState().waitForAllThreadsLocked(lock);
|
||||
}
|
||||
|
||||
void GlobalHelperThreadState::waitForAllThreads() {
|
||||
AutoLockHelperThreadState lock;
|
||||
waitForAllThreadsLocked(lock);
|
||||
|
|
|
@ -5,65 +5,496 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* API for managing off-thread work.
|
||||
* Definitions for managing off-thread work using a process wide list
|
||||
* of worklist items and pool of threads. Worklist items are engine internal,
|
||||
* and are distinct from e.g. web workers.
|
||||
*/
|
||||
|
||||
#ifndef vm_HelperThreads_h
|
||||
#define vm_HelperThreads_h
|
||||
|
||||
#include "NamespaceImports.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||
|
||||
#include "js/OffThreadScriptCompilation.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "threading/LockGuard.h"
|
||||
#include "threading/Mutex.h"
|
||||
#include "wasm/WasmConstants.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "ds/Fifo.h"
|
||||
#include "frontend/CompilationInfo.h" // frontend::CompilationInfo
|
||||
#include "jit/JitContext.h"
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/shadow/Zone.h" // JS::shadow::Zone::GCState
|
||||
#include "js/SourceText.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "threading/ConditionVariable.h"
|
||||
#include "threading/Thread.h"
|
||||
#include "vm/HelperThreadTask.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/MutexIDs.h"
|
||||
#include "vm/OffThreadPromiseRuntimeState.h" // js::OffThreadPromiseTask
|
||||
#include "vm/PromiseObject.h" // js::PromiseObject
|
||||
|
||||
namespace JS {
|
||||
class OffThreadToken {};
|
||||
class ReadOnlyCompileOptions;
|
||||
class Zone;
|
||||
} // namespace JS
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoLockHelperThreadState;
|
||||
class AutoUnlockHelperThreadState;
|
||||
class CompileError;
|
||||
struct ParseTask;
|
||||
struct PromiseHelperTask;
|
||||
class SourceCompressionTask;
|
||||
|
||||
namespace jit {
|
||||
class IonCompileTask;
|
||||
class IonFreeTask;
|
||||
} // namespace jit
|
||||
|
||||
namespace wasm {
|
||||
struct CompileTask;
|
||||
struct CompileTaskState;
|
||||
struct Tier2GeneratorTask;
|
||||
using UniqueTier2GeneratorTask = UniquePtr<Tier2GeneratorTask>;
|
||||
} // namespace wasm
|
||||
|
||||
/*
|
||||
* Lock protecting all mutable shared state accessed by helper threads, and used
|
||||
* by all condition variables.
|
||||
*/
|
||||
extern Mutex gHelperThreadLock;
|
||||
enum class ParseTaskKind { Script, Module, ScriptDecode, MultiScriptsDecode };
|
||||
enum class StartEncoding { No, Yes };
|
||||
|
||||
class MOZ_RAII AutoLockHelperThreadState : public LockGuard<Mutex> {
|
||||
using Base = LockGuard<Mutex>;
|
||||
namespace wasm {
|
||||
|
||||
public:
|
||||
explicit AutoLockHelperThreadState() : Base(gHelperThreadLock) {}
|
||||
struct CompileTask;
|
||||
typedef Fifo<CompileTask*, 0, SystemAllocPolicy> CompileTaskPtrFifo;
|
||||
|
||||
struct Tier2GeneratorTask : public HelperThreadTask {
|
||||
virtual ~Tier2GeneratorTask() = default;
|
||||
virtual void cancel() = 0;
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoUnlockHelperThreadState : public UnlockGuard<Mutex> {
|
||||
using Base = UnlockGuard<Mutex>;
|
||||
using UniqueTier2GeneratorTask = UniquePtr<Tier2GeneratorTask>;
|
||||
typedef Vector<Tier2GeneratorTask*, 0, SystemAllocPolicy>
|
||||
Tier2GeneratorTaskPtrVector;
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
// Per-process state for off thread work items.
|
||||
class GlobalHelperThreadState {
|
||||
friend class AutoLockHelperThreadState;
|
||||
friend class AutoUnlockHelperThreadState;
|
||||
|
||||
public:
|
||||
explicit AutoUnlockHelperThreadState(AutoLockHelperThreadState& locked)
|
||||
: Base(locked) {}
|
||||
// A single tier-2 ModuleGenerator job spawns many compilation jobs, and we
|
||||
// do not want to allow more than one such ModuleGenerator to run at a time.
|
||||
static const size_t MaxTier2GeneratorTasks = 1;
|
||||
|
||||
// Number of CPUs to treat this machine as having when creating threads.
|
||||
// May be accessed without locking.
|
||||
size_t cpuCount;
|
||||
|
||||
// Number of threads to create. May be accessed without locking.
|
||||
size_t threadCount;
|
||||
|
||||
typedef Vector<jit::IonCompileTask*, 0, SystemAllocPolicy>
|
||||
IonCompileTaskVector;
|
||||
using IonFreeTaskVector =
|
||||
Vector<js::UniquePtr<jit::IonFreeTask>, 0, SystemAllocPolicy>;
|
||||
typedef Vector<UniquePtr<ParseTask>, 0, SystemAllocPolicy> ParseTaskVector;
|
||||
using ParseTaskList = mozilla::LinkedList<ParseTask>;
|
||||
typedef Vector<UniquePtr<SourceCompressionTask>, 0, SystemAllocPolicy>
|
||||
SourceCompressionTaskVector;
|
||||
using GCParallelTaskList = mozilla::LinkedList<GCParallelTask>;
|
||||
typedef Vector<PromiseHelperTask*, 0, SystemAllocPolicy>
|
||||
PromiseHelperTaskVector;
|
||||
typedef Vector<JSContext*, 0, SystemAllocPolicy> ContextVector;
|
||||
using HelperThreadVector =
|
||||
Vector<UniquePtr<HelperThread>, 0, SystemAllocPolicy>;
|
||||
|
||||
// Count of running task by each threadType.
|
||||
mozilla::EnumeratedArray<ThreadType, ThreadType::THREAD_TYPE_MAX, size_t>
|
||||
runningTaskCount;
|
||||
size_t totalCountRunningTasks;
|
||||
|
||||
WriteOnceData<JS::RegisterThreadCallback> registerThread;
|
||||
WriteOnceData<JS::UnregisterThreadCallback> unregisterThread;
|
||||
|
||||
private:
|
||||
// The lists below are all protected by |lock|.
|
||||
|
||||
// List of available helper threads.
|
||||
HelperThreadVector threads_;
|
||||
|
||||
// Ion compilation worklist and finished jobs.
|
||||
IonCompileTaskVector ionWorklist_, ionFinishedList_;
|
||||
IonFreeTaskVector ionFreeList_;
|
||||
|
||||
// wasm worklists.
|
||||
wasm::CompileTaskPtrFifo wasmWorklist_tier1_;
|
||||
wasm::CompileTaskPtrFifo wasmWorklist_tier2_;
|
||||
wasm::Tier2GeneratorTaskPtrVector wasmTier2GeneratorWorklist_;
|
||||
|
||||
// Count of finished Tier2Generator tasks.
|
||||
uint32_t wasmTier2GeneratorsFinished_;
|
||||
|
||||
// Async tasks that, upon completion, are dispatched back to the JSContext's
|
||||
// owner thread via embedding callbacks instead of a finished list.
|
||||
PromiseHelperTaskVector promiseHelperTasks_;
|
||||
|
||||
// Script parsing/emitting worklist and finished jobs.
|
||||
ParseTaskVector parseWorklist_;
|
||||
ParseTaskList parseFinishedList_;
|
||||
|
||||
// Parse tasks waiting for an atoms-zone GC to complete.
|
||||
ParseTaskVector parseWaitingOnGC_;
|
||||
|
||||
// Source compression worklist of tasks that we do not yet know can start.
|
||||
SourceCompressionTaskVector compressionPendingList_;
|
||||
|
||||
// Source compression worklist of tasks that can start.
|
||||
SourceCompressionTaskVector compressionWorklist_;
|
||||
|
||||
// Finished source compression tasks.
|
||||
SourceCompressionTaskVector compressionFinishedList_;
|
||||
|
||||
// GC tasks needing to be done in parallel.
|
||||
GCParallelTaskList gcParallelWorklist_;
|
||||
size_t gcParallelThreadCount;
|
||||
|
||||
// Global list of JSContext for GlobalHelperThreadState to use.
|
||||
ContextVector helperContexts_;
|
||||
|
||||
using HelperThreadTaskVector =
|
||||
Vector<HelperThreadTask*, 0, SystemAllocPolicy>;
|
||||
// Vector of running HelperThreadTask.
|
||||
// This is used to get the HelperThreadTask that are currently running.
|
||||
HelperThreadTaskVector helperTasks_;
|
||||
|
||||
ParseTask* removeFinishedParseTask(ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
|
||||
public:
|
||||
void addSizeOfIncludingThis(JS::GlobalStats* stats,
|
||||
AutoLockHelperThreadState& lock) const;
|
||||
|
||||
size_t maxIonCompilationThreads() const;
|
||||
size_t maxWasmCompilationThreads() const;
|
||||
size_t maxWasmTier2GeneratorThreads() const;
|
||||
size_t maxPromiseHelperThreads() const;
|
||||
size_t maxParseThreads() const;
|
||||
size_t maxCompressionThreads() const;
|
||||
size_t maxGCParallelThreads(const AutoLockHelperThreadState& lock) const;
|
||||
|
||||
GlobalHelperThreadState();
|
||||
|
||||
HelperThreadVector& threads(const AutoLockHelperThreadState& lock) {
|
||||
return threads_;
|
||||
}
|
||||
const HelperThreadVector& threads(
|
||||
const AutoLockHelperThreadState& lock) const {
|
||||
return threads_;
|
||||
}
|
||||
|
||||
bool ensureInitialized();
|
||||
bool ensureThreadCount(size_t count);
|
||||
void finish();
|
||||
void finishThreads();
|
||||
|
||||
MOZ_MUST_USE bool ensureContextList(size_t count);
|
||||
JSContext* getFirstUnusedContext(AutoLockHelperThreadState& locked);
|
||||
void destroyHelperContexts(AutoLockHelperThreadState& lock);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool isLockedByCurrentThread() const;
|
||||
#endif
|
||||
|
||||
enum CondVar {
|
||||
// For notifying threads waiting for work that they may be able to make
|
||||
// progress, ie, a work item has been completed by a helper thread and
|
||||
// the thread that created the work item can now consume it.
|
||||
CONSUMER,
|
||||
|
||||
// For notifying helper threads doing the work that they may be able to
|
||||
// make progress, ie, a work item has been enqueued and an idle helper
|
||||
// thread may pick up up the work item and perform it.
|
||||
PRODUCER,
|
||||
};
|
||||
|
||||
void wait(AutoLockHelperThreadState& locked, CondVar which,
|
||||
mozilla::TimeDuration timeout = mozilla::TimeDuration::Forever());
|
||||
void notifyAll(CondVar which, const AutoLockHelperThreadState&);
|
||||
|
||||
private:
|
||||
void notifyOne(CondVar which, const AutoLockHelperThreadState&);
|
||||
|
||||
public:
|
||||
// Helper method for removing items from the vectors below while iterating
|
||||
// over them.
|
||||
template <typename T>
|
||||
void remove(T& vector, size_t* index) {
|
||||
// Self-moving is undefined behavior.
|
||||
if (*index != vector.length() - 1) {
|
||||
vector[*index] = std::move(vector.back());
|
||||
}
|
||||
(*index)--;
|
||||
vector.popBack();
|
||||
}
|
||||
|
||||
IonCompileTaskVector& ionWorklist(const AutoLockHelperThreadState&) {
|
||||
return ionWorklist_;
|
||||
}
|
||||
IonCompileTaskVector& ionFinishedList(const AutoLockHelperThreadState&) {
|
||||
return ionFinishedList_;
|
||||
}
|
||||
IonFreeTaskVector& ionFreeList(const AutoLockHelperThreadState&) {
|
||||
return ionFreeList_;
|
||||
}
|
||||
|
||||
wasm::CompileTaskPtrFifo& wasmWorklist(const AutoLockHelperThreadState&,
|
||||
wasm::CompileMode m) {
|
||||
switch (m) {
|
||||
case wasm::CompileMode::Once:
|
||||
case wasm::CompileMode::Tier1:
|
||||
return wasmWorklist_tier1_;
|
||||
case wasm::CompileMode::Tier2:
|
||||
return wasmWorklist_tier2_;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
wasm::Tier2GeneratorTaskPtrVector& wasmTier2GeneratorWorklist(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return wasmTier2GeneratorWorklist_;
|
||||
}
|
||||
|
||||
void incWasmTier2GeneratorsFinished(const AutoLockHelperThreadState&) {
|
||||
wasmTier2GeneratorsFinished_++;
|
||||
}
|
||||
|
||||
uint32_t wasmTier2GeneratorsFinished(const AutoLockHelperThreadState&) const {
|
||||
return wasmTier2GeneratorsFinished_;
|
||||
}
|
||||
|
||||
PromiseHelperTaskVector& promiseHelperTasks(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return promiseHelperTasks_;
|
||||
}
|
||||
|
||||
ParseTaskVector& parseWorklist(const AutoLockHelperThreadState&) {
|
||||
return parseWorklist_;
|
||||
}
|
||||
ParseTaskList& parseFinishedList(const AutoLockHelperThreadState&) {
|
||||
return parseFinishedList_;
|
||||
}
|
||||
ParseTaskVector& parseWaitingOnGC(const AutoLockHelperThreadState&) {
|
||||
return parseWaitingOnGC_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionPendingList(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionPendingList_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionWorklist(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionWorklist_;
|
||||
}
|
||||
|
||||
SourceCompressionTaskVector& compressionFinishedList(
|
||||
const AutoLockHelperThreadState&) {
|
||||
return compressionFinishedList_;
|
||||
}
|
||||
|
||||
GCParallelTaskList& gcParallelWorklist(const AutoLockHelperThreadState&) {
|
||||
return gcParallelWorklist_;
|
||||
}
|
||||
|
||||
void setGCParallelThreadCount(size_t count,
|
||||
const AutoLockHelperThreadState&) {
|
||||
MOZ_ASSERT(count >= 1);
|
||||
MOZ_ASSERT(count <= threadCount);
|
||||
gcParallelThreadCount = count;
|
||||
}
|
||||
|
||||
HelperThreadTaskVector& helperTasks(const AutoLockHelperThreadState&) {
|
||||
return helperTasks_;
|
||||
}
|
||||
|
||||
HelperThreadTask* maybeGetWasmCompile(const AutoLockHelperThreadState& lock,
|
||||
wasm::CompileMode mode);
|
||||
|
||||
HelperThreadTask* maybeGetWasmTier1CompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetWasmTier2CompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetWasmTier2GeneratorTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetPromiseHelperTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetIonCompileTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetIonFreeTask(const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetParseTask(const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetCompressionTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
HelperThreadTask* maybeGetGCParallelTask(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
|
||||
enum class ScheduleCompressionTask { GC, API };
|
||||
|
||||
// Used by a major GC to signal processing enqueued compression tasks.
|
||||
void startHandlingCompressionTasks(const AutoLockHelperThreadState&,
|
||||
ScheduleCompressionTask schedule);
|
||||
|
||||
jit::IonCompileTask* highestPriorityPendingIonCompile(
|
||||
const AutoLockHelperThreadState& lock);
|
||||
|
||||
private:
|
||||
void scheduleCompressionTasks(const AutoLockHelperThreadState&,
|
||||
ScheduleCompressionTask schedule);
|
||||
|
||||
UniquePtr<ParseTask> finishParseTaskCommon(JSContext* cx, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
|
||||
JSScript* finishSingleParseTask(
|
||||
JSContext* cx, ParseTaskKind kind, JS::OffThreadToken* token,
|
||||
StartEncoding startEncoding = StartEncoding::No);
|
||||
bool generateLCovSources(JSContext* cx, ParseTask* parseTask);
|
||||
bool finishMultiParseTask(JSContext* cx, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token,
|
||||
MutableHandle<ScriptVector> scripts);
|
||||
|
||||
void mergeParseTaskRealm(JSContext* cx, ParseTask* parseTask,
|
||||
JS::Realm* dest);
|
||||
|
||||
public:
|
||||
void cancelParseTask(JSRuntime* rt, ParseTaskKind kind,
|
||||
JS::OffThreadToken* token);
|
||||
void destroyParseTask(JSRuntime* rt, ParseTask* parseTask);
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
JSScript* finishScriptParseTask(
|
||||
JSContext* cx, JS::OffThreadToken* token,
|
||||
StartEncoding startEncoding = StartEncoding::No);
|
||||
JSScript* finishScriptDecodeTask(JSContext* cx, JS::OffThreadToken* token);
|
||||
bool finishMultiScriptsDecodeTask(JSContext* cx, JS::OffThreadToken* token,
|
||||
MutableHandle<ScriptVector> scripts);
|
||||
JSObject* finishModuleParseTask(JSContext* cx, JS::OffThreadToken* token);
|
||||
|
||||
bool hasActiveThreads(const AutoLockHelperThreadState&);
|
||||
void waitForAllThreads();
|
||||
void waitForAllThreadsLocked(AutoLockHelperThreadState&);
|
||||
|
||||
bool checkTaskThreadLimit(ThreadType threadType, size_t maxThreads,
|
||||
bool isMaster,
|
||||
const AutoLockHelperThreadState& lock) const;
|
||||
bool checkTaskThreadLimit(ThreadType threadType, size_t maxThreads,
|
||||
const AutoLockHelperThreadState& lock) const {
|
||||
return checkTaskThreadLimit(threadType, maxThreads, /* isMaster */ false,
|
||||
lock);
|
||||
}
|
||||
|
||||
void triggerFreeUnusedMemory();
|
||||
|
||||
private:
|
||||
/*
|
||||
* Lock protecting all mutable shared state accessed by helper threads, and
|
||||
* used by all condition variables.
|
||||
*/
|
||||
js::Mutex helperLock;
|
||||
|
||||
/* Condvars for threads waiting/notifying each other. */
|
||||
js::ConditionVariable consumerWakeup;
|
||||
js::ConditionVariable producerWakeup;
|
||||
|
||||
js::ConditionVariable& whichWakeup(CondVar which) {
|
||||
switch (which) {
|
||||
case CONSUMER:
|
||||
return consumerWakeup;
|
||||
case PRODUCER:
|
||||
return producerWakeup;
|
||||
default:
|
||||
MOZ_CRASH("Invalid CondVar in |whichWakeup|");
|
||||
}
|
||||
}
|
||||
|
||||
void dispatch(const AutoLockHelperThreadState& locked);
|
||||
|
||||
public:
|
||||
bool submitTask(wasm::UniqueTier2GeneratorTask task);
|
||||
bool submitTask(wasm::CompileTask* task, wasm::CompileMode mode);
|
||||
bool submitTask(UniquePtr<jit::IonFreeTask> task,
|
||||
const AutoLockHelperThreadState& lock);
|
||||
bool submitTask(jit::IonCompileTask* task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(UniquePtr<SourceCompressionTask> task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(JSRuntime* rt, UniquePtr<ParseTask> task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
bool submitTask(PromiseHelperTask* task);
|
||||
bool submitTask(GCParallelTask* task,
|
||||
const AutoLockHelperThreadState& locked);
|
||||
void runTaskLocked(HelperThreadTask* task, AutoLockHelperThreadState& lock);
|
||||
};
|
||||
|
||||
static inline GlobalHelperThreadState& HelperThreadState() {
|
||||
extern GlobalHelperThreadState* gHelperThreadState;
|
||||
|
||||
MOZ_ASSERT(gHelperThreadState);
|
||||
return *gHelperThreadState;
|
||||
}
|
||||
|
||||
/* Individual helper thread, one allocated per core. */
|
||||
class HelperThread {
|
||||
Thread thread;
|
||||
|
||||
/*
|
||||
* The profiling thread for this helper thread, which can be used to push
|
||||
* and pop label frames.
|
||||
* This field being non-null indicates that this thread has been registered
|
||||
* and needs to be unregistered at shutdown.
|
||||
*/
|
||||
ProfilingStack* profilingStack = nullptr;
|
||||
|
||||
/*
|
||||
* Indicate to a thread that it should terminate itself. This is only read
|
||||
* or written with the helper thread state lock held.
|
||||
*/
|
||||
bool terminate = false;
|
||||
|
||||
public:
|
||||
HelperThread();
|
||||
MOZ_MUST_USE bool init();
|
||||
|
||||
ThreadId threadId() { return thread.get_id(); }
|
||||
|
||||
void setTerminate(const AutoLockHelperThreadState& lock);
|
||||
void join();
|
||||
|
||||
static void ThreadMain(void* arg);
|
||||
void threadLoop();
|
||||
|
||||
void ensureRegisteredWithProfiler();
|
||||
void unregisterWithProfilerIfNeeded();
|
||||
|
||||
private:
|
||||
struct AutoProfilerLabel {
|
||||
AutoProfilerLabel(HelperThread* helperThread, const char* label,
|
||||
JS::ProfilingCategoryPair categoryPair);
|
||||
~AutoProfilerLabel();
|
||||
|
||||
private:
|
||||
ProfilingStack* profilingStack;
|
||||
};
|
||||
|
||||
using Selector = HelperThreadTask* (
|
||||
GlobalHelperThreadState::*)(const AutoLockHelperThreadState&);
|
||||
static const Selector selectors[];
|
||||
|
||||
HelperThreadTask* findHighestPriorityTask(
|
||||
const AutoLockHelperThreadState& locked);
|
||||
};
|
||||
|
||||
/* Methods for interacting with helper threads. */
|
||||
|
||||
// Create data structures used by helper threads.
|
||||
bool CreateHelperThreadsState();
|
||||
|
||||
|
@ -80,13 +511,6 @@ bool SetFakeCPUCount(size_t count);
|
|||
// Enqueues a wasm compilation task.
|
||||
bool StartOffThreadWasmCompile(wasm::CompileTask* task, wasm::CompileMode mode);
|
||||
|
||||
// Remove any pending wasm compilation tasks queued with
|
||||
// StartOffThreadWasmCompile that match the arguments. Return the number
|
||||
// removed.
|
||||
size_t RemovePendingWasmCompileTasks(const wasm::CompileTaskState& taskState,
|
||||
wasm::CompileMode mode,
|
||||
const AutoLockHelperThreadState& lock);
|
||||
|
||||
// Enqueues a wasm compilation task.
|
||||
void StartOffThreadWasmTier2Generator(wasm::UniqueTier2GeneratorTask task);
|
||||
|
||||
|
@ -139,7 +563,7 @@ struct CompilationsUsingNursery {
|
|||
};
|
||||
|
||||
using CompilationSelector =
|
||||
mozilla::Variant<JSScript*, JS::Realm*, JS::Zone*, ZonesInState, JSRuntime*,
|
||||
mozilla::Variant<JSScript*, JS::Realm*, Zone*, ZonesInState, JSRuntime*,
|
||||
CompilationsUsingNursery>;
|
||||
|
||||
/*
|
||||
|
@ -155,7 +579,7 @@ inline void CancelOffThreadIonCompile(JS::Realm* realm) {
|
|||
CancelOffThreadIonCompile(CompilationSelector(realm));
|
||||
}
|
||||
|
||||
inline void CancelOffThreadIonCompile(JS::Zone* zone) {
|
||||
inline void CancelOffThreadIonCompile(Zone* zone) {
|
||||
CancelOffThreadIonCompile(CompilationSelector(zone));
|
||||
}
|
||||
|
||||
|
@ -229,9 +653,6 @@ bool StartOffThreadDecodeMultiScripts(JSContext* cx,
|
|||
*/
|
||||
void EnqueuePendingParseTasksAfterGC(JSRuntime* rt);
|
||||
|
||||
void WaitForAllHelperThreads();
|
||||
void WaitForAllHelperThreads(AutoLockHelperThreadState& lock);
|
||||
|
||||
struct AutoEnqueuePendingParseTasksAfterGC {
|
||||
const gc::GCRuntime& gc_;
|
||||
explicit AutoEnqueuePendingParseTasksAfterGC(const gc::GCRuntime& gc)
|
||||
|
@ -253,10 +674,218 @@ void AttachFinishedCompressions(JSRuntime* runtime,
|
|||
// Run all pending source compression tasks synchronously, for testing purposes
|
||||
void RunPendingSourceCompressions(JSRuntime* runtime);
|
||||
|
||||
class MOZ_RAII AutoLockHelperThreadState : public LockGuard<Mutex> {
|
||||
using Base = LockGuard<Mutex>;
|
||||
|
||||
public:
|
||||
explicit AutoLockHelperThreadState() : Base(HelperThreadState().helperLock) {}
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoUnlockHelperThreadState : public UnlockGuard<Mutex> {
|
||||
using Base = UnlockGuard<Mutex>;
|
||||
|
||||
public:
|
||||
explicit AutoUnlockHelperThreadState(AutoLockHelperThreadState& locked)
|
||||
: Base(locked) {}
|
||||
};
|
||||
|
||||
struct MOZ_RAII AutoSetHelperThreadContext {
|
||||
JSContext* cx;
|
||||
explicit AutoSetHelperThreadContext();
|
||||
~AutoSetHelperThreadContext() {
|
||||
AutoLockHelperThreadState lock;
|
||||
cx->tempLifoAlloc().releaseAll();
|
||||
if (cx->shouldFreeUnusedMemory()) {
|
||||
cx->tempLifoAlloc().freeAll();
|
||||
cx->setFreeUnusedMemory(false);
|
||||
}
|
||||
cx->clearHelperThread(lock);
|
||||
cx = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct MOZ_RAII AutoSetContextRuntime {
|
||||
explicit AutoSetContextRuntime(JSRuntime* rt) {
|
||||
TlsContext.get()->setRuntime(rt);
|
||||
}
|
||||
~AutoSetContextRuntime() { TlsContext.get()->setRuntime(nullptr); }
|
||||
};
|
||||
|
||||
struct ParseTask : public mozilla::LinkedListElement<ParseTask>,
|
||||
public JS::OffThreadToken,
|
||||
public HelperThreadTask {
|
||||
ParseTaskKind kind;
|
||||
JS::OwningCompileOptions options;
|
||||
|
||||
// HelperThreads are shared between all runtimes in the process so explicitly
|
||||
// track which one we are associated with.
|
||||
JSRuntime* runtime = nullptr;
|
||||
|
||||
// The global object to use while parsing.
|
||||
JSObject* parseGlobal;
|
||||
|
||||
// Callback invoked off thread when the parse finishes.
|
||||
JS::OffThreadCompileCallback callback;
|
||||
void* callbackData;
|
||||
|
||||
// Holds the final scripts between the invocation of the callback and the
|
||||
// point where FinishOffThreadScript is called, which will destroy the
|
||||
// ParseTask.
|
||||
GCVector<JSScript*, 1, SystemAllocPolicy> scripts;
|
||||
|
||||
// Holds the ScriptSourceObjects generated for the script compilation.
|
||||
GCVector<ScriptSourceObject*, 1, SystemAllocPolicy> sourceObjects;
|
||||
|
||||
// Holds the CompilationInfo generated for the script compilation.
|
||||
UniquePtr<frontend::CompilationInfo> compilationInfo_;
|
||||
|
||||
// Any errors or warnings produced during compilation. These are reported
|
||||
// when finishing the script.
|
||||
Vector<UniquePtr<CompileError>, 0, SystemAllocPolicy> errors;
|
||||
bool overRecursed;
|
||||
bool outOfMemory;
|
||||
|
||||
ParseTask(ParseTaskKind kind, JSContext* cx,
|
||||
JS::OffThreadCompileCallback callback, void* callbackData);
|
||||
virtual ~ParseTask();
|
||||
|
||||
bool init(JSContext* cx, const JS::ReadOnlyCompileOptions& options,
|
||||
JSObject* global);
|
||||
|
||||
void activate(JSRuntime* rt);
|
||||
virtual void parse(JSContext* cx) = 0;
|
||||
bool instantiateStencils(JSContext* cx);
|
||||
|
||||
bool runtimeMatches(JSRuntime* rt) { return runtime == rt; }
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
void runTask();
|
||||
ThreadType threadType() override { return ThreadType::THREAD_TYPE_PARSE; }
|
||||
};
|
||||
|
||||
struct ScriptDecodeTask : public ParseTask {
|
||||
const JS::TranscodeRange range;
|
||||
|
||||
ScriptDecodeTask(JSContext* cx, const JS::TranscodeRange& range,
|
||||
JS::OffThreadCompileCallback callback, void* callbackData);
|
||||
void parse(JSContext* cx) override;
|
||||
};
|
||||
|
||||
struct MultiScriptsDecodeTask : public ParseTask {
|
||||
JS::TranscodeSources* sources;
|
||||
|
||||
MultiScriptsDecodeTask(JSContext* cx, JS::TranscodeSources& sources,
|
||||
JS::OffThreadCompileCallback callback,
|
||||
void* callbackData);
|
||||
void parse(JSContext* cx) override;
|
||||
};
|
||||
|
||||
// Return whether, if a new parse task was started, it would need to wait for
|
||||
// an in-progress GC to complete before starting.
|
||||
extern bool OffThreadParsingMustWaitForGC(JSRuntime* rt);
|
||||
|
||||
} // namespace js
|
||||
// It is not desirable to eagerly compress: if lazy functions that are tied to
|
||||
// the ScriptSource were to be executed relatively soon after parsing, they
|
||||
// would need to block on decompression, which hurts responsiveness.
|
||||
//
|
||||
// To this end, compression tasks are heap allocated and enqueued in a pending
|
||||
// list by ScriptSource::setSourceCopy. When a major GC occurs, we schedule
|
||||
// pending compression tasks and move the ones that are ready to be compressed
|
||||
// to the worklist. Currently, a compression task is considered ready 2 major
|
||||
// GCs after being enqueued. Completed tasks are handled during the sweeping
|
||||
// phase by AttachCompressedSourcesTask, which runs in parallel with other GC
|
||||
// sweeping tasks.
|
||||
class SourceCompressionTask : public HelperThreadTask {
|
||||
friend class HelperThread;
|
||||
friend class ScriptSource;
|
||||
|
||||
// The runtime that the ScriptSource is associated with, in the sense that
|
||||
// it uses the runtime's immutable string cache.
|
||||
JSRuntime* runtime_;
|
||||
|
||||
// The major GC number of the runtime when the task was enqueued.
|
||||
uint64_t majorGCNumber_;
|
||||
|
||||
// The source to be compressed.
|
||||
ScriptSourceHolder sourceHolder_;
|
||||
|
||||
// The resultant compressed string. If the compressed string is larger
|
||||
// than the original, or we OOM'd during compression, or nothing else
|
||||
// except the task is holding the ScriptSource alive when scheduled to
|
||||
// compress, this will remain None upon completion.
|
||||
mozilla::Maybe<SharedImmutableString> resultString_;
|
||||
|
||||
public:
|
||||
// The majorGCNumber is used for scheduling tasks.
|
||||
SourceCompressionTask(JSRuntime* rt, ScriptSource* source)
|
||||
: runtime_(rt),
|
||||
majorGCNumber_(rt->gc.majorGCCount()),
|
||||
sourceHolder_(source) {}
|
||||
virtual ~SourceCompressionTask() = default;
|
||||
|
||||
bool runtimeMatches(JSRuntime* runtime) const { return runtime == runtime_; }
|
||||
bool shouldStart() const {
|
||||
// We wait 2 major GCs to start compressing, in order to avoid
|
||||
// immediate compression.
|
||||
return runtime_->gc.majorGCCount() > majorGCNumber_ + 1;
|
||||
}
|
||||
|
||||
bool shouldCancel() const {
|
||||
// If the refcount is exactly 1, then nothing else is holding on to the
|
||||
// ScriptSource, so no reason to compress it and we should cancel the task.
|
||||
return sourceHolder_.get()->refs == 1;
|
||||
}
|
||||
|
||||
void runTask();
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
void complete();
|
||||
|
||||
ThreadType threadType() override { return ThreadType::THREAD_TYPE_COMPRESS; }
|
||||
|
||||
private:
|
||||
struct PerformTaskWork;
|
||||
friend struct PerformTaskWork;
|
||||
|
||||
// The work algorithm, aware whether it's compressing one-byte UTF-8 source
|
||||
// text or UTF-16, for CharT either Utf8Unit or char16_t. Invoked by
|
||||
// work() after doing a type-test of the ScriptSource*.
|
||||
template <typename CharT>
|
||||
void workEncodingSpecific();
|
||||
};
|
||||
|
||||
// A PromiseHelperTask is an OffThreadPromiseTask that executes a single job on
|
||||
// a helper thread. Call js::StartOffThreadPromiseHelperTask to submit a
|
||||
// PromiseHelperTask for execution.
|
||||
//
|
||||
// Concrete subclasses must implement execute and OffThreadPromiseTask::resolve.
|
||||
// The helper thread will call execute() to do the main work. Then, the thread
|
||||
// of the JSContext used to create the PromiseHelperTask will call resolve() to
|
||||
// resolve promise according to those results.
|
||||
struct PromiseHelperTask : OffThreadPromiseTask, public HelperThreadTask {
|
||||
PromiseHelperTask(JSContext* cx, Handle<PromiseObject*> promise)
|
||||
: OffThreadPromiseTask(cx, promise) {}
|
||||
|
||||
// To be called on a helper thread and implemented by the derived class.
|
||||
virtual void execute() = 0;
|
||||
|
||||
// May be called in the absence of helper threads or off-thread promise
|
||||
// support to synchronously execute and resolve a PromiseTask.
|
||||
//
|
||||
// Warning: After this function returns, 'this' can be deleted at any time, so
|
||||
// the caller must immediately return from the stream callback.
|
||||
void executeAndResolveAndDestroy(JSContext* cx);
|
||||
|
||||
void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
|
||||
ThreadType threadType() override { return THREAD_TYPE_PROMISE_TASK; }
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* vm_HelperThreads_h */
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
#include "vm/BytecodeUtil.h" // JSDVG_IGNORE_STACK
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Iteration.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSFunction.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "jit/BaselineJIT.h"
|
||||
#include "jit/IonAnalysis.h"
|
||||
#include "jit/JitScript.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "wasm/AsmJS.h"
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/Compression.h"
|
||||
#include "vm/FunctionFlags.h" // js::FunctionFlags
|
||||
#include "vm/HelperThreadState.h" // js::RunPendingSourceCompressions
|
||||
#include "vm/HelperThreads.h" // js::RunPendingSourceCompressions
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSFunction.h"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "util/Text.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/BigIntType.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/JSScript.h"
|
||||
#include "vm/Realm.h"
|
||||
|
|
|
@ -162,7 +162,7 @@ bool OffThreadPromiseRuntimeState::internalDispatchToEventLoop(
|
|||
OffThreadPromiseRuntimeState& state =
|
||||
*reinterpret_cast<OffThreadPromiseRuntimeState*>(closure);
|
||||
MOZ_ASSERT(state.usingInternalDispatchQueue());
|
||||
MOZ_ASSERT(gHelperThreadLock.ownedByCurrentThread());
|
||||
MOZ_ASSERT(HelperThreadState().isLockedByCurrentThread());
|
||||
|
||||
if (state.internalDispatchQueueClosed_) {
|
||||
return false;
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions
|
||||
#include "js/SourceText.h" // JS::SourceText
|
||||
#include "vm/HelperThreadState.h" // js::OffThreadParsingMustWaitForGC, js::StartOffThreadParseScript
|
||||
#include "vm/HelperThreads.h" // js::OffThreadParsingMustWaitForGC, js::StartOffThreadParseScript
|
||||
#include "vm/JSContext.h" // JSContext
|
||||
#include "vm/Runtime.h" // js::CanUseExtraThreads
|
||||
|
||||
|
|
|
@ -412,7 +412,7 @@ bool RootList::init(CompartmentSet& debuggees) {
|
|||
if (!tracer.okay) {
|
||||
return false;
|
||||
}
|
||||
js::gc::TraceIncomingCCWs(&tracer, debuggees);
|
||||
TraceIncomingCCWs(&tracer, debuggees);
|
||||
if (!tracer.okay) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "jsapi.h" // js::AssertHeapIsIdle
|
||||
|
||||
#include "vm/EnvironmentObject.h" // js::LexicalEnvironmentObject
|
||||
#include "vm/GlobalObject.h" // js::GlobalObject
|
||||
#include "vm/JSContext.h" // JSContext, CHECK_THREAD
|
||||
#include "vm/JSObject.h" // JSObject
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "debugger/DebugAPI.h"
|
||||
#include "js/BuildId.h" // JS::BuildIdCharVector
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSScript.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
|
|
@ -118,6 +118,7 @@
|
|||
#include "jit/IonTypes.h"
|
||||
#include "jit/JitAllocPolicy.h"
|
||||
#include "jit/Label.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "jit/MIR.h"
|
||||
#include "jit/RegisterAllocator.h"
|
||||
#include "jit/Registers.h"
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "jit/ProcessExecutableMemory.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "wasm/WasmBaselineCompile.h"
|
||||
#include "wasm/WasmCraneliftCompile.h"
|
||||
#include "wasm/WasmGenerator.h"
|
||||
|
|
|
@ -915,27 +915,6 @@ static const unsigned FailFP = 0xbad;
|
|||
|
||||
static const unsigned MaxVarU32DecodedBytes = 5;
|
||||
|
||||
// Which backend to use in the case of the optimized tier.
|
||||
|
||||
enum class OptimizedBackend {
|
||||
Ion,
|
||||
Cranelift,
|
||||
};
|
||||
|
||||
// The CompileMode controls how compilation of a module is performed (notably,
|
||||
// how many times we compile it).
|
||||
|
||||
enum class CompileMode { Once, Tier1, Tier2 };
|
||||
|
||||
// Typed enum for whether debugging is enabled.
|
||||
|
||||
enum class DebugEnabled { False, True };
|
||||
|
||||
// A wasm module can either use no memory, a unshared memory (ArrayBuffer) or
|
||||
// shared memory (SharedArrayBuffer).
|
||||
|
||||
enum class MemoryUsage { None = false, Unshared = 1, Shared = 2 };
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -19,19 +19,10 @@
|
|||
#ifndef wasm_gc_h
|
||||
#define wasm_gc_h
|
||||
|
||||
#include "mozilla/BinarySearch.h"
|
||||
|
||||
#include "jit/MacroAssembler.h" // For ABIArgIter
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/Vector.h"
|
||||
#include "jit/MacroAssembler.h"
|
||||
#include "util/Memory.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
namespace jit {
|
||||
class MacroAssembler;
|
||||
} // namespace jit
|
||||
|
||||
namespace wasm {
|
||||
|
||||
using namespace js::jit;
|
||||
|
@ -236,8 +227,8 @@ class StackMaps {
|
|||
};
|
||||
|
||||
size_t result;
|
||||
if (mozilla::BinarySearchIf(mapping_, 0, mapping_.length(),
|
||||
Comparator(nextInsnAddr), &result)) {
|
||||
if (BinarySearchIf(mapping_, 0, mapping_.length(), Comparator(nextInsnAddr),
|
||||
&result)) {
|
||||
return mapping_[result].map;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "util/Memory.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/HelperThreadState.h"
|
||||
#include "vm/Time.h"
|
||||
#include "wasm/WasmBaselineCompile.h"
|
||||
#include "wasm/WasmCompile.h"
|
||||
|
@ -109,7 +108,12 @@ ModuleGenerator::~ModuleGenerator() {
|
|||
AutoLockHelperThreadState lock;
|
||||
|
||||
// Remove any pending compilation tasks from the worklist.
|
||||
size_t removed = RemovePendingWasmCompileTasks(taskState_, mode(), lock);
|
||||
CompileTaskPtrFifo& worklist =
|
||||
HelperThreadState().wasmWorklist(lock, mode());
|
||||
auto pred = [this](CompileTask* task) {
|
||||
return &task->state == &taskState_;
|
||||
};
|
||||
size_t removed = worklist.eraseIf(pred);
|
||||
MOZ_ASSERT(outstanding_ >= removed);
|
||||
outstanding_ -= removed;
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "vm/ErrorObject.h"
|
||||
#include "vm/FunctionFlags.h" // js::FunctionFlags
|
||||
#include "vm/GlobalObject.h" // js::GlobalObject
|
||||
#include "vm/HelperThreadState.h" // js::PromiseHelperTask
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "vm/PromiseObject.h" // js::PromiseObject
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "js/BuildId.h" // JS::BuildIdCharVector
|
||||
#include "js/experimental/TypedData.h" // JS_NewUint8Array
|
||||
#include "threading/LockGuard.h"
|
||||
#include "vm/HelperThreadState.h" // Tier2GeneratorTask
|
||||
#include "vm/PlainObject.h" // js::PlainObject
|
||||
#include "wasm/WasmBaselineCompile.h"
|
||||
#include "wasm/WasmCompile.h"
|
||||
|
|
|
@ -952,6 +952,27 @@ enum class Tier {
|
|||
Serialized = Optimized
|
||||
};
|
||||
|
||||
// Which backend to use in the case of the optimized tier.
|
||||
|
||||
enum class OptimizedBackend {
|
||||
Ion,
|
||||
Cranelift,
|
||||
};
|
||||
|
||||
// The CompileMode controls how compilation of a module is performed (notably,
|
||||
// how many times we compile it).
|
||||
|
||||
enum class CompileMode { Once, Tier1, Tier2 };
|
||||
|
||||
// Typed enum for whether debugging is enabled.
|
||||
|
||||
enum class DebugEnabled { False, True };
|
||||
|
||||
// A wasm module can either use no memory, a unshared memory (ArrayBuffer) or
|
||||
// shared memory (SharedArrayBuffer).
|
||||
|
||||
enum class MemoryUsage { None = false, Unshared = 1, Shared = 2 };
|
||||
|
||||
// Iterator over tiers present in a tiered data structure.
|
||||
|
||||
class Tiers {
|
||||
|
|
Загрузка…
Ссылка в новой задаче