Backed out 3 changesets (bug 939581) to see if it fixes the apparently permanent rootanalysis orange

Backed out changeset 6034450c8684 (bug 939581)
Backed out changeset 6badd39e9d6f (bug 939581)
Backed out changeset 4abc092e62c5 (bug 939581)
This commit is contained in:
Wes Kocher 2014-01-03 18:23:45 -08:00
Родитель 4d93bc9db0
Коммит ce414466c8
7 изменённых файлов: 71 добавлений и 181 удалений

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

@ -6391,16 +6391,8 @@ class CGMemberJITInfo(CGThing):
# one of them must take arguments.
methodInfal = False
args = None
movable = False
else:
sig = sigs[0]
# For pure methods, it's OK to set movable to our notion of
# infallible on the C++ side, without considering argument
# conversions, since argument conversions that can reliably
# throw would be effectful anyway and the jit doesn't move
# effectful things.
hasInfallibleImpl = "infallible" in self.descriptor.getExtendedAttributes(self.member)
movable = methodPure and hasInfallibleImpl
# XXXbz can we move the smarts about fallibility due to arg
# conversions into the JIT, using our new args stuff?
if (len(sig[1]) != 0 or
@ -6408,19 +6400,19 @@ class CGMemberJITInfo(CGThing):
# We have arguments or our return-value boxing can fail
methodInfal = False
else:
methodInfal = hasInfallibleImpl
methodInfal = "infallible" in self.descriptor.getExtendedAttributes(self.member)
# For now, only bother to output args if we're pure
if methodPure:
args = sig[1]
else:
args = None
if args is not None:
if args:
aliasSet = "AliasDOMSets"
else:
aliasSet = "AliasEverything"
result = self.defineJitInfo(methodinfo, method, "Method",
methodInfal, movable, aliasSet, False, "0",
methodInfal, False, aliasSet, False, "0",
[s[0] for s in sigs], args)
return result
raise TypeError("Illegal member type to CGPropertyJITInfo")

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

@ -1781,7 +1781,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative *call)
JS_ASSERT(target);
JS_ASSERT(target->isNative());
JS_ASSERT(target->jitInfo());
JS_ASSERT(call->mir()->isCallDOMNative());
JS_ASSERT(call->mir()->isDOMFunction());
int callargslot = call->argslot();
int unusedStack = StackOffsetOfPassedArg(callargslot);

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

@ -5170,22 +5170,8 @@ IonBuilder::makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtC
if (target && !target->isNative())
targetArgs = Max<uint32_t>(target->nargs(), callInfo.argc());
bool isDOMCall = false;
if (target && !callInfo.constructing()) {
// We know we have a single call target. Check whether the "this" types
// are DOM types and our function a DOM function, and if so flag the
// MCall accordingly.
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
if (thisTypes &&
thisTypes->isDOMClass() &&
testShouldDOMCall(thisTypes, target, JSJitInfo::Method))
{
isDOMCall = true;
}
}
MCall *call = MCall::New(alloc(), target, targetArgs + 1, callInfo.argc(),
callInfo.constructing(), isDOMCall);
MCall *call =
MCall::New(alloc(), target, targetArgs + 1, callInfo.argc(), callInfo.constructing());
if (!call)
return nullptr;
@ -5202,9 +5188,6 @@ IonBuilder::makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtC
for (int32_t i = callInfo.argc() - 1; i >= 0; i--)
call->addArg(i + 1, callInfo.getArg(i));
// Now that we've told it about all the args, compute whether it's movable
call->computeMovable();
// Inline the constructor on the caller-side.
if (callInfo.constructing()) {
MDefinition *create = createThis(target, callInfo.fun());
@ -5228,6 +5211,19 @@ IonBuilder::makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtC
callInfo.setFun(fun);
}
if (target && JSOp(*pc) == JSOP_CALL) {
// We know we have a single call target. Check whether the "this" types
// are DOM types and our function a DOM function, and if so flag the
// MCall accordingly.
types::TemporaryTypeSet *thisTypes = thisArg->resultTypeSet();
if (thisTypes &&
thisTypes->isDOMClass() &&
testShouldDOMCall(thisTypes, target, JSJitInfo::Method))
{
call->setDOMFunction();
}
}
if (target && !testNeedsArgumentCheck(target, callInfo))
call->disableArgCheck();
@ -5267,12 +5263,12 @@ IonBuilder::makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsit
return false;
current->push(call);
if (call->isEffectful() && !resumeAfter(call))
if (!resumeAfter(call))
return false;
types::TemporaryTypeSet *types = bytecodeTypes(pc);
if (call->isCallDOMNative())
if (call->isDOMFunction())
return pushDOMTypeBarrier(call, types, call->getSingleTarget());
return pushTypeBarrier(call, types, true);

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

@ -408,7 +408,7 @@ LIRGenerator::visitCall(MCall *call)
JSFunction *target = call->getSingleTarget();
// Call DOM functions.
if (call->isCallDOMNative()) {
if (call->isDOMFunction()) {
JS_ASSERT(target && target->isNative());
Register cxReg, objReg, privReg, argsReg;
GetTempRegForIntArg(0, 0, &cxReg);

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

@ -648,120 +648,15 @@ MParameter::congruentTo(MDefinition *ins) const
MCall *
MCall::New(TempAllocator &alloc, JSFunction *target, size_t maxArgc, size_t numActualArgs,
bool construct, bool isDOMCall)
bool construct)
{
JS_ASSERT(maxArgc >= numActualArgs);
MCall *ins;
if (isDOMCall) {
JS_ASSERT(!construct);
ins = new(alloc) MCallDOMNative(target, numActualArgs);
} else {
ins = new(alloc) MCall(target, numActualArgs, construct);
}
MCall *ins = new(alloc) MCall(target, numActualArgs, construct);
if (!ins->init(alloc, maxArgc + NumNonArgumentOperands))
return nullptr;
return ins;
}
AliasSet
MCallDOMNative::getAliasSet() const
{
JS_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
const JSJitInfo *jitInfo = getSingleTarget()->jitInfo();
JS_ASSERT(jitInfo);
JS_ASSERT(jitInfo->aliasSet != JSJitInfo::AliasNone);
// If we don't know anything about the types of our arguments, we have to
// assume that type-coercions can have side-effects, so we need to alias
// everything.
if (jitInfo->aliasSet != JSJitInfo::AliasDOMSets || !jitInfo->argTypes)
return AliasSet::Store(AliasSet::Any);
uint32_t argIndex = 0;
for (const JSJitInfo::ArgType *argType = jitInfo->argTypes;
*argType != JSJitInfo::ArgTypeListEnd;
++argType, ++argIndex)
{
if (argIndex >= numActualArgs()) {
// Passing through undefined can't have side-effects
continue;
}
// getArg(0) is "this", so skip it
MDefinition *arg = getArg(argIndex+1);
MIRType actualType = arg->type();
// The only way to reliably avoid side-effects given the informtion we
// have here is if we're passing in a known primitive value to an
// argument that expects a primitive value. XXXbz maybe we need to
// communicate better information. For example, a sequence argument
// will sort of unavoidably have side effects, while a typed array
// argument won't have any, but both are claimed to be
// JSJitInfo::Object.
if ((actualType == MIRType_Value || actualType == MIRType_Object) ||
(*argType & JSJitInfo::Object))
{
return AliasSet::Store(AliasSet::Any);
}
}
// We checked all the args, and they check out. So we only
// alias DOM mutations.
return AliasSet::Load(AliasSet::DOMProperty);
}
void
MCallDOMNative::computeMovable()
{
// We are movable if the jitinfo says we can be and if we're also not
// effectful. The jitinfo can't check for the latter, since it depends on
// the types of our arguments.
JS_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
const JSJitInfo *jitInfo = getSingleTarget()->jitInfo();
JS_ASSERT(jitInfo);
JS_ASSERT_IF(jitInfo->isMovable,
jitInfo->aliasSet != JSJitInfo::AliasEverything);
if (jitInfo->isMovable && !isEffectful())
setMovable();
}
bool
MCallDOMNative::congruentTo(MDefinition *ins) const
{
if (!isMovable())
return false;
if (!ins->isCall())
return false;
MCall *call = ins->toCall();
if (!call->isCallDOMNative())
return false;
if (getSingleTarget() != call->getSingleTarget())
return false;
if (isConstructing() != call->isConstructing())
return false;
if (numActualArgs() != call->numActualArgs())
return false;
if (needsArgCheck() != call->needsArgCheck())
return false;
if (!congruentIfOperandsEqual(call))
return false;
// The other call had better be movable at this point!
JS_ASSERT(call->isMovable());
return true;
}
MApplyArgs *
MApplyArgs::New(TempAllocator &alloc, JSFunction *target, MDefinition *fun, MDefinition *argc,
MDefinition *self)

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

@ -59,6 +59,8 @@ MIRType MIRTypeFromValue(const js::Value &vp)
* points.
*/ \
_(Unused) \
_(DOMFunction) /* Contains or uses a common DOM method function */ \
\
/* Marks if an instruction has fewer uses than the original code.
* E.g. UCE can remove code.
* Every instruction where an use is/was removed from an instruction and
@ -1804,7 +1806,7 @@ class MCall
public:
INSTRUCTION_HEADER(Call)
static MCall *New(TempAllocator &alloc, JSFunction *target, size_t maxArgc, size_t numActualArgs,
bool construct, bool isDOMCall);
bool construct);
void initFunction(MDefinition *func) {
return setOperand(FunctionOperandIndex, func);
@ -1830,6 +1832,10 @@ class MCall
return getOperand(NumNonArgumentOperands + index);
}
void replaceArg(uint32_t index, MDefinition *def) {
replaceOperand(NumNonArgumentOperands + index, def);
}
static size_t IndexOfThis() {
return NumNonArgumentOperands;
}
@ -1865,48 +1871,49 @@ class MCall
TypePolicy *typePolicy() {
return this;
}
AliasSet getAliasSet() const {
if (isDOMFunction()) {
JS_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
const JSJitInfo* jitInfo = getSingleTarget()->jitInfo();
JS_ASSERT(jitInfo);
JS_ASSERT(jitInfo->aliasSet != JSJitInfo::AliasNone);
if (jitInfo->aliasSet == JSJitInfo::AliasDOMSets &&
jitInfo->argTypes) {
uint32_t argIndex = 0;
for (const JSJitInfo::ArgType* argType = jitInfo->argTypes;
*argType != JSJitInfo::ArgTypeListEnd;
++argType, ++argIndex)
{
if (argIndex >= numActualArgs()) {
// Passing through undefined can't have side-effects
continue;
}
// getArg(0) is "this", so skip it
MDefinition *arg = getArg(argIndex+1);
MIRType actualType = arg->type();
// The only way to get side-effects is if we're passing in
// something that might be an object to an argument that
// expects a numeric, string, or boolean value.
if ((actualType == MIRType_Value || actualType == MIRType_Object) &&
(*argType &
(JSJitInfo::Boolean | JSJitInfo::String | JSJitInfo::Numeric)))
{
return AliasSet::Store(AliasSet::Any);
}
}
// We checked all the args, and they check out. So we only
// alias DOM mutations.
return AliasSet::Load(AliasSet::DOMProperty);
}
}
return AliasSet::Store(AliasSet::Any);
}
bool possiblyCalls() const {
return true;
}
virtual bool isCallDOMNative() const {
return false;
}
// A method that can be called to tell the MCall to figure out whether it's
// movable or not. This can't be done in the constructor, because it
// depends on the arguments to the call, and those aren't passed to the
// constructor but are set up later via addArg.
virtual void computeMovable() {
}
};
class MCallDOMNative : public MCall
{
// A helper class for MCalls for DOM natives. Note that this is NOT
// actually a separate MIR op from MCall, because all sorts of places use
// isCall() to check for calls and all we really want is to overload a few
// virtual things from MCall.
protected:
MCallDOMNative(JSFunction *target, uint32_t numActualArgs)
: MCall(target, numActualArgs, false)
{
}
friend MCall *MCall::New(TempAllocator &alloc, JSFunction *target, size_t maxArgc,
size_t numActualArgs, bool construct, bool isDOMCall);
public:
virtual AliasSet getAliasSet() const MOZ_OVERRIDE;
virtual bool congruentTo(MDefinition *ins) const MOZ_OVERRIDE;
virtual bool isCallDOMNative() const MOZ_OVERRIDE {
return true;
}
virtual void computeMovable() MOZ_OVERRIDE;
};
// fun.apply(self, arguments)

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

@ -697,7 +697,7 @@ bool
ParallelSafetyVisitor::visitCall(MCall *ins)
{
// DOM? Scary.
if (ins->isCallDOMNative()) {
if (ins->isDOMFunction()) {
SpewMIR(ins, "call to dom function");
return markUnsafe();
}