зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1381891 - Inline IsTypedArray even when non-TypedArrays were observed. r=jandem
This commit is contained in:
Родитель
c3d68d0f00
Коммит
457b12734d
|
@ -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, ¬Array);
|
||||
}
|
||||
|
||||
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), ¬TypedArray);
|
||||
masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), ¬TypedArray);
|
||||
|
||||
masm.move32(Imm32(1), output);
|
||||
masm.jump(&done);
|
||||
masm.bind(¬TypedArray);
|
||||
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) \
|
||||
|
|
Загрузка…
Ссылка в новой задаче