author | Hannes Verschore <hv1989@gmail.com> |
Tue, 25 Nov 2014 12:43:21 +0100 | |
changeset 243890 | 0164b161e0d88b50e1a24b301708ef973c68843f |
parent 243889 | 351a308ffe20c33bb7d740d8925209226bce673a |
child 243891 | 89edc525856a6f98cee69a4fba2b9552bcd68f0f |
push id | 660 |
push user | raliiev@mozilla.com |
push date | Wed, 18 Feb 2015 20:30:48 +0000 |
treeherder | mozilla-release@49e493494178 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 1103032 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -1212,18 +1212,18 @@ PrepareAndExecuteRegExp(JSContext *cx, M masm.storePtr(temp3, lazySourceAddress); masm.load32(Address(temp2, RegExpShared::offsetOfFlags()), temp3); masm.store32(temp3, Address(temp1, RegExpStatics::offsetOfLazyFlags())); return true; } static void -CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, Register scratch, - size_t fromWidth, size_t toWidth); +CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, + Register byteOpScratch, size_t fromWidth, size_t toWidth); static void CreateDependentString(MacroAssembler &masm, const JSAtomState &names, bool latin1, Register string, Register base, Register temp1, Register temp2, BaseIndex startIndexAddress, BaseIndex limitIndexAddress, Label *failure) { @@ -5916,18 +5916,18 @@ CodeGenerator::visitConcatPar(LConcatPar MOZ_ASSERT(ToRegister(lir->temp3()) == CallTempReg2); MOZ_ASSERT(ToRegister(lir->temp4()) == CallTempReg3); MOZ_ASSERT(output == CallTempReg5); return emitConcat(lir, lhs, rhs, output); } static void -CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, Register scratch, - size_t fromWidth, size_t toWidth) +CopyStringChars(MacroAssembler &masm, Register to, Register from, Register len, + Register byteOpScratch, size_t fromWidth, size_t toWidth) { // Copy |len| char16_t code units from |from| to |to|. Assumes len > 0 // (checked below in debug builds), and when done |to| must point to the // next available char. #ifdef DEBUG Label ok; masm.branch32(Assembler::GreaterThan, len, Imm32(0), &ok); @@ -5937,23 +5937,23 @@ CopyStringChars(MacroAssembler &masm, Re MOZ_ASSERT(fromWidth == 1 || fromWidth == 2); MOZ_ASSERT(toWidth == 1 || toWidth == 2); MOZ_ASSERT_IF(toWidth == 1, fromWidth == 1); Label start; masm.bind(&start); if (fromWidth == 2) - masm.load16ZeroExtend(Address(from, 0), scratch); + masm.load16ZeroExtend(Address(from, 0), byteOpScratch); else - masm.load8ZeroExtend(Address(from, 0), scratch); + masm.load8ZeroExtend(Address(from, 0), byteOpScratch); if (toWidth == 2) - masm.store16(scratch, Address(to, 0)); + masm.store16(byteOpScratch, Address(to, 0)); else - masm.store8(scratch, Address(to, 0)); + masm.store8(byteOpScratch, Address(to, 0)); masm.addPtr(Imm32(fromWidth), from); masm.addPtr(Imm32(toWidth), to); masm.branchSub32(Assembler::NonZero, Imm32(1), len, &start); } static void CopyStringCharsMaybeInflate(MacroAssembler &masm, Register input, Register destChars, Register temp1, Register temp2) @@ -6060,18 +6060,22 @@ static const VMFunction SubstringKernelI bool CodeGenerator::visitSubstr(LSubstr *lir) { Register string = ToRegister(lir->string()); Register begin = ToRegister(lir->begin()); Register length = ToRegister(lir->length()); Register output = ToRegister(lir->output()); Register temp = ToRegister(lir->temp()); - Register temp2 = ToRegister(lir->temp2()); Register temp3 = ToRegister(lir->temp3()); + + // On x86 there are not enough registers. In that case reuse the string + // register as temporary. + Register temp2 = lir->temp2()->isBogusTemp() ? string : ToRegister(lir->temp2()); + Address stringFlags(string, JSString::offsetOfFlags()); Label isLatin1, notInline, nonZero, isInlinedLatin1; // For every edge case use the C++ variant. // Note: we also use this upon allocation failure in newGCString and // newGCFatInlineString. To squeeze out even more performance those failures // can be handled by allocate in ool code and returning to jit code to fill @@ -6105,35 +6109,43 @@ bool CodeGenerator::visitSubstr(LSubstr Address outputStorage(output, JSInlineString::offsetOfInlineStorage()); masm.branchTest32(Assembler::NonZero, stringFlags, Imm32(JSString::LATIN1_CHARS_BIT), &isInlinedLatin1); { masm.store32(Imm32(JSString::INIT_FAT_INLINE_FLAGS), Address(output, JSString::offsetOfFlags())); masm.computeEffectiveAddress(stringStorage, temp); + if (temp2 == string) + masm.push(string); BaseIndex chars(temp, begin, ScaleFromElemWidth(sizeof(char16_t))); masm.computeEffectiveAddress(chars, temp2); masm.computeEffectiveAddress(outputStorage, temp); CopyStringChars(masm, temp, temp2, length, temp3, sizeof(char16_t), sizeof(char16_t)); masm.load32(Address(output, JSString::offsetOfLength()), length); masm.store16(Imm32(0), Address(temp, 0)); + if (temp2 == string) + masm.pop(string); masm.jump(done); } masm.bind(&isInlinedLatin1); { masm.store32(Imm32(JSString::INIT_FAT_INLINE_FLAGS | JSString::LATIN1_CHARS_BIT), Address(output, JSString::offsetOfFlags())); + if (temp2 == string) + masm.push(string); masm.computeEffectiveAddress(stringStorage, temp2); static_assert(sizeof(char) == 1, "begin index shouldn't need scaling"); masm.addPtr(begin, temp2); masm.computeEffectiveAddress(outputStorage, temp); CopyStringChars(masm, temp, temp2, length, temp3, sizeof(char), sizeof(char)); masm.load32(Address(output, JSString::offsetOfLength()), length); masm.store8(Imm32(0), Address(temp, 0)); + if (temp2 == string) + masm.pop(string); masm.jump(done); } // Handle other cases with a DependentString. masm.bind(¬Inline); masm.newGCString(output, temp, slowPath); masm.store32(length, Address(output, JSString::offsetOfLength())); masm.storePtr(string, Address(output, JSDependentString::offsetOfBase()));
--- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -2177,31 +2177,16 @@ LIRGenerator::visitStringReplace(MString LStringReplace *lir = new(alloc()) LStringReplace(useRegisterOrConstantAtStart(ins->string()), useRegisterAtStart(ins->pattern()), useRegisterOrConstantAtStart(ins->replacement())); return defineReturn(lir, ins) && assignSafepoint(lir, ins); } bool -LIRGenerator::visitSubstr(MSubstr *ins) -{ - // The last temporary need to be a register that can handle 8bit moves, but - // there is no way to signal that to register allocator, except to give a - // fixed temporary that is able to do this. - LSubstr *lir = new (alloc()) LSubstr(useRegister(ins->string()), - useRegister(ins->begin()), - useRegister(ins->length()), - temp(), - temp(), - tempFixed(CallTempReg1)); - return define(lir, ins) && assignSafepoint(lir, ins); -} - -bool LIRGenerator::visitLambda(MLambda *ins) { if (ins->info().singletonType || ins->info().useNewTypeForClone) { // If the function has a singleton type, this instruction will only be // executed once so we don't bother inlining it. // // If UseNewTypeForClone is true, we will assign a singleton type to // the clone and we have to clone the script, we can't do that inline.
--- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -141,17 +141,16 @@ class LIRGenerator : public LIRGenerator bool visitMul(MMul *ins); bool visitDiv(MDiv *ins); bool visitMod(MMod *ins); bool visitConcat(MConcat *ins); bool visitConcatPar(MConcatPar *ins); bool visitCharCodeAt(MCharCodeAt *ins); bool visitFromCharCode(MFromCharCode *ins); bool visitStringSplit(MStringSplit *ins); - bool visitSubstr(MSubstr *ins); bool visitStart(MStart *start); bool visitOsrEntry(MOsrEntry *entry); bool visitNop(MNop *nop); bool visitLimitedTruncate(MLimitedTruncate *nop); bool visitOsrValue(MOsrValue *value); bool visitOsrScopeChain(MOsrScopeChain *object); bool visitOsrReturnValue(MOsrReturnValue *value); bool visitOsrArgumentsObject(MOsrArgumentsObject *object);
--- a/js/src/jit/arm/Lowering-arm.cpp +++ b/js/src/jit/arm/Lowering-arm.cpp @@ -50,16 +50,22 @@ LIRGeneratorARM::useByteOpRegister(MDefi } LAllocation LIRGeneratorARM::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir) { return useRegisterOrNonDoubleConstant(mir); } +LDefinition +LIRGeneratorARM::tempByteOpRegister() +{ + return temp(); +} + bool LIRGeneratorARM::lowerConstantDouble(double d, MInstruction *mir) { return define(new(alloc()) LDouble(d), mir); } bool LIRGeneratorARM::lowerConstantFloat32(float d, MInstruction *mir) @@ -669,8 +675,20 @@ LIRGeneratorARM::visitAsmJSAtomicBinopHe LAsmJSAtomicBinopHeap *lir = new(alloc()) LAsmJSAtomicBinopHeap(useRegister(ptr), useRegister(ins->value()), LDefinition::BogusTemp()); return define(lir, ins); } + +bool +LIRGeneratorARM::visitSubstr(MSubstr *ins) +{ + LSubstr *lir = new (alloc()) LSubstr(useRegister(ins->string()), + useRegister(ins->begin()), + useRegister(ins->length()), + temp(), + temp(), + tempByteOpRegister()); + return define(lir, ins) && assignSafepoint(lir, ins); +}
--- a/js/src/jit/arm/Lowering-arm.h +++ b/js/src/jit/arm/Lowering-arm.h @@ -25,16 +25,17 @@ class LIRGeneratorARM : public LIRGenera bool useBox(LInstruction *lir, size_t n, MDefinition *mir, LUse::Policy policy = LUse::REGISTER, bool useAtStart = false); bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2); // x86 has constraints on what registers can be formatted for 1-byte // stores and loads; on ARM all registers are okay. LAllocation useByteOpRegister(MDefinition *mir); LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir); + LDefinition tempByteOpRegister(); inline LDefinition tempToUnbox() { return LDefinition::BogusTemp(); } bool needTempForPostBarrier() { return false; } // x64 has a scratch register, so no need for another temp for dispatch @@ -106,16 +107,17 @@ class LIRGeneratorARM : public LIRGenera bool visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins); bool visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); bool visitForkJoinGetSlice(MForkJoinGetSlice *ins); bool visitSimdTernaryBitwise(MSimdTernaryBitwise *ins); bool visitSimdSplatX4(MSimdSplatX4 *ins); bool visitSimdValueX4(MSimdValueX4 *ins); bool visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins); bool visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins); + bool visitSubstr(MSubstr *ins); }; typedef LIRGeneratorARM LIRGeneratorSpecific; } // namespace jit } // namespace js #endif /* jit_arm_Lowering_arm_h */
--- a/js/src/jit/mips/Lowering-mips.cpp +++ b/js/src/jit/mips/Lowering-mips.cpp @@ -52,16 +52,22 @@ LIRGeneratorMIPS::useByteOpRegister(MDef } LAllocation LIRGeneratorMIPS::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir) { return useRegisterOrNonDoubleConstant(mir); } +LDefinition +LIRGeneratorMIPS::tempByteOpRegister() +{ + return temp(); +} + bool LIRGeneratorMIPS::lowerConstantDouble(double d, MInstruction *mir) { return define(new(alloc()) LDouble(d), mir); } bool LIRGeneratorMIPS::lowerConstantFloat32(float d, MInstruction *mir) @@ -521,16 +527,28 @@ LIRGeneratorMIPS::lowerTruncateFToInt32( { MDefinition *opd = ins->input(); MOZ_ASSERT(opd->type() == MIRType_Float32); return define(new(alloc()) LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()), ins); } bool +LIRGeneratorMIPS::visitSubstr(MSubstr *ins) +{ + LSubstr *lir = new (alloc()) LSubstr(useRegister(ins->string()), + useRegister(ins->begin()), + useRegister(ins->length()), + temp(), + temp(), + tempByteOpRegister()); + return define(lir, ins) && assignSafepoint(lir, ins); +} + +bool LIRGeneratorMIPS::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins) { MOZ_CRASH("NYI"); } bool LIRGeneratorMIPS::visitForkJoinGetSlice(MForkJoinGetSlice *ins) {
--- a/js/src/jit/mips/Lowering-mips.h +++ b/js/src/jit/mips/Lowering-mips.h @@ -25,16 +25,17 @@ class LIRGeneratorMIPS : public LIRGener bool useBox(LInstruction *lir, size_t n, MDefinition *mir, LUse::Policy policy = LUse::REGISTER, bool useAtStart = false); bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register reg2); // x86 has constraints on what registers can be formatted for 1-byte // stores and loads; on MIPS all registers are okay. LAllocation useByteOpRegister(MDefinition *mir); LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir); + LDefinition tempByteOpRegister(); inline LDefinition tempToUnbox() { return LDefinition::BogusTemp(); } bool needTempForPostBarrier() { return false; } // MIPS has a scratch register, so no need for another temp for dispatch @@ -104,16 +105,17 @@ class LIRGeneratorMIPS : public LIRGener bool visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins); bool visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); bool visitForkJoinGetSlice(MForkJoinGetSlice *ins); bool visitSimdTernaryBitwise(MSimdTernaryBitwise *ins); bool visitSimdSplatX4(MSimdSplatX4 *ins); bool visitSimdValueX4(MSimdValueX4 *ins); bool visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins); bool visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins); + bool visitSubstr(MSubstr *ins); }; typedef LIRGeneratorMIPS LIRGeneratorSpecific; } // namespace jit } // namespace js #endif /* jit_mips_Lowering_mips_h */
--- a/js/src/jit/none/Lowering-none.h +++ b/js/src/jit/none/Lowering-none.h @@ -24,16 +24,17 @@ class LIRGeneratorNone : public LIRGener bool useBox(LInstruction *, size_t, MDefinition *, LUse::Policy a = LUse::REGISTER, bool b = false) { MOZ_CRASH(); } bool useBoxFixed(LInstruction *, size_t, MDefinition *, Register, Register) { MOZ_CRASH(); } LAllocation useByteOpRegister(MDefinition *) { MOZ_CRASH(); } LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *) { MOZ_CRASH(); } + LDefinition tempByteOpRegister() { MOZ_CRASH(); } LDefinition tempToUnbox() { MOZ_CRASH(); } bool needTempForPostBarrier() { MOZ_CRASH(); } LDefinition tempForDispatchCache(MIRType v = MIRType_None) { MOZ_CRASH(); } void lowerUntypedPhiInput(MPhi *, uint32_t, LBlock *, size_t) { MOZ_CRASH(); } bool defineUntypedPhi(MPhi *, size_t) { MOZ_CRASH(); } bool lowerForShift(LInstructionHelper<1, 2, 0> *, MDefinition *, MDefinition *, MDefinition *) { MOZ_CRASH(); }
--- a/js/src/jit/x64/Lowering-x64.cpp +++ b/js/src/jit/x64/Lowering-x64.cpp @@ -45,16 +45,22 @@ LIRGeneratorX64::useByteOpRegister(MDefi LAllocation LIRGeneratorX64::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir) { return useRegisterOrNonDoubleConstant(mir); } LDefinition +LIRGeneratorX64::tempByteOpRegister() +{ + return temp(); +} + +LDefinition LIRGeneratorX64::tempToUnbox() { return temp(); } bool LIRGeneratorX64::visitBox(MBox *box) { @@ -186,12 +192,24 @@ LIRGeneratorX64::visitAsmJSStoreHeap(MAs bool LIRGeneratorX64::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins) { return define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index()), temp()), ins); } bool +LIRGeneratorX64::visitSubstr(MSubstr *ins) +{ + LSubstr *lir = new (alloc()) LSubstr(useRegister(ins->string()), + useRegister(ins->begin()), + useRegister(ins->length()), + temp(), + temp(), + tempByteOpRegister()); + return define(lir, ins) && assignSafepoint(lir, ins); +} + +bool LIRGeneratorX64::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins) { MOZ_CRASH("NYI"); }
--- a/js/src/jit/x64/Lowering-x64.h +++ b/js/src/jit/x64/Lowering-x64.h @@ -27,16 +27,17 @@ class LIRGeneratorX64 : public LIRGenera bool useBox(LInstruction *lir, size_t n, MDefinition *mir, LUse::Policy policy = LUse::REGISTER, bool useAtStart = false); bool useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register); // x86 has constraints on what registers can be formatted for 1-byte // stores and loads; on x64 all registers are okay. LAllocation useByteOpRegister(MDefinition *mir); LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir); + LDefinition tempByteOpRegister(); LDefinition tempToUnbox(); bool needTempForPostBarrier() { return false; } // x64 has a scratch register, so no need for another temp for dispatch // ICs. LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) { @@ -48,16 +49,17 @@ class LIRGeneratorX64 : public LIRGenera bool visitUnbox(MUnbox *unbox); bool visitReturn(MReturn *ret); bool visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins); bool visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins); bool visitAsmJSLoadHeap(MAsmJSLoadHeap *ins); bool visitAsmJSStoreHeap(MAsmJSStoreHeap *ins); bool visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins); bool visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); + bool visitSubstr(MSubstr *ins); static bool allowInlineForkJoinGetSlice() { return true; } }; typedef LIRGeneratorX64 LIRGeneratorSpecific;
--- a/js/src/jit/x86/Lowering-x86.cpp +++ b/js/src/jit/x86/Lowering-x86.cpp @@ -71,16 +71,22 @@ LIRGeneratorX86::useByteOpRegister(MDefi } LAllocation LIRGeneratorX86::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir) { return useFixed(mir, eax); } +LDefinition +LIRGeneratorX86::tempByteOpRegister() +{ + return tempFixed(eax); +} + bool LIRGeneratorX86::visitBox(MBox *box) { MDefinition *inner = box->getOperand(0); // If the box wrapped a double, it needs a new register. if (IsFloatingPointType(inner->type())) return defineBox(new(alloc()) LBoxFloatingPoint(useRegisterAtStart(inner), tempCopy(inner, 0), @@ -304,8 +310,23 @@ LIRGeneratorX86::visitStoreTypedArrayEle return add(lir, ins); } bool LIRGeneratorX86::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins) { return define(new(alloc()) LAsmJSLoadFuncPtr(useRegisterAtStart(ins->index())), ins); } + +bool +LIRGeneratorX86::visitSubstr(MSubstr *ins) +{ + // Due to lack of registers on x86, we reuse the string register as + // temporary. As a result we only need two temporary registers and take a + // bugos temporary as fifth argument. + LSubstr *lir = new (alloc()) LSubstr(useRegister(ins->string()), + useRegister(ins->begin()), + useRegister(ins->length()), + temp(), + LDefinition::BogusTemp(), + tempByteOpRegister()); + return define(lir, ins) && assignSafepoint(lir, ins); +}
--- a/js/src/jit/x86/Lowering-x86.h +++ b/js/src/jit/x86/Lowering-x86.h @@ -28,16 +28,17 @@ class LIRGeneratorX86 : public LIRGenera // It's a trap! On x86, the 1-byte store can only use one of // {al,bl,cl,dl,ah,bh,ch,dh}. That means if the register allocator // gives us one of {edi,esi,ebp,esp}, we're out of luck. (The formatter // will assert on us.) Ideally, we'd just ask the register allocator to // give us one of {al,bl,cl,dl}. For now, just useFixed(al). LAllocation useByteOpRegister(MDefinition *mir); LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition *mir); + LDefinition tempByteOpRegister(); inline LDefinition tempToUnbox() { return LDefinition::BogusTemp(); } bool needTempForPostBarrier() { return true; } LDefinition tempForDispatchCache(MIRType outputType = MIRType_None); @@ -50,16 +51,17 @@ class LIRGeneratorX86 : public LIRGenera bool visitUnbox(MUnbox *unbox); bool visitReturn(MReturn *ret); bool visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins); bool visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins); bool visitAsmJSLoadHeap(MAsmJSLoadHeap *ins); bool visitAsmJSStoreHeap(MAsmJSStoreHeap *ins); bool visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins); bool visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins); + bool visitSubstr(MSubstr *ins); bool lowerPhi(MPhi *phi); static bool allowTypedElementHoleCheck() { return true; } static bool allowStaticTypedArrayAccesses() { return true;