зеркало из https://github.com/mozilla/gecko-dev.git
Bug 902508 - Try to recover type sets for the initial values of arguments during Ion compilation, r=jandem.
This commit is contained in:
Родитель
539558980d
Коммит
d29e980958
|
@ -22,7 +22,8 @@ using namespace js;
|
||||||
using namespace js::ion;
|
using namespace js::ion;
|
||||||
|
|
||||||
BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
|
BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
|
||||||
: BaselineCompilerSpecific(cx, script)
|
: BaselineCompilerSpecific(cx, script),
|
||||||
|
modifiesArguments_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +189,9 @@ BaselineCompiler::compile()
|
||||||
ImmWord(uintptr_t(-1)));
|
ImmWord(uintptr_t(-1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (modifiesArguments_)
|
||||||
|
baselineScript->setModifiesArguments();
|
||||||
|
|
||||||
// All barriers are emitted off-by-default, toggle them on if needed.
|
// All barriers are emitted off-by-default, toggle them on if needed.
|
||||||
if (cx->zone()->needsBarrier())
|
if (cx->zone()->needsBarrier())
|
||||||
baselineScript->toggleBarriers(true);
|
baselineScript->toggleBarriers(true);
|
||||||
|
@ -2192,6 +2196,8 @@ BaselineCompiler::emit_JSOP_CALLARG()
|
||||||
bool
|
bool
|
||||||
BaselineCompiler::emit_JSOP_SETARG()
|
BaselineCompiler::emit_JSOP_SETARG()
|
||||||
{
|
{
|
||||||
|
modifiesArguments_ = true;
|
||||||
|
|
||||||
uint32_t arg = GET_SLOTNO(pc);
|
uint32_t arg = GET_SLOTNO(pc);
|
||||||
return emitFormalArgAccess(arg, /* get = */ false);
|
return emitFormalArgAccess(arg, /* get = */ false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,9 @@ class BaselineCompiler : public BaselineCompilerSpecific
|
||||||
// Native code offset right before the scope chain is initialized.
|
// Native code offset right before the scope chain is initialized.
|
||||||
CodeOffsetLabel prologueOffset_;
|
CodeOffsetLabel prologueOffset_;
|
||||||
|
|
||||||
|
// Whether any on stack arguments are modified.
|
||||||
|
bool modifiesArguments_;
|
||||||
|
|
||||||
Label *labelOf(jsbytecode *pc) {
|
Label *labelOf(jsbytecode *pc) {
|
||||||
return &labels_[pc - script->code];
|
return &labels_[pc - script->code];
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,11 @@ struct BaselineScript
|
||||||
|
|
||||||
// Flag set when discarding JIT code, to indicate this script is
|
// Flag set when discarding JIT code, to indicate this script is
|
||||||
// on the stack and should not be discarded.
|
// on the stack and should not be discarded.
|
||||||
ACTIVE = 1 << 1
|
ACTIVE = 1 << 1,
|
||||||
|
|
||||||
|
// Flag set when the script contains any writes to its on-stack
|
||||||
|
// (rather than call object stored) arguments.
|
||||||
|
MODIFIES_ARGUMENTS = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -181,6 +185,13 @@ struct BaselineScript
|
||||||
flags_ |= NEEDS_ARGS_OBJ;
|
flags_ |= NEEDS_ARGS_OBJ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setModifiesArguments() {
|
||||||
|
flags_ |= MODIFIES_ARGUMENTS;
|
||||||
|
}
|
||||||
|
bool modifiesArguments() {
|
||||||
|
return flags_ & MODIFIES_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t prologueOffset() const {
|
uint32_t prologueOffset() const {
|
||||||
return prologueOffset_;
|
return prologueOffset_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -803,13 +803,27 @@ IonBuilder::initParameters()
|
||||||
if (!info().fun())
|
if (!info().fun())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
MParameter *param = MParameter::New(MParameter::THIS_SLOT,
|
// If we are doing OSR on a frame which initially executed in the
|
||||||
cloneTypeSet(types::TypeScript::ThisTypes(script())));
|
// interpreter and didn't accumulate type information, try to use that OSR
|
||||||
|
// frame to determine possible initial types for 'this' and parameters.
|
||||||
|
|
||||||
|
types::StackTypeSet *thisTypes = types::TypeScript::ThisTypes(script());
|
||||||
|
if (thisTypes->empty() && baselineFrame_)
|
||||||
|
thisTypes->addType(cx, types::GetValueType(cx, baselineFrame_->thisValue()));
|
||||||
|
|
||||||
|
MParameter *param = MParameter::New(MParameter::THIS_SLOT, cloneTypeSet(thisTypes));
|
||||||
current->add(param);
|
current->add(param);
|
||||||
current->initSlot(info().thisSlot(), param);
|
current->initSlot(info().thisSlot(), param);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < info().nargs(); i++) {
|
for (uint32_t i = 0; i < info().nargs(); i++) {
|
||||||
param = MParameter::New(i, cloneTypeSet(types::TypeScript::ArgTypes(script(), i)));
|
types::StackTypeSet *argTypes = types::TypeScript::ArgTypes(script(), i);
|
||||||
|
if (argTypes->empty() && baselineFrame_ &&
|
||||||
|
!script_->baselineScript()->modifiesArguments())
|
||||||
|
{
|
||||||
|
argTypes->addType(cx, types::GetValueType(cx, baselineFrame_->argv()[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
param = MParameter::New(i, cloneTypeSet(argTypes));
|
||||||
current->add(param);
|
current->add(param);
|
||||||
current->initSlot(info().argSlotUnchecked(i), param);
|
current->initSlot(info().argSlotUnchecked(i), param);
|
||||||
}
|
}
|
||||||
|
@ -1279,7 +1293,35 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||||
// convert all arg accesses to go through the arguments object.
|
// convert all arg accesses to go through the arguments object.
|
||||||
if (info().hasArguments())
|
if (info().hasArguments())
|
||||||
return abort("NYI: arguments & setarg.");
|
return abort("NYI: arguments & setarg.");
|
||||||
current->setArg(GET_SLOTNO(pc));
|
|
||||||
|
int32_t arg = GET_SLOTNO(pc);
|
||||||
|
|
||||||
|
// If this assignment is at the start of the function and is coercing
|
||||||
|
// the original value for the argument which was passed in, loosen
|
||||||
|
// the type information for that original argument if it is currently
|
||||||
|
// empty due to originally executing in the interpreter.
|
||||||
|
MDefinition *value = current->peek(-1);
|
||||||
|
if (graph().numBlocks() == 1 &&
|
||||||
|
(value->isBitOr() || value->isBitAnd() || value->isMul() /* for JSOP_POS */))
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < value->numOperands(); i++) {
|
||||||
|
MDefinition *op = value->getOperand(i);
|
||||||
|
if (op->isParameter() &&
|
||||||
|
op->toParameter()->index() == arg &&
|
||||||
|
op->resultTypeSet() &&
|
||||||
|
op->resultTypeSet()->empty())
|
||||||
|
{
|
||||||
|
types::TypeSet *argTypes = types::TypeScript::ArgTypes(script(), arg);
|
||||||
|
|
||||||
|
// During parallel compilation the parameter's type set
|
||||||
|
// will be a clone of the actual argument type set.
|
||||||
|
argTypes->addType(cx, types::Type::UnknownType());
|
||||||
|
op->resultTypeSet()->addType(cx, types::Type::UnknownType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current->setArg(arg);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -2494,6 +2494,8 @@ BEGIN_CASE(JSOP_FUNCALL)
|
||||||
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
|
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
|
||||||
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
||||||
|
|
||||||
|
TypeMonitorCall(cx, args, construct);
|
||||||
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
InvokeState state(cx, args, initial);
|
InvokeState state(cx, args, initial);
|
||||||
if (newType)
|
if (newType)
|
||||||
|
@ -2526,8 +2528,6 @@ BEGIN_CASE(JSOP_FUNCALL)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TypeMonitorCall(cx, args, construct);
|
|
||||||
|
|
||||||
funScript = fun->nonLazyScript();
|
funScript = fun->nonLazyScript();
|
||||||
if (!activation.pushInlineFrame(args, funScript, initial))
|
if (!activation.pushInlineFrame(args, funScript, initial))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче