зеркало из https://github.com/mozilla/pjs.git
Fix crash in AtSafePoint (bug 589398, r=dmandelin).
This commit is contained in:
Родитель
14fea6ff85
Коммит
7dcc38f5b2
|
@ -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. */
|
||||
|
Загрузка…
Ссылка в новой задаче