mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
fix jsiter, convert jsmath
This commit is contained in:
parent
588e08228c
commit
36fb0452a3
@ -3351,6 +3351,8 @@ class Value
|
||||
data.dbl = d;
|
||||
}
|
||||
|
||||
inline void setNumber(double d);
|
||||
|
||||
double &asDoubleRef() {
|
||||
JS_ASSERT(size_t(&data.dbl) % sizeof(double) == 0);
|
||||
JS_ASSERT(isDouble());
|
||||
@ -3622,6 +3624,7 @@ struct AssertLayoutCompatible
|
||||
/* XXX: this is a temporary hack until copying is implicit. */
|
||||
struct CopyableValue : Value
|
||||
{
|
||||
CopyableValue() {}
|
||||
CopyableValue(NullTag arg) : Value(arg) {}
|
||||
CopyableValue(UndefinedTag arg) : Value(arg) {}
|
||||
CopyableValue(Int32Tag arg) : Value(arg) {}
|
||||
@ -3629,7 +3632,7 @@ struct CopyableValue : Value
|
||||
CopyableValue(JSString *arg) : Value(arg) {}
|
||||
CopyableValue(FunObjTag arg) : Value(arg) {}
|
||||
CopyableValue(NonFunObjTag arg) : Value(arg) {}
|
||||
CopyableValue(ObjectTag arg) : Value(arg) {}
|
||||
inline CopyableValue(ObjectTag arg);
|
||||
CopyableValue(BooleanTag arg) : Value(arg) {}
|
||||
CopyableValue(JSWhyMagic arg) : Value(arg) {}
|
||||
};
|
||||
|
@ -2205,7 +2205,8 @@ class AutoGCRooter {
|
||||
XML = -10, /* js::AutoXMLRooter */
|
||||
OBJECT = -11, /* js::AutoObjectRooter */
|
||||
ID = -12, /* js::AutoIdRooter */
|
||||
VECTOR = -13 /* js::AutoValueVector */
|
||||
VALVECTOR = -13, /* js::AutoValueVector */
|
||||
BOXEDVECTOR = -14 /* js::AutoBoxedWordVector */
|
||||
};
|
||||
|
||||
private:
|
||||
@ -2985,7 +2986,7 @@ class AutoValueVector : private AutoGCRooter
|
||||
public:
|
||||
explicit AutoValueVector(JSContext *cx
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, VECTOR), vector(cx)
|
||||
: AutoGCRooter(cx, VALVECTOR), vector(cx)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
@ -3023,6 +3024,48 @@ class AutoValueVector : private AutoGCRooter
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
class AutoBoxedWordVector : private AutoGCRooter
|
||||
{
|
||||
public:
|
||||
explicit AutoBoxedWordVector(JSContext *cx
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: AutoGCRooter(cx, BOXEDVECTOR), vector(cx)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
size_t length() const { return vector.length(); }
|
||||
|
||||
bool append(jsid id) { return vector.append(id); }
|
||||
|
||||
void popBack() { vector.popBack(); }
|
||||
|
||||
bool resize(size_t newLength) {
|
||||
return vector.resize(newLength);
|
||||
}
|
||||
|
||||
bool reserve(size_t newLength) {
|
||||
return vector.reserve(newLength);
|
||||
}
|
||||
|
||||
jsid operator[](size_t i) { return vector[i]; }
|
||||
jsid operator[](size_t i) const { return vector[i]; }
|
||||
|
||||
const jsid *begin() const { return vector.begin(); }
|
||||
jsid *begin() { return vector.begin(); }
|
||||
|
||||
const jsid *end() const { return vector.end(); }
|
||||
jsid *end() { return vector.end(); }
|
||||
|
||||
jsid back() const { return vector.back(); }
|
||||
|
||||
friend void AutoGCRooter::trace(JSTracer *trc);
|
||||
|
||||
private:
|
||||
Vector<jsboxedword, 8> vector;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
static JS_ALWAYS_INLINE void
|
||||
SetValueRangeToUndefined(Value *vec, Value *end)
|
||||
{
|
||||
|
@ -257,11 +257,17 @@ AutoGCRooter::trace(JSTracer *trc)
|
||||
CallGCMarkerIfGCThing(trc, static_cast<AutoIdRooter *>(this)->idval);
|
||||
return;
|
||||
|
||||
case VECTOR: {
|
||||
case VALVECTOR: {
|
||||
Vector<Value, 8> &vector = static_cast<AutoValueVector *>(this)->vector;
|
||||
TraceValues(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
|
||||
return;
|
||||
}
|
||||
|
||||
case BOXEDVECTOR: {
|
||||
Vector<jsboxedword, 8> &vector = static_cast<AutoBoxedWordVector *>(this)->vector;
|
||||
TraceBoxedWords(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
JS_ASSERT(tag >= 0);
|
||||
|
@ -1125,6 +1125,87 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
CopyableValue
|
||||
BoxedWordToValue(jsboxedword w)
|
||||
{
|
||||
CopyableValue v;
|
||||
if (JSBOXEDWORD_IS_STRING(w))
|
||||
v.setString(JSBOXEDWORD_TO_STRING(w));
|
||||
else if (JSBOXEDWORD_IS_INT(w))
|
||||
v.setInt32(JSBOXEDWORD_TO_INT(w));
|
||||
else if (JSBOXEDWORD_IS_DOUBLE(w))
|
||||
v.setDouble(*JSBOXEDWORD_TO_DOUBLE(w));
|
||||
else if (JSBOXEDWORD_IS_OBJECT(w))
|
||||
v.setObjectOrNull(JSBOXEDWORD_TO_OBJECT(w));
|
||||
else if (JSBOXEDWORD_IS_VOID(w))
|
||||
v.setUndefined();
|
||||
else
|
||||
v.setBoolean(JSBOXEDWORD_TO_BOOLEAN(w));
|
||||
return v;
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToBoxedWord(JSContext *cx, const Value *vp, jsboxedword *wp)
|
||||
{
|
||||
int32_t i;
|
||||
if (vp->isInt32() &&
|
||||
INT32_FITS_IN_JSID((i = vp->asInt32()))) {
|
||||
*wp = INT_TO_JSBOXEDWORD(i);
|
||||
return true;
|
||||
}
|
||||
if (vp->isString()) {
|
||||
*wp = STRING_TO_JSBOXEDWORD(vp->asString());
|
||||
return true;
|
||||
}
|
||||
if (vp->isObjectOrNull()) {
|
||||
*wp = OBJECT_TO_JSBOXEDWORD(vp->asObjectOrNull());
|
||||
return true;
|
||||
}
|
||||
if (vp->isBoolean()) {
|
||||
*wp = BOOLEAN_TO_JSBOXEDWORD(vp->asBoolean());
|
||||
return true;
|
||||
}
|
||||
if (vp->isUndefined()) {
|
||||
*wp = JSBOXEDWORD_VOID;
|
||||
return true;
|
||||
}
|
||||
double *dp = js_NewWeaklyRootedDoubleAtom(cx, vp->asDouble());
|
||||
if (!dp)
|
||||
return false;
|
||||
*wp = DOUBLE_TO_JSBOXEDWORD(dp);
|
||||
return true;
|
||||
}
|
||||
|
||||
Value
|
||||
IdToValue(jsid id)
|
||||
{
|
||||
return BoxedWordToValue(id);
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToId(JSContext *cx, const Value *vp, jsid *idp)
|
||||
{
|
||||
int32_t i;
|
||||
if (ValueFitsInInt32(*vp, &i) && INT32_FITS_IN_JSID(i)) {
|
||||
*idp = INT_TO_JSID(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (vp->isObject()) {
|
||||
Class *clasp = vp->asObject().getClass();
|
||||
if (JS_UNLIKELY(clasp == &js_QNameClass.base ||
|
||||
clasp == &js_AttributeNameClass ||
|
||||
clasp == &js_AnyNameClass)) {
|
||||
*idp = OBJECT_TO_JSID(&vp->asObject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return js_ValueToStringId(cx, *vp, idp);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
@ -1279,46 +1360,6 @@ js_GetUpvar(JSContext *cx, uintN level, uintN cookie)
|
||||
return vp[slot];
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToId(JSContext *cx, const Value *vp, jsid *idp)
|
||||
{
|
||||
int32_t i;
|
||||
if (ValueFitsInInt32(*vp, &i) && INT32_FITS_IN_JSID(i)) {
|
||||
*idp = INT_TO_JSID(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
if (vp->isObject()) {
|
||||
Class *clasp = vp->asObject().getClass();
|
||||
if (JS_UNLIKELY(clasp == &js_QNameClass.base ||
|
||||
clasp == &js_AttributeNameClass ||
|
||||
clasp == &js_AnyNameClass)) {
|
||||
*idp = OBJECT_TO_JSID(&vp->asObject());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return js_ValueToStringId(cx, *vp, idp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally, js::Value should not be passed by value, but this function should
|
||||
* only be used on cold paths, so ease of use wins out.
|
||||
*/
|
||||
Value
|
||||
IdToValue(jsid id)
|
||||
{
|
||||
if (JSID_IS_INT(id))
|
||||
return CopyableValue(Int32Tag(JSID_TO_INT(id)));
|
||||
else if (JSID_IS_ATOM(id))
|
||||
return CopyableValue(ATOM_TO_STRING(JSID_TO_ATOM(id)));
|
||||
else if (JSID_IS_NULL(id))
|
||||
return CopyableValue(NullTag());
|
||||
return CopyableValue(ObjectTag(*JSID_TO_OBJECT(id)));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
JS_STATIC_INTERPRET JS_REQUIRES_STACK void
|
||||
@ -1995,7 +2036,7 @@ IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
if (iterobj->getClass() == &js_IteratorClass.base) {
|
||||
NativeIterator *ni = (NativeIterator *) iterobj->getPrivate();
|
||||
JS_ASSERT(ni->props_cursor < ni->props_end);
|
||||
BoxedWordToValue(*ni->props_cursor, rval);
|
||||
rval->copy(BoxedWordToValue(*ni->props_cursor));
|
||||
if (rval->isString() || (ni->flags & JSITER_FOREACH)) {
|
||||
ni->props_cursor++;
|
||||
return true;
|
||||
|
@ -389,29 +389,18 @@ GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
|
||||
return obj->getPrivate();
|
||||
}
|
||||
|
||||
extern CopyableValue
|
||||
BoxedWordToValue(jsboxedword w);
|
||||
|
||||
extern bool
|
||||
ValueToBoxedWord(JSContext *cx, const Value &v, jsboxedword *w);
|
||||
|
||||
extern Value
|
||||
IdToValue(jsid id);
|
||||
|
||||
extern bool
|
||||
ValueToId(JSContext *cx, const Value &v, jsid *idp);
|
||||
|
||||
inline void
|
||||
BoxedWordToValue(jsboxedword w, Value *vp)
|
||||
{
|
||||
if (JSBOXEDWORD_IS_STRING(w))
|
||||
vp->setString(JSBOXEDWORD_TO_STRING(w));
|
||||
else if (JSBOXEDWORD_IS_INT(w))
|
||||
vp->setInt32(JSBOXEDWORD_TO_INT(w));
|
||||
else if (JSBOXEDWORD_IS_DOUBLE(w))
|
||||
vp->setDouble(*JSBOXEDWORD_TO_DOUBLE(w));
|
||||
else if (JSBOXEDWORD_IS_OBJECT(w))
|
||||
vp->setObjectOrNull(JSBOXEDWORD_TO_OBJECT(w));
|
||||
vp->setBoolean(JSBOXEDWORD_TO_BOOLEAN(w));
|
||||
}
|
||||
|
||||
bool
|
||||
ValueToBoxedWord(JSContext *cx, const Value &v, jsboxedword *w);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
|
@ -133,7 +133,7 @@ iterator_trace(JSTracer *trc, JSObject *obj)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
NewKeyValuePair(JSContext *cx, const Value &key, const Value &val, Value *rval)
|
||||
NewKeyValuePair(JSContext *cx, const Value &key, const Value &val, jsboxedword *wp)
|
||||
{
|
||||
Value vec[2];
|
||||
vec[0].copy(key);
|
||||
@ -143,13 +143,13 @@ NewKeyValuePair(JSContext *cx, const Value &key, const Value &val, Value *rval)
|
||||
JSObject *aobj = js_NewArrayObject(cx, 2, vec);
|
||||
if (!aobj)
|
||||
return false;
|
||||
rval->setNonFunObj(*aobj);
|
||||
*wp = OBJECT_TO_JSBOXEDWORD(aobj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
Enumerate(JSContext *cx, JSObject *obj, jsid id, bool enumerable, uintN flags,
|
||||
HashSet<jsid>& ht, AutoValueVector& vec)
|
||||
Value *tmpRoot, HashSet<jsid>& ht, AutoBoxedWordVector& vec)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_INT(id) || JSID_IS_ATOM(id));
|
||||
|
||||
@ -165,27 +165,37 @@ Enumerate(JSContext *cx, JSObject *obj, jsid id, bool enumerable, uintN flags,
|
||||
}
|
||||
}
|
||||
if (enumerable) {
|
||||
Value idval(IdToValue(id));
|
||||
if (!vec.append(idval)) {
|
||||
if (!vec.append(id)) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
if (flags & JSITER_FOREACH) {
|
||||
Value *vp = vec.end() - 1;
|
||||
if (!obj->getProperty(cx, id, vp))
|
||||
return false;
|
||||
if (flags & JSITER_KEYVALUE && !NewKeyValuePair(cx, idval, *vp, vp))
|
||||
jsboxedword *wp = vec.end() - 1;
|
||||
if (!obj->getProperty(cx, id, tmpRoot))
|
||||
return false;
|
||||
if (flags & JSITER_KEYVALUE) {
|
||||
if (!NewKeyValuePair(cx, IdToValue(id), *tmpRoot, wp))
|
||||
return false;
|
||||
} else {
|
||||
/*
|
||||
* TODO: This is expensive and unnecessary if there are a bunch
|
||||
* of doubles. To fix, we need to change the stored type of
|
||||
* iterators to something fatter than jsboxedword when
|
||||
* iterating in a for-each.
|
||||
*/
|
||||
if (!ValueToBoxedWord(cx, *tmpRoot, wp))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, HashSet<jsid> &ht,
|
||||
AutoValueVector& props)
|
||||
EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, Value *tmpRoot,
|
||||
HashSet<jsid> &ht, AutoBoxedWordVector& props)
|
||||
{
|
||||
AutoValueVector sprops(cx);
|
||||
AutoBoxedWordVector sprops(cx);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
||||
@ -194,7 +204,7 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, HashSet<jsi
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if (!sprop->id != JSBOXEDWORD_VOID &&
|
||||
!sprop->isAlias() &&
|
||||
!Enumerate(cx, obj, sprop->id, sprop->enumerable(), flags, ht, sprops)) {
|
||||
!Enumerate(cx, obj, sprop->id, sprop->enumerable(), flags, tmpRoot, ht, sprops)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -213,8 +223,8 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, HashSet<jsi
|
||||
}
|
||||
|
||||
static bool
|
||||
EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, HashSet<jsid> &ht,
|
||||
AutoValueVector& props)
|
||||
EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, Value *tmpRoot,
|
||||
HashSet<jsid> &ht, AutoBoxedWordVector& props)
|
||||
{
|
||||
size_t count = obj->getDenseArrayCount();
|
||||
|
||||
@ -224,7 +234,7 @@ EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, HashSet
|
||||
for (size_t i = 0; i < capacity; ++i, ++vp) {
|
||||
if (!vp->isMagic(JS_ARRAY_HOLE)) {
|
||||
/* Dense arrays never get so large that i would not fit into an integer id. */
|
||||
if (!Enumerate(cx, obj, INT_TO_JSID(i), true, flags, ht, props))
|
||||
if (!Enumerate(cx, obj, INT_TO_JSID(i), true, flags, tmpRoot, ht, props))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -242,7 +252,8 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoValueVector props(cx);
|
||||
AutoBoxedWordVector props(cx);
|
||||
AutoValueRooter avr(cx);
|
||||
|
||||
while (obj) {
|
||||
Class *clasp = obj->getClass();
|
||||
@ -251,17 +262,17 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
!(clasp->flags & JSCLASS_NEW_ENUMERATE)) {
|
||||
if (!clasp->enumerate(cx, obj))
|
||||
return false;
|
||||
if (!EnumerateNativeProperties(cx, obj, flags, ht, props))
|
||||
if (!EnumerateNativeProperties(cx, obj, flags, avr.addr(), ht, props))
|
||||
return false;
|
||||
} else if (obj->isDenseArray()) {
|
||||
if (!EnumerateDenseArrayProperties(cx, obj, flags, ht, props))
|
||||
if (!EnumerateDenseArrayProperties(cx, obj, flags, avr.addr(), ht, props))
|
||||
return false;
|
||||
} else {
|
||||
Value state;
|
||||
if (!obj->enumerate(cx, JSENUMERATE_INIT, &state, NULL))
|
||||
return false;
|
||||
if (state.isMagic(JS_NATIVE_ENUMERATE)) {
|
||||
if (!EnumerateNativeProperties(cx, obj, flags, ht, props))
|
||||
if (!EnumerateNativeProperties(cx, obj, flags, avr.addr(), ht, props))
|
||||
return false;
|
||||
} else {
|
||||
while (true) {
|
||||
@ -270,7 +281,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
return false;
|
||||
if (state.isNull())
|
||||
break;
|
||||
if (!Enumerate(cx, obj, id, true, flags, ht, props))
|
||||
if (!Enumerate(cx, obj, id, true, flags, avr.addr(), ht, props))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -285,7 +296,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
size_t plength = props.length();
|
||||
|
||||
NativeIterator *ni = (NativeIterator *)
|
||||
cx->malloc(sizeof(NativeIterator) + plength * sizeof(Value) + slength * sizeof(uint32));
|
||||
cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsboxedword) + slength * sizeof(uint32));
|
||||
if (!ni) {
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -293,7 +304,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui
|
||||
ni->props_array = ni->props_cursor = (jsboxedword *) (ni + 1);
|
||||
ni->props_end = ni->props_array + plength;
|
||||
if (plength)
|
||||
memcpy(ni->props_array, props.begin(), plength * sizeof(Value));
|
||||
memcpy(ni->props_array, props.begin(), plength * sizeof(jsboxedword));
|
||||
ni->shapes_array = (uint32 *) ni->props_end;
|
||||
ni->shapes_length = slength;
|
||||
ni->shapes_key = key;
|
||||
@ -482,11 +493,10 @@ iterator_next(JSContext *cx, uintN argc, Value *vp)
|
||||
|
||||
if (!js_IteratorMore(cx, obj, vp))
|
||||
return false;
|
||||
if (vp->isBoolean(false)) {
|
||||
if (!vp->asBoolean()) {
|
||||
js_ThrowStopIteration(cx);
|
||||
return false;
|
||||
}
|
||||
JS_ASSERT(vp->isBoolean(true));
|
||||
return js_IteratorNext(cx, obj, vp);
|
||||
}
|
||||
|
||||
@ -647,7 +657,7 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval)
|
||||
*/
|
||||
NativeIterator *ni = iterobj->getNativeIterator();
|
||||
JS_ASSERT(ni->props_cursor < ni->props_end);
|
||||
BoxedWordToValue(*ni->props_cursor++, rval);
|
||||
rval->copy(BoxedWordToValue(*ni->props_cursor++));
|
||||
|
||||
if (rval->isString() || (ni->flags & JSITER_FOREACH))
|
||||
return true;
|
||||
|
@ -56,7 +56,6 @@
|
||||
#include "jsmath.h"
|
||||
#include "jsnum.h"
|
||||
#include "jslibmath.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
@ -114,67 +113,71 @@ math_abs(JSContext *cx, uintN argc, Value *vp)
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = fabs(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_acos(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_acos(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
#if defined(SOLARIS) && defined(__GNUC__)
|
||||
if (x < -1 || 1 < x) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
z = acos(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_asin(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_asin(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
#if defined(SOLARIS) && defined(__GNUC__)
|
||||
if (x < -1 || 1 < x) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
z = asin(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_atan(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_atan(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = atan(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static inline jsdouble JS_FASTCALL
|
||||
@ -208,19 +211,21 @@ math_atan2_kernel(jsdouble x, jsdouble y)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_atan2(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_atan2(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, y;
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (argc <= 1) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
if (!ValueToNumber(cx, vp[3], &y))
|
||||
if (!ValueToNumber(cx, &vp[3], &y))
|
||||
return JS_FALSE;
|
||||
return js_NewNumberInRootedValue(cx, math_atan2_kernel (x, y), vp);
|
||||
z = math_atan2_kernel(x, y);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static inline jsdouble JS_FASTCALL
|
||||
@ -234,115 +239,120 @@ math_ceil_kernel(jsdouble x)
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_ceil(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_math_ceil(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = math_ceil_kernel(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_cos(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_cos(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = cos(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_exp(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_exp(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
#ifdef _WIN32
|
||||
if (!JSDOUBLE_IS_NaN(x)) {
|
||||
if (x == js_PositiveInfinity) {
|
||||
*vp = cx->runtime->positiveInfinityValue;
|
||||
vp->setDouble(js_PositiveInfinity);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (x == js_NegativeInfinity) {
|
||||
*vp = JSVAL_ZERO;
|
||||
vp->setInt32(0);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
z = exp(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_floor(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_math_floor(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = floor(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_log(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_log(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
#if defined(SOLARIS) && defined(__GNUC__)
|
||||
if (x < 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
z = log(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_max(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_math_max(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z = js_NegativeInfinity;
|
||||
jsval *argv;
|
||||
Value *argv;
|
||||
uintN i;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->negativeInfinityValue;
|
||||
vp->setDouble(js_NegativeInfinity);
|
||||
return JS_TRUE;
|
||||
}
|
||||
argv = vp + 2;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ValueToNumber(cx, argv[i], &x))
|
||||
if (!ValueToNumber(cx, &argv[i], &x))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(x)) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (x == 0 && x == z) {
|
||||
@ -352,26 +362,27 @@ js_math_max(JSContext *cx, uintN argc, jsval *vp)
|
||||
z = (x > z) ? x : z;
|
||||
}
|
||||
}
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_math_min(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_math_min(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z = js_PositiveInfinity;
|
||||
jsval *argv;
|
||||
Value *argv;
|
||||
uintN i;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->positiveInfinityValue;
|
||||
vp->setDouble(js_PositiveInfinity);
|
||||
return JS_TRUE;
|
||||
}
|
||||
argv = vp + 2;
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!ValueToNumber(cx, argv[i], &x))
|
||||
if (!ValueToNumber(cx, &argv[i], &x))
|
||||
return JS_FALSE;
|
||||
if (JSDOUBLE_IS_NaN(x)) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (x == 0 && x == z) {
|
||||
@ -381,37 +392,39 @@ js_math_min(JSContext *cx, uintN argc, jsval *vp)
|
||||
z = (x < z) ? x : z;
|
||||
}
|
||||
}
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_pow(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_pow(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, y, z;
|
||||
|
||||
if (argc <= 1) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
if (!ValueToNumber(cx, vp[3], &y))
|
||||
if (!ValueToNumber(cx, &vp[3], &y))
|
||||
return JS_FALSE;
|
||||
/*
|
||||
* Because C99 and ECMA specify different behavior for pow(),
|
||||
* we need to wrap the libm call to make it ECMA compliant.
|
||||
*/
|
||||
if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
/* pow(x, +-0) is always 1, even for x = NaN. */
|
||||
if (y == 0) {
|
||||
*vp = JSVAL_ONE;
|
||||
vp->setInt32(1);
|
||||
return JS_TRUE;
|
||||
}
|
||||
z = pow(x, y);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL;
|
||||
@ -460,10 +473,11 @@ random_nextDouble(JSContext *cx)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_random(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_random(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble z = random_nextDouble(cx);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if defined _WIN32 && !defined WINCE && _MSC_VER < 1400
|
||||
@ -482,70 +496,74 @@ js_copysign(double x, double y)
|
||||
#endif
|
||||
|
||||
JSBool
|
||||
js_math_round(JSContext *cx, uintN argc, jsval *vp)
|
||||
js_math_round(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = js_copysign(floor(x + 0.5), x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setNumber(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_sin(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_sin(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = sin(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_sqrt(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_sqrt(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = sqrt(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
math_tan(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_tan(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
jsdouble x, z;
|
||||
|
||||
if (argc == 0) {
|
||||
*vp = cx->runtime->NaNValue;
|
||||
vp->setDouble(js_NaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
if (!ValueToNumber(cx, vp[2], &x))
|
||||
if (!ValueToNumber(cx, &vp[2], &x))
|
||||
return JS_FALSE;
|
||||
z = tan(x);
|
||||
return js_NewNumberInRootedValue(cx, z, vp);
|
||||
vp->setDouble(z);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
static JSBool
|
||||
math_toSource(JSContext *cx, uintN argc, jsval *vp)
|
||||
math_toSource(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
*vp = ATOM_KEY(CLASS_ATOM(cx, Math));
|
||||
vp->setString(ATOM_TO_STRING(CLASS_ATOM(cx, Math)));
|
||||
return JS_TRUE;
|
||||
}
|
||||
#endif
|
||||
@ -739,7 +757,7 @@ js_InitMathClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *Math;
|
||||
|
||||
Math = JS_NewObject(cx, &js_MathClass, NULL, obj);
|
||||
Math = JS_NewObject(cx, Jsvalify(&js_MathClass), NULL, obj);
|
||||
if (!Math)
|
||||
return NULL;
|
||||
if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
|
||||
|
@ -52,18 +52,18 @@ extern void
|
||||
js_InitRandom(JSContext *cx);
|
||||
|
||||
extern JSBool
|
||||
js_math_ceil(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_math_ceil(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_math_floor(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_math_floor(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_math_max(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_math_max(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_math_min(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_math_min(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
extern JSBool
|
||||
js_math_round(JSContext *cx, uintN argc, jsval *vp);
|
||||
js_math_round(JSContext *cx, uintN argc, js::Value *vp);
|
||||
|
||||
#endif /* jsmath_h___ */
|
||||
|
@ -615,6 +615,16 @@ Uint32ToValue(uint32_t u, Value *vp)
|
||||
vp->setInt32((int32_t)u);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void
|
||||
Value::setNumber(double d)
|
||||
{
|
||||
int32_t i;
|
||||
if (JSDOUBLE_IS_INT32(d, i))
|
||||
setInt32(i);
|
||||
else
|
||||
setDouble(d);
|
||||
}
|
||||
|
||||
template<typename T> struct NumberTraits { };
|
||||
template<> struct NumberTraits<int32> {
|
||||
static JS_ALWAYS_INLINE int32 NaN() { return 0; }
|
||||
|
@ -685,6 +685,11 @@ Value::Value(ObjectTag arg)
|
||||
data.obj = &arg.obj;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
CopyableValue::CopyableValue(ObjectTag arg)
|
||||
: Value(arg)
|
||||
{}
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
Value::Value(ObjectOrNullTag arg)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user