mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 19:55:39 +00:00
Bug 1391304
- Inline IsCallable when called with MIRType::Value. r=jandem
This commit is contained in:
parent
fecbd1f9b8
commit
537d49e004
@ -11902,18 +11902,22 @@ CodeGenerator::visitSetDOMProperty(LSetDOMProperty* ins)
|
||||
|
||||
class OutOfLineIsCallable : public OutOfLineCodeBase<CodeGenerator>
|
||||
{
|
||||
LIsCallable* ins_;
|
||||
Register object_;
|
||||
Register output_;
|
||||
|
||||
public:
|
||||
explicit OutOfLineIsCallable(LIsCallable* ins)
|
||||
: ins_(ins)
|
||||
OutOfLineIsCallable(Register object, Register output)
|
||||
: object_(object), output_(output)
|
||||
{ }
|
||||
|
||||
void accept(CodeGenerator* codegen) {
|
||||
codegen->visitOutOfLineIsCallable(this);
|
||||
}
|
||||
LIsCallable* ins() const {
|
||||
return ins_;
|
||||
Register object() const {
|
||||
return object_;
|
||||
}
|
||||
Register output() const {
|
||||
return output_;
|
||||
}
|
||||
};
|
||||
|
||||
@ -11966,12 +11970,12 @@ CodeGenerator::emitIsCallableOrConstructor(Register object, Register output, Lab
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitIsCallable(LIsCallable* ins)
|
||||
CodeGenerator::visitIsCallableO(LIsCallableO* ins)
|
||||
{
|
||||
Register object = ToRegister(ins->object());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
OutOfLineIsCallable* ool = new(alloc()) OutOfLineIsCallable(ins);
|
||||
OutOfLineIsCallable* ool = new(alloc()) OutOfLineIsCallable(object, output);
|
||||
addOutOfLineCode(ool, ins->mir());
|
||||
|
||||
emitIsCallableOrConstructor<Callable>(object, output, ool->entry());
|
||||
@ -11979,12 +11983,34 @@ CodeGenerator::visitIsCallable(LIsCallable* ins)
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitIsCallableV(LIsCallableV* ins)
|
||||
{
|
||||
ValueOperand val = ToValue(ins, LIsCallableV::Value);
|
||||
Register output = ToRegister(ins->output());
|
||||
Register temp = ToRegister(ins->temp());
|
||||
|
||||
Label notObject;
|
||||
masm.branchTestObject(Assembler::NotEqual, val, ¬Object);
|
||||
masm.unboxObject(val, temp);
|
||||
|
||||
OutOfLineIsCallable* ool = new(alloc()) OutOfLineIsCallable(temp, output);
|
||||
addOutOfLineCode(ool, ins->mir());
|
||||
|
||||
emitIsCallableOrConstructor<Callable>(temp, output, ool->entry());
|
||||
masm.jump(ool->rejoin());
|
||||
|
||||
masm.bind(¬Object);
|
||||
masm.move32(Imm32(0), output);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitOutOfLineIsCallable(OutOfLineIsCallable* ool)
|
||||
{
|
||||
LIsCallable* ins = ool->ins();
|
||||
Register object = ToRegister(ins->object());
|
||||
Register output = ToRegister(ins->output());
|
||||
Register object = ool->object();
|
||||
Register output = ool->output();
|
||||
|
||||
saveVolatile(output);
|
||||
masm.setupUnalignedABICall(output);
|
||||
|
@ -386,7 +386,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
||||
};
|
||||
template <CallableOrConstructor mode>
|
||||
void emitIsCallableOrConstructor(Register object, Register output, Label* failure);
|
||||
void visitIsCallable(LIsCallable* lir);
|
||||
void visitIsCallableO(LIsCallableO* lir);
|
||||
void visitIsCallableV(LIsCallableV* lir);
|
||||
void visitOutOfLineIsCallable(OutOfLineIsCallable* ool);
|
||||
void visitIsConstructor(LIsConstructor* lir);
|
||||
void visitOutOfLineIsConstructor(OutOfLineIsConstructor* ool);
|
||||
|
@ -4359,9 +4359,14 @@ LIRGenerator::visitIsTypedArray(MIsTypedArray* ins)
|
||||
void
|
||||
LIRGenerator::visitIsCallable(MIsCallable* ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->object()->type() == MIRType::Object);
|
||||
MOZ_ASSERT(ins->type() == MIRType::Boolean);
|
||||
define(new(alloc()) LIsCallable(useRegister(ins->object())), ins);
|
||||
|
||||
if (ins->object()->type() == MIRType::Object) {
|
||||
define(new(alloc()) LIsCallableO(useRegister(ins->object())), ins);
|
||||
} else {
|
||||
MOZ_ASSERT(ins->object()->type() == MIRType::Value);
|
||||
define(new(alloc()) LIsCallableV(useBox(ins->object()), temp()), ins);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2982,25 +2982,24 @@ IonBuilder::inlineIsCallable(CallInfo& callInfo)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* arg = callInfo.getArg(0);
|
||||
// Do not inline if the type of arg is neither primitive nor object.
|
||||
if (arg->type() > MIRType::Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Try inlining with constant true/false: only objects may be callable at
|
||||
// all, and if we know the class check if it is callable.
|
||||
bool isCallableKnown = false;
|
||||
bool isCallableConstant;
|
||||
if (arg->type() != MIRType::Object) {
|
||||
// Primitive (including undefined and null).
|
||||
isCallableKnown = true;
|
||||
isCallableConstant = false;
|
||||
} else {
|
||||
if (arg->type() == MIRType::Object) {
|
||||
TemporaryTypeSet* types = arg->resultTypeSet();
|
||||
const Class* clasp = types ? types->getKnownClass(constraints()) : nullptr;
|
||||
if (clasp && !clasp->isProxy()) {
|
||||
isCallableKnown = true;
|
||||
isCallableConstant = clasp->nonProxyCallable();
|
||||
}
|
||||
} else if (!arg->mightBeType(MIRType::Object)) {
|
||||
// Primitive (including undefined and null).
|
||||
isCallableKnown = true;
|
||||
isCallableConstant = false;
|
||||
} else if (arg->type() != MIRType::Value) {
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
@ -13444,11 +13444,12 @@ class MResumePoint final :
|
||||
|
||||
class MIsCallable
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
public BoxExceptPolicy<0, MIRType::Object>::Data
|
||||
{
|
||||
explicit MIsCallable(MDefinition* object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
MOZ_ASSERT(object->type() == MIRType::Object || object->type() == MIRType::Value);
|
||||
setResultType(MIRType::Boolean);
|
||||
setMovable();
|
||||
}
|
||||
|
@ -8008,11 +8008,11 @@ class LCallInstanceOf : public LCallInstructionHelper<1, BOX_PIECES+1, 0>
|
||||
static const size_t RHS = BOX_PIECES;
|
||||
};
|
||||
|
||||
class LIsCallable : public LInstructionHelper<1, 1, 0>
|
||||
class LIsCallableO : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(IsCallable);
|
||||
explicit LIsCallable(const LAllocation& object) {
|
||||
LIR_HEADER(IsCallableO);
|
||||
explicit LIsCallableO(const LAllocation& object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
|
||||
@ -8024,6 +8024,24 @@ class LIsCallable : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LIsCallableV : public LInstructionHelper<1, BOX_PIECES, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(IsCallableV);
|
||||
static const size_t Value = 0;
|
||||
|
||||
LIsCallableV(const LBoxAllocation& value, const LDefinition& temp) {
|
||||
setBoxOperand(0, value);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
const LDefinition* temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
MIsCallable* mir() const {
|
||||
return mir_->toIsCallable();
|
||||
}
|
||||
};
|
||||
|
||||
class LIsConstructor : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
|
@ -390,7 +390,8 @@
|
||||
_(GetDOMMemberT) \
|
||||
_(SetDOMProperty) \
|
||||
_(CallDOMNative) \
|
||||
_(IsCallable) \
|
||||
_(IsCallableO) \
|
||||
_(IsCallableV) \
|
||||
_(IsConstructor) \
|
||||
_(IsArrayO) \
|
||||
_(IsArrayV) \
|
||||
|
Loading…
Reference in New Issue
Block a user