Bug 1381891 - Inline IsTypedArray even when non-TypedArrays were observed. r=jandem

This commit is contained in:
André Bargull 2017-07-18 09:46:08 -07:00
Родитель c3d68d0f00
Коммит 457b12734d
9 изменённых файлов: 109 добавлений и 16 удалений

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

@ -49,6 +49,7 @@
#include "vm/RegExpObject.h"
#include "vm/RegExpStatics.h"
#include "vm/TraceLogging.h"
#include "vm/TypedArrayObject.h"
#include "vm/Unicode.h"
#include "vtune/VTuneWrapper.h"
@ -12026,6 +12027,32 @@ CodeGenerator::visitIsArrayV(LIsArrayV* lir)
EmitObjectIsArray(masm, ool, temp, output, &notArray);
}
void
CodeGenerator::visitIsTypedArray(LIsTypedArray* lir)
{
Register object = ToRegister(lir->object());
Register output = ToRegister(lir->output());
Label notTypedArray;
Label done;
static_assert(Scalar::Int8 == 0, "Int8 is the first typed array class");
static_assert((Scalar::Uint8Clamped - Scalar::Int8) == Scalar::MaxTypedArrayViewType - 1,
"Uint8Clamped is the last typed array class");
const Class* firstTypedArrayClass = TypedArrayObject::classForType(Scalar::Int8);
const Class* lastTypedArrayClass = TypedArrayObject::classForType(Scalar::Uint8Clamped);
masm.loadObjClass(object, output);
masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass), &notTypedArray);
masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), &notTypedArray);
masm.move32(Imm32(1), output);
masm.jump(&done);
masm.bind(&notTypedArray);
masm.move32(Imm32(0), output);
masm.bind(&done);
}
void
CodeGenerator::visitIsObject(LIsObject* ins)
{

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

@ -389,6 +389,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitOutOfLineIsConstructor(OutOfLineIsConstructor* ool);
void visitIsArrayO(LIsArrayO* lir);
void visitIsArrayV(LIsArrayV* lir);
void visitIsTypedArray(LIsTypedArray* lir);
void visitIsObject(LIsObject* lir);
void visitIsObjectAndBranch(LIsObjectAndBranch* lir);
void visitHasClass(LHasClass* lir);

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

@ -4321,6 +4321,16 @@ LIRGenerator::visitIsArray(MIsArray* ins)
}
}
void
LIRGenerator::visitIsTypedArray(MIsTypedArray* ins)
{
MOZ_ASSERT(ins->value()->type() == MIRType::Object);
MOZ_ASSERT(ins->type() == MIRType::Boolean);
auto* lir = new(alloc()) LIsTypedArray(useRegister(ins->value()));
define(lir, ins);
}
void
LIRGenerator::visitIsCallable(MIsCallable* ins)
{

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

@ -295,6 +295,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitIsCallable(MIsCallable* ins);
void visitIsConstructor(MIsConstructor* ins);
void visitIsArray(MIsArray* ins);
void visitIsTypedArray(MIsTypedArray* ins);
void visitIsObject(MIsObject* ins);
void visitHasClass(MHasClass* ins);
void visitWasmAddOffset(MWasmAddOffset* ins);

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

@ -2525,23 +2525,31 @@ IonBuilder::inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappi
if (!types)
return InliningStatus_NotInlined;
// Wrapped typed arrays won't appear to be typed arrays per a
// |forAllClasses| query. If wrapped typed arrays are to be considered
// typed arrays, a negative answer is not conclusive. Don't inline in
// that case.
auto isPossiblyWrapped = [this, wrappingBehavior, types]() {
if (wrappingBehavior != AllowWrappedTypedArrays)
return false;
switch (types->forAllClasses(constraints(), IsProxyClass)) {
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
case TemporaryTypeSet::ForAllResult::EMPTY:
break;
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
case TemporaryTypeSet::ForAllResult::MIXED:
return true;
}
return false;
};
bool result = false;
bool isConstant = true;
switch (types->forAllClasses(constraints(), IsTypedArrayClass)) {
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
// Wrapped typed arrays won't appear to be typed arrays per a
// |forAllClasses| query. If wrapped typed arrays are to be considered
// typed arrays, a negative answer is not conclusive. Don't inline in
// that case.
if (wrappingBehavior == AllowWrappedTypedArrays) {
switch (types->forAllClasses(constraints(), IsProxyClass)) {
case TemporaryTypeSet::ForAllResult::ALL_FALSE:
case TemporaryTypeSet::ForAllResult::EMPTY:
break;
case TemporaryTypeSet::ForAllResult::ALL_TRUE:
case TemporaryTypeSet::ForAllResult::MIXED:
return InliningStatus_NotInlined;
}
}
if (isPossiblyWrapped())
return InliningStatus_NotInlined;
MOZ_FALLTHROUGH;
@ -2554,10 +2562,20 @@ IonBuilder::inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappi
break;
case TemporaryTypeSet::ForAllResult::MIXED:
return InliningStatus_NotInlined;
if (isPossiblyWrapped())
return InliningStatus_NotInlined;
isConstant = false;
break;
}
pushConstant(BooleanValue(result));
if (isConstant) {
pushConstant(BooleanValue(result));
} else {
auto* ins = MIsTypedArray::New(alloc(), callInfo.getArg(0));
current->add(ins);
current->push(ins);
}
callInfo.setImplicitlyUsedUnchecked();
return InliningStatus_Inlined;

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

@ -13484,6 +13484,27 @@ class MIsArray
NAMED_OPERANDS((0, value))
};
class MIsTypedArray
: public MUnaryInstruction,
public SingleObjectPolicy::Data
{
explicit MIsTypedArray(MDefinition* value)
: MUnaryInstruction(value)
{
setResultType(MIRType::Boolean);
setMovable();
}
public:
INSTRUCTION_HEADER(IsTypedArray)
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, value))
AliasSet getAliasSet() const override {
return AliasSet::None();
}
};
class MCheckReturn
: public MBinaryInstruction,
public BoxInputsPolicy::Data

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

@ -279,6 +279,7 @@ namespace jit {
_(IsConstructor) \
_(IsCallable) \
_(IsArray) \
_(IsTypedArray) \
_(IsObject) \
_(HasClass) \
_(CopySign) \

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

@ -8032,6 +8032,19 @@ class LIsArrayV : public LInstructionHelper<1, BOX_PIECES, 1>
}
};
class LIsTypedArray : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(IsTypedArray);
explicit LIsTypedArray(const LAllocation& object) {
setOperand(0, object);
}
const LAllocation* object() {
return getOperand(0);
}
};
class LIsObject : public LInstructionHelper<1, BOX_PIECES, 0>
{
public:

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

@ -392,6 +392,7 @@
_(IsConstructor) \
_(IsArrayO) \
_(IsArrayV) \
_(IsTypedArray) \
_(IsObject) \
_(IsObjectAndBranch) \
_(HasClass) \