Bug 1382837 - Optimize Array.join in ion for empty and single-item arrays. r=tcampbell

This commit is contained in:
Kannan Vijayan 2017-08-09 17:06:40 -04:00
Родитель 186677c392
Коммит fb3ee9fa6a
6 изменённых файлов: 80 добавлений и 8 удалений

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

@ -9295,10 +9295,45 @@ static const VMFunction ArrayJoinInfo = FunctionInfo<ArrayJoinFn>(jit::ArrayJoin
void
CodeGenerator::visitArrayJoin(LArrayJoin* lir)
{
pushArg(ToRegister(lir->separator()));
pushArg(ToRegister(lir->array()));
Label skipCall;
Register output = ToRegister(lir->output());
Register sep = ToRegister(lir->separator());
Register array = ToRegister(lir->array());
if (lir->mir()->optimizeForArray()) {
Register temp = ToRegister(lir->temp());
masm.loadPtr(Address(array, NativeObject::offsetOfElements()), temp);
Address length(temp, ObjectElements::offsetOfLength());
Address initLength(temp, ObjectElements::offsetOfInitializedLength());
// Check for length == 0
Label notEmpty;
masm.branch32(Assembler::NotEqual, length, Imm32(0), &notEmpty);
const JSAtomState& names = GetJitContext()->runtime->names();
masm.movePtr(ImmGCPtr(names.empty), output);
masm.jump(&skipCall);
masm.bind(&notEmpty);
Label notSingleString;
// Check for length == 1, initializedLength >= 1, arr[0].isString()
masm.branch32(Assembler::NotEqual, length, Imm32(1), &notSingleString);
masm.branch32(Assembler::LessThan, initLength, Imm32(1), &notSingleString);
Address elem0(temp, 0);
masm.branchTestString(Assembler::NotEqual, elem0, &notSingleString);
// At this point, 'output' can be used as a scratch register, since we're
// guaranteed to succeed.
masm.unboxString(elem0, output);
masm.jump(&skipCall);
masm.bind(&notSingleString);
}
pushArg(sep);
pushArg(array);
callVM(ArrayJoinInfo, lir);
masm.bind(&skipCall);
}
void

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

@ -3542,8 +3542,13 @@ LIRGenerator::visitArrayJoin(MArrayJoin* ins)
MOZ_ASSERT(ins->array()->type() == MIRType::Object);
MOZ_ASSERT(ins->sep()->type() == MIRType::String);
LDefinition tempDef = LDefinition::BogusTemp();
if (ins->optimizeForArray())
tempDef = temp();
LArrayJoin* lir = new(alloc()) LArrayJoin(useRegisterAtStart(ins->array()),
useRegisterAtStart(ins->sep()));
useRegisterAtStart(ins->sep()),
tempDef);
defineReturn(lir, ins);
assignSafepoint(lir, ins);
}

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

@ -758,9 +758,25 @@ IonBuilder::inlineArrayJoin(CallInfo& callInfo)
if (callInfo.getArg(0)->type() != MIRType::String)
return InliningStatus_NotInlined;
// If we can confirm that the class is an array, the codegen
// for MArrayJoin can be notified to check for common empty and one-item arrays.
bool optimizeForArray = ([&](){
TemporaryTypeSet* thisTypes = callInfo.thisArg()->resultTypeSet();
if (!thisTypes)
return false;
const Class* clasp = thisTypes->getKnownClass(constraints());
// TODO: Handle unboxed arrays?
if (clasp != &ArrayObject::class_)
return false;
return true;
})();
callInfo.setImplicitlyUsedUnchecked();
MArrayJoin* ins = MArrayJoin::New(alloc(), callInfo.thisArg(), callInfo.getArg(0));
MArrayJoin* ins = MArrayJoin::New(alloc(), callInfo.thisArg(), callInfo.getArg(0),
optimizeForArray);
current->add(ins);
current->push(ins);

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

@ -10167,8 +10167,11 @@ class MArrayJoin
: public MBinaryInstruction,
public MixPolicy<ObjectPolicy<0>, StringPolicy<1> >::Data
{
MArrayJoin(MDefinition* array, MDefinition* sep)
: MBinaryInstruction(array, sep)
bool optimizeForArray_;
MArrayJoin(MDefinition* array, MDefinition* sep, bool optimizeForArray)
: MBinaryInstruction(array, sep),
optimizeForArray_(optimizeForArray)
{
setResultType(MIRType::String);
}
@ -10177,6 +10180,9 @@ class MArrayJoin
TRIVIAL_NEW_WRAPPERS
NAMED_OPERANDS((0, array), (1, sep))
bool optimizeForArray() const {
return optimizeForArray_;
}
bool possiblyCalls() const override {
return true;
}

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

@ -6179,25 +6179,34 @@ class LArraySlice : public LCallInstructionHelper<1, 3, 2>
}
};
class LArrayJoin : public LCallInstructionHelper<1, 2, 0>
class LArrayJoin : public LCallInstructionHelper<1, 2, 1>
{
public:
LIR_HEADER(ArrayJoin)
LArrayJoin(const LAllocation& array, const LAllocation& sep) {
LArrayJoin(const LAllocation& array, const LAllocation& sep,
const LDefinition& temp)
{
setOperand(0, array);
setOperand(1, sep);
setTemp(0, temp);
}
const MArrayJoin* mir() const {
return mir_->toArrayJoin();
}
const LDefinition* output() {
return getDef(0);
}
const LAllocation* array() {
return getOperand(0);
}
const LAllocation* separator() {
return getOperand(1);
}
const LDefinition* temp() {
return getTemp(0);
}
};
class LLoadUnboxedScalar : public LInstructionHelper<1, 2, 1>

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

@ -789,6 +789,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void unboxString(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxString(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxString(const Address& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
void unboxSymbol(const Operand& src, Register dest) { unboxNonDouble(src, dest); }