Bug 844253 - Change useNewType to be a flag on StackFrame instead of an explicitly passed argument. r=bhackett

This commit is contained in:
Kannan Vijayan 2013-02-25 00:57:39 -05:00
parent 23730fbeba
commit 259242f46c
8 changed files with 54 additions and 21 deletions

View File

@ -1472,8 +1472,7 @@ ion::CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp,
}
MethodStatus
ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
bool isConstructing, bool newType)
ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing)
{
JS_ASSERT(ion::IsEnabled(cx));
@ -1495,7 +1494,7 @@ ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
if (isConstructing && fp.thisValue().isPrimitive()) {
RootedScript scriptRoot(cx, script);
RootedObject callee(cx, &fp.callee());
RootedObject obj(cx, CreateThisForFunction(cx, callee, newType));
RootedObject obj(cx, CreateThisForFunction(cx, callee, fp.useNewType()));
if (!obj)
return Method_Skipped;
fp.thisValue().setObject(*obj);

View File

@ -261,8 +261,7 @@ bool SetIonContext(IonContext *ctx);
MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script,
AbstractFramePtr fp, jsbytecode *pc, bool isConstructing);
MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp,
bool isConstructing, bool newType);
MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing);
MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs);
enum IonExecStatus

View File

@ -276,6 +276,20 @@ js::RunScript(JSContext *cx, StackFrame *fp)
JS_CHECK_RECURSION(cx, return false);
// Check to see if useNewType flag should be set for this frame.
if (fp->isFunctionFrame() && fp->isConstructing() && !fp->isGeneratorFrame()) {
StackIter iter(cx);
if (!iter.done()) {
++iter;
if (iter.isScript()) {
RawScript script = iter.script();
jsbytecode *pc = iter.pc();
if (UseNewType(cx, script, pc))
fp->setUseNewType();
}
}
}
#ifdef DEBUG
struct CheckStackBalance {
JSContext *cx;
@ -294,7 +308,7 @@ js::RunScript(JSContext *cx, StackFrame *fp)
#ifdef JS_ION
if (ion::IsEnabled(cx)) {
ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(fp),
fp->isConstructing(), false);
fp->isConstructing());
if (status == ion::Method_Error)
return false;
if (status == ion::Method_Compiled) {
@ -1159,7 +1173,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
if (interpMode == JSINTERP_NORMAL) {
StackFrame *fp = regs.fp();
if (!fp->isGeneratorFrame()) {
if (!fp->prologue(cx, UseNewTypeAtEntry(cx, fp)))
if (!fp->prologue(cx))
goto error;
} else {
Probes::enterScript(cx, script, script->function(), fp);
@ -2361,6 +2375,9 @@ BEGIN_CASE(JSOP_FUNCALL)
funScript = fun->nonLazyScript();
if (!cx->stack.pushInlineFrame(cx, regs, args, fun, funScript, initial))
goto error;
if (newType)
regs.fp()->setUseNewType();
SET_SCRIPT(regs.fp()->script());
#ifdef JS_METHODJIT
@ -2370,7 +2387,7 @@ BEGIN_CASE(JSOP_FUNCALL)
#ifdef JS_ION
if (!newType && ion::IsEnabled(cx)) {
ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(regs.fp()),
regs.fp()->isConstructing(), newType);
regs.fp()->isConstructing());
if (status == ion::Method_Error)
goto error;
if (status == ion::Method_Compiled) {
@ -2405,7 +2422,7 @@ BEGIN_CASE(JSOP_FUNCALL)
}
#endif
if (!regs.fp()->prologue(cx, newType))
if (!regs.fp()->prologue(cx))
goto error;
if (cx->compartment->debugMode()) {
switch (ScriptDebugPrologue(cx, regs.fp())) {

View File

@ -940,7 +940,9 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
return js_InternalThrow(f);
fp->initVarsToUndefined();
fp->scopeChain();
if (!fp->prologue(cx, types::UseNewTypeAtEntry(cx, fp)))
if (types::UseNewTypeAtEntry(cx, fp))
fp->setUseNewType();
if (!fp->prologue(cx))
return js_InternalThrow(f);
/*

View File

@ -808,8 +808,7 @@ stubs::TriggerIonCompile(VMFrame &f)
compileStatus = ion::CanEnterAtBranch(f.cx, script, f.cx->fp(), osrPC,
f.fp()->isConstructing());
} else {
compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing(),
/* newType = */ false);
compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing());
}
if (compileStatus != ion::Method_Compiled) {

View File

@ -738,6 +738,13 @@ AbstractFramePtr::hasCallObj() const
return false;
}
inline bool
AbstractFramePtr::useNewType() const
{
if (isStackFrame())
return asStackFrame()->useNewType();
return false;
}
inline bool
AbstractFramePtr::isGeneratorFrame() const
{
if (isStackFrame())

View File

@ -307,7 +307,7 @@ StackFrame::initFunctionScopeObjects(JSContext *cx)
}
bool
StackFrame::prologue(JSContext *cx, bool newType)
StackFrame::prologue(JSContext *cx)
{
RootedScript script(cx, this->script());
@ -339,7 +339,7 @@ StackFrame::prologue(JSContext *cx, bool newType)
if (isConstructing()) {
RootedObject callee(cx, &this->callee());
JSObject *obj = CreateThisForFunction(cx, callee, newType);
JSObject *obj = CreateThisForFunction(cx, callee, useNewType());
if (!obj)
return false;
functionThis() = ObjectValue(*obj);

View File

@ -297,6 +297,7 @@ class AbstractFramePtr
inline bool hasArgsObj() const;
inline ArgumentsObject &argsObj() const;
inline void initArgsObj(ArgumentsObject &argsobj) const;
inline bool useNewType() const;
inline bool copyRawFrameSlots(AutoValueVector *vec) const;
@ -389,10 +390,13 @@ class StackFrame
HAS_PUSHED_SPS_FRAME = 0x100000, /* SPS was notified of enty */
/* Ion frame state */
RUNNING_IN_ION = 0x200000, /* frame is running in Ion */
CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */
RUNNING_IN_ION = 0x200000, /* frame is running in Ion */
CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */
JIT_REVISED_STACK = 0x800000 /* sp was revised by JIT for lowered apply */
JIT_REVISED_STACK = 0x800000, /* sp was revised by JIT for lowered apply */
/* Miscellaneous state. */
USE_NEW_TYPE = 0x1000000 /* Use new type for constructed |this| object. */
};
private:
@ -489,12 +493,9 @@ class StackFrame
* over-recursed) after pushing the stack frame but before 'prologue' is
* called or completes fully. To simplify usage, 'epilogue' does not assume
* 'prologue' has completed and handles all the intermediate state details.
*
* The 'newType' option indicates whether the constructed 'this' value (if
* there is one) should be given a new singleton type.
*/
bool prologue(JSContext *cx, bool newType);
bool prologue(JSContext *cx);
void epilogue(JSContext *cx);
/* Subsets of 'prologue' called from jit code. */
@ -1052,6 +1053,15 @@ class StackFrame
return flags_ & HAS_ARGS_OBJ;
}
void setUseNewType() {
JS_ASSERT(isConstructing());
flags_ |= USE_NEW_TYPE;
}
bool useNewType() const {
JS_ASSERT(isConstructing());
return flags_ & USE_NEW_TYPE;
}
/*
* The method JIT call/apply optimization can erase Function.{call,apply}
* invocations from the stack and push the callee frame directly. The base