Luke Wagner – Bug 634542 - Temporary diagnostic patch 2 (r=dvander,a=shaver)

This commit is contained in:
Luke Wagner 2011-02-18 18:38:10 -08:00
Родитель 371e0dbf74
Коммит 0abe4fd441
11 изменённых файлов: 147 добавлений и 65 удалений

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

@ -4189,7 +4189,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
assertSameCompartment(cx, parent); // XXX no funobj for now
if (!parent) {
if (cx->hasfp())
parent = GetScopeChain(cx, cx->fp());
parent = GetScopeChain(cx, cx->fp(), ORIGIN_CLONE_FUNOBJ);
if (!parent)
parent = cx->globalObject;
JS_ASSERT(parent);

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

@ -1395,7 +1395,7 @@ JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
/* Force creation of argument and call objects if not yet created */
(void) JS_GetFrameCallObject(cx, fp);
return GetScopeChain(cx, fp);
return GetScopeChain(cx, fp, ORIGIN_GET_FRAME_SCOPE_CHAIN);
}
JS_PUBLIC_API(JSObject *)
@ -1417,7 +1417,7 @@ JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
* XXX ill-defined: null return here means error was reported, unlike a
* null returned above or in the #else
*/
return js_GetCallObject(cx, fp);
return js_GetCallObject(cx, fp, ORIGIN_GET_FRAME_OBJ);
}
JS_PUBLIC_API(JSBool)

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

@ -359,7 +359,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 = GetScopeChain(cx, fp);
JSObject *scopeChain = GetScopeChain(cx, fp, ORIGIN_WESC);
if (!scopeChain)
return NULL;
@ -948,7 +948,8 @@ namespace js {
* on behalf of which the call object is being created.
*/
JSObject *
NewCallObject(JSContext *cx, Bindings *bindings, JSObject &scopeChain, JSObject *callee)
NewCallObject(JSContext *cx, Bindings *bindings, JSObject &scopeChain, JSObject *callee,
Origins origin)
{
size_t argsVars = bindings->countArgsAndVars();
size_t slots = JSObject::CALL_RESERVED_SLOTS + argsVars;
@ -977,6 +978,7 @@ NewCallObject(JSContext *cx, Bindings *bindings, JSObject &scopeChain, JSObject
#endif
callobj->setCallObjCallee(callee);
callobj->setOrigin(origin);
return callobj;
}
@ -995,17 +997,13 @@ NewDeclEnvObject(JSContext *cx, JSStackFrame *fp)
}
JSObject *
js_GetCallObject(JSContext *cx, JSStackFrame *fp)
js_GetCallObject(JSContext *cx, JSStackFrame *fp, Origins origin)
{
/* Create a call object for fp only if it lacks one. */
JS_ASSERT(fp->isFunctionFrame());
if (fp->hasCallObj())
return &fp->callObj();
JS_ASSERT(!fp->isEvalFrame());
if (fp->isEvalFrame())
*((int *)0xeca1) = 0;
#ifdef DEBUG
/* A call object should be a frame's outermost scope chain element. */
Class *clasp = fp->scopeChain().getClass();
@ -1040,7 +1038,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
}
JSObject *callobj =
NewCallObject(cx, &fp->fun()->script()->bindings, fp->scopeChain(), &fp->callee());
NewCallObject(cx, &fp->fun()->script()->bindings, fp->scopeChain(), &fp->callee(), origin);
if (!callobj)
return NULL;
@ -1061,7 +1059,7 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO
JS_ASSERT(!js_IsNamedLambda(fun));
JS_ASSERT(scopeChain);
JS_ASSERT(callee);
return NewCallObject(cx, &fun->script()->bindings, *scopeChain, callee);
return NewCallObject(cx, &fun->script()->bindings, *scopeChain, callee, ORIGIN_ON_TRACE);
}
JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT,
@ -1373,24 +1371,67 @@ call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
return true;
}
JS_PUBLIC_DATA(volatile JSStackFrame *volatile) leakage;
struct Cargo
{
uint32 bef;
JSObject *callObjCallee;
uint32 atomLength;
jschar atom[64];
uint32 filenameLength;
char filename[128];
uint32 lineno;
uint32 callObjFlags;
uint32 aft;
Cargo() : bef(0xaaaaaaaa), aft(0xbbbbbbbb) {}
};
JS_PUBLIC_DATA(Cargo *) cargoEscape;
static void
call_trace(JSTracer *trc, JSObject *obj)
{
JSStackFrame frameCopy[3];
JS_ASSERT(obj->isCall());
if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) {
memset(&frameCopy[0], 0xaa, sizeof(JSStackFrame));
memcpy(&frameCopy[1], fp, sizeof(JSStackFrame));
memset(&frameCopy[2], 0xbb, sizeof(JSStackFrame));
leakage = frameCopy;
bool bad = fp->isEvalFrame() && !fp->script()->strictModeCode;
if (JSStackFrame *fp = obj->maybeCallObjStackFrame()) {
// TEMPORARY BUG FINDING CODE
Cargo cargo;
cargoEscape = &cargo;
cargo.callObjFlags = obj->flags;
cargo.callObjCallee = obj->getCallObjCallee();
if (cargo.callObjCallee) {
JSFunction *fun = cargo.callObjCallee->getFunctionPrivate();
if (fun->atom) {
cargo.atomLength = fun->atom->length();
js_strncpy(cargo.atom, fun->atom->chars(), Min(cargo.atomLength, (uint32)64));
} else {
strcpy((char *)cargo.atom, "(unnamed)");
}
if (fun->isInterpreted()) {
JSScript *script = fun->script();
cargo.lineno = script->lineno;
cargo.filenameLength = strlen(script->filename);
if (const char *filename = script->filename) {
strncpy(cargo.filename, filename, Min(cargo.filenameLength, (uint32)128));
} else {
strcpy(cargo.filename, "(no file)");
}
} else {
*((int *)0xbad1) = 0;
}
} else {
strcpy((char *)cargo.atom, "(eval)");
}
bool bad = obj != &fp->callObj();
JS_ASSERT(!bad);
if (bad)
*(int *)0xbad = 0;
*((int *)0xbad2) = 0;
/*
* FIXME: Hide copies of stack values rooted by fp from the Cycle

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

@ -328,7 +328,8 @@ namespace js {
* must be null.
*/
extern JSObject *
NewCallObject(JSContext *cx, js::Bindings *bindings, JSObject &scopeChain, JSObject *callee);
NewCallObject(JSContext *cx, js::Bindings *bindings, JSObject &scopeChain, JSObject *callee,
Origins origin);
/*
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
@ -516,7 +517,7 @@ extern void
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject *
js_GetCallObject(JSContext *cx, JSStackFrame *fp);
js_GetCallObject(JSContext *cx, JSStackFrame *fp, Origins origin);
extern JSObject * JS_FASTCALL
js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSObject *scopeChain);

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

@ -110,22 +110,6 @@ using namespace js::gc;
JSObject *const JSStackFrame::sInvalidScopeChain = (JSObject *)0xbeef;
#endif
JS_NEVER_INLINE void
js::PutActivationObjects(JSContext *cx, JSStackFrame *fp)
{
JS_ASSERT(fp->isFunctionFrame() && !fp->isEvalFrame());
if (fp->isEvalFrame())
*((int *)0x1337) = 0;
/* The order is important as js_PutCallObject needs to access argsObj. */
if (fp->hasCallObj()) {
js_PutCallObject(cx, fp);
} else if (fp->hasArgsObj()) {
js_PutArgsObject(cx, fp);
}
}
jsbytecode *
JSStackFrame::pc(JSContext *cx, JSStackFrame *next)
{
@ -265,7 +249,7 @@ js::GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
* some other cases --- entering 'with' blocks, for example.
*/
static JSObject *
GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain, Origins origin)
{
JSObject *sharedBlock = blockChain;
@ -293,7 +277,7 @@ GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
if (fp->isFunctionFrame() && !fp->hasCallObj()) {
JS_ASSERT_IF(fp->scopeChain().isClonedBlock(),
fp->scopeChain().getPrivate() != js_FloatingFrameIfGenerator(cx, fp));
if (!js_GetCallObject(cx, fp))
if (!js_GetCallObject(cx, fp, origin))
return NULL;
/* We know we must clone everything on blockChain. */
@ -386,15 +370,15 @@ GetScopeChainFull(JSContext *cx, JSStackFrame *fp, JSObject *blockChain)
}
JSObject *
js::GetScopeChain(JSContext *cx, JSStackFrame *fp)
js::GetScopeChain(JSContext *cx, JSStackFrame *fp, Origins origin)
{
return GetScopeChainFull(cx, fp, GetBlockChain(cx, fp));
return GetScopeChainFull(cx, fp, GetBlockChain(cx, fp), origin);
}
JSObject *
js::GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen)
js::GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen, Origins origin)
{
return GetScopeChainFull(cx, fp, GetBlockChainFast(cx, fp, op, oplen));
return GetScopeChainFull(cx, fp, GetBlockChainFast(cx, fp, op, oplen), origin);
}
/* Some objects (e.g., With) delegate 'this' to another object. */
@ -709,7 +693,7 @@ Invoke(JSContext *cx, const CallArgs &argsRef, uint32 flags)
cx->stack().pushInvokeFrame(cx, args, &frame);
/* Now that the new frame is rooted, maybe create a call object. */
if (fun->isHeavyweight() && !js_GetCallObject(cx, fp))
if (fun->isHeavyweight() && !js_GetCallObject(cx, fp, ORIGIN_INVOKE))
return false;
/* Run function until JSOP_STOP, JSOP_RETURN or error. */
@ -949,7 +933,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
*/
if ((flags & JSFRAME_EVAL) && script->strictModeCode) {
AutoScriptRooter root(cx, script);
initialVarObj = NewCallObject(cx, &script->bindings, *initialVarObj, NULL);
initialVarObj = NewCallObject(cx, &script->bindings, *initialVarObj, NULL, ORIGIN_EXEC);
if (!initialVarObj)
return false;
initialVarObj->setPrivate(frame.fp());
@ -1300,7 +1284,7 @@ DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp)
AutoFunctionCallProbe callProbe(cx, evalfun, caller->script());
JSObject *scopeChain =
GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH, ORIGIN_DEVAL);
if (!scopeChain || !EvalKernel(cx, argc, vp, DIRECT_EVAL, caller, scopeChain))
return false;
cx->regs->sp = vp + 1;
@ -1353,7 +1337,7 @@ js_EnterWith(JSContext *cx, jsint stackIndex, JSOp op, size_t oplen)
sp[-1].setObject(*obj);
}
JSObject *parent = GetScopeChainFast(cx, fp, op, oplen);
JSObject *parent = GetScopeChainFast(cx, fp, op, oplen, ORIGIN_WITH);
if (!parent)
return JS_FALSE;
@ -4713,7 +4697,7 @@ BEGIN_CASE(JSOP_FUNCALL)
atoms = script->atomMap.vector;
/* Now that the new frame is rooted, maybe create a call object. */
if (newfun->isHeavyweight() && !js_GetCallObject(cx, regs.fp))
if (newfun->isHeavyweight() && !js_GetCallObject(cx, regs.fp, ORIGIN_INTERP))
goto error;
inlineCallCount++;
@ -5377,7 +5361,7 @@ BEGIN_CASE(JSOP_DEFFUN)
} else {
JS_ASSERT(!fun->isFlatClosure());
obj2 = GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
obj2 = GetScopeChainFast(cx, regs.fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH, ORIGIN_DEFFUN);
if (!obj2)
goto error;
}
@ -5516,7 +5500,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
goto error;
} else {
JSObject *parent = GetScopeChainFast(cx, regs.fp, JSOP_DEFLOCALFUN,
JSOP_DEFLOCALFUN_LENGTH);
JSOP_DEFLOCALFUN_LENGTH, ORIGIN_DEFLOCALFUN);
if (!parent)
goto error;
@ -5679,7 +5663,7 @@ BEGIN_CASE(JSOP_LAMBDA)
}
#endif
} else {
parent = GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
parent = GetScopeChainFast(cx, regs.fp, JSOP_LAMBDA, JSOP_LAMBDA_LENGTH, ORIGIN_LAMBDA);
if (!parent)
goto error;
}

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

@ -811,10 +811,10 @@ GetBlockChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
* must reflect at runtime.
*/
extern JSObject *
GetScopeChain(JSContext *cx, JSStackFrame *fp);
GetScopeChain(JSContext *cx, JSStackFrame *fp, Origins);
extern JSObject *
GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen);
GetScopeChainFast(JSContext *cx, JSStackFrame *fp, JSOp op, size_t oplen, Origins);
/*
* Report an error that the this value passed as |this| in the given arguments
@ -834,7 +834,7 @@ ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp);
template <typename T>
bool GetPrimitiveThis(JSContext *cx, Value *vp, T *v);
void
inline void
PutActivationObjects(JSContext *cx, JSStackFrame *fp);
/*

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

@ -524,6 +524,19 @@ struct AutoInterpPreparer {
}
};
inline void
PutActivationObjects(JSContext *cx, JSStackFrame *fp)
{
JS_ASSERT(fp->isFunctionFrame() && !fp->isEvalFrame());
/* The order is important as js_PutCallObject needs to access argsObj. */
if (fp->hasCallObj()) {
js_PutCallObject(cx, fp);
} else if (fp->hasArgsObj()) {
js_PutArgsObject(cx, fp);
}
}
class InvokeSessionGuard
{
InvokeArgsGuard args_;
@ -722,6 +735,8 @@ ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
JS_ASSERT(fp->hasCallObj());
JS_ASSERT(fp->callObj().callIsForEval());
js_PutCallObject(cx, fp);
} else if (fp->hasCallObj()) {
fp->callObj().setSkipped();
}
} else {
/*
@ -732,6 +747,8 @@ ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
if (fp->isFunctionFrame() && !fp->isYielding()) {
JS_ASSERT_IF(fp->hasCallObj(), !fp->callObj().callIsForEval());
PutActivationObjects(cx, fp);
} else if (fp->hasCallObj()) {
fp->callObj().setSkipped();
}
}

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

@ -287,6 +287,31 @@ namespace nanojit {
class ValidateWriter;
}
// TEMPORARY CRASH-FINDING
enum Origins {
ORIGIN_ON_TRACE = 1,
ORIGIN_EXEC = 2,
ORIGIN_GET_FRAME_OBJ = 3,
ORIGIN_INVOKE = 4,
ORIGIN_INTERP = 5,
ORIGIN_GET_SCOPE_CHAIN_API = 6,
ORIGIN_CLONE_FUNOBJ = 7,
ORIGIN_GET_FRAME_SCOPE_CHAIN = 8,
ORIGIN_WESC = 9,
ORIGIN_DEVAL = 10,
ORIGIN_WITH = 11,
ORIGIN_DEFFUN = 12,
ORIGIN_DEFLOCALFUN = 13,
ORIGIN_LAMBDA = 14,
ORIGIN_LAME = 15,
ORIGIN_MJIT_DEFFUN = 16,
ORIGIN_MJIT_DEFLOCALFUN = 17,
ORIGIN_MJIT_LAMBDA = 18,
ORIGIN_COMPILE_FUNCTION = 19,
ORIGIN_UIC = 20,
ORIGIN_MJIT_GCO = 21
};
/*
* JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
* 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
@ -386,9 +411,23 @@ struct JSObject : js::gc::Cell {
HAS_EQUALITY = 0x200,
METHOD_THRASH_COUNT_MASK = 0xc00,
METHOD_THRASH_COUNT_SHIFT = 10,
METHOD_THRASH_COUNT_MAX = METHOD_THRASH_COUNT_MASK >> METHOD_THRASH_COUNT_SHIFT
METHOD_THRASH_COUNT_MAX = METHOD_THRASH_COUNT_MASK >> METHOD_THRASH_COUNT_SHIFT,
ORIGIN_MASK = 0xff000000,
ORIGIN_SHIFT = 24,
SKIPPED_BIT = 0x00100000
};
// TMP CRASH-FINDING
void setOrigin(Origins origin) {
flags = (flags & ~(uint32)ORIGIN_MASK) | (origin << ORIGIN_SHIFT);
}
void setSkipped() {
flags |= SKIPPED_BIT;
}
/*
* Impose a sane upper bound, originally checked only for dense arrays, on
* number of slots in an object.

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

@ -1681,7 +1681,7 @@ static JSObject *
GetXMLScopeChain(JSContext *cx)
{
if (JSStackFrame *fp = js_GetTopStackFrame(cx))
return GetScopeChain(cx, fp);
return GetScopeChain(cx, fp, ORIGIN_LAME);
/*
* There is no code active on this context. In place of an actual scope

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

@ -325,7 +325,7 @@ stubs::CompileFunction(VMFrame &f, uint32 nactual)
f.regs.sp = fp->base();
f.regs.pc = script->code;
if (fun->isHeavyweight() && !js_GetCallObject(cx, fp))
if (fun->isHeavyweight() && !js_GetCallObject(cx, fp, ORIGIN_COMPILE_FUNCTION))
THROWV(NULL);
CompileStatus status = CanMethodJIT(cx, script, fp, CompileRequest_JIT);
@ -368,7 +368,7 @@ UncachedInlineCall(VMFrame &f, uint32 flags, void **pret, bool *unjittable, uint
JS_ASSERT(newfp == f.regs.fp);
/* Scope with a call object parented by callee's parent. */
if (newfun->isHeavyweight() && !js_GetCallObject(cx, newfp))
if (newfun->isHeavyweight() && !js_GetCallObject(cx, newfp, ORIGIN_UIC))
return false;
/* Try to compile if not already compiled. */
@ -588,7 +588,7 @@ void JS_FASTCALL
stubs::GetCallObject(VMFrame &f)
{
JS_ASSERT(f.fp()->fun()->isHeavyweight());
if (!js_GetCallObject(f.cx, f.fp()))
if (!js_GetCallObject(f.cx, f.fp(), ORIGIN_MJIT_GCO))
THROW();
}

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

@ -725,7 +725,7 @@ stubs::DefFun(VMFrame &f, JSFunction *fun)
} else {
JS_ASSERT(!fun->isFlatClosure());
obj2 = GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH);
obj2 = GetScopeChainFast(cx, fp, JSOP_DEFFUN, JSOP_DEFFUN_LENGTH, ORIGIN_MJIT_DEFFUN);
if (!obj2)
THROW();
}
@ -1386,7 +1386,7 @@ stubs::DefLocalFun(VMFrame &f, JSFunction *fun)
THROWV(NULL);
} else {
JSObject *parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
JSOP_DEFLOCALFUN_LENGTH);
JSOP_DEFLOCALFUN_LENGTH, ORIGIN_MJIT_DEFLOCALFUN);
if (!parent)
THROWV(NULL);
@ -1515,7 +1515,7 @@ stubs::Lambda(VMFrame &f, JSFunction *fun)
if (FUN_NULL_CLOSURE(fun)) {
parent = &f.fp()->scopeChain();
} else {
parent = GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
parent = GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH, ORIGIN_MJIT_LAMBDA);
if (!parent)
THROWV(NULL);
}