Bug 807228 - clean up the JSFUN_* flags situation (r=jorendorff)
authorLuke Wagner <luke@mozilla.com>
Thu, 01 Nov 2012 21:35:09 -0700
changeset 120544 247fb06146151efbce3291faabd392c31b115423
parent 120543 ed5120ffd1184809a436b7b95dedd011ac11351a
child 120545 2628f57bdd4bb7409407aea52b3c3a936158e4d4
push id1997
push userakeybl@mozilla.com
push dateMon, 07 Jan 2013 21:25:26 +0000
treeherdermozilla-beta@4baf45cdcf21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs807228
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 807228 - clean up the JSFUN_* flags situation (r=jorendorff)
js/src/builtin/ParallelArray.cpp
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/Parser.cpp
js/src/ion/CodeGenerator.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsbool.cpp
js/src/jscntxt.cpp
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsfuninlines.h
js/src/jsobj.cpp
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsreflect.cpp
js/src/jstypedarray.cpp
js/src/methodjit/Compiler.cpp
js/src/perf/jsperf.cpp
js/src/shell/js.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -1003,19 +1003,19 @@ ParallelArrayObject::initClass(JSContext
     }
 
     // Define the length and shape properties.
     RootedId lengthId(cx, AtomToId(cx->names().length));
     RootedId shapeId(cx, AtomToId(cx->names().shape));
     unsigned flags = JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_GETTER;
 
     RootedObject scriptedLength(cx, js_NewFunction(cx, NullPtr(), NonGenericMethod<lengthGetter>,
-                                                   0, 0, global, NullPtr()));
+                                                   0, JSFunction::NATIVE_FUN, global, NullPtr()));
     RootedObject scriptedShape(cx, js_NewFunction(cx, NullPtr(), NonGenericMethod<dimensionsGetter>,
-                                                  0, 0, global, NullPtr()));
+                                                  0, JSFunction::NATIVE_FUN, global, NullPtr()));
 
     RootedValue value(cx, UndefinedValue());
     if (!scriptedLength || !scriptedShape ||
         !DefineNativeProperty(cx, proto, lengthId, value,
                               JS_DATA_TO_FUNC_PTR(PropertyOp, scriptedLength.get()), NULL,
                               flags, 0, 0) ||
         !DefineNativeProperty(cx, proto, shapeId, value,
                               JS_DATA_TO_FUNC_PTR(PropertyOp, scriptedShape.get()), NULL,
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1371,17 +1371,17 @@ BindNameToSlot(JSContext *cx, BytecodeEm
         /*
          * Currently, the ALIASEDVAR ops do not support accessing the
          * callee of a DeclEnvObject, so use NAME.
          */
         if (dn->pn_cookie.level() != bce->script->staticLevel)
             return true;
 
         RootedFunction fun(cx, bce->sc->asFunbox()->function());
-        JS_ASSERT(fun->flags & JSFUN_LAMBDA);
+        JS_ASSERT(fun->isLambda());
         JS_ASSERT(pn->pn_atom == fun->atom());
 
         /*
          * Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
          * address two cases: a new binding introduced by eval, and
          * assignment to the name in strict mode.
          *
          *   var fun = (function f(s) { eval(s); return f; });
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -312,17 +312,17 @@ ParseContext::generateFunctionBindings(J
     if (!Bindings::initWithTemporaryStorage(cx, bindings, args_.length(), vars_.length(),
                                             packedBindings))
     {
         return false;
     }
 
     FunctionBox *funbox = sc->asFunbox();
     if (bindings->hasAnyAliasedBindings() || funbox->hasExtensibleScope())
-        funbox->function()->flags |= JSFUN_HEAVYWEIGHT;
+        funbox->function()->setIsHeavyweight();
 
     return true;
 }
 
 Parser::Parser(JSContext *cx, const CompileOptions &options,
                StableCharPtr chars, size_t length, bool foldConstants)
   : AutoGCRooter(cx, PARSER),
     context(cx),
@@ -1047,20 +1047,22 @@ Parser::newFunction(ParseContext *pc, Ha
      */
     while (pc->parent)
         pc = pc->parent;
 
     RootedObject parent(context);
     parent = pc->sc->isFunction ? NULL : pc->sc->asGlobal()->scopeChain();
 
     RootedFunction fun(context);
-    uint32_t flags = JSFUN_INTERPRETED | (kind == Expression ? JSFUN_LAMBDA : 0);
+    JSFunction::Flags flags = (kind == Expression)
+                              ? JSFunction::INTERPRETED_LAMBDA
+                              : JSFunction::INTERPRETED;
+    fun = js_NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom);
     if (selfHostingMode)
-        flags |= JSFUN_SELF_HOSTED;
-    fun = js_NewFunction(context, NullPtr(), NULL, 0, flags, parent, atom);
+        fun->setIsSelfHostedBuiltin();
     if (fun && !compileAndGo) {
         if (!JSObject::clearParent(context, fun))
             return NULL;
         if (!JSObject::clearType(context, fun))
             return NULL;
         fun->setEnvironment(NULL);
     }
     return fun;
@@ -1142,17 +1144,17 @@ LeaveFunction(ParseNode *fn, Parser *par
                  * definitions in the ParseContext by generateFunctionBindings).
                  *
                  * If 'dn' has been assigned to, then we also flag the function
                  * scope has needing a dynamic scope so that dynamic scope
                  * setter can either ignore the set (in non-strict mode) or
                  * produce an error (in strict mode).
                  */
                 if (dn->isClosed() || dn->isAssigned())
-                    funbox->function()->flags |= JSFUN_HEAVYWEIGHT;
+                    funbox->function()->setIsHeavyweight();
                 continue;
             }
 
             Definition *outer_dn = pc->decls().lookupFirst(atom);
 
             /*
              * Make sure to deoptimize lexical dependencies that are polluted
              * by eval and function statements (which both flag the function as
@@ -1627,17 +1629,17 @@ Parser::functionDef(HandlePropertyName f
         reportError(NULL, JSMSG_ACCESSOR_WRONG_ARGS, "setter", "one", "");
         return NULL;
     }
 
     FunctionBodyType bodyType = StatementListBody;
 #if JS_HAS_EXPR_CLOSURES
     if (tokenStream.getToken(TSF_OPERAND) != TOK_LC) {
         tokenStream.ungetToken();
-        fun->flags |= JSFUN_EXPR_CLOSURE;
+        fun->setIsExprClosure();
         bodyType = ExpressionBody;
     }
 #else
     MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
 #endif
 
     ParseNode *body = functionBody(bodyType);
     if (!body)
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -301,17 +301,17 @@ CodeGenerator::visitLambda(LLambda *lir)
     union {
         struct S {
             uint16_t nargs;
             uint16_t flags;
         } s;
         uint32_t word;
     } u;
     u.s.nargs = fun->nargs;
-    u.s.flags = fun->flags & ~JSFUN_EXTENDED;
+    u.s.flags = fun->flags & ~JSFunction::EXTENDED;
 
     JS_STATIC_ASSERT(offsetof(JSFunction, flags) == offsetof(JSFunction, nargs) + 2);
     masm.store32(Imm32(u.word), Address(output, offsetof(JSFunction, nargs)));
     masm.storePtr(ImmGCPtr(fun->script().unsafeGet()),
                   Address(output, JSFunction::offsetOfNativeOrScript()));
     masm.storePtr(scopeChain, Address(output, JSFunction::offsetOfEnvironment()));
     masm.storePtr(ImmGCPtr(fun->displayAtom()), Address(output, JSFunction::offsetOfAtom()));
 
@@ -822,21 +822,21 @@ CodeGenerator::visitCallGeneric(LCallGen
 
     // Guard that calleereg is actually a function object.
     masm.loadObjClass(calleereg, nargsreg);
     masm.cmpPtr(nargsreg, ImmWord(&js::FunctionClass));
     if (!bailoutIf(Assembler::NotEqual, call->snapshot()))
         return false;
 
     // Guard that calleereg is a non-native function:
-    // Non-native iff (callee->flags & JSFUN_KINDMASK >= JSFUN_INTERPRETED).
-    // This is equivalent to testing if any of the bits in JSFUN_KINDMASK are set.
+    // We do this by testing whether JSFunction::INTERPRETED is set
+    // TODO: this could be optimized
     Address flags(calleereg, offsetof(JSFunction, flags));
-    masm.load16ZeroExtend_mask(flags, Imm32(JSFUN_INTERPRETED), nargsreg);
-    masm.branch32(Assembler::NotEqual, nargsreg, Imm32(JSFUN_INTERPRETED), &invoke);
+    masm.load16ZeroExtend_mask(flags, Imm32(JSFunction::INTERPRETED), nargsreg);
+    masm.branch32(Assembler::NotEqual, nargsreg, Imm32(JSFunction::INTERPRETED), &invoke);
 
     // Knowing that calleereg is a non-native function, load the JSScript.
     masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
     masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
 
     // Guard that the IonScript has been compiled.
     masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
 
@@ -1124,23 +1124,23 @@ CodeGenerator::visitApplyArgsGeneric(LAp
             return false;
         emitPopArguments(apply, copyreg);
         return true;
     }
 
     Label end, invoke;
 
     // Guard that calleereg is a non-native function:
-    // Non-native iff (callee->flags & JSFUN_KINDMASK >= JSFUN_INTERPRETED).
-    // This is equivalent to testing if any of the bits in JSFUN_KINDMASK are set.
+    // We do this by testing whether JSFunction::INTERPRETED is set
+    // TODO: this could be optimized
     if (!apply->hasSingleTarget()) {
         Register kind = objreg;
         Address flags(calleereg, offsetof(JSFunction, flags));
-        masm.load16ZeroExtend_mask(flags, Imm32(JSFUN_INTERPRETED), kind);
-        masm.branch32(Assembler::NotEqual, kind, Imm32(JSFUN_INTERPRETED), &invoke);
+        masm.load16ZeroExtend_mask(flags, Imm32(JSFunction::INTERPRETED), kind);
+        masm.branch32(Assembler::NotEqual, kind, Imm32(JSFunction::INTERPRETED), &invoke);
     } else {
         // Native single targets are handled by LCallNative.
         JS_ASSERT(!apply->getSingleTarget()->isNative());
     }
 
     // Knowing that calleereg is a non-native function, load the JSScript.
     masm.movePtr(Address(calleereg, offsetof(JSFunction, u.i.script_)), objreg);
     masm.movePtr(Address(objreg, offsetof(JSScript, ion)), objreg);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4815,32 +4815,34 @@ JS_NewFunction(JSContext *cx, JSNative n
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
             return NULL;
     }
 
-    return js_NewFunction(cx, NullPtr(), native, nargs, flags, parent, atom);
+    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
+    return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                    jsid id)
 {
     RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
-    return js_NewFunction(cx, NullPtr(), native, nargs, flags, parent, atom);
+    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
+    return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSRawObject parentArg)
 {
     RootedObject funobj(cx, funobjArg);
     RootedObject parent(cx, parentArg);
     AssertHeapIsIdle(cx);
@@ -4888,22 +4890,16 @@ JS_GetFunctionId(JSFunction *fun)
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetFunctionDisplayId(JSFunction *fun)
 {
     return fun->displayAtom();
 }
 
-JS_PUBLIC_API(unsigned)
-JS_GetFunctionFlags(JSFunction *fun)
-{
-    return fun->flags;
-}
-
 JS_PUBLIC_API(uint16_t)
 JS_GetFunctionArity(JSFunction *fun)
 {
     return fun->nargs;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ObjectIsFunction(JSContext *cx, RawObject obj)
@@ -4921,16 +4917,22 @@ JS_PUBLIC_API(JSBool)
 JS_IsNativeFunction(JSRawObject funobj, JSNative call)
 {
     if (!funobj->isFunction())
         return false;
     JSFunction *fun = funobj->toFunction();
     return fun->isNative() && fun->native() == call;
 }
 
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructor(JSFunction *fun)
+{
+    return fun->isNativeConstructor() || fun->isInterpretedConstructor();
+}
+
 JS_PUBLIC_API(JSObject*)
 JS_BindCallable(JSContext *cx, JSObject *targetArg, JSRawObject newThis)
 {
     RootedObject target(cx, targetArg);
     RootedValue thisArg(cx, ObjectValue(*newThis));
     return js_fun_bind(cx, target, thisArg, NULL, 0);
 }
 
@@ -4960,48 +4962,47 @@ js_generic_native_method_dispatcher(JSCo
     vp[2 + --argc].setUndefined();
 
     return fs->call.op(cx, argc, vp);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *objArg, JSFunctionSpec *fs)
 {
+    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, objArg);
+
     RootedObject obj(cx, objArg);
-    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
-    unsigned flags;
     RootedObject ctor(cx);
-    JSFunction *fun;
-
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj);
+
     for (; fs->name; fs++) {
-        flags = fs->flags;
-
         RootedAtom atom(cx, Atomize(cx, fs->name, strlen(fs->name)));
         if (!atom)
             return JS_FALSE;
 
         Rooted<jsid> id(cx, AtomToId(atom));
 
         /*
          * Define a generic arity N+1 static method for the arity N prototype
          * method if flags contains JSFUN_GENERIC_NATIVE.
          */
+        unsigned flags = fs->flags;
         if (flags & JSFUN_GENERIC_NATIVE) {
             if (!ctor) {
                 ctor = JS_GetConstructor(cx, obj);
                 if (!ctor)
                     return JS_FALSE;
             }
 
             flags &= ~JSFUN_GENERIC_NATIVE;
-            fun = js_DefineFunction(cx, ctor, id, js_generic_native_method_dispatcher,
-                                    fs->nargs + 1, flags, NullPtr(), JSFunction::ExtendedFinalizeKind);
+            JSFunction *fun = js_DefineFunction(cx, ctor, id, js_generic_native_method_dispatcher,
+                                    fs->nargs + 1, flags, NullPtr(),
+                                    JSFunction::ExtendedFinalizeKind);
             if (!fun)
                 return JS_FALSE;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             fun->setExtendedSlot(0, PrivateValue(fs));
@@ -5019,17 +5020,18 @@ JS_DefineFunctions(JSContext *cx, JSObje
 
         Rooted<PropertyName*> selfHostedPropertyName(cx);
         if (fs->selfHostedName) {
             JSAtom *selfHostedAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName));
             if (!selfHostedAtom)
                 return JS_FALSE;
             selfHostedPropertyName = selfHostedAtom->asPropertyName();
         }
-        fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags, selfHostedPropertyName);
+        JSFunction *fun = js_DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags,
+                                            selfHostedPropertyName);
         if (!fun)
             return JS_FALSE;
         if (fs->call.info)
             fun->setJitInfo(fs->call.info);
     }
     return JS_TRUE;
 }
 
@@ -5418,17 +5420,17 @@ JS::CompileFunction(JSContext *cx, Handl
 
     AutoNameVector formals(cx);
     for (unsigned i = 0; i < nargs; i++) {
         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
         if (!argAtom || !formals.append(argAtom->asPropertyName()))
             return NULL;
     }
 
-    RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFUN_INTERPRETED, obj, funAtom));
+    RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj, funAtom));
     if (!fun)
         return NULL;
 
     if (!frontend::CompileFunctionBody(cx, fun, options, formals, StableCharPtr(chars, length), length))
         return NULL;
 
     if (obj && funAtom) {
         Rooted<jsid> id(cx, AtomToId(funAtom));
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2435,70 +2435,49 @@ class AutoIdRooter : private AutoGCRoote
 
 /* Property attributes, set in JSPropertySpec and passed to API functions. */
 #define JSPROP_ENUMERATE        0x01    /* property is visible to for/in loop */
 #define JSPROP_READONLY         0x02    /* not settable: assignment is no-op.
                                            This flag is only valid when neither
                                            JSPROP_GETTER nor JSPROP_SETTER is
                                            set. */
 #define JSPROP_PERMANENT        0x04    /* property cannot be deleted */
+#define JSPROP_NATIVE_ACCESSORS 0x08    /* set in JSPropertyDescriptor.flags
+                                           if getters/setters are JSNatives */
 #define JSPROP_GETTER           0x10    /* property holds getter function */
 #define JSPROP_SETTER           0x20    /* property holds setter function */
 #define JSPROP_SHARED           0x40    /* don't allocate a value slot for this
                                            property; don't copy the property on
                                            set of the same-named property in an
                                            object that delegates to a prototype
                                            containing this property */
 #define JSPROP_INDEX            0x80    /* name is actually (int) index */
-#define JSPROP_SHORTID          0x100   /* set in JS_DefineProperty attrs
+#define JSPROP_SHORTID         0x100    /* set in JS_DefineProperty attrs
                                            if getters/setters use a shortid */
-#define JSPROP_NATIVE_ACCESSORS 0x08    /* set in JSPropertyDescriptor.flags
-                                           if getters/setters are JSNatives */
-
-/* Function flags, internal use only, returned by JS_GetFunctionFlags. */
-#define JSFUN_LAMBDA            0x08    /* expressed, not declared, function */
-
-#define JSFUN_SELF_HOSTED       0x20    /* function is self-hosted builtin and
-                                           must not be decompilable nor
-                                           constructible. */
-
-#define JSFUN_SELF_HOSTED_CTOR  0x40    /* function is self-hosted builtin
-                                           constructor and must be constructible
-                                           but not decompilable. */
-
-#define JSFUN_HEAVYWEIGHT       0x80    /* activation requires a Call object */
-
-#define JSFUN_HEAVYWEIGHT_TEST(f)  ((f) & JSFUN_HEAVYWEIGHT)
-
-#define JSFUN_HAS_REST          0x0100  /* function has a rest (...) parameter */
-#define JSFUN_CONSTRUCTOR       0x0200  /* native that can be called as a ctor
-                                           without creating a this object */
-#define JSFUN_HAS_DEFAULTS      0x0400  /* function has at least one default
-                                           parameter */
-
-#define JSFUN_FLAGS_MASK        0x07f8  /* overlay JSFUN_* attributes --
-                                           bits 12-15 are used internally to
-                                           flag interpreted functions */
-
-#define JSFUN_STUB_GSOPS        0x1000  /* use JS_PropertyStub getter/setter
+
+#define JSFUN_STUB_GSOPS       0x200    /* use JS_PropertyStub getter/setter
                                            instead of defaulting to class gsops
                                            for property holding function */
 
-/*
- * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in
- * JSFunctionSpec arrays that specify generic native prototype methods, i.e.,
- * methods of a class prototype that are exposed as static methods taking an
- * extra leading argument: the generic |this| parameter.
+#define JSFUN_CONSTRUCTOR      0x400    /* native that can be called as a ctor */
+
+
+/*
+ * Specify a generic native prototype methods, i.e., methods of a class
+ * prototype that are exposed as static methods taking an extra leading
+ * argument: the generic |this| parameter.
  *
  * If you set this flag in a JSFunctionSpec struct's flags initializer, then
  * that struct must live at least as long as the native static method object
  * created due to this flag by JS_DefineFunctions or JS_InitClass.  Typically
  * JSFunctionSpec structs are allocated in static arrays.
  */
-#define JSFUN_GENERIC_NATIVE    JSFUN_LAMBDA
+#define JSFUN_GENERIC_NATIVE   0x800
+
+#define JSFUN_FLAGS_MASK       0xe00    /* | of all the JSFUN_* flags */
 
 /*
  * The first call to JS_CallOnce by any thread in a process will call 'func'.
  * Later calls to JS_CallOnce with the same JSCallOnceType object will be
  * suppressed.
  *
  * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce
  * to invoke its JSInitCallback.
@@ -4787,22 +4766,16 @@ JS_GetFunctionId(JSFunction *fun);
  * engine in the case that the function was defined to be anonymous. This can
  * still return NULL if a useful display name could not be inferred. The same
  * restrictions on rooting as those in JS_GetFunctionId apply.
  */
 extern JS_PUBLIC_API(JSString *)
 JS_GetFunctionDisplayId(JSFunction *fun);
 
 /*
- * Return JSFUN_* flags for fun.
- */
-extern JS_PUBLIC_API(unsigned)
-JS_GetFunctionFlags(JSFunction *fun);
-
-/*
  * Return the arity (length) of fun.
  */
 extern JS_PUBLIC_API(uint16_t)
 JS_GetFunctionArity(JSFunction *fun);
 
 /*
  * Infallible predicate to test whether obj is a function object (faster than
  * comparing obj's class name to "Function", but equivalent unless someone has
@@ -4813,16 +4786,20 @@ extern JS_PUBLIC_API(JSBool)
 JS_ObjectIsFunction(JSContext *cx, JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_ObjectIsCallable(JSContext *cx, JSRawObject obj);
 
 extern JS_PUBLIC_API(JSBool)
 JS_IsNativeFunction(JSRawObject funobj, JSNative call);
 
+/* Return whether the given function is a valid constructor. */
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructor(JSFunction *fun);
+
 /*
  * Bind the given callable to use the given object as "this".
  *
  * If |callable| is not callable, will throw and return NULL.
  */
 extern JS_PUBLIC_API(JSObject*)
 JS_BindCallable(JSContext *cx, JSObject *callable, JSRawObject newThis);
 
@@ -5964,17 +5941,17 @@ class JSAutoSetRuntimeThread
  */
 static JS_ALWAYS_INLINE JSBool
 JS_IsConstructing(JSContext *cx, const jsval *vp)
 {
 #ifdef DEBUG
     JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
     if (JS_ObjectIsFunction(cx, callee)) {
         JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
-        JS_ASSERT((JS_GetFunctionFlags(fun) & JSFUN_CONSTRUCTOR) != 0);
+        JS_ASSERT(JS_IsConstructor(fun));
     } else {
         JS_ASSERT(JS_GetClass(callee)->construct != NULL);
     }
 #else
     (void)cx;
 #endif
 
     return JSVAL_IS_MAGIC_IMPL(JSVAL_TO_IMPL(vp[1]));
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -161,19 +161,21 @@ js_InitBooleanClass(JSContext *cx, Handl
     if (!LinkConstructorAndPrototype(cx, ctor, booleanProto))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, booleanProto, NULL, boolean_methods))
         return NULL;
 
     Handle<PropertyName*> valueOfName = cx->names().valueOf;
     RootedFunction
-        valueOf(cx, js_NewFunction(cx, NullPtr(), bool_valueOf, 0, 0, global, valueOfName));
+        valueOf(cx, js_NewFunction(cx, NullPtr(), bool_valueOf, 0, JSFunction::NATIVE_FUN,
+                                   global, valueOfName));
     if (!valueOf)
         return NULL;
+
     RootedValue value(cx, ObjectValue(*valueOf));
     if (!JSObject::defineProperty(cx, booleanProto, valueOfName, value,
                                   JS_PropertyStub, JS_StrictPropertyStub, 0))
     {
         return NULL;
     }
 
     global->setBooleanValueOf(valueOf);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -316,17 +316,17 @@ intrinsic_ThrowError(JSContext *cx, unsi
 static JSBool
 intrinsic_MakeConstructible(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() >= 1);
     JS_ASSERT(args[0].isObject());
     RootedObject obj(cx, &args[0].toObject());
     JS_ASSERT(obj->isFunction());
-    obj->toFunction()->flags |= JSFUN_SELF_HOSTED_CTOR;
+    obj->toFunction()->setIsSelfHostedConstructor();
     return true;
 }
 
 JSFunctionSpec intrinsic_functions[] = {
     JS_FN("ToObject",           intrinsic_ToObject,             1,0),
     JS_FN("ToInteger",          intrinsic_ToInteger,            1,0),
     JS_FN("IsCallable",         intrinsic_IsCallable,           1,0),
     JS_FN("ThrowError",         intrinsic_ThrowError,           4,0),
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -398,32 +398,34 @@ js::NewFunctionWithReserved(JSContext *c
 
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
             return NULL;
     }
 
-    return js_NewFunction(cx, NullPtr(), native, nargs, flags, parent, atom,
+    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
+    return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
                           JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSFunction *)
 js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
                                 jsid id)
 {
     RootedObject parent(cx, parentArg);
     JS_ASSERT(JSID_IS_STRING(id));
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
-    return js_NewFunction(cx, NullPtr(), native, nargs, flags, parent, atom,
+    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
+    return js_NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom,
                           JSFunction::ExtendedFinalizeKind);
 }
 
 JS_FRIEND_API(JSObject *)
 js::InitClassWithReserved(JSContext *cx, JSObject *objArg, JSObject *parent_protoArg,
                           JSClass *clasp, JSNative constructor, unsigned nargs,
                           JSPropertySpec *ps, JSFunctionSpec *fs,
                           JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1409,22 +1409,24 @@ struct JSJitInfo {
 
 static JS_ALWAYS_INLINE const JSJitInfo *
 FUNCTION_VALUE_TO_JITINFO(const JS::Value& v)
 {
     JS_ASSERT(js::GetObjectClass(&v.toObject()) == &js::FunctionClass);
     return reinterpret_cast<js::shadow::Function *>(&v.toObject())->jitinfo;
 }
 
+/* Statically asserted in jsfun.h. */
+static const unsigned JS_FUNCTION_INTERPRETED_BIT = 0x1;
+
 static JS_ALWAYS_INLINE void
 SET_JITINFO(JSFunction * func, const JSJitInfo *info)
 {
     js::shadow::Function *fun = reinterpret_cast<js::shadow::Function *>(func);
-    /* JS_ASSERT(func->isNative()). 0x4000 is JSFUN_INTERPRETED */
-    JS_ASSERT(!(fun->flags & 0x4000));
+    JS_ASSERT(!(fun->flags & JS_FUNCTION_INTERPRETED_BIT));
     fun->jitinfo = info;
 }
 
 /*
  * Engine-internal extensions of jsid.  This code is here only until we
  * eliminate Gecko's dependencies on it!
  */
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -399,17 +399,17 @@ js::XDRInterpretedFunction(XDRState<mode
             return false;
         }
         firstword = !!fun->atom();
         flagsword = (fun->nargs << 16) | fun->flags;
         atom = fun->atom();
         script = fun->script();
     } else {
         RootedObject parent(cx, NULL);
-        fun = js_NewFunction(cx, NullPtr(), NULL, 0, JSFUN_INTERPRETED, parent, NullPtr());
+        fun = js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, parent, NullPtr());
         if (!fun)
             return false;
         if (!JSObject::clearParent(cx, fun))
             return false;
         if (!JSObject::clearType(cx, fun))
             return false;
         atom = NULL;
         script = NULL;
@@ -452,17 +452,17 @@ JSObject *
 js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
 {
     AssertCanGC();
 
     /* NB: Keep this in sync with XDRInterpretedFunction. */
 
     RootedObject parent(cx, NULL);
     RootedFunction
-        clone(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFUN_INTERPRETED, parent, NullPtr()));
+        clone(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, parent, NullPtr()));
     if (!clone)
         return NULL;
     if (!JSObject::clearParent(cx, clone))
         return NULL;
     if (!JSObject::clearType(cx, clone))
         return NULL;
 
     RootedScript srcScript(cx, srcFun->script());
@@ -595,17 +595,17 @@ FindBody(JSContext *cx, HandleFunction f
           default:
             break;
         }
     } while (onward);
     TokenKind tt = ts.getToken();
     if (tt == TOK_ERROR)
         return false;
     bool braced = tt == TOK_LC;
-    JS_ASSERT(!!(fun->flags & JSFUN_EXPR_CLOSURE) ^ braced);
+    JS_ASSERT(fun->isExprClosure() == !braced);
     *bodyStart = ts.offsetOfToken(ts.currentToken());
     if (braced)
         *bodyStart += 1;
     StableCharPtr end(chars.get() + length, chars.get(), length);
     if (end[-1] == '}') {
         end--;
     } else {
         JS_ASSERT(!braced);
@@ -632,17 +632,17 @@ js::FunctionToString(JSContext *cx, Hand
             !out.append("\n    [generator expression]\n") ||
             (!bodyOnly && !out.append("}"))) {
             return NULL;
         }
         return out.finishString();
     }
     if (!bodyOnly) {
         // If we're not in pretty mode, put parentheses around lambda functions.
-        if (fun->isInterpreted() && !lambdaParen && (fun->flags & JSFUN_LAMBDA)) {
+        if (fun->isInterpreted() && !lambdaParen && fun->isLambda()) {
             if (!out.append("("))
                 return NULL;
         }
         if (!out.append("function "))
             return NULL;
         if (fun->atom()) {
             if (!out.append(fun->atom()))
                 return NULL;
@@ -658,17 +658,17 @@ js::FunctionToString(JSContext *cx, Hand
         RootedString srcStr(cx, script->sourceData(cx));
         if (!srcStr)
             return NULL;
         Rooted<JSStableString *> src(cx, srcStr->ensureStable(cx));
         if (!src)
             return NULL;
 
         StableCharPtr chars = src->chars();
-        bool exprBody = fun->flags & JSFUN_EXPR_CLOSURE;
+        bool exprBody = fun->isExprClosure();
         // The source data for functions created by calling the Function
         // constructor is only the function's body.
         bool funCon = script->sourceStart == 0 && script->scriptSource()->argumentsNotIncluded();
 
         // Functions created with the constructor should not be using the
         // expression body extension.
         JS_ASSERT_IF(funCon, !exprBody);
         JS_ASSERT_IF(!funCon, src->length() > 0 && chars[0] == '(');
@@ -746,29 +746,29 @@ js::FunctionToString(JSContext *cx, Hand
         if (buildBody) {
             if (!out.append("\n}"))
                 return NULL;
         }
         if (bodyOnly) {
             // Slap a semicolon on the end of functions with an expression body.
             if (exprBody && !out.append(";"))
                 return NULL;
-        } else if (!lambdaParen && (fun->flags & JSFUN_LAMBDA)) {
+        } else if (!lambdaParen && fun->isLambda()) {
             if (!out.append(")"))
                 return NULL;
         }
     } else if (fun->isInterpreted() && !fun->isSelfHostedBuiltin()) {
         if ((!bodyOnly && !out.append("() {\n    ")) ||
             !out.append("[sourceless code]") ||
             (!bodyOnly && !out.append("\n}")))
             return NULL;
-        if (!lambdaParen && (fun->flags & JSFUN_LAMBDA) && (!out.append(")")))
+        if (!lambdaParen && fun->isLambda() && !out.append(")"))
             return NULL;
     } else {
-        JS_ASSERT(!(fun->flags & JSFUN_EXPR_CLOSURE));
+        JS_ASSERT(!fun->isExprClosure());
         if ((!bodyOnly && !out.append("() {\n    ")) ||
             !out.append("[native code]") ||
             (!bodyOnly && !out.append("\n}")))
             return NULL;
     }
     return out.finishString();
 }
 
@@ -1181,17 +1181,17 @@ js_fun_bind(JSContext *cx, HandleObject 
         if (nargs > argslen)
             length = nargs - argslen;
     }
 
     /* Step 4-6, 10-11. */
     RootedAtom name(cx, target->isFunction() ? target->toFunction()->atom() : NULL);
 
     RootedObject funobj(cx, js_NewFunction(cx, NullPtr(), CallOrConstructBoundFunction, length,
-                                           JSFUN_CONSTRUCTOR, target, name));
+                                           JSFunction::NATIVE_CTOR, target, name));
     if (!funobj)
         return NULL;
 
     /* NB: Bound functions abuse |parent| to store their target. */
     if (!JSObject::setParent(cx, funobj, target))
         return NULL;
 
     if (!funobj->toFunction()->initBoundFunction(cx, thisArg, boundArgs, argslen))
@@ -1409,17 +1409,17 @@ Function(JSContext *cx, unsigned argc, V
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      */
     RootedAtom anonymousAtom(cx, cx->names().anonymous);
-    RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
+    RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
                                           global, anonymousAtom));
     if (!fun)
         return false;
 
     if (hasRest)
         fun->setHasRest();
 
     bool ok = frontend::CompileFunctionBody(cx, fun, options, formals, chars, length);
@@ -1432,17 +1432,17 @@ IsBuiltinFunctionConstructor(JSFunction 
 {
     return fun->maybeNative() == Function;
 }
 
 } /* namespace js */
 
 JSFunction *
 js_NewFunction(JSContext *cx, HandleObject funobjArg, Native native, unsigned nargs,
-               unsigned flags, HandleObject parent, HandleAtom atom, js::gc::AllocKind kind)
+               JSFunction::Flags flags, HandleObject parent, HandleAtom atom, js::gc::AllocKind kind)
 {
     JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
     JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
     JS_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
 
     RootedObject funobj(cx, funobjArg);
     if (funobj) {
         JS_ASSERT(funobj->isFunction());
@@ -1451,27 +1451,28 @@ js_NewFunction(JSContext *cx, HandleObje
         funobj = NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
         if (!funobj)
             return NULL;
     }
     RootedFunction fun(cx, funobj->toFunction());
 
     /* Initialize all function members. */
     fun->nargs = uint16_t(nargs);
-    fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED);
-    if (flags & JSFUN_INTERPRETED) {
+    fun->flags = flags;
+    if (fun->isInterpreted()) {
         JS_ASSERT(!native);
         fun->mutableScript().init(NULL);
         fun->initEnvironment(parent);
     } else {
+        JS_ASSERT(fun->isNative());
         JS_ASSERT(native);
         fun->initNative(native, NULL);
     }
     if (kind == JSFunction::ExtendedFinalizeKind) {
-        fun->flags |= JSFUN_EXTENDED;
+        fun->flags |= JSFunction::EXTENDED;
         fun->initializeExtended();
     }
     fun->initAtom(atom);
 
     if (native && !JSObject::setSingletonType(cx, fun))
         return NULL;
 
     return fun;
@@ -1488,27 +1489,27 @@ js_CloneFunctionObject(JSContext *cx, Ha
 
     RawObject cloneobj =
         NewObjectWithClassProto(cx, &FunctionClass, NULL, SkipScopeParent(parent), kind);
     if (!cloneobj)
         return NULL;
     RootedFunction clone(cx, cloneobj->toFunction());
 
     clone->nargs = fun->nargs;
-    clone->flags = fun->flags & ~JSFUN_EXTENDED;
+    clone->flags = fun->flags & ~JSFunction::EXTENDED;
     if (fun->isInterpreted()) {
         clone->initScript(fun->script().unsafeGet());
         clone->initEnvironment(parent);
     } else {
         clone->initNative(fun->native(), fun->jitInfo());
     }
     clone->initAtom(fun->displayAtom());
 
     if (kind == JSFunction::ExtendedFinalizeKind) {
-        clone->flags |= JSFUN_EXTENDED;
+        clone->flags |= JSFunction::EXTENDED;
         clone->initializeExtended();
     }
 
     if (cx->compartment == fun->compartment() && !types::UseNewTypeForClone(fun)) {
         /*
          * We can use the same type as the original function provided that (a)
          * its prototype is correct, and (b) its type is not a singleton. The
          * first case will hold in all compileAndGo code, and the second case
@@ -1552,61 +1553,60 @@ js_CloneFunctionObject(JSContext *cx, Ha
             Debugger::onNewScript(cx, script, global);
         }
     }
     return clone;
 }
 
 JSFunction *
 js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
-                  unsigned nargs, unsigned attrs, Handle<PropertyName*> selfHostedName, AllocKind kind)
+                  unsigned nargs, unsigned flags, Handle<PropertyName*> selfHostedName, AllocKind kind)
 {
     PropertyOp gop;
     StrictPropertyOp sop;
 
     RootedFunction fun(cx);
 
-    if (attrs & JSFUN_STUB_GSOPS) {
+    if (flags & JSFUN_STUB_GSOPS) {
         /*
          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
          * the defined property's attributes. This allows us to encode another,
          * internal flag using the same bit, JSFUN_EXPR_CLOSURE -- see jsfun.h
          * for more on this.
          */
-        attrs &= ~JSFUN_STUB_GSOPS;
+        flags &= ~JSFUN_STUB_GSOPS;
         gop = JS_PropertyStub;
         sop = JS_StrictPropertyStub;
     } else {
         gop = NULL;
         sop = NULL;
     }
 
     /*
      * To support specifying both native and self-hosted functions using
      * JSFunctionSpec, js_DefineFunction can be invoked with either native
      * or selfHostedName set. It is assumed that selfHostedName is set if
      * native isn't.
      */
     if (native) {
         JS_ASSERT(!selfHostedName);
         RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : NULL);
+        JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
         fun = js_NewFunction(cx, NullPtr(), native, nargs,
-                             attrs & (JSFUN_FLAGS_MASK),
-                             obj, atom, kind);
+                             funFlags, obj, atom, kind);
     } else {
-        JS_ASSERT(attrs & JSFUN_INTERPRETED);
         JS_ASSERT(!cx->runtime->isSelfHostedGlobal(cx->global()));
         fun = cx->runtime->getSelfHostedFunction(cx, selfHostedName);
         fun->initAtom(JSID_TO_ATOM(id));
     }
     if (!fun)
         return NULL;
 
     RootedValue funVal(cx, ObjectValue(*fun));
-    if (!JSObject::defineGeneric(cx, obj, id, funVal, gop, sop, attrs & ~JSFUN_FLAGS_MASK))
+    if (!JSObject::defineGeneric(cx, obj, id, funVal, gop, sop, flags & ~JSFUN_FLAGS_MASK))
         return NULL;
 
     return fun;
 }
 
 void
 js::ReportIncompatibleMethod(JSContext *cx, CallReceiver call, Class *clasp)
 {
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -13,53 +13,52 @@
 #include "jspubtd.h"
 #include "jsobj.h"
 #include "jsatom.h"
 #include "jsscript.h"
 #include "jsstr.h"
 
 #include "gc/Barrier.h"
 
-/*
- * The high two bits of JSFunction.flags encode whether the function is native
- * or interpreted, and if interpreted, what kind of optimized closure form (if
- * any) it might be.
- *
- *   00   not interpreted
- *   01   interpreted, not null closure
- *   11   interpreted, null closure
- *
- * 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 interpreted functions can
- * move to u.i.script->flags. For now we use function flag bits to minimize
- * pointer-chasing.
- */
-#define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
-                                       global object */
-
-#define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
-#define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
-/*
- * NB: JSFUN_INTERPRETED is hardcode duplicated in SET_JITINFO() in
- * jsfriendapi.h. If it changes, it must also be updated there.
- */
-#define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.native */
-
-#define JSFUN_HAS_GUESSED_ATOM  0x8000  /* function had no explicit name, but a
-                                           name was guessed for it anyway */
-
 namespace js { class FunctionExtended; }
 
 struct JSFunction : public JSObject
 {
+    enum Flags {
+        INTERPRETED      = 0x0001,  /* function has a JSScript and environment. */
+        NATIVE_CTOR      = 0x0002,  /* native that can be called as a constructor */
+        EXTENDED         = 0x0004,  /* structure is FunctionExtended */
+        HEAVYWEIGHT      = 0x0008,  /* activation requires a Call object */
+        IS_FUN_PROTO     = 0x0010,  /* function is Function.prototype for some global object */
+        EXPR_CLOSURE     = 0x0020,  /* expression closure: function(x) x*x */
+        HAS_GUESSED_ATOM = 0x0040,  /* function had no explicit name, but a
+                                       name was guessed for it anyway */
+        LAMBDA           = 0x0080,  /* function comes from a FunctionExpression or Function() call
+                                       (not a FunctionDeclaration or nonstandard function-statement) */
+        SELF_HOSTED      = 0x0100,  /* function is self-hosted builtin and must not be
+                                       decompilable nor constructible. */
+        SELF_HOSTED_CTOR = 0x0200,  /* function is self-hosted builtin constructor and
+                                       must be constructible but not decompilable. */
+        HAS_REST         = 0x0400,  /* function has a rest (...) parameter */
+        HAS_DEFAULTS     = 0x0800,  /* function has at least one default parameter */
+
+        /* Derived Flags values for convenience: */
+        NATIVE_FUN = 0,
+        INTERPRETED_LAMBDA = INTERPRETED | LAMBDA
+    };
+
+    static void staticAsserts() {
+        JS_STATIC_ASSERT(INTERPRETED == JS_FUNCTION_INTERPRETED_BIT);
+        MOZ_STATIC_ASSERT(sizeof(JSFunction) == sizeof(js::shadow::Function),
+                          "shadow interface must match actual interface");
+    }
+
     uint16_t        nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
-    uint16_t        flags;        /* flags, see JSFUN_* below and in jsapi.h */
+    uint16_t        flags;        /* bitfield composed of the above Flags enum */
     union U {
         class Native {
             friend struct JSFunction;
             js::Native          native;       /* native method pointer or null */
             const JSJitInfo     *jitinfo;     /* Information about this function to be
                                                  used by the JIT;
                                                  use the accessor! */
         } n;
@@ -70,51 +69,86 @@ struct JSFunction : public JSObject
                                      use the accessor! */
         } i;
         void            *nativeOrScript;
     } u;
   private:
     js::HeapPtrAtom  atom_;       /* name for diagnostics and decompiling */
   public:
 
-    bool hasDefaults()       const { return flags & JSFUN_HAS_DEFAULTS; }
-    bool hasRest()           const { return flags & JSFUN_HAS_REST; }
-    bool hasGuessedAtom()    const { return flags & JSFUN_HAS_GUESSED_ATOM; }
-    bool isInterpreted()     const { return flags & JSFUN_INTERPRETED; }
-    bool isNative()          const { return !isInterpreted(); }
-    bool isSelfHostedBuiltin() const { return flags & JSFUN_SELF_HOSTED; }
-    bool isBuiltin()         const { return isNative() || isSelfHostedBuiltin(); }
-    bool isSelfHostedConstructor() const { return flags & JSFUN_SELF_HOSTED_CTOR; }
-    bool isNativeConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
-    bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
-    bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
+    /* A function can be classified as either native (C++) or interpreted (JS): */
+    bool isInterpreted()            const { return flags & INTERPRETED; }
+    bool isNative()                 const { return !(flags & INTERPRETED); }
+
+    /* Possible attributes of a native function: */
+    bool isNativeConstructor()      const { return flags & NATIVE_CTOR; }
+
+    /* Possible attributes of an interpreted function: */
+    bool isHeavyweight()            const { return flags & HEAVYWEIGHT; }
+    bool isFunctionPrototype()      const { return flags & IS_FUN_PROTO; }
+    bool isExprClosure()            const { return flags & EXPR_CLOSURE; }
+    bool hasGuessedAtom()           const { return flags & HAS_GUESSED_ATOM; }
+    bool isLambda()                 const { return flags & LAMBDA; }
+    bool isSelfHostedBuiltin()      const { return flags & SELF_HOSTED; }
+    bool isSelfHostedConstructor()  const { return flags & SELF_HOSTED_CTOR; }
+    bool hasRest()                  const { return flags & HAS_REST; }
+    bool hasDefaults()              const { return flags & HAS_DEFAULTS; }
+
+    /* Compound attributes: */
+    bool isBuiltin() const {
+        return isNative() || isSelfHostedBuiltin();
+    }
     bool isInterpretedConstructor() const {
         return isInterpreted() && !isFunctionPrototype() &&
                (!isSelfHostedBuiltin() || isSelfHostedConstructor());
     }
     bool isNamedLambda()     const {
-        return (flags & JSFUN_LAMBDA) && atom_ && !hasGuessedAtom();
+        return isLambda() && atom_ && !hasGuessedAtom();
     }
 
     /* Returns the strictness of this function, which must be interpreted. */
     inline bool inStrictMode() const;
 
     void setArgCount(uint16_t nargs) {
         JS_ASSERT(this->nargs == 0);
         this->nargs = nargs;
     }
 
     void setHasRest() {
         JS_ASSERT(!hasRest());
-        this->flags |= JSFUN_HAS_REST;
+        flags |= HAS_REST;
     }
 
     void setHasDefaults() {
         JS_ASSERT(!hasDefaults());
-        this->flags |= JSFUN_HAS_DEFAULTS;
+        flags |= HAS_DEFAULTS;
+    }
+
+    void setIsSelfHostedBuiltin() {
+        JS_ASSERT(!isSelfHostedBuiltin());
+        flags |= SELF_HOSTED;
+    }
+
+    void setIsSelfHostedConstructor() {
+        JS_ASSERT(!isSelfHostedConstructor());
+        flags |= SELF_HOSTED_CTOR;
+    }
+
+    void setIsFunctionPrototype() {
+        JS_ASSERT(!isFunctionPrototype());
+        flags |= IS_FUN_PROTO;
+    }
+
+    void setIsHeavyweight() {
+        flags |= HEAVYWEIGHT;
+    }
+
+    void setIsExprClosure() {
+        JS_ASSERT(!isExprClosure());
+        flags |= EXPR_CLOSURE;
     }
 
     JSAtom *atom() const { return hasGuessedAtom() ? NULL : atom_.get(); }
     inline void initAtom(JSAtom *atom);
     JSAtom *displayAtom() const { return atom_; }
 
     inline void setGuessedAtom(JSAtom *atom);
 
@@ -189,35 +223,31 @@ struct JSFunction : public JSObject
     inline size_t getBoundFunctionArgumentCount() const;
 
   private:
     inline js::FunctionExtended *toExtended();
     inline const js::FunctionExtended *toExtended() const;
 
     inline bool isExtended() const {
         JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind);
-        JS_ASSERT(!!(flags & JSFUN_EXTENDED) == (getAllocKind() == ExtendedFinalizeKind));
-        return !!(flags & JSFUN_EXTENDED);
+        JS_ASSERT(!!(flags & EXTENDED) == (getAllocKind() == ExtendedFinalizeKind));
+        return !!(flags & EXTENDED);
     }
 
   public:
     /* Accessors for data stored in extended functions. */
     inline void initializeExtended();
     inline void setExtendedSlot(size_t which, const js::Value &val);
     inline const js::Value &getExtendedSlot(size_t which) const;
 
     /* Constructs a new type for the function if necessary. */
     static bool setTypeForScriptedFunction(JSContext *cx, js::HandleFunction fun,
                                            bool singleton = false);
 
   private:
-    static void staticAsserts() {
-        MOZ_STATIC_ASSERT(sizeof(JSFunction) == sizeof(js::shadow::Function),
-                          "shadow interface must match actual interface");
-    }
     /*
      * These member functions are inherited from JSObject, but should never be applied to
      * a value statically known to be a JSFunction.
      */
     inline JSFunction *toFunction() MOZ_DELETE;
     inline const JSFunction *toFunction() const MOZ_DELETE;
 };
 
@@ -233,19 +263,27 @@ JSObject::toFunction() const
 {
     JS_ASSERT(JS_ObjectIsFunction(NULL, const_cast<JSObject *>(this)));
     return static_cast<const JSFunction *>(this);
 }
 
 extern JSString *
 fun_toStringHelper(JSContext *cx, js::HandleObject obj, unsigned indent);
 
+inline JSFunction::Flags
+JSAPIToJSFunctionFlags(unsigned flags)
+{
+    return (flags & JSFUN_CONSTRUCTOR)
+           ? JSFunction::NATIVE_CTOR
+           : JSFunction::NATIVE_FUN;
+}
+
 extern JSFunction *
 js_NewFunction(JSContext *cx, js::HandleObject funobj, JSNative native, unsigned nargs,
-               unsigned flags, js::HandleObject parent, js::HandleAtom atom,
+               JSFunction::Flags flags, js::HandleObject parent, js::HandleAtom atom,
                js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 extern JSFunction * JS_FASTCALL
 js_CloneFunctionObject(JSContext *cx, js::HandleFunction fun,
                        js::HandleObject parent, js::HandleObject proto,
                        js::gc::AllocKind kind = JSFunction::FinalizeKind);
 
 extern JSFunction *
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -26,21 +26,21 @@ inline void
 JSFunction::initAtom(JSAtom *atom)
 {
     atom_.init(atom);
 }
 
 inline void
 JSFunction::setGuessedAtom(JSAtom *atom)
 {
-    JS_ASSERT(this->atom_ == NULL);
+    JS_ASSERT(atom_ == NULL);
     JS_ASSERT(atom != NULL);
     JS_ASSERT(!hasGuessedAtom());
-    this->atom_ = atom;
-    this->flags |= JSFUN_HAS_GUESSED_ATOM;
+    atom_ = atom;
+    flags |= HAS_GUESSED_ATOM;
 }
 
 inline JSObject *
 JSFunction::environment() const
 {
     JS_ASSERT(isInterpreted());
     return u.i.env_;
 }
@@ -178,17 +178,17 @@ SameTraceType(const Value &lhs, const Va
 /* Valueified JS_IsConstructing. */
 static JS_ALWAYS_INLINE bool
 IsConstructing(const Value *vp)
 {
 #ifdef DEBUG
     JSObject *callee = &JS_CALLEE(cx, vp).toObject();
     if (callee->isFunction()) {
         JSFunction *fun = callee->toFunction();
-        JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
+        JS_ASSERT(fun->isNativeConstructor());
     } else {
         JS_ASSERT(callee->getClass()->construct != NULL);
     }
 #endif
     return vp[1].isMagic();
 }
 
 inline bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3081,18 +3081,18 @@ DefineConstructorAndPrototype(JSContext 
         ctor = proto;
     } else {
         /*
          * Create the constructor, not using GlobalObject::createConstructor
          * 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.)
          */
-        RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), constructor, nargs, JSFUN_CONSTRUCTOR,
-                                              obj, atom, ctorKind));
+        RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), constructor, nargs,
+                                              JSFunction::NATIVE_CTOR, obj, atom, ctorKind));
         if (!fun)
             goto bad;
 
         /*
          * Set the class object early for standard class constructors. Type
          * inference may need to access these, and js_GetClassPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
          */
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1309,17 +1309,17 @@ ToPrimitive(JSContext *cx, JSType prefer
  * 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)
 {
     JSFunction *fun = funobj->toFunction();
-    return (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
+    return fun->isLambda() && !funobj->getParent();
 }
 
 class AutoPropDescArrayRooter : private AutoGCRooter
 {
   public:
     AutoPropDescArrayRooter(JSContext *cx)
       : AutoGCRooter(cx, DESCRIPTORS), descriptors(cx), skip(cx, &descriptors)
     { }
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -3637,26 +3637,26 @@ Decompile(SprintStack *ss, jsbytecode *p
 
               case JSOP_RETRVAL:
                 todo = -2;
                 break;
 
               case JSOP_RETURN:
                 LOCAL_ASSERT(jp->fun);
                 fun = jp->fun;
-                if (fun->flags & JSFUN_EXPR_CLOSURE) {
+                if (fun->isExprClosure()) {
                     /* Turn on parens around comma-expression here. */
                     op = JSOP_SETNAME;
                     rval = PopStr(ss, op, &rvalpc);
                     bool parens = (*rval == '{');
                     if (parens)
                         js_printf(jp, "(");
                     SprintOpcodePermanent(jp, rval, rvalpc);
                     js_printf(jp, parens ? ")%s" : "%s",
-                              ((fun->flags & JSFUN_LAMBDA) || !fun->atom())
+                              (fun->isLambda() || !fun->atom())
                               ? ""
                               : ";");
                     todo = -2;
                     break;
                 }
                 /* FALL THROUGH */
 
               case JSOP_SETRVAL:
@@ -4863,17 +4863,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 fun = jp->script->getFunction(GET_UINT32_INDEX(pc));
                 {
                     /*
                      * Always parenthesize expression closures. We can't force
                      * saveop to a low-precedence op to arrange for auto-magic
                      * parenthesization without confusing getter/setter code
                      * that checks for JSOP_LAMBDA.
                      */
-                    bool grouped = !(fun->flags & JSFUN_EXPR_CLOSURE);
+                    bool grouped = !fun->isExprClosure();
                     bool strict = jp->script->strictModeCode;
                     str = js_DecompileToString(cx, "lambda", fun, 0,
                                                false, grouped, strict,
                                                js_DecompileFunction);
                     if (!str)
                         return NULL;
                 }
               sprint_string:
@@ -5543,17 +5543,17 @@ DecompileCode(JSPrinter *jp, JSScript *s
  * script. Start at |pc|; go to the end of |script|. Include a directive
  * prologue, if appropriate.
  */
 static JSBool
 DecompileBody(JSPrinter *jp, JSScript *script, jsbytecode *pc)
 {
     /* Print a strict mode code directive, if needed. */
     if (script->strictModeCode && !jp->strict) {
-        if (jp->fun && (jp->fun->flags & JSFUN_EXPR_CLOSURE)) {
+        if (jp->fun && jp->fun->isExprClosure()) {
             /*
              * We have no syntax for strict function expressions;
              * at least give a hint.
              */
             js_printf(jp, "\t/* use strict */ \n");
         } else {
             js_printf(jp, "\t\"use strict\";\n");
         }
@@ -5619,17 +5619,17 @@ js_DecompileFunction(JSPrinter *jp)
     /*
      * If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
      * FunctionDeclaration.  Otherwise, check the JSFUN_LAMBDA flag and force
      * an expression by parenthesizing.
      */
     if (jp->pretty) {
         js_printf(jp, "\t");
     } else {
-        if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
+        if (!jp->grouped && fun->isLambda())
             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, "(");
 
@@ -5727,32 +5727,32 @@ js_DecompileFunction(JSPrinter *jp)
         }
 
 #if JS_HAS_DESTRUCTURING
         jp->script = NULL;
 #endif
         if (!ok)
             return JS_FALSE;
         js_printf(jp, ") ");
-        if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
+        if (!fun->isExprClosure()) {
             js_printf(jp, "{\n");
             jp->indent += 4;
         }
 
         ok = DecompileBody(jp, script, pc);
         if (!ok)
             return JS_FALSE;
 
-        if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
+        if (!fun->isExprClosure()) {
             jp->indent -= 4;
             js_printf(jp, "\t}");
         }
     }
 
-    if (!jp->pretty && !jp->grouped && (fun->flags & JSFUN_LAMBDA))
+    if (!jp->pretty && !jp->grouped && fun->isLambda())
         js_puts(jp, ")");
 
     return JS_TRUE;
 }
 
 static JSObject *
 GetBlockChainAtPC(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -3223,17 +3223,17 @@ ASTSerializer::function(ParseNode *pn, A
 #if JS_HAS_GENERATORS
         pn->pn_funbox->isGenerator();
 #else
         false;
 #endif
 
     bool isExpression =
 #if JS_HAS_EXPR_CLOSURES
-        func->flags & JSFUN_EXPR_CLOSURE;
+        func->isExprClosure();
 #else
         false;
 #endif
 
     RootedValue id(cx);
     RootedAtom funcAtom(cx, func->atom());
     if (!optIdentifier(funcAtom, NULL, &id))
         return false;
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1652,18 +1652,18 @@ class TypedArrayTemplate
     template<Value ValueGetter(JSObject *obj)>
     static bool
     DefineGetter(JSContext *cx, PropertyName *name, HandleObject proto)
     {
         RootedId id(cx, NameToId(name));
         unsigned flags = JSPROP_SHARED | JSPROP_GETTER | JSPROP_PERMANENT;
 
         Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
-        RawObject getter =
-            js_NewFunction(cx, NullPtr(), Getter<ValueGetter>, 0, 0, global, NullPtr());
+        RawObject getter = js_NewFunction(cx, NullPtr(), Getter<ValueGetter>, 0,
+                                          JSFunction::NATIVE_FUN, global, NullPtr());
         if (!getter)
             return false;
 
         RootedValue value(cx, UndefinedValue());
         return DefineNativeProperty(cx, proto, id, value,
                                     JS_DATA_TO_FUNC_PTR(PropertyOp, getter), NULL,
                                     flags, 0, 0);
     }
@@ -3313,17 +3313,17 @@ InitTypedArrayClass(JSContext *cx)
 
     if (!JS_DefineFunctions(cx, proto, ArrayType::jsfuncs))
         return NULL;
 
     RootedFunction fun(cx);
     fun =
         js_NewFunction(cx, NullPtr(),
                        ArrayBufferObject::createTypedArrayFromBuffer<typename ArrayType::ThisType>,
-                       0, 0, global, NullPtr());
+                       0, JSFunction::NATIVE_FUN, global, NullPtr());
     if (!fun)
         return NULL;
 
     if (!DefineConstructorAndPrototype(cx, global, ArrayType::key, ctor, proto))
         return NULL;
 
     global->setCreateArrayFromBuffer<typename ArrayType::ThisType>(fun);
 
@@ -3377,18 +3377,18 @@ InitArrayBufferClass(JSContext *cx)
     if (!ctor)
         return NULL;
 
     if (!LinkConstructorAndPrototype(cx, ctor, arrayBufferProto))
         return NULL;
 
     RootedId byteLengthId(cx, NameToId(cx->names().byteLength));
     unsigned flags = JSPROP_SHARED | JSPROP_GETTER | JSPROP_PERMANENT;
-    RawObject getter = js_NewFunction(cx, NullPtr(), ArrayBufferObject::byteLengthGetter, 0, 0,
-                                      global, NullPtr());
+    RawObject getter = js_NewFunction(cx, NullPtr(), ArrayBufferObject::byteLengthGetter, 0,
+                                      JSFunction::NATIVE_FUN, global, NullPtr());
     if (!getter)
         return NULL;
 
     RootedValue value(cx, UndefinedValue());
     if (!DefineNativeProperty(cx, arrayBufferProto, byteLengthId, value,
                               JS_DATA_TO_FUNC_PTR(PropertyOp, getter), NULL, flags, 0, 0))
         return NULL;
 
@@ -3479,18 +3479,18 @@ DataViewObject::getter(JSContext *cx, un
 template<Value ValueGetter(DataViewObject &view)>
 bool
 DataViewObject::defineGetter(JSContext *cx, PropertyName *name, HandleObject proto)
 {
     RootedId id(cx, NameToId(name));
     unsigned flags = JSPROP_SHARED | JSPROP_GETTER | JSPROP_PERMANENT;
 
     Rooted<GlobalObject*> global(cx, cx->compartment->maybeGlobal());
-    JSObject *getter = js_NewFunction(cx, NullPtr(), DataViewObject::getter<ValueGetter>, 0, 0,
-                                      global, NullPtr());
+    JSObject *getter = js_NewFunction(cx, NullPtr(), DataViewObject::getter<ValueGetter>, 0,
+                                      JSFunction::NATIVE_FUN, global, NullPtr());
     if (!getter)
         return false;
 
     RootedValue value(cx, UndefinedValue());
     return DefineNativeProperty(cx, proto, id, value,
                                 JS_DATA_TO_FUNC_PTR(PropertyOp, getter), NULL,
                                 flags, 0, 0);
 }
@@ -3524,17 +3524,17 @@ DataViewObject::initClass(JSContext *cx)
         return NULL;
 
     /*
      * Create a helper function to implement the craziness of
      * |new DataView(new otherWindow.ArrayBuffer())|, and install it in the
      * global for use by the DataView constructor.
      */
     RootedFunction fun(cx, js_NewFunction(cx, NullPtr(), ArrayBufferObject::createDataViewForThis,
-                                          0, 0, global, NullPtr()));
+                                          0, JSFunction::NATIVE_FUN, global, NullPtr()));
     if (!fun)
         return NULL;
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_DataView, ctor, proto))
         return NULL;
 
     global->setCreateDataViewForThis(fun);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -4426,17 +4426,17 @@ mjit::Compiler::inlineCallHelper(uint32_
          * Test if the callee is even a function. If this doesn't match, we
          * take a _really_ slow path later.
          */
         Jump notFunction = stubcc.masm.testFunction(Assembler::NotEqual, icCalleeData, tmp);
 
         /* Test if the function is scripted. */
         stubcc.masm.load16(Address(icCalleeData, offsetof(JSFunction, flags)), tmp);
         Jump isNative = stubcc.masm.branchTest32(Assembler::Zero, tmp,
-                                                 Imm32(JSFUN_INTERPRETED));
+                                                 Imm32(JSFunction::INTERPRETED));
         tempRegs.putReg(tmp);
 
         /*
          * N.B. After this call, the frame will have a dynamic frame size.
          * Check after the function is known not to be a native so that the
          * catch-all/native path has a static depth.
          */
         if (callIC.frameSize.isDynamic()) {
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -85,17 +85,17 @@ pm_canMeasureSomething(JSContext* cx, un
     PerfMeasurement* p = GetPMFromThis(cx, vp);
     if (!p)
         return JS_FALSE;
 
     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(p->canMeasureSomething()));
     return JS_TRUE;
 }
 
-const uint8_t PM_FATTRS = JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED;
+const uint8_t PM_FATTRS = JSPROP_READONLY | JSPROP_PERMANENT;
 static JSFunctionSpec pm_fns[] = {
     JS_FN("start",               pm_start,               0, PM_FATTRS),
     JS_FN("stop",                pm_stop,                0, PM_FATTRS),
     JS_FN("reset",               pm_reset,               0, PM_FATTRS),
     JS_FN("canMeasureSomething", pm_canMeasureSomething, 0, PM_FATTRS),
     JS_FS_END
 };
 
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1748,28 +1748,30 @@ TryNotes(JSContext *cx, JSScript *script
 }
 
 static bool
 DisassembleScript(JSContext *cx, JSScript *script_, JSFunction *fun, bool lines, bool recursive,
                   Sprinter *sp)
 {
     Rooted<JSScript*> script(cx, script_);
 
-    if (fun && (fun->flags & ~7U)) {
-        uint16_t flags = fun->flags;
+    if (fun) {
         Sprint(sp, "flags:");
-
-#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) Sprint(sp, " " #flag);
-
-        SHOW_FLAG(LAMBDA);
-        SHOW_FLAG(HEAVYWEIGHT);
-        SHOW_FLAG(EXPR_CLOSURE);
-
-#undef SHOW_FLAG
-
+        if (fun->isLambda())
+            Sprint(sp, " LAMBDA");
+        if (fun->isHeavyweight())
+            Sprint(sp, " HEAVYWEIGHT");
+        if (fun->isExprClosure())
+            Sprint(sp, " EXPRESSION CLOSURE");
+        if (fun->isFunctionPrototype())
+            Sprint(sp, " Function.prototype");
+        if (fun->isSelfHostedBuiltin())
+            Sprint(sp, " SELF_HOSTED");
+        if (fun->isSelfHostedConstructor())
+            Sprint(sp, " SELF_HOSTED_CTOR");
         Sprint(sp, "\n");
     }
 
     if (!js_Disassemble(cx, script, lines, sp))
         return false;
     SrcNotes(cx, script, sp);
     TryNotes(cx, script, sp);
 
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -3403,18 +3403,19 @@ DebuggerFrame_getArguments(JSContext *cx
         {
             return false;
         }
 
         Rooted<jsid> id(cx);
         RootedValue undefinedValue(cx, UndefinedValue());
         for (unsigned i = 0; i < fargc; i++) {
             RootedFunction getobj(cx);
-            getobj = js_NewFunction(cx, NullPtr(), DebuggerArguments_getArg, 0, 0, global,
-                                    NullPtr(), JSFunction::ExtendedFinalizeKind);
+            getobj = js_NewFunction(cx, NullPtr(), DebuggerArguments_getArg, 0,
+                                    JSFunction::NATIVE_FUN, global, NullPtr(),
+                                    JSFunction::ExtendedFinalizeKind);
             if (!getobj)
                 return false;
             id = INT_TO_JSID(i);
             if (!getobj ||
                 !DefineNativeProperty(cx, argsobj, id, undefinedValue,
                                       JS_DATA_TO_FUNC_PTR(PropertyOp, getobj.get()), NULL,
                                       JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_GETTER, 0, 0))
             {
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -209,22 +209,22 @@ GlobalObject::initFunctionAndObjectClass
             return NULL;
         functionProto = functionProto_->toFunction();
 
         /*
          * Bizarrely, |Function.prototype| must be an interpreted function, so
          * give it the guts to be one.
          */
         {
-            RawObject proto = js_NewFunction(cx, functionProto,
-                                             NULL, 0, JSFUN_INTERPRETED, self, NullPtr());
+            RawObject proto = js_NewFunction(cx, functionProto, NULL, 0, JSFunction::INTERPRETED,
+                                             self, NullPtr());
             if (!proto)
                 return NULL;
             JS_ASSERT(proto == functionProto);
-            functionProto->flags |= JSFUN_PROTOTYPE;
+            functionProto->setIsFunctionPrototype();
         }
 
         const char *rawSource = "() {\n}";
         size_t sourceLen = strlen(rawSource);
         jschar *source = InflateString(cx, rawSource, &sourceLen);
         if (!source)
             return NULL;
         ScriptSource *ss = cx->new_<ScriptSource>();
@@ -267,17 +267,18 @@ GlobalObject::initFunctionAndObjectClass
 
     /* Create the Object function now that we have a [[Prototype]] for it. */
     RootedFunction objectCtor(cx);
     {
         RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self));
         if (!ctor)
             return NULL;
         RootedAtom objectAtom(cx, cx->names().Object);
-        objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self, objectAtom);
+        objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFunction::NATIVE_CTOR, self,
+                                    objectAtom);
         if (!objectCtor)
             return NULL;
     }
 
     /*
      * Install |Object| and |Object.prototype| for the benefit of subsequent
      * code that looks for them.
      */
@@ -286,17 +287,17 @@ GlobalObject::initFunctionAndObjectClass
     /* Create |Function| so it and |Function.prototype| can be installed. */
     RootedFunction functionCtor(cx);
     {
         // Note that ctor is rooted purely for the JS_ASSERT at the end
         RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self));
         if (!ctor)
             return NULL;
         RootedAtom functionAtom(cx, cx->names().Function);
-        functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
+        functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFunction::NATIVE_CTOR, self,
                                       functionAtom);
         if (!functionCtor)
             return NULL;
         JS_ASSERT(ctor == functionCtor);
     }
 
     /*
      * Install |Function| and |Function.prototype| so that we can freely create
@@ -315,21 +316,23 @@ GlobalObject::initFunctionAndObjectClass
     }
 
     /*
      * Add an Object.prototype.__proto__ accessor property to implement that
      * extension (if it's actually enabled).  Cache the getter for this
      * function so that cross-compartment [[Prototype]]-getting is implemented
      * in one place.
      */
-    RootedFunction getter(cx, js_NewFunction(cx, NullPtr(), ProtoGetter, 0, 0, self, NullPtr()));
+    RootedFunction getter(cx, js_NewFunction(cx, NullPtr(), ProtoGetter, 0, JSFunction::NATIVE_FUN,
+                                             self, NullPtr()));
     if (!getter)
         return NULL;
 #if JS_HAS_OBJ_PROTO_PROP
-    RootedFunction setter(cx, js_NewFunction(cx, NullPtr(), ProtoSetter, 0, 0, self, NullPtr()));
+    RootedFunction setter(cx, js_NewFunction(cx, NullPtr(), ProtoSetter, 0, JSFunction::NATIVE_FUN,
+                                             self, NullPtr()));
     if (!setter)
         return NULL;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!JSObject::defineProperty(cx, objectProto,
                                   cx->names().proto, undefinedValue,
                                   JS_DATA_TO_FUNC_PTR(PropertyOp, getter.get()),
                                   JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setter.get()),
                                   JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED))
@@ -359,18 +362,18 @@ GlobalObject::initFunctionAndObjectClass
     /* ES5 15.1.2.1. */
     RootedId evalId(cx, NameToId(cx->names().eval));
     RawObject evalobj = js_DefineFunction(cx, self, evalId, IndirectEval, 1, JSFUN_STUB_GSOPS);
     if (!evalobj)
         return NULL;
     self->setOriginalEval(evalobj);
 
     /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
-    RootedFunction throwTypeError(cx, js_NewFunction(cx, NullPtr(), ThrowTypeError, 0, 0, self,
-                                                     NullPtr()));
+    RootedFunction throwTypeError(cx, js_NewFunction(cx, NullPtr(), ThrowTypeError, 0,
+                                                     JSFunction::NATIVE_FUN, self, NullPtr()));
     if (!throwTypeError)
         return NULL;
     if (!throwTypeError->preventExtensions(cx))
         return NULL;
     self->setThrowTypeError(throwTypeError);
 
     RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self));
     if (!intrinsicsHolder)
@@ -486,17 +489,17 @@ GlobalObject::isRuntimeCodeGenEnabled(JS
 }
 
 JSFunction *
 GlobalObject::createConstructor(JSContext *cx, Native ctor, JSAtom *nameArg, unsigned length,
                                 gc::AllocKind kind)
 {
     RootedAtom name(cx, nameArg);
     RootedObject self(cx, this);
-    return js_NewFunction(cx, NullPtr(), ctor, length, JSFUN_CONSTRUCTOR, self, name, kind);
+    return js_NewFunction(cx, NullPtr(), ctor, length, JSFunction::NATIVE_CTOR, self, name, kind);
 }
 
 static JSObject *
 CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &global)
 {
     JS_ASSERT(clasp != &ObjectClass);
     JS_ASSERT(clasp != &FunctionClass);