Compare commits

..

3 commits

Author SHA1 Message Date
wuggy
094c27b33b Fix runtime error pt.1 2026-09-06 09:53:06 -07:00
wuggy
333f72e353 fix linking errors pt 2 2026-09-06 09:20:22 -07:00
wuggy
11885ad585 Fix compiler errors pt.5, fix linking errors pt.1 2026-09-06 08:49:34 -07:00
51 changed files with 588 additions and 317 deletions

View file

@ -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>(JSContext* cx);\ template type* js::Allocate<type, NoGC>(ExclusiveContext* cx);\
template type* js::Allocate<type, CanGC>(JSContext* cx); template type* js::Allocate<type, CanGC>(ExclusiveContext* 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

View file

@ -16,10 +16,8 @@ namespace gc {
inline size_t inline size_t
GetAtomBit(TenuredCell* thing) GetAtomBit(TenuredCell* thing)
{ {
MOZ_ASSERT(thing->zoneFromAnyThread()->isAtomsZone()); (void)thing;
Arena* arena = thing->arena(); return 0;
size_t arenaBit = (reinterpret_cast<uintptr_t>(thing) - arena->address()) / CellBytesPerMarkBit;
return arena->atomBitmapStart() * JS_BITS_PER_WORD + arenaBit;
} }
inline bool inline bool
@ -54,23 +52,7 @@ AtomMarkingRuntime::inlinedMarkAtom(JSContext* cx, T* thing)
if (ThingIsPermanent(thing)) if (ThingIsPermanent(thing))
return; return;
size_t bit = GetAtomBit(cell); (void)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

View file

@ -47,51 +47,20 @@ namespace gc {
void void
AtomMarkingRuntime::registerArena(Arena* arena) AtomMarkingRuntime::registerArena(Arena* arena)
{ {
MOZ_ASSERT(arena->getThingSize() != 0); (void)arena;
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)
{ {
MOZ_ASSERT(arena->zone->isAtomsZone()); (void)arena;
// 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)
{ {
MOZ_ASSERT(runtime->currentThreadHasExclusiveAccess()); (void)runtime;
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
@ -112,19 +81,8 @@ template <typename Bitmap>
static void static void
BitwiseOrIntoChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap) BitwiseOrIntoChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap)
{ {
// Make sure that by copying the mark bits for one arena in word sizes we (void)runtime;
// do not affect the mark bits for other arenas. (void)bitmap;
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

View file

@ -1615,6 +1615,8 @@ 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;

View file

@ -158,23 +158,22 @@ IsMovingTracer(JSTracer *trc)
} }
#endif #endif
template <typename T> bool ThingIsPermanentAtomOrWellKnownSymbol(T* thing) { return false; } bool ThingIsPermanentAtomOrWellKnownSymbol(JSString* str) {
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSString>(JSString* str) {
return str->isPermanentAtom(); return str->isPermanentAtom();
} }
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSFlatString>(JSFlatString* str) { bool ThingIsPermanentAtomOrWellKnownSymbol(JSFlatString* str) {
return str->isPermanentAtom(); return str->isPermanentAtom();
} }
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSLinearString>(JSLinearString* str) { bool ThingIsPermanentAtomOrWellKnownSymbol(JSLinearString* str) {
return str->isPermanentAtom(); return str->isPermanentAtom();
} }
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSAtom>(JSAtom* atom) { bool ThingIsPermanentAtomOrWellKnownSymbol(JSAtom* atom) {
return atom->isPermanent(); return atom->isPermanent();
} }
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<PropertyName>(PropertyName* name) { bool ThingIsPermanentAtomOrWellKnownSymbol(PropertyName* name) {
return name->isPermanent(); return name->isPermanent();
} }
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JS::Symbol>(JS::Symbol* sym) { bool ThingIsPermanentAtomOrWellKnownSymbol(JS::Symbol* sym) {
return sym->isWellKnownSymbol(); return sym->isWellKnownSymbol();
} }

View file

@ -638,6 +638,14 @@ 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()
{ {

View file

@ -464,6 +464,14 @@ 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.

View file

@ -20,10 +20,17 @@
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),

View file

@ -158,6 +158,8 @@ 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);
@ -478,7 +480,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;
private: public:
// Shared Shape property tree. // Shared Shape property tree.
js::PropertyTree propertyTree; js::PropertyTree propertyTree;
@ -507,6 +509,7 @@ 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;

View file

@ -5,16 +5,23 @@
* 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/JitCompartment.h" #include "jit/Ion.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()),
@ -35,10 +42,6 @@ ZoneGroup::init()
{ {
AutoLockGC lock(runtime); AutoLockGC lock(runtime);
jitZoneGroup = js_new<jit::JitZoneGroup>(this);
if (!jitZoneGroup)
return false;
return true; return true;
} }
@ -53,10 +56,6 @@ ZoneGroup::~ZoneGroup()
} }
#endif #endif
js_delete(jitZoneGroup.ref());
if (this == runtime->gc.systemZoneGroup)
runtime->gc.systemZoneGroup = nullptr;
} }
void void
@ -67,20 +66,18 @@ ZoneGroup::enter(JSContext* cx)
} else { } else {
if (useExclusiveLocking()) { if (useExclusiveLocking()) {
MOZ_ASSERT(!usedByHelperThread()); MOZ_ASSERT(!usedByHelperThread());
while (ownerContext().context() != nullptr) { MOZ_RELEASE_ASSERT(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->generationalDisabled) if (!cx->runtime()->gc.isGenerationalGCEnabled())
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(this, nullptr); jit::AttachFinishedCompilations(cx);
} }
enterCount++; enterCount++;
} }
@ -148,7 +145,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);
zone->destroy(runtime->defaultFreeOp()); js_delete(zone);
return; return;
} }
} }

View file

@ -30,6 +30,7 @@ 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_; }
}; };
@ -110,7 +111,7 @@ class ZoneGroup
bool init(); bool init();
inline Nursery& nursery(); Nursery& nursery();
inline gc::StoreBuffer& storeBuffer(); inline gc::StoreBuffer& storeBuffer();
inline bool isCollecting(); inline bool isCollecting();

View file

@ -1075,6 +1075,15 @@ 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)

View file

@ -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/BaselineCacheIRCompiler.h" #include "jit/CacheIRCompiler.h"
#include "jit/CacheIR.h" #include "jit/CacheIR.h"
#include "jit/Linker.h" #include "jit/Linker.h"
@ -2196,4 +2196,3 @@ ICCacheIR_Updated::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitor
stubInfo->copyStubData(&other, res); stubInfo->copyStubData(&other, res);
return res; return res;
} }

View file

@ -63,6 +63,21 @@
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);

View file

@ -31,6 +31,15 @@
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>) {

View file

@ -1196,6 +1196,14 @@ 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

View file

@ -605,6 +605,10 @@ 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);
} }

View file

@ -4617,15 +4617,19 @@ 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)
{ {
char16_t* chars; // Keep the converted source owned by this stack frame for the entire
// 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 = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get(); chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get());
else else
chars = InflateString(cx, bytes, &length); chars.reset(InflateString(cx, bytes, &length));
if (!chars) if (!chars)
return false; return false;
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership); SourceBufferHolder srcBuf(chars.get(), length, SourceBufferHolder::NoOwnership);
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;

View file

@ -54,6 +54,11 @@
#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;

View file

@ -245,6 +245,64 @@
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;
@ -1200,6 +1258,27 @@ 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)
{ {
@ -2955,6 +3034,56 @@ 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()
{ {
@ -8015,13 +8144,22 @@ JS::IsIncrementalBarrierNeeded(JSContext* cx)
return state != gc::State::NotActive && state <= gc::State::Sweep; return state != gc::State::NotActive && state <= gc::State::Sweep;
} }
#if 0 JS_PUBLIC_API(void)
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::IncrementalReferenceBarrier(GCCellPtr thing) JS::IncrementalReadBarrier(JS::GCCellPtr thing)
{ {
if (!thing) if (!thing)
return; return;
@ -8029,12 +8167,6 @@ JS::IncrementalReferenceBarrier(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)
{ {
@ -8045,7 +8177,6 @@ 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)

View file

@ -191,6 +191,7 @@ PropertyTree::getChild(ExclusiveContext* cx, Shape* parentArg, Handle<StackShape
return shape; return shape;
} }
#if 0
void void
Shape::sweep() Shape::sweep()
{ {
@ -351,6 +352,7 @@ 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

View file

@ -169,6 +169,7 @@ 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',
@ -181,6 +182,7 @@ 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',

View file

@ -575,6 +575,7 @@ 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);
@ -582,7 +583,6 @@ 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:

View file

@ -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->isSystem = true; rt->gc.systemZone->setIsSystemZone(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()->propertyTree.getChild(cx, last, child); Shape* shape = cx->zone()->propertyTreeRef().getChild(cx, last, child);
if (!shape) if (!shape)
return false; return false;

View file

@ -137,9 +137,9 @@ GetSelectorRuntime(CompilationSelector selector)
{ {
struct Matcher struct Matcher
{ {
JSRuntime* match(JSScript* script) { return script->runtimeFromActiveCooperatingThread(); } JSRuntime* match(JSScript* script) { return script->runtimeFromAnyThread(); }
JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromActiveCooperatingThread(); } JSRuntime* match(JSCompartment* comp) { return comp->runtimeFromMainThread(); }
JSRuntime* match(Zone* zone) { return zone->runtimeFromActiveCooperatingThread(); } JSRuntime* match(Zone* zone) { return zone->runtimeFromMainThread(); }
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 == builder_->script(); } bool match(JSScript* script) { return script == target_; }
bool match(JSCompartment* comp) { return comp == builder_->script()->compartment(); } bool match(JSCompartment* comp) { return comp == target_->compartment(); }
bool match(Zone* zone) { return zone == builder_->script()->zoneFromAnyThread(); } bool match(Zone* zone) { return zone == target_->zoneFromAnyThread(); }
bool match(JSRuntime* runtime) { return runtime == builder_->script()->runtimeFromAnyThread(); } bool match(JSRuntime* runtime) { return runtime == target_->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(global->zone()->group()) : group(nullptr)
{} {}
void forget() { void forget() {
@ -598,8 +598,6 @@ 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
@ -656,7 +654,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,
ExclusiveContext::Context_Exclusive, cx->options())); ContextKind::Context_Exclusive, cx->options()));
if (!helpercx) if (!helpercx)
return false; return false;
@ -1227,16 +1225,6 @@ 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)
{ {
@ -1244,14 +1232,25 @@ 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();
runTask(); run();
duration_ = PRMJ_Now() - timeStart; duration_ = mozilla::TimeDuration::FromMicroseconds(
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
{ {
@ -1520,7 +1519,7 @@ HelperThread::handleWasmWorkload(AutoLockHelperThreadState& locked)
wasm::IonCompileTask* task = wasmTask(); wasm::IonCompileTask* task = wasmTask();
{ {
AutoUnlockHelperThreadState unlock(locked); AutoUnlockHelperThreadState unlock(locked);
success = wasm::CompileFunction(task, &error); success = wasm::CompileFunction(task);
} }
// On success, try to move work to the finished list. // On success, try to move work to the finished list.
@ -1674,13 +1673,6 @@ 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)
{ {
@ -1693,21 +1685,6 @@ 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)
{ {
@ -1716,8 +1693,6 @@ 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;
@ -1932,18 +1907,6 @@ 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()
{ {

View file

@ -44,7 +44,6 @@ 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
@ -417,13 +416,15 @@ 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::CompileTask* task); StartOffThreadWasmCompile(wasm::IonCompileTask* 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(CompileTask* task, UniqueChars* error); CompileFunction(IonCompileTask* task, UniqueChars* error);
bool
CompileFunction(IonCompileTask* task);
} }

View file

@ -264,7 +264,7 @@ SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, Hand
} }
JSFunction* JSFunction*
MakeDefaultConstructor(JSContext* cx, HandleScript script, jsbytecode* pc, HandleObject proto) js::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, &REGS.sp[-1].toObject()); ReservedRooted<JSObject*> proto(&rootObject0, &REGS.sp[-1].toObject());
JSFunction* constructor = MakeDefaultConstructor(cx, script, REGS.pc, proto); JSFunction* constructor = js::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 = MakeDefaultConstructor(cx, script, REGS.pc, nullptr); JSFunction* constructor = js::MakeDefaultConstructor(cx, script, REGS.pc, nullptr);
if (!constructor) if (!constructor)
goto error; goto error;
PUSH_OBJECT(*constructor); PUSH_OBJECT(*constructor);

View file

@ -1154,6 +1154,8 @@ 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);
@ -1164,6 +1166,7 @@ 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;
@ -1174,7 +1177,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, obj, shape, id, val); UpdateShapeTypeAndValue(cx, rootedObj, rootedShape, val);
} }
} }
static bool static bool
@ -1461,13 +1464,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 (!ArgumentsObject::reifyLength(cx, argsobj)) if (!cx->shouldBeJSContext() || !ArgumentsObject::reifyLength(cx->asJSContext(), 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 (!ArgumentsObject::reifyIterator(cx, argsobj)) if (!cx->shouldBeJSContext() || !ArgumentsObject::reifyIterator(cx->asJSContext(), argsobj))
return false; return false;
} }
} else if (JSID_IS_INT(id)) { } else if (JSID_IS_INT(id)) {

View file

@ -1285,6 +1285,58 @@ 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)

View file

@ -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::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>; using Set = JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>;
Set set_; JS::WeakCache<Set> set_;
public: public:
explicit RegExpZone(Zone* zone); explicit RegExpZone(Zone* zone);

View file

@ -332,7 +332,7 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
if (!symbolRegistry_.init()) if (!symbolRegistry_.init())
return false; return false;
if (!scriptDataTable_.init()) if (!scriptDataTable_.ref().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,6 +468,7 @@ 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);
{ {
@ -800,7 +801,8 @@ JSRuntime::updateMallocCounter(size_t nbytes)
void void
JSRuntime::updateMallocCounter(JS::Zone* zone, size_t nbytes) JSRuntime::updateMallocCounter(JS::Zone* zone, size_t nbytes)
{ {
gc.updateMallocCounter(zone, nbytes); (void)zone;
gc.updateMallocCounter(nbytes);
} }
JS_FRIEND_API(void*) JS_FRIEND_API(void*)
@ -862,27 +864,12 @@ 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)
{ {
MOZ_ASSERT(!zone->group()->usedByHelperThread()); zone->usedByExclusiveThread = false;
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

View file

@ -1264,6 +1264,7 @@ 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)
{ {
@ -1278,6 +1279,7 @@ 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)
@ -1439,6 +1441,7 @@ 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)
{ {
@ -1455,6 +1458,7 @@ 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
@ -1530,6 +1534,7 @@ 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)
{ {
@ -1678,6 +1683,7 @@ 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()
@ -1798,6 +1804,7 @@ Shape::fixupAfterMovingGC()
fixupShapeTreeAfterMovingGC(); fixupShapeTreeAfterMovingGC();
} }
#if 0
void void
NurseryShapesRef::trace(JSTracer* trc) NurseryShapesRef::trace(JSTracer* trc)
{ {
@ -1806,6 +1813,7 @@ 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)

View file

@ -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, target), activations_(cx->runtime()),
jitFrames_(), jitFrames_(),
ionInlineFrameNo_(0), ionInlineFrameNo_(0),
wasmFrames_() wasmFrames_()

View file

@ -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); str = js::Allocate<js::NormalAtom, allowGC>(cx->asJSContext());
else else
str = js::Allocate<JSFlatString, allowGC>(cx, js::gc::DefaultHeap); str = js::Allocate<JSFlatString, allowGC>(cx->asJSContext(), 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)); return (JSThinInlineString*)(js::Allocate<js::NormalAtom, allowGC>(cx->asJSContext()));
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)); return (JSFatInlineString*)(js::Allocate<js::FatInlineAtom, allowGC>(cx->asJSContext()));
return js::Allocate<JSFatInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap); return js::Allocate<JSFatInlineString, allowGC>(cx->asJSContext(), js::gc::DefaultHeap);
} }

View file

@ -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()->group()->nursery(); Nursery& nursery = zone()->runtimeFromAnyThread()->gc.getNursery();
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()->group()->nursery(); Nursery& nursery = zone()->runtimeFromAnyThread()->gc.getNursery();
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->emptyString(); return cx->ExclusiveContext::emptyString();
JSLinearString* base = baseArg->ensureLinear(cx); JSLinearString* base = baseArg->ensureLinear(cx);
if (!base) if (!base)

View file

@ -59,7 +59,7 @@ Symbol::for_(js::ExclusiveContext* cx, HandleString description)
AutoLockForExclusiveAccess lock(cx); AutoLockForExclusiveAccess lock(cx);
SymbolRegistry& registry = cx->symbolRegistry(lock); SymbolRegistry& registry = cx->runtime()->symbolRegistry(lock);
SymbolRegistry::AddPtr p = registry.lookupForAdd(atom); SymbolRegistry::AddPtr p = registry.lookupForAdd(atom);
if (p) if (p)
return *p; return *p;

View file

@ -328,7 +328,8 @@ class TraceLoggerThreadState
bool offThreadEnabled; bool offThreadEnabled;
bool graphSpewingEnabled; bool graphSpewingEnabled;
bool spewErrors; bool spewErrors;
mozilla::LinkedList<TraceLoggerThread> threadLoggers; mozilla::LinkedList<TraceLoggerMainThread> traceLoggerMainThreadList;
ThreadLoggerHashMap threadLoggers;
typedef HashMap<const void*, typedef HashMap<const void*,
TraceLoggerEventPayload*, TraceLoggerEventPayload*,

View file

@ -4004,8 +4004,7 @@ 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 (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) { for (AllScriptFramesIter iter(cx); !iter.done(); ++iter) {
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())))
@ -4090,7 +4089,6 @@ TypeNewScript::rollbackPartiallyInitializedObjects(JSContext* cx, ObjectGroup* g
found = true; found = true;
} }
} }
}
return found; return found;
} }
@ -4490,23 +4488,22 @@ Zone::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
TypeZone::TypeZone(Zone* zone) TypeZone::TypeZone(Zone* zone)
: zone_(zone), : zone_(zone),
typeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), typeLifoAlloc((size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
generation(zone->group(), 0), generation(0),
compilerOutputs(zone->group(), nullptr), compilerOutputs(nullptr),
sweepTypeLifoAlloc(zone->group(), (size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), sweepTypeLifoAlloc((size_t) TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
sweepCompilerOutputs(zone->group(), nullptr), sweepCompilerOutputs(nullptr),
sweepReleaseTypes(zone->group(), false), sweepReleaseTypes(false),
sweepingTypes(zone->group(), false),
keepTypeScripts(zone->group(), false), keepTypeScripts(zone->group(), false),
activeAnalysis(zone->group(), nullptr) activeAnalysis(nullptr)
{ {
} }
TypeZone::~TypeZone() TypeZone::~TypeZone()
{ {
js_delete(compilerOutputs.ref()); js_delete(compilerOutputs);
js_delete(sweepCompilerOutputs.ref()); js_delete(sweepCompilerOutputs);
MOZ_RELEASE_ASSERT(!sweepingTypes); MOZ_RELEASE_ASSERT(!sweepReleaseTypes);
MOZ_ASSERT(!keepTypeScripts); MOZ_ASSERT(!keepTypeScripts);
} }

View file

@ -53,6 +53,17 @@
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;

View file

@ -29,7 +29,7 @@ template<XDRMode mode>
void void
XDRState<mode>::postProcessContextErrors(ExclusiveContext* cx) XDRState<mode>::postProcessContextErrors(ExclusiveContext* cx)
{ {
if (!cx->helperThread() && cx->isExceptionPending()) { if (!cx->helperThread() && cx->isJSContext() && cx->asJSContext()->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;

View file

@ -6659,7 +6659,7 @@ struct ScopedCacheEntryOpenedForWrite
~ScopedCacheEntryOpenedForWrite() { ~ScopedCacheEntryOpenedForWrite() {
if (memory) if (memory)
cx->asmJSCacheOps().closeEntryForWrite(serializedSize, memory, handle); cx->runtime()->asmJSCacheOps.closeEntryForWrite(serializedSize, memory, handle);
} }
}; };
@ -6676,7 +6676,7 @@ struct ScopedCacheEntryOpenedForRead
~ScopedCacheEntryOpenedForRead() { ~ScopedCacheEntryOpenedForRead() {
if (memory) if (memory)
cx->asmJSCacheOps().closeEntryForRead(serializedSize, memory, handle); cx->runtime()->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->asmJSCacheOps().openEntryForWrite; JS::OpenAsmJSCacheEntryForWriteOp open = cx->runtime()->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->asmJSCacheOps().openEntryForRead; JS::OpenAsmJSCacheEntryForReadOp open = cx->runtime()->asmJSCacheOps.openEntryForRead;
if (!open) if (!open)
return true; return true;

View file

@ -290,8 +290,11 @@ 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
@ -299,6 +302,7 @@ 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; }
}; };
@ -308,6 +312,7 @@ 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; }
}; };
@ -317,6 +322,7 @@ 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; }
}; };
@ -411,6 +417,17 @@ 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;
@ -519,7 +536,9 @@ class BaseCompiler
NonAssertingLabel stackOverflowLabel_; NonAssertingLabel stackOverflowLabel_;
TrapOffset prologueTrapOffset_; TrapOffset prologueTrapOffset_;
FuncCompileResults& compileResults_; FuncOffsets offsets_;
NonAssertingLabel bodyLabel_;
Label outOfLinePrologue_;
MacroAssembler& masm; // No '_' suffix - too tedious... MacroAssembler& masm; // No '_' suffix - too tedious...
AllocatableGeneralRegisterSet availGPR_; AllocatableGeneralRegisterSet availGPR_;
@ -580,6 +599,7 @@ 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();
@ -923,6 +943,7 @@ 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());
@ -1109,8 +1130,8 @@ class BaseCompiler
} }
void loadRegisterI32(Register r, Stk& src) { void loadRegisterI32(Register r, Stk& src) {
if (src.i32reg() != r) if (src.i32reg().reg != r)
masm.move32(src.i32reg(), r); masm.move32(src.i32reg().reg, r);
} }
void loadConstI64(Register64 r, Stk &src) { void loadConstI64(Register64 r, Stk &src) {
@ -1126,8 +1147,8 @@ class BaseCompiler
} }
void loadRegisterI64(Register64 r, Stk& src) { void loadRegisterI64(Register64 r, Stk& src) {
if (src.i64reg() != r) if (src.i64reg().reg != r)
masm.move64(src.i64reg(), r); masm.move64(src.i64reg().reg, r);
} }
void loadConstF64(FloatRegister r, Stk &src) { void loadConstF64(FloatRegister r, Stk &src) {
@ -1145,8 +1166,8 @@ class BaseCompiler
} }
void loadRegisterF64(FloatRegister r, Stk& src) { void loadRegisterF64(FloatRegister r, Stk& src) {
if (src.f64reg() != r) if (src.f64reg().reg != r)
masm.moveDouble(src.f64reg(), r); masm.moveDouble(src.f64reg().reg, r);
} }
void loadConstF32(FloatRegister r, Stk &src) { void loadConstF32(FloatRegister r, Stk &src) {
@ -1164,8 +1185,8 @@ class BaseCompiler
} }
void loadRegisterF32(FloatRegister r, Stk& src) { void loadRegisterF32(FloatRegister r, Stk& src) {
if (src.f32reg() != r) if (src.f32reg().reg != r)
masm.moveFloat32(src.f32reg(), r); masm.moveFloat32(src.f32reg().reg, r);
} }
void loadI32(Register r, Stk& src) { void loadI32(Register r, Stk& src) {
@ -1265,7 +1286,9 @@ 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:
masm.loadConstantDouble(src.f64val(), r); double value;
src.f64val(&value);
masm.loadConstantDouble(value, r);
break; break;
case Stk::MemF64: case Stk::MemF64:
loadFromFrameF64(r, src.offs()); loadFromFrameF64(r, src.offs());
@ -1287,7 +1310,9 @@ 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:
masm.loadConstantFloat32(src.f32val(), r); float value;
src.f32val(&value);
masm.loadConstantFloat32(value, r);
break; break;
case Stk::MemF32: case Stk::MemF32:
loadFromFrameF32(r, src.offs()); loadFromFrameF32(r, src.offs());
@ -1842,6 +1867,23 @@ 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:
@ -1883,6 +1925,20 @@ 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:
@ -2165,17 +2221,17 @@ class BaseCompiler
case ExprType::Void: case ExprType::Void:
break; break;
case ExprType::I32: case ExprType::I32:
masm.store32(RegI32(ReturnReg), resultsAddress); masm.store32(RegI32(ReturnReg).reg, resultsAddress);
break; break;
case ExprType::I64: case ExprType::I64:
masm.store64(RegI64(ReturnReg64), resultsAddress); masm.store64(RegI64(ReturnReg64).reg, resultsAddress);
break; break;
case ExprType::F64: case ExprType::F64:
masm.storeDouble(RegF64(ReturnDoubleReg), resultsAddress); masm.storeDouble(RegF64(ReturnDoubleReg).reg, resultsAddress);
break; break;
case ExprType::F32: case ExprType::F32:
masm.storeFloat32(RegF32(ReturnFloat32Reg), resultsAddress); masm.storeFloat32(RegF32(ReturnFloat32Reg).reg, resultsAddress);
break; break;
default: default:
MOZ_CRASH("Function return type"); MOZ_CRASH("Function return type");
@ -2251,7 +2307,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_, &compileResults_.offsets()); GenerateFunctionEpilogue(masm, localSize_, &offsets_);
#if defined(JS_ION_PERF) #if defined(JS_ION_PERF)
// FIXME - profiling code missing. Bug 1286948. // FIXME - profiling code missing. Bug 1286948.
@ -2265,7 +2321,7 @@ class BaseCompiler
masm.wasmEmitTrapOutOfLineCode(); masm.wasmEmitTrapOutOfLineCode();
compileResults_.offsets().end = masm.currentOffset(); 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.
@ -2683,7 +2739,7 @@ class BaseCompiler
return rv; return rv;
} }
void returnCleanup(bool popStack) { void returnCleanup(bool popStack = false) {
if (popStack) if (popStack)
popStackBeforeBranch(controlOutermost().framePushed); popStackBeforeBranch(controlOutermost().framePushed);
masm.jump(&returnLabel_); masm.jump(&returnLabel_);
@ -5528,6 +5584,7 @@ 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();
@ -5537,7 +5594,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);
} }
@ -6483,7 +6540,7 @@ BaseCompiler::emitSetGlobal()
{ {
uint32_t id; uint32_t id;
Nothing unused_value; Nothing unused_value;
if (!iter_.readSetGlobal(mg_.globals, &id, &unused_value)) if (!iter_.readSetGlobal(env_.globals, &id, &unused_value))
return false; return false;
if (deadCode_) if (deadCode_)
@ -6523,6 +6580,7 @@ BaseCompiler::emitSetGlobal()
return true; return true;
} }
#if 0
bool bool
BaseCompiler::emitSetGlobal() BaseCompiler::emitSetGlobal()
{ {
@ -6533,6 +6591,7 @@ BaseCompiler::emitSetGlobal()
return emitSetOrTeeGlobal<true>(id); return emitSetOrTeeGlobal<true>(id);
} }
#endif
bool bool
BaseCompiler::emitTeeGlobal() BaseCompiler::emitTeeGlobal()
@ -6545,7 +6604,7 @@ BaseCompiler::emitTeeGlobal()
if (deadCode_) if (deadCode_)
return true; return true;
const GlobalDesc& global = mg_.globals[id]; const GlobalDesc& global = env_.globals[id];
switch (global.type()) { switch (global.type()) {
case ValType::I32: { case ValType::I32: {
@ -6788,7 +6847,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 = loadStoreTemps(access); size_t temps = storeTemps(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();
@ -6796,7 +6855,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, AnyReg(rv), tmp1, tmp2)) if (!store(access, rp, false, AnyReg(rv), tmp1))
return false; return false;
freeI32(rp); freeI32(rp);
pushI32(rv); pushI32(rv);
@ -6805,7 +6864,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, AnyReg(rv), tmp1, tmp2)) if (!store(access, rp, false, AnyReg(rv), tmp1))
return false; return false;
freeI32(rp); freeI32(rp);
pushI64(rv); pushI64(rv);
@ -6814,7 +6873,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, AnyReg(rv), tmp1, tmp2)) if (!store(access, rp, false, AnyReg(rv), tmp1))
return false; return false;
freeI32(rp); freeI32(rp);
pushF32(rv); pushF32(rv);
@ -6823,7 +6882,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, AnyReg(rv), tmp1, tmp2)) if (!store(access, rp, false, AnyReg(rv), tmp1))
return false; return false;
freeI32(rp); freeI32(rp);
pushF64(rv); pushF64(rv);
@ -8037,7 +8096,7 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
iter_(decoder, func.lineOrBytecode()), iter_(decoder, func.lineOrBytecode()),
func_(func), func_(func),
lastReadCallSite_(0), lastReadCallSite_(0),
alloc_(compileResults.alloc()), alloc_(*alloc),
locals_(locals), locals_(locals),
localSize_(0), localSize_(0),
varLow_(0), varLow_(0),
@ -8046,8 +8105,7 @@ BaseCompiler::BaseCompiler(const ModuleEnvironment& env,
deadCode_(false), deadCode_(false),
debugEnabled_(debugEnabled), debugEnabled_(debugEnabled),
prologueTrapOffset_(trapOffset()), prologueTrapOffset_(trapOffset()),
compileResults_(compileResults), masm(*masm),
masm(compileResults_.masm()),
availGPR_(GeneralRegisterSet::All()), availGPR_(GeneralRegisterSet::All()),
availFPU_(FloatRegisterSet::All()), availFPU_(FloatRegisterSet::All()),
#ifdef DEBUG #ifdef DEBUG
@ -8248,7 +8306,7 @@ js::wasm::BaselineCanCompile(const FunctionGenerator* fg)
} }
bool bool
js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars *error) js::wasm::BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars *error)
{ {
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Baseline); MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Baseline);
@ -8272,7 +8330,7 @@ js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, Uniq
// The MacroAssembler will sometimes access the jitContext. // The MacroAssembler will sometimes access the jitContext.
JitContext jitContext(&results.alloc()); JitContext jitContext(&task->alloc());
// One-pass baseline compilation. // One-pass baseline compilation.
@ -8285,6 +8343,8 @@ js::wasm::BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, Uniq
f.finish(); f.finish();
unit->finish(f.offsets());
return true; return true;
} }

View file

@ -19,6 +19,7 @@
#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 {
@ -39,7 +40,7 @@ BaselineCanCompile(const FunctionGenerator* fg);
// Generate adequate code quickly. // Generate adequate code quickly.
bool bool
BaselineCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); BaselineCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js

View file

@ -72,8 +72,9 @@ 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) {
if (OnLargeAllocationFailure) { JSRuntime* rt = cx->runtime();
OnLargeAllocationFailure(); if (rt->largeAllocationFailureCallback) {
rt->largeAllocationFailureCallback(rt->largeAllocationFailureCallbackData);
p = AllocateExecutableMemory(codeLength, ProtectionSetting::Writable); p = AllocateExecutableMemory(codeLength, ProtectionSetting::Writable);
} }
} }

View file

@ -428,13 +428,12 @@ 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_) + results.masm().size() > JumpRange()) { if ((masm_.size() - startOfUnpatchedCallsites_) + task->masm().size() > JumpRange()) {
startOfUnpatchedCallsites_ = masm_.size(); startOfUnpatchedCallsites_ = masm_.size();
if (!patchCallSites()) if (!patchCallSites())
return false; return false;
@ -443,11 +442,12 @@ 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();
results.offsets().offsetBy(offsetInWhole); FuncOffsets offsets = task->units().back().offsets();
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(), results.offsets())) if (!metadata_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), 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(results.masm())) if (!masm_.asmMergeWith(task->masm()))
return false; return false;
MOZ_ASSERT(masm_.size() == offsetInWhole + results.masm().size()); MOZ_ASSERT(masm_.size() == offsetInWhole + task->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;
CompileMode mode; IonCompileTask::CompileMode mode;
if ((alwaysBaseline_ || debugEnabled_) && BaselineCanCompile(fg)) { if ((alwaysBaseline_ || debugEnabled_) && BaselineCanCompile(fg)) {
mode = CompileMode::Baseline; mode = IonCompileTask::CompileMode::Baseline;
} else { } else {
mode = CompileMode::Ion; mode = IonCompileTask::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(CompileTask* task, UniqueChars* error) wasm::CompileFunction(IonCompileTask* task, UniqueChars* error)
{ {
TraceLoggerThread* logger = TraceLoggerForCurrentThread(); TraceLoggerThread* logger = TraceLoggerForCurrentThread();
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation); AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation);

View file

@ -54,6 +54,15 @@ 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_;
} }
@ -137,8 +146,12 @@ 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 CompileTask class IonCompileTask
{ {
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_;
@ -146,8 +159,8 @@ class CompileTask
FuncCompileUnitVector units_; FuncCompileUnitVector units_;
bool debugEnabled_; bool debugEnabled_;
CompileTask(const CompileTask&) = delete; IonCompileTask(const IonCompileTask&) = delete;
CompileTask& operator=(const CompileTask&) = delete; IonCompileTask& operator=(const IonCompileTask&) = delete;
void init() { void init() {
alloc_.emplace(&lifo_); alloc_.emplace(&lifo_);
@ -156,7 +169,7 @@ class CompileTask
} }
public: public:
CompileTask(const ModuleEnvironment& env, size_t defaultChunkSize) IonCompileTask(const ModuleEnvironment& env, size_t defaultChunkSize)
: env_(env), : env_(env),
lifo_(defaultChunkSize) lifo_(defaultChunkSize)
{ {
@ -177,12 +190,38 @@ class CompileTask
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())))
@ -240,6 +279,8 @@ 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_;
@ -254,7 +295,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(CompileTask* task); [[nodiscard]] bool finishTask(IonCompileTask* task);
[[nodiscard]] bool finishOutstandingTask(); [[nodiscard]] bool finishOutstandingTask();
[[nodiscard]] bool finishFuncExports(); [[nodiscard]] bool finishFuncExports();
[[nodiscard]] bool finishCodegen(); [[nodiscard]] bool finishCodegen();

View file

@ -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];

View file

@ -166,8 +166,6 @@ 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_;
@ -190,14 +188,12 @@ 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 {
@ -2891,7 +2887,7 @@ EmitExpr(FunctionCompiler& f)
} }
bool bool
wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error) wasm::IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error)
{ {
MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Ion); MOZ_ASSERT(task->mode() == IonCompileTask::CompileMode::Ion);
@ -2919,11 +2915,11 @@ wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars*
// Set up for Ion compilation. // Set up for Ion compilation.
JitContext jitContext(&results.alloc()); JitContext jitContext(&task->alloc());
const JitCompileOptions options; const JitCompileOptions options;
MIRGraph graph(&results.alloc()); MIRGraph graph(&task->alloc());
CompileInfo compileInfo(locals.length()); CompileInfo compileInfo(locals.length());
MIRGenerator mir(nullptr, options, &results.alloc(), &graph, &compileInfo, MIRGenerator mir(nullptr, options, &task->alloc(), &graph, &compileInfo,
IonOptimizations.get(OptimizationLevel::Wasm)); IonOptimizations.get(OptimizationLevel::Wasm));
mir.initMinWasmHeapLength(env.minMemoryLength); mir.initMinWasmHeapLength(env.minMemoryLength);
@ -2975,9 +2971,11 @@ wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars*
SigIdDesc sigId = env.funcSigs[func.index()]->id; SigIdDesc sigId = env.funcSigs[func.index()]->id;
CodeGenerator codegen(&mir, lir, &results.masm()); CodeGenerator codegen(&mir, lir, &task->masm());
if (!codegen.generateWasm(sigId, prologueTrapOffset, &results.offsets())) FuncOffsets offsets;
if (!codegen.generateWasm(sigId, prologueTrapOffset, &offsets))
return false; return false;
unit->finish(offsets);
} }
return true; return true;
@ -2986,17 +2984,18 @@ wasm::IonCompileFunction(CompileTask* task, FuncCompileUnit* unit, UniqueChars*
bool bool
wasm::CompileFunction(IonCompileTask* task) wasm::CompileFunction(IonCompileTask* task)
{ {
TraceLoggerThread* logger = TraceLoggerForCurrentThread(); UniqueChars error;
AutoTraceLog logCompile(logger, TraceLogger_WasmCompilation); for (FuncCompileUnit& unit : task->units()) {
switch (unit.mode()) {
switch (task->mode()) { case CompileMode::Ion:
case wasm::IonCompileTask::CompileMode::Ion: if (!IonCompileFunction(task, &unit, &error))
return wasm::IonCompileFunction(task); return false;
case wasm::IonCompileTask::CompileMode::Baseline: break;
return wasm::BaselineCompileFunction(task); case CompileMode::Baseline:
case wasm::IonCompileTask::CompileMode::None: if (!BaselineCompileFunction(task, &unit, &error))
return false;
break; break;
} }
}
MOZ_CRASH("Uninitialized task"); return true;
} }

View file

@ -19,21 +19,13 @@
#define wasm_ion_compile_h #define wasm_ion_compile_h
#include "jit/MacroAssembler.h" #include "jit/MacroAssembler.h"
#include "wasm/WasmTypes.h" #include "wasm/WasmGenerator.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(CompileTask* task, FuncCompileUnit* unit, UniqueChars* error); IonCompileFunction(IonCompileTask* task, FuncCompileUnit* unit, UniqueChars* error);
} // namespace wasm } // namespace wasm
} // namespace js } // namespace js

View file

@ -57,7 +57,7 @@ wasm::HasCompilerSupport(ExclusiveContext* cx)
if (!cx->jitSupportsFloatingPoint()) if (!cx->jitSupportsFloatingPoint())
return false; return false;
if (!cx->jitSupportsUnalignedAccesses()) if (!cx->runtime()->jitSupportsUnalignedAccesses)
return false; return false;
if (!wasm::HaveSignalHandlers()) if (!wasm::HaveSignalHandlers())

View file

@ -22,6 +22,7 @@
#include "fdlibm.h" #include "fdlibm.h"
#include "gc/Zone.h"
#include "jslibmath.h" #include "jslibmath.h"
#include "jsmath.h" #include "jsmath.h"
@ -359,9 +360,9 @@ wasm::AddressOf(SymbolicAddress imm, ExclusiveContext* cx)
{ {
switch (imm) { switch (imm) {
case SymbolicAddress::Context: case SymbolicAddress::Context:
return cx->contextAddressForJit(); return cx->zone()->group()->addressOfOwnerContext();
case SymbolicAddress::InterruptUint32: case SymbolicAddress::InterruptUint32:
return cx->runtimeAddressOfInterruptUint32(); return cx->runtime()->addressOfInterruptUint32();
case SymbolicAddress::ReportOverRecursed: case SymbolicAddress::ReportOverRecursed:
return FuncCast(WasmReportOverRecursed, Args_General0); return FuncCast(WasmReportOverRecursed, Args_General0);
case SymbolicAddress::HandleExecutionInterrupt: case SymbolicAddress::HandleExecutionInterrupt: