Bug 902508 - Try to recover type sets for the initial values of arguments during Ion compilation, r=jandem.

This commit is contained in:
Brian Hackett 2013-08-13 12:04:40 -06:00
Родитель 539558980d
Коммит d29e980958
5 изменённых файлов: 70 добавлений и 8 удалений

Просмотреть файл

@ -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;