Bug 880041 (part 3) - Use JSObject::{is,as} for ArrayBufferObject. r=luke.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 16 Jun 2013 17:07:35 -0700
changeset 135232 4b9f61b1d406dbea5ed1c5692f72c17b958a46a7
parent 135231 a741a5faa4d3268ab3f263d7e79098e3385bd5e0
child 135233 23c5c0ae167d95ee83208306105c1952a7400458
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)
reviewersluke
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 3) - Use JSObject::{is,as} for ArrayBufferObject. r=luke.
js/src/gc/Nursery.cpp
js/src/ion/AsmJSLink.cpp
js/src/jsapi.cpp
js/src/jsclone.cpp
js/src/jsinferinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jstypedarrayinlines.h
js/src/vm/GlobalObject.cpp
js/src/vm/ObjectImpl.cpp
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -355,17 +355,17 @@ js::Nursery::moveElementsToTenured(JSObj
     /* TODO Bug 874151: Prefer to put element data inline if we have space. */
     if (!isInside(srcHeader)) {
         JS_ASSERT(src->elements == dst->elements);
         hugeSlots.remove(reinterpret_cast<HeapSlot*>(srcHeader));
         return 0;
     }
 
     /* ArrayBuffer stores byte-length, not Value count. */
-    if (src->isArrayBuffer()) {
+    if (src->is<ArrayBufferObject>()) {
         size_t nbytes = sizeof(ObjectElements) + srcHeader->initializedLength;
         if (src->hasDynamicElements()) {
             dstHeader = static_cast<ObjectElements *>(alloc->malloc_(nbytes));
             if (!dstHeader)
                 MOZ_CRASH();
         } else {
             dst->setFixedElements();
             dstHeader = dst->getElementsHeader();
--- a/js/src/ion/AsmJSLink.cpp
+++ b/js/src/ion/AsmJSLink.cpp
@@ -181,17 +181,17 @@ DynamicallyLinkModule(JSContext *cx, Cal
     if (args.length() > 2)
         bufferVal = args[2];
 
     Rooted<ArrayBufferObject*> heap(cx);
     if (module.hasArrayView()) {
         if (!IsTypedArrayBuffer(bufferVal))
             return LinkFail(cx, "bad ArrayBuffer argument");
 
-        heap = &bufferVal.toObject().asArrayBuffer();
+        heap = &bufferVal.toObject().as<ArrayBufferObject>();
 
         if (!IsPowerOfTwo(heap->byteLength()) || heap->byteLength() < AsmJSAllocationGranularity)
             return LinkFail(cx, "ArrayBuffer byteLength must be a power of two greater than or equal to 4096");
 
         if (!ArrayBufferObject::prepareForAsmJS(cx, heap))
             return LinkFail(cx, "Unable to prepare ArrayBuffer for asm.js use");
 
 #if defined(JS_CPU_X86)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1877,17 +1877,17 @@ static JSStdName standard_class_names[] 
     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
     {js_InitExceptionClasses,   EAGER_CLASS_ATOM(URIError), CLASP(Error)},
 
     {js_InitIteratorClasses,    EAGER_CLASS_ATOM(Iterator), &PropertyIteratorObject::class_},
 
     /* Typed Arrays */
-    {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(ArrayBuffer),  &ArrayBufferClass},
+    {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(ArrayBuffer),  &ArrayBufferObject::class_},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int8Array),    TYPED_ARRAY_CLASP(TYPE_INT8)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint8Array),   TYPED_ARRAY_CLASP(TYPE_UINT8)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int16Array),   TYPED_ARRAY_CLASP(TYPE_INT16)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint16Array),  TYPED_ARRAY_CLASP(TYPE_UINT16)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int32Array),   TYPED_ARRAY_CLASP(TYPE_INT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint32Array),  TYPED_ARRAY_CLASP(TYPE_UINT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)},
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -480,17 +480,17 @@ JSStructuredCloneWriter::parseTransferab
             return false;
         }
 
         JSObject* tObj = CheckedUnwrap(&v.toObject());
         if (!tObj) {
             JS_ReportError(context(), "Permission denied to access object");
             return false;
         }
-        if (!tObj->isArrayBuffer()) {
+        if (!tObj->is<ArrayBufferObject>()) {
             reportErrorTransferable();
             return false;
         }
 
         // No duplicate:
         if (transferableObjects.has(tObj)) {
             reportErrorTransferable();
             return false;
@@ -595,17 +595,17 @@ JSStructuredCloneWriter::writeTypedArray
         return false;
 
     return out.write(TypedArray::byteOffset(arr));
 }
 
 bool
 JSStructuredCloneWriter::writeArrayBuffer(JSHandleObject obj)
 {
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     return out.writePair(SCTAG_ARRAY_BUFFER_OBJECT, buffer.byteLength()) &&
            out.writeBytes(buffer.dataPointer(), buffer.byteLength());
 }
 
 bool
 JSStructuredCloneWriter::startObject(JSHandleObject obj, bool *backref)
 {
     /* Handle cycles in the object graph. */
@@ -685,17 +685,17 @@ JSStructuredCloneWriter::startWrite(cons
             RegExpObject &reobj = obj->asRegExp();
             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->isArrayBuffer() && obj->asArrayBuffer().hasData()) {
+        } else if (obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().hasData()) {
             return writeArrayBuffer(obj);
         } else if (obj->isObject() || obj->isArray()) {
             return traverseObject(obj);
         } else if (obj->isBoolean()) {
             return out.writePair(SCTAG_BOOLEAN_OBJECT, obj->asBoolean().unbox());
         } else if (obj->isNumber()) {
             return out.writePair(SCTAG_NUMBER_OBJECT, 0) &&
                    out.writeDouble(obj->asNumber().unbox());
@@ -942,17 +942,17 @@ JSStructuredCloneReader::readTypedArray(
 
 bool
 JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
 {
     JSObject *obj = ArrayBufferObject::create(context(), nbytes);
     if (!obj)
         return false;
     vp->setObject(*obj);
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     JS_ASSERT(buffer.byteLength() == nbytes);
     return in.readArray(buffer.dataPointer(), nbytes);
 }
 
 static size_t
 bytesPerTypedArrayElement(uint32_t arrayType)
 {
     switch (arrayType) {
@@ -984,17 +984,17 @@ JSStructuredCloneReader::readV1ArrayBuff
 {
     JS_ASSERT(arrayType <= TypedArray::TYPE_UINT8_CLAMPED);
 
     uint32_t nbytes = nelems * bytesPerTypedArrayElement(arrayType);
     JSObject *obj = ArrayBufferObject::create(context(), nbytes);
     if (!obj)
         return false;
     vp->setObject(*obj);
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     JS_ASSERT(buffer.byteLength() == nbytes);
 
     switch (arrayType) {
       case TypedArray::TYPE_INT8:
       case TypedArray::TYPE_UINT8:
       case TypedArray::TYPE_UINT8_CLAMPED:
         return in.readArray((uint8_t*) buffer.dataPointer(), nelems);
       case TypedArray::TYPE_INT16:
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -480,17 +480,17 @@ GetClassForProtoKey(JSProtoKey key)
       case JSProto_Int32Array:
       case JSProto_Uint32Array:
       case JSProto_Float32Array:
       case JSProto_Float64Array:
       case JSProto_Uint8ClampedArray:
         return &TypedArray::classes[key - JSProto_Int8Array];
 
       case JSProto_ArrayBuffer:
-        return &ArrayBufferClass;
+        return &ArrayBufferObject::class_;
 
       case JSProto_DataView:
         return &DataViewClass;
 
       case JSProto_ParallelArray:
         return &ParallelArrayObject::class_;
 
       default:
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1984,17 +1984,17 @@ JSObject::TradeGuts(JSContext *cx, JSObj
 
     /* 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.
      */
-    JS_ASSERT(!a->isArrayBuffer() && !b->isArrayBuffer());
+    JS_ASSERT(!a->is<ArrayBufferObject>() && !b->is<ArrayBufferObject>());
 
     /* Trade the guts of the objects. */
     const size_t size = a->tenuredSizeOfThis();
     if (size == b->tenuredSizeOfThis()) {
         /*
          * If the objects are the same size, then we make no assumptions about
          * whether they have dynamically allocated slots and instead just copy
          * them over wholesale.
@@ -5325,17 +5325,17 @@ JSObject::sizeOfExcludingThis(JSMallocSi
         sizes->slots = mallocSizeOf(slots);
 
     if (hasDynamicElements()) {
         js::ObjectElements *elements = getElementsHeader();
         if (JS_UNLIKELY(elements->isAsmJSArrayBuffer())) {
 #if defined (JS_CPU_X64)
             // On x64, ArrayBufferObject::prepareForAsmJS switches the
             // ArrayBufferObject to use mmap'd storage.
-            sizes->elementsAsmJSNonHeap = asArrayBuffer().byteLength();
+            sizes->elementsAsmJSNonHeap = as<ArrayBufferObject>().byteLength();
 #else
             sizes->elementsAsmJSHeap = mallocSizeOf(elements);
 #endif
         } else {
             sizes->elementsNonAsmJS = mallocSizeOf(elements);
         }
     }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -199,17 +199,16 @@ extern JSBool
 DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSBool *succeeded);
 
 extern JSBool
 DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, JSBool *succeeded);
 
 } /* namespace js::baseops */
 
 extern Class ArrayClass;
-extern Class ArrayBufferClass;
 extern Class BlockClass;
 extern Class BooleanClass;
 extern Class CallableObjectClass;
 extern Class DataViewClass;
 extern Class DateClass;
 extern Class ErrorClass;
 extern Class ElementIteratorClass;
 extern Class GeneratorClass;
@@ -974,17 +973,16 @@ class JSObject : public js::ObjectImpl
     template <class T>
     const T &as() const {
         JS_ASSERT(is<T>());
         return *static_cast<const T *>(this);
     }
 
     /* Direct subtypes of JSObject: */
     inline bool isArray()            const { return hasClass(&js::ArrayClass); }
-    inline bool isArrayBuffer()      const { return hasClass(&js::ArrayBufferClass); }
     inline bool isDataView()         const { return hasClass(&js::DataViewClass); }
     inline bool isDate()             const { return hasClass(&js::DateClass); }
     inline bool isElementIterator()  const { return hasClass(&js::ElementIteratorClass); }
     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 isMapIterator()      const { return hasClass(&js::MapIteratorClass); }
@@ -1016,17 +1014,16 @@ class JSObject : public js::ObjectImpl
     inline bool isString()  const { return hasClass(&js::StringClass); }
 
     /* Subtypes of Proxy. */
     inline bool isDebugScope()              const;
     inline bool isWrapper()                 const;
     inline bool isFunctionProxy()           const { return hasClass(&js::FunctionProxyClass); }
     inline bool isCrossCompartmentWrapper() const;
 
-    inline js::ArrayBufferObject &asArrayBuffer();
     inline js::BlockObject &asBlock();
     inline js::BooleanObject &asBoolean();
     inline js::CallObject &asCall();
     inline js::ClonedBlockObject &asClonedBlock();
     inline js::DataViewObject &asDataView();
     inline js::DeclEnvObject &asDeclEnv();
     inline js::DebugScopeObject &asDebugScope();
     inline js::GlobalObject &asGlobal();
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -921,17 +921,17 @@ JSObject::create(JSContext *cx, js::gc::
     obj->slots = slots;
     obj->elements = js::emptyObjectElements;
 
     const js::Class *clasp = type->clasp;
     if (clasp->hasPrivate())
         obj->privateRef(shape->numFixedSlots()) = NULL;
 
     size_t span = shape->slotSpan();
-    if (span && clasp != &js::ArrayBufferClass)
+    if (span && clasp != &js::ArrayBufferObject::class_)
         obj->initializeSlotRange(0, span);
 
     return obj;
 }
 
 /* static */ inline JSObject *
 JSObject::createArray(JSContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
                       js::HandleShape shape, js::HandleTypeObject type,
@@ -1681,17 +1681,17 @@ ObjectClassIs(HandleObject obj, ESClassV
         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_ArrayBuffer: return obj->isArrayBuffer();
+      case ESClass_ArrayBuffer: return obj->is<ArrayBufferObject>();
       case ESClass_Date: return obj->isDate();
     }
     JS_NOT_REACHED("bad classValue");
     return false;
 }
 
 inline bool
 IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx)
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -109,24 +109,24 @@ ToClampedIndex(JSContext *cx, const Valu
  * This class holds the underlying raw buffer that the TypedArray classes
  * access.  It can be created explicitly and passed to a TypedArray, or
  * can be created implicitly by constructing a TypedArray with a size.
  */
 
 JS_ALWAYS_INLINE bool
 IsArrayBuffer(const Value &v)
 {
-    return v.isObject() && v.toObject().hasClass(&ArrayBufferClass);
+    return v.isObject() && v.toObject().hasClass(&ArrayBufferObject::class_);
 }
 
 JS_ALWAYS_INLINE bool
 ArrayBufferObject::byteLengthGetterImpl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArrayBuffer(args.thisv()));
-    args.rval().setInt32(args.thisv().toObject().asArrayBuffer().byteLength());
+    args.rval().setInt32(args.thisv().toObject().as<ArrayBufferObject>().byteLength());
     return true;
 }
 
 JSBool
 ArrayBufferObject::byteLengthGetter(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsArrayBuffer, byteLengthGetterImpl>(cx, args);
@@ -135,33 +135,33 @@ ArrayBufferObject::byteLengthGetter(JSCo
 bool
 ArrayBufferObject::fun_slice_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArrayBuffer(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     // these are the default values
-    uint32_t length = thisObj->asArrayBuffer().byteLength();
+    uint32_t length = thisObj->as<ArrayBufferObject>().byteLength();
     uint32_t begin = 0, end = length;
 
     if (args.length() > 0) {
         if (!ToClampedIndex(cx, args[0], length, &begin))
             return false;
 
         if (args.length() > 1) {
             if (!ToClampedIndex(cx, args[1], length, &end))
                 return false;
         }
     }
 
     if (begin > end)
         begin = end;
 
-    JSObject *nobj = createSlice(cx, thisObj->asArrayBuffer(), begin, end);
+    JSObject *nobj = createSlice(cx, thisObj->as<ArrayBufferObject>(), begin, end);
     if (!nobj)
         return false;
     args.rval().setObject(*nobj);
     return true;
 }
 
 JSBool
 ArrayBufferObject::fun_slice(JSContext *cx, unsigned argc, Value *vp)
@@ -239,17 +239,17 @@ AllocateArrayBufferContents(JSContext *m
 bool
 ArrayBufferObject::allocateSlots(JSContext *maybecx, uint32_t bytes, uint8_t *contents)
 {
     /*
      * ArrayBufferObjects delegate added properties to another JSObject, so
      * their internal layout can use the object's fixed slots for storage.
      * Set up the object to look like an array with an elements header.
      */
-    JS_ASSERT(isArrayBuffer() && !hasDynamicSlots() && !hasDynamicElements());
+    JS_ASSERT(is<ArrayBufferObject>() && !hasDynamicSlots() && !hasDynamicElements());
 
     size_t usableSlots = ARRAYBUFFER_RESERVED_SLOTS - ObjectElements::VALUES_PER_HEADER;
 
     if (bytes > sizeof(Value) * usableSlots) {
         ObjectElements *header = AllocateArrayBufferContents(maybecx, bytes, contents);
         if (!header)
             return false;
         elements = header->elements();
@@ -407,17 +407,17 @@ ArrayBufferObject::prepareForAsmJS(JSCon
     newHeader->setIsAsmJSArrayBuffer();
     JS_ASSERT(data == buffer->dataPointer());
     return true;
 }
 
 void
 ArrayBufferObject::releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj)
 {
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     JS_ASSERT(buffer.isAsmJSArrayBuffer());
 
     uint8_t *p = buffer.dataPointer() - PageSize ;
     JS_ASSERT(uintptr_t(p) % PageSize == 0);
 # ifdef XP_WIN
     VirtualFree(p, 0, MEM_RELEASE);
 # else
     munmap(p, AsmJSMappedSize);
@@ -448,17 +448,17 @@ ArrayBufferObject::prepareForAsmJS(JSCon
 
     buffer->getElementsHeader()->setIsAsmJSArrayBuffer();
     return true;
 }
 
 void
 ArrayBufferObject::releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj)
 {
-    fop->free_(obj->asArrayBuffer().getElementsHeader());
+    fop->free_(obj->as<ArrayBufferObject>().getElementsHeader());
 }
 
 void
 ArrayBufferObject::neuterAsmJSArrayBuffer(ArrayBufferObject &buffer)
 {
     // TODO: be ever-so-slightly unsound (but safe) for now.
 }
 #endif
@@ -546,34 +546,34 @@ ArrayBufferObject::addView(JSObject *vie
     privateWriteBarrierPost((void**)views);
 }
 
 JSObject *
 ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, uint8_t *contents)
 {
     SkipRoot skip(cx, &contents);
 
-    RootedObject obj(cx, NewBuiltinClassInstance(cx, &ArrayBufferClass));
+    RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
     if (!obj)
         return NULL;
     JS_ASSERT_IF(obj->isTenured(), obj->tenuredGetAllocKind() == gc::FINALIZE_OBJECT16_BACKGROUND);
-    JS_ASSERT(obj->getClass() == &ArrayBufferClass);
-
-    js::Shape *empty = EmptyShape::getInitialShape(cx, &ArrayBufferClass,
+    JS_ASSERT(obj->getClass() == &class_);
+
+    js::Shape *empty = EmptyShape::getInitialShape(cx, &class_,
                                                    obj->getProto(), obj->getParent(), obj->getMetadata(),
                                                    gc::FINALIZE_OBJECT16_BACKGROUND);
     if (!empty)
         return NULL;
     obj->setLastPropertyInfallible(empty);
 
     /*
      * The beginning stores an ObjectElements header structure holding the
      * length. The rest of it is a flat data store for the array buffer.
      */
-    if (!obj->asArrayBuffer().allocateSlots(cx, nbytes, contents))
+    if (!obj->as<ArrayBufferObject>().allocateSlots(cx, nbytes, contents))
         return NULL;
 
     return obj;
 }
 
 JSObject *
 ArrayBufferObject::createSlice(JSContext *cx, ArrayBufferObject &arrayBuffer,
                                uint32_t begin, uint32_t end)
@@ -619,17 +619,17 @@ ArrayBufferObject::createDataViewForThis
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
 }
 
 bool
 ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
                                  uint8_t **data)
 {
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     JSObject *views = *GetViewList(&buffer);
     js::ObjectElements *header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
     if (buffer.hasDynamicElements() && !buffer.isAsmJSArrayBuffer()) {
         *GetViewList(&buffer) = NULL;
         *contents = header;
         *data = buffer.dataPointer();
 
         buffer.setFixedElements();
@@ -681,17 +681,17 @@ ArrayBufferObject::obj_trace(JSTracer *t
     // Instead, ArrayBuffers with a single view hold a strong pointer to the
     // view. This can entrain garbage when the single view becomes otherwise
     // unreachable while the buffer is still live, but this is expected to be
     // rare. ArrayBuffers with 0-1 views are expected to be by far the most
     // common cases. ArrayBuffers with multiple views are collected into a
     // linked list during collection, and then swept to prune out their dead
     // views.
 
-    HeapPtrObject *views = GetViewList(&obj->asArrayBuffer());
+    HeapPtrObject *views = GetViewList(&obj->as<ArrayBufferObject>());
     if (!*views)
         return;
 
     // During minor collections, these edges are normally kept alive by the
     // store buffer. If the store buffer overflows, fallback marking should
     // just treat these as strong references for simplicity.
     if (trc->runtime->isHeapMinorCollecting()) {
         MarkObject(trc, views, "arraybuffer.viewlist");
@@ -737,17 +737,17 @@ ArrayBufferObject::obj_trace(JSTracer *t
 void
 ArrayBufferObject::sweep(JSCompartment *compartment)
 {
     JSObject *buffer = compartment->gcLiveArrayBuffers;
     JS_ASSERT(buffer != UNSET_BUFFER_LINK);
     compartment->gcLiveArrayBuffers = NULL;
 
     while (buffer) {
-        HeapPtrObject *views = GetViewList(&buffer->asArrayBuffer());
+        HeapPtrObject *views = GetViewList(&buffer->as<ArrayBufferObject>());
         JS_ASSERT(*views);
 
         JSObject *nextBuffer = BufferLink(*views);
         JS_ASSERT(nextBuffer != UNSET_BUFFER_LINK);
         SetBufferLink(*views, UNSET_BUFFER_LINK);
 
         // Rebuild the list of views of the ArrayBuffer, discarding dead views.
         // If there is only one view, it will have already been marked.
@@ -771,51 +771,51 @@ ArrayBufferObject::sweep(JSCompartment *
 void
 ArrayBufferObject::resetArrayBufferList(JSCompartment *comp)
 {
     JSObject *buffer = comp->gcLiveArrayBuffers;
     JS_ASSERT(buffer != UNSET_BUFFER_LINK);
     comp->gcLiveArrayBuffers = NULL;
 
     while (buffer) {
-        JSObject *view = *GetViewList(&buffer->asArrayBuffer());
+        JSObject *view = *GetViewList(&buffer->as<ArrayBufferObject>());
         JS_ASSERT(view);
 
         JSObject *nextBuffer = BufferLink(view);
         JS_ASSERT(nextBuffer != UNSET_BUFFER_LINK);
 
         SetBufferLink(view, UNSET_BUFFER_LINK);
         buffer = nextBuffer;
     }
 }
 
 /* static */ bool
 ArrayBufferObject::saveArrayBufferList(JSCompartment *comp, ArrayBufferVector &vector)
 {
     JSObject *obj = comp->gcLiveArrayBuffers;
     while (obj) {
         JS_ASSERT(obj != UNSET_BUFFER_LINK);
-        ArrayBufferObject *buffer = &obj->asArrayBuffer();
+        ArrayBufferObject *buffer = &obj->as<ArrayBufferObject>();
         if (!vector.append(buffer))
             return false;
 
         JSObject *view = *GetViewList(buffer);
         JS_ASSERT(view);
         obj = BufferLink(view);
     }
     return true;
 }
 
 /* static */ void
 ArrayBufferObject::restoreArrayBufferLists(ArrayBufferVector &vector)
 {
     for (ArrayBufferObject **p = vector.begin(); p != vector.end(); p++) {
         ArrayBufferObject *buffer = *p;
         JSCompartment *comp = buffer->compartment();
-        JSObject *firstView = *GetViewList(&buffer->asArrayBuffer());
+        JSObject *firstView = *GetViewList(&buffer->as<ArrayBufferObject>());
         JS_ASSERT(firstView);
         JS_ASSERT(firstView->compartment() == comp);
         JS_ASSERT(BufferLink(firstView) == UNSET_BUFFER_LINK);
         SetBufferLink(firstView, comp->gcLiveArrayBuffers);
         comp->gcLiveArrayBuffers = buffer;
     }
 }
 
@@ -941,51 +941,51 @@ ArrayBufferObject::obj_defineSpecial(JSC
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
 }
 
 JSBool
 ArrayBufferObject::obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
                                   HandleId id, MutableHandleValue vp)
 {
-    JS_ASSERT(obj->isArrayBuffer());
+    JS_ASSERT(obj->is<ArrayBufferObject>());
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetProperty(cx, delegate, receiver, id, vp);
 }
 
 JSBool
 ArrayBufferObject::obj_getProperty(JSContext *cx, HandleObject obj,
                                    HandleObject receiver, HandlePropertyName name, MutableHandleValue vp)
 {
-    JS_ASSERT(obj->isArrayBuffer());
+    JS_ASSERT(obj->is<ArrayBufferObject>());
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     Rooted<jsid> id(cx, NameToId(name));
     return baseops::GetProperty(cx, delegate, receiver, id, vp);
 }
 
 JSBool
 ArrayBufferObject::obj_getElement(JSContext *cx, HandleObject obj,
                                   HandleObject receiver, uint32_t index, MutableHandleValue vp)
 {
-    JS_ASSERT(obj->isArrayBuffer());
+    JS_ASSERT(obj->is<ArrayBufferObject>());
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return baseops::GetElement(cx, delegate, receiver, index, vp);
 }
 
 JSBool
 ArrayBufferObject::obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver,
                                            uint32_t index, MutableHandleValue vp, bool *present)
 {
-    JS_ASSERT(obj->isArrayBuffer());
+    JS_ASSERT(obj->is<ArrayBufferObject>());
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
     return JSObject::getElementIfPresent(cx, delegate, receiver, index, vp, present);
 }
 
 JSBool
 ArrayBufferObject::obj_getSpecial(JSContext *cx, HandleObject obj,
@@ -1762,18 +1762,18 @@ class TypedArrayTemplate
         if (!obj)
             return NULL;
         JS_ASSERT_IF(obj->isTenured(),
                      obj->tenuredGetAllocKind() == gc::FINALIZE_OBJECT8_BACKGROUND);
 
         obj->setSlot(TYPE_SLOT, Int32Value(ArrayTypeID()));
         obj->setSlot(BUFFER_SLOT, ObjectValue(*bufobj));
 
-        JS_ASSERT(bufobj->isArrayBuffer());
-        Rooted<ArrayBufferObject *> buffer(cx, &bufobj->asArrayBuffer());
+        JS_ASSERT(bufobj->is<ArrayBufferObject>());
+        Rooted<ArrayBufferObject *> buffer(cx, &bufobj->as<ArrayBufferObject>());
 
         InitArrayBufferViewDataPointer(obj, buffer, byteOffset);
         obj->setSlot(LENGTH_SLOT, Int32Value(len));
         obj->setSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
         obj->setSlot(BYTELENGTH_SLOT, Int32Value(len * sizeof(NativeType)));
         obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(NULL));
         obj->setSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK));
 
@@ -1853,17 +1853,17 @@ class TypedArrayTemplate
         /*
          * (typedArray)
          * (type[] array)
          *
          * Otherwise create a new typed array and copy elements 0..len-1
          * properties from the object, treating it as some sort of array.
          * Note that offset and length will be ignored
          */
-        if (!UncheckedUnwrap(dataObj)->isArrayBuffer())
+        if (!UncheckedUnwrap(dataObj)->is<ArrayBufferObject>())
             return fromArray(cx, dataObj);
 
         /* (ArrayBuffer, [byteOffset, [length]]) */
         int32_t byteOffset = 0;
         int32_t length = -1;
 
         if (argc > 1) {
             if (!ToInt32(cx, argv[1], &byteOffset))
@@ -2123,17 +2123,17 @@ class TypedArrayTemplate
     fromBuffer(JSContext *cx, HandleObject bufobj, uint32_t byteOffset, int32_t lengthInt,
                HandleObject proto)
     {
         if (!ObjectClassIs(bufobj, ESClass_ArrayBuffer, cx)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
             return NULL; // must be arrayBuffer
         }
 
-        JS_ASSERT(bufobj->isArrayBuffer() || bufobj->isProxy());
+        JS_ASSERT(bufobj->is<ArrayBufferObject>() || bufobj->isProxy());
         if (bufobj->isProxy()) {
             /*
              * Normally, NonGenericMethodGuard handles the case of transparent
              * wrappers. However, we have a peculiar situation: we want to
              * construct the new typed array in the compartment of the buffer,
              * so that the typed array can point directly at their buffer's
              * data without crossing compartment boundaries. So we use the
              * machinery underlying NonGenericMethodGuard directly to proxy the
@@ -2141,17 +2141,17 @@ class TypedArrayTemplate
              * compartment for a view in the target compartment referencing the
              * ArrayBuffer in that same compartment.
              */
             JSObject *wrapped = CheckedUnwrap(bufobj);
             if (!wrapped) {
                 JS_ReportError(cx, "Permission denied to access object");
                 return NULL;
             }
-            if (wrapped->isArrayBuffer()) {
+            if (wrapped->is<ArrayBufferObject>()) {
                 /*
                  * And for even more fun, the new view's prototype should be
                  * set to the origin compartment's prototype object, not the
                  * target's (specifically, the actual view in the target
                  * compartment will use as its prototype a wrapper around the
                  * origin compartment's view.prototype object).
                  *
                  * Rather than hack some crazy solution together, implement
@@ -2176,22 +2176,22 @@ class TypedArrayTemplate
                 ag[2] = ObjectValue(*proto);
 
                 if (!Invoke(cx, ag))
                     return NULL;
                 return &ag.rval().toObject();
             }
         }
 
-        if (!bufobj->isArrayBuffer()) {
+        if (!bufobj->is<ArrayBufferObject>()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
             return NULL; // must be arrayBuffer
         }
 
-        ArrayBufferObject &buffer = bufobj->asArrayBuffer();
+        ArrayBufferObject &buffer = bufobj->as<ArrayBufferObject>();
 
         if (byteOffset > buffer.byteLength() || byteOffset % sizeof(NativeType) != 0) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
             return NULL; // invalid byteOffset
         }
 
         uint32_t len;
         if (lengthInt == -1) {
@@ -2698,23 +2698,23 @@ TypedArrayTemplate<double>::copyIndexToV
      * object-typed jsval.
      */
     vp.setDouble(JS_CANONICALIZE_NAN(val));
 }
 
 JSBool
 DataViewObject::construct(JSContext *cx, JSObject *bufobj, const CallArgs &args, HandleObject proto)
 {
-    if (!bufobj->isArrayBuffer()) {
+    if (!bufobj->is<ArrayBufferObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
                              "DataView", "ArrayBuffer", bufobj->getClass()->name);
         return false;
     }
 
-    Rooted<ArrayBufferObject*> buffer(cx, &bufobj->asArrayBuffer());
+    Rooted<ArrayBufferObject*> buffer(cx, &bufobj->as<ArrayBufferObject>());
     uint32_t bufferLength = buffer->byteLength();
     uint32_t byteOffset = 0;
     uint32_t byteLength = bufferLength;
 
     if (args.length() > 1) {
         if (!ToUint32(cx, args[1], &byteOffset))
             return false;
         if (byteOffset > INT32_MAX) {
@@ -2761,17 +2761,17 @@ JSBool
 DataViewObject::class_constructor(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     RootedObject bufobj(cx);
     if (!GetFirstArgumentAsObject(cx, args, "DataView constructor", &bufobj))
         return false;
 
-    if (bufobj->isWrapper() && UncheckedUnwrap(bufobj)->isArrayBuffer()) {
+    if (bufobj->isWrapper() && UncheckedUnwrap(bufobj)->is<ArrayBufferObject>()) {
         Rooted<GlobalObject*> global(cx, cx->compartment()->maybeGlobal());
         Rooted<JSObject*> proto(cx, global->getOrCreateDataViewPrototype(cx));
         if (!proto)
             return false;
 
         InvokeArgsGuard ag;
         if (!cx->stack.pushInvokeArgs(cx, args.length() + 1, &ag))
             return false;
@@ -3303,17 +3303,17 @@ Class ArrayBufferObject::protoClass = {
     JS_DeletePropertyStub,   /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
-Class js::ArrayBufferClass = {
+Class ArrayBufferObject::class_ = {
     "ArrayBuffer",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_IMPLEMENTS_BARRIERS |
     Class::NON_NATIVE |
     JSCLASS_HAS_RESERVED_SLOTS(ARRAYBUFFER_RESERVED_SLOTS) |
     JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayBuffer),
     JS_PropertyStub,         /* addProperty */
     JS_DeletePropertyStub,   /* delProperty */
@@ -3867,26 +3867,26 @@ js::IsTypedArrayConstructor(const Value 
     }
     JS_NOT_REACHED("unexpected typed array type");
     return false;
 }
 
 bool
 js::IsTypedArrayBuffer(const Value &v)
 {
-    return v.isObject() && v.toObject().isArrayBuffer();
+    return v.isObject() && v.toObject().is<ArrayBufferObject>();
 }
 
 /* JS Friend API */
 
 JS_FRIEND_API(JSBool)
 JS_IsArrayBufferObject(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
-    return obj ? obj->isArrayBuffer() : false;
+    return obj ? obj->is<ArrayBufferObject>() : false;
 }
 
 JS_FRIEND_API(JSBool)
 JS_IsTypedArrayObject(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     return obj ? obj->isTypedArray() : false;
 }
@@ -3897,26 +3897,26 @@ JS_IsArrayBufferViewObject(JSObject *obj
     obj = CheckedUnwrap(obj);
     return obj ? (obj->isTypedArray() || obj->isDataView()) : false;
 }
 
 JS_FRIEND_API(uint32_t)
 JS_GetArrayBufferByteLength(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
-    return obj ? obj->asArrayBuffer().byteLength() : 0;
+    return obj ? obj->as<ArrayBufferObject>().byteLength() : 0;
 }
 
 JS_FRIEND_API(uint8_t *)
 JS_GetArrayBufferData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return NULL;
-    ArrayBufferObject &buffer = obj->asArrayBuffer();
+    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
     if (!buffer.uninlineData(NULL))
         return NULL;
     return buffer.dataPointer();
 }
 
 JS_FRIEND_API(JSObject *)
 JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
 {
@@ -3927,17 +3927,17 @@ JS_NewArrayBuffer(JSContext *cx, uint32_
 JS_PUBLIC_API(JSObject *)
 JS_NewArrayBufferWithContents(JSContext *cx, void *contents)
 {
     JS_ASSERT(contents);
     JSObject *obj = ArrayBufferObject::create(cx, 0);
     if (!obj)
         return NULL;
     obj->setDynamicElements(reinterpret_cast<js::ObjectElements *>(contents));
-    JS_ASSERT(*GetViewList(&obj->asArrayBuffer()) == NULL);
+    JS_ASSERT(*GetViewList(&obj->as<ArrayBufferObject>()) == NULL);
     return obj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data)
 {
     js::ObjectElements *header = AllocateArrayBufferContents(cx, nbytes, NULL);
     if (!header)
@@ -3966,17 +3966,17 @@ JS_ReallocateArrayBufferContents(JSConte
 
 JS_PUBLIC_API(JSBool)
 JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
                             uint8_t **data)
 {
     if (!(obj = CheckedUnwrap(obj)))
         return false;
 
-    if (!obj->isArrayBuffer()) {
+    if (!obj->is<ArrayBufferObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
         return false;
     }
 
     if (!ArrayBufferObject::stealContents(cx, obj, contents, data))
         return false;
 
     return true;
@@ -4210,16 +4210,16 @@ JS_GetObjectAsArrayBufferView(JSObject *
     return obj;
 }
 
 JS_FRIEND_API(JSObject *)
 JS_GetObjectAsArrayBuffer(JSObject *obj, uint32_t *length, uint8_t **data)
 {
    if (!(obj = CheckedUnwrap(obj)))
        return NULL;
-    if (!obj->isArrayBuffer())
+    if (!obj->is<ArrayBufferObject>())
         return NULL;
 
-    *length = obj->asArrayBuffer().byteLength();
-    *data = obj->asArrayBuffer().dataPointer();
+    *length = obj->as<ArrayBufferObject>().byteLength();
+    *data = obj->as<ArrayBufferObject>().dataPointer();
 
     return obj;
 }
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -28,16 +28,18 @@ typedef Vector<ArrayBufferObject *, 0, S
  * implicitly by constructing a TypedArray with a size.
  */
 class ArrayBufferObject : public JSObject
 {
     static bool byteLengthGetterImpl(JSContext *cx, CallArgs args);
     static bool fun_slice_impl(JSContext *cx, CallArgs args);
 
   public:
+    static Class class_;
+
     static Class protoClass;
     static const JSFunctionSpec jsfuncs[];
 
     static JSBool byteLengthGetter(JSContext *cx, unsigned argc, Value *vp);
 
     static JSBool fun_slice(JSContext *cx, unsigned argc, Value *vp);
 
     static JSBool class_constructor(JSContext *cx, unsigned argc, Value *vp);
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -33,46 +33,39 @@ inline uint32_t
 js::ArrayBufferObject::getElementsHeaderInitializedLength(const js::ObjectElements *header)
 {
     return header->initializedLength;
 }
 
 inline uint32_t
 js::ArrayBufferObject::byteLength() const
 {
-    JS_ASSERT(isArrayBuffer());
+    JS_ASSERT(is<ArrayBufferObject>());
     return getElementsHeader()->initializedLength;
 }
 
 inline uint8_t *
 js::ArrayBufferObject::dataPointer() const
 {
     return (uint8_t *) elements;
 }
 
-inline js::ArrayBufferObject &
-JSObject::asArrayBuffer()
-{
-    JS_ASSERT(isArrayBuffer());
-    return *static_cast<js::ArrayBufferObject *>(this);
-}
-
 inline js::DataViewObject &
 JSObject::asDataView()
 {
     JS_ASSERT(isDataView());
     return *static_cast<js::DataViewObject *>(this);
 }
 
 namespace js {
 
 inline bool
 ArrayBufferObject::hasData() const
 {
-    return getClass() == &ArrayBufferClass;
+    return getClass() == &class_;
 }
 
 inline bool
 ArrayBufferObject::isAsmJSArrayBuffer() const
 {
     return getElementsHeader()->isAsmJSArrayBuffer();
 }
 
@@ -137,17 +130,17 @@ TypedArray::bufferValue(JSObject *obj)
 {
     JS_ASSERT(obj->isTypedArray());
     return obj->getFixedSlot(BUFFER_SLOT);
 }
 
 inline ArrayBufferObject *
 TypedArray::buffer(JSObject *obj)
 {
-    return &bufferValue(obj).toObject().asArrayBuffer();
+    return &bufferValue(obj).toObject().as<ArrayBufferObject>();
 }
 
 inline void *
 TypedArray::viewData(JSObject *obj)
 {
     JS_ASSERT(obj->isTypedArray());
     return (void *)obj->getPrivate(DATA_SLOT);
 }
@@ -198,17 +191,17 @@ class ArrayBufferViewByteOffsetRef : pub
         return false;
     }
 
     void mark(JSTracer *trc) {
         /* Update obj's private to point to the moved buffer's array data. */
         MarkObjectUnbarriered(trc, &obj, "TypedArray");
         HeapSlot &bufSlot = obj->getReservedSlotRef(BufferView::BUFFER_SLOT);
         gc::MarkSlot(trc, &bufSlot, "TypedArray::BUFFER_SLOT");
-        ArrayBufferObject &buf = bufSlot.toObject().asArrayBuffer();
+        ArrayBufferObject &buf = bufSlot.toObject().as<ArrayBufferObject>();
         int32_t offset = obj->getReservedSlot(BufferView::BYTEOFFSET_SLOT).toInt32();
         obj->initPrivate(buf.dataPointer() + offset);
     }
 };
 #endif
 
 static inline void
 InitArrayBufferViewDataPointer(JSObject *obj, ArrayBufferObject *buffer, size_t byteOffset)
@@ -265,31 +258,31 @@ DataViewObject::create(JSContext *cx, ui
             RootedScript script(cx, cx->stack.currentScript(&pc));
             if (script) {
                 if (!types::SetInitializerObjectType(cx, script, pc, obj, newKind))
                     return NULL;
             }
         }
     }
 
-    JS_ASSERT(arrayBuffer->isArrayBuffer());
+    JS_ASSERT(arrayBuffer->is<ArrayBufferObject>());
 
     DataViewObject &dvobj = obj->asDataView();
     dvobj.setFixedSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
     dvobj.setFixedSlot(BYTELENGTH_SLOT, Int32Value(byteLength));
     dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
     dvobj.setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(NULL));
     dvobj.setFixedSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK));
     InitArrayBufferViewDataPointer(obj, arrayBuffer, byteOffset);
     JS_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
 
     // Verify that the private slot is at the expected place
     JS_ASSERT(dvobj.numFixedSlots() == DATA_SLOT);
 
-    arrayBuffer->asArrayBuffer().addView(&dvobj);
+    arrayBuffer->as<ArrayBufferObject>().addView(&dvobj);
 
     return &dvobj;
 }
 
 inline uint32_t
 DataViewObject::byteLength()
 {
     JS_ASSERT(isDataView());
@@ -313,17 +306,17 @@ DataViewObject::dataPointer()
     JS_ASSERT(isDataView());
     return getPrivate();
 }
 
 inline ArrayBufferObject &
 DataViewObject::arrayBuffer()
 {
     JS_ASSERT(isDataView());
-    return getReservedSlot(BUFFER_SLOT).toObject().asArrayBuffer();
+    return getReservedSlot(BUFFER_SLOT).toObject().as<ArrayBufferObject>();
 }
 
 inline bool
 DataViewObject::hasBuffer() const
 {
     JS_ASSERT(isDataView());
     return getReservedSlot(BUFFER_SLOT).isObject();
 }
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -130,17 +130,17 @@ ProtoSetterImpl(JSContext *cx, CallArgs 
     }
 
     /*
      * Disallow mutating the [[Prototype]] of a proxy that wasn't simply
      * wrapping some other object.  Also disallow it on ArrayBuffer objects,
      * which due to their complicated delegate-object shenanigans can't easily
      * have a mutable [[Prototype]].
      */
-    if (obj->isProxy() || obj->isArrayBuffer()) {
+    if (obj->isProxy() || obj->is<ArrayBufferObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
                              "Object", "__proto__ setter",
                              obj->isProxy() ? "Proxy" : "ArrayBuffer");
         return false;
     }
 
     /* Do nothing if __proto__ isn't being set to an object or null. */
     if (args.length() == 0 || !args[0].isObjectOrNull()) {
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -509,17 +509,17 @@ DenseElementsHeader::defineElement(JSCon
     obj->elements[index].set(obj->asObjectPtr(), HeapSlot::Element, index, desc.value());
     *succeeded = true;
     return true;
 }
 
 JSObject *
 js::ArrayBufferDelegate(JSContext *cx, Handle<ObjectImpl*> obj)
 {
-    MOZ_ASSERT(obj->hasClass(&ArrayBufferClass));
+    MOZ_ASSERT(obj->hasClass(&ArrayBufferObject::class_));
     if (obj->getPrivate())
         return static_cast<JSObject *>(obj->getPrivate());
     JSObject *delegate = NewObjectWithGivenProto(cx, &ObjectClass, obj->getProto(), NULL);
     obj->setPrivateGCThing(delegate);
     return delegate;
 }
 
 template <typename T>