mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bug 944930 - Remove block index from aliasedvar ops, use a binary search to find the block chain for a given pc, r=luke.
This commit is contained in:
parent
688dd8051e
commit
6ebb9c6ffe
@ -1135,7 +1135,6 @@ if test "$GNU_CC"; then
|
||||
#
|
||||
_WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
|
||||
MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
|
||||
MOZ_C_SUPPORTS_WARNING(-W, sign-compare, ac_c_has_sign_compare)
|
||||
|
||||
|
@ -678,13 +678,20 @@ static bool
|
||||
PushBlockScopeBCE(BytecodeEmitter *bce, StmtInfoBCE *stmt, ObjectBox *objbox,
|
||||
ptrdiff_t top)
|
||||
{
|
||||
uint32_t parent = UINT32_MAX;
|
||||
if (bce->blockChain) {
|
||||
StmtInfoBCE *stmt = bce->topScopeStmt;
|
||||
for (; stmt->blockObj != bce->blockChain; stmt = stmt->down) {}
|
||||
parent = stmt->blockScopeIndex;
|
||||
}
|
||||
|
||||
StaticBlockObject &blockObj = objbox->object->as<StaticBlockObject>();
|
||||
|
||||
PushStatementBCE(bce, stmt, STMT_BLOCK, top);
|
||||
|
||||
unsigned scopeObjectIndex = bce->objectList.add(objbox);
|
||||
stmt->blockScopeIndex = bce->blockScopeList.length();
|
||||
if (!bce->blockScopeList.append(scopeObjectIndex, bce->offset()))
|
||||
if (!bce->blockScopeList.append(scopeObjectIndex, bce->offset(), parent))
|
||||
return false;
|
||||
|
||||
blockObj.initEnclosingStaticScope(EnclosingStaticScope(bce));
|
||||
@ -814,11 +821,7 @@ EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmit
|
||||
{
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
|
||||
|
||||
uint32_t maybeBlockIndex = UINT32_MAX;
|
||||
if (bce->blockChain)
|
||||
maybeBlockIndex = bce->objectList.indexOf(bce->blockChain);
|
||||
|
||||
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t);
|
||||
unsigned n = 2 * sizeof(uint16_t);
|
||||
JS_ASSERT(int(n) + 1 /* op */ == js_CodeSpec[op].length);
|
||||
|
||||
ptrdiff_t off = EmitN(cx, bce, op, n);
|
||||
@ -830,7 +833,6 @@ EmitAliasedVarOp(ExclusiveContext *cx, JSOp op, ScopeCoordinate sc, BytecodeEmit
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT16(pc, sc.slot);
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT32_INDEX(pc, maybeBlockIndex);
|
||||
CheckTypeSet(cx, bce, op);
|
||||
return true;
|
||||
}
|
||||
@ -6879,13 +6881,14 @@ CGTryNoteList::finish(TryNoteArray *array)
|
||||
}
|
||||
|
||||
bool
|
||||
CGBlockScopeList::append(uint32_t scopeObject, uint32_t offset)
|
||||
CGBlockScopeList::append(uint32_t scopeObject, uint32_t offset, uint32_t parent)
|
||||
{
|
||||
BlockScopeNote note;
|
||||
mozilla::PodZero(¬e);
|
||||
|
||||
note.index = scopeObject;
|
||||
note.start = offset;
|
||||
note.parent = parent;
|
||||
|
||||
return list.append(note);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ struct CGBlockScopeList {
|
||||
Vector<BlockScopeNote> list;
|
||||
CGBlockScopeList(ExclusiveContext *cx) : list(cx) {}
|
||||
|
||||
bool append(uint32_t scopeObject, uint32_t offset);
|
||||
bool append(uint32_t scopeObject, uint32_t offset, uint32_t parent);
|
||||
void recordEnd(uint32_t index, uint32_t offset);
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(BlockScopeArray *array);
|
||||
|
@ -3,7 +3,7 @@ setDebug(true);
|
||||
x = "notset";
|
||||
function main() {
|
||||
/* The JSOP_STOP in main. */
|
||||
a = { valueOf: function () { trap(main, 95, "success()"); } };
|
||||
a = { valueOf: function () { trap(main, 91, "success()"); } };
|
||||
b = "";
|
||||
eval();
|
||||
a + b;
|
||||
|
@ -1432,25 +1432,52 @@ js_QuoteString(ExclusiveContext *cx, JSString *str, jschar quote)
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
static JSObject *
|
||||
GetBlockChainAtPC(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
StaticBlockObject *
|
||||
js::GetBlockChainAtPC(JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(script->containsPC(pc));
|
||||
JS_ASSERT(pc >= script->main());
|
||||
|
||||
ptrdiff_t offset = pc - script->main();
|
||||
|
||||
if (!script->hasBlockScopes())
|
||||
return nullptr;
|
||||
|
||||
if (pc < script->main())
|
||||
return nullptr;
|
||||
ptrdiff_t offset = pc - script->main();
|
||||
|
||||
BlockScopeArray *blockScopes = script->blockScopes();
|
||||
JSObject *blockChain = nullptr;
|
||||
for (uint32_t n = 0; n < blockScopes->length; n++) {
|
||||
const BlockScopeNote *note = &blockScopes->vector[n];
|
||||
if (note->start > offset)
|
||||
break;
|
||||
if (offset <= note->start + note->length)
|
||||
blockChain = script->getObject(note->index);
|
||||
StaticBlockObject *blockChain = nullptr;
|
||||
|
||||
// Find the innermost block chain using a binary search.
|
||||
size_t bottom = 0;
|
||||
size_t top = blockScopes->length;
|
||||
|
||||
while (bottom < top) {
|
||||
size_t mid = bottom + (top - bottom) / 2;
|
||||
const BlockScopeNote *note = &blockScopes->vector[mid];
|
||||
if (note->start <= offset) {
|
||||
// Block scopes are ordered in the list by their starting offset, and since
|
||||
// blocks form a tree ones earlier in the list may cover the pc even if
|
||||
// later blocks end before the pc. This only happens when the earlier block
|
||||
// is a parent of the later block, so we need to check parents of |mid| in
|
||||
// the searched range for coverage.
|
||||
size_t check = mid;
|
||||
while (check >= bottom) {
|
||||
const BlockScopeNote *checkNote = &blockScopes->vector[check];
|
||||
JS_ASSERT(checkNote->start <= offset);
|
||||
if (offset <= checkNote->start + checkNote->length) {
|
||||
// We found a matching block chain but there may be inner ones
|
||||
// at a higher block chain index than mid. Continue the binary search.
|
||||
blockChain = &script->getObject(checkNote->index)->as<StaticBlockObject>();
|
||||
break;
|
||||
}
|
||||
if (checkNote->parent == UINT32_MAX)
|
||||
break;
|
||||
check = checkNote->parent;
|
||||
}
|
||||
bottom = mid + 1;
|
||||
} else {
|
||||
top = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return blockChain;
|
||||
@ -1716,7 +1743,7 @@ JSAtom *
|
||||
ExpressionDecompiler::findLetVar(jsbytecode *pc, unsigned depth)
|
||||
{
|
||||
if (script->hasObjects()) {
|
||||
JSObject *chain = GetBlockChainAtPC(cx, script, pc);
|
||||
JSObject *chain = GetBlockChainAtPC(script, pc);
|
||||
if (!chain)
|
||||
return nullptr;
|
||||
JS_ASSERT(chain->is<BlockObject>());
|
||||
|
@ -777,6 +777,11 @@ GetNextPc(jsbytecode *pc)
|
||||
return pc + GetBytecodeLength(pc);
|
||||
}
|
||||
|
||||
class StaticBlockObject;
|
||||
|
||||
StaticBlockObject *
|
||||
GetBlockChainAtPC(JSScript *script, jsbytecode *pc);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
@ -318,12 +318,10 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, JOF_BYTE)
|
||||
* 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.
|
||||
*/
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 9, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 9, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 9, 1, 1, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 5, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 5, 0, 1, JOF_SCOPECOORD|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 5, 1, 1, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
|
||||
OPDEF(JSOP_UNUSED139, 139, "unused139", NULL, 1, 0, 0, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED140, 140, "unused140", NULL, 1, 0, 0, JOF_BYTE)
|
||||
|
@ -807,7 +807,8 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
||||
BlockScopeNote *note = &script->blockScopes()->vector[i];
|
||||
if (!xdr->codeUint32(¬e->index) ||
|
||||
!xdr->codeUint32(¬e->start) ||
|
||||
!xdr->codeUint32(¬e->length))
|
||||
!xdr->codeUint32(¬e->length) ||
|
||||
!xdr->codeUint32(¬e->parent))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ 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.
|
||||
uint32_t parent; // Index of parent block scope in notes, or UINT32_MAX.
|
||||
};
|
||||
|
||||
struct ConstArray {
|
||||
|
@ -38,11 +38,10 @@ InnermostStaticScope(JSScript *script, jsbytecode *pc)
|
||||
JS_ASSERT(script->containsPC(pc));
|
||||
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
||||
|
||||
uint32_t blockIndex = GET_UINT32_INDEX(pc + 2 * sizeof(uint16_t));
|
||||
|
||||
if (blockIndex == UINT32_MAX)
|
||||
return script->function();
|
||||
return &script->getObject(blockIndex)->as<StaticBlockObject>();
|
||||
StaticBlockObject *block = GetBlockChainAtPC(script, pc);
|
||||
if (block)
|
||||
return block;
|
||||
return script->function();
|
||||
}
|
||||
|
||||
Shape *
|
||||
|
@ -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 - 155);
|
||||
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 156);
|
||||
|
||||
class XDRBuffer {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user