зеркало из https://github.com/mozilla/gecko-dev.git
Bug 939581 part 3. Mark DOM calls as movable as needed and allow them to be CSE'd. r=efaust
This commit is contained in:
Родитель
0a6e649aa0
Коммит
b1083f6892
|
@ -6391,8 +6391,16 @@ class CGMemberJITInfo(CGThing):
|
||||||
# one of them must take arguments.
|
# one of them must take arguments.
|
||||||
methodInfal = False
|
methodInfal = False
|
||||||
args = None
|
args = None
|
||||||
|
movable = False
|
||||||
else:
|
else:
|
||||||
sig = sigs[0]
|
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
|
# XXXbz can we move the smarts about fallibility due to arg
|
||||||
# conversions into the JIT, using our new args stuff?
|
# conversions into the JIT, using our new args stuff?
|
||||||
if (len(sig[1]) != 0 or
|
if (len(sig[1]) != 0 or
|
||||||
|
@ -6400,19 +6408,19 @@ class CGMemberJITInfo(CGThing):
|
||||||
# We have arguments or our return-value boxing can fail
|
# We have arguments or our return-value boxing can fail
|
||||||
methodInfal = False
|
methodInfal = False
|
||||||
else:
|
else:
|
||||||
methodInfal = "infallible" in self.descriptor.getExtendedAttributes(self.member)
|
methodInfal = hasInfallibleImpl
|
||||||
# For now, only bother to output args if we're pure
|
# For now, only bother to output args if we're pure
|
||||||
if methodPure:
|
if methodPure:
|
||||||
args = sig[1]
|
args = sig[1]
|
||||||
else:
|
else:
|
||||||
args = None
|
args = None
|
||||||
|
|
||||||
if args:
|
if args is not None:
|
||||||
aliasSet = "AliasDOMSets"
|
aliasSet = "AliasDOMSets"
|
||||||
else:
|
else:
|
||||||
aliasSet = "AliasEverything"
|
aliasSet = "AliasEverything"
|
||||||
result = self.defineJitInfo(methodinfo, method, "Method",
|
result = self.defineJitInfo(methodinfo, method, "Method",
|
||||||
methodInfal, False, aliasSet, False, "0",
|
methodInfal, movable, aliasSet, False, "0",
|
||||||
[s[0] for s in sigs], args)
|
[s[0] for s in sigs], args)
|
||||||
return result
|
return result
|
||||||
raise TypeError("Illegal member type to CGPropertyJITInfo")
|
raise TypeError("Illegal member type to CGPropertyJITInfo")
|
||||||
|
|
|
@ -5202,6 +5202,9 @@ IonBuilder::makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtC
|
||||||
for (int32_t i = callInfo.argc() - 1; i >= 0; i--)
|
for (int32_t i = callInfo.argc() - 1; i >= 0; i--)
|
||||||
call->addArg(i + 1, callInfo.getArg(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.
|
// Inline the constructor on the caller-side.
|
||||||
if (callInfo.constructing()) {
|
if (callInfo.constructing()) {
|
||||||
MDefinition *create = createThis(target, callInfo.fun());
|
MDefinition *create = createThis(target, callInfo.fun());
|
||||||
|
|
|
@ -690,12 +690,15 @@ MCallDOMNative::getAliasSet() const
|
||||||
// getArg(0) is "this", so skip it
|
// getArg(0) is "this", so skip it
|
||||||
MDefinition *arg = getArg(argIndex+1);
|
MDefinition *arg = getArg(argIndex+1);
|
||||||
MIRType actualType = arg->type();
|
MIRType actualType = arg->type();
|
||||||
// The only way to get side-effects is if we're passing in
|
// The only way to reliably avoid side-effects given the informtion we
|
||||||
// something that might be an object to an argument that
|
// have here is if we're passing in a known primitive value to an
|
||||||
// expects a numeric, string, or boolean value.
|
// argument that expects a primitive value. XXXbz maybe we need to
|
||||||
if ((actualType == MIRType_Value || actualType == MIRType_Object) &&
|
// communicate better information. For example, a sequence argument
|
||||||
(*argType &
|
// will sort of unavoidably have side effects, while a typed array
|
||||||
(JSJitInfo::Boolean | JSJitInfo::String | JSJitInfo::Numeric)))
|
// 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);
|
return AliasSet::Store(AliasSet::Any);
|
||||||
}
|
}
|
||||||
|
@ -706,6 +709,59 @@ MCallDOMNative::getAliasSet() const
|
||||||
return AliasSet::Load(AliasSet::DOMProperty);
|
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 *
|
||||||
MApplyArgs::New(TempAllocator &alloc, JSFunction *target, MDefinition *fun, MDefinition *argc,
|
MApplyArgs::New(TempAllocator &alloc, JSFunction *target, MDefinition *fun, MDefinition *argc,
|
||||||
MDefinition *self)
|
MDefinition *self)
|
||||||
|
|
|
@ -1830,10 +1830,6 @@ class MCall
|
||||||
return getOperand(NumNonArgumentOperands + index);
|
return getOperand(NumNonArgumentOperands + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceArg(uint32_t index, MDefinition *def) {
|
|
||||||
replaceOperand(NumNonArgumentOperands + index, def);
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t IndexOfThis() {
|
static size_t IndexOfThis() {
|
||||||
return NumNonArgumentOperands;
|
return NumNonArgumentOperands;
|
||||||
}
|
}
|
||||||
|
@ -1877,6 +1873,13 @@ class MCall
|
||||||
virtual bool isCallDOMNative() const {
|
virtual bool isCallDOMNative() const {
|
||||||
return false;
|
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
|
class MCallDOMNative : public MCall
|
||||||
|
@ -1897,9 +1900,13 @@ class MCallDOMNative : public MCall
|
||||||
public:
|
public:
|
||||||
virtual AliasSet getAliasSet() const MOZ_OVERRIDE;
|
virtual AliasSet getAliasSet() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool congruentTo(MDefinition *ins) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool isCallDOMNative() const MOZ_OVERRIDE {
|
virtual bool isCallDOMNative() const MOZ_OVERRIDE {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void computeMovable() MOZ_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// fun.apply(self, arguments)
|
// fun.apply(self, arguments)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче