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;
}
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. */
@@ -1121,9 +1121,9 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
}
/* 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())
obj->setProto(NonFunObjPtr(*obj_proto));
obj->setProto(NonFunObjTag(*obj_proto));
out:
/* 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);
if (!nobj)
return NULL;
if (!DefineProperty(cx, obj, name, ToValue(nobj), NULL, NULL, attrs,
if (!DefineProperty(cx, obj, name, ObjectTag(*nobj), NULL, NULL, attrs,
0, 0)) {
return NULL;
}
@@ -3064,7 +3064,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop,
if (sprop->isMethod()) {
AutoScopePropertyRooter root(cx, sprop);
JS_UNLOCK_OBJ(cx, obj2);
vp->copy(sprop->methodValue());
vp->setFunObj(sprop->methodFunObj());
return obj2->scope()->methodReadBarrier(cx, sprop, vp);
}
@@ -3966,7 +3966,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
*idp = JSID_VOID;
} else {
*idp = ida->vector[--i];
iterobj->setSlot(JSSLOT_ITER_INDEX, Value(i));
iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Tag(i));
}
}
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!).
*/
Value v;
SetObject(&v, funobj);
v.setObject(*funobj);
js_ReportIsNotFunction(cx, &v, 0);
return NULL;
}
@@ -4684,8 +4684,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
}
if (obj && funAtom &&
!obj->defineProperty(cx, ATOM_TO_JSID(funAtom),
FunObjValue(*FUN_OBJECT(fun)),
!obj->defineProperty(cx, ATOM_TO_JSID(funAtom), fun->funObjVal(),
NULL, NULL, JSPROP_ENUMERATE)) {
fun = NULL;
}
@@ -4849,8 +4848,8 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
JSBool ok;
CHECK_REQUEST(cx);
ok = InternalCall(cx, obj, FunObjValue(*FUN_OBJECT(fun)), argc,
Valueify(argv), Valueify(rval));
ok = InternalCall(cx, obj, fun->funObjVal(), argc, Valueify(argv),
Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}
@@ -4898,7 +4897,7 @@ JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
return NULL;
Value *vp = args.getvp();
SetObject(&vp[0], ctor);
vp[0].setObject(*ctor);
vp[1].setNull();
memcpy(vp + 2, argv, argc * sizeof(jsval));

View File

@@ -2950,6 +2950,59 @@ JS_END_EXTERN_C
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,
* non-function object and function object. ObjPtr is useful when code
@@ -2981,14 +3034,41 @@ class ObjPtr
public:
/* Constructors */
/* N.B. defualt construction yields a ObjPtr in an undefined state. */
ObjPtr() {}
ObjPtr() {
/* N.B. mask and obj are undefined */
}
/*
* To construct a null pointer, use NullObjPtr. To construct pointers to
* objects statically known to be, or not to be, function objects, use
* FunObjPtr, NonFunObjPtr.
*/
ObjPtr(NullTag) {
mask = NullMask;
obj = NULL;
}
ObjPtr(FunObjTag arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg.obj));
mask = FunObjMask;
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 */
@@ -3040,28 +3120,32 @@ class ObjPtr
obj = NULL;
}
void setFunObj(JSObject &o) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &o));
void setFunObj(JSObject &arg) {
JS_ASSERT(JS_ObjectIsFunction(NULL, &arg));
mask = FunObjMask;
obj = &o;
obj = &arg;
}
void setNonFunObj(JSObject &o) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &o));
mask = NonFunObjMask;
obj = &o;
void setFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, JS_ObjectIsFunction(NULL, arg));
mask = arg ? FunObjMask : NullMask;
obj = arg;
}
void setNonFunObjOrNull(JSObject *o) {
if (o) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, o));
void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_ObjectIsFunction(NULL, &arg));
mask = NonFunObjMask;
obj = o;
} else {
mask = NullMask;
obj = o;
obj = &arg;
}
void setNonFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, !JS_ObjectIsFunction(NULL, arg));
mask = arg ? NonFunObjMask : NullMask;
obj = arg;
}
inline void setObject(JSObject &arg);
inline void setObjectOrNull(JSObject *arg);
};
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!=(JSObject *lhs, ObjPtr rhs) { return !(lhs == rhs); }
/*
* 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;
class CopyableValue;
/*
* While there is a single representation for values, there are two declared
@@ -3195,65 +3230,90 @@ class Value
Value &operator=(const Value &);
public:
/* XXX: this can be removed when copying is public/implicit */
inline Value(const ExplicitlyConstructedValue &v);
/* Constructors */
/*
* Constructors
*
* 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.
*/
Value() {
/* N.B. mask and data are undefined. */
}
/* N.B. default construction yields a Value in an undefined state. */
Value() {}
Value(NullTag) {
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 */
explicit Value(const Value &v)
: mask(v.mask), data(v.data)
{}
explicit Value(int32 i32) {
mask = Int32Mask;
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;
}
/* XXX: can be removed when copy is implicit */
Value(const CopyableValue &);
/* Mutators */
@@ -3294,6 +3354,39 @@ class Value
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) {
mask = BooleanMask;
data.boo = b;
@@ -3306,28 +3399,6 @@ class Value
#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 */
/* 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
* 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.
* 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) {
@@ -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
{
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(((jsval *)0)->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
* widespread casting, the following safe casts are provided.

View File

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

View File

@@ -95,7 +95,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
const char *
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;
@@ -1299,7 +1299,7 @@ js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
if (obj->isXML()) {
JSObject &idobj = idval.asObject();
*idp = OBJECT_TO_JSID(&idobj);
SetObject(vp, idobj);
vp->setObject(idobj);
return true;
}
@@ -1351,16 +1351,13 @@ ValueToId(JSContext *cx, const Value *vp, jsid *idp)
Value
IdToValue(jsid id)
{
ExplicitlyConstructedValue v;
if (JSID_IS_INT(id))
v.setInt32(JSID_TO_INT(id));
return CopyableValue(Int32Tag(JSID_TO_INT(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))
v.setNull();
else
SetObject(&v, *JSID_TO_OBJECT(id));
return v;
return CopyableValue(NullTag());
return CopyableValue(ObjectTag(*JSID_TO_OBJECT(id)));
}
} /* namespace js */

View File

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

View File

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

View File

@@ -2242,7 +2242,7 @@ class AutoValueRooter : private AutoGCRooter
public:
explicit AutoValueRooter(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(js::NullValue())
: AutoGCRooter(cx, JSVAL), val(js::NullTag())
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
@@ -2990,7 +2990,7 @@ class AutoValueVector : private AutoGCRooter
size_t length() const { return vector.length(); }
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(); }

View File

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

View File

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

View File

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

View File

@@ -176,8 +176,8 @@ NewArguments(JSContext *cx, JSObject *parent, uint32 argc, JSObject *callee)
return NULL;
/* Init immediately to avoid GC seeing a half-init'ed object. */
argsobj->init(&js_ArgumentsClass, NonFunObjPtr(*proto), parent, NullValue());
argsobj->setArgsCallee(ToValue(callee));
argsobj->init(&js_ArgumentsClass, NonFunObjTag(*proto), parent, NullTag());
argsobj->setArgsCallee(ObjectOrNullTag(callee));
argsobj->setArgsLength(argc);
argsobj->map = cx->runtime->emptyArgumentsScope;
@@ -841,7 +841,7 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO
JSObject *callobj = NewCallObject(cx, fun, scopeChain);
if (!callobj)
return NULL;
callobj->setSlot(JSSLOT_CALLEE, NonFunObjValue(*callee));
callobj->setSlot(JSSLOT_CALLEE, NonFunObjTag(*callee));
return callobj;
}
@@ -877,7 +877,7 @@ js_PutCallObject(JSContext *cx, JSStackFrame *fp)
/* Get the arguments object to snapshot fp's actual argument values. */
if (fp->argsobj) {
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);
}
@@ -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
* 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;
}
@@ -2527,7 +2527,7 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, Native native,
fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
if (!fun)
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)) {
return NULL;
}

View File

@@ -199,6 +199,10 @@ struct JSFunction : public JSObject
bool mightEscape() const {
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);
extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, const js::Value &parent,
const js::Value &proto);
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JSObject *proto);
inline JSObject *
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
@@ -319,8 +323,7 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
JSObject *proto;
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
return NULL;
return js_CloneFunctionObject(cx, fun, js::NonFunObjValue(*parent),
js::FunObjValue(*proto));
return js_CloneFunctionObject(cx, fun, parent, proto);
}
extern JS_REQUIRES_STACK JSObject *

View File

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

View File

@@ -273,7 +273,7 @@ ComputeGlobalThis(JSContext *cx, Value *argv)
thisp = cx->globalObject;
else
thisp = argv[-2].asObject().getGlobal();
return CallThisObjectHook(cx, NonFunObjPtr(*thisp), argv);
return CallThisObjectHook(cx, NonFunObjTag(*thisp), argv);
}
static bool
@@ -482,7 +482,7 @@ Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags)
if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
/* Handle bound method special case. */
SetObject(&vp[1], parent);
vp[1].setObjectOrNull(parent);
} else if (vp[1].isPrimitive()) {
JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
if (PrimitiveThisTest(fun, vp[1]))
@@ -667,7 +667,7 @@ InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
return JS_FALSE;
args.getvp()[0].copy(fval);
SetObject(&args.getvp()[1], obj);
args.getvp()[1].setObjectOrNull(obj);
memcpy(args.getvp() + 2, argv, argc * sizeof(*argv));
if (!Invoke(cx, args, flags))
@@ -792,7 +792,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSObject *thisp = chain->thisObject(cx);
if (!thisp)
return false;
SetObject(&fp->thisv, *thisp);
fp->thisv.setObject(*thisp);
fp->flags = flags | JSFRAME_COMPUTED_THIS;
fp->argc = 0;
fp->argv = NULL;
@@ -1105,7 +1105,7 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn
return JS_FALSE;
/* 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))
return JS_FALSE;
@@ -1118,7 +1118,7 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn
js_ValueToPrintableString(cx, *vp));
return JS_FALSE;
}
SetObject(vp, *obj);
vp->setObject(*obj);
}
JS_RUNTIME_METER(cx->runtime, constructs);
@@ -1682,10 +1682,10 @@ namespace reprmeter {
#define PUSH_BOOLEAN(b) regs.sp++->setBoolean(b)
#define PUSH_INT32(i) regs.sp++->setInt32(i)
#define PUSH_STRING(s) regs.sp++->setString(s)
#define PUSH_NONFUNOBJ(o) regs.sp++->setNonFunObj(o)
#define PUSH_FUNOBJ(o) regs.sp++->setFunObj(o)
#define PUSH_OBJECT(o) SetObject(regs.sp++, o)
#define PUSH_OBJECT_OR_NULL(o) SetObject(regs.sp++, o)
#define PUSH_NONFUNOBJ(obj) regs.sp++->setNonFunObj(obj)
#define PUSH_FUNOBJ(obj) regs.sp++->setFunObj(obj)
#define PUSH_OBJECT(obj) regs.sp++->setObject(obj)
#define PUSH_OBJECT_OR_NULL(obj) regs.sp++->setObject(obj)
#define PUSH_HOLE() regs.sp++->setMagic(JS_ARRAY_HOLE)
#define POP_COPY_TO(v) v.copy(*--regs.sp)
@@ -1859,7 +1859,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
} else if (entry->vword.isSprop()) {
JS_ASSERT(entry->vword.toSprop() == sprop);
JS_ASSERT_IF(sprop->isMethod(),
sprop->methodValue().isSame(pobj->lockedGetSlot(sprop->slot)));
&sprop->methodFunObj() == &pobj->lockedGetSlot(sprop->slot).asFunObj());
} else {
Value v;
JS_ASSERT(entry->vword.isFunObj());
@@ -1872,7 +1872,7 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
if (sprop->isMethod()) {
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)
return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */
if (!js::ComputeThisFromArgv(cx, argv))
return js::NullObjPtr();
return js::NullTag();
thisv.copy(argv[-1]);
flags |= JSFRAME_COMPUTED_THIS;
return thisv.asObjPtr();

View File

@@ -103,9 +103,9 @@ ExtendedClass js_IteratorClass = {
void
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_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);
if (!pobj)
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 (slot == JSSLOT_PROTO)
obj->setProto(ToObjPtr(pobj));
obj->setProto(ObjectOrNullTag(pobj));
else
obj->setParent(pobj);
} else {
@@ -332,14 +332,14 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
JSScopeProperty *sprop = (JSScopeProperty *) prop;
val.setUndefined();
if (attrs & JSPROP_GETTER)
val.copy(sprop->getterValue());
val.setFunObjOrUndefined(sprop->getterObject());
if (attrs & JSPROP_SETTER) {
if (!val.isUndefined()) {
/* Mark the getter, then set val to setter. */
ok = (MarkSharpObjects(cx, &val.asFunObj(), NULL)
!= NULL);
}
val.copy(sprop->setterValue());
val.setFunObjOrUndefined(sprop->setterObject());
}
} else {
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);
Value localroot[4] = {NullValue(), NullValue(), NullValue(), NullValue()};
CopyableValue localroot[4] = { NullTag(), NullTag(), NullTag(), NullTag() };
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroot), localroot);
/* 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))) {
JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (attrs & JSPROP_GETTER) {
val[valcnt].copy(sprop->getterValue());
val[valcnt].setFunObjOrUndefined(sprop->getterObject());
gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.getAtom);
valcnt++;
}
if (attrs & JSPROP_SETTER) {
val[valcnt].copy(sprop->setterValue());
val[valcnt].setFunObjOrUndefined(sprop->setterObject());
gsop[valcnt] = ATOM_TO_STRING(cx->runtime->atomState.setAtom);
valcnt++;
}
@@ -1248,7 +1248,7 @@ obj_eval(JSContext *cx, uintN argc, Value *vp)
scopeobj = withGuard.obj;
JS_ASSERT(argc >= 2);
SetObject(&argv[1], *withGuard.obj);
argv[1].setObject(*withGuard.obj);
}
/* 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[1].copy(*old);
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);
return ok;
}
@@ -1729,7 +1729,7 @@ obj_lookupGetter(JSContext *cx, uintN argc, Value *vp)
if (pobj->isNative()) {
JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (sprop->hasGetterValue())
vp->copy(sprop->getterValue());
vp->setFunObjOrUndefined(sprop->getterObject());
}
pobj->dropProperty(cx, prop);
}
@@ -1752,7 +1752,7 @@ obj_lookupSetter(JSContext *cx, uintN argc, Value *vp)
if (pobj->isNative()) {
JSScopeProperty *sprop = (JSScopeProperty *) prop;
if (sprop->hasSetterValue())
vp->copy(sprop->setterValue());
vp->setFunObjOrUndefined(sprop->setterObject());
}
pobj->dropProperty(cx, prop);
}
@@ -1802,15 +1802,15 @@ js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp)
return false;
}
Value roots[] = { UndefinedValue(), UndefinedValue() };
CopyableValue roots[2] = { UndefinedTag(), UndefinedTag() };
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots);
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
if (obj->isNative()) {
JSScopeProperty *sprop = reinterpret_cast<JSScopeProperty *>(prop);
if (attrs & JSPROP_GETTER)
roots[0].copy(sprop->getterValue());
roots[0].setFunObjOrUndefined(sprop->getterObject());
if (attrs & JSPROP_SETTER)
roots[1].copy(sprop->setterValue());
roots[1].setFunObjOrUndefined(sprop->setterObject());
}
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);
if (!desc)
return false;
SetObject(vp, *desc); /* Root and return. */
vp->setObject(*desc); /* Root and return. */
const JSAtomState &atomState = cx->runtime->atomState;
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
@@ -1934,9 +1934,9 @@ HasProperty(JSContext* cx, JSObject* obj, jsid id, Value* vp, JSBool* answerp)
PropertyDescriptor::PropertyDescriptor()
: id(INT_TO_JSID(0)),
value(UndefinedValue()),
get(UndefinedValue()),
set(UndefinedValue()),
value(UndefinedTag()),
get(UndefinedTag()),
set(UndefinedTag()),
attrs(0),
hasGet(false),
hasSet(false),
@@ -2142,14 +2142,12 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &d
break;
if (desc.hasGet &&
!SameValue(cx, desc.getterValue(),
sprop->hasGetterValue() ? sprop->getterValue() : UndefinedValue())) {
!SameValue(cx, desc.getterValue(), sprop->getterOrUndefined())) {
break;
}
if (desc.hasSet &&
!SameValue(cx, desc.setterValue(),
sprop->hasSetterValue() ? sprop->setterValue() : UndefinedValue())) {
!SameValue(cx, desc.setterValue(), sprop->setterOrUndefined())) {
break;
}
} else {
@@ -2261,11 +2259,9 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &d
JS_ASSERT(desc.isAccessorDescriptor() && sprop->isAccessorDescriptor());
if (!sprop->configurable()) {
if ((desc.hasSet &&
!SameValue(cx, desc.setterValue(),
sprop->hasSetterValue() ? sprop->setterValue() : UndefinedValue())) ||
!SameValue(cx, desc.setterValue(), sprop->setterOrUndefined())) ||
(desc.hasGet &&
!SameValue(cx, desc.getterValue(),
sprop->hasGetterValue() ? sprop->getterValue() : UndefinedValue()))) {
!SameValue(cx, desc.getterValue(), sprop->getterOrUndefined()))) {
return Reject(cx, obj2, current, JSMSG_CANT_REDEFINE_UNCONFIGURABLE_PROP,
throwError, desc.id, rval);
}
@@ -3028,7 +3024,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSStackFrame *fp)
/* The caller sets parent on its own. */
Value priv;
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]);
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) {
named = JS_FALSE;
} else {
named = obj->defineProperty(cx, ATOM_TO_JSID(atom), ToValue(proto),
named = obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectOrNullTag(proto),
PropertyStub, PropertyStub,
(clasp->flags & JSCLASS_IS_ANONYMOUS)
? JSPROP_READONLY | JSPROP_PERMANENT
@@ -3410,7 +3406,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
ctor = FUN_OBJECT(fun);
if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
Value rval;
if (!InternalConstruct(cx, proto, ToValue(ctor), 0, NULL, &rval))
if (!InternalConstruct(cx, proto, ObjectOrNullTag(ctor), 0, NULL, &rval))
goto bad;
if (rval.isObject() && &rval.asObject() != proto)
proto = &rval.asObject();
@@ -3424,7 +3420,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
/* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
if (ctor->getClass() == clasp)
ctor->setProto(ToObjPtr(proto));
ctor->setProto(ObjectOrNullTag(proto));
}
/* 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))
return JS_TRUE;
return js_SetReservedSlot(cx, obj, key, ToValue(cobj));
return js_SetReservedSlot(cx, obj, key, ObjectOrNullTag(cobj));
}
JSBool
@@ -3709,7 +3705,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
if (!js_GetClassObject(cx, obj, protoKey, &cobj))
return JS_FALSE;
if (cobj) {
SetObject(vp, *cobj);
vp->setObject(*cobj);
return JS_TRUE;
}
id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[protoKey]);
@@ -4588,7 +4584,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
return true;
if (JS_UNLIKELY(sprop->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER)) {
JS_ASSERT(sprop->methodValue().isSame(*vp));
JS_ASSERT(&sprop->methodFunObj() == &vp->asFunObj());
return true;
}
@@ -5204,7 +5200,7 @@ JSBool
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
{
Value v;
SetObject(&v, obj);
v.setObject(*obj);
if (hint == JSTYPE_STRING) {
JS_ASSERT(hint != JSTYPE_OBJECT && hint != JSTYPE_FUNCTION);
@@ -5281,7 +5277,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
} else {
str = NULL;
}
SetObject(vp, *obj);
vp->setObject(*obj);
js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,
JSDVG_SEARCH_STACK, *vp, str,
(hint == JSTYPE_VOID)
@@ -5556,7 +5552,7 @@ js_HasInstance(JSContext *cx, JSObject *obj, const Value *vp, JSBool *bp)
}
#endif
js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
JSDVG_SEARCH_STACK, ToValue(*obj), NULL);
JSDVG_SEARCH_STACK, ObjectTag(*obj), NULL);
return JS_FALSE;
}
@@ -5682,7 +5678,7 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs
* DontDelete.
*/
if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom),
ToValue(proto), PropertyStub, PropertyStub, attrs)) {
ObjectOrNullTag(proto), PropertyStub, PropertyStub, attrs)) {
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.
*/
return proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
ToValue(ctor), CheckCtorGetAccess, CheckCtorSetAccess, 0);
ObjectOrNullTag(ctor), CheckCtorGetAccess, CheckCtorSetAccess, 0);
}
JSBool
@@ -6375,11 +6371,11 @@ DumpObject(JSObject *obj)
}
fprintf(stderr, "proto ");
dumpValue(ToValue(obj->getProto()));
dumpValue(obj->getProtoValue());
fputc('\n', stderr);
fprintf(stderr, "parent ");
dumpValue(ToValue(obj->getParent()));
dumpValue(obj->getParentValue());
fputc('\n', stderr);
i = JSSLOT_PRIVATE;
@@ -6409,7 +6405,7 @@ MaybeDumpObject(const char *name, JSObject *obj)
{
if (obj) {
fprintf(stderr, " %s: ", name);
dumpValue(ToValue(*obj));
dumpValue(ObjectTag(*obj));
fputc('\n', stderr);
}
}

View File

@@ -1292,21 +1292,4 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
JSBool
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___ */

View File

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

View File

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

View File

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