static bool ValidateConstant(JSContext *cx, AsmJSModule::Global &global, HandleValue globalVal) { RootedPropertyName field(cx, global.constantName()); RootedValue v(cx, globalVal); if (global.constantKind() == AsmJSModule::Global::MathConstant) { if (!GetDataProperty(cx, v, cx->names().Math, &v)) return false; } if (!GetDataProperty(cx, v, field, &v)) return false; if (!v.isNumber()) return LinkFail(cx, "math / global constant value needs to be a number"); // NaN != NaN if (IsNaN(global.constantValue())) { if (!IsNaN(v.toNumber())) return LinkFail(cx, "global constant value needs to be NaN"); } else { if (v.toNumber() != global.constantValue()) return LinkFail(cx, "global constant value mismatch"); } return true; }
static bool GetGlobalExport(JSContext* cx, const GlobalDescVector& globals, uint32_t globalIndex, const ValVector& globalImports, MutableHandleValue jsval) { const GlobalDesc& global = globals[globalIndex]; // Imports are located upfront in the globals array. Val val; switch (global.kind()) { case GlobalKind::Import: val = globalImports[globalIndex]; break; case GlobalKind::Variable: MOZ_CRASH("mutable variables can't be exported"); case GlobalKind::Constant: val = global.constantValue(); break; } switch (global.type()) { case ValType::I32: { jsval.set(Int32Value(val.i32())); return true; } case ValType::I64: { MOZ_ASSERT(JitOptions.wasmTestMode, "no int64 in asm.js/wasm"); RootedObject obj(cx, CreateI64Object(cx, val.i64())); if (!obj) return false; jsval.set(ObjectValue(*obj)); return true; } case ValType::F32: { float f = val.f32(); if (JitOptions.wasmTestMode && IsNaN(f)) { RootedObject obj(cx, CreateCustomNaNObject(cx, &f)); if (!obj) return false; jsval.set(ObjectValue(*obj)); return true; } jsval.set(DoubleValue(double(f))); return true; } case ValType::F64: { double d = val.f64(); if (JitOptions.wasmTestMode && IsNaN(d)) { RootedObject obj(cx, CreateCustomNaNObject(cx, &d)); if (!obj) return false; jsval.set(ObjectValue(*obj)); return true; } jsval.set(DoubleValue(d)); return true; } default: { break; } } MOZ_CRASH("unexpected type when creating global exports"); }
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; }
//////////////////////////////////////////////////// // nsGeoPositionCoords //////////////////////////////////////////////////// nsGeoPositionCoords::nsGeoPositionCoords(double aLat, double aLong, double aAlt, double aHError, double aVError, double aHeading, double aSpeed) : mLat(aLat), mLong(aLong), mAlt(aAlt), mHError((aHError >= 0) ? aHError : 0) // altitudeAccuracy without an altitude doesn't make any sense. , mVError((aVError >= 0 && !IsNaN(aAlt)) ? aVError : NaN()) // If the hosting device is stationary (i.e. the value of the speed // attribute is 0), then the value of the heading attribute must be NaN // (or null). , mHeading((aHeading >= 0 && aHeading < 360 && aSpeed > 0) ? aHeading : NaN()), mSpeed(aSpeed >= 0 ? aSpeed : NaN()) { // Sanity check the location provider's results in debug builds. If the // location provider is returning bogus results, we'd like to know, but // we prefer to return some position data to JavaScript over a // POSITION_UNAVAILABLE error. MOZ_ASSERT(aLat >= -90 && aLat <= 90); MOZ_ASSERT(aLong >= -180 && aLong <= 180); MOZ_ASSERT(!(aLat == 0 && aLong == 0)); // valid but probably a bug MOZ_ASSERT(EqualOrNaN(mAlt, aAlt)); MOZ_ASSERT(mHError == aHError); MOZ_ASSERT(EqualOrNaN(mVError, aVError)); MOZ_ASSERT(EqualOrNaN(mHeading, aHeading)); MOZ_ASSERT(EqualOrNaN(mSpeed, aSpeed)); }
static bool RenderFloat32(WasmRenderContext& c, float f) { if (IsNaN(f)) return RenderNaN(c.sb(), f); return RenderDouble(c, double(f)); }
static double max_double(double x, double y) { // Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0 if (x > y || IsNaN(x) || (x == y && IsNegative(y))) return x; return y; }
double js::math_max_impl(double x, double y) { // Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0 if (x > y || IsNaN(x) || (x == y && IsNegative(y))) return x; return y; }
static bool RenderFloat32(WasmRenderContext& c, RawF32 num) { float f = num.fp(); if (IsNaN(f)) return RenderNaN(c.sb(), num); return RenderDouble(c, RawF64(double(f))); }
static double min_double(double x, double y) { // Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0 if (x < y || IsNaN(x) || (x == y && IsNegativeZero(x))) return x; return y; }
double js::math_min_impl(double x, double y) { // Math.min(num, NaN) => NaN, Math.min(-0, +0) => -0 if (x < y || IsNaN(x) || (x == y && IsNegativeZero(x))) return x; return y; }
double js::math_exp_impl(MathCache *cache, double x) { #ifdef _WIN32 if (!IsNaN(x)) { if (x == js_PositiveInfinity) return js_PositiveInfinity; if (x == js_NegativeInfinity) return 0.0; } #endif return cache->lookup(exp, x); }
static bool DecodeConstF64(FunctionDecoder& f, ExprType expected) { double value; if (!f.d().readFixedF64(&value)) return f.fail("unable to read f64.const immediate"); if (IsNaN(value)) { const double jsNaN = JS::GenericNaN(); if (memcmp(&value, &jsNaN, sizeof(value)) != 0) return f.fail("NYI: NaN literals with custom payloads"); } return CheckType(f, ExprType::F64, expected); }
static bool RenderDouble(WasmRenderContext& c, double d) { if (IsNaN(d)) return RenderNaN(c.sb(), d); if (IsNegativeZero(d)) return c.buffer.append("-0"); if (IsInfinite(d)) { if (d > 0) return c.buffer.append("infinity"); return c.buffer.append("-infinity"); } return NumberValueToStringBuffer(c.cx, DoubleValue(d), c.sb()); }
static bool RenderDouble(WasmRenderContext& c, double num) { if (IsNegativeZero(num)) return c.buffer.append("-0"); if (IsNaN(num)) return c.buffer.append("nan"); if (IsInfinite(num)) { if (num > 0) return c.buffer.append("infinity"); return c.buffer.append("-infinity"); } return NumberValueToStringBuffer(c.cx, DoubleValue(num), c.buffer); }
static bool DecodeConstF32(FunctionDecoder& f, ExprType* type) { float value; if (!f.d().readFixedF32(&value)) return f.fail("unable to read f32.const immediate"); if (IsNaN(value)) { const float jsNaN = (float)JS::GenericNaN(); if (memcmp(&value, &jsNaN, sizeof(value)) != 0) return f.fail("NYI: NaN literals with custom payloads"); } *type = ExprType::F32; return true; }
bool js_math_max(JSContext *cx, unsigned argc, Value *vp) { CallArgs args = CallArgsFromVp(argc, vp); double maxval = NegativeInfinity(); for (unsigned i = 0; i < args.length(); i++) { double x; if (!ToNumber(cx, args[i], &x)) return false; // Math.max(num, NaN) => NaN, Math.max(-0, +0) => +0 if (x > maxval || IsNaN(x) || (x == maxval && IsNegative(maxval))) maxval = x; } args.rval().setNumber(maxval); 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; // 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; }
static JSObject* CreateCustomNaNObject(JSContext* cx, T* addr) { MOZ_ASSERT(IsNaN(*addr)); RootedObject obj(cx, JS_NewPlainObject(cx)); if (!obj) return nullptr; int32_t* i32 = (int32_t*)addr; RootedValue intVal(cx, Int32Value(i32[0])); if (!JS_DefineProperty(cx, obj, "nan_low", intVal, JSPROP_ENUMERATE)) return nullptr; if (IsSame<double, T>::value) { intVal = Int32Value(i32[1]); if (!JS_DefineProperty(cx, obj, "nan_high", intVal, JSPROP_ENUMERATE)) return nullptr; } return obj; }
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)); }
bool JSStructuredCloneReader::startRead(Value *vp) { uint32_t tag, data; if (!in.readPair(&tag, &data)) return false; switch (tag) { case SCTAG_NULL: vp->setNull(); break; case SCTAG_UNDEFINED: vp->setUndefined(); break; case SCTAG_BOOLEAN: case SCTAG_BOOLEAN_OBJECT: vp->setBoolean(!!data); if (tag == SCTAG_BOOLEAN_OBJECT && !js_PrimitiveToObject(context(), vp)) return false; break; case SCTAG_STRING: case SCTAG_STRING_OBJECT: { JSString *str = readString(data); if (!str) return false; vp->setString(str); if (tag == SCTAG_STRING_OBJECT && !js_PrimitiveToObject(context(), vp)) return false; break; } case SCTAG_NUMBER_OBJECT: { double d; if (!in.readDouble(&d) || !checkDouble(d)) return false; vp->setDouble(d); if (!js_PrimitiveToObject(context(), vp)) return false; break; } case SCTAG_DATE_OBJECT: { double d; if (!in.readDouble(&d) || !checkDouble(d)) return false; if (!IsNaN(d) && d != TimeClip(d)) { JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "date"); return false; } JSObject *obj = js_NewDateObjectMsec(context(), d); if (!obj) return false; vp->setObject(*obj); break; } case SCTAG_REGEXP_OBJECT: { RegExpFlag flags = RegExpFlag(data); uint32_t tag2, nchars; if (!in.readPair(&tag2, &nchars)) return false; if (tag2 != SCTAG_STRING) { JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "regexp"); return false; } JSString *str = readString(nchars); if (!str) return false; JSStableString *stable = str->ensureStable(context()); if (!stable) return false; size_t length = stable->length(); const StableCharPtr chars = stable->chars(); RegExpObject *reobj = RegExpObject::createNoStatics(context(), chars.get(), length, flags, NULL); if (!reobj) return false; vp->setObject(*reobj); break; } case SCTAG_ARRAY_OBJECT: case SCTAG_OBJECT_OBJECT: { JSObject *obj = (tag == SCTAG_ARRAY_OBJECT) ? NewDenseEmptyArray(context()) : NewBuiltinClassInstance(context(), &ObjectClass); if (!obj || !objs.append(ObjectValue(*obj))) return false; vp->setObject(*obj); break; } case SCTAG_BACK_REFERENCE_OBJECT: { if (data >= allObjs.length()) { JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "invalid back reference in input"); return false; } *vp = allObjs[data]; return true; } case SCTAG_TRANSFER_MAP_HEADER: // A map header cannot be here but just at the beginning of the buffer. JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "invalid input"); return false; case SCTAG_TRANSFER_MAP: // A map cannot be here but just at the beginning of the buffer. JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "invalid input"); return false; case SCTAG_ARRAY_BUFFER_OBJECT: if (!readArrayBuffer(data, vp)) return false; break; case SCTAG_TYPED_ARRAY_OBJECT: // readTypedArray adds the array to allObjs uint64_t arrayType; if (!in.read(&arrayType)) return false; return readTypedArray(arrayType, data, vp); break; default: { if (tag <= SCTAG_FLOAT_MAX) { double d = ReinterpretPairAsDouble(tag, data); if (!checkDouble(d)) return false; vp->setNumber(d); break; } if (SCTAG_TYPED_ARRAY_V1_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_V1_MAX) { // A v1-format typed array // readTypedArray adds the array to allObjs return readTypedArray(TagToV1ArrayType(tag), data, vp, true); } if (!callbacks || !callbacks->read) { JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA, "unsupported type"); return false; } JSObject *obj = callbacks->read(context(), this, tag, data, closure); if (!obj) return false; vp->setObject(*obj); } } if (vp->isObject() && !allObjs.append(*vp)) return false; return true; }
bool Instance::callExport(JSContext* cx, uint32_t funcIndex, CallArgs args) { if (!cx->compartment()->wasm.ensureProfilingState(cx)) return false; const FuncExport& func = metadata().lookupFuncExport(funcIndex); // The calling convention for an external call into wasm is to pass an // array of 16-byte values where each value contains either a coerced int32 // (in the low word), a double value (in the low dword) or a SIMD vector // value, with the coercions specified by the wasm signature. The external // entry point unpacks this array into the system-ABI-specified registers // and stack memory and then calls into the internal entry point. The return // value is stored in the first element of the array (which, therefore, must // have length >= 1). Vector<ExportArg, 8> exportArgs(cx); if (!exportArgs.resize(Max<size_t>(1, func.sig().args().length()))) return false; RootedValue v(cx); for (unsigned i = 0; i < func.sig().args().length(); ++i) { v = i < args.length() ? args[i] : UndefinedValue(); switch (func.sig().arg(i)) { case ValType::I32: if (!ToInt32(cx, v, (int32_t*)&exportArgs[i])) return false; break; case ValType::I64: if (!JitOptions.wasmTestMode) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64); return false; } if (!ReadI64Object(cx, v, (int64_t*)&exportArgs[i])) return false; break; case ValType::F32: if (JitOptions.wasmTestMode && v.isObject()) { if (!ReadCustomFloat32NaNObject(cx, v, (float*)&exportArgs[i])) return false; break; } if (!RoundFloat32(cx, v, (float*)&exportArgs[i])) return false; break; case ValType::F64: if (JitOptions.wasmTestMode && v.isObject()) { if (!ReadCustomDoubleNaNObject(cx, v, (double*)&exportArgs[i])) return false; break; } if (!ToNumber(cx, v, (double*)&exportArgs[i])) return false; break; case ValType::I8x16: { SimdConstant simd; if (!ToSimdConstant<Int8x16>(cx, v, &simd)) return false; memcpy(&exportArgs[i], simd.asInt8x16(), Simd128DataSize); break; } case ValType::I16x8: { SimdConstant simd; if (!ToSimdConstant<Int16x8>(cx, v, &simd)) return false; memcpy(&exportArgs[i], simd.asInt16x8(), Simd128DataSize); break; } case ValType::I32x4: { SimdConstant simd; if (!ToSimdConstant<Int32x4>(cx, v, &simd)) return false; memcpy(&exportArgs[i], simd.asInt32x4(), Simd128DataSize); break; } case ValType::F32x4: { SimdConstant simd; if (!ToSimdConstant<Float32x4>(cx, v, &simd)) return false; memcpy(&exportArgs[i], simd.asFloat32x4(), Simd128DataSize); break; } case ValType::B8x16: { SimdConstant simd; if (!ToSimdConstant<Bool8x16>(cx, v, &simd)) return false; // Bool8x16 uses the same representation as Int8x16. memcpy(&exportArgs[i], simd.asInt8x16(), Simd128DataSize); break; } case ValType::B16x8: { SimdConstant simd; if (!ToSimdConstant<Bool16x8>(cx, v, &simd)) return false; // Bool16x8 uses the same representation as Int16x8. memcpy(&exportArgs[i], simd.asInt16x8(), Simd128DataSize); break; } case ValType::B32x4: { SimdConstant simd; if (!ToSimdConstant<Bool32x4>(cx, v, &simd)) return false; // Bool32x4 uses the same representation as Int32x4. memcpy(&exportArgs[i], simd.asInt32x4(), Simd128DataSize); break; } case ValType::Limit: MOZ_CRASH("Limit"); } } { // Push a WasmActivation to describe the wasm frames we're about to push // when running this module. Additionally, push a JitActivation so that // the optimized wasm-to-Ion FFI call path (which we want to be very // fast) can avoid doing so. The JitActivation is marked as inactive so // stack iteration will skip over it. WasmActivation activation(cx); JitActivation jitActivation(cx, /* active */ false); // Call the per-exported-function trampoline created by GenerateEntry. auto funcPtr = JS_DATA_TO_FUNC_PTR(ExportFuncPtr, codeBase() + func.entryOffset()); if (!CALL_GENERATED_2(funcPtr, exportArgs.begin(), &tlsData_)) return false; } if (args.isConstructing()) { // By spec, when a function is called as a constructor and this function // returns a primary type, which is the case for all wasm exported // functions, the returned value is discarded and an empty object is // returned instead. PlainObject* obj = NewBuiltinClassInstance<PlainObject>(cx); if (!obj) return false; args.rval().set(ObjectValue(*obj)); return true; } void* retAddr = &exportArgs[0]; JSObject* retObj = nullptr; switch (func.sig().ret()) { case ExprType::Void: args.rval().set(UndefinedValue()); break; case ExprType::I32: args.rval().set(Int32Value(*(int32_t*)retAddr)); break; case ExprType::I64: if (!JitOptions.wasmTestMode) { JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_I64); return false; } retObj = CreateI64Object(cx, *(int64_t*)retAddr); if (!retObj) return false; break; case ExprType::F32: if (JitOptions.wasmTestMode && IsNaN(*(float*)retAddr)) { retObj = CreateCustomNaNObject(cx, (float*)retAddr); if (!retObj) return false; break; } args.rval().set(NumberValue(*(float*)retAddr)); break; case ExprType::F64: if (JitOptions.wasmTestMode && IsNaN(*(double*)retAddr)) { retObj = CreateCustomNaNObject(cx, (double*)retAddr); if (!retObj) return false; break; } args.rval().set(NumberValue(*(double*)retAddr)); break; case ExprType::I8x16: retObj = CreateSimd<Int8x16>(cx, (int8_t*)retAddr); if (!retObj) return false; break; case ExprType::I16x8: retObj = CreateSimd<Int16x8>(cx, (int16_t*)retAddr); if (!retObj) return false; break; case ExprType::I32x4: retObj = CreateSimd<Int32x4>(cx, (int32_t*)retAddr); if (!retObj) return false; break; case ExprType::F32x4: retObj = CreateSimd<Float32x4>(cx, (float*)retAddr); if (!retObj) return false; break; case ExprType::B8x16: retObj = CreateSimd<Bool8x16>(cx, (int8_t*)retAddr); if (!retObj) return false; break; case ExprType::B16x8: retObj = CreateSimd<Bool16x8>(cx, (int16_t*)retAddr); if (!retObj) return false; break; case ExprType::B32x4: retObj = CreateSimd<Bool32x4>(cx, (int32_t*)retAddr); if (!retObj) return false; break; case ExprType::Limit: MOZ_CRASH("Limit"); } if (retObj) args.rval().set(ObjectValue(*retObj)); return true; }
static bool EqualOrNaN(double a, double b) { return (a == b) || (IsNaN(a) && IsNaN(b)); }
static T apply(T l, T r) { return IsNaN(l) ? r : (IsNaN(r) ? l : math_max_impl(l, r)); }
static inline T apply(T l, T r) { return IsNaN(l) ? r : (IsNaN(r) ? l : math_min_impl(l, r)); }