Convert JSScript::*Offset into offsets from the end of JSScript, not from its start, to escape an offset <= 0xFF requirement failing due to an impending increase in the size of JSScripts for bug 614493. r=brendan

--HG--
extra : rebase_source : 8c4046bdc99b8280d414cba864b7d5e1b1f25331
This commit is contained in:
Jeff Walden 2010-12-02 14:23:51 -08:00
Родитель 152f416f22
Коммит e37a3021fa
11 изменённых файлов: 95 добавлений и 74 удалений

Просмотреть файл

@ -1755,7 +1755,7 @@ JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
continue;
nbytes += (sn - notes + 1) * sizeof *sn;
if (script->objectsOffset != 0) {
if (JSScript::isValidOffset(script->objectsOffset)) {
objarray = script->objects();
i = objarray->length;
nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
@ -1764,7 +1764,7 @@ JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
} while (i != 0);
}
if (script->regexpsOffset != 0) {
if (JSScript::isValidOffset(script->regexpsOffset)) {
objarray = script->regexps();
i = objarray->length;
nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
@ -1773,7 +1773,7 @@ JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
} while (i != 0);
}
if (script->trynotesOffset != 0) {
if (JSScript::isValidOffset(script->trynotesOffset)) {
nbytes += sizeof(JSTryNoteArray) +
script->trynotes()->length * sizeof(JSTryNote);
}

Просмотреть файл

@ -389,20 +389,20 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
/* NB: GC must not occur before wscript is homed in wfun->u.i.script. */
JSScript *wscript = JSScript::NewScript(cx, script->length, nsrcnotes,
script->atomMap.length,
(script->objectsOffset != 0)
JSScript::isValidOffset(script->objectsOffset)
? script->objects()->length
: 0,
fun->u.i.nupvars,
(script->regexpsOffset != 0)
JSScript::isValidOffset(script->regexpsOffset)
? script->regexps()->length
: 0,
(script->trynotesOffset != 0)
JSScript::isValidOffset(script->trynotesOffset)
? script->trynotes()->length
: 0,
(script->constOffset != 0)
JSScript::isValidOffset(script->constOffset)
? script->consts()->length
: 0,
(script->globalsOffset != 0)
JSScript::isValidOffset(script->globalsOffset)
? script->globals()->length
: 0,
script->nClosedArgs,
@ -416,19 +416,19 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
memcpy(wscript->notes(), snbase, nsrcnotes * sizeof(jssrcnote));
memcpy(wscript->atomMap.vector, script->atomMap.vector,
wscript->atomMap.length * sizeof(JSAtom *));
if (script->objectsOffset != 0) {
if (JSScript::isValidOffset(script->objectsOffset)) {
memcpy(wscript->objects()->vector, script->objects()->vector,
wscript->objects()->length * sizeof(JSObject *));
}
if (script->regexpsOffset != 0) {
if (JSScript::isValidOffset(script->regexpsOffset)) {
memcpy(wscript->regexps()->vector, script->regexps()->vector,
wscript->regexps()->length * sizeof(JSObject *));
}
if (script->trynotesOffset != 0) {
if (JSScript::isValidOffset(script->trynotesOffset)) {
memcpy(wscript->trynotes()->vector, script->trynotes()->vector,
wscript->trynotes()->length * sizeof(JSTryNote));
}
if (script->globalsOffset != 0) {
if (JSScript::isValidOffset(script->globalsOffset)) {
memcpy(wscript->globals()->vector, script->globals()->vector,
wscript->globals()->length * sizeof(GlobalSlotArray::Entry));
}
@ -2859,7 +2859,7 @@ JSObject * JS_FASTCALL
js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
{
JS_ASSERT(FUN_FLAT_CLOSURE(fun));
JS_ASSERT((fun->u.i.script->upvarsOffset
JS_ASSERT((JSScript::isValidOffset(fun->u.i.script->upvarsOffset)
? fun->u.i.script->upvars()->length
: 0) == fun->u.i.nupvars);

Просмотреть файл

@ -6829,7 +6829,7 @@ END_CASE(JSOP_ARRAYPUSH)
/*
* Look for a try block in script that can catch this exception.
*/
if (script->trynotesOffset == 0)
if (!JSScript::isValidOffset(script->trynotesOffset))
goto no_catch;
offset = (uint32)(regs.pc - script->main);

Просмотреть файл

@ -1055,7 +1055,7 @@ EvalCacheLookup(JSContext *cx, JSString *str, JSStackFrame *caller, uintN static
int i = 1;
if (objarray->length == 1) {
if (script->regexpsOffset != 0) {
if (JSScript::isValidOffset(script->regexpsOffset)) {
objarray = script->regexps();
i = 0;
} else {
@ -3538,9 +3538,9 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
if (xdr->mode == JSXDR_ENCODE) {
obj = *objp;
parent = obj->getParent();
parentId = (xdr->script->objectsOffset == 0)
? NO_PARENT_INDEX
: FindObjectIndex(xdr->script->objects(), parent);
parentId = JSScript::isValidOffset(xdr->script->objectsOffset)
? FindObjectIndex(xdr->script->objects(), parent)
: NO_PARENT_INDEX;
depth = (uint16)OBJ_BLOCK_DEPTH(cx, obj);
count = (uint16)OBJ_BLOCK_COUNT(cx, obj);
depthAndCount = (uint32)(depth << 16) | count;

Просмотреть файл

@ -1337,7 +1337,7 @@ GetLocal(SprintStack *ss, jsint i)
* not in a block. In either case, return GetStr(ss, i).
*/
JSScript *script = ss->printer->script;
if (script->objectsOffset == 0)
if (!JSScript::isValidOffset(script->objectsOffset))
return GetStr(ss, i);
for (jsatomid j = 0, n = script->objects()->length; j != n; j++) {
@ -2890,7 +2890,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
JS_ASSERT(fp->prev()->fun() == jp->fun);
JS_ASSERT(FUN_INTERPRETED(jp->fun));
JS_ASSERT(jp->script != jp->fun->u.i.script);
JS_ASSERT(jp->script->upvarsOffset != 0);
JS_ASSERT(JSScript::isValidOffset(jp->script->upvarsOffset));
}
#endif
uva = jp->script->upvars();

Просмотреть файл

@ -1070,7 +1070,7 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip
JSScript *inner = worklist.back();
worklist.popBack();
if (inner->objectsOffset != 0) {
if (JSScript::isValidOffset(inner->objectsOffset)) {
JSObjectArray *arr = inner->objects();
for (size_t i = 0; i < arr->length; i++) {
JSObject *obj = arr->vector[i];
@ -1079,14 +1079,16 @@ Compiler::defineGlobals(JSContext *cx, GlobalScope &globalScope, JSScript *scrip
JSFunction *fun = obj->getFunctionPrivate();
JS_ASSERT(fun->isInterpreted());
JSScript *inner = fun->u.i.script;
if (inner->globalsOffset == 0 && inner->objectsOffset == 0)
if (!JSScript::isValidOffset(inner->globalsOffset) &&
!JSScript::isValidOffset(inner->objectsOffset)) {
continue;
}
if (!worklist.append(inner))
return false;
}
}
if (inner->globalsOffset == 0)
if (!JSScript::isValidOffset(inner->globalsOffset))
continue;
GlobalSlotArray *globalUses = inner->globals();

Просмотреть файл

@ -110,7 +110,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
notes = NULL;
/* Should not XDR scripts optimized for a single global object. */
JS_ASSERT_IF(script, !script->globalsOffset);
JS_ASSERT_IF(script, !JSScript::isValidOffset(script->globalsOffset));
if (xdr->mode == JSXDR_ENCODE)
magic = JSXDR_MAGIC_SCRIPT_CURRENT;
@ -150,15 +150,15 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
nsrcnotes = sn - notes;
nsrcnotes++; /* room for the terminator */
if (script->objectsOffset != 0)
if (JSScript::isValidOffset(script->objectsOffset))
nobjects = script->objects()->length;
if (script->upvarsOffset != 0)
if (JSScript::isValidOffset(script->upvarsOffset))
nupvars = script->upvars()->length;
if (script->regexpsOffset != 0)
if (JSScript::isValidOffset(script->regexpsOffset))
nregexps = script->regexps()->length;
if (script->trynotesOffset != 0)
if (JSScript::isValidOffset(script->trynotesOffset))
ntrynotes = script->trynotes()->length;
if (script->constOffset != 0)
if (JSScript::isValidOffset(script->constOffset))
nconsts = script->consts()->length;
nClosedArgs = script->nClosedArgs;
@ -898,39 +898,52 @@ JSScript::NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natom
script->length = length;
script->setVersion(cx->findVersion());
uint8 *scriptEnd = reinterpret_cast<uint8 *>(script + 1);
cursor = (uint8 *)script + sizeof(JSScript);
if (nobjects != 0) {
script->objectsOffset = (uint8)(cursor - (uint8 *)script);
script->objectsOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(JSObjectArray);
} else {
script->objectsOffset = JSScript::INVALID_OFFSET;
}
if (nupvars != 0) {
script->upvarsOffset = (uint8)(cursor - (uint8 *)script);
script->upvarsOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(JSUpvarArray);
} else {
script->upvarsOffset = JSScript::INVALID_OFFSET;
}
if (nregexps != 0) {
script->regexpsOffset = (uint8)(cursor - (uint8 *)script);
script->regexpsOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(JSObjectArray);
} else {
script->regexpsOffset = JSScript::INVALID_OFFSET;
}
if (ntrynotes != 0) {
script->trynotesOffset = (uint8)(cursor - (uint8 *)script);
script->trynotesOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(JSTryNoteArray);
} else {
script->trynotesOffset = JSScript::INVALID_OFFSET;
}
if (nglobals != 0) {
script->globalsOffset = (uint8)(cursor - (uint8 *)script);
script->globalsOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(GlobalSlotArray);
} else {
script->globalsOffset = JSScript::INVALID_OFFSET;
}
JS_ASSERT((cursor - (uint8 *)script) <= 0xFF);
JS_ASSERT((cursor - (uint8 *)script) < 0xFF);
if (nconsts != 0) {
script->constOffset = (uint8)(cursor - (uint8 *)script);
script->constOffset = (uint8)(cursor - scriptEnd);
cursor += sizeof(JSConstArray);
} else {
script->constOffset = JSScript::INVALID_OFFSET;
}
JS_STATIC_ASSERT(sizeof(JSScript) +
sizeof(JSObjectArray) +
JS_STATIC_ASSERT(sizeof(JSObjectArray) +
sizeof(JSUpvarArray) +
sizeof(JSObjectArray) +
sizeof(JSTryNoteArray) +
sizeof(GlobalSlotArray) <= 0xFF);
sizeof(GlobalSlotArray) < 0xFF);
if (natoms != 0) {
script->atomMap.length = natoms;
@ -1132,7 +1145,7 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
if (cg->inFunction()) {
fun = cg->fun();
JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
if (script->upvarsOffset != 0)
if (JSScript::isValidOffset(script->upvarsOffset))
JS_ASSERT(script->upvars()->length == fun->u.i.nupvars);
else
fun->u.i.nupvars = 0;
@ -1157,10 +1170,10 @@ JSScript::NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
newTotal =
JS_RUNTIME_METER(cx->runtime, totalEmptyScripts) + cx->runtime->totalScripts;
} else {
newLive = JS_RUNTIME_METER(cx->runtime, liveScripts);
newEmptyLive = cx->runtime->liveEmptyScripts;
newLive = JS_RUNTIME_METER(cx->runtime, liveScripts);
newTotal =
JS_RUNTIME_METER(cx->runtime, totalScripts) + cx->runtime->totalEmptyScripts;
cx->runtime->totalEmptyScripts + JS_RUNTIME_METER(cx->runtime, totalScripts);
}
jsrefcount oldHigh = cx->runtime->highWaterLiveScripts;
@ -1304,7 +1317,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
JSAtomMap *map = &script->atomMap;
MarkAtomRange(trc, map->length, map->vector, "atomMap");
if (script->objectsOffset != 0) {
if (JSScript::isValidOffset(script->objectsOffset)) {
JSObjectArray *objarray = script->objects();
uintN i = objarray->length;
do {
@ -1316,7 +1329,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
} while (i != 0);
}
if (script->regexpsOffset != 0) {
if (JSScript::isValidOffset(script->regexpsOffset)) {
JSObjectArray *objarray = script->regexps();
uintN i = objarray->length;
do {
@ -1328,7 +1341,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
} while (i != 0);
}
if (script->constOffset != 0) {
if (JSScript::isValidOffset(script->constOffset)) {
JSConstArray *constarray = script->consts();
MarkValueRange(trc, constarray->length, constarray->vector, "consts");
}

Просмотреть файл

@ -213,19 +213,22 @@ struct JSScript {
uint16 version; /* JS version under which script was compiled */
uint16 nfixed; /* number of slots besides stack operands in
slot array */
/*
* Offsets to various array structures from the end of this script, or
* JSScript::INVALID_OFFSET if the array has length 0.
*/
uint8 objectsOffset; /* offset to the array of nested function,
block, scope, xml and one-time regexps
objects or 0 if none */
objects */
uint8 upvarsOffset; /* offset of the array of display ("up")
closure vars or 0 if none */
closure vars */
uint8 regexpsOffset; /* offset to the array of to-be-cloned
regexps or 0 if none. */
uint8 trynotesOffset; /* offset to the array of try notes or
0 if none */
uint8 globalsOffset; /* offset to the array of global slots or
0 if none */
uint8 constOffset; /* offset to the array of constants or
0 if none */
regexps */
uint8 trynotesOffset; /* offset to the array of try notes */
uint8 globalsOffset; /* offset to the array of global slots */
uint8 constOffset; /* offset to the array of constants */
bool noScriptRval:1; /* no need for result value of last
expression statement */
bool savedCallerFun:1; /* object 0 is caller function */
@ -316,34 +319,37 @@ struct JSScript {
/* Script notes are allocated right after the code. */
jssrcnote *notes() { return (jssrcnote *)(code + length); }
static const uint8 INVALID_OFFSET = 0xFF;
static bool isValidOffset(uint8 offset) { return offset != INVALID_OFFSET; }
JSObjectArray *objects() {
JS_ASSERT(objectsOffset != 0);
return (JSObjectArray *)((uint8 *) this + objectsOffset);
JS_ASSERT(isValidOffset(objectsOffset));
return (JSObjectArray *)((uint8 *) (this + 1) + objectsOffset);
}
JSUpvarArray *upvars() {
JS_ASSERT(upvarsOffset != 0);
return (JSUpvarArray *) ((uint8 *) this + upvarsOffset);
JS_ASSERT(isValidOffset(upvarsOffset));
return (JSUpvarArray *) ((uint8 *) (this + 1) + upvarsOffset);
}
JSObjectArray *regexps() {
JS_ASSERT(regexpsOffset != 0);
return (JSObjectArray *) ((uint8 *) this + regexpsOffset);
JS_ASSERT(isValidOffset(regexpsOffset));
return (JSObjectArray *) ((uint8 *) (this + 1) + regexpsOffset);
}
JSTryNoteArray *trynotes() {
JS_ASSERT(trynotesOffset != 0);
return (JSTryNoteArray *) ((uint8 *) this + trynotesOffset);
JS_ASSERT(isValidOffset(trynotesOffset));
return (JSTryNoteArray *) ((uint8 *) (this + 1) + trynotesOffset);
}
js::GlobalSlotArray *globals() {
JS_ASSERT(globalsOffset != 0);
return (js::GlobalSlotArray *) ((uint8 *)this + globalsOffset);
JS_ASSERT(isValidOffset(globalsOffset));
return (js::GlobalSlotArray *) ((uint8 *) (this + 1) + globalsOffset);
}
JSConstArray *consts() {
JS_ASSERT(constOffset != 0);
return (JSConstArray *) ((uint8 *) this + constOffset);
JS_ASSERT(isValidOffset(constOffset));
return (JSConstArray *) ((uint8 *) (this + 1) + constOffset);
}
JSAtom *getAtom(size_t index) {

Просмотреть файл

@ -2221,7 +2221,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
global_slots(NULL),
callDepth(anchor ? anchor->calldepth : 0),
atoms(FrameAtomBase(cx, cx->fp())),
consts(cx->fp()->script()->constOffset
consts(JSScript::isValidOffset(cx->fp()->script()->constOffset)
? cx->fp()->script()->consts()->vector
: NULL),
strictModeCode_ins(NULL),
@ -7884,9 +7884,9 @@ TraceRecorder::updateAtoms()
{
JSScript *script = cx->fp()->script();
atoms = FrameAtomBase(cx, cx->fp());
consts = cx->fp()->hasImacropc() || script->constOffset == 0
? 0
: script->consts()->vector;
consts = (cx->fp()->hasImacropc() || !JSScript::isValidOffset(script->constOffset))
? 0
: script->consts()->vector;
strictModeCode_ins = w.name(w.immi(script->strictModeCode), "strict");
}
@ -7894,7 +7894,7 @@ JS_REQUIRES_STACK void
TraceRecorder::updateAtoms(JSScript *script)
{
atoms = script->atomMap.vector;
consts = script->constOffset == 0 ? 0 : script->consts()->vector;
consts = JSScript::isValidOffset(script->constOffset) ? script->consts()->vector : 0;
strictModeCode_ins = w.name(w.immi(script->strictModeCode), "strict");
}

Просмотреть файл

@ -81,7 +81,7 @@ FindExceptionHandler(JSContext *cx)
JSScript *script = fp->script();
top:
if (cx->throwing && script->trynotesOffset) {
if (cx->throwing && JSScript::isValidOffset(script->trynotesOffset)) {
// The PC is updated before every stub call, so we can use it here.
unsigned offset = cx->regs->pc - script->main;

Просмотреть файл

@ -1975,7 +1975,7 @@ TryNotes(JSContext *cx, JSScript *script)
{
JSTryNote *tn, *tnlimit;
if (script->trynotesOffset == 0)
if (!JSScript::isValidOffset(script->trynotesOffset))
return JS_TRUE;
tn = script->trynotes()->vector;
@ -2053,7 +2053,7 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive)
SrcNotes(cx, script);
TryNotes(cx, script);
if (recursive && script->objectsOffset != 0) {
if (recursive && JSScript::isValidOffset(script->objectsOffset)) {
JSObjectArray *objects = script->objects();
for (uintN i = 0; i != objects->length; ++i) {
JSObject *obj = objects->vector[i];