Bug 993034: SIMD - Clean up coding style and reorganize functions by number of arguments; r=nmatsakis

This commit is contained in:
Benjamin Bouvier 2014-04-16 16:21:12 +02:00
parent 0d4975cceb
commit ed7ffdf9c0
2 changed files with 191 additions and 205 deletions

View File

@ -389,6 +389,7 @@ template<typename V>
JSObject *
js::Create(JSContext *cx, typename V::Elem *data)
{
typedef typename V::Elem Elem;
Rooted<TypeDescr*> typeDescr(cx, &V::GetTypeDescr(*cx->global()));
JS_ASSERT(typeDescr);
@ -396,8 +397,8 @@ js::Create(JSContext *cx, typename V::Elem *data)
if (!result)
return nullptr;
typename V::Elem *resultMem = reinterpret_cast<typename V::Elem *>(result->typedMem());
memcpy(resultMem, data, sizeof(typename V::Elem) * V::lanes);
Elem *resultMem = reinterpret_cast<Elem *>(result->typedMem());
memcpy(resultMem, data, sizeof(Elem) * V::lanes);
return result;
}
@ -407,127 +408,127 @@ template JSObject *js::Create<Int32x4>(JSContext *cx, Int32x4::Elem *data);
namespace js {
template<typename T, typename V>
struct Abs {
static inline T apply(T x, T zero) {return V::toType(x < 0 ? -1 * x : x);}
static inline T apply(T x, T zero) { return V::toType(x < 0 ? -1 * x : x); }
};
template<typename T, typename V>
struct Neg {
static inline T apply(T x, T zero) {return V::toType(-1 * x);}
static inline T apply(T x, T zero) { return V::toType(-1 * x); }
};
template<typename T, typename V>
struct Not {
static inline T apply(T x, T zero) {return V::toType(~x);}
static inline T apply(T x, T zero) { return V::toType(~x); }
};
template<typename T, typename V>
struct Rec {
static inline T apply(T x, T zero) {return V::toType(1 / x);}
static inline T apply(T x, T zero) { return V::toType(1 / x); }
};
template<typename T, typename V>
struct RecSqrt {
static inline T apply(T x, T zero) {return V::toType(1 / sqrt(x));}
static inline T apply(T x, T zero) { return V::toType(1 / sqrt(x)); }
};
template<typename T, typename V>
struct Sqrt {
static inline T apply(T x, T zero) {return V::toType(sqrt(x));}
static inline T apply(T x, T zero) { return V::toType(sqrt(x)); }
};
template<typename T, typename V>
struct Add {
static inline T apply(T l, T r) {return V::toType(l + r);}
static inline T apply(T l, T r) { return V::toType(l + r); }
};
template<typename T, typename V>
struct Sub {
static inline T apply(T l, T r) {return V::toType(l - r);}
static inline T apply(T l, T r) { return V::toType(l - r); }
};
template<typename T, typename V>
struct Div {
static inline T apply(T l, T r) {return V::toType(l / r);}
static inline T apply(T l, T r) { return V::toType(l / r); }
};
template<typename T, typename V>
struct Mul {
static inline T apply(T l, T r) {return V::toType(l * r);}
static inline T apply(T l, T r) { return V::toType(l * r); }
};
template<typename T, typename V>
struct Minimum {
static inline T apply(T l, T r) {return V::toType(l < r ? l : r);}
static inline T apply(T l, T r) { return V::toType(l < r ? l : r); }
};
template<typename T, typename V>
struct Maximum {
static inline T apply(T l, T r) {return V::toType(l > r ? l : r);}
static inline T apply(T l, T r) { return V::toType(l > r ? l : r); }
};
template<typename T, typename V>
struct LessThan {
static inline T apply(T l, T r) {return V::toType(l < r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l < r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct LessThanOrEqual {
static inline T apply(T l, T r) {return V::toType(l <= r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l <= r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct GreaterThan {
static inline T apply(T l, T r) {return V::toType(l > r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l > r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct GreaterThanOrEqual {
static inline T apply(T l, T r) {return V::toType(l >= r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l >= r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct Equal {
static inline T apply(T l, T r) {return V::toType(l == r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l == r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct NotEqual {
static inline T apply(T l, T r) {return V::toType(l != r ? 0xFFFFFFFF: 0x0);}
static inline T apply(T l, T r) { return V::toType(l != r ? 0xFFFFFFFF : 0x0); }
};
template<typename T, typename V>
struct Xor {
static inline T apply(T l, T r) {return V::toType(l ^ r);}
static inline T apply(T l, T r) { return V::toType(l ^ r); }
};
template<typename T, typename V>
struct And {
static inline T apply(T l, T r) {return V::toType(l & r);}
static inline T apply(T l, T r) { return V::toType(l & r); }
};
template<typename T, typename V>
struct Or {
static inline T apply(T l, T r) {return V::toType(l | r);}
static inline T apply(T l, T r) { return V::toType(l | r); }
};
template<typename T, typename V>
struct Scale {
static inline T apply(int32_t lane, T scalar, T x) {return V::toType(scalar * x);}
static inline T apply(int32_t lane, T scalar, T x) { return V::toType(scalar * x); }
};
template<typename T, typename V>
struct WithX {
static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 0 ? scalar : x);}
static inline T apply(int32_t lane, T scalar, T x) { return V::toType(lane == 0 ? scalar : x); }
};
template<typename T, typename V>
struct WithY {
static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 1 ? scalar : x);}
static inline T apply(int32_t lane, T scalar, T x) { return V::toType(lane == 1 ? scalar : x); }
};
template<typename T, typename V>
struct WithZ {
static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 2 ? scalar : x);}
static inline T apply(int32_t lane, T scalar, T x) { return V::toType(lane == 2 ? scalar : x); }
};
template<typename T, typename V>
struct WithW {
static inline T apply(int32_t lane, T scalar, T x) {return V::toType(lane == 3 ? scalar : x);}
static inline T apply(int32_t lane, T scalar, T x) { return V::toType(lane == 3 ? scalar : x); }
};
template<typename T, typename V>
struct WithFlagX {
static inline T apply(T l, T f, T x) { return V::toType(l == 0 ? (f ? 0xFFFFFFFF : 0x0) : x);}
static inline T apply(T l, T f, T x) { return V::toType(l == 0 ? (f ? 0xFFFFFFFF : 0x0) : x); }
};
template<typename T, typename V>
struct WithFlagY {
static inline T apply(T l, T f, T x) { return V::toType(l == 1 ? (f ? 0xFFFFFFFF : 0x0) : x);}
static inline T apply(T l, T f, T x) { return V::toType(l == 1 ? (f ? 0xFFFFFFFF : 0x0) : x); }
};
template<typename T, typename V>
struct WithFlagZ {
static inline T apply(T l, T f, T x) { return V::toType(l == 2 ? (f ? 0xFFFFFFFF : 0x0) : x);}
static inline T apply(T l, T f, T x) { return V::toType(l == 2 ? (f ? 0xFFFFFFFF : 0x0) : x); }
};
template<typename T, typename V>
struct WithFlagW {
static inline T apply(T l, T f, T x) { return V::toType(l == 3 ? (f ? 0xFFFFFFFF : 0x0) : x);}
static inline T apply(T l, T f, T x) { return V::toType(l == 3 ? (f ? 0xFFFFFFFF : 0x0) : x); }
};
template<typename T, typename V>
struct Shuffle {
static inline int32_t apply(int32_t l, int32_t mask) {return V::toType((mask >> l) & 0x3);}
static inline int32_t apply(int32_t l, int32_t mask) { return V::toType((mask >> l) & 0x3); }
};
}
@ -535,45 +536,39 @@ template<typename V, typename Op, typename Vret>
static bool
Func(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename V::Elem Elem;
typedef typename Vret::Elem RetElem;
if (args.length() == 1) {
if((!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()))) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1 && args.length() != 2) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *val =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
typename Vret::Elem result[Vret::lanes];
RetElem result[Vret::lanes];
if (args.length() == 1) {
if (!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
Elem *val = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = Op::apply(val[i], 0);
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
} else if (args.length() == 2) {
if((!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())) ||
(!args[1].isObject() || !ObjectIsVector<V>(args[1].toObject())))
} else {
JS_ASSERT(args.length() == 2);
if(!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()) ||
!args[1].isObject() || !ObjectIsVector<V>(args[1].toObject()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *left =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
typename V::Elem *right =
reinterpret_cast<typename V::Elem *>(
args[1].toObject().as<TypedObject>().typedMem());
typename Vret::Elem result[Vret::lanes];
Elem *left = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
Elem *right = reinterpret_cast<Elem *>(args[1].toObject().as<TypedObject>().typedMem());
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = Op::apply(left[i], right[i]);
}
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
@ -581,41 +576,39 @@ Func(JSContext *cx, unsigned argc, Value *vp)
args.rval().setObject(*obj);
return true;
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
}
template<typename V, typename OpWith, typename Vret>
static bool
FuncWith(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename V::Elem Elem;
typedef typename Vret::Elem RetElem;
if ((args.length() != 2) ||
(!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())) ||
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 2 ||
!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()) ||
(!args[1].isNumber() && !args[1].isBoolean()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *val =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
Elem *val = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
RetElem result[Vret::lanes];
typename Vret::Elem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++) {
if(args[1].isNumber()) {
typename Vret::Elem arg1;
if (!Vret::toType(cx, args[1], &arg1))
if (args[1].isNumber()) {
Elem withAsNumber;
if (!Vret::toType(cx, args[1], &withAsNumber))
return false;
result[i] = OpWith::apply(i, arg1, val[i]);
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = OpWith::apply(i, withAsNumber, val[i]);
} else if (args[1].isBoolean()) {
result[i] = OpWith::apply(i, args[1].toBoolean(), val[i]);
}
bool withAsBool = args[1].toBoolean();
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = OpWith::apply(i, withAsBool, val[i]);
}
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
return false;
@ -628,87 +621,83 @@ template<typename V, typename OpShuffle, typename Vret>
static bool
FuncShuffle(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename V::Elem Elem;
typedef typename Vret::Elem RetElem;
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 2 && args.length() != 3) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
RetElem result[Vret::lanes];
if (args.length() == 2) {
if ((!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())) ||
(!args[1].isNumber()))
if (!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()) ||
!args[1].isNumber())
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *val =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
typename Vret::Elem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++) {
typename Vret::Elem arg1;
Elem *val = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
Elem arg1;
if (!Vret::toType(cx, args[1], &arg1))
return false;
result[i] = val[OpShuffle::apply(i * 2, arg1)];
}
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
} else if (args.length() == 3) {
if ((!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())) ||
(!args[1].isObject() || !ObjectIsVector<V>(args[1].toObject())) ||
(!args[2].isNumber()))
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = val[OpShuffle::apply(i * 2, arg1)];
} else {
JS_ASSERT(args.length() == 3);
if (!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()) ||
!args[1].isObject() || !ObjectIsVector<V>(args[1].toObject()) ||
!args[2].isNumber())
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *val1 =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
typename V::Elem *val2 =
reinterpret_cast<typename V::Elem *>(
args[1].toObject().as<TypedObject>().typedMem());
typename Vret::Elem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++) {
typename Vret::Elem arg2;
Elem *val1 = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
Elem *val2 = reinterpret_cast<Elem *>(args[1].toObject().as<TypedObject>().typedMem());
Elem arg2;
if (!Vret::toType(cx, args[2], &arg2))
return false;
if(i < Vret::lanes / 2) {
for (int32_t i = 0; i < Vret::lanes; i++) {
if (i < Vret::lanes / 2)
result[i] = val1[OpShuffle::apply(i * 2, arg2)];
} else {
else
result[i] = val2[OpShuffle::apply(i * 2, arg2)];
}
}
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
}
template<typename V, typename Vret>
static bool
FuncConvert(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename V::Elem Elem;
typedef typename Vret::Elem RetElem;
if ((args.length() != 1) ||
(!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())))
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1 ||
!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename V::Elem *val =
reinterpret_cast<typename V::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
typename Vret::Elem result[Vret::lanes];
Elem *val = reinterpret_cast<Elem *>(args[0].toObject().as<TypedObject>().typedMem());
RetElem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = static_cast<typename Vret::Elem>(val[i]);
result[i] = RetElem(val[i]);
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
@ -722,17 +711,17 @@ template<typename V, typename Vret>
static bool
FuncConvertBits(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename Vret::Elem RetElem;
if ((args.length() != 1) ||
(!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject())))
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1 ||
!args[0].isObject() || !ObjectIsVector<V>(args[0].toObject()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename Vret::Elem *val =
reinterpret_cast<typename Vret::Elem *>(
args[0].toObject().as<TypedObject>().typedMem());
RetElem *val = reinterpret_cast<RetElem *>(args[0].toObject().as<TypedObject>().typedMem());
RootedObject obj(cx, Create<Vret>(cx, val));
if (!obj)
@ -746,15 +735,17 @@ template<typename Vret>
static bool
FuncZero(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename Vret::Elem RetElem;
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename Vret::Elem result[Vret::lanes];
RetElem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = static_cast<typename Vret::Elem>(0);
result[i] = RetElem(0);
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
@ -768,19 +759,21 @@ template<typename Vret>
static bool
FuncSplat(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
typedef typename Vret::Elem RetElem;
if ((args.length() != 1) || (!args[0].isNumber())) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1 || !args[0].isNumber()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
typename Vret::Elem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++) {
typename Vret::Elem arg0;
if (!Vret::toType(cx, args[0], &arg0))
RetElem arg;
if (!Vret::toType(cx, args[0], &arg))
return false;
result[i] = static_cast<typename Vret::Elem>(arg0);
}
RetElem result[Vret::lanes];
for (int32_t i = 0; i < Vret::lanes; i++)
result[i] = arg;
RootedObject obj(cx, Create<Vret>(cx, result));
if (!obj)
@ -794,14 +787,14 @@ static bool
Int32x4Bool(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if ((args.length() != 4) ||
(!args[0].isBoolean()) || !args[1].isBoolean() ||
(!args[2].isBoolean()) || !args[3].isBoolean())
if (args.length() != 4 ||
!args[0].isBoolean() || !args[1].isBoolean() ||
!args[2].isBoolean() || !args[3].isBoolean())
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
int32_t result[Int32x4::lanes];
for (int32_t i = 0; i < Int32x4::lanes; i++)
result[i] = args[i].toBoolean() ? 0xFFFFFFFF : 0x0;
@ -818,31 +811,25 @@ static bool
Float32x4Clamp(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if ((args.length() != 3) ||
(!args[0].isObject() || !ObjectIsVector<Float32x4>(args[0].toObject())) ||
(!args[1].isObject() || !ObjectIsVector<Float32x4>(args[1].toObject())) ||
(!args[2].isObject() || !ObjectIsVector<Float32x4>(args[2].toObject())))
if (args.length() != 3 ||
!args[0].isObject() || !ObjectIsVector<Float32x4>(args[0].toObject()) ||
!args[1].isObject() || !ObjectIsVector<Float32x4>(args[1].toObject()) ||
!args[2].isObject() || !ObjectIsVector<Float32x4>(args[2].toObject()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
float *val = reinterpret_cast<float *>(
args[0].toObject().as<TypedObject>().typedMem());
float *lowerLimit = reinterpret_cast<float *>(
args[1].toObject().as<TypedObject>().typedMem());
float *upperLimit = reinterpret_cast<float *>(
args[2].toObject().as<TypedObject>().typedMem());
float *val = reinterpret_cast<float *>(args[0].toObject().as<TypedObject>().typedMem());
float *lowerLimit = reinterpret_cast<float *>(args[1].toObject().as<TypedObject>().typedMem());
float *upperLimit = reinterpret_cast<float *>(args[2].toObject().as<TypedObject>().typedMem());
float result[Float32x4::lanes];
result[0] = val[0] < lowerLimit[0] ? lowerLimit[0] : val[0];
result[1] = val[1] < lowerLimit[1] ? lowerLimit[1] : val[1];
result[2] = val[2] < lowerLimit[2] ? lowerLimit[2] : val[2];
result[3] = val[3] < lowerLimit[3] ? lowerLimit[3] : val[3];
result[0] = result[0] > upperLimit[0] ? upperLimit[0] : result[0];
result[1] = result[1] > upperLimit[1] ? upperLimit[1] : result[1];
result[2] = result[2] > upperLimit[2] ? upperLimit[2] : result[2];
result[3] = result[3] > upperLimit[3] ? upperLimit[3] : result[3];
for (int32_t i = 0; i < Float32x4::lanes; i++) {
result[i] = val[i] < lowerLimit[i] ? lowerLimit[i] : val[i];
result[i] = result[i] > upperLimit[i] ? upperLimit[i] : result[i];
}
RootedObject obj(cx, Create<Float32x4>(cx, result));
if (!obj)
return false;
@ -855,30 +842,31 @@ static bool
Int32x4Select(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if ((args.length() != 3) ||
(!args[0].isObject() || !ObjectIsVector<Int32x4>(args[0].toObject())) ||
(!args[1].isObject() || !ObjectIsVector<Float32x4>(args[1].toObject())) ||
(!args[2].isObject() || !ObjectIsVector<Float32x4>(args[2].toObject())))
if (args.length() != 3 ||
!args[0].isObject() || !ObjectIsVector<Int32x4>(args[0].toObject()) ||
!args[1].isObject() || !ObjectIsVector<Float32x4>(args[1].toObject()) ||
!args[2].isObject() || !ObjectIsVector<Float32x4>(args[2].toObject()))
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
int32_t *val = reinterpret_cast<int32_t *>(
args[0].toObject().as<TypedObject>().typedMem());
int32_t *tv = reinterpret_cast<int32_t *>(
args[1].toObject().as<TypedObject>().typedMem());
int32_t *fv = reinterpret_cast<int32_t *>(
args[2].toObject().as<TypedObject>().typedMem());
int32_t *val = reinterpret_cast<int32_t *>(args[0].toObject().as<TypedObject>().typedMem());
int32_t *tv = reinterpret_cast<int32_t *>(args[1].toObject().as<TypedObject>().typedMem());
int32_t *fv = reinterpret_cast<int32_t *>(args[2].toObject().as<TypedObject>().typedMem());
int32_t tr[Int32x4::lanes];
for (int32_t i = 0; i < Int32x4::lanes; i++)
tr[i] = And<int32_t, Int32x4>::apply(val[i], tv[i]);
int32_t fr[Int32x4::lanes];
for (int32_t i = 0; i < Int32x4::lanes; i++)
fr[i] = And<int32_t, Int32x4>::apply(Not<int32_t, Int32x4>::apply(val[i], 0), fv[i]);
int32_t orInt[Int32x4::lanes];
for (int32_t i = 0; i < Int32x4::lanes; i++)
orInt[i] = Or<int32_t, Int32x4>::apply(tr[i], fr[i]);
float *result[Float32x4::lanes];
*result = reinterpret_cast<float *>(&orInt);
RootedObject obj(cx, Create<Float32x4>(cx, *result));

View File

@ -117,8 +117,7 @@ class SIMDObject : public JSObject
struct Float32x4 {
typedef float Elem;
static const int32_t lanes = 4;
static const X4TypeDescr::Type type =
X4TypeDescr::TYPE_FLOAT32;
static const X4TypeDescr::Type type = X4TypeDescr::TYPE_FLOAT32;
static TypeDescr &GetTypeDescr(GlobalObject &global) {
return global.float32x4TypeDescr().as<TypeDescr>();
@ -138,8 +137,7 @@ struct Float32x4 {
struct Int32x4 {
typedef int32_t Elem;
static const int32_t lanes = 4;
static const X4TypeDescr::Type type =
X4TypeDescr::TYPE_INT32;
static const X4TypeDescr::Type type = X4TypeDescr::TYPE_INT32;
static TypeDescr &GetTypeDescr(GlobalObject &global) {
return global.int32x4TypeDescr().as<TypeDescr>();