Bug 1380344 - Add Ion support for IsPackedArray. r=jandem

--HG--
extra : rebase_source : 8599c33b39806d1580a3a5fd208f39150f6c2c3e
extra : histedit_source : de214f94b5b5eb2d440519634555da3a0dc72b85
This commit is contained in:
André Bargull 2017-07-17 08:56:22 -07:00
Родитель a32a33c30a
Коммит ceca1e45b7
13 изменённых файлов: 127 добавлений и 1 удалений

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

@ -124,6 +124,7 @@ GetObject(const MDefinition* ins)
case MDefinition::Op_TypedArrayElements:
case MDefinition::Op_TypedObjectElements:
case MDefinition::Op_CopyLexicalEnvironmentObject:
case MDefinition::Op_IsPackedArray:
object = ins->getOperand(0);
break;
case MDefinition::Op_GetPropertyCache:

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

@ -12842,5 +12842,30 @@ CodeGenerator::visitFinishBoundFunctionInit(LFinishBoundFunctionInit* lir)
masm.bind(ool->rejoin());
}
void
CodeGenerator::visitIsPackedArray(LIsPackedArray* lir)
{
Register array = ToRegister(lir->array());
Register output = ToRegister(lir->output());
Register elementsTemp = ToRegister(lir->temp());
Label notPacked, done;
// Load elements and length.
masm.loadPtr(Address(array, NativeObject::offsetOfElements()), elementsTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), output);
// Test length == initializedLength.
Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, output, &notPacked);
masm.move32(Imm32(1), output);
masm.jump(&done);
masm.bind(&notPacked);
masm.move32(Imm32(0), output);
masm.bind(&done);
}
} // namespace jit
} // namespace js

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

@ -411,6 +411,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitNaNToZero(LNaNToZero* ins);
void visitOutOfLineNaNToZero(OutOfLineNaNToZero* ool);
void visitFinishBoundFunctionInit(LFinishBoundFunctionInit* lir);
void visitIsPackedArray(LIsPackedArray* lir);
void visitCheckOverRecursed(LCheckOverRecursed* lir);
void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);

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

@ -122,6 +122,7 @@
_(IntrinsicSubstringKernel) \
_(IntrinsicObjectHasPrototype) \
_(IntrinsicFinishBoundFunctionInit) \
_(IntrinsicIsPackedArray) \
\
_(IntrinsicIsArrayIterator) \
_(IntrinsicIsMapIterator) \

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

@ -781,6 +781,7 @@ class IonBuilder
InliningResult inlineSubstringKernel(CallInfo& callInfo);
InliningResult inlineObjectHasPrototype(CallInfo& callInfo);
InliningResult inlineFinishBoundFunctionInit(CallInfo& callInfo);
InliningResult inlineIsPackedArray(CallInfo& callInfo);
// Testing functions.
InliningResult inlineBailout(CallInfo& callInfo);

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

@ -4972,6 +4972,16 @@ LIRGenerator::visitFinishBoundFunctionInit(MFinishBoundFunctionInit* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitIsPackedArray(MIsPackedArray* ins)
{
MOZ_ASSERT(ins->array()->type() == MIRType::Object);
MOZ_ASSERT(ins->type() == MIRType::Boolean);
auto lir = new(alloc()) LIsPackedArray(useRegister(ins->array()), temp());
define(lir, ins);
}
static void
SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
{

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

@ -343,6 +343,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitCheckObjCoercible(MCheckObjCoercible* ins);
void visitDebugCheckSelfHosted(MDebugCheckSelfHosted* ins);
void visitFinishBoundFunctionInit(MFinishBoundFunctionInit* ins);
void visitIsPackedArray(MIsPackedArray* ins);
};
} // namespace jit

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

@ -312,6 +312,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
return inlineObjectHasPrototype(callInfo);
case InlinableNative::IntrinsicFinishBoundFunctionInit:
return inlineFinishBoundFunctionInit(callInfo);
case InlinableNative::IntrinsicIsPackedArray:
return inlineIsPackedArray(callInfo);
// Map intrinsics.
case InlinableNative::IntrinsicIsMapObject:
@ -1745,6 +1747,47 @@ IonBuilder::inlineFinishBoundFunctionInit(CallInfo& callInfo)
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
IonBuilder::inlineIsPackedArray(CallInfo& callInfo)
{
MOZ_ASSERT(!callInfo.constructing());
MOZ_ASSERT(callInfo.argc() == 1);
if (getInlineReturnType() != MIRType::Boolean)
return InliningStatus_NotInlined;
MDefinition* array = callInfo.getArg(0);
if (array->type() != MIRType::Object)
return InliningStatus_NotInlined;
TemporaryTypeSet* arrayTypes = array->resultTypeSet();
if (!arrayTypes)
return InliningStatus_NotInlined;
const Class* clasp = arrayTypes->getKnownClass(constraints());
if (clasp != &ArrayObject::class_)
return InliningStatus_NotInlined;
// Only inline if the array uses dense storage.
ObjectGroupFlags unhandledFlags = OBJECT_FLAG_SPARSE_INDEXES |
OBJECT_FLAG_LENGTH_OVERFLOW |
OBJECT_FLAG_NON_PACKED;
if (arrayTypes->hasObjectFlags(constraints(), unhandledFlags)) {
trackOptimizationOutcome(TrackedOutcome::ArrayBadFlags);
return InliningStatus_NotInlined;
}
callInfo.setImplicitlyUsedUnchecked();
auto* ins = MIsPackedArray::New(alloc(), array);
current->add(ins);
current->push(ins);
return InliningStatus_Inlined;
}
IonBuilder::InliningResult
IonBuilder::inlineStrCharCodeAt(CallInfo& callInfo)
{

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

@ -13857,6 +13857,27 @@ class MFinishBoundFunctionInit
NAMED_OPERANDS((0, bound), (1, target), (2, argCount))
};
class MIsPackedArray
: public MUnaryInstruction,
public SingleObjectPolicy::Data
{
explicit MIsPackedArray(MDefinition* array)
: MUnaryInstruction(array)
{
setResultType(MIRType::Boolean);
setMovable();
}
public:
INSTRUCTION_HEADER(IsPackedArray)
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, array))
AliasSet getAliasSet() const override {
return AliasSet::Load(AliasSet::ObjectFields);
}
};
// Flips the input's sign bit, independently of the rest of the number's
// payload. Note this is different from multiplying by minus-one, which has
// side-effects for e.g. NaNs.

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

@ -298,6 +298,7 @@ namespace jit {
_(CheckObjCoercible) \
_(DebugCheckSelfHosted) \
_(FinishBoundFunctionInit) \
_(IsPackedArray) \
_(AsmJSLoadHeap) \
_(AsmJSStoreHeap) \
_(AsmJSCompareExchangeHeap) \

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

@ -9318,6 +9318,25 @@ class LFinishBoundFunctionInit : public LInstructionHelper<0, 3, 2>
}
};
class LIsPackedArray : public LInstructionHelper<1, 1, 1>
{
public:
LIR_HEADER(IsPackedArray)
LIsPackedArray(const LAllocation& array, const LDefinition& temp)
{
setOperand(0, array);
setTemp(0, temp);
}
const LAllocation* array() {
return getOperand(0);
}
const LDefinition* temp() {
return getTemp(0);
}
};
} // namespace jit
} // namespace js

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

@ -415,6 +415,7 @@
_(CheckObjCoercible) \
_(DebugCheckSelfHosted) \
_(FinishBoundFunctionInit) \
_(IsPackedArray) \
_(AsmJSLoadHeap) \
_(AsmJSStoreHeap) \
_(AsmJSCompareExchangeHeap) \

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

@ -2301,7 +2301,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("UnsafeGetBooleanFromReservedSlot", intrinsic_UnsafeGetBooleanFromReservedSlot,2,0,
IntrinsicUnsafeGetBooleanFromReservedSlot),
JS_FN("IsPackedArray", intrinsic_IsPackedArray, 1,0),
JS_INLINABLE_FN("IsPackedArray", intrinsic_IsPackedArray, 1,0,
IntrinsicIsPackedArray),
JS_FN("GetIteratorPrototype", intrinsic_GetIteratorPrototype, 0,0),