Bug 679879 - Change JSFunction macros to methods. Part 2, js/src changes. r=Waldo.
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 18 Aug 2011 12:39:44 -0500
changeset 75501 1dccbc1234f4b8869449c0242f8d4f9e3052162e
parent 75500 a5c778f36c33c585196dabc198cbe7ea94fd37a6
child 75502 5691363f380fe07517235de738216fb40837fb1b
push idunknown
push userunknown
push dateunknown
reviewersWaldo
bugs679879
milestone9.0a1
Bug 679879 - Change JSFunction macros to methods. Part 2, js/src changes. r=Waldo.
js/src/jsapi-tests/testLookup.cpp
js/src/jsapi.cpp
js/src/jsbuiltins.cpp
js/src/jscntxt.cpp
js/src/jsdbgapi.cpp
js/src/jsemit.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsfuninlines.h
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsparse.cpp
js/src/jsprobes.cpp
js/src/jspropertycache.cpp
js/src/jsscript.cpp
js/src/jsscriptinlines.h
js/src/jstracer.cpp
js/src/jsxml.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/js.cpp
js/src/vm/GlobalObject.cpp
js/src/xpconnect/src/xpcwrappednativejsops.cpp
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -21,17 +21,17 @@ BEGIN_TEST(testLookup_bug522590)
 
     // This lookup must not return an internal function object.
     jsvalRoot r(cx);
     CHECK(JS_LookupProperty(cx, xobj, "f", r.addr()));
     CHECK(JSVAL_IS_OBJECT(r));
     JSObject *funobj = JSVAL_TO_OBJECT(r);
     CHECK(funobj->isFunction());
     CHECK(!js::IsInternalFunctionObject(funobj));
-    CHECK(GET_FUNCTION_PRIVATE(cx, funobj) != (JSFunction *) funobj);
+    CHECK(funobj->getFunctionPrivate() != (JSFunction *) funobj);
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 JSBool
 document_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
 {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -338,17 +338,17 @@ JS_ConvertArgumentsVA(JSContext *cx, uin
             *sp = OBJECT_TO_JSVAL(obj);
             *va_arg(ap, JSObject **) = obj;
             break;
           case 'f':
             obj = js_ValueToFunctionObject(cx, Valueify(sp), 0);
             if (!obj)
                 return JS_FALSE;
             *sp = OBJECT_TO_JSVAL(obj);
-            *va_arg(ap, JSFunction **) = GET_FUNCTION_PRIVATE(cx, obj);
+            *va_arg(ap, JSFunction **) = obj->getFunctionPrivate();
             break;
           case 'v':
             *va_arg(ap, jsval *) = *sp;
             break;
           case '*':
             break;
           default:
             format--;
@@ -2265,20 +2265,20 @@ JS_PrintTraceThingInfo(char *buf, size_t
         bufsize--;
 
         switch (kind) {
           case JSTRACE_OBJECT:
           {
             JSObject  *obj = (JSObject *)thing;
             Class *clasp = obj->getClass();
             if (clasp == &js_FunctionClass) {
-                JSFunction *fun = GET_FUNCTION_PRIVATE(trc->context, obj);
+                JSFunction *fun = obj->getFunctionPrivate();
                 if (!fun) {
                     JS_snprintf(buf, bufsize, "<newborn>");
-                } else if (FUN_OBJECT(fun) != obj) {
+                } else if (fun != obj) {
                     JS_snprintf(buf, bufsize, "%p", fun);
                 } else {
                     if (fun->atom)
                         PutEscapedString(buf, bufsize, fun->atom, 0);
                 }
             } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
                 JS_snprintf(buf, bufsize, "%p", obj->getPrivate());
             } else {
@@ -4203,18 +4203,18 @@ JS_CloneFunctionObject(JSContext *cx, JS
          * We cannot clone this object, so fail (we used to return funobj, bad
          * idea, but we changed incompatibly to teach any abusers a lesson!).
          */
         Value v = ObjectValue(*funobj);
         js_ReportIsNotFunction(cx, &v, 0);
         return NULL;
     }
 
-    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
-    if (!FUN_FLAT_CLOSURE(fun))
+    JSFunction *fun = funobj->getFunctionPrivate();
+    if (!fun->isFlatClosure())
         return CloneFunctionObject(cx, fun, parent);
 
     /*
      * A flat closure carries its own environment, so why clone it? In case
      * someone wants to mutate its fixed slots or add ad-hoc properties. API
      * compatibility suggests we not return funobj and let callers mutate the
      * returned object at will.
      *
@@ -4249,17 +4249,17 @@ JS_CloneFunctionObject(JSContext *cx, JS
     }
 
     return clone;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFunctionObject(JSFunction *fun)
 {
-    return FUN_OBJECT(fun);
+    return fun;
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetFunctionId(JSFunction *fun)
 {
     return fun->atom;
 }
 
@@ -4352,17 +4352,17 @@ JS_DefineFunctions(JSContext *cx, JSObje
             if (!fun)
                 return JS_FALSE;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             Value priv = PrivateValue(fs);
-            if (!js_SetReservedSlot(cx, FUN_OBJECT(fun), 0, priv))
+            if (!js_SetReservedSlot(cx, fun, 0, priv))
                 return JS_FALSE;
         }
 
         fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
     }
     return JS_TRUE;
@@ -4707,68 +4707,66 @@ CompileUCFunctionForPrincipalsCommon(JSC
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, principals);
     if (!name) {
         funAtom = NULL;
     } else {
         funAtom = js_Atomize(cx, name, strlen(name));
         if (!funAtom) {
             fun = NULL;
-            goto out2;
+            goto out;
         }
     }
 
     fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
     if (!fun)
-        goto out2;
+        goto out;
 
     {
         EmptyShape *emptyCallShape = EmptyShape::getEmptyCallShape(cx);
-        if (!emptyCallShape) {
+        if (!emptyCallShape)
             fun = NULL;
-            goto out2;
-        }
         AutoShapeRooter shapeRoot(cx, emptyCallShape);
 
-        AutoObjectRooter tvr(cx, FUN_OBJECT(fun));
-        MUST_FLOW_THROUGH("out");
+        AutoObjectRooter tvr(cx, fun);
 
         Bindings bindings(cx, emptyCallShape);
         AutoBindingsRooter root(cx, bindings);
         for (i = 0; i < nargs; i++) {
             argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]));
             if (!argAtom) {
                 fun = NULL;
-                goto out2;
+                goto out;
             }
 
             uint16 dummy;
             if (!bindings.addArgument(cx, argAtom, &dummy)) {
                 fun = NULL;
-                goto out2;
+                goto out;
             }
         }
 
         if (!Compiler::compileFunctionBody(cx, fun, principals, &bindings,
                                            chars, length, filename, lineno, version)) {
             fun = NULL;
-            goto out2;
+            goto out;
         }
 
         if (obj && funAtom &&
             !obj->defineProperty(cx, ATOM_TO_JSID(funAtom), ObjectValue(*fun),
                                  NULL, NULL, JSPROP_ENUMERATE)) {
             fun = NULL;
         }
     }
 
-  out2:
+  out:
     LAST_FRAME_CHECKS(cx, fun);
     return fun;
 }
+
 JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                          JSPrincipals *principals, const char *name,
                                          uintN nargs, const char **argnames,
                                          const jschar *chars, size_t length,
                                          const char *filename, uintN lineno,
                                          JSVersion version)
 {
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -305,17 +305,17 @@ JS_DEFINE_CALLINFO_2(extern, STRING, js_
 JSObject* FASTCALL
 js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* parent)
 {
     JS_ASSERT(funobj->isFunction());
     JS_ASSERT(proto->isFunction());
     JS_ASSERT(JS_ON_TRACE(cx));
 
     JSFunction *fun = (JSFunction*) funobj;
-    JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
+    JS_ASSERT(funobj->getFunctionPrivate() == fun);
 
     JSObject* closure = js_NewGCObject(cx, gc::FINALIZE_OBJECT2);
     if (!closure)
         return NULL;
 
     if (!closure->initSharingEmptyShape(cx, &js_FunctionClass, proto, parent,
                                         fun, gc::FINALIZE_OBJECT2)) {
         return NULL;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1078,17 +1078,17 @@ js_ReportMissingArg(JSContext *cx, const
 {
     char argbuf[11];
     char *bytes;
     JSAtom *atom;
 
     JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
     bytes = NULL;
     if (IsFunctionObject(v)) {
-        atom = GET_FUNCTION_PRIVATE(cx, &v.toObject())->atom;
+        atom = v.toObject().getFunctionPrivate()->atom;
         bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
                                         v, atom);
         if (!bytes)
             return;
     }
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                          JSMSG_MISSING_FUN_ARG, argbuf,
                          bytes ? bytes : "");
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -543,17 +543,17 @@ extern JS_PUBLIC_API(void)
 JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
 {
     JS_ARENA_RELEASE(&cx->tempPool, mark);
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
 {
-    return FUN_SCRIPT(fun);
+    return fun->maybeScript();
 }
 
 JS_PUBLIC_API(JSNative)
 JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
 {
     return Jsvalify(fun->maybeNative());
 }
 
@@ -1090,18 +1090,18 @@ GetAtomTotalSize(JSContext *cx, JSAtom *
 }
 
 JS_PUBLIC_API(size_t)
 JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
 {
     size_t nbytes;
 
     nbytes = sizeof *fun;
-    nbytes += JS_GetObjectTotalSize(cx, FUN_OBJECT(fun));
-    if (FUN_INTERPRETED(fun))
+    nbytes += JS_GetObjectTotalSize(cx, fun);
+    if (fun->isInterpreted())
         nbytes += JS_GetScriptTotalSize(cx, fun->script());
     if (fun->atom)
         nbytes += GetAtomTotalSize(cx, fun->atom);
     return nbytes;
 }
 
 #include "jsemit.h"
 
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -4810,32 +4810,32 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
         if (pn->pn_arity == PN_NULLARY) {
             if (js_Emit1(cx, cg, JSOP_GETFUNNS) < 0)
                 return JS_FALSE;
             break;
         }
 #endif
 
         fun = pn->pn_funbox->function();
-        JS_ASSERT(FUN_INTERPRETED(fun));
+        JS_ASSERT(fun->isInterpreted());
         if (fun->script()) {
             /*
              * This second pass is needed to emit JSOP_NOP with a source note
              * for the already-emitted function definition prolog opcode. See
              * comments in the TOK_LC case.
              */
             JS_ASSERT(pn->pn_op == JSOP_NOP);
             JS_ASSERT(cg->inFunction());
             if (!EmitFunctionDefNop(cx, cg, pn->pn_index))
                 return JS_FALSE;
             break;
         }
 
         JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
-                     FUN_KIND(fun) == JSFUN_INTERPRETED);
+                     fun->kind() == JSFUN_INTERPRETED);
 
         /* Generate code for the function's body. */
         void *cg2mark = JS_ARENA_MARK(cg->codePool);
         void *cg2space;
         JS_ARENA_ALLOCATE_TYPE(cg2space, JSCodeGenerator, cg->codePool);
         if (!cg2space) {
             js_ReportOutOfMemory(cx);
             return JS_FALSE;
@@ -4908,17 +4908,17 @@ js_EmitTree(JSContext *cx, JSCodeGenerat
          * definitions can be scheduled before generating the rest of code.
          */
         if (!cg->inFunction()) {
             JS_ASSERT(!cg->topStmt);
             if (!BindGlobal(cx, cg, pn, fun->atom))
                 return false;
             if (pn->pn_cookie.isFree()) {
                 CG_SWITCH_TO_PROLOG(cg);
-                op = FUN_FLAT_CLOSURE(fun) ? JSOP_DEFFUN_FC : JSOP_DEFFUN;
+                op = fun->isFlatClosure() ? JSOP_DEFFUN_FC : JSOP_DEFFUN;
                 EMIT_INDEX_OP(op, index);
 
                 /* Make blockChain determination quicker. */
                 if (EmitBlockChain(cx, cg) < 0)
                     return JS_FALSE;
                 CG_SWITCH_TO_MAIN(cg);
             }
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -523,49 +523,49 @@ js_ErrorFromException(JSContext *cx, jsv
         return NULL;
     priv = GetExnPrivate(obj);
     if (!priv)
         return NULL;
     return priv->errorReport;
 }
 
 static JSString *
-ValueToShortSource(JSContext *cx, jsval v)
+ValueToShortSource(JSContext *cx, const Value &v)
 {
     JSString *str;
 
     /* Avoid toSource bloat and fallibility for object types. */
-    if (JSVAL_IS_PRIMITIVE(v))
-        return js_ValueToSource(cx, Valueify(v));
+    if (!v.isObject())
+        return js_ValueToSource(cx, v);
 
-    AutoCompartment ac(cx, JSVAL_TO_OBJECT(v));
+    JSObject *obj = &v.toObject();
+    AutoCompartment ac(cx, obj);
     if (!ac.enter())
         return NULL;
 
-    if (VALUE_IS_FUNCTION(cx, v)) {
+    if (obj->isFunction()) {
         /*
          * XXX Avoid function decompilation bloat for now.
          */
-        str = JS_GetFunctionId(JS_ValueToFunction(cx, v));
-        if (!str && !(str = js_ValueToSource(cx, Valueify(v)))) {
+        str = JS_GetFunctionId(obj->getFunctionPrivate());
+        if (!str && !(str = js_ValueToSource(cx, v))) {
             /*
              * Continue to soldier on if the function couldn't be
              * converted into a string.
              */
             JS_ClearPendingException(cx);
             str = JS_NewStringCopyZ(cx, "[unknown function]");
         }
     } else {
         /*
          * XXX Avoid toString on objects, it takes too long and uses too much
          * memory, for too many classes (see Mozilla bug 166743).
          */
         char buf[100];
-        JS_snprintf(buf, sizeof buf, "[object %s]",
-                    JSVAL_TO_OBJECT(v)->getClass()->name);
+        JS_snprintf(buf, sizeof buf, "[object %s]", obj->getClass()->name);
         str = JS_NewStringCopyZ(cx, buf);
     }
 
     ac.leave();
 
     if (!str || !cx->compartment->wrap(cx, &str))
         return NULL;
     return str;
@@ -633,17 +633,17 @@ StackTraceToString(JSContext *cx, JSExnP
     elem = priv->stackElems;
     for (endElem = elem + priv->stackDepth; elem != endElem; elem++) {
         if (elem->funName) {
             APPEND_STRING_TO_STACK(elem->funName);
             APPEND_CHAR_TO_STACK('(');
             for (i = 0; i != elem->argc; i++, values++) {
                 if (i > 0)
                     APPEND_CHAR_TO_STACK(',');
-                str = ValueToShortSource(cx, *values);
+                str = ValueToShortSource(cx, Valueify(*values));
                 if (!str)
                     goto bad;
                 APPEND_STRING_TO_STACK(str);
             }
             APPEND_CHAR_TO_STACK(')');
         }
         APPEND_CHAR_TO_STACK('@');
         if (elem->filename) {
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1246,18 +1246,19 @@ StackFrame::getValidCalleeObject(JSConte
                             return true;
                         }
 
                         if (shape->hasSlot()) {
                             Value v = thisp->getSlot(shape->slot);
                             JSObject *clone;
 
                             if (IsFunctionObject(v, &clone) &&
-                                GET_FUNCTION_PRIVATE(cx, clone) == fun &&
-                                clone->hasMethodObj(*thisp)) {
+                                clone->getFunctionPrivate() == fun &&
+                                clone->hasMethodObj(*thisp))
+                            {
                                 JS_ASSERT(clone != &funobj);
                                 *vp = v;
                                 overwriteCallee(*clone);
                                 return true;
                             }
                         }
                     }
 
@@ -1539,18 +1540,18 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
     JSFunction *fun;
     uint32 firstword;           /* flag telling whether fun->atom is non-null,
                                    plus for fun->u.i.skipmin, fun->u.i.wrapper,
                                    and 14 bits reserved for future use */
     uint32 flagsword;           /* word for argument count and fun->flags */
 
     cx = xdr->cx;
     if (xdr->mode == JSXDR_ENCODE) {
-        fun = GET_FUNCTION_PRIVATE(cx, *objp);
-        if (!FUN_INTERPRETED(fun)) {
+        fun = (*objp)->getFunctionPrivate();
+        if (!fun->isInterpreted()) {
             JSAutoByteString funNameBytes;
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
                                      name);
             }
             return false;
         }
         if (fun->u.i.wrapper) {
@@ -1561,21 +1562,21 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
         }
         JS_ASSERT((fun->u.i.wrapper & ~1U) == 0);
         firstword = (fun->u.i.skipmin << 2) | (fun->u.i.wrapper << 1) | !!fun->atom;
         flagsword = (fun->nargs << 16) | fun->flags;
     } else {
         fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
         if (!fun)
             return false;
-        FUN_OBJECT(fun)->clearParent();
-        FUN_OBJECT(fun)->clearProto();
+        fun->clearParent();
+        fun->clearProto();
     }
 
-    AutoObjectRooter tvr(cx, FUN_OBJECT(fun));
+    AutoObjectRooter tvr(cx, fun);
 
     if (!JS_XDRUint32(xdr, &firstword))
         return false;
     if ((firstword & 1U) && !js_XDRAtom(xdr, &fun->atom))
         return false;
     if (!JS_XDRUint32(xdr, &flagsword))
         return false;
 
@@ -1592,17 +1593,17 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
      * at the same time as we set the script's owner.
      */
     JSScript *script = fun->u.i.script;
     if (!js_XDRScript(xdr, &script))
         return false;
     fun->u.i.script = script;
 
     if (xdr->mode == JSXDR_DECODE) {
-        *objp = FUN_OBJECT(fun);
+        *objp = fun;
         fun->u.i.script->setOwnerObject(fun);
 #ifdef CHECK_SCRIPT_OWNER
         fun->script()->owner = NULL;
 #endif
         JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
     }
 
@@ -1731,17 +1732,17 @@ fun_toStringHelper(JSContext *cx, JSObje
             return JSProxy::fun_toString(cx, obj, indent);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO,
                              js_Function_str, js_toString_str,
                              "object");
         return NULL;
     }
 
-    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
+    JSFunction *fun = obj->getFunctionPrivate();
     if (!fun)
         return NULL;
 
     if (!indent && !cx->compartment->toSourceCache.empty()) {
         ToSourceCache::Ptr p = cx->compartment->toSourceCache.ref().lookup(fun);
         if (p)
             return p->value;
     }
@@ -2024,17 +2025,17 @@ static JSBool
 fun_isGenerator(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *funobj;
     if (!IsFunctionObject(vp[1], &funobj)) {
         JS_SET_RVAL(cx, vp, BooleanValue(false));
         return true;
     }
 
-    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
+    JSFunction *fun = funobj->getFunctionPrivate();
 
     bool result = false;
     if (fun->isInterpreted()) {
         JSScript *script = fun->script();
         JS_ASSERT(script->length != 0);
         result = script->code[0] == JSOP_GENERATOR;
     }
 
@@ -2434,17 +2435,17 @@ js_NewFunction(JSContext *cx, JSObject *
             fun->u.n.native = native;
             fun->u.n.trcinfo = NULL;
         }
         JS_ASSERT(fun->u.n.native);
     }
     fun->atom = atom;
 
     /* Set private to self to indicate non-cloned fully initialized function. */
-    FUN_OBJECT(fun)->setPrivate(fun);
+    fun->setPrivate(fun);
     return fun;
 }
 
 JSObject * JS_FASTCALL
 js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
                        JSObject *proto)
 {
     JS_ASSERT(parent);
@@ -2648,17 +2649,17 @@ JS_STATIC_ASSERT((JSV2F_CONSTRUCT & JSV2
 JSFunction *
 js_ValueToFunction(JSContext *cx, const Value *vp, uintN flags)
 {
     JSObject *funobj;
     if (!IsFunctionObject(*vp, &funobj)) {
         js_ReportIsNotFunction(cx, vp, flags);
         return NULL;
     }
-    return GET_FUNCTION_PRIVATE(cx, funobj);
+    return funobj->getFunctionPrivate();
 }
 
 JSObject *
 js_ValueToFunctionObject(JSContext *cx, Value *vp, uintN flags)
 {
     JSObject *funobj;
     if (!IsFunctionObject(*vp, &funobj)) {
         js_ReportIsNotFunction(cx, vp, flags);
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -55,38 +55,38 @@
  * or interpreted, and if interpreted, what kind of optimized closure form (if
  * any) it might be.
  *
  *   00   not interpreted
  *   01   interpreted, neither flat nor null closure
  *   10   interpreted, flat closure
  *   11   interpreted, null closure
  *
- * FUN_FLAT_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset != 0.
- * FUN_NULL_CLOSURE implies FUN_INTERPRETED and u.i.script->upvarsOffset == 0.
+ * isFlatClosure() implies isInterpreted() and u.i.script->upvarsOffset != 0.
+ * isNullClosure() implies isInterpreted() and u.i.script->upvarsOffset == 0.
  *
- * FUN_INTERPRETED but not FUN_FLAT_CLOSURE and u.i.script->upvarsOffset != 0
+ * isInterpreted() but not isFlatClosure() and u.i.script->upvarsOffset != 0
  * is an Algol-like function expression or nested function, i.e., a function
  * that never escapes upward or downward (heapward), and is only ever called.
  *
- * Finally, FUN_INTERPRETED and u.i.script->upvarsOffset == 0 could be either
+ * Finally, isInterpreted() and u.i.script->upvarsOffset == 0 could be either
  * a non-closure (a global function definition, or any function that uses no
  * outer names), or a closure of an escaping function that uses outer names
  * whose values can't be snapshot (because the outer names could be reassigned
  * after the closure is formed, or because assignments could not be analyzed
  * due to with or eval).
  *
  * Such a hard-case function must use JSOP_NAME, etc., and reify outer function
  * activations' call objects, etc. if it's not a global function.
  *
  * NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
  * bit only, never stored in fun->flags.
  *
- * If we need more bits in the future, all flags for FUN_INTERPRETED functions
- * can move to u.i.script->flags. For now we use function flag bits to minimize
+ * If we need more bits in the future, all flags for interpreted functions can
+ * move to u.i.script->flags. For now we use function flag bits to minimize
  * pointer-chasing.
  */
 #define JSFUN_JOINABLE      0x0001  /* function is null closure that does not
                                        appear to call itself via its own name
                                        or arguments.callee */
 
 #define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
                                        global object */
@@ -96,29 +96,16 @@
                                        JSFunctionSpec::call points to a
                                        JSNativeTraceInfo. */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.n */
 #define JSFUN_FLAT_CLOSURE  0x8000  /* flat (aka "display") closure */
 #define JSFUN_NULL_CLOSURE  0xc000  /* null closure entrains no scope chain */
 #define JSFUN_KINDMASK      0xc000  /* encode interp vs. native and closure
                                        optimization level -- see above */
 
-#define FUN_OBJECT(fun)      (static_cast<JSObject *>(fun))
-#define FUN_KIND(fun)        ((fun)->flags & JSFUN_KINDMASK)
-#define FUN_SET_KIND(fun,k)  ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
-#define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
-#define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
-#define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
-#define FUN_SCRIPT(fun)      (FUN_INTERPRETED(fun) ? (fun)->script() : NULL)
-#define FUN_CLASP(fun)       (JS_ASSERT(!FUN_INTERPRETED(fun)),               \
-                              fun->u.n.clasp)
-#define FUN_TRCINFO(fun)     (JS_ASSERT(!FUN_INTERPRETED(fun)),               \
-                              JS_ASSERT((fun)->flags & JSFUN_TRCINFO),        \
-                              fun->u.n.trcinfo)
-
 struct JSFunction : public JSObject_Slots2
 {
     /* Functions always have two fixed slots (FUN_CLASS_RESERVED_SLOTS). */
 
     uint16          nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
     uint16          flags;        /* flags, see JSFUN_* below and in jsapi.h */
     union U {
@@ -140,26 +127,35 @@ struct JSFunction : public JSObject_Slot
                                      indirect eval; if true, then this function
                                      object's proto is the wrapped object */
             js::Shape   *names;   /* argument and variable names */
         } i;
         void            *nativeOrScript;
     } u;
     JSAtom          *atom;        /* name for diagnostics and decompiling */
 
-    bool optimizedClosure()  const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
-    bool isInterpreted()     const { return FUN_INTERPRETED(this); }
-    bool isNative()          const { return !FUN_INTERPRETED(this); }
+    bool optimizedClosure()  const { return kind() > JSFUN_INTERPRETED; }
+    bool isInterpreted()     const { return kind() >= JSFUN_INTERPRETED; }
+    bool isNative()          const { return !isInterpreted(); }
     bool isConstructor()     const { return flags & JSFUN_CONSTRUCTOR; }
     bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
-    bool isFlatClosure()     const { return FUN_KIND(this) == JSFUN_FLAT_CLOSURE; }
+    bool isNullClosure()     const { return kind() == JSFUN_NULL_CLOSURE; }
+    bool isFlatClosure()     const { return kind() == JSFUN_FLAT_CLOSURE; }
     bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
     bool isInterpretedConstructor() const { return isInterpreted() && !isFunctionPrototype(); }
+
+    uint16 kind()            const { return flags & JSFUN_KINDMASK; }
+    void setKind(uint16 k) {
+        JS_ASSERT(!(k & ~JSFUN_KINDMASK));
+        flags = (flags & ~JSFUN_KINDMASK) | k;
+    }
+
     /* Returns the strictness of this function, which must be interpreted. */
     inline bool inStrictMode() const;
+
     void setArgCount(uint16 nargs) {
         JS_ASSERT(this->nargs == 0);
         this->nargs = nargs;
     }
 
     /* uint16 representation bounds number of call object dynamic slots. */
     enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
 
@@ -205,16 +201,20 @@ struct JSFunction : public JSObject_Slot
 
     inline void setMethodAtom(JSAtom *atom);
 
     JSScript *script() const {
         JS_ASSERT(isInterpreted());
         return u.i.script;
     }
 
+    JSScript * maybeScript() const {
+        return isInterpreted() ? script() : NULL;
+    }
+
     js::Native native() const {
         JS_ASSERT(isNative());
         return u.n.native;
     }
 
     js::Native maybeNative() const {
         return isInterpreted() ? NULL : native();
     }
@@ -222,16 +222,33 @@ struct JSFunction : public JSObject_Slot
     static uintN offsetOfNativeOrScript() {
         JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script));
         JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript));
         return offsetof(JSFunction, u.nativeOrScript);
     }
 
     /* Number of extra fixed function object slots. */
     static const uint32 CLASS_RESERVED_SLOTS = JSObject::FUN_CLASS_RESERVED_SLOTS;
+
+
+    js::Class *getConstructorClass() const {
+        JS_ASSERT(isNative());
+        return u.n.clasp;
+    }
+
+    void setConstructorClass(js::Class *clasp) {
+        JS_ASSERT(isNative());
+        u.n.clasp = clasp;
+    }
+
+    JSNativeTraceInfo *getTraceInfo() const {
+        JS_ASSERT(isNative());
+        JS_ASSERT(flags & JSFUN_TRCINFO);
+        return u.n.trcinfo;
+    }
 };
 
 /*
  * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
  * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
  * JSNativeTraceInfo*.
  */
 #ifdef JS_TRACER
@@ -264,22 +281,16 @@ inline JSFunction *
 JSObject::getFunctionPrivate() const
 {
     JS_ASSERT(isFunction());
     return reinterpret_cast<JSFunction *>(getPrivate());
 }
 
 namespace js {
 
-/*
- * 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.toObject().isFunction();
 }
 
 static JS_ALWAYS_INLINE bool
 IsFunctionObject(const js::Value &v, JSObject **funobj)
@@ -350,24 +361,16 @@ extern JS_ALWAYS_INLINE bool
 SameTraceType(const Value &lhs, const Value &rhs)
 {
     return SameType(lhs, rhs) &&
            (lhs.isPrimitive() ||
             lhs.toObject().isFunction() == rhs.toObject().isFunction());
 }
 
 /*
- * Macro to access the private slot of the function object after the slot is
- * initialized.
- */
-#define GET_FUNCTION_PRIVATE(cx, funobj)                                      \
-    (JS_ASSERT((funobj)->isFunction()),                                       \
-     (JSFunction *) (funobj)->getPrivate())
-
-/*
  * Return true if this is a compiler-created internal function accessed by
  * its own object. Such a function object must not be accessible to script
  * or embedding code.
  */
 inline bool
 IsInternalFunctionObject(JSObject *funobj)
 {
     JS_ASSERT(funobj->isFunction());
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -47,17 +47,17 @@ inline bool
 JSFunction::inStrictMode() const
 {
     return script()->strictModeCode;
 }
 
 inline void
 JSFunction::setJoinable()
 {
-    JS_ASSERT(FUN_INTERPRETED(this));
+    JS_ASSERT(isInterpreted());
     setSlot(METHOD_ATOM_SLOT, js::NullValue());
     flags |= JSFUN_JOINABLE;
 }
 
 inline void
 JSFunction::setMethodAtom(JSAtom *atom)
 {
     JS_ASSERT(joinable());
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -4585,20 +4585,20 @@ BEGIN_CASE(JSOP_DEFFUN)
     /*
      * A top-level function defined in Global or Eval code (see ECMA-262
      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
      * a compound statement (not at the top statement level of global code, or
      * at the top level of a function body).
      */
     JSFunction *fun;
     LOAD_FUNCTION(0);
-    JSObject *obj = FUN_OBJECT(fun);
+    JSObject *obj = fun;
 
     JSObject *obj2;
-    if (FUN_NULL_CLOSURE(fun)) {
+    if (fun->isNullClosure()) {
         /*
          * Even a null closure needs a parent for principals finding.
          * FIXME: bug 476950, although debugger users may also demand some kind
          * of scope link for debugger-assisted eval-in-frame.
          */
         obj2 = &regs.fp()->scopeChain();
     } else {
         JS_ASSERT(!fun->isFlatClosure());
@@ -4725,20 +4725,20 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
      * function), parented by the current scope chain, stored in a local
      * variable slot that the compiler allocated.  This is an optimization over
      * JSOP_DEFFUN that avoids requiring a call object for the outer function's
      * activation.
      */
     JSFunction *fun;
     LOAD_FUNCTION(SLOTNO_LEN);
     JS_ASSERT(fun->isInterpreted());
-    JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
-    JSObject *obj = FUN_OBJECT(fun);
-
-    if (FUN_NULL_CLOSURE(fun)) {
+    JS_ASSERT(!fun->isFlatClosure());
+    JSObject *obj = fun;
+
+    if (fun->isNullClosure()) {
         obj = CloneFunctionObject(cx, fun, &regs.fp()->scopeChain());
         if (!obj)
             goto error;
     } else {
         JSObject *parent = GetScopeChainFast(cx, regs.fp(), JSOP_DEFLOCALFUN,
                                              JSOP_DEFLOCALFUN_LENGTH);
         if (!parent)
             goto error;
@@ -4777,22 +4777,22 @@ BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
 }
 END_CASE(JSOP_DEFLOCALFUN_FC)
 
 BEGIN_CASE(JSOP_LAMBDA)
 {
     /* Load the specified function object literal. */
     JSFunction *fun;
     LOAD_FUNCTION(0);
-    JSObject *obj = FUN_OBJECT(fun);
+    JSObject *obj = fun;
 
     /* do-while(0) so we can break instead of using a goto. */
     do {
         JSObject *parent;
-        if (FUN_NULL_CLOSURE(fun)) {
+        if (fun->isNullClosure()) {
             parent = &regs.fp()->scopeChain();
 
             if (obj->getParent() == parent) {
                 jsbytecode *pc2 = AdvanceOverBlockchainOp(regs.pc + JSOP_LAMBDA_LENGTH);
                 JSOp op2 = JSOp(*pc2);
 
                 /*
                  * Optimize var obj = {method: function () { ... }, ...},
@@ -4840,17 +4840,17 @@ BEGIN_CASE(JSOP_LAMBDA)
                          * Note that we have not yet pushed obj as the final argument,
                          * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
                          * is the callee for this JSOP_CALL.
                          */
                         const Value &cref = regs.sp[1 - (iargc + 2)];
                         JSObject *callee;
 
                         if (IsFunctionObject(cref, &callee)) {
-                            JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
+                            JSFunction *calleeFun = callee->getFunctionPrivate();
                             if (Native native = calleeFun->maybeNative()) {
                                 if ((iargc == 1 && native == array_sort) ||
                                     (iargc == 2 && native == str_replace)) {
                                     break;
                                 }
                             }
                         }
                     } else if (op2 == JSOP_NULL) {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3914,29 +3914,29 @@ DefineConstructorAndPrototype(JSContext 
          * because the constructor currently must have |obj| as its parent.
          * (FIXME: remove this dependency on the exact identity of the parent,
          * perhaps as part of bug 638316.)
          */
         JSFunction *fun =
             js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom);
         if (!fun)
             goto bad;
-        FUN_CLASP(fun) = clasp;
+        fun->setConstructorClass(clasp);
 
         AutoValueRooter tvr2(cx, ObjectValue(*fun));
         if (!DefineStandardSlot(cx, obj, key, atom, tvr2.value(), 0, named))
             goto bad;
 
         /*
          * Optionally construct the prototype object, before the class has
          * been fully initialized.  Allow the ctor to replace proto with a
          * different object, as is done for operator new -- and as at least
          * XML support requires.
          */
-        ctor = FUN_OBJECT(fun);
+        ctor = fun;
         if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
             Value rval;
             if (!InvokeConstructorWithGivenThis(cx, proto, ObjectOrNullValue(ctor),
                                                 0, NULL, &rval)) {
                 goto bad;
             }
             if (rval.isObject() && &rval.toObject() != proto)
                 proto = &rval.toObject();
@@ -4704,17 +4704,17 @@ DefineNativeProperty(JSContext *cx, JSOb
         /* Add a new property, or replace an existing one of the same id. */
         if (defineHow & DNP_SET_METHOD) {
             JS_ASSERT(clasp == &js_ObjectClass);
             JS_ASSERT(IsFunctionObject(value));
             JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
             JS_ASSERT(!getter && !setter);
 
             JSObject *funobj = &value.toObject();
-            if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
+            if (funobj->getFunctionPrivate() == funobj) {
                 flags |= Shape::METHOD;
                 getter = CastAsPropertyOp(funobj);
             }
         }
 
         if (const Shape *existingShape = obj->nativeLookup(id)) {
             if (existingShape->hasSlot())
                 AbortRecordingIfUnexpectedGlobalWrite(cx, obj, existingShape->slot);
@@ -5657,17 +5657,17 @@ js_SetPropertyHelper(JSContext *cx, JSOb
          * Check for Object class here to avoid defining a method on a class
          * with magic resolve, addProperty, getProperty, etc. hooks.
          */
         if ((defineHow & DNP_SET_METHOD) && obj->canHaveMethodBarrier()) {
             JS_ASSERT(IsFunctionObject(*vp));
             JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
 
             JSObject *funobj = &vp->toObject();
-            JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
+            JSFunction *fun = funobj->getFunctionPrivate();
             if (fun == funobj) {
                 flags |= Shape::METHOD;
                 getter = CastAsPropertyOp(funobj);
             }
         }
 
         shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
                                  attrs, flags, shortid);
@@ -5792,17 +5792,17 @@ js_DeleteProperty(JSContext *cx, JSObjec
          * We do not check suspended frames. They can't be reached via caller,
          * so the only way they could have the method's joined function object
          * as callee is through an API abusage. We break any such edge case.
          */
         if (obj->hasMethodBarrier()) {
             JSObject *funobj;
 
             if (IsFunctionObject(v, &funobj)) {
-                JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
+                JSFunction *fun = funobj->getFunctionPrivate();
 
                 if (fun != funobj) {
                     for (StackFrame *fp = cx->maybefp(); fp; fp = fp->prev()) {
                         if (fp->isFunctionFrame() &&
                             fp->callee() == fun->compiledFunObj() &&
                             fp->thisValue().isObject())
                         {
                             JSObject *tmp = &fp->thisValue().toObject();
@@ -6487,17 +6487,17 @@ dumpValue(const Value &v)
     else if (v.isInt32())
         fprintf(stderr, "%d", v.toInt32());
     else if (v.isDouble())
         fprintf(stderr, "%g", v.toDouble());
     else if (v.isString())
         dumpString(v.toString());
     else if (v.isObject() && v.toObject().isFunction()) {
         JSObject *funobj = &v.toObject();
-        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
+        JSFunction *fun = funobj->getFunctionPrivate();
         if (fun->atom) {
             fputs("<function ", stderr);
             FileEscapedString(stderr, fun->atom, 0);
         } else {
             fputs("<unnamed function", stderr);
         }
         if (fun->isInterpreted()) {
             JSScript *script = fun->script();
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -213,17 +213,17 @@ JSObject::methodReadBarrier(JSContext *c
     JS_ASSERT(shape.writable());
     JS_ASSERT(shape.slot != SHAPE_INVALID_SLOT);
     JS_ASSERT(shape.hasDefaultSetter());
     JS_ASSERT(!isGlobal());  /* i.e. we are not changing the global shape */
 
     JSObject *funobj = &vp->toObject();
     JSFunction *fun = funobj->getFunctionPrivate();
     JS_ASSERT(fun == funobj);
-    JS_ASSERT(FUN_NULL_CLOSURE(fun));
+    JS_ASSERT(fun->isNullClosure());
 
     funobj = CloneFunctionObject(cx, fun, funobj->getParent());
     if (!funobj)
         return NULL;
     funobj->setMethodObj(*this);
 
     /*
      * Replace the method property with an ordinary data property. This is
@@ -545,17 +545,17 @@ JSObject::setFlatClosureUpvar(uint32 i, 
     JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars());
     getFlatClosureUpvars()[i] = v;
 }
 
 inline void
 JSObject::setFlatClosureUpvars(js::Value *upvars)
 {
     JS_ASSERT(isFunction());
-    JS_ASSERT(FUN_FLAT_CLOSURE(getFunctionPrivate()));
+    JS_ASSERT(getFunctionPrivate()->isFlatClosure());
     setSlot(JSSLOT_FLAT_CLOSURE_UPVARS, PrivateValue(upvars));
 }
 
 inline bool
 JSObject::hasMethodObj(const JSObject& obj) const
 {
     return JSSLOT_FUN_METHOD_OBJ < numSlots() &&
            getSlot(JSSLOT_FUN_METHOD_OBJ).isObject() &&
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -391,17 +391,17 @@ ToDisassemblySource(JSContext *cx, jsval
             source = JS_sprintf_append(source, "}");
             if (!source)
                 return false;
             bytes->initBytes(source);
             return true;
         }
 
         if (clasp == &js_FunctionClass) {
-            JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
+            JSFunction *fun = obj->getFunctionPrivate();
             JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
             if (!str)
                 return false;
             return bytes->encode(cx, str);
         }
 
         if (clasp == &js_RegExpClass) {
             AutoValueRooter tvr(cx);
@@ -4967,17 +4967,17 @@ static const char native_code_str[] = "\
 
 JSBool
 js_DecompileFunctionBody(JSPrinter *jp)
 {
     JSScript *script;
 
     JS_ASSERT(jp->fun);
     JS_ASSERT(!jp->script);
-    if (!FUN_INTERPRETED(jp->fun)) {
+    if (!jp->fun->isInterpreted()) {
         js_printf(jp, native_code_str);
         return JS_TRUE;
     }
 
     script = jp->fun->script();
     return DecompileBody(jp, script, script->code);
 }
 
@@ -5006,17 +5006,17 @@ js_DecompileFunction(JSPrinter *jp)
             js_puts(jp, "(");
     }
 
     js_printf(jp, "%s ", js_function_str);
     if (fun->atom && !QuoteString(&jp->sprinter, fun->atom, 0))
         return JS_FALSE;
     js_puts(jp, "(");
 
-    if (!FUN_INTERPRETED(fun)) {
+    if (!fun->isInterpreted()) {
         js_printf(jp, ") {\n");
         jp->indent += 4;
         js_printf(jp, native_code_str);
         jp->indent -= 4;
         js_printf(jp, "\t}");
     } else {
         JSScript *script = fun->script();
 #if JS_HAS_DESTRUCTURING
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -308,17 +308,17 @@ Parser::newFunctionBox(JSObject *obj, JS
     if (tc->innermostWith)
         funbox->tcflags |= TCF_IN_WITH;
     return funbox;
 }
 
 bool
 JSFunctionBox::joinable() const
 {
-    return FUN_NULL_CLOSURE(function()) &&
+    return function()->isNullClosure() &&
            !(tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME));
 }
 
 bool
 JSFunctionBox::inAnyDynamicScope() const
 {
     for (const JSFunctionBox *funbox = this; funbox; funbox = funbox->parent) {
         if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_CALLS_EVAL))
@@ -985,17 +985,17 @@ Compiler::compileScript(JSContext *cx, J
         }
 
         if (callerFrame && callerFrame->isFunctionFrame()) {
             /*
              * An eval script in a caller frame needs to have its enclosing
              * function captured in case it refers to an upvar, and someone
              * wishes to decompile it while it's running.
              */
-            JSObjectBox *funbox = parser.newObjectBox(FUN_OBJECT(callerFrame->fun()));
+            JSObjectBox *funbox = parser.newObjectBox(callerFrame->fun());
             if (!funbox)
                 goto out;
             funbox->emitLink = cg.objectList.lastbox;
             cg.objectList.lastbox = funbox;
             cg.objectList.length++;
 #ifdef DEBUG
             savedCallerFun = true;
 #endif
@@ -1973,18 +1973,18 @@ Parser::newFunction(JSTreeContext *tc, J
         tc = tc->parent;
     JSObject *parent = tc->inFunction() ? NULL : tc->scopeChain();
 
     JSFunction *fun =
         js_NewFunction(context, NULL, NULL, 0,
                        JSFUN_INTERPRETED | (kind == Expression ? JSFUN_LAMBDA : 0),
                        parent, atom);
     if (fun && !tc->compileAndGo()) {
-        FUN_OBJECT(fun)->clearParent();
-        FUN_OBJECT(fun)->clearProto();
+        fun->clearParent();
+        fun->clearProto();
     }
     return fun;
 }
 
 static JSBool
 MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
 {
     TokenKind tt = ts->peekTokenSameLine(TSF_OPERAND);
@@ -2456,22 +2456,22 @@ Parser::setFunctionKinds(JSFunctionBox *
 
                 if (funbox->shouldUnbrand(methodSets, slowMethodSets))
                     funbox->tcflags |= TCF_FUN_UNBRAND_THIS;
             }
         }
 
         JSFunction *fun = funbox->function();
 
-        JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED);
+        JS_ASSERT(fun->kind() == JSFUN_INTERPRETED);
 
         if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
             /* nothing to do */
         } else if (funbox->inAnyDynamicScope()) {
-            JS_ASSERT(!FUN_NULL_CLOSURE(fun));
+            JS_ASSERT(!fun->isNullClosure());
         } else if (pn->pn_type != TOK_UPVARS) {
             /*
              * No lexical dependencies => null closure, for best performance.
              * A null closure needs no scope chain, but alas we've coupled
              * principals-finding to scope (for good fundamental reasons, but
              * the implementation overloads the parent slot and we should fix
              * that). See, e.g., the JSOP_LAMBDA case in jsinterp.cpp.
              *
@@ -2479,17 +2479,17 @@ Parser::setFunctionKinds(JSFunctionBox *
              * "joined function objects", or not, at its discretion. But real-
              * world implementations always create unique function objects for
              * closures, and this can be detected via mutation. Open question:
              * do popular implementations create unique function objects for
              * null closures?
              *
              * FIXME: bug 476950.
              */
-            FUN_SET_KIND(fun, JSFUN_NULL_CLOSURE);
+            fun->setKind(JSFUN_NULL_CLOSURE);
         } else {
             AtomDefnMapPtr upvars = pn->pn_names;
             JS_ASSERT(!upvars->empty());
 
             if (!fn->isFunArg()) {
                 /*
                  * This function is Algol-like, it never escapes.
                  *
@@ -2507,17 +2507,17 @@ Parser::setFunctionKinds(JSFunctionBox *
 
                     if (!lexdep->isFreeVar()) {
                         JS_ASSERT(lexdep->frameLevel() <= funbox->level);
                         break;
                     }
                 }
 
                 if (r.empty())
-                    FUN_SET_KIND(fun, JSFUN_NULL_CLOSURE);
+                    fun->setKind(JSFUN_NULL_CLOSURE);
             } else {
                 uintN nupvars = 0, nflattened = 0;
 
                 /*
                  * For each lexical dependency from this closure to an outer
                  * binding, analyze whether it is safe to copy the binding's
                  * value into a flat closure slot when the closure is formed.
                  */
@@ -2545,23 +2545,23 @@ Parser::setFunctionKinds(JSFunctionBox *
                          * closure. This is safe because we leave fun's kind
                          * set to interpreted, so all functions holding its
                          * upvars will be flagged as heavyweight.
                          */
                     }
                 }
 
                 if (nupvars == 0) {
-                    FUN_SET_KIND(fun, JSFUN_NULL_CLOSURE);
+                    fun->setKind(JSFUN_NULL_CLOSURE);
                 } else if (nflattened == nupvars) {
                     /*
                      * We made it all the way through the upvar loop, so it's
                      * safe to optimize to a flat closure.
                      */
-                    FUN_SET_KIND(fun, JSFUN_FLAT_CLOSURE);
+                    fun->setKind(JSFUN_FLAT_CLOSURE);
                     switch (PN_OP(fn)) {
                       case JSOP_DEFFUN:
                         fn->pn_op = JSOP_DEFFUN_FC;
                         break;
                       case JSOP_DEFLOCALFUN:
                         fn->pn_op = JSOP_DEFLOCALFUN_FC;
                         break;
                       case JSOP_LAMBDA:
@@ -2570,17 +2570,17 @@ Parser::setFunctionKinds(JSFunctionBox *
                       default:
                         /* js_EmitTree's case TOK_FUNCTION: will select op. */
                         JS_ASSERT(PN_OP(fn) == JSOP_NOP);
                     }
                 }
             }
         }
 
-        if (FUN_KIND(fun) == JSFUN_INTERPRETED && pn->pn_type == TOK_UPVARS) {
+        if (fun->kind() == JSFUN_INTERPRETED && pn->pn_type == TOK_UPVARS) {
             /*
              * One or more upvars cannot be safely snapshot into a flat
              * closure's non-reserved slot (see JSOP_GETFCSLOT), so we loop
              * again over all upvars, and for each non-free upvar, ensure that
              * its containing function has been flagged as heavyweight.
              *
              * The emitter must see TCF_FUN_HEAVYWEIGHT accurately before
              * generating any code for a tree of nested functions.
@@ -2616,17 +2616,17 @@ Parser::setFunctionKinds(JSFunctionBox *
  * must have their OWN_SHAPE flags set; the comments for
  * js::Bindings::extensibleParents explain why.
  */
 void
 Parser::markExtensibleScopeDescendants(JSFunctionBox *funbox, bool hasExtensibleParent) 
 {
     for (; funbox; funbox = funbox->siblings) {
         /*
-         * It would be nice to use FUN_KIND(fun) here to recognize functions
+         * It would be nice to use fun->kind() here to recognize functions
          * that will never consult their parent chains, and thus don't need
          * their 'extensible parents' flag set. Filed as bug 619750. 
          */
 
         JS_ASSERT(!funbox->bindings.extensibleParents());
         if (hasExtensibleParent)
             funbox->bindings.setExtensibleParents();
 
@@ -2658,17 +2658,17 @@ EnterFunction(JSParseNode *fn, JSTreeCon
               FunctionSyntaxKind kind = Expression)
 {
     JSTreeContext *tc = funtc->parent;
     JSFunction *fun = tc->parser->newFunction(tc, funAtom, kind);
     if (!fun)
         return NULL;
 
     /* Create box for fun->object early to protect against last-ditch GC. */
-    JSFunctionBox *funbox = tc->parser->newFunctionBox(FUN_OBJECT(fun), fn, tc);
+    JSFunctionBox *funbox = tc->parser->newFunctionBox(fun, fn, tc);
     if (!funbox)
         return NULL;
 
     /* Initialize non-default members of funtc. */
     funtc->flags |= funbox->tcflags;
     funtc->blockidGen = tc->blockidGen;
     if (!GenerateBlockId(funtc, funtc->bodyid))
         return NULL;
--- a/js/src/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -85,20 +85,20 @@ FunctionName(JSContext *cx, const JSFunc
     if (!atom)
         return Probes::anonymousName;
     return bytes->encode(cx, atom) ? bytes->ptr() : Probes::nullName;
 }
 
 static const char *
 FunctionClassname(const JSFunction *fun)
 {
-    if (!fun || FUN_INTERPRETED(fun))
+    if (!fun || fun->isInterpreted())
         return Probes::nullName;
-    if (!(fun->flags & JSFUN_TRCINFO) && FUN_CLASP(fun))
-        return (char *)FUN_CLASP(fun)->name;
+    if (!(fun->flags & JSFUN_TRCINFO) && fun->getConstructorClass())
+        return fun->getConstructorClass()->name;
     return Probes::nullName;
 }
 
 /*
  * These functions call the DTrace macros for the JavaScript USDT probes.
  * Originally this code was inlined in the JavaScript code; however since
  * a number of operations are called, these have been placed into functions
  * to reduce any negative compiler optimization effect that the addition of
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -166,17 +166,17 @@ PropertyCache::fill(JSContext *cx, JSObj
                      * obj with a new shape and set the JSObject::BRANDED flag.
                      * Once this flag is set, any property assignment that
                      * changes the value from or to a different function object
                      * will result in shape being regenerated.
                      */
                     if (!pobj->branded()) {
                         PCMETER(brandfills++);
 #ifdef DEBUG_notme
-                        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v));
+                        JSFunction *fun = JSVAL_TO_OBJECT(v)->getFunctionPrivate();
                         JSAutoByteString funNameBytes;
                         if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                             fprintf(stderr,
                                     "branding %p (%s) for funobj %p (%s), shape %lu\n",
                                     pobj, pobj->getClass()->name, JSVAL_TO_OBJECT(v), funName,
                                     obj->shape());
                         }
 #endif
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1229,17 +1229,17 @@ JSScript::NewScriptFromCG(JSContext *cx,
     }
 
     script->bindings.transfer(cx, &cg->bindings);
 
     fun = NULL;
     if (cg->inFunction()) {
         /*
          * We initialize fun->u.i.script to be the script constructed above
-         * so that the debugger has a valid FUN_SCRIPT(fun).
+         * so that the debugger has a valid fun->script().
          */
         fun = cg->fun();
         JS_ASSERT(fun->isInterpreted());
         JS_ASSERT(!fun->script());
 #ifdef DEBUG
         if (JSScript::isValidOffset(script->upvarsOffset))
             JS_ASSERT(script->upvars()->length == script->bindings.countUpvars());
         else
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -115,17 +115,17 @@ CurrentScriptFileAndLine(JSContext *cx, 
 
 inline JSFunction *
 JSScript::getFunction(size_t index)
 {
     JSObject *funobj = getObject(index);
     JS_ASSERT(funobj->isFunction());
     JS_ASSERT(funobj == (JSObject *) funobj->getPrivate());
     JSFunction *fun = (JSFunction *) funobj;
-    JS_ASSERT(FUN_INTERPRETED(fun));
+    JS_ASSERT(fun->isInterpreted());
     return fun;
 }
 
 inline JSFunction *
 JSScript::getCallerFunction()
 {
     JS_ASSERT(savedCallerFun);
     return getFunction(0);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2805,17 +2805,17 @@ ValueToNative(const Value &v, JSValueTyp
 
       case JSVAL_TYPE_MAGIC:
         JS_ASSERT(v.isMagic());
         debug_only_print0(LC_TMTracer, "hole ");
         return;
 
       case JSVAL_TYPE_FUNOBJ: {
         JS_ASSERT(IsFunctionObject(v));
-        JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.toObject());
+        JSFunction* fun = v.toObject().getFunctionPrivate();
 #if defined JS_JIT_SPEW
         if (LogController.lcbits & LC_TMTracer) {
             char funName[40];
             if (fun->atom)
                 JS_PutEscapedFlatString(funName, sizeof funName, fun->atom, 0);
             else
                 strcpy(funName, "unnamed");
             LogController.printf("function<%p:%s> ", (void*)*(JSObject **)slot, funName);
@@ -3104,17 +3104,17 @@ NativeToValue(JSContext* cx, Value& v, J
         break;
       case JSVAL_TYPE_MAGIC:
         debug_only_printf(LC_TMTracer, "magic<%d> ", v.whyMagic());
         break;
       case JSVAL_TYPE_FUNOBJ:
         JS_ASSERT(IsFunctionObject(v));
 #if defined JS_JIT_SPEW
         if (LogController.lcbits & LC_TMTracer) {
-            JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &v.toObject());
+            JSFunction* fun = v.toObject().getFunctionPrivate();
             char funName[40];
             if (fun->atom)
                 JS_PutEscapedFlatString(funName, sizeof funName, fun->atom, 0);
             else
                 strcpy(funName, "unnamed");
             LogController.printf("function<%p:%s> ", (void*) &v.toObject(), funName);
         }
 #endif
@@ -3380,17 +3380,17 @@ GetUpvarOnTrace(JSContext* cx, uint32 up
         FrameInfo* fi = *fip;
 
         /*
          * The loop starts aligned to the top of the stack, so move down to the first meaningful
          * callee. Then read the callee directly from the frame.
          */
         stackOffset -= fi->callerHeight;
         JSObject* callee = *(JSObject**)(&state->stackBase[stackOffset]);
-        JSFunction* fun = GET_FUNCTION_PRIVATE(cx, callee);
+        JSFunction* fun = callee->getFunctionPrivate();
         uintN calleeLevel = fun->script()->staticLevel;
         if (calleeLevel == upvarLevel) {
             /*
              * Now find the upvar's value in the native stack. stackOffset is
              * the offset of the start of the activation record corresponding
              * to *fip in the native stack.
              */
             uint32 native_slot = T::native_slot(fi->callerArgc, slot);
@@ -10536,17 +10536,17 @@ TraceRecorder::record_JSOP_LEAVEWITH()
 {
     return ARECORD_STOP;
 }
 
 static JSBool JS_FASTCALL
 functionProbe(JSContext *cx, JSFunction *fun, int enter)
 {
 #ifdef MOZ_TRACE_JSCALLS
-    JSScript *script = fun ? FUN_SCRIPT(fun) : NULL;
+    JSScript *script = fun ? fun->maybeScript() : NULL;
     if (enter > 0)
         Probes::enterJSFun(cx, fun, script, enter);
     else
         Probes::exitJSFun(cx, fun, script, enter);
 #endif
     return true;
 }
 
@@ -11006,17 +11006,17 @@ TraceRecorder::record_JSOP_OBJTOP()
     return ARECORD_CONTINUE;
 }
 
 RecordingStatus
 TraceRecorder::getClassPrototype(JSObject* ctor, LIns*& proto_ins)
 {
     // ctor must be a function created via js_InitClass.
 #ifdef DEBUG
-    Class *clasp = FUN_CLASP(GET_FUNCTION_PRIVATE(cx, ctor));
+    Class *clasp = ctor->getFunctionPrivate()->getConstructorClass();
     JS_ASSERT(clasp);
 
     TraceMonitor &localtm = *traceMonitor;
 #endif
 
     Value pval;
     if (!ctor->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &pval))
         RETURN_ERROR("error getting prototype from constructor");
@@ -11548,17 +11548,17 @@ TraceRecorder::callNative(uintN argc, JS
                 pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                 return RECORD_CONTINUE;
             }
         }
         break;
     }
 
     if (fun->flags & JSFUN_TRCINFO) {
-        JSNativeTraceInfo *trcinfo = FUN_TRCINFO(fun);
+        JSNativeTraceInfo *trcinfo = fun->getTraceInfo();
         JS_ASSERT(trcinfo && fun->u.n.native == trcinfo->native);
 
         /* Try to call a type specialized version of the native. */
         if (trcinfo->specializations) {
             RecordingStatus status = callSpecializedNative(trcinfo, argc, mode == JSOP_NEW);
             if (status != RECORD_STOP)
                 return status;
         }
@@ -11703,28 +11703,28 @@ TraceRecorder::functionCall(uintN argc, 
      * or JSOP_CALLPROP that callee is a *particular* function, since these hit
      * the property cache and guard on the object (this) in which the callee
      * was found. So it's sufficient to test here that the particular function
      * is interpreted, not guard on that condition.
      *
      * 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.toObject());
+    JSFunction* fun = fval.toObject().getFunctionPrivate();
 
     if (Probes::callTrackingActive(cx)) {
-        JSScript *script = FUN_SCRIPT(fun);
+        JSScript *script = fun->maybeScript();
         if (!script || !script->isEmpty()) {
             LIns* args[] = { w.immi(1), w.nameImmpNonGC(fun), cx_ins };
             LIns* call_ins = w.call(&functionProbe_ci, args);
             guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
         }
     }
 
-    if (FUN_INTERPRETED(fun))
+    if (fun->isInterpreted())
         return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
 
     Native native = fun->maybeNative();
     Value* argv = &tval + 1;
     if (native == js_Array)
         return newArray(&fval.toObject(), argc, argv, &fval);
     if (native == js_String && argc == 1) {
         if (mode == JSOP_NEW)
@@ -13612,17 +13612,18 @@ TraceRecorder::guardCallee(Value& callee
      * after, or vice versa. The function must escape, i.e., be a "funarg", or
      * else there's no need to guard callee parent at all. So once we know (by
      * static analysis) that a function may escape, we cannot avoid guarding on
      * either the private data of the Call object or the Call object itself, if
      * we wish to optimize for the particular deactivated stack frame (null
      * private data) case as noted above.
      */
     if (callee_fun->isInterpreted() &&
-        (!FUN_NULL_CLOSURE(callee_fun) || callee_fun->script()->bindings.hasUpvars())) {
+        (!callee_fun->isNullClosure() || callee_fun->script()->bindings.hasUpvars()))
+    {
         JSObject* parent = callee_obj.getParent();
 
         if (parent != globalObj) {
             if (!parent->isCall())
                 RETURN_STOP("closure scoped by neither the global object nor a Call object");
 
             guard(true,
                   w.eqp(w.ldpObjParent(callee_ins), w.immpObjGC(parent)),
@@ -13814,18 +13815,18 @@ TraceRecorder::record_JSOP_FUNAPPLY()
 
     JS_ASSERT(!cx->fp()->hasImacropc());
 
     if (!IsFunctionObject(vp[0]))
         return record_JSOP_CALL();
     RETURN_IF_XML_A(vp[0]);
 
     JSObject* obj = &vp[0].toObject();
-    JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj);
-    if (FUN_INTERPRETED(fun))
+    JSFunction* fun = obj->getFunctionPrivate();
+    if (fun->isInterpreted())
         return record_JSOP_CALL();
 
     bool apply = fun->u.n.native == js_fun_apply;
     if (!apply && fun->u.n.native != js_fun_call)
         return record_JSOP_CALL();
 
     /*
      * We don't trace apply and call with a primitive 'this', which is the
@@ -15417,44 +15418,44 @@ TraceRecorder::getFullIndex(ptrdiff_t pc
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_LAMBDA()
 {
     JSFunction* fun;
     fun = cx->fp()->script()->getFunction(getFullIndex());
 
-    if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() != globalObj)
+    if (fun->isNullClosure() && fun->getParent() != globalObj)
         RETURN_STOP_A("Null closure function object parent must be global object");
 
     /*
      * Emit code to clone a null closure parented by this recorder's global
      * object, in order to preserve function object evaluation rules observable
      * via identity and mutation. But don't clone if our result is consumed by
      * JSOP_SETMETHOD or JSOP_INITMETHOD, since we optimize away the clone for
      * these combinations and clone only if the "method value" escapes.
      *
      * See jsinterp.cpp, the JSOP_LAMBDA null closure case. The JSOP_SETMETHOD and
      * JSOP_INITMETHOD logic governing the early ARECORD_CONTINUE returns below
      * must agree with the corresponding break-from-do-while(0) logic there.
      */
-    if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() == &cx->fp()->scopeChain()) {
+    if (fun->isNullClosure() && fun->getParent() == &cx->fp()->scopeChain()) {
         jsbytecode *pc2 = AdvanceOverBlockchainOp(cx->regs().pc + JSOP_LAMBDA_LENGTH);
         JSOp op2 = JSOp(*pc2);
 
         if (op2 == JSOP_INITMETHOD) {
-            stack(0, w.immpObjGC(FUN_OBJECT(fun)));
+            stack(0, w.immpObjGC(fun));
             return ARECORD_CONTINUE;
         }
 
         if (op2 == JSOP_SETMETHOD) {
             Value lval = stackval(-1);
 
             if (!lval.isPrimitive() && lval.toObject().canHaveMethodBarrier()) {
-                stack(0, w.immpObjGC(FUN_OBJECT(fun)));
+                stack(0, w.immpObjGC(fun));
                 return ARECORD_CONTINUE;
             }
         } else if (fun->joinable()) {
             if (op2 == JSOP_CALL) {
                 /*
                  * Array.prototype.sort and String.prototype.replace are
                  * optimized as if they are special form. We know that they
                  * won't leak the joined function object in obj, therefore
@@ -15472,26 +15473,26 @@ TraceRecorder::record_JSOP_LAMBDA()
                 JSObject *callee;
 
                 if (IsFunctionObject(cref, &callee)) {
                     JSFunction *calleeFun = callee->getFunctionPrivate();
                     Native native = calleeFun->maybeNative();
 
                     if ((iargc == 1 && native == array_sort) ||
                         (iargc == 2 && native == str_replace)) {
-                        stack(0, w.immpObjGC(FUN_OBJECT(fun)));
+                        stack(0, w.immpObjGC(fun));
                         return ARECORD_CONTINUE;
                     }
                 }
             } else if (op2 == JSOP_NULL) {
                 pc2 += JSOP_NULL_LENGTH;
                 op2 = JSOp(*pc2);
 
                 if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0) {
-                    stack(0, w.immpObjGC(FUN_OBJECT(fun)));
+                    stack(0, w.immpObjGC(fun));
                     return ARECORD_CONTINUE;
                 }
             }
         }
 
         LIns *proto_ins;
         CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins));
 
@@ -15519,17 +15520,17 @@ TraceRecorder::record_JSOP_LAMBDA()
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_LAMBDA_FC()
 {
     JSFunction* fun;
     fun = cx->fp()->script()->getFunction(getFullIndex());
 
-    if (FUN_OBJECT(fun)->getParent() != globalObj)
+    if (fun->getParent() != globalObj)
         return ARECORD_STOP;
 
     if (GetBlockChainFast(cx, cx->fp(), JSOP_LAMBDA_FC, JSOP_LAMBDA_FC_LENGTH))
         RETURN_STOP_A("Unable to trace creating lambda in let");
 
     LIns* args[] = { scopeChain(), w.immpFunGC(fun), cx_ins };
     LIns* closure_ins = w.call(&js_AllocFlatClosure_ci, args);
     guard(false,
@@ -15667,19 +15668,19 @@ TraceRecorder::record_JSOP_ARGCNT()
     }
     stack(0, w.immd(fp->numActualArgs()));
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj)
 {
-    JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj);
-
-    if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() == globalObj) {
+    JSFunction* fun = obj->getFunctionPrivate();
+
+    if (fun->isNullClosure() && fun->getParent() == globalObj) {
         LIns *proto_ins;
         CHECK_STATUS_A(getClassPrototype(JSProto_Function, proto_ins));
 
         LIns* args[] = { w.immpObjGC(globalObj), proto_ins, w.immpFunGC(fun), cx_ins };
         LIns* x = w.call(&js_NewNullClosure_ci, args);
         var(slot, x);
         return ARECORD_CONTINUE;
     }
@@ -16007,17 +16008,17 @@ TraceRecorder::record_JSOP_CALLPROP()
     PCVal pcval;
     CHECK_STATUS_A(test_property_cache(obj, obj_ins, obj2, pcval));
 
     if (pcval.isNull())
         RETURN_STOP_A("callprop of missing method");
 
     if (pcval.isFunObj()) {
         if (l.isPrimitive()) {
-            JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &pcval.toFunObj());
+            JSFunction* fun = pcval.toFunObj().getFunctionPrivate();
             if (fun->isInterpreted() && !fun->inStrictMode())
                 RETURN_STOP_A("callee does not accept primitive |this|");
         }
         set(&l, w.immpObjGC(&pcval.toFunObj()));
     } else {
         if (l.isPrimitive())
             RETURN_STOP_A("callprop of primitive method");
         JS_ASSERT_IF(pcval.isShape(), !pcval.toShape()->isMethod());
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -1638,17 +1638,17 @@ fail:
  */
 static JSBool
 GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
 {
     jsval v;
 
     if (!js_FindClassObject(cx, NULL, JSProto_XML, Valueify(&v)))
         return JS_FALSE;
-    if (!VALUE_IS_FUNCTION(cx, v)) {
+    if (JSVAL_IS_PRIMITIVE(v) || !JSVAL_TO_OBJECT(v)->isFunction()) {
         *vp = JSVAL_VOID;
         return JS_TRUE;
     }
     return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp);
 }
 
 static JSBool
 GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp)
@@ -5148,17 +5148,18 @@ JS_FRIEND_DATA(Class) js_XMLClass = {
 
 static JSXML *
 StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
 {
     JSXML *xml;
     JSFunction *fun;
     char numBuf[12];
 
-    JS_ASSERT(VALUE_IS_FUNCTION(cx, *vp));
+    JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+    JS_ASSERT(JSVAL_TO_OBJECT(*vp)->isFunction());
 
     *objp = ToObject(cx, Valueify(&vp[1]));
     if (!*objp)
         return NULL;
     if (!(*objp)->isXML()) {
         ReportIncompatibleMethod(cx, Valueify(vp), &js_XMLClass);
         return NULL;
     }
@@ -5172,17 +5173,17 @@ StartNonListXMLMethod(JSContext *cx, jsv
             *objp = js_GetXMLObject(cx, xml);
             if (!*objp)
                 return NULL;
             vp[1] = OBJECT_TO_JSVAL(*objp);
             return xml;
         }
     }
 
-    fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp));
+    fun = JSVAL_TO_OBJECT(*vp)->getFunctionPrivate();
     JS_snprintf(numBuf, sizeof numBuf, "%u", xml->xml_kids.length);
     JSAutoByteString funNameBytes;
     if (const char *funName = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NON_LIST_XML_METHOD,
                              funName, numBuf);
     }
     return NULL;
 }
@@ -7495,17 +7496,17 @@ GetXMLFunction(JSContext *cx, JSObject *
      * See comments before xml_lookupProperty about the need for the proto
      * chain lookup.
      */
     JSObject *target = obj;
     AutoObjectRooter tvr(cx);
     for (;;) {
         if (!js_GetProperty(cx, target, id, Valueify(vp)))
             return false;
-        if (VALUE_IS_FUNCTION(cx, *vp))
+        if (!JSVAL_IS_PRIMITIVE(*vp) && JSVAL_TO_OBJECT(*vp)->isFunction())
             return true;
         target = target->getProto();
         if (target == NULL || !target->isNative())
             break;
         tvr.setObject(target);
     }
 
     JSXML *xml = (JSXML *) obj->getPrivate();
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -414,17 +414,17 @@ stubs::UncachedCallHelper(VMFrame &f, ui
 {
     ucr->init();
 
     JSContext *cx = f.cx;
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
 
     if (IsFunctionObject(args.calleev(), &ucr->callee)) {
         ucr->callee = &args.callee();
-        ucr->fun = GET_FUNCTION_PRIVATE(cx, ucr->callee);
+        ucr->fun = ucr->callee->getFunctionPrivate();
 
         if (ucr->fun->isInterpreted()) {
             if (!UncachedInlineCall(f, NO_CONSTRUCT, &ucr->codeAddr, &ucr->unjittable, argc))
                 THROW();
             return;
         }
 
         if (ucr->fun->isNative()) {
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -553,17 +553,17 @@ class SetPropCompiler : public PICStubCo
             uintN flags = 0;
             PropertyOp getter = clasp->getProperty;
 
             if (pic.kind == ic::PICInfo::SETMETHOD) {
                 if (!obj->canHaveMethodBarrier())
                     return disable("can't have method barrier");
 
                 JSObject *funobj = &f.regs.sp[-1].toObject();
-                if (funobj != GET_FUNCTION_PRIVATE(cx, funobj))
+                if (funobj != funobj->getFunctionPrivate())
                     return disable("mismatched function");
 
                 flags |= Shape::METHOD;
                 getter = CastAsPropertyOp(funobj);
             }
 
             /*
              * Define the property but do not set it yet. For setmethod,
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -699,19 +699,19 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
     StackFrame *fp = f.fp();
 
     /*
      * A top-level function defined in Global or Eval code (see ECMA-262
      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
      * a compound statement (not at the top statement level of global code, or
      * at the top level of a function body).
      */
-    JSObject *obj = FUN_OBJECT(fun);
+    JSObject *obj = fun;
 
-    if (FUN_NULL_CLOSURE(fun)) {
+    if (fun->isNullClosure()) {
         /*
          * Even a null closure needs a parent for principals finding.
          * FIXME: bug 476950, although debugger users may also demand some kind
          * of scope link for debugger-assisted eval-in-frame.
          */
         obj2 = &fp->scopeChain();
     } else {
         JS_ASSERT(!fun->isFlatClosure());
@@ -1320,20 +1320,20 @@ stubs::DefLocalFun(VMFrame &f, JSFunctio
     /*
      * Define a local function (i.e., one nested at the top level of another
      * function), parented by the current scope chain, stored in a local
      * variable slot that the compiler allocated.  This is an optimization over
      * JSOP_DEFFUN that avoids requiring a call object for the outer function's
      * activation.
      */
     JS_ASSERT(fun->isInterpreted());
-    JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
-    JSObject *obj = FUN_OBJECT(fun);
+    JS_ASSERT(!fun->isFlatClosure());
+    JSObject *obj = fun;
 
-    if (FUN_NULL_CLOSURE(fun)) {
+    if (fun->isNullClosure()) {
         obj = CloneFunctionObject(f.cx, fun, &f.fp()->scopeChain());
         if (!obj)
             THROWV(NULL);
     } else {
         JSObject *parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
                                              JSOP_DEFLOCALFUN_LENGTH);
         if (!parent)
             THROWV(NULL);
@@ -1376,43 +1376,43 @@ stubs::RegExp(VMFrame &f, JSObject *rege
     if (!obj)
         THROWV(NULL);
     return obj;
 }
 
 JSObject * JS_FASTCALL
 stubs::LambdaForInit(VMFrame &f, JSFunction *fun)
 {
-    JSObject *obj = FUN_OBJECT(fun);
-    if (FUN_NULL_CLOSURE(fun) && obj->getParent() == &f.fp()->scopeChain()) {
+    JSObject *obj = fun;
+    if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
         fun->setMethodAtom(f.fp()->script()->getAtom(GET_SLOTNO(f.regs.pc)));
         return obj;
     }
     return Lambda(f, fun);
 }
 
 JSObject * JS_FASTCALL
 stubs::LambdaForSet(VMFrame &f, JSFunction *fun)
 {
-    JSObject *obj = FUN_OBJECT(fun);
-    if (FUN_NULL_CLOSURE(fun) && obj->getParent() == &f.fp()->scopeChain()) {
+    JSObject *obj = fun;
+    if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
         const Value &lref = f.regs.sp[-1];
         if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
             fun->setMethodAtom(f.fp()->script()->getAtom(GET_SLOTNO(f.regs.pc)));
             return obj;
         }
     }
     return Lambda(f, fun);
 }
 
 JSObject * JS_FASTCALL
 stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
 {
-    JSObject *obj = FUN_OBJECT(fun);
-    if (FUN_NULL_CLOSURE(fun) && obj->getParent() == &f.fp()->scopeChain()) {
+    JSObject *obj = fun;
+    if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
         /*
          * Array.prototype.sort and String.prototype.replace are
          * optimized as if they are special form. We know that they
          * won't leak the joined function object in obj, therefore
          * we don't need to clone that compiler- created function
          * object for identity/mutation reasons.
          */
         int iargc = GET_ARGC(f.regs.pc);
@@ -1438,34 +1438,34 @@ stubs::LambdaJoinableForCall(VMFrame &f,
         }
     }
     return Lambda(f, fun);
 }
 
 JSObject * JS_FASTCALL
 stubs::LambdaJoinableForNull(VMFrame &f, JSFunction *fun)
 {
-    JSObject *obj = FUN_OBJECT(fun);
-    if (FUN_NULL_CLOSURE(fun) && obj->getParent() == &f.fp()->scopeChain()) {
+    JSObject *obj = fun;
+    if (fun->isNullClosure() && obj->getParent() == &f.fp()->scopeChain()) {
         jsbytecode *pc2 = f.regs.pc + JSOP_NULL_LENGTH;
         JSOp op2 = JSOp(*pc2);
 
         if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
             return obj;
     }
     return Lambda(f, fun);
 }
 
 JSObject * JS_FASTCALL
 stubs::Lambda(VMFrame &f, JSFunction *fun)
 {
-    JSObject *obj = FUN_OBJECT(fun);
+    JSObject *obj = fun;
 
     JSObject *parent;
-    if (FUN_NULL_CLOSURE(fun)) {
+    if (fun->isNullClosure()) {
         parent = &f.fp()->scopeChain();
     } else {
         parent = GetScopeChainFast(f.cx, f.fp(), JSOP_LAMBDA, JSOP_LAMBDA_LENGTH);
         if (!parent)
             THROWV(NULL);
     }
 
     obj = CloneFunctionObject(f.cx, fun, parent);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1549,25 +1549,25 @@ ValueToScript(JSContext *cx, jsval v)
         JSObject *obj = JSVAL_TO_OBJECT(v);
         JSClass *clasp = JS_GET_CLASS(cx, obj);
 
         if (clasp == Jsvalify(&js_ScriptClass)) {
             script = (JSScript *) JS_GetPrivate(cx, obj);
         } else if (clasp == Jsvalify(&js_GeneratorClass)) {
             JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
             fun = gen->floatingFrame()->fun();
-            script = FUN_SCRIPT(fun);
+            script = fun->script();
         }
     }
 
     if (!script) {
         fun = JS_ValueToFunction(cx, v);
         if (!fun)
             return NULL;
-        script = FUN_SCRIPT(fun);
+        script = fun->maybeScript();
         if (!script) {
             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                                  JSSMSG_SCRIPTS_ONLY);
         }
     }
 
     return script;
 }
@@ -1987,35 +1987,35 @@ TryNotes(JSContext *cx, JSScript *script
 }
 
 static bool
 DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive, Sprinter *sp)
 {
     JSScript *script = ValueToScript(cx, v);
     if (!script)
         return false;
-    if (VALUE_IS_FUNCTION(cx, v)) {
+    if (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction()) {
         JSFunction *fun = JS_ValueToFunction(cx, v);
         if (fun && (fun->flags & ~7U)) {
             uint16 flags = fun->flags;
             Sprint(sp, "flags:");
 
 #define SHOW_FLAG(flag) if (flags & JSFUN_##flag) Sprint(sp, " " #flag);
 
             SHOW_FLAG(LAMBDA);
             SHOW_FLAG(HEAVYWEIGHT);
             SHOW_FLAG(EXPR_CLOSURE);
             SHOW_FLAG(TRCINFO);
 
 #undef SHOW_FLAG
 
-            if (FUN_INTERPRETED(fun)) {
-                if (FUN_NULL_CLOSURE(fun))
+            if (fun->isInterpreted()) {
+                if (fun->isNullClosure())
                     Sprint(sp, " NULL_CLOSURE");
-                else if (FUN_FLAT_CLOSURE(fun))
+                else if (fun->isFlatClosure())
                     Sprint(sp, " FLAT_CLOSURE");
 
                 JSScript *script = fun->script();
                 if (script->bindings.hasUpvars()) {
                     Sprint(sp, "\nupvars: {\n");
 
                     Vector<JSAtom *> localNames(cx);
                     if (!script->bindings.getLocalNameArray(cx, &localNames))
@@ -2693,17 +2693,17 @@ Clone(JSContext *cx, uintN argc, jsval *
         if (!JSVAL_IS_PRIMITIVE(argv[0]) &&
             JSVAL_TO_OBJECT(argv[0])->isCrossCompartmentWrapper())
         {
             JSObject *obj = JSVAL_TO_OBJECT(argv[0])->unwrap();
             if (!ac.enter(cx, obj))
                 return JS_FALSE;
             argv[0] = OBJECT_TO_JSVAL(obj);
         }
-        if (VALUE_IS_FUNCTION(cx, argv[0])) {
+        if (!JSVAL_IS_PRIMITIVE(argv[0]) && JSVAL_TO_OBJECT(argv[0])->isFunction()) {
             funobj = JSVAL_TO_OBJECT(argv[0]);
         } else {
             JSFunction *fun = JS_ValueToFunction(cx, argv[0]);
             if (!fun)
                 return JS_FALSE;
             funobj = JS_GetFunctionObject(fun);
         }
     }
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -209,17 +209,17 @@ GlobalObject::createConstructor(JSContex
     JSFunction *fun = js_NewFunction(cx, NULL, ctor, length, JSFUN_CONSTRUCTOR, this, name);
     if (!fun)
         return NULL;
 
     /*
      * Remember the class this function is a constructor for so that we know to
      * create an object of this class when we call the constructor.
      */
-    FUN_CLASP(fun) = clasp;
+    fun->setConstructorClass(clasp);
     return fun;
 }
 
 static JSObject *
 CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
 {
     JS_ASSERT(clasp != &js_ObjectClass);
     JS_ASSERT(clasp != &js_FunctionClass);
--- a/js/src/xpconnect/src/xpcwrappednativejsops.cpp
+++ b/js/src/xpconnect/src/xpcwrappednativejsops.cpp
@@ -1571,17 +1571,17 @@ XPC_WN_CallMethod(JSContext *cx, uintN a
     JSObject* funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
     JSObject* obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
 #ifdef DEBUG_slimwrappers
     {
-        JSFunction* fun = GET_FUNCTION_PRIVATE(cx, funobj);
+        JSFunction* fun = funobj->getFunctionPrivate();
         JSString *funid = JS_GetFunctionId(fun);
         JSAutoByteString bytes;
         const char *funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
     }
 #endif
     if(IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
@@ -1610,17 +1610,17 @@ XPC_WN_GetterSetter(JSContext *cx, uintN
         return JS_FALSE;
 
 #ifdef DEBUG_slimwrappers
     {
         const char* funname = nsnull;
         JSAutoByteString bytes;
         if(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION)
         {
-            JSString *funid = JS_GetFunctionId(GET_FUNCTION_PRIVATE(cx, funobj));
+            JSString *funid = JS_GetFunctionId(funobj->getFunctionPrivate());
             funname = !funid ? "" : bytes.encode(cx, funid) ? bytes.ptr() : "<error>";
         }
         SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
     }
 #endif
     if(IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);