зеркало из 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;
|
||||
|
||||
BaselineCompiler::BaselineCompiler(JSContext *cx, HandleScript script)
|
||||
: BaselineCompilerSpecific(cx, script)
|
||||
: BaselineCompilerSpecific(cx, script),
|
||||
modifiesArguments_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -188,6 +189,9 @@ BaselineCompiler::compile()
|
|||
ImmWord(uintptr_t(-1)));
|
||||
}
|
||||
|
||||
if (modifiesArguments_)
|
||||
baselineScript->setModifiesArguments();
|
||||
|
||||
// All barriers are emitted off-by-default, toggle them on if needed.
|
||||
if (cx->zone()->needsBarrier())
|
||||
baselineScript->toggleBarriers(true);
|
||||
|
@ -2192,6 +2196,8 @@ BaselineCompiler::emit_JSOP_CALLARG()
|
|||
bool
|
||||
BaselineCompiler::emit_JSOP_SETARG()
|
||||
{
|
||||
modifiesArguments_ = true;
|
||||
|
||||
uint32_t arg = GET_SLOTNO(pc);
|
||||
return emitFormalArgAccess(arg, /* get = */ false);
|
||||
}
|
||||
|
|
|
@ -185,6 +185,9 @@ class BaselineCompiler : public BaselineCompilerSpecific
|
|||
// Native code offset right before the scope chain is initialized.
|
||||
CodeOffsetLabel prologueOffset_;
|
||||
|
||||
// Whether any on stack arguments are modified.
|
||||
bool modifiesArguments_;
|
||||
|
||||
Label *labelOf(jsbytecode *pc) {
|
||||
return &labels_[pc - script->code];
|
||||
}
|
||||
|
|
|
@ -124,7 +124,11 @@ struct BaselineScript
|
|||
|
||||
// Flag set when discarding JIT code, to indicate this script is
|
||||
// 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:
|
||||
|
@ -181,6 +185,13 @@ struct BaselineScript
|
|||
flags_ |= NEEDS_ARGS_OBJ;
|
||||
}
|
||||
|
||||
void setModifiesArguments() {
|
||||
flags_ |= MODIFIES_ARGUMENTS;
|
||||
}
|
||||
bool modifiesArguments() {
|
||||
return flags_ & MODIFIES_ARGUMENTS;
|
||||
}
|
||||
|
||||
uint32_t prologueOffset() const {
|
||||
return prologueOffset_;
|
||||
}
|
||||
|
|
|
@ -803,13 +803,27 @@ IonBuilder::initParameters()
|
|||
if (!info().fun())
|
||||
return true;
|
||||
|
||||
MParameter *param = MParameter::New(MParameter::THIS_SLOT,
|
||||
cloneTypeSet(types::TypeScript::ThisTypes(script())));
|
||||
// If we are doing OSR on a frame which initially executed in the
|
||||
// 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->initSlot(info().thisSlot(), param);
|
||||
|
||||
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->initSlot(info().argSlotUnchecked(i), param);
|
||||
}
|
||||
|
@ -1279,7 +1293,35 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
// convert all arg accesses to go through the arguments object.
|
||||
if (info().hasArguments())
|
||||
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;
|
||||
|
||||
|
|
|
@ -2494,6 +2494,8 @@ BEGIN_CASE(JSOP_FUNCALL)
|
|||
InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
|
||||
bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
|
||||
|
||||
TypeMonitorCall(cx, args, construct);
|
||||
|
||||
#ifdef JS_ION
|
||||
InvokeState state(cx, args, initial);
|
||||
if (newType)
|
||||
|
@ -2526,8 +2528,6 @@ BEGIN_CASE(JSOP_FUNCALL)
|
|||
}
|
||||
#endif
|
||||
|
||||
TypeMonitorCall(cx, args, construct);
|
||||
|
||||
funScript = fun->nonLazyScript();
|
||||
if (!activation.pushInlineFrame(args, funScript, initial))
|
||||
goto error;
|
||||
|
|
Загрузка…
Ссылка в новой задаче