mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 03:47:31 +09:00
Compare commits
No commits in common. "094c27b33bd6078b8a00b419b9df09afb0c67ba6" and "4ab3f72e15d328979d3c0e2d580470f2841397b3" have entirely different histories.
094c27b33b
...
4ab3f72e15
51 changed files with 317 additions and 588 deletions
|
|
@ -229,8 +229,8 @@ js::Allocate(ExclusiveContext* cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECL_ALLOCATOR_INSTANCES(allocKind, traceKind, type, sizedType, bgFinal, nursery) \
|
#define DECL_ALLOCATOR_INSTANCES(allocKind, traceKind, type, sizedType, bgFinal, nursery) \
|
||||||
template type* js::Allocate<type, NoGC>(ExclusiveContext* cx);\
|
template type* js::Allocate<type, NoGC>(JSContext* cx);\
|
||||||
template type* js::Allocate<type, CanGC>(ExclusiveContext* cx);
|
template type* js::Allocate<type, CanGC>(JSContext* cx);
|
||||||
FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(DECL_ALLOCATOR_INSTANCES)
|
FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(DECL_ALLOCATOR_INSTANCES)
|
||||||
#undef DECL_ALLOCATOR_INSTANCES
|
#undef DECL_ALLOCATOR_INSTANCES
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@ namespace gc {
|
||||||
inline size_t
|
inline size_t
|
||||||
GetAtomBit(TenuredCell* thing)
|
GetAtomBit(TenuredCell* thing)
|
||||||
{
|
{
|
||||||
(void)thing;
|
MOZ_ASSERT(thing->zoneFromAnyThread()->isAtomsZone());
|
||||||
return 0;
|
Arena* arena = thing->arena();
|
||||||
|
size_t arenaBit = (reinterpret_cast<uintptr_t>(thing) - arena->address()) / CellBytesPerMarkBit;
|
||||||
|
return arena->atomBitmapStart() * JS_BITS_PER_WORD + arenaBit;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
|
@ -52,7 +54,23 @@ AtomMarkingRuntime::inlinedMarkAtom(JSContext* cx, T* thing)
|
||||||
if (ThingIsPermanent(thing))
|
if (ThingIsPermanent(thing))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
(void)cell;
|
size_t bit = GetAtomBit(cell);
|
||||||
|
MOZ_ASSERT(bit / JS_BITS_PER_WORD < allocatedWords);
|
||||||
|
|
||||||
|
cx->zone()->markedAtoms().setBit(bit);
|
||||||
|
|
||||||
|
if (!cx->helperThread()) {
|
||||||
|
// Trigger a read barrier on the atom, in case there is an incremental
|
||||||
|
// GC in progress. This is necessary if the atom is being marked
|
||||||
|
// because a reference to it was obtained from another zone which is
|
||||||
|
// not being collected by the incremental GC.
|
||||||
|
T::readBarrier(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children of the thing also need to be marked in the context's zone.
|
||||||
|
// We don't have a JSTracer for this so manually handle the cases in which
|
||||||
|
// an atom can reference other atoms.
|
||||||
|
markChildren(cx, thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gc
|
} // namespace gc
|
||||||
|
|
|
||||||
|
|
@ -47,20 +47,51 @@ namespace gc {
|
||||||
void
|
void
|
||||||
AtomMarkingRuntime::registerArena(Arena* arena)
|
AtomMarkingRuntime::registerArena(Arena* arena)
|
||||||
{
|
{
|
||||||
(void)arena;
|
MOZ_ASSERT(arena->getThingSize() != 0);
|
||||||
|
MOZ_ASSERT(arena->getThingSize() % CellAlignBytes == 0);
|
||||||
|
MOZ_ASSERT(arena->zone->isAtomsZone());
|
||||||
|
MOZ_ASSERT(arena->zone->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
|
||||||
|
|
||||||
|
// We need to find a range of bits from the atoms bitmap for this arena.
|
||||||
|
|
||||||
|
// Look for a free range of bits compatible with this arena.
|
||||||
|
if (freeArenaIndexes.ref().length()) {
|
||||||
|
arena->atomBitmapStart() = freeArenaIndexes.ref().popCopy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a range of bits from the end for this arena.
|
||||||
|
arena->atomBitmapStart() = allocatedWords;
|
||||||
|
allocatedWords += ArenaBitmapWords;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AtomMarkingRuntime::unregisterArena(Arena* arena)
|
AtomMarkingRuntime::unregisterArena(Arena* arena)
|
||||||
{
|
{
|
||||||
(void)arena;
|
MOZ_ASSERT(arena->zone->isAtomsZone());
|
||||||
|
|
||||||
|
// Leak these atom bits if we run out of memory.
|
||||||
|
mozilla::Unused << freeArenaIndexes.ref().emplaceBack(arena->atomBitmapStart());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AtomMarkingRuntime::computeBitmapFromChunkMarkBits(JSRuntime* runtime, DenseBitmap& bitmap)
|
AtomMarkingRuntime::computeBitmapFromChunkMarkBits(JSRuntime* runtime, DenseBitmap& bitmap)
|
||||||
{
|
{
|
||||||
(void)runtime;
|
MOZ_ASSERT(runtime->currentThreadHasExclusiveAccess());
|
||||||
return bitmap.ensureSpace(0);
|
|
||||||
|
if (!bitmap.ensureSpace(allocatedWords))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Zone* atomsZone = runtime->unsafeAtomsCompartment()->zone();
|
||||||
|
for (auto thingKind : AllAllocKinds()) {
|
||||||
|
for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
|
||||||
|
Arena* arena = aiter.get();
|
||||||
|
uintptr_t* chunkWords = arena->chunk()->bitmap.arenaBits(arena);
|
||||||
|
bitmap.copyBitsFrom(arena->atomBitmapStart(), ArenaBitmapWords, chunkWords);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -81,8 +112,19 @@ template <typename Bitmap>
|
||||||
static void
|
static void
|
||||||
BitwiseOrIntoChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap)
|
BitwiseOrIntoChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap)
|
||||||
{
|
{
|
||||||
(void)runtime;
|
// Make sure that by copying the mark bits for one arena in word sizes we
|
||||||
(void)bitmap;
|
// do not affect the mark bits for other arenas.
|
||||||
|
static_assert(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD,
|
||||||
|
"ArenaBitmapWords must evenly divide ArenaBitmapBits");
|
||||||
|
|
||||||
|
Zone* atomsZone = runtime->unsafeAtomsCompartment()->zone();
|
||||||
|
for (auto thingKind : AllAllocKinds()) {
|
||||||
|
for (ArenaIter aiter(atomsZone, thingKind); !aiter.done(); aiter.next()) {
|
||||||
|
Arena* arena = aiter.get();
|
||||||
|
uintptr_t* chunkWords = arena->chunk()->bitmap.arenaBits(arena);
|
||||||
|
bitmap.bitwiseOrRangeInto(arena->atomBitmapStart(), ArenaBitmapWords, chunkWords);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -1615,8 +1615,6 @@ class GCRuntime
|
||||||
friend class AutoEnterIteration;
|
friend class AutoEnterIteration;
|
||||||
};
|
};
|
||||||
|
|
||||||
MOZ_MUST_USE bool InitializeStaticData();
|
|
||||||
|
|
||||||
/* Prevent compartments and zones from being collected during iteration. */
|
/* Prevent compartments and zones from being collected during iteration. */
|
||||||
class MOZ_RAII AutoEnterIteration {
|
class MOZ_RAII AutoEnterIteration {
|
||||||
GCRuntime* gc;
|
GCRuntime* gc;
|
||||||
|
|
|
||||||
|
|
@ -158,22 +158,23 @@ IsMovingTracer(JSTracer *trc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(JSString* str) {
|
template <typename T> bool ThingIsPermanentAtomOrWellKnownSymbol(T* thing) { return false; }
|
||||||
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSString>(JSString* str) {
|
||||||
return str->isPermanentAtom();
|
return str->isPermanentAtom();
|
||||||
}
|
}
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(JSFlatString* str) {
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSFlatString>(JSFlatString* str) {
|
||||||
return str->isPermanentAtom();
|
return str->isPermanentAtom();
|
||||||
}
|
}
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(JSLinearString* str) {
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSLinearString>(JSLinearString* str) {
|
||||||
return str->isPermanentAtom();
|
return str->isPermanentAtom();
|
||||||
}
|
}
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(JSAtom* atom) {
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSAtom>(JSAtom* atom) {
|
||||||
return atom->isPermanent();
|
return atom->isPermanent();
|
||||||
}
|
}
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(PropertyName* name) {
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<PropertyName>(PropertyName* name) {
|
||||||
return name->isPermanent();
|
return name->isPermanent();
|
||||||
}
|
}
|
||||||
bool ThingIsPermanentAtomOrWellKnownSymbol(JS::Symbol* sym) {
|
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JS::Symbol>(JS::Symbol* sym) {
|
||||||
return sym->isWellKnownSymbol();
|
return sym->isWellKnownSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -638,14 +638,6 @@ js::Nursery::printProfileTimes(const ProfileTimes& times)
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
|
||||||
js::Nursery::printProfileDurations(const ProfileDurations& times)
|
|
||||||
{
|
|
||||||
for (auto duration : times)
|
|
||||||
fprintf(stderr, " %6" PRIi64, int64_t(duration.ToMicroseconds()));
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
js::Nursery::printTotalProfileTimes()
|
js::Nursery::printTotalProfileTimes()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -464,14 +464,6 @@ class BufferGrayRootsTracer : public JS::CallbackTracer
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline void
|
|
||||||
BufferGrayRootsTracer::bufferRoot(T* thing)
|
|
||||||
{
|
|
||||||
if (thing)
|
|
||||||
onChild(JS::GCCellPtr(thing));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Return true if this trace is happening on behalf of gray buffering during
|
// Return true if this trace is happening on behalf of gray buffering during
|
||||||
// the marking phase of incremental GC.
|
// the marking phase of incremental GC.
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,10 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
bool
|
|
||||||
js::RuntimeFromActiveCooperatingThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<Zone*>(shadowZone)->runtimeFromAnyThread()->isHeapMajorCollecting();
|
|
||||||
}
|
|
||||||
|
|
||||||
Zone * const Zone::NotOnList = reinterpret_cast<Zone*>(1);
|
Zone * const Zone::NotOnList = reinterpret_cast<Zone*>(1);
|
||||||
|
|
||||||
JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
|
JS::Zone::Zone(JSRuntime* rt, ZoneGroup* group)
|
||||||
: JS::shadow::Zone(rt, &rt->gc.marker),
|
: JS::shadow::Zone(rt, &rt->gc.marker),
|
||||||
group_(group),
|
|
||||||
debuggers(nullptr),
|
debuggers(nullptr),
|
||||||
suppressAllocationMetadataBuilder(false),
|
suppressAllocationMetadataBuilder(false),
|
||||||
arenas(rt, group),
|
arenas(rt, group),
|
||||||
|
|
|
||||||
|
|
@ -158,8 +158,6 @@ struct Zone : public JS::shadow::Zone,
|
||||||
explicit Zone(JSRuntime* rt, js::ZoneGroup* group = nullptr);
|
explicit Zone(JSRuntime* rt, js::ZoneGroup* group = nullptr);
|
||||||
~Zone();
|
~Zone();
|
||||||
bool active = false;
|
bool active = false;
|
||||||
js::ZoneGroup* group_;
|
|
||||||
js::ZoneGroup* group() const { return group_; }
|
|
||||||
MOZ_MUST_USE bool init(bool isSystem);
|
MOZ_MUST_USE bool init(bool isSystem);
|
||||||
|
|
||||||
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
|
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
|
||||||
|
|
@ -480,7 +478,7 @@ struct Zone : public JS::shadow::Zone,
|
||||||
js::ZoneGroupData<uint32_t> tenuredStrings;
|
js::ZoneGroupData<uint32_t> tenuredStrings;
|
||||||
js::ZoneGroupData<bool> allocNurseryStrings;
|
js::ZoneGroupData<bool> allocNurseryStrings;
|
||||||
|
|
||||||
public:
|
private:
|
||||||
// Shared Shape property tree.
|
// Shared Shape property tree.
|
||||||
js::PropertyTree propertyTree;
|
js::PropertyTree propertyTree;
|
||||||
|
|
||||||
|
|
@ -509,7 +507,6 @@ struct Zone : public JS::shadow::Zone,
|
||||||
void setData(void* value) { data = value; }
|
void setData(void* value) { data = value; }
|
||||||
void* getData() const { return data; }
|
void* getData() const { return data; }
|
||||||
bool isSystemZone() const { return isSystem; }
|
bool isSystemZone() const { return isSystem; }
|
||||||
void setIsSystemZone(bool value) { isSystem = value; }
|
|
||||||
js::PropertyTree& propertyTreeRef() { return propertyTree; }
|
js::PropertyTree& propertyTreeRef() { return propertyTree; }
|
||||||
|
|
||||||
bool usedByExclusiveThread = false;
|
bool usedByExclusiveThread = false;
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,16 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "gc/ZoneGroup.h"
|
#include "gc/ZoneGroup.h"
|
||||||
#include "gc/Nursery.h"
|
|
||||||
|
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
|
|
||||||
#include "jit/IonBuilder.h"
|
#include "jit/IonBuilder.h"
|
||||||
#include "jit/Ion.h"
|
#include "jit/JitCompartment.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
Nursery&
|
|
||||||
ZoneGroup::nursery()
|
|
||||||
{
|
|
||||||
return runtime->gc.getNursery();
|
|
||||||
}
|
|
||||||
|
|
||||||
ZoneGroup::ZoneGroup(JSRuntime* runtime)
|
ZoneGroup::ZoneGroup(JSRuntime* runtime)
|
||||||
: runtime(runtime),
|
: runtime(runtime),
|
||||||
ownerContext_(TlsContext.get()),
|
ownerContext_(TlsContext.get()),
|
||||||
|
|
@ -42,6 +35,10 @@ ZoneGroup::init()
|
||||||
{
|
{
|
||||||
AutoLockGC lock(runtime);
|
AutoLockGC lock(runtime);
|
||||||
|
|
||||||
|
jitZoneGroup = js_new<jit::JitZoneGroup>(this);
|
||||||
|
if (!jitZoneGroup)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,6 +53,10 @@ ZoneGroup::~ZoneGroup()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
js_delete(jitZoneGroup.ref());
|
||||||
|
|
||||||
|
if (this == runtime->gc.systemZoneGroup)
|
||||||
|
runtime->gc.systemZoneGroup = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -66,18 +67,20 @@ ZoneGroup::enter(JSContext* cx)
|
||||||
} else {
|
} else {
|
||||||
if (useExclusiveLocking()) {
|
if (useExclusiveLocking()) {
|
||||||
MOZ_ASSERT(!usedByHelperThread());
|
MOZ_ASSERT(!usedByHelperThread());
|
||||||
MOZ_RELEASE_ASSERT(ownerContext().context() == nullptr);
|
while (ownerContext().context() != nullptr) {
|
||||||
|
cx->yieldToEmbedding();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MOZ_RELEASE_ASSERT(ownerContext().context() == nullptr);
|
MOZ_RELEASE_ASSERT(ownerContext().context() == nullptr);
|
||||||
MOZ_ASSERT(enterCount == 0);
|
MOZ_ASSERT(enterCount == 0);
|
||||||
ownerContext_ = CooperatingContext(cx);
|
ownerContext_ = CooperatingContext(cx);
|
||||||
if (!cx->runtime()->gc.isGenerationalGCEnabled())
|
if (cx->generationalDisabled)
|
||||||
nursery().disable();
|
nursery().disable();
|
||||||
|
|
||||||
// Finish any Ion compilations in this zone group, in case compilation
|
// Finish any Ion compilations in this zone group, in case compilation
|
||||||
// finished for some script in this group while no thread was in this
|
// finished for some script in this group while no thread was in this
|
||||||
// group.
|
// group.
|
||||||
jit::AttachFinishedCompilations(cx);
|
jit::AttachFinishedCompilations(this, nullptr);
|
||||||
}
|
}
|
||||||
enterCount++;
|
enterCount++;
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +148,7 @@ ZoneGroup::deleteEmptyZone(Zone* zone)
|
||||||
for (auto& i : zones()) {
|
for (auto& i : zones()) {
|
||||||
if (i == zone) {
|
if (i == zone) {
|
||||||
zones().erase(&i);
|
zones().erase(&i);
|
||||||
js_delete(zone);
|
zone->destroy(runtime->defaultFreeOp());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ class CooperatingContext
|
||||||
JSContext* operator*() const { return cx_; }
|
JSContext* operator*() const { return cx_; }
|
||||||
JSContext* operator->() const { return cx_; }
|
JSContext* operator->() const { return cx_; }
|
||||||
explicit operator bool() const { return !!cx_; }
|
explicit operator bool() const { return !!cx_; }
|
||||||
JSContext* context() const { return cx_; }
|
|
||||||
JSContext* get() const { return cx_; }
|
JSContext* get() const { return cx_; }
|
||||||
void* addressOfContext() { return &cx_; }
|
void* addressOfContext() { return &cx_; }
|
||||||
};
|
};
|
||||||
|
|
@ -111,7 +110,7 @@ class ZoneGroup
|
||||||
|
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
Nursery& nursery();
|
inline Nursery& nursery();
|
||||||
inline gc::StoreBuffer& storeBuffer();
|
inline gc::StoreBuffer& storeBuffer();
|
||||||
|
|
||||||
inline bool isCollecting();
|
inline bool isCollecting();
|
||||||
|
|
|
||||||
|
|
@ -1075,15 +1075,6 @@ BaselineCacheIRCompiler::init(CacheKind kind)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These operations are not supported by this branch's Baseline CacheIR
|
|
||||||
// format. Keep explicit handlers so every operation declared by CACHE_IR_OPS
|
|
||||||
// has a linkable implementation.
|
|
||||||
bool BaselineCacheIRCompiler::emitAllocateAndStoreDynamicSlot() { return false; }
|
|
||||||
bool BaselineCacheIRCompiler::emitAddAndStoreFixedSlot() { return false; }
|
|
||||||
bool BaselineCacheIRCompiler::emitAddAndStoreDynamicSlot() { return false; }
|
|
||||||
bool BaselineCacheIRCompiler::emitCallNativeGetterResult() { return false; }
|
|
||||||
bool BaselineCacheIRCompiler::emitLoadEnclosingEnvironment() { return false; }
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static GCPtr<T>*
|
static GCPtr<T>*
|
||||||
AsGCPtr(uintptr_t* ptr)
|
AsGCPtr(uintptr_t* ptr)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "jit/CacheIRCompiler.h"
|
#include "jit/BaselineCacheIRCompiler.h"
|
||||||
|
|
||||||
#include "jit/CacheIR.h"
|
#include "jit/CacheIR.h"
|
||||||
#include "jit/Linker.h"
|
#include "jit/Linker.h"
|
||||||
|
|
@ -2196,3 +2196,4 @@ ICCacheIR_Updated::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitor
|
||||||
stubInfo->copyStubData(&other, res);
|
stubInfo->copyStubData(&other, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,21 +63,6 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
bool
|
|
||||||
JitZone::init(JSContext* cx)
|
|
||||||
{
|
|
||||||
(void)cx;
|
|
||||||
return baselineCacheIRStubCodes_.init() && ionCacheIRStubInfoSet_.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
JitZone::sweep(FreeOp* fop)
|
|
||||||
{
|
|
||||||
(void)fop;
|
|
||||||
baselineCacheIRStubCodes_.sweep();
|
|
||||||
ionCacheIRStubInfoSet_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assert that JitCode is gc::Cell aligned.
|
// Assert that JitCode is gc::Cell aligned.
|
||||||
JS_STATIC_ASSERT(sizeof(JitCode) % gc::CellSize == 0);
|
JS_STATIC_ASSERT(sizeof(JitCode) % gc::CellSize == 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,6 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
void
|
|
||||||
MacroAssembler::loadJSContext(Register dest)
|
|
||||||
{
|
|
||||||
// The wasm Context symbolic address points at the current thread's
|
|
||||||
// cooperating-context slot. Load the JSContext pointer stored there.
|
|
||||||
movePtr(wasm::SymbolicAddress::Context, dest);
|
|
||||||
loadPtr(Address(dest, 0), dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void branchTestStringHelper(MacroAssembler& masm, Assembler::Condition cond, const T& src, Label* label) {
|
void branchTestStringHelper(MacroAssembler& masm, Assembler::Condition cond, const T& src, Label* label) {
|
||||||
if constexpr (std::is_same_v<T, ValueOperand>) {
|
if constexpr (std::is_same_v<T, ValueOperand>) {
|
||||||
|
|
|
||||||
|
|
@ -1196,14 +1196,6 @@ namespace jit {
|
||||||
TEMPLATE_TYPE_POLICY_LIST(template<> DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
|
TEMPLATE_TYPE_POLICY_LIST(template<> DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_)
|
||||||
#undef DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_
|
#undef DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_
|
||||||
|
|
||||||
template<>
|
|
||||||
TypePolicy*
|
|
||||||
MixPolicy<BoxPolicy<0>, CacheIdPolicy<1>>::Data::thisTypePolicy()
|
|
||||||
{
|
|
||||||
static MixPolicy<BoxPolicy<0>, CacheIdPolicy<1>> singletonType;
|
|
||||||
return &singletonType;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -605,10 +605,6 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||||
load32(Address(scratch, 0x0), dest);
|
load32(Address(scratch, 0x0), dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load32(const Address& address, Register dest) {
|
|
||||||
MacroAssemblerX86Shared::load32(Operand(address), dest);
|
|
||||||
}
|
|
||||||
void load64(const Address& address, Register64 dest) {
|
void load64(const Address& address, Register64 dest) {
|
||||||
movq(Operand(address), dest.reg);
|
movq(Operand(address), dest.reg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4617,19 +4617,15 @@ extern JS_PUBLIC_API(bool)
|
||||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
const char* bytes, size_t length, MutableHandleValue rval)
|
const char* bytes, size_t length, MutableHandleValue rval)
|
||||||
{
|
{
|
||||||
// Keep the converted source owned by this stack frame for the entire
|
char16_t* chars;
|
||||||
// compilation. SourceBufferHolder only borrows it; transferring
|
|
||||||
// ownership here can leave the parser reading freed/poisoned memory when
|
|
||||||
// self-hosted code is initialized.
|
|
||||||
UniqueTwoByteChars chars;
|
|
||||||
if (options.utf8)
|
if (options.utf8)
|
||||||
chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get());
|
chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
|
||||||
else
|
else
|
||||||
chars.reset(InflateString(cx, bytes, &length));
|
chars = InflateString(cx, bytes, &length);
|
||||||
if (!chars)
|
if (!chars)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SourceBufferHolder srcBuf(chars.get(), length, SourceBufferHolder::NoOwnership);
|
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
|
||||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||||
bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
|
bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
|
||||||
return ok;
|
return ok;
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,6 @@
|
||||||
|
|
||||||
#include "vm/Stack-inl.h"
|
#include "vm/Stack-inl.h"
|
||||||
|
|
||||||
// The execution context is stored in thread-local storage and is declared in
|
|
||||||
// jscntxt.h. Keep the single definition here so every user of the GC and
|
|
||||||
// zone-group code links against the same TLS slot.
|
|
||||||
MOZ_THREAD_LOCAL(JSContext*) js::TlsContext;
|
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
|
|
|
||||||
149
js/src/jsgc.cpp
149
js/src/jsgc.cpp
|
|
@ -245,64 +245,6 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
js::gc::MemoryCounter::MemoryCounter()
|
|
||||||
: bytes_(0),
|
|
||||||
maxBytes_(0),
|
|
||||||
bytesAtStartOfGC_(0),
|
|
||||||
triggered_(NoTrigger)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
js::gc::MemoryCounter::setMax(size_t newMax, const AutoLockGC& lock)
|
|
||||||
{
|
|
||||||
(void)lock;
|
|
||||||
maxBytes_ = newMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
js::gc::MemoryCounter::adopt(MemoryCounter& other)
|
|
||||||
{
|
|
||||||
bytes_ = size_t(other.bytes_);
|
|
||||||
maxBytes_ = other.maxBytes_;
|
|
||||||
bytesAtStartOfGC_ = other.bytesAtStartOfGC_;
|
|
||||||
triggered_ = TriggerKind(other.triggered_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
js::gc::MemoryCounter::recordTrigger(TriggerKind trigger)
|
|
||||||
{
|
|
||||||
if (trigger > triggered_)
|
|
||||||
triggered_ = trigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
js::gc::MemoryCounter::updateOnGCStart()
|
|
||||||
{
|
|
||||||
bytesAtStartOfGC_ = bytes_;
|
|
||||||
triggered_ = NoTrigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
js::gc::MemoryCounter::updateOnGCEnd(const GCSchedulingTunables& tunables,
|
|
||||||
const AutoLockGC& lock)
|
|
||||||
{
|
|
||||||
(void)tunables;
|
|
||||||
(void)lock;
|
|
||||||
bytes_ = bytesAtStartOfGC_;
|
|
||||||
triggered_ = NoTrigger;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GCRuntime::updateMallocCountersOnGCStart()
|
|
||||||
{
|
|
||||||
mallocCounter.updateOnGCStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
GCRuntime::initializeSweepActions()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
using mozilla::ArrayLength;
|
using mozilla::ArrayLength;
|
||||||
using mozilla::Get;
|
using mozilla::Get;
|
||||||
|
|
@ -1258,27 +1200,6 @@ GCRuntime::finish()
|
||||||
stats.printTotalProfileTimes();
|
stats.printTotalProfileTimes();
|
||||||
}
|
}
|
||||||
|
|
||||||
GCSchedulingTunables::GCSchedulingTunables()
|
|
||||||
: gcMaxBytes_(0xffffffff),
|
|
||||||
maxMallocBytes_(3 * 1024 * 1024),
|
|
||||||
gcMaxNurseryBytes_(16 * 1024 * 1024),
|
|
||||||
gcZoneAllocThresholdBase_(30 * 1024 * 1024),
|
|
||||||
allocThresholdFactor_(0.9f),
|
|
||||||
allocThresholdFactorAvoidInterrupt_(0.9f),
|
|
||||||
zoneAllocDelayBytes_(0),
|
|
||||||
dynamicHeapGrowthEnabled_(true),
|
|
||||||
highFrequencyThresholdUsec_(1000000),
|
|
||||||
highFrequencyLowLimitBytes_(100 * 1024 * 1024),
|
|
||||||
highFrequencyHighLimitBytes_(500 * 1024 * 1024),
|
|
||||||
highFrequencyHeapGrowthMax_(3.0),
|
|
||||||
highFrequencyHeapGrowthMin_(1.5),
|
|
||||||
lowFrequencyHeapGrowth_(1.5),
|
|
||||||
dynamicMarkSliceEnabled_(true),
|
|
||||||
refreshFrameSlicesEnabled_(false),
|
|
||||||
minEmptyChunkCount_(1),
|
|
||||||
maxEmptyChunkCount_(30)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GCRuntime::setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock)
|
GCRuntime::setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock)
|
||||||
{
|
{
|
||||||
|
|
@ -3034,56 +2955,6 @@ ArenaLists::queueForegroundThingsForSweep(FreeOp* fop)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ArenaLists::ArenaLists(JSRuntime* rt, ZoneGroup* group)
|
|
||||||
: runtime_(rt),
|
|
||||||
freeLists_(group),
|
|
||||||
arenaLists_(group),
|
|
||||||
backgroundFinalizeState_(),
|
|
||||||
arenaListsToSweep_(),
|
|
||||||
incrementalSweptArenaKind(group),
|
|
||||||
incrementalSweptArenas(group),
|
|
||||||
gcShapeArenasToUpdate(group),
|
|
||||||
gcAccessorShapeArenasToUpdate(group),
|
|
||||||
gcScriptArenasToUpdate(group),
|
|
||||||
gcObjectGroupArenasToUpdate(group),
|
|
||||||
savedObjectArenas_(group),
|
|
||||||
savedEmptyObjectArenas(group)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ArenaLists::~ArenaLists() = default;
|
|
||||||
|
|
||||||
void
|
|
||||||
ArenaLists::queueForBackgroundSweep(FreeOp* fop, const FinalizePhase& phase)
|
|
||||||
{
|
|
||||||
(void)fop;
|
|
||||||
(void)phase;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArenaLists::queueForegroundObjectsForSweep(FreeOp* fop)
|
|
||||||
{
|
|
||||||
(void)fop;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArenaLists::queueForegroundThingsForSweep(FreeOp* fop)
|
|
||||||
{
|
|
||||||
(void)fop;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArenaLists::mergeForegroundSweptObjectArenas()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void
|
|
||||||
ArenaLists::backgroundFinalize(FreeOp* fop, Arena* listHead, Arena** empty)
|
|
||||||
{
|
|
||||||
(void)fop;
|
|
||||||
(void)listHead;
|
|
||||||
if (empty)
|
|
||||||
*empty = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SliceBudget::reset()
|
SliceBudget::reset()
|
||||||
{
|
{
|
||||||
|
|
@ -8144,22 +8015,13 @@ JS::IsIncrementalBarrierNeeded(JSContext* cx)
|
||||||
return state != gc::State::NotActive && state <= gc::State::Sweep;
|
return state != gc::State::NotActive && state <= gc::State::Sweep;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
#if 0
|
||||||
js::gc::MarkGCThingAsLive(JSRuntime* rt, JS::GCCellPtr thing)
|
|
||||||
{
|
|
||||||
if (!thing || js::gc::IsInsideNursery(thing.asCell()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
MOZ_ASSERT(thing.asCell()->runtimeFromAnyThread() == rt);
|
|
||||||
thing.asCell()->asTenured().markIfUnmarked(js::gc::MarkColor::Black);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct IncrementalReferenceBarrierFunctor {
|
struct IncrementalReferenceBarrierFunctor {
|
||||||
template <typename T> void operator()(T* t) { T::writeBarrierPre(t); }
|
template <typename T> void operator()(T* t) { T::writeBarrierPre(t); }
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
JS::IncrementalReadBarrier(JS::GCCellPtr thing)
|
JS::IncrementalReferenceBarrier(GCCellPtr thing)
|
||||||
{
|
{
|
||||||
if (!thing)
|
if (!thing)
|
||||||
return;
|
return;
|
||||||
|
|
@ -8167,6 +8029,12 @@ JS::IncrementalReadBarrier(JS::GCCellPtr thing)
|
||||||
DispatchTyped(IncrementalReferenceBarrierFunctor(), thing);
|
DispatchTyped(IncrementalReferenceBarrierFunctor(), thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS::IncrementalValueBarrier(const Value& v)
|
||||||
|
{
|
||||||
|
js::GCPtrValue::writeBarrierPre(v);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
JS::IncrementalObjectBarrier(JSObject* obj)
|
JS::IncrementalObjectBarrier(JSObject* obj)
|
||||||
{
|
{
|
||||||
|
|
@ -8177,6 +8045,7 @@ JS::IncrementalObjectBarrier(JSObject* obj)
|
||||||
|
|
||||||
JSObject::writeBarrierPre(obj);
|
JSObject::writeBarrierPre(obj);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
JS::WasIncrementalGC(JSContext* cx)
|
JS::WasIncrementalGC(JSContext* cx)
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,6 @@ PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, Handle<StackShape
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void
|
void
|
||||||
Shape::sweep()
|
Shape::sweep()
|
||||||
{
|
{
|
||||||
|
|
@ -352,7 +351,6 @@ Shape::fixupGetterSetterForBarrier(JSTracer* trc)
|
||||||
MOZ_ASSERT_IF(parent && !parent->inDictionary() && parent->kids.isHash(),
|
MOZ_ASSERT_IF(parent && !parent->inDictionary() && parent->kids.isHash(),
|
||||||
parent->kids.toHash()->has(StackShape(this)));
|
parent->kids.toHash()->has(StackShape(this)));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,6 @@ main_deunified_sources = [
|
||||||
'frontend/TokenStream.cpp',
|
'frontend/TokenStream.cpp',
|
||||||
'frontend/TryEmitter.cpp',
|
'frontend/TryEmitter.cpp',
|
||||||
'gc/Allocator.cpp',
|
'gc/Allocator.cpp',
|
||||||
'gc/AtomMarking.cpp',
|
|
||||||
'gc/Barrier.cpp',
|
'gc/Barrier.cpp',
|
||||||
'gc/GCTrace.cpp',
|
'gc/GCTrace.cpp',
|
||||||
'gc/Iteration.cpp',
|
'gc/Iteration.cpp',
|
||||||
|
|
@ -182,7 +181,6 @@ main_deunified_sources = [
|
||||||
'gc/Tracer.cpp',
|
'gc/Tracer.cpp',
|
||||||
'gc/Verifier.cpp',
|
'gc/Verifier.cpp',
|
||||||
'gc/Zone.cpp',
|
'gc/Zone.cpp',
|
||||||
'gc/ZoneGroup.cpp',
|
|
||||||
'irregexp/NativeRegExpMacroAssembler.cpp',
|
'irregexp/NativeRegExpMacroAssembler.cpp',
|
||||||
'irregexp/RegExpAST.cpp',
|
'irregexp/RegExpAST.cpp',
|
||||||
'irregexp/RegExpCharacters.cpp',
|
'irregexp/RegExpCharacters.cpp',
|
||||||
|
|
|
||||||
|
|
@ -575,7 +575,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||||
|
|
||||||
GlobalObject* unwrapDebuggeeArgument(JSContext* cx, const Value& v);
|
GlobalObject* unwrapDebuggeeArgument(JSContext* cx, const Value& v);
|
||||||
|
|
||||||
public:
|
|
||||||
static void traceObject(JSTracer* trc, JSObject* obj);
|
static void traceObject(JSTracer* trc, JSObject* obj);
|
||||||
void trace(JSTracer* trc);
|
void trace(JSTracer* trc);
|
||||||
static void finalize(FreeOp* fop, JSObject* obj);
|
static void finalize(FreeOp* fop, JSObject* obj);
|
||||||
|
|
@ -583,6 +582,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||||
|
|
||||||
static const ClassOps classOps_;
|
static const ClassOps classOps_;
|
||||||
|
|
||||||
|
public:
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ GlobalObject::new_(JSContext* cx, const Class* clasp, JSPrincipals* principals,
|
||||||
// Lazily create the system zone.
|
// Lazily create the system zone.
|
||||||
if (!rt->gc.systemZone && zoneSpecifier == JS::SystemZone) {
|
if (!rt->gc.systemZone && zoneSpecifier == JS::SystemZone) {
|
||||||
rt->gc.systemZone = compartment->zone();
|
rt->gc.systemZone = compartment->zone();
|
||||||
rt->gc.systemZone->setIsSystemZone(true);
|
rt->gc.systemZone->isSystem = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rooted<GlobalObject*> global(cx);
|
Rooted<GlobalObject*> global(cx);
|
||||||
|
|
@ -863,7 +863,7 @@ GlobalObject::addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
|
||||||
|
|
||||||
RootedId id(cx, NameToId(name));
|
RootedId id(cx, NameToId(name));
|
||||||
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
|
Rooted<StackShape> child(cx, StackShape(base, id, slot, 0, 0));
|
||||||
Shape* shape = cx->zone()->propertyTreeRef().getChild(cx, last, child);
|
Shape* shape = cx->zone()->propertyTree.getChild(cx, last, child);
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,9 @@ GetSelectorRuntime(CompilationSelector selector)
|
||||||
{
|
{
|
||||||
struct Matcher
|
struct Matcher
|
||||||
{
|
{
|
||||||
JSRuntime* match(JSScript* script) { return script->runtimeFromAnyThread(); }
|
JSRuntime* match(JSScript* script) { return script->runtimeFromActiveCooperatingThread(); }
|
||||||
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromMainThread(); }
|
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromActiveCooperatingThread(); }
|
||||||
JSRuntime* match(Zone* zone) { return zone->runtimeFromMainThread(); }
|
JSRuntime* match(Zone* zone) { return zone->runtimeFromActiveCooperatingThread(); }
|
||||||
JSRuntime* match(ZonesInState zbs) { return zbs.runtime; }
|
JSRuntime* match(ZonesInState zbs) { return zbs.runtime; }
|
||||||
JSRuntime* match(JSRuntime* runtime) { return runtime; }
|
JSRuntime* match(JSRuntime* runtime) { return runtime; }
|
||||||
JSRuntime* match(AllCompilations all) { return nullptr; }
|
JSRuntime* match(AllCompilations all) { return nullptr; }
|
||||||
|
|
@ -171,10 +171,10 @@ CompiledScriptMatches(CompilationSelector selector, JSScript* target)
|
||||||
{
|
{
|
||||||
JSScript* target_;
|
JSScript* target_;
|
||||||
|
|
||||||
bool match(JSScript* script) { return script == target_; }
|
bool match(JSScript* script) { return script == builder_->script(); }
|
||||||
bool match(JSCompartment* comp) { return comp == target_->compartment(); }
|
bool match(JSCompartment* comp) { return comp == builder_->script()->compartment(); }
|
||||||
bool match(Zone* zone) { return zone == target_->zoneFromAnyThread(); }
|
bool match(Zone* zone) { return zone == builder_->script()->zoneFromAnyThread(); }
|
||||||
bool match(JSRuntime* runtime) { return runtime == target_->runtimeFromAnyThread(); }
|
bool match(JSRuntime* runtime) { return runtime == builder_->script()->runtimeFromAnyThread(); }
|
||||||
bool match(AllCompilations all) { return true; }
|
bool match(AllCompilations all) { return true; }
|
||||||
bool match(ZonesInState zbs) {
|
bool match(ZonesInState zbs) {
|
||||||
return zbs.runtime == target_->runtimeFromAnyThread() &&
|
return zbs.runtime == target_->runtimeFromAnyThread() &&
|
||||||
|
|
@ -557,7 +557,7 @@ class AutoClearUsedByHelperThread
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoClearUsedByHelperThread(JSObject* global)
|
AutoClearUsedByHelperThread(JSObject* global)
|
||||||
: group(nullptr)
|
: group(global->zone()->group())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void forget() {
|
void forget() {
|
||||||
|
|
@ -598,6 +598,8 @@ CreateGlobalForOffThreadParse(JSContext* cx, ParseTaskKind kind,
|
||||||
|
|
||||||
// Mark this zone group as created for a helper thread. This prevents it
|
// Mark this zone group as created for a helper thread. This prevents it
|
||||||
// from being collected until clearUsedByHelperThread() is called.
|
// from being collected until clearUsedByHelperThread() is called.
|
||||||
|
ZoneGroup* group = global->zone()->group();
|
||||||
|
group->setCreatedForHelperThread();
|
||||||
clearUseGuard.emplace(global);
|
clearUseGuard.emplace(global);
|
||||||
|
|
||||||
// Initialize all classes required for parsing while still on the active
|
// Initialize all classes required for parsing while still on the active
|
||||||
|
|
@ -654,7 +656,7 @@ StartOffThreadParseTask(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||||
|
|
||||||
ScopedJSDeletePtr<ExclusiveContext> helpercx(
|
ScopedJSDeletePtr<ExclusiveContext> helpercx(
|
||||||
cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData*) nullptr,
|
cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData*) nullptr,
|
||||||
ContextKind::Context_Exclusive, cx->options()));
|
ExclusiveContext::Context_Exclusive, cx->options()));
|
||||||
if (!helpercx)
|
if (!helpercx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -1225,6 +1227,16 @@ js::GCParallelTask::join()
|
||||||
joinWithLockHeld(helperLock);
|
joinWithLockHeld(helperLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::GCParallelTask::runFromMainThread(JSRuntime* rt)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(state == NotStarted);
|
||||||
|
MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(rt));
|
||||||
|
uint64_t timeStart = PRMJ_Now();
|
||||||
|
runTask();
|
||||||
|
duration_ = PRMJ_Now() - timeStart;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
|
js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
|
||||||
{
|
{
|
||||||
|
|
@ -1232,25 +1244,14 @@ js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& locked)
|
||||||
AutoUnlockHelperThreadState parallelSection(locked);
|
AutoUnlockHelperThreadState parallelSection(locked);
|
||||||
gc::AutoSetThreadIsPerformingGC performingGC;
|
gc::AutoSetThreadIsPerformingGC performingGC;
|
||||||
uint64_t timeStart = PRMJ_Now();
|
uint64_t timeStart = PRMJ_Now();
|
||||||
run();
|
runTask();
|
||||||
duration_ = mozilla::TimeDuration::FromMicroseconds(
|
duration_ = PRMJ_Now() - timeStart;
|
||||||
double(PRMJ_Now() - timeStart));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = Finished;
|
state = Finished;
|
||||||
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
js::GCParallelTask::runFromActiveCooperatingThread(JSRuntime* rt)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(rt == runtime_);
|
|
||||||
uint64_t timeStart = PRMJ_Now();
|
|
||||||
run();
|
|
||||||
duration_ = mozilla::TimeDuration::FromMicroseconds(
|
|
||||||
double(PRMJ_Now() - timeStart));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::GCParallelTask::isRunningWithLockHeld(const AutoLockHelperThreadState& locked) const
|
js::GCParallelTask::isRunningWithLockHeld(const AutoLockHelperThreadState& locked) const
|
||||||
{
|
{
|
||||||
|
|
@ -1519,7 +1520,7 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked)
|
||||||
wasm::IonCompileTask* task = wasmTask();
|
wasm::IonCompileTask* task = wasmTask();
|
||||||
{
|
{
|
||||||
AutoUnlockHelperThreadState unlock(locked);
|
AutoUnlockHelperThreadState unlock(locked);
|
||||||
success = wasm::CompileFunction(task);
|
success = wasm::CompileFunction(task, &error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On success, try to move work to the finished list.
|
// On success, try to move work to the finished list.
|
||||||
|
|
@ -1673,6 +1674,13 @@ js::PauseCurrentHelperThread()
|
||||||
HelperThreadState().wait(lock, GlobalHelperThreadState::PAUSE);
|
HelperThreadState().wait(lock, GlobalHelperThreadState::PAUSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ExclusiveContext::setHelperThread(HelperThread* thread)
|
||||||
|
{
|
||||||
|
helperThread_ = thread;
|
||||||
|
perThreadData = thread->threadData.ptr();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExclusiveContext::addPendingCompileError(frontend::CompileError** error)
|
ExclusiveContext::addPendingCompileError(frontend::CompileError** error)
|
||||||
{
|
{
|
||||||
|
|
@ -1685,6 +1693,21 @@ ExclusiveContext::addPendingCompileError(frontend::CompileError** error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ExclusiveContext::addPendingOverRecursed()
|
||||||
|
{
|
||||||
|
if (helperThread()->parseTask())
|
||||||
|
helperThread()->parseTask()->overRecursed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ExclusiveContext::addPendingOutOfMemory()
|
||||||
|
{
|
||||||
|
// Keep in sync with recoverFromOutOfMemory.
|
||||||
|
if (helperThread()->parseTask())
|
||||||
|
helperThread()->parseTask()->outOfMemory = true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HelperThread::handleParseWorkload(AutoLockHelperThreadState& locked, uintptr_t stackLimit)
|
HelperThread::handleParseWorkload(AutoLockHelperThreadState& locked, uintptr_t stackLimit)
|
||||||
{
|
{
|
||||||
|
|
@ -1693,6 +1716,8 @@ HelperThread::handleParseWorkload(AutoLockHelperThreadState& locked, uintptr_t s
|
||||||
|
|
||||||
currentTask.emplace(HelperThreadState().parseWorklist(locked).popCopy());
|
currentTask.emplace(HelperThreadState().parseWorklist(locked).popCopy());
|
||||||
ParseTask* task = parseTask();
|
ParseTask* task = parseTask();
|
||||||
|
task->cx->setHelperThread(this);
|
||||||
|
|
||||||
for (size_t i = 0; i < ArrayLength(task->cx->nativeStackLimit); i++)
|
for (size_t i = 0; i < ArrayLength(task->cx->nativeStackLimit); i++)
|
||||||
task->cx->nativeStackLimit[i] = stackLimit;
|
task->cx->nativeStackLimit[i] = stackLimit;
|
||||||
|
|
||||||
|
|
@ -1907,6 +1932,18 @@ HelperThread::handleGCHelperWorkload(AutoLockHelperThreadState& locked)
|
||||||
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JSContext::setHelperThread(HelperThread* thread)
|
||||||
|
{
|
||||||
|
if (helperThread_)
|
||||||
|
allowNurseryAllocations();
|
||||||
|
|
||||||
|
helperThread_ = thread;
|
||||||
|
|
||||||
|
if (helperThread_)
|
||||||
|
suppressNurseryAllocations();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
HelperThread::threadLoop()
|
HelperThread::threadLoop()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ namespace wasm {
|
||||||
class FuncIR;
|
class FuncIR;
|
||||||
class FunctionCompileResults;
|
class FunctionCompileResults;
|
||||||
class IonCompileTask;
|
class IonCompileTask;
|
||||||
|
class CompileTask;
|
||||||
typedef Vector<IonCompileTask*, 0, SystemAllocPolicy> IonCompileTaskPtrVector;
|
typedef Vector<IonCompileTask*, 0, SystemAllocPolicy> IonCompileTaskPtrVector;
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
|
|
||||||
|
|
@ -416,15 +417,13 @@ PauseCurrentHelperThread();
|
||||||
|
|
||||||
/* Perform MIR optimization and LIR generation on a single function. */
|
/* Perform MIR optimization and LIR generation on a single function. */
|
||||||
bool
|
bool
|
||||||
StartOffThreadWasmCompile(wasm::IonCompileTask* task);
|
StartOffThreadWasmCompile(wasm::CompileTask* task);
|
||||||
|
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
// Performs MIR optimization and LIR generation on one or several functions.
|
// Performs MIR optimization and LIR generation on one or several functions.
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
CompileFunction(IonCompileTask* task, UniqueChars* error);
|
CompileFunction(CompileTask* task, UniqueChars* error);
|
||||||
bool
|
|
||||||
CompileFunction(IonCompileTask* task);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, Hand
|
||||||
}
|
}
|
||||||
|
|
||||||
JSFunction*
|
JSFunction*
|
||||||
js::MakeDefaultConstructor(JSContext* cx, HandleScript script, jsbytecode* pc, HandleObject proto)
|
MakeDefaultConstructor(JSContext* cx, HandleScript script, jsbytecode* pc, HandleObject proto)
|
||||||
{
|
{
|
||||||
JSOp op = JSOp(*pc);
|
JSOp op = JSOp(*pc);
|
||||||
JSAtom* atom = script->getAtom(pc);
|
JSAtom* atom = script->getAtom(pc);
|
||||||
|
|
@ -4180,7 +4180,7 @@ CASE(JSOP_DERIVEDCONSTRUCTOR)
|
||||||
MOZ_ASSERT(REGS.sp[-1].isObject());
|
MOZ_ASSERT(REGS.sp[-1].isObject());
|
||||||
ReservedRooted<JSObject*> proto(&rootObject0, ®S.sp[-1].toObject());
|
ReservedRooted<JSObject*> proto(&rootObject0, ®S.sp[-1].toObject());
|
||||||
|
|
||||||
JSFunction* constructor = js::MakeDefaultConstructor(cx, script, REGS.pc, proto);
|
JSFunction* constructor = MakeDefaultConstructor(cx, script, REGS.pc, proto);
|
||||||
|
|
||||||
if (!constructor)
|
if (!constructor)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
@ -4191,7 +4191,7 @@ END_CASE(JSOP_DERIVEDCONSTRUCTOR)
|
||||||
|
|
||||||
CASE(JSOP_CLASSCONSTRUCTOR)
|
CASE(JSOP_CLASSCONSTRUCTOR)
|
||||||
{
|
{
|
||||||
JSFunction* constructor = js::MakeDefaultConstructor(cx, script, REGS.pc, nullptr);
|
JSFunction* constructor = MakeDefaultConstructor(cx, script, REGS.pc, nullptr);
|
||||||
if (!constructor)
|
if (!constructor)
|
||||||
goto error;
|
goto error;
|
||||||
PUSH_OBJECT(*constructor);
|
PUSH_OBJECT(*constructor);
|
||||||
|
|
|
||||||
|
|
@ -1154,8 +1154,6 @@ js::AddPropertyTypesAfterProtoChange(JSContext* cx, NativeObject* obj, ObjectGro
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedNativeObject rootedObj(cx, obj);
|
|
||||||
|
|
||||||
// Add dense element types.
|
// Add dense element types.
|
||||||
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
||||||
Value val = obj->getDenseElement(i);
|
Value val = obj->getDenseElement(i);
|
||||||
|
|
@ -1166,7 +1164,6 @@ js::AddPropertyTypesAfterProtoChange(JSContext* cx, NativeObject* obj, ObjectGro
|
||||||
// Add property types.
|
// Add property types.
|
||||||
for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
|
for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
|
||||||
Shape* shape = &r.front();
|
Shape* shape = &r.front();
|
||||||
RootedShape rootedShape(cx, shape);
|
|
||||||
jsid id = shape->propid();
|
jsid id = shape->propid();
|
||||||
if (JSID_IS_EMPTY(id))
|
if (JSID_IS_EMPTY(id))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1177,7 +1174,7 @@ js::AddPropertyTypesAfterProtoChange(JSContext* cx, NativeObject* obj, ObjectGro
|
||||||
}
|
}
|
||||||
|
|
||||||
Value val = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
|
Value val = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
|
||||||
UpdateShapeTypeAndValue(cx, rootedObj, rootedShape, val);
|
UpdateShapeTypeAndValue(cx, obj, shape, id, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
|
|
@ -1464,13 +1461,13 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
||||||
// resolving, the JSPROP_RESOLVING mask is set; whereas the first
|
// resolving, the JSPROP_RESOLVING mask is set; whereas the first
|
||||||
// time it is redefined, it isn't set.
|
// time it is redefined, it isn't set.
|
||||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
||||||
if (!cx->shouldBeJSContext() || !ArgumentsObject::reifyLength(cx->asJSContext(), argsobj))
|
if (!ArgumentsObject::reifyLength(cx, argsobj))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
|
} else if (JSID_IS_SYMBOL(id) && JSID_TO_SYMBOL(id) == cx->wellKnownSymbols().iterator) {
|
||||||
// Do same thing as .length for [@@iterator].
|
// Do same thing as .length for [@@iterator].
|
||||||
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
if ((desc_.attributes() & JSPROP_RESOLVING) == 0) {
|
||||||
if (!cx->shouldBeJSContext() || !ArgumentsObject::reifyIterator(cx->asJSContext(), argsobj))
|
if (!ArgumentsObject::reifyIterator(cx, argsobj))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (JSID_IS_INT(id)) {
|
} else if (JSID_IS_INT(id)) {
|
||||||
|
|
|
||||||
|
|
@ -1285,58 +1285,6 @@ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RegExpZone */
|
|
||||||
|
|
||||||
RegExpZone::RegExpZone(Zone* zone)
|
|
||||||
: set_(zone, ZoneAllocPolicy(zone))
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RegExpZone::init()
|
|
||||||
{
|
|
||||||
return set_.init(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RegExpZone::get(JSContext* cx, HandleAtom source, RegExpFlag flags,
|
|
||||||
MutableHandleRegExpShared result)
|
|
||||||
{
|
|
||||||
DependentAddPtr<Set> p(cx, set_.get(), Key(source, flags));
|
|
||||||
if (p) {
|
|
||||||
result.set(*p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shared = Allocate<RegExpShared>(cx);
|
|
||||||
if (!shared)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
new (shared) RegExpShared(source, flags);
|
|
||||||
if (!p.add(cx, set_.get(), Key(source, flags), shared)) {
|
|
||||||
ReportOutOfMemory(cx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.set(shared);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
RegExpZone::get(JSContext* cx, HandleAtom atom, JSString* opt,
|
|
||||||
MutableHandleRegExpShared shared)
|
|
||||||
{
|
|
||||||
RegExpFlag flags = RegExpFlag(0);
|
|
||||||
if (opt && !ParseRegExpFlags(cx, opt, &flags))
|
|
||||||
return false;
|
|
||||||
return get(cx, atom, flags, shared);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
RegExpZone::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
|
||||||
{
|
|
||||||
return set_.sizeOfExcludingThis(mallocSizeOf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RegExpCompartment */
|
/* RegExpCompartment */
|
||||||
|
|
||||||
RegExpCompartment::RegExpCompartment(Zone* zone)
|
RegExpCompartment::RegExpCompartment(Zone* zone)
|
||||||
|
|
|
||||||
|
|
@ -290,8 +290,8 @@ class RegExpZone
|
||||||
* The set of all RegExpShareds in the zone. On every GC, every RegExpShared
|
* The set of all RegExpShareds in the zone. On every GC, every RegExpShared
|
||||||
* that was not marked is deleted and removed from the set.
|
* that was not marked is deleted and removed from the set.
|
||||||
*/
|
*/
|
||||||
using Set = JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>;
|
using Set = JS::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>;
|
||||||
JS::WeakCache<Set> set_;
|
Set set_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit RegExpZone(Zone* zone);
|
explicit RegExpZone(Zone* zone);
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||||
if (!symbolRegistry_.init())
|
if (!symbolRegistry_.init())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!scriptDataTable_.ref().init())
|
if (!scriptDataTable_.init())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* The garbage collector depends on everything before this point being initialized. */
|
/* The garbage collector depends on everything before this point being initialized. */
|
||||||
|
|
@ -468,7 +468,6 @@ JSRuntime::destroyRuntime()
|
||||||
void
|
void
|
||||||
JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* rtSizes)
|
JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* rtSizes)
|
||||||
{
|
{
|
||||||
JSContext* cx = contextFromMainThread();
|
|
||||||
rtSizes->object += mallocSizeOf(this);
|
rtSizes->object += mallocSizeOf(this);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -801,8 +800,7 @@ JSRuntime::updateMallocCounter(size_t nbytes)
|
||||||
void
|
void
|
||||||
JSRuntime::updateMallocCounter(JS::Zone* zone, size_t nbytes)
|
JSRuntime::updateMallocCounter(JS::Zone* zone, size_t nbytes)
|
||||||
{
|
{
|
||||||
(void)zone;
|
gc.updateMallocCounter(zone, nbytes);
|
||||||
gc.updateMallocCounter(nbytes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(void*)
|
JS_FRIEND_API(void*)
|
||||||
|
|
@ -864,12 +862,27 @@ JSRuntime::setUsedByExclusiveThread(Zone* zone)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!zone->usedByExclusiveThread);
|
MOZ_ASSERT(!zone->usedByExclusiveThread);
|
||||||
zone->usedByExclusiveThread = true;
|
zone->usedByExclusiveThread = true;
|
||||||
|
numExclusiveThreads++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
JSRuntime::clearUsedByExclusiveThread(Zone* zone)
|
JSRuntime::clearUsedByExclusiveThread(Zone* zone)
|
||||||
{
|
{
|
||||||
zone->usedByExclusiveThread = false;
|
MOZ_ASSERT(!zone->group()->usedByHelperThread());
|
||||||
|
MOZ_ASSERT(!zone->wasGCStarted());
|
||||||
|
zone->group()->setUsedByHelperThread();
|
||||||
|
numActiveHelperThreadZones++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
JSRuntime::clearUsedByHelperThread(Zone* zone)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(zone->group()->usedByHelperThread());
|
||||||
|
zone->group()->clearUsedByHelperThread();
|
||||||
|
numActiveHelperThreadZones--;
|
||||||
|
JSContext* cx = TlsContext.get();
|
||||||
|
if (gc.fullGCForAtomsRequested() && cx->canCollectAtoms())
|
||||||
|
gc.triggerFullGCForAtoms(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
||||||
|
|
@ -1264,7 +1264,6 @@ Shape::setObjectFlags(ExclusiveContext* cx, BaseShape::Flag flags, TaggedProto p
|
||||||
return replaceLastProperty(cx, base, proto, lastRoot);
|
return replaceLastProperty(cx, base, proto, lastRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* static */ inline HashNumber
|
/* static */ inline HashNumber
|
||||||
StackBaseShape::hash(const Lookup& lookup)
|
StackBaseShape::hash(const Lookup& lookup)
|
||||||
{
|
{
|
||||||
|
|
@ -1279,7 +1278,6 @@ StackBaseShape::match(ReadBarriered<UnownedBaseShape*> key, const Lookup& lookup
|
||||||
return key.unbarrieredGet()->flags == lookup.flags &&
|
return key.unbarrieredGet()->flags == lookup.flags &&
|
||||||
key.unbarrieredGet()->clasp_ == lookup.clasp;
|
key.unbarrieredGet()->clasp_ == lookup.clasp;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
BaseShape::BaseShape(const StackBaseShape& base)
|
BaseShape::BaseShape(const StackBaseShape& base)
|
||||||
|
|
@ -1441,7 +1439,6 @@ InitialShapeEntry::InitialShapeEntry(Shape* shape, const Lookup::ShapeProto& pro
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* static */ inline HashNumber
|
/* static */ inline HashNumber
|
||||||
InitialShapeEntry::hash(const Lookup& lookup)
|
InitialShapeEntry::hash(const Lookup& lookup)
|
||||||
{
|
{
|
||||||
|
|
@ -1458,7 +1455,6 @@ InitialShapeEntry::match(const InitialShapeEntry& key, const Lookup& lookup)
|
||||||
&& lookup.baseFlags == shape->getObjectFlags()
|
&& lookup.baseFlags == shape->getObjectFlags()
|
||||||
&& lookup.proto.match(key.proto);
|
&& lookup.proto.match(key.proto);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||||
|
|
||||||
|
|
@ -1534,7 +1530,6 @@ HashChildren(Shape* kid1, Shape* kid2)
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool
|
bool
|
||||||
PropertyTree::insertChild(JSContext* cx, Shape* parent, Shape* child)
|
PropertyTree::insertChild(JSContext* cx, Shape* parent, Shape* child)
|
||||||
{
|
{
|
||||||
|
|
@ -1683,7 +1678,6 @@ PropertyTree::getChild(JSContext* cx, Shape* parent, Handle<StackShape> child)
|
||||||
{
|
{
|
||||||
return inlinedGetChild(cx, parent, child);
|
return inlinedGetChild(cx, parent, child);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Shape::sweep()
|
Shape::sweep()
|
||||||
|
|
@ -1804,7 +1798,6 @@ Shape::fixupAfterMovingGC()
|
||||||
fixupShapeTreeAfterMovingGC();
|
fixupShapeTreeAfterMovingGC();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void
|
void
|
||||||
NurseryShapesRef::trace(JSTracer* trc)
|
NurseryShapesRef::trace(JSTracer* trc)
|
||||||
{
|
{
|
||||||
|
|
@ -1813,7 +1806,6 @@ NurseryShapesRef::trace(JSTracer* trc)
|
||||||
shape->fixupGetterSetterForBarrier(trc);
|
shape->fixupGetterSetterForBarrier(trc);
|
||||||
shapes.clearAndFree();
|
shapes.clearAndFree();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Shape::fixupGetterSetterForBarrier(JSTracer* trc)
|
Shape::fixupGetterSetterForBarrier(JSTracer* trc)
|
||||||
|
|
|
||||||
|
|
@ -605,7 +605,7 @@ FrameIter::Data::Data(JSContext* cx, const CooperatingContext& target,
|
||||||
state_(DONE),
|
state_(DONE),
|
||||||
pc_(nullptr),
|
pc_(nullptr),
|
||||||
interpFrames_(nullptr),
|
interpFrames_(nullptr),
|
||||||
activations_(cx->runtime()),
|
activations_(cx, target),
|
||||||
jitFrames_(),
|
jitFrames_(),
|
||||||
ionInlineFrameNo_(0),
|
ionInlineFrameNo_(0),
|
||||||
wasmFrames_()
|
wasmFrames_()
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,9 @@ JSFlatString::new_(js::ExclusiveContext* cx, const CharT* chars, size_t length)
|
||||||
|
|
||||||
JSFlatString* str;
|
JSFlatString* str;
|
||||||
if (cx->compartment()->isAtomsCompartment())
|
if (cx->compartment()->isAtomsCompartment())
|
||||||
str = js::Allocate<js::NormalAtom, allowGC>(cx->asJSContext());
|
str = js::Allocate<js::NormalAtom, allowGC>(cx);
|
||||||
else
|
else
|
||||||
str = js::Allocate<JSFlatString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
|
str = js::Allocate<JSFlatString, allowGC>(cx, js::gc::DefaultHeap);
|
||||||
if (!str)
|
if (!str)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
@ -273,7 +273,7 @@ MOZ_ALWAYS_INLINE JSThinInlineString*
|
||||||
JSThinInlineString::new_(js::ExclusiveContext* cx)
|
JSThinInlineString::new_(js::ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
if (cx->compartment()->isAtomsCompartment())
|
if (cx->compartment()->isAtomsCompartment())
|
||||||
return (JSThinInlineString*)(js::Allocate<js::NormalAtom, allowGC>(cx->asJSContext()));
|
return (JSThinInlineString*)(js::Allocate<js::NormalAtom, allowGC>(cx));
|
||||||
|
|
||||||
return js::Allocate<JSThinInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
|
return js::Allocate<JSThinInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +283,7 @@ MOZ_ALWAYS_INLINE JSFatInlineString*
|
||||||
JSFatInlineString::new_(js::ExclusiveContext* cx)
|
JSFatInlineString::new_(js::ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
if (cx->compartment()->isAtomsCompartment())
|
if (cx->compartment()->isAtomsCompartment())
|
||||||
return (JSFatInlineString*)(js::Allocate<js::FatInlineAtom, allowGC>(cx->asJSContext()));
|
return (JSFatInlineString*)(js::Allocate<js::FatInlineAtom, allowGC>(cx));
|
||||||
|
|
||||||
return js::Allocate<JSFatInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
|
return js::Allocate<JSFatInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -497,7 +497,7 @@ JSRope::flattenInternal(ExclusiveContext* maybecx)
|
||||||
else
|
else
|
||||||
left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
|
left.d.u1.flags = DEPENDENT_FLAGS | LATIN1_CHARS_BIT;
|
||||||
left.d.s.u3.base = (JSLinearString*)this; /* will be true on exit */
|
left.d.s.u3.base = (JSLinearString*)this; /* will be true on exit */
|
||||||
Nursery& nursery = zone()->runtimeFromAnyThread()->gc.getNursery();
|
Nursery& nursery = zone()->group()->nursery();
|
||||||
bool inTenured = !bufferIfNursery;
|
bool inTenured = !bufferIfNursery;
|
||||||
if (!inTenured && left.isTenured()) {
|
if (!inTenured && left.isTenured()) {
|
||||||
// tenured leftmost child is giving its chars buffer to the
|
// tenured leftmost child is giving its chars buffer to the
|
||||||
|
|
@ -521,7 +521,7 @@ JSRope::flattenInternal(ExclusiveContext* maybecx)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isTenured()) {
|
if (!isTenured()) {
|
||||||
Nursery& nursery = zone()->runtimeFromAnyThread()->gc.getNursery();
|
Nursery& nursery = zone()->group()->nursery();
|
||||||
if (!nursery.registerMallocedBuffer(wholeChars)) {
|
if (!nursery.registerMallocedBuffer(wholeChars)) {
|
||||||
js_free(wholeChars);
|
js_free(wholeChars);
|
||||||
if (maybecx)
|
if (maybecx)
|
||||||
|
|
@ -1186,7 +1186,7 @@ JSLinearString*
|
||||||
js::NewDependentString(JSContext* cx, JSString* baseArg, size_t start, size_t length)
|
js::NewDependentString(JSContext* cx, JSString* baseArg, size_t start, size_t length)
|
||||||
{
|
{
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return cx->ExclusiveContext::emptyString();
|
return cx->emptyString();
|
||||||
|
|
||||||
JSLinearString* base = baseArg->ensureLinear(cx);
|
JSLinearString* base = baseArg->ensureLinear(cx);
|
||||||
if (!base)
|
if (!base)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ Symbol::for_(js::ExclusiveContext* cx, HandleString description)
|
||||||
|
|
||||||
AutoLockForExclusiveAccess lock(cx);
|
AutoLockForExclusiveAccess lock(cx);
|
||||||
|
|
||||||
SymbolRegistry& registry = cx->runtime()->symbolRegistry(lock);
|
SymbolRegistry& registry = cx->symbolRegistry(lock);
|
||||||
SymbolRegistry::AddPtr p = registry.lookupForAdd(atom);
|
SymbolRegistry::AddPtr p = registry.lookupForAdd(atom);
|
||||||
if (p)
|
if (p)
|
||||||
return *p;
|
return *p;
|
||||||
|
|
|
||||||
|
|
@ -328,8 +328,7 @@ class TraceLoggerThreadState
|
||||||
bool offThreadEnabled;
|
bool offThreadEnabled;
|
||||||
bool graphSpewingEnabled;
|
bool graphSpewingEnabled;
|
||||||
bool spewErrors;
|
bool spewErrors;
|
||||||
mozilla::LinkedList<TraceLoggerMainThread> traceLoggerMainThreadList;
|
mozilla::LinkedList<TraceLoggerThread> threadLoggers;
|
||||||
ThreadLoggerHashMap threadLoggers;
|
|
||||||
|
|
||||||
typedef HashMap<const void*,
|
typedef HashMap<const void*,
|
||||||
TraceLoggerEventPayload*,
|
TraceLoggerEventPayload*,
|
||||||
|
|
|
||||||
|
|
@ -4004,7 +4004,8 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
|
||||||
RootedFunction function(cx, this->function());
|
RootedFunction function(cx, this->function());
|
||||||
Vector<uint32_t, 32> pcOffsets(cx);
|
Vector<uint32_t, 32> pcOffsets(cx);
|
||||||
JSRuntime::AutoProhibitActiveContextChange apacc(cx->runtime());
|
JSRuntime::AutoProhibitActiveContextChange apacc(cx->runtime());
|
||||||
for (AllScriptFramesIter iter(cx); !iter.done(); ++iter) {
|
for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
|
||||||
|
for (AllScriptFramesIter iter(cx, target); !iter.done(); ++iter) {
|
||||||
{
|
{
|
||||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
if (!pcOffsets.append(iter.script()->pcToOffset(iter.pc())))
|
if (!pcOffsets.append(iter.script()->pcToOffset(iter.pc())))
|
||||||
|
|
@ -4088,6 +4089,7 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
|
||||||
(void) NativeObject::rollbackProperties(cx, obj, numProperties);
|
(void) NativeObject::rollbackProperties(cx, obj, numProperties);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
|
@ -4488,22 +4490,23 @@ Zone::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||||
|
|
||||||
TypeZone::TypeZone(Zone* zone)
|
TypeZone::TypeZone(Zone* zone)
|
||||||
: zone_(zone),
|
: zone_(zone),
|
||||||
typeLifoAlloc((size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
typeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||||
generation(0),
|
generation(zone->group(), 0),
|
||||||
compilerOutputs(nullptr),
|
compilerOutputs(zone->group(), nullptr),
|
||||||
sweepTypeLifoAlloc((size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
sweepTypeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||||
sweepCompilerOutputs(nullptr),
|
sweepCompilerOutputs(zone->group(), nullptr),
|
||||||
sweepReleaseTypes(false),
|
sweepReleaseTypes(zone->group(), false),
|
||||||
|
sweepingTypes(zone->group(), false),
|
||||||
keepTypeScripts(zone->group(), false),
|
keepTypeScripts(zone->group(), false),
|
||||||
activeAnalysis(nullptr)
|
activeAnalysis(zone->group(), nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeZone::~TypeZone()
|
TypeZone::~TypeZone()
|
||||||
{
|
{
|
||||||
js_delete(compilerOutputs);
|
js_delete(compilerOutputs.ref());
|
||||||
js_delete(sweepCompilerOutputs);
|
js_delete(sweepCompilerOutputs.ref());
|
||||||
MOZ_RELEASE_ASSERT(!sweepReleaseTypes);
|
MOZ_RELEASE_ASSERT(!sweepingTypes);
|
||||||
MOZ_ASSERT(!keepTypeScripts);
|
MOZ_ASSERT(!keepTypeScripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,17 +53,6 @@
|
||||||
using namespace js;
|
using namespace js;
|
||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
/* static */ gc::AllocKind
|
|
||||||
js::TypedArrayObject::AllocKindForLazyBuffer(size_t nbytes)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(nbytes <= INLINE_BUFFER_LIMIT);
|
|
||||||
if (nbytes == 0)
|
|
||||||
nbytes += sizeof(uint8_t);
|
|
||||||
size_t dataSlots = AlignBytes(nbytes, sizeof(Value)) / sizeof(Value);
|
|
||||||
MOZ_ASSERT(nbytes <= dataSlots * sizeof(Value));
|
|
||||||
return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots);
|
|
||||||
}
|
|
||||||
|
|
||||||
using mozilla::AssertedCast;
|
using mozilla::AssertedCast;
|
||||||
using JS::CanonicalizeNaN;
|
using JS::CanonicalizeNaN;
|
||||||
using JS::ToInt32;
|
using JS::ToInt32;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ template<XDRMode mode>
|
||||||
void
|
void
|
||||||
XDRState<mode>::postProcessContextErrors(ExclusiveContext* cx)
|
XDRState<mode>::postProcessContextErrors(ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
if (!cx->helperThread() && cx->isJSContext() && cx->asJSContext()->isExceptionPending()) {
|
if (!cx->helperThread() && cx->isExceptionPending()) {
|
||||||
MOZ_ASSERT(resultCode_ == JS::TranscodeResult_Ok ||
|
MOZ_ASSERT(resultCode_ == JS::TranscodeResult_Ok ||
|
||||||
resultCode_ == JS::TranscodeResult_Throw);
|
resultCode_ == JS::TranscodeResult_Throw);
|
||||||
resultCode_ = JS::TranscodeResult_Throw;
|
resultCode_ = JS::TranscodeResult_Throw;
|
||||||
|
|
|
||||||
|
|
@ -6659,7 +6659,7 @@ struct ScopedCacheEntryOpenedForWrite
|
||||||
|
|
||||||
~ScopedCacheEntryOpenedForWrite() {
|
~ScopedCacheEntryOpenedForWrite() {
|
||||||
if (memory)
|
if (memory)
|
||||||
cx->runtime()->asmJSCacheOps.closeEntryForWrite(serializedSize, memory, handle);
|
cx->asmJSCacheOps().closeEntryForWrite(serializedSize, memory, handle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -6676,7 +6676,7 @@ struct ScopedCacheEntryOpenedForRead
|
||||||
|
|
||||||
~ScopedCacheEntryOpenedForRead() {
|
~ScopedCacheEntryOpenedForRead() {
|
||||||
if (memory)
|
if (memory)
|
||||||
cx->runtime()->asmJSCacheOps.closeEntryForRead(serializedSize, memory, handle);
|
cx->asmJSCacheOps().closeEntryForRead(serializedSize, memory, handle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -6698,7 +6698,7 @@ StoreAsmJSModuleInCache(AsmJSParser& parser, Module& module, ExclusiveContext* c
|
||||||
compiledSize +
|
compiledSize +
|
||||||
moduleChars.serializedSize();
|
moduleChars.serializedSize();
|
||||||
|
|
||||||
JS::OpenAsmJSCacheEntryForWriteOp open = cx->runtime()->asmJSCacheOps.openEntryForWrite;
|
JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite;
|
||||||
if (!open)
|
if (!open)
|
||||||
return JS::AsmJSCache_Disabled_Internal;
|
return JS::AsmJSCache_Disabled_Internal;
|
||||||
|
|
||||||
|
|
@ -6737,7 +6737,7 @@ LookupAsmJSModuleInCache(ExclusiveContext* cx, AsmJSParser& parser, bool* loaded
|
||||||
|
|
||||||
*loadedFromCache = false;
|
*loadedFromCache = false;
|
||||||
|
|
||||||
JS::OpenAsmJSCacheEntryForReadOp open = cx->runtime()->asmJSCacheOps.openEntryForRead;
|
JS::OpenAsmJSCacheEntryForReadOp open = cx->asmJSCacheOps().openEntryForRead;
|
||||||
if (!open)
|
if (!open)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -290,11 +290,8 @@ class BaseCompiler
|
||||||
RegI32() : reg(Register::Invalid()) {}
|
RegI32() : reg(Register::Invalid()) {}
|
||||||
explicit RegI32(Register reg) : reg(reg) {}
|
explicit RegI32(Register reg) : reg(reg) {}
|
||||||
Register reg;
|
Register reg;
|
||||||
operator Register() const { return reg; }
|
|
||||||
bool operator==(const RegI32& that) { return reg == that.reg; }
|
bool operator==(const RegI32& that) { return reg == that.reg; }
|
||||||
bool operator!=(const RegI32& that) { return reg != that.reg; }
|
bool operator!=(const RegI32& that) { return reg != that.reg; }
|
||||||
bool operator==(Register that) const { return reg == that; }
|
|
||||||
bool operator!=(Register that) const { return reg != that; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegI64
|
struct RegI64
|
||||||
|
|
@ -302,7 +299,6 @@ class BaseCompiler
|
||||||
RegI64() : reg(Register64::Invalid()) {}
|
RegI64() : reg(Register64::Invalid()) {}
|
||||||
explicit RegI64(Register64 reg) : reg(reg) {}
|
explicit RegI64(Register64 reg) : reg(reg) {}
|
||||||
Register64 reg;
|
Register64 reg;
|
||||||
operator Register64() const { return reg; }
|
|
||||||
bool operator==(const RegI64& that) { return reg == that.reg; }
|
bool operator==(const RegI64& that) { return reg == that.reg; }
|
||||||
bool operator!=(const RegI64& that) { return reg != that.reg; }
|
bool operator!=(const RegI64& that) { return reg != that.reg; }
|
||||||
};
|
};
|
||||||
|
|
@ -312,7 +308,6 @@ class BaseCompiler
|
||||||
RegF32() {}
|
RegF32() {}
|
||||||
explicit RegF32(FloatRegister reg) : reg(reg) {}
|
explicit RegF32(FloatRegister reg) : reg(reg) {}
|
||||||
FloatRegister reg;
|
FloatRegister reg;
|
||||||
operator FloatRegister() const { return reg; }
|
|
||||||
bool operator==(const RegF32& that) { return reg == that.reg; }
|
bool operator==(const RegF32& that) { return reg == that.reg; }
|
||||||
bool operator!=(const RegF32& that) { return reg != that.reg; }
|
bool operator!=(const RegF32& that) { return reg != that.reg; }
|
||||||
};
|
};
|
||||||
|
|
@ -322,7 +317,6 @@ class BaseCompiler
|
||||||
RegF64() {}
|
RegF64() {}
|
||||||
explicit RegF64(FloatRegister reg) : reg(reg) {}
|
explicit RegF64(FloatRegister reg) : reg(reg) {}
|
||||||
FloatRegister reg;
|
FloatRegister reg;
|
||||||
operator FloatRegister() const { return reg; }
|
|
||||||
bool operator==(const RegF64& that) { return reg == that.reg; }
|
bool operator==(const RegF64& that) { return reg == that.reg; }
|
||||||
bool operator!=(const RegF64& that) { return reg != that.reg; }
|
bool operator!=(const RegF64& that) { return reg != that.reg; }
|
||||||
};
|
};
|
||||||
|
|
@ -417,17 +411,6 @@ class BaseCompiler
|
||||||
bool deadThenBranch; // deadCode_ was set on exit from "then"
|
bool deadThenBranch; // deadCode_ was set on exit from "then"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BranchState {
|
|
||||||
enum { NoPop = UINT32_MAX };
|
|
||||||
Label* label;
|
|
||||||
uint32_t framePushed;
|
|
||||||
InvertBranch invert;
|
|
||||||
ExprType type;
|
|
||||||
BranchState(Label* label, uint32_t framePushed, InvertBranch invert,
|
|
||||||
ExprType type = ExprType::Void)
|
|
||||||
: label(label), framePushed(framePushed), invert(invert), type(type) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BaseCompilePolicy : OpIterPolicy
|
struct BaseCompilePolicy : OpIterPolicy
|
||||||
{
|
{
|
||||||
static const bool Output = true;
|
static const bool Output = true;
|
||||||
|
|
@ -536,9 +519,7 @@ class BaseCompiler
|
||||||
NonAssertingLabel stackOverflowLabel_;
|
NonAssertingLabel stackOverflowLabel_;
|
||||||
TrapOffset prologueTrapOffset_;
|
TrapOffset prologueTrapOffset_;
|
||||||
|
|
||||||
FuncOffsets offsets_;
|
FuncCompileResults& compileResults_;
|
||||||
NonAssertingLabel bodyLabel_;
|
|
||||||
Label outOfLinePrologue_;
|
|
||||||
MacroAssembler& masm; // No '_' suffix - too tedious...
|
MacroAssembler& masm; // No '_' suffix - too tedious...
|
||||||
|
|
||||||
AllocatableGeneralRegisterSet availGPR_;
|
AllocatableGeneralRegisterSet availGPR_;
|
||||||
|
|
@ -599,7 +580,6 @@ class BaseCompiler
|
||||||
MOZ_MUST_USE bool init();
|
MOZ_MUST_USE bool init();
|
||||||
|
|
||||||
void finish();
|
void finish();
|
||||||
const FuncOffsets& offsets() const { return offsets_; }
|
|
||||||
|
|
||||||
MOZ_MUST_USE bool emitFunction();
|
MOZ_MUST_USE bool emitFunction();
|
||||||
|
|
||||||
|
|
@ -943,7 +923,6 @@ class BaseCompiler
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Stk, 8, SystemAllocPolicy> stk_;
|
Vector<Stk, 8, SystemAllocPolicy> stk_;
|
||||||
Vector<Control, 8, SystemAllocPolicy> ctl_;
|
|
||||||
|
|
||||||
Stk& push() {
|
Stk& push() {
|
||||||
stk_.infallibleEmplaceBack(Stk());
|
stk_.infallibleEmplaceBack(Stk());
|
||||||
|
|
@ -1130,8 +1109,8 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadRegisterI32(Register r, Stk& src) {
|
void loadRegisterI32(Register r, Stk& src) {
|
||||||
if (src.i32reg().reg != r)
|
if (src.i32reg() != r)
|
||||||
masm.move32(src.i32reg().reg, r);
|
masm.move32(src.i32reg(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadConstI64(Register64 r, Stk &src) {
|
void loadConstI64(Register64 r, Stk &src) {
|
||||||
|
|
@ -1147,8 +1126,8 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadRegisterI64(Register64 r, Stk& src) {
|
void loadRegisterI64(Register64 r, Stk& src) {
|
||||||
if (src.i64reg().reg != r)
|
if (src.i64reg() != r)
|
||||||
masm.move64(src.i64reg().reg, r);
|
masm.move64(src.i64reg(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadConstF64(FloatRegister r, Stk &src) {
|
void loadConstF64(FloatRegister r, Stk &src) {
|
||||||
|
|
@ -1166,8 +1145,8 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadRegisterF64(FloatRegister r, Stk& src) {
|
void loadRegisterF64(FloatRegister r, Stk& src) {
|
||||||
if (src.f64reg().reg != r)
|
if (src.f64reg() != r)
|
||||||
masm.moveDouble(src.f64reg().reg, r);
|
masm.moveDouble(src.f64reg(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadConstF32(FloatRegister r, Stk &src) {
|
void loadConstF32(FloatRegister r, Stk &src) {
|
||||||
|
|
@ -1185,8 +1164,8 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadRegisterF32(FloatRegister r, Stk& src) {
|
void loadRegisterF32(FloatRegister r, Stk& src) {
|
||||||
if (src.f32reg().reg != r)
|
if (src.f32reg() != r)
|
||||||
masm.moveFloat32(src.f32reg().reg, r);
|
masm.moveFloat32(src.f32reg(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadI32(Register r, Stk& src) {
|
void loadI32(Register r, Stk& src) {
|
||||||
|
|
@ -1286,9 +1265,7 @@ class BaseCompiler
|
||||||
void loadF64(FloatRegister r, Stk& src) {
|
void loadF64(FloatRegister r, Stk& src) {
|
||||||
switch (src.kind()) {
|
switch (src.kind()) {
|
||||||
case Stk::ConstF64:
|
case Stk::ConstF64:
|
||||||
double value;
|
masm.loadConstantDouble(src.f64val(), r);
|
||||||
src.f64val(&value);
|
|
||||||
masm.loadConstantDouble(value, r);
|
|
||||||
break;
|
break;
|
||||||
case Stk::MemF64:
|
case Stk::MemF64:
|
||||||
loadFromFrameF64(r, src.offs());
|
loadFromFrameF64(r, src.offs());
|
||||||
|
|
@ -1310,9 +1287,7 @@ class BaseCompiler
|
||||||
void loadF32(FloatRegister r, Stk& src) {
|
void loadF32(FloatRegister r, Stk& src) {
|
||||||
switch (src.kind()) {
|
switch (src.kind()) {
|
||||||
case Stk::ConstF32:
|
case Stk::ConstF32:
|
||||||
float value;
|
masm.loadConstantFloat32(src.f32val(), r);
|
||||||
src.f32val(&value);
|
|
||||||
masm.loadConstantFloat32(value, r);
|
|
||||||
break;
|
break;
|
||||||
case Stk::MemF32:
|
case Stk::MemF32:
|
||||||
loadFromFrameF32(r, src.offs());
|
loadFromFrameF32(r, src.offs());
|
||||||
|
|
@ -1867,23 +1842,6 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_MUST_USE AnyReg captureJoinRegUnlessVoid(ExprType type) {
|
|
||||||
switch (type) {
|
|
||||||
case ExprType::I32:
|
|
||||||
return AnyReg(joinRegI32);
|
|
||||||
case ExprType::I64:
|
|
||||||
return AnyReg(joinRegI64);
|
|
||||||
case ExprType::F32:
|
|
||||||
return AnyReg(joinRegF32);
|
|
||||||
case ExprType::F64:
|
|
||||||
return AnyReg(joinRegF64);
|
|
||||||
case ExprType::Void:
|
|
||||||
return AnyReg();
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("Compiler bug: unexpected join type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_MUST_USE AnyReg allocJoinReg(ExprType type) {
|
MOZ_MUST_USE AnyReg allocJoinReg(ExprType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ExprType::I32:
|
case ExprType::I32:
|
||||||
|
|
@ -1925,20 +1883,6 @@ class BaseCompiler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pushJoinRegUnlessVoid(AnyReg r) {
|
|
||||||
if (r.tag != AnyReg::NONE)
|
|
||||||
pushJoinReg(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitBranchSetup(BranchState* b) {
|
|
||||||
if (b->framePushed != BranchState::NoPop)
|
|
||||||
popStackOnBlockExit(b->framePushed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void emitBranchPerform(BranchState* b) {
|
|
||||||
masm.jump(b->label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void freeJoinReg(AnyReg r) {
|
void freeJoinReg(AnyReg r) {
|
||||||
switch (r.tag) {
|
switch (r.tag) {
|
||||||
case AnyReg::NONE:
|
case AnyReg::NONE:
|
||||||
|
|
@ -2221,17 +2165,17 @@ class BaseCompiler
|
||||||
case ExprType::Void:
|
case ExprType::Void:
|
||||||
break;
|
break;
|
||||||
case ExprType::I32:
|
case ExprType::I32:
|
||||||
masm.store32(RegI32(ReturnReg).reg, resultsAddress);
|
masm.store32(RegI32(ReturnReg), resultsAddress);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExprType::I64:
|
case ExprType::I64:
|
||||||
masm.store64(RegI64(ReturnReg64).reg, resultsAddress);
|
masm.store64(RegI64(ReturnReg64), resultsAddress);
|
||||||
break;
|
break;
|
||||||
case ExprType::F64:
|
case ExprType::F64:
|
||||||
masm.storeDouble(RegF64(ReturnDoubleReg).reg, resultsAddress);
|
masm.storeDouble(RegF64(ReturnDoubleReg), resultsAddress);
|
||||||
break;
|
break;
|
||||||
case ExprType::F32:
|
case ExprType::F32:
|
||||||
masm.storeFloat32(RegF32(ReturnFloat32Reg).reg, resultsAddress);
|
masm.storeFloat32(RegF32(ReturnFloat32Reg), resultsAddress);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Function return type");
|
MOZ_CRASH("Function return type");
|
||||||
|
|
@ -2307,7 +2251,7 @@ class BaseCompiler
|
||||||
// Restore the TLS register in case it was overwritten by the function.
|
// Restore the TLS register in case it was overwritten by the function.
|
||||||
loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
|
loadFromFramePtr(WasmTlsReg, frameOffsetFromSlot(tlsSlot_, MIRType::Pointer));
|
||||||
|
|
||||||
GenerateFunctionEpilogue(masm, localSize_, &offsets_);
|
GenerateFunctionEpilogue(masm, localSize_, &compileResults_.offsets());
|
||||||
|
|
||||||
#if defined(JS_ION_PERF)
|
#if defined(JS_ION_PERF)
|
||||||
// FIXME - profiling code missing. Bug 1286948.
|
// FIXME - profiling code missing. Bug 1286948.
|
||||||
|
|
@ -2321,7 +2265,7 @@ class BaseCompiler
|
||||||
|
|
||||||
masm.wasmEmitTrapOutOfLineCode();
|
masm.wasmEmitTrapOutOfLineCode();
|
||||||
|
|
||||||
offsets_.end = masm.currentOffset();
|
compileResults_.offsets().end = masm.currentOffset();
|
||||||
|
|
||||||
// A frame greater than 256KB is implausible, probably an attack,
|
// A frame greater than 256KB is implausible, probably an attack,
|
||||||
// so fail the compilation.
|
// so fail the compilation.
|
||||||
|
|
@ -2739,7 +2683,7 @@ class BaseCompiler
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void returnCleanup(bool popStack = false) {
|
void returnCleanup(bool popStack) {
|
||||||
if (popStack)
|
if (popStack)
|
||||||
popStackBeforeBranch(controlOutermost().framePushed);
|
popStackBeforeBranch(controlOutermost().framePushed);
|
||||||
masm.jump(&returnLabel_);
|
masm.jump(&returnLabel_);
|
||||||
|
|
@ -5584,7 +5528,6 @@ BaseCompiler::emitIf()
|
||||||
if (!iter_.readIf(&unused_cond))
|
if (!iter_.readIf(&unused_cond))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RegI32 rc;
|
|
||||||
BranchState b(&controlItem().otherLabel, BranchState::NoPop, InvertBranch(true));
|
BranchState b(&controlItem().otherLabel, BranchState::NoPop, InvertBranch(true));
|
||||||
if (!deadCode_) {
|
if (!deadCode_) {
|
||||||
rc = popI32();
|
rc = popI32();
|
||||||
|
|
@ -5594,7 +5537,7 @@ BaseCompiler::emitIf()
|
||||||
initControl(controlItem());
|
initControl(controlItem());
|
||||||
|
|
||||||
if (!deadCode_) {
|
if (!deadCode_) {
|
||||||
masm.branch32(Assembler::Equal, rc.reg, Imm32(0), &controlItem(0).otherLabel);
|
masm.branch32(Assembler::Equal, rc.reg, Imm32(0), controlItem(0).otherLabel);
|
||||||
freeI32(rc);
|
freeI32(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6540,7 +6483,7 @@ BaseCompiler::emitSetGlobal()
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
Nothing unused_value;
|
Nothing unused_value;
|
||||||
if (!iter_.readSetGlobal(env_.globals, &id, &unused_value))
|
if (!iter_.readSetGlobal(mg_.globals, &id, &unused_value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (deadCode_)
|
if (deadCode_)
|
||||||
|
|
@ -6580,7 +6523,6 @@ BaseCompiler::emitSetGlobal()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool
|
bool
|
||||||
BaseCompiler::emitSetGlobal()
|
BaseCompiler::emitSetGlobal()
|
||||||
{
|
{
|
||||||
|
|
@ -6591,7 +6533,6 @@ BaseCompiler::emitSetGlobal()
|
||||||
|
|
||||||
return emitSetOrTeeGlobal<true>(id);
|
return emitSetOrTeeGlobal<true>(id);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BaseCompiler::emitTeeGlobal()
|
BaseCompiler::emitTeeGlobal()
|
||||||
|
|
@ -6604,7 +6545,7 @@ BaseCompiler::emitTeeGlobal()
|
||||||
if (deadCode_)
|
if (deadCode_)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
const GlobalDesc& global = env_.globals[id];
|
const GlobalDesc& global = mg_.globals[id];
|
||||||
|
|
||||||
switch (global.type()) {
|
switch (global.type()) {
|
||||||
case ValType::I32: {
|
case ValType::I32: {
|
||||||
|
|
@ -6847,7 +6788,7 @@ BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
|
||||||
|
|
||||||
MemoryAccessDesc access(viewType, addr.align, addr.offset, trapIfNotAsmJS());
|
MemoryAccessDesc access(viewType, addr.align, addr.offset, trapIfNotAsmJS());
|
||||||
|
|
||||||
size_t temps = storeTemps(access);
|
size_t temps = loadStoreTemps(access);
|
||||||
RegI32 tmp1 = temps >= 1 ? needI32() : invalidI32();
|
RegI32 tmp1 = temps >= 1 ? needI32() : invalidI32();
|
||||||
RegI32 tmp2 = temps >= 2 ? needI32() : invalidI32();
|
RegI32 tmp2 = temps >= 2 ? needI32() : invalidI32();
|
||||||
|
|
||||||
|
|
@ -6855,7 +6796,7 @@ BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
|
||||||
case ValType::I32: {
|
case ValType::I32: {
|
||||||
RegI32 rp, rv;
|
RegI32 rp, rv;
|
||||||
pop2xI32(&rp, &rv);
|
pop2xI32(&rp, &rv);
|
||||||
if (!store(access, rp, false, AnyReg(rv), tmp1))
|
if (!store(access, rp, AnyReg(rv), tmp1, tmp2))
|
||||||
return false;
|
return false;
|
||||||
freeI32(rp);
|
freeI32(rp);
|
||||||
pushI32(rv);
|
pushI32(rv);
|
||||||
|
|
@ -6864,7 +6805,7 @@ BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
|
||||||
case ValType::I64: {
|
case ValType::I64: {
|
||||||
RegI64 rv = popI64();
|
RegI64 rv = popI64();
|
||||||
RegI32 rp = popI32();
|
RegI32 rp = popI32();
|
||||||
if (!store(access, rp, false, AnyReg(rv), tmp1))
|
if (!store(access, rp, AnyReg(rv), tmp1, tmp2))
|
||||||
return false;
|
return false;
|
||||||
freeI32(rp);
|
freeI32(rp);
|
||||||
pushI64(rv);
|
pushI64(rv);
|
||||||
|
|
@ -6873,7 +6814,7 @@ BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
|
||||||
case ValType::F32: {
|
case ValType::F32: {
|
||||||
RegF32 rv = popF32();
|
RegF32 rv = popF32();
|
||||||
RegI32 rp = popI32();
|
RegI32 rp = popI32();
|
||||||
if (!store(access, rp, false, AnyReg(rv), tmp1))
|
if (!store(access, rp, AnyReg(rv), tmp1, tmp2))
|
||||||
return false;
|
return false;
|
||||||
freeI32(rp);
|
freeI32(rp);
|
||||||
pushF32(rv);
|
pushF32(rv);
|
||||||
|
|
@ -6882,7 +6823,7 @@ BaseCompiler::emitTeeStore(ValType resultType, Scalar::Type viewType)
|
||||||
case ValType::F64: {
|
case ValType::F64: {
|
||||||
RegF64 rv = popF64();
|
RegF64 rv = popF64();
|
||||||
RegI32 rp = popI32();
|
RegI32 rp = popI32();
|
||||||
if (!store(access, rp, false, AnyReg(rv), tmp1))
|
if (!store(access, rp, AnyReg(rv), tmp1, tmp2))
|
||||||
return false;
|
return false;
|
||||||
freeI32(rp);
|
freeI32(rp);
|
||||||
pushF64(rv);
|
pushF64(rv);
|
||||||
|
|
@ -8096,7 +8037,7 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
|
||||||
iter_(decoder, func.lineOrBytecode()),
|
iter_(decoder, func.lineOrBytecode()),
|
||||||
func_(func),
|
func_(func),
|
||||||
lastReadCallSite_(0),
|
lastReadCallSite_(0),
|
||||||
alloc_(*alloc),
|
alloc_(compileResults.alloc()),
|
||||||
locals_(locals),
|
locals_(locals),
|
||||||
localSize_(0),
|
localSize_(0),
|
||||||
varLow_(0),
|
varLow_(0),
|
||||||
|
|
@ -8105,7 +8046,8 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
|
||||||
deadCode_(false),
|
deadCode_(false),
|
||||||
debugEnabled_(debugEnabled),
|
debugEnabled_(debugEnabled),
|
||||||
prologueTrapOffset_(trapOffset()),
|
prologueTrapOffset_(trapOffset()),
|
||||||
masm(*masm),
|
compileResults_(compileResults),
|
||||||
|
masm(compileResults_.masm()),
|
||||||
availGPR_(GeneralRegisterSet::All()),
|
availGPR_(GeneralRegisterSet::All()),
|
||||||
availFPU_(FloatRegisterSet::All()),
|
availFPU_(FloatRegisterSet::All()),
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -8306,7 +8248,7 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::wasm::BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars *error)
|
js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars *error)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Baseline);
|
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Baseline);
|
||||||
|
|
||||||
|
|
@ -8330,7 +8272,7 @@ js::wasm::BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, U
|
||||||
|
|
||||||
// The MacroAssembler will sometimes access the jitContext.
|
// The MacroAssembler will sometimes access the jitContext.
|
||||||
|
|
||||||
JitContext jitContext(&task->alloc());
|
JitContext jitContext(&results.alloc());
|
||||||
|
|
||||||
// One-pass baseline compilation.
|
// One-pass baseline compilation.
|
||||||
|
|
||||||
|
|
@ -8343,8 +8285,6 @@ js::wasm::BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, U
|
||||||
|
|
||||||
f.finish();
|
f.finish();
|
||||||
|
|
||||||
unit->finish(f.offsets());
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#define asmjs_wasm_baseline_compile_h
|
#define asmjs_wasm_baseline_compile_h
|
||||||
|
|
||||||
#include "wasm/WasmTypes.h"
|
#include "wasm/WasmTypes.h"
|
||||||
#include "wasm/WasmGenerator.h"
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
@ -40,7 +39,7 @@ BaselineCanCompile(const FunctionGenerator* fg);
|
||||||
|
|
||||||
// Generate adequate code quickly.
|
// Generate adequate code quickly.
|
||||||
bool
|
bool
|
||||||
BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
|
BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
|
||||||
|
|
@ -72,9 +72,8 @@ AllocateCodeSegment(JSContext* cx, uint32_t codeLength)
|
||||||
// to purge all memory (which, in gecko, does a purging GC/CC/GC), do that
|
// to purge all memory (which, in gecko, does a purging GC/CC/GC), do that
|
||||||
// then retry the allocation.
|
// then retry the allocation.
|
||||||
if (!p) {
|
if (!p) {
|
||||||
JSRuntime* rt = cx->runtime();
|
if (OnLargeAllocationFailure) {
|
||||||
if (rt->largeAllocationFailureCallback) {
|
OnLargeAllocationFailure();
|
||||||
rt->largeAllocationFailureCallback(rt->largeAllocationFailureCallbackData);
|
|
||||||
p = AllocateExecutableMemory(codeLength, ProtectionSetting::Writable);
|
p = AllocateExecutableMemory(codeLength, ProtectionSetting::Writable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -428,12 +428,13 @@ bool
|
||||||
ModuleGenerator::finishTask(IonCompileTask* task)
|
ModuleGenerator::finishTask(IonCompileTask* task)
|
||||||
{
|
{
|
||||||
const FuncBytes& func = task->func();
|
const FuncBytes& func = task->func();
|
||||||
|
FuncCompileResults& results = task->results();
|
||||||
|
|
||||||
masm_.haltingAlign(CodeAlignment);
|
masm_.haltingAlign(CodeAlignment);
|
||||||
|
|
||||||
// Before merging in the new function's code, if calls in a prior function
|
// Before merging in the new function's code, if calls in a prior function
|
||||||
// body might go out of range, insert far jumps to extend the range.
|
// body might go out of range, insert far jumps to extend the range.
|
||||||
if ((masm_.size() - startOfUnpatchedCallsites_) + task->masm().size() > JumpRange()) {
|
if ((masm_.size() - startOfUnpatchedCallsites_) + results.masm().size() > JumpRange()) {
|
||||||
startOfUnpatchedCallsites_ = masm_.size();
|
startOfUnpatchedCallsites_ = masm_.size();
|
||||||
if (!patchCallSites())
|
if (!patchCallSites())
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -442,12 +443,11 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
||||||
// Offset the recorded FuncOffsets by the offset of the function in the
|
// Offset the recorded FuncOffsets by the offset of the function in the
|
||||||
// whole module's code segment.
|
// whole module's code segment.
|
||||||
uint32_t offsetInWhole = masm_.size();
|
uint32_t offsetInWhole = masm_.size();
|
||||||
FuncOffsets offsets = task->units().back().offsets();
|
results.offsets().offsetBy(offsetInWhole);
|
||||||
offsets.offsetBy(offsetInWhole);
|
|
||||||
|
|
||||||
// Add the CodeRange for this function.
|
// Add the CodeRange for this function.
|
||||||
uint32_t funcCodeRangeIndex = metadata_->codeRanges.length();
|
uint32_t funcCodeRangeIndex = metadata_->codeRanges.length();
|
||||||
if (!metadata_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), offsets))
|
if (!metadata_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), results.offsets()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MOZ_ASSERT(!funcIsCompiled(func.index()));
|
MOZ_ASSERT(!funcIsCompiled(func.index()));
|
||||||
|
|
@ -455,9 +455,9 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
||||||
|
|
||||||
// Merge the compiled results into the whole-module masm.
|
// Merge the compiled results into the whole-module masm.
|
||||||
mozilla::DebugOnly<size_t> sizeBefore = masm_.size();
|
mozilla::DebugOnly<size_t> sizeBefore = masm_.size();
|
||||||
if (!masm_.asmMergeWith(task->masm()))
|
if (!masm_.asmMergeWith(results.masm()))
|
||||||
return false;
|
return false;
|
||||||
MOZ_ASSERT(masm_.size() == offsetInWhole + task->masm().size());
|
MOZ_ASSERT(masm_.size() == offsetInWhole + results.masm().size());
|
||||||
|
|
||||||
freeTasks_.infallibleAppend(task);
|
freeTasks_.infallibleAppend(task);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -934,11 +934,11 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, FunctionGenerator* fg)
|
||||||
if (!func)
|
if (!func)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IonCompileTask::CompileMode mode;
|
CompileMode mode;
|
||||||
if ((alwaysBaseline_ || debugEnabled_) && BaselineCanCompile(fg)) {
|
if ((alwaysBaseline_ || debugEnabled_) && BaselineCanCompile(fg)) {
|
||||||
mode = IonCompileTask::CompileMode::Baseline;
|
mode = CompileMode::Baseline;
|
||||||
} else {
|
} else {
|
||||||
mode = IonCompileTask::CompileMode::Ion;
|
mode = CompileMode::Ion;
|
||||||
// Ion does not support debugging -- reset debugEnabled_ flags to avoid
|
// Ion does not support debugging -- reset debugEnabled_ flags to avoid
|
||||||
// turning debugging for wasm::Code.
|
// turning debugging for wasm::Code.
|
||||||
debugEnabled_ = false;
|
debugEnabled_ = false;
|
||||||
|
|
@ -1177,7 +1177,7 @@ ModuleGenerator::finish(const ShareableBytes& bytecode)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm::CompileFunction(IonCompileTask* task, UniqueChars* error)
|
wasm::CompileFunction(CompileTask* task, UniqueChars* error)
|
||||||
{
|
{
|
||||||
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
||||||
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
|
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
|
||||||
|
|
|
||||||
|
|
@ -54,15 +54,6 @@ class FuncBytes
|
||||||
lineOrBytecode_(UINT32_MAX)
|
lineOrBytecode_(UINT32_MAX)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
FuncBytes(Bytes bytes, uint32_t index, const SigWithId& sig,
|
|
||||||
uint32_t lineOrBytecode, Uint32Vector callSiteLineNums)
|
|
||||||
: bytes_(Move(bytes)),
|
|
||||||
index_(index),
|
|
||||||
sig_(&sig),
|
|
||||||
lineOrBytecode_(lineOrBytecode),
|
|
||||||
callSiteLineNums_(Move(callSiteLineNums))
|
|
||||||
{}
|
|
||||||
|
|
||||||
Bytes& bytes() {
|
Bytes& bytes() {
|
||||||
return bytes_;
|
return bytes_;
|
||||||
}
|
}
|
||||||
|
|
@ -146,12 +137,8 @@ typedef Vector<FuncCompileUnit, 8, SystemAllocPolicy> FuncCompileUnitVector;
|
||||||
// finally sent back to the validation thread. To save time allocating and
|
// finally sent back to the validation thread. To save time allocating and
|
||||||
// freeing memory, CompileTasks are reset() and reused.
|
// freeing memory, CompileTasks are reset() and reused.
|
||||||
|
|
||||||
class IonCompileTask
|
class CompileTask
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
enum class CompileMode { None, Baseline, Ion };
|
|
||||||
|
|
||||||
private:
|
|
||||||
const ModuleEnvironment& env_;
|
const ModuleEnvironment& env_;
|
||||||
LifoAlloc lifo_;
|
LifoAlloc lifo_;
|
||||||
Maybe<jit::TempAllocator> alloc_;
|
Maybe<jit::TempAllocator> alloc_;
|
||||||
|
|
@ -159,8 +146,8 @@ class IonCompileTask
|
||||||
FuncCompileUnitVector units_;
|
FuncCompileUnitVector units_;
|
||||||
bool debugEnabled_;
|
bool debugEnabled_;
|
||||||
|
|
||||||
IonCompileTask(const IonCompileTask&) = delete;
|
CompileTask(const CompileTask&) = delete;
|
||||||
IonCompileTask& operator=(const IonCompileTask&) = delete;
|
CompileTask& operator=(const CompileTask&) = delete;
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
alloc_.emplace(&lifo_);
|
alloc_.emplace(&lifo_);
|
||||||
|
|
@ -169,7 +156,7 @@ class IonCompileTask
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IonCompileTask(const ModuleEnvironment& env, size_t defaultChunkSize)
|
CompileTask(const ModuleEnvironment& env, size_t defaultChunkSize)
|
||||||
: env_(env),
|
: env_(env),
|
||||||
lifo_(defaultChunkSize)
|
lifo_(defaultChunkSize)
|
||||||
{
|
{
|
||||||
|
|
@ -190,38 +177,12 @@ class IonCompileTask
|
||||||
FuncCompileUnitVector& units() {
|
FuncCompileUnitVector& units() {
|
||||||
return units_;
|
return units_;
|
||||||
}
|
}
|
||||||
const FuncBytes& func() const {
|
|
||||||
MOZ_ASSERT(!units_.empty());
|
|
||||||
return units_[0].func();
|
|
||||||
}
|
|
||||||
CompileMode mode() const {
|
|
||||||
if (units_.empty())
|
|
||||||
return CompileMode::None;
|
|
||||||
return units_[0].mode() == ::js::wasm::CompileMode::Baseline
|
|
||||||
? CompileMode::Baseline
|
|
||||||
: CompileMode::Ion;
|
|
||||||
}
|
|
||||||
bool debugEnabled() const {
|
bool debugEnabled() const {
|
||||||
return debugEnabled_;
|
return debugEnabled_;
|
||||||
}
|
}
|
||||||
void setDebugEnabled(bool enabled) {
|
void setDebugEnabled(bool enabled) {
|
||||||
debugEnabled_ = enabled;
|
debugEnabled_ = enabled;
|
||||||
}
|
}
|
||||||
void init(UniqueFuncBytes func, CompileMode mode) {
|
|
||||||
units_.infallibleEmplaceBack(Move(func),
|
|
||||||
mode == CompileMode::Baseline
|
|
||||||
? ::js::wasm::CompileMode::Baseline
|
|
||||||
: ::js::wasm::CompileMode::Ion);
|
|
||||||
}
|
|
||||||
bool reset(Bytes* unused) {
|
|
||||||
(void)unused;
|
|
||||||
units_.clear();
|
|
||||||
masm_.reset();
|
|
||||||
alloc_.reset();
|
|
||||||
lifo_.releaseAll();
|
|
||||||
init();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool reset(UniqueFuncBytesVector* freeFuncBytes) {
|
bool reset(UniqueFuncBytesVector* freeFuncBytes) {
|
||||||
for (FuncCompileUnit& unit : units_) {
|
for (FuncCompileUnit& unit : units_) {
|
||||||
if (!freeFuncBytes->emplaceBack(Move(unit.recycle())))
|
if (!freeFuncBytes->emplaceBack(Move(unit.recycle())))
|
||||||
|
|
@ -279,8 +240,6 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||||
uint32_t outstanding_;
|
uint32_t outstanding_;
|
||||||
IonCompileTaskVector tasks_;
|
IonCompileTaskVector tasks_;
|
||||||
IonCompileTaskPtrVector freeTasks_;
|
IonCompileTaskPtrVector freeTasks_;
|
||||||
IonCompileTask* currentTask_ = nullptr;
|
|
||||||
size_t batchedBytecode_ = 0;
|
|
||||||
|
|
||||||
// Assertions
|
// Assertions
|
||||||
DebugOnly<FunctionGenerator*> activeFuncDef_;
|
DebugOnly<FunctionGenerator*> activeFuncDef_;
|
||||||
|
|
@ -295,7 +254,7 @@ public:
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] bool patchCallSites(TrapExitOffsetArray* maybeTrapExits = nullptr);
|
[[nodiscard]] bool patchCallSites(TrapExitOffsetArray* maybeTrapExits = nullptr);
|
||||||
[[nodiscard]] bool patchFarJumps(const TrapExitOffsetArray& trapExits, const Offsets& debugTrapStub);
|
[[nodiscard]] bool patchFarJumps(const TrapExitOffsetArray& trapExits, const Offsets& debugTrapStub);
|
||||||
[[nodiscard]] bool finishTask(IonCompileTask* task);
|
[[nodiscard]] bool finishTask(CompileTask* task);
|
||||||
[[nodiscard]] bool finishOutstandingTask();
|
[[nodiscard]] bool finishOutstandingTask();
|
||||||
[[nodiscard]] bool finishFuncExports();
|
[[nodiscard]] bool finishFuncExports();
|
||||||
[[nodiscard]] bool finishCodegen();
|
[[nodiscard]] bool finishCodegen();
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,7 @@ Instance::Instance(JSContext* cx,
|
||||||
tlsData()->instance = this;
|
tlsData()->instance = this;
|
||||||
tlsData()->globalData = globals_->globalData();
|
tlsData()->globalData = globals_->globalData();
|
||||||
tlsData()->memoryBase = memory ? memory->buffer().dataPointerEither().unwrap() : nullptr;
|
tlsData()->memoryBase = memory ? memory->buffer().dataPointerEither().unwrap() : nullptr;
|
||||||
tlsData()->stackLimit = *(void**)cx->stackLimitAddressForJitCode(js::StackForUntrustedScript);
|
tlsData()->stackLimit = *(void**)cx->stackLimitAddressForJitCode(JS::StackForUntrustedScript);
|
||||||
|
|
||||||
for (size_t i = 0; i < metadata().funcImports.length(); i++) {
|
for (size_t i = 0; i < metadata().funcImports.length(); i++) {
|
||||||
HandleFunction f = funcImports[i];
|
HandleFunction f = funcImports[i];
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,8 @@ class FunctionCompiler
|
||||||
uint32_t blockDepth_;
|
uint32_t blockDepth_;
|
||||||
ControlFlowPatchsVector blockPatches_;
|
ControlFlowPatchsVector blockPatches_;
|
||||||
|
|
||||||
|
FuncCompileResults& compileResults_;
|
||||||
|
|
||||||
// TLS pointer argument to the current function.
|
// TLS pointer argument to the current function.
|
||||||
MWasmParameter* tlsPointer_;
|
MWasmParameter* tlsPointer_;
|
||||||
|
|
||||||
|
|
@ -188,12 +190,14 @@ class FunctionCompiler
|
||||||
maxStackArgBytes_(0),
|
maxStackArgBytes_(0),
|
||||||
loopDepth_(0),
|
loopDepth_(0),
|
||||||
blockDepth_(0),
|
blockDepth_(0),
|
||||||
|
compileResults_(compileResults),
|
||||||
tlsPointer_(nullptr)
|
tlsPointer_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const ModuleEnvironment& env() const { return env_; }
|
const ModuleEnvironment& env() const { return env_; }
|
||||||
IonOpIter& iter() { return iter_; }
|
IonOpIter& iter() { return iter_; }
|
||||||
TempAllocator& alloc() const { return alloc_; }
|
TempAllocator& alloc() const { return alloc_; }
|
||||||
|
MacroAssembler& masm() const { return compileResults_.masm(); }
|
||||||
const Sig& sig() const { return func_.sig(); }
|
const Sig& sig() const { return func_.sig(); }
|
||||||
|
|
||||||
TrapOffset trapOffset() const {
|
TrapOffset trapOffset() const {
|
||||||
|
|
@ -2887,7 +2891,7 @@ EmitExpr(FunctionCompiler& f)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
wasm::IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
|
wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Ion);
|
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Ion);
|
||||||
|
|
||||||
|
|
@ -2915,11 +2919,11 @@ wasm::IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChar
|
||||||
|
|
||||||
// Set up for Ion compilation.
|
// Set up for Ion compilation.
|
||||||
|
|
||||||
JitContext jitContext(&task->alloc());
|
JitContext jitContext(&results.alloc());
|
||||||
const JitCompileOptions options;
|
const JitCompileOptions options;
|
||||||
MIRGraph graph(&task->alloc());
|
MIRGraph graph(&results.alloc());
|
||||||
CompileInfo compileInfo(locals.length());
|
CompileInfo compileInfo(locals.length());
|
||||||
MIRGenerator mir(nullptr, options, &task->alloc(), &graph, &compileInfo,
|
MIRGenerator mir(nullptr, options, &results.alloc(), &graph, &compileInfo,
|
||||||
IonOptimizations.get(OptimizationLevel::Wasm));
|
IonOptimizations.get(OptimizationLevel::Wasm));
|
||||||
mir.initMinWasmHeapLength(env.minMemoryLength);
|
mir.initMinWasmHeapLength(env.minMemoryLength);
|
||||||
|
|
||||||
|
|
@ -2971,11 +2975,9 @@ wasm::IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChar
|
||||||
|
|
||||||
SigIdDesc sigId = env.funcSigs[func.index()]->id;
|
SigIdDesc sigId = env.funcSigs[func.index()]->id;
|
||||||
|
|
||||||
CodeGenerator codegen(&mir, lir, &task->masm());
|
CodeGenerator codegen(&mir, lir, &results.masm());
|
||||||
FuncOffsets offsets;
|
if (!codegen.generateWasm(sigId, prologueTrapOffset, &results.offsets()))
|
||||||
if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets))
|
|
||||||
return false;
|
return false;
|
||||||
unit->finish(offsets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2984,18 +2986,17 @@ wasm::IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChar
|
||||||
bool
|
bool
|
||||||
wasm::CompileFunction(IonCompileTask* task)
|
wasm::CompileFunction(IonCompileTask* task)
|
||||||
{
|
{
|
||||||
UniqueChars error;
|
TraceLoggerThread* logger = TraceLoggerForCurrentThread();
|
||||||
for (FuncCompileUnit& unit : task->units()) {
|
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);
|
||||||
switch (unit.mode()) {
|
|
||||||
case CompileMode::Ion:
|
switch (task->mode()) {
|
||||||
if (!IonCompileFunction(task, &unit, &error))
|
case wasm::IonCompileTask::CompileMode::Ion:
|
||||||
return false;
|
return wasm::IonCompileFunction(task);
|
||||||
break;
|
case wasm::IonCompileTask::CompileMode::Baseline:
|
||||||
case CompileMode::Baseline:
|
return wasm::BaselineCompileFunction(task);
|
||||||
if (!BaselineCompileFunction(task, &unit, &error))
|
case wasm::IonCompileTask::CompileMode::None:
|
||||||
return false;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
MOZ_CRASH("Uninitialized task");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,21 @@
|
||||||
#define wasm_ion_compile_h
|
#define wasm_ion_compile_h
|
||||||
|
|
||||||
#include "jit/MacroAssembler.h"
|
#include "jit/MacroAssembler.h"
|
||||||
#include "wasm/WasmGenerator.h"
|
#include "wasm/WasmTypes.h"
|
||||||
|
|
||||||
|
#include "wasm/WasmTypes.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace wasm {
|
namespace wasm {
|
||||||
|
|
||||||
|
struct ModuleGeneratorData;
|
||||||
|
|
||||||
|
typedef Vector<jit::MIRType, 8, SystemAllocPolicy> MIRTypeVector;
|
||||||
|
typedef jit::ABIArgIter<MIRTypeVector> ABIArgMIRTypeIter;
|
||||||
|
typedef jit::ABIArgIter<ValTypeVector> ABIArgValTypeIter;
|
||||||
|
|
||||||
[[nodiscard]] bool
|
[[nodiscard]] bool
|
||||||
IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
|
IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
|
||||||
|
|
||||||
} // namespace wasm
|
} // namespace wasm
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ wasm::HasCompilerSupport(ExclusiveContext* cx)
|
||||||
if (!cx->jitSupportsFloatingPoint())
|
if (!cx->jitSupportsFloatingPoint())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!cx->runtime()->jitSupportsUnalignedAccesses)
|
if (!cx->jitSupportsUnalignedAccesses())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!wasm::HaveSignalHandlers())
|
if (!wasm::HaveSignalHandlers())
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include "fdlibm.h"
|
#include "fdlibm.h"
|
||||||
|
|
||||||
#include "gc/Zone.h"
|
|
||||||
#include "jslibmath.h"
|
#include "jslibmath.h"
|
||||||
#include "jsmath.h"
|
#include "jsmath.h"
|
||||||
|
|
||||||
|
|
@ -360,9 +359,9 @@ wasm::AddressOf(SymbolicAddress imm, ExclusiveContext* cx)
|
||||||
{
|
{
|
||||||
switch (imm) {
|
switch (imm) {
|
||||||
case SymbolicAddress::Context:
|
case SymbolicAddress::Context:
|
||||||
return cx->zone()->group()->addressOfOwnerContext();
|
return cx->contextAddressForJit();
|
||||||
case SymbolicAddress::InterruptUint32:
|
case SymbolicAddress::InterruptUint32:
|
||||||
return cx->runtime()->addressOfInterruptUint32();
|
return cx->runtimeAddressOfInterruptUint32();
|
||||||
case SymbolicAddress::ReportOverRecursed:
|
case SymbolicAddress::ReportOverRecursed:
|
||||||
return FuncCast(WasmReportOverRecursed, Args_General0);
|
return FuncCast(WasmReportOverRecursed, Args_General0);
|
||||||
case SymbolicAddress::HandleExecutionInterrupt:
|
case SymbolicAddress::HandleExecutionInterrupt:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue