From fe3f4744fbdc0e529d3648e105b9d6bd91c66f8e Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 28 Oct 2013 13:56:25 +0100 Subject: [PATCH 01/51] Bug 929280: fix ThrowError invocation arities (r=shu). --- js/src/builtin/ParallelArray.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/src/builtin/ParallelArray.js b/js/src/builtin/ParallelArray.js index 9776d849d54..4441f39a119 100644 --- a/js/src/builtin/ParallelArray.js +++ b/js/src/builtin/ParallelArray.js @@ -791,10 +791,10 @@ function ParallelArrayScatter(targets, defaultValue, conflictFunc, length, mode) var targetsLength = std_Math_min(targets.length, self.shape[0]); if (targetsLength >>> 0 !== targetsLength) - ThrowError(JSMSG_BAD_ARRAY_LENGTH, ".prototype.scatter"); + ThrowError(JSMSG_PAR_ARRAY_BAD_ARG, ".prototype.scatter length"); if (length >>> 0 !== length) - ThrowError(JSMSG_BAD_ARRAY_LENGTH, ".prototype.scatter"); + ThrowError(JSMSG_PAR_ARRAY_BAD_ARG, ".prototype.scatter length"); parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc if (ShouldForceSequential()) From 3b96b2be73fa5b7342ac1aac8d0ccf50ab6080ab Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 28 Oct 2013 14:24:19 +0100 Subject: [PATCH 02/51] Bug 930477: Specialize Math.floor for Float32; r=jandem,jonco --- js/src/assembler/assembler/X86Assembler.h | 15 +++++ .../tests/ion/testFloat32-correctness.js | 38 +++++++++++ js/src/jit/CodeGenerator.cpp | 19 +++--- js/src/jit/LIR-Common.h | 13 +++- js/src/jit/LOpcodes.h | 1 + js/src/jit/Lowering.cpp | 13 +++- js/src/jit/MCallOptimize.cpp | 5 +- js/src/jit/MIR.cpp | 50 +++++++++----- js/src/jit/MIR.h | 14 +++- js/src/jit/arm/CodeGenerator-arm.cpp | 12 ++++ js/src/jit/arm/CodeGenerator-arm.h | 1 + js/src/jit/arm/MacroAssembler-arm.cpp | 52 ++++++++++++++ js/src/jit/arm/MacroAssembler-arm.h | 1 + js/src/jit/shared/Assembler-x86-shared.h | 15 +++++ .../jit/shared/CodeGenerator-x86-shared.cpp | 67 +++++++++++++++++++ js/src/jit/shared/CodeGenerator-x86-shared.h | 1 + js/src/jit/x64/MacroAssembler-x64.cpp | 8 +++ js/src/jit/x64/MacroAssembler-x64.h | 4 +- js/src/jit/x86/MacroAssembler-x86.cpp | 14 ++++ js/src/jit/x86/MacroAssembler-x86.h | 4 +- 20 files changed, 309 insertions(+), 38 deletions(-) diff --git a/js/src/assembler/assembler/X86Assembler.h b/js/src/assembler/assembler/X86Assembler.h index 552b5c94754..80b6aef5331 100644 --- a/js/src/assembler/assembler/X86Assembler.h +++ b/js/src/assembler/assembler/X86Assembler.h @@ -322,6 +322,7 @@ private: } TwoByteOpcodeID; typedef enum { + OP3_ROUNDSS_VsdWsd = 0x0A, OP3_ROUNDSD_VsdWsd = 0x0B, OP3_PTEST_VdVd = 0x17, OP3_PINSRD_VsdWsd = 0x22 @@ -740,6 +741,11 @@ public: spew("fstp %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base)); m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FSTP, base, offset); } + void fstp32_m(int offset, RegisterID base) + { + spew("fstp32 %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base)); + m_formatter.oneByteOp(OP_FLD32, FPU6_OP_FSTP, base, offset); + } void negl_r(RegisterID dst) { @@ -2938,6 +2944,15 @@ public: m_formatter.immediate8(mode); } + void roundss_rr(XMMRegisterID src, XMMRegisterID dst, RoundingMode mode) + { + spew("roundss %s, %s, %d", + nameFPReg(src), nameFPReg(dst), (int)mode); + m_formatter.prefix(PRE_SSE_66); + m_formatter.threeByteOp(OP3_ROUNDSS_VsdWsd, ESCAPE_ROUNDSD, (RegisterID)dst, (RegisterID)src); + m_formatter.immediate8(mode); // modes are the same for roundsd and roundss + } + void pinsrd_rr(RegisterID src, XMMRegisterID dst) { spew("pinsrd $1, %s, %s", diff --git a/js/src/jit-test/tests/ion/testFloat32-correctness.js b/js/src/jit-test/tests/ion/testFloat32-correctness.js index 4db32c0a5a6..98b25f75a29 100644 --- a/js/src/jit-test/tests/ion/testFloat32-correctness.js +++ b/js/src/jit-test/tests/ion/testFloat32-correctness.js @@ -227,3 +227,41 @@ function otherMath() { }; test(setupComp, otherMath); +function setupFloor() { + f32[0] = -5.5; + f32[1] = -0.5; + f32[2] = 0; + f32[3] = 1.5; +} +function setupFloorDouble() { + f32[4] = NaN; + f32[5] = -0; + f32[6] = Infinity; + f32[7] = -Infinity; + f32[8] = Math.pow(2,31); // too big to fit into a int +} +function testFloor() { + for (var i = 0; i < 4; ++i) { + var f = Math.floor(f32[i]); + assertFloat32(g, false); // f is an int32 + + var g = Math.floor(-0 + f32[i]); + assertFloat32(g, false); + + assertEq(f, g); + } +} +function testFloorDouble() { + for (var i = 4; i < 9; ++i) { + var f = Math.fround(Math.floor(f32[i])); + assertFloat32(f, true); + + var g = Math.floor(-0 + f32[i]); + assertFloat32(g, false); + + assertEq(f, g); + } +} +test(setupFloor, testFloor); +test(setupFloorDouble, testFloorDouble); + diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 7cd15edabd6..2fa50955ee3 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -3899,19 +3899,20 @@ CodeGenerator::visitMathFunctionF(LMathFunctionF *ins) void *funptr = nullptr; switch (ins->mir()->function()) { - case MMathFunction::Log: funptr = JS_FUNC_TO_DATA_PTR(void *, logf); break; - case MMathFunction::Sin: funptr = JS_FUNC_TO_DATA_PTR(void *, sinf); break; - case MMathFunction::Cos: funptr = JS_FUNC_TO_DATA_PTR(void *, cosf); break; - case MMathFunction::Exp: funptr = JS_FUNC_TO_DATA_PTR(void *, expf); break; - case MMathFunction::Tan: funptr = JS_FUNC_TO_DATA_PTR(void *, tanf); break; - case MMathFunction::ATan: funptr = JS_FUNC_TO_DATA_PTR(void *, atanf); break; - case MMathFunction::ASin: funptr = JS_FUNC_TO_DATA_PTR(void *, sinf); break; - case MMathFunction::ACos: funptr = JS_FUNC_TO_DATA_PTR(void *, acosf); break; + case MMathFunction::Log: funptr = JS_FUNC_TO_DATA_PTR(void *, logf); break; + case MMathFunction::Sin: funptr = JS_FUNC_TO_DATA_PTR(void *, sinf); break; + case MMathFunction::Cos: funptr = JS_FUNC_TO_DATA_PTR(void *, cosf); break; + case MMathFunction::Exp: funptr = JS_FUNC_TO_DATA_PTR(void *, expf); break; + case MMathFunction::Tan: funptr = JS_FUNC_TO_DATA_PTR(void *, tanf); break; + case MMathFunction::ATan: funptr = JS_FUNC_TO_DATA_PTR(void *, atanf); break; + case MMathFunction::ASin: funptr = JS_FUNC_TO_DATA_PTR(void *, sinf); break; + case MMathFunction::ACos: funptr = JS_FUNC_TO_DATA_PTR(void *, acosf); break; + case MMathFunction::Floor: funptr = JS_FUNC_TO_DATA_PTR(void *, floorf); break; default: MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function"); } - masm.callWithABI(funptr, MacroAssembler::DOUBLE); + masm.callWithABI(funptr, MacroAssembler::FLOAT); return true; } diff --git a/js/src/jit/LIR-Common.h b/js/src/jit/LIR-Common.h index 24915fc950f..12f12367e5c 100644 --- a/js/src/jit/LIR-Common.h +++ b/js/src/jit/LIR-Common.h @@ -4366,7 +4366,7 @@ class LStringLength : public LInstructionHelper<1, 1, 0> } }; -// Take the floor of a number. Implements Math.floor(). +// Take the floor of a double precision number. Implements Math.floor(). class LFloor : public LInstructionHelper<1, 1, 0> { public: @@ -4375,9 +4375,16 @@ class LFloor : public LInstructionHelper<1, 1, 0> LFloor(const LAllocation &num) { setOperand(0, num); } +}; - MRound *mir() const { - return mir_->toRound(); +// Take the floor of a single precision number. Implements Math.floor(). +class LFloorF : public LInstructionHelper<1, 1, 0> +{ + public: + LIR_HEADER(FloorF) + + LFloorF(const LAllocation &num) { + setOperand(0, num); } }; diff --git a/js/src/jit/LOpcodes.h b/js/src/jit/LOpcodes.h index 62eb6a205f1..a5f481f9a76 100644 --- a/js/src/jit/LOpcodes.h +++ b/js/src/jit/LOpcodes.h @@ -246,6 +246,7 @@ _(TypeOfV) \ _(ToIdV) \ _(Floor) \ + _(FloorF) \ _(Round) \ _(In) \ _(InArray) \ diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 2585348fe01..ae5e035b3d4 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -1129,8 +1129,17 @@ LIRGenerator::visitUrsh(MUrsh *ins) bool LIRGenerator::visitFloor(MFloor *ins) { - JS_ASSERT(ins->num()->type() == MIRType_Double); - LFloor *lir = new LFloor(useRegister(ins->num())); + MIRType type = ins->num()->type(); + JS_ASSERT(IsFloatingPointType(type)); + + if (type == MIRType_Double) { + LFloor *lir = new LFloor(useRegister(ins->num())); + if (!assignSnapshot(lir)) + return false; + return define(lir, ins); + } + + LFloorF *lir = new LFloorF(useRegister(ins->num())); if (!assignSnapshot(lir)) return false; return define(lir, ins); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index e716cc02d95..215e2650775 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -554,7 +554,6 @@ IonBuilder::inlineMathAbs(CallInfo &callInfo) IonBuilder::InliningStatus IonBuilder::inlineMathFloor(CallInfo &callInfo) { - if (callInfo.constructing()) return InliningStatus_NotInlined; @@ -571,7 +570,7 @@ IonBuilder::inlineMathFloor(CallInfo &callInfo) return InliningStatus_Inlined; } - if (argType == MIRType_Double && returnType == MIRType_Int32) { + if (IsFloatingPointType(argType) && returnType == MIRType_Int32) { callInfo.unwrapArgs(); MFloor *ins = new MFloor(callInfo.getArg(0)); current->add(ins); @@ -579,7 +578,7 @@ IonBuilder::inlineMathFloor(CallInfo &callInfo) return InliningStatus_Inlined; } - if (argType == MIRType_Double && returnType == MIRType_Double) { + if (IsFloatingPointType(argType) && returnType == MIRType_Double) { callInfo.unwrapArgs(); MMathFunction *ins = MMathFunction::New(callInfo.getArg(0), MMathFunction::Floor, nullptr); current->add(ins); diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 3887b7040f6..7013c2947e7 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -30,6 +30,23 @@ using mozilla::DoublesAreIdentical; using mozilla::IsFloat32Representable; using mozilla::Maybe; +template static void +ConvertDefinitionToDouble(MDefinition *def, MInstruction *consumer) +{ + MInstruction *replace = MToDouble::New(def); + consumer->replaceOperand(Op, replace); + consumer->block()->insertBefore(consumer, replace); +} + +static bool +CheckUsesAreFloat32Consumers(MInstruction *ins) +{ + bool allConsumerUses = true; + for (MUseDefIterator use(ins); allConsumerUses && use; use++) + allConsumerUses &= use.def()->canConsumeFloat32(); + return allConsumerUses; +} + void MDefinition::PrintOpcodeName(FILE *fp, MDefinition::Opcode op) { @@ -650,6 +667,22 @@ MStringLength::foldsTo(bool useValueNumbers) return this; } +void +MFloor::trySpecializeFloat32() +{ + // No need to look at the output, as it's an integer (see IonBuilder::inlineMathFloor) + if (!input()->canProduceFloat32()) { + if (input()->type() == MIRType_Float32) + ConvertDefinitionToDouble<0>(input(), this); + return; + } + + if (type() == MIRType_Double) + setResultType(MIRType_Float32); + + setPolicyType(MIRType_Float32); +} + MTest * MTest::New(MDefinition *ins, MBasicBlock *ifTrue, MBasicBlock *ifFalse) { @@ -1236,23 +1269,6 @@ MBinaryArithInstruction::foldsTo(bool useValueNumbers) return this; } -template static void -ConvertDefinitionToDouble(MDefinition *def, MInstruction *consumer) -{ - MInstruction *replace = MToDouble::New(def); - consumer->replaceOperand(Op, replace); - consumer->block()->insertBefore(consumer, replace); -} - -static bool -CheckUsesAreFloat32Consumers(MInstruction *ins) -{ - bool allConsumerUses = true; - for (MUseDefIterator use(ins); allConsumerUses && use; use++) - allConsumerUses &= use.def()->canConsumeFloat32(); - return allConsumerUses; -} - void MBinaryArithInstruction::trySpecializeFloat32() { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index e27e244f3b6..2bed8d68b23 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3748,7 +3748,7 @@ class MMathFunction bool isFloat32Commutative() const { return function_ == Log || function_ == Sin || function_ == Cos || function_ == Exp || function_ == Tan || function_ == ATan - || function_ == ASin || function_ == ACos; + || function_ == ASin || function_ == ACos || function_ == Floor; } void trySpecializeFloat32(); }; @@ -7595,13 +7595,14 @@ class MStringLength // Inlined version of Math.floor(). class MFloor : public MUnaryInstruction, - public DoublePolicy<0> + public FloatingPointPolicy<0> { public: MFloor(MDefinition *num) : MUnaryInstruction(num) { setResultType(MIRType_Int32); + setPolicyType(MIRType_Double); setMovable(); } @@ -7616,6 +7617,15 @@ class MFloor TypePolicy *typePolicy() { return this; } + bool isFloat32Commutative() const { + return true; + } + void trySpecializeFloat32(); +#ifdef DEBUG + bool isConsistentFloat32Use() const { + return true; + } +#endif }; // Inlined version of Math.round(). diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index c41e7d91d97..9a881340b27 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -1202,6 +1202,18 @@ CodeGeneratorARM::visitFloor(LFloor *lir) return true; } +bool +CodeGeneratorARM::visitFloorF(LFloorF *lir) +{ + FloatRegister input = ToFloatRegister(lir->input()); + Register output = ToRegister(lir->output()); + Label bail; + masm.floorf(input, output, &bail); + if (!bailoutFrom(&bail, lir->snapshot())) + return false; + return true; +} + bool CodeGeneratorARM::visitRound(LRound *lir) { diff --git a/js/src/jit/arm/CodeGenerator-arm.h b/js/src/jit/arm/CodeGenerator-arm.h index c53c17a99c4..712cafbfd1b 100644 --- a/js/src/jit/arm/CodeGenerator-arm.h +++ b/js/src/jit/arm/CodeGenerator-arm.h @@ -110,6 +110,7 @@ class CodeGeneratorARM : public CodeGeneratorShared virtual bool visitMathD(LMathD *math); virtual bool visitMathF(LMathF *math); virtual bool visitFloor(LFloor *lir); + virtual bool visitFloorF(LFloorF *lir); virtual bool visitRound(LRound *lir); virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins); virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins); diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 4ca8879860d..bb4089e3996 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -3830,6 +3830,58 @@ MacroAssemblerARMCompat::floor(FloatRegister input, Register output, Label *bail bind(&fin); } +void +MacroAssemblerARMCompat::floorf(FloatRegister input, Register output, Label *bail) +{ + Label handleZero; + Label handleNeg; + Label fin; + compareFloat(input, InvalidFloatReg); + ma_b(&handleZero, Assembler::Equal); + ma_b(&handleNeg, Assembler::Signed); + // NaN is always a bail condition, just bail directly. + ma_b(bail, Assembler::Overflow); + + // The argument is a positive number, truncation is the path to glory; + // Since it is known to be > 0.0, explicitly convert to a larger range, + // then a value that rounds to INT_MAX is explicitly different from an + // argument that clamps to INT_MAX + ma_vcvt_F32_U32(input, ScratchFloatReg); + ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output); + ma_mov(output, output, SetCond); + ma_b(bail, Signed); + ma_b(&fin); + + bind(&handleZero); + // Move the top word of the double into the output reg, if it is non-zero, + // then the original value was -0.0 + as_vxfer(output, InvalidReg, VFPRegister(input).singleOverlay(), FloatToCore, Always, 0); + ma_cmp(output, Imm32(0)); + ma_b(bail, NonZero); + ma_b(&fin); + + bind(&handleNeg); + // Negative case, negate, then start dancing + ma_vneg_f32(input, input); + ma_vcvt_F32_U32(input, ScratchFloatReg); + ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output); + ma_vcvt_U32_F32(ScratchFloatReg, ScratchFloatReg); + compareFloat(ScratchFloatReg, input); + ma_add(output, Imm32(1), output, NoSetCond, NotEqual); + // Negate the output. Since INT_MIN < -INT_MAX, even after adding 1, + // the result will still be a negative number + ma_rsb(output, Imm32(0), output, SetCond); + // Flip the negated input back to its original value. + ma_vneg_f32(input, input); + // If the result looks non-negative, then this value didn't actually fit into + // the int range, and special handling is required. + // zero is also caught by this case, but floor of a negative number + // should never be zero. + ma_b(bail, Unsigned); + + bind(&fin); +} + CodeOffsetLabel MacroAssemblerARMCompat::toggledJump(Label *label) { diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index a46eeeda97c..064fc8639f4 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -1435,6 +1435,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM ma_add(dest, Imm32(address.offset), dest, NoSetCond); } void floor(FloatRegister input, Register output, Label *handleNotAnInt); + void floorf(FloatRegister input, Register output, Label *handleNotAnInt); void round(FloatRegister input, Register output, Label *handleNotAnInt, FloatRegister tmp); void clampCheck(Register r, Label *handleNotAnInt) { diff --git a/js/src/jit/shared/Assembler-x86-shared.h b/js/src/jit/shared/Assembler-x86-shared.h index a88325c38d7..e80bee02f0b 100644 --- a/js/src/jit/shared/Assembler-x86-shared.h +++ b/js/src/jit/shared/Assembler-x86-shared.h @@ -1466,6 +1466,12 @@ class AssemblerX86Shared JS_ASSERT(HasSSE41()); masm.roundsd_rr(src.code(), dest.code(), mode); } + void roundss(const FloatRegister &src, const FloatRegister &dest, + JSC::X86Assembler::RoundingMode mode) + { + JS_ASSERT(HasSSE41()); + masm.roundss_rr(src.code(), dest.code(), mode); + } void minsd(const FloatRegister &src, const FloatRegister &dest) { JS_ASSERT(HasSSE2()); masm.minsd_rr(src.code(), dest.code()); @@ -1528,6 +1534,15 @@ class AssemblerX86Shared MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); } } + void fstp32(const Operand &src) { + switch (src.kind()) { + case Operand::MEM_REG_DISP: + masm.fstp32_m(src.disp(), src.base()); + break; + default: + MOZ_ASSUME_UNREACHABLE("unexpected operand kind"); + } + } // Defined for compatibility with ARM's assembler uint32_t actualOffset(uint32_t x) { diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index 5e63b3e3003..635a6aaacef 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -1448,6 +1448,73 @@ CodeGeneratorX86Shared::visitFloor(LFloor *lir) return true; } +bool +CodeGeneratorX86Shared::visitFloorF(LFloorF *lir) +{ + FloatRegister input = ToFloatRegister(lir->input()); + FloatRegister scratch = ScratchFloatReg; + Register output = ToRegister(lir->output()); + + if (AssemblerX86Shared::HasSSE41()) { + // Bail on negative-zero. + Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output); + if (!bailoutIf(bailCond, lir->snapshot())) + return false; + + // Round toward -Infinity. + masm.roundss(input, scratch, JSC::X86Assembler::RoundDown); + + masm.cvttss2si(scratch, output); + masm.cmp32(output, Imm32(INT_MIN)); + if (!bailoutIf(Assembler::Equal, lir->snapshot())) + return false; + } else { + Label negative, end; + + // Branch to a slow path for negative inputs. Doesn't catch NaN or -0. + masm.xorps(scratch, scratch); + masm.branchFloat(Assembler::DoubleLessThan, input, scratch, &negative); + + // Bail on negative-zero. + Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output); + if (!bailoutIf(bailCond, lir->snapshot())) + return false; + + // Input is non-negative, so truncation correctly rounds. + masm.cvttss2si(input, output); + masm.cmp32(output, Imm32(INT_MIN)); + if (!bailoutIf(Assembler::Equal, lir->snapshot())) + return false; + + masm.jump(&end); + + // Input is negative, but isn't -0. + // Negative values go on a comparatively expensive path, since no + // native rounding mode matches JS semantics. Still better than callVM. + masm.bind(&negative); + { + // Truncate and round toward zero. + // This is off-by-one for everything but integer-valued inputs. + masm.cvttss2si(input, output); + masm.cmp32(output, Imm32(INT_MIN)); + if (!bailoutIf(Assembler::Equal, lir->snapshot())) + return false; + + // Test whether the input double was integer-valued. + masm.convertInt32ToFloat32(output, scratch); + masm.branchFloat(Assembler::DoubleEqualOrUnordered, input, scratch, &end); + + // Input is not integer-valued, so we rounded off-by-one in the + // wrong direction. Correct by subtraction. + masm.subl(Imm32(1), output); + // Cannot overflow: output was already checked against INT_MIN. + } + + masm.bind(&end); + } + return true; +} + bool CodeGeneratorX86Shared::visitRound(LRound *lir) { diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.h b/js/src/jit/shared/CodeGenerator-x86-shared.h index 899652d2d74..9efbc8fdad4 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.h +++ b/js/src/jit/shared/CodeGenerator-x86-shared.h @@ -114,6 +114,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared virtual bool visitMathD(LMathD *math); virtual bool visitMathF(LMathF *math); virtual bool visitFloor(LFloor *lir); + virtual bool visitFloorF(LFloorF *lir); virtual bool visitRound(LRound *lir); virtual bool visitGuardShape(LGuardShape *guard); virtual bool visitGuardObjectType(LGuardObjectType *guard); diff --git a/js/src/jit/x64/MacroAssembler-x64.cpp b/js/src/jit/x64/MacroAssembler-x64.cpp index f949d5bab7d..cf95d88d7f5 100644 --- a/js/src/jit/x64/MacroAssembler-x64.cpp +++ b/js/src/jit/x64/MacroAssembler-x64.cpp @@ -364,3 +364,11 @@ MacroAssemblerX64::testNegativeZero(const FloatRegister ®, const Register &sc cmpq(scratch, Imm32(1)); return Overflow; } + +Assembler::Condition +MacroAssemblerX64::testNegativeZeroFloat32(const FloatRegister ®, const Register &scratch) +{ + movd(reg, scratch); + cmpl(scratch, Imm32(1)); + return Overflow; +} diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index 4e6794f48a1..081a8f1d9a8 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -81,7 +81,8 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared enum Result { GENERAL, - DOUBLE + DOUBLE, + FLOAT }; typedef MoveResolver::MoveOperand MoveOperand; @@ -466,6 +467,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared } Condition testNegativeZero(const FloatRegister ®, const Register &scratch); + Condition testNegativeZeroFloat32(const FloatRegister ®, const Register &scratch); ///////////////////////////////////////////////////////////////// // Common interface. diff --git a/js/src/jit/x86/MacroAssembler-x86.cpp b/js/src/jit/x86/MacroAssembler-x86.cpp index 3d2c3bbbfe1..77b9a16ccf5 100644 --- a/js/src/jit/x86/MacroAssembler-x86.cpp +++ b/js/src/jit/x86/MacroAssembler-x86.cpp @@ -239,6 +239,12 @@ MacroAssemblerX86::callWithABIPost(uint32_t stackAdjust, Result result) loadDouble(Operand(esp, 0), ReturnFloatReg); freeStack(sizeof(double)); } + if (result == FLOAT) { + reserveStack(sizeof(float)); + fstp32(Operand(esp, 0)); + loadFloat(Operand(esp, 0), ReturnFloatReg); + freeStack(sizeof(float)); + } if (dynamicAlignment_) pop(esp); @@ -401,3 +407,11 @@ MacroAssemblerX86::testNegativeZero(const FloatRegister ®, const Register &sc bind(&nonZero); return Zero; } + +Assembler::Condition +MacroAssemblerX86::testNegativeZeroFloat32(const FloatRegister ®, const Register &scratch) +{ + movd(reg, scratch); + cmpl(scratch, Imm32(1)); + return Overflow; +} diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 767c3e470b2..b13516f4cc2 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -72,7 +72,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared enum Result { GENERAL, - DOUBLE + DOUBLE, + FLOAT }; typedef MoveResolver::MoveOperand MoveOperand; @@ -499,6 +500,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared } Condition testNegativeZero(const FloatRegister ®, const Register &scratch); + Condition testNegativeZeroFloat32(const FloatRegister ®, const Register &scratch); ///////////////////////////////////////////////////////////////// // Common interface. From db72f294d32bfd15e5ecfe32d5e3f13dfd332990 Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Mon, 28 Oct 2013 04:52:00 +0000 Subject: [PATCH 03/51] Bug 929297 - Part 1: AddonManager should refuse to run in child processes. r=Unfocused --- toolkit/mozapps/extensions/AddonManager.jsm | 13 ++++++++++++ .../test/xpcshell/test_childprocess.js | 21 +++++++++++++++++++ .../test/xpcshell/xpcshell-shared.ini | 1 + 3 files changed, 35 insertions(+) create mode 100644 toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 91f547425e3..ed4311bd444 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -9,6 +9,19 @@ const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; +// Cannot use Services.appinfo here, or else xpcshell-tests will blow up, as +// most tests later register different nsIAppInfo implementations, which +// wouldn't be reflected in Services.appinfo anymore, as the lazy getter +// underlying it would have been initialized if we used it here. +if ("@mozilla.org/xre/app-info;1" in Cc) { + let runtime = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime); + if (runtime.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) { + // Refuse to run in child processes. + throw new Error("You cannot use the AddonManager in child processes!"); + } +} + + const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion"; const PREF_EM_UPDATE_ENABLED = "extensions.update.enabled"; const PREF_EM_LAST_APP_VERSION = "extensions.lastAppVersion"; diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js b/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js new file mode 100644 index 00000000000..a6c635eac4f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_childprocess.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +// This verifies that the AddonManager refuses to load in child processes. + +function run_test() { + // Already loaded the module by head_addons.js. Need to unload this again, so + // that overriding the app-info and re-importing the module works. + Components.utils.unload("resource://gre/modules/AddonManager.jsm"); + createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); + gAppInfo.processType = AM_Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT; + try { + Components.utils.import("resource://gre/modules/AddonManager.jsm"); + do_throw("AddonManager should have refused to load"); + } + catch (ex) { + do_print(ex.message); + do_check_true(!!ex.message); + } +} diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini index 541da136a1d..b1187eb9c8d 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini @@ -141,6 +141,7 @@ fail-if = os == "android" [test_bug757663.js] [test_cacheflush.js] [test_checkcompatibility.js] +[test_childprocess.js] [test_ChromeManifestParser.js] [test_compatoverrides.js] [test_corrupt.js] From 429701a91264ef2f1bcb822f19c5f13cebc6dae5 Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Mon, 28 Oct 2013 04:53:00 +0000 Subject: [PATCH 04/51] Bug 929297 - Part 2: Avoid calling amIAddonManager in reporters off the main process. r=njn --- dom/base/nsWindowMemoryReporter.cpp | 7 +++++-- dom/workers/WorkerPrivate.cpp | 5 +++++ js/xpconnect/src/XPCJSRuntime.cpp | 14 ++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 087c2aefa9b..e60754f4c72 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -484,8 +484,11 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb, // Collect window memory usage. nsWindowSizes windowTotalSizes(NULL); - nsCOMPtr addonManager = - do_GetService("@mozilla.org/addons/integration;1"); + nsCOMPtr addonManager; + if (XRE_GetProcessType() == GeckoProcessType_Default) { + // Only try to access the service from the main process. + addonManager = do_GetService("@mozilla.org/addons/integration;1"); + } for (uint32_t i = 0; i < windows.Length(); i++) { rv = CollectWindowReports(windows[i], addonManager, &windowTotalSizes, &ghostWindows, diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 1957081c141..1d6c2a34cd6 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -1990,6 +1990,11 @@ private: mAlreadyMappedToAddon = true; + if (XRE_GetProcessType() != GeckoProcessType_Default) { + // Only try to access the service from the main process. + return; + } + nsAutoCString addonId; bool ok; nsCOMPtr addonManager = diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index d961782c438..e3b61f4bec9 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -2366,8 +2366,11 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, nsIMemoryReporterCallback *cb, nsISupports *closure, size_t *rtTotalOut) { - nsCOMPtr am = - do_GetService("@mozilla.org/addons/integration;1"); + nsCOMPtr am; + if (XRE_GetProcessType() == GeckoProcessType_Default) { + // Only try to access the service from the main process. + am = do_GetService("@mozilla.org/addons/integration;1"); + } return ReportJSRuntimeExplicitTreeStats(rtStats, rtPath, am.get(), cb, closure, rtTotalOut); } @@ -2604,8 +2607,11 @@ JSReporter::CollectReports(WindowPaths *windowPaths, // callback may be a JS function, and executing JS while getting these // stats seems like a bad idea. - nsCOMPtr addonManager = - do_GetService("@mozilla.org/addons/integration;1"); + nsCOMPtr addonManager; + if (XRE_GetProcessType() == GeckoProcessType_Default) { + // Only try to access the service from the main process. + addonManager = do_GetService("@mozilla.org/addons/integration;1"); + } bool getLocations = !!addonManager; XPCJSRuntimeStats rtStats(windowPaths, topWindowPaths, getLocations); OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject); From 683730b5d9100d34efce5a5a79e9093fb231ab98 Mon Sep 17 00:00:00 2001 From: Bill Gianopoulos Date: Sat, 26 Oct 2013 20:42:34 -0400 Subject: [PATCH 05/51] Bug 931428 - Include NullPtr.h in GStreamerLoader.cpp; r=ehsan --- content/media/gstreamer/GStreamerLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/content/media/gstreamer/GStreamerLoader.cpp b/content/media/gstreamer/GStreamerLoader.cpp index b8d6fdc7ad4..5961b23198b 100644 --- a/content/media/gstreamer/GStreamerLoader.cpp +++ b/content/media/gstreamer/GStreamerLoader.cpp @@ -7,6 +7,7 @@ #include #include "GStreamerLoader.h" +#include "mozilla/NullPtr.h" #define LIBGSTREAMER 0 #define LIBGSTAPP 1 From 7b51758e7aff3d4be7065bdd6fa7a6ec9731d82a Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Mon, 28 Oct 2013 10:04:12 -0400 Subject: [PATCH 06/51] Bug 784739 - Switch from NULL to nullptr in dom/ (1/2); r=ehsan --- dom/base/Navigator.cpp | 2 +- dom/base/nsDOMClassInfo.cpp | 2 +- dom/base/nsDOMJSUtils.h | 6 ++--- dom/base/nsFocusManager.cpp | 2 +- dom/base/nsFocusManager.h | 2 +- dom/base/nsGlobalWindow.cpp | 18 +++++++------- dom/base/nsJSEnvironment.cpp | 9 +++---- dom/base/nsJSTimeoutHandler.cpp | 2 +- dom/base/nsWindowMemoryReporter.cpp | 8 +++--- dom/base/nsWindowMemoryReporter.h | 2 +- dom/bindings/BindingDeclarations.h | 2 +- dom/bindings/BindingUtils.cpp | 25 ++++++++++--------- dom/bindings/BindingUtils.h | 6 ++--- dom/bindings/DOMJSProxyHandler.cpp | 5 ++-- dom/bluetooth/BluetoothService.h | 2 +- dom/bluetooth/BluetoothUtils.cpp | 2 +- dom/bluetooth/ObexBase.cpp | 2 +- dom/bluetooth/linux/BluetoothDBusService.cpp | 26 ++++++++++---------- dom/browser-element/BrowserElementParent.cpp | 2 +- dom/ipc/ContentChild.cpp | 10 ++++---- dom/ipc/ContentParent.cpp | 22 ++++++++--------- dom/ipc/CrashReporterParent.cpp | 2 +- dom/ipc/CrashReporterParent.h | 2 +- dom/ipc/TabChild.cpp | 6 ++--- dom/ipc/TabParent.cpp | 2 +- dom/media/bridge/MediaModule.cpp | 6 ++--- 26 files changed, 88 insertions(+), 87 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 6938ea3cea5..c9f9bd8b337 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -656,7 +656,7 @@ VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent) nsCOMPtr window = do_QueryReferent(mWindow); hal::CancelVibrate(window); RemoveListener(); - gVibrateWindowListener = NULL; + gVibrateWindowListener = nullptr; // Careful: The line above might have deleted |this|! } diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index a37c0a2d6e2..58584daef02 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -3606,7 +3606,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, } // Handle resolving if id refers to a name resolved by DOM worker code. - JS::Rooted tmp(cx, NULL); + JS::Rooted tmp(cx, nullptr); if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) { return NS_ERROR_FAILURE; } diff --git a/dom/base/nsDOMJSUtils.h b/dom/base/nsDOMJSUtils.h index 1f7e9d5909a..3d1d1ab5a62 100644 --- a/dom/base/nsDOMJSUtils.h +++ b/dom/base/nsDOMJSUtils.h @@ -37,9 +37,9 @@ JSObject* GetDefaultScopeFromJSContext(JSContext *cx); // ((JS::Value*)aArgv)[0], ..., ((JS::Value*)aArgv)[aArgc - 1] // The resulting object will take a copy of the array, and ensure each // element is rooted. -// Optionally, aArgv may be NULL, in which case the array is allocated and -// rooted, but all items remain NULL. This presumably means the caller will -// then QI us for nsIJSArgArray, and set our array elements. +// Optionally, aArgv may be nullptr, in which case the array is allocated and +// rooted, but all items remain nullptr. This presumably means the caller +// will then QI us for nsIJSArgArray, and set our array elements. nsresult NS_CreateJSArgv(JSContext *aContext, uint32_t aArgc, void *aArgv, nsIJSArgArray **aArray); diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index d2d0a20b86c..a3f7d1bccfa 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -145,7 +145,7 @@ static const char* kObservedPrefs[] = { "accessibility.tabfocus_applies_to_xul", "accessibility.mouse_focuses_formcontrol", "focusmanager.testmode", - NULL + nullptr }; nsFocusManager::nsFocusManager() diff --git a/dom/base/nsFocusManager.h b/dom/base/nsFocusManager.h index 17e332391a1..ffadbfa426e 100644 --- a/dom/base/nsFocusManager.h +++ b/dom/base/nsFocusManager.h @@ -518,7 +518,7 @@ private: // When a mouse down event process is finished, ESM sets focus to the target // content. Therefore, while DOM event handlers are handling mouse down // events, the handlers should be able to steal focus from any elements even - // if focus is in chrome content. So, if this isn't NULL and the caller + // if focus is in chrome content. So, if this isn't nullptr and the caller // can access the document node, the caller should succeed in moving focus. nsCOMPtr mMouseDownEventHandlingDocument; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8a507e17b14..527a9773180 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -676,7 +676,7 @@ nsOuterWindowProxy::preventExtensions(JSContext *cx, JS::Handle proxy) { // See above. - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CHANGE_EXTENSIBILITY); return false; } @@ -1222,7 +1222,7 @@ nsGlobalWindow::~nsGlobalWindow() if (IsOuterWindow()) { JSObject *proxy = GetWrapperPreserveColor(); if (proxy) { - js::SetProxyExtra(proxy, 0, js::PrivateValue(NULL)); + js::SetProxyExtra(proxy, 0, js::PrivateValue(nullptr)); } // An outer window is destroyed with inner windows still possibly @@ -2115,7 +2115,7 @@ CreateNativeGlobalForInner(JSContext* aCx, MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aHolder); - nsGlobalWindow *top = NULL; + nsGlobalWindow *top = nullptr; if (aNewInner->GetOuterWindow()) { top = aNewInner->GetTop(); } @@ -2396,7 +2396,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, return NS_ERROR_FAILURE; } - js::SetProxyExtra(mJSObject, 0, js::PrivateValue(NULL)); + js::SetProxyExtra(mJSObject, 0, js::PrivateValue(nullptr)); JS::Rooted obj(cx, mJSObject); outerObject = xpc::TransplantObject(cx, obj, outerObject); @@ -3133,7 +3133,7 @@ void nsGlobalWindow::OnFinalize(JSObject* aObject) { if (aObject == mJSObject) { - mJSObject = NULL; + mJSObject = nullptr; } } @@ -5618,7 +5618,7 @@ nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust) pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), this, getter_AddRefs(mWakeLock)); } else if (mWakeLock && !mFullScreen) { mWakeLock->Unlock(); - mWakeLock = NULL; + mWakeLock = nullptr; } return NS_OK; @@ -10441,7 +10441,7 @@ nsGlobalWindow::ShowSlowScriptDialog() } } - // GetStringFromName can return NS_OK and still give NULL string + // GetStringFromName can return NS_OK and still give nullptr string if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton || (!debugButton && debugPossible) || !neverShowDlg) { NS_ERROR("Failed to get localized strings."); @@ -10956,7 +10956,7 @@ nsGlobalWindow::GetParentInternal() return parent; } - return NULL; + return nullptr; } void @@ -12697,7 +12697,7 @@ nsGlobalWindow::SyncGamepadState() { FORWARD_TO_INNER_VOID(SyncGamepadState, ()); if (mHasSeenGamepadInput) { - mGamepads.EnumerateRead(EnumGamepadsForSync, NULL); + mGamepads.EnumerateRead(EnumGamepadsForSync, nullptr); } } #endif diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 8f3265f02b5..b2576ffe4fd 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1062,7 +1062,7 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, rv = NS_ERROR_OUT_OF_MEMORY; } } else { - funobj = NULL; + funobj = nullptr; } aBoundHandler.set(funobj); @@ -1187,9 +1187,8 @@ nsJSContext::SetProperty(JS::Handle aTarget, const char* aPropName, n } JS::Value vargs = OBJECT_TO_JSVAL(args); - return JS_DefineProperty(mContext, aTarget, aPropName, vargs, NULL, NULL, 0) - ? NS_OK - : NS_ERROR_FAILURE; + return JS_DefineProperty(mContext, aTarget, aPropName, vargs, + nullptr, nullptr, 0) ? NS_OK : NS_ERROR_FAILURE; } nsresult @@ -2519,7 +2518,7 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::GCProgress aProgress, const JS::GCDescrip if (!sShuttingDown) { CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer); sInterSliceGCTimer->InitWithFuncCallback(InterSliceGCTimerFired, - NULL, + nullptr, NS_INTERSLICE_GC_DELAY, nsITimer::TYPE_ONE_SHOT); } diff --git a/dom/base/nsJSTimeoutHandler.cpp b/dom/base/nsJSTimeoutHandler.cpp index 7bc69d45c0a..3cc8311999f 100644 --- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -93,7 +93,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler) JS_GetObjectFunction(js::UncheckedUnwrap(tmp->mFunction->Callable())); if (fun && JS_GetFunctionId(fun)) { JSFlatString *funId = JS_ASSERT_STRING_IS_FLAT(JS_GetFunctionId(fun)); - size_t size = 1 + JS_PutEscapedFlatString(NULL, 0, funId, 0); + size_t size = 1 + JS_PutEscapedFlatString(nullptr, 0, funId, 0); char *funIdName = new char[size]; if (funIdName) { JS_PutEscapedFlatString(funIdName, size, funId, 0); diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index e60754f4c72..daa97ed1847 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -100,7 +100,7 @@ nsWindowMemoryReporter::Init() nsCOMPtr os = services::GetObserverService(); if (os) { // DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment", - // when a window's docshell is set to NULL. + // when a window's docshell is set to nullptr. os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC, /* weakRef = */ true); os->AddObserver(sWindowReporter, "after-minimize-memory-usage", @@ -185,7 +185,7 @@ CollectWindowReports(nsGlobalWindow *aWindow, // Avoid calling aWindow->GetTop() if there's no outer window. It will work // just fine, but will spew a lot of warnings. - nsGlobalWindow *top = NULL; + nsGlobalWindow *top = nullptr; nsCOMPtr location; if (aWindow->GetOuterWindow()) { // Our window should have a null top iff it has a null docshell. @@ -483,7 +483,7 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb, WindowPaths topWindowPaths; // Collect window memory usage. - nsWindowSizes windowTotalSizes(NULL); + nsWindowSizes windowTotalSizes(nullptr); nsCOMPtr addonManager; if (XRE_GetProcessType() == GeckoProcessType_Default) { // Only try to access the service from the main process. @@ -775,7 +775,7 @@ GetNonDetachedWindowDomainsEnumerator(const uint64_t& aId, nsGlobalWindow* aWind */ void nsWindowMemoryReporter::CheckForGhostWindows( - nsTHashtable *aOutGhostIDs /* = NULL */) + nsTHashtable *aOutGhostIDs /* = nullptr */) { nsCOMPtr tldService = do_GetService( NS_EFFECTIVETLDSERVICE_CONTRACTID); diff --git a/dom/base/nsWindowMemoryReporter.h b/dom/base/nsWindowMemoryReporter.h index 2f38343c894..dbf38084f06 100644 --- a/dom/base/nsWindowMemoryReporter.h +++ b/dom/base/nsWindowMemoryReporter.h @@ -202,7 +202,7 @@ private: * This is called asynchronously after we observe a DOM window being detached * from its docshell, and also right before we generate a memory report. */ - void CheckForGhostWindows(nsTHashtable *aOutGhostIDs = NULL); + void CheckForGhostWindows(nsTHashtable *aOutGhostIDs = nullptr); /** * Maps a weak reference to a detached window (nsIWeakReference) to the time diff --git a/dom/bindings/BindingDeclarations.h b/dom/bindings/BindingDeclarations.h index 5c28363ebba..482aebf7a71 100644 --- a/dom/bindings/BindingDeclarations.h +++ b/dom/bindings/BindingDeclarations.h @@ -459,7 +459,7 @@ GetWrapperCache(nsGlobalWindow*) inline nsWrapperCache* GetWrapperCache(void* p) { - return NULL; + return nullptr; } // Helper template for smart pointers to resolve ambiguity between diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index 227ace74897..e97b26c2353 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -263,7 +263,7 @@ DefineConstants(JSContext* cx, JS::Handle obj, { for (; cs->name; ++cs) { bool ok = - JS_DefineProperty(cx, obj, cs->name, cs->value, NULL, NULL, + JS_DefineProperty(cx, obj, cs->name, cs->value, nullptr, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); if (!ok) { return false; @@ -329,8 +329,8 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp) JS::Rooted callee(cx, &args.callee()); if (!args.thisv().isObject()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO, - "null", "object"); + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, + JSMSG_CANT_CONVERT_TO, "null", "object"); return false; } @@ -344,7 +344,8 @@ InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp) const jschar* name = JS_GetInternedStringCharsAndLength(jsname, &length); if (js::GetObjectJSClass(&args.thisv().toObject()) != clasp) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, + JSMSG_INCOMPATIBLE_PROTO, NS_ConvertUTF16toUTF8(name).get(), "toString", "object"); return false; @@ -429,7 +430,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle global, ctorNargs); } if (!constructor) { - return NULL; + return nullptr; } if (constructorClass) { @@ -441,12 +442,12 @@ CreateInterfaceObject(JSContext* cx, JS::Handle global, InterfaceObjectToString, 0, 0)); if (!toString) { - return NULL; + return nullptr; } JSString *str = ::JS_InternString(cx, name); if (!str) { - return NULL; + return nullptr; } JSObject* toStringObj = JS_GetFunctionObject(toString); js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT, @@ -457,7 +458,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle global, if (!JS_DefineProperty(cx, constructor, "length", JS::Int32Value(ctorNargs), nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) { - return NULL; + return nullptr; } } @@ -497,7 +498,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle global, } if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) { - return NULL; + return nullptr; } if (defineOnGlobal && !DefineConstructor(cx, global, name, constructor)) { @@ -558,7 +559,7 @@ CreateInterfacePrototypeObject(JSContext* cx, JS::Handle global, JS::Rooted ourProto(cx, JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global)); if (!ourProto) { - return NULL; + return nullptr; } if (properties) { @@ -703,8 +704,8 @@ NativeInterface2JSObjectAndThrowIfFailed(JSContext* aCx, MOZ_ASSERT(NS_IsMainThread()); - if (!XPCConvert::NativeInterface2JSObject(aRetval, NULL, aHelper, aIID, - NULL, aAllowNativeWrapper, &rv)) { + if (!XPCConvert::NativeInterface2JSObject(aRetval, nullptr, aHelper, aIID, + nullptr, aAllowNativeWrapper, &rv)) { // I can't tell if NativeInterface2JSObject throws JS exceptions // or not. This is a sloppy stab at the right semantics; the // method really ought to be fixed to behave consistently. diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 75c7884473b..2d520a98472 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -1032,7 +1032,7 @@ inline bool WrapObject(JSContext* cx, JS::Handle scope, T* p, JS::MutableHandle rval) { - return WrapObject(cx, scope, p, NULL, rval); + return WrapObject(cx, scope, p, nullptr, rval); } // Helper to make it possible to wrap directly out of an nsCOMPtr @@ -1050,7 +1050,7 @@ inline bool WrapObject(JSContext* cx, JS::Handle scope, const nsCOMPtr& p, JS::MutableHandle rval) { - return WrapObject(cx, scope, p, NULL, rval); + return WrapObject(cx, scope, p, nullptr, rval); } // Helper to make it possible to wrap directly out of an nsRefPtr @@ -1068,7 +1068,7 @@ inline bool WrapObject(JSContext* cx, JS::Handle scope, const nsRefPtr& p, JS::MutableHandle rval) { - return WrapObject(cx, scope, p, NULL, rval); + return WrapObject(cx, scope, p, nullptr, rval); } // Specialization to make it easy to use WrapObject in codegen. diff --git a/dom/bindings/DOMJSProxyHandler.cpp b/dom/bindings/DOMJSProxyHandler.cpp index 420ee6f84e8..3bb3185d181 100644 --- a/dom/bindings/DOMJSProxyHandler.cpp +++ b/dom/bindings/DOMJSProxyHandler.cpp @@ -154,7 +154,8 @@ bool DOMProxyHandler::preventExtensions(JSContext *cx, JS::Handle proxy) { // Throw a TypeError, per WebIDL. - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY); + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, + JSMSG_CANT_CHANGE_EXTENSIBILITY); return false; } @@ -192,7 +193,7 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle proxy, JS:: return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT | JSREPORT_STRICT_MODE_ERROR, - js_GetErrorMessage, NULL, + js_GetErrorMessage, nullptr, JSMSG_GETTER_ONLY); } diff --git a/dom/bluetooth/BluetoothService.h b/dom/bluetooth/BluetoothService.h index 4aa1c412849..fc22a85804c 100644 --- a/dom/bluetooth/BluetoothService.h +++ b/dom/bluetooth/BluetoothService.h @@ -117,7 +117,7 @@ public: * Returns the path of the default adapter, implemented via a platform * specific method. * - * @return Default adapter path/name on success, NULL otherwise + * @return NS_OK on success, NS_ERROR_FAILURE otherwise */ virtual nsresult GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0; diff --git a/dom/bluetooth/BluetoothUtils.cpp b/dom/bluetooth/BluetoothUtils.cpp index 32422b5b1ab..17a39642a9e 100644 --- a/dom/bluetooth/BluetoothUtils.cpp +++ b/dom/bluetooth/BluetoothUtils.cpp @@ -111,7 +111,7 @@ BroadcastSystemMessage(const nsAString& aType, NS_ASSERTION(!::JS_IsExceptionPending(cx), "Shouldn't get here when an exception is pending!"); - JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL)); + JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr)); if (!obj) { BT_WARNING("Failed to new JSObject for system message!"); return false; diff --git a/dom/bluetooth/ObexBase.cpp b/dom/bluetooth/ObexBase.cpp index 0b643d35f1b..a11026b6a93 100644 --- a/dom/bluetooth/ObexBase.cpp +++ b/dom/bluetooth/ObexBase.cpp @@ -95,7 +95,7 @@ ParseHeaders(const uint8_t* aHeaderStart, switch (headerId >> 6) { case 0x00: - // NULL terminated Unicode text, length prefixed with 2-byte + // Null-terminated Unicode text, length prefixed with 2-byte // unsigned integer. case 0x01: // byte sequence, length prefixed with 2 byte unsigned integer. diff --git a/dom/bluetooth/linux/BluetoothDBusService.cpp b/dom/bluetooth/linux/BluetoothDBusService.cpp index 475e406d9c8..1a0469ac726 100644 --- a/dom/bluetooth/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/linux/BluetoothDBusService.cpp @@ -580,7 +580,7 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes, InfallibleTArray& aProperties) { DBusMessageIter prop_val, array_val_iter; - char* property = NULL; + char* property = nullptr; uint32_t array_type; int i, expectedType, receivedType; @@ -942,14 +942,14 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) goto handle_error; } - dbus_connection_send(conn, reply, NULL); + dbus_connection_send(conn, reply, nullptr); dbus_message_unref(reply); v = parameters; } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Authorize")) { // This method gets called when the service daemon needs to authorize a // connection/service request. const char *uuid; - if (!dbus_message_get_args(msg, NULL, + if (!dbus_message_get_args(msg, nullptr, DBUS_TYPE_OBJECT_PATH, &objectPath, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID)) { @@ -987,7 +987,7 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) goto handle_error; } - dbus_connection_send(conn, reply, NULL); + dbus_connection_send(conn, reply, nullptr); dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, @@ -995,7 +995,7 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) // This method gets called when the service daemon needs to confirm a // passkey for an authentication. uint32_t passkey; - if (!dbus_message_get_args(msg, NULL, + if (!dbus_message_get_args(msg, nullptr, DBUS_TYPE_OBJECT_PATH, &objectPath, DBUS_TYPE_UINT32, &passkey, DBUS_TYPE_INVALID)) { @@ -1019,7 +1019,7 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) // This method gets called when the service daemon needs to get the passkey // for an authentication. The return value should be a string of 1-16 // characters length. The string can be alphanumeric. - if (!dbus_message_get_args(msg, NULL, + if (!dbus_message_get_args(msg, nullptr, DBUS_TYPE_OBJECT_PATH, &objectPath, DBUS_TYPE_INVALID)) { errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method"); @@ -1040,7 +1040,7 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) // This method gets called when the service daemon needs to get the passkey // for an authentication. The return value should be a numeric value // between 0-999999. - if (!dbus_message_get_args(msg, NULL, + if (!dbus_message_get_args(msg, nullptr, DBUS_TYPE_OBJECT_PATH, &objectPath, DBUS_TYPE_INVALID)) { errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method"); @@ -1068,7 +1068,7 @@ AgentEventFilter(DBusConnection *conn, DBusMessage *msg, void *data) goto handle_error; } - dbus_connection_send(conn, reply, NULL); + dbus_connection_send(conn, reply, nullptr); dbus_message_unref(reply); // Do not send an notification to upper layer, too annoying. @@ -1138,7 +1138,7 @@ public: if (!dbus_connection_register_object_path(threadConnection->GetConnection(), KEY_REMOTE_AGENT, mAgentVTable, - NULL)) { + nullptr)) { BT_WARNING("%s: Can't register object path %s for remote device agent!", __FUNCTION__, KEY_REMOTE_AGENT); return; @@ -1157,7 +1157,7 @@ public: void Handle(DBusMessage* aReply) { static const DBusObjectPathVTable sAgentVTable = { - NULL, AgentEventFilter, NULL, NULL, NULL, NULL + nullptr, AgentEventFilter, nullptr, nullptr, nullptr, nullptr }; MOZ_ASSERT(!NS_IsMainThread()); // DBus thread @@ -1227,7 +1227,7 @@ private: if (!dbus_connection_register_object_path(threadConnection->GetConnection(), KEY_LOCAL_AGENT, aAgentVTable, - NULL)) { + nullptr)) { BT_WARNING("%s: Can't register object path %s for agent!", __FUNCTION__, KEY_LOCAL_AGENT); return false; @@ -1341,7 +1341,7 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - if (dbus_message_get_path(aMsg) == NULL) { + if (dbus_message_get_path(aMsg) == nullptr) { BT_WARNING("DBusMessage %s has no bluetooth destination, ignoring\n", dbus_message_get_member(aMsg)); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -1664,7 +1664,7 @@ BluetoothDBusService::StartInternal() // Add a filter for all incoming messages_base if (!dbus_connection_add_filter(mConnection->GetConnection(), - EventFilter, NULL, NULL)) { + EventFilter, nullptr, nullptr)) { BT_WARNING("Cannot create DBus Event Filter for DBus Thread!"); return NS_ERROR_FAILURE; } diff --git a/dom/browser-element/BrowserElementParent.cpp b/dom/browser-element/BrowserElementParent.cpp index 17de9033b10..7975dbad73e 100644 --- a/dom/browser-element/BrowserElementParent.cpp +++ b/dom/browser-element/BrowserElementParent.cpp @@ -226,7 +226,7 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow, const nsACString& aFeatures, nsIDOMWindow** aReturnWindow) { - *aReturnWindow = NULL; + *aReturnWindow = nullptr; // If we call window.open from an