Exemple #1
0
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();
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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());
}
Exemple #7
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
static double sign(double x)
{
    if (mozilla::IsNaN(x))
        return GenericNaN();

    return x == 0 ? x : x < 0 ? -1 : 1;
}
Exemple #11
0
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;
}
Exemple #12
0
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;
}
Exemple #13
0
// 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;
    }
}
Exemple #15
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;
}
Exemple #16
0
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;
}
Exemple #17
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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;
}
Exemple #20
0
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;
}
Exemple #22
0
bool
SCInput::readDouble(double *p)
{
    union {
        uint64_t u;
        double d;
    } pun;
    if (!read(&pun.u))
        return false;
    *p = CanonicalizeNaN(pun.d);
    return true;
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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));
}
Exemple #27
0
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;
}
Exemple #28
0
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;
}
Exemple #29
0
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));
        }
    }