зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central and mozilla-inbound
This commit is contained in:
Коммит
c0b6dfafe8
|
@ -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)
|
||||
|
|
|
@ -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 { };
|
||||
|
|
Загрузка…
Ссылка в новой задаче