Bug 880041 (part 21) - Use JSObject::{is,as} for GlobalObject. r=sfink.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 17 Jun 2013 16:23:11 -0700
changeset 135933 8526023eb2b1bac08d21749ce7dd77aea483902d
parent 135932 6da87883494aacd1697f37444a2d86b2d4181dce
child 135934 1c6097e5c4d4b758f040f0bcc5e46cc4042a997a
push id29888
push usernnethercote@mozilla.com
push dateFri, 21 Jun 2013 05:43:27 +0000
treeherdermozilla-inbound@1c6097e5c4d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs880041
milestone24.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 880041 (part 21) - Use JSObject::{is,as} for GlobalObject. r=sfink.
js/src/builtin/Eval.cpp
js/src/builtin/Intl.cpp
js/src/builtin/MapObject.cpp
js/src/builtin/ParallelArray.cpp
js/src/builtin/RegExp.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/frontend/Parser.cpp
js/src/ion/BaselineIC.cpp
js/src/ion/IonBuilder.cpp
js/src/ion/IonCaches.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jscntxtinlines.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsstr.cpp
js/src/jstypedarray.cpp
js/src/jsweakmap.cpp
js/src/vm/Debugger.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/RegExpObject.cpp
js/src/vm/SelfHosting.cpp
js/src/vm/Shape.cpp
js/src/vm/Stack.cpp
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -229,17 +229,17 @@ enum EvalType { DIRECT_EVAL = EXECUTE_DI
 //
 // On success, store the completion value in call.rval and return true.
 static bool
 EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFramePtr caller,
            HandleObject scopeobj, jsbytecode *pc)
 {
     JS_ASSERT((evalType == INDIRECT_EVAL) == !caller);
     JS_ASSERT((evalType == INDIRECT_EVAL) == !pc);
-    JS_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->isGlobal());
+    JS_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->is<GlobalObject>());
     AssertInnerizedScopeChain(cx, *scopeobj);
 
     Rooted<GlobalObject*> scopeObjGlobal(cx, &scopeobj->global());
     if (!GlobalObject::isRuntimeCodeGenEnabled(cx, scopeObjGlobal)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
         return false;
     }
 
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -701,17 +701,17 @@ collator_finalize(FreeOp *fop, JSObject 
 
 static JSObject *
 InitCollatorClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*> global)
 {
     RootedFunction ctor(cx, global->createConstructor(cx, &Collator, cx->names().Collator, 0));
     if (!ctor)
         return NULL;
 
-    RootedObject proto(cx, global->asGlobal().getOrCreateCollatorPrototype(cx));
+    RootedObject proto(cx, global->as<GlobalObject>().getOrCreateCollatorPrototype(cx));
     if (!proto)
         return NULL;
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     // 10.2.2
     if (!JS_DefineFunctions(cx, ctor, collator_static_methods))
         return NULL;
@@ -1180,17 +1180,17 @@ numberFormat_finalize(FreeOp *fop, JSObj
 
 static JSObject *
 InitNumberFormatClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*> global)
 {
     RootedFunction ctor(cx, global->createConstructor(cx, &NumberFormat, cx->names().NumberFormat, 0));
     if (!ctor)
         return NULL;
 
-    RootedObject proto(cx, global->asGlobal().getOrCreateNumberFormatPrototype(cx));
+    RootedObject proto(cx, global->as<GlobalObject>().getOrCreateNumberFormatPrototype(cx));
     if (!proto)
         return NULL;
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     // 11.2.2
     if (!JS_DefineFunctions(cx, ctor, numberFormat_static_methods))
         return NULL;
@@ -1629,17 +1629,17 @@ dateTimeFormat_finalize(FreeOp *fop, JSO
 
 static JSObject *
 InitDateTimeFormatClass(JSContext *cx, HandleObject Intl, Handle<GlobalObject*> global)
 {
     RootedFunction ctor(cx, global->createConstructor(cx, &DateTimeFormat, cx->names().DateTimeFormat, 0));
     if (!ctor)
         return NULL;
 
-    RootedObject proto(cx, global->asGlobal().getOrCreateDateTimeFormatPrototype(cx));
+    RootedObject proto(cx, global->as<GlobalObject>().getOrCreateDateTimeFormatPrototype(cx));
     if (!proto)
         return NULL;
     if (!LinkConstructorAndPrototype(cx, ctor, proto))
         return NULL;
 
     // 12.2.2
     if (!JS_DefineFunctions(cx, ctor, dateTimeFormat_static_methods))
         return NULL;
@@ -2021,18 +2021,18 @@ static const JSFunctionSpec intl_static_
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
  * Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
  */
 JSObject *
 js_InitIntlClass(JSContext *cx, HandleObject obj)
 {
-    JS_ASSERT(obj->isGlobal());
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    JS_ASSERT(obj->is<GlobalObject>());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     // The constructors above need to be able to determine whether they've been
     // called with this being "the standard built-in Intl object". The global
     // object reserves slots to track standard built-in objects, but doesn't
     // normally keep references to non-constructors. This makes sure there is one.
     RootedObject Intl(cx, global->getOrCreateIntlObject(cx));
     if (!Intl)
         return NULL;
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1053,17 +1053,17 @@ InitClass(JSContext *cx, Handle<GlobalOb
         return NULL;
     }
     return proto;
 }
 
 JSObject *
 MapObject::initClass(JSContext *cx, JSObject *obj)
 {
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     RootedObject proto(cx,
         InitClass(cx, global, &class_, JSProto_Map, construct, properties, methods));
     if (proto) {
         // Define the "entries" method.
         JSFunction *fun = JS_DefineFunction(cx, proto, "entries", entries, 0, 0);
         if (!fun)
             return NULL;
 
@@ -1589,17 +1589,17 @@ const JSFunctionSpec SetObject::methods[
     JS_FN("entries", entries, 0, 0),
     JS_FN("clear", clear, 0, 0),
     JS_FS_END
 };
 
 JSObject *
 SetObject::initClass(JSContext *cx, JSObject *obj)
 {
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     RootedObject proto(cx,
         InitClass(cx, global, &class_, JSProto_Set, construct, properties, methods));
     if (proto) {
         // Define the "values" method.
         JSFunction *fun = JS_DefineFunction(cx, proto, "values", values, 0, 0);
         if (!fun)
             return NULL;
 
--- a/js/src/builtin/ParallelArray.cpp
+++ b/js/src/builtin/ParallelArray.cpp
@@ -194,17 +194,17 @@ ParallelArrayObject::initClass(JSContext
         for (uint32_t i = 0; i < NumCtors; i++) {
             JSAtom *atom = Atomize(cx, ctorStrs[i], strlen(ctorStrs[i]), InternAtom);
             if (!atom)
                 return NULL;
             ctorNames[i].init(atom->asPropertyName());
         }
     }
 
-    Rooted<GlobalObject *> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
 
     RootedObject proto(cx, global->createBlankPrototype(cx, &protoClass));
     if (!proto)
         return NULL;
 
     JSProtoKey key = JSProto_ParallelArray;
     RootedFunction ctor(cx, global->createConstructor(cx, construct,
                                                       cx->names().ParallelArray, 0));
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -488,17 +488,17 @@ static const JSPropertySpec regexp_stati
     {0,0,0,JSOP_NULLWRAPPER,JSOP_NULLWRAPPER}
 };
 
 JSObject *
 js_InitRegExpClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpObject::class_));
     if (!proto)
         return NULL;
     proto->setPrivate(NULL);
 
     HandlePropertyName empty = cx->names().empty;
     RegExpObjectBuilder builder(cx, &proto->as<RegExpObject>());
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -522,17 +522,17 @@ frontend::CompileFunctionBody(JSContext 
          * The reason for checking fun->environment() below is that certain
          * consumers of JS::CompileFunction, namely
          * nsEventListenerManager::CompileEventHandlerInternal, passes in a
          * NULL environment. This compiled function is never used, but instead
          * is cloned immediately onto the right scope chain.
          */
         BytecodeEmitter funbce(/* parent = */ NULL, &parser, funbox, script,
                                /* insideEval = */ false, /* evalCaller = */ NullPtr(),
-                               fun->environment() && fun->environment()->isGlobal(),
+                               fun->environment() && fun->environment()->is<GlobalObject>(),
                                options.lineno);
         if (!funbce.init())
             return false;
 
         if (!EmitFunctionScript(cx, &funbce, pn))
             return false;
     }
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1180,19 +1180,19 @@ template <typename ParseHandler>
 JSFunction *
 Parser<ParseHandler>::newFunction(GenericParseContext *pc, HandleAtom atom,
                                   FunctionSyntaxKind kind)
 {
     JS_ASSERT_IF(kind == Statement, atom != NULL);
 
     /*
      * Find the global compilation context in order to pre-set the newborn
-     * function's parent slot to pc->sc->asGlobal()->scopeChain. If the global
-     * context is a compile-and-go one, we leave the pre-set parent intact;
-     * otherwise we clear parent and proto.
+     * function's parent slot to pc->sc->as<GlobalObject>()->scopeChain. If the
+     * global context is a compile-and-go one, we leave the pre-set parent
+     * intact; otherwise we clear parent and proto.
      */
     while (pc->parent)
         pc = pc->parent;
 
     RootedObject parent(context);
     parent = pc->sc->isFunctionBox() ? NULL : pc->sc->asGlobalSharedContext()->scopeChain();
 
     RootedFunction fun(context);
--- a/js/src/ion/BaselineIC.cpp
+++ b/js/src/ion/BaselineIC.cpp
@@ -4783,17 +4783,17 @@ ICIn_Fallback::Compiler::generateStubCod
     return tailCallVM(DoInFallbackInfo, masm);
 }
 
 // Attach an optimized stub for a GETGNAME/CALLGNAME op.
 static bool
 TryAttachGlobalNameStub(JSContext *cx, HandleScript script, ICGetName_Fallback *stub,
                         HandleObject global, HandlePropertyName name)
 {
-    JS_ASSERT(global->isGlobal());
+    JS_ASSERT(global->is<GlobalObject>());
 
     RootedId id(cx, NameToId(name));
 
     // The property must be found, and it must be found as a normal data property.
     RootedShape shape(cx, global->nativeLookup(cx, id));
     if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
         return true;
 
@@ -4821,17 +4821,17 @@ TryAttachScopeNameStub(JSContext *cx, Ha
     RootedId id(cx, NameToId(name));
     RootedObject scopeChain(cx, initialScopeChain);
 
     Shape *shape = NULL;
     while (scopeChain) {
         if (!shapes.append(scopeChain->lastProperty()))
             return false;
 
-        if (scopeChain->isGlobal()) {
+        if (scopeChain->is<GlobalObject>()) {
             shape = scopeChain->nativeLookup(cx, id);
             if (shape)
                 break;
             return true;
         }
 
         if (!scopeChain->is<ScopeObject>() || scopeChain->is<WithObject>())
             return true;
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -5971,21 +5971,21 @@ IonBuilder::pushTypeBarrier(MInstruction
     }
     current->push(barrier);
     return true;
 }
 
 bool
 IonBuilder::getStaticName(HandleObject staticObject, HandlePropertyName name, bool *psucceeded)
 {
-    JS_ASSERT(staticObject->isGlobal() || staticObject->is<CallObject>());
+    JS_ASSERT(staticObject->is<GlobalObject>() || staticObject->is<CallObject>());
 
     *psucceeded = true;
 
-    if (staticObject->isGlobal()) {
+    if (staticObject->is<GlobalObject>()) {
         // Optimize undefined, NaN, and Infinity.
         if (name == cx->names().undefined)
             return pushConstant(UndefinedValue());
         if (name == cx->names().NaN)
             return pushConstant(cx->runtime()->NaNValue);
         if (name == cx->names().Infinity)
             return pushConstant(cx->runtime()->positiveInfinityValue);
     }
@@ -6087,17 +6087,17 @@ ion::NeedsPostBarrier(CompileInfo &info,
     return info.executionMode() != ParallelExecution && value->mightBeType(MIRType_Object);
 }
 
 bool
 IonBuilder::setStaticName(HandleObject staticObject, HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
 
-    JS_ASSERT(staticObject->isGlobal() || staticObject->is<CallObject>());
+    JS_ASSERT(staticObject->is<GlobalObject>() || staticObject->is<CallObject>());
 
     MDefinition *value = current->peek(-1);
 
     if (staticObject->watched())
         return jsop_setprop(name);
 
     // For the fastest path, the property must be found, and it must be found
     // as a normal data property on exactly the global object.
@@ -6131,17 +6131,17 @@ IonBuilder::setStaticName(HandleObject s
     // If we have a property type set, the isOwnProperty call will trigger recompilation
     // if the property is deleted or reconfigured. Without TI, we always need a shape guard
     // to guard against the property being reconfigured as non-writable.
     if (!propertyTypes)
         obj = addShapeGuard(obj, staticObject->lastProperty(), Bailout_ShapeGuard);
 
     // Note: we do not use a post barrier when writing to the global object.
     // Slots in the global object will be treated as roots during a minor GC.
-    if (!staticObject->isGlobal() && NeedsPostBarrier(info(), value))
+    if (!staticObject->is<GlobalObject>() && NeedsPostBarrier(info(), value))
         current->add(MPostWriteBarrier::New(obj, value));
 
     // If the property has a known type, we may be able to optimize typed stores by not
     // storing the type tag. This only works if the property does not have its initial
     // |undefined| value; if |undefined| is assigned at a later point, it will be added
     // to the type set.
     //
     // We also need to make sure the typeset reflects the inherited types from
@@ -8289,17 +8289,17 @@ IonBuilder::hasStaticScopeObject(ScopeCo
     // Look for the call object on the current script's function's scope chain.
     // If the current script is inner to the outer script and the function has
     // singleton type then it should show up here.
 
     MDefinition *scope = current->getSlot(info().scopeChainSlot());
     scope->setFoldedUnchecked();
 
     JSObject *environment = script()->function()->environment();
-    while (environment && !environment->isGlobal()) {
+    while (environment && !environment->is<GlobalObject>()) {
         if (environment->is<CallObject>() &&
             !environment->as<CallObject>().isForEval() &&
             environment->as<CallObject>().callee().nonLazyScript() == outerScript)
         {
             JS_ASSERT(environment->hasSingletonType());
             pcall.set(environment);
             return true;
         }
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -2710,17 +2710,17 @@ SetElementIC::reset()
 {
     RepatchIonCache::reset();
     hasDenseStub_ = false;
 }
 
 bool
 BindNameIC::attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain)
 {
-    JS_ASSERT(scopeChain->isGlobal());
+    JS_ASSERT(scopeChain->is<GlobalObject>());
 
     MacroAssembler masm(cx);
     RepatchStubAppender attacher(*this);
 
     // Guard on the scope chain.
     attacher.branchNextStub(masm, Assembler::NotEqual, scopeChainReg(),
                             ImmGCPtr(scopeChain));
     masm.movePtr(ImmGCPtr(scopeChain), outputReg());
@@ -2740,17 +2740,17 @@ GenerateScopeChainGuard(MacroAssembler &
         // variables).
         CallObject *callObj = &scopeObj->as<CallObject>();
         if (!callObj->isForEval()) {
             JSFunction *fun = &callObj->callee();
             JSScript *script = fun->nonLazyScript();
             if (!script->funHasExtensibleScope)
                 return;
         }
-    } else if (scopeObj->isGlobal()) {
+    } else if (scopeObj->is<GlobalObject>()) {
         // If this is the last object on the scope walk, and the property we've
         // found is not configurable, then we don't need a shape guard because
         // the shape cannot be removed.
         if (shape && !shape->configurable())
             return;
     }
 
     Address shapeAddr(scopeObjReg, JSObject::offsetOfShape());
@@ -2761,17 +2761,17 @@ static void
 GenerateScopeChainGuards(MacroAssembler &masm, JSObject *scopeChain, JSObject *holder,
                          Register outputReg, Label *failures)
 {
     JSObject *tobj = scopeChain;
 
     // Walk up the scope chain. Note that IsCacheableScopeChain guarantees the
     // |tobj == holder| condition terminates the loop.
     while (true) {
-        JS_ASSERT(IsCacheableNonGlobalScope(tobj) || tobj->isGlobal());
+        JS_ASSERT(IsCacheableNonGlobalScope(tobj) || tobj->is<GlobalObject>());
 
         GenerateScopeChainGuard(masm, tobj, outputReg, NULL, failures);
         if (tobj == holder)
             break;
 
         // Load the next link.
         tobj = &tobj->as<ScopeObject>().enclosingScope();
         masm.extractObject(Address(outputReg, ScopeObject::offsetOfEnclosingScope()), outputReg);
@@ -2843,27 +2843,27 @@ BindNameIC::update(JSContext *cx, size_t
 {
     AutoFlushCache afc ("BindNameCache");
 
     IonScript *ion = GetTopIonJSScript(cx)->ionScript();
     BindNameIC &cache = ion->getCache(cacheIndex).toBindName();
     HandlePropertyName name = cache.name();
 
     RootedObject holder(cx);
-    if (scopeChain->isGlobal()) {
+    if (scopeChain->is<GlobalObject>()) {
         holder = scopeChain;
     } else {
         if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &holder))
             return NULL;
     }
 
     // Stop generating new stubs once we hit the stub count limit, see
     // GetPropertyCache.
     if (cache.canAttachStub()) {
-        if (scopeChain->isGlobal()) {
+        if (scopeChain->is<GlobalObject>()) {
             if (!cache.attachGlobal(cx, ion, scopeChain))
                 return NULL;
         } else if (IsCacheableScopeChain(scopeChain, holder)) {
             if (!cache.attachNonGlobal(cx, ion, scopeChain, holder))
                 return NULL;
         } else {
             IonSpew(IonSpew_InlineCaches, "BINDNAME uncacheable scope chain");
         }
@@ -2913,36 +2913,36 @@ IsCacheableNameReadSlot(JSContext *cx, H
 {
     if (!shape)
         return false;
     if (!obj->isNative())
         return false;
     if (obj != holder)
         return false;
 
-    if (obj->isGlobal()) {
+    if (obj->is<GlobalObject>()) {
         // Support only simple property lookups.
         if (!IsCacheableGetPropReadSlot(obj, holder, shape) &&
             !IsCacheableNoProperty(obj, holder, shape, pc, output))
             return false;
     } else if (obj->is<CallObject>()) {
         if (!shape->hasDefaultGetter())
             return false;
     } else {
         // We don't yet support lookups on Block or DeclEnv objects.
         return false;
     }
 
     RootedObject obj2(cx, scopeChain);
     while (obj2) {
-        if (!IsCacheableNonGlobalScope(obj2) && !obj2->isGlobal())
+        if (!IsCacheableNonGlobalScope(obj2) && !obj2->is<GlobalObject>())
             return false;
 
         // Stop once we hit the global or target obj.
-        if (obj2->isGlobal() || obj2 == obj)
+        if (obj2->is<GlobalObject>() || obj2 == obj)
             break;
 
         obj2 = obj2->enclosingScope();
     }
 
     return obj == obj2;
 }
 
@@ -2968,17 +2968,17 @@ NameIC::attachCallGetter(JSContext *cx, 
 }
 
 static bool
 IsCacheableNameCallGetter(JSObject *scopeChain, JSObject *obj, JSObject *holder, Shape *shape)
 {
     if (obj != scopeChain)
         return false;
 
-    if (!obj->isGlobal())
+    if (!obj->is<GlobalObject>())
         return false;
 
     return IsCacheableGetPropCallNative(obj, holder, shape) ||
         IsCacheableGetPropCallPropertyOp(obj, holder, shape);
 }
 
 bool
 NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1997,17 +1997,17 @@ JS_ResolveStandardClass(JSContext *cx, H
         }
     }
 
     if (stdnm) {
         /*
          * If this standard class is anonymous, then we don't want to resolve
          * by name.
          */
-        JS_ASSERT(obj->isGlobal());
+        JS_ASSERT(obj->is<GlobalObject>());
         if (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)
             return true;
 
         if (IsStandardClassResolved(obj, stdnm->clasp))
             return true;
 
         if (!stdnm->init(cx, obj))
             return false;
@@ -2114,17 +2114,17 @@ JS_GetGlobalForObject(JSContext *cx, JSO
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     return &obj->global();
 }
 
 extern JS_PUBLIC_API(JSBool)
 JS_IsGlobalObject(JSObject *obj)
 {
-    return obj->isGlobal();
+    return obj->is<GlobalObject>();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c)
 {
     AssertHeapIsIdleOrIterating(cx);
     assertSameCompartment(cx, c);
     return c->maybeGlobal();
@@ -4423,17 +4423,17 @@ LastConfigurableShape(JSObject *obj)
 JS_PUBLIC_API(void)
 JS_ClearNonGlobalObject(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
-    JS_ASSERT(!obj->isGlobal());
+    JS_ASSERT(!obj->is<GlobalObject>());
 
     if (!obj->isNative())
         return;
 
     /* Remove all configurable properties from obj. */
     RootedShape shape(cx);
     while ((shape = LastConfigurableShape(obj))) {
         if (!obj->removeProperty(cx, shape->propid()))
@@ -4810,17 +4810,17 @@ JS_CloneFunctionObject(JSContext *cx, JS
      */
     RootedFunction fun(cx, funobj->toFunction());
     if (fun->isInterpretedLazy()) {
         AutoCompartment ac(cx, funobj);
         if (!fun->getOrCreateScript(cx))
             return NULL;
     }
     if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
-        (fun->nonLazyScript()->compileAndGo && !parent->isGlobal())))
+        (fun->nonLazyScript()->compileAndGo && !parent->is<GlobalObject>())))
     {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
         return NULL;
     }
 
     if (fun->isBoundFunction()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CLONE_OBJECT);
         return NULL;
@@ -6662,66 +6662,66 @@ JS_NewRegExpObject(JSContext *cx, JSObje
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
 
-    RegExpStatics *res = obj->asGlobal().getRegExpStatics();
+    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
     RegExpObject *reobj = RegExpObject::create(cx, res, chars, length,
                                                RegExpFlag(flags), NULL);
     js_free(chars);
     return reobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_NewUCRegExpObject(JSContext *cx, JSObject *objArg, jschar *chars, size_t length, unsigned flags)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    RegExpStatics *res = obj->asGlobal().getRegExpStatics();
+    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
     return RegExpObject::create(cx, res, chars, length,
                                 RegExpFlag(flags), NULL);
 }
 
 JS_PUBLIC_API(void)
 JS_SetRegExpInput(JSContext *cx, JSObject *objArg, JSString *input, JSBool multiline)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, input);
 
-    obj->asGlobal().getRegExpStatics()->reset(cx, input, !!multiline);
+    obj->as<GlobalObject>().getRegExpStatics()->reset(cx, input, !!multiline);
 }
 
 JS_PUBLIC_API(void)
 JS_ClearRegExpStatics(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     JS_ASSERT(obj);
 
-    obj->asGlobal().getRegExpStatics()->clear();
+    obj->as<GlobalObject>().getRegExpStatics()->clear();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ExecuteRegExp(JSContext *cx, JSObject *objArg, JSObject *reobjArg, jschar *chars, size_t length,
                  size_t *indexp, JSBool test, jsval *rval)
 {
     RootedObject obj(cx, objArg);
     RootedObject reobj(cx, reobjArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    RegExpStatics *res = obj->asGlobal().getRegExpStatics();
+    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
 
     RootedValue val(cx);
     if (!ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), NullPtr(), chars, length, indexp,
                              test, &val))
     {
         return false;
     }
     *rval = val;
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2788,17 +2788,17 @@ js_Array(JSContext *cx, unsigned argc, V
     return true;
 }
 
 JSObject *
 js_InitArrayClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject proto(cx, global->getOrCreateObjectPrototype(cx));
     if (!proto)
         return NULL;
 
     RootedTypeObject type(cx, proto->getNewType(cx, &ArrayClass));
     if (!type)
         return NULL;
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -135,17 +135,17 @@ Boolean(JSContext *cx, unsigned argc, Va
     return true;
 }
 
 JSObject *
 js_InitBooleanClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject booleanProto (cx, global->createBlankPrototype(cx, &BooleanObject::class_));
     if (!booleanProto)
         return NULL;
     booleanProto->setFixedSlot(BooleanObject::PRIMITIVE_VALUE_SLOT, BooleanValue(false));
 
     RootedFunction ctor(cx, global->createConstructor(cx, Boolean, cx->names().Boolean, 1));
     if (!ctor)
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -43,17 +43,17 @@ NewObjectCache::lookup(Class *clasp, gc:
 
     /* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
     return (entry->clasp == clasp && entry->key == key);
 }
 
 inline bool
 NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
 {
-    JS_ASSERT(!proto->isGlobal());
+    JS_ASSERT(!proto->is<GlobalObject>());
     return lookup(clasp, proto, kind, pentry);
 }
 
 inline bool
 NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
 {
     return lookup(clasp, global, kind, pentry);
 }
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3133,17 +3133,17 @@ js_Date(JSContext *cx, unsigned argc, Va
     return true;
 }
 
 JSObject *
 js_InitDateClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject dateProto(cx, global->createBlankPrototype(cx, &DateClass));
     if (!dateProto)
         return NULL;
     SetUTCTime(dateProto, js_NaN);
 
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, js_Date, cx->names().Date, MAXARGS);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -825,20 +825,20 @@ InitErrorClass(JSContext *cx, Handle<Glo
     JS_ASSERT(!errorProto->getPrivate());
 
     return errorProto;
 }
 
 JSObject *
 js_InitExceptionClasses(JSContext *cx, HandleObject obj)
 {
-    JS_ASSERT(obj->isGlobal());
+    JS_ASSERT(obj->is<GlobalObject>());
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject objectProto(cx, global->getOrCreateObjectPrototype(cx));
     if (!objectProto)
         return NULL;
 
     /* Initialize the base Error class first. */
     RootedObject errorProto(cx, InitErrorClass(cx, global, JSEXN_ERR, objectProto));
     if (!errorProto)
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1840,13 +1840,13 @@ GlobalObject::initIteratorClasses(JSCont
     }
 
     return true;
 }
 
 JSObject *
 js_InitIteratorClasses(JSContext *cx, HandleObject obj)
 {
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
     if (!GlobalObject::initIteratorClasses(cx, global))
         return NULL;
     return global->getIteratorPrototype();
 }
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -1122,17 +1122,17 @@ js::FinishRuntimeNumberState(JSRuntime *
 JSObject *
 js_InitNumberClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
     /* XXX must do at least once per new thread, so do it per JSContext... */
     FIX_FPU();
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject numberProto(cx, global->createBlankPrototype(cx, &NumberObject::class_));
     if (!numberProto)
         return NULL;
     numberProto->as<NumberObject>().setPrimitiveValue(0);
 
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, Number, cx->names().Number, 1);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1277,17 +1277,17 @@ NewObject(JSContext *cx, Class *clasp, t
     Probes::createObject(cx, obj);
     return obj;
 }
 
 void
 NewObjectCache::fillProto(EntryIndex entry, Class *clasp, js::TaggedProto proto,
                           gc::AllocKind kind, JSObject *obj)
 {
-    JS_ASSERT_IF(proto.isObject(), !proto.toObject()->isGlobal());
+    JS_ASSERT_IF(proto.isObject(), !proto.toObject()->is<GlobalObject>());
     JS_ASSERT(obj->getTaggedProto() == proto);
     return fill(entry, clasp, proto.raw(), kind, obj);
 }
 
 JSObject *
 js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp,
                             js::TaggedProto proto_, JSObject *parent_,
                             gc::AllocKind allocKind, NewObjectKind newKind)
@@ -1299,17 +1299,18 @@ js::NewObjectWithGivenProto(JSContext *c
         allocKind = GetBackgroundAllocKind(allocKind);
 
     NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
     if (proto.isObject() &&
         newKind == GenericObject &&
         !cx->compartment()->objectMetadataCallback &&
-        (!parent || parent == proto.toObject()->getParent()) && !proto.toObject()->isGlobal())
+        (!parent || parent == proto.toObject()->getParent()) &&
+        !proto.toObject()->is<GlobalObject>())
     {
         if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
             if (obj)
                 return obj;
         }
     }
 
@@ -1356,22 +1357,22 @@ js::NewObjectWithClassProtoCommon(JSCont
      * stored in an immutable slot on the global (except for ClearScope, which
      * will flush the new object cache).
      */
     JSProtoKey protoKey = GetClassProtoKey(clasp);
 
     NewObjectCache &cache = cx->runtime()->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
-    if (parentArg->isGlobal() &&
+    if (parentArg->is<GlobalObject>() &&
         protoKey != JSProto_Null &&
         newKind == GenericObject &&
         !cx->compartment()->objectMetadataCallback)
     {
-        if (cache.lookupGlobal(clasp, &parentArg->asGlobal(), allocKind, &entry)) {
+        if (cache.lookupGlobal(clasp, &parentArg->as<GlobalObject>(), allocKind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
             if (obj)
                 return obj;
         }
     }
 
     RootedObject parent(cx, parentArg);
     RootedObject proto(cx, protoArg);
@@ -1383,17 +1384,17 @@ js::NewObjectWithClassProtoCommon(JSCont
     if (!type)
         return NULL;
 
     JSObject *obj = NewObject(cx, clasp, type, parent, allocKind, newKind);
     if (!obj)
         return NULL;
 
     if (entry != -1 && !obj->hasDynamicSlots())
-        cache.fillGlobal(entry, clasp, &parent->asGlobal(), allocKind, obj);
+        cache.fillGlobal(entry, clasp, &parent->as<GlobalObject>(), allocKind, obj);
 
     return obj;
 }
 
 JSObject *
 js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
                       NewObjectKind newKind /* = GenericObject */)
 {
@@ -2129,17 +2130,17 @@ DefineStandardSlot(JSContext *cx, Handle
     RootedId id(cx, AtomToId(atom));
 
     if (key != JSProto_Null) {
         /*
          * Initializing an actual standard class on a global object. If the
          * property is not yet present, force it into a new one bound to a
          * reserved slot. Otherwise, go through the normal property path.
          */
-        JS_ASSERT(obj->isGlobal());
+        JS_ASSERT(obj->is<GlobalObject>());
         JS_ASSERT(obj->isNative());
 
         if (!obj->nativeLookup(cx, id)) {
             uint32_t slot = 2 * JSProto_LIMIT + key;
             obj->setReservedSlot(slot, v);
             if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
                 return false;
             AddTypePropertyId(cx, obj, id, v);
@@ -2153,28 +2154,28 @@ DefineStandardSlot(JSContext *cx, Handle
                                     v, JS_PropertyStub, JS_StrictPropertyStub, attrs);
     return named;
 }
 
 static void
 SetClassObject(JSObject *obj, JSProtoKey key, JSObject *cobj, JSObject *proto)
 {
     JS_ASSERT(!obj->getParent());
-    if (!obj->isGlobal())
+    if (!obj->is<GlobalObject>())
         return;
 
     obj->setReservedSlot(key, ObjectOrNullValue(cobj));
     obj->setReservedSlot(JSProto_LIMIT + key, ObjectOrNullValue(proto));
 }
 
 static void
 ClearClassObject(JSObject *obj, JSProtoKey key)
 {
     JS_ASSERT(!obj->getParent());
-    if (!obj->isGlobal())
+    if (!obj->is<GlobalObject>())
         return;
 
     obj->setSlot(key, UndefinedValue());
     obj->setSlot(JSProto_LIMIT + key, UndefinedValue());
 }
 
 JSObject *
 js::DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
@@ -2223,17 +2224,19 @@ js::DefineConstructorAndPrototype(JSCont
     bool cached = false;
     if (!constructor) {
         /*
          * Lacking a constructor, name the prototype (e.g., Math) unless this
          * class (a) is anonymous, i.e. for internal use only; (b) the class
          * of obj (the global object) is has a reserved slot indexed by key;
          * and (c) key is not the null key.
          */
-        if (!(clasp->flags & JSCLASS_IS_ANONYMOUS) || !obj->isGlobal() || key == JSProto_Null) {
+        if (!(clasp->flags & JSCLASS_IS_ANONYMOUS) || !obj->is<GlobalObject>() ||
+            key == JSProto_Null)
+        {
             uint32_t attrs = (clasp->flags & JSCLASS_IS_ANONYMOUS)
                            ? JSPROP_READONLY | JSPROP_PERMANENT
                            : 0;
             RootedValue value(cx, ObjectValue(*proto));
             if (!DefineStandardSlot(cx, obj, key, atom, value, attrs, named))
                 goto bad;
         }
 
@@ -2517,17 +2520,17 @@ JSObject::growSlots(JSContext *cx, Handl
         return false;  /* Leave slots at its old size. */
 
     bool changed = obj->slots != newslots;
     obj->slots = newslots;
 
     Debug_SetSlotRangeToCrashOnTouch(obj->slots + oldCount, newCount - oldCount);
 
     /* Changes in the slots of global objects can trigger recompilation. */
-    if (changed && obj->isGlobal())
+    if (changed && obj->is<GlobalObject>())
         types::MarkObjectStateChange(cx, obj);
 
     return true;
 }
 
 static void
 FreeSlots(JSContext *cx, HeapSlot *slots)
 {
@@ -2562,17 +2565,17 @@ JSObject::shrinkSlots(JSContext *cx, Han
     HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots, oldCount, newCount);
     if (!newslots)
         return;  /* Leave slots at its old size. */
 
     bool changed = obj->slots != newslots;
     obj->slots = newslots;
 
     /* Watch for changes in global object slots, as for growSlots. */
-    if (changed && obj->isGlobal())
+    if (changed && obj->is<GlobalObject>())
         types::MarkObjectStateChange(cx, obj);
 }
 
 /* static */ bool
 JSObject::sparsifyDenseElement(JSContext *cx, HandleObject obj, uint32_t index)
 {
     RootedValue value(cx, obj->getDenseElement(index));
     JS_ASSERT(!value.isMagic(JS_ELEMENTS_HOLE));
@@ -2986,17 +2989,17 @@ js::SetClassAndProto(JSContext *cx, Hand
     obj->setType(type);
     return true;
 }
 
 bool
 js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, MutableHandleObject objp)
 {
     RootedObject global(cx, &obj->global());
-    if (!global->isGlobal()) {
+    if (!global->is<GlobalObject>()) {
         objp.set(NULL);
         return true;
     }
 
     Value v = global->getReservedSlot(key);
     if (v.isObject()) {
         objp.set(&v.toObject());
         return true;
@@ -3751,17 +3754,17 @@ js::LookupNameWithGlobalDefault(JSContex
                                 MutableHandleObject objp)
 {
     RootedId id(cx, NameToId(name));
 
     RootedObject pobj(cx);
     RootedShape prop(cx);
 
     RootedObject scope(cx, scopeChain);
-    for (; !scope->isGlobal(); scope = scope->enclosingScope()) {
+    for (; !scope->is<GlobalObject>(); scope = scope->enclosingScope()) {
         if (!JSObject::lookupGeneric(cx, scope, id, &pobj, &prop))
             return false;
         if (prop)
             break;
     }
 
     objp.set(scope);
     return true;
@@ -4293,17 +4296,17 @@ baseops::SetPropertyHelper(JSContext *cx
             }
 
             shape = NULL;
         }
     } else {
         /* We should never add properties to lexical blocks. */
         JS_ASSERT(!obj->is<BlockObject>());
 
-        if (obj->isGlobal() &&
+        if (obj->is<GlobalObject>() &&
             (defineHow & DNP_UNQUALIFIED) &&
             !MaybeReportUndeclaredVarAssignment(cx, JSID_TO_STRING(id)))
         {
             return false;
         }
     }
 
     /*
@@ -4948,17 +4951,17 @@ js_GetObjectSlotName(JSTracer *trc, char
         while (shape && (!shape->hasSlot() || shape->slot() != slot))
             shape = shape->previous();
     } else {
         shape = NULL;
     }
 
     if (!shape) {
         const char *slotname = NULL;
-        if (obj->isGlobal()) {
+        if (obj->is<GlobalObject>()) {
 #define TEST_SLOT_MATCHES_PROTOTYPE(name,code,init)                           \
             if ((code) == slot) { slotname = js_##name##_str; goto found; }
             JS_FOR_EACH_PROTOTYPE(TEST_SLOT_MATCHES_PROTOTYPE)
 #undef TEST_SLOT_MATCHES_PROTOTYPE
         }
       found:
         if (slotname)
             JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -891,34 +891,34 @@ class JSObject : public js::ObjectImpl
 
     inline void initArrayClass();
 
     /*
      * In addition to the generic object interface provided by JSObject,
      * specific types of objects may provide additional operations. To access,
      * these addition operations, callers should use the pattern:
      *
-     *   if (obj.isX()) {
-     *     XObject &x = obj.asX();
+     *   if (obj.is<XObject>()) {
+     *     XObject &x = obj.as<XObject>();
      *     x.foo();
      *   }
      *
      * These XObject classes form a hierarchy. For example, for a cloned block
      * object, the following predicates are true: is<ClonedBlockObject>,
      * is<BlockObject>, is<NestedScopeObject> and is<ScopeObject>. Each of
      * these has a respective class that derives and adds operations.
      *
      * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
      * triplet (along with any class YObject that derives XObject).
      *
      * Note that X represents a low-level representation and does not query the
      * [[Class]] property of object defined by the spec (for this, see
      * js::ObjectClassIs).
      *
-     * SpiderMonkey has not been completely switched to the isX/asX/XObject
+     * SpiderMonkey has not been completely switched to the is/as/XObject
      * pattern so in some cases there is no XObject class and the engine
      * instead pokes directly at reserved slots and getPrivate. In such cases,
      * consider adding the missing XObject class.
      */
 
     template <class T>
     inline bool is() const { return getClass() == &T::class_; }
 
@@ -934,29 +934,26 @@ class JSObject : public js::ObjectImpl
         return *static_cast<const T *>(this);
     }
 
     /* Direct subtypes of JSObject: */
     inline bool isArray()            const { return hasClass(&js::ArrayClass); }
     inline bool isDate()             const { return hasClass(&js::DateClass); }
     inline bool isError()            const { return hasClass(&js::ErrorClass); }
     inline bool isFunction()         const { return hasClass(&js::FunctionClass); }
-    inline bool isGlobal()           const;
     inline bool isObject()           const { return hasClass(&js::ObjectClass); }
     using js::ObjectImpl::isProxy;
     inline bool isRegExpStatics()    const { return hasClass(&js::RegExpStaticsClass); }
     inline bool isTypedArray()       const;
 
     /* Subtypes of Proxy. */
     inline bool isWrapper()                 const;
     inline bool isFunctionProxy()           const { return hasClass(&js::FunctionProxyClass); }
     inline bool isCrossCompartmentWrapper() const;
 
-    inline js::GlobalObject &asGlobal();
-
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
 
 #ifdef DEBUG
     void dump();
 #endif
 
   private:
     static void staticAsserts() {
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -276,17 +276,17 @@ JSObject::canRemoveLastProperty()
     return previous->getObjectParent() == lastProperty()->getObjectParent()
         && previous->getObjectMetadata() == lastProperty()->getObjectMetadata()
         && previous->getObjectFlags() == lastProperty()->getObjectFlags();
 }
 
 inline const js::HeapSlot *
 JSObject::getRawSlots()
 {
-    JS_ASSERT(isGlobal());
+    JS_ASSERT(is<js::GlobalObject>());
     return slots;
 }
 
 inline void
 JSObject::setReservedSlot(uint32_t index, const js::Value &v)
 {
     JS_ASSERT(index < JSSLOT_FREE(getClass()));
     setSlot(index, v);
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -885,17 +885,17 @@ static const JSFunctionSpec json_static_
     JS_FN("parse",          js_json_parse,      2, 0),
     JS_FN("stringify",      js_json_stringify,  3, 0),
     JS_FS_END
 };
 
 JSObject *
 js_InitJSONClass(JSContext *cx, HandleObject obj)
 {
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     /*
      * JSON requires that Boolean.prototype.valueOf be created and stashed in a
      * reserved slot on the global object; see js::BooleanGetPrimitiveValueSlow
      * called from PreprocessValue above.
      */
     if (!global->getOrCreateBooleanPrototype(cx))
         return NULL;
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3587,17 +3587,17 @@ StringObject::assignInitialShape(JSConte
                            JSPROP_PERMANENT | JSPROP_READONLY);
 }
 
 JSObject *
 js_InitStringClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     Rooted<JSString*> empty(cx, cx->runtime()->emptyString);
     RootedObject proto(cx, global->createBlankPrototype(cx, &StringObject::class_));
     if (!proto || !proto->as<StringObject>().init(cx, empty))
         return NULL;
 
     /* Now create the String function. */
     RootedFunction ctor(cx);
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -3809,17 +3809,17 @@ DataViewObject::initClass(JSContext *cx)
 
     return proto;
 }
 
 JSObject *
 js_InitTypedArrayClasses(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     /* Idempotency required: we initialize several things, possibly lazily. */
     RootedObject stop(cx);
     if (!js_GetClassObject(cx, global, JSProto_ArrayBuffer, &stop))
         return NULL;
     if (stop)
         return stop;
 
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -413,17 +413,17 @@ static const JSFunctionSpec weak_map_met
     JS_FS_END
 };
 
 JSObject *
 js_InitWeakMapClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    Rooted<GlobalObject*> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     RootedObject weakMapProto(cx, global->createBlankPrototype(cx, &WeakMapObject::class_));
     if (!weakMapProto)
         return NULL;
 
     RootedFunction ctor(cx, global->createConstructor(cx, WeakMap_construct,
                                                       cx->names().WeakMap, 0));
     if (!ctor)
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1909,23 +1909,23 @@ Debugger::unwrapDebuggeeArgument(JSConte
     }
 
     /* If that produced an outer window, innerize it. */
     obj = GetInnerObject(cx, obj);
     if (!obj)
         return NULL;
 
     /* If that didn't produce a global object, it's an error. */
-    if (!obj->isGlobal()) {
+    if (!obj->is<GlobalObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNEXPECTED_TYPE,
                              "argument", "not a global object");
         return NULL;
     }
 
-    return &obj->asGlobal();
+    return &obj->as<GlobalObject>();
 }
 
 JSBool
 Debugger::addDebuggee(JSContext *cx, unsigned argc, Value *vp)
 {
     REQUIRE_ARGC("Debugger.addDebuggee", 1);
     THIS_DEBUGGER(cx, argc, vp, "addDebuggee", args, dbg);
     Rooted<GlobalObject*> global(cx, dbg->unwrapDebuggeeArgument(cx, args[0]));
@@ -4126,28 +4126,28 @@ js::EvaluateInEnv(JSContext *cx, Handle<
     RootedScript script(cx, frontend::CompileScript(cx, env, callerScript,
                                                     options, chars.get(), length,
                                                     /* source = */ NULL,
                                                     /* staticLevel = */ frame ? 1 : 0));
     if (!script)
         return false;
 
     script->isActiveEval = true;
-    ExecuteType type = !frame && env->isGlobal() ? EXECUTE_DEBUG_GLOBAL : EXECUTE_DEBUG;
+    ExecuteType type = !frame && env->is<GlobalObject>() ? EXECUTE_DEBUG_GLOBAL : EXECUTE_DEBUG;
     return ExecuteKernel(cx, script, *env, thisv, type, frame, rval.address());
 }
 
 static JSBool
 DebuggerGenericEval(JSContext *cx, const char *fullMethodName,
                     const Value &code, Value *bindings, MutableHandleValue vp,
                     Debugger *dbg, HandleObject scope, ScriptFrameIter *iter)
 {
     /* Either we're specifying the frame, or a global. */
     JS_ASSERT_IF(iter, !scope);
-    JS_ASSERT_IF(!iter, scope && scope->isGlobal());
+    JS_ASSERT_IF(!iter, scope && scope->is<GlobalObject>());
 
     /* Check the first argument, the eval code string. */
     if (!code.isString()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
                              fullMethodName, "string", InformalValueTypeName(code));
         return false;
     }
     Rooted<JSStableString *> stable(cx, code.toString()->ensureStable(cx));
@@ -4964,21 +4964,21 @@ DebuggerObject_makeDebuggeeValue(JSConte
 
     args.rval().set(arg0);
     return true;
 }
 
 static bool
 RequireGlobalObject(JSContext *cx, HandleValue dbgobj, HandleObject obj)
 {
-    if (!obj->isGlobal()) {
+    if (!obj->is<GlobalObject>()) {
         /* Help the poor programmer by pointing out wrappers around globals. */
         if (obj->isWrapper()) {
             JSObject *unwrapped = js::UncheckedUnwrap(obj);
-            if (unwrapped->isGlobal()) {
+            if (unwrapped->is<GlobalObject>()) {
                 js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_WRAPPER_IN_WAY,
                                          JSDVG_SEARCH_STACK, dbgobj, NullPtr(),
                                          "a global object", NULL);
                 return false;
             }
         }
 
         js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_DEBUG_BAD_REFERENT,
@@ -5406,17 +5406,17 @@ JS_DefineDebuggerObject(JSContext *cx, J
         debugCtor(cx),
         debugProto(cx),
         frameProto(cx),
         scriptProto(cx),
         sourceProto(cx),
         objectProto(cx),
         envProto(cx);
 
-    objProto = obj->asGlobal().getOrCreateObjectPrototype(cx);
+    objProto = obj->as<GlobalObject>().getOrCreateObjectPrototype(cx);
     if (!objProto)
         return false;
 
 
     debugProto = js_InitClass(cx, obj,
                               objProto, &Debugger::jsclass, Debugger::construct,
                               1, Debugger::properties, Debugger::methods, NULL, NULL,
                               debugCtor.address());
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -28,25 +28,25 @@
 
 using namespace js;
 
 JSObject *
 js_InitObjectClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    return obj->asGlobal().getOrCreateObjectPrototype(cx);
+    return obj->as<GlobalObject>().getOrCreateObjectPrototype(cx);
 }
 
 JSObject *
 js_InitFunctionClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
-    return obj->asGlobal().getOrCreateFunctionPrototype(cx);
+    return obj->as<GlobalObject>().getOrCreateFunctionPrototype(cx);
 }
 
 static JSBool
 ThrowTypeError(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
                                  JSMSG_THROW_TYPE_ERROR);
     return false;
@@ -419,17 +419,17 @@ GlobalObject *
 GlobalObject::create(JSContext *cx, Class *clasp)
 {
     JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
 
     JSObject *obj = NewObjectWithGivenProto(cx, clasp, NULL, NULL, SingletonObject);
     if (!obj)
         return NULL;
 
-    Rooted<GlobalObject *> global(cx, &obj->asGlobal());
+    Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
 
     cx->compartment()->initGlobal(*global);
 
     if (!global->setVarObj(cx))
         return NULL;
     if (!global->setDelegate(cx))
         return NULL;
 
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -463,22 +463,16 @@ LinkConstructorAndPrototype(JSContext *c
 extern bool
 DefinePropertiesAndBrand(JSContext *cx, JSObject *obj,
                          const JSPropertySpec *ps, const JSFunctionSpec *fs);
 
 typedef HashSet<GlobalObject *, DefaultHasher<GlobalObject *>, SystemAllocPolicy> GlobalObjectSet;
 
 } // namespace js
 
+template<>
 inline bool
-JSObject::isGlobal() const
+JSObject::is<js::GlobalObject>() const
 {
     return !!(js::GetObjectClass(const_cast<JSObject*>(this))->flags & JSCLASS_IS_GLOBAL);
 }
 
-js::GlobalObject &
-JSObject::asGlobal()
-{
-    JS_ASSERT(isGlobal());
-    return *static_cast<js::GlobalObject *>(this);
-}
-
 #endif /* vm_GlobalObject_h */
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -54,17 +54,17 @@ namespace js {
  * We set *vp to undefined early to reduce code size and bias this code for the
  * common and future-friendly cases.
  */
 inline bool
 ComputeImplicitThis(JSContext *cx, HandleObject obj, MutableHandleValue vp)
 {
     vp.setUndefined();
 
-    if (obj->isGlobal())
+    if (obj->is<GlobalObject>())
         return true;
 
     if (IsCacheableNonGlobalScope(obj))
         return true;
 
     JSObject *nobj = JSObject::thisObject(cx, obj);
     if (!nobj)
         return false;
@@ -329,17 +329,17 @@ SetNameOperation(JSContext *cx, JSScript
     RootedPropertyName name(cx, script->getName(pc));
     RootedValue valCopy(cx, val);
 
     /*
      * In strict-mode, we need to trigger an error when trying to assign to an
      * undeclared global variable. To do this, we call SetPropertyHelper
      * directly and pass DNP_UNQUALIFIED.
      */
-    if (scope->isGlobal()) {
+    if (scope->is<GlobalObject>()) {
         JS_ASSERT(!scope->getOps()->setProperty);
         RootedId id(cx, NameToId(name));
         return baseops::SetPropertyHelper(cx, scope, scope, id, DNP_UNQUALIFIED, &valCopy, strict);
     }
 
     return JSObject::setProperty(cx, scope, scope, name, &valCopy, strict);
 }
 
@@ -349,17 +349,17 @@ DefVarOrConstOperation(JSContext *cx, Ha
     JS_ASSERT(varobj->isVarObj());
 
     RootedShape prop(cx);
     RootedObject obj2(cx);
     if (!JSObject::lookupProperty(cx, varobj, dn, &obj2, &prop))
         return false;
 
     /* Steps 8c, 8d. */
-    if (!prop || (obj2 != varobj && varobj->isGlobal())) {
+    if (!prop || (obj2 != varobj && varobj->is<GlobalObject>())) {
         RootedValue value(cx, UndefinedValue());
         if (!JSObject::defineProperty(cx, varobj, dn, value, JS_PropertyStub,
                                       JS_StrictPropertyStub, attrs)) {
             return false;
         }
     } else {
         /*
          * Extension: ordinarily we'd be done here -- but for |const|.  If we
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -607,17 +607,17 @@ js::Execute(JSContext *cx, HandleScript 
     if (!scopeChain)
         return false;
 
     /* Ensure the scope chain is all same-compartment and terminates in a global. */
 #ifdef DEBUG
     JSObject *s = scopeChain;
     do {
         assertSameCompartment(cx, s);
-        JS_ASSERT_IF(!s->enclosingScope(), s->isGlobal());
+        JS_ASSERT_IF(!s->enclosingScope(), s->is<GlobalObject>());
     } while ((s = s->enclosingScope()));
 #endif
 
     /* The VAROBJFIX option makes varObj == globalObj in global code. */
     if (!cx->hasOption(JSOPTION_VAROBJFIX)) {
         if (!scopeChain->setVarObj(cx))
             return false;
     }
@@ -3341,17 +3341,17 @@ js::DefFunOperation(JSContext *cx, Handl
     /* Steps 5d, 5f. */
     if (!shape || pobj != parent) {
         return JSObject::defineProperty(cx, parent, name, rval, JS_PropertyStub,
                                         JS_StrictPropertyStub, attrs);
     }
 
     /* Step 5e. */
     JS_ASSERT(parent->isNative());
-    if (parent->isGlobal()) {
+    if (parent->is<GlobalObject>()) {
         if (shape->configurable()) {
             return JSObject::defineProperty(cx, parent, name, rval, JS_PropertyStub,
                                             JS_StrictPropertyStub, attrs);
         }
 
         if (shape->isAccessorDescriptor() || !shape->writable() || !shape->enumerable()) {
             JSAutoByteString bytes;
             if (js_AtomToPrintableString(cx, name, &bytes)) {
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -93,17 +93,17 @@ RegExpObjectBuilder::clone(Handle<RegExp
     if (!getOrCreateClone(proto))
         return NULL;
 
     /*
      * Check that the RegExpShared for the original is okay to use in
      * the clone -- if the |RegExpStatics| provides more flags we'll
      * need a different |RegExpShared|.
      */
-    RegExpStatics *res = proto->getParent()->asGlobal().getRegExpStatics();
+    RegExpStatics *res = proto->getParent()->as<GlobalObject>().getRegExpStatics();
     RegExpFlag origFlags = other->getFlags();
     RegExpFlag staticsFlags = res->getFlags();
     if ((origFlags & staticsFlags) != staticsFlags) {
         RegExpFlag newFlags = RegExpFlag(origFlags | staticsFlags);
         Rooted<JSAtom *> source(cx, other->getSource());
         return build(source, newFlags);
     }
 
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -647,17 +647,17 @@ bool
 JSRuntime::initSelfHosting(JSContext *cx)
 {
     JS_ASSERT(!selfHostingGlobal_);
     RootedObject savedGlobal(cx, js::GetDefaultGlobalForContext(cx));
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL)))
         return false;
     JS_SetGlobalObject(cx, selfHostingGlobal_);
     JSAutoCompartment ac(cx, cx->global());
-    Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->asGlobal());
+    Rooted<GlobalObject*> shg(cx, &selfHostingGlobal_->as<GlobalObject>());
     /*
      * During initialization of standard classes for the self-hosting global,
      * all self-hosted functions are ignored. Thus, we don't create cyclic
      * dependencies in the order of initialization.
      */
     if (!GlobalObject::initStandardClasses(cx, shg))
         return false;
 
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -1368,17 +1368,17 @@ NewObjectCache::invalidateEntriesForShap
         kind = GetBackgroundAllocKind(kind);
 
     Rooted<GlobalObject *> global(cx, &shape->getObjectParent()->global());
     Rooted<types::TypeObject *> type(cx, proto->getNewType(cx, clasp));
 
     EntryIndex entry;
     if (lookupGlobal(clasp, global, kind, &entry))
         PodZero(&entries[entry]);
-    if (!proto->isGlobal() && lookupProto(clasp, proto, kind, &entry))
+    if (!proto->is<GlobalObject>() && lookupProto(clasp, proto, kind, &entry))
         PodZero(&entries[entry]);
     if (lookupType(clasp, type, kind, &entry))
         PodZero(&entries[entry]);
 }
 
 /* static */ void
 EmptyShape::insertInitialShape(JSContext *cx, HandleShape shape, HandleObject proto)
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -347,20 +347,22 @@ StackFrame::epilogue(JSContext *cx)
         } else {
             /*
              * Debugger.Object.prototype.evalInGlobal creates indirect eval
              * frames scoped to the given global;
              * Debugger.Object.prototype.evalInGlobalWithBindings creates
              * indirect eval frames scoped to an object carrying the introduced
              * bindings.
              */
-            if (isDebuggerFrame())
-                JS_ASSERT(scopeChain()->isGlobal() || scopeChain()->enclosingScope()->isGlobal());
-            else
-                JS_ASSERT(scopeChain()->isGlobal());
+            if (isDebuggerFrame()) {
+                JS_ASSERT(scopeChain()->is<GlobalObject>() ||
+                          scopeChain()->enclosingScope()->is<GlobalObject>());
+            } else {
+                JS_ASSERT(scopeChain()->is<GlobalObject>());
+            }
         }
         return;
     }
 
     if (isGlobalFrame()) {
         JS_ASSERT(!scopeChain()->is<ScopeObject>());
         return;
     }