mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 659577 - Embed blockChain information in ALIASEDVAR ops (r=waldo)
--HG-- extra : rebase_source : ea0deae107902520b392ed1eeddcd8c6420945ee
This commit is contained in:
parent
da494c3aae
commit
304ebf5156
@ -806,7 +806,7 @@ static bool
|
|||||||
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
|
EmitObjectOp(JSContext *cx, ObjectBox *objbox, JSOp op, BytecodeEmitter *bce)
|
||||||
{
|
{
|
||||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
|
JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
|
||||||
return EmitIndex32(cx, op, bce->objectList.index(objbox), bce);
|
return EmitIndex32(cx, op, bce->objectList.add(objbox), bce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -834,13 +834,13 @@ EmitUnaliasedVarOp(JSContext *cx, JSOp op, uint16_t slot, BytecodeEmitter *bce)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitAliasedVarOp(JSContext *cx, JSOp op, ScopeCoordinate sc, JSAtom *atom, BytecodeEmitter *bce)
|
EmitAliasedVarOp(JSContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmitter *bce)
|
||||||
{
|
{
|
||||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
|
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
|
||||||
|
|
||||||
jsatomid atomIndex;
|
uint32_t maybeBlockIndex = UINT32_MAX;
|
||||||
if (!bce->makeAtomIndex(atom, &atomIndex))
|
if (bce->sc->blockChain)
|
||||||
return false;
|
maybeBlockIndex = bce->objectList.indexOf(bce->sc->blockChain);
|
||||||
|
|
||||||
bool decomposed = js_CodeSpec[op].format & JOF_DECOMPOSE;
|
bool decomposed = js_CodeSpec[op].format & JOF_DECOMPOSE;
|
||||||
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (decomposed ? 1 : 0);
|
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (decomposed ? 1 : 0);
|
||||||
@ -855,7 +855,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ScopeCoordinate sc, JSAtom *atom, Bytec
|
|||||||
pc += sizeof(uint16_t);
|
pc += sizeof(uint16_t);
|
||||||
SET_UINT16(pc, sc.binding);
|
SET_UINT16(pc, sc.binding);
|
||||||
pc += sizeof(uint16_t);
|
pc += sizeof(uint16_t);
|
||||||
SET_UINT32_INDEX(pc, atomIndex);
|
SET_UINT32_INDEX(pc, maybeBlockIndex);
|
||||||
pc += sizeof(uint32_t);
|
pc += sizeof(uint32_t);
|
||||||
SET_UINT16(pc, sc.frameBinding);
|
SET_UINT16(pc, sc.frameBinding);
|
||||||
return true;
|
return true;
|
||||||
@ -911,7 +911,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EmitAliasedVarOp(cx, op, sc, pn->atom(), bce);
|
return EmitAliasedVarOp(cx, op, sc, bce);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -2639,8 +2639,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
|
|||||||
sc.hops = 0;
|
sc.hops = 0;
|
||||||
sc.binding = bce->sc->bindings.localToBinding(bce->sc->argumentsLocalSlot());
|
sc.binding = bce->sc->bindings.localToBinding(bce->sc->argumentsLocalSlot());
|
||||||
sc.frameBinding = sc.binding;
|
sc.frameBinding = sc.binding;
|
||||||
JSAtom *atom = cx->runtime->atomState.argumentsAtom;
|
if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, bce))
|
||||||
if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, atom, bce))
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, bce->sc->argumentsLocalSlot(), bce))
|
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, bce->sc->argumentsLocalSlot(), bce))
|
||||||
@ -4877,7 +4876,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make the function object a literal in the outer script's pool. */
|
/* Make the function object a literal in the outer script's pool. */
|
||||||
unsigned index = bce->objectList.index(pn->pn_funbox);
|
unsigned index = bce->objectList.add(pn->pn_funbox);
|
||||||
|
|
||||||
/* Emit a bytecode pointing to the closure object in its immediate. */
|
/* Emit a bytecode pointing to the closure object in its immediate. */
|
||||||
if (pn->getOp() != JSOP_NOP) {
|
if (pn->getOp() != JSOP_NOP) {
|
||||||
@ -5766,7 +5765,7 @@ EmitObject(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||||||
ObjectBox *objbox = bce->parser->newObjectBox(obj);
|
ObjectBox *objbox = bce->parser->newObjectBox(obj);
|
||||||
if (!objbox)
|
if (!objbox)
|
||||||
return false;
|
return false;
|
||||||
unsigned index = bce->objectList.index(objbox);
|
unsigned index = bce->objectList.add(objbox);
|
||||||
MOZ_STATIC_ASSERT(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
MOZ_STATIC_ASSERT(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
|
||||||
"newinit and newobject must have equal length to edit in-place");
|
"newinit and newobject must have equal length to edit in-place");
|
||||||
EMIT_UINT32_IN_PLACE(offset, JSOP_NEWOBJECT, uint32_t(index));
|
EMIT_UINT32_IN_PLACE(offset, JSOP_NEWOBJECT, uint32_t(index));
|
||||||
@ -6454,7 +6453,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||||||
|
|
||||||
case PNK_REGEXP:
|
case PNK_REGEXP:
|
||||||
JS_ASSERT(pn->isOp(JSOP_REGEXP));
|
JS_ASSERT(pn->isOp(JSOP_REGEXP));
|
||||||
ok = EmitRegExp(cx, bce->regexpList.index(pn->pn_objbox), bce);
|
ok = EmitRegExp(cx, bce->regexpList.add(pn->pn_objbox), bce);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
@ -6954,7 +6953,7 @@ frontend::FinishTakingTryNotes(BytecodeEmitter *bce, TryNoteArray *array)
|
|||||||
* the pre-compilation prototype, a pigeon-hole problem for instanceof tests.
|
* the pre-compilation prototype, a pigeon-hole problem for instanceof tests.
|
||||||
*/
|
*/
|
||||||
unsigned
|
unsigned
|
||||||
CGObjectList::index(ObjectBox *objbox)
|
CGObjectList::add(ObjectBox *objbox)
|
||||||
{
|
{
|
||||||
JS_ASSERT(!objbox->emitLink);
|
JS_ASSERT(!objbox->emitLink);
|
||||||
objbox->emitLink = lastbox;
|
objbox->emitLink = lastbox;
|
||||||
@ -6962,6 +6961,16 @@ CGObjectList::index(ObjectBox *objbox)
|
|||||||
return length++;
|
return length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
CGObjectList::indexOf(JSObject *obj)
|
||||||
|
{
|
||||||
|
JS_ASSERT(length > 0);
|
||||||
|
unsigned index = length - 1;
|
||||||
|
for (ObjectBox *box = lastbox; box->object != obj; box = box->emitLink)
|
||||||
|
index--;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CGObjectList::finish(ObjectArray *array)
|
CGObjectList::finish(ObjectArray *array)
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,8 @@ struct CGObjectList {
|
|||||||
|
|
||||||
CGObjectList() : length(0), lastbox(NULL) {}
|
CGObjectList() : length(0), lastbox(NULL) {}
|
||||||
|
|
||||||
unsigned index(ObjectBox *objbox);
|
unsigned add(ObjectBox *objbox);
|
||||||
|
unsigned indexOf(JSObject *obj);
|
||||||
void finish(ObjectArray *array);
|
void finish(ObjectArray *array);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,9 +136,7 @@ struct SharedContext {
|
|||||||
StmtInfo *topStmt; /* top of statement info stack */
|
StmtInfo *topStmt; /* top of statement info stack */
|
||||||
StmtInfo *topScopeStmt; /* top lexical scope statement */
|
StmtInfo *topScopeStmt; /* top lexical scope statement */
|
||||||
Rooted<StaticBlockObject *> blockChain;
|
Rooted<StaticBlockObject *> blockChain;
|
||||||
/* compile time block scope chain (NB: one
|
/* compile time block scope chain */
|
||||||
deeper than the topScopeStmt/downScope
|
|
||||||
chain when in head of let block/expr) */
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const RootedFunction fun_; /* function to store argument and variable
|
const RootedFunction fun_; /* function to store argument and variable
|
||||||
|
@ -514,14 +514,15 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case JOF_SCOPECOORD: {
|
case JOF_SCOPECOORD: {
|
||||||
unsigned i = GET_UINT16(pc);
|
Value v = StringValue(ScopeCoordinateName(script, pc));
|
||||||
Sprint(sp, " %u", i);
|
JSAutoByteString bytes;
|
||||||
pc += sizeof(uint16_t);
|
if (!ToDisassemblySource(cx, v, &bytes))
|
||||||
i = GET_UINT16(pc);
|
return 0;
|
||||||
Sprint(sp, " %u", i);
|
ScopeCoordinate sc(pc);
|
||||||
pc += sizeof(uint16_t);
|
Sprint(sp, " %s (hops = %u, slot = %u)", bytes.ptr(), sc.hops, sc.binding);
|
||||||
/* FALL THROUGH */
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case JOF_ATOM: {
|
case JOF_ATOM: {
|
||||||
Value v = StringValue(script->getAtom(GET_UINT32_INDEX(pc)));
|
Value v = StringValue(script->getAtom(GET_UINT32_INDEX(pc)));
|
||||||
JSAutoByteString bytes;
|
JSAutoByteString bytes;
|
||||||
@ -1843,7 +1844,7 @@ static bool
|
|||||||
IsVarSlot(JSPrinter *jp, jsbytecode *pc, JSAtom **varAtom, int *localSlot)
|
IsVarSlot(JSPrinter *jp, jsbytecode *pc, JSAtom **varAtom, int *localSlot)
|
||||||
{
|
{
|
||||||
if (JOF_OPTYPE(*pc) == JOF_SCOPECOORD) {
|
if (JOF_OPTYPE(*pc) == JOF_SCOPECOORD) {
|
||||||
*varAtom = ScopeCoordinateAtom(jp->script, pc);
|
*varAtom = ScopeCoordinateName(jp->script, pc);
|
||||||
LOCAL_ASSERT_RV(*varAtom, NULL);
|
LOCAL_ASSERT_RV(*varAtom, NULL);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ typedef enum JSOp {
|
|||||||
#define JOF_INT8 18 /* int8_t immediate operand */
|
#define JOF_INT8 18 /* int8_t immediate operand */
|
||||||
#define JOF_ATOMOBJECT 19 /* uint16_t constant index + object index */
|
#define JOF_ATOMOBJECT 19 /* uint16_t constant index + object index */
|
||||||
#define JOF_UINT16PAIR 20 /* pair of uint16_t immediates */
|
#define JOF_UINT16PAIR 20 /* pair of uint16_t immediates */
|
||||||
#define JOF_SCOPECOORD 21 /* pair of uint16_t immediates followed by atom index */
|
#define JOF_SCOPECOORD 21 /* pair of uint16_t immediates followed by block index */
|
||||||
#define JOF_TYPEMASK 0x001f /* mask for above immediate types */
|
#define JOF_TYPEMASK 0x001f /* mask for above immediate types */
|
||||||
|
|
||||||
#define JOF_NAME (1U<<5) /* name operation */
|
#define JOF_NAME (1U<<5) /* name operation */
|
||||||
|
@ -334,6 +334,14 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
|
|||||||
* 'with', 'arguments' and E4X filters. All of these cases require creating a
|
* 'with', 'arguments' and E4X filters. All of these cases require creating a
|
||||||
* CallObject to own the aliased variable.
|
* CallObject to own the aliased variable.
|
||||||
*
|
*
|
||||||
|
* An ALIASEDVAR opcode contains the following immediates:
|
||||||
|
* uint16 hops: the number of scope objects to skip to find the ScopeObject
|
||||||
|
* containing the variable being accessed
|
||||||
|
* uint16 slot: the slot containing the variable in the ScopeObject (this
|
||||||
|
* 'slot' does not include RESERVED_SLOTS).
|
||||||
|
* uint32 block: the index (into the script object table) of the block chain
|
||||||
|
* at the point of the variable access.
|
||||||
|
*
|
||||||
* XXX: there is also a temporary 2-byte index (indicating the frame slot
|
* XXX: there is also a temporary 2-byte index (indicating the frame slot
|
||||||
* aliased by the scope chain) which will be removed with the last patch of bug
|
* aliased by the scope chain) which will be removed with the last patch of bug
|
||||||
* 659577.
|
* 659577.
|
||||||
|
@ -20,13 +20,6 @@ ScopeCoordinate::ScopeCoordinate(jsbytecode *pc)
|
|||||||
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSAtom *
|
|
||||||
ScopeCoordinateAtom(JSScript *script, jsbytecode *pc)
|
|
||||||
{
|
|
||||||
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
|
||||||
return script->getAtom(GET_UINT32_INDEX(pc + 2 * sizeof(uint16_t)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline JSObject &
|
inline JSObject &
|
||||||
ScopeObject::enclosingScope() const
|
ScopeObject::enclosingScope() const
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,51 @@ using namespace js::types;
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
StaticBlockObject *
|
||||||
|
js::ScopeCoordinateBlockChain(JSScript *script, jsbytecode *pc)
|
||||||
|
{
|
||||||
|
ScopeCoordinate sc(pc);
|
||||||
|
|
||||||
|
uint32_t blockIndex = GET_UINT32_INDEX(pc + 2 * sizeof(uint16_t));
|
||||||
|
if (blockIndex == UINT32_MAX)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
StaticBlockObject *block = &script->getObject(blockIndex)->asStaticBlock();
|
||||||
|
unsigned i = 0;
|
||||||
|
while (true) {
|
||||||
|
while (block && !block->needsClone())
|
||||||
|
block = block->enclosingBlock();
|
||||||
|
if (i++ == sc.hops)
|
||||||
|
break;
|
||||||
|
block = block->enclosingBlock();
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyName *
|
||||||
|
js::ScopeCoordinateName(JSScript *script, jsbytecode *pc)
|
||||||
|
{
|
||||||
|
StaticBlockObject *maybeBlock = ScopeCoordinateBlockChain(script, pc);
|
||||||
|
ScopeCoordinate sc(pc);
|
||||||
|
|
||||||
|
uint32_t targetSlot;
|
||||||
|
Shape *shape;
|
||||||
|
if (maybeBlock) {
|
||||||
|
targetSlot = BlockObject::RESERVED_SLOTS + sc.binding;
|
||||||
|
shape = maybeBlock->lastProperty();
|
||||||
|
} else {
|
||||||
|
targetSlot = CallObject::RESERVED_SLOTS + sc.binding;
|
||||||
|
shape = script->bindings.lastShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape::Range r = shape->all();
|
||||||
|
while (r.front().slot() != targetSlot)
|
||||||
|
r.popFront();
|
||||||
|
return JSID_TO_ATOM(r.front().propid())->asPropertyName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
js_PutCallObject(StackFrame *fp, CallObject &callobj)
|
js_PutCallObject(StackFrame *fp, CallObject &callobj)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,9 @@ namespace js {
|
|||||||
* given lexically-enclosing variable. A scope coordinate has two dimensions:
|
* given lexically-enclosing variable. A scope coordinate has two dimensions:
|
||||||
* - hops: the number of scope objects on the scope chain to skip
|
* - hops: the number of scope objects on the scope chain to skip
|
||||||
* - binding: which binding on the scope object
|
* - binding: which binding on the scope object
|
||||||
|
* Additionally (as described in jsopcode.tbl) there is a 'block' index, but
|
||||||
|
* this is only needed for decompilation/inference so it is not included in the
|
||||||
|
* main ScopeCoordinate struct: use ScopeCoordinate{BlockChain,Atom} instead.
|
||||||
*/
|
*/
|
||||||
struct ScopeCoordinate
|
struct ScopeCoordinate
|
||||||
{
|
{
|
||||||
@ -35,8 +38,13 @@ struct ScopeCoordinate
|
|||||||
inline ScopeCoordinate() {}
|
inline ScopeCoordinate() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline JSAtom *
|
/* Return the static block chain (or null) accessed by *pc. */
|
||||||
ScopeCoordinateAtom(JSScript *script, jsbytecode *pc);
|
extern StaticBlockObject *
|
||||||
|
ScopeCoordinateBlockChain(JSScript *script, jsbytecode *pc);
|
||||||
|
|
||||||
|
/* Return the name being accessed by the given ALIASEDVAR op. */
|
||||||
|
extern PropertyName *
|
||||||
|
ScopeCoordinateName(JSScript *script, jsbytecode *pc);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user