зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1288715 - Refactor SharedScriptData to prepare for making it refcounted r=till
This commit is contained in:
Родитель
c3fe802818
Коммит
38ebe42aaa
|
@ -586,9 +586,6 @@ FindScopeObjectIndex(JSScript* script, NestedStaticScope& scope)
|
|||
MOZ_CRASH("Scope not found");
|
||||
}
|
||||
|
||||
static bool
|
||||
SaveSharedScriptData(ExclusiveContext*, Handle<JSScript*>, SharedScriptData*, uint32_t);
|
||||
|
||||
enum XDRClassKind {
|
||||
CK_BlockObject = 0,
|
||||
CK_WithObject = 1,
|
||||
|
@ -880,7 +877,6 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
|
||||
MOZ_ASSERT(!script->mainOffset());
|
||||
script->mainOffset_ = prologueLength;
|
||||
script->setLength(length);
|
||||
script->funLength_ = funLength;
|
||||
|
||||
scriptp.set(script);
|
||||
|
@ -954,22 +950,18 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
script->nslots_ = nslots;
|
||||
}
|
||||
|
||||
jsbytecode* code = script->code();
|
||||
SharedScriptData* ssd;
|
||||
auto scriptDataGuard = mozilla::MakeScopeExit([&] {
|
||||
if (mode == XDR_DECODE)
|
||||
script->freeScriptData();
|
||||
});
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
ssd = SharedScriptData::new_(cx, length, nsrcnotes, natoms);
|
||||
if (!ssd)
|
||||
if (!script->createScriptData(cx, length, nsrcnotes, natoms))
|
||||
return false;
|
||||
code = ssd->data;
|
||||
if (natoms != 0) {
|
||||
script->natoms_ = natoms;
|
||||
script->atoms = ssd->atoms();
|
||||
}
|
||||
}
|
||||
|
||||
jsbytecode* code = script->code();
|
||||
if (!xdr->codeBytes(code, length) || !xdr->codeBytes(code + length, nsrcnotes)) {
|
||||
if (mode == XDR_DECODE)
|
||||
js_free(ssd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -978,16 +970,17 @@ js::XDRScript(XDRState<mode>* xdr, HandleObject enclosingScopeArg, HandleScript
|
|||
RootedAtom tmp(cx);
|
||||
if (!XDRAtom(xdr, &tmp))
|
||||
return false;
|
||||
script->atoms[i].init(tmp);
|
||||
script->atoms()[i].init(tmp);
|
||||
} else {
|
||||
RootedAtom tmp(cx, script->atoms[i]);
|
||||
RootedAtom tmp(cx, script->atoms()[i]);
|
||||
if (!XDRAtom(xdr, &tmp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
scriptDataGuard.release();
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!SaveSharedScriptData(cx, script, ssd, nsrcnotes))
|
||||
if (!script->shareScriptData(cx))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2416,53 +2409,69 @@ SharedScriptData*
|
|||
js::SharedScriptData::new_(ExclusiveContext* cx, uint32_t codeLength,
|
||||
uint32_t srcnotesLength, uint32_t natoms)
|
||||
{
|
||||
/*
|
||||
* Ensure the atoms are aligned, as some architectures don't allow unaligned
|
||||
* access.
|
||||
*/
|
||||
const uint32_t pointerSize = sizeof(JSAtom*);
|
||||
const uint32_t pointerMask = pointerSize - 1;
|
||||
const uint32_t dataOffset = offsetof(SharedScriptData, data);
|
||||
uint32_t baseLength = codeLength + srcnotesLength;
|
||||
uint32_t padding = (pointerSize - ((baseLength + dataOffset) & pointerMask)) & pointerMask;
|
||||
uint32_t length = baseLength + padding + pointerSize * natoms;
|
||||
|
||||
SharedScriptData* entry = reinterpret_cast<SharedScriptData*>(
|
||||
cx->zone()->pod_malloc<uint8_t>(length + dataOffset));
|
||||
uint32_t dataLength = natoms * sizeof(GCPtrAtom) + codeLength + srcnotesLength;
|
||||
uint32_t allocLength = offsetof(SharedScriptData, data_) + dataLength;
|
||||
auto entry = reinterpret_cast<SharedScriptData*>(cx->zone()->pod_malloc<uint8_t>(allocLength));
|
||||
if (!entry) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
entry->length = length;
|
||||
entry->natoms = natoms;
|
||||
entry->marked = false;
|
||||
memset(entry->data + baseLength, 0, padding);
|
||||
entry->dataLength_ = dataLength;
|
||||
entry->natoms_ = natoms;
|
||||
entry->codeLength_ = codeLength;
|
||||
entry->marked_ = false;
|
||||
|
||||
/*
|
||||
* Call constructors to initialize the storage that will be accessed as a
|
||||
* GCPtrAtom array via atoms().
|
||||
*/
|
||||
GCPtrAtom* atoms = entry->atoms();
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(atoms) % sizeof(JSAtom*) == 0);
|
||||
MOZ_ASSERT(reinterpret_cast<uintptr_t>(atoms) % sizeof(GCPtrAtom*) == 0);
|
||||
for (unsigned i = 0; i < natoms; ++i)
|
||||
new (&atoms[i]) GCPtrAtom();
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::createScriptData(ExclusiveContext* cx, uint32_t codeLength, uint32_t srcnotesLength,
|
||||
uint32_t natoms)
|
||||
{
|
||||
MOZ_ASSERT(!scriptData());
|
||||
SharedScriptData* ssd = SharedScriptData::new_(cx, codeLength, srcnotesLength, natoms);
|
||||
if (!ssd)
|
||||
return false;
|
||||
|
||||
setScriptData(ssd);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::freeScriptData()
|
||||
{
|
||||
js_free(scriptData_);
|
||||
scriptData_ = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::setScriptData(js::SharedScriptData* data)
|
||||
{
|
||||
MOZ_ASSERT(!scriptData_);
|
||||
scriptData_ = data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Takes ownership of its *ssd parameter and either adds it into the runtime's
|
||||
* ScriptDataTable or frees it if a matching entry already exists.
|
||||
*
|
||||
* Sets the |code| and |atoms| fields on the given JSScript.
|
||||
*/
|
||||
static bool
|
||||
SaveSharedScriptData(ExclusiveContext* cx, Handle<JSScript*> script, SharedScriptData* ssd,
|
||||
uint32_t nsrcnotes)
|
||||
bool
|
||||
JSScript::shareScriptData(ExclusiveContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(script != nullptr);
|
||||
MOZ_ASSERT(ssd != nullptr);
|
||||
SharedScriptData* ssd = scriptData();
|
||||
MOZ_ASSERT(ssd);
|
||||
|
||||
AutoLockForExclusiveAccess lock(cx);
|
||||
|
||||
|
@ -2470,13 +2479,12 @@ SaveSharedScriptData(ExclusiveContext* cx, Handle<JSScript*> script, SharedScrip
|
|||
|
||||
ScriptDataTable::AddPtr p = cx->scriptDataTable(lock).lookupForAdd(l);
|
||||
if (p) {
|
||||
js_free(ssd);
|
||||
ssd = *p;
|
||||
MOZ_ASSERT(ssd != *p);
|
||||
freeScriptData();
|
||||
setScriptData(*p);
|
||||
} else {
|
||||
if (!cx->scriptDataTable(lock).add(p, ssd)) {
|
||||
script->setCode(nullptr);
|
||||
script->atoms = nullptr;
|
||||
js_free(ssd);
|
||||
freeScriptData();
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
@ -2491,35 +2499,19 @@ SaveSharedScriptData(ExclusiveContext* cx, Handle<JSScript*> script, SharedScrip
|
|||
if (cx->isJSContext()) {
|
||||
JSContext* ncx = cx->asJSContext();
|
||||
if (JS::IsIncrementalGCInProgress(ncx) && ncx->gc.isFullGc())
|
||||
ssd->marked = true;
|
||||
scriptData()->setMarked(true);
|
||||
}
|
||||
|
||||
script->setCode(ssd->data);
|
||||
script->atoms = ssd->atoms();
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
MarkScriptData(JSRuntime* rt, const jsbytecode* bytecode)
|
||||
{
|
||||
/*
|
||||
* As an invariant, a ScriptBytecodeEntry should not be 'marked' outside of
|
||||
* a GC. Since SweepScriptBytecodes is only called during a full gc,
|
||||
* to preserve this invariant, only mark during a full gc.
|
||||
*/
|
||||
if (rt->gc.isFullGc())
|
||||
SharedScriptData::fromBytecode(bytecode)->marked = true;
|
||||
}
|
||||
|
||||
void
|
||||
js::UnmarkScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
MOZ_ASSERT(rt->gc.isFullGc());
|
||||
ScriptDataTable& table = rt->scriptDataTable(lock);
|
||||
for (ScriptDataTable::Enum e(table); !e.empty(); e.popFront()) {
|
||||
SharedScriptData* entry = e.front();
|
||||
entry->marked = false;
|
||||
}
|
||||
for (ScriptDataTable::Enum e(table); !e.empty(); e.popFront())
|
||||
e.front()->setMarked(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2533,7 +2525,7 @@ js::SweepScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock)
|
|||
|
||||
for (ScriptDataTable::Enum e(table); !e.empty(); e.popFront()) {
|
||||
SharedScriptData* entry = e.front();
|
||||
if (!entry->marked) {
|
||||
if (!entry->marked()) {
|
||||
js_free(entry);
|
||||
e.removeFront();
|
||||
}
|
||||
|
@ -2833,14 +2825,13 @@ JSScript::fullyInitTrivial(ExclusiveContext* cx, Handle<JSScript*> script)
|
|||
if (!partiallyInit(cx, script, 0, 0, 0, 0, 0, 0))
|
||||
return false;
|
||||
|
||||
SharedScriptData* ssd = SharedScriptData::new_(cx, 1, 1, 0);
|
||||
if (!ssd)
|
||||
if (!script->createScriptData(cx, 1, 1, 0))
|
||||
return false;
|
||||
|
||||
ssd->data[0] = JSOP_RETRVAL;
|
||||
ssd->data[1] = SRC_NULL;
|
||||
script->setLength(1);
|
||||
return SaveSharedScriptData(cx, script, ssd, 1);
|
||||
jsbytecode* code = script->code();
|
||||
code[0] = JSOP_RETRVAL;
|
||||
code[1] = SRC_NULL;
|
||||
return script->shareScriptData(cx);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
@ -2926,19 +2917,16 @@ JSScript::fullyInitFromEmitter(ExclusiveContext* cx, HandleScript script, Byteco
|
|||
|
||||
script->lineno_ = bce->firstLine;
|
||||
|
||||
script->setLength(prologueLength + mainLength);
|
||||
script->natoms_ = natoms;
|
||||
SharedScriptData* ssd = SharedScriptData::new_(cx, script->length(), nsrcnotes, natoms);
|
||||
if (!ssd)
|
||||
if (!script->createScriptData(cx, prologueLength + mainLength, nsrcnotes, natoms))
|
||||
return false;
|
||||
|
||||
jsbytecode* code = ssd->data;
|
||||
jsbytecode* code = script->code();
|
||||
PodCopy<jsbytecode>(code, bce->prologue.code.begin(), prologueLength);
|
||||
PodCopy<jsbytecode>(code + prologueLength, bce->main.code.begin(), mainLength);
|
||||
bce->copySrcNotes((jssrcnote*)(code + script->length()), nsrcnotes);
|
||||
InitAtomMap(bce->atomIndices.getMap(), ssd->atoms());
|
||||
InitAtomMap(bce->atomIndices.getMap(), script->atoms());
|
||||
|
||||
if (!SaveSharedScriptData(cx, script, ssd, nsrcnotes))
|
||||
if (!script->shareScriptData(cx))
|
||||
return false;
|
||||
|
||||
if (bce->constList.length() != 0)
|
||||
|
@ -3562,13 +3550,10 @@ js::detail::CopyScript(JSContext* cx, HandleObject scriptStaticScope, HandleScri
|
|||
memcpy(dst->data, src->data, size);
|
||||
|
||||
/* Script filenames, bytecodes and atoms are runtime-wide. */
|
||||
dst->setCode(src->code());
|
||||
dst->atoms = src->atoms;
|
||||
dst->setScriptData(src->scriptData());
|
||||
|
||||
dst->setLength(src->length());
|
||||
dst->lineno_ = src->lineno();
|
||||
dst->mainOffset_ = src->mainOffset();
|
||||
dst->natoms_ = src->natoms();
|
||||
dst->funLength_ = src->funLength();
|
||||
dst->nTypeSets_ = src->nTypeSets();
|
||||
dst->nslots_ = src->nslots();
|
||||
|
@ -3914,6 +3899,21 @@ JSScript::hasBreakpointsAt(jsbytecode* pc)
|
|||
return site->enabledCount > 0;
|
||||
}
|
||||
|
||||
void
|
||||
SharedScriptData::traceChildren(JSTracer* trc)
|
||||
{
|
||||
for (uint32_t i = 0; i < natoms(); ++i)
|
||||
TraceNullableEdge(trc, &atoms()[i], "atom");
|
||||
|
||||
/*
|
||||
* As an invariant, a ScriptBytecodeEntry should not be 'marked' outside of
|
||||
* a GC. Since SweepScriptBytecodes is only called during a full gc,
|
||||
* to preserve this invariant, only mark during a full gc.
|
||||
*/
|
||||
if (trc->isMarkingTracer() && trc->runtime()->gc.isFullGc())
|
||||
setMarked(true);
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::traceChildren(JSTracer* trc)
|
||||
{
|
||||
|
@ -3926,10 +3926,8 @@ JSScript::traceChildren(JSTracer* trc)
|
|||
static_cast<GCMarker*>(trc)->shouldCheckCompartments(),
|
||||
zone()->isCollecting());
|
||||
|
||||
if (atoms) {
|
||||
for (uint32_t i = 0; i < natoms(); ++i)
|
||||
TraceNullableEdge(trc, &atoms[i], "atom");
|
||||
}
|
||||
if (scriptData())
|
||||
scriptData()->traceChildren(trc);
|
||||
|
||||
if (hasObjects()) {
|
||||
ObjectArray* objarray = objects();
|
||||
|
@ -3952,13 +3950,9 @@ JSScript::traceChildren(JSTracer* trc)
|
|||
if (maybeLazyScript())
|
||||
TraceManuallyBarrieredEdge(trc, &lazyScript, "lazyScript");
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
if (trc->isMarkingTracer())
|
||||
compartment()->mark();
|
||||
|
||||
if (code())
|
||||
MarkScriptData(trc->runtime(), code());
|
||||
}
|
||||
|
||||
bindings.trace(trc);
|
||||
|
||||
jit::TraceJitScripts(trc, this);
|
||||
|
|
|
@ -934,6 +934,89 @@ template<XDRMode mode>
|
|||
bool
|
||||
XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp);
|
||||
|
||||
/*
|
||||
* Common data that can be shared between many scripts in a single runtime.
|
||||
*/
|
||||
class SharedScriptData
|
||||
{
|
||||
uint32_t dataLength_;
|
||||
uint32_t natoms_;
|
||||
uint32_t codeLength_;
|
||||
mozilla::Atomic<bool, mozilla::ReleaseAcquire> marked_;
|
||||
uintptr_t data_[1];
|
||||
|
||||
public:
|
||||
static SharedScriptData* new_(ExclusiveContext* cx, uint32_t codeLength,
|
||||
uint32_t srcnotesLength, uint32_t natoms);
|
||||
|
||||
uint32_t dataLength() const {
|
||||
return dataLength_;
|
||||
}
|
||||
uint8_t* data() {
|
||||
return reinterpret_cast<uint8_t*>(data_);
|
||||
}
|
||||
|
||||
uint32_t natoms() const {
|
||||
return natoms_;
|
||||
}
|
||||
GCPtrAtom* atoms() {
|
||||
if (!natoms_)
|
||||
return nullptr;
|
||||
return reinterpret_cast<GCPtrAtom*>(data());
|
||||
}
|
||||
|
||||
uint32_t codeLength() const {
|
||||
return codeLength_;
|
||||
}
|
||||
jsbytecode* code() {
|
||||
return reinterpret_cast<jsbytecode*>(data() + natoms_ * sizeof(GCPtrAtom));
|
||||
}
|
||||
|
||||
bool marked() const {
|
||||
return marked_;
|
||||
}
|
||||
void setMarked(bool marked) {
|
||||
marked_ = marked;
|
||||
}
|
||||
|
||||
void traceChildren(JSTracer* trc);
|
||||
|
||||
private:
|
||||
SharedScriptData() = delete;
|
||||
SharedScriptData(const SharedScriptData&) = delete;
|
||||
SharedScriptData& operator=(const SharedScriptData&) = delete;
|
||||
};
|
||||
|
||||
struct ScriptBytecodeHasher
|
||||
{
|
||||
struct Lookup
|
||||
{
|
||||
const uint8_t* data;
|
||||
uint32_t length;
|
||||
|
||||
explicit Lookup(SharedScriptData* ssd) : data(ssd->data()), length(ssd->dataLength()) {}
|
||||
};
|
||||
static HashNumber hash(const Lookup& l) { return mozilla::HashBytes(l.data, l.length); }
|
||||
static bool match(SharedScriptData* entry, const Lookup& lookup) {
|
||||
if (entry->dataLength() != lookup.length)
|
||||
return false;
|
||||
return mozilla::PodEqual<uint8_t>(entry->data(), lookup.data, lookup.length);
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashSet<SharedScriptData*,
|
||||
ScriptBytecodeHasher,
|
||||
SystemAllocPolicy> ScriptDataTable;
|
||||
|
||||
extern void
|
||||
UnmarkScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
extern void
|
||||
SweepScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
extern void
|
||||
FreeScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
class JSScript : public js::gc::TenuredCell
|
||||
|
@ -980,13 +1063,11 @@ class JSScript : public js::gc::TenuredCell
|
|||
// Word-sized fields.
|
||||
|
||||
private:
|
||||
jsbytecode* code_; /* bytecodes and their immediate operands */
|
||||
js::SharedScriptData* scriptData_;
|
||||
public:
|
||||
uint8_t* data; /* pointer to variable-length data array (see
|
||||
comment above Create() for details) */
|
||||
|
||||
js::GCPtrAtom* atoms; /* maps immediate index to literal struct */
|
||||
|
||||
JSCompartment* compartment_;
|
||||
|
||||
private:
|
||||
|
@ -1026,7 +1107,6 @@ class JSScript : public js::gc::TenuredCell
|
|||
|
||||
// 32-bit fields.
|
||||
|
||||
uint32_t length_; /* length of code vector */
|
||||
uint32_t dataSize_; /* size of the used part of the data array */
|
||||
|
||||
uint32_t lineno_; /* base line number of script */
|
||||
|
@ -1035,7 +1115,6 @@ class JSScript : public js::gc::TenuredCell
|
|||
uint32_t mainOffset_;/* offset of main entry point from code, after
|
||||
predef'ing prologue */
|
||||
|
||||
uint32_t natoms_; /* length of atoms array */
|
||||
uint32_t nslots_; /* vars plus maximum stack depth */
|
||||
|
||||
/* Range of characters in scriptSource which contains this script's source. */
|
||||
|
@ -1200,7 +1279,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
// instead of private to suppress -Wunused-private-field compiler warnings.
|
||||
protected:
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
// No padding currently required.
|
||||
uint32_t padding_;
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -1248,16 +1327,20 @@ class JSScript : public js::gc::TenuredCell
|
|||
|
||||
void setVersion(JSVersion v) { version = v; }
|
||||
|
||||
// Script bytecode is immutable after creation.
|
||||
jsbytecode* code() const {
|
||||
return code_;
|
||||
}
|
||||
size_t length() const {
|
||||
return length_;
|
||||
js::SharedScriptData* scriptData() {
|
||||
return scriptData_;
|
||||
}
|
||||
|
||||
void setCode(jsbytecode* code) { code_ = code; }
|
||||
void setLength(size_t length) { length_ = length; }
|
||||
// Script bytecode is immutable after creation.
|
||||
jsbytecode* code() const {
|
||||
if (!scriptData_)
|
||||
return nullptr;
|
||||
return scriptData_->code();
|
||||
}
|
||||
size_t length() const {
|
||||
MOZ_ASSERT(scriptData_);
|
||||
return scriptData_->codeLength();
|
||||
}
|
||||
|
||||
jsbytecode* codeEnd() const { return code() + length(); }
|
||||
|
||||
|
@ -1714,6 +1797,12 @@ class JSScript : public js::gc::TenuredCell
|
|||
private:
|
||||
bool makeTypes(JSContext* cx);
|
||||
|
||||
bool createScriptData(js::ExclusiveContext* cx, uint32_t codeLength, uint32_t srcnotesLength,
|
||||
uint32_t natoms);
|
||||
bool shareScriptData(js::ExclusiveContext* cx);
|
||||
void freeScriptData();
|
||||
void setScriptData(js::SharedScriptData* data);
|
||||
|
||||
public:
|
||||
uint32_t getWarmUpCount() const { return warmUpCount; }
|
||||
uint32_t incWarmUpCounter(uint32_t amount = 1) { return warmUpCount += amount; }
|
||||
|
@ -1807,11 +1896,18 @@ class JSScript : public js::gc::TenuredCell
|
|||
|
||||
bool hasLoops();
|
||||
|
||||
size_t natoms() const { return natoms_; }
|
||||
size_t natoms() const {
|
||||
MOZ_ASSERT(scriptData_);
|
||||
return scriptData_->natoms();
|
||||
}
|
||||
js::GCPtrAtom* atoms() const {
|
||||
MOZ_ASSERT(scriptData_);
|
||||
return scriptData_->atoms();
|
||||
}
|
||||
|
||||
js::GCPtrAtom& getAtom(size_t index) const {
|
||||
MOZ_ASSERT(index < natoms());
|
||||
return atoms[index];
|
||||
return atoms()[index];
|
||||
}
|
||||
|
||||
js::GCPtrAtom& getAtom(jsbytecode* pc) const {
|
||||
|
@ -2411,61 +2507,6 @@ class LazyScript : public gc::TenuredCell
|
|||
/* If this fails, add/remove padding within LazyScript. */
|
||||
JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);
|
||||
|
||||
struct SharedScriptData
|
||||
{
|
||||
uint32_t length;
|
||||
uint32_t natoms;
|
||||
mozilla::Atomic<bool, mozilla::ReleaseAcquire> marked;
|
||||
jsbytecode data[1];
|
||||
|
||||
static SharedScriptData* new_(ExclusiveContext* cx, uint32_t codeLength,
|
||||
uint32_t srcnotesLength, uint32_t natoms);
|
||||
|
||||
GCPtrAtom* atoms() {
|
||||
if (!natoms)
|
||||
return nullptr;
|
||||
return reinterpret_cast<GCPtrAtom*>(data + length - sizeof(JSAtom*) * natoms);
|
||||
}
|
||||
|
||||
static SharedScriptData* fromBytecode(const jsbytecode* bytecode) {
|
||||
return (SharedScriptData*)(bytecode - offsetof(SharedScriptData, data));
|
||||
}
|
||||
|
||||
private:
|
||||
SharedScriptData() = delete;
|
||||
SharedScriptData(const SharedScriptData&) = delete;
|
||||
};
|
||||
|
||||
struct ScriptBytecodeHasher
|
||||
{
|
||||
struct Lookup
|
||||
{
|
||||
jsbytecode* code;
|
||||
uint32_t length;
|
||||
|
||||
explicit Lookup(SharedScriptData* ssd) : code(ssd->data), length(ssd->length) {}
|
||||
};
|
||||
static HashNumber hash(const Lookup& l) { return mozilla::HashBytes(l.code, l.length); }
|
||||
static bool match(SharedScriptData* entry, const Lookup& lookup) {
|
||||
if (entry->length != lookup.length)
|
||||
return false;
|
||||
return mozilla::PodEqual<jsbytecode>(entry->data, lookup.code, lookup.length);
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashSet<SharedScriptData*,
|
||||
ScriptBytecodeHasher,
|
||||
SystemAllocPolicy> ScriptDataTable;
|
||||
|
||||
extern void
|
||||
UnmarkScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
extern void
|
||||
SweepScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
extern void
|
||||
FreeScriptData(JSRuntime* rt, AutoLockForExclusiveAccess& lock);
|
||||
|
||||
struct ScriptAndCounts
|
||||
{
|
||||
/* This structure is stored and marked from the JSRuntime. */
|
||||
|
|
Загрузка…
Ссылка в новой задаче