Fix some bugs when we fail to get a translation

If we failed to get the translation for a cloned closure, we didnt
clean the registers.

VMRegAnchor::VMRegAncor(ActRec*,bool) didnt know how to set things
up for continuations, and had an unused bool parameter.

RetFromInterpretedFrame isnt suitable for returning from a
generator - so just preserve m_savedRip across the doFCall.
Esse commit está contido em:
mwilliams
2013-04-04 16:10:12 -07:00
commit de Sara Golemon
commit b9e7308acb
3 arquivos alterados com 45 adições e 38 exclusões
+8 -1
Ver Arquivo
@@ -1790,7 +1790,14 @@ bool VMExecutionContext::prepareFuncEntry(ActRec *ar,
func = ar->m_func;
}
pushLocalsAndIterators(func, nlocals);
if (LIKELY(!func->isGenerator())) {
/*
* we only get here from callAndResume
* if we failed to get a translation for
* a generator's prologue
*/
pushLocalsAndIterators(func, nlocals);
}
/*
* If we're reentering, make sure to finalize the ActRec before
+7 -13
Ver Arquivo
@@ -90,27 +90,21 @@ struct VMRegAnchor : private boost::noncopyable {
m_old = tl_regState;
Translator::Get()->sync();
}
VMRegAnchor(ActRec* ar, bool atFCall=false) {
VMRegAnchor(ActRec* ar) {
// Some C++ entry points have an ActRec prepared from after a call
// instruction. This syncs us to right after the call instruction.
assert(tl_regState == REGSTATE_DIRTY);
m_old = REGSTATE_DIRTY;
tl_regState = REGSTATE_CLEAN;
int numArgs = ar->numArgs();
const Func* prevF = ((ActRec*)(ar->m_savedRbp))->m_func;
vmsp() = (TypedValue*)ar - numArgs;
auto prevAr = (ActRec*)ar->m_savedRbp;
const Func* prevF = prevAr->m_func;
vmsp() = ar->m_func->isGenerator() ?
Stack::generatorStackBase(ar) :
(TypedValue*)ar - ar->numArgs();
assert(g_vmContext->m_stack.isValidAddress((uintptr_t)vmsp()));
vmpc() = prevF->unit()->at(prevF->base() + ar->m_soff);
if (atFCall) {
// VMExecutionContext::doFCall expects vmfp to be the caller's
// ActRec, but if we call VMRegAnchor while executing the FCall
// sequence (in TargetCache::callAndResume), we actually have the
// callee's ActRec.
vmfp() = (TypedValue*)ar->m_savedRbp;
} else {
vmfp() = (TypedValue*)ar;
}
vmfp() = (TypedValue*)prevAr;
}
~VMRegAnchor() {
tl_regState = m_old;
@@ -78,6 +78,29 @@ void TranslatorX64::reqLitHelper(const ReqLitStaticArgs* args) {
framePtr->m_savedRbp = (uint64_t)ec->m_fp;
}
static void setupAfterProlog(ActRec* fp) {
g_vmContext->m_fp = fp;
g_vmContext->m_stack.top() = sp;
int nargs = fp->numArgs();
int nparams = fp->m_func->numParams();
Offset firstDVInitializer = InvalidAbsoluteOffset;
if (nargs < nparams) {
const Func::ParamInfoVec& paramInfo = fp->m_func->params();
for (int i = nargs; i < nparams; ++i) {
Offset dvInitializer = paramInfo[i].funcletOff();
if (dvInitializer != InvalidAbsoluteOffset) {
firstDVInitializer = dvInitializer;
break;
}
}
}
if (firstDVInitializer != InvalidAbsoluteOffset) {
g_vmContext->m_pc = fp->m_func->unit()->entry() + firstDVInitializer;
} else {
g_vmContext->m_pc = fp->m_func->getEntry();
}
}
/*
* fcallHelperThunk--
*
@@ -93,10 +116,13 @@ static TCA callAndResume(ActRec *ar) {
* array is just being used as entry points for the
* dv funclets. Dont run the prolog again.
*/
VMRegAnchor _(ar, true);
VMRegAnchor _(ar);
uint64_t rip = ar->m_savedRip;
g_vmContext->doFCall<true>(ar, g_vmContext->m_pc);
ar->m_savedRip = rip;
return Translator::Get()->getResumeHelperRet();
}
setupAfterProlog(ar);
return Translator::Get()->getResumeHelper();
}
@@ -218,34 +244,14 @@ asm (
* neither requires different entry points for different callsite arities.
*/
TCA funcBodyHelper(ActRec* fp) {
g_vmContext->m_fp = fp;
g_vmContext->m_stack.top() = sp;
int nargs = fp->numArgs();
int nparams = fp->m_func->numParams();
Offset firstDVInitializer = InvalidAbsoluteOffset;
if (nargs < nparams) {
const Func::ParamInfoVec& paramInfo = fp->m_func->params();
for (int i = nargs; i < nparams; ++i) {
Offset dvInitializer = paramInfo[i].funcletOff();
if (dvInitializer != InvalidAbsoluteOffset) {
firstDVInitializer = dvInitializer;
break;
}
}
}
if (firstDVInitializer != InvalidAbsoluteOffset) {
g_vmContext->m_pc = fp->m_func->unit()->entry() + firstDVInitializer;
} else {
g_vmContext->m_pc = fp->m_func->getEntry();
}
setupAfterProlog(fp);
tl_regState = REGSTATE_CLEAN;
Func* func = const_cast<Func*>(fp->m_func);
SrcKey sk(func, func->base());
TCA tca;
if (func->isGenerator()) {
assert(nargs == 1);
tca = tx64->funcPrologue(func, nargs);
assert(fp->numArgs() == 1);
tca = tx64->funcPrologue(func, 1);
} else {
tca = tx64->getCallArrayProlog(func);
}