Fix crash in AtSafePoint (bug 589398, r=dmandelin).

This commit is contained in:
David Anderson 2010-10-05 16:41:06 -07:00
Родитель 14fea6ff85
Коммит 7dcc38f5b2
8 изменённых файлов: 97 добавлений и 63 удалений

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

@ -2303,7 +2303,7 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, uintN
do { \
JS_ASSERT_IF(leaveOnSafePoint, !TRACE_RECORDER(cx)); \
if (leaveOnSafePoint && !regs.fp->hasImacropc() && \
script->hasNativeCodeForPC(regs.fp->isConstructing(), regs.pc)) { \
script->maybeNativeCodeForPC(regs.fp->isConstructing(), regs.pc)) { \
JS_ASSERT(!TRACE_RECORDER(cx)); \
interpReturnOK = true; \
goto stop_recording; \

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

@ -294,12 +294,44 @@ struct JSScript {
js::mjit::JITScript *jitNormal; /* Extra JIT info for normal scripts */
js::mjit::JITScript *jitCtor; /* Extra JIT info for constructors */
void **nmapNormal;
void **nmapCtor;
bool hasJITCode() {
return jitNormal || jitCtor;
}
inline void **maybeNativeMap(bool constructing);
inline bool hasNativeCodeForPC(bool constructing, jsbytecode *pc);
void setNativeMap(bool constructing, void **map) {
if (constructing)
nmapCtor = map;
else
nmapNormal = map;
}
void **maybeNativeMap(bool constructing) {
return constructing ? nmapCtor : nmapNormal;
}
void **nativeMap(bool constructing) {
void **nmap = maybeNativeMap(constructing);
JS_ASSERT(nmap);
return nmap;
}
void *maybeNativeCodeForPC(bool constructing, jsbytecode *pc) {
void **nmap = maybeNativeMap(constructing);
if (!nmap)
return NULL;
JS_ASSERT(pc >= code && pc < code + length);
return nmap[pc - code];
}
void *nativeCodeForPC(bool constructing, jsbytecode *pc) {
void **nmap = nativeMap(constructing);
JS_ASSERT(pc >= code && pc < code + length);
JS_ASSERT(nmap[pc - code]);
return nmap[pc - code];
}
js::mjit::JITScript *getJIT(bool constructing) {
return constructing ? jitCtor : jitNormal;

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

@ -370,7 +370,6 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
/* Build the pc -> ncode mapping. */
void **nmap = (void **)cursor;
jit->nmap = nmap;
cursor += sizeof(void *) * script->length;
for (size_t i = 0; i < script->length; i++) {
@ -590,6 +589,7 @@ mjit::Compiler::finishThisUp(JITScript **jitp)
JS_ASSERT(size_t(cursor - (uint8*)jit) == totalBytes);
script->setNativeMap(isConstructing, nmap);
*jitp = jit;
return Compile_Okay;

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

@ -588,8 +588,7 @@ js_InternalThrow(VMFrame &f)
JSStackFrame *fp = cx->fp();
JSScript *script = fp->script();
JITScript *jit = script->getJIT(fp->isConstructing());
return jit->nmap[pc - script->code];
return script->nativeCodeForPC(fp->isConstructing(), pc);
}
void JS_FASTCALL
@ -677,7 +676,7 @@ HandleErrorInExcessFrames(VMFrame &f, JSStackFrame *stopFp)
return returnOK;
}
static inline bool
static inline void *
AtSafePoint(JSContext *cx)
{
JSStackFrame *fp = cx->fp();
@ -685,12 +684,7 @@ AtSafePoint(JSContext *cx)
return false;
JSScript *script = fp->script();
JITScript *jit = script->getJIT(fp->isConstructing());
if (!jit->nmap)
return false;
JS_ASSERT(cx->regs->pc >= script->code && cx->regs->pc < script->code + script->length);
return !!jit->nmap[cx->regs->pc - script->code];
return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc);
}
static inline JSBool
@ -700,9 +694,9 @@ PartialInterpret(VMFrame &f)
JSStackFrame *fp = cx->fp();
#ifdef DEBUG
JITScript *jit = fp->script()->getJIT(fp->isConstructing());
JS_ASSERT(fp->hasImacropc() || !jit->nmap ||
!jit->nmap[cx->regs->pc - fp->script()->code]);
JSScript *script = fp->script();
JS_ASSERT(fp->hasImacropc() ||
!script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs->pc));
#endif
JSBool ok = JS_TRUE;
@ -729,12 +723,8 @@ FinishExcessFrames(VMFrame &f, JSStackFrame *entryFrame)
{
JSContext *cx = f.cx;
while (cx->fp() != entryFrame || entryFrame->hasImacropc()) {
JSStackFrame *fp = cx->fp();
if (AtSafePoint(cx)) {
JSScript *script = fp->script();
JITScript *jit = script->getJIT(fp->isConstructing());
if (!JaegerShotAtSafePoint(cx, jit->nmap[cx->regs->pc - script->code])) {
if (void *ncode = AtSafePoint(cx)) {
if (!JaegerShotAtSafePoint(cx, ncode)) {
if (!HandleErrorInExcessFrames(f, entryFrame))
return false;
@ -887,12 +877,8 @@ RunTracer(VMFrame &f)
JS_ASSERT(!entryFrame->hasImacropc());
/* Step 2. If entryFrame is at a safe point, just leave. */
if (AtSafePoint(cx)) {
JITScript *jit = entryFrame->script()->getJIT(entryFrame->isConstructing());
uint32 offs = uint32(cx->regs->pc - entryFrame->script()->code);
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
}
if (void *ncode = AtSafePoint(cx))
return ncode;
/* Step 3. If entryFrame is at a RETURN, then leave slightly differently. */
if (JSOp op = FrameIsFinished(cx)) {

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

@ -829,6 +829,7 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
script->jitArityCheckNormal = NULL;
cx->free(script->jitNormal);
script->jitNormal = NULL;
script->nmapNormal = NULL;
}
if (script->jitCtor) {
@ -836,6 +837,7 @@ mjit::ReleaseScriptCode(JSContext *cx, JSScript *script)
script->jitArityCheckCtor = NULL;
cx->free(script->jitCtor);
script->jitCtor = NULL;
script->nmapCtor = NULL;
}
}

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

@ -190,7 +190,6 @@ struct JITScript {
js::mjit::CallSite *callSites;
uint32 nCallSites;
void **nmap; /* scripted pc to native code map. */
#ifdef JS_MONOIC
ic::MICInfo *mics; /* MICs in this script. */
uint32 nMICs; /* number of MonoICs */
@ -263,25 +262,6 @@ struct CallSite
} /* namespace js */
inline void **
JSScript::maybeNativeMap(bool constructing)
{
js::mjit::JITScript *jit = constructing ? jitCtor : jitNormal;
if (!jit)
return NULL;
return jit->nmap;
}
inline bool
JSScript::hasNativeCodeForPC(bool constructing, jsbytecode *pc)
{
js::mjit::JITScript *jit = getJIT(constructing);
if (!jit)
return false;
JS_ASSERT(pc >= code && pc < code + length);
return !!jit->nmap[pc - code];
}
#ifdef _MSC_VER
extern "C" void *JaegerThrowpoline(js::VMFrame *vmFrame);
#else

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

@ -2533,15 +2533,15 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
{
jsbytecode *jpc = pc;
JSScript *script = f.fp()->script();
JITScript *jit = script->getJIT(f.fp()->isConstructing());
void **nmap = script->nativeMap(f.fp()->isConstructing());
/* This is correct because the compiler adjusts the stack beforehand. */
Value lval = f.regs.sp[-1];
if (!lval.isPrimitive()) {
ptrdiff_t offs = (pc + GET_JUMP_OFFSET(pc)) - script->code;
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
JS_ASSERT(nmap[offs]);
return nmap[offs];
}
JS_ASSERT(pc[0] == JSOP_LOOKUPSWITCH);
@ -2561,8 +2561,8 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
JSString *rhs = rval.toString();
if (rhs == str || js_EqualStrings(str, rhs)) {
ptrdiff_t offs = (jpc + GET_JUMP_OFFSET(pc)) - script->code;
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
JS_ASSERT(nmap[offs]);
return nmap[offs];
}
}
pc += JUMP_OFFSET_LEN;
@ -2574,8 +2574,8 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
pc += INDEX_LEN;
if (rval.isNumber() && d == rval.toNumber()) {
ptrdiff_t offs = (jpc + GET_JUMP_OFFSET(pc)) - script->code;
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
JS_ASSERT(nmap[offs]);
return nmap[offs];
}
pc += JUMP_OFFSET_LEN;
}
@ -2585,16 +2585,16 @@ stubs::LookupSwitch(VMFrame &f, jsbytecode *pc)
pc += INDEX_LEN;
if (lval == rval) {
ptrdiff_t offs = (jpc + GET_JUMP_OFFSET(pc)) - script->code;
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
JS_ASSERT(nmap[offs]);
return nmap[offs];
}
pc += JUMP_OFFSET_LEN;
}
}
ptrdiff_t offs = (jpc + GET_JUMP_OFFSET(jpc)) - script->code;
JS_ASSERT(jit->nmap[offs]);
return jit->nmap[offs];
JS_ASSERT(nmap[offs]);
return nmap[offs];
}
void * JS_FASTCALL
@ -2602,8 +2602,6 @@ stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
{
jsbytecode * const originalPC = origPc;
jsbytecode *pc = originalPC;
JSScript *script = f.fp()->script();
JITScript *jit = script->getJIT(f.fp()->isConstructing());
uint32 jumpOffset = GET_JUMP_OFFSET(pc);
pc += JUMP_OFFSET_LEN;
@ -2641,10 +2639,13 @@ stubs::TableSwitch(VMFrame &f, jsbytecode *origPc)
}
finally:
JSScript *script = f.fp()->script();
void **nmap = script->nativeMap(f.fp()->isConstructing());
/* Provide the native address. */
ptrdiff_t offset = (originalPC + jumpOffset) - script->code;
JS_ASSERT(jit->nmap[offset]);
return jit->nmap[offset];
JS_ASSERT(nmap[offset]);
return nmap[offset];
}
void JS_FASTCALL

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

@ -0,0 +1,33 @@
/* vim: set ts=4 sw=4 tw=99 et: */
function J(i) {
/* Cause a branch to build. */
if (i % 3)
<xml></xml>
}
function h(i) {
J(i);
/* Generate a safe point in the method JIT. */
if (1 == 14) { eval(); }
return J(i);
}
function g(i) {
/* Method JIT will try to remove this frame. */
if (i == 14) { <xml></xml> }
return h(i);
}
function f() {
for (var i = 0; i < RUNLOOP * 2; i++) {
g(i);
}
}
f();
/* Don't crash. */