bool js::math_hypot(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); bool isInfinite = false; bool isNaN = false; double scale = 0; double sumsq = 1; for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; isInfinite |= mozilla::IsInfinite(x); isNaN |= mozilla::IsNaN(x); double xabs = mozilla::Abs(x); if (scale < xabs) { sumsq = 1 + sumsq * (scale / xabs) * (scale / xabs); scale = xabs; } else if (scale != 0) { sumsq += (xabs / scale) * (xabs / scale); } } double result = isInfinite ? PositiveInfinity() : isNaN ? GenericNaN() : scale * sqrt(sumsq); args.rval().setNumber(result); return true; }
bool js::math_hypot(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); // IonMonkey calls the system hypot function directly if two arguments are // given. Do that here as well to get the same results. if (args.length() == 2) { double x, y; if (!ToNumber(cx, args[0], &x)) return false; if (!ToNumber(cx, args[1], &y)) return false; double result = ecmaHypot(x, y); args.rval().setNumber(result); return true; } bool isInfinite = false; bool isNaN = false; double scale = 0; double sumsq = 1; for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; isInfinite |= mozilla::IsInfinite(x); isNaN |= mozilla::IsNaN(x); double xabs = mozilla::Abs(x); if (scale < xabs) { sumsq = 1 + sumsq * (scale / xabs) * (scale / xabs); scale = xabs; } else if (scale != 0) { sumsq += (xabs / scale) * (xabs / scale); } } double result = isInfinite ? PositiveInfinity() : isNaN ? GenericNaN() : scale * sqrt(sumsq); args.rval().setNumber(result); return true; }
static void TestExponentComponent() { MOZ_ASSERT(ExponentComponent(0.0) == -int_fast16_t(DoubleExponentBias)); MOZ_ASSERT(ExponentComponent(-0.0) == -int_fast16_t(DoubleExponentBias)); MOZ_ASSERT(ExponentComponent(0.125) == -3); MOZ_ASSERT(ExponentComponent(0.5) == -1); MOZ_ASSERT(ExponentComponent(1.0) == 0); MOZ_ASSERT(ExponentComponent(1.5) == 0); MOZ_ASSERT(ExponentComponent(2.0) == 1); MOZ_ASSERT(ExponentComponent(7) == 2); MOZ_ASSERT(ExponentComponent(PositiveInfinity()) == DoubleExponentBias + 1); MOZ_ASSERT(ExponentComponent(NegativeInfinity()) == DoubleExponentBias + 1); MOZ_ASSERT(ExponentComponent(UnspecifiedNaN()) == DoubleExponentBias + 1); }
bool js_math_min(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double minval = PositiveInfinity(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; // Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0 if (x < minval || IsNaN(x) || (x == minval && IsNegativeZero(x))) minval = x; } args.rval().setNumber(minval); return true; }
JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) : JS::shadow::Runtime( #ifdef JSGC_GENERATIONAL &gcStoreBuffer #endif ), mainThread(this), interrupt(0), handlingSignal(false), operationCallback(nullptr), #ifdef JS_THREADSAFE operationCallbackLock(nullptr), operationCallbackOwner(nullptr), #else operationCallbackLockTaken(false), #endif #ifdef JS_WORKER_THREADS workerThreadState(nullptr), exclusiveAccessLock(nullptr), exclusiveAccessOwner(nullptr), mainThreadHasExclusiveAccess(false), numExclusiveThreads(0), #endif systemZone(nullptr), numCompartments(0), localeCallbacks(nullptr), defaultLocale(nullptr), defaultVersion_(JSVERSION_DEFAULT), #ifdef JS_THREADSAFE ownerThread_(nullptr), #endif tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), freeLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE), execAlloc_(nullptr), bumpAlloc_(nullptr), jitRuntime_(nullptr), selfHostingGlobal_(nullptr), nativeStackBase(0), cxCallback(nullptr), destroyCompartmentCallback(nullptr), destroyZoneCallback(nullptr), sweepZoneCallback(nullptr), compartmentNameCallback(nullptr), activityCallback(nullptr), activityCallbackArg(nullptr), #ifdef JS_THREADSAFE requestDepth(0), # ifdef DEBUG checkRequestDepth(0), # endif #endif gcSystemAvailableChunkListHead(nullptr), gcUserAvailableChunkListHead(nullptr), gcBytes(0), gcMaxBytes(0), gcMaxMallocBytes(0), gcNumArenasFreeCommitted(0), gcMarker(this), gcVerifyPreData(nullptr), gcVerifyPostData(nullptr), gcChunkAllocationSinceLastGC(false), gcNextFullGCTime(0), gcLastGCTime(0), gcJitReleaseTime(0), gcAllocationThreshold(30 * 1024 * 1024), gcHighFrequencyGC(false), gcHighFrequencyTimeThreshold(1000), gcHighFrequencyLowLimitBytes(100 * 1024 * 1024), gcHighFrequencyHighLimitBytes(500 * 1024 * 1024), gcHighFrequencyHeapGrowthMax(3.0), gcHighFrequencyHeapGrowthMin(1.5), gcLowFrequencyHeapGrowth(1.5), gcDynamicHeapGrowth(false), gcDynamicMarkSlice(false), gcDecommitThreshold(32 * 1024 * 1024), gcShouldCleanUpEverything(false), gcGrayBitsValid(false), gcIsNeeded(0), gcStats(thisFromCtor()), gcNumber(0), gcStartNumber(0), gcIsFull(false), gcTriggerReason(JS::gcreason::NO_REASON), gcStrictCompartmentChecking(false), #ifdef DEBUG gcDisableStrictProxyCheckingCount(0), #endif gcIncrementalState(gc::NO_INCREMENTAL), gcLastMarkSlice(false), gcSweepOnBackgroundThread(false), gcFoundBlackGrayEdges(false), gcSweepingZones(nullptr), gcZoneGroupIndex(0), gcZoneGroups(nullptr), gcCurrentZoneGroup(nullptr), gcSweepPhase(0), gcSweepZone(nullptr), gcSweepKindIndex(0), gcAbortSweepAfterCurrentGroup(false), gcArenasAllocatedDuringSweep(nullptr), #ifdef DEBUG gcMarkingValidator(nullptr), #endif gcInterFrameGC(0), gcSliceBudget(SliceBudget::Unlimited), gcIncrementalEnabled(true), gcGenerationalEnabled(true), gcManipulatingDeadZones(false), gcObjectsMarkedInDeadZones(0), gcPoke(false), heapState(Idle), #ifdef JSGC_GENERATIONAL gcNursery(thisFromCtor()), gcStoreBuffer(thisFromCtor(), gcNursery), #endif #ifdef JS_GC_ZEAL gcZeal_(0), gcZealFrequency(0), gcNextScheduled(0), gcDeterministicOnly(false), gcIncrementalLimit(0), #endif gcValidate(true), gcFullCompartmentChecks(false), gcCallback(nullptr), gcSliceCallback(nullptr), gcFinalizeCallback(nullptr), gcMallocBytes(0), gcMallocGCTriggered(false), scriptAndCountsVector(nullptr), NaNValue(DoubleNaNValue()), negativeInfinityValue(DoubleValue(NegativeInfinity())), positiveInfinityValue(DoubleValue(PositiveInfinity())), emptyString(nullptr), debugMode(false), spsProfiler(thisFromCtor()), profilingScripts(false), alwaysPreserveCode(false), hadOutOfMemory(false), haveCreatedContext(false), data(nullptr), gcLock(nullptr), gcLockOwner(nullptr), gcHelperThread(thisFromCtor()), signalHandlersInstalled_(false), defaultFreeOp_(thisFromCtor(), false), debuggerMutations(0), securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)), DOMcallbacks(nullptr), destroyPrincipals(nullptr), structuredCloneCallbacks(nullptr), telemetryCallback(nullptr), propertyRemovals(0), #if !EXPOSE_INTL_API thousandsSeparator(0), decimalSeparator(0), numGrouping(0), #endif heapProtected_(false), mathCache_(nullptr), activeCompilations_(0), keepAtoms_(0), trustedPrincipals_(nullptr), atomsCompartment_(nullptr), beingDestroyed_(false), wrapObjectCallback(TransparentObjectWrapper), sameCompartmentWrapObjectCallback(nullptr), preWrapObjectCallback(nullptr), preserveWrapperCallback(nullptr), #ifdef DEBUG noGCOrAllocationCheck(0), #endif jitHardening(false), jitSupportsFloatingPoint(false), ionPcScriptCache(nullptr), threadPool(this), defaultJSContextCallback(nullptr), ctypesActivityCallback(nullptr), parallelWarmup(0), ionReturnOverride_(MagicValue(JS_ARG_POISON)), useHelperThreads_(useHelperThreads), #ifdef JS_THREADSAFE cpuCount_(GetCPUCount()), #else cpuCount_(1), #endif parallelIonCompilationEnabled_(true), parallelParsingEnabled_(true), isWorkerRuntime_(false) #ifdef DEBUG , enteredPolicy(nullptr) #endif { MOZ_ASSERT(cpuCount_ > 0, "GetCPUCount() seems broken"); liveRuntimesCount++; setGCMode(JSGC_MODE_GLOBAL); /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */ JS_INIT_CLIST(&onNewGlobalObjectWatchers); PodZero(&debugHooks); PodZero(&atomState); PodArrayZero(nativeStackQuota); PodZero(&asmJSCacheOps); #if JS_STACK_GROWTH_DIRECTION > 0 nativeStackLimit = UINTPTR_MAX; #endif }
static void TestDoublesAreIdentical() { ShouldBeIdentical(+0.0, +0.0); ShouldBeIdentical(-0.0, -0.0); ShouldNotBeIdentical(+0.0, -0.0); ShouldBeIdentical(1.0, 1.0); ShouldNotBeIdentical(-1.0, 1.0); ShouldBeIdentical(4294967295.0, 4294967295.0); ShouldNotBeIdentical(-4294967295.0, 4294967295.0); ShouldBeIdentical(4294967296.0, 4294967296.0); ShouldBeIdentical(4294967297.0, 4294967297.0); ShouldBeIdentical(1e300, 1e300); ShouldBeIdentical(PositiveInfinity(), PositiveInfinity()); ShouldBeIdentical(NegativeInfinity(), NegativeInfinity()); ShouldNotBeIdentical(PositiveInfinity(), NegativeInfinity()); ShouldNotBeIdentical(-0.0, NegativeInfinity()); ShouldNotBeIdentical(+0.0, NegativeInfinity()); ShouldNotBeIdentical(1e300, NegativeInfinity()); ShouldNotBeIdentical(3.141592654, NegativeInfinity()); ShouldBeIdentical(UnspecifiedNaN(), UnspecifiedNaN()); ShouldBeIdentical(-UnspecifiedNaN(), UnspecifiedNaN()); ShouldBeIdentical(UnspecifiedNaN(), -UnspecifiedNaN()); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 42)); ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(1, 42)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(1, 42)); ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 42)); const uint64_t Mask = 0xfffffffffffffULL; for (unsigned i = 0; i < 52; i++) { for (unsigned j = 0; j < 52; j++) { for (unsigned sign = 0; i < 2; i++) { ShouldBeIdentical(SpecificNaN(0, 1ULL << i), SpecificNaN(sign, 1ULL << j)); ShouldBeIdentical(SpecificNaN(1, 1ULL << i), SpecificNaN(sign, 1ULL << j)); ShouldBeIdentical(SpecificNaN(0, Mask & ~(1ULL << i)), SpecificNaN(sign, Mask & ~(1ULL << j))); ShouldBeIdentical(SpecificNaN(1, Mask & ~(1ULL << i)), SpecificNaN(sign, Mask & ~(1ULL << j))); } } } ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x8000000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x4000000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x2000000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x1000000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0800000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0400000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0200000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0100000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0080000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0040000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0020000000000ULL)); ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0010000000000ULL)); ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0xff0ffffffffffULL)); ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0xfffffffffff0fULL)); ShouldNotBeIdentical(UnspecifiedNaN(), +0.0); ShouldNotBeIdentical(UnspecifiedNaN(), -0.0); ShouldNotBeIdentical(UnspecifiedNaN(), 1.0); ShouldNotBeIdentical(UnspecifiedNaN(), -1.0); ShouldNotBeIdentical(UnspecifiedNaN(), PositiveInfinity()); ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity()); }
static void TestPredicates() { MOZ_ASSERT(IsNaN(UnspecifiedNaN())); MOZ_ASSERT(IsNaN(SpecificNaN(1, 17)));; MOZ_ASSERT(IsNaN(SpecificNaN(0, 0xfffffffffff0fULL))); MOZ_ASSERT(!IsNaN(0)); MOZ_ASSERT(!IsNaN(-0.0)); MOZ_ASSERT(!IsNaN(1.0)); MOZ_ASSERT(!IsNaN(PositiveInfinity())); MOZ_ASSERT(!IsNaN(NegativeInfinity())); MOZ_ASSERT(IsInfinite(PositiveInfinity())); MOZ_ASSERT(IsInfinite(NegativeInfinity())); MOZ_ASSERT(!IsInfinite(UnspecifiedNaN())); MOZ_ASSERT(!IsInfinite(0)); MOZ_ASSERT(!IsInfinite(-0.0)); MOZ_ASSERT(!IsInfinite(1.0)); MOZ_ASSERT(!IsFinite(PositiveInfinity())); MOZ_ASSERT(!IsFinite(NegativeInfinity())); MOZ_ASSERT(!IsFinite(UnspecifiedNaN())); MOZ_ASSERT(IsFinite(0)); MOZ_ASSERT(IsFinite(-0.0)); MOZ_ASSERT(IsFinite(1.0)); MOZ_ASSERT(!IsNegative(PositiveInfinity())); MOZ_ASSERT(IsNegative(NegativeInfinity())); MOZ_ASSERT(IsNegative(-0.0)); MOZ_ASSERT(!IsNegative(0.0)); MOZ_ASSERT(IsNegative(-1.0)); MOZ_ASSERT(!IsNegative(1.0)); MOZ_ASSERT(!IsNegativeZero(PositiveInfinity())); MOZ_ASSERT(!IsNegativeZero(NegativeInfinity())); MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));; MOZ_ASSERT(!IsNegativeZero(SpecificNaN(1, 0xfffffffffff0fULL))); MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));; MOZ_ASSERT(!IsNegativeZero(SpecificNaN(0, 0xfffffffffff0fULL))); MOZ_ASSERT(!IsNegativeZero(UnspecifiedNaN())); MOZ_ASSERT(IsNegativeZero(-0.0)); MOZ_ASSERT(!IsNegativeZero(0.0)); MOZ_ASSERT(!IsNegativeZero(-1.0)); MOZ_ASSERT(!IsNegativeZero(1.0)); int32_t i; MOZ_ASSERT(DoubleIsInt32(0.0, &i)); MOZ_ASSERT(i == 0); MOZ_ASSERT(!DoubleIsInt32(-0.0, &i)); MOZ_ASSERT(DoubleEqualsInt32(0.0, &i)); MOZ_ASSERT(i == 0); MOZ_ASSERT(DoubleEqualsInt32(-0.0, &i)); MOZ_ASSERT(i == 0); MOZ_ASSERT(DoubleIsInt32(INT32_MIN, &i)); MOZ_ASSERT(i == INT32_MIN); MOZ_ASSERT(DoubleIsInt32(INT32_MAX, &i)); MOZ_ASSERT(i == INT32_MAX); MOZ_ASSERT(DoubleEqualsInt32(INT32_MIN, &i)); MOZ_ASSERT(i == INT32_MIN); MOZ_ASSERT(DoubleEqualsInt32(INT32_MAX, &i)); MOZ_ASSERT(i == INT32_MAX); MOZ_ASSERT(!DoubleIsInt32(0.5, &i)); MOZ_ASSERT(!DoubleIsInt32(double(INT32_MAX) + 0.1, &i)); MOZ_ASSERT(!DoubleIsInt32(double(INT32_MIN) - 0.1, &i)); MOZ_ASSERT(!DoubleIsInt32(NegativeInfinity(), &i)); MOZ_ASSERT(!DoubleIsInt32(PositiveInfinity(), &i)); MOZ_ASSERT(!DoubleIsInt32(UnspecifiedNaN(), &i)); MOZ_ASSERT(!DoubleEqualsInt32(0.5, &i)); MOZ_ASSERT(!DoubleEqualsInt32(double(INT32_MAX) + 0.1, &i)); MOZ_ASSERT(!DoubleEqualsInt32(double(INT32_MIN) - 0.1, &i)); MOZ_ASSERT(!DoubleEqualsInt32(NegativeInfinity(), &i)); MOZ_ASSERT(!DoubleEqualsInt32(PositiveInfinity(), &i)); MOZ_ASSERT(!DoubleEqualsInt32(UnspecifiedNaN(), &i)); }