New Tag scheme, no SetObject silliness

This commit is contained in:
Luke Wagner
2010-05-12 16:36:10 -07:00
parent 9c76bf645d
commit 2ebaed25ab
22 changed files with 427 additions and 433 deletions

View File

@@ -1105,7 +1105,7 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
goto out; goto out;
} }
obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)), obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
FunObjValue(*ctor), 0, 0, 0); FunObjTag(*ctor), 0, 0, 0);
} }
/* Initialize the object class next so Object.prototype works. */ /* Initialize the object class next so Object.prototype works. */
@@ -1121,9 +1121,9 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
} }
/* Function.prototype and the global object delegate to Object.prototype. */ /* Function.prototype and the global object delegate to Object.prototype. */
fun_proto->setProto(NonFunObjPtr(*obj_proto)); fun_proto->setProto(NonFunObjTag(*obj_proto));
if (!obj->getProto()) if (!obj->getProto())
obj->setProto(NonFunObjPtr(*obj_proto)); obj->setProto(NonFunObjTag(*obj_proto));
out: out:
/* If resolving, remove the other entry (Object or Function) from table. */ /* If resolving, remove the other entry (Object or Function) from table. */
@@ -2894,7 +2894,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
JSObject *nobj = NewObject(cx, clasp, proto, obj); JSObject *nobj = NewObject(cx, clasp, proto, obj);
if (!nobj) if (!nobj)
return NULL; return NULL;
if (!DefineProperty(cx, obj, name, ToValue(nobj), NULL, NULL, attrs, if (!DefineProperty(cx, obj, name, ObjectTag(*nobj), NULL, NULL, attrs,
0, 0)) { 0, 0)) {
return NULL; return NULL;
} }
@@ -3064,7 +3064,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop,
if (sprop->isMethod()) { if (sprop->isMethod()) {
AutoScopePropertyRooter root(cx, sprop); AutoScopePropertyRooter root(cx, sprop);
JS_UNLOCK_OBJ(cx, obj2); JS_UNLOCK_OBJ(cx, obj2);
vp->copy(sprop->methodValue()); vp->setFunObj(sprop->methodFunObj());
return obj2->scope()->methodReadBarrier(cx, sprop, vp); return obj2->scope()->methodReadBarrier(cx, sprop, vp);
} }
@@ -3966,7 +3966,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
*idp = JSID_VOID; *idp = JSID_VOID;
} else { } else {
*idp = ida->vector[--i]; *idp = ida->vector[--i];
iterobj->setSlot(JSSLOT_ITER_INDEX, Value(i)); iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Tag(i));
} }
} }
return JS_TRUE; return JS_TRUE;
@@ -4081,7 +4081,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
* idea, but we changed incompatibly to teach any abusers a lesson!). * idea, but we changed incompatibly to teach any abusers a lesson!).
*/ */
Value v; Value v;
SetObject(&v, funobj); v.setObject(*funobj);
js_ReportIsNotFunction(cx, &v, 0); js_ReportIsNotFunction(cx, &v, 0);
return NULL; return NULL;
} }
@@ -4684,8 +4684,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
} }
if (obj && funAtom && if (obj && funAtom &&
!obj->defineProperty(cx, ATOM_TO_JSID(funAtom), !obj->defineProperty(cx, ATOM_TO_JSID(funAtom), fun->funObjVal(),
FunObjValue(*FUN_OBJECT(fun)),
NULL, NULL, JSPROP_ENUMERATE)) { NULL, NULL, JSPROP_ENUMERATE)) {
fun = NULL; fun = NULL;
} }
@@ -4849,8 +4848,8 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
JSBool ok; JSBool ok;
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
ok = InternalCall(cx, obj, FunObjValue(*FUN_OBJECT(fun)), argc, ok = InternalCall(cx, obj, fun->funObjVal(), argc, Valueify(argv),
Valueify(argv), Valueify(rval)); Valueify(rval));
LAST_FRAME_CHECKS(cx, ok); LAST_FRAME_CHECKS(cx, ok);
return ok; return ok;
} }
@@ -4898,7 +4897,7 @@ JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
return NULL; return NULL;
Value *vp = args.getvp(); Value *vp = args.getvp();
SetObject(&vp[0], ctor); vp[0].setObject(*ctor);
vp[1].setNull(); vp[1].setNull();
memcpy(vp + 2, argv, argc * sizeof(jsval)); memcpy(vp + 2, argv, argc * sizeof(jsval));

View File

@@ -2950,6 +2950,59 @@ JS_END_EXTERN_C
namespace js { namespace js {
struct NullTag {
explicit NullTag() {}
};
struct UndefinedTag {
explicit UndefinedTag() {}
};
struct Int32Tag {
explicit Int32Tag(int32 i32) : i32(i32) {}
int32 i32;
};
struct FunObjTag {
explicit FunObjTag(JSObject &obj) : obj(obj) {}
JSObject &obj;
};
struct FunObjOrNull {
explicit FunObjOrNull(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct FunObjOrUndefinedTag {
explicit FunObjOrUndefinedTag(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct NonFunObjTag {
explicit NonFunObjTag(JSObject &o) : obj(obj) {}
JSObject &obj;
};
struct NonFunObjOrNull {
explicit NonFunObjOrNull(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct ObjectTag {
explicit ObjectTag(JSObject &obj) : obj(obj) {}
JSObject &obj;
};
struct ObjectOrNullTag {
explicit ObjectOrNullTag(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct BooleanTag {
explicit BooleanTag(bool boo) : boo(boo) {}
bool boo;
};
/* /*
* An ObjPtr is a restriction of a Value (below) to the three types: null, * An ObjPtr is a restriction of a Value (below) to the three types: null,
* non-function object and function object. ObjPtr is useful when code * non-function object and function object. ObjPtr is useful when code
@@ -2980,15 +3033,42 @@ class ObjPtr
public: public:
/* Constructors */ /* Constructors */
ObjPtr() {
/* N.B. mask and obj are undefined */
}
/* N.B. defualt construction yields a ObjPtr in an undefined state. */ ObjPtr(NullTag) {
ObjPtr() {} mask = NullMask;
obj = NULL;
}
/* ObjPtr(FunObjTag arg) {
* To construct a null pointer, use NullObjPtr. To construct pointers to JS_ASSERT(JS_ObjectIsFunction(NULL, &arg.obj));
* objects statically known to be, or not to be, function objects, use mask = FunObjMask;
* FunObjPtr, NonFunObjPtr. obj = &arg.obj;
*/ }
ObjPtr(FunObjOrNull arg) {
JS_ASSERT_IF(arg.obj, JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? FunObjMask : NullMask;
obj = arg.obj;
}
ObjPtr(NonFunObjTag arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg.obj));
mask = NonFunObjMask;
obj = &arg.obj;
}
ObjPtr(NonFunObjOrNull arg) {
JS_ASSERT_IF(arg.obj, !JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? NonFunObjMask : NullMask;
obj = arg.obj;
}
inline ObjPtr(ObjectTag arg);
inline ObjPtr(ObjectOrNullTag arg);
/* Accessors */ /* Accessors */
@@ -3040,28 +3120,32 @@ class ObjPtr
obj = NULL; obj = NULL;
} }
void setFunObj(JSObject &o) { void setFunObj(JSObject &arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o)); JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
mask = FunObjMask; mask = FunObjMask;
obj = &o; obj = &arg;
} }
void setNonFunObj(JSObject &o) { void setFunObjOrNull(JSObject *arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &o)); JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
mask = arg ? FunObjMask : NullMask;
obj = arg;
}
void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
mask = NonFunObjMask; mask = NonFunObjMask;
obj = &o; obj = &arg;
} }
void setNonFunObjOrNull(JSObject *o) { void setNonFunObjOrNull(JSObject *arg) {
if (o) { JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
JS_ASSERT(!JS_ObjectIsFunction(NULL, o)); mask = arg ? NonFunObjMask : NullMask;
mask = NonFunObjMask; obj = arg;
obj = o;
} else {
mask = NullMask;
obj = o;
}
} }
inline void setObject(JSObject &arg);
inline void setObjectOrNull(JSObject *arg);
}; };
inline bool operator==(ObjPtr lhs, ObjPtr rhs) { return lhs == rhs; } inline bool operator==(ObjPtr lhs, ObjPtr rhs) { return lhs == rhs; }
@@ -3071,56 +3155,7 @@ inline bool operator!=(ObjPtr lhs, ObjPtr rhs) { return !(lhs == rhs); }
inline bool operator!=(ObjPtr lhs, JSObject *rhs) { return !(lhs == rhs); } inline bool operator!=(ObjPtr lhs, JSObject *rhs) { return !(lhs == rhs); }
inline bool operator!=(JSObject *lhs, ObjPtr rhs) { return !(lhs == rhs); } inline bool operator!=(JSObject *lhs, ObjPtr rhs) { return !(lhs == rhs); }
/* class CopyableValue;
* These types are intended to be used like:
*
* ObjPtr p = NullObjPtr();
* void f1(ObjPtr);
* f1(FunObjPtr(funobj));
*/
struct NullObjPtr : ObjPtr
{
explicit NullObjPtr() {
mask = NullMask;
obj = NULL;
}
};
struct FunObjPtr : ObjPtr
{
explicit FunObjPtr(JSObject &o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o));
mask = FunObjMask;
obj = &o;
}
};
struct NonFunObjPtr : ObjPtr
{
explicit NonFunObjPtr(JSObject &o) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &o));
mask = NonFunObjMask;
obj = &o;
}
};
struct NonFunObjOrNullPtr : ObjPtr
{
explicit NonFunObjOrNullPtr(JSObject *o) {
if (o) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, o));
mask = NonFunObjMask;
obj = o;
} else {
mask = NullMask;
obj = NULL;
}
}
};
/* TODO: this can be removed when copying is implicit/public. */
class ExplicitlyConstructedValue;
/* /*
* While there is a single representation for values, there are two declared * While there is a single representation for values, there are two declared
@@ -3195,65 +3230,90 @@ class Value
Value &operator=(const Value &); Value &operator=(const Value &);
public: public:
/* XXX: this can be removed when copying is public/implicit */ /* Constructors */
inline Value(const ExplicitlyConstructedValue &v);
/* Value() {
* Constructors /* N.B. mask and data are undefined. */
* }
* To construct a null value, use NullValue. To construct pointers to
* objects statically known to be, or not to be, function objects, use
* FunObjValue, NonFunObjValue.
*/
/* N.B. default construction yields a Value in an undefined state. */ Value(NullTag) {
Value() {} mask = NullMask;
data.obj = NULL;
}
Value(UndefinedTag) {
mask = UndefinedMask;
/* N.B. data is undefined */
}
Value(Int32Tag arg) {
mask = Int32Mask;
data.i32 = arg.i32;
}
Value(double arg) {
mask = DoubleMask;
data.dbl = arg;
}
Value(JSString *arg) {
mask = StringMask;
data.str = arg;
}
Value(FunObjTag arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg.obj));
mask = FunObjMask;
data.obj = &arg.obj;
}
Value(FunObjOrNull arg) {
JS_ASSERT_IF(arg.obj, JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? FunObjMask : NullMask;
data.obj = arg.obj;
}
Value(FunObjOrUndefinedTag arg) {
JS_ASSERT_IF(arg.obj, JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? FunObjMask : UndefinedMask;
data.obj = arg.obj;
}
Value(NonFunObjTag arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg.obj));
mask = NonFunObjMask;
data.obj = &arg.obj;
}
Value(NonFunObjOrNull arg) {
JS_ASSERT_IF(arg.obj, !JS_ObjectIsFunction(NULL, arg.obj));
mask = arg.obj ? NonFunObjMask : NullMask;
data.obj = arg.obj;
}
inline Value(ObjectTag arg);
inline Value(ObjectOrNullTag arg);
Value(BooleanTag arg) {
mask = BooleanMask;
data.boo = arg.boo;
}
Value(JSWhyMagic arg) {
mask = MagicMask;
#ifdef DEBUG
data.why = arg;
#endif
}
/* XXX: 'explicit' can be removed when copying is public/implicit */ /* XXX: 'explicit' can be removed when copying is public/implicit */
explicit Value(const Value &v) explicit Value(const Value &v)
: mask(v.mask), data(v.data) : mask(v.mask), data(v.data)
{} {}
explicit Value(int32 i32) { /* XXX: can be removed when copy is implicit */
mask = Int32Mask; Value(const CopyableValue &);
data.i32 = i32;
}
explicit Value(double dbl) {
mask = DoubleMask;
data.dbl = dbl;
}
Value(JSString *str) {
mask = StringMask;
data.str = str;
}
private:
/*
* This overload catches values constructed with unsupported T* types
* before they are implicitly converted to bool.
*/
template <class T> explicit Value(T *); /* undefined */
public:
explicit Value(bool b) {
mask = BooleanMask;
data.boo = b;
}
explicit Value(JSWhyMagic why) {
mask = MagicMask;
#ifdef DEBUG
data.why = why;
#endif
}
Value(ObjPtr ptr) {
mask = ptr.mask;
data.obj = ptr.obj;
}
/* Mutators */ /* Mutators */
@@ -3294,6 +3354,39 @@ class Value
data.str = str; data.str = str;
} }
void setFunObj(JSObject &arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
mask = FunObjMask;
data.obj = &arg;
}
void setFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
mask = arg ? FunObjMask : NullMask;
data.obj = arg;
}
void setFunObjOrUndefined(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
mask = arg ? FunObjMask : UndefinedMask;
data.obj = arg;
}
void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
mask = NonFunObjMask;
data.obj = &arg;
}
void setNonFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
mask = arg ? NonFunObjMask : NullMask;
data.obj = arg;
}
inline void setObject(JSObject &arg);
inline void setObjectOrNull(JSObject *arg);
void setBoolean(bool b) { void setBoolean(bool b) {
mask = BooleanMask; mask = BooleanMask;
data.boo = b; data.boo = b;
@@ -3306,28 +3399,6 @@ class Value
#endif #endif
} }
void setFunObj(JSObject &o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o));
mask = FunObjMask;
data.obj = &o;
}
void setNonFunObj(JSObject &o) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &o));
mask = NonFunObjMask;
data.obj = &o;
}
void setNonFunObjOrNull(JSObject *o) {
if (o) {
mask = NonFunObjMask;
data.obj = o;
} else {
mask = NullMask;
data.obj = NULL;
}
}
/* Mutators */ /* Mutators */
/* XXX: to be removed when copying is implicit/public */ /* XXX: to be removed when copying is implicit/public */
@@ -3496,7 +3567,7 @@ class Value
* Private setters/getters allow the caller to read/write arbitrary types * Private setters/getters allow the caller to read/write arbitrary types
* that fit in the 64-bit payload. It is the caller's responsibility, after * that fit in the 64-bit payload. It is the caller's responsibility, after
* storing to a value with setPrivateX to only read with getPrivateX. * storing to a value with setPrivateX to only read with getPrivateX.
* Privates values are given a valid type of Int32 and are thus GC-safe. * Privates values are given a valid type of Int32Tag and are thus GC-safe.
*/ */
void setPrivateVoidPtr(void *p) { void setPrivateVoidPtr(void *p) {
@@ -3525,69 +3596,6 @@ class Value
} }
}; };
/*
* These types are intended to be used like:
*
* Value v = NullValue();
* void f1(Value);
* f1(FunObjValue(funobj));
*/
/* TODO: this hackiness will be removed once copying is public/implicit */
struct ExplicitlyConstructedValue : Value {};
JS_ALWAYS_INLINE
Value::Value(const ExplicitlyConstructedValue &v)
: mask(v.mask), data(v.data)
{}
struct NullValue : ExplicitlyConstructedValue
{
explicit NullValue() {
mask = NullMask;
data.obj = NULL;
}
};
struct UndefinedValue : ExplicitlyConstructedValue
{
explicit UndefinedValue() {
mask = UndefinedMask;
}
};
struct FunObjValue : ExplicitlyConstructedValue
{
explicit FunObjValue(JSObject &o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o));
mask = FunObjMask;
data.obj = &o;
}
};
struct NonFunObjValue : ExplicitlyConstructedValue
{
explicit NonFunObjValue(JSObject &o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o));
mask = NonFunObjMask;
data.obj = &o;
}
};
struct NonFunObjOrNullValue : ExplicitlyConstructedValue
{
explicit NonFunObjOrNullValue(JSObject *o) {
if (o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, o));
mask = NonFunObjMask;
data.obj = o;
} else {
mask = NullMask;
data.obj = NULL;
}
}
};
struct AssertLayoutCompatible struct AssertLayoutCompatible
{ {
JS_STATIC_ASSERT(sizeof(jsval) == 16); JS_STATIC_ASSERT(sizeof(jsval) == 16);
@@ -3601,12 +3609,31 @@ struct AssertLayoutCompatible
JS_STATIC_ASSERT(sizeof(Value::MaskType) == sizeof(JSValueMaskType)); JS_STATIC_ASSERT(sizeof(Value::MaskType) == sizeof(JSValueMaskType));
JS_STATIC_ASSERT(sizeof(Value::MaskType) == sizeof(((jsval *)0)->mask)); JS_STATIC_ASSERT(sizeof(Value::MaskType) == sizeof(((jsval *)0)->mask));
JS_STATIC_ASSERT(offsetof(Value, mask) == offsetof(jsval, mask)); JS_STATIC_ASSERT(offsetof(Value, mask) == offsetof(jsval, mask));
JS_STATIC_ASSERT(sizeof(NullValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(UndefinedValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(FunObjValue) == sizeof(Value));
JS_STATIC_ASSERT(sizeof(NonFunObjValue) == sizeof(Value));
}; };
/* XXX: this is a temporary hack until copying is implicit. */
struct CopyableValue : Value
{
CopyableValue(NullTag arg) : Value(arg) {}
CopyableValue(UndefinedTag arg) : Value(arg) {}
CopyableValue(Int32Tag arg) : Value(arg) {}
CopyableValue(double arg) : Value(arg) {}
CopyableValue(JSString *arg) : Value(arg) {}
CopyableValue(FunObjTag arg) : Value(arg) {}
CopyableValue(NonFunObjTag arg) : Value(arg) {}
CopyableValue(ObjectTag arg) : Value(arg) {}
CopyableValue(BooleanTag arg) : Value(arg) {}
CopyableValue(JSWhyMagic arg) : Value(arg) {}
};
JS_ALWAYS_INLINE
Value::Value(const CopyableValue &v) {
mask = v.mask;
data = v.data;
}
JS_STATIC_ASSERT(sizeof(CopyableValue) == sizeof(Value));
/* /*
* As asserted above, js::Value and jsval are layout equivalent. To provide * As asserted above, js::Value and jsval are layout equivalent. To provide
* widespread casting, the following safe casts are provided. * widespread casting, the following safe casts are provided.

View File

@@ -241,7 +241,7 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
return true; return true;
} }
AutoValueRooter tvr(cx, NullValue()); AutoValueRooter tvr(cx);
if (!obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), tvr.addr())) if (!obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), tvr.addr()))
return false; return false;
@@ -276,7 +276,7 @@ js_IndexToId(JSContext *cx, jsuint index, jsid *idp)
str = js_NumberToString(cx, index); str = js_NumberToString(cx, index);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
return js_ValueToStringId(cx, Value(str), idp); return js_ValueToStringId(cx, str, idp);
} }
static JSBool static JSBool
@@ -350,7 +350,7 @@ JSObject::resizeDenseArrayElements(JSContext *cx, uint32 oldcap, uint32 newcap,
if (initializeAllSlots) { if (initializeAllSlots) {
for (uint32 i = oldcap; i < newcap; i++) for (uint32 i = oldcap; i < newcap; i++)
setDenseArrayElement(i, Value(JS_ARRAY_HOLE)); setDenseArrayElement(i, JS_ARRAY_HOLE);
} }
return true; return true;
@@ -405,7 +405,7 @@ JSObject::ensureDenseArrayElements(JSContext *cx, uint32 newcap, bool initialize
* Initialize the slots caller didn't actually ask for. * Initialize the slots caller didn't actually ask for.
*/ */
for (uint32 i = newcap; i < actualCapacity; i++) { for (uint32 i = newcap; i < actualCapacity; i++) {
setDenseArrayElement(i, Value(JS_ARRAY_HOLE)); setDenseArrayElement(i, JS_ARRAY_HOLE);
} }
} }
} }
@@ -415,7 +415,7 @@ JSObject::ensureDenseArrayElements(JSContext *cx, uint32 newcap, bool initialize
static bool static bool
ReallyBigIndexToId(JSContext* cx, jsdouble index, jsid* idp) ReallyBigIndexToId(JSContext* cx, jsdouble index, jsid* idp)
{ {
return js_ValueToStringId(cx, Value(index), idp); return js_ValueToStringId(cx, index, idp);
} }
static bool static bool
@@ -534,7 +534,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index)
if (!INDEX_TOO_SPARSE(obj, idx) && idx < obj->getDenseArrayCapacity()) { if (!INDEX_TOO_SPARSE(obj, idx) && idx < obj->getDenseArrayCapacity()) {
if (!obj->getDenseArrayElement(idx).isMagic(JS_ARRAY_HOLE)) if (!obj->getDenseArrayElement(idx).isMagic(JS_ARRAY_HOLE))
obj->decDenseArrayCountBy(1); obj->decDenseArrayCountBy(1);
obj->setDenseArrayElement(idx, Value(JS_ARRAY_HOLE)); obj->setDenseArrayElement(idx, JS_ARRAY_HOLE);
return JS_TRUE; return JS_TRUE;
} }
} }
@@ -582,7 +582,7 @@ JSBool
js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{ {
JSErrorReporter older = JS_SetErrorReporter(cx, NULL); JSErrorReporter older = JS_SetErrorReporter(cx, NULL);
AutoValueRooter tvr(cx, NullValue()); AutoValueRooter tvr(cx);
jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
JSBool ok = obj->getProperty(cx, id, tvr.addr()); JSBool ok = obj->getProperty(cx, id, tvr.addr());
JS_SetErrorReporter(cx, older); JS_SetErrorReporter(cx, older);
@@ -1050,7 +1050,7 @@ array_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval)
if (js_IdIsIndex(id, &i) && i < obj->getDenseArrayCapacity() && if (js_IdIsIndex(id, &i) && i < obj->getDenseArrayCapacity() &&
!obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) { !obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
obj->decDenseArrayCountBy(1); obj->decDenseArrayCountBy(1);
obj->setDenseArrayElement(i, Value(JS_ARRAY_HOLE)); obj->setDenseArrayElement(i, JS_ARRAY_HOLE);
} }
rval->setBoolean(true); rval->setBoolean(true);
@@ -1163,7 +1163,7 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
goto out_bad; goto out_bad;
if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) { if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
obj->setDenseArrayElement(i, UndefinedValue()); obj->setDenseArrayElement(i, UndefinedTag());
continue; continue;
} }
@@ -1528,7 +1528,7 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint count, Valu
JS_ASSERT(start == MAXINDEX); JS_ASSERT(start == MAXINDEX);
AutoValueRooter tvr(cx); AutoValueRooter tvr(cx);
AutoIdRooter idr(cx); AutoIdRooter idr(cx);
Value idval(double(MAXINDEX)); Value idval(MAXINDEX);
do { do {
tvr.addr()->copy(*vector++); tvr.addr()->copy(*vector++);
if (!js_ValueToStringId(cx, idval, idr.addr()) || if (!js_ValueToStringId(cx, idval, idr.addr()) ||
@@ -1601,7 +1601,7 @@ array_reverse(JSContext *cx, uintN argc, Value *vp)
JSObject *obj = ComputeThisObjectFromVp(cx, vp); JSObject *obj = ComputeThisObjectFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &len)) if (!obj || !js_GetLengthProperty(cx, obj, &len))
return JS_FALSE; return JS_FALSE;
SetObject(vp, *obj); vp->setObject(*obj);
if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) { if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) {
/* An empty array or an array with no elements is already reversed. */ /* An empty array or an array with no elements is already reversed. */
@@ -1899,7 +1899,7 @@ array_sort(JSContext *cx, uintN argc, Value *vp)
if (!obj || !js_GetLengthProperty(cx, obj, &len)) if (!obj || !js_GetLengthProperty(cx, obj, &len))
return false; return false;
if (len == 0) { if (len == 0) {
SetObject(vp, *obj); vp->setObject(*obj);
return true; return true;
} }
@@ -2110,7 +2110,7 @@ array_sort(JSContext *cx, uintN argc, Value *vp)
if (!JS_CHECK_OPERATION_LIMIT(cx) || !DeleteArrayElement(cx, obj, --len)) if (!JS_CHECK_OPERATION_LIMIT(cx) || !DeleteArrayElement(cx, obj, --len))
return JS_FALSE; return JS_FALSE;
} }
SetObject(vp, *obj); vp->setObject(*obj);
return true; return true;
} }
@@ -2273,7 +2273,7 @@ array_shift(JSContext *cx, uintN argc, Value *vp)
obj->decDenseArrayCountBy(1); obj->decDenseArrayCountBy(1);
Value *elems = obj->getDenseArrayElements(); Value *elems = obj->getDenseArrayElements();
memmove(elems, elems + 1, length * sizeof(jsval)); memmove(elems, elems + 1, length * sizeof(jsval));
obj->setDenseArrayElement(length, Value(JS_ARRAY_HOLE)); obj->setDenseArrayElement(length, JS_ARRAY_HOLE);
obj->setDenseArrayLength(length); obj->setDenseArrayLength(length);
return JS_TRUE; return JS_TRUE;
} }
@@ -2323,7 +2323,7 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
Value *elems = obj->getDenseArrayElements(); Value *elems = obj->getDenseArrayElements();
memmove(elems + argc, elems, length * sizeof(jsval)); memmove(elems + argc, elems, length * sizeof(jsval));
for (uint32 i = 0; i < argc; i++) for (uint32 i = 0; i < argc; i++)
obj->setDenseArrayElement(i, Value(JS_ARRAY_HOLE)); obj->setDenseArrayElement(i, JS_ARRAY_HOLE);
} else { } else {
last = length; last = length;
jsdouble upperIndex = last + argc; jsdouble upperIndex = last + argc;
@@ -2413,7 +2413,7 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
argv++; argv++;
} }
AutoValueRooter tvr(cx, NullValue()); AutoValueRooter tvr(cx);
/* If there are elements to remove, put them into the return value. */ /* If there are elements to remove, put them into the return value. */
if (count > 0) { if (count > 0) {
@@ -2545,7 +2545,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
length = 0; length = 0;
} }
AutoValueRooter tvr(cx, NullValue()); AutoValueRooter tvr(cx);
/* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */ /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
for (uintN i = 0; i <= argc; i++) { for (uintN i = 0; i <= argc; i++) {
@@ -2874,9 +2874,9 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
Value *invokevp = args.getvp(); Value *invokevp = args.getvp();
Value calleev, thisv, objv; Value calleev, thisv, objv;
SetObject(&calleev, callable); calleev.setObject(*callable);
SetObject(&thisv, thisp); thisv.setObjectOrNull(thisp);
SetObject(&objv, obj); objv.setObject(*obj);
AutoValueRooter tvr(cx); AutoValueRooter tvr(cx);
for (jsint i = start; i != end; i += step) { for (jsint i = start; i != end; i += step) {
JSBool hole; JSBool hole;
@@ -3098,7 +3098,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
/* Initialize all fields of JSObject. */ /* Initialize all fields of JSObject. */
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap); obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
obj->init(&js_ArrayClass, NonFunObjPtr(*proto), proto->getParent(), NullValue()); obj->init(&js_ArrayClass, NonFunObjTag(*proto), proto->getParent(), NullTag());
obj->setDenseArrayLength(0); obj->setDenseArrayLength(0);
obj->setDenseArrayCount(0); obj->setDenseArrayCount(0);
return obj; return obj;

View File

@@ -95,7 +95,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
const char * const char *
js_AtomToPrintableString(JSContext *cx, JSAtom *atom) js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
{ {
return js_ValueToPrintableString(cx, Value(ATOM_TO_STRING(atom))); return js_ValueToPrintableString(cx, ATOM_TO_STRING(atom));
} }
#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name; #define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
@@ -1299,7 +1299,7 @@ js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
if (obj->isXML()) { if (obj->isXML()) {
JSObject &idobj = idval.asObject(); JSObject &idobj = idval.asObject();
*idp = OBJECT_TO_JSID(&idobj); *idp = OBJECT_TO_JSID(&idobj);
SetObject(vp, idobj); vp->setObject(idobj);
return true; return true;
} }
@@ -1351,16 +1351,13 @@ ValueToId(JSContext *cx, const Value *vp, jsid *idp)
Value Value
IdToValue(jsid id) IdToValue(jsid id)
{ {
ExplicitlyConstructedValue v;
if (JSID_IS_INT(id)) if (JSID_IS_INT(id))
v.setInt32(JSID_TO_INT(id)); return CopyableValue(Int32Tag(JSID_TO_INT(id)));
else if (JSID_IS_ATOM(id)) else if (JSID_IS_ATOM(id))
v.setString(ATOM_TO_STRING(JSID_TO_ATOM(id))); return CopyableValue(ATOM_TO_STRING(JSID_TO_ATOM(id)));
else if (JSID_IS_NULL(id)) else if (JSID_IS_NULL(id))
v.setNull(); return CopyableValue(NullTag());
else return CopyableValue(ObjectTag(*JSID_TO_OBJECT(id)));
SetObject(&v, *JSID_TO_OBJECT(id));
return v;
} }
} /* namespace js */ } /* namespace js */

View File

@@ -98,7 +98,7 @@ js_Int32ToId(JSContext* cx, int32 index, jsid* id)
JSString* str = js_NumberToString(cx, index); JSString* str = js_NumberToString(cx, index);
if (!str) if (!str)
return false; return false;
return js_ValueToStringId(cx, js::Value(str), id); return js_ValueToStringId(cx, str, id);
} }
inline bool inline bool

View File

@@ -152,7 +152,7 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
NULL, boolean_methods, NULL, NULL); NULL, boolean_methods, NULL, NULL);
if (!proto) if (!proto)
return NULL; return NULL;
proto->setPrimitiveThis(Value(false)); proto->setPrimitiveThis(BooleanTag(false));
return proto; return proto;
} }

View File

@@ -2242,7 +2242,7 @@ class AutoValueRooter : private AutoGCRooter
public: public:
explicit AutoValueRooter(JSContext *cx explicit AutoValueRooter(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM) JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(js::NullValue()) : AutoGCRooter(cx, JSVAL), val(js::NullTag())
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
} }
@@ -2990,7 +2990,7 @@ class AutoValueVector : private AutoGCRooter
size_t length() const { return vector.length(); } size_t length() const { return vector.length(); }
bool append(const Value &v) { return vector.append(v); } bool append(const Value &v) { return vector.append(v); }
bool append(JSString *str) { return append(Value(str)); } bool append(JSString *str) { return append(str); }
void popBack() { vector.popBack(); } void popBack() { vector.popBack(); }

View File

@@ -679,7 +679,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
/* Initialize slots/frame. */ /* Initialize slots/frame. */
Value *vp = frame.getvp(); Value *vp = frame.getvp();
PodZero(vp, vplen); PodZero(vp, vplen);
SetObject(&vp[0], closure); vp[0].setObject(*closure);
JSStackFrame *fp = frame.getFrame(); JSStackFrame *fp = frame.getFrame();
PodZero(fp->slots(), nfixed); PodZero(fp->slots(), nfixed);
PodZero(fp); PodZero(fp);
@@ -707,7 +707,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
JSBool ok = !wp->setter || JSBool ok = !wp->setter ||
(sprop->hasSetterValue() (sprop->hasSetterValue()
? InternalCall(cx, obj, ? InternalCall(cx, obj,
ToValue(CastAsObject(wp->setter)), ObjectTag(*CastAsObject(wp->setter)),
1, vp, vp) 1, vp, vp)
: wp->setter(cx, obj, userid, vp)); : wp->setter(cx, obj, userid, vp));

View File

@@ -53,6 +53,8 @@
#include "jslibmath.h" #include "jslibmath.h"
#include "jscntxt.h" #include "jscntxt.h"
#include "jsobjinlines.h"
#ifdef IS_LITTLE_ENDIAN #ifdef IS_LITTLE_ENDIAN
#define IEEE_8087 #define IEEE_8087
#else #else

View File

@@ -285,7 +285,8 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
valueCount = 0; valueCount = 0;
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) { for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
if (fp->fun && fp->argv) { if (fp->fun && fp->argv) {
NullValue v; Value v;
v.setNull();
if (checkAccess && if (checkAccess &&
!checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) { !checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
break; break;

View File

@@ -176,8 +176,8 @@ NewArguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee)
return NULL; return NULL;
/* Init immediately to avoid GC seeing a half-init'ed object. */ /* Init immediately to avoid GC seeing a half-init'ed object. */
argsobj->init(&js_ArgumentsClass, NonFunObjPtr(*proto), parent, NullValue()); argsobj->init(&js_ArgumentsClass, NonFunObjTag(*proto), parent, NullTag());
argsobj->setArgsCallee(ToValue(callee)); argsobj->setArgsCallee(ObjectOrNullTag(callee));
argsobj->setArgsLength(argc); argsobj->setArgsLength(argc);
argsobj->map = cx->runtime->emptyArgumentsScope; argsobj->map = cx->runtime->emptyArgumentsScope;
@@ -841,7 +841,7 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO
JSObject *callobj = NewCallObject(cx, fun, scopeChain); JSObject *callobj = NewCallObject(cx, fun, scopeChain);
if (!callobj) if (!callobj)
return NULL; return NULL;
callobj->setSlot(JSSLOT_CALLEE, NonFunObjValue(*callee)); callobj->setSlot(JSSLOT_CALLEE, NonFunObjTag(*callee));
return callobj; return callobj;
} }
@@ -877,7 +877,7 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
/* Get the arguments object to snapshot fp's actual argument values. */ /* Get the arguments object to snapshot fp's actual argument values. */
if (fp->argsobj) { if (fp->argsobj) {
if (!(fp->flags & JSFRAME_OVERRIDE_ARGS)) if (!(fp->flags & JSFRAME_OVERRIDE_ARGS))
callobj->setSlot(JSSLOT_CALL_ARGUMENTS, NonFunObjValue(*fp->argsobj)); callobj->setSlot(JSSLOT_CALL_ARGUMENTS, NonFunObjTag(*fp->argsobj));
js_PutArgsObject(cx, fp); js_PutArgsObject(cx, fp);
} }
@@ -1723,7 +1723,7 @@ fun_hasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp)
* Throw a runtime error if instanceof is called on a function that * Throw a runtime error if instanceof is called on a function that
* has a non-object as its .prototype value. * has a non-object as its .prototype value.
*/ */
js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, ToValue(obj), NULL); js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE, -1, ObjectTag(*obj), NULL);
return JS_FALSE; return JS_FALSE;
} }
@@ -2527,7 +2527,7 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, Native native,
fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom); fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
if (!fun) if (!fun)
return NULL; return NULL;
if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), FunObjValue(*FUN_OBJECT(fun)), if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), fun->funObjVal(),
gsop, gsop, attrs & ~JSFUN_FLAGS_MASK)) { gsop, gsop, attrs & ~JSFUN_FLAGS_MASK)) {
return NULL; return NULL;
} }

View File

@@ -199,6 +199,10 @@ struct JSFunction : public JSObject
bool mightEscape() const { bool mightEscape() const {
return FUN_INTERPRETED(this) && (FUN_FLAT_CLOSURE(this) || u.i.nupvars == 0); return FUN_INTERPRETED(this) && (FUN_FLAT_CLOSURE(this) || u.i.nupvars == 0);
} }
js::FunObjTag funObjVal() {
return js::FunObjTag(*this);
}
}; };
/* /*
@@ -309,8 +313,8 @@ extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun); js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSObject * extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, const js::Value &parent, js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
const js::Value &proto); JSObject *proto);
inline JSObject * inline JSObject *
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent) CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
@@ -319,8 +323,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
JSObject *proto; JSObject *proto;
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto)) if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
return NULL; return NULL;
return js_CloneFunctionObject(cx, fun, js::NonFunObjValue(*parent), return js_CloneFunctionObject(cx, fun, parent, proto);
js::FunObjValue(*proto));
} }
extern JS_REQUIRES_STACK JSObject * extern JS_REQUIRES_STACK JSObject *

View File

@@ -2343,7 +2343,7 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
pobj = ssr->pobj; pobj = ssr->pobj;
if (slot == JSSLOT_PROTO) { if (slot == JSSLOT_PROTO) {
obj->setProto(ToObjPtr(pobj)); obj->setProto(ObjectOrNullTag(pobj));
} else { } else {
JS_ASSERT(slot == JSSLOT_PARENT); JS_ASSERT(slot == JSSLOT_PARENT);
obj->setParent(pobj); obj->setParent(pobj);

View File

@@ -273,7 +273,7 @@ ComputeGlobalThis(JSContext *cx, Value *argv)
thisp = cx->globalObject; thisp = cx->globalObject;
else else
thisp = argv[-2].asObject().getGlobal(); thisp = argv[-2].asObject().getGlobal();
return CallThisObjectHook(cx, NonFunObjPtr(*thisp), argv); return CallThisObjectHook(cx, NonFunObjTag(*thisp), argv);
} }
static bool static bool
@@ -482,7 +482,7 @@ Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags)
if (JSFUN_BOUND_METHOD_TEST(fun->flags)) { if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
/* Handle bound method special case. */ /* Handle bound method special case. */
SetObject(&vp[1], parent); vp[1].setObjectOrNull(parent);
} else if (vp[1].isPrimitive()) { } else if (vp[1].isPrimitive()) {
JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT)); JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
if (PrimitiveThisTest(fun, vp[1])) if (PrimitiveThisTest(fun, vp[1]))
@@ -667,7 +667,7 @@ InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
return JS_FALSE; return JS_FALSE;
args.getvp()[0].copy(fval); args.getvp()[0].copy(fval);
SetObject(&args.getvp()[1], obj); args.getvp()[1].setObjectOrNull(obj);
memcpy(args.getvp() + 2, argv, argc * sizeof(*argv)); memcpy(args.getvp() + 2, argv, argc * sizeof(*argv));
if (!Invoke(cx, args, flags)) if (!Invoke(cx, args, flags))
@@ -792,7 +792,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSObject *thisp = chain->thisObject(cx); JSObject *thisp = chain->thisObject(cx);
if (!thisp) if (!thisp)
return false; return false;
SetObject(&fp->thisv, *thisp); fp->thisv.setObject(*thisp);
fp->flags = flags | JSFRAME_COMPUTED_THIS; fp->flags = flags | JSFRAME_COMPUTED_THIS;
fp->argc = 0; fp->argc = 0;
fp->argv = NULL; fp->argv = NULL;
@@ -1105,7 +1105,7 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn
return JS_FALSE; return JS_FALSE;
/* Now we have an object with a constructor method; call it. */ /* Now we have an object with a constructor method; call it. */
SetObject(&vp[1], *obj); vp[1].setObject(*obj);
if (!Invoke(cx, args, JSINVOKE_CONSTRUCT)) if (!Invoke(cx, args, JSINVOKE_CONSTRUCT))
return JS_FALSE; return JS_FALSE;
@@ -1118,7 +1118,7 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn
js_ValueToPrintableString(cx, *vp)); js_ValueToPrintableString(cx, *vp));
return JS_FALSE; return JS_FALSE;
} }
SetObject(vp, *obj); vp->setObject(*obj);
} }
JS_RUNTIME_METER(cx->runtime, constructs); JS_RUNTIME_METER(cx->runtime, constructs);
@@ -1676,18 +1676,18 @@ namespace reprmeter {
} }
#endif /* JS_REPRMETER */ #endif /* JS_REPRMETER */
#define PUSH_COPY(v) regs.sp++->copy(v) #define PUSH_COPY(v) regs.sp++->copy(v)
#define PUSH_NULL() regs.sp++->setNull() #define PUSH_NULL() regs.sp++->setNull()
#define PUSH_UNDEFINED() regs.sp++->setUndefined() #define PUSH_UNDEFINED() regs.sp++->setUndefined()
#define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b) #define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b)
#define PUSH_INT32(i) regs.sp++->setInt32(i) #define PUSH_INT32(i) regs.sp++->setInt32(i)
#define PUSH_STRING(s) regs.sp++->setString(s) #define PUSH_STRING(s) regs.sp++->setString(s)
#define PUSH_NONFUNOBJ(o) regs.sp++->setNonFunObj(o) #define PUSH_NONFUNOBJ(obj) regs.sp++->setNonFunObj(obj)
#define PUSH_FUNOBJ(o) regs.sp++->setFunObj(o) #define PUSH_FUNOBJ(obj) regs.sp++->setFunObj(obj)
#define PUSH_OBJECT(o) SetObject(regs.sp++, o) #define PUSH_OBJECT(obj) regs.sp++->setObject(obj)
#define PUSH_OBJECT_OR_NULL(o) SetObject(regs.sp++, o) #define PUSH_OBJECT_OR_NULL(obj) regs.sp++->setObject(obj)
#define PUSH_HOLE() regs.sp++->setMagic(JS_ARRAY_HOLE) #define PUSH_HOLE() regs.sp++->setMagic(JS_ARRAY_HOLE)
#define POP_COPY_TO(v) v.copy(*--regs.sp) #define POP_COPY_TO(v) v.copy(*--regs.sp)
/* /*
* Push the jsdouble d using sp from the lexical environment. Try to convert d * Push the jsdouble d using sp from the lexical environment. Try to convert d
@@ -1859,7 +1859,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
} else if (entry->vword.isSprop()) { } else if (entry->vword.isSprop()) {
JS_ASSERT(entry->vword.toSprop() == sprop); JS_ASSERT(entry->vword.toSprop() == sprop);
JS_ASSERT_IF(sprop->isMethod(), JS_ASSERT_IF(sprop->isMethod(),
sprop->methodValue().isSame(pobj->lockedGetSlot(sprop->slot))); &sprop->methodFunObj() == &pobj->lockedGetSlot(sprop->slot).asFunObj());
} else { } else {
Value v; Value v;
JS_ASSERT(entry->vword.isFunObj()); JS_ASSERT(entry->vword.isFunObj());
@@ -1872,7 +1872,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
if (sprop->isMethod()) { if (sprop->isMethod()) {
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_CALLOP); JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_CALLOP);
JS_ASSERT(sprop->methodValue().isSame(v)); JS_ASSERT(&sprop->methodFunObj() == &v.asFunObj());
} }
} }

View File

@@ -476,7 +476,7 @@ JSStackFrame::getThisObject(JSContext *cx)
if (flags & JSFRAME_COMPUTED_THIS) if (flags & JSFRAME_COMPUTED_THIS)
return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */ return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */
if (!js::ComputeThisFromArgv(cx, argv)) if (!js::ComputeThisFromArgv(cx, argv))
return js::NullObjPtr(); return js::NullTag();
thisv.copy(argv[-1]); thisv.copy(argv[-1]);
flags |= JSFRAME_COMPUTED_THIS; flags |= JSFRAME_COMPUTED_THIS;
return thisv.asObjPtr(); return thisv.asObjPtr();

View File

@@ -103,9 +103,9 @@ ExtendedClass js_IteratorClass = {
void void
NativeIterator::mark(JSTracer *trc) NativeIterator::mark(JSTracer *trc)
{ {
for (jsval *vp = props_array; vp < props_end; ++vp) { for (Value *vp = props_array; vp < props_end; ++vp) {
JS_SET_TRACING_INDEX(trc, "props", (vp - props_array)); JS_SET_TRACING_INDEX(trc, "props", (vp - props_array));
js_CallValueTracerIfGCThing(trc, *vp); CallGCMarkerIfGCThing(trc, *vp);
} }
} }

View File

@@ -164,7 +164,7 @@ obj_getProto(JSContext *cx, JSObject *obj, jsid id, Value *vp)
pobj = thisObject(cx, pobj); pobj = thisObject(cx, pobj);
if (!pobj) if (!pobj)
return JS_FALSE; return JS_FALSE;
SetObject(vp, *pobj); vp->setObject(*pobj);
} }
} }
} }
@@ -239,7 +239,7 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
if (!pobj || !checkForCycles) { if (!pobj || !checkForCycles) {
if (slot == JSSLOT_PROTO) if (slot == JSSLOT_PROTO)
obj->setProto(ToObjPtr(pobj)); obj->setProto(ObjectOrNullTag(pobj));
else else
obj->setParent(pobj); obj->setParent(pobj);
} else { } else {
@@ -332,14 +332,14 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
JSScopeProperty *sprop = (JSScopeProperty *) prop; JSScopeProperty *sprop = (JSScopeProperty *) prop;
val.setUndefined(); val.setUndefined();
if (attrs & JSPROP_GETTER) if (attrs & JSPROP_GETTER)
val.copy(sprop->getterValue()); val.setFunObjOrUndefined(sprop->getterObject());
if (attrs & JSPROP_SETTER) { if (attrs & JSPROP_SETTER) {
if (!val.isUndefined()) { if (!val.isUndefined()) {
/* Mark the getter, then set val to setter. */ /* Mark the getter, then set val to setter. */
ok = (MarkSharpObjects(cx, &val.asFunObj(), NULL) ok = (MarkSharpObjects(cx, &val.asFunObj(), NULL)
!= NULL); != NULL);
} }
val.copy(sprop->setterValue()); val.setFunObjOrUndefined(sprop->setterObject());
} }
} else { } else {
ok = obj->getProperty(cx, id, &val); ok = obj->getProperty(cx, id, &val);
@@ -575,7 +575,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
JS_CHECK_RECURSION(cx, return JS_FALSE); JS_CHECK_RECURSION(cx, return JS_FALSE);
Value localroot[4] = {NullValue(), NullValue(), NullValue(), NullValue()}; CopyableValue localroot[4] = { NullTag(), NullTag(), NullTag(), NullTag() };
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroot), localroot); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroot), localroot);
/* If outermost, we need parentheses to be an expression, not a block. */ /* If outermost, we need parentheses to be an expression, not a block. */
@@ -674,12 +674,12 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
if (obj2->isNative() && (attrs & (JSPROP_GETTER | JSPROP_SETTER))) { if (obj2->isNative() && (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
JSScopeProperty *sprop = (JSScopeProperty *) prop; JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (attrs & JSPROP_GETTER) { if (attrs & JSPROP_GETTER) {
val[valcnt].copy(sprop->getterValue()); val[valcnt].setFunObjOrUndefined(sprop->getterObject());
gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.getAtom); gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.getAtom);
valcnt++; valcnt++;
} }
if (attrs & JSPROP_SETTER) { if (attrs & JSPROP_SETTER) {
val[valcnt].copy(sprop->setterValue()); val[valcnt].setFunObjOrUndefined(sprop->setterObject());
gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setAtom); gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setAtom);
valcnt++; valcnt++;
} }
@@ -1248,7 +1248,7 @@ obj_eval(JSContext *cx, uintN argc, Value *vp)
scopeobj = withGuard.obj; scopeobj = withGuard.obj;
JS_ASSERT(argc >= 2); JS_ASSERT(argc >= 2);
SetObject(&argv[1], *withGuard.obj); argv[1].setObject(*withGuard.obj);
} }
/* We're pretending that we're in global code. */ /* We're pretending that we're in global code. */
@@ -1434,7 +1434,7 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, const Value *old,
argv[0].copy(IdToValue(id)); argv[0].copy(IdToValue(id));
argv[1].copy(*old); argv[1].copy(*old);
argv[2].copy(*nvp); argv[2].copy(*nvp);
ok = InternalCall(cx, obj, ToValue(callable), 3, argv, nvp); ok = InternalCall(cx, obj, ObjectOrNullTag(callable), 3, argv, nvp);
js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation); js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
return ok; return ok;
} }
@@ -1729,7 +1729,7 @@ obj_lookupGetter(JSContext *cx, uintN argc, Value *vp)
if (pobj->isNative()) { if (pobj->isNative()) {
JSScopeProperty *sprop = (JSScopeProperty *) prop; JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (sprop->hasGetterValue()) if (sprop->hasGetterValue())
vp->copy(sprop->getterValue()); vp->setFunObjOrUndefined(sprop->getterObject());
} }
pobj->dropProperty(cx, prop); pobj->dropProperty(cx, prop);
} }
@@ -1752,7 +1752,7 @@ obj_lookupSetter(JSContext *cx, uintN argc, Value *vp)
if (pobj->isNative()) { if (pobj->isNative()) {
JSScopeProperty *sprop = (JSScopeProperty *) prop; JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (sprop->hasSetterValue()) if (sprop->hasSetterValue())
vp->copy(sprop->setterValue()); vp->setFunObjOrUndefined(sprop->setterObject());
} }
pobj->dropProperty(cx, prop); pobj->dropProperty(cx, prop);
} }
@@ -1802,15 +1802,15 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp)
return false; return false;
} }
Value roots[] = { UndefinedValue(), UndefinedValue() }; CopyableValue roots[2] = { UndefinedTag(), UndefinedTag() };
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
if (obj->isNative()) { if (obj->isNative()) {
JSScopeProperty *sprop = reinterpret_cast<JSScopeProperty *>(prop); JSScopeProperty *sprop = reinterpret_cast<JSScopeProperty *>(prop);
if (attrs & JSPROP_GETTER) if (attrs & JSPROP_GETTER)
roots[0].copy(sprop->getterValue()); roots[0].setFunObjOrUndefined(sprop->getterObject());
if (attrs & JSPROP_SETTER) if (attrs & JSPROP_SETTER)
roots[1].copy(sprop->setterValue()); roots[1].setFunObjOrUndefined(sprop->setterObject());
} }
pobj->dropProperty(cx, prop); pobj->dropProperty(cx, prop);
@@ -1826,7 +1826,7 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp)
JSObject *desc = NewObject(cx, &js_ObjectClass, NULL, NULL); JSObject *desc = NewObject(cx, &js_ObjectClass, NULL, NULL);
if (!desc) if (!desc)
return false; return false;
SetObject(vp, *desc); /* Root and return. */ vp->setObject(*desc); /* Root and return. */
const JSAtomState &atomState = cx->runtime->atomState; const JSAtomState &atomState = cx->runtime->atomState;
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
@@ -1934,9 +1934,9 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id, Value* vp, JSBool* answerp)
PropertyDescriptor::PropertyDescriptor() PropertyDescriptor::PropertyDescriptor()
: id(INT_TO_JSID(0)), : id(INT_TO_JSID(0)),
value(UndefinedValue()), value(UndefinedTag()),
get(UndefinedValue()), get(UndefinedTag()),
set(UndefinedValue()), set(UndefinedTag()),
attrs(0), attrs(0),
hasGet(false), hasGet(false),
hasSet(false), hasSet(false),
@@ -2142,14 +2142,12 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &d
break; break;
if (desc.hasGet && if (desc.hasGet &&
!SameValue(cx, desc.getterValue(), !SameValue(cx, desc.getterValue(), sprop->getterOrUndefined())) {
sprop->hasGetterValue() ? sprop->getterValue() : UndefinedValue())) {
break; break;
} }
if (desc.hasSet && if (desc.hasSet &&
!SameValue(cx, desc.setterValue(), !SameValue(cx, desc.setterValue(), sprop->setterOrUndefined())) {
sprop->hasSetterValue() ? sprop->setterValue() : UndefinedValue())) {
break; break;
} }
} else { } else {
@@ -2261,11 +2259,9 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &d
JS_ASSERT(desc.isAccessorDescriptor() && sprop->isAccessorDescriptor()); JS_ASSERT(desc.isAccessorDescriptor() && sprop->isAccessorDescriptor());
if (!sprop->configurable()) { if (!sprop->configurable()) {
if ((desc.hasSet && if ((desc.hasSet &&
!SameValue(cx, desc.setterValue(), !SameValue(cx, desc.setterValue(), sprop->setterOrUndefined())) ||
sprop->hasSetterValue() ? sprop->setterValue() : UndefinedValue())) ||
(desc.hasGet && (desc.hasGet &&
!SameValue(cx, desc.getterValue(), !SameValue(cx, desc.getterValue(), sprop->getterOrUndefined()))) {
sprop->hasGetterValue() ? sprop->getterValue() : UndefinedValue()))) {
return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_UNCONFIGURABLE_PROP, return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_UNCONFIGURABLE_PROP,
throwError, desc.id, rval); throwError, desc.id, rval);
} }
@@ -3028,7 +3024,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSStackFrame *fp)
/* The caller sets parent on its own. */ /* The caller sets parent on its own. */
Value priv; Value priv;
priv.setPrivateVoidPtr(js_FloatingFrameIfGenerator(cx, fp)); priv.setPrivateVoidPtr(js_FloatingFrameIfGenerator(cx, fp));
clone->init(&js_BlockClass, NonFunObjPtr(*proto), NULL, priv); clone->init(&js_BlockClass, NonFunObjTag(*proto), NULL, priv);
clone->fslots[JSSLOT_BLOCK_DEPTH].copy(proto->fslots[JSSLOT_BLOCK_DEPTH]); clone->fslots[JSSLOT_BLOCK_DEPTH].copy(proto->fslots[JSSLOT_BLOCK_DEPTH]);
JS_ASSERT(cx->runtime->emptyBlockScope->freeslot == JSSLOT_BLOCK_DEPTH + 1); JS_ASSERT(cx->runtime->emptyBlockScope->freeslot == JSSLOT_BLOCK_DEPTH + 1);
@@ -3376,7 +3372,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
key != JSProto_Null) { key != JSProto_Null) {
named = JS_FALSE; named = JS_FALSE;
} else { } else {
named = obj->defineProperty(cx, ATOM_TO_JSID(atom), ToValue(proto), named = obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectOrNullTag(proto),
PropertyStub, PropertyStub, PropertyStub, PropertyStub,
(clasp->flags & JSCLASS_IS_ANONYMOUS) (clasp->flags & JSCLASS_IS_ANONYMOUS)
? JSPROP_READONLY | JSPROP_PERMANENT ? JSPROP_READONLY | JSPROP_PERMANENT
@@ -3410,7 +3406,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
ctor = FUN_OBJECT(fun); ctor = FUN_OBJECT(fun);
if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) { if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
Value rval; Value rval;
if (!InternalConstruct(cx, proto, ToValue(ctor), 0, NULL, &rval)) if (!InternalConstruct(cx, proto, ObjectOrNullTag(ctor), 0, NULL, &rval))
goto bad; goto bad;
if (rval.isObject() && &rval.asObject() != proto) if (rval.isObject() && &rval.asObject() != proto)
proto = &rval.asObject(); proto = &rval.asObject();
@@ -3424,7 +3420,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
/* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
if (ctor->getClass() == clasp) if (ctor->getClass() == clasp)
ctor->setProto(ToObjPtr(proto)); ctor->setProto(ObjectOrNullTag(proto));
} }
/* Add properties and methods to the prototype and the constructor. */ /* Add properties and methods to the prototype and the constructor. */
@@ -3663,7 +3659,7 @@ js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj)
if (!(obj->getClass()->flags & JSCLASS_IS_GLOBAL)) if (!(obj->getClass()->flags & JSCLASS_IS_GLOBAL))
return JS_TRUE; return JS_TRUE;
return js_SetReservedSlot(cx, obj, key, ToValue(cobj)); return js_SetReservedSlot(cx, obj, key, ObjectOrNullTag(cobj));
} }
JSBool JSBool
@@ -3709,7 +3705,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
if (!js_GetClassObject(cx, obj, protoKey, &cobj)) if (!js_GetClassObject(cx, obj, protoKey, &cobj))
return JS_FALSE; return JS_FALSE;
if (cobj) { if (cobj) {
SetObject(vp, *cobj); vp->setObject(*cobj);
return JS_TRUE; return JS_TRUE;
} }
id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[protoKey]); id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[protoKey]);
@@ -4588,7 +4584,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
return true; return true;
if (JS_UNLIKELY(sprop->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER)) { if (JS_UNLIKELY(sprop->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER)) {
JS_ASSERT(sprop->methodValue().isSame(*vp)); JS_ASSERT(&sprop->methodFunObj() == &vp->asFunObj());
return true; return true;
} }
@@ -5204,7 +5200,7 @@ JSBool
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp) js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
{ {
Value v; Value v;
SetObject(&v, obj); v.setObject(*obj);
if (hint == JSTYPE_STRING) { if (hint == JSTYPE_STRING) {
JS_ASSERT(hint != JSTYPE_OBJECT && hint != JSTYPE_FUNCTION); JS_ASSERT(hint != JSTYPE_OBJECT && hint != JSTYPE_FUNCTION);
@@ -5281,7 +5277,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
} else { } else {
str = NULL; str = NULL;
} }
SetObject(vp, *obj); vp->setObject(*obj);
js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO, js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,
JSDVG_SEARCH_STACK, *vp, str, JSDVG_SEARCH_STACK, *vp, str,
(hint == JSTYPE_VOID) (hint == JSTYPE_VOID)
@@ -5556,7 +5552,7 @@ js_HasInstance(JSContext *cx, JSObject *obj, const Value *vp, JSBool *bp)
} }
#endif #endif
js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
JSDVG_SEARCH_STACK, ToValue(*obj), NULL); JSDVG_SEARCH_STACK, ObjectTag(*obj), NULL);
return JS_FALSE; return JS_FALSE;
} }
@@ -5682,7 +5678,7 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs
* DontDelete. * DontDelete.
*/ */
if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom),
ToValue(proto), PropertyStub, PropertyStub, attrs)) { ObjectOrNullTag(proto), PropertyStub, PropertyStub, attrs)) {
return JS_FALSE; return JS_FALSE;
} }
@@ -5691,7 +5687,7 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs
* for a user-defined function f, is DontEnum. * for a user-defined function f, is DontEnum.
*/ */
return proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), return proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
ToValue(ctor), CheckCtorGetAccess, CheckCtorSetAccess, 0); ObjectOrNullTag(ctor), CheckCtorGetAccess, CheckCtorSetAccess, 0);
} }
JSBool JSBool
@@ -6375,11 +6371,11 @@ DumpObject(JSObject *obj)
} }
fprintf(stderr, "proto "); fprintf(stderr, "proto ");
dumpValue(ToValue(obj->getProto())); dumpValue(obj->getProtoValue());
fputc('\n', stderr); fputc('\n', stderr);
fprintf(stderr, "parent "); fprintf(stderr, "parent ");
dumpValue(ToValue(obj->getParent())); dumpValue(obj->getParentValue());
fputc('\n', stderr); fputc('\n', stderr);
i = JSSLOT_PRIVATE; i = JSSLOT_PRIVATE;
@@ -6409,7 +6405,7 @@ MaybeDumpObject(const char *name, JSObject *obj)
{ {
if (obj) { if (obj) {
fprintf(stderr, " %s: ", name); fprintf(stderr, " %s: ", name);
dumpValue(ToValue(*obj)); dumpValue(ObjectTag(*obj));
fputc('\n', stderr); fputc('\n', stderr);
} }
} }

View File

@@ -1292,21 +1292,4 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
JSBool JSBool
js_Object(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval); js_Object(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
namespace js {
/*
* Convenience functions for manipulating objects and values. To be inlined,
* these functions need to be in jsobj.h, so they cannot be member functions.
*/
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject *pobj);
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject &obj);
JS_ALWAYS_INLINE Value ToValue(JSObject *pobj);
JS_ALWAYS_INLINE Value ToValue(JSObject &obj);
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject *pobj);
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject *pobj);
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject &obj);
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject &obj);
} /* namespace js */
#endif /* jsobj_h___ */ #endif /* jsobj_h___ */

View File

@@ -470,10 +470,10 @@ inline js::ObjPtr
JSObject::thisObject(JSContext *cx, js::ObjPtr obj) JSObject::thisObject(JSContext *cx, js::ObjPtr obj)
{ {
if (JSObjectOp thisOp = obj->map->ops->thisObject) { if (JSObjectOp thisOp = obj->map->ops->thisObject) {
JSObject *o = thisOp(cx, obj); JSObject *pobj = thisOp(cx, obj);
if (!o) if (!pobj)
return js::NullObjPtr(); return js::NullTag();
SetObject(&obj, *o); obj.setObject(*pobj);
} }
return obj; return obj;
} }
@@ -590,7 +590,7 @@ NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto,
* the parent of the prototype's constructor. * the parent of the prototype's constructor.
*/ */
obj->init(clasp, obj->init(clasp,
ToObjPtr(proto), js::ObjectOrNullTag(proto),
(!parent && proto) ? proto->getParent() : parent, (!parent && proto) ? proto->getParent() : parent,
JSObject::defaultPrivate(clasp)); JSObject::defaultPrivate(clasp));
@@ -650,80 +650,60 @@ NewObject(JSContext *cx, js::Class *clasp, JSObject *proto,
return NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize); return NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
} }
JS_ALWAYS_INLINE ObjPtr JS_ALWAYS_INLINE
ToObjPtr(JSObject *pobj) ObjPtr::ObjPtr(ObjectTag arg)
{ {
if (pobj) mask = arg.obj.isFunction() ? FunObjMask : NonFunObjMask;
return NullObjPtr(); obj = &arg.obj;
if (pobj->isFunction())
return FunObjPtr(*pobj);
return NonFunObjPtr(*pobj);
} }
JS_ALWAYS_INLINE ObjPtr JS_ALWAYS_INLINE
ToObjPtr(JSObject &obj) ObjPtr::ObjPtr(ObjectOrNullTag arg)
{ {
if (obj.isFunction()) mask = arg.obj ? arg.obj->isFunction() ? FunObjMask : NonFunObjMask : NullMask;
return FunObjPtr(obj); obj = arg.obj;
return NonFunObjPtr(obj);
}
JS_ALWAYS_INLINE Value
ToValue(JSObject *pobj)
{
if (pobj)
return NullValue();
if (pobj->isFunction())
return FunObjValue(*pobj);
return NonFunObjValue(*pobj);
}
JS_ALWAYS_INLINE Value
ToValue(JSObject &obj)
{
if (obj.isFunction())
return FunObjValue(obj);
return NonFunObjValue(obj);
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
SetObject(ObjPtr *vp, JSObject *pobj) ObjPtr::setObject(JSObject &arg)
{ {
if (!pobj) mask = arg.isFunction() ? FunObjMask : NonFunObjMask;
vp->setNull(); obj = &arg;
else if (pobj->isFunction())
vp->setFunObj(*pobj);
else
vp->setNonFunObj(*pobj);
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
SetObject(Value *vp, JSObject *pobj) ObjPtr::setObjectOrNull(JSObject *arg)
{ {
if (!pobj) mask = arg ? arg->isFunction() ? FunObjMask : NonFunObjMask : NullMask;
vp->setNull(); obj = arg;
if (pobj->isFunction()) }
vp->setFunObj(*pobj);
else JS_ALWAYS_INLINE
vp->setNonFunObj(*pobj); Value::Value(ObjectTag arg)
{
mask = arg.obj.isFunction() ? FunObjMask : NonFunObjMask;
data.obj = &arg.obj;
}
JS_ALWAYS_INLINE
Value::Value(ObjectOrNullTag arg)
{
mask = arg.obj ? arg.obj->isFunction() ? FunObjMask : NonFunObjMask : NullMask;
data.obj = arg.obj;
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
SetObject(ObjPtr *vp, JSObject &obj) Value::setObject(JSObject &arg)
{ {
if (obj.isFunction()) mask = arg.isFunction() ? FunObjMask : NonFunObjMask;
vp->setFunObj(obj); data.obj = &arg;
else
vp->setNonFunObj(obj);
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
SetObject(Value *vp, JSObject &obj) Value::setObjectOrNull(JSObject *arg)
{ {
if (obj.isFunction()) mask = arg ? arg->isFunction() ? FunObjMask : NonFunObjMask : NullMask;
vp->setFunObj(obj); data.obj = arg;
else
vp->setNonFunObj(obj);
} }
} /* namespace js */ } /* namespace js */

View File

@@ -3151,7 +3151,8 @@ BEGIN_CASE(JSOP_DEFFUN)
MUST_FLOW_THROUGH("restore_scope"); MUST_FLOW_THROUGH("restore_scope");
fp->scopeChain = obj; fp->scopeChain = obj;
FunObjValue rval(*obj); Value rval;
rval.setFunObj(*obj);
/* /*
* ECMA requires functions defined when entering Eval code to be * ECMA requires functions defined when entering Eval code to be
@@ -3250,7 +3251,9 @@ BEGIN_CASE(JSOP_DEFFUN_DBGFC)
: js_NewDebuggableFlatClosure(cx, fun); : js_NewDebuggableFlatClosure(cx, fun);
if (!obj) if (!obj)
goto error; goto error;
FunObjValue rval(*obj);
Value rval;
rval.setFunObj(*obj);
uintN attrs = (fp->flags & JSFRAME_EVAL) uintN attrs = (fp->flags & JSFRAME_EVAL)
? JSPROP_ENUMERATE ? JSPROP_ENUMERATE
@@ -4044,7 +4047,7 @@ BEGIN_CASE(JSOP_QNAMECONST)
JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval); JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
if (!obj) if (!obj)
goto error; goto error;
SetObject(&regs.sp[-1], *obj); regs.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_QNAMECONST) END_CASE(JSOP_QNAMECONST)
@@ -4057,7 +4060,7 @@ BEGIN_CASE(JSOP_QNAME)
if (!obj) if (!obj)
goto error; goto error;
regs.sp--; regs.sp--;
SetObject(&regs.sp[-1], *obj); regs.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_QNAME) END_CASE(JSOP_QNAME)
@@ -4107,7 +4110,7 @@ BEGIN_CASE(JSOP_BINDXMLNAME)
jsid id; jsid id;
if (!js_FindXMLProperty(cx, lval, &obj, &id)) if (!js_FindXMLProperty(cx, lval, &obj, &id))
goto error; goto error;
SetObject(&regs.sp[-1], obj); regs.sp[-1].setObjectOrNull(obj);
PUSH_COPY(IdToValue(id)); PUSH_COPY(IdToValue(id));
} }
END_CASE(JSOP_BINDXMLNAME) END_CASE(JSOP_BINDXMLNAME)
@@ -4215,7 +4218,7 @@ BEGIN_CASE(JSOP_TOXML)
JSObject *obj = js_ValueToXMLObject(cx, rval); JSObject *obj = js_ValueToXMLObject(cx, rval);
if (!obj) if (!obj)
goto error; goto error;
SetObject(&regs.sp[-1], *obj); regs.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_TOXML) END_CASE(JSOP_TOXML)
@@ -4226,7 +4229,7 @@ BEGIN_CASE(JSOP_TOXMLLIST)
JSObject *obj = js_ValueToXMLListObject(cx, rval); JSObject *obj = js_ValueToXMLListObject(cx, rval);
if (!obj) if (!obj)
goto error; goto error;
SetObject(&regs.sp[-1], *obj); regs.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_TOXMLLIST) END_CASE(JSOP_TOXMLLIST)
@@ -4305,7 +4308,7 @@ BEGIN_CASE(JSOP_XMLPI)
JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, str, str2); JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, str, str2);
if (!obj) if (!obj)
goto error; goto error;
SetObject(&regs.sp[-1], *obj); regs.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_XMLPI) END_CASE(JSOP_XMLPI)

View File

@@ -689,8 +689,7 @@ struct JSScopeProperty {
bool hasShortID() const { return (flags & HAS_SHORTID) != 0; } bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
bool isMethod() const { return (flags & METHOD) != 0; } bool isMethod() const { return (flags & METHOD) != 0; }
JSObject *methodObject() const { JS_ASSERT(isMethod()); return getterObj; } JSObject &methodFunObj() const { JS_ASSERT(isMethod()); return *getterObj; }
js::Value methodValue() const { return js::FunObjValue(*methodObject()); }
js::PropertyOp getter() const { return rawGetter; } js::PropertyOp getter() const { return rawGetter; }
bool hasDefaultGetter() const { return !rawGetter; } bool hasDefaultGetter() const { return !rawGetter; }
@@ -698,11 +697,13 @@ struct JSScopeProperty {
JSObject *getterObject() const { JS_ASSERT(hasGetterValue()); return getterObj; } JSObject *getterObject() const { JS_ASSERT(hasGetterValue()); return getterObj; }
// Per ES5, decode null getterObj as the undefined value, which encodes as null. // Per ES5, decode null getterObj as the undefined value, which encodes as null.
js::Value getterValue() const { js::FunObjOrUndefinedTag getterValue() const {
JS_ASSERT(hasGetterValue()); JS_ASSERT(hasGetterValue());
if (getterObj) return js::FunObjOrUndefinedTag(getterObj);
return js::FunObjValue(*getterObj); }
return js::UndefinedValue();
js::FunObjOrUndefinedTag getterOrUndefined() const {
return js::FunObjOrUndefinedTag(hasGetterValue() ? getterObj : NULL);
} }
js::PropertyOp setter() const { return rawSetter; } js::PropertyOp setter() const { return rawSetter; }
@@ -711,11 +712,13 @@ struct JSScopeProperty {
JSObject *setterObject() const { JS_ASSERT(hasSetterValue()); return setterObj; } JSObject *setterObject() const { JS_ASSERT(hasSetterValue()); return setterObj; }
// Per ES5, decode null setterObj as the undefined value, which encodes as null. // Per ES5, decode null setterObj as the undefined value, which encodes as null.
js::Value setterValue() const { js::FunObjOrUndefinedTag setterValue() const {
JS_ASSERT(hasSetterValue()); JS_ASSERT(hasSetterValue());
if (setterObj) return js::FunObjOrUndefinedTag(setterObj);
return js::FunObjValue(*setterObj); }
return js::UndefinedValue();
js::FunObjOrUndefinedTag setterOrUndefined() const {
return js::FunObjOrUndefinedTag(hasSetterValue() ? setterObj : NULL);
} }
inline JSDHashNumber hash() const; inline JSDHashNumber hash() const;
@@ -964,7 +967,7 @@ JSScopeProperty::get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp
} }
if (isMethod()) { if (isMethod()) {
vp->copy(methodValue()); vp->setFunObj(methodFunObj());
JSScope *scope = pobj->scope(); JSScope *scope = pobj->scope();
JS_ASSERT(scope->object == pobj); JS_ASSERT(scope->object == pobj);

View File

@@ -119,7 +119,7 @@ JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp)
JS_ASSERT(hasMethodBarrier()); JS_ASSERT(hasMethodBarrier());
JS_ASSERT(hasProperty(sprop)); JS_ASSERT(hasProperty(sprop));
JS_ASSERT(sprop->isMethod()); JS_ASSERT(sprop->isMethod());
JS_ASSERT(sprop->methodValue().isSame(*vp)); JS_ASSERT(&vp->asFunObj() == &sprop->methodFunObj());
JS_ASSERT(object->getClass() == &js_ObjectClass); JS_ASSERT(object->getClass() == &js_ObjectClass);
JSObject *funobj = &vp->asFunObj(); JSObject *funobj = &vp->asFunObj();