Module::Module(UniqueModuleData module) : module_(Move(module)), staticallyLinked_(false), interrupt_(nullptr), outOfBounds_(nullptr), dynamicallyLinked_(false), profilingEnabled_(false) { *(double*)(globalData() + NaN64GlobalDataOffset) = GenericNaN(); *(float*)(globalData() + NaN32GlobalDataOffset) = GenericNaN(); }
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<double>() : isNaN ? GenericNaN() : scale * sqrt(sumsq); args.rval().setNumber(result); return true; }
bool js::math_atan2_handle(JSContext *cx, HandleValue y, HandleValue x, MutableHandleValue res) { double dy; if (!ToNumber(cx, y, &dy)) return false; double dx; if (!ToNumber(cx, x, &dx)) return false; double z = ecmaAtan2(dy, dx); res.setDouble(z); return true; }
bool js::math_pow_handle(JSContext *cx, HandleValue base, HandleValue power, MutableHandleValue result) { double x; if (!ToNumber(cx, base, &x)) return false; double y; if (!ToNumber(cx, power, &y)) return false; double z = ecmaPow(x, y); result.setNumber(z); return true; }
bool HashableValue::setValue(JSContext* cx, HandleValue v) { if (v.isString()) { // Atomize so that hash() and operator==() are fast and infallible. JSString* str = AtomizeString(cx, v.toString(), DoNotPinAtom); if (!str) return false; value = StringValue(str); } else if (v.isDouble()) { double d = v.toDouble(); int32_t i; if (NumberEqualsInt32(d, &i)) { // Normalize int32_t-valued doubles to int32_t for faster hashing and testing. value = Int32Value(i); } else if (IsNaN(d)) { // NaNs with different bits must hash and test identically. value = DoubleNaNValue(); } else { value = v; } } else { value = v; } MOZ_ASSERT(value.isUndefined() || value.isNull() || value.isBoolean() || value.isNumber() || value.isString() || value.isSymbol() || value.isObject()); return true; }
bool js::intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); MOZ_ASSERT(args.length() == 3); MOZ_ASSERT(args[0].isObject()); MOZ_ASSERT(args[1].isNumber()); MOZ_ASSERT(args[2].isBoolean()); Rooted<DateTimeFormatObject*> dateTimeFormat(cx); dateTimeFormat = &args[0].toObject().as<DateTimeFormatObject>(); ClippedTime x = TimeClip(args[1].toNumber()); if (!x.isValid()) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DATE_NOT_FINITE); return false; } // Obtain a cached UDateFormat object. void* priv = dateTimeFormat->getReservedSlot(DateTimeFormatObject::UDATE_FORMAT_SLOT).toPrivate(); UDateFormat* df = static_cast<UDateFormat*>(priv); if (!df) { df = NewUDateFormat(cx, dateTimeFormat); if (!df) return false; dateTimeFormat->setReservedSlot(DateTimeFormatObject::UDATE_FORMAT_SLOT, PrivateValue(df)); } // Use the UDateFormat to actually format the time stamp. return args[2].toBoolean() ? intl_FormatToPartsDateTime(cx, df, x, args.rval()) : intl_FormatDateTime(cx, df, x, args.rval()); }
double js::ecmaPow(double x, double y) { /* * Use powi if the exponent is an integer-valued double. We don't have to * check for NaN since a comparison with NaN is always false. */ int32_t yi; if (NumberEqualsInt32(y, &yi)) return powi(x, yi); /* * Because C99 and ECMA specify different behavior for pow(), * we need to wrap the libm call to make it ECMA compliant. */ if (!IsFinite(y) && (x == 1.0 || x == -1.0)) return GenericNaN(); /* pow(x, +-0) is always 1, even for x = NaN (MSVC gets this wrong). */ if (y == 0) return 1; /* * Special case for square roots. Note that pow(x, 0.5) != sqrt(x) * when x = -0.0, so we have to guard for this. */ if (IsFinite(x) && x != 0.0) { if (y == 0.5) return sqrt(x); if (y == -0.5) return 1.0 / sqrt(x); } return pow(x, y); }
/* * new ArrayBuffer(byteLength) */ bool ArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); if (!ThrowIfNotConstructing(cx, args, "ArrayBuffer")) return false; int32_t nbytes = 0; if (argc > 0 && !ToInt32(cx, args[0], &nbytes)) return false; if (nbytes < 0) { /* * We're just not going to support arrays that are bigger than what will fit * as an integer value; if someone actually ever complains (validly), then we * can fix. */ JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH); return false; } RootedObject proto(cx); RootedObject newTarget(cx, &args.newTarget().toObject()); if (!GetPrototypeFromConstructor(cx, newTarget, &proto)) return false; JSObject* bufobj = create(cx, uint32_t(nbytes), proto); if (!bufobj) return false; args.rval().setObject(*bufobj); return true; }
bool /* ES5 15.8.2.15. */ js_math_round(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setDouble(js_NaN); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; int32_t i; if (DoubleIsInt32(x, &i)) { args.rval().setInt32(i); return true; } /* Some numbers are so big that adding 0.5 would give the wrong number. */ if (ExponentComponent(x) >= 52) { args.rval().setNumber(x); return true; } args.rval().setNumber(js_copysign(floor(x + 0.5), x)); return true; }
static double sign(double x) { if (mozilla::IsNaN(x)) return GenericNaN(); return x == 0 ? x : x < 0 ? -1 : 1; }
bool js_math_pow(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double x; if (!ToNumber(cx, args.get(0), &x)) return false; double y; if (!ToNumber(cx, args.get(1), &y)) return false; double z = ecmaPow(x, y); args.rval().setNumber(z); return true; }
bool js::math_atan2(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double y; if (!ToNumber(cx, args.get(0), &y)) return false; double x; if (!ToNumber(cx, args.get(1), &x)) return false; double z = ecmaAtan2(y, x); args.rval().setDouble(z); return true; }
// Implements Math.fround (20.2.2.16) up to step 3 bool js::RoundFloat32(JSContext *cx, HandleValue v, float *out) { double d; bool success = ToNumber(cx, v, &d); *out = static_cast<float>(d); return success; }
static void SetXMMRegToNaN(bool isFloat32, T *xmm_reg) { if (isFloat32) { JS_STATIC_ASSERT(sizeof(T) == 4 * sizeof(float)); float *floats = reinterpret_cast<float*>(xmm_reg); floats[0] = GenericNaN(); floats[1] = 0; floats[2] = 0; floats[3] = 0; } else { JS_STATIC_ASSERT(sizeof(T) == 2 * sizeof(double)); double *dbls = reinterpret_cast<double*>(xmm_reg); dbls[0] = GenericNaN(); dbls[1] = 0; } }
bool js::minmax_impl(JSContext *cx, bool max, HandleValue a, HandleValue b, MutableHandleValue res) { double x, y; if (!ToNumber(cx, a, &x)) return false; if (!ToNumber(cx, b, &y)) return false; if (max) res.setNumber(max_double(x, y)); else res.setNumber(min_double(x, y)); return true; }
bool js::math_atan2(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() <= 1) { args.rval().setDouble(js_NaN); return true; } double x, y; if (!ToNumber(cx, args[0], &x) || !ToNumber(cx, args[1], &y)) return false; double z = ecmaAtan2(x, y); args.rval().setDouble(z); return true; }
bool js::math_hypot_handle(JSContext* cx, HandleValueArray args, MutableHandleValue res) { // 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); res.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); if (isInfinite || isNaN) continue; hypot_step(scale, sumsq, x); } double result = isInfinite ? PositiveInfinity<double>() : isNaN ? GenericNaN() : scale * sqrt(sumsq); res.setNumber(result); return true; }
static bool math_function(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() == 0) { args.rval().setNumber(GenericNaN()); return true; } double x; if (!ToNumber(cx, args[0], &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = F(mathCache, x); args.rval().setNumber(z); return true; }
bool js::math_round_handle(JSContext *cx, HandleValue arg, MutableHandleValue res) { double d; if (!ToNumber(cx, arg, &d)) return false; d = math_round_impl(d); res.setNumber(d); return true; }
bool js::math_ceil_handle(JSContext* cx, HandleValue v, MutableHandleValue res) { double d; if(!ToNumber(cx, v, &d)) return false; double result = math_ceil_impl(d); res.setNumber(result); return true; }
bool TypedElementsHeader<T>::setElement(JSContext *cx, Handle<ObjectImpl*> obj, Handle<ObjectImpl*> receiver, uint32_t index, const Value &v, unsigned resolveFlags, bool *succeeded) { MOZ_ASSERT(this == &obj->elementsHeader()); uint32_t len = length(); if (index >= len) { /* * Silent ignore is better than an exception here, because at some * point we may want to support other properties on these objects. */ *succeeded = true; return true; } /* Convert the value being set to the element type. */ double d; if (v.isNumber()) { d = v.toNumber(); } else if (v.isNull()) { d = 0.0; } else if (v.isPrimitive()) { if (v.isString()) { if (!StringToNumber(cx, v.toString(), &d)) return false; } else if (v.isUndefined()) { d = GenericNaN(); } else { d = double(v.toBoolean()); } } else { // non-primitive assignments become NaN or 0 (for float/int arrays) d = GenericNaN(); } assign(index, d); *succeeded = true; return true; }
bool SCInput::readDouble(double *p) { union { uint64_t u; double d; } pun; if (!read(&pun.u)) return false; *p = CanonicalizeNaN(pun.d); return true; }
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; }
bool js::math_floor_handle(JSContext *cx, HandleValue v, MutableHandleValue r) { double d; if(!ToNumber(cx, v, &d)) return false; double z = math_floor_impl(d); r.setNumber(z); return true; }
bool js_math_pow(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); if (args.length() <= 1) { args.rval().setDouble(js_NaN); return true; } double x, y; if (!ToNumber(cx, args[0], &x) || !ToNumber(cx, args[1], &y)) return false; /* * Special case for square roots. Note that pow(x, 0.5) != sqrt(x) * when x = -0.0, so we have to guard for this. */ if (IsFinite(x) && x != 0.0) { if (y == 0.5) { args.rval().setNumber(sqrt(x)); return true; } if (y == -0.5) { args.rval().setNumber(1.0/sqrt(x)); return true; } } /* pow(x, +-0) is always 1, even for x = NaN. */ if (y == 0) { args.rval().setInt32(1); return true; } double z = ecmaPow(x, y); args.rval().setNumber(z); return true; }
Value SharedTypedArrayObjectTemplate<double>::getIndexValue(JSObject *tarray, uint32_t index) { double val = getIndex(tarray, index); /* * Doubles in typed arrays could be typed-punned arrays of integers. This * could allow user code to break the engine-wide invariant that only * canonical nans are stored into jsvals, which means user code could * confuse the engine into interpreting a double-typed jsval as an * object-typed jsval. */ return DoubleValue(CanonicalizeNaN(val)); }
bool js::math_sqrt_handle(JSContext *cx, HandleValue number, MutableHandleValue result) { double x; if (!ToNumber(cx, number, &x)) return false; MathCache *mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double z = mathCache->lookup(sqrt, x, MathCache::Sqrt); result.setDouble(z); return true; }
bool js::math_sin_handle(JSContext* cx, HandleValue val, MutableHandleValue res) { double in; if (!ToNumber(cx, val, &in)) return false; MathCache* mathCache = cx->runtime()->getMathCache(cx); if (!mathCache) return false; double out = math_sin_impl(mathCache, in); res.setDouble(out); return true; }
bool js::math_min(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double minval = PositiveInfinity<double>(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; minval = min_double(x, minval); } args.rval().setNumber(minval); return true; }
static void setIndexValue(SharedTypedArrayObject& tarray, uint32_t index, double d) { // If the array is an integer array, we only handle up to // 32-bit ints from this point on. if we want to handle // 64-bit ints, we'll need some changes. // Assign based on characteristics of the destination type if (ArrayTypeIsFloatingPoint()) { setIndex(tarray, index, NativeType(d)); } else if (ArrayTypeIsUnsigned()) { MOZ_ASSERT(sizeof(NativeType) <= 4); uint32_t n = ToUint32(d); setIndex(tarray, index, NativeType(n)); } else if (ArrayTypeID() == Scalar::Uint8Clamped) { // The uint8_clamped type has a special rounding converter // for doubles. setIndex(tarray, index, NativeType(d)); } else { MOZ_ASSERT(sizeof(NativeType) <= 4); int32_t n = ToInt32(d); setIndex(tarray, index, NativeType(n)); } }