mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 932276 - Reserve space in JSScript for an optional block scope array. r=jorendorff
This commit is contained in:
parent
7ee3876782
commit
22d47fa02a
@ -416,7 +416,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
};
|
||||
|
||||
uint32_t length, lineno, nslots;
|
||||
uint32_t natoms, nsrcnotes, ntrynotes, nobjects, nregexps, nconsts, i;
|
||||
uint32_t natoms, nsrcnotes, i;
|
||||
uint32_t nconsts, nobjects, nregexps, ntrynotes, nblockscopes;
|
||||
uint32_t prologLength, version;
|
||||
uint32_t funLength = 0;
|
||||
uint32_t nTypeSets = 0;
|
||||
@ -424,7 +425,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
|
||||
JSContext *cx = xdr->cx();
|
||||
RootedScript script(cx);
|
||||
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = 0;
|
||||
natoms = nsrcnotes = 0;
|
||||
nconsts = nobjects = nregexps = ntrynotes = nblockscopes = 0;
|
||||
|
||||
/* XDR arguments and vars. */
|
||||
uint16_t nargs = 0, nvars = 0;
|
||||
@ -468,6 +470,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
nregexps = script->regexps()->length;
|
||||
if (script->hasTrynotes())
|
||||
ntrynotes = script->trynotes()->length;
|
||||
if (script->hasBlockScopes())
|
||||
nblockscopes = script->blockScopes()->length;
|
||||
|
||||
nTypeSets = script->nTypeSets;
|
||||
funLength = script->funLength;
|
||||
@ -512,21 +516,20 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
if (!xdr->codeUint32(&version))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* To fuse allocations, we need srcnote, atom, objects, regexp, and trynote
|
||||
* counts early.
|
||||
*/
|
||||
// To fuse allocations, we need lengths of all embedded arrays early.
|
||||
if (!xdr->codeUint32(&natoms))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nsrcnotes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&ntrynotes))
|
||||
if (!xdr->codeUint32(&nconsts))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nobjects))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nregexps))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nconsts))
|
||||
if (!xdr->codeUint32(&ntrynotes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nblockscopes))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&nTypeSets))
|
||||
return false;
|
||||
@ -569,8 +572,11 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
return false;
|
||||
|
||||
if (mode == XDR_DECODE) {
|
||||
if (!JSScript::partiallyInit(cx, script, nobjects, nregexps, ntrynotes, nconsts, nTypeSets))
|
||||
if (!JSScript::partiallyInit(cx, script, nconsts, nobjects, nregexps, ntrynotes,
|
||||
nblockscopes, nTypeSets))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(!script->mainOffset);
|
||||
script->mainOffset = prologLength;
|
||||
@ -664,6 +670,14 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nconsts) {
|
||||
HeapValue *vector = script->consts()->vector;
|
||||
for (i = 0; i != nconsts; ++i) {
|
||||
if (!XDRScriptConst(xdr, &vector[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here looping from 0-to-length to xdr objects is essential to ensure that
|
||||
* all references to enclosing blocks (via FindBlockIndex below) happen
|
||||
@ -740,6 +754,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
*objp = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i != nregexps; ++i) {
|
||||
if (!XDRScriptRegExpObject(xdr, &script->regexps()->vector[i]))
|
||||
return false;
|
||||
@ -776,11 +791,13 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
} while (tn != tnfirst);
|
||||
}
|
||||
|
||||
if (nconsts) {
|
||||
HeapValue *vector = script->consts()->vector;
|
||||
for (i = 0; i != nconsts; ++i) {
|
||||
if (!XDRScriptConst(xdr, &vector[i]))
|
||||
return false;
|
||||
for (i = 0; i < nblockscopes; ++i) {
|
||||
BlockScopeNote *note = &script->blockScopes()->vector[i];
|
||||
if (!xdr->codeUint32(¬e->index) ||
|
||||
!xdr->codeUint32(¬e->start) ||
|
||||
!xdr->codeUint32(¬e->length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1580,6 +1597,7 @@ js::FreeScriptData(JSRuntime *rt)
|
||||
* ObjectArray Objects objects()
|
||||
* ObjectArray Regexps regexps()
|
||||
* TryNoteArray Try notes trynotes()
|
||||
* BlockScopeArray Scope notes blockScopes()
|
||||
*
|
||||
* Then are the elements of several arrays.
|
||||
* - Most of these arrays have headers listed above (if present). For each of
|
||||
@ -1595,6 +1613,7 @@ js::FreeScriptData(JSRuntime *rt)
|
||||
* Objects objects()->vector objects()->length
|
||||
* Regexps regexps()->vector regexps()->length
|
||||
* Try notes trynotes()->vector trynotes()->length
|
||||
* Scope notes blockScopes()->vector blockScopes()->length
|
||||
*
|
||||
* IMPORTANT: This layout has two key properties.
|
||||
* - It ensures that everything has sufficient alignment; in particular, the
|
||||
@ -1640,6 +1659,7 @@ js::FreeScriptData(JSRuntime *rt)
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(ConstArray));
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(ObjectArray)); /* there are two of these */
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(TryNoteArray));
|
||||
JS_STATIC_ASSERT(KEEPS_JSVAL_ALIGNMENT(BlockScopeArray));
|
||||
|
||||
/* These assertions ensure there is no padding required between array elements. */
|
||||
JS_STATIC_ASSERT(HAS_JSVAL_ALIGNMENT(HeapValue));
|
||||
@ -1649,9 +1669,15 @@ JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapPtrObject, JSTryNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(JSTryNote, uint32_t));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(uint32_t, uint32_t));
|
||||
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapValue, BlockScopeNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(BlockScopeNote, BlockScopeNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(JSTryNote, BlockScopeNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(HeapPtrObject, BlockScopeNote));
|
||||
JS_STATIC_ASSERT(NO_PADDING_BETWEEN_ENTRIES(BlockScopeNote, uint32_t));
|
||||
|
||||
static inline size_t
|
||||
ScriptDataSize(uint32_t nbindings, uint32_t nobjects, uint32_t nregexps,
|
||||
uint32_t ntrynotes, uint32_t nconsts)
|
||||
ScriptDataSize(uint32_t nbindings, uint32_t nconsts, uint32_t nobjects, uint32_t nregexps,
|
||||
uint32_t ntrynotes, uint32_t nblockscopes)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
@ -1663,6 +1689,8 @@ ScriptDataSize(uint32_t nbindings, uint32_t nobjects, uint32_t nregexps,
|
||||
size += sizeof(ObjectArray) + nregexps * sizeof(JSObject *);
|
||||
if (ntrynotes != 0)
|
||||
size += sizeof(TryNoteArray) + ntrynotes * sizeof(JSTryNote);
|
||||
if (nblockscopes != 0)
|
||||
size += sizeof(BlockScopeArray) + nblockscopes * sizeof(BlockScopeNote);
|
||||
|
||||
if (nbindings != 0) {
|
||||
// Make sure bindings are sufficiently aligned.
|
||||
@ -1736,10 +1764,12 @@ AllocScriptData(ExclusiveContext *cx, size_t size)
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nobjects,
|
||||
uint32_t nregexps, uint32_t ntrynotes, uint32_t nconsts, uint32_t nTypeSets)
|
||||
JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nconsts,
|
||||
uint32_t nobjects, uint32_t nregexps, uint32_t ntrynotes,
|
||||
uint32_t nblockscopes, uint32_t nTypeSets)
|
||||
{
|
||||
size_t size = ScriptDataSize(script->bindings.count(), nobjects, nregexps, ntrynotes, nconsts);
|
||||
size_t size = ScriptDataSize(script->bindings.count(), nconsts, nobjects, nregexps, ntrynotes,
|
||||
nblockscopes);
|
||||
script->data = AllocScriptData(cx, size);
|
||||
if (!script->data)
|
||||
return false;
|
||||
@ -1765,6 +1795,10 @@ JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nobj
|
||||
script->setHasArray(TRYNOTES);
|
||||
cursor += sizeof(TryNoteArray);
|
||||
}
|
||||
if (nblockscopes != 0) {
|
||||
script->setHasArray(BLOCK_SCOPES);
|
||||
cursor += sizeof(BlockScopeArray);
|
||||
}
|
||||
|
||||
if (nconsts != 0) {
|
||||
JS_ASSERT(reinterpret_cast<uintptr_t>(cursor) % sizeof(jsval) == 0);
|
||||
@ -1795,6 +1829,16 @@ JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nobj
|
||||
cursor += vectorSize;
|
||||
}
|
||||
|
||||
if (nblockscopes != 0) {
|
||||
script->blockScopes()->length = nblockscopes;
|
||||
script->blockScopes()->vector = reinterpret_cast<BlockScopeNote *>(cursor);
|
||||
size_t vectorSize = nblockscopes * sizeof(script->blockScopes()->vector[0]);
|
||||
#ifdef DEBUG
|
||||
memset(cursor, 0, vectorSize);
|
||||
#endif
|
||||
cursor += vectorSize;
|
||||
}
|
||||
|
||||
if (script->bindings.count() != 0) {
|
||||
// Make sure bindings are sufficiently aligned.
|
||||
cursor = reinterpret_cast<uint8_t*>
|
||||
@ -1809,7 +1853,7 @@ JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nobj
|
||||
/* static */ bool
|
||||
JSScript::fullyInitTrivial(ExclusiveContext *cx, Handle<JSScript*> script)
|
||||
{
|
||||
if (!partiallyInit(cx, script, 0, 0, 0, 0, 0))
|
||||
if (!partiallyInit(cx, script, 0, 0, 0, 0, 0, 0))
|
||||
return false;
|
||||
|
||||
SharedScriptData *ssd = SharedScriptData::new_(cx, 1, 1, 0);
|
||||
@ -1834,9 +1878,10 @@ JSScript::fullyInitFromEmitter(ExclusiveContext *cx, HandleScript script, Byteco
|
||||
uint32_t prologLength = bce->prologOffset();
|
||||
uint32_t nsrcnotes = uint32_t(bce->countFinalSourceNotes());
|
||||
uint32_t natoms = bce->atomIndices->count();
|
||||
uint32_t nblockscopes = 0;
|
||||
if (!partiallyInit(cx, script,
|
||||
bce->objectList.length, bce->regexpList.length, bce->tryNoteList.length(),
|
||||
bce->constList.length(), bce->typesetCount))
|
||||
bce->constList.length(), bce->objectList.length, bce->regexpList.length,
|
||||
bce->tryNoteList.length(), nblockscopes, bce->typesetCount))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -1873,6 +1918,7 @@ JSScript::fullyInitFromEmitter(ExclusiveContext *cx, HandleScript script, Byteco
|
||||
|
||||
FunctionBox *funbox = bce->sc->isFunctionBox() ? bce->sc->asFunctionBox() : nullptr;
|
||||
|
||||
// FIXME: Initialize blockScopes here.
|
||||
if (bce->tryNoteList.length() != 0)
|
||||
bce->tryNoteList.finish(script->trynotes());
|
||||
if (bce->objectList.length != 0)
|
||||
@ -2279,6 +2325,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
uint32_t nobjects = src->hasObjects() ? src->objects()->length : 0;
|
||||
uint32_t nregexps = src->hasRegexps() ? src->regexps()->length : 0;
|
||||
uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
|
||||
uint32_t nblockscopes = src->hasBlockScopes() ? src->blockScopes()->length : 0;
|
||||
|
||||
/* Script data */
|
||||
|
||||
@ -2444,6 +2491,8 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
}
|
||||
if (ntrynotes != 0)
|
||||
dst->trynotes()->vector = Rebase<JSTryNote>(dst, src, src->trynotes()->vector);
|
||||
if (nblockscopes != 0)
|
||||
dst->blockScopes()->vector = Rebase<BlockScopeNote>(dst, src, src->blockScopes()->vector);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
@ -81,19 +81,31 @@ struct JSTryNote {
|
||||
|
||||
namespace js {
|
||||
|
||||
struct BlockScopeNote {
|
||||
uint32_t index; // Index of StaticScopeObject in the object array.
|
||||
uint32_t start; // Bytecode offset at which this scope starts.
|
||||
uint32_t length; // Bytecode length of scope.
|
||||
uint32_t padding; // Pad to 64-bit boundary.
|
||||
};
|
||||
|
||||
struct ConstArray {
|
||||
js::HeapValue *vector; /* array of indexed constant values */
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
struct ObjectArray {
|
||||
js::HeapPtrObject *vector; /* array of indexed objects */
|
||||
uint32_t length; /* count of indexed objects */
|
||||
js::HeapPtrObject *vector; // Array of indexed objects.
|
||||
uint32_t length; // Count of indexed objects.
|
||||
};
|
||||
|
||||
struct TryNoteArray {
|
||||
JSTryNote *vector; /* array of indexed try notes */
|
||||
uint32_t length; /* count of indexed try notes */
|
||||
JSTryNote *vector; // Array of indexed try notes.
|
||||
uint32_t length; // Count of indexed try notes.
|
||||
};
|
||||
|
||||
struct BlockScopeArray {
|
||||
BlockScopeNote *vector; // Array of indexed BlockScopeNote records.
|
||||
uint32_t length; // Count of indexed try notes.
|
||||
};
|
||||
|
||||
/*
|
||||
@ -552,6 +564,7 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
OBJECTS,
|
||||
REGEXPS,
|
||||
TRYNOTES,
|
||||
BLOCK_SCOPES,
|
||||
ARRAY_KIND_BITS
|
||||
};
|
||||
|
||||
@ -564,7 +577,7 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
uint8_t generatorKindBits_:2;
|
||||
|
||||
// Unused padding; feel free to steal these if you need them.
|
||||
uint8_t padToByte_:2;
|
||||
uint8_t padToByte_:1;
|
||||
|
||||
// 1-bit fields.
|
||||
|
||||
@ -650,8 +663,9 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
// successfully creating any kind (function or other) of new JSScript.
|
||||
// However, callers of fullyInitFromEmitter() do not need to do this.
|
||||
static bool partiallyInit(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
|
||||
uint32_t nobjects, uint32_t nregexps,
|
||||
uint32_t ntrynotes, uint32_t nconsts, uint32_t nTypeSets);
|
||||
uint32_t nconsts, uint32_t nobjects, uint32_t nregexps,
|
||||
uint32_t ntrynotes, uint32_t nblockscopes,
|
||||
uint32_t nTypeSets);
|
||||
static bool fullyInitFromEmitter(js::ExclusiveContext *cx, JS::Handle<JSScript*> script,
|
||||
js::frontend::BytecodeEmitter *bce);
|
||||
// Initialize a no-op script.
|
||||
@ -913,6 +927,7 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
bool hasObjects() { return hasArray(OBJECTS); }
|
||||
bool hasRegexps() { return hasArray(REGEXPS); }
|
||||
bool hasTrynotes() { return hasArray(TRYNOTES); }
|
||||
bool hasBlockScopes() { return hasArray(BLOCK_SCOPES); }
|
||||
|
||||
#define OFF(fooOff, hasFoo, t) (fooOff() + (hasFoo() ? sizeof(t) : 0))
|
||||
|
||||
@ -920,6 +935,7 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
size_t objectsOffset() { return OFF(constsOffset, hasConsts, js::ConstArray); }
|
||||
size_t regexpsOffset() { return OFF(objectsOffset, hasObjects, js::ObjectArray); }
|
||||
size_t trynotesOffset() { return OFF(regexpsOffset, hasRegexps, js::ObjectArray); }
|
||||
size_t blockScopesOffset(){ return OFF(trynotesOffset, hasTrynotes, js::TryNoteArray); }
|
||||
|
||||
js::ConstArray *consts() {
|
||||
JS_ASSERT(hasConsts());
|
||||
@ -941,6 +957,11 @@ class JSScript : public js::gc::BarrieredCell<JSScript>
|
||||
return reinterpret_cast<js::TryNoteArray *>(data + trynotesOffset());
|
||||
}
|
||||
|
||||
js::BlockScopeArray *blockScopes() {
|
||||
JS_ASSERT(hasBlockScopes());
|
||||
return reinterpret_cast<js::BlockScopeArray *>(data + blockScopesOffset());
|
||||
}
|
||||
|
||||
bool hasLoops();
|
||||
|
||||
js::HeapPtrAtom &getAtom(size_t index) const {
|
||||
|
@ -22,7 +22,7 @@ namespace js {
|
||||
* and saved versions. If deserialization fails, the data should be
|
||||
* invalidated if possible.
|
||||
*/
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 153);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 154);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user