Bug 880041 (part 9) - Use JSObject::{is,as} for RegExpObject. r=sfink.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 16 Jun 2013 17:39:43 -0700
changeset 135238 74831022f42f2758406511bf52aff36ef7e88700
parent 135237 584ad9e66195fa105b411ca26808a8aa3aac0027
child 135239 45f4120fe067b734643cc1464df620ad77fafd2d
push id29584
push usernnethercote@mozilla.com
push dateMon, 17 Jun 2013 05:34:23 +0000
treeherdermozilla-inbound@90b688861270 [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 9) - Use JSObject::{is,as} for RegExpObject. r=sfink.
js/src/builtin/RegExp.cpp
js/src/ion/MCallOptimize.cpp
js/src/jsapi.cpp
js/src/jsclone.cpp
js/src/jsinfer.cpp
js/src/jsinferinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsopcode.cpp
js/src/jsreflect.cpp
js/src/jsscript.cpp
js/src/jsscriptinlines.h
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/SelfHosting.cpp
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -219,17 +219,17 @@ CompileRegExpObject(JSContext *cx, RegEx
     /*
      * If we get passed in an object whose internal [[Class]] property is
      * "RegExp", return a new object with the same source/flags.
      */
     if (IsObjectWithClass(sourceValue, ESClass_RegExp, cx)) {
         /*
          * Beware, sourceObj may be a (transparent) proxy to a RegExp, so only
          * use generic (proxyable) operations on sourceObj that do not assume
-         * sourceObj.isRegExp().
+         * sourceObj.is<RegExpObject>().
          */
         RootedObject sourceObj(cx, &sourceValue.toObject());
 
         if (args.hasDefined(1)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED);
             return false;
         }
 
@@ -301,24 +301,24 @@ CompileRegExpObject(JSContext *cx, RegEx
 
     args.rval().setObject(*reobj);
     return true;
 }
 
 JS_ALWAYS_INLINE bool
 IsRegExp(const Value &v)
 {
-    return v.isObject() && v.toObject().hasClass(&RegExpClass);
+    return v.isObject() && v.toObject().is<RegExpObject>();
 }
 
 JS_ALWAYS_INLINE bool
 regexp_compile_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsRegExp(args.thisv()));
-    RegExpObjectBuilder builder(cx, &args.thisv().toObject().asRegExp());
+    RegExpObjectBuilder builder(cx, &args.thisv().toObject().as<RegExpObject>());
     return CompileRegExpObject(cx, builder, args);
 }
 
 JSBool
 regexp_compile(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsRegExp, regexp_compile_impl>(cx, args);
@@ -348,17 +348,17 @@ regexp_construct(JSContext *cx, unsigned
     return CompileRegExpObject(cx, builder, args);
 }
 
 JS_ALWAYS_INLINE bool
 regexp_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsRegExp(args.thisv()));
 
-    JSString *str = args.thisv().toObject().asRegExp().toString(cx);
+    JSString *str = args.thisv().toObject().as<RegExpObject>().toString(cx);
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
 JSBool
@@ -490,23 +490,23 @@ static const JSPropertySpec regexp_stati
 
 JSObject *
 js_InitRegExpClass(JSContext *cx, HandleObject obj)
 {
     JS_ASSERT(obj->isNative());
 
     Rooted<GlobalObject*> global(cx, &obj->asGlobal());
 
-    RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpClass));
+    RootedObject proto(cx, global->createBlankPrototype(cx, &RegExpObject::class_));
     if (!proto)
         return NULL;
     proto->setPrivate(NULL);
 
     HandlePropertyName empty = cx->names().empty;
-    RegExpObjectBuilder builder(cx, &proto->asRegExp());
+    RegExpObjectBuilder builder(cx, &proto->as<RegExpObject>());
     if (!builder.build(empty, RegExpFlag(0)))
         return NULL;
 
     if (!DefinePropertiesAndBrand(cx, proto, NULL, regexp_methods))
         return NULL;
 
     RootedFunction ctor(cx);
     ctor = global->createConstructor(cx, regexp_construct, cx->names().RegExp, 2);
@@ -525,17 +525,17 @@ js_InitRegExpClass(JSContext *cx, Handle
 
     return proto;
 }
 
 RegExpRunStatus
 js::ExecuteRegExp(JSContext *cx, HandleObject regexp, HandleString string, MatchConduit &matches)
 {
     /* Step 1 (b) was performed by CallNonGenericMethod. */
-    Rooted<RegExpObject*> reobj(cx, &regexp->asRegExp());
+    Rooted<RegExpObject*> reobj(cx, &regexp->as<RegExpObject>());
 
     RegExpGuard re(cx);
     if (!reobj->getShared(cx, &re))
         return RegExpRunStatus_Error;
 
     RegExpStatics *res = cx->regExpStatics();
 
     /* Step 3. */
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -921,17 +921,17 @@ IonBuilder::inlineRegExpTest(CallInfo &c
     // TI can infer a NULL return type of regexp_test with eager compilation.
     if (CallResultEscapes(pc) && getInlineReturnType() != MIRType_Boolean)
         return InliningStatus_NotInlined;
 
     if (callInfo.thisArg()->type() != MIRType_Object)
         return InliningStatus_NotInlined;
     types::StackTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
     Class *clasp = thisTypes ? thisTypes->getKnownClass() : NULL;
-    if (clasp != &RegExpClass)
+    if (clasp != &RegExpObject::class_)
         return InliningStatus_NotInlined;
     if (callInfo.getArg(0)->type() != MIRType_String)
         return InliningStatus_NotInlined;
 
     callInfo.unwrapArgs();
 
     MInstruction *match = MRegExpTest::New(callInfo.thisArg(), callInfo.getArg(0));
     current->add(match);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1787,20 +1787,22 @@ JS_InitStandardClasses(JSContext *cx, JS
     cx->setDefaultCompartmentObjectIfUnset(obj);
     assertSameCompartment(cx, obj);
 
     Rooted<GlobalObject*> global(cx, &obj->global());
     return GlobalObject::initStandardClasses(cx, global);
 }
 
 #define CLASP(name)                 (&name##Class)
+#define OCLASP(name)                (&name##Object::class_)
 #define TYPED_ARRAY_CLASP(type)     (&TypedArray::classes[TypedArray::type])
 #define EAGER_ATOM(name)            NAME_OFFSET(name)
 #define EAGER_CLASS_ATOM(name)      NAME_OFFSET(name)
 #define EAGER_ATOM_AND_CLASP(name)  EAGER_CLASS_ATOM(name), CLASP(name)
+#define EAGER_ATOM_AND_OCLASP(name) EAGER_CLASS_ATOM(name), OCLASP(name)
 
 typedef struct JSStdName {
     JSClassInitializerOp init;
     size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
     Class       *clasp;
 } JSStdName;
 
 static Handle<PropertyName*>
@@ -1818,27 +1820,27 @@ static JSStdName standard_class_atoms[] 
     {js_InitObjectClass,                EAGER_ATOM_AND_CLASP(Object)},
     {js_InitArrayClass,                 EAGER_ATOM_AND_CLASP(Array)},
     {js_InitBooleanClass,               EAGER_ATOM_AND_CLASP(Boolean)},
     {js_InitDateClass,                  EAGER_ATOM_AND_CLASP(Date)},
     {js_InitMathClass,                  EAGER_ATOM_AND_CLASP(Math)},
     {js_InitNumberClass,                EAGER_ATOM_AND_CLASP(Number)},
     {js_InitStringClass,                EAGER_ATOM_AND_CLASP(String)},
     {js_InitExceptionClasses,           EAGER_ATOM_AND_CLASP(Error)},
-    {js_InitRegExpClass,                EAGER_ATOM_AND_CLASP(RegExp)},
+    {js_InitRegExpClass,                EAGER_ATOM_AND_OCLASP(RegExp)},
 #if JS_HAS_GENERATORS
     {js_InitIteratorClasses,            EAGER_ATOM_AND_CLASP(StopIteration)},
 #endif
     {js_InitJSONClass,                  EAGER_ATOM_AND_CLASP(JSON)},
     {js_InitTypedArrayClasses,          EAGER_CLASS_ATOM(ArrayBuffer), &js::ArrayBufferObject::protoClass},
     {js_InitWeakMapClass,               EAGER_ATOM_AND_CLASP(WeakMap)},
-    {js_InitMapClass,                   EAGER_CLASS_ATOM(Map), &js::MapObject::class_},
-    {js_InitSetClass,                   EAGER_CLASS_ATOM(Set), &js::SetObject::class_},
+    {js_InitMapClass,                   EAGER_ATOM_AND_OCLASP(Map)},
+    {js_InitSetClass,                   EAGER_ATOM_AND_OCLASP(Set)},
 #ifdef ENABLE_PARALLEL_JS
-    {js_InitParallelArrayClass,         EAGER_CLASS_ATOM(ParallelArray), &js::ParallelArrayObject::class_},
+    {js_InitParallelArrayClass,         EAGER_ATOM_AND_OCLASP(ParallelArray)},
 #endif
     {js_InitProxyClass,                 EAGER_ATOM_AND_CLASP(Proxy)},
 #if ENABLE_INTL_API
     {js_InitIntlClass,                  EAGER_ATOM_AND_CLASP(Intl)},
 #endif
     {NULL,                              0, NULL}
 };
 
@@ -6833,18 +6835,18 @@ JS_ExecuteRegExp(JSContext *cx, JSObject
     RootedObject obj(cx, objArg);
     RootedObject reobj(cx, reobjArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     RegExpStatics *res = obj->asGlobal().getRegExpStatics();
 
     RootedValue val(cx);
-    if (!ExecuteRegExpLegacy(cx, res, reobj->asRegExp(), NullPtr(), chars, length, indexp, test,
-                             &val))
+    if (!ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), NullPtr(), chars, length, indexp,
+                             test, &val))
     {
         return false;
     }
     *rval = val;
     return true;
 }
 
 JS_PUBLIC_API(JSObject *)
@@ -6874,18 +6876,18 @@ JS_PUBLIC_API(JSBool)
 JS_ExecuteRegExpNoStatics(JSContext *cx, JSObject *objArg, jschar *chars, size_t length,
                           size_t *indexp, JSBool test, jsval *rval)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     RootedValue val(cx);
-    if (!ExecuteRegExpLegacy(cx, NULL, obj->asRegExp(), NullPtr(), chars, length, indexp, test,
-                             &val))
+    if (!ExecuteRegExpLegacy(cx, NULL, obj->as<RegExpObject>(), NullPtr(), chars, length, indexp,
+                             test, &val))
     {
         return false;
     }
     *rval = val;
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
@@ -6898,27 +6900,27 @@ JS_ObjectIsRegExp(JSContext *cx, JSObjec
 
 JS_PUBLIC_API(unsigned)
 JS_GetRegExpFlags(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    return obj->asRegExp().getFlags();
+    return obj->as<RegExpObject>().getFlags();
 }
 
 JS_PUBLIC_API(JSString *)
 JS_GetRegExpSource(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    return obj->asRegExp().getSource();
+    return obj->as<RegExpObject>().getSource();
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetDefaultLocale(JSRuntime *rt, const char *locale)
 {
     AssertHeapIsIdle(rt);
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -676,18 +676,18 @@ JSStructuredCloneWriter::startWrite(cons
         AutoCompartment ac(context(), obj);
 
         bool backref;
         if (!startObject(obj, &backref))
             return false;
         if (backref)
             return true;
 
-        if (obj->isRegExp()) {
-            RegExpObject &reobj = obj->asRegExp();
+        if (obj->is<RegExpObject>()) {
+            RegExpObject &reobj = obj->as<RegExpObject>();
             return out.writePair(SCTAG_REGEXP_OBJECT, reobj.getFlags()) &&
                    writeString(SCTAG_STRING, reobj.getSource());
         } else if (obj->isDate()) {
             double d = js_DateGetMsecSinceEpoch(obj);
             return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
         } else if (obj->isTypedArray()) {
             return writeTypedArray(obj);
         } else if (obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().hasData()) {
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -6136,17 +6136,17 @@ JSCompartment::getNewType(JSContext *cx,
      * types and the possible js::Class of objects with that type.
      */
     if (proto.isObject()) {
         RootedObject obj(cx, proto.toObject());
 
         if (fun)
             CheckNewScriptProperties(cx, type, fun);
 
-        if (obj->isRegExp()) {
+        if (obj->is<RegExpObject>()) {
             AddTypeProperty(cx, type, "source", types::Type::StringType());
             AddTypeProperty(cx, type, "global", types::Type::BooleanType());
             AddTypeProperty(cx, type, "ignoreCase", types::Type::BooleanType());
             AddTypeProperty(cx, type, "multiline", types::Type::BooleanType());
             AddTypeProperty(cx, type, "sticky", types::Type::BooleanType());
             AddTypeProperty(cx, type, "lastIndex", types::Type::Int32Type());
         }
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -466,17 +466,17 @@ GetClassForProtoKey(JSProtoKey key)
 
       case JSProto_Number:
         return &NumberClass;
       case JSProto_Boolean:
         return &BooleanClass;
       case JSProto_String:
         return &StringClass;
       case JSProto_RegExp:
-        return &RegExpClass;
+        return &RegExpObject::class_;
 
       case JSProto_Int8Array:
       case JSProto_Uint8Array:
       case JSProto_Int16Array:
       case JSProto_Uint16Array:
       case JSProto_Int32Array:
       case JSProto_Uint32Array:
       case JSProto_Float32Array:
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1975,17 +1975,17 @@ JSObject::TradeGuts(JSContext *cx, JSObj
     /* Don't try to swap a JSFunction for a plain function JSObject. */
     JS_ASSERT_IF(a->isFunction(), a->tenuredSizeOfThis() == b->tenuredSizeOfThis());
 
     /*
      * Regexp guts are more complicated -- we would need to migrate the
      * refcounted JIT code blob for them across compartments instead of just
      * swapping guts.
      */
-    JS_ASSERT(!a->isRegExp() && !b->isRegExp());
+    JS_ASSERT(!a->is<RegExpObject>() && !b->is<RegExpObject>());
 
     /* Arrays can use their fixed storage for elements. */
     JS_ASSERT(!a->isArray() && !b->isArray());
 
     /*
      * Callers should not try to swap ArrayBuffer objects,
      * these use a different slot representation from other objects.
      */
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -211,17 +211,16 @@ extern Class DateClass;
 extern Class ErrorClass;
 extern Class GeneratorClass;
 extern Class IntlClass;
 extern Class JSONClass;
 extern Class MathClass;
 extern Class NumberClass;
 extern Class ObjectClass;
 extern Class ProxyClass;
-extern Class RegExpClass;
 extern Class RegExpStaticsClass;
 extern Class SetIteratorClass;
 extern Class ScriptSourceClass;
 extern Class StopIterationClass;
 extern Class StringClass;
 extern Class WeakMapClass;
 extern Class WithClass;
 
@@ -238,17 +237,16 @@ class NewObjectCache;
 class NormalArgumentsObject;
 class NumberObject;
 class ScopeObject;
 class SetObject;
 class SetIteratorObject;
 class StaticBlockObject;
 class StrictArgumentsObject;
 class StringObject;
-class RegExpObject;
 class WithObject;
 
 }  /* namespace js */
 
 #define JSSLOT_FREE(clasp)  JSCLASS_RESERVED_SLOTS(clasp)
 
 /*
  * The public interface for an object.
@@ -973,17 +971,16 @@ class JSObject : public js::ObjectImpl
     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 isGenerator()        const { return hasClass(&js::GeneratorClass); }
     inline bool isGlobal()           const;
     inline bool isObject()           const { return hasClass(&js::ObjectClass); }
     using js::ObjectImpl::isProxy;
-    inline bool isRegExp()           const { return hasClass(&js::RegExpClass); }
     inline bool isRegExpStatics()    const { return hasClass(&js::RegExpStaticsClass); }
     inline bool isScope()            const { return isCall() || isDeclEnv() || isNestedScope(); }
     inline bool isScriptSource()     const { return hasClass(&js::ScriptSourceClass); }
     inline bool isSetIterator()      const { return hasClass(&js::SetIteratorClass); }
     inline bool isStopIteration()    const { return hasClass(&js::StopIterationClass); }
     inline bool isTypedArray()       const;
     inline bool isWeakMap()          const { return hasClass(&js::WeakMapClass); }
 
@@ -1012,17 +1009,16 @@ class JSObject : public js::ObjectImpl
     inline js::CallObject &asCall();
     inline js::ClonedBlockObject &asClonedBlock();
     inline js::DeclEnvObject &asDeclEnv();
     inline js::DebugScopeObject &asDebugScope();
     inline js::GlobalObject &asGlobal();
     inline js::MapObject &asMap();
     inline js::NestedScopeObject &asNestedScope();
     inline js::NumberObject &asNumber();
-    inline js::RegExpObject &asRegExp();
     inline js::ScopeObject &asScope();
     inline js::SetObject &asSet();
     inline js::SetIteratorObject &asSetIterator();
     inline js::ScriptSourceObject &asScriptSource();
     inline js::StaticBlockObject &asStaticBlock();
     inline js::StringObject &asString();
     inline js::WithObject &asWith();
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1680,17 +1680,17 @@ ObjectClassIs(HandleObject obj, ESClassV
     if (JS_UNLIKELY(obj->isProxy()))
         return Proxy::objectClassIs(obj, classValue, cx);
 
     switch (classValue) {
       case ESClass_Array: return obj->isArray();
       case ESClass_Number: return obj->isNumber();
       case ESClass_String: return obj->isString();
       case ESClass_Boolean: return obj->isBoolean();
-      case ESClass_RegExp: return obj->isRegExp();
+      case ESClass_RegExp: return obj->is<RegExpObject>();
       case ESClass_ArrayBuffer: return obj->is<ArrayBufferObject>();
       case ESClass_Date: return obj->isDate();
     }
     JS_NOT_REACHED("bad classValue");
     return false;
 }
 
 inline bool
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -510,18 +510,18 @@ ToDisassemblySource(JSContext *cx, jsval
 
         if (obj->isFunction()) {
             JSString *str = JS_DecompileFunction(cx, obj->toFunction(), JS_DONT_PRETTY_PRINT);
             if (!str)
                 return false;
             return bytes->encodeLatin1(cx, str);
         }
 
-        if (obj->isRegExp()) {
-            JSString *source = obj->asRegExp().toString(cx);
+        if (obj->is<RegExpObject>()) {
+            JSString *source = obj->as<RegExpObject>().toString(cx);
             if (!source)
                 return false;
             JS::Anchor<JSString *> anchor(source);
             return bytes->encodeLatin1(cx, source);
         }
     }
 
     return !!js_ValueToPrintable(cx, v, bytes, true);
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2644,17 +2644,17 @@ ASTSerializer::literal(ParseNode *pn, Mu
     switch (pn->getKind()) {
       case PNK_STRING:
         val.setString(pn->pn_atom);
         break;
 
       case PNK_REGEXP:
       {
         RootedObject re1(cx, pn->pn_objbox ? pn->pn_objbox->object : NULL);
-        LOCAL_ASSERT(re1 && re1->isRegExp());
+        LOCAL_ASSERT(re1 && re1->is<RegExpObject>());
 
         RootedObject proto(cx);
         if (!js_GetClassPrototype(cx, JSProto_RegExp, &proto))
             return false;
 
         RootedObject re2(cx, CloneRegExpObject(cx, re1, proto));
         if (!re2)
             return false;
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2351,17 +2351,17 @@ js::CloneScript(JSContext *cx, HandleObj
     }
 
     /* RegExps */
 
     AutoObjectVector regexps(cx);
     for (unsigned i = 0; i < nregexps; i++) {
         HeapPtrObject *vector = src->regexps()->vector;
         for (unsigned i = 0; i < nregexps; i++) {
-            JSObject *clone = CloneScriptRegExpObject(cx, vector[i]->asRegExp());
+            JSObject *clone = CloneScriptRegExpObject(cx, vector[i]->as<RegExpObject>());
             if (!clone || !regexps.append(clone))
                 return NULL;
         }
     }
 
     /* Now that all fallible allocation is complete, create the GC thing. */
 
     CompileOptions options(cx);
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -122,17 +122,17 @@ JSScript::functionOrCallerFunction()
 }
 
 inline js::RegExpObject *
 JSScript::getRegExp(size_t index)
 {
     js::ObjectArray *arr = regexps();
     JS_ASSERT(uint32_t(index) < arr->length);
     JSObject *obj = arr->vector[index];
-    JS_ASSERT(obj->isRegExp());
+    JS_ASSERT(obj->is<js::RegExpObject>());
     return (js::RegExpObject *) obj;
 }
 
 inline bool
 JSScript::isEmpty() const
 {
     if (length > 3)
         return false;
--- a/js/src/vm/RegExpObject-inl.h
+++ b/js/src/vm/RegExpObject-inl.h
@@ -10,23 +10,16 @@
 #include "mozilla/Util.h"
 
 #include "RegExpObject.h"
 
 #include "jsstrinlines.h"
 
 #include "String-inl.h"
 
-inline js::RegExpObject &
-JSObject::asRegExp()
-{
-    JS_ASSERT(isRegExp());
-    return *static_cast<js::RegExpObject *>(this);
-}
-
 namespace js {
 
 inline RegExpShared *
 RegExpObject::maybeShared() const
 {
     return static_cast<RegExpShared *>(JSObject::getPrivate());
 }
 
@@ -109,18 +102,18 @@ RegExpShared::isJITRuntimeEnabled(JSCont
 #else
     return false;
 #endif
 }
 
 inline bool
 RegExpToShared(JSContext *cx, HandleObject obj, RegExpGuard *g)
 {
-    if (obj->isRegExp())
-        return obj->asRegExp().getShared(cx, g);
+    if (obj->is<RegExpObject>())
+        return obj->as<RegExpObject>().getShared(cx, g);
     return Proxy::regexp_toShared(cx, obj, g);
 }
 
 inline void
 RegExpShared::prepareForUse(JSContext *cx)
 {
     gcNumberWhenUsed = cx->runtime()->gcNumber;
 }
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -32,39 +32,39 @@ RegExpObjectBuilder::RegExpObjectBuilder
 bool
 RegExpObjectBuilder::getOrCreate()
 {
     if (reobj_)
         return true;
 
     // Note: RegExp objects are always allocated in the tenured heap. This is
     // not strictly required, but simplifies embedding them in jitcode.
-    JSObject *obj = NewBuiltinClassInstance(cx, &RegExpClass, TenuredObject);
+    JSObject *obj = NewBuiltinClassInstance(cx, &RegExpObject::class_, TenuredObject);
     if (!obj)
         return false;
     obj->initPrivate(NULL);
 
-    reobj_ = &obj->asRegExp();
+    reobj_ = &obj->as<RegExpObject>();
     return true;
 }
 
 bool
 RegExpObjectBuilder::getOrCreateClone(RegExpObject *proto)
 {
     JS_ASSERT(!reobj_);
 
     // Note: RegExp objects are always allocated in the tenured heap. This is
     // not strictly required, but simplifies embedding them in jitcode.
-    JSObject *clone = NewObjectWithGivenProto(cx, &RegExpClass, proto, proto->getParent(),
+    JSObject *clone = NewObjectWithGivenProto(cx, &RegExpObject::class_, proto, proto->getParent(),
                                               TenuredObject);
     if (!clone)
         return false;
     clone->initPrivate(NULL);
 
-    reobj_ = &clone->asRegExp();
+    reobj_ = &clone->as<RegExpObject>();
     return true;
 }
 
 RegExpObject *
 RegExpObjectBuilder::build(HandleAtom source, RegExpShared &shared)
 {
     if (!getOrCreate())
         return NULL;
@@ -202,17 +202,17 @@ regexp_trace(JSTracer *trc, JSObject *ob
       * We have to check both conditions, since:
       *   1. During TraceRuntime, isHeapBusy() is true
       *   2. When a write barrier executes, IS_GC_MARKING_TRACER is true.
       */
     if (trc->runtime->isHeapBusy() && IS_GC_MARKING_TRACER(trc))
         obj->setPrivate(NULL);
 }
 
-Class js::RegExpClass = {
+Class RegExpObject::class_ = {
     js_RegExp_str,
     JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS |
     JSCLASS_HAS_RESERVED_SLOTS(RegExpObject::RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
     JS_PropertyStub,         /* addProperty */
     JS_DeletePropertyStub,   /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
@@ -268,17 +268,17 @@ RegExpObject::createShared(JSContext *cx
 
     self->setShared(cx, **g);
     return true;
 }
 
 Shape *
 RegExpObject::assignInitialShape(JSContext *cx)
 {
-    JS_ASSERT(isRegExp());
+    JS_ASSERT(is<RegExpObject>());
     JS_ASSERT(nativeEmpty());
 
     JS_STATIC_ASSERT(LAST_INDEX_SLOT == 0);
     JS_STATIC_ASSERT(SOURCE_SLOT == LAST_INDEX_SLOT + 1);
     JS_STATIC_ASSERT(GLOBAL_FLAG_SLOT == SOURCE_SLOT + 1);
     JS_STATIC_ASSERT(IGNORE_CASE_FLAG_SLOT == GLOBAL_FLAG_SLOT + 1);
     JS_STATIC_ASSERT(MULTILINE_FLAG_SLOT == IGNORE_CASE_FLAG_SLOT + 1);
     JS_STATIC_ASSERT(STICKY_FLAG_SLOT == MULTILINE_FLAG_SLOT + 1);
@@ -731,18 +731,18 @@ RegExpCompartment::sizeOfExcludingThis(J
 }
 
 /* Functions */
 
 JSObject *
 js::CloneRegExpObject(JSContext *cx, JSObject *obj_, JSObject *proto_)
 {
     RegExpObjectBuilder builder(cx);
-    Rooted<RegExpObject*> regex(cx, &obj_->asRegExp());
-    Rooted<RegExpObject*> proto(cx, &proto_->asRegExp());
+    Rooted<RegExpObject*> regex(cx, &obj_->as<RegExpObject>());
+    Rooted<RegExpObject*> proto(cx, &proto_->as<RegExpObject>());
     return builder.clone(regex, proto);
 }
 
 bool
 js::ParseRegExpFlags(JSContext *cx, JSString *flagStr, RegExpFlag *flagsOut)
 {
     size_t n = flagStr->length();
     const jschar *s = flagStr->getChars(cx);
@@ -784,17 +784,17 @@ js::XDRScriptRegExpObject(XDRState<mode>
 {
     /* NB: Keep this in sync with CloneScriptRegExpObject. */
 
     RootedAtom source(xdr->cx());
     uint32_t flagsword = 0;
 
     if (mode == XDR_ENCODE) {
         JS_ASSERT(objp);
-        RegExpObject &reobj = (*objp)->asRegExp();
+        RegExpObject &reobj = (*objp)->as<RegExpObject>();
         source = reobj.getSource();
         flagsword = reobj.getFlags();
     }
     if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword))
         return false;
     if (mode == XDR_DECODE) {
         RegExpFlag flags = RegExpFlag(flagsword);
         RegExpObject *reobj = RegExpObject::createNoStatics(xdr->cx(), source, flags, NULL);
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -289,16 +289,18 @@ class RegExpObject : public JSObject
     static const unsigned GLOBAL_FLAG_SLOT         = 2;
     static const unsigned IGNORE_CASE_FLAG_SLOT    = 3;
     static const unsigned MULTILINE_FLAG_SLOT      = 4;
     static const unsigned STICKY_FLAG_SLOT         = 5;
 
   public:
     static const unsigned RESERVED_SLOTS = 6;
 
+    static Class class_;
+
     /*
      * Note: The regexp statics flags are OR'd into the provided flags,
      * so this function is really meant for object creation during code
      * execution, as opposed to during something like XDR.
      */
     static RegExpObject *
     create(JSContext *cx, RegExpStatics *res, const jschar *chars, size_t length,
            RegExpFlag flags, frontend::TokenStream *ts);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -615,18 +615,18 @@ CloneObject(JSContext *cx, HandleObject 
         if (srcObj->toFunction()->isWrappable()) {
             clone = srcObj;
             if (!cx->compartment()->wrap(cx, clone.address()))
                 return NULL;
         } else {
             RootedFunction fun(cx, srcObj->toFunction());
             clone = CloneFunctionObject(cx, fun, cx->global(), fun->getAllocKind(), TenuredObject);
         }
-    } else if (srcObj->isRegExp()) {
-        RegExpObject &reobj = srcObj->asRegExp();
+    } else if (srcObj->is<RegExpObject>()) {
+        RegExpObject &reobj = srcObj->as<RegExpObject>();
         RootedAtom source(cx, reobj.getSource());
         clone = RegExpObject::createNoStatics(cx, source, reobj.getFlags(), NULL);
     } else if (srcObj->isDate()) {
         clone = JS_NewDateObjectMsec(cx, srcObj->getDateUTCTime().toNumber());
     } else if (srcObj->isBoolean()) {
         clone = BooleanObject::create(cx, srcObj->asBoolean().unbox());
     } else if (srcObj->isNumber()) {
         clone = NumberObject::create(cx, srcObj->asNumber().unbox());