Resolve the merge conflict from bug 674998 correctly by removing InvokeSessionGuard completely, r=luke

This commit is contained in:
Ehsan Akhgari 2011-09-07 11:34:15 -04:00
parent b663b676ff
commit 8f876c5ce8
2 changed files with 0 additions and 221 deletions

View File

@ -683,106 +683,6 @@ js::InvokeKernel(JSContext *cx, const CallArgs &argsRef, MaybeConstruct construc
return ok;
}
bool
InvokeSessionGuard::start(JSContext *cx, const Value &calleev, const Value &thisv, uintN argc)
{
#ifdef JS_TRACER
if (TRACE_RECORDER(cx))
AbortRecording(cx, "attempt to reenter VM while recording");
LeaveTrace(cx);
#endif
/* Always push arguments, regardless of optimized/normal invoke. */
ContextStack &stack = cx->stack;
if (!stack.pushInvokeArgs(cx, argc, &args_))
return false;
/* Callees may clobber 'this' or 'callee'. */
savedCallee_ = args_.calleev() = calleev;
savedThis_ = args_.thisv() = thisv;
/* If anyone (through jsdbgapi) finds this frame, make it safe. */
MakeRangeGCSafe(args_.argv(), args_.argc());
do {
/* Hoist dynamic checks from scripted Invoke. */
if (!calleev.isObject())
break;
JSObject &callee = calleev.toObject();
if (callee.getClass() != &FunctionClass)
break;
JSFunction *fun = callee.getFunctionPrivate();
if (fun->isNative())
break;
script_ = fun->script();
if (!script_->ensureRanAnalysis(cx, fun, callee.getParent()))
return false;
if (FunctionNeedsPrologue(cx, fun) || script_->isEmpty())
break;
/*
* The frame will remain pushed even when the callee isn't active which
* will affect the observable current global, so avoid any change.
*/
if (callee.getGlobal() != GetGlobalForScopeChain(cx))
break;
/* Push the stack frame once for the session. */
if (!stack.pushInvokeFrame(cx, args_, INITIAL_NONE, &ifg_))
return false;
/*
* Update the 'this' type of the callee according to the value given,
* along with the types of any missing arguments. These will be the
* same across all calls.
*/
TypeScript::SetThis(cx, script_, thisv);
for (unsigned i = argc; i < fun->nargs; i++)
TypeScript::SetArgument(cx, script_, i, types::Type::UndefinedType());
StackFrame *fp = ifg_.fp();
#ifdef JS_METHODJIT
/* Hoist dynamic checks from RunScript. */
mjit::CompileStatus status = mjit::CanMethodJIT(cx, script_, false,
mjit::CompileRequest_JIT);
if (status == mjit::Compile_Error)
return false;
if (status != mjit::Compile_Okay)
break;
/* Cannot also cache the raw code pointer; it can change. */
/* Hoist dynamic checks from CheckStackAndEnterMethodJIT. */
JS_CHECK_RECURSION(cx, return false);
stackLimit_ = stack.space().getStackLimit(cx, REPORT_ERROR);
if (!stackLimit_)
return false;
stop_ = script_->code + script_->length - 1;
JS_ASSERT(*stop_ == JSOP_STOP);
#endif
/* Cached to avoid canonicalActualArg in InvokeSessionGuard::operator[]. */
nformals_ = fp->numFormalArgs();
formals_ = fp->formalArgs();
actuals_ = args_.argv();
JS_ASSERT(actuals_ == fp->actualArgs());
return true;
} while (0);
/*
* Use the normal invoke path.
*
* The callee slot gets overwritten during an unoptimized Invoke, so we
* cache it here and restore it before every Invoke call. The 'this' value
* does not get overwritten, so we can fill it here once.
*/
if (ifg_.pushed())
ifg_.pop();
formals_ = actuals_ = args_.argv();
nformals_ = (unsigned)-1;
return true;
}
bool
js::Invoke(JSContext *cx, const Value &thisv, const Value &fval, uintN argc, Value *argv,
Value *rval)

View File

@ -71,127 +71,6 @@ class AutoPreserveEnumerators {
}
};
class InvokeSessionGuard
{
InvokeArgsGuard args_;
InvokeFrameGuard ifg_;
Value savedCallee_, savedThis_;
Value *formals_, *actuals_;
unsigned nformals_;
JSScript *script_;
Value *stackLimit_;
jsbytecode *stop_;
bool optimized() const { return ifg_.pushed(); }
public:
InvokeSessionGuard() : args_(), ifg_() {}
~InvokeSessionGuard() {}
bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
bool invoke(JSContext *cx);
bool started() const {
return args_.pushed();
}
Value &operator[](unsigned i) const {
JS_ASSERT(i < argc());
Value &arg = i < nformals_ ? formals_[i] : actuals_[i];
JS_ASSERT_IF(optimized(), &arg == &ifg_.fp()->canonicalActualArg(i));
JS_ASSERT_IF(!optimized(), &arg == &args_[i]);
return arg;
}
uintN argc() const {
return args_.argc();
}
const Value &rval() const {
return optimized() ? ifg_.fp()->returnValue() : args_.rval();
}
};
inline bool
InvokeSessionGuard::invoke(JSContext *cx)
{
/* N.B. Must be kept in sync with Invoke */
/* Refer to canonical (callee, this) for optimized() sessions. */
formals_[-2] = savedCallee_;
formals_[-1] = savedThis_;
/* Prevent spurious accessing-callee-after-rval assert. */
args_.calleeHasBeenReset();
if (!optimized())
return Invoke(cx, args_);
/*
* Update the types of each argument. The 'this' type and missing argument
* types were handled when the invoke session was created.
*/
for (unsigned i = 0; i < Min(argc(), nformals_); i++)
types::TypeScript::SetArgument(cx, script_, i, (*this)[i]);
#ifdef JS_METHODJIT
mjit::JITScript *jit = script_->getJIT(false /* !constructing */);
if (!jit) {
/* Watch in case the code was thrown away due a recompile. */
mjit::CompileStatus status = mjit::TryCompile(cx, script_, false);
if (status == mjit::Compile_Error)
return false;
JS_ASSERT(status == mjit::Compile_Okay);
jit = script_->getJIT(false);
}
void *code;
if (!(code = jit->invokeEntry))
return Invoke(cx, args_);
#endif
StackFrame *fp = ifg_.fp();
/*
* Clear any activation objects on the frame. Normally the frame should not
* have any, but since we leave it on the stack between calls to invoke()
* the debugger can start operating on it. See markFunctionEpilogueDone()
* calls below. :XXX: this is pretty gross, and slows us down. Can the
* debugger be prevented from observing this frame?
*/
fp->functionEpilogue(/* activationOnly = */ true);
fp->markFunctionEpilogueDone(/* activationOnly = */ true);
fp->resetCallFrame(script_);
JSBool ok;
{
AutoPreserveEnumerators preserve(cx);
args_.setActive(); /* From js::Invoke(InvokeArgsGuard) overload. */
Probes::enterJSFun(cx, fp->fun(), script_);
#ifdef JS_METHODJIT
ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_, /* partial = */ false);
cx->regs().pc = stop_;
#else
cx->regs().pc = script_->code;
ok = Interpret(cx, cx->fp());
/* Interpret does not perform the entry frame's epilogue, unlike EnterMethodJIT. */
cx->fp()->functionEpilogue();
#endif
Probes::exitJSFun(cx, fp->fun(), script_);
args_.setInactive();
}
/*
* Clear activation object flags, for the functionEpilogue() call in the
* next invoke().
*/
fp->markFunctionEpilogueDone(/* activationOnly = */ true);
/* Don't clobber callee with rval; rval gets read from fp->rval. */
return ok;
}
namespace detail {
template<typename T> class PrimitiveBehavior { };