diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 504fc6a14868..ceb86e3b9af1 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1429,57 +1429,6 @@ js_QuoteString(ExclusiveContext *cx, JSString *str, jschar quote) /************************************************************************/ -StaticBlockObject * -js::GetBlockChainAtPC(JSScript *script, jsbytecode *pc) -{ - JS_ASSERT(script->containsPC(pc)); - - if (!script->hasBlockScopes()) - return nullptr; - - if (pc < script->main()) - return nullptr; - ptrdiff_t offset = pc - script->main(); - - BlockScopeArray *blockScopes = script->blockScopes(); - 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(); - break; - } - if (checkNote->parent == UINT32_MAX) - break; - check = checkNote->parent; - } - bottom = mid + 1; - } else { - top = mid; - } - } - - return blockChain; -} - namespace { /* * The expression decompiler is invoked by error handling code to produce a @@ -1740,7 +1689,7 @@ JSAtom * ExpressionDecompiler::findLetVar(jsbytecode *pc, unsigned depth) { if (script->hasObjects()) { - JSObject *chain = GetBlockChainAtPC(script, pc); + JSObject *chain = script->getBlockScope(pc); if (!chain) return nullptr; JS_ASSERT(chain->is()); diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 3f019c99aeb0..ed75130495f7 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -777,11 +777,6 @@ GetNextPc(jsbytecode *pc) return pc + GetBytecodeLength(pc); } -class StaticBlockObject; - -StaticBlockObject * -GetBlockChainAtPC(JSScript *script, jsbytecode *pc); - } /* namespace js */ #if defined(DEBUG) diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index e1004f988947..b94db57d618e 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -2894,6 +2894,58 @@ LazyScript::finalize(FreeOp *fop) fop->free_(table_); } +StaticBlockObject * +JSScript::getBlockScope(jsbytecode *pc) +{ + JS_ASSERT(containsPC(pc)); + + if (!hasBlockScopes()) + return nullptr; + + ptrdiff_t offset = pc - main(); + + if (offset < 0) + return nullptr; + + BlockScopeArray *scopes = blockScopes(); + StaticBlockObject *blockChain = nullptr; + + // Find the innermost block chain using a binary search. + size_t bottom = 0; + size_t top = scopes->length; + + while (bottom < top) { + size_t mid = bottom + (top - bottom) / 2; + const BlockScopeNote *note = &scopes->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 = &scopes->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 = &getObject(checkNote->index)->as(); + break; + } + if (checkNote->parent == UINT32_MAX) + break; + check = checkNote->parent; + } + bottom = mid + 1; + } else { + top = mid; + } + } + + return blockChain; +} + void JSScript::setArgumentsHasVarBinding() { diff --git a/js/src/jsscript.h b/js/src/jsscript.h index 544f3798767f..09d88c489bdc 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -43,6 +43,7 @@ class RegExpObject; struct SourceCompressionTask; class Shape; class WatchpointMap; +class StaticBlockObject; namespace analyze { class ScriptAnalysis; @@ -1268,6 +1269,8 @@ class JSScript : public js::gc::BarrieredCell return arr->vector[index]; } + js::StaticBlockObject *getBlockScope(jsbytecode *pc); + /* * The isEmpty method tells whether this script has code that computes any * result (not return value, result AKA normal completion value) other than diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 4997f4022e25..8114c0b89a65 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -38,7 +38,7 @@ InnermostStaticScope(JSScript *script, jsbytecode *pc) JS_ASSERT(script->containsPC(pc)); JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD); - StaticBlockObject *block = GetBlockChainAtPC(script, pc); + StaticBlockObject *block = script->getBlockScope(pc); if (block) return block; return script->function();