diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 6baec5f9c52..0b5967765d6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -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; } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 9b316d1e873..99d8822ee37 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -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 { diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index cb90ddc5904..f6e8af2af71 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -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(&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; diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 7635026db63..fa7aa82cc64 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -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; } diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index d9f34d09a76..dfd0b38efab 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -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) { diff --git a/js/src/jsbuiltins.h b/js/src/jsbuiltins.h index d3e2dbebb5a..5e30b326752 100644 --- a/js/src/jsbuiltins.h +++ b/js/src/jsbuiltins.h @@ -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) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 9f8d778d501..4205d112174 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -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) diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index afbfdcfa6d7..d42029fa6e6 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -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; diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index c2941257d31..396fa4401db 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -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); } /* diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 5f176d30767..e1b3af9b78b 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -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 { diff --git a/js/src/jsfun.h b/js/src/jsfun.h index d878bb6b8ad..11506f160d3 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -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 diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index b709edd544a..71af04fb6f5 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -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(entry.key)); + MarkGCThing(trc, *reinterpret_cast(entry.key)); else MarkValueRaw(trc, *reinterpret_cast(entry.key)); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index c0b083ef4e5..273cab74524 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -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 * diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 486854ffcb4..272e3895301 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -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()); } } diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index c97ae90e60e..1e96f6550c2 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -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() { diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index d500501e224..ceeeaeadb9a 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -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; } } diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 5b0086ed6b0..d3dfec46f7c 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -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"); diff --git a/js/src/jsobj.h b/js/src/jsobj.h index f174edeedf1..5c712da957b 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -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 \ diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index dcd8e444b2f..54a7ce80745 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -187,7 +187,7 @@ BEGIN_CASE(JSOP_ENTERWITH) END_CASE(JSOP_ENTERWITH) BEGIN_CASE(JSOP_LEAVEWITH) - JS_ASSERT(®s.sp[-1].asNonFunObj() == fp->scopeChainObj()); + JS_ASSERT(®s.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, ®s.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; diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index 674a10d7a24..0b46fa958f4 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -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; diff --git a/js/src/jspropertycache.cpp b/js/src/jspropertycache.cpp index c4de4426aaa..4f6553d28ef 100644 --- a/js/src/jspropertycache.cpp +++ b/js/src/jspropertycache.cpp @@ -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; } } diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 1a1f52ab442..c20892c88d1 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -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; } diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index ff8a81b9e96..187f98fc797 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -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___ */ diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 0ea4150f08d..f03ea78b1a8 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -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 diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 75d882b33df..535d939954b 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -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); } diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 55b07d34995..9e12189d592 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -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); } } diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 3b2fd91f961..fe19ec5d9e1 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -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); diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 056264631c0..25632a54523 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -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 diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index f3624495105..55804038b54 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -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) diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 64db8dddace..31f93e1c5ae 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -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; } diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 4e75b4cb499..4762afcd5bd 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -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) diff --git a/js/src/jstracer.h b/js/src/jstracer.h index d39c005f4a2..cbb85339b9f 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -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); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index 9ce44f08594..03e888ce9d1 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -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; } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 79e12719def..eb0af6f9ab5 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -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; diff --git a/js/src/jsxml.h b/js/src/jsxml.h index bdbda2232a5..27360f25526 100644 --- a/js/src/jsxml.h +++ b/js/src/jsxml.h @@ -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 * diff --git a/js/src/methodjit/BaseAssembler.h b/js/src/methodjit/BaseAssembler.h index 4abc6cf7c38..27e55681453 100644 --- a/js/src/methodjit/BaseAssembler.h +++ b/js/src/methodjit/BaseAssembler.h @@ -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. */ diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 1cf7e8056d2..edd26d6d623 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -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); diff --git a/js/src/methodjit/FrameState-inl.h b/js/src/methodjit/FrameState-inl.h index 7440cc47a9b..f412ec79d10 100644 --- a/js/src/methodjit/FrameState-inl.h +++ b/js/src/methodjit/FrameState-inl.h @@ -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 diff --git a/js/src/methodjit/FrameState.h b/js/src/methodjit/FrameState.h index c9cf34f1602..f7c755bef6e 100644 --- a/js/src/methodjit/FrameState.h +++ b/js/src/methodjit/FrameState.h @@ -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 diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 9f1fcb8663d..f98301dd5ee 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -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); } diff --git a/js/src/methodjit/PolyIC.cpp b/js/src/methodjit/PolyIC.cpp index a68e214c352..71e39d58cd9 100644 --- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -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, ®s.sp[-1])) THROW(); usePIC = false; diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 5ea313048cb..36c7967c425 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -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, ®s.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(); } diff --git a/js/src/methodjit/StubCalls.h b/js/src/methodjit/StubCalls.h index 530594fdbbc..228c373fcc5 100644 --- a/js/src/methodjit/StubCalls.h +++ b/js/src/methodjit/StubCalls.h @@ -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); diff --git a/js/src/methodjit/nunbox/Assembler.h b/js/src/methodjit/nunbox/Assembler.h index d56bbb3ded5..386cc2feba1 100644 --- a/js/src/methodjit/nunbox/Assembler.h +++ b/js/src/methodjit/nunbox/Assembler.h @@ -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) { diff --git a/js/src/methodjit/nunbox/FastOps.cpp b/js/src/methodjit/nunbox/FastOps.cpp index af801e8d12b..91118eeb045 100644 --- a/js/src/methodjit/nunbox/FastOps.cpp +++ b/js/src/methodjit/nunbox/FastOps.cpp @@ -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); }