[JAEGER] Merge from fatval.

This commit is contained in:
David Anderson 2010-06-30 11:46:07 -07:00
commit 9c55bbcdbc
45 changed files with 704 additions and 721 deletions

View File

@ -1106,7 +1106,7 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
goto out;
}
obj->defineProperty(cx, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
FunObjTag(*ctor), 0, 0, 0);
ObjectTag(*ctor), 0, 0, 0);
}
/* Initialize the object class next so Object.prototype works. */
@ -1122,9 +1122,9 @@ js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
}
/* Function.prototype and the global object delegate to Object.prototype. */
fun_proto->setProto(NonFunObjTag(*obj_proto));
fun_proto->setProto(ObjectTag(*obj_proto));
if (!obj->getProto())
obj->setProto(NonFunObjTag(*obj_proto));
obj->setProto(ObjectTag(*obj_proto));
out:
/* If resolving, remove the other entry (Object or Function) from table. */
@ -1905,7 +1905,7 @@ JS_TraceRuntime(JSTracer *trc)
JS_PUBLIC_API(void)
JS_CallTracer(JSTracer *trc, void *thing, uint32 kind)
{
MarkRaw(trc, thing, kind);
Mark(trc, thing, kind);
}
#ifdef DEBUG
@ -2714,12 +2714,13 @@ JS_GetConstructor(JSContext *cx, JSObject *proto)
if (!proto->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.constructorAtom), &cval))
return NULL;
}
if (!cval.isFunObj()) {
JSObject *funobj;
if (!IsFunctionObject(cval, &funobj)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
proto->getClass()->name);
return NULL;
}
return &cval.asFunObj();
return &cval.asObject();
}
JS_PUBLIC_API(JSBool)
@ -2881,7 +2882,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id,
if (sprop->isMethod()) {
AutoScopePropertyRooter root(cx, sprop);
JS_UNLOCK_OBJ(cx, obj2);
vp->setFunObj(sprop->methodFunObj());
vp->setObject(sprop->methodObject());
return obj2->scope()->methodReadBarrier(cx, sprop, vp);
}
@ -3296,7 +3297,7 @@ GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (sprop->isMethod()) {
desc->getter = desc->setter = PropertyStub;
desc->value.setFunObj(sprop->methodFunObj());
desc->value.setObject(sprop->methodObject());
} else {
desc->getter = sprop->getter();
desc->setter = sprop->setter();
@ -4381,7 +4382,7 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
}
if (obj && funAtom &&
!obj->defineProperty(cx, ATOM_TO_JSID(funAtom), fun->funObjVal(),
!obj->defineProperty(cx, ATOM_TO_JSID(funAtom), ObjectTag(*fun),
NULL, NULL, JSPROP_ENUMERATE)) {
fun = NULL;
}
@ -4558,8 +4559,7 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, jsval
JSBool ok;
CHECK_REQUEST(cx);
ok = InternalCall(cx, obj, fun->funObjVal(), argc, Valueify(argv),
Valueify(rval));
ok = InternalCall(cx, obj, ObjectTag(*fun), argc, Valueify(argv), Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}

View File

@ -193,11 +193,9 @@ JSVAL_TO_OBJECT(jsval v)
static JS_ALWAYS_INLINE jsval
OBJECT_TO_JSVAL(JSObject *obj)
{
JSValueType type;
if (!obj)
return JSVAL_NULL;
type = JS_OBJ_IS_FUN_IMPL(obj) ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(type, obj));
if (obj)
return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(obj));
return JSVAL_NULL;
}
static JS_ALWAYS_INLINE JSBool
@ -1357,7 +1355,9 @@ JS_MarkGCThing(JSContext *cx, jsval v, const char *name, void *arg);
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_TRACEABLE(jsval v)
{
return JSVAL_IS_GCTHING(v);
jsval_layout l;
l.asBits = JSVAL_BITS(v);
return JSVAL_IS_TRACEABLE_IMPL(l);
}
static JS_ALWAYS_INLINE void *
@ -3133,26 +3133,6 @@ struct StringTag {
JSString *str;
};
struct FunObjTag {
explicit FunObjTag(JSObject &obj) : obj(obj) {}
JSObject &obj;
};
struct FunObjOrNull {
explicit FunObjOrNull(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct NonFunObjTag {
explicit NonFunObjTag(JSObject &obj) : obj(obj) {}
JSObject &obj;
};
struct NonFunObjOrNullTag {
explicit NonFunObjOrNullTag(JSObject *obj) : obj(obj) {}
JSObject *obj;
};
struct ObjectTag {
explicit ObjectTag(JSObject &obj) : obj(obj) {}
JSObject &obj;
@ -3208,24 +3188,20 @@ class Value
/* Construct a Value of a single type */
Value(NullTag) { setNull(); }
Value(UndefinedTag) { setUndefined(); }
Value(Int32Tag arg) { setInt32(arg.i32); }
Value(DoubleTag arg) { setDouble(arg.dbl); }
Value(StringTag arg) { setString(arg.str); }
Value(FunObjTag arg) { setFunObj(arg.obj); }
Value(NonFunObjTag arg) { setNonFunObj(arg.obj); }
Value(BooleanTag arg) { setBoolean(arg.boo); }
Value(JSWhyMagic arg) { setMagic(arg); }
Value(NullTag) { setNull(); }
Value(UndefinedTag) { setUndefined(); }
Value(Int32Tag arg) { setInt32(arg.i32); }
Value(DoubleTag arg) { setDouble(arg.dbl); }
Value(StringTag arg) { setString(arg.str); }
Value(BooleanTag arg) { setBoolean(arg.boo); }
Value(ObjectTag arg) { setObject(arg.obj); }
Value(JSWhyMagic arg) { setMagic(arg); }
/* Construct a Value of a type dynamically chosen from a set of types */
Value(FunObjOrNull arg) { setFunObjOrNull(arg.obj); }
Value(NonFunObjOrNullTag arg) { setNonFunObjOrNull(arg.obj); }
inline Value(NumberTag arg);
inline Value(ObjectTag arg) { setObject(arg.obj); }
inline Value(ObjectOrNullTag arg) { setObjectOrNull(arg.obj); }
inline Value(ObjectOrUndefinedTag arg) { setObjectOrUndefined(arg.obj); }
Value(ObjectOrNullTag arg) { setObjectOrNull(arg.obj); }
Value(ObjectOrUndefinedTag arg) { setObjectOrUndefined(arg.obj); }
/* Change to a Value of a single type */
@ -3259,14 +3235,8 @@ class Value
data = STRING_TO_JSVAL_IMPL(str);
}
void setFunObj(JSObject &arg) {
JS_ASSERT(JS_OBJ_IS_FUN_IMPL(&arg));
data = OBJECT_TO_JSVAL_IMPL(JSVAL_TYPE_FUNOBJ, &arg);
}
void setNonFunObj(JSObject &arg) {
JS_ASSERT(!JS_OBJ_IS_FUN_IMPL(&arg));
data = OBJECT_TO_JSVAL_IMPL(JSVAL_TYPE_NONFUNOBJ, &arg);
void setObject(JSObject &obj) {
data = OBJECT_TO_JSVAL_IMPL(&obj);
}
void setBoolean(bool b) {
@ -3288,29 +3258,11 @@ class Value
inline void setNumber(double d);
void setFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, JS_OBJ_IS_FUN_IMPL(arg));
JSValueType type = arg ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NULL;
data = OBJECT_TO_JSVAL_IMPL(type, arg);
}
void setNonFunObjOrNull(JSObject *arg) {
JS_ASSERT_IF(arg, !JS_OBJ_IS_FUN_IMPL(arg));
JSValueType type = arg ? JSVAL_TYPE_NONFUNOBJ : JSVAL_TYPE_NULL;
data = OBJECT_TO_JSVAL_IMPL(type, arg);
}
inline void setObject(JSObject &arg) {
JSValueType type = JS_OBJ_IS_FUN_IMPL(&arg) ? JSVAL_TYPE_FUNOBJ
: JSVAL_TYPE_NONFUNOBJ;
data = OBJECT_TO_JSVAL_IMPL(type, &arg);
}
inline void setObjectOrNull(JSObject *arg) {
JSValueType type = arg ? JS_OBJ_IS_FUN_IMPL(arg) ? JSVAL_TYPE_FUNOBJ
: JSVAL_TYPE_NONFUNOBJ
: JSVAL_TYPE_NULL;
data = OBJECT_TO_JSVAL_IMPL(type, arg);
if (arg)
setObject(*arg);
else
setNull();
}
inline void setObjectOrUndefined(JSObject *arg) {
@ -3354,14 +3306,6 @@ class Value
return JSVAL_IS_STRING_IMPL(data);
}
bool isNonFunObj() const {
return JSVAL_IS_NONFUNOBJ_IMPL(data);
}
bool isFunObj() const {
return JSVAL_IS_FUNOBJ_IMPL(data);
}
bool isObject() const {
return JSVAL_IS_OBJECT_IMPL(data);
}
@ -3399,8 +3343,12 @@ class Value
return JSVAL_IS_MAGIC_IMPL(data);
}
int32 traceKind() const {
JS_ASSERT(isGCThing());
bool isMarkable() const {
return JSVAL_IS_TRACEABLE_IMPL(data);
}
int32 gcKind() const {
JS_ASSERT(isMarkable());
return JSVAL_TRACE_KIND_IMPL(data);
}
@ -3421,8 +3369,8 @@ class Value
return data.asBits != rhs.data.asBits;
}
friend bool SamePrimitiveTypeOrBothObjects(const Value &lhs, const Value &rhs) {
return JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(lhs.data, rhs.data);
friend bool SameType(const Value &lhs, const Value &rhs) {
return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
}
/* Extract a Value's payload */
@ -3447,16 +3395,6 @@ class Value
return JSVAL_TO_STRING_IMPL(data);
}
JSObject &asNonFunObj() const {
JS_ASSERT(isNonFunObj());
return *JSVAL_TO_OBJECT_IMPL(data);
}
JSObject &asFunObj() const {
JS_ASSERT(isFunObj());
return *JSVAL_TO_OBJECT_IMPL(data);
}
JSObject &asObject() const {
JS_ASSERT(isObject());
JS_ASSERT(JSVAL_TO_OBJECT_IMPL(data));
@ -3487,12 +3425,12 @@ class Value
return data.asBits;
}
JSValueType extractNonDoubleType() const {
return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
JSValueType extractNonDoubleObjectType() const {
return JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TYPE_IMPL(data);
}
JSValueTag extractNonDoubleTag() const {
return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
JSValueTag extractNonDoubleObjectTag() const {
return JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TAG_IMPL(data);
}
void unboxNonDoubleTo(uint64 *out) const {

View File

@ -2347,7 +2347,7 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
JSObject *obj2 = js_NewArrayObject(cx, 0, NULL);
if (!obj2)
return JS_FALSE;
vp->setNonFunObj(*obj2);
vp->setObject(*obj2);
/* Nothing to do if no args. Otherwise get length. */
if (argc == 0)
@ -2511,7 +2511,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
if (!nobj)
return JS_FALSE;
nobj->setDenseArrayLength(length);
vp->setNonFunObj(*nobj);
vp->setObject(*nobj);
if (argc == 0)
return JS_TRUE;
argc--;
@ -2520,7 +2520,7 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
nobj = js_NewArrayObject(cx, 0, NULL);
if (!nobj)
return JS_FALSE;
vp->setNonFunObj(*nobj);
vp->setObject(*nobj);
length = 0;
}
@ -2626,7 +2626,7 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
obj->getDenseArrayCount() != obj->getArrayLength());
if (!nobj)
return JS_FALSE;
vp->setNonFunObj(*nobj);
vp->setObject(*nobj);
return JS_TRUE;
}
@ -2634,7 +2634,7 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
nobj = js_NewArrayObject(cx, 0, NULL);
if (!nobj)
return JS_FALSE;
vp->setNonFunObj(*nobj);
vp->setObject(*nobj);
AutoValueRooter tvr(cx);
for (slot = begin; slot < end; slot++) {
@ -2811,7 +2811,7 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
newarr = js_NewArrayObject(cx, newlen, NULL);
if (!newarr)
return JS_FALSE;
vp->setNonFunObj(*newarr);
vp->setObject(*newarr);
break;
case SOME:
vp->setBoolean(false);
@ -3038,7 +3038,7 @@ js_Array(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
obj = NewObject(cx, &js_ArrayClass, NULL, NULL);
if (!obj)
return JS_FALSE;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
if (argc == 0) {
@ -3071,7 +3071,7 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
/* Initialize all fields of JSObject. */
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
obj->init(&js_ArrayClass, NonFunObjTag(*proto), proto->getParentValue(), NullTag());
obj->init(&js_ArrayClass, ObjectTag(*proto), proto->getParentValue(), NullTag());
obj->setDenseArrayLength(0);
obj->setDenseArrayCount(0);
return obj;

View File

@ -488,7 +488,7 @@ js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT;
}
JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
MarkRaw(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
Mark(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
return JS_DHASH_NEXT;
}
@ -506,7 +506,7 @@ js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
? "pinned_atom"
: "interned_atom",
(size_t)number);
MarkRaw(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
Mark(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
}
return JS_DHASH_NEXT;
}

View File

@ -297,22 +297,11 @@ JS_DEFINE_CALLINFO_3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, IN
JSString* FASTCALL
js_TypeOfObject(JSContext* cx, JSObject* obj)
{
if (!obj)
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_OBJECT]);
JS_ASSERT(obj);
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[obj->typeOf(cx)]);
}
JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, ACC_NONE)
JSString* FASTCALL
js_TypeOfBoolean(JSContext* cx, int32 unboxed)
{
JS_ASSERT(unboxed == JS_FALSE || unboxed == JS_TRUE);
jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
JSType type = JS_TypeOfValue(cx, boxed);
return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
}
JS_DEFINE_CALLINFO_2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, ACC_NONE)
JSString* FASTCALL
js_BooleanIntToString(JSContext *cx, int32 unboxed)
{

View File

@ -566,7 +566,6 @@ JS_DECLARE_CALLINFO(js_AddAtomProperty)
JS_DECLARE_CALLINFO(js_HasNamedProperty)
JS_DECLARE_CALLINFO(js_HasNamedPropertyInt32)
JS_DECLARE_CALLINFO(js_TypeOfObject)
JS_DECLARE_CALLINFO(js_TypeOfBoolean)
JS_DECLARE_CALLINFO(js_BooleanIntToString)
JS_DECLARE_CALLINFO(js_NewNullClosure)
JS_DECLARE_CALLINFO(js_PopInterpFrame)

View File

@ -2090,8 +2090,8 @@ js_ReportMissingArg(JSContext *cx, const Value &v, uintN arg)
JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
bytes = NULL;
if (v.isFunObj()) {
atom = GET_FUNCTION_PRIVATE(cx, &v.asFunObj())->atom;
if (IsFunctionObject(v)) {
atom = GET_FUNCTION_PRIVATE(cx, &v.asObject())->atom;
bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
v, ATOM_TO_STRING(atom));
if (!bytes)

View File

@ -1337,7 +1337,7 @@ js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
{
js_PushStatement(tc, stmt, STMT_BLOCK, top);
stmt->flags |= SIF_SCOPE;
blockObj->setParent(NonFunObjOrNullTag(tc->blockChain));
blockObj->setParent(ObjectOrNullTag(tc->blockChain));
stmt->downScope = tc->topScopeStmt;
tc->topScopeStmt = stmt;
tc->blockChain = blockObj;

View File

@ -709,7 +709,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
obj = NewObject(cx, &js_ErrorClass, &rval->asObject(), NULL);
if (!obj)
return JS_FALSE;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
/*

View File

@ -109,7 +109,7 @@ js_GetArgsValue(JSContext *cx, JSStackFrame *fp, Value *vp)
argsobj = js_GetArgsObject(cx, fp);
if (!argsobj)
return JS_FALSE;
vp->setNonFunObj(*argsobj);
vp->setObject(*argsobj);
return JS_TRUE;
}
@ -176,7 +176,7 @@ 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, NonFunObjTag(*proto), NonFunObjTag(*parent), PrivateTag(NULL));
argsobj->init(&js_ArgumentsClass, ObjectTag(*proto), ObjectTag(*parent), PrivateTag(NULL));
argsobj->setArgsCallee(ObjectOrNullTag(callee));
argsobj->setArgsLength(argc);
@ -731,8 +731,8 @@ CheckForEscapingClosure(JSContext *cx, JSObject *obj, Value *vp)
const Value &v = *vp;
if (v.isFunObj()) {
JSObject *funobj = &v.asFunObj();
JSObject *funobj;
if (IsFunctionObject(v, &funobj)) {
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
/*
@ -749,7 +749,7 @@ CheckForEscapingClosure(JSContext *cx, JSObject *obj, Value *vp)
JSObject *wrapper = WrapEscapingClosure(cx, fp, funobj, fun);
if (!wrapper)
return false;
vp->setFunObj(*wrapper);
vp->setObject(*wrapper);
return true;
}
@ -775,7 +775,7 @@ NewCallObject(JSContext *cx, JSFunction *fun, JSObject *scopeChain)
return NULL;
/* Init immediately to avoid GC seeing a half-init'ed object. */
callobj->init(&js_CallClass, NullTag(), NonFunObjTag(*scopeChain), PrivateTag(NULL));
callobj->init(&js_CallClass, NullTag(), ObjectTag(*scopeChain), PrivateTag(NULL));
callobj->map = cx->runtime->emptyCallScope->hold();
@ -856,7 +856,7 @@ js_CreateCallObjectOnTrace(JSContext *cx, JSFunction *fun, JSObject *callee, JSO
JSObject *callobj = NewCallObject(cx, fun, scopeChain);
if (!callobj)
return NULL;
callobj->setSlot(JSSLOT_CALLEE, FunObjTag(*callee));
callobj->setSlot(JSSLOT_CALLEE, ObjectTag(*callee));
return callobj;
}
@ -1046,7 +1046,7 @@ CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, Value *vp,
argsobj = js_GetArgsObject(cx, fp);
if (!argsobj)
return false;
vp->setNonFunObj(*argsobj);
vp->setObject(*argsobj);
} else {
*vp = obj->getSlot(JSSLOT_CALL_ARGUMENTS);
}
@ -1177,7 +1177,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
const Value &callee = obj->getSlot(JSSLOT_CALLEE);
if (callee.isUndefined())
return JS_TRUE;
fun = GET_FUNCTION_PRIVATE(cx, &callee.asFunObj());
fun = GET_FUNCTION_PRIVATE(cx, &callee.asObject());
/*
* Check whether the id refers to a formal parameter, local variable or
@ -1229,8 +1229,9 @@ call_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
Value v;
if (!CallPropertyOp(cx, obj, INT_TO_JSID((int16)slot), &v, cpkind))
return JS_FALSE;
if (v.isFunObj() &&
GET_FUNCTION_PRIVATE(cx, &v.asFunObj())->needsWrapper()) {
JSObject *funobj;
if (IsFunctionObject(v, &funobj) &&
GET_FUNCTION_PRIVATE(cx, funobj)->needsWrapper()) {
getter = js_GetCallVarChecked;
}
}
@ -1271,7 +1272,7 @@ call_reserveSlots(JSContext *cx, JSObject *obj)
return fun->countArgsAndVars();
}
JS_FRIEND_DATA(Class) js_CallClass = {
JS_PUBLIC_DATA(Class) js_CallClass = {
"Call",
JSCLASS_HAS_PRIVATE |
JSCLASS_HAS_RESERVED_SLOTS(CALL_CLASS_FIXED_RESERVED_SLOTS) |
@ -1382,7 +1383,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
JSObject *wrapper = WrapEscapingClosure(cx, fp->down, FUN_OBJECT(caller), caller);
if (!wrapper)
return JS_FALSE;
vp->setFunObj(*wrapper);
vp->setObject(*wrapper);
return JS_TRUE;
}
@ -1824,7 +1825,7 @@ fun_reserveSlots(JSContext *cx, JSObject *obj)
* does not bloat every instance, only those on which reserved slots are set,
* and those on which ad-hoc properties are defined.
*/
JS_FRIEND_DATA(Class) js_FunctionClass = {
JS_PUBLIC_DATA(Class) js_FunctionClass = {
js_Function_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
@ -1845,7 +1846,8 @@ fun_toStringHelper(JSContext *cx, uint32_t indent, uintN argc, Value *vp)
return JS_FALSE;
Value fval = vp[1];
if (!fval.isFunObj()) {
JSObject *obj;
if (!IsFunctionObject(fval, &obj)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
js_Function_str, js_toString_str,
@ -1853,7 +1855,6 @@ fun_toStringHelper(JSContext *cx, uint32_t indent, uintN argc, Value *vp)
return JS_FALSE;
}
JSObject *obj = &fval.asFunObj();
if (argc != 0) {
if (!ValueToECMAUint32(cx, vp[2], &indent))
return JS_FALSE;
@ -2123,7 +2124,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
obj = NewObject(cx, &js_FunctionClass, NULL, NULL);
if (!obj)
return JS_FALSE;
rval->setFunObj(*obj);
rval->setObject(*obj);
} else {
/*
* The constructor is called before the private slot is initialized so
@ -2523,7 +2524,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), fun->funObjVal(),
if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectTag(*fun),
gsop, gsop, attrs & ~JSFUN_FLAGS_MASK)) {
return NULL;
}
@ -2537,11 +2538,12 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, Native native,
JSFunction *
js_ValueToFunction(JSContext *cx, const Value *vp, uintN flags)
{
if (!vp->isFunObj()) {
JSObject *funobj;
if (!IsFunctionObject(*vp, &funobj)) {
js_ReportIsNotFunction(cx, vp, flags);
return NULL;
}
return GET_FUNCTION_PRIVATE(cx, &vp->asObject());
return GET_FUNCTION_PRIVATE(cx, funobj);
}
JSObject *
@ -2551,13 +2553,14 @@ js_ValueToFunctionObject(JSContext *cx, Value *vp, uintN flags)
JSStackFrame *caller;
JSPrincipals *principals;
if (vp->isFunObj())
return &vp->asFunObj();
JSObject *funobj;
if (IsFunctionObject(*vp, &funobj))
return funobj;
fun = js_ValueToFunction(cx, vp, flags);
if (!fun)
return NULL;
vp->setFunObj(*FUN_OBJECT(fun));
vp->setObject(*fun);
caller = js_GetScriptedCaller(cx, NULL);
if (caller) {
@ -2963,7 +2966,7 @@ trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
JS_SET_TRACING_INDEX(trc,
entry->localKind == JSLOCAL_ARG ? "arg" : "var",
entry->index);
MarkRaw(trc, ATOM_TO_STRING(entry->name), JSTRACE_STRING);
Mark(trc, ATOM_TO_STRING(entry->name), JSTRACE_STRING);
return JS_DHASH_NEXT;
}
@ -2988,7 +2991,7 @@ TraceLocalNames(JSTracer *trc, JSFunction *fun)
JS_SET_TRACING_INDEX(trc,
i < fun->nargs ? "arg" : "var",
i < fun->nargs ? i : i - fun->nargs);
MarkRaw(trc, ATOM_TO_STRING(atom), JSTRACE_STRING);
Mark(trc, ATOM_TO_STRING(atom), JSTRACE_STRING);
}
} while (i != 0);
} else {

View File

@ -202,10 +202,6 @@ 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);
}
};
JS_STATIC_ASSERT(sizeof(JSFunction) % JS_GCTHING_ALIGN == 0);
@ -246,9 +242,9 @@ JSObject::isArguments() const
return getClass() == &js_ArgumentsClass;
}
extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern js::Class js_DeclEnvClass;
extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
extern JS_PUBLIC_DATA(js::Class) js_CallClass;
extern JS_PUBLIC_DATA(js::Class) js_FunctionClass;
inline bool
JSObject::isFunction() const
@ -256,7 +252,25 @@ JSObject::isFunction() const
return getClass() == &js_FunctionClass;
}
#define VALUE_IS_FUNCTION(cx, v) (Valueify(v).isFunObj())
extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
/*
* NB: jsapi.h and jsobj.h must be included before any call to this macro.
*/
#define VALUE_IS_FUNCTION(cx, v) \
(!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction())
static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v)
{
return v.isObject() && v.asObject().isFunction();
}
static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v, JSObject **funobj)
{
return v.isObject() && (*funobj = &v.asObject())->isFunction();
}
/*
* Macro to access the private slot of the function object after the slot is

View File

@ -1765,7 +1765,7 @@ MarkDelayedChildren(JSTracer *trc)
namespace js {
void
MarkRaw(JSTracer *trc, void *thing, uint32 kind)
Mark(JSTracer *trc, void *thing, uint32 kind)
{
JSContext *cx;
JSRuntime *rt;
@ -1853,7 +1853,7 @@ MarkRaw(JSTracer *trc, void *thing, uint32 kind)
}
void
MarkGCThingRaw(JSTracer *trc, void *thing)
MarkGCThing(JSTracer *trc, void *thing)
{
JS_ASSERT(size_t(thing) % JS_GCTHING_ALIGN == 0);
@ -1861,7 +1861,7 @@ MarkGCThingRaw(JSTracer *trc, void *thing)
return;
uint32 kind = js_GetGCThingTraceKind(thing);
MarkRaw(trc, thing, kind);
Mark(trc, thing, kind);
}
} /* namespace js */
@ -1909,7 +1909,7 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry)
#endif
JS_SET_TRACING_NAME(trc, entry.value.name ? entry.value.name : "root");
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
MarkGCThingRaw(trc, *reinterpret_cast<void **>(entry.key));
MarkGCThing(trc, *reinterpret_cast<void **>(entry.key));
else
MarkValueRaw(trc, *reinterpret_cast<Value *>(entry.key));
}

View File

@ -461,20 +461,20 @@ namespace js {
/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */
void
MarkRaw(JSTracer *trc, void *thing, uint32 kind);
Mark(JSTracer *trc, void *thing, uint32 kind);
static inline void
Mark(JSTracer *trc, void *thing, uint32 kind, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkRaw(trc, thing, kind);
Mark(trc, thing, kind);
}
static inline void
MarkString(JSTracer *trc, JSString *str, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkRaw(trc, str, JSTRACE_STRING);
Mark(trc, str, JSTRACE_STRING);
}
static inline void
@ -496,7 +496,7 @@ static inline void
MarkObject(JSTracer *trc, JSObject *obj, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkRaw(trc, obj, JSTRACE_OBJECT);
Mark(trc, obj, JSTRACE_OBJECT);
}
static inline void
@ -512,8 +512,8 @@ MarkObjectRange(JSTracer *trc, size_t len, JSObject **vec, const char *name)
static inline void
MarkValueRaw(JSTracer *trc, const js::Value &v)
{
if (v.isGCThing())
return MarkRaw(trc, v.asGCThing(), v.traceKind());
if (v.isMarkable())
return Mark(trc, v.asGCThing(), v.gcKind());
}
static inline void
@ -562,20 +562,20 @@ MarkIdRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */
void
MarkGCThingRaw(JSTracer *trc, void *thing);
MarkGCThing(JSTracer *trc, void *thing);
static inline void
MarkGCThing(JSTracer *trc, void *thing, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkGCThingRaw(trc, thing);
MarkGCThing(trc, thing);
}
static inline void
MarkGCThing(JSTracer *trc, void *thing, const char *name, size_t index)
{
JS_SET_TRACING_INDEX(trc, name, index);
MarkGCThingRaw(trc, thing);
MarkGCThing(trc, thing);
}
JSCompartment *

View File

@ -207,7 +207,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
if (!clone)
return NULL;
newChild->setParent(NonFunObjTag(*clone));
newChild->setParent(ObjectTag(*clone));
newChild = clone;
}
newChild->setParent(fp->scopeChain);
@ -353,7 +353,7 @@ js_OnUnknownMethod(JSContext *cx, Value *vp)
return false;
obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.value();
obj->fslots[JSSLOT_SAVED_ID] = vp[0];
vp[0].setNonFunObj(*obj);
vp[0].setObject(*obj);
}
return true;
}
@ -377,7 +377,7 @@ NoSuchMethod(JSContext *cx, uintN argc, Value *vp, uint32 flags)
JSObject *argsobj = js_NewArrayObject(cx, argc, vp + 2);
if (!argsobj)
return JS_FALSE;
invokevp[3].setNonFunObj(*argsobj);
invokevp[3].setObject(*argsobj);
JSBool ok = (flags & JSINVOKE_CONSTRUCT)
? InvokeConstructor(cx, args, JS_TRUE)
: Invoke(cx, args, flags);
@ -984,7 +984,7 @@ CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
Value value;
if (!obj->getProperty(cx, id, &value))
return JS_FALSE;
isFunction = value.isFunObj();
isFunction = IsFunctionObject(value);
}
}
@ -1019,7 +1019,7 @@ bool
StrictlyEqual(JSContext *cx, const Value &lref, const Value &rref)
{
Value lval = lref, rval = rref;
if (SamePrimitiveTypeOrBothObjects(lval, rval)) {
if (SameType(lval, rval)) {
if (lval.isString())
return js_EqualStrings(lval.asString(), rval.asString());
if (lval.isDouble())
@ -1107,11 +1107,12 @@ JS_REQUIRES_STACK bool
InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn)
{
JSFunction *fun = NULL;
JSObject *obj2 = NULL;
Value *vp = args.getvp();
/* XXX clean up to avoid special cases above ObjectOps layer */
if (vp->isPrimitive() || vp->isFunObj() ||
!vp->asNonFunObj().map->ops->construct)
if (vp->isPrimitive() || (obj2 = &vp->asObject())->isFunction() ||
!obj2->map->ops->construct)
{
fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT);
if (!fun)
@ -1757,8 +1758,6 @@ namespace reprmeter {
#define PUSH_DOUBLE(d) regs.sp++->setDouble(d)
#define PUSH_INT32(i) regs.sp++->setInt32(i)
#define PUSH_STRING(s) regs.sp++->setString(s)
#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++->setObjectOrNull(obj)
#define PUSH_HOLE() regs.sp++->setMagic(JS_ARRAY_HOLE)
@ -1930,7 +1929,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->methodFunObj() == &pobj->lockedGetSlot(sprop->slot).asFunObj());
&sprop->methodObject() == &pobj->lockedGetSlot(sprop->slot).asObject());
} else {
Value v;
JS_ASSERT(entry->vword.isFunObj());
@ -1939,11 +1938,11 @@ AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
JS_ASSERT(sprop->hasDefaultGetterOrIsMethod());
JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, pobj->scope()));
v = pobj->lockedGetSlot(sprop->slot);
JS_ASSERT(&entry->vword.toFunObj() == &v.asFunObj());
JS_ASSERT(&entry->vword.toFunObj() == &v.asObject());
if (sprop->isMethod()) {
JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_CALLOP);
JS_ASSERT(&sprop->methodFunObj() == &v.asFunObj());
JS_ASSERT(&sprop->methodObject() == &v.asObject());
}
}

View File

@ -174,7 +174,7 @@ struct JSStackFrame
if (callobj) {
js_PutCallObject(cx, this);
JS_ASSERT(argsval.isNull());
} else if (argsval.isNonFunObj()) {
} else if (argsval.isObject()) {
js_PutArgsObject(cx, this);
}
}
@ -208,10 +208,7 @@ struct JSStackFrame
}
void setArgsObj(JSObject *obj) {
if (obj)
argsval.setNonFunObj(*obj);
else
argsval.setNull();
argsval.setObjectOrNull(obj);
}
JSObject *scopeChainObj() {

View File

@ -147,7 +147,7 @@ NewKeyValuePair(JSContext *cx, jsid id, const Value &val, Value *rval)
JSObject *aobj = js_NewArrayObject(cx, 2, vec);
if (!aobj)
return false;
rval->setNonFunObj(*aobj);
rval->setObject(*aobj);
return true;
}
@ -539,7 +539,7 @@ JSIdArrayToIterator(JSContext *cx, JSObject *obj, uintN flags, JSIdArray *ida, V
if (!iterobj)
return false;
vp->setNonFunObj(*iterobj);
vp->setObject(*iterobj);
NativeIterator *ni = NativeIterator::allocateKeyIterator(cx, 0, ida->vector, ida->length);
if (!ni)
@ -593,7 +593,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
if (ni->shapes_key == key &&
ni->shapes_length == shapes.length() &&
Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
vp->setNonFunObj(*iterobj);
vp->setObject(*iterobj);
*hp = ni->next;
RegisterEnumerator(cx, iterobj, ni);
@ -616,7 +616,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
return false;
/* Store in *vp to protect it from GC (callers must root vp). */
vp->setNonFunObj(*iterobj);
vp->setObject(*iterobj);
NativeIterator *ni = (flags & JSITER_FOREACH)
? SnapshotValues(cx, obj, flags, shapes.begin(), shapes.length(), key)
@ -735,7 +735,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
JSObject *iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH));
if (!iterobj)
return false;
vp->setNonFunObj(*iterobj);
vp->setObject(*iterobj);
return true;
}
}

View File

@ -727,7 +727,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
* Remove '(function ' from the beginning of valstr and ')' from the
* end so that we can put "get" in front of the function definition.
*/
if (gsop[j] && val[j].isFunObj()) {
if (gsop[j] && IsFunctionObject(val[j])) {
JSFunction *fun = js_ValueToFunction(cx, &val[j], JSV2F_SEARCH_STACK);
const jschar *start = vchars;
const jschar *end = vchars + vlength;
@ -1887,13 +1887,13 @@ obj_keys(JSContext *cx, uintN argc, Value *vp)
JSObject *proto;
if (!js_GetClassPrototype(cx, NULL, JSProto_Array, &proto))
return JS_FALSE;
vp[1].setNonFunObj(*proto);
vp[1].setObject(*proto);
JS_ASSERT(ida.length() <= UINT32_MAX);
JSObject *aobj = js_NewArrayWithSlots(cx, proto, uint32(ida.length()));
if (!aobj)
return JS_FALSE;
vp->setNonFunObj(*aobj);
vp->setObject(*aobj);
size_t len = ida.length();
JS_ASSERT(aobj->getDenseArrayCapacity() >= len);
@ -2553,7 +2553,7 @@ obj_create(JSContext *cx, uintN argc, Value *vp)
NewObjectWithGivenProto(cx, &js_ObjectClass, v.asObjectOrNull(), JS_GetScopeChain(cx));
if (!obj)
return JS_FALSE;
vp->setNonFunObj(*obj); /* Root and prepare for eventual return. */
vp->setObject(*obj); /* Root and prepare for eventual return. */
/* 15.2.3.5 step 4. */
if (argc > 1 && !vp[3].isUndefined()) {
@ -2653,7 +2653,7 @@ js_Object(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
if (!nullobj)
return JS_FALSE;
rval->setNonFunObj(*nullobj);
rval->setObject(*nullobj);
return JS_TRUE;
}
@ -3063,7 +3063,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSStackFrame *fp)
Value privateValue = PrivateTag(js_FloatingFrameIfGenerator(cx, fp));
/* The caller sets parent on its own. */
clone->init(&js_BlockClass, NonFunObjTag(*proto), NullTag(), privateValue);
clone->init(&js_BlockClass, ObjectTag(*proto), NullTag(), privateValue);
clone->fslots[JSSLOT_BLOCK_DEPTH] = proto->fslots[JSSLOT_BLOCK_DEPTH];
JS_ASSERT(cx->runtime->emptyBlockScope->freeslot == JSSLOT_BLOCK_DEPTH + 1);
@ -3303,7 +3303,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
parent = NULL;
else
parent = xdr->script->getObject(parentId);
obj->setParent(NonFunObjOrNullTag(parent));
obj->setParent(ObjectOrNullTag(parent));
}
AutoObjectRooter tvr(cx, obj);
@ -3506,7 +3506,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
if (!fun)
goto bad;
AutoValueRooter tvr2(cx, FunObjTag(*fun));
AutoValueRooter tvr2(cx, ObjectTag(*fun));
if (!DefineStandardSlot(cx, obj, key, atom, tvr2.value(), 0, named))
goto bad;
@ -4253,11 +4253,11 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &valu
/* Add a new property, or replace an existing one of the same id. */
if (defineHow & JSDNP_SET_METHOD) {
JS_ASSERT(clasp == &js_ObjectClass);
JS_ASSERT(value.isFunObj());
JS_ASSERT(IsFunctionObject(value));
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JS_ASSERT(!getter && !setter);
JSObject *funobj = &value.asFunObj();
JSObject *funobj = &value.asObject();
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
flags |= JSScopeProperty::METHOD;
getter = CastAsPropertyOp(funobj);
@ -4718,7 +4718,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
return true;
if (JS_UNLIKELY(sprop->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER)) {
JS_ASSERT(&sprop->methodFunObj() == &vp->asFunObj());
JS_ASSERT(&sprop->methodObject() == &vp->asObject());
return true;
}
@ -5151,10 +5151,10 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
*/
if ((defineHow & JSDNP_SET_METHOD) &&
obj->getClass() == &js_ObjectClass) {
JS_ASSERT(vp->isFunObj());
JS_ASSERT(IsFunctionObject(*vp));
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JSObject *funobj = &vp->asFunObj();
JSObject *funobj = &vp->asObject();
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
flags |= JSScopeProperty::METHOD;
getter = CastAsPropertyOp(funobj);
@ -5349,8 +5349,8 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
if (sprop && sprop->hasDefaultGetter() && SPROP_HAS_VALID_SLOT(sprop, scope)) {
const Value &fval = pobj->lockedGetSlot(sprop->slot);
if (fval.isFunObj()) {
JSObject *funobj = &fval.asFunObj();
JSObject *funobj;
if (IsFunctionObject(fval, &funobj)) {
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
if (FUN_FAST_NATIVE(fun) == js_str_toString) {
@ -5722,8 +5722,8 @@ js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
Value v;
if (!js_FindClassObject(cx, scope, protoKey, &v, clasp))
return JS_FALSE;
if (v.isFunObj()) {
JSObject *ctor = &v.asFunObj();
JSObject *ctor;
if (IsFunctionObject(v, &ctor)) {
if (!ctor->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &v))
return JS_FALSE;
if (v.isObject()) {
@ -5818,7 +5818,7 @@ js_PrimitiveToObject(JSContext *cx, Value *vp)
return JS_FALSE;
obj->setPrimitiveThis(v);
vp->setNonFunObj(*obj);
vp->setObject(*obj);
return JS_TRUE;
}
@ -6351,21 +6351,21 @@ dumpValue(const Value &v)
fprintf(stderr, "%g", v.asDouble());
else if (v.isString())
dumpString(v.asString());
else if (v.isNonFunObj()) {
JSObject *obj = &v.asNonFunObj();
Class *cls = obj->getClass();
fprintf(stderr, "<%s%s at %p>",
cls->name,
cls == &js_ObjectClass ? "" : " object",
(void *) obj);
} else if (v.isFunObj()) {
JSObject *funobj = &v.asFunObj();
else if (v.isObject() && v.asObject().isFunction()) {
JSObject *funobj = &v.asObject();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
fprintf(stderr, "<%s %s at %p (JSFunction at %p)>",
fun->atom ? "function" : "unnamed",
fun->atom ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom)) : "function",
(void *) funobj,
(void *) fun);
} else if (v.isObject()) {
JSObject *obj = &v.asObject();
Class *cls = obj->getClass();
fprintf(stderr, "<%s%s at %p>",
cls->name,
cls == &js_ObjectClass ? "" : " object",
(void *) obj);
} else if (v.isBoolean()) {
if (v.asBoolean())
fprintf(stderr, "true");

View File

@ -739,7 +739,6 @@ struct JSObject {
};
JS_STATIC_ASSERT(sizeof(JSObject) % JS_GCTHING_ALIGN == 0);
JS_STATIC_ASSERT(offsetof(JSObject, clasp) == offsetof(JSPretendObject, clasp));
#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
? JSSLOT_PRIVATE + 1 \

View File

@ -187,7 +187,7 @@ BEGIN_CASE(JSOP_ENTERWITH)
END_CASE(JSOP_ENTERWITH)
BEGIN_CASE(JSOP_LEAVEWITH)
JS_ASSERT(&regs.sp[-1].asNonFunObj() == fp->scopeChainObj());
JS_ASSERT(&regs.sp[-1].asObject() == fp->scopeChainObj());
regs.sp--;
js_LeaveWith(cx);
END_CASE(JSOP_LEAVEWITH)
@ -741,7 +741,7 @@ END_CASE(JSOP_ENUMCONSTELEM)
#endif
BEGIN_CASE(JSOP_BINDGNAME)
PUSH_NONFUNOBJ(*fp->scopeChainObj()->getGlobal());
PUSH_OBJECT(*fp->scopeChainObj()->getGlobal());
END_CASE(JSOP_BINDGNAME)
BEGIN_CASE(JSOP_BINDNAME)
@ -782,7 +782,7 @@ BEGIN_CASE(JSOP_BINDNAME)
if (!obj)
goto error;
} while (0);
PUSH_NONFUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_BINDNAME)
@ -824,8 +824,8 @@ END_CASE(JSOP_BITAND)
*/
#if JS_HAS_XML_SUPPORT
#define XML_EQUALITY_OP(OP) \
if ((lval.isNonFunObj() && lval.asObject().isXML()) || \
(rval.isNonFunObj() && rval.asObject().isXML())) { \
if ((lval.isObject() && lval.asObject().isXML()) || \
(rval.isObject() && rval.asObject().isXML())) { \
if (!js_TestXMLEquality(cx, lval, rval, &cond)) \
goto error; \
cond = cond OP JS_TRUE; \
@ -850,7 +850,7 @@ END_CASE(JSOP_BITAND)
Value rval = regs.sp[-1]; \
Value lval = regs.sp[-2]; \
XML_EQUALITY_OP(OP) \
if (SamePrimitiveTypeOrBothObjects(lval, rval)) { \
if (SameType(lval, rval)) { \
if (lval.isString()) { \
JSString *l = lval.asString(), *r = rval.asString(); \
cond = js_EqualStrings(l, r) OP JS_TRUE; \
@ -1055,8 +1055,7 @@ BEGIN_CASE(JSOP_ADD)
regs.sp[-1].setInt32(sum);
} else
#if JS_HAS_XML_SUPPORT
if (lval.isNonFunObj() && lval.asObject().isXML() &&
rval.isNonFunObj() && rval.asObject().isXML()) {
if (IsXML(lval) && IsXML(rval)) {
if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
goto error;
regs.sp--;
@ -1616,7 +1615,7 @@ BEGIN_CASE(JSOP_GETXPROP)
if (!atom) {
ASSERT_VALID_PROPERTY_CACHE_HIT(i, aobj, obj2, entry);
if (entry->vword.isFunObj()) {
rval.setFunObj(entry->vword.toFunObj());
rval.setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -1697,7 +1696,7 @@ BEGIN_CASE(JSOP_CALLPROP)
JSObject *pobj;
if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
goto error;
objv.setNonFunObj(*pobj);
objv.setObject(*pobj);
}
JSObject *aobj = js_GetProtoIfDenseArray(&objv.asObject());
@ -1710,7 +1709,7 @@ BEGIN_CASE(JSOP_CALLPROP)
if (!atom) {
ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);
if (entry->vword.isFunObj()) {
rval.setFunObj(entry->vword.toFunObj());
rval.setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -1758,8 +1757,9 @@ BEGIN_CASE(JSOP_CALLPROP)
/* Wrap primitive lval in object clothing if necessary. */
if (lval.isPrimitive()) {
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
if (!rval.isFunObj() ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, &rval.asFunObj()), lval)) {
JSObject *funobj;
if (!IsFunctionObject(rval, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
goto error;
}
@ -1787,7 +1787,7 @@ BEGIN_CASE(JSOP_SETPROP)
BEGIN_CASE(JSOP_SETMETHOD)
{
Value &rref = regs.sp[-1];
JS_ASSERT_IF(op == JSOP_SETMETHOD, rref.isFunObj());
JS_ASSERT_IF(op == JSOP_SETMETHOD, IsFunctionObject(rref));
Value &lref = regs.sp[-2];
JS_ASSERT_IF(op == JSOP_SETNAME, lref.isObject());
JSObject *obj;
@ -2158,8 +2158,7 @@ BEGIN_CASE(JSOP_NEW)
* Assign lval, obj, and fun exactly as the code at inline_call: expects to
* find them, to avoid nesting a js_Interpret call via js_InvokeConstructor.
*/
if (vp[0].isFunObj()) {
obj = &vp[0].asFunObj();
if (IsFunctionObject(vp[0], &obj)) {
fun = GET_FUNCTION_PRIVATE(cx, obj);
if (fun->isInterpreted()) {
/* Root as we go using vp[1]. */
@ -2174,12 +2173,12 @@ BEGIN_CASE(JSOP_NEW)
goto error;
if (fun->u.i.script->isEmpty()) {
vp[0].setNonFunObj(*obj2);
vp[0].setObject(*obj2);
regs.sp = vp + 1;
goto end_new;
}
vp[1].setNonFunObj(*obj2);
vp[1].setObject(*obj2);
flags = JSFRAME_CONSTRUCTING;
goto inline_call;
}
@ -2202,8 +2201,7 @@ BEGIN_CASE(JSOP_APPLY)
argc = GET_ARGC(regs.pc);
vp = regs.sp - (argc + 2);
if (vp->isFunObj()) {
obj = &vp->asFunObj();
if (IsFunctionObject(*vp, &obj)) {
fun = GET_FUNCTION_PRIVATE(cx, obj);
/* Clear frame flags since this is not a constructor call. */
@ -2429,7 +2427,7 @@ BEGIN_CASE(JSOP_CALLNAME)
if (!atom) {
ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
if (entry->vword.isFunObj()) {
PUSH_FUNOBJ(entry->vword.toFunObj());
PUSH_OBJECT(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uintN slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -2553,7 +2551,7 @@ BEGIN_CASE(JSOP_OBJECT)
JSObject *obj;
LOAD_OBJECT(0, obj);
/* Only XML and RegExp objects are emitted. */
PUSH_NONFUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_OBJECT)
@ -2575,7 +2573,7 @@ BEGIN_CASE(JSOP_REGEXP)
JSObject *obj = js_CloneRegExpObject(cx, script->getRegExp(index), proto);
if (!obj)
goto error;
PUSH_NONFUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_REGEXP)
@ -3100,7 +3098,7 @@ BEGIN_CASE(JSOP_DEFFUN)
MUST_FLOW_THROUGH("restore_scope");
fp->setScopeChainObj(obj);
Value rval = FunObjTag(*obj);
Value rval = ObjectTag(*obj);
/*
* ECMA requires functions defined when entering Eval code to be
@ -3200,7 +3198,7 @@ BEGIN_CASE(JSOP_DEFFUN_DBGFC)
if (!obj)
goto error;
Value rval = FunObjTag(*obj);
Value rval = ObjectTag(*obj);
uintN attrs = (fp->flags & JSFRAME_EVAL)
? JSPROP_ENUMERATE
@ -3278,7 +3276,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
uint32 slot = GET_SLOTNO(regs.pc);
TRACE_2(DefLocalFunSetSlot, slot, obj);
fp->slots()[slot].setFunObj(*obj);
fp->slots()[slot].setObject(*obj);
}
END_CASE(JSOP_DEFLOCALFUN)
@ -3294,7 +3292,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
uint32 slot = GET_SLOTNO(regs.pc);
TRACE_2(DefLocalFunSetSlot, slot, obj);
fp->slots()[slot].setFunObj(*obj);
fp->slots()[slot].setObject(*obj);
}
END_CASE(JSOP_DEFLOCALFUN_FC)
@ -3308,7 +3306,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN_DBGFC)
goto error;
uint32 slot = GET_SLOTNO(regs.pc);
fp->slots()[slot].setFunObj(*obj);
fp->slots()[slot].setObject(*obj);
}
END_CASE(JSOP_DEFLOCALFUN_DBGFC)
@ -3365,7 +3363,7 @@ BEGIN_CASE(JSOP_LAMBDA)
goto error;
} while (0);
PUSH_FUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_LAMBDA)
@ -3378,7 +3376,7 @@ BEGIN_CASE(JSOP_LAMBDA_FC)
if (!obj)
goto error;
PUSH_FUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_LAMBDA_FC)
@ -3391,7 +3389,7 @@ BEGIN_CASE(JSOP_LAMBDA_DBGFC)
if (!obj)
goto error;
PUSH_FUNOBJ(*obj);
PUSH_OBJECT(*obj);
}
END_CASE(JSOP_LAMBDA_DBGFC)
@ -3525,7 +3523,7 @@ BEGIN_CASE(JSOP_NEWARRAY)
if (!obj)
goto error;
regs.sp -= len - 1;
regs.sp[-1].setNonFunObj(*obj);
regs.sp[-1].setObject(*obj);
}
END_CASE(JSOP_NEWARRAY)
@ -3561,7 +3559,7 @@ BEGIN_CASE(JSOP_NEWINIT)
}
}
PUSH_NONFUNOBJ(*obj);
PUSH_OBJECT(*obj);
CHECK_INTERRUPT_HANDLER();
}
END_CASE(JSOP_NEWINIT)
@ -3729,7 +3727,7 @@ BEGIN_CASE(JSOP_DEFSHARP)
obj = js_NewArrayObject(cx, 0, NULL);
if (!obj)
goto error;
fp->slots()[slot].setNonFunObj(*obj);
fp->slots()[slot].setObject(*obj);
}
jsint i = (jsint) GET_UINT16(regs.pc + UINT16_LEN);
jsid id = INT_TO_JSID(i);
@ -4341,7 +4339,7 @@ BEGIN_CASE(JSOP_GENERATOR)
if (!obj)
goto error;
JS_ASSERT(!fp->callobj && !fp->argsObj());
fp->rval.setNonFunObj(*obj);
fp->rval.setObject(*obj);
interpReturnOK = true;
if (inlineCallCount != 0)
goto inline_return;

View File

@ -960,7 +960,7 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle
* optimizations only take place if the property is not
* defined.
*/
rval.setFunObj(*fun);
rval.setObject(*fun);
} else {
rval.setUndefined();
}
@ -5595,7 +5595,7 @@ Parser::statement()
JS_SCOPE_DEPTH_METERING(++tc->scopeDepth > tc->maxScopeDepth &&
(tc->maxScopeDepth = tc->scopeDepth));
obj->setParent(NonFunObjOrNullTag(tc->blockChain));
obj->setParent(ObjectOrNullTag(tc->blockChain));
tc->blockChain = obj;
stmt->blockObj = obj;

View File

@ -145,8 +145,8 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
* memoized in the property tree.
*/
JS_ASSERT(scope->hasMethodBarrier());
JSObject &funobj = sprop->methodFunObj();
JS_ASSERT(&funobj == &pobj->lockedGetSlot(sprop->slot).asFunObj());
JSObject &funobj = sprop->methodObject();
JS_ASSERT(&funobj == &pobj->lockedGetSlot(sprop->slot).asObject());
vword.setFunObj(funobj);
break;
}
@ -155,7 +155,8 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
sprop->hasDefaultGetter() &&
SPROP_HAS_VALID_SLOT(sprop, scope)) {
const Value &v = pobj->lockedGetSlot(sprop->slot);
if (v.isFunObj()) {
JSObject *funobj;
if (IsFunctionObject(v, &funobj)) {
/*
* Great, we have a function-valued prototype property
* where the getter is JS_PropertyStub. The type id in
@ -181,7 +182,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, uintN protoI
if (!scope->brand(cx, sprop->slot, v))
return JS_NO_PROP_CACHE_FILL;
}
vword.setFunObj(v.asFunObj());
vword.setFunObj(*funobj);
break;
}
}

View File

@ -963,13 +963,13 @@ proxy_Construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rv
JSObject *newobj = NewObject(cx, &js_ObjectClass, proto, NULL);
if (!newobj)
return false;
rval->setNonFunObj(*newobj);
rval->setObject(*newobj);
/* If the call returns an object, return that, otherwise the original newobj. */
if (!InternalCall(cx, newobj, proxy->fslots[JSSLOT_PROXY_CALL], argc, argv, rval))
return false;
if (rval->isPrimitive())
rval->setNonFunObj(*newobj);
rval->setObject(*newobj);
return true;
}
@ -1075,16 +1075,16 @@ proxy_create(JSContext *cx, uintN argc, Value *vp)
proto = &vp[3].asObject();
parent = proto->getParent();
} else {
JS_ASSERT(vp[0].isFunObj());
JS_ASSERT(IsFunctionObject(vp[0]));
proto = NULL;
parent = vp[0].asFunObj().getParent();
parent = vp[0].asObject().getParent();
}
JSString *className = (argc > 2 && vp[4].isString()) ? vp[4].asString() : NULL;
JSObject *proxy = NewObjectProxy(cx, ObjectTag(*handler), proto, parent, className);
if (!proxy)
return false;
vp->setNonFunObj(*proxy);
vp->setObject(*proxy);
return true;
}
@ -1120,7 +1120,7 @@ proxy_createFunction(JSContext *cx, uintN argc, Value *vp)
if (!proxy)
return false;
vp->setNonFunObj(*proxy);
vp->setObject(*proxy);
return true;
}
@ -1208,13 +1208,13 @@ callable_Construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value
JSObject *newobj = NewObject(cx, &js_ObjectClass, proto, NULL);
if (!newobj)
return false;
rval->setNonFunObj(*newobj);
rval->setObject(*newobj);
/* If the call returns an object, return that, otherwise the original newobj. */
if (!InternalCall(cx, newobj, callable->fslots[JSSLOT_CALLABLE_CALL], argc, argv, rval))
return false;
if (rval->isPrimitive())
rval->setNonFunObj(*newobj);
rval->setObject(*newobj);
return true;
}

View File

@ -193,17 +193,20 @@ typedef struct JSCompartment JSCompartment;
/* Remember to propagate changes to the C defines below. */
JS_ENUM_HEADER(JSValueType, uint8)
{
JSVAL_TYPE_DOUBLE = 0x0,
JSVAL_TYPE_INT32 = 0x1,
JSVAL_TYPE_UNDEFINED = 0x2,
JSVAL_TYPE_STRING = 0x3,
JSVAL_TYPE_BOOLEAN = 0x4,
JSVAL_TYPE_MAGIC = 0x5,
JSVAL_TYPE_NULL = 0x6,
JSVAL_TYPE_NONFUNOBJ = 0x7,
JSVAL_TYPE_FUNOBJ = 0xF,
JSVAL_TYPE_DOUBLE = 0x00,
JSVAL_TYPE_INT32 = 0x01,
JSVAL_TYPE_UNDEFINED = 0x02,
JSVAL_TYPE_BOOLEAN = 0x03,
JSVAL_TYPE_MAGIC = 0x04,
JSVAL_TYPE_STRING = 0x05,
JSVAL_TYPE_NULL = 0x06,
JSVAL_TYPE_OBJECT = 0x07,
/* The below types never appear in a jsval; they are only used in tracing. */
JSVAL_TYPE_NONFUNOBJ = 0x57,
JSVAL_TYPE_FUNOBJ = 0x67,
/* Cannot not appear in any jsval ever; trace-jit only. */
JSVAL_TYPE_STRORNULL = 0x97,
JSVAL_TYPE_OBJORNULL = 0x98,
JSVAL_TYPE_BOXED = 0x99,
@ -222,8 +225,7 @@ JS_ENUM_HEADER(JSValueTag, uint32)
JSVAL_TAG_BOOLEAN = JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL,
JSVAL_TAG_NONFUNOBJ = JSVAL_TAG_CLEAR | JSVAL_TYPE_NONFUNOBJ,
JSVAL_TAG_FUNOBJ = JSVAL_TAG_CLEAR | JSVAL_TYPE_FUNOBJ
JSVAL_TAG_OBJECT = JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT
} JS_ENUM_FOOTER(JSValueType);
#elif JS_BITS_PER_WORD == 64
@ -238,8 +240,7 @@ JS_ENUM_HEADER(JSValueTag, uint32)
JSVAL_TAG_BOOLEAN = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN,
JSVAL_TAG_MAGIC = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC,
JSVAL_TAG_NULL = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL,
JSVAL_TAG_NONFUNOBJ = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NONFUNOBJ,
JSVAL_TAG_FUNOBJ = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_FUNOBJ
JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
} JS_ENUM_FOOTER(JSValueType);
#endif
@ -247,15 +248,16 @@ JS_ENUM_HEADER(JSValueTag, uint32)
#else /* defined(__cplusplus) */
typedef uint8 JSValueType;
#define JSVAL_TYPE_DOUBLE ((uint8)0x0)
#define JSVAL_TYPE_INT32 ((uint8)0x1)
#define JSVAL_TYPE_UNDEFINED ((uint8)0x2)
#define JSVAL_TYPE_STRING ((uint8)0x3)
#define JSVAL_TYPE_BOOLEAN ((uint8)0x4)
#define JSVAL_TYPE_MAGIC ((uint8)0x5)
#define JSVAL_TYPE_NULL ((uint8)0x6)
#define JSVAL_TYPE_NONFUNOBJ ((uint8)0x7)
#define JSVAL_TYPE_FUNOBJ ((uint8)0xF)
#define JSVAL_TYPE_DOUBLE ((uint8)0x00)
#define JSVAL_TYPE_INT32 ((uint8)0x01)
#define JSVAL_TYPE_UNDEFINED ((uint8)0x02)
#define JSVAL_TYPE_BOOLEAN ((uint8)0x03)
#define JSVAL_TYPE_MAGIC ((uint8)0x04)
#define JSVAL_TYPE_STRING ((uint8)0x05)
#define JSVAL_TYPE_NULL ((uint8)0x06)
#define JSVAL_TYPE_OBJECT ((uint8)0x07)
#define JSVAL_TYPE_NONFUNOBJ ((uint8)0x57)
#define JSVAL_TYPE_FUNOBJ ((uint8)0x67)
#define JSVAL_TYPE_STRORNULL ((uint8)0x97)
#define JSVAL_TYPE_OBJORNULL ((uint8)0x98)
#define JSVAL_TYPE_BOXED ((uint8)0x99)
@ -271,8 +273,7 @@ typedef uint32 JSValueTag;
#define JSVAL_TAG_BOOLEAN ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
#define JSVAL_TAG_MAGIC ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
#define JSVAL_TAG_NULL ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
#define JSVAL_TAG_NONFUNOBJ ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NONFUNOBJ))
#define JSVAL_TAG_FUNOBJ ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_FUNOBJ))
#define JSVAL_TAG_OBJECT ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
#elif JS_BITS_PER_WORD == 64
@ -284,32 +285,32 @@ typedef uint32 JSValueTag;
#define JSVAL_TAG_BOOLEAN (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
#define JSVAL_TAG_MAGIC (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
#define JSVAL_TAG_NULL (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
#define JSVAL_TAG_NONFUNOBJ (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NONFUNOBJ)
#define JSVAL_TAG_FUNOBJ (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_FUNOBJ)
#define JSVAL_TAG_OBJECT (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
#endif /* JS_BITS_PER_WORD */
#endif /* defined(__cplusplus) */
#define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET JSVAL_TYPE_NULL
#define JSVAL_LOWER_INCL_TYPE_OF_OBJ_SET JSVAL_TYPE_NONFUNOBJ
#define JSVAL_UPPER_INCL_TYPE_OF_OBJ_SET JSVAL_TYPE_FUNOBJ
#define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
#define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET JSVAL_TYPE_NULL
#define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET JSVAL_TYPE_OBJECT
#define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
#define JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET JSVAL_TYPE_STRING
#define JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET JSVAL_TYPE_OBJECT
#define JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET JSVAL_TYPE_FUNOBJ
#if JS_BITS_PER_WORD == 32
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | type))
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_SET JSVAL_TAG_NONFUNOBJ
#define JSVAL_UPPER_INCL_TAG_OF_OBJ_SET JSVAL_TAG_FUNOBJ
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
#define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET JSVAL_TAG_NULL
#define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT
#define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32
#define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING
#elif JS_BITS_PER_WORD == 64
#define JSVAL_TAG_SHIFT 47
#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | type))
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_MAX_DOUBLE (((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT)
@ -319,12 +320,12 @@ typedef uint32 JSValueTag;
#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_MAGIC (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_NULL (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_NONFUNOBJ (((uint64)JSVAL_TAG_NONFUNOBJ) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_FUNOBJ (((uint64)JSVAL_TAG_FUNOBJ) << JSVAL_TAG_SHIFT)
#define JSVAL_SHIFTED_TAG_OBJECT (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_SET JSVAL_SHIFTED_TAG_NONFUNOBJ
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
#endif /* JS_BITS_PER_WORD */
@ -508,33 +509,21 @@ MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NONFUNOBJ_IMPL(jsval_layout l)
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
{
return l.s.tag == JSVAL_TAG_NONFUNOBJ;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_FUNOBJ_IMPL(jsval_layout l)
{
return l.s.tag == JSVAL_TAG_FUNOBJ;
return l.s.tag == JSVAL_TAG_OBJECT;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
{
JSValueTag tag = l.s.tag;
return tag < JSVAL_LOWER_INCL_TAG_OF_OBJ_SET;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
{
return l.s.tag >= JSVAL_LOWER_INCL_TAG_OF_OBJ_SET;
return l.s.tag < JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
{
JS_ASSERT(l.s.tag <= JSVAL_TAG_OBJECT);
return l.s.tag >= JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
}
@ -545,10 +534,10 @@ JSVAL_TO_OBJECT_IMPL(jsval_layout l)
}
static JS_ALWAYS_INLINE jsval_layout
OBJECT_TO_JSVAL_IMPL(JSValueType type, JSObject *obj)
OBJECT_TO_JSVAL_IMPL(JSObject *obj)
{
jsval_layout l;
l.s.tag = JSVAL_TYPE_TO_TAG(type);
l.s.tag = JSVAL_TAG_OBJECT;
l.s.payload.obj = obj;
return l;
}
@ -559,12 +548,6 @@ JSVAL_IS_NULL_IMPL(jsval_layout l)
return l.s.tag == JSVAL_TAG_NULL;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
{
return l.s.payload.ptr;
}
static JS_ALWAYS_INLINE jsval_layout
PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
{
@ -582,37 +565,51 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
return l.s.payload.ptr;
}
#ifdef __cplusplus
JS_STATIC_ASSERT((JSVAL_TAG_FUNOBJ ^ JSVAL_TAG_NONFUNOBJ) == 0x8);
#endif
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
return l.s.tag >= JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
{
return l.s.payload.ptr;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
{
return l.s.tag == JSVAL_TAG_STRING || l.s.tag == JSVAL_TAG_OBJECT;
}
static JS_ALWAYS_INLINE uint32
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
{
return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
{
/*
* The second disjunct uses the fact that the funobj and nonfunobj tags
* differ in only 1 type bit and any other pair of tags will differ in at
* least one other bit.
*/
JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
return (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR) ||
(((ltag ^ rtag) & 0xFFFFFFF7) == 0);
return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
}
static JS_ALWAYS_INLINE JSValueType
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TYPE_IMPL(jsval_layout l)
{
uint32 type = l.s.tag & 0xF;
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type < JSVAL_TYPE_OBJECT);
return (JSValueType)type;
}
static JS_ALWAYS_INLINE JSValueTag
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TAG_IMPL(jsval_layout l)
{
JSValueTag t = l.s.tag;
JS_ASSERT(t >= JSVAL_TAG_INT32);
return t;
JSValueTag tag = l.s.tag;
JS_ASSERT(tag >= JSVAL_TAG_INT32 && tag != JSVAL_TAG_OBJECT);
return tag;
}
static JS_ALWAYS_INLINE jsval_layout
@ -631,12 +628,17 @@ JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
return l.s.payload.u32;
}
#ifdef __cplusplus
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
#endif
static JS_ALWAYS_INLINE jsval_layout
BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
{
jsval_layout l;
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
l.s.tag = JSVAL_TYPE_TO_TAG(type);
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
l.s.tag = JSVAL_TYPE_TO_TAG(type & 0xF);
l.s.payload.u32 = *(uint32 *)slot;
return l;
}
@ -768,33 +770,23 @@ MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
return l;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_NONFUNOBJ_IMPL(jsval_layout l)
{
return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_NONFUNOBJ;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_FUNOBJ_IMPL(jsval_layout l)
{
return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_FUNOBJ;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
{
return l.asBits < JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_SET;
return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
{
return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_SET;
JS_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_SHIFTED_TAG_OBJECT);
return l.asBits >= JSVAL_SHIFTED_TAG_OBJECT;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
{
JS_ASSERT((l.asBits >> JSVAL_TAG_SHIFT) <= JSVAL_TAG_OBJECT);
return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET;
}
@ -807,13 +799,12 @@ JSVAL_TO_OBJECT_IMPL(jsval_layout l)
}
static JS_ALWAYS_INLINE jsval_layout
OBJECT_TO_JSVAL_IMPL(JSValueType type, JSObject *obj)
OBJECT_TO_JSVAL_IMPL(JSObject *obj)
{
jsval_layout l;
uint64 objBits = (uint64)obj;
JS_ASSERT(type >= JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET);
JS_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
l.asBits = objBits | JSVAL_TYPE_TO_SHIFTED_TAG(type);
l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
return l;
}
@ -823,6 +814,12 @@ JSVAL_IS_NULL_IMPL(jsval_layout l)
return l.asBits == JSVAL_SHIFTED_TAG_NULL;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
return l.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET;
}
static JS_ALWAYS_INLINE void *
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
{
@ -831,6 +828,18 @@ JSVAL_TO_GCTHING_IMPL(jsval_layout l)
return (void *)ptrBits;
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
{
return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
}
static JS_ALWAYS_INLINE uint32
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
{
return (uint32)(JSBool)!(JSVAL_IS_OBJECT_IMPL(l));
}
static JS_ALWAYS_INLINE jsval_layout
PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
{
@ -849,21 +858,12 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
return (void *)(l.asBits << 1);
}
#ifdef __cplusplus
JS_STATIC_ASSERT((JSVAL_SHIFTED_TAG_FUNOBJ ^ JSVAL_SHIFTED_TAG_NONFUNOBJ) == 0x0004000000000000LL);
#endif
static JS_ALWAYS_INLINE JSBool
JSVAL_SAME_PRIMITIVE_TYPE_OR_BOTH_OBJECTS_IMPL(jsval_layout lhs, jsval_layout rhs)
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
{
/*
* The second disjunct uses the fact that the funobj and nonfunobj tags
* differ in only 1 type bit and any other pair of tags will differ in at
* least one other bit.
*/
uint64 lbits = lhs.asBits, rbits = rhs.asBits;
return (lbits < JSVAL_TAG_MAX_DOUBLE && rbits < JSVAL_TAG_MAX_DOUBLE) ||
(((lbits ^ rbits) & 0xFFFB800000000000LL) == 0);
return (lbits <= JSVAL_TAG_MAX_DOUBLE && rbits <= JSVAL_TAG_MAX_DOUBLE) ||
(((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
}
static JS_ALWAYS_INLINE jsval_layout
@ -883,23 +883,25 @@ JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
}
static JS_ALWAYS_INLINE JSValueType
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TYPE_IMPL(jsval_layout l)
{
uint64 type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type < JSVAL_TYPE_OBJECT);
return (JSValueType)type;
}
static JS_ALWAYS_INLINE JSValueTag
JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
JSVAL_EXTRACT_NON_DOUBLE_OBJECT_TAG_IMPL(jsval_layout l)
{
uint64 tag = l.asBits >> JSVAL_TAG_SHIFT;
JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE);
JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE && tag != JSVAL_TAG_OBJECT);
return (JSValueTag)tag;
}
#ifdef __cplusplus
JS_STATIC_ASSERT(offsetof(jsval_layout, s.payload) == 0);
JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
#endif
static JS_ALWAYS_INLINE jsval_layout
@ -907,13 +909,12 @@ BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
{
/* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
jsval_layout l;
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_TYPE_FUNOBJ);
uint32 isI32 = (uint32)((type != JSVAL_TYPE_STRING) &
(type < JSVAL_LOWER_INCL_TYPE_OF_OBJ_SET));
JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET);
uint32 shift = isI32 * 32;
uint64 mask = ((uint64)-1) >> shift;
uint64 payload = *slot & mask;
l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type);
l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
return l;
}
@ -926,19 +927,6 @@ UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
#endif
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
{
return JSVAL_IS_OBJECT_IMPL(l) || JSVAL_IS_STRING_IMPL(l);
}
static JS_ALWAYS_INLINE uint32
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
{
JS_ASSERT(JSVAL_IS_GCTHING_IMPL(l));
return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
}
static JS_ALWAYS_INLINE JSBool
JSVAL_IS_UNDERLYING_TYPE_OF_PRIVATE_IMPL(jsval_layout l)
{
@ -1495,27 +1483,6 @@ static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHa
static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */
} /* namespace js */
typedef js::Class JSFunctionClassType;
extern "C" JS_FRIEND_DATA(JSFunctionClassType) js_FunctionClass;
#else /* !defined(__cplusplus) */
typedef JSClass JSFunctionClassType;
extern JS_FRIEND_DATA(JSFunctionClassType) js_FunctionClass;
#endif /* __cplusplus */
typedef struct JSPretendObject
{
void *_;
JSFunctionClassType *clasp;
} JSPretendObject;
static JS_ALWAYS_INLINE JSBool
JS_OBJ_IS_FUN_IMPL(JSObject *obj)
{
return ((JSPretendObject *)obj)->clasp == &js_FunctionClass;
}
#endif /* defined(__cplusplus) */
#endif /* jspubtd_h___ */

View File

@ -734,11 +734,18 @@ TraceRecorder::slurpDoubleSlot(LIns* addr_ins, ptrdiff_t offset, VMSideExit* exi
return unbox_number_as_double(addr_ins, offset, tag_ins, exit, ACC_OTHER);
}
JS_REQUIRES_STACK inline LIns*
TraceRecorder::slurpNonDoubleSlot(LIns* addr_ins, ptrdiff_t offset, JSValueTag tag, VMSideExit* exit)
JS_REQUIRES_STACK LIns*
TraceRecorder::slurpObjectSlot(LIns* addr_ins, ptrdiff_t offset, JSValueType type, VMSideExit* exit)
{
LIns* tag_ins = lir->insLoad(LIR_ldi, addr_ins, offset + sTagOffset, ACC_OTHER);
return unbox_non_double(addr_ins, offset, tag_ins, tag, exit, ACC_OTHER);
return unbox_object(addr_ins, offset, tag_ins, type, exit, ACC_OTHER);
}
JS_REQUIRES_STACK inline LIns*
TraceRecorder::slurpNonDoubleObjectSlot(LIns* addr_ins, ptrdiff_t offset, JSValueType type, VMSideExit* exit)
{
LIns* tag_ins = lir->insLoad(LIR_ldi, addr_ins, offset + sTagOffset, ACC_OTHER);
return unbox_non_double_object(addr_ins, offset, tag_ins, type, exit, ACC_OTHER);
}
#elif JS_BITS_PER_WORD == 64
JS_REQUIRES_STACK inline LIns*
@ -748,11 +755,18 @@ TraceRecorder::slurpDoubleSlot(LIns* addr_ins, ptrdiff_t offset, VMSideExit* exi
return unbox_number_as_double(v_ins, exit);
}
JS_REQUIRES_STACK inline LIns*
TraceRecorder::slurpNonDoubleSlot(LIns* addr_ins, ptrdiff_t offset, JSValueTag tag, VMSideExit* exit)
JS_REQUIRES_STACK LIns*
TraceRecorder::slurpObjectSlot(LIns* addr_ins, ptrdiff_t offset, JSValueType type, VMSideExit* exit)
{
LIns* v_ins = lir->insLoad(LIR_ldq, addr_ins, offset, ACC_OTHER);
return unbox_non_double(v_ins, tag, exit);
return unbox_object(v_ins, type, exit);
}
JS_REQUIRES_STACK inline LIns*
TraceRecorder::slurpNonDoubleObjectSlot(LIns* addr_ins, ptrdiff_t offset, JSValueType type, VMSideExit* exit)
{
LIns* v_ins = lir->insLoad(LIR_ldq, addr_ins, offset, ACC_OTHER);
return unbox_non_double_object(v_ins, type, exit);
}
#endif
@ -761,8 +775,10 @@ TraceRecorder::slurpSlot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSideExit
{
if (exit->slurpType == JSVAL_TYPE_DOUBLE)
return slurpDoubleSlot(addr_ins, offset, exit);
JSValueTag tag = JSVAL_TYPE_TO_TAG(exit->slurpType);
return slurpNonDoubleSlot(addr_ins, offset, tag, exit);
if (exit->slurpType == JSVAL_TYPE_FUNOBJ || exit->slurpType == JSVAL_TYPE_NONFUNOBJ)
return slurpObjectSlot(addr_ins, offset, exit->slurpType, exit);
JSValueType type = exit->slurpType;
return slurpNonDoubleObjectSlot(addr_ins, offset, type, exit);
}
JS_REQUIRES_STACK void

View File

@ -4985,7 +4985,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
ok = JS_FALSE;
goto out;
}
rval->setNonFunObj(*obj);
rval->setObject(*obj);
#define DEFVAL(valinit, id) { \
Value tmp = valinit; \
@ -5569,7 +5569,7 @@ created:
JS_UNLOCK_OBJ(cx, obj);
if (oldre)
js_DestroyRegExp(cx, oldre);
rval->setNonFunObj(*obj);
rval->setObject(*obj);
return JS_TRUE;
}
@ -5710,7 +5710,7 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
* regexp_compile_sub does not use rval to root its temporaries so we
* can use it to root obj.
*/
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
return regexp_compile_sub(cx, obj, argc, argv, rval);
}

View File

@ -1195,7 +1195,7 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop)
if (sprop->isMethod()) {
#ifdef DEBUG
const Value &prev = object->lockedGetSlot(sprop->slot);
JS_ASSERT(&sprop->methodFunObj() == &prev.asObject());
JS_ASSERT(&sprop->methodObject() == &prev.asObject());
JS_ASSERT(hasMethodBarrier());
JS_ASSERT(object->getClass() == &js_ObjectClass);
JS_ASSERT(!sprop->rawSetter || sprop->rawSetter == js_watch_set);
@ -1310,16 +1310,16 @@ JSScopeProperty::trace(JSTracer *trc)
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
if ((attrs & JSPROP_GETTER) && rawGetter) {
JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, this, 0);
MarkRaw(trc, getterObject(), JSTRACE_OBJECT);
Mark(trc, getterObject(), JSTRACE_OBJECT);
}
if ((attrs & JSPROP_SETTER) && rawSetter) {
JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, this, 1);
MarkRaw(trc, setterObject(), JSTRACE_OBJECT);
Mark(trc, setterObject(), JSTRACE_OBJECT);
}
}
if (isMethod()) {
JS_SET_TRACING_DETAILS(trc, PrintPropertyMethod, this, 0);
MarkRaw(trc, &methodFunObj(), JSTRACE_OBJECT);
Mark(trc, &methodObject(), JSTRACE_OBJECT);
}
}

View File

@ -704,7 +704,7 @@ struct JSScopeProperty {
bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
bool isMethod() const { return (flags & METHOD) != 0; }
JSObject &methodFunObj() const { JS_ASSERT(isMethod()); return *getterObj; }
JSObject &methodObject() const { JS_ASSERT(isMethod()); return *getterObj; }
js::PropertyOp getter() const { return rawGetter; }
bool hasDefaultGetter() const { return !rawGetter; }
@ -982,7 +982,7 @@ JSScopeProperty::get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp
}
if (isMethod()) {
vp->setFunObj(methodFunObj());
vp->setObject(methodObject());
JSScope *scope = pobj->scope();
JS_ASSERT(scope->object == pobj);

View File

@ -120,25 +120,26 @@ JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp)
JS_ASSERT(hasMethodBarrier());
JS_ASSERT(hasProperty(sprop));
JS_ASSERT(sprop->isMethod());
JS_ASSERT(&vp->asFunObj() == &sprop->methodFunObj());
JS_ASSERT(&vp->asObject() == &sprop->methodObject());
JS_ASSERT(object->getClass() == &js_ObjectClass);
JSObject *funobj = &vp->asFunObj();
JSObject *funobj = &vp->asObject();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun));
funobj = CloneFunctionObject(cx, fun, funobj->getParent());
if (!funobj)
return false;
vp->setFunObj(*funobj);
vp->setObject(*funobj);
return !!js_SetPropertyHelper(cx, object, sprop->id, 0, vp);
}
static JS_ALWAYS_INLINE bool
ChangesMethodValue(const js::Value &prev, const js::Value &v)
{
return prev.isFunObj() &&
(!v.isFunObj() || &v.asFunObj() != &prev.asFunObj());
JSObject *prevObj;
return prev.isObject() && (prevObj = &prev.asObject())->isFunction() &&
(!v.isObject() || &v.asObject() != prevObj);
}
inline bool

View File

@ -1258,7 +1258,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
--i;
if (objarray->vector[i]) {
JS_SET_TRACING_INDEX(trc, "objects", i);
MarkRaw(trc, objarray->vector[i], JSTRACE_OBJECT);
Mark(trc, objarray->vector[i], JSTRACE_OBJECT);
}
} while (i != 0);
}
@ -1270,7 +1270,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
--i;
if (objarray->vector[i]) {
JS_SET_TRACING_INDEX(trc, "regexps", i);
MarkRaw(trc, objarray->vector[i], JSTRACE_OBJECT);
Mark(trc, objarray->vector[i], JSTRACE_OBJECT);
}
} while (i != 0);
}
@ -1282,7 +1282,7 @@ js_TraceScript(JSTracer *trc, JSScript *script)
if (script->u.object) {
JS_SET_TRACING_NAME(trc, "object");
MarkRaw(trc, script->u.object, JSTRACE_OBJECT);
Mark(trc, script->u.object, JSTRACE_OBJECT);
}
if (IS_GC_MARKING_TRACER(trc) && script->filename)

View File

@ -1598,7 +1598,7 @@ BuildFlatMatchArray(JSContext *cx, JSString *textstr, const RegExpGuard &g,
JSObject *obj = js_NewSlowArrayObject(cx);
if (!obj)
return false;
vp->setNonFunObj(*obj);
vp->setObject(*obj);
return obj->defineProperty(cx, INT_TO_JSID(0), StringTag(g.patstr)) &&
obj->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.indexAtom),
@ -1628,7 +1628,7 @@ str_match(JSContext *cx, uintN argc, Value *vp)
/* When not global, DoMatch will leave |RegEx.exec()| in *vp. */
if (g.re()->flags & JSREG_GLOB)
vp->setNonFunObjOrNull(array.object());
vp->setObjectOrNull(array.object());
return true;
}
@ -2113,7 +2113,7 @@ str_split(JSContext *cx, uintN argc, Value *vp)
JSObject *aobj = js_NewArrayObject(cx, 1, &v);
if (!aobj)
return false;
vp->setNonFunObj(*aobj);
vp->setObject(*aobj);
return true;
}
@ -2195,7 +2195,7 @@ str_split(JSContext *cx, uintN argc, Value *vp)
JSObject *aobj = js_NewArrayObject(cx, splits.length(), splits.begin());
if (!aobj)
return false;
vp->setNonFunObj(*aobj);
vp->setObject(*aobj);
return true;
}

View File

@ -1041,7 +1041,9 @@ GetPromotedType(const Value &v)
{
if (v.isNumber())
return JSVAL_TYPE_DOUBLE;
return v.extractNonDoubleType();
if (v.isObject())
return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return v.extractNonDoubleObjectType();
}
/* Return JSVAL_TYPE_INT32 for all whole numbers that fit into signed 32-bit and the tag otherwise. */
@ -1054,8 +1056,9 @@ getCoercedType(const Value &v)
? JSVAL_TYPE_INT32
: JSVAL_TYPE_DOUBLE;
}
return v.extractNonDoubleType();
if (v.isObject())
return v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return v.extractNonDoubleObjectType();
}
/* Constant seed and accumulate step borrowed from the DJB hash. */
@ -2427,7 +2430,7 @@ TraceRecorder::insImmObj(JSObject* obj)
inline LIns*
TraceRecorder::insImmFun(JSFunction* fun)
{
tree->gcthings.addUnique(FunObjTag(*FUN_OBJECT(fun)));
tree->gcthings.addUnique(ObjectTag(*fun));
return lir->insImmP((void*)fun);
}
@ -2545,34 +2548,31 @@ static inline void
ValueToNative(const Value &v, JSValueType type, double* slot)
{
if (type > JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET) {
JS_ASSERT(v.extractNonDoubleType() == type);
v.unboxNonDoubleTo((uint64 *)slot);
} else if (type == JSVAL_TYPE_INT32) {
#ifdef DEBUG
int32_t _;
JS_ASSERT_IF(v.isDouble(), JSDOUBLE_IS_INT32(v.asDouble(), _));
#endif
*(int32_t *)slot = v.isInt32() ? v.asInt32() : (int32_t)v.asDouble();
} else {
JS_ASSERT(type == JSVAL_TYPE_DOUBLE);
*(double *)slot = v.asNumber();
}
#ifdef DEBUG
int32_t _;
switch (type) {
case JSVAL_TYPE_NONFUNOBJ: {
JS_ASSERT(v.isNonFunObj());
JS_ASSERT(!IsFunctionObject(v));
debug_only_printf(LC_TMTracer,
"object<%p:%s> ", (void*)*(JSObject **)slot,
v.asNonFunObj().getClass()->name);
v.asObject().getClass()->name);
return;
}
case JSVAL_TYPE_INT32:
JS_ASSERT(v.isInt32() || (v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), _)));
debug_only_printf(LC_TMTracer, "int<%d> ", *(jsint *)slot);
return;
case JSVAL_TYPE_DOUBLE:
JS_ASSERT(v.isNumber());
debug_only_printf(LC_TMTracer, "double<%g> ", *(jsdouble *)slot);
return;
@ -2581,6 +2581,7 @@ ValueToNative(const Value &v, JSValueType type, double* slot)
return;
case JSVAL_TYPE_STRING:
JS_ASSERT(v.isString());
debug_only_printf(LC_TMTracer, "string<%p> ", (void*)*(JSString**)slot);
return;
@ -2605,7 +2606,8 @@ ValueToNative(const Value &v, JSValueType type, double* slot)
return;
case JSVAL_TYPE_FUNOBJ: {
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.asFunObj());
JS_ASSERT(IsFunctionObject(v));
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.asObject());
debug_only_printf(LC_TMTracer,
"function<%p:%s> ", (void*)*(JSObject **)slot,
fun->atom
@ -2675,7 +2677,7 @@ MarkTree(JSTracer* trc, TreeFragment *f)
while (len--) {
Value &v = *vp++;
JS_SET_TRACING_NAME(trc, "jitgcthing");
MarkRaw(trc, v.asGCThing(), v.traceKind());
Mark(trc, v.asGCThing(), v.gcKind());
}
JSScopeProperty** spropp = f->sprops.data();
len = f->sprops.length();
@ -2716,7 +2718,7 @@ NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot)
{
if (type == JSVAL_TYPE_DOUBLE) {
v.setNumber(*slot);
} else if (JS_LIKELY(type <= JSVAL_UPPER_INCL_TYPE_OF_OBJ_SET)) {
} else if (JS_LIKELY(type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET)) {
v.boxNonDoubleFrom(type, (uint64 *)slot);
} else if (type == JSVAL_TYPE_STRORNULL) {
JSString *str = *(JSString**) slot;
@ -2727,7 +2729,7 @@ NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot)
} else if (type == JSVAL_TYPE_OBJORNULL) {
JSObject *obj = *(JSObject**) slot;
if (obj)
v.setNonFunObj(*obj);
v.setObject(*obj);
else
v.setNull();
} else {
@ -2739,10 +2741,11 @@ NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot)
#ifdef DEBUG
switch (type) {
case JSVAL_TYPE_NONFUNOBJ:
JS_ASSERT(!IsFunctionObject(v));
debug_only_printf(LC_TMTracer,
"object<%p:%s> ",
(void*) &v.asNonFunObj(),
v.asNonFunObj().getClass()->name);
(void*) &v.asObject(),
v.asObject().getClass()->name);
break;
case JSVAL_TYPE_INT32:
debug_only_printf(LC_TMTracer, "int<%d> ", v.asInt32());
@ -2766,9 +2769,10 @@ NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot)
debug_only_printf(LC_TMTracer, "magic<%d> ", v.whyMagic());
break;
case JSVAL_TYPE_FUNOBJ: {
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.asFunObj());
JS_ASSERT(IsFunctionObject(v));
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.asObject());
debug_only_printf(LC_TMTracer,
"function<%p:%s> ", (void*) &v.asFunObj(),
"function<%p:%s> ", (void*) &v.asObject(),
fun->atom
? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
: "unnamed");
@ -3814,7 +3818,9 @@ TraceRecorder::determineSlotType(Value* vp)
return t;
}
return vp->extractNonDoubleType();
if (vp->isObject())
return vp->asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return vp->extractNonDoubleObjectType();
}
class DetermineTypesVisitor : public SlotVisitorBase
@ -6000,8 +6006,7 @@ ValueTypeTag(const Value &v)
if (v.isInt32()) return 'I';
if (v.isDouble()) return 'D';
if (v.isString()) return 'S';
if (v.isFunObj()) return 'F';
if (v.isNonFunObj()) return 'O';
if (v.isObject()) return v.asObject().isFunction() ? 'F' : 'O';
if (v.isBoolean()) return 'B';
if (v.isNull()) return 'N';
if (v.isUndefined()) return 'U';
@ -6021,54 +6026,62 @@ IsEntryTypeCompatible(Value* vp, JSValueType* typep)
JSValueType type = *typep;
Value v = *vp;
bool match;
if (type > JSVAL_TYPE_INT32) {
match = v.isNumber() ? false : (v.extractNonDoubleType() == type);
} else if (type == JSVAL_TYPE_INT32) {
int32_t _;
match = v.isInt32() || (v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), _));
} else {
JS_ASSERT(type == JSVAL_TYPE_DOUBLE);
match = v.isNumber();
}
JS_ASSERT(type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
int32_t _;
#ifdef DEBUG
switch (type) {
case JSVAL_TYPE_NONFUNOBJ:
debug_only_printf(LC_TMTracer, "object != tag%c ", tag);
break;
case JSVAL_TYPE_INT32:
debug_only_printf(LC_TMTracer, "int != tag%c ", tag);
break;
case JSVAL_TYPE_DOUBLE:
if (v.isNumber())
return true;
debug_only_printf(LC_TMTracer, "double != tag%c ", tag);
break;
case JSVAL_TYPE_BOXED:
JS_NOT_REACHED("shouldn't see jsval type in entry");
case JSVAL_TYPE_INT32:
if (v.isInt32() || (v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), _)))
return true;
debug_only_printf(LC_TMTracer, "int != tag%c ", tag);
break;
case JSVAL_TYPE_UNDEFINED:
if (v.isUndefined())
return true;
debug_only_printf(LC_TMTracer, "undefined != tag%c ", tag);
break;
case JSVAL_TYPE_BOOLEAN:
if (v.isBoolean())
return true;
debug_only_printf(LC_TMTracer, "bool != tag%c ", tag);
break;
case JSVAL_TYPE_MAGIC:
if (v.isMagic())
return true;
debug_only_printf(LC_TMTracer, "magic != tag%c ", tag);
break;
case JSVAL_TYPE_STRING:
if (v.isString())
return true;
debug_only_printf(LC_TMTracer, "string != tag%c ", tag);
break;
case JSVAL_TYPE_NULL:
if (v.isNull())
return true;
debug_only_printf(LC_TMTracer, "null != tag%c ", tag);
break;
case JSVAL_TYPE_BOOLEAN:
debug_only_printf(LC_TMTracer, "bool != tag%c ", tag);
case JSVAL_TYPE_OBJECT:
JS_NOT_REACHED("JSVAL_TYPE_OBJECT does not belong in a type map");
break;
case JSVAL_TYPE_UNDEFINED:
debug_only_printf(LC_TMTracer, "undefined != tag%c ", tag);
case JSVAL_TYPE_NONFUNOBJ:
if (v.isObject() && !v.asObject().isFunction())
return true;
debug_only_printf(LC_TMTracer, "object != tag%c ", tag);
break;
case JSVAL_TYPE_MAGIC:
debug_only_printf(LC_TMTracer, "hole != tag%c ", tag);
break;
default:
JS_ASSERT(type == JSVAL_TYPE_FUNOBJ);
case JSVAL_TYPE_FUNOBJ:
if (v.isObject() && v.asObject().isFunction())
return true;
debug_only_printf(LC_TMTracer, "fun != tag%c ", tag);
break;
default:
JS_NOT_REACHED("unexpected type");
}
#endif
return match;
return false;
}
class TypeCompatibilityVisitor : public SlotVisitorBase
@ -9381,26 +9394,39 @@ TraceRecorder::unbox_number_as_double(LIns *vaddr_ins, ptrdiff_t offset, LIns *t
}
inline LIns*
TraceRecorder::unbox_non_double(LIns* vaddr_ins, ptrdiff_t offset,
LIns* tag_ins, JSValueTag tag, VMSideExit* exit,
AccSet accSet)
TraceRecorder::unbox_non_double_object(LIns* vaddr_ins, ptrdiff_t offset, LIns* tag_ins,
JSValueType type, VMSideExit* exit, AccSet accSet)
{
LIns *val_ins;
if (tag == JSVAL_TAG_UNDEFINED) {
if (type == JSVAL_TYPE_UNDEFINED) {
val_ins = INS_UNDEFINED();
} else if (tag == JSVAL_TAG_NULL) {
} else if (type == JSVAL_TYPE_NULL) {
val_ins = INS_NULL();
} else {
JS_ASSERT(tag == JSVAL_TAG_INT32 || tag == JSVAL_TAG_FUNOBJ ||
tag == JSVAL_TAG_NONFUNOBJ || tag == JSVAL_TAG_STRING ||
tag == JSVAL_TAG_BOOLEAN || tag == JSVAL_TAG_MAGIC);
JS_ASSERT(type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_OBJECT ||
type == JSVAL_TYPE_STRING || type == JSVAL_TYPE_BOOLEAN ||
type == JSVAL_TYPE_MAGIC);
val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet);
}
guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(tag)), exit);
guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TYPE_TO_TAG(type))), exit);
return val_ins;
}
LIns*
TraceRecorder::unbox_object(LIns* vaddr_ins, ptrdiff_t offset, LIns* tag_ins,
JSValueType type, VMSideExit* exit, AccSet accSet)
{
JS_ASSERT(type == JSVAL_TYPE_FUNOBJ || type == JSVAL_TYPE_NONFUNOBJ);
guard(true, lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_OBJECT)), exit);
LIns *payload_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + sPayloadOffset, accSet);
if (type == JSVAL_TYPE_FUNOBJ)
guardClass(payload_ins, &js_FunctionClass, exit, ACC_OTHER);
else
guardNotClass(payload_ins, &js_FunctionClass, exit, ACC_OTHER);
return payload_ins;
}
LIns*
TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit,
bool force_double)
@ -9421,14 +9447,20 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM
return lir->insLoad(LIR_ldd, vaddr_ins, offset + sPayloadOffset, accSet);
}
return unbox_non_double(vaddr_ins, offset, tag_ins, v.extractNonDoubleTag(), exit, accSet);
if (v.isObject()) {
JSValueType type = v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return unbox_object(vaddr_ins, offset, tag_ins, type, exit, accSet);
}
JSValueType type = v.extractNonDoubleObjectType();
return unbox_non_double_object(vaddr_ins, offset, tag_ins, type, exit, accSet);
}
void
TraceRecorder::unbox_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet)
TraceRecorder::unbox_any_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet)
{
LIns *tag_ins = lir->insLoad(LIR_ldp, vaddr_ins, sTagOffset, accSet);
*is_obj_ins = lir->ins2(LIR_geup, tag_ins, INS_CONSTU(JSVAL_LOWER_INCL_TAG_OF_OBJ_SET));
*is_obj_ins = lir->ins2(LIR_eqi, tag_ins, INS_CONSTU(JSVAL_TAG_OBJECT));
*obj_ins = lir->insLoad(LIR_ldp, vaddr_ins, sPayloadOffset, accSet);
}
@ -9463,12 +9495,12 @@ TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, pt
return;
}
JSValueTag tag = v.extractNonDoubleTag();
if (tag == JSVAL_TAG_UNDEFINED) {
if (v.isUndefined()) {
box_undefined_into(dstaddr_ins, offset, accSet);
} else if (tag == JSVAL_TAG_NULL) {
} else if (v.isNull()) {
box_null_into(dstaddr_ins, offset, accSet);
} else {
JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTag();
lir->insStore(INS_CONSTU(tag), dstaddr_ins, offset + sTagOffset, ACC_OTHER);
lir->insStore(v_ins, dstaddr_ins, offset + sPayloadOffset, ACC_OTHER);
}
@ -9517,11 +9549,11 @@ TraceRecorder::box_undefined_into(LIns *vaddr_ins, ptrdiff_t offset, AccSet accS
}
inline LIns *
TraceRecorder::non_double_value_has_tag(LIns *v_ins, JSValueTag tag)
TraceRecorder::non_double_object_value_has_type(LIns *v_ins, JSValueType type)
{
return lir->ins2(LIR_eqi,
lir->ins1(LIR_q2i, lir->ins2ImmI(LIR_rshuq, v_ins, JSVAL_TAG_SHIFT)),
INS_CONSTU(tag));
INS_CONSTU(JSVAL_TYPE_TO_TAG(type)));
}
inline LIns *
@ -9541,24 +9573,41 @@ TraceRecorder::unbox_number_as_double(LIns *v_ins, VMSideExit *exit)
}
inline nanojit::LIns*
TraceRecorder::unbox_non_double(LIns* v_ins, JSValueTag tag, VMSideExit* exit)
TraceRecorder::unbox_non_double_object(LIns* v_ins, JSValueType type, VMSideExit* exit)
{
JS_ASSERT(type <= JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET);
LIns *unboxed_ins;
if (tag == JSVAL_TAG_UNDEFINED) {
if (type == JSVAL_TYPE_UNDEFINED) {
unboxed_ins = INS_UNDEFINED();
} else if (tag == JSVAL_TAG_NULL) {
} else if (type == JSVAL_TYPE_NULL) {
unboxed_ins = INS_NULL();
} else if (tag == JSVAL_TAG_STRING || tag == JSVAL_TAG_FUNOBJ || tag == JSVAL_TAG_NONFUNOBJ) {
} else if (type >= JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET) {
unboxed_ins = unpack_ptr(v_ins);
} else {
JS_ASSERT(tag == JSVAL_TAG_INT32 || tag == JSVAL_TAG_BOOLEAN || tag == JSVAL_TAG_MAGIC);
JS_ASSERT(type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN || type == JSVAL_TYPE_MAGIC);
unboxed_ins = lir->ins1(LIR_q2i, v_ins);
}
guard(true, non_double_value_has_tag(v_ins, tag), exit);
guard(true, non_double_object_value_has_type(v_ins, type), exit);
return unboxed_ins;
}
LIns*
TraceRecorder::unbox_object(LIns* v_ins, JSValueType type, VMSideExit* exit)
{
JS_STATIC_ASSERT(JSVAL_TYPE_OBJECT == JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET);
JS_ASSERT(type == JSVAL_TYPE_FUNOBJ || type == JSVAL_TYPE_NONFUNOBJ);
guard(true,
lir->ins2(LIR_geuq, v_ins, INS_CONSTQWORD(JSVAL_SHIFTED_TAG_OBJECT)),
exit);
v_ins = unpack_ptr(v_ins);
if (type == JSVAL_TYPE_FUNOBJ)
guardClass(v_ins, &js_FunctionClass, exit, ACC_OTHER);
else
guardNotClass(v_ins, &js_FunctionClass, exit, ACC_OTHER);
return v_ins;
}
LIns*
TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit,
bool force_double)
@ -9570,7 +9619,7 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM
return unbox_number_as_double(v_ins, exit);
if (v.isInt32()) {
guard(true, non_double_value_has_tag(v_ins, JSVAL_TAG_INT32), exit);
guard(true, non_double_object_value_has_type(v_ins, JSVAL_TYPE_INT32), exit);
return i2d(lir->ins1(LIR_q2i, v_ins));
}
@ -9580,15 +9629,21 @@ TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VM
return lir->insLoad(LIR_ldd, vaddr_ins, offset, accSet);
}
return unbox_non_double(v_ins, v.extractNonDoubleTag(), exit);
if (v.isObject()) {
JSValueType type = v.asObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
return unbox_object(v_ins, type, exit);
}
JSValueType type = v.extractNonDoubleObjectType();
return unbox_non_double_object(v_ins, type, exit);
}
void
TraceRecorder::unbox_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet)
TraceRecorder::unbox_any_object(LIns *vaddr_ins, LIns **obj_ins, LIns **is_obj_ins, AccSet accSet)
{
JS_STATIC_ASSERT(JSVAL_TYPE_OBJECT == JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET);
LIns *v_ins = lir->insLoad(LIR_ldq, vaddr_ins, 0, accSet);
*is_obj_ins = lir->ins2(LIR_geuq, v_ins,
INS_CONSTQWORD(JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_SET));
*is_obj_ins = lir->ins2(LIR_geuq, v_ins, INS_CONSTQWORD(JSVAL_TYPE_OBJECT));
*obj_ins = unpack_ptr(v_ins);
}
@ -9617,15 +9672,16 @@ TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins)
return lir->insLoad(LIR_ldq, tmp, 0, ACC_OTHER);
}
JSValueTag tag = v.extractNonDoubleTag();
if (tag == JSVAL_TAG_NULL)
if (v.isNull())
return INS_CONSTQWORD(JSVAL_BITS(JSVAL_NULL));
if (tag == JSVAL_TAG_UNDEFINED)
if (v.isUndefined())
return INS_CONSTQWORD(JSVAL_BITS(JSVAL_VOID));
JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTag();
uint64 shiftedTag = ((uint64)tag) << JSVAL_TAG_SHIFT;
LIns *shiftedTag_ins = INS_CONSTQWORD(shiftedTag);
if (v.isObject() || v.isString())
if (v.isGCThing())
return lir->ins2(LIR_orq, v_ins, shiftedTag_ins);
return lir->ins2(LIR_orq, lir->ins1(LIR_ui2uq, v_ins), shiftedTag_ins);
}
@ -10822,7 +10878,7 @@ TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[],
JSObject* funobj = &stackval(0 - (2 + argc)).asObject();
if (FUN_SLOW_NATIVE(GET_FUNCTION_PRIVATE(cx, funobj))) {
exit->setNativeCallee(funobj, constructing);
tree->gcthings.addUnique(FunObjTag(*funobj));
tree->gcthings.addUnique(ObjectTag(*funobj));
}
}
@ -10952,7 +11008,7 @@ TraceRecorder::callSpecializedNative(JSNativeTraceInfo *trcinfo, uintN argc,
if (!VALUE_IS_REGEXP(cx, arg))
goto next_specialization;
} else if (argtype == 'f') {
if (!arg.isFunObj())
if (!IsFunctionObject(arg))
goto next_specialization;
} else if (argtype == 'v') {
*argp = box_value_for_native_call(arg, *argp);
@ -11189,7 +11245,7 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
Value& fval = stackval(0 - (2 + argc));
JS_ASSERT(&fval >= cx->fp->base());
if (!fval.isFunObj())
if (!IsFunctionObject(fval))
RETURN_STOP("callee is not a function");
Value& tval = stackval(0 - (1 + argc));
@ -11212,7 +11268,7 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
* Bytecode sequences that push shapeless callees must guard on the callee
* class being Function and the function being interpreted.
*/
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.asFunObj());
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.asObject());
if (FUN_INTERPRETED(fun)) {
if (mode == JSOP_NEW) {
@ -11350,16 +11406,15 @@ TraceRecorder::record_JSOP_TYPEOF()
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_STRING]);
} else if (r.isNumber()) {
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
} else if (r.isFunObj()) {
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_FUNCTION]);
} else if (r.isUndefined()) {
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
} else if (r.isBoolean()) {
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_BOOLEAN]);
} else {
LIns* args[] = { get(&r), cx_ins };
if (r.isBoolean()) {
type = lir->insCall(&js_TypeOfBoolean_ci, args);
if (r.asObject().isFunction()) {
type = INS_ATOM(cx->runtime->atomState.typeAtoms[JSTYPE_FUNCTION]);
} else {
JS_ASSERT(r.isObjectOrNull());
LIns* args[] = { get(&r), cx_ins };
type = lir->insCall(&js_TypeOfObject_ci, args);
}
}
@ -11546,7 +11601,7 @@ MethodWriteBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObjec
{
AutoObjectRooter tvr(cx, funobj);
return obj->scope()->methodWriteBarrier(cx, sprop, FunObjTag(*tvr.object()));
return obj->scope()->methodWriteBarrier(cx, sprop, ObjectTag(*tvr.object()));
}
JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, MethodWriteBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT,
0, ACC_STORE_ANY)
@ -11602,7 +11657,7 @@ TraceRecorder::setProp(Value &l, PropertyCacheEntry* entry, JSScopeProperty* spr
* this, because functions have distinct trace-type from other values and
* branded-ness is implied by the shape, which we've already guarded on.
*/
if (scope->brandedOrHasMethodBarrier() && v.isFunObj() && entry->directHit()) {
if (scope->brandedOrHasMethodBarrier() && IsFunctionObject(v) && entry->directHit()) {
if (obj == globalObj)
RETURN_STOP("can't trace function-valued property set in branded global scope");
@ -12870,7 +12925,7 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc,
tree->gcthings.addUnique(fval);
fi->block = fp->blockChain;
if (fp->blockChain)
tree->gcthings.addUnique(NonFunObjTag(*fp->blockChain));
tree->gcthings.addUnique(ObjectTag(*fp->blockChain));
fi->pc = cx->regs->pc;
fi->imacpc = fp->imacpc;
fi->spdist = cx->regs->sp - fp->slots();
@ -12947,7 +13002,7 @@ TraceRecorder::record_JSOP_APPLY()
JS_ASSERT(!cx->fp->imacpc);
if (!vp[0].isFunObj())
if (!IsFunctionObject(vp[0]))
return record_JSOP_CALL();
RETURN_IF_XML_A(vp[0]);
@ -12970,7 +13025,7 @@ TraceRecorder::record_JSOP_APPLY()
/*
* Guard on the identity of this, which is the function we are applying.
*/
if (!vp[1].isFunObj())
if (!IsFunctionObject(vp[1]))
RETURN_STOP_A("callee is not a function");
CHECK_STATUS_A(guardCallee(vp[1]));
@ -13065,7 +13120,7 @@ TraceRecorder::record_NativeCallComplete()
// v_ins := the object payload from native_rval_ins
// cond_ins := true if native_rval_ins contains a JSObject*
unbox_object(native_rval_ins, &v_ins, &cond_ins, ACC_OTHER);
unbox_any_object(native_rval_ins, &v_ins, &cond_ins, ACC_OTHER);
// x := v_ins if native_rval_ins contains a JSObject*, NULL otherwise
x = lir->insChoose(cond_ins, v_ins, INS_CONSTWORD(0), avmplus::AvmCore::use_cmov());
// v_ins := newobj_ins if native_rval_ins doesn't contain a JSObject*,
@ -13165,12 +13220,12 @@ TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr)
static JSObject* FASTCALL
MethodReadBarrier(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, JSObject* funobj)
{
Value v = FunObjTag(*funobj);
Value v = ObjectTag(*funobj);
AutoValueRooter tvr(cx, v);
if (!obj->scope()->methodReadBarrier(cx, sprop, tvr.addr()))
return NULL;
return &tvr.value().asFunObj();
return &tvr.value().asObject();
}
JS_DEFINE_CALLINFO_4(static, OBJECT_FAIL, MethodReadBarrier, CONTEXT, OBJECT, SCOPEPROP, OBJECT,
0, ACC_STORE_ANY)

View File

@ -1064,8 +1064,10 @@ class TraceRecorder
JS_REQUIRES_STACK void guard(bool expected, nanojit::LIns* cond, VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* guard_xov(nanojit::LOpcode op, nanojit::LIns* d0,
nanojit::LIns* d1, VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* slurpNonDoubleSlot(nanojit::LIns* val_ins, ptrdiff_t offset,
JSValueTag mask, VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* slurpNonDoubleObjectSlot(nanojit::LIns* val_ins, ptrdiff_t offset,
JSValueType type, VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* slurpObjectSlot(nanojit::LIns* val_ins, ptrdiff_t offset,
JSValueType type, VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* slurpDoubleSlot(nanojit::LIns* val_ins, ptrdiff_t offset,
VMSideExit* exit);
JS_REQUIRES_STACK nanojit::LIns* slurpSlot(nanojit::LIns* val_ins, ptrdiff_t offset, Value* vp, VMSideExit* exit);
@ -1272,21 +1274,25 @@ class TraceRecorder
nanojit::LIns* unbox_number_as_double(nanojit::LIns* vaddr_ins, ptrdiff_t offset,
nanojit::LIns* tag_ins, VMSideExit* exit,
nanojit::AccSet);
nanojit::LIns* unbox_non_double(nanojit::LIns* vaddr_ins, ptrdiff_t offset,
nanojit::LIns* tag_ins, JSValueTag tag, VMSideExit* exit,
nanojit::AccSet);
nanojit::LIns* unbox_object(nanojit::LIns* vaddr_ins, ptrdiff_t offset,
nanojit::LIns* tag_ins, JSValueType type, VMSideExit* exit,
nanojit::AccSet);
nanojit::LIns* unbox_non_double_object(nanojit::LIns* vaddr_ins, ptrdiff_t offset,
nanojit::LIns* tag_ins, JSValueType type,
VMSideExit* exit, nanojit::AccSet);
#elif JS_BITS_PER_WORD == 64
nanojit::LIns* non_double_value_has_tag(nanojit::LIns* v_ins, JSValueTag tag);
nanojit::LIns* non_double_object_value_has_type(nanojit::LIns* v_ins, JSValueType type);
nanojit::LIns* unpack_ptr(nanojit::LIns* v_ins);
nanojit::LIns* unbox_number_as_double(nanojit::LIns* v_ins, VMSideExit* exit);
nanojit::LIns* unbox_non_double(nanojit::LIns* v_ins, JSValueTag tag, VMSideExit* exit);
nanojit::LIns* unbox_object(nanojit::LIns* v_ins, JSValueType type, VMSideExit* exit);
nanojit::LIns* unbox_non_double_object(nanojit::LIns* v_ins, JSValueType type, VMSideExit* exit);
#endif
nanojit::LIns* unbox_value(const Value& v, nanojit::LIns* vaddr_ins,
ptrdiff_t offset, VMSideExit* exit,
bool force_double=false);
void unbox_object(nanojit::LIns* vaddr_ins, nanojit::LIns** obj_ins,
nanojit::LIns** is_obj_ins, nanojit::AccSet);
void unbox_any_object(nanojit::LIns* vaddr_ins, nanojit::LIns** obj_ins,
nanojit::LIns** is_obj_ins, nanojit::AccSet);
nanojit::LIns* is_boxed_true(nanojit::LIns* vaddr_ins, nanojit::AccSet);
nanojit::LIns* is_string_id(nanojit::LIns* id_ins);

View File

@ -110,7 +110,7 @@ ArrayBuffer::class_constructor(JSContext *cx, JSObject *obj,
obj = NewObject(cx, &ArrayBuffer::jsclass, NULL, NULL);
if (!obj)
return false;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
return create(cx, obj, argc, argv, rval);
@ -124,7 +124,7 @@ ArrayBuffer::create(JSContext *cx, JSObject *obj,
obj = NewObject(cx, &ArrayBuffer::jsclass, NULL, NULL);
if (!obj)
return false;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
if (argc == 0) {
@ -244,7 +244,7 @@ class TypedArrayGetter {
inline Value
getBuffer(TypedArray *tarray)
{
return NonFunObjTag(*tarray->bufferJS);
return ObjectTag(*tarray->bufferJS);
}
JSBool
@ -719,7 +719,7 @@ class TypedArrayTemplate
obj = NewObject(cx, slowClass(), NULL, NULL);
if (!obj)
return false;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
return create(cx, obj, argc, argv, rval);
@ -732,7 +732,7 @@ class TypedArrayTemplate
obj = NewObject(cx, slowClass(), NULL, NULL);
if (!obj)
return false;
rval->setNonFunObj(*obj);
rval->setObject(*obj);
}
ThisTypeArray *tarray = 0;
@ -878,7 +878,7 @@ class TypedArrayTemplate
makeFastWithPrivate(cx, nobj, ntarray);
vp->setNonFunObj(*nobj);
vp->setObject(*nobj);
return true;
}
@ -1550,15 +1550,15 @@ js_ReparentTypedArrayToScope(JSContext *cx, JSObject *obj, JSObject *scope)
if (!js_GetClassPrototype(cx, scope, key, &proto))
return JS_FALSE;
obj->setProto(NonFunObjTag(*proto));
obj->setParent(NonFunObjTag(*scope));
obj->setProto(ObjectTag(*proto));
obj->setParent(ObjectTag(*scope));
key = JSCLASS_CACHED_PROTO_KEY(&ArrayBuffer::jsclass);
if (!js_GetClassPrototype(cx, scope, key, &proto))
return JS_FALSE;
buffer->setProto(NonFunObjTag(*proto));
buffer->setParent(NonFunObjTag(*scope));
buffer->setProto(ObjectTag(*proto));
buffer->setParent(ObjectTag(*scope));
return JS_TRUE;
}

View File

@ -4598,7 +4598,7 @@ xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len)
xml = vec[i];
if (xml) {
JS_SET_TRACING_INDEX(trc, "xml_vector", i);
MarkRaw(trc, xml, JSTRACE_XML);
Mark(trc, xml, JSTRACE_XML);
}
}
}
@ -4671,7 +4671,7 @@ static JSBool
xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
PropertyOp getter, PropertyOp setter, uintN attrs)
{
if (v->isFunObj() || getter || setter ||
if (IsFunctionObject(*v) || getter || setter ||
(attrs & JSPROP_ENUMERATE) == 0 ||
(attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
return js_DefineProperty(cx, obj, id, v, getter, setter, attrs);
@ -4782,7 +4782,7 @@ xml_defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
if (!obj)
return JS_FALSE;
}
vp->setNonFunObj(*obj);
vp->setObject(*obj);
return JS_TRUE;
}
@ -5041,7 +5041,7 @@ js_ConcatenateXML(JSContext *cx, JSObject *obj, JSObject *robj, Value *vp)
if (!ok)
goto out;
vp->setNonFunObj(*listobj);
vp->setObject(*listobj);
out:
js_LeaveLocalRootScopeWithResult(cx, *vp);
return ok;
@ -5727,7 +5727,7 @@ class AutoNamespaceArray : public js::AutoNamespaces {
JSObject *ns = XMLARRAY_MEMBER(&array, i, JSObject);
if (!ns)
continue;
tvr.addr()->setNonFunObj(*ns);
tvr.addr()->setObject(*ns);
if (!arrayobj->setProperty(context, INT_TO_JSID(i), tvr.addr()))
return false;
}
@ -7188,7 +7188,7 @@ js_GetFunctionNamespace(JSContext *cx, Value *vp)
}
JS_UNLOCK_GC(rt);
}
vp->setNonFunObj(*obj);
vp->setObject(*obj);
return JS_TRUE;
}
@ -7257,7 +7257,7 @@ js_SetDefaultXMLNamespace(JSContext *cx, const Value &v)
fp = js_GetTopStackFrame(cx);
varobj = fp->varobj(cx);
if (!varobj->defineProperty(cx, JSID_DEFAULT_XML_NAMESPACE(), NonFunObjTag(*ns),
if (!varobj->defineProperty(cx, JSID_DEFAULT_XML_NAMESPACE(), ObjectTag(*ns),
PropertyStub, PropertyStub,
JSPROP_PERMANENT)) {
return JS_FALSE;

View File

@ -242,7 +242,7 @@ JSObject::isQName() const
static inline bool
IsXML(const js::Value &v)
{
return v.isNonFunObj() && v.asNonFunObj().isXML();
return v.isObject() && v.asObject().isXML();
}
extern JSObject *

View File

@ -122,6 +122,11 @@ class BaseAssembler : public JSC::MacroAssembler
load32(Address(shape, offsetof(JSObjectMap, shape)), shape);
}
Jump testFunction(Condition cond, RegisterID fun) {
return branchPtr(cond, Address(fun, offsetof(JSObject, clasp)),
ImmPtr(&js_FunctionClass));
}
/*
* Finds and returns the address of a known object and slot.
*/

View File

@ -955,7 +955,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::NewInitObject, Uses(0), Defs(1));
}
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
END_CASE(JSOP_NEWINIT)
@ -1087,7 +1087,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::Lambda, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_FUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
END_CASE(JSOP_LAMBDA)
@ -1123,7 +1123,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::DefLocalFun, Uses(0), Defs(0));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_FUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
frame.storeLocal(slot);
frame.pop();
}
@ -1151,7 +1151,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(regex), Registers::ArgReg1);
stubCall(stubs::RegExp, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
END_CASE(JSOP_REGEXP)
@ -1243,7 +1243,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::NewArray, Uses(len), Defs(1));
frame.popn(len);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
END_CASE(JSOP_NEWARRAY)
@ -1254,7 +1254,7 @@ mjit::Compiler::generateMethod()
masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stubs::FlatLambda, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_FUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
END_CASE(JSOP_LAMBDA_FC)
@ -1491,9 +1491,8 @@ mjit::Compiler::emitReturn()
Jump j = stubcc.masm.jump();
/* if (arguments) ... */
Jump argsObj = masm.branch32(Assembler::Equal,
masm.tagOf(Address(JSFrameReg, offsetof(JSStackFrame, argsval))),
ImmTag(JSVAL_TAG_NONFUNOBJ));
Jump argsObj = masm.testObject(Assembler::Equal,
Address(JSFrameReg, offsetof(JSStackFrame, argsval)));
stubcc.linkExit(argsObj);
stubcc.call(stubs::PutArgsObject);
stubcc.rejoin(0);
@ -1556,7 +1555,7 @@ mjit::Compiler::inlineCallHelper(uint32 argc, bool callingNew)
FrameEntry *fe = frame.peek(-int(argc + 2));
bool typeKnown = fe->isTypeKnown();
if (typeKnown && fe->getTypeTag() != JSVAL_TAG_FUNOBJ) {
if (typeKnown && fe->getTypeTag() != JSVAL_TAG_OBJECT) {
VoidPtrStubUInt32 stub = callingNew ? stubs::SlowNew : stubs::SlowCall;
masm.move(Imm32(argc), Registers::ArgReg1);
masm.stubCall(stub, PC, frame.stackDepth() + script->nfixed);
@ -1592,11 +1591,13 @@ mjit::Compiler::inlineCallHelper(uint32 argc, bool callingNew)
if (!typeKnown) {
Jump j;
if (!hasTypeReg)
j = masm.testFunObj(Assembler::NotEqual, frame.addressOf(fe));
j = masm.testObject(Assembler::NotEqual, frame.addressOf(fe));
else
j = masm.testFunObj(Assembler::NotEqual, type);
j = masm.testObject(Assembler::NotEqual, type);
invoke = stubcc.masm.label();
stubcc.linkExit(j);
j = masm.testFunction(Assembler::NotEqual, data);
stubcc.linkExit(j);
stubcc.leave();
stubcc.masm.move(Imm32(argc), Registers::ArgReg1);
stubcc.call(callingNew ? stubs::SlowNew : stubs::SlowCall);
@ -1871,10 +1872,7 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
FrameEntry *top = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */
if (top->isTypeKnown() &&
(top->getTypeTag() != JSVAL_TAG_FUNOBJ &&
top->getTypeTag() != JSVAL_TAG_NONFUNOBJ))
{
if (top->isTypeKnown() && top->getTypeTag() != JSVAL_TAG_OBJECT) {
JS_ASSERT_IF(atom == cx->runtime->atomState.lengthAtom,
top->getTypeTag() != JSVAL_TAG_STRING);
jsop_getprop_slow();
@ -1898,13 +1896,12 @@ mjit::Compiler::jsop_getprop(JSAtom *atom, bool doTypeCheck)
/* Guard that the type is an object. */
Jump typeCheck;
if (doTypeCheck && !top->isTypeKnown()) {
JS_STATIC_ASSERT(JSVAL_TAG_NONFUNOBJ < JSVAL_TAG_FUNOBJ);
RegisterID reg = frame.tempRegForType(top);
pic.typeReg = reg;
/* Start the hot path where it's easy to patch it. */
pic.hotPathBegin = masm.label();
Jump j = masm.branch32(Assembler::Below, reg, ImmTag(JSVAL_TAG_NONFUNOBJ));
Jump j = masm.testObject(Assembler::NotEqual, reg);
pic.typeCheck = stubcc.masm.label();
stubcc.linkExit(j);
@ -1974,7 +1971,6 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
PICGenInfo pic(ic::PICInfo::CALL);
/* Guard that the type is an object. */
JS_STATIC_ASSERT(JSVAL_TAG_NONFUNOBJ < JSVAL_TAG_FUNOBJ);
pic.typeReg = frame.copyTypeIntoReg(top);
/* Start the hot path where it's easy to patch it. */
@ -1986,7 +1982,7 @@ mjit::Compiler::jsop_callprop_generic(JSAtom *atom)
* path to the final call. We need a label in between that jump, which
* will be the target of patched jumps in the PIC.
*/
Jump typeCheck = masm.branch32(Assembler::Below, pic.typeReg, ImmTag(JSVAL_TAG_NONFUNOBJ));
Jump typeCheck = masm.testObject(Assembler::NotEqual, pic.typeReg);
stubcc.linkExit(typeCheck);
stubcc.leave();
Jump typeCheckDone = stubcc.masm.jump();
@ -2060,7 +2056,7 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
/* Force into a register because getprop won't expect a constant. */
RegisterID reg = frame.allocReg();
masm.move(ImmPtr(obj), reg);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, reg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg);
/* Get the property. */
jsop_getprop(atom);
@ -2075,9 +2071,11 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
JS_ASSERT(!funFe->isTypeKnown());
RegisterID temp = frame.allocReg();
Jump notFun = frame.testFunObj(Assembler::NotEqual, funFe);
Address fslot(frame.tempRegForData(funFe),
offsetof(JSObject, fslots) + JSSLOT_PRIVATE * sizeof(Value));
RegisterID funReg = frame.copyDataIntoReg(funFe);
Jump notFun1 = frame.testObject(Assembler::NotEqual, funFe);
Jump notFun2 = masm.testFunction(Assembler::NotEqual, funReg);
Address fslot(funReg, offsetof(JSObject, fslots) + JSSLOT_PRIVATE * sizeof(Value));
masm.loadData32(fslot, temp);
masm.load16(Address(temp, offsetof(JSFunction, flags)), temp);
masm.and32(Imm32(JSFUN_THISP_STRING), temp);
@ -2088,8 +2086,10 @@ mjit::Compiler::jsop_callprop_str(JSAtom *atom)
stubcc.call(stubs::WrapPrimitiveThis);
}
frame.freeReg(funReg);
frame.freeReg(temp);
notFun.linkTo(masm.label(), &masm);
notFun2.linkTo(masm.label(), &masm);
notFun1.linkTo(masm.label(), &masm);
stubcc.rejoin(1);
@ -2104,8 +2104,7 @@ mjit::Compiler::jsop_callprop_obj(JSAtom *atom)
PICGenInfo pic(ic::PICInfo::CALL);
JS_ASSERT(top->isTypeKnown());
JS_ASSERT(top->getTypeTag() == JSVAL_TAG_FUNOBJ ||
top->getTypeTag() == JSVAL_TAG_NONFUNOBJ);
JS_ASSERT(top->getTypeTag() == JSVAL_TAG_OBJECT);
pic.hotPathBegin = masm.label();
pic.hasTypeCheck = false;
@ -2167,10 +2166,7 @@ mjit::Compiler::jsop_callprop(JSAtom *atom)
FrameEntry *top = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */
if (top->isTypeKnown() &&
(top->getTypeTag() != JSVAL_TAG_FUNOBJ &&
top->getTypeTag() != JSVAL_TAG_NONFUNOBJ))
{
if (top->isTypeKnown() && top->getTypeTag() != JSVAL_TAG_OBJECT) {
if (top->getTypeTag() == JSVAL_TAG_STRING)
return jsop_callprop_str(atom);
return jsop_callprop_slow(atom);
@ -2188,10 +2184,7 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
FrameEntry *rhs = frame.peek(-1);
/* If the incoming type will never PIC, take slow path. */
if (lhs->isTypeKnown() &&
(lhs->getTypeTag() != JSVAL_TAG_FUNOBJ &&
lhs->getTypeTag() != JSVAL_TAG_NONFUNOBJ))
{
if (lhs->isTypeKnown() && lhs->getTypeTag() != JSVAL_TAG_OBJECT) {
jsop_setprop_slow(atom);
return;
}
@ -2202,13 +2195,12 @@ mjit::Compiler::jsop_setprop(JSAtom *atom)
/* Guard that the type is an object. */
Jump typeCheck;
if (!lhs->isTypeKnown()) {
JS_STATIC_ASSERT(JSVAL_TAG_NONFUNOBJ < JSVAL_TAG_FUNOBJ);
RegisterID reg = frame.tempRegForType(lhs);
pic.typeReg = reg;
/* Start the hot path where it's easy to patch it. */
pic.hotPathBegin = masm.label();
Jump j = masm.branch32(Assembler::Below, reg, ImmTag(JSVAL_TAG_NONFUNOBJ));
Jump j = masm.branch32(Assembler::NotEqual, reg, ImmTag(JSVAL_TAG_OBJECT));
pic.typeCheck = stubcc.masm.label();
stubcc.linkExit(j);
@ -2337,13 +2329,25 @@ mjit::Compiler::jsop_getarg(uint32 index)
void
mjit::Compiler::jsop_this()
{
frame.push(Address(JSFrameReg, offsetof(JSStackFrame, thisv)));
FrameEntry *thisv = frame.peek(-1);
Jump null = frame.testNull(Assembler::Equal, thisv);
stubcc.linkExit(null);
stubcc.leave();
stubcc.call(stubs::This);
stubcc.rejoin(1);
Address thisvAddr(JSFrameReg, offsetof(JSStackFrame, thisv));
if (0 && !script->strictModeCode) {
Jump null = masm.testNull(Assembler::Equal, thisvAddr);
stubcc.linkExit(null);
stubcc.leave();
stubcc.call(stubs::ComputeThis);
stubcc.rejoin(0);
RegisterID reg = frame.allocReg();
masm.loadData32(thisvAddr, reg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg);
} else {
frame.push(thisvAddr);
Jump null = frame.testNull(Assembler::Equal, frame.peek(-1));
stubcc.linkExit(null);
stubcc.leave();
stubcc.call(stubs::This);
stubcc.rejoin(1);
}
}
void
@ -2564,7 +2568,7 @@ void
mjit::Compiler::jsop_bindgname()
{
if (script->compileAndGo && globalObj) {
frame.push(NonFunObjTag(*globalObj));
frame.push(ObjectTag(*globalObj));
return;
}
@ -2572,7 +2576,7 @@ mjit::Compiler::jsop_bindgname()
prepareStubCall();
stubCall(stubs::BindGlobalName, Uses(0), Defs(1));
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, Registers::ReturnReg);
}
void
@ -2582,7 +2586,7 @@ mjit::Compiler::jsop_getgname(uint32 index)
jsop_bindgname();
FrameEntry *fe = frame.peek(-1);
JS_ASSERT(fe->isTypeKnown() && fe->getTypeTag() == JSVAL_TAG_NONFUNOBJ);
JS_ASSERT(fe->isTypeKnown() && fe->getTypeTag() == JSVAL_TAG_OBJECT);
MICGenInfo mic;
RegisterID objReg;
@ -2658,7 +2662,7 @@ mjit::Compiler::jsop_setgname(uint32 index)
{
#if ENABLE_MIC
FrameEntry *objFe = frame.peek(-2);
JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getTypeTag() == JSVAL_TAG_NONFUNOBJ);
JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getTypeTag() == JSVAL_TAG_OBJECT);
MICGenInfo mic;
RegisterID objReg;
@ -2787,7 +2791,7 @@ mjit::Compiler::jsop_instanceof()
* thus have fun_instanceOf, which we're inlining.
*/
if (rhs->isTypeKnown() && rhs->getTypeTag() != JSVAL_TAG_FUNOBJ) {
if (rhs->isTypeKnown() && rhs->getTypeTag() != JSVAL_TAG_OBJECT) {
prepareStubCall();
stubCall(stubs::InstanceOf, Uses(2), Defs(1));
frame.popn(2);
@ -2799,7 +2803,10 @@ mjit::Compiler::jsop_instanceof()
Jump firstSlow;
bool typeKnown = rhs->isTypeKnown();
if (!typeKnown) {
Jump j = frame.testFunObj(Assembler::NotEqual, rhs);
Jump j = frame.testObject(Assembler::NotEqual, rhs);
stubcc.linkExit(j);
RegisterID reg = frame.tempRegForData(rhs);
j = masm.testFunction(Assembler::NotEqual, reg);
stubcc.linkExit(j);
stubcc.leave();
stubcc.call(stubs::InstanceOf);

View File

@ -527,21 +527,12 @@ FrameState::testPrimitive(Assembler::Condition cond, FrameEntry *fe)
}
inline JSC::MacroAssembler::Jump
FrameState::testNonFunObj(Assembler::Condition cond, FrameEntry *fe)
FrameState::testObject(Assembler::Condition cond, FrameEntry *fe)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
if (shouldAvoidTypeRemat(fe))
return masm.testNonFunObj(cond, addressOf(fe));
return masm.testNonFunObj(cond, tempRegForType(fe));
}
inline JSC::MacroAssembler::Jump
FrameState::testFunObj(Assembler::Condition cond, FrameEntry *fe)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
if (shouldAvoidTypeRemat(fe))
return masm.testFunObj(cond, addressOf(fe));
return masm.testFunObj(cond, tempRegForType(fe));
return masm.testObject(cond, addressOf(fe));
return masm.testObject(cond, tempRegForType(fe));
}
inline JSC::MacroAssembler::Jump

View File

@ -451,13 +451,7 @@ class FrameState
* Helper function. Tests if a slot's type is a non-funobj. Condition should
* be Equal or NotEqual.
*/
inline Jump testNonFunObj(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is a funobj. Condition should
* be Equal or NotEqual.
*/
inline Jump testFunObj(Assembler::Condition cond, FrameEntry *fe);
inline Jump testObject(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is primitve. Condition should

View File

@ -170,7 +170,7 @@ CreateFrame(VMFrame &f, uint32 flags, uint32 argc)
JSContext *cx = f.cx;
JSStackFrame *fp = f.fp;
Value *vp = f.regs.sp - (argc + 2);
JSObject *funobj = &vp->asFunObj();
JSObject *funobj = &vp->asObject();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
JS_ASSERT(FUN_INTERPRETED(fun));
@ -211,7 +211,7 @@ CreateFrame(VMFrame &f, uint32 flags, uint32 argc)
newfp->argv = vp + 2;
newfp->rval.setUndefined();
newfp->annotation = NULL;
newfp->scopeChain.setNonFunObj(*funobj->getParent());
newfp->scopeChain.setObject(*funobj->getParent());
newfp->flags = flags;
newfp->blockChain = NULL;
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
@ -341,9 +341,9 @@ InlineConstruct(VMFrame &f, uint32 argc)
JSContext *cx = f.cx;
Value *vp = f.regs.sp - (argc + 2);
JS_ASSERT(vp[0].isFunObj());
JSObject *funobj = &vp[0].asObject();
JS_ASSERT(funobj->isFunction());
JSObject *funobj = &vp[0].asFunObj();
jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
if (!funobj->getProperty(cx, id, &vp[1]))
return NULL;
@ -358,8 +358,8 @@ stubs::SlowCall(VMFrame &f, uint32 argc)
JSContext *cx = f.cx;
Value *vp = f.regs.sp - (argc + 2);
if (vp->isFunObj()) {
JSObject *obj = &vp->asFunObj();
JSObject *obj;
if (IsFunctionObject(*vp, &obj)) {
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
if (fun->isInterpreted()) {
@ -397,8 +397,8 @@ stubs::SlowNew(VMFrame &f, uint32 argc)
JSContext *cx = f.cx;
Value *vp = f.regs.sp - (argc + 2);
if (vp->isFunObj()) {
JSObject *obj = &vp->asFunObj();
JSObject *obj;
if (IsFunctionObject(*vp, &obj)) {
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
if (fun->isInterpreted()) {
@ -408,7 +408,7 @@ stubs::SlowNew(VMFrame &f, uint32 argc)
THROWV(NULL);
if (script->isEmpty()) {
vp[0].setNonFunObj(*obj2);
vp[0].setObject(*obj2);
return NULL;
}
@ -432,7 +432,7 @@ CreateLightFrame(VMFrame &f, uint32 flags, uint32 argc)
JSContext *cx = f.cx;
JSStackFrame *fp = f.fp;
Value *vp = f.regs.sp - (argc + 2);
JSObject *funobj = &vp->asFunObj();
JSObject *funobj = &vp->asObject();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
JS_ASSERT(FUN_INTERPRETED(fun));
@ -473,7 +473,7 @@ CreateLightFrame(VMFrame &f, uint32 flags, uint32 argc)
newfp->argv = vp + 2;
newfp->rval.setUndefined();
newfp->annotation = NULL;
newfp->scopeChain.setNonFunObj(*funobj->getParent());
newfp->scopeChain.setObject(*funobj->getParent());
newfp->flags = flags;
newfp->blockChain = NULL;
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
@ -526,7 +526,7 @@ stubs::New(VMFrame &f, uint32 argc)
if (!obj)
THROWV(NULL);
f.regs.sp[-int(argc + 1)].setNonFunObj(*obj);
f.regs.sp[-int(argc + 1)].setObject(*obj);
if (!CreateLightFrame(f, JSFRAME_CONSTRUCTING, argc))
THROWV(NULL);
@ -546,7 +546,7 @@ stubs::PutCallObject(VMFrame &f)
void JS_FASTCALL
stubs::PutArgsObject(VMFrame &f)
{
JS_ASSERT(f.fp->argsval.isNonFunObj());
JS_ASSERT(f.fp->argsval.isObject());
js_PutArgsObject(f.cx, f.fp);
}

View File

@ -310,7 +310,10 @@ class SetPropCompiler : public PICStubCompiler
JSScope *scope = obj->scope();
if (scope->brandedOrHasMethodBarrier()) {
masm.loadTypeTag(address, pic.shapeReg);
rebrand = masm.branch32(Assembler::Equal, pic.shapeReg, ImmTag(JSVAL_TAG_FUNOBJ));
Jump skip = masm.testObject(Assembler::NotEqual, pic.shapeReg);
masm.loadData32(address, pic.shapeReg);
rebrand = masm.testFunction(Assembler::Equal, pic.shapeReg);
skip.linkTo(masm.label(), &masm);
}
if (pic.u.vr.isConstant) {
@ -1006,7 +1009,7 @@ ic::CallProp(VMFrame &f, uint32 index)
JSObject *pobj;
if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
THROW();
objv.setNonFunObj(*pobj);
objv.setObject(*pobj);
}
JSObject *aobj = js_GetProtoIfDenseArray(&objv.asObject());
@ -1020,7 +1023,7 @@ ic::CallProp(VMFrame &f, uint32 index)
JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
if (!atom) {
if (entry->vword.isFunObj()) {
rval.setFunObj(entry->vword.toFunObj());
rval.setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -1071,8 +1074,9 @@ ic::CallProp(VMFrame &f, uint32 index)
/* Wrap primitive lval in object clothing if necessary. */
if (lval.isPrimitive()) {
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
if (!rval.isFunObj() ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, &rval.asFunObj()), lval)) {
JSObject *funobj;
if (!IsFunctionObject(rval, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
THROW();
usePIC = false;

View File

@ -93,7 +93,7 @@ mjit::stubs::BindName(VMFrame &f)
THROW();
}
f.regs.sp++;
f.regs.sp[-1].setNonFunObj(*obj);
f.regs.sp[-1].setObject(*obj);
}
JSObject * JS_FASTCALL
@ -338,7 +338,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
if (!atom) {
if (entry->vword.isFunObj()) {
f.regs.sp++;
f.regs.sp[-1].setFunObj(entry->vword.toFunObj());
f.regs.sp[-1].setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uintN slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -416,7 +416,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
return NULL;
}
f.regs.sp++;
f.regs.sp[-1].setNonFunObjOrNull(thisp);
f.regs.sp[-1].setObjectOrNull(thisp);
}
return obj;
}
@ -876,7 +876,7 @@ stubs::DefFun(VMFrame &f, uint32 index)
fp->setScopeChainObj(obj);
Value rval;
rval.setFunObj(*obj);
rval.setObject(*obj);
/*
* ECMA requires functions defined when entering Eval code to be
@ -1057,15 +1057,15 @@ StubEqualityOp(VMFrame &f)
JSBool cond;
#if JS_HAS_XML_SUPPORT
if ((lval.isNonFunObj() && lval.asObject().isXML()) ||
(rval.isNonFunObj() && rval.asObject().isXML())) {
if ((lval.isObject() && lval.asObject().isXML()) ||
(rval.isObject() && rval.asObject().isXML())) {
if (!js_TestXMLEquality(cx, lval, rval, &cond))
return false;
cond = cond == EQ;
} else
#endif
if (SamePrimitiveTypeOrBothObjects(lval, rval)) {
if (SameType(lval, rval)) {
if (lval.isString()) {
JSString *l = lval.asString();
JSString *r = rval.asString();
@ -1175,8 +1175,8 @@ stubs::Add(VMFrame &f)
regs.sp[-1].setInt32(sum);
} else
#if JS_HAS_XML_SUPPORT
if (lval.isNonFunObj() && lval.asObject().isXML() &&
rval.isNonFunObj() && rval.asObject().isXML()) {
if (lval.isObject() && lval.asObject().isXML() &&
rval.isObject() && rval.asObject().isXML()) {
if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
THROW();
regs.sp--;
@ -1338,6 +1338,13 @@ stubs::This(VMFrame &f)
f.regs.sp[-1] = f.fp->thisv;
}
void JS_FASTCALL
stubs::ComputeThis(VMFrame &f)
{
if (!f.fp->getThisObject(f.cx))
THROW();
}
void JS_FASTCALL
stubs::Neg(VMFrame &f)
{
@ -1816,7 +1823,7 @@ InlineGetProp(VMFrame &f)
JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
if (!atom) {
if (entry->vword.isFunObj()) {
rval.setFunObj(entry->vword.toFunObj());
rval.setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -1882,7 +1889,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
JSObject *pobj;
if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
THROW();
objv.setNonFunObj(*pobj);
objv.setObject(*pobj);
}
JSObject *aobj = js_GetProtoIfDenseArray(&objv.asObject());
@ -1894,7 +1901,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
JS_PROPERTY_CACHE(cx).test(cx, regs.pc, aobj, obj2, entry, atom);
if (!atom) {
if (entry->vword.isFunObj()) {
rval.setFunObj(entry->vword.toFunObj());
rval.setObject(entry->vword.toFunObj());
} else if (entry->vword.isSlot()) {
uint32 slot = entry->vword.toSlot();
JS_ASSERT(slot < obj2->scope()->freeslot);
@ -1945,8 +1952,9 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
/* Wrap primitive lval in object clothing if necessary. */
if (lval.isPrimitive()) {
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
if (!rval.isFunObj() ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, &rval.asFunObj()), lval)) {
JSObject *funobj;
if (!IsFunctionObject(rval, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
THROW();
}
@ -1970,8 +1978,9 @@ stubs::WrapPrimitiveThis(VMFrame &f)
JS_ASSERT(thisv.isPrimitive());
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
if (!funv.isFunObj() ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, &funv.asFunObj()), thisv)) {
JSObject *funobj;
if (!IsFunctionObject(funv, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), thisv)) {
if (!js_PrimitiveToObject(cx, &f.regs.sp[-1]))
THROW();
}

View File

@ -48,6 +48,7 @@ namespace mjit {
namespace stubs {
void JS_FASTCALL This(VMFrame &f);
void JS_FASTCALL ComputeThis(VMFrame &f);
JSObject * JS_FASTCALL NewInitArray(VMFrame &f);
JSObject * JS_FASTCALL NewInitObject(VMFrame &f, uint32 empty);
JSObject * JS_FASTCALL NewArray(VMFrame &f, uint32 len);

View File

@ -173,28 +173,20 @@ class Assembler : public BaseAssembler
Jump testPrimitive(Assembler::Condition cond, RegisterID reg) {
cond = (cond == Assembler::NotEqual) ? Assembler::AboveOrEqual : Assembler::Below;
return branch32(cond, reg, ImmTag(JSVAL_TAG_NONFUNOBJ));
return branch32(cond, reg, ImmTag(JSVAL_TAG_OBJECT));
}
Jump testPrimitive(Assembler::Condition cond, Address address) {
cond = (cond == Assembler::NotEqual) ? Assembler::AboveOrEqual : Assembler::Below;
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_NONFUNOBJ));
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_OBJECT));
}
Jump testNonFunObj(Assembler::Condition cond, RegisterID reg) {
return branch32(cond, reg, ImmTag(JSVAL_TAG_NONFUNOBJ));
Jump testObject(Assembler::Condition cond, RegisterID reg) {
return branch32(cond, reg, ImmTag(JSVAL_TAG_OBJECT));
}
Jump testNonFunObj(Assembler::Condition cond, Address address) {
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_NONFUNOBJ));
}
Jump testFunObj(Assembler::Condition cond, RegisterID reg) {
return branch32(cond, reg, ImmTag(JSVAL_TAG_FUNOBJ));
}
Jump testFunObj(Assembler::Condition cond, Address address) {
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_FUNOBJ));
Jump testObject(Assembler::Condition cond, Address address) {
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_OBJECT));
}
Jump testDouble(Assembler::Condition cond, RegisterID reg) {

View File

@ -65,7 +65,7 @@ mjit::Compiler::jsop_bindname(uint32 index)
stubcc.leave();
stubcc.call(stubs::BindName);
frame.pushTypedPayload(JSVAL_TAG_NONFUNOBJ, reg);
frame.pushTypedPayload(JSVAL_TAG_OBJECT, reg);
stubcc.rejoin(1);
}
@ -681,8 +681,7 @@ mjit::Compiler::jsop_not()
break;
}
case JSVAL_TAG_NONFUNOBJ:
case JSVAL_TAG_FUNOBJ:
case JSVAL_TAG_OBJECT:
{
frame.pop();
frame.push(BooleanTag(false));
@ -776,8 +775,7 @@ mjit::Compiler::jsop_typeof()
case JSVAL_TAG_NULL:
atom = rt->atomState.typeAtoms[JSTYPE_OBJECT];
break;
case JSVAL_TAG_FUNOBJ:
case JSVAL_TAG_NONFUNOBJ:
case JSVAL_TAG_OBJECT:
atom = NULL;
break;
case JSVAL_TAG_BOOLEAN:
@ -923,7 +921,7 @@ mjit::Compiler::jsop_setelem()
FrameEntry *id = frame.peek(-2);
FrameEntry *fe = frame.peek(-1);
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_NONFUNOBJ) ||
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_OBJECT) ||
(id->isTypeKnown() && id->getTypeTag() != JSVAL_TAG_INT32) ||
(id->isConstant() && id->getValue().asInt32() < 0)) {
jsop_setelem_slow();
@ -936,9 +934,9 @@ mjit::Compiler::jsop_setelem()
stubcc.linkExit(j);
}
/* obj.isNonFunObj() */
/* obj.isObject() */
if (!obj->isTypeKnown()) {
Jump j = frame.testNonFunObj(Assembler::NotEqual, obj);
Jump j = frame.testObject(Assembler::NotEqual, obj);
stubcc.linkExit(j);
}
@ -1027,7 +1025,7 @@ mjit::Compiler::jsop_getelem()
FrameEntry *obj = frame.peek(-2);
FrameEntry *id = frame.peek(-1);
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_NONFUNOBJ) ||
if ((obj->isTypeKnown() && obj->getTypeTag() != JSVAL_TAG_OBJECT) ||
(id->isTypeKnown() && id->getTypeTag() != JSVAL_TAG_INT32) ||
(id->isConstant() && id->getValue().asInt32() < 0)) {
jsop_getelem_slow();
@ -1042,7 +1040,7 @@ mjit::Compiler::jsop_getelem()
/* obj.isNonFunObj() */
if (!obj->isTypeKnown()) {
Jump j = frame.testNonFunObj(Assembler::NotEqual, obj);
Jump j = frame.testObject(Assembler::NotEqual, obj);
stubcc.linkExit(j);
}