Example #1
0
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;
}
Example #2
0
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");
}
Example #3
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;
}
Example #4
0
////////////////////////////////////////////////////
// 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));
}
Example #6
0
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;
}
Example #7
0
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)));
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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);
}
Example #12
0
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());
}
Example #14
0
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);
}
Example #15
0
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;
}
Example #16
0
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;
}
Example #17
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;
        // 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;
}
Example #18
0
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;
}
Example #19
0
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));
}
Example #20
0
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;
}
Example #21
0
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;
}
Example #22
0
static bool EqualOrNaN(double a, double b) {
  return (a == b) || (IsNaN(a) && IsNaN(b));
}
Example #23
0
 static T apply(T l, T r) {
     return IsNaN(l) ? r : (IsNaN(r) ? l : math_max_impl(l, r));
 }
Example #24
0
 static inline T apply(T l, T r) { return IsNaN(l) ? r : (IsNaN(r) ? l : math_min_impl(l, r)); }