Bug 739512 - Patch 2: space-optimize representation of closedArgs and closedVars. r=dvander.

--HG--
extra : rebase_source : 8738fae7581265ba464899c9a7b6c53c118740b8
This commit is contained in:
Nicholas Nethercote 2012-03-25 17:07:33 -07:00
parent 8b3be8fd77
commit 0180fca1d0
5 changed files with 196 additions and 122 deletions

View File

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

View File

@ -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");
}

View File

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

View File

@ -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
{

View File

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