mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
[mq]: Refactor value logic for better reuse
This commit is contained in:
parent
a2c395a9dc
commit
f7242c4d3f
230
js/src/jsapi.h
230
js/src/jsapi.h
@ -52,12 +52,12 @@
|
|||||||
JS_BEGIN_EXTERN_C
|
JS_BEGIN_EXTERN_C
|
||||||
|
|
||||||
/* Well-known JS values, initialized on startup. */
|
/* Well-known JS values, initialized on startup. */
|
||||||
#define JSVAL_NULL JSVAL_CONSTANT(JSVAL_MASK32_NULL, 0)
|
#define JSVAL_NULL BUILD_JSVAL(JSVAL_MASK32_NULL, 0)
|
||||||
#define JSVAL_ZERO JSVAL_CONSTANT(JSVAL_MASK32_INT32, 0)
|
#define JSVAL_ZERO BUILD_JSVAL(JSVAL_MASK32_INT32, 0)
|
||||||
#define JSVAL_ONE JSVAL_CONSTANT(JSVAL_MASK32_INT32, 1)
|
#define JSVAL_ONE BUILD_JSVAL(JSVAL_MASK32_INT32, 1)
|
||||||
#define JSVAL_FALSE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_FALSE)
|
#define JSVAL_FALSE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_FALSE)
|
||||||
#define JSVAL_TRUE JSVAL_CONSTANT(JSVAL_MASK32_BOOLEAN, JS_TRUE)
|
#define JSVAL_TRUE BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, JS_TRUE)
|
||||||
#define JSVAL_VOID JSVAL_CONSTANT(JSVAL_MASK32_UNDEFINED, 0)
|
#define JSVAL_VOID BUILD_JSVAL(JSVAL_MASK32_UNDEFINED, 0)
|
||||||
|
|
||||||
/* Predicates for type testing. */
|
/* Predicates for type testing. */
|
||||||
|
|
||||||
@ -65,14 +65,14 @@ static JS_ALWAYS_INLINE JSBool
|
|||||||
JSVAL_IS_NULL(jsval v)
|
JSVAL_IS_NULL(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.mask32 == JSVAL_MASK32_NULL;
|
return JSVAL_IS_NULL_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_VOID(jsval v)
|
JSVAL_IS_VOID(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.mask32 == JSVAL_MASK32_UNDEFINED;
|
return JSVAL_IS_UNDEFINED_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
@ -103,17 +103,14 @@ INT_FITS_IN_JSVAL(jsint i)
|
|||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
INT_TO_JSVAL(int32 i)
|
INT_TO_JSVAL(int32 i)
|
||||||
{
|
{
|
||||||
jsval_layout l;
|
return INT32_TO_JSVAL_IMPL(i).asBits;
|
||||||
l.s.mask32 = JSVAL_MASK32_INT32;
|
|
||||||
l.s.payload.i32 = i;
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_DOUBLE(jsval v)
|
JSVAL_IS_DOUBLE(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.mask32 < JSVAL_MASK32_CLEAR;
|
return JSVAL_IS_DOUBLE_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE jsdouble
|
static JS_ALWAYS_INLINE jsdouble
|
||||||
@ -127,16 +124,14 @@ JSVAL_TO_DOUBLE(jsval v)
|
|||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
DOUBLE_TO_JSVAL(jsdouble d)
|
DOUBLE_TO_JSVAL(jsdouble d)
|
||||||
{
|
{
|
||||||
jsval_layout l;
|
return DOUBLE_TO_JSVAL_IMPL(d).asBits;
|
||||||
l.asDouble = d;
|
|
||||||
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_NUMBER(jsval v)
|
JSVAL_IS_NUMBER(jsval v)
|
||||||
{
|
{
|
||||||
return JSVAL_IS_INT(v) | JSVAL_IS_DOUBLE(v);
|
jsval_layout l = { v };
|
||||||
|
return JSVAL_IS_NUMBER_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
@ -151,30 +146,20 @@ JSVAL_TO_STRING(jsval v)
|
|||||||
{
|
{
|
||||||
JS_ASSERT(JSVAL_IS_STRING(v));
|
JS_ASSERT(JSVAL_IS_STRING(v));
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.payload.str;
|
return JSVAL_TO_STRING_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
STRING_TO_JSVAL(JSString *str)
|
STRING_TO_JSVAL(JSString *str)
|
||||||
{
|
{
|
||||||
jsval_layout l;
|
return STRING_TO_JSVAL_IMPL(str).asBits;
|
||||||
l.s.mask32 = JSVAL_MASK32_STRING;
|
|
||||||
l.s.payload.str = str;
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* N.B. These functions use the older meaning of "object" as "object or null".
|
|
||||||
* This is not a problem if code only works with jsvals or only works with
|
|
||||||
* js::Value, but if both uses are mixed, it is important not to get confused
|
|
||||||
* by the two meanings. For example, JSVAL_IS_OBJECT(v) does not imply
|
|
||||||
* v.isObject().
|
|
||||||
*/
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_OBJECT(jsval v)
|
JSVAL_IS_OBJECT(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return (l.s.mask32 & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR;
|
return JSVAL_IS_OBJECT_OR_NULL_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSObject *
|
static JS_ALWAYS_INLINE JSObject *
|
||||||
@ -182,9 +167,10 @@ JSVAL_TO_OBJECT(jsval v)
|
|||||||
{
|
{
|
||||||
JS_ASSERT(JSVAL_IS_OBJECT(v));
|
JS_ASSERT(JSVAL_IS_OBJECT(v));
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.payload.obj;
|
return JSVAL_TO_OBJECT_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* N.B. Not cheap; uses public API instead of obj->isFunction()! */
|
||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
OBJECT_TO_JSVAL(JSObject *obj)
|
OBJECT_TO_JSVAL(JSObject *obj)
|
||||||
{
|
{
|
||||||
@ -193,12 +179,10 @@ OBJECT_TO_JSVAL(JSObject *obj)
|
|||||||
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return JSVAL_NULL;
|
return JSVAL_NULL;
|
||||||
uint32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
|
|
||||||
: JSVAL_MASK32_NONFUNOBJ;
|
JSValueMask32 mask = JS_ObjectIsFunction(NULL, obj) ? JSVAL_MASK32_FUNOBJ
|
||||||
jsval_layout l;
|
: JSVAL_MASK32_NONFUNOBJ;
|
||||||
l.s.mask32 = mask;
|
return OBJECT_TO_JSVAL_IMPL(mask, obj).asBits;
|
||||||
l.s.payload.obj = obj;
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
@ -219,24 +203,21 @@ JSVAL_TO_BOOLEAN(jsval v)
|
|||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
BOOLEAN_TO_JSVAL(JSBool b)
|
BOOLEAN_TO_JSVAL(JSBool b)
|
||||||
{
|
{
|
||||||
jsval_layout l;
|
return BOOLEAN_TO_JSVAL_IMPL(b).asBits;
|
||||||
l.s.mask32 = JSVAL_MASK32_BOOLEAN;
|
|
||||||
l.s.payload.boo = b;
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_PRIMITIVE(jsval v)
|
JSVAL_IS_PRIMITIVE(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return (l.s.mask32 & JSVAL_MASK32_OBJECT) <= JSVAL_MASK32_CLEAR;
|
return JSVAL_IS_PRIMITIVE_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE JSBool
|
static JS_ALWAYS_INLINE JSBool
|
||||||
JSVAL_IS_GCTHING(jsval v)
|
JSVAL_IS_GCTHING(jsval v)
|
||||||
{
|
{
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return (l.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR;
|
return JSVAL_IS_GCTHING_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE void *
|
static JS_ALWAYS_INLINE void *
|
||||||
@ -244,24 +225,23 @@ JSVAL_TO_GCTHING(jsval v)
|
|||||||
{
|
{
|
||||||
JS_ASSERT(JSVAL_IS_GCTHING(v));
|
JS_ASSERT(JSVAL_IS_GCTHING(v));
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.payload.ptr;
|
return JSVAL_TO_GCTHING_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* To be GC-safe, privates are tagged as doubles. */
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE jsval
|
static JS_ALWAYS_INLINE jsval
|
||||||
PRIVATE_TO_JSVAL(void *ptr)
|
PRIVATE_TO_JSVAL(void *ptr)
|
||||||
{
|
{
|
||||||
jsval_layout l;
|
return PRIVATE_TO_JSVAL_IMPL(ptr).asBits;
|
||||||
l.s.mask32 = JSVAL_MASK32_INT32;
|
|
||||||
l.s.payload.ptr = ptr;
|
|
||||||
return l.asBits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JS_ALWAYS_INLINE void *
|
static JS_ALWAYS_INLINE void *
|
||||||
JSVAL_TO_PRIVATE(jsval v)
|
JSVAL_TO_PRIVATE(jsval v)
|
||||||
{
|
{
|
||||||
JS_ASSERT(JSVAL_IS_INT(v));
|
JS_ASSERT(JSVAL_IS_DOUBLE(v));
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return l.s.payload.ptr;
|
return JSVAL_TO_PRIVATE_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lock and unlock the GC thing held by a jsval. */
|
/* Lock and unlock the GC thing held by a jsval. */
|
||||||
@ -1187,7 +1167,7 @@ JSVAL_TRACE_KIND(jsval v)
|
|||||||
{
|
{
|
||||||
JS_ASSERT(JSVAL_IS_GCTHING(v));
|
JS_ASSERT(JSVAL_IS_GCTHING(v));
|
||||||
jsval_layout l = { v };
|
jsval_layout l = { v };
|
||||||
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING);
|
return JSVAL_TRACE_KIND_IMPL(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JSTracer {
|
struct JSTracer {
|
||||||
@ -3007,44 +2987,26 @@ class Value
|
|||||||
* break this encapsulation should be listed as friends below. Also see
|
* break this encapsulation should be listed as friends below. Also see
|
||||||
* uses of public jsval members in jsapi.h/jspubtd.h.
|
* uses of public jsval members in jsapi.h/jspubtd.h.
|
||||||
*/
|
*/
|
||||||
friend bool StrictlyEqual(JSContext *, const Value &, const Value &);
|
|
||||||
friend bool Interpret(JSContext *); /* grep "value representation" */
|
|
||||||
friend class PrimitiveValue;
|
friend class PrimitiveValue;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Type masks */
|
/* Type masks */
|
||||||
|
|
||||||
|
template <int I> class T {};
|
||||||
|
|
||||||
void staticAssertions() {
|
void staticAssertions() {
|
||||||
JS_STATIC_ASSERT(sizeof(void *) == 4);
|
|
||||||
JS_STATIC_ASSERT(sizeof(jsval) == 8);
|
|
||||||
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
|
|
||||||
JS_STATIC_ASSERT(sizeof(JSValueMask16) == 2);
|
JS_STATIC_ASSERT(sizeof(JSValueMask16) == 2);
|
||||||
JS_STATIC_ASSERT(sizeof(jsval_payload) == 4);
|
JS_STATIC_ASSERT(JSVAL_NANBOX_PATTERN == 0xFFFF);
|
||||||
|
JS_STATIC_ASSERT(sizeof(JSValueMask32) == 4);
|
||||||
|
JS_STATIC_ASSERT(JSVAL_MASK32_CLEAR == 0xFFFF0000);
|
||||||
|
JS_STATIC_ASSERT(sizeof(JSBool) == 4);
|
||||||
JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
|
JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
|
||||||
|
JS_STATIC_ASSERT(sizeof(((jsval_layout *)0)->s.payload) == 4);
|
||||||
|
JS_STATIC_ASSERT(sizeof(jsval) == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
jsval_layout data;
|
jsval_layout data;
|
||||||
|
|
||||||
static bool isNullOrUndefinedMask(uint32 mask) {
|
|
||||||
return (mask & JSVAL_MASK32_SINGLETON) > JSVAL_MASK32_CLEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isDoubleMask(uint32 mask) {
|
|
||||||
return mask < JSVAL_MASK32_CLEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isNumberMask(uint32 mask) {
|
|
||||||
return (mask < JSVAL_MASK32_CLEAR) | (mask == JSVAL_MASK32_INT32);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isObjectMask(uint32 mask) {
|
|
||||||
return (mask & JSVAL_MASK32_OBJECT) > JSVAL_MASK32_CLEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isObjectOrNullMask(uint32 mask) {
|
|
||||||
return (mask & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
|
||||||
@ -3075,18 +3037,15 @@ class Value
|
|||||||
/* Change to a Value of a single type */
|
/* Change to a Value of a single type */
|
||||||
|
|
||||||
void setNull() {
|
void setNull() {
|
||||||
data.s.mask32 = JSVAL_MASK32_NULL;
|
data.asBits = JSVAL_NULL;
|
||||||
data.s.payload.obj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUndefined() {
|
void setUndefined() {
|
||||||
data.s.mask32 = JSVAL_MASK32_UNDEFINED;
|
data.asBits = JSVAL_VOID;
|
||||||
data.s.payload.obj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInt32(int32 i) {
|
void setInt32(int32 i) {
|
||||||
data.s.mask32 = JSVAL_MASK32_INT32;
|
data = INT32_TO_JSVAL_IMPL(i);
|
||||||
data.s.payload.i32 = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 &asInt32Ref() {
|
int32 &asInt32Ref() {
|
||||||
@ -3096,8 +3055,7 @@ class Value
|
|||||||
|
|
||||||
void setDouble(double d) {
|
void setDouble(double d) {
|
||||||
ASSERT_DOUBLE_ALIGN();
|
ASSERT_DOUBLE_ALIGN();
|
||||||
data.asDouble = d;
|
data = DOUBLE_TO_JSVAL_IMPL(d);
|
||||||
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double &asDoubleRef() {
|
double &asDoubleRef() {
|
||||||
@ -3107,62 +3065,54 @@ class Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setString(JSString *str) {
|
void setString(JSString *str) {
|
||||||
data.s.mask32 = JSVAL_MASK32_STRING;
|
data = STRING_TO_JSVAL_IMPL(str);
|
||||||
data.s.payload.str = str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFunObj(JSObject &arg) {
|
void setFunObj(JSObject &arg) {
|
||||||
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
|
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
|
||||||
data.s.mask32 = JSVAL_MASK32_FUNOBJ;
|
data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_FUNOBJ, &arg);
|
||||||
data.s.payload.obj = &arg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNonFunObj(JSObject &arg) {
|
void setNonFunObj(JSObject &arg) {
|
||||||
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
|
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
|
||||||
data.s.mask32 = JSVAL_MASK32_NONFUNOBJ;
|
data = OBJECT_TO_JSVAL_IMPL(JSVAL_MASK32_NONFUNOBJ, &arg);
|
||||||
data.s.payload.obj = &arg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBoolean(bool b) {
|
void setBoolean(bool b) {
|
||||||
data.s.mask32 = JSVAL_MASK32_BOOLEAN;
|
data = BOOLEAN_TO_JSVAL_IMPL(b);
|
||||||
data.s.payload.boo = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMagic(JSWhyMagic why) {
|
void setMagic(JSWhyMagic why) {
|
||||||
data.s.mask32 = JSVAL_MASK32_MAGIC;
|
data = MAGIC_TO_JSVAL_IMPL(why);
|
||||||
data.s.payload.why = why;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change to a Value of a type dynamically chosen from a set of types */
|
/* Change to a Value of a type dynamically chosen from a set of types */
|
||||||
|
|
||||||
void setNumber(uint32 ui) {
|
void setNumber(uint32 ui) {
|
||||||
if (ui > JSVAL_INT_MAX) {
|
if (ui > JSVAL_INT_MAX)
|
||||||
data.asDouble = ui;
|
data = DOUBLE_TO_JSVAL_IMPL(ui);
|
||||||
JS_ASSERT(data.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
|
else
|
||||||
} else {
|
data = INT32_TO_JSVAL_IMPL((int32)ui);
|
||||||
data.s.mask32 = JSVAL_MASK32_INT32;
|
|
||||||
data.s.payload.i32 = (int32)ui;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setNumber(double d);
|
inline void setNumber(double d);
|
||||||
|
|
||||||
void setFunObjOrNull(JSObject *arg) {
|
void setFunObjOrNull(JSObject *arg) {
|
||||||
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
|
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
|
||||||
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL;
|
JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_NULL;
|
||||||
data.s.payload.obj = arg;
|
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFunObjOrUndefined(JSObject *arg) {
|
void setFunObjOrUndefined(JSObject *arg) {
|
||||||
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
|
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
|
||||||
data.s.mask32 = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED;
|
JSValueMask32 mask = arg ? JSVAL_MASK32_FUNOBJ : JSVAL_MASK32_UNDEFINED;
|
||||||
data.s.payload.obj = arg;
|
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNonFunObjOrNull(JSObject *arg) {
|
void setNonFunObjOrNull(JSObject *arg) {
|
||||||
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
|
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
|
||||||
data.s.mask32 = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL;
|
JSValueMask32 mask = arg ? JSVAL_MASK32_NONFUNOBJ : JSVAL_MASK32_NULL;
|
||||||
data.s.payload.obj = arg;
|
data = OBJECT_TO_JSVAL_IMPL(mask, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setObject(JSObject &arg);
|
inline void setObject(JSObject &arg);
|
||||||
@ -3171,15 +3121,15 @@ class Value
|
|||||||
/* Query a Value's type */
|
/* Query a Value's type */
|
||||||
|
|
||||||
bool isUndefined() const {
|
bool isUndefined() const {
|
||||||
return data.s.mask32 == JSVAL_MASK32_UNDEFINED;
|
return JSVAL_IS_UNDEFINED_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return data.s.mask32 == JSVAL_MASK32_NULL;
|
return JSVAL_IS_NULL_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNullOrUndefined() const {
|
bool isNullOrUndefined() const {
|
||||||
return isNullOrUndefinedMask(data.s.mask32);
|
return JSVAL_IS_SINGLETON_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInt32() const {
|
bool isInt32() const {
|
||||||
@ -3187,16 +3137,15 @@ class Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isInt32(int32 i32) const {
|
bool isInt32(int32 i32) const {
|
||||||
return (data.s.mask32 == JSVAL_MASK32_INT32) &
|
return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
|
||||||
(data.s.payload.i32 == i32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDouble() const {
|
bool isDouble() const {
|
||||||
return isDoubleMask(data.s.mask32);
|
return JSVAL_IS_DOUBLE_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNumber() const {
|
bool isNumber() const {
|
||||||
return isNumberMask(data.s.mask32);
|
return JSVAL_IS_NUMBER_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isString() const {
|
bool isString() const {
|
||||||
@ -3212,19 +3161,19 @@ class Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isObject() const {
|
bool isObject() const {
|
||||||
return isObjectMask(data.s.mask32);
|
return JSVAL_IS_OBJECT_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPrimitive() const {
|
bool isPrimitive() const {
|
||||||
return !isObject();
|
return JSVAL_IS_PRIMITIVE_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isObjectOrNull() const {
|
bool isObjectOrNull() const {
|
||||||
return isObjectOrNullMask(data.s.mask32);
|
return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isGCThing() const {
|
bool isGCThing() const {
|
||||||
return (data.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR;
|
return JSVAL_IS_GCTHING_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoolean() const {
|
bool isBoolean() const {
|
||||||
@ -3232,13 +3181,11 @@ class Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isTrue() const {
|
bool isTrue() const {
|
||||||
return data.s.mask32 == JSVAL_MASK32_BOOLEAN &&
|
return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
|
||||||
data.s.payload.boo == JS_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFalse() const {
|
bool isFalse() const {
|
||||||
return data.s.mask32 == JSVAL_MASK32_BOOLEAN &&
|
return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
|
||||||
data.s.payload.boo == JS_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMagic() const {
|
bool isMagic() const {
|
||||||
@ -3252,13 +3199,17 @@ class Value
|
|||||||
|
|
||||||
int32 traceKind() const {
|
int32 traceKind() const {
|
||||||
JS_ASSERT(isGCThing());
|
JS_ASSERT(isGCThing());
|
||||||
return (int32)(data.s.mask32 == JSVAL_MASK32_STRING);
|
return JSVAL_TRACE_KIND_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
JSWhyMagic whyMagic() const {
|
JSWhyMagic whyMagic() const {
|
||||||
JS_ASSERT(isMagic());
|
JS_ASSERT(isMagic());
|
||||||
return data.s.payload.why;
|
return data.s.payload.why;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Comparison */
|
||||||
|
|
||||||
bool operator==(const Value &rhs) const {
|
bool operator==(const Value &rhs) const {
|
||||||
return data.asBits == rhs.data.asBits;
|
return data.asBits == rhs.data.asBits;
|
||||||
@ -3268,6 +3219,18 @@ class Value
|
|||||||
return data.asBits != rhs.data.asBits;
|
return data.asBits != rhs.data.asBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend bool SamePrimitiveTypeOrBothObjects(const Value &lhs, const Value &rhs) {
|
||||||
|
return JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(lhs.data, rhs.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool BothInt32(const Value &lhs, const Value &rhs) {
|
||||||
|
return JSVAL_BOTH_INT32_IMPL(lhs.data, rhs.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool BothString(const Value &lhs, const Value &rhs) {
|
||||||
|
return JSVAL_BOTH_STRING_IMPL(lhs.data, rhs.data);
|
||||||
|
}
|
||||||
|
|
||||||
/* Extract a Value's payload */
|
/* Extract a Value's payload */
|
||||||
|
|
||||||
int32 asInt32() const {
|
int32 asInt32() const {
|
||||||
@ -3288,32 +3251,32 @@ class Value
|
|||||||
|
|
||||||
JSString *asString() const {
|
JSString *asString() const {
|
||||||
JS_ASSERT(isString());
|
JS_ASSERT(isString());
|
||||||
return data.s.payload.str;
|
return JSVAL_TO_STRING_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject &asNonFunObj() const {
|
JSObject &asNonFunObj() const {
|
||||||
JS_ASSERT(isNonFunObj());
|
JS_ASSERT(isNonFunObj());
|
||||||
return *data.s.payload.obj;
|
return *JSVAL_TO_OBJECT_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject &asFunObj() const {
|
JSObject &asFunObj() const {
|
||||||
JS_ASSERT(isFunObj());
|
JS_ASSERT(isFunObj());
|
||||||
return *data.s.payload.obj;
|
return *JSVAL_TO_OBJECT_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject &asObject() const {
|
JSObject &asObject() const {
|
||||||
JS_ASSERT(isObject());
|
JS_ASSERT(isObject());
|
||||||
return *data.s.payload.obj;
|
return *JSVAL_TO_OBJECT_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject *asObjectOrNull() const {
|
JSObject *asObjectOrNull() const {
|
||||||
JS_ASSERT(isObjectOrNull());
|
JS_ASSERT(isObjectOrNull());
|
||||||
return data.s.payload.obj;
|
return JSVAL_TO_OBJECT_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *asGCThing() const {
|
void *asGCThing() const {
|
||||||
JS_ASSERT(isGCThing());
|
JS_ASSERT(isGCThing());
|
||||||
return data.s.payload.ptr;
|
return JSVAL_TO_GCTHING_IMPL(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool asBoolean() const {
|
bool asBoolean() const {
|
||||||
@ -3321,6 +3284,11 @@ class Value
|
|||||||
return data.s.payload.boo;
|
return data.s.payload.boo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 asRawUint32() const {
|
||||||
|
JS_ASSERT(!isDouble());
|
||||||
|
return data.s.payload.u32;
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap two Values */
|
/* Swap two Values */
|
||||||
|
|
||||||
void swap(Value &rhs) {
|
void swap(Value &rhs) {
|
||||||
|
@ -385,8 +385,7 @@ NoSuchMethod(JSContext *cx, uintN argc, Value *vp, uint32 flags)
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 |
|
static const uint32 FAKE_NUMBER_MASK = JSVAL_MASK32_INT32 | PrimitiveValue::DOUBLE_MASK;
|
||||||
PrimitiveValue::DOUBLE_MASK;
|
|
||||||
|
|
||||||
const uint32 PrimitiveValue::Masks[PrimitiveValue::THISP_ARRAY_SIZE] = {
|
const uint32 PrimitiveValue::Masks[PrimitiveValue::THISP_ARRAY_SIZE] = {
|
||||||
0, /* 000 */
|
0, /* 000 */
|
||||||
@ -952,36 +951,29 @@ EqualObjects(JSContext *cx, JSObject *lobj, JSObject *robj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval)
|
StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref)
|
||||||
{
|
{
|
||||||
uint32 lmask = lval.data.s.mask32;
|
Value lval = lref, rval = rref;
|
||||||
uint32 rmask = rval.data.s.mask32;
|
if (SamePrimitiveTypeOrBothObjects(lval, rval)) {
|
||||||
if (lmask == rmask) {
|
if (lval.isString())
|
||||||
if (lmask == JSVAL_MASK32_STRING)
|
return js_EqualStrings(lval.asString(), rval.asString());
|
||||||
return js_EqualStrings(lval.data.s.payload.str, rval.data.s.payload.str);
|
if (lval.isDouble())
|
||||||
if (Value::isObjectMask(lmask))
|
return JSDOUBLE_COMPARE(lval.asDouble(), ==, rval.asDouble(), JS_FALSE);
|
||||||
return EqualObjects(cx, lval.data.s.payload.obj, rval.data.s.payload.obj);
|
if (lval.isObject())
|
||||||
if (Value::isDoubleMask(lmask))
|
return EqualObjects(cx, &lval.asObject(), &rval.asObject());
|
||||||
return JSDOUBLE_COMPARE(lval.data.asDouble, ==, rval.data.asDouble, JS_FALSE);
|
return lval.asRawUint32() == rval.asRawUint32();
|
||||||
JS_ASSERT(lmask == JSVAL_MASK32_NULL ||
|
|
||||||
lmask == JSVAL_MASK32_UNDEFINED ||
|
|
||||||
lmask == JSVAL_MASK32_INT32 ||
|
|
||||||
lmask == JSVAL_MASK32_FUNOBJ ||
|
|
||||||
lmask == JSVAL_MASK32_NONFUNOBJ ||
|
|
||||||
lmask == JSVAL_MASK32_BOOLEAN);
|
|
||||||
return lval.data.s.payload.u32 == rval.data.s.payload.u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Value::isNumberMask(lmask) && Value::isNumberMask(rmask)) {
|
if (lval.isDouble() && rval.isInt32()) {
|
||||||
double ld = lmask == JSVAL_MASK32_INT32 ? lval.data.s.payload.i32
|
double ld = lval.asDouble();
|
||||||
: lval.data.asDouble;
|
double rd = rval.asInt32();
|
||||||
double rd = rmask == JSVAL_MASK32_INT32 ? rval.data.s.payload.i32
|
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
||||||
: rval.data.asDouble;
|
}
|
||||||
|
if (lval.isInt32() && rval.isDouble()) {
|
||||||
|
double ld = lval.asInt32();
|
||||||
|
double rd = rval.asDouble();
|
||||||
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Value::isObjectMask(lmask) && Value::isObjectMask(rmask))
|
|
||||||
return EqualObjects(cx, lval.data.s.payload.obj, rval.data.s.payload.obj);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1787,6 +1779,15 @@ namespace reprmeter {
|
|||||||
VALUE_TO_OBJECT(cx, vp_, obj); \
|
VALUE_TO_OBJECT(cx, vp_, obj); \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
|
#define DEFAULT_VALUE(cx, n, hint, v) \
|
||||||
|
JS_BEGIN_MACRO \
|
||||||
|
JS_ASSERT(v.isObject()); \
|
||||||
|
JS_ASSERT(v == regs.sp[n]); \
|
||||||
|
if (!v.asObject().defaultValue(cx, hint, ®s.sp[n])) \
|
||||||
|
goto error; \
|
||||||
|
v = regs.sp[n]; \
|
||||||
|
JS_END_MACRO
|
||||||
|
|
||||||
/* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */
|
/* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */
|
||||||
static JS_ALWAYS_INLINE bool
|
static JS_ALWAYS_INLINE bool
|
||||||
CanIncDecWithoutOverflow(int32_t i)
|
CanIncDecWithoutOverflow(int32_t i)
|
||||||
|
@ -283,7 +283,7 @@ class PrimitiveValue
|
|||||||
static const uint32 Masks[THISP_ARRAY_SIZE];
|
static const uint32 Masks[THISP_ARRAY_SIZE];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint32 DOUBLE_MASK = 0x8000;
|
static const uint32 DOUBLE_MASK = 0xFFFF8000;
|
||||||
|
|
||||||
static bool test(JSFunction *fun, const Value &v) {
|
static bool test(JSFunction *fun, const Value &v) {
|
||||||
uint32 mask = Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK];
|
uint32 mask = Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK];
|
||||||
|
178
js/src/jsops.cpp
178
js/src/jsops.cpp
@ -816,9 +816,9 @@ END_CASE(JSOP_BITAND)
|
|||||||
*/
|
*/
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
#define XML_EQUALITY_OP(OP) \
|
#define XML_EQUALITY_OP(OP) \
|
||||||
if ((lmask == JSVAL_MASK32_NONFUNOBJ && lref.asObject().isXML()) || \
|
if ((lval.isNonFunObj() && lval.asObject().isXML()) || \
|
||||||
(rmask == JSVAL_MASK32_NONFUNOBJ && rref.asObject().isXML())) { \
|
(rval.isNonFunObj() && rval.asObject().isXML())) { \
|
||||||
if (!js_TestXMLEquality(cx, lref, rref, &cond)) \
|
if (!js_TestXMLEquality(cx, lval, rval, &cond)) \
|
||||||
goto error; \
|
goto error; \
|
||||||
cond = cond OP JS_TRUE; \
|
cond = cond OP JS_TRUE; \
|
||||||
} else
|
} else
|
||||||
@ -826,7 +826,7 @@ END_CASE(JSOP_BITAND)
|
|||||||
#define EXTENDED_EQUALITY_OP(OP) \
|
#define EXTENDED_EQUALITY_OP(OP) \
|
||||||
if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \
|
if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \
|
||||||
((ExtendedClass *)clasp)->equality) { \
|
((ExtendedClass *)clasp)->equality) { \
|
||||||
if (!((ExtendedClass *)clasp)->equality(cx, l, &rref, &cond)) \
|
if (!((ExtendedClass *)clasp)->equality(cx, l, &lval, &cond)) \
|
||||||
goto error; \
|
goto error; \
|
||||||
cond = cond OP JS_TRUE; \
|
cond = cond OP JS_TRUE; \
|
||||||
} else
|
} else
|
||||||
@ -837,57 +837,42 @@ END_CASE(JSOP_BITAND)
|
|||||||
|
|
||||||
#define EQUALITY_OP(OP, IFNAN) \
|
#define EQUALITY_OP(OP, IFNAN) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
/* Depends on the value representation. */ \
|
|
||||||
Class *clasp; \
|
Class *clasp; \
|
||||||
JSBool cond; \
|
JSBool cond; \
|
||||||
Value &rref = regs.sp[-1]; \
|
Value rval = regs.sp[-1]; \
|
||||||
Value &lref = regs.sp[-2]; \
|
Value lval = regs.sp[-2]; \
|
||||||
uint32 rmask = rref.data.s.mask32; \
|
|
||||||
uint32 lmask = lref.data.s.mask32; \
|
|
||||||
XML_EQUALITY_OP(OP) \
|
XML_EQUALITY_OP(OP) \
|
||||||
if (lmask == rmask || \
|
if (SamePrimitiveTypeOrBothObjects(lval, rval)) { \
|
||||||
(Value::isObjectMask(lmask) && Value::isObjectMask(rmask))) { \
|
if (lval.isString()) { \
|
||||||
if (lmask == JSVAL_MASK32_STRING) { \
|
JSString *l = lval.asString(), *r = rval.asString(); \
|
||||||
JSString *l = lref.asString(), *r = rref.asString(); \
|
|
||||||
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
||||||
} else if (Value::isObjectMask(lmask)) { \
|
} else if (lval.isDouble()) { \
|
||||||
JSObject *l = &lref.asObject(), *r = &rref.asObject(); \
|
double l = lval.asDouble(), r = rval.asDouble(); \
|
||||||
|
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
||||||
|
} else if (lval.isObject()) { \
|
||||||
|
JSObject *l = &lval.asObject(), *r = &rval.asObject(); \
|
||||||
EXTENDED_EQUALITY_OP(OP) \
|
EXTENDED_EQUALITY_OP(OP) \
|
||||||
cond = l OP r; \
|
cond = l OP r; \
|
||||||
} else if (JS_UNLIKELY(Value::isDoubleMask(lmask))) { \
|
|
||||||
double l = lref.asDouble(), r = rref.asDouble(); \
|
|
||||||
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
|
||||||
} else { \
|
} else { \
|
||||||
cond = lref.data.s.payload.u32 OP rref.data.s.payload.u32; \
|
cond = lval.asRawUint32() OP rval.asRawUint32(); \
|
||||||
} \
|
} \
|
||||||
} else if (Value::isDoubleMask(lmask) && Value::isDoubleMask(rmask)) { \
|
|
||||||
double l = lref.asDouble(), r = rref.asDouble(); \
|
|
||||||
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
|
||||||
} else { \
|
} else { \
|
||||||
if (Value::isNullOrUndefinedMask(lmask)) { \
|
if (lval.isNullOrUndefined()) { \
|
||||||
cond = Value::isNullOrUndefinedMask(rmask) OP true; \
|
cond = rval.isNullOrUndefined() OP true; \
|
||||||
} else if (Value::isNullOrUndefinedMask(rmask)) { \
|
} else if (rval.isNullOrUndefined()) { \
|
||||||
cond = true OP false; \
|
cond = true OP false; \
|
||||||
} else { \
|
} else { \
|
||||||
if (Value::isObjectMask(lmask)) { \
|
if (lval.isObject()) \
|
||||||
JSObject &obj = lref.asObject(); \
|
DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval); \
|
||||||
if (!obj.defaultValue(cx, JSTYPE_VOID, &lref)) \
|
if (rval.isObject()) \
|
||||||
goto error; \
|
DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
|
||||||
lmask = lref.data.s.mask32; \
|
if (BothString(lval, rval)) { \
|
||||||
} \
|
JSString *l = lval.asString(), *r = rval.asString(); \
|
||||||
if (Value::isObjectMask(rmask)) { \
|
|
||||||
JSObject &obj = rref.asObject(); \
|
|
||||||
if (!obj.defaultValue(cx, JSTYPE_VOID, &rref)) \
|
|
||||||
goto error; \
|
|
||||||
rmask = rref.data.s.mask32; \
|
|
||||||
} \
|
|
||||||
if (lmask == JSVAL_MASK32_STRING && rmask == JSVAL_MASK32_STRING) { \
|
|
||||||
JSString *l = lref.asString(), *r = rref.asString(); \
|
|
||||||
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
cond = js_EqualStrings(l, r) OP JS_TRUE; \
|
||||||
} else { \
|
} else { \
|
||||||
double l, r; \
|
double l, r; \
|
||||||
if (!ValueToNumber(cx, lref, &l) || \
|
if (!ValueToNumber(cx, lval, &l) || \
|
||||||
!ValueToNumber(cx, rref, &r)) { \
|
!ValueToNumber(cx, rval, &r)) { \
|
||||||
goto error; \
|
goto error; \
|
||||||
} \
|
} \
|
||||||
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
cond = JSDOUBLE_COMPARE(l, OP, r, IFNAN); \
|
||||||
@ -963,39 +948,24 @@ END_CASE(JSOP_CASEX)
|
|||||||
|
|
||||||
#define RELATIONAL_OP(OP) \
|
#define RELATIONAL_OP(OP) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
/* Depends on the value representation */ \
|
Value rval = regs.sp[-1]; \
|
||||||
Value &rref = regs.sp[-1]; \
|
Value lval = regs.sp[-2]; \
|
||||||
Value &lref = regs.sp[-2]; \
|
|
||||||
uint32 rmask = rref.data.s.mask32; \
|
|
||||||
uint32 lmask = lref.data.s.mask32; \
|
|
||||||
uint32 maskand = lmask & rmask; \
|
|
||||||
bool cond; \
|
bool cond; \
|
||||||
/* Optimize for two int-tagged operands (typical loop control). */ \
|
/* Optimize for two int-tagged operands (typical loop control). */ \
|
||||||
if (maskand == JSVAL_MASK32_INT32) { \
|
if (BothInt32(lval, rval)) { \
|
||||||
cond = lref.asInt32() OP rref.asInt32(); \
|
cond = lval.asInt32() OP rval.asInt32(); \
|
||||||
} else { \
|
} else { \
|
||||||
if (Value::isObjectMask(lmask | rmask)) { \
|
if (lval.isObject()) \
|
||||||
if (Value::isObjectMask(lmask)) { \
|
DEFAULT_VALUE(cx, -2, JSTYPE_NUMBER, lval); \
|
||||||
JSObject &obj = lref.asObject(); \
|
if (rval.isObject()) \
|
||||||
if (!obj.defaultValue(cx, JSTYPE_NUMBER, &lref)) \
|
DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
|
||||||
goto error; \
|
if (BothString(lval, rval)) { \
|
||||||
lmask = lref.data.s.mask32; \
|
JSString *l = lval.asString(), *r = rval.asString(); \
|
||||||
} \
|
|
||||||
if (Value::isObjectMask(rmask)) { \
|
|
||||||
JSObject &obj = rref.asObject(); \
|
|
||||||
if (!obj.defaultValue(cx, JSTYPE_NUMBER, &rref)) \
|
|
||||||
goto error; \
|
|
||||||
rmask = rref.data.s.mask32; \
|
|
||||||
} \
|
|
||||||
maskand = lmask & rmask; \
|
|
||||||
} \
|
|
||||||
if (maskand == JSVAL_MASK32_STRING) { \
|
|
||||||
JSString *l = lref.asString(), *r = rref.asString(); \
|
|
||||||
cond = js_CompareStrings(l, r) OP 0; \
|
cond = js_CompareStrings(l, r) OP 0; \
|
||||||
} else { \
|
} else { \
|
||||||
double l, r; \
|
double l, r; \
|
||||||
if (!ValueToNumber(cx, lref, &l) || \
|
if (!ValueToNumber(cx, lval, &l) || \
|
||||||
!ValueToNumber(cx, rref, &r)) { \
|
!ValueToNumber(cx, rval, &r)) { \
|
||||||
goto error; \
|
goto error; \
|
||||||
} \
|
} \
|
||||||
cond = JSDOUBLE_COMPARE(l, OP, r, false); \
|
cond = JSDOUBLE_COMPARE(l, OP, r, false); \
|
||||||
@ -1064,14 +1034,11 @@ END_CASE(JSOP_URSH)
|
|||||||
|
|
||||||
BEGIN_CASE(JSOP_ADD)
|
BEGIN_CASE(JSOP_ADD)
|
||||||
{
|
{
|
||||||
/* Depends on the value representation */
|
Value rval = regs.sp[-1];
|
||||||
Value &rref = regs.sp[-1];
|
Value lval = regs.sp[-2];
|
||||||
Value &lref = regs.sp[-2];
|
|
||||||
uint32 rmask = rref.data.s.mask32;
|
|
||||||
uint32 lmask = lref.data.s.mask32;
|
|
||||||
|
|
||||||
if ((lmask & rmask) == JSVAL_MASK32_INT32) {
|
if (BothInt32(lval, rval)) {
|
||||||
int32_t l = lref.asInt32(), r = rref.asInt32();
|
int32_t l = lval.asInt32(), r = rval.asInt32();
|
||||||
int32_t sum = l + r;
|
int32_t sum = l + r;
|
||||||
regs.sp--;
|
regs.sp--;
|
||||||
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000)))
|
if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000)))
|
||||||
@ -1080,50 +1047,47 @@ BEGIN_CASE(JSOP_ADD)
|
|||||||
regs.sp[-1].setInt32(sum);
|
regs.sp[-1].setInt32(sum);
|
||||||
} else
|
} else
|
||||||
#if JS_HAS_XML_SUPPORT
|
#if JS_HAS_XML_SUPPORT
|
||||||
if (lmask == JSVAL_MASK32_NONFUNOBJ && lref.asObject().isXML() &&
|
if (lval.isNonFunObj() && lval.asObject().isXML() &&
|
||||||
rmask == JSVAL_MASK32_NONFUNOBJ && rref.asObject().isXML()) {
|
rval.isNonFunObj() && rval.asObject().isXML()) {
|
||||||
Value rval;
|
Value rval;
|
||||||
if (!js_ConcatenateXML(cx, &lref.asObject(), &rref.asObject(), &rval))
|
if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
|
||||||
goto error;
|
goto error;
|
||||||
regs.sp--;
|
regs.sp--;
|
||||||
regs.sp[-1] = rval;
|
regs.sp[-1] = rval;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (Value::isObjectMask(lmask)) {
|
if (lval.isObject())
|
||||||
if (!lref.asObject().defaultValue(cx, JSTYPE_VOID, &lref))
|
DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);
|
||||||
goto error;
|
if (rval.isObject())
|
||||||
lmask = lref.data.s.mask32;
|
DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);
|
||||||
}
|
bool lIsString, rIsString;
|
||||||
if (Value::isObjectMask(rmask)) {
|
if ((lIsString = lval.isString()) | (rIsString = rval.isString())) {
|
||||||
if (!rref.asObject().defaultValue(cx, JSTYPE_VOID, &rref))
|
JSString *lstr, *rstr;
|
||||||
goto error;
|
if (lIsString) {
|
||||||
rmask = rref.data.s.mask32;
|
lstr = lval.asString();
|
||||||
}
|
|
||||||
if (lmask == JSVAL_MASK32_STRING || rmask == JSVAL_MASK32_STRING) {
|
|
||||||
JSString *str1, *str2;
|
|
||||||
if (lmask == rmask) {
|
|
||||||
str1 = lref.asString();
|
|
||||||
str2 = rref.asString();
|
|
||||||
} else if (lmask == JSVAL_MASK32_STRING) {
|
|
||||||
str1 = lref.asString();
|
|
||||||
str2 = js_ValueToString(cx, rref);
|
|
||||||
if (!str2)
|
|
||||||
goto error;
|
|
||||||
} else {
|
} else {
|
||||||
str2 = rref.asString();
|
lstr = js_ValueToString(cx, lval);
|
||||||
str1 = js_ValueToString(cx, lref);
|
if (!lstr)
|
||||||
if (!str1)
|
|
||||||
goto error;
|
goto error;
|
||||||
|
regs.sp[-2].setString(lstr);
|
||||||
}
|
}
|
||||||
JSString *str = js_ConcatStrings(cx, str1, str2);
|
if (rIsString) {
|
||||||
|
rstr = rval.asString();
|
||||||
|
} else {
|
||||||
|
rstr = js_ValueToString(cx, rval);
|
||||||
|
if (!rstr)
|
||||||
|
goto error;
|
||||||
|
regs.sp[-1].setString(rstr);
|
||||||
|
}
|
||||||
|
JSString *str = js_ConcatStrings(cx, lstr, rstr);
|
||||||
if (!str)
|
if (!str)
|
||||||
goto error;
|
goto error;
|
||||||
regs.sp--;
|
regs.sp--;
|
||||||
regs.sp[-1].setString(str);
|
regs.sp[-1].setString(str);
|
||||||
} else {
|
} else {
|
||||||
double l, r;
|
double l, r;
|
||||||
if (!ValueToNumber(cx, lref, &l) || !ValueToNumber(cx, rref, &r))
|
if (!ValueToNumber(cx, lval, &l) || !ValueToNumber(cx, rval, &r))
|
||||||
goto error;
|
goto error;
|
||||||
l += r;
|
l += r;
|
||||||
regs.sp--;
|
regs.sp--;
|
||||||
@ -2135,15 +2099,10 @@ END_CASE(JSOP_GETELEM)
|
|||||||
|
|
||||||
BEGIN_CASE(JSOP_CALLELEM)
|
BEGIN_CASE(JSOP_CALLELEM)
|
||||||
{
|
{
|
||||||
/* Depends on the value representation. */
|
|
||||||
|
|
||||||
/* Fetch the left part and resolve it to a non-null object. */
|
/* Fetch the left part and resolve it to a non-null object. */
|
||||||
JSObject *obj;
|
JSObject *obj;
|
||||||
FETCH_OBJECT(cx, -2, obj);
|
FETCH_OBJECT(cx, -2, obj);
|
||||||
|
|
||||||
/* Save the mask so that we don't need to query it later. */
|
|
||||||
uint32 objmask = regs.sp[-2].data.s.mask32;
|
|
||||||
|
|
||||||
/* Fetch index and convert it to id suitable for use with obj. */
|
/* Fetch index and convert it to id suitable for use with obj. */
|
||||||
jsid id;
|
jsid id;
|
||||||
FETCH_ELEMENT_ID(obj, -1, id);
|
FETCH_ELEMENT_ID(obj, -1, id);
|
||||||
@ -2161,8 +2120,7 @@ BEGIN_CASE(JSOP_CALLELEM)
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
regs.sp[-1].data.s.mask32 = objmask;
|
regs.sp[-1].setObject(*obj);
|
||||||
regs.sp[-1].data.s.payload.obj = obj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
END_CASE(JSOP_CALLELEM)
|
END_CASE(JSOP_CALLELEM)
|
||||||
|
461
js/src/jspubtd.h
461
js/src/jspubtd.h
@ -158,35 +158,12 @@ typedef struct JSONParser JSONParser;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: wrong, fix, explain more
|
* TODO: explain boxing strategy
|
||||||
* Engine-internal value details:
|
|
||||||
*
|
|
||||||
* A jsval has an abstract type which is represented by a mask which assigns a
|
|
||||||
* bit to each type. This allows fast set-membership queries. However, we give
|
|
||||||
* one type (null) a mask of 0 for two reasons:
|
|
||||||
*
|
|
||||||
* 1. memset'ing values to 0 produces a valid value. This was true of the old,
|
|
||||||
* boxed jsvals (and now jsboxedwords) and eases the transition.
|
|
||||||
*
|
|
||||||
* 2. Testing for null can often be compiled to slightly shorter/faster code.
|
|
||||||
*
|
|
||||||
* The down-side is that set-membership queries need to be done more carefully.
|
|
||||||
* E.g., to test whether a value v is undefined or null, the correct test is:
|
|
||||||
*
|
|
||||||
* (v.mask & ~UndefinedMask) == 0
|
|
||||||
*
|
|
||||||
* instead of the intuitive (but incorrect) test:
|
|
||||||
*
|
|
||||||
* (v.mask & (NullMask | UndefinedMask)) != 0
|
|
||||||
*
|
|
||||||
* Since the value representation is kept a private detail of js::Value and
|
|
||||||
* only exposed to a few functions through friendship, this type of error
|
|
||||||
* should be hidden behind simple inline methods like v.isNullOrUndefined().
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef enum JSValueMask16
|
typedef enum JSValueMask16
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
#if defined(_MSC_VER)
|
||||||
: unsigned short
|
: uint16
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
JSVAL_MASK16_NULL = (uint16)0x0001,
|
JSVAL_MASK16_NULL = (uint16)0x0001,
|
||||||
@ -203,6 +180,11 @@ typedef enum JSValueMask16
|
|||||||
JSVAL_MASK16_OBJORNULL = JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL,
|
JSVAL_MASK16_OBJORNULL = JSVAL_MASK16_OBJECT | JSVAL_MASK16_NULL,
|
||||||
JSVAL_MASK16_GCTHING = JSVAL_MASK16_OBJECT | JSVAL_MASK16_STRING,
|
JSVAL_MASK16_GCTHING = JSVAL_MASK16_OBJECT | JSVAL_MASK16_STRING,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This enumerator value plus __attribute__((packed)) plus the static
|
||||||
|
* assert that sizeof(JSValueMask16) == 2 should guarantee that enumerators
|
||||||
|
* are uint16 in GCC.
|
||||||
|
*/
|
||||||
JSVAL_NANBOX_PATTERN = ((uint16)0xFFFF)
|
JSVAL_NANBOX_PATTERN = ((uint16)0xFFFF)
|
||||||
}
|
}
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
@ -210,45 +192,36 @@ __attribute__((packed))
|
|||||||
#endif
|
#endif
|
||||||
JSValueMask16;
|
JSValueMask16;
|
||||||
|
|
||||||
#define JSVAL_MASK32_CLEAR ((uint32)0xFFFF0000)
|
typedef enum JSValueMask32
|
||||||
|
#if defined(_MSC_VER)
|
||||||
#define JSVAL_MASK32_NULL ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NULL))
|
: uint32
|
||||||
#define JSVAL_MASK32_UNDEFINED ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_UNDEFINED))
|
|
||||||
#define JSVAL_MASK32_INT32 ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_INT32))
|
|
||||||
#define JSVAL_MASK32_STRING ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_STRING))
|
|
||||||
#define JSVAL_MASK32_NONFUNOBJ ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NONFUNOBJ))
|
|
||||||
#define JSVAL_MASK32_FUNOBJ ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_FUNOBJ))
|
|
||||||
#define JSVAL_MASK32_BOOLEAN ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_BOOLEAN))
|
|
||||||
#define JSVAL_MASK32_MAGIC ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_MAGIC))
|
|
||||||
|
|
||||||
#define JSVAL_MASK32_SINGLETON ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_SINGLETON))
|
|
||||||
#define JSVAL_MASK32_OBJECT ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJECT))
|
|
||||||
#define JSVAL_MASK32_OBJORNULL ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJORNULL))
|
|
||||||
#define JSVAL_MASK32_GCTHING ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_GCTHING))
|
|
||||||
|
|
||||||
typedef enum JSWhyMagic
|
|
||||||
{
|
|
||||||
JS_ARRAY_HOLE, /* a hole in a dense array */
|
|
||||||
JS_ARGS_HOLE, /* a hole in the args object's array */
|
|
||||||
JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
|
|
||||||
* to js_Enumerate, which really means the object can be
|
|
||||||
* enumerated like a native object. */
|
|
||||||
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
|
|
||||||
JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */
|
|
||||||
} JSWhyMagic;
|
|
||||||
|
|
||||||
typedef union jsval_payload
|
|
||||||
{
|
|
||||||
int32 i32;
|
|
||||||
uint32 u32;
|
|
||||||
JSBool boo;
|
|
||||||
#if JS_BITS_PER_WORD == 32
|
|
||||||
JSString *str;
|
|
||||||
JSObject *obj;
|
|
||||||
void *ptr;
|
|
||||||
#endif
|
#endif
|
||||||
JSWhyMagic why;
|
{
|
||||||
} jsval_data;
|
/*
|
||||||
|
* This enumerator value plus __attribute__((packed)) plus the static
|
||||||
|
* assert that sizeof(JSValueMask32) == 4 should guarantee that enumerators
|
||||||
|
* are uint32 in GCC.
|
||||||
|
*/
|
||||||
|
JSVAL_MASK32_CLEAR = ((uint32)0xFFFF0000),
|
||||||
|
|
||||||
|
JSVAL_MASK32_NULL = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NULL)),
|
||||||
|
JSVAL_MASK32_UNDEFINED = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_UNDEFINED)),
|
||||||
|
JSVAL_MASK32_INT32 = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_INT32)),
|
||||||
|
JSVAL_MASK32_STRING = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_STRING)),
|
||||||
|
JSVAL_MASK32_NONFUNOBJ = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_NONFUNOBJ)),
|
||||||
|
JSVAL_MASK32_FUNOBJ = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_FUNOBJ)),
|
||||||
|
JSVAL_MASK32_BOOLEAN = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_BOOLEAN)),
|
||||||
|
JSVAL_MASK32_MAGIC = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_MAGIC)),
|
||||||
|
|
||||||
|
JSVAL_MASK32_SINGLETON = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_SINGLETON)),
|
||||||
|
JSVAL_MASK32_OBJECT = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJECT)),
|
||||||
|
JSVAL_MASK32_OBJORNULL = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_OBJORNULL)),
|
||||||
|
JSVAL_MASK32_GCTHING = ((uint32)(JSVAL_MASK32_CLEAR | JSVAL_MASK16_GCTHING))
|
||||||
|
}
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
__attribute__((packed))
|
||||||
|
#endif
|
||||||
|
JSValueMask32;
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
# define VALUE_ALIGNMENT __attribute__((aligned (8)))
|
# define VALUE_ALIGNMENT __attribute__((aligned (8)))
|
||||||
@ -264,32 +237,376 @@ typedef union jsval_payload
|
|||||||
# error "TODO: do something for compiler"
|
# error "TODO: do something for compiler"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef VALUE_ALIGNMENT uint64 jsval;
|
||||||
|
|
||||||
|
#define BUILD_JSVAL(mask32, payload) ((jsval)((((uint64)(uint32)(mask32)) << 32) | (uint32)(payload)))
|
||||||
|
|
||||||
|
typedef enum JSWhyMagic
|
||||||
|
{
|
||||||
|
JS_ARRAY_HOLE, /* a hole in a dense array */
|
||||||
|
JS_ARGS_HOLE, /* a hole in the args object's array */
|
||||||
|
JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
|
||||||
|
* to js_Enumerate, which really means the object can be
|
||||||
|
* enumerated like a native object. */
|
||||||
|
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
|
||||||
|
JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */
|
||||||
|
} JSWhyMagic;
|
||||||
|
|
||||||
#if !defined(IS_LITTLE_ENDIAN)
|
#if !defined(IS_LITTLE_ENDIAN)
|
||||||
# error "Need to fix up jsval_layout"
|
# error "Unsupported configuration"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: explain
|
|
||||||
typedef union jsval_layout
|
typedef union jsval_layout
|
||||||
{
|
{
|
||||||
uint64 asBits;
|
uint64 asBits;
|
||||||
struct {
|
struct {
|
||||||
jsval_payload payload;
|
union {
|
||||||
|
int32 i32;
|
||||||
|
uint32 u32;
|
||||||
|
JSBool boo;
|
||||||
|
#if JS_BITS_PER_WORD == 32
|
||||||
|
JSString *str;
|
||||||
|
JSObject *obj;
|
||||||
|
void *ptr;
|
||||||
|
#elif JS_BITS_PER_WORD == 64
|
||||||
|
uint32 ptr;
|
||||||
|
#else
|
||||||
|
# error "Unsupported configuration"
|
||||||
|
#endif
|
||||||
|
JSWhyMagic why;
|
||||||
|
} payload;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
JSValueMask16 mask16;
|
JSValueMask16 mask16;
|
||||||
uint16 nanBits;
|
uint16 nanBits;
|
||||||
} tag;
|
} tag;
|
||||||
uint32 mask32;
|
JSValueMask32 mask32;
|
||||||
};
|
};
|
||||||
} s;
|
} s;
|
||||||
double asDouble;
|
double asDouble;
|
||||||
} jsval_layout;
|
} jsval_layout;
|
||||||
|
|
||||||
typedef uint64 jsval;
|
#if JS_BITS_PER_WORD == 32
|
||||||
|
|
||||||
/* These are engine-internal details, not part of the public API */
|
static JS_ALWAYS_INLINE JSBool
|
||||||
#define DOUBLE_AS_JSVAL(d) (*(jsval *)&(d))
|
JSVAL_IS_NULL_IMPL(jsval_layout l)
|
||||||
#define JSVAL_CONSTANT(mask32, payload) ((jsval)((((uint64)(mask32)) << 32) | (payload)))
|
{
|
||||||
|
return l.s.mask32 == JSVAL_MASK32_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.mask32 == JSVAL_MASK32_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||||
|
{
|
||||||
|
return l.s.mask32 == JSVAL_MASK32_INT32 && l.s.payload.i32 == i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
INT32_TO_JSVAL_IMPL(int32 i)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.mask32 = JSVAL_MASK32_INT32;
|
||||||
|
l.s.payload.i32 = i;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.mask32 < JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
DOUBLE_TO_JSVAL_IMPL(jsdouble d)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.asDouble = d;
|
||||||
|
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
STRING_TO_JSVAL_IMPL(JSString *str)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.mask32 = JSVAL_MASK32_STRING;
|
||||||
|
l.s.payload.str = str;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSString *
|
||||||
|
JSVAL_TO_STRING_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.payload.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSObject *
|
||||||
|
JSVAL_TO_OBJECT_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.payload.obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
OBJECT_TO_JSVAL_IMPL(JSValueMask32 mask, JSObject *obj)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.mask32 = mask;
|
||||||
|
l.s.payload.obj = obj;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.mask32 = JSVAL_MASK32_BOOLEAN;
|
||||||
|
l.s.payload.boo = b;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE void *
|
||||||
|
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.payload.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 == JSVAL_MASK32_BOOLEAN) && (l.s.payload.boo == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
PRIVATE_TO_JSVAL_IMPL(void *ptr)
|
||||||
|
{
|
||||||
|
JS_ASSERT(((uint32)ptr | 1) == 0);
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.tag.nanBits = 0;
|
||||||
|
l.s.payload.ptr = ptr;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE void *
|
||||||
|
JSVAL_TO_PRIVATE_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.s.payload.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.s.mask32 = JSVAL_MASK32_MAGIC;
|
||||||
|
l.s.payload.why = why;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
return ((lhs.s.mask32 ^ rhs.s.mask32) & ~(uint32)JSVAL_MASK16_OBJECT) == 0 ||
|
||||||
|
(lhs.s.mask32 < JSVAL_MASK32_CLEAR && rhs.s.mask32 < JSVAL_MASK32_CLEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_BOTH_STRING_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
return (lhs.s.mask32 & rhs.s.mask32) == JSVAL_MASK32_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_BOTH_INT32_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
return (lhs.s.mask32 & rhs.s.mask32) == JSVAL_MASK32_INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif JS_BITS_PER_WORD == 64
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_NULL_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_UNDEFINED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
|
||||||
|
{
|
||||||
|
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_INT32, i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
INT32_TO_JSVAL_IMPL(int32 i)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = BUILD_JSVAL(JSVAL_MASK32_INT32, i);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return l.asBits < BUILD_JSVAL(JSVAL_MASK32_CLEAR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
DOUBLE_TO_JSVAL_IMPL(jsdouble d)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.asDouble = d;
|
||||||
|
JS_ASSERT(l.s.tag.nanBits != JSVAL_NANBOX_PATTERN);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
STRING_TO_JSVAL_IMPL(JSString *str)
|
||||||
|
{
|
||||||
|
JS_ASSERT((size_t)str < (size_t)0xFFFFFFFF);
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = BUILD_JSVAL(JSVAL_MASK32_STRING, (uint32)str);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSString *
|
||||||
|
JSVAL_TO_STRING_IMPL(jsval_layout v)
|
||||||
|
{
|
||||||
|
return (JSString *)(uint64)l.s.payload.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSObject *
|
||||||
|
JSVAL_TO_OBJECT_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (JSObject *)(uint64)l.s.payload.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
OBJECT_TO_JSVAL_IMPL(JSValueMask32 mask32, JSObject *obj)
|
||||||
|
{
|
||||||
|
JS_ASSERT((size_t)obj < (size_t)0xFFFFFFFF);
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = BUILD_JSVAL(mask32, (uint32)obj);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, b);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE void *
|
||||||
|
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (void *)(uint64)l.s.payload.ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||||
|
{
|
||||||
|
return l.asBits == BUILD_JSVAL(JSVAL_MASK32_BOOLEAN, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
PRIVATE_TO_JSVAL_IMPL(void *ptr)
|
||||||
|
{
|
||||||
|
JS_ASSERT(((uint32)ptr | 1) == 0);
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = 0x8000000000000000LL | (ptr >> 1);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE void *
|
||||||
|
JSVAL_TO_PRIVATE_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (void *)(l.s.payload.asBits << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE jsval_layout
|
||||||
|
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||||
|
{
|
||||||
|
jsval_layout l;
|
||||||
|
l.asBits = BUILD_JSVAL(JSVAL_MASK32_MAGIC, why);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
uint32 xor32 = (uint32)((lhs.asBits ^ rhs.asBits) >> 32);
|
||||||
|
return (xor32 & ~(uint32)JSVAL_MASK16_OBJECT) == 0 ||
|
||||||
|
(JSVAL_IS_DOUBLE_IMPL(lhs) && JSVAL_IS_DOUBLE_IMPL(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_BOTH_STRING_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
return (uint32)((lhs.asBits & rhs.asBits) >> 32) == JSVAL_MASK32_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_BOTH_INT32_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||||
|
{
|
||||||
|
return (uint32)((lhs.asBits & rhs.asBits) >> 32) == JSVAL_MASK32_INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
# error "Unsupported configuration"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_SINGLETON_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 & JSVAL_MASK32_SINGLETON) > JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_NUMBER_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
JSValueMask32 mask = l.s.mask32;
|
||||||
|
return mask < JSVAL_MASK32_CLEAR || mask == JSVAL_MASK32_INT32;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 & JSVAL_MASK32_OBJECT) > JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 & JSVAL_MASK32_OBJORNULL) > JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 & JSVAL_MASK32_OBJECT) <= JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE JSBool
|
||||||
|
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (l.s.mask32 & JSVAL_MASK32_GCTHING) > JSVAL_MASK32_CLEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JS_ALWAYS_INLINE uint32
|
||||||
|
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
|
||||||
|
{
|
||||||
|
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Boxed word macros (private engine detail)
|
* Boxed word macros (private engine detail)
|
||||||
|
Loading…
Reference in New Issue
Block a user