bool LIRGeneratorX86Shared::lowerModI(MMod *mod) { if (mod->isUnsigned()) return lowerUMod(mod); if (mod->rhs()->isConstant()) { int32_t rhs = mod->rhs()->toConstant()->value().toInt32(); int32_t shift = FloorLog2(Abs(rhs)); if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) { LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift); if (mod->fallible() && !assignSnapshot(lir, Bailout_DoubleOutput)) return false; return defineReuseInput(lir, mod, 0); } else if (rhs != 0 && gen->optimizationInfo().registerAllocator() != RegisterAllocator_LSRA) { LDivOrModConstantI *lir; lir = new(alloc()) LDivOrModConstantI(useRegister(mod->lhs()), rhs, tempFixed(edx)); if (mod->fallible() && !assignSnapshot(lir, Bailout_DoubleOutput)) return false; return defineFixed(lir, mod, LAllocation(AnyRegister(eax))); } } LModI *lir = new(alloc()) LModI(useRegister(mod->lhs()), useRegister(mod->rhs()), tempFixed(eax)); if (mod->fallible() && !assignSnapshot(lir, Bailout_DoubleOutput)) return false; return defineFixed(lir, mod, LAllocation(AnyRegister(edx))); }
void LIRGeneratorX86Shared::lowerModI(MMod* mod) { if (mod->isUnsigned()) { lowerUMod(mod); return; } if (mod->rhs()->isConstant()) { int32_t rhs = mod->rhs()->toConstant()->toInt32(); int32_t shift = FloorLog2(Abs(rhs)); if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) { LModPowTwoI* lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift); if (mod->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineReuseInput(lir, mod, 0); return; } if (rhs != 0) { LDivOrModConstantI* lir; lir = new(alloc()) LDivOrModConstantI(useRegister(mod->lhs()), rhs, tempFixed(edx)); if (mod->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineFixed(lir, mod, LAllocation(AnyRegister(eax))); return; } } LModI* lir = new(alloc()) LModI(useRegister(mod->lhs()), useRegister(mod->rhs()), tempFixed(eax)); if (mod->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineFixed(lir, mod, LAllocation(AnyRegister(edx))); }
void LIRGeneratorX86Shared::lowerDivI(MDiv *div) { if (div->isUnsigned()) { lowerUDiv(div); return; } // Division instructions are slow. Division by constant denominators can be // rewritten to use other instructions. if (div->rhs()->isConstant()) { int32_t rhs = div->rhs()->toConstant()->value().toInt32(); // Division by powers of two can be done by shifting, and division by // other numbers can be done by a reciprocal multiplication technique. int32_t shift = FloorLog2(Abs(rhs)); if (rhs != 0 && uint32_t(1) << shift == Abs(rhs)) { LAllocation lhs = useRegisterAtStart(div->lhs()); LDivPowTwoI *lir; if (!div->canBeNegativeDividend()) { // Numerator is unsigned, so does not need adjusting. lir = new(alloc()) LDivPowTwoI(lhs, lhs, shift, rhs < 0); } else { // Numerator is signed, and needs adjusting, and an extra // lhs copy register is needed. lir = new(alloc()) LDivPowTwoI(lhs, useRegister(div->lhs()), shift, rhs < 0); } if (div->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineReuseInput(lir, div, 0); return; } if (rhs != 0 && gen->optimizationInfo().registerAllocator() != RegisterAllocator_LSRA) { LDivOrModConstantI *lir; lir = new(alloc()) LDivOrModConstantI(useRegister(div->lhs()), rhs, tempFixed(eax)); if (div->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineFixed(lir, div, LAllocation(AnyRegister(edx))); return; } } LDivI *lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()), tempFixed(edx)); if (div->fallible()) assignSnapshot(lir, Bailout_DoubleOutput); defineFixed(lir, div, LAllocation(AnyRegister(eax))); }
bool js::math_abs_handle(JSContext *cx, js::HandleValue v, js::MutableHandleValue r) { double x; if (!ToNumber(cx, v, &x)) return false; double z = Abs(x); r.setNumber(z); return true; }
JSBool js_math_abs(JSContext *cx, unsigned argc, Value *vp) { double x, z; if (argc == 0) { vp->setDouble(js_NaN); return JS_TRUE; } if (!ToNumber(cx, vp[2], &x)) return JS_FALSE; z = Abs(x); vp->setNumber(z); return JS_TRUE; }
bool js_math_abs(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNaN(); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; double z = Abs(x); args.rval().setNumber(z); return true; }
/* void seek (in int32_t whence, in int32_t offset); */ NS_IMETHODIMP nsMultiplexInputStream::Seek(int32_t aWhence, int64_t aOffset) { if (NS_FAILED(mStatus)) return mStatus; nsresult rv; uint32_t oldCurrentStream = mCurrentStream; bool oldStartedReadingCurrent = mStartedReadingCurrent; if (aWhence == NS_SEEK_SET) { int64_t remaining = aOffset; if (aOffset == 0) { mCurrentStream = 0; } for (uint32_t i = 0; i < mStreams.Length(); ++i) { nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]); if (!stream) { return NS_ERROR_FAILURE; } // See if all remaining streams should be rewound if (remaining == 0) { if (i < oldCurrentStream || (i == oldCurrentStream && oldStartedReadingCurrent)) { rv = stream->Seek(NS_SEEK_SET, 0); NS_ENSURE_SUCCESS(rv, rv); continue; } else { break; } } // Get position in current stream int64_t streamPos; if (i > oldCurrentStream || (i == oldCurrentStream && !oldStartedReadingCurrent)) { streamPos = 0; } else { rv = stream->Tell(&streamPos); NS_ENSURE_SUCCESS(rv, rv); } // See if we need to seek current stream forward or backward if (remaining < streamPos) { rv = stream->Seek(NS_SEEK_SET, remaining); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = remaining != 0; remaining = 0; } else if (remaining > streamPos) { if (i < oldCurrentStream) { // We're already at end so no need to seek this stream remaining -= streamPos; NS_ASSERTION(remaining >= 0, "Remaining invalid"); } else { uint64_t avail; rv = mStreams[i]->Available(&avail); NS_ENSURE_SUCCESS(rv, rv); int64_t newPos = XPCOM_MIN(remaining, streamPos + (int64_t)avail); rv = stream->Seek(NS_SEEK_SET, newPos); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = true; remaining -= newPos; NS_ASSERTION(remaining >= 0, "Remaining invalid"); } } else { NS_ASSERTION(remaining == streamPos, "Huh?"); remaining = 0; } } return NS_OK; } if (aWhence == NS_SEEK_CUR && aOffset > 0) { int64_t remaining = aOffset; for (uint32_t i = mCurrentStream; remaining && i < mStreams.Length(); ++i) { nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]); uint64_t avail; rv = mStreams[i]->Available(&avail); NS_ENSURE_SUCCESS(rv, rv); int64_t seek = XPCOM_MIN((int64_t)avail, remaining); rv = stream->Seek(NS_SEEK_CUR, seek); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = true; remaining -= seek; } return NS_OK; } if (aWhence == NS_SEEK_CUR && aOffset < 0) { int64_t remaining = -aOffset; for (uint32_t i = mCurrentStream; remaining && i != (uint32_t)-1; --i) { nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]); int64_t pos; rv = stream->Tell(&pos); NS_ENSURE_SUCCESS(rv, rv); int64_t seek = XPCOM_MIN(pos, remaining); rv = stream->Seek(NS_SEEK_CUR, -seek); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = seek != -pos; remaining -= seek; } return NS_OK; } if (aWhence == NS_SEEK_CUR) { NS_ASSERTION(aOffset == 0, "Should have handled all non-zero values"); return NS_OK; } if (aWhence == NS_SEEK_END) { if (aOffset > 0) { return NS_ERROR_INVALID_ARG; } int64_t remaining = aOffset; for (uint32_t i = mStreams.Length() - 1; i != (uint32_t)-1; --i) { nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]); // See if all remaining streams should be seeked to end if (remaining == 0) { if (i >= oldCurrentStream) { rv = stream->Seek(NS_SEEK_END, 0); NS_ENSURE_SUCCESS(rv, rv); } else { break; } } // Get position in current stream int64_t streamPos; if (i < oldCurrentStream) { streamPos = 0; } else { uint64_t avail; rv = mStreams[i]->Available(&avail); NS_ENSURE_SUCCESS(rv, rv); streamPos = avail; } // See if we have enough data in the current stream. if (Abs(remaining) < streamPos) { rv = stream->Seek(NS_SEEK_END, remaining); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = true; remaining = 0; } else if (Abs(remaining) > streamPos) { if (i > oldCurrentStream || (i == oldCurrentStream && !oldStartedReadingCurrent)) { // We're already at start so no need to seek this stream remaining += streamPos; } else { int64_t avail; rv = stream->Tell(&avail); NS_ENSURE_SUCCESS(rv, rv); int64_t newPos = streamPos + XPCOM_MIN(avail, Abs(remaining)); rv = stream->Seek(NS_SEEK_END, -newPos); NS_ENSURE_SUCCESS(rv, rv); mCurrentStream = i; mStartedReadingCurrent = true; remaining += newPos; } } else { NS_ASSERTION(remaining == streamPos, "Huh?"); remaining = 0; } } return NS_OK; } // other Seeks not implemented yet return NS_ERROR_NOT_IMPLEMENTED; }