зеркало из https://github.com/mozilla/gecko-dev.git
Bug 939581 part 1. Factor out MCallDOMNative from MCall. r=efaust,jandem
This commit is contained in:
Родитель
f98a8d58d2
Коммит
5d40f3015e
|
@ -1781,7 +1781,7 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative *call)
|
|||
JS_ASSERT(target);
|
||||
JS_ASSERT(target->isNative());
|
||||
JS_ASSERT(target->jitInfo());
|
||||
JS_ASSERT(call->mir()->isDOMFunction());
|
||||
JS_ASSERT(call->mir()->isCallDOMNative());
|
||||
|
||||
int callargslot = call->argslot();
|
||||
int unusedStack = StackOffsetOfPassedArg(callargslot);
|
||||
|
|
|
@ -5170,8 +5170,22 @@ IonBuilder::makeCallHelper(JSFunction *target, CallInfo &callInfo, bool cloneAtC
|
|||
if (target && !target->isNative())
|
||||
targetArgs = Max<uint32_t>(target->nargs(), callInfo.argc());
|
||||
|
||||
MCall *call =
|
||||
MCall::New(alloc(), target, targetArgs + 1, callInfo.argc(), callInfo.constructing());
|
||||
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);
|
||||
if (!call)
|
||||
return nullptr;
|
||||
|
||||
|
@ -5211,19 +5225,6 @@ 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();
|
||||
|
||||
|
@ -5268,7 +5269,7 @@ IonBuilder::makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsit
|
|||
|
||||
types::TemporaryTypeSet *types = bytecodeTypes(pc);
|
||||
|
||||
if (call->isDOMFunction())
|
||||
if (call->isCallDOMNative())
|
||||
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->isDOMFunction()) {
|
||||
if (call->isCallDOMNative()) {
|
||||
JS_ASSERT(target && target->isNative());
|
||||
Register cxReg, objReg, privReg, argsReg;
|
||||
GetTempRegForIntArg(0, 0, &cxReg);
|
||||
|
|
|
@ -648,15 +648,64 @@ MParameter::congruentTo(MDefinition *ins) const
|
|||
|
||||
MCall *
|
||||
MCall::New(TempAllocator &alloc, JSFunction *target, size_t maxArgc, size_t numActualArgs,
|
||||
bool construct)
|
||||
bool construct, bool isDOMCall)
|
||||
{
|
||||
JS_ASSERT(maxArgc >= numActualArgs);
|
||||
MCall *ins = new(alloc) MCall(target, numActualArgs, construct);
|
||||
MCall *ins;
|
||||
if (isDOMCall) {
|
||||
JS_ASSERT(!construct);
|
||||
ins = new(alloc) MCallDOMNative(target, numActualArgs);
|
||||
} else {
|
||||
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 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);
|
||||
}
|
||||
|
||||
MApplyArgs *
|
||||
MApplyArgs::New(TempAllocator &alloc, JSFunction *target, MDefinition *fun, MDefinition *argc,
|
||||
MDefinition *self)
|
||||
|
|
|
@ -59,8 +59,6 @@ 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
|
||||
|
@ -1806,7 +1804,7 @@ class MCall
|
|||
public:
|
||||
INSTRUCTION_HEADER(Call)
|
||||
static MCall *New(TempAllocator &alloc, JSFunction *target, size_t maxArgc, size_t numActualArgs,
|
||||
bool construct);
|
||||
bool construct, bool isDOMCall);
|
||||
|
||||
void initFunction(MDefinition *func) {
|
||||
return setOperand(FunctionOperandIndex, func);
|
||||
|
@ -1871,49 +1869,37 @@ 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;
|
||||
}
|
||||
};
|
||||
|
||||
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 isCallDOMNative() const MOZ_OVERRIDE {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// fun.apply(self, arguments)
|
||||
|
|
|
@ -697,7 +697,7 @@ bool
|
|||
ParallelSafetyVisitor::visitCall(MCall *ins)
|
||||
{
|
||||
// DOM? Scary.
|
||||
if (ins->isDOMFunction()) {
|
||||
if (ins->isCallDOMNative()) {
|
||||
SpewMIR(ins, "call to dom function");
|
||||
return markUnsafe();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче