зеркало из https://github.com/mozilla/gecko-dev.git
Bug 607724: Minor scope chain function cleanup. (r=mrbkap)
This commit is contained in:
Родитель
1ec7c780d5
Коммит
0083db09f1
|
@ -1881,31 +1881,8 @@ JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp)
|
|||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetScopeChain(JSContext *cx)
|
||||
{
|
||||
JSStackFrame *fp;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
fp = js_GetTopStackFrame(cx);
|
||||
if (!fp) {
|
||||
/*
|
||||
* There is no code active on this context. In place of an actual
|
||||
* scope chain, use the context's global object, which is set in
|
||||
* js_InitFunctionAndObjectClasses, and which represents the default
|
||||
* scope chain for the embedding. See also js_FindClassObject.
|
||||
*
|
||||
* For embeddings that use the inner and outer object hooks, the inner
|
||||
* object represents the ultimate global object, with the outer object
|
||||
* acting as a stand-in.
|
||||
*/
|
||||
JSObject *obj = cx->globalObject;
|
||||
if (!obj) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||
return obj;
|
||||
}
|
||||
return js_GetScopeChain(cx, fp);
|
||||
return GetScopeChain(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
@ -1918,26 +1895,8 @@ JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
|
|||
JS_PUBLIC_API(JSObject *)
|
||||
JS_GetGlobalForScopeChain(JSContext *cx)
|
||||
{
|
||||
/*
|
||||
* This is essentially JS_GetScopeChain(cx)->getGlobal(), but without
|
||||
* falling off trace.
|
||||
*
|
||||
* This use of cx->fp, possibly on trace, is deliberate:
|
||||
* cx->fp->scopeChain->getGlobal() returns the same object whether we're on
|
||||
* trace or not, since we do not trace calls across global objects.
|
||||
*/
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
if (cx->hasfp())
|
||||
return cx->fp()->scopeChain().getGlobal();
|
||||
|
||||
JSObject *scope = cx->globalObject;
|
||||
if (!scope) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
|
||||
return NULL;
|
||||
}
|
||||
OBJ_TO_INNER_OBJECT(cx, scope);
|
||||
return scope;
|
||||
CHECK_REQUEST(cx);
|
||||
return GetGlobalForScopeChain(cx);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(jsval)
|
||||
|
@ -4172,7 +4131,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
|
|||
assertSameCompartment(cx, parent); // XXX no funobj for now
|
||||
if (!parent) {
|
||||
if (cx->hasfp())
|
||||
parent = js_GetScopeChain(cx, cx->fp());
|
||||
parent = GetScopeChain(cx, cx->fp());
|
||||
if (!parent)
|
||||
parent = cx->globalObject;
|
||||
JS_ASSERT(parent);
|
||||
|
|
|
@ -48,12 +48,33 @@
|
|||
#include "jsregexp.h"
|
||||
#include "jsgc.h"
|
||||
|
||||
inline js::RegExpStatics *
|
||||
JSContext::regExpStatics()
|
||||
namespace js {
|
||||
|
||||
static inline JSObject *
|
||||
GetGlobalForScopeChain(JSContext *cx)
|
||||
{
|
||||
JSObject *global = JS_GetGlobalForScopeChain(this);
|
||||
js::RegExpStatics *res = js::RegExpStatics::extractFrom(global);
|
||||
return res;
|
||||
/*
|
||||
* This is essentially GetScopeChain(cx)->getGlobal(), but without
|
||||
* falling off trace.
|
||||
*
|
||||
* This use of cx->fp, possibly on trace, is deliberate:
|
||||
* cx->fp->scopeChain->getGlobal() returns the same object whether we're on
|
||||
* trace or not, since we do not trace calls across global objects.
|
||||
*/
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
if (cx->hasfp())
|
||||
return cx->fp()->scopeChain().getGlobal();
|
||||
|
||||
JSObject *scope = cx->globalObject;
|
||||
if (!scope) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
|
||||
return NULL;
|
||||
}
|
||||
OBJ_TO_INNER_OBJECT(cx, scope);
|
||||
return scope;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -80,6 +101,12 @@ JSContext::computeNextFrame(JSStackFrame *fp)
|
|||
}
|
||||
}
|
||||
|
||||
inline js::RegExpStatics *
|
||||
JSContext::regExpStatics()
|
||||
{
|
||||
return js::RegExpStatics::extractFrom(js::GetGlobalForScopeChain(this));
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
||||
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSFrameRegs *
|
||||
|
|
|
@ -1187,7 +1187,7 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
|
|||
|
||||
/* Force creation of argument and call objects if not yet created */
|
||||
(void) JS_GetFrameCallObject(cx, fp);
|
||||
return js_GetScopeChain(cx, fp);
|
||||
return GetScopeChain(cx, fp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
|
|
|
@ -358,7 +358,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
|
|||
* _DBG* opcodes used by wrappers created here must cope with unresolved
|
||||
* upvars and throw them as reference errors. Caveat debuggers!
|
||||
*/
|
||||
JSObject *scopeChain = js_GetScopeChain(cx, fp);
|
||||
JSObject *scopeChain = GetScopeChain(cx, fp);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
|
||||
|
@ -2928,7 +2928,7 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun, JSOp op, size_t oplen)
|
|||
* Flat closures can be partial, they may need to search enclosing scope
|
||||
* objects via JSOP_NAME, etc.
|
||||
*/
|
||||
JSObject *scopeChain = js_GetScopeChainFast(cx, cx->fp(), op, oplen);
|
||||
JSObject *scopeChain = GetScopeChainFast(cx, cx->fp(), op, oplen);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -162,6 +162,33 @@ JSStackFrame::pc(JSContext *cx, JSStackFrame *next)
|
|||
#endif
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::GetScopeChain(JSContext *cx)
|
||||
{
|
||||
JSStackFrame *fp = js_GetTopStackFrame(cx);
|
||||
if (!fp) {
|
||||
/*
|
||||
* There is no code active on this context. In place of an actual
|
||||
* scope chain, use the context's global object, which is set in
|
||||
* js_InitFunctionAndObjectClasses, and which represents the default
|
||||
* scope chain for the embedding. See also js_FindClassObject.
|
||||
*
|
||||
* For embeddings that use the inner and outer object hooks, the inner
|
||||
* object represents the ultimate global object, with the outer object
|
||||
* acting as a stand-in.
|
||||
*/
|
||||
JSObject *obj = cx->globalObject;
|
||||
if (!obj) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||
return obj;
|
||||
}
|
||||
return GetScopeChain(cx, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This computes the blockChain by iterating through the bytecode
|
||||
* of the current script until it reaches the PC. Each time it sees
|
||||
|
@ -170,7 +197,7 @@ JSStackFrame::pc(JSContext *cx, JSStackFrame *next)
|
|||
* require bytecode scanning appears below.
|
||||
*/
|
||||
JSObject *
|
||||
js_GetBlockChain(JSContext *cx, JSStackFrame *fp)
|
||||
js::GetBlockChain(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
if (!fp->isScriptFrame())
|
||||
return NULL;
|
||||
|
@ -218,7 +245,7 @@ js_GetBlockChain(JSContext *cx, JSStackFrame *fp)
|
|||
* |oplen| is the length of opcode at the current PC.
|
||||
*/
|
||||
JSObject *
|
||||
js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
|
||||
js::GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
|
||||
{
|
||||
/* Assume that we're in a script frame. */
|
||||
jsbytecode *pc = fp->pc(cx);
|
||||
|
@ -274,11 +301,11 @@ js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
|
|||
* closure's scope chain. If we never close over a lexical block, we never
|
||||
* place a mutable clone of it on scopeChain.
|
||||
*
|
||||
* This lazy cloning is implemented in js_GetScopeChain, which is also used in
|
||||
* This lazy cloning is implemented in GetScopeChain, which is also used in
|
||||
* some other cases --- entering 'with' blocks, for example.
|
||||
*/
|
||||
static JSObject *
|
||||
js_GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
|
||||
GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
|
||||
{
|
||||
JSObject *sharedBlock = blockChain;
|
||||
|
||||
|
@ -399,15 +426,15 @@ js_GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
|
|||
}
|
||||
|
||||
JSObject *
|
||||
js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
|
||||
js::GetScopeChain(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
return js_GetScopeChainFull(cx, fp, js_GetBlockChain(cx, fp));
|
||||
return GetScopeChainFull(cx, fp, GetBlockChain(cx, fp));
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js_GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
|
||||
js::GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
|
||||
{
|
||||
return js_GetScopeChainFull(cx, fp, js_GetBlockChainFast(cx, fp, op, oplen));
|
||||
return GetScopeChainFull(cx, fp, GetBlockChainFast(cx, fp, op, oplen));
|
||||
}
|
||||
|
||||
/* Some objects (e.g., With) delegate 'this' to another object. */
|
||||
|
@ -716,7 +743,7 @@ Invoke(JSContext *cx, const CallArgs &argsRef, uint32 flags)
|
|||
*
|
||||
* Compute |this|. Currently, this must happen after the frame is pushed
|
||||
* and fp->scopeChain is correct because the thisObject hook may call
|
||||
* JS_GetScopeChain.
|
||||
* GetScopeChain.
|
||||
*/
|
||||
if (!(flags & JSINVOKE_CONSTRUCT)) {
|
||||
Value &thisv = fp->functionThis();
|
||||
|
@ -1348,7 +1375,7 @@ js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen)
|
|||
sp[-1].setObject(*obj);
|
||||
}
|
||||
|
||||
JSObject *parent = js_GetScopeChainFast(cx, fp, op, oplen);
|
||||
JSObject *parent = GetScopeChainFast(cx, fp, op, oplen);
|
||||
if (!parent)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -2716,7 +2743,7 @@ BEGIN_CASE(JSOP_POPN)
|
|||
regs.sp -= GET_UINT16(regs.pc);
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(regs.fp->base() <= regs.sp);
|
||||
JSObject *obj = js_GetBlockChain(cx, regs.fp);
|
||||
JSObject *obj = GetBlockChain(cx, regs.fp);
|
||||
JS_ASSERT_IF(obj,
|
||||
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
|
||||
<= (size_t) (regs.sp - regs.fp->base()));
|
||||
|
@ -4908,7 +4935,7 @@ BEGIN_CASE(JSOP_REGEXP)
|
|||
* bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was
|
||||
* flouted by many browser-based implementations.
|
||||
*
|
||||
* We avoid the js_GetScopeChain call here and pass fp->scopeChain as
|
||||
* We avoid the GetScopeChain call here and pass fp->scopeChain as
|
||||
* js_GetClassPrototype uses the latter only to locate the global.
|
||||
*/
|
||||
jsatomid index = GET_FULL_INDEX(0);
|
||||
|
@ -5368,7 +5395,7 @@ BEGIN_CASE(JSOP_DEFFUN)
|
|||
} else {
|
||||
JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
|
||||
|
||||
obj2 = js_GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
|
||||
obj2 = GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
|
||||
if (!obj2)
|
||||
goto error;
|
||||
}
|
||||
|
@ -5515,8 +5542,8 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
|
|||
if (!obj)
|
||||
goto error;
|
||||
} else {
|
||||
JSObject *parent = js_GetScopeChainFast(cx, regs.fp, JSOP_DEFLOCALFUN,
|
||||
JSOP_DEFLOCALFUN_LENGTH);
|
||||
JSObject *parent = GetScopeChainFast(cx, regs.fp, JSOP_DEFLOCALFUN,
|
||||
JSOP_DEFLOCALFUN_LENGTH);
|
||||
if (!parent)
|
||||
goto error;
|
||||
|
||||
|
@ -5679,7 +5706,7 @@ BEGIN_CASE(JSOP_LAMBDA)
|
|||
}
|
||||
#endif
|
||||
} else {
|
||||
parent = js_GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
|
||||
parent = GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
|
||||
if (!parent)
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -783,14 +783,14 @@ namespace js {
|
|||
|
||||
static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern JSObject *
|
||||
GetBlockChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSObject *
|
||||
js_GetBlockChain(JSContext *cx, JSStackFrame *fp);
|
||||
GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
|
||||
|
||||
extern JSObject *
|
||||
js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
|
||||
GetScopeChain(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Refresh and return fp->scopeChain. It may be stale if block scopes are
|
||||
|
@ -800,12 +800,10 @@ js_GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
|
|||
* must reflect at runtime.
|
||||
*/
|
||||
extern JSObject *
|
||||
js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
GetScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JSObject *
|
||||
js_GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
|
||||
|
||||
namespace js {
|
||||
GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
|
||||
|
||||
/*
|
||||
* Report an error that the this value passed as |this| in the given arguments
|
||||
|
|
|
@ -1155,8 +1155,8 @@ eval(JSContext *cx, uintN argc, Value *vp)
|
|||
if (directCall) {
|
||||
/* Compile using the caller's current scope object. */
|
||||
staticLevel = caller->script()->staticLevel + 1;
|
||||
scopeobj = js_GetScopeChainFast(cx, caller, JSOP_EVAL,
|
||||
JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
|
||||
scopeobj = GetScopeChainFast(cx, caller, JSOP_EVAL,
|
||||
JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
|
||||
if (!scopeobj)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -15468,7 +15468,7 @@ TraceRecorder::record_JSOP_LAMBDA()
|
|||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
if (js_GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH))
|
||||
if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH))
|
||||
RETURN_STOP_A("Unable to trace creating lambda in let");
|
||||
|
||||
LIns *proto_ins;
|
||||
|
@ -15494,7 +15494,7 @@ TraceRecorder::record_JSOP_LAMBDA_FC()
|
|||
if (FUN_OBJECT(fun)->getParent() != globalObj)
|
||||
return ARECORD_STOP;
|
||||
|
||||
if (js_GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH))
|
||||
if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH))
|
||||
RETURN_STOP_A("Unable to trace creating lambda in let");
|
||||
|
||||
LIns* args[] = {
|
||||
|
|
|
@ -1763,7 +1763,7 @@ ParseXMLSource(JSContext *cx, JSString *src)
|
|||
{
|
||||
Parser parser(cx);
|
||||
if (parser.init(chars, length, NULL, filename, lineno)) {
|
||||
JSObject *scopeChain = JS_GetScopeChain(cx);
|
||||
JSObject *scopeChain = GetScopeChain(cx);
|
||||
if (!scopeChain)
|
||||
return NULL;
|
||||
JSParseNode *pn = parser.parseXMLText(scopeChain, false);
|
||||
|
@ -7210,7 +7210,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
|
|||
JSObject *ns, *obj, *tmp;
|
||||
jsval v;
|
||||
|
||||
JSObject *scopeChain = JS_GetScopeChain(cx);
|
||||
JSObject *scopeChain = GetScopeChain(cx);
|
||||
|
||||
obj = NULL;
|
||||
for (tmp = scopeChain; tmp; tmp = tmp->getParent()) {
|
||||
|
|
|
@ -817,7 +817,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
|
|||
} else {
|
||||
JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
|
||||
|
||||
obj2 = js_GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
|
||||
obj2 = GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
|
||||
if (!obj2)
|
||||
THROW();
|
||||
}
|
||||
|
@ -1467,8 +1467,8 @@ stubs::DefLocalFun(VMFrame &f, JSFunction *fun)
|
|||
if (!obj)
|
||||
THROWV(NULL);
|
||||
} else {
|
||||
JSObject *parent = js_GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
|
||||
JSOP_DEFLOCALFUN_LENGTH);
|
||||
JSObject *parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
|
||||
JSOP_DEFLOCALFUN_LENGTH);
|
||||
if (!parent)
|
||||
THROWV(NULL);
|
||||
|
||||
|
@ -1499,7 +1499,7 @@ stubs::RegExp(VMFrame &f, JSObject *regex)
|
|||
* bytecode at pc. ES5 finally fixed this bad old ES3 design flaw which was
|
||||
* flouted by many browser-based implementations.
|
||||
*
|
||||
* We avoid the js_GetScopeChain call here and pass fp->scopeChain() as
|
||||
* We avoid the GetScopeChain call here and pass fp->scopeChain() as
|
||||
* js_GetClassPrototype uses the latter only to locate the global.
|
||||
*/
|
||||
JSObject *proto;
|
||||
|
@ -1597,7 +1597,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun)
|
|||
if (FUN_NULL_CLOSURE(fun)) {
|
||||
parent = &f.fp()->scopeChain();
|
||||
} else {
|
||||
parent = js_GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
|
||||
parent = GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
|
||||
if (!parent)
|
||||
THROWV(NULL);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче