mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 739512 - Patch 2: space-optimize representation of closedArgs and closedVars. r=dvander.
--HG-- extra : rebase_source : 8738fae7581265ba464899c9a7b6c53c118740b8
This commit is contained in:
parent
8b3be8fd77
commit
0180fca1d0
@ -188,7 +188,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
for (unsigned i = 0; i < nargs; i++)
|
||||
escapedSlots[ArgSlot(i)] = true;
|
||||
} else {
|
||||
for (unsigned i = 0; i < script->nClosedArgs; i++) {
|
||||
for (uint32_t i = 0; i < script->nClosedArgs(); i++) {
|
||||
unsigned arg = script->getClosedArg(i);
|
||||
JS_ASSERT(arg < nargs);
|
||||
escapedSlots[ArgSlot(arg)] = true;
|
||||
@ -199,7 +199,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
for (unsigned i = 0; i < script->nfixed; i++)
|
||||
escapedSlots[LocalSlot(script, i)] = true;
|
||||
} else {
|
||||
for (uint32_t i = 0; i < script->nClosedVars; i++) {
|
||||
for (uint32_t i = 0; i < script->nClosedVars(); i++) {
|
||||
unsigned local = script->getClosedVar(i);
|
||||
JS_ASSERT(local < script->nfixed);
|
||||
escapedSlots[LocalSlot(script, local)] = true;
|
||||
@ -218,13 +218,13 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
isCompileable = true;
|
||||
|
||||
isInlineable = true;
|
||||
if (script->nClosedArgs || script->nClosedVars || heavyweight ||
|
||||
if (script->nClosedArgs() || script->nClosedVars() || heavyweight ||
|
||||
script->usesEval || script->mayNeedArgsObj() || cx->compartment->debugMode()) {
|
||||
isInlineable = false;
|
||||
}
|
||||
|
||||
modifiesArguments_ = false;
|
||||
if (script->nClosedArgs || heavyweight)
|
||||
if (script->nClosedArgs() || heavyweight)
|
||||
modifiesArguments_ = true;
|
||||
|
||||
canTrackVars = true;
|
||||
|
@ -405,15 +405,14 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||
};
|
||||
|
||||
uint32_t length, lineno, nslots;
|
||||
uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, i;
|
||||
uint32_t prologLength, version, encodedClosedCount;
|
||||
uint16_t nClosedArgs = 0, nClosedVars = 0;
|
||||
uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, nClosedArgs, nClosedVars, i;
|
||||
uint32_t prologLength, version;
|
||||
uint32_t nTypeSets = 0;
|
||||
uint32_t scriptBits = 0;
|
||||
|
||||
JSContext *cx = xdr->cx();
|
||||
JSScript *script;
|
||||
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
||||
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = nClosedArgs = nClosedVars = 0;
|
||||
jssrcnote *notes = NULL;
|
||||
|
||||
/* XDR arguments, local vars, and upvars. */
|
||||
@ -533,18 +532,17 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||
notes = script->notes();
|
||||
nsrcnotes = script->numNotes();
|
||||
|
||||
if (JSScript::isValidOffset(script->constsOffset))
|
||||
nconsts = script->consts()->length;
|
||||
if (JSScript::isValidOffset(script->objectsOffset))
|
||||
nobjects = script->objects()->length;
|
||||
if (JSScript::isValidOffset(script->regexpsOffset))
|
||||
nregexps = script->regexps()->length;
|
||||
if (JSScript::isValidOffset(script->trynotesOffset))
|
||||
ntrynotes = script->trynotes()->length;
|
||||
if (JSScript::isValidOffset(script->constOffset))
|
||||
nconsts = script->consts()->length;
|
||||
|
||||
nClosedArgs = script->nClosedArgs;
|
||||
nClosedVars = script->nClosedVars;
|
||||
encodedClosedCount = (nClosedArgs << 16) | nClosedVars;
|
||||
/* no globals when encoding; see assertion above */
|
||||
nClosedArgs = script->nClosedArgs();
|
||||
nClosedVars = script->nClosedVars();
|
||||
|
||||
nTypeSets = script->nTypeSets;
|
||||
|
||||
@ -597,7 +595,9 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||
return JS_FALSE;
|
||||
if (!xdr->codeUint32(&nconsts))
|
||||
return JS_FALSE;
|
||||
if (!xdr->codeUint32(&encodedClosedCount))
|
||||
if (!xdr->codeUint32(&nClosedArgs))
|
||||
return JS_FALSE;
|
||||
if (!xdr->codeUint32(&nClosedVars))
|
||||
return JS_FALSE;
|
||||
if (!xdr->codeUint32(&nTypeSets))
|
||||
return JS_FALSE;
|
||||
@ -605,9 +605,6 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||
return JS_FALSE;
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
nClosedArgs = encodedClosedCount >> 16;
|
||||
nClosedVars = encodedClosedCount & 0xFFFF;
|
||||
|
||||
/* Note: version is packed into the 32b space with another 16b value. */
|
||||
JSVersion version_ = JSVersion(version & JS_BITMASK(16));
|
||||
JS_ASSERT((version_ & VersionFlags::FULL_MASK) == unsigned(version_));
|
||||
@ -715,11 +712,11 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i != nClosedArgs; ++i) {
|
||||
if (!xdr->codeUint32(&script->closedSlots[i]))
|
||||
if (!xdr->codeUint32(&script->closedArgs()->vector[i]))
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i != nClosedVars; ++i) {
|
||||
if (!xdr->codeUint32(&script->closedSlots[nClosedArgs + i]))
|
||||
if (!xdr->codeUint32(&script->closedVars()->vector[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -908,53 +905,102 @@ js::FreeScriptFilenames(JSCompartment *comp)
|
||||
}
|
||||
|
||||
/*
|
||||
* JSScript data structures memory alignment:
|
||||
* JSScript::data has a complex, manually-controlled, memory layout.
|
||||
*
|
||||
* JSScript
|
||||
* JSObjectArray script objects' descriptor if JSScript.objectsOffset != 0,
|
||||
* use script->objects() to access it.
|
||||
* JSObjectArray script regexps' descriptor if JSScript.regexpsOffset != 0,
|
||||
* use script->regexps() to access it.
|
||||
* JSTryNoteArray script try notes' descriptor if JSScript.tryNotesOffset
|
||||
* != 0, use script->trynotes() to access it.
|
||||
* JSAtom *a[] array of JSScript.natoms atoms pointed by
|
||||
* JSScript.atoms if any.
|
||||
* JSObject *o[] array of script->objects()->length objects if any
|
||||
* pointed by script->objects()->vector.
|
||||
* JSObject *r[] array of script->regexps()->length regexps if any
|
||||
* pointed by script->regexps()->vector.
|
||||
* JSTryNote t[] array of script->trynotes()->length try notes if any
|
||||
* pointed by script->trynotes()->vector.
|
||||
* jsbytecode b[] script bytecode pointed by JSScript.code.
|
||||
* jssrcnote s[] script source notes, use script->notes() to access it
|
||||
* First are some optional array headers. They are optional because they
|
||||
* often aren't needed, i.e. the corresponding arrays often have zero elements.
|
||||
* Each header has an offset in JSScript that indicates its location within
|
||||
* |data|; that offset is INVALID_OFFSET if the array header is not present.
|
||||
* Each header also has an accessor function in JSScript.
|
||||
*
|
||||
* The alignment avoids gaps between entries as alignment requirement for each
|
||||
* subsequent structure or array is the same or divides the alignment
|
||||
* requirement for the previous one.
|
||||
* Array type Array elements Offset Accessor
|
||||
* ---------- -------------- ------ --------
|
||||
* JSConstArray Consts constsOffset consts()
|
||||
* JSObjectArray Objects objectsOffset objects()
|
||||
* JSObjectArray Regexps regexpsOffset regexps()
|
||||
* JSTryNoteArray Try notes tryNotesOffset trynotes()
|
||||
* GlobalSlotArray Globals globalsOffset globals()
|
||||
* ClosedSlotArray ClosedArgs closedArgsOffset closedArgs()
|
||||
* ClosedSlotArray ClosedVars closedVarsOffset closedVars()
|
||||
*
|
||||
* The followings asserts checks that assuming that the alignment requirement
|
||||
* for JSObjectArray and JSTryNoteArray are sizeof(void *) and for JSTryNote
|
||||
* it is sizeof(uint32_t) as the structure consists of 3 uint32_t fields.
|
||||
* Then are the elements of several arrays.
|
||||
* - Most of these arrays have headers listed above (if present). For each of
|
||||
* these, the array pointer and the array length is stored in the header.
|
||||
* - The remaining arrays have pointers and lengths that are stored directly in
|
||||
* JSScript. This is because, unlike the others, they are nearly always
|
||||
* non-zero length and so the optional-header space optimization isn't
|
||||
* worthwhile.
|
||||
*
|
||||
* Array elements Pointed to by Length
|
||||
* -------------- ------------- ------
|
||||
* Consts consts()->vector consts()->length
|
||||
* Atoms atoms natoms
|
||||
* Objects objects()->vector objects()->length
|
||||
* Regexps regexps()->vector regexps()->length
|
||||
* Try notes trynotes()->vector trynotes()->length
|
||||
* Globals globals()->vector globals()->length
|
||||
* Closed args closedArgs()->vector closedArgs()->length
|
||||
* Closed vars closedVars()->vector closedVars()->length
|
||||
* Bytecodes code length
|
||||
* Source notes notes() numNotes() * sizeof(jssrcnote)
|
||||
*
|
||||
* IMPORTANT: This layout has two key properties.
|
||||
* - It ensures that everything has sufficient alignment; in particular, the
|
||||
* consts() elements need jsval alignment.
|
||||
* - It ensures there are no gaps between elements, which saves space and makes
|
||||
* manual layout easy. In particular, in the second part, arrays with larger
|
||||
* elements precede arrays with smaller elements.
|
||||
*
|
||||
* The following static assertions check these properties.
|
||||
*/
|
||||
JS_STATIC_ASSERT(sizeof(JSScript) % sizeof(void *) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(void *) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSTryNoteArray) == sizeof(JSObjectArray));
|
||||
JS_STATIC_ASSERT(sizeof(JSAtom *) == sizeof(JSObject *));
|
||||
JS_STATIC_ASSERT(sizeof(JSObject *) % sizeof(uint32_t) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSTryNote) == 3 * sizeof(uint32_t));
|
||||
JS_STATIC_ASSERT(sizeof(uint32_t) % sizeof(jsbytecode) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(jsbytecode) % sizeof(jssrcnote) == 0);
|
||||
|
||||
#define KEEPS_JSVAL_ALIGNMENT(T) \
|
||||
(JS_ALIGNMENT_OF(jsval) % JS_ALIGNMENT_OF(T) == 0 && \
|
||||
sizeof(T) % sizeof(jsval) == 0)
|
||||
|
||||
#define HAS_JSVAL_ALIGNMENT(T) \
|
||||
(JS_ALIGNMENT_OF(jsval) == JS_ALIGNMENT_OF(T) && \
|
||||
sizeof(T) == sizeof(jsval))
|
||||
|
||||
#define NO_PADDING_BETWEEN_ENTRIES(T1, T2) \
|
||||
(JS_ALIGNMENT_OF(T1) % JS_ALIGNMENT_OF(T2) == 0)
|
||||
|
||||
/*
|
||||
* These assertions ensure that there is no padding between the array headers,
|
||||
* and also that the consts() elements (which follow immediately afterward) are
|
||||
* jsval-aligned. (There is an assumption that |data| itself is jsval-aligned;
|
||||
* we check this below).
|
||||
*/
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(JSConstArray));
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(JSObjectArray)); /* there are two of these */
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(JSTryNoteArray));
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(GlobalSlotArray));
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(ClosedSlotArray)); /* there are two of these */
|
||||
|
||||
/* These assertions ensure there is no padding required between array elements. */
|
||||
JS_STATIC_ASSERT(HAS_JSVAL_ALIGNMENT(HeapValue));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapValue, JSAtom *));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(JSAtom *, HeapPtrObject));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapPtrObject, HeapPtrObject));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapPtrObject, JSTryNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(JSTryNote, GlobalSlotArray::Entry));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(GlobalSlotArray::Entry, uint32_t));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(uint32_t, uint32_t));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(uint32_t, jsbytecode));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(jsbytecode, jssrcnote));
|
||||
|
||||
/*
|
||||
* Check that uint8_t offsets is enough to reach any optional array allocated
|
||||
* after JSScript. For that we check that the maximum possible offset for
|
||||
* JSConstArray, that last optional array, still fits 1 byte and do not
|
||||
* coincide with INVALID_OFFSET.
|
||||
* within |data|. For that we check that the maximum possible offset for the
|
||||
* closedVars array -- the last optional array -- still fits in 1 byte and does
|
||||
* not coincide with INVALID_OFFSET.
|
||||
*/
|
||||
JS_STATIC_ASSERT(sizeof(JSObjectArray) +
|
||||
JS_STATIC_ASSERT(sizeof(JSConstArray) +
|
||||
sizeof(JSObjectArray) +
|
||||
sizeof(JSObjectArray) +
|
||||
sizeof(JSTryNoteArray) +
|
||||
sizeof(js::GlobalSlotArray)
|
||||
sizeof(js::GlobalSlotArray) +
|
||||
sizeof(js::ClosedSlotArray)
|
||||
< JSScript::INVALID_OFFSET);
|
||||
JS_STATIC_ASSERT(JSScript::INVALID_OFFSET <= 255);
|
||||
|
||||
@ -964,7 +1010,11 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t
|
||||
uint32_t ntrynotes, uint32_t nconsts, uint32_t nglobals,
|
||||
uint16_t nClosedArgs, uint16_t nClosedVars, uint32_t nTypeSets, JSVersion version)
|
||||
{
|
||||
size_t size = sizeof(JSAtom *) * natoms;
|
||||
size_t size = 0;
|
||||
|
||||
if (nconsts != 0)
|
||||
size += sizeof(JSConstArray) + nconsts * sizeof(Value);
|
||||
size += sizeof(JSAtom *) * natoms;
|
||||
if (nobjects != 0)
|
||||
size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
|
||||
if (nregexps != 0)
|
||||
@ -973,24 +1023,13 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t
|
||||
size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
|
||||
if (nglobals != 0)
|
||||
size += sizeof(GlobalSlotArray) + nglobals * sizeof(GlobalSlotArray::Entry);
|
||||
uint32_t totalClosed = nClosedArgs + nClosedVars;
|
||||
if (totalClosed != 0)
|
||||
size += totalClosed * sizeof(uint32_t);
|
||||
if (nClosedArgs != 0)
|
||||
size += sizeof(ClosedSlotArray) + nClosedArgs * sizeof(uint32_t);
|
||||
if (nClosedVars != 0)
|
||||
size += sizeof(ClosedSlotArray) + nClosedVars * sizeof(uint32_t);
|
||||
|
||||
/*
|
||||
* To esnure jsval alignment for the const array we place it immediately
|
||||
* after JSSomethingArray structs as their sizes all divide sizeof(jsval).
|
||||
* This works as long as the data itself is allocated with proper
|
||||
* alignment which we ensure below.
|
||||
*/
|
||||
JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(jsval) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSTryNoteArray) % sizeof(jsval) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(GlobalSlotArray) % sizeof(jsval) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(JSConstArray) % sizeof(jsval) == 0);
|
||||
if (nconsts != 0)
|
||||
size += sizeof(JSConstArray) + nconsts * sizeof(Value);
|
||||
|
||||
size += length * sizeof(jsbytecode) + nsrcnotes * sizeof(jssrcnote);
|
||||
size += length * sizeof(jsbytecode);
|
||||
size += nsrcnotes * sizeof(jssrcnote);
|
||||
|
||||
/*
|
||||
* We assume that calloc aligns on sizeof(Value) if the size we ask to
|
||||
@ -1014,6 +1053,12 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t
|
||||
new (&script->bindings) Bindings(cx);
|
||||
|
||||
uint8_t *cursor = data;
|
||||
if (nconsts != 0) {
|
||||
script->constsOffset = uint8_t(cursor - data);
|
||||
cursor += sizeof(JSConstArray);
|
||||
} else {
|
||||
script->constsOffset = JSScript::INVALID_OFFSET;
|
||||
}
|
||||
if (nobjects != 0) {
|
||||
script->objectsOffset = uint8_t(cursor - data);
|
||||
cursor += sizeof(JSObjectArray);
|
||||
@ -1038,19 +1083,19 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t
|
||||
} else {
|
||||
script->globalsOffset = JSScript::INVALID_OFFSET;
|
||||
}
|
||||
JS_ASSERT(cursor - data < 0xFF);
|
||||
if (nconsts != 0) {
|
||||
script->constOffset = uint8_t(cursor - data);
|
||||
cursor += sizeof(JSConstArray);
|
||||
if (nClosedArgs != 0) {
|
||||
script->closedArgsOffset = uint8_t(cursor - data);
|
||||
cursor += sizeof(ClosedSlotArray);
|
||||
} else {
|
||||
script->constOffset = JSScript::INVALID_OFFSET;
|
||||
script->closedArgsOffset = JSScript::INVALID_OFFSET;
|
||||
}
|
||||
JS_ASSERT(cursor - data < 0xFF);
|
||||
if (nClosedVars != 0) {
|
||||
script->closedVarsOffset = uint8_t(cursor - data);
|
||||
cursor += sizeof(ClosedSlotArray);
|
||||
} else {
|
||||
script->closedVarsOffset = JSScript::INVALID_OFFSET;
|
||||
}
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSObjectArray) +
|
||||
sizeof(JSObjectArray) +
|
||||
sizeof(JSTryNoteArray) +
|
||||
sizeof(GlobalSlotArray) < 0xFF);
|
||||
|
||||
|
||||
if (nconsts != 0) {
|
||||
JS_ASSERT(reinterpret_cast<uintptr_t>(cursor) % sizeof(jsval) == 0);
|
||||
@ -1093,11 +1138,16 @@ JSScript::NewScript(JSContext *cx, uint32_t length, uint32_t nsrcnotes, uint32_t
|
||||
cursor += nglobals * sizeof(script->globals()->vector[0]);
|
||||
}
|
||||
|
||||
if (totalClosed != 0) {
|
||||
script->nClosedArgs = nClosedArgs;
|
||||
script->nClosedVars = nClosedVars;
|
||||
script->closedSlots = reinterpret_cast<uint32_t *>(cursor);
|
||||
cursor += totalClosed * sizeof(uint32_t);
|
||||
if (nClosedArgs != 0) {
|
||||
script->closedArgs()->length = nClosedArgs;
|
||||
script->closedArgs()->vector = reinterpret_cast<uint32_t *>(cursor);
|
||||
cursor += nClosedArgs * sizeof(script->closedArgs()->vector[0]);
|
||||
}
|
||||
|
||||
if (nClosedVars != 0) {
|
||||
script->closedVars()->length = nClosedVars;
|
||||
script->closedVars()->vector = reinterpret_cast<uint32_t *>(cursor);
|
||||
cursor += nClosedVars * sizeof(script->closedVars()->vector[0]);
|
||||
}
|
||||
|
||||
JS_ASSERT(nTypeSets <= UINT16_MAX);
|
||||
@ -1229,12 +1279,10 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
bce->globalUses.length());
|
||||
}
|
||||
|
||||
if (script->nClosedArgs)
|
||||
PodCopy<uint32_t>(script->closedSlots, &bce->closedArgs[0], script->nClosedArgs);
|
||||
if (script->nClosedVars) {
|
||||
PodCopy<uint32_t>(&script->closedSlots[script->nClosedArgs], &bce->closedVars[0],
|
||||
script->nClosedVars);
|
||||
}
|
||||
if (nClosedArgs)
|
||||
PodCopy<uint32_t>(script->closedArgs()->vector, &bce->closedArgs[0], nClosedArgs);
|
||||
if (nClosedVars)
|
||||
PodCopy<uint32_t>(script->closedVars()->vector, &bce->closedVars[0], nClosedVars);
|
||||
|
||||
script->bindings.transfer(cx, &bce->bindings);
|
||||
|
||||
@ -1614,12 +1662,6 @@ js::CloneScript(JSContext *cx, JSScript *script)
|
||||
return newScript;
|
||||
}
|
||||
|
||||
void
|
||||
JSScript::copyClosedSlotsTo(JSScript *other)
|
||||
{
|
||||
js_memcpy(other->closedSlots, closedSlots, nClosedArgs + nClosedVars);
|
||||
}
|
||||
|
||||
bool
|
||||
JSScript::ensureHasDebug(JSContext *cx)
|
||||
{
|
||||
@ -1804,7 +1846,7 @@ JSScript::markChildren(JSTracer *trc)
|
||||
MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
|
||||
}
|
||||
|
||||
if (JSScript::isValidOffset(constOffset)) {
|
||||
if (JSScript::isValidOffset(constsOffset)) {
|
||||
JSConstArray *constarray = consts();
|
||||
MarkValueRange(trc, constarray->length, constarray->vector, "consts");
|
||||
}
|
||||
|
@ -101,6 +101,11 @@ struct GlobalSlotArray {
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct ClosedSlotArray {
|
||||
uint32_t *vector; /* array of closed slots */
|
||||
uint32_t length; /* count of closed slots */
|
||||
};
|
||||
|
||||
struct Shape;
|
||||
|
||||
enum BindingKind { NONE, ARGUMENT, VARIABLE, CONSTANT };
|
||||
@ -348,7 +353,8 @@ struct JSScript : public js::gc::Cell
|
||||
|
||||
public:
|
||||
jsbytecode *code; /* bytecodes and their immediate operands */
|
||||
uint8_t *data; /* pointer to variable-length data array */
|
||||
uint8_t *data; /* pointer to variable-length data array (see
|
||||
comment above NewScript() for details) */
|
||||
|
||||
const char *filename; /* source filename or null */
|
||||
JSAtom **atoms; /* maps immediate index to literal struct */
|
||||
@ -371,8 +377,6 @@ struct JSScript : public js::gc::Cell
|
||||
*/
|
||||
js::HeapPtr<js::GlobalObject, JSScript*> globalObject;
|
||||
|
||||
uint32_t *closedSlots; /* vector of closed slots; args first, then vars. */
|
||||
|
||||
/* Execution and profiling information for JIT code in the script. */
|
||||
js::ScriptOpcodeCounts pcCounters;
|
||||
|
||||
@ -440,9 +444,6 @@ struct JSScript : public js::gc::Cell
|
||||
uint16_t nslots; /* vars plus maximum stack depth */
|
||||
uint16_t staticLevel;/* static level for display maintenance */
|
||||
|
||||
uint16_t nClosedArgs;/* number of args which are closed over. */
|
||||
uint16_t nClosedVars;/* number of vars which are closed over. */
|
||||
|
||||
/* 8-bit fields. */
|
||||
|
||||
/*
|
||||
@ -450,6 +451,7 @@ struct JSScript : public js::gc::Cell
|
||||
* JSScript::INVALID_OFFSET if the array has length 0.
|
||||
*/
|
||||
public:
|
||||
uint8_t constsOffset; /* offset to the array of constants */
|
||||
uint8_t objectsOffset; /* offset to the array of nested function,
|
||||
block, scope, xml and one-time regexps
|
||||
objects */
|
||||
@ -457,7 +459,8 @@ struct JSScript : public js::gc::Cell
|
||||
regexps */
|
||||
uint8_t trynotesOffset; /* offset to the array of try notes */
|
||||
uint8_t globalsOffset; /* offset to the array of global slots */
|
||||
uint8_t constOffset; /* offset to the array of constants */
|
||||
uint8_t closedArgsOffset; /* offset to the array of closed args */
|
||||
uint8_t closedVarsOffset; /* offset to the array of closed vars */
|
||||
|
||||
/* 1-bit fields. */
|
||||
|
||||
@ -650,6 +653,11 @@ struct JSScript : public js::gc::Cell
|
||||
static const uint8_t INVALID_OFFSET = 0xFF;
|
||||
static bool isValidOffset(uint8_t offset) { return offset != INVALID_OFFSET; }
|
||||
|
||||
JSConstArray *consts() {
|
||||
JS_ASSERT(isValidOffset(constsOffset));
|
||||
return reinterpret_cast<JSConstArray *>(data + constsOffset);
|
||||
}
|
||||
|
||||
JSObjectArray *objects() {
|
||||
JS_ASSERT(isValidOffset(objectsOffset));
|
||||
return reinterpret_cast<JSObjectArray *>(data + objectsOffset);
|
||||
@ -670,9 +678,22 @@ struct JSScript : public js::gc::Cell
|
||||
return reinterpret_cast<js::GlobalSlotArray *>(data + globalsOffset);
|
||||
}
|
||||
|
||||
JSConstArray *consts() {
|
||||
JS_ASSERT(isValidOffset(constOffset));
|
||||
return reinterpret_cast<JSConstArray *>(data + constOffset);
|
||||
js::ClosedSlotArray *closedArgs() {
|
||||
JS_ASSERT(isValidOffset(closedArgsOffset));
|
||||
return reinterpret_cast<js::ClosedSlotArray *>(data + closedArgsOffset);
|
||||
}
|
||||
|
||||
js::ClosedSlotArray *closedVars() {
|
||||
JS_ASSERT(isValidOffset(closedVarsOffset));
|
||||
return reinterpret_cast<js::ClosedSlotArray *>(data + closedVarsOffset);
|
||||
}
|
||||
|
||||
uint32_t nClosedArgs() {
|
||||
return isValidOffset(closedArgsOffset) ? closedArgs()->length : 0;
|
||||
}
|
||||
|
||||
uint32_t nClosedVars() {
|
||||
return isValidOffset(closedVarsOffset) ? closedVars()->length : 0;
|
||||
}
|
||||
|
||||
JSAtom *getAtom(size_t index) {
|
||||
@ -713,17 +734,17 @@ struct JSScript : public js::gc::Cell
|
||||
inline bool isEmpty() const;
|
||||
|
||||
uint32_t getClosedArg(uint32_t index) {
|
||||
JS_ASSERT(index < nClosedArgs);
|
||||
return closedSlots[index];
|
||||
js::ClosedSlotArray *arr = closedArgs();
|
||||
JS_ASSERT(index < arr->length);
|
||||
return arr->vector[index];
|
||||
}
|
||||
|
||||
uint32_t getClosedVar(uint32_t index) {
|
||||
JS_ASSERT(index < nClosedVars);
|
||||
return closedSlots[nClosedArgs + index];
|
||||
js::ClosedSlotArray *arr = closedVars();
|
||||
JS_ASSERT(index < arr->length);
|
||||
return arr->vector[index];
|
||||
}
|
||||
|
||||
void copyClosedSlotsTo(JSScript *other);
|
||||
|
||||
private:
|
||||
/*
|
||||
* Attempt to recompile with or without single-stepping support, as directed
|
||||
|
@ -65,6 +65,17 @@ js_memcpy(void *dst_, const void *src_, size_t len)
|
||||
#ifdef __cplusplus
|
||||
namespace js {
|
||||
|
||||
template <class T>
|
||||
struct AlignmentTestStruct
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
};
|
||||
|
||||
/* This macro determines the alignment requirements of a type. */
|
||||
#define JS_ALIGNMENT_OF(t_) \
|
||||
(sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_))
|
||||
|
||||
template <class T>
|
||||
class AlignedPtrAndFlag
|
||||
{
|
||||
|
@ -99,7 +99,7 @@ js_PutCallObject(StackFrame *fp)
|
||||
* caches the return value in the slot, so we can't assert that
|
||||
* it's undefined.
|
||||
*/
|
||||
uint32_t nclosed = script->nClosedArgs;
|
||||
uint32_t nclosed = script->nClosedArgs();
|
||||
for (uint32_t i = 0; i < nclosed; i++) {
|
||||
uint32_t e = script->getClosedArg(i);
|
||||
#ifdef JS_GC_ZEAL
|
||||
@ -109,7 +109,7 @@ js_PutCallObject(StackFrame *fp)
|
||||
#endif
|
||||
}
|
||||
|
||||
nclosed = script->nClosedVars;
|
||||
nclosed = script->nClosedVars();
|
||||
for (uint32_t i = 0; i < nclosed; i++) {
|
||||
uint32_t e = script->getClosedVar(i);
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
Loading…
Reference in New Issue
Block a user