Backed out changeset 3b9852666565 (bug 664249) for possible orange r=killer
authorMichael Wu <mwu@mozilla.com>
Mon, 01 Aug 2011 21:20:01 -0700
changeset 74431 9bf13a8e7d3e8aa79f44ff5d9f8ea451d486bba3
parent 74417 3b9852666565460810853575b911052705ce2267
child 74432 18f4994c24cc29cda0768482028a6dcfdd93f235
push id235
push userbzbarsky@mozilla.com
push dateTue, 27 Sep 2011 17:13:04 +0000
treeherdermozilla-beta@2d1e082d176a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskiller
bugs664249
milestone8.0a1
backs out3b9852666565460810853575b911052705ce2267
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
Backed out changeset 3b9852666565 (bug 664249) for possible orange r=killer
js/src/jsclone.cpp
js/src/jsinterp.cpp
js/src/jstracer.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jstypedarrayinlines.h
js/src/methodjit/PolyIC.cpp
js/src/methodjit/TypedArrayIC.h
js/src/shell/js.cpp
js/src/tests/js1_8_5/extensions/typedarray.js
js/src/tracejit/Writer.cpp
js/src/tracejit/Writer.h
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -433,34 +433,34 @@ TagToArrayType(uint32_t tag)
 {
     JS_ASSERT(SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX);
     return tag - SCTAG_TYPED_ARRAY_MIN;
 }
 
 bool
 JSStructuredCloneWriter::writeTypedArray(JSObject *obj)
 {
-    JSObject *arr = TypedArray::getTypedArray(obj);
-    if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr)))
+    TypedArray *arr = TypedArray::fromJSObject(obj);
+    if (!out.writePair(ArrayTypeToTag(arr->type), arr->length))
         return false;
 
-    switch (TypedArray::getType(arr)) {
+    switch (arr->type) {
     case TypedArray::TYPE_INT8:
     case TypedArray::TYPE_UINT8:
     case TypedArray::TYPE_UINT8_CLAMPED:
-        return out.writeArray((const uint8_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr));
+        return out.writeArray((const uint8_t *) arr->data, arr->length);
     case TypedArray::TYPE_INT16:
     case TypedArray::TYPE_UINT16:
-        return out.writeArray((const uint16_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr));
+        return out.writeArray((const uint16_t *) arr->data, arr->length);
     case TypedArray::TYPE_INT32:
     case TypedArray::TYPE_UINT32:
     case TypedArray::TYPE_FLOAT32:
-        return out.writeArray((const uint32_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr));
+        return out.writeArray((const uint32_t *) arr->data, arr->length);
     case TypedArray::TYPE_FLOAT64:
-        return out.writeArray((const uint64_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr));
+        return out.writeArray((const uint64_t *) arr->data, arr->length);
     default:
         JS_NOT_REACHED("unknown TypedArray type");
         return false;
     }
 }
 
 bool
 JSStructuredCloneWriter::writeArrayBuffer(JSObject *obj)
@@ -656,33 +656,33 @@ bool
 JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp)
 {
     uint32_t atype = TagToArrayType(tag);
     JSObject *obj = js_CreateTypedArray(context(), atype, nelems);
     if (!obj)
         return false;
     vp->setObject(*obj);
 
-    JSObject *arr = TypedArray::getTypedArray(obj);
-    JS_ASSERT(TypedArray::getLength(arr) == nelems);
-    JS_ASSERT(TypedArray::getType(arr) == atype);
+    TypedArray *arr = TypedArray::fromJSObject(obj);
+    JS_ASSERT(arr->length == nelems);
+    JS_ASSERT(arr->type == atype);
     switch (atype) {
       case TypedArray::TYPE_INT8:
       case TypedArray::TYPE_UINT8:
       case TypedArray::TYPE_UINT8_CLAMPED:
-        return in.readArray((uint8_t *) TypedArray::getDataOffset(arr), nelems);
+        return in.readArray((uint8_t *) arr->data, nelems);
       case TypedArray::TYPE_INT16:
       case TypedArray::TYPE_UINT16:
-        return in.readArray((uint16_t *) TypedArray::getDataOffset(arr), nelems);
+        return in.readArray((uint16_t *) arr->data, nelems);
       case TypedArray::TYPE_INT32:
       case TypedArray::TYPE_UINT32:
       case TypedArray::TYPE_FLOAT32:
-        return in.readArray((uint32_t *) TypedArray::getDataOffset(arr), nelems);
+        return in.readArray((uint32_t *) arr->data, nelems);
       case TypedArray::TYPE_FLOAT64:
-        return in.readArray((uint64_t *) TypedArray::getDataOffset(arr), nelems);
+        return in.readArray((uint64_t *) arr->data, nelems);
       default:
         JS_NOT_REACHED("unknown TypedArray type");
         return false;
     }
 }
 
 bool
 JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -83,17 +83,16 @@
 #include "jsatominlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
 #include "jsprobes.h"
 #include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsopcodeinlines.h"
-#include "jstypedarrayinlines.h"
 
 #include "vm/Stack-inl.h"
 #include "vm/String-inl.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
@@ -3553,18 +3552,18 @@ BEGIN_CASE(JSOP_LENGTH)
                     JS_ASSERT(length < INT32_MAX);
                     regs.sp[-1].setInt32(int32_t(length));
                     len = JSOP_LENGTH_LENGTH;
                     DO_NEXT_OP(len);
                 }
             }
 
             if (js_IsTypedArray(obj)) {
-                JSObject *tarray = TypedArray::getTypedArray(obj);
-                regs.sp[-1].setInt32(TypedArray::getLength(tarray));
+                TypedArray *tarray = TypedArray::fromJSObject(obj);
+                regs.sp[-1].setNumber(tarray->length);
                 len = JSOP_LENGTH_LENGTH;
                 DO_NEXT_OP(len);
             }
         }
 
         i = -2;
         goto do_getprop_with_lval;
     }
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -86,17 +86,16 @@
 #include "jsfuninlines.h"
 #include "jsinterpinlines.h"
 #include "jspropertycacheinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jscntxtinlines.h"
 #include "jsopcodeinlines.h"
-#include "jstypedarrayinlines.h"
 
 #include "vm/Stack-inl.h"
 
 #ifdef JS_METHODJIT
 #include "methodjit/MethodJIT.h"
 #endif
 
 #include "tracejit/Writer-inl.h"
@@ -13193,38 +13192,32 @@ TraceRecorder::setElem(int lval_spindex,
                                              *cx->regs().pc == JSOP_INITELEM));
     } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) {
         // Fast path: assigning to element of typed array.
         VMSideExit* branchExit = snapshot(BRANCH_EXIT);
 
         // Ensure array is a typed array and is the same type as what was written
         guardClass(obj_ins, obj->getClass(), branchExit, LOAD_CONST);
 
-        JSObject* tarray = js::TypedArray::getTypedArray(obj);
+        js::TypedArray* tarray = js::TypedArray::fromJSObject(obj);
+
+        LIns* priv_ins = w.ldpObjPrivate(obj_ins);
 
         // The index was on the stack and is therefore a LIR float; force it to
         // be an integer.                              
         CHECK_STATUS_A(makeNumberInt32(idx_ins, &idx_ins));
 
-        LIns* slots_ins = w.ldpObjFixedSlots(obj_ins);
         // Ensure idx >= 0 && idx < length (by using uint32)
         CHECK_STATUS_A(guard(true,
-                             w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(slots_ins)),
+                             w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)),
                                     "inRange"),
                              OVERFLOW_EXIT, /* abortIfAlwaysExits = */true));
 
         // We're now ready to store
-        LIns* data_base_ins = w.ldpConstTypedArrayData(slots_ins);
-        LIns* offset_ins = w.ldiConstTypedArrayByteOffset(slots_ins);
-#ifdef NANOJIT_64BIT
-        LIns* data_ins = w.addp(data_base_ins, w.ui2uq(offset_ins));
-#else
-        LIns* data_ins = w.addp(data_base_ins, offset_ins);
-#endif
-
+        LIns* data_ins = w.ldpConstTypedArrayData(priv_ins);
         LIns* pidx_ins = w.ui2p(idx_ins);
         LIns* typed_v_ins = v_ins;
 
         // If it's not a number, convert objects to NaN,
         // null to 0, and call StringToNumber or BooleanOrUndefinedToNumber
         // for those.
         if (!v.isNumber()) {
             if (v.isNull()) {
@@ -13241,17 +13234,17 @@ TraceRecorder::setElem(int lval_spindex,
             } else if (v.isBoolean()) {
                 JS_ASSERT(v.isBoolean());
                 typed_v_ins = w.i2d(typed_v_ins);
             } else {
                 typed_v_ins = w.immd(js_NaN);
             }
         }
 
-        switch (js::TypedArray::getType(tarray)) {
+        switch (tarray->type) {
           case js::TypedArray::TYPE_INT8:
           case js::TypedArray::TYPE_INT16:
           case js::TypedArray::TYPE_INT32:
             typed_v_ins = d2i(typed_v_ins);
             break;
           case js::TypedArray::TYPE_UINT8:
           case js::TypedArray::TYPE_UINT16:
           case js::TypedArray::TYPE_UINT32:
@@ -13272,17 +13265,17 @@ TraceRecorder::setElem(int lval_spindex,
           case js::TypedArray::TYPE_FLOAT32:
           case js::TypedArray::TYPE_FLOAT64:
             // Do nothing, this is already a float
             break;
           default:
             JS_NOT_REACHED("Unknown typed array type in tracer");       
         }
 
-        switch (js::TypedArray::getType(tarray)) {
+        switch (tarray->type) {
           case js::TypedArray::TYPE_INT8:
           case js::TypedArray::TYPE_UINT8_CLAMPED:
           case js::TypedArray::TYPE_UINT8:
             w.sti2cTypedArrayElement(typed_v_ins, data_ins, pidx_ins);
             break;
           case js::TypedArray::TYPE_INT16:
           case js::TypedArray::TYPE_UINT16:
             w.sti2sTypedArrayElement(typed_v_ins, data_ins, pidx_ins);
@@ -14282,49 +14275,44 @@ TraceRecorder::typedArrayElement(Value& 
 
     JSObject* obj = &oval.toObject();
     LIns* obj_ins = get(&oval);
     jsint idx = ival.toInt32();
     LIns* idx_ins;
     CHECK_STATUS_A(makeNumberInt32(get(&ival), &idx_ins));
     LIns* pidx_ins = w.ui2p(idx_ins);
 
-    JSObject* tarray = js::TypedArray::getTypedArray(obj);
+    js::TypedArray* tarray = js::TypedArray::fromJSObject(obj);
     JS_ASSERT(tarray);
 
-    LIns *slots_ins = w.ldpObjFixedSlots(obj_ins);
+    /* priv_ins will load the TypedArray* */
+    LIns* priv_ins = w.ldpObjPrivate(obj_ins);
 
     /* Abort if out-of-range. */
-    if ((jsuint) idx >= js::TypedArray::getLength(tarray))
+    if ((jsuint) idx >= tarray->length)
         RETURN_STOP_A("out-of-range index on typed array");
 
     /*
      * Ensure idx < length
      *
      * NOTE! mLength is uint32, but it's guaranteed to fit in a Value
      * int, so we can treat it as either signed or unsigned.
      * If the index happens to be negative, when it's treated as
      * unsigned it'll be a very large int, and thus won't be less than
      * length.
      */
     guard(true,
-          w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(slots_ins)), "inRange"),
+          w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), "inRange"),
           BRANCH_EXIT);
 
     /* We are now ready to load.  Do a different type of load
      * depending on what type of thing we're loading. */
-    LIns* data_base_ins = w.ldpConstTypedArrayData(slots_ins);
-    LIns* offset_ins = w.ldiConstTypedArrayByteOffset(slots_ins);
-#ifdef NANOJIT_64BIT
-    LIns* data_ins = w.addp(data_base_ins, w.ui2uq(offset_ins));
-#else
-    LIns* data_ins = w.addp(data_base_ins, offset_ins);
-#endif
-
-    switch (js::TypedArray::getType(tarray)) {
+    LIns* data_ins = w.ldpConstTypedArrayData(priv_ins);
+
+    switch (tarray->type) {
       case js::TypedArray::TYPE_INT8:
         v_ins = w.i2d(w.ldc2iTypedArrayElement(data_ins, pidx_ins));
         break;
       case js::TypedArray::TYPE_UINT8:
       case js::TypedArray::TYPE_UINT8_CLAMPED:
         // i2d on purpose here:  it's safe, because an 8-bit uint is guaranteed
         // to fit in a 32-bit int, and i2d gets more optimization than ui2d.
         v_ins = w.i2d(w.lduc2uiTypedArrayElement(data_ins, pidx_ins));
@@ -16343,17 +16331,17 @@ TraceRecorder::record_JSOP_LENGTH()
             guard(true, w.leui(v_ins, w.immi(JSVAL_INT_MAX)), BRANCH_EXIT);
             v_ins = w.i2d(v_ins);
         } else {
             v_ins = w.ui2d(v_ins);
         }
     } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) {
         // Ensure array is a typed array and is the same type as what was written
         guardClass(obj_ins, obj->getClass(), snapshot(BRANCH_EXIT), LOAD_NORMAL);
-        v_ins = w.i2d(w.ldiConstTypedArrayLength(w.ldpObjFixedSlots(obj_ins)));
+        v_ins = w.i2d(w.ldiConstTypedArrayLength(w.ldpObjPrivate(obj_ins)));
     } else {
         if (!obj->isNative())
             RETURN_STOP_A("can't trace length property access on non-array, non-native object");
         return getProp(obj, obj_ins);
     }
     set(&l, v_ins);
     return ARECORD_CONTINUE;
 }
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -145,17 +145,17 @@ ArrayBuffer::class_constructor(JSContext
     JSObject *bufobj = create(cx, nbytes);
     if (!bufobj)
         return false;
     vp->setObject(*bufobj);
     return true;
 }
 
 static inline JSBool
-AllocateArrayBufferSlots(JSContext *cx, JSObject *obj, uint32 size)
+AllocateSlots(JSContext *cx, JSObject *obj, uint32 size)
 {
     uint32 bytes = size + sizeof(Value);
     if (size > sizeof(Value) * ARRAYBUFFER_RESERVED_SLOTS - sizeof(Value) ) {
         JS_ASSERT(!obj->hasSlotsArray());
         Value *tmpslots = (Value *)cx->calloc_(bytes);
         if (!tmpslots)
             return false;
         obj->setSlotsPtr(tmpslots);
@@ -199,17 +199,17 @@ ArrayBuffer::create(JSContext *cx, int32
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
         return NULL;
     }
 
     /*
      * The first 8 bytes hold the length.
      * The rest of it is a flat data store for the array buffer.
      */
-    if (!AllocateArrayBufferSlots(cx, obj, nbytes))
+    if (!AllocateSlots(cx, obj, nbytes))
         return NULL;
 
     JS_ASSERT(obj->getClass() == &ArrayBuffer::slowClass);
     obj->setSharedNonNativeMap();
     obj->clasp = &ArrayBuffer::fastClass;
     return obj;
 }
 
@@ -319,26 +319,26 @@ ArrayBuffer::obj_setProperty(JSContext *
         // since obj_getProperty will fetch it as a plain
         // property from the delegate.
         JSObject *delegate = DelegateObject(cx, obj);
         if (!delegate)
             return false;
 
         JSObject *oldDelegateProto = delegate->getProto();
 
-        if (!js_SetPropertyHelper(cx, delegate, id, 0, vp, strict))
+        if (!js_SetProperty(cx, delegate, id, vp, strict))
             return false;
 
         if (delegate->getProto() != oldDelegateProto) {
             // actual __proto__ was set and not a plain property called
             // __proto__
             if (!SetProto(cx, obj, vp->toObjectOrNull(), true)) {
                 // this can be caused for example by setting x.__proto__ = x
                 // restore delegate prototype chain
-                SetProto(cx, delegate, oldDelegateProto, true);
+                delegate->setProto(oldDelegateProto);
                 return false;
             }
         }
         return true;
     }
 
     JSObject *delegate = DelegateObject(cx, obj);
     if (!delegate)
@@ -407,131 +407,134 @@ ArrayBuffer::obj_typeOf(JSContext *cx, J
 /*
  * TypedArray
  *
  * The non-templated base class for the specific typed implementations.
  * This class holds all the member variables that are used by
  * the subclasses.
  */
 
-JSObject *
-TypedArray::getTypedArray(JSObject *obj)
+TypedArray *
+TypedArray::fromJSObject(JSObject *obj)
 {
     while (!js_IsTypedArray(obj))
         obj = obj->getProto();
-    return obj;
+    return reinterpret_cast<TypedArray*>(obj->getPrivate());
 }
 
 inline bool
-TypedArray::isArrayIndex(JSContext *cx, JSObject *obj, jsid id, jsuint *ip)
+TypedArray::isArrayIndex(JSContext *cx, jsid id, jsuint *ip)
 {
     jsuint index;
-    if (js_IdIsIndex(id, &index) && index < getLength(obj)) {
+    if (js_IdIsIndex(id, &index) && index < length) {
         if (ip)
             *ip = index;
         return true;
     }
 
     return false;
 }
 
-typedef Value (* TypedArrayPropertyGetter)(JSObject *tarray);
+typedef Value (* TypedArrayPropertyGetter)(TypedArray *tarray);
 
 template <TypedArrayPropertyGetter Get>
 class TypedArrayGetter {
   public:
     static inline bool get(JSContext *cx, JSObject *obj, jsid id, Value *vp) {
         do {
             if (js_IsTypedArray(obj)) {
-                JSObject *tarray = TypedArray::getTypedArray(obj);
+                TypedArray *tarray = TypedArray::fromJSObject(obj);
                 if (tarray)
                     *vp = Get(tarray);
                 return true;
             }
         } while ((obj = obj->getProto()) != NULL);
         return true;
     }
 };
 
-/*
- * For now (until slots directly hold data)
- * slots data element points to the JSObject representing the ArrayBuffer.
- */
 inline Value
-getBufferValue(JSObject *tarray)
+getBuffer(TypedArray *tarray)
 {
-    JSObject *buffer = TypedArray::getBuffer(tarray);
-    return ObjectValue(*buffer);
+    return ObjectValue(*tarray->bufferJS);
 }
 
 JSBool
 TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
-    return TypedArrayGetter<getBufferValue>::get(cx, obj, id, vp);
+    return TypedArrayGetter<getBuffer>::get(cx, obj, id, vp);
 }
 
 inline Value
-getByteOffsetValue(JSObject *tarray)
+getByteOffset(TypedArray *tarray)
 {
-    return Int32Value(TypedArray::getByteOffset(tarray));
+    return Int32Value(tarray->byteOffset);
 }
 
 JSBool
 TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
-    return TypedArrayGetter<getByteOffsetValue>::get(cx, obj, id, vp);
+    return TypedArrayGetter<getByteOffset>::get(cx, obj, id, vp);
 }
 
 inline Value
-getByteLengthValue(JSObject *tarray)
+getByteLength(TypedArray *tarray)
 {
-    return Int32Value(TypedArray::getByteLength(tarray));
+    return Int32Value(tarray->byteLength);
 }
 
 JSBool
 TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
-    return TypedArrayGetter<getByteLengthValue>::get(cx, obj, id, vp);
+    return TypedArrayGetter<getByteLength>::get(cx, obj, id, vp);
 }
 
 inline Value
-getLengthValue(JSObject *tarray)
+getLength(TypedArray *tarray)
 {
-    return Int32Value(TypedArray::getLength(tarray));
+    return Int32Value(tarray->length);
 }
 
 JSBool
 TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
-    return TypedArrayGetter<getLengthValue>::get(cx, obj, id, vp);
+    return TypedArrayGetter<getLength>::get(cx, obj, id, vp);
 }
 
 JSBool
 TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                                JSObject **objp, JSProperty **propp)
 {
-    JSObject *tarray = getTypedArray(obj);
+    TypedArray *tarray = fromJSObject(obj);
     JS_ASSERT(tarray);
 
-    if (isArrayIndex(cx, tarray, id)) {
+    if (tarray->isArrayIndex(cx, id)) {
         *propp = (JSProperty *) 1;  /* non-null to indicate found */
         *objp = obj;
         return true;
     }
 
     JSObject *proto = obj->getProto();
     if (!proto) {
         *objp = NULL;
         *propp = NULL;
         return true;
     }
 
     return proto->lookupProperty(cx, id, objp, propp);
 }
 
+void
+TypedArray::obj_trace(JSTracer *trc, JSObject *obj)
+{
+    TypedArray *tarray = fromJSObject(obj);
+    JS_ASSERT(tarray);
+    MarkObject(trc, *tarray->bufferJS, "typedarray.buffer");
+}
+
 JSBool
 TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp)
 {
     *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
               ? JSPROP_PERMANENT | JSPROP_READONLY
               : JSPROP_PERMANENT | JSPROP_ENUMERATE;
     return true;
 }
@@ -704,38 +707,31 @@ class TypedArrayTemplate
         return &TypedArray::slowClasses[ArrayTypeID()];
     }
 
     static inline Class *fastClass()
     {
         return &TypedArray::fastClasses[ArrayTypeID()];
     }
 
-    static void
-    obj_trace(JSTracer *trc, JSObject *obj)
-    {
-        JSObject *buffer = static_cast<JSObject*>(getBuffer(obj));
-        if (buffer)
-            MarkObject(trc, *buffer, "typedarray.buffer");
-    }
-
     static JSBool
     obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
     {
-        JSObject *tarray = getTypedArray(obj);
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
+        JS_ASSERT(tarray);
 
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
-            vp->setNumber(getLength(tarray));
+            vp->setNumber(tarray->length);
             return true;
         }
 
         jsuint index;
-        if (isArrayIndex(cx, tarray, id, &index)) {
+        if (tarray->isArrayIndex(cx, id, &index)) {
             // this inline function is specialized for each type
-            copyIndexToValue(cx, tarray, index, vp);
+            tarray->copyIndexToValue(cx, index, vp);
         } else {
             JSObject *obj2;
             JSProperty *prop;
             const Shape *shape;
 
             JSObject *proto = obj->getProto();
             if (!proto) {
                 vp->setUndefined();
@@ -756,43 +752,43 @@ class TypedArrayTemplate
         }
 
         return true;
     }
 
     static JSBool
     obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict)
     {
-        JSObject *tarray = getTypedArray(obj);
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
         JS_ASSERT(tarray);
 
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
-            vp->setNumber(getLength(tarray));
+            vp->setNumber(tarray->length);
             return true;
         }
 
         jsuint index;
         // We can't just chain to js_SetPropertyHelper, because we're not a normal object.
-        if (!isArrayIndex(cx, tarray, id, &index)) {
+        if (!tarray->isArrayIndex(cx, id, &index)) {
 #if 0
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_TYPED_ARRAY_BAD_INDEX);
             return false;
 #endif
             // Silent ignore is better than an exception here, because
             // at some point we may want to support other properties on
             // these objects.  This is especially true when these arrays
             // are used to implement HTML Canvas 2D's PixelArray objects,
             // which used to be plain old arrays.
             vp->setUndefined();
             return true;
         }
 
         if (vp->isInt32()) {
-            setIndex(tarray, index, NativeType(vp->toInt32()));
+            tarray->setIndex(index, NativeType(vp->toInt32()));
             return true;
         }
 
         jsdouble d;
 
         if (vp->isDouble()) {
             d = vp->toDouble();
         } else if (vp->isNull()) {
@@ -812,29 +808,29 @@ class TypedArrayTemplate
         }
 
         // If the array is an integer array, we only handle up to
         // 32-bit ints from this point on.  if we want to handle
         // 64-bit ints, we'll need some changes.
 
         // Assign based on characteristics of the destination type
         if (ArrayTypeIsFloatingPoint()) {
-            setIndex(tarray, index, NativeType(d));
+            tarray->setIndex(index, NativeType(d));
         } else if (ArrayTypeIsUnsigned()) {
             JS_ASSERT(sizeof(NativeType) <= 4);
             uint32 n = js_DoubleToECMAUint32(d);
-            setIndex(tarray, index, NativeType(n));
+            tarray->setIndex(index, NativeType(n));
         } else if (ArrayTypeID() == TypedArray::TYPE_UINT8_CLAMPED) {
             // The uint8_clamped type has a special rounding converter
             // for doubles.
-            setIndex(tarray, index, NativeType(d));
+            tarray->setIndex(index, NativeType(d));
         } else {
             JS_ASSERT(sizeof(NativeType) <= 4);
             int32 n = js_DoubleToECMAInt32(d);
-            setIndex(tarray, index, NativeType(n));
+            tarray->setIndex(index, NativeType(n));
         }
 
         return true;
     }
 
     static JSBool
     obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
                        PropertyOp getter, StrictPropertyOp setter, uintN attrs)
@@ -849,64 +845,64 @@ class TypedArrayTemplate
     static JSBool
     obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
     {
         if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
             rval->setBoolean(false);
             return true;
         }
 
-        JSObject *tarray = TypedArray::getTypedArray(obj);
+        TypedArray *tarray = TypedArray::fromJSObject(obj);
         JS_ASSERT(tarray);
 
-        if (isArrayIndex(cx, tarray, id)) {
+        if (tarray->isArrayIndex(cx, id)) {
             rval->setBoolean(false);
             return true;
         }
 
         rval->setBoolean(true);
         return true;
     }
 
     static JSBool
     obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                   Value *statep, jsid *idp)
     {
-        JSObject *tarray = getTypedArray(obj);
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
         JS_ASSERT(tarray);
 
         /*
          * Iteration is "length" (if JSENUMERATE_INIT_ALL), then [0, length).
          * *statep is JSVAL_TRUE if enumerating "length" and
          * JSVAL_TO_INT(index) when enumerating index.
          */
         switch (enum_op) {
           case JSENUMERATE_INIT_ALL:
             statep->setBoolean(true);
             if (idp)
-                *idp = ::INT_TO_JSID(getLength(tarray) + 1);
+                *idp = ::INT_TO_JSID(tarray->length + 1);
             break;
 
           case JSENUMERATE_INIT:
             statep->setInt32(0);
             if (idp)
-                *idp = ::INT_TO_JSID(getLength(tarray));
+                *idp = ::INT_TO_JSID(tarray->length);
             break;
 
           case JSENUMERATE_NEXT:
             if (statep->isTrue()) {
                 *idp = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
                 statep->setInt32(0);
             } else {
                 uint32 index = statep->toInt32();
-                if (index < getLength(tarray)) {
+                if (index < uint32(tarray->length)) {
                     *idp = ::INT_TO_JSID(index);
                     statep->setInt32(index + 1);
                 } else {
-                    JS_ASSERT(index == getLength(tarray));
+                    JS_ASSERT(index == tarray->length);
                     statep->setNull();
                 }
             }
             break;
 
           case JSENUMERATE_DESTROY:
             statep->setNull();
             break;
@@ -919,50 +915,28 @@ class TypedArrayTemplate
     obj_typeOf(JSContext *cx, JSObject *obj)
     {
         return JSTYPE_OBJECT;
     }
 
     static JSObject *
     createTypedArray(JSContext *cx, JSObject *bufobj, uint32 byteOffset, uint32 len)
     {
-        JS_ASSERT(bufobj->getClass() == &ArrayBuffer::fastClass);
         JSObject *obj = NewBuiltinClassInstance(cx, slowClass());
         if (!obj)
             return NULL;
 
-        obj->setSlot(FIELD_TYPE, Int32Value(ArrayTypeID()));
-
-        do {
-            obj->setSlot(FIELD_BUFFER, ObjectValue(*bufobj));
-            /*
-             * NOTE: unlike the earlier implementation where the 'data' pointed
-             * directly to the right offset in the ArrayBuffer
-             * this points to the base of the ArrayBuffer.
-             * getIndex is modified to get the right index.
-             *
-             * This is because on 64 bit systems the jsval.h Private API
-             * requires pointers stored in jsvals to be two-byte aligned.
-             * TM and JM both need a few extra instructions to add the offset.
-             */
-            obj->setSlot(FIELD_DATA, PrivateValue(ArrayBuffer::getDataOffset(bufobj)));
-        } while(0);
-
-        obj->setSlot(FIELD_LENGTH, Int32Value(len));
-        obj->setSlot(FIELD_BYTEOFFSET, Int32Value(byteOffset));
-        obj->setSlot(FIELD_BYTELENGTH, Int32Value(len * sizeof(NativeType)));
-
-        JS_ASSERT(ArrayBuffer::getByteLength(getBuffer(obj)) - getByteOffset(obj) >= getByteLength(obj));
-        JS_ASSERT(getByteOffset(obj) <= ArrayBuffer::getByteLength(getBuffer(obj)));
-        JS_ASSERT(ArrayBuffer::getDataOffset(getBuffer(obj)) <= getDataOffset(obj));
-        JS_ASSERT(getDataOffset(obj) <= offsetData(obj, ArrayBuffer::getByteLength(getBuffer(obj))));
+        ThisTypeArray *tarray = cx->new_<ThisTypeArray>(bufobj, byteOffset, len);
+        if (!tarray)
+            return NULL;
 
         JS_ASSERT(obj->getClass() == slowClass());
         obj->setSharedNonNativeMap();
         obj->clasp = fastClass();
+        obj->setPrivate(tarray);
 
         // FIXME Bug 599008: make it ok to call preventExtensions here.
         obj->flags |= JSObject::NOT_EXTENSIBLE;
 
         return obj;
     }
 
     /*
@@ -1003,26 +977,26 @@ class TypedArrayTemplate
                                  JSMSG_TYPED_ARRAY_BAD_ARGS);
             return NULL;
         }
 
         JSObject *dataObj = &argv[0].toObject();
 
         /* (typedArray) */
         if (js_IsTypedArray(dataObj)) {
-            JSObject *otherTypedArray = getTypedArray(dataObj);
+            TypedArray *otherTypedArray = TypedArray::fromJSObject(dataObj);
             JS_ASSERT(otherTypedArray);
 
-            uint32 len = getLength(otherTypedArray);
+            uint32 len = otherTypedArray->length;
             JSObject *bufobj = createBufferWithSizeAndCount(cx, len);
             if (!bufobj)
                 return NULL;
 
             JSObject *obj = createTypedArray(cx, bufobj, 0, len);
-            if (!obj || !copyFromTypedArray(cx, obj, otherTypedArray, 0))
+            if (!obj || !copyFrom(cx, obj, otherTypedArray, 0))
                 return NULL;
             return obj;
         }
 
         /* (obj, byteOffset, length). */
         int32_t byteOffset = -1;
         int32_t length = -1;
 
@@ -1045,37 +1019,45 @@ class TypedArrayTemplate
                 }
             }
         }
 
         /* (obj, byteOffset, length) */
         return createTypedArrayWithOffsetLength(cx, dataObj, byteOffset, length);
     }
 
+    static void
+    class_finalize(JSContext *cx, JSObject *obj)
+    {
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
+        if (tarray)
+            cx->delete_(tarray);
+    }
+
     /* subarray(start[, end]) */
     static JSBool
     fun_subarray(JSContext *cx, uintN argc, Value *vp)
     {
         JSObject *obj = ToObject(cx, &vp[1]);
         if (!obj)
             return false;
 
         if (obj->getClass() != fastClass()) {
             // someone tried to apply this subarray() to the wrong class
             ReportIncompatibleMethod(cx, vp, fastClass());
             return false;
         }
 
-        JSObject *tarray = getTypedArray(obj);
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
         if (!tarray)
             return true;
 
         // these are the default values
-        int32_t begin = 0, end = getLength(tarray);
-        int32_t length = int32(getLength(tarray));
+        int32_t begin = 0, end = tarray->length;
+        int32_t length = int32(tarray->length);
 
         if (argc > 0) {
             Value *argv = JS_ARGV(cx, vp);
             if (!ValueToInt32(cx, argv[0], &begin))
                 return false;
             if (begin < 0) {
                 begin += length;
                 if (begin < 0)
@@ -1116,29 +1098,29 @@ class TypedArrayTemplate
             return false;
 
         if (obj->getClass() != fastClass()) {
             // someone tried to apply this set() to the wrong class
             ReportIncompatibleMethod(cx, vp, fastClass());
             return false;
         }
 
-        JSObject *tarray = getTypedArray(obj);
+        ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
         if (!tarray)
             return true;
 
         // these are the default values
         int32_t off = 0;
 
         Value *argv = JS_ARGV(cx, vp);
         if (argc > 1) {
             if (!ValueToInt32(cx, argv[1], &off))
                 return false;
 
-            if (off < 0 || uint32_t(off) > getLength(tarray)) {
+            if (off < 0 || uint32_t(off) > tarray->length) {
                 // the given offset is bogus
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_TYPED_ARRAY_BAD_ARGS);
                 return false;
             }
         }
 
         uint32 offset(off);
@@ -1147,48 +1129,76 @@ class TypedArrayTemplate
         if (argc == 0 || !argv[0].isObject()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_TYPED_ARRAY_BAD_ARGS);
             return false;
         }
 
         JSObject *arg0 = argv[0].toObjectOrNull();
         if (js_IsTypedArray(arg0)) {
-            JSObject *src = TypedArray::getTypedArray(arg0);
+            TypedArray *src = TypedArray::fromJSObject(arg0);
             if (!src ||
-                getLength(src) > getLength(tarray) - offset)
+                src->length > tarray->length - offset)
             {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_TYPED_ARRAY_BAD_ARGS);
                 return false;
             }
 
-            if (!copyFromTypedArray(cx, obj, src, offset))
+            if (!copyFrom(cx, obj, src, offset))
                 return false;
         } else {
             jsuint len;
             if (!js_GetLengthProperty(cx, arg0, &len))
                 return false;
 
             // avoid overflow; we know that offset <= length
-            if (len > getLength(tarray) - offset) {
+            if (len > tarray->length - offset) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_TYPED_ARRAY_BAD_ARGS);
                 return false;
             }
 
-            if (!copyFromArray(cx, obj, arg0, len, offset))
+            if (!copyFrom(cx, obj, arg0, len, offset))
                 return false;
         }
 
         vp->setUndefined();
         return true;
     }
 
+    static ThisTypeArray *
+    fromJSObject(JSObject *obj)
+    {
+        JS_ASSERT(obj->getClass() == fastClass());
+        return reinterpret_cast<ThisTypeArray*>(obj->getPrivate());
+    }
+
   public:
+    TypedArrayTemplate(JSObject *bufobj, uint32 byteOffset, uint32 len)
+    {
+        JS_ASSERT(bufobj->getClass() == &ArrayBuffer::fastClass);
+
+        type = ArrayTypeID();
+        bufferJS = bufobj;
+        length = 0;
+
+        this->byteOffset = byteOffset;
+
+        JS_ASSERT(byteOffset <= ArrayBuffer::getByteLength(bufferJS));
+        this->data = offsetData(bufferJS, byteOffset);
+        JS_ASSERT(ArrayBuffer::getDataOffset(bufferJS) <= this->data);
+        JS_ASSERT(this->data <= offsetData(bufferJS, ArrayBuffer::getByteLength(bufferJS)));
+
+        this->byteLength = len * sizeof(NativeType);
+        JS_ASSERT(ArrayBuffer::getByteLength(bufferJS) - byteOffset >= this->byteLength);
+
+        this->length = len;
+    }
+
     static JSObject *
     createTypedArrayWithOffsetLength(JSContext *cx, JSObject *other,
                                      int32 byteOffsetInt, int32 lengthInt)
     {
         JS_ASSERT(!js_IsTypedArray(other));
 
         /* Handle creation from an ArrayBuffer not ArrayBuffer.prototype. */
         if (other->getClass() == &ArrayBuffer::fastClass) {
@@ -1239,54 +1249,54 @@ class TypedArrayTemplate
         if (!js_GetLengthProperty(cx, other, &len))
             return NULL;
 
         JSObject *bufobj = createBufferWithSizeAndCount(cx, len);
         if (!bufobj)
             return NULL;
 
         JSObject *obj = createTypedArray(cx, bufobj, 0, len);
-        if (!obj || !copyFromArray(cx, obj, other, len))
+        if (!obj || !copyFrom(cx, obj, other, len))
             return NULL;
         return obj;
     }
 
-    static const NativeType
-    getIndex(JSObject *obj, uint32 index)
+    const NativeType
+    getIndex(uint32 index) const
     {
-        return *(static_cast<const NativeType*>(getDataOffset(obj)) + index);
+        return *(static_cast<const NativeType*>(data) + index);
     }
 
-    static void
-    setIndex(JSObject *obj, uint32 index, NativeType val)
+    void
+    setIndex(uint32 index, NativeType val)
     {
-        *(static_cast<NativeType*>(getDataOffset(obj)) + index) = val;
+        *(static_cast<NativeType*>(data) + index) = val;
     }
 
-    static void copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp);
+    inline void copyIndexToValue(JSContext *cx, uint32 index, Value *vp);
 
     static JSObject *
-    createSubarray(JSContext *cx, JSObject *tarray, uint32 begin, uint32 end)
+    createSubarray(JSContext *cx, ThisTypeArray *tarray, uint32 begin, uint32 end)
     {
         JS_ASSERT(tarray);
 
         JS_ASSERT(0 <= begin);
-        JS_ASSERT(begin <= getLength(tarray));
+        JS_ASSERT(begin <= tarray->length);
         JS_ASSERT(0 <= end);
-        JS_ASSERT(end <= getLength(tarray));
+        JS_ASSERT(end <= tarray->length);
 
-        JSObject *bufobj = getBuffer(tarray);
+        JSObject *bufobj = tarray->bufferJS;
         JS_ASSERT(bufobj);
 
         JS_ASSERT(begin <= end);
         uint32 length = end - begin;
 
         JS_ASSERT(begin < UINT32_MAX / sizeof(NativeType));
-        JS_ASSERT(UINT32_MAX - begin * sizeof(NativeType) >= getByteOffset(tarray));
-        uint32 byteOffset = getByteOffset(tarray) + begin * sizeof(NativeType);
+        JS_ASSERT(UINT32_MAX - begin * sizeof(NativeType) >= tarray->byteOffset);
+        uint32 byteOffset = tarray->byteOffset + begin * sizeof(NativeType);
 
         return createTypedArray(cx, bufobj, byteOffset, length);
     }
 
   protected:
     static NativeType
     nativeFromValue(JSContext *cx, const Value &v)
     {
@@ -1312,25 +1322,25 @@ class TypedArrayTemplate
 
         if (ArrayTypeIsFloatingPoint())
             return NativeType(js_NaN);
 
         return NativeType(int32(0));
     }
 
     static bool
-    copyFromArray(JSContext *cx, JSObject *thisTypedArrayObj,
+    copyFrom(JSContext *cx, JSObject *thisTypedArrayObj,
              JSObject *ar, jsuint len, jsuint offset = 0)
     {
-        thisTypedArrayObj = getTypedArray(thisTypedArrayObj);
-        JS_ASSERT(thisTypedArrayObj);
+        ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj);
+        JS_ASSERT(thisTypedArray);
 
-        JS_ASSERT(offset <= getLength(thisTypedArrayObj));
-        JS_ASSERT(len <= getLength(thisTypedArrayObj) - offset);
-        NativeType *dest = static_cast<NativeType*>(getDataOffset(thisTypedArrayObj)) + offset;
+        JS_ASSERT(offset <= thisTypedArray->length);
+        JS_ASSERT(len <= thisTypedArray->length - offset);
+        NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset;
 
         if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) {
             JS_ASSERT(ar->getArrayLength() == len);
 
             const Value *src = ar->getDenseArrayElements();
 
             for (uintN i = 0; i < len; ++i)
                 *dest++ = nativeFromValue(cx, *src++);
@@ -1344,173 +1354,173 @@ class TypedArrayTemplate
                 *dest++ = nativeFromValue(cx, v);
             }
         }
 
         return true;
     }
 
     static bool
-    copyFromTypedArray(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *tarray, jsuint offset)
+    copyFrom(JSContext *cx, JSObject *thisTypedArrayObj, TypedArray *tarray, jsuint offset)
     {
-        thisTypedArrayObj = getTypedArray(thisTypedArrayObj);
-        JS_ASSERT(thisTypedArrayObj);
+        ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj);
+        JS_ASSERT(thisTypedArray);
 
-        JS_ASSERT(offset <= getLength(thisTypedArrayObj));
-        JS_ASSERT(getLength(tarray) <= getLength(thisTypedArrayObj) - offset);
-        if (getBuffer(tarray) == getBuffer(thisTypedArrayObj))
-            return copyFromWithOverlap(cx, thisTypedArrayObj, tarray, offset);
+        JS_ASSERT(offset <= thisTypedArray->length);
+        JS_ASSERT(tarray->length <= thisTypedArray->length - offset);
+        if (tarray->bufferJS == thisTypedArray->bufferJS)
+            return thisTypedArray->copyFromWithOverlap(cx, tarray, offset);
 
-        NativeType *dest = static_cast<NativeType*>((void*)getDataOffset(thisTypedArrayObj)) + offset;
+        NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset;
 
-        if (getType(tarray) == getType(thisTypedArrayObj)) {
-            memcpy(dest, getDataOffset(tarray), getByteLength(tarray));
+        if (tarray->type == thisTypedArray->type) {
+            memcpy(dest, tarray->data, tarray->byteLength);
             return true;
         }
 
-        uintN srclen = getLength(tarray);
-        switch (getType(tarray)) {
+        uintN srclen = tarray->length;
+        switch (tarray->type) {
           case TypedArray::TYPE_INT8: {
-            int8 *src = static_cast<int8*>(getDataOffset(tarray));
+            int8 *src = static_cast<int8*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT8:
           case TypedArray::TYPE_UINT8_CLAMPED: {
-            uint8 *src = static_cast<uint8*>(getDataOffset(tarray));
+            uint8 *src = static_cast<uint8*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_INT16: {
-            int16 *src = static_cast<int16*>(getDataOffset(tarray));
+            int16 *src = static_cast<int16*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT16: {
-            uint16 *src = static_cast<uint16*>(getDataOffset(tarray));
+            uint16 *src = static_cast<uint16*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_INT32: {
-            int32 *src = static_cast<int32*>(getDataOffset(tarray));
+            int32 *src = static_cast<int32*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT32: {
-            uint32 *src = static_cast<uint32*>(getDataOffset(tarray));
+            uint32 *src = static_cast<uint32*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_FLOAT32: {
-            float *src = static_cast<float*>(getDataOffset(tarray));
+            float *src = static_cast<float*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_FLOAT64: {
-            double *src = static_cast<double*>(getDataOffset(tarray));
+            double *src = static_cast<double*>(tarray->data);
             for (uintN i = 0; i < srclen; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           default:
             JS_NOT_REACHED("copyFrom with a TypedArray of unknown type");
             break;
         }
 
         return true;
     }
 
-    static bool
-    copyFromWithOverlap(JSContext *cx, JSObject *self, JSObject *tarray, jsuint offset)
+    bool
+    copyFromWithOverlap(JSContext *cx, TypedArray *tarray, jsuint offset)
     {
-        JS_ASSERT(offset <= getLength(self));
+        JS_ASSERT(offset <= length);
 
-        NativeType *dest = static_cast<NativeType*>(getDataOffset(self)) + offset;
+        NativeType *dest = static_cast<NativeType*>(data) + offset;
 
-        if (getType(tarray) == getType(self)) {
-            memmove(dest, getDataOffset(tarray), getByteLength(tarray));
+        if (tarray->type == type) {
+            memmove(dest, tarray->data, tarray->byteLength);
             return true;
         }
 
         // We have to make a copy of the source array here, since
         // there's overlap, and we have to convert types.
-        void *srcbuf = cx->malloc_(getLength(tarray));
+        void *srcbuf = cx->malloc_(tarray->byteLength);
         if (!srcbuf)
             return false;
-        memcpy(srcbuf, getDataOffset(tarray), getByteLength(tarray));
+        memcpy(srcbuf, tarray->data, tarray->byteLength);
 
-        switch (getType(tarray)) {
+        switch (tarray->type) {
           case TypedArray::TYPE_INT8: {
             int8 *src = (int8*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT8:
           case TypedArray::TYPE_UINT8_CLAMPED: {
             uint8 *src = (uint8*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_INT16: {
             int16 *src = (int16*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT16: {
             uint16 *src = (uint16*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_INT32: {
             int32 *src = (int32*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_UINT32: {
             uint32 *src = (uint32*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_FLOAT32: {
             float *src = (float*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           case TypedArray::TYPE_FLOAT64: {
             double *src = (double*) srcbuf;
-            for (uintN i = 0; i < getLength(tarray); ++i)
+            for (uintN i = 0; i < tarray->length; ++i)
                 *dest++ = NativeType(*src++);
             break;
           }
           default:
             JS_NOT_REACHED("copyFromWithOverlap with a TypedArray of unknown type");
             break;
         }
 
         UnwantedForeground::free_(srcbuf);
         return true;
     }
 
-    static void *
+    void *
     offsetData(JSObject *obj, uint32 offs) {
-        return (void*)(((uint8*)getDataOffset(obj)) + offs);
+        return (void*)(((uint8*)ArrayBuffer::getDataOffset(obj)) + offs);
     }
 
     static JSObject *
     createBufferWithSizeAndCount(JSContext *cx, uint32 count)
     {
         size_t size = sizeof(NativeType);
         if (size != 0 && count >= INT32_MAX / size) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@@ -1522,45 +1532,45 @@ class TypedArrayTemplate
         return ArrayBuffer::create(cx, bytelen);
     }
 };
 
 // this default implementation is only valid for integer types
 // less than 32-bits in size.
 template<typename NativeType>
 void
-TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
+TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp)
 {
     JS_STATIC_ASSERT(sizeof(NativeType) < 4);
 
-    vp->setInt32(getIndex(tarray, index));
+    vp->setInt32(getIndex(index));
 }
 
 // and we need to specialize for 32-bit integers and floats
 template<>
 void
-TypedArrayTemplate<int32>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
+TypedArrayTemplate<int32>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp)
 {
-    int32 val = getIndex(tarray, index);
+    int32 val = getIndex(index);
     vp->setInt32(val);
 }
 
 template<>
 void
-TypedArrayTemplate<uint32>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
+TypedArrayTemplate<uint32>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp)
 {
-    uint32 val = getIndex(tarray, index);
+    uint32 val = getIndex(index);
     vp->setNumber(val);
 }
 
 template<>
 void
-TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
+TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp)
 {
-    float val = getIndex(tarray, index);
+    float val = getIndex(index);
     double dval = val;
 
     /*
      * Doubles in typed arrays could be typed-punned arrays of integers. This
      * could allow user code to break the engine-wide invariant that only
      * canonical nans are stored into jsvals, which means user code could
      * confuse the engine into interpreting a double-typed jsval as an
      * object-typed jsval.
@@ -1571,19 +1581,19 @@ TypedArrayTemplate<float>::copyIndexToVa
     if (JS_UNLIKELY(JSDOUBLE_IS_NaN(dval)))
         dval = js_NaN;
 
     vp->setDouble(dval);
 }
 
 template<>
 void
-TypedArrayTemplate<double>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
+TypedArrayTemplate<double>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp)
 {
-    double val = getIndex(tarray, index);
+    double val = getIndex(index);
 
     /*
      * Doubles in typed arrays could be typed-punned arrays of integers. This
      * could allow user code to break the engine-wide invariant that only
      * canonical nans are stored into jsvals, which means user code could
      * confuse the engine into interpreting a double-typed jsval as an
      * object-typed jsval.
      */
@@ -1681,56 +1691,54 @@ JSPropertySpec TypedArray::jsprops[] = {
 };
 
 /*
  * TypedArray boilerplate
  */
 
 #define IMPL_TYPED_ARRAY_STATICS(_typedArray)                                  \
 template<> JSFunctionSpec _typedArray::jsfuncs[] = {                           \
-    JS_FN("subarray", _typedArray::fun_subarray, 2, JSFUN_GENERIC_NATIVE),     \
-    JS_FN("set", _typedArray::fun_set, 2, JSFUN_GENERIC_NATIVE),               \
+    JS_FN("subarray", _typedArray::fun_subarray, 2, 0),                            \
+    JS_FN("set", _typedArray::fun_set, 2, 0),                                  \
     JS_FS_END                                                                  \
 }
 
 #define IMPL_TYPED_ARRAY_SLOW_CLASS(_typedArray)                               \
 {                                                                              \
     #_typedArray,                                                              \
-    JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) |                        \
-    JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray),                           \
+    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray),     \
     PropertyStub,         /* addProperty */                                    \
     PropertyStub,         /* delProperty */                                    \
     PropertyStub,         /* getProperty */                                    \
     StrictPropertyStub,   /* setProperty */                                    \
     EnumerateStub,                                                             \
     ResolveStub,                                                               \
     ConvertStub,                                                               \
     FinalizeStub                                                               \
 }
 
 #define IMPL_TYPED_ARRAY_FAST_CLASS(_typedArray)                               \
 {                                                                              \
     #_typedArray,                                                              \
-    JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) |                        \
-    Class::NON_NATIVE,                                                         \
+    Class::NON_NATIVE | JSCLASS_HAS_PRIVATE,                                   \
     PropertyStub,         /* addProperty */                                    \
     PropertyStub,         /* delProperty */                                    \
     PropertyStub,         /* getProperty */                                    \
     StrictPropertyStub,   /* setProperty */                                    \
     EnumerateStub,                                                             \
     ResolveStub,                                                               \
     ConvertStub,                                                               \
-    NULL,           /* finalize    */                                          \
+    _typedArray::class_finalize,                                               \
     NULL,           /* reserved0   */                                          \
     NULL,           /* checkAccess */                                          \
     NULL,           /* call        */                                          \
     NULL,           /* construct   */                                          \
     NULL,           /* xdrObject   */                                          \
     NULL,           /* hasInstance */                                          \
-    _typedArray::obj_trace,           /* trace       */                                          \
+    _typedArray::obj_trace,                                                    \
     JS_NULL_CLASS_EXT,                                                         \
     {                                                                          \
         _typedArray::obj_lookupProperty,                                       \
         _typedArray::obj_defineProperty,                                       \
         _typedArray::obj_getProperty,                                          \
         _typedArray::obj_setProperty,                                          \
         _typedArray::obj_getAttributes,                                        \
         _typedArray::obj_setAttributes,                                        \
@@ -1760,16 +1768,17 @@ do {                                    
                            JSPROP_PERMANENT | JSPROP_READONLY) ||              \
         !JS_DefineProperty(cx, proto, "BYTES_PER_ELEMENT",                     \
                            INT_TO_JSVAL(sizeof(_typedArray::ThisType)),        \
                            JS_PropertyStub, JS_StrictPropertyStub,             \
                            JSPROP_PERMANENT | JSPROP_READONLY))                \
     {                                                                          \
         return NULL;                                                           \
     }                                                                          \
+    proto->setPrivate(0);                                                      \
 } while (0)
 
 IMPL_TYPED_ARRAY_STATICS(Int8Array);
 IMPL_TYPED_ARRAY_STATICS(Uint8Array);
 IMPL_TYPED_ARRAY_STATICS(Int16Array);
 IMPL_TYPED_ARRAY_STATICS(Uint16Array);
 IMPL_TYPED_ARRAY_STATICS(Int32Array);
 IMPL_TYPED_ARRAY_STATICS(Uint32Array);
@@ -1831,17 +1840,17 @@ js_InitTypedArrayClasses(JSContext *cx, 
 
     proto->setPrivate(NULL);
 
     /*
      * Initialize the slots to hold the length as 0
      * This is required otherwise the length of a
      * ArrayBuffer's prototype is undefined.
      */
-    if (!AllocateArrayBufferSlots(cx, proto, 0))
+    if (!AllocateSlots(cx, proto, 0))
         return NULL;
     return proto;
 }
 
 JS_FRIEND_API(JSBool)
 js_IsArrayBuffer(JSObject *obj)
 {
     JS_ASSERT(obj);
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -136,64 +136,62 @@ struct JS_FRIEND_API(TypedArray) {
          * Special type that's a uint8, but assignments are clamped to 0 .. 255.
          * Treat the raw data type as a uint8.
          */
         TYPE_UINT8_CLAMPED,
 
         TYPE_MAX
     };
 
-    enum {
-        FIELD_LENGTH = 0,
-        FIELD_BYTEOFFSET,
-        FIELD_BYTELENGTH,
-        FIELD_TYPE,
-        FIELD_BUFFER,
-        FIELD_DATA,
-        FIELD_MAX
-    };
-
     // and MUST NOT be used to construct new objects.
     static Class fastClasses[TYPE_MAX];
 
     // These are the slow/original classes, used
     // fo constructing new objects
     static Class slowClasses[TYPE_MAX];
 
     static JSPropertySpec jsprops[];
 
-    static JSObject *getTypedArray(JSObject *obj);
+    static TypedArray *fromJSObject(JSObject *obj);
 
     static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 
     static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                                      JSObject **objp, JSProperty **propp);
 
+    static void obj_trace(JSTracer *trc, JSObject *obj);
+
     static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
     static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
-    static JSUint32 getLength(JSObject *obj);
-    static JSUint32 getByteOffset(JSObject *obj);
-    static JSUint32 getByteLength(JSObject *obj);
-    static JSUint32 getType(JSObject *obj);
-    static JSObject * getBuffer(JSObject *obj);
-    static void * getDataOffset(JSObject *obj);
-
+    static int32 lengthOffset() { return offsetof(TypedArray, length); }
+    static int32 dataOffset() { return offsetof(TypedArray, data); }
+    static int32 typeOffset() { return offsetof(TypedArray, type); }
     static void *offsetData(JSObject *obj, uint32 offs);
 
   public:
-    static bool
-    isArrayIndex(JSContext *cx, JSObject *obj, jsid id, jsuint *ip = NULL);
+    TypedArray() : bufferJS(0) { }
+
+    bool isArrayIndex(JSContext *cx, jsid id, jsuint *ip = NULL);
+    bool valid() { return bufferJS != 0; }
 
-    static inline int slotWidth(JSObject *obj) {
-        switch (getType(obj)) {
+    JSObject *bufferJS;
+    uint32 byteOffset;
+    uint32 byteLength;
+    uint32 length;
+    uint32 type;
+
+    void *data;
+
+    inline int slotWidth() const {
+        switch (type) {
           case js::TypedArray::TYPE_INT8:
           case js::TypedArray::TYPE_UINT8:
           case js::TypedArray::TYPE_UINT8_CLAMPED:
             return 1;
           case js::TypedArray::TYPE_INT16:
           case js::TypedArray::TYPE_UINT16:
             return 2;
           case js::TypedArray::TYPE_INT32:
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -51,40 +51,10 @@ ArrayBuffer::getByteLength(JSObject *obj
     return *((JSUint32*) obj->getSlotsPtr());
 }
 
 inline uint8 *
 ArrayBuffer::getDataOffset(JSObject *obj) {
     uint64 *base = ((uint64*)obj->getSlotsPtr()) + 1;
     return (uint8*) base;
 }
-
-inline JSUint32
-TypedArray::getLength(JSObject *obj) {
-    return obj->getSlot(FIELD_LENGTH).toInt32();
-}
-
-inline JSUint32
-TypedArray::getByteOffset(JSObject *obj) {
-    return obj->getSlot(FIELD_BYTEOFFSET).toInt32();
-}
-
-inline JSUint32
-TypedArray::getByteLength(JSObject *obj) {
-    return obj->getSlot(FIELD_BYTELENGTH).toInt32();
-}
-
-inline JSUint32
-TypedArray::getType(JSObject *obj) {
-    return obj->getSlot(FIELD_TYPE).toInt32();
-}
-
-inline JSObject *
-TypedArray::getBuffer(JSObject *obj) {
-    return &obj->getSlot(FIELD_BUFFER).toObject();
-}
-
-inline void *
-TypedArray::getDataOffset(JSObject *obj) {
-    return (void *)((uint8*)obj->getSlot(FIELD_DATA).toPrivate() + getByteOffset(obj));
-}
 }
 #endif /* jstypedarrayinlines_h */
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -2462,39 +2462,33 @@ GetElementIC::attachTypedArray(JSContext
     JS_ASSERT(hasInlineTypeGuard() || idRemat.knownType() == JSVAL_TYPE_INT32);
 
     Assembler masm;
 
     // Guard on this typed array's clasp.
     Jump claspGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass());
 
     // Get the internal typed array.
-    masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg);
+    masm.loadPtr(Address(objReg, offsetof(JSObject, privateData)), objReg);
 
     // Bounds check.
     Jump outOfBounds;
-    Address typedArrayLength(objReg, sizeof(uint64) * js::TypedArray::FIELD_LENGTH);
-    typedArrayLength = masm.payloadOf(typedArrayLength);
+    Address typedArrayLength(objReg, js::TypedArray::lengthOffset());
     if (idRemat.isConstant()) {
         JS_ASSERT(idRemat.value().toInt32() == v.toInt32());
         outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, Imm32(v.toInt32()));
     } else {
         outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, idRemat.dataReg());
     }
 
     // Load the array's packed data vector.
-    Address data_base(objReg, sizeof(Value) * js::TypedArray::FIELD_DATA);
-    masm.loadPrivate(data_base, objReg);
-
-    JSObject *tarray = js::TypedArray::getTypedArray(obj);
-    int shift = js::TypedArray::slotWidth(tarray);
-
-    int byteOffset = js::TypedArray::getByteOffset(tarray);
-    masm.addPtr(Imm32(byteOffset), objReg);
-
+    masm.loadPtr(Address(objReg, js::TypedArray::dataOffset()), objReg);
+
+    js::TypedArray *tarray = js::TypedArray::fromJSObject(obj);
+    int shift = tarray->slotWidth();
     if (idRemat.isConstant()) {
         int32 index = v.toInt32();
         Address addr(objReg, index * shift);
         LoadFromTypedArray(masm, tarray, addr, typeReg, objReg);
     } else {
         Assembler::Scale scale = Assembler::TimesOne;
         switch (shift) {
           case 2:
@@ -2805,41 +2799,36 @@ SetElementIC::attachHoleStub(JSContext *
 #if defined JS_POLYIC_TYPED_ARRAY
 LookupStatus
 SetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, int32 key)
 {
     // Right now, only one clasp guard extension is supported.
     JS_ASSERT(!inlineClaspGuardPatched);
 
     Assembler masm;
-    //masm.breakpoint();
 
     // Guard on this typed array's clasp.
     Jump claspGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass());
 
     // Get the internal typed array.
-    masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg);
+    masm.loadPtr(Address(objReg, offsetof(JSObject, privateData)), objReg);
 
     // Bounds check.
     Jump outOfBounds;
-    Address typedArrayLength(objReg, sizeof(uint64) * js::TypedArray::FIELD_LENGTH);
-    typedArrayLength = masm.payloadOf(typedArrayLength);
+    Address typedArrayLength(objReg, js::TypedArray::lengthOffset());
     if (hasConstantKey)
         outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, Imm32(keyValue));
     else
         outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, keyReg);
 
     // Load the array's packed data vector.
-    JSObject *tarray = js::TypedArray::getTypedArray(obj);
-    int byteOffset = js::TypedArray::getByteOffset(tarray);
-    Address base_data(objReg, sizeof(uint64) * js::TypedArray::FIELD_DATA);
-    masm.loadPrivate(base_data, objReg);
-    masm.addPtr(Imm32(byteOffset), objReg);
-
-    int shift = js::TypedArray::slotWidth(obj);
+    js::TypedArray *tarray = js::TypedArray::fromJSObject(obj);
+    masm.loadPtr(Address(objReg, js::TypedArray::dataOffset()), objReg);
+
+    int shift = tarray->slotWidth();
     if (hasConstantKey) {
         Address addr(objReg, keyValue * shift);
         if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask))
             return error(cx);
     } else {
         Assembler::Scale scale = Assembler::TimesOne;
         switch (shift) {
           case 2:
--- a/js/src/methodjit/TypedArrayIC.h
+++ b/js/src/methodjit/TypedArrayIC.h
@@ -39,35 +39,34 @@
 
 #ifndef js_typedarray_ic_h___
 #define js_typedarray_ic_h___
 
 #include "jscntxt.h"
 #include "jstypedarray.h"
 
 #include "jsnuminlines.h"
-#include "jstypedarrayinlines.h"
 
 namespace js {
 namespace mjit {
 
 #ifdef JS_POLYIC_TYPED_ARRAY
 
 typedef JSC::MacroAssembler::RegisterID RegisterID;
 typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
 typedef JSC::MacroAssembler::Jump Jump;
 typedef JSC::MacroAssembler::Imm32 Imm32;
 typedef JSC::MacroAssembler::ImmDouble ImmDouble;
 
 template <typename T>
 static void
-LoadFromTypedArray(Assembler &masm, JSObject *tarray, T address,
+LoadFromTypedArray(Assembler &masm, js::TypedArray *tarray, T address,
                    RegisterID typeReg, RegisterID dataReg)
 {
-    switch (TypedArray::getType(tarray)) {
+    switch (tarray->type) {
       case js::TypedArray::TYPE_INT8:
         masm.load8SignExtend(address, dataReg);
         masm.move(ImmType(JSVAL_TYPE_INT32), typeReg);
         break;
       case js::TypedArray::TYPE_UINT8:
       case js::TypedArray::TYPE_UINT8_CLAMPED:
         masm.load8ZeroExtend(address, dataReg);
         masm.move(ImmType(JSVAL_TYPE_INT32), typeReg);
@@ -92,17 +91,17 @@ LoadFromTypedArray(Assembler &masm, JSOb
         masm.convertUInt32ToDouble(dataReg, FPRegisters::First);
         masm.breakDouble(FPRegisters::First, typeReg, dataReg);
         safeInt.linkTo(masm.label(), &masm);
         break;
       }
       case js::TypedArray::TYPE_FLOAT32:
       case js::TypedArray::TYPE_FLOAT64:
       {
-        if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32)
+        if (tarray->type == js::TypedArray::TYPE_FLOAT32)
             masm.loadFloat(address, FPRegisters::First);
         else
             masm.loadDouble(address, FPRegisters::First);
         // Make sure NaN gets canonicalized.
         Jump notNaN = masm.branchDouble(Assembler::DoubleEqual,
                                         FPRegisters::First,
                                         FPRegisters::First);
         masm.loadStaticDouble(&js_NaN, FPRegisters::First, dataReg);
@@ -159,17 +158,17 @@ ClampIntForUint8Array(int32 x)
     if (x < 0)
         return 0;
     if (x > 255)
         return 255;
     return x;
 }
 
 static inline bool
-ConstantFoldForIntArray(JSContext *cx, JSObject *tarray, ValueRemat *vr)
+ConstantFoldForIntArray(JSContext *cx, js::TypedArray *tarray, ValueRemat *vr)
 {
     if (!vr->isTypeKnown())
         return true;
 
     // Objects and undefined coerce to NaN, which coerces to 0.
     // Null converts to 0.
     if (vr->knownType() == JSVAL_TYPE_OBJECT ||
         vr->knownType() == JSVAL_TYPE_UNDEFINED ||
@@ -187,39 +186,39 @@ ConstantFoldForIntArray(JSContext *cx, J
         double d;
         if (!StringToNumberType<double>(cx, v.toString(), &d))
             return false;
         v.setNumber(d);
     }
 
     int32 i32 = 0;
     if (v.isDouble()) {
-        i32 = (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED)
+        i32 = (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED)
               ? js_TypedArray_uint8_clamp_double(v.toDouble())
               : js_DoubleToECMAInt32(v.toDouble());
     } else if (v.isInt32()) {
         i32 = v.toInt32();
-        if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED)
+        if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED)
             i32 = ClampIntForUint8Array(i32);
     } else if (v.isBoolean()) {
         i32 = v.toBoolean() ? 1 : 0;
     } else {
         JS_NOT_REACHED("unknown constant type");
     }
 
     *vr = ValueRemat::FromConstant(Int32Value(i32));
 
     return true;
 }
 
 template <typename S, typename T>
 static void
-StoreToIntArray(Assembler &masm, JSObject *tarray, S src, T address)
+StoreToIntArray(Assembler &masm, js::TypedArray *tarray, S src, T address)
 {
-    switch (TypedArray::getType(tarray)) {
+    switch (tarray->type) {
       case js::TypedArray::TYPE_INT8:
       case js::TypedArray::TYPE_UINT8:
       case js::TypedArray::TYPE_UINT8_CLAMPED:
         masm.store8(src, address);
         break;
       case js::TypedArray::TYPE_INT16:
       case js::TypedArray::TYPE_UINT16:
         masm.store16(src, address);
@@ -230,31 +229,31 @@ StoreToIntArray(Assembler &masm, JSObjec
         break;
       default:
         JS_NOT_REACHED("unknown int array type");
     }
 }
 
 template <typename S, typename T>
 static void
-StoreToFloatArray(Assembler &masm, JSObject *tarray, S src, T address)
+StoreToFloatArray(Assembler &masm, js::TypedArray *tarray, S src, T address)
 {
-    if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32)
+    if (tarray->type == js::TypedArray::TYPE_FLOAT32)
         masm.storeFloat(src, address);
     else
         masm.storeDouble(src, address);
 }
 
 // Generate code that will ensure a dynamically typed value, pinned in |vr|,
 // can be stored in an integer typed array. If any sort of conversion is
 // required, |dataReg| will be clobbered by a new value. |saveMask| is
 // used to ensure that |dataReg| (and volatile registers) are preserved
 // across any conversion process.
 static void
-GenConversionForIntArray(Assembler &masm, JSObject *tarray, const ValueRemat &vr,
+GenConversionForIntArray(Assembler &masm, js::TypedArray *tarray, const ValueRemat &vr,
                          uint32 saveMask)
 {
     if (vr.isConstant()) {
         // Constants are always folded to ints up-front.
         JS_ASSERT(vr.knownType() == JSVAL_TYPE_INT32);
         return;
     }
 
@@ -273,33 +272,33 @@ GenConversionForIntArray(Assembler &masm
         saveForCall.preserve(saveMask & Registers::TempRegs);
 
         masm.setupABICall(Registers::FastCall, 2);
         masm.storeArg(0, masm.vmFrameOffset(offsetof(VMFrame, cx)));
         masm.storeArgAddr(1, masm.addressOfExtra(vp));
 
         typedef int32 (JS_FASTCALL *Int32CxVp)(JSContext *, Value *);
         Int32CxVp stub;
-        if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED)
+        if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED)
             stub = stubs::ConvertToTypedInt<true>;
         else 
             stub = stubs::ConvertToTypedInt<false>;
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, stub), false);
         if (vr.dataReg() != Registers::ReturnReg)
             masm.move(Registers::ReturnReg, vr.dataReg());
 
         saveForCall.restore();
         masm.freeStack(vp);
 
         if (checkInt32.isSet())
             checkInt32.get().linkTo(masm.label(), &masm);
     }
 
     // Performing clamping, if needed.
-    if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED) {
+    if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED) {
         //     cmp dr, 0
         //     jge _min
         //     mov dr, 0
         //     jump _done
         // _min:
         //     cmp dr, 255
         //     jle _done
         //     mov dr, 255
@@ -319,17 +318,17 @@ GenConversionForIntArray(Assembler &masm
 // Generate code that will ensure a dynamically typed value, pinned in |vr|,
 // can be stored in an integer typed array.  saveMask| is used to ensure that
 // |dataReg| (and volatile registers) are preserved across any conversion
 // process.
 //
 // Constants are left untouched. Any other value is placed into
 // FPRegisters::First.
 static void
-GenConversionForFloatArray(Assembler &masm, JSObject *tarray, const ValueRemat &vr,
+GenConversionForFloatArray(Assembler &masm, js::TypedArray *tarray, const ValueRemat &vr,
                            FPRegisterID destReg, uint32 saveMask)
 {
     if (vr.isConstant()) {
         // Constants are always folded to doubles up-front.
         JS_ASSERT(vr.knownType() == JSVAL_TYPE_DOUBLE);
         return;
     }
 
@@ -384,28 +383,28 @@ GenConversionForFloatArray(Assembler &ma
         masm.fastLoadDouble(vr.dataReg(), vr.typeReg(), destReg);
 
     // At this point, all loads into xmm1 are complete.
     if (skip1.isSet())
         skip1.get().linkTo(masm.label(), &masm);
     if (skip2.isSet())
         skip2.get().linkTo(masm.label(), &masm);
 
-    if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32)
+    if (tarray->type == js::TypedArray::TYPE_FLOAT32)
         masm.convertDoubleToFloat(destReg, destReg);
 }
 
 template <typename T>
 static bool
-StoreToTypedArray(JSContext *cx, Assembler &masm, JSObject *tarray, T address,
+StoreToTypedArray(JSContext *cx, Assembler &masm, js::TypedArray *tarray, T address,
                   const ValueRemat &vrIn, uint32 saveMask)
 {
     ValueRemat vr = vrIn;
 
-    switch (TypedArray::getType(tarray)) {
+    switch (tarray->type) {
       case js::TypedArray::TYPE_INT8:
       case js::TypedArray::TYPE_UINT8:
       case js::TypedArray::TYPE_UINT8_CLAMPED:
       case js::TypedArray::TYPE_INT16:
       case js::TypedArray::TYPE_UINT16:
       case js::TypedArray::TYPE_INT32:
       case js::TypedArray::TYPE_UINT32:
       {
@@ -424,21 +423,21 @@ StoreToTypedArray(JSContext *cx, Assembl
         // In all of these cases, we try to find a free register that can be
         // used to mutate the RHS. Failing that, we evict an existing volatile
         // register.
         //
         // Note that we are careful to preserve the RHS before saving registers
         // for the conversion call. This is because the object and key may be
         // in temporary registers, and we want to restore those without killing
         // the mutated RHS.
-        bool singleByte = (TypedArray::getType(tarray) == js::TypedArray::TYPE_INT8 ||
-                           TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8 ||
-                           TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED);
+        bool singleByte = (tarray->type == js::TypedArray::TYPE_INT8 ||
+                           tarray->type == js::TypedArray::TYPE_UINT8 ||
+                           tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED);
         bool mayNeedConversion = (!vr.isTypeKnown() || vr.knownType() != JSVAL_TYPE_INT32);
-        bool mayNeedClamping = !vr.isConstant() && (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED);
+        bool mayNeedClamping = !vr.isConstant() && (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED);
         bool needsSingleByteReg = singleByte &&
                                   !vr.isConstant() &&
                                   !(Registers::SingleByteRegs & Registers::maskReg(vr.dataReg()));
         bool rhsIsMutable = !vr.isConstant() && !(saveMask & Registers::maskReg(vr.dataReg()));
 
         if (((mayNeedConversion || mayNeedClamping) && !rhsIsMutable) || needsSingleByteReg) {
             // First attempt to find a free temporary register that:
             //   - is compatible with the RHS constraints
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -69,17 +69,16 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "json.h"
 #include "jsparse.h"
 #include "jsreflect.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jstypedarray.h"
-#include "jstypedarrayinlines.h"
 #include "jsxml.h"
 #include "jsperf.h"
 
 #include "prmjtime.h"
 
 #ifdef JSDEBUGGER
 #include "jsdebug.h"
 #ifdef JSDEBUGGER_JAVA_UI
@@ -879,17 +878,17 @@ FileAsTypedArray(JSContext *cx, const ch
     } else {
         size_t len = ftell(file);
         if (fseek(file, 0, SEEK_SET) != 0) {
             JS_ReportError(cx, "can't seek start of %s", pathname);
         } else {
             obj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, len);
             if (!obj)
                 return NULL;
-            char *buf = (char *) TypedArray::getDataOffset(TypedArray::getTypedArray(obj));
+            char *buf = (char *) TypedArray::fromJSObject(obj)->data;
             size_t cc = fread(buf, 1, len, file);
             if (cc != len) {
                 JS_ReportError(cx, "can't read %s: %s", pathname,
                                (ptrdiff_t(cc) < 0) ? strerror(errno) : "short read");
                 obj = NULL;
             }
         }
     }
@@ -4325,44 +4324,44 @@ Serialize(JSContext *cx, uintN argc, jsv
     if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, NULL, NULL))
         return false;
 
     JSObject *arrayobj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, nbytes);
     if (!arrayobj) {
         JS_free(cx, datap);
         return false;
     }
-    JSObject *array = TypedArray::getTypedArray(arrayobj);
-    JS_ASSERT((uintptr_t(TypedArray::getDataOffset(array)) & 7) == 0);
-    memcpy(TypedArray::getDataOffset(array), datap, nbytes);
+    TypedArray *array = TypedArray::fromJSObject(arrayobj);
+    JS_ASSERT((uintptr_t(array->data) & 7) == 0);
+    memcpy(array->data, datap, nbytes);
     JS_free(cx, datap);
     JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(arrayobj));
     return true;
 }
 
 JSBool
 Deserialize(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval v = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
     JSObject *obj;
     if (JSVAL_IS_PRIMITIVE(v) || !js_IsTypedArray((obj = JSVAL_TO_OBJECT(v)))) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
         return false;
     }
-    JSObject *array = TypedArray::getTypedArray(obj);
-    if ((TypedArray::getByteLength(array) & 7) != 0) {
+    TypedArray *array = TypedArray::fromJSObject(obj);
+    if ((array->byteLength & 7) != 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
         return false;
     }
-    if ((uintptr_t(TypedArray::getDataOffset(array)) & 7) != 0) {
+    if ((uintptr_t(array->data) & 7) != 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT);
         return false;
     }
 
-    if (!JS_ReadStructuredClone(cx, (uint64 *) TypedArray::getDataOffset(array), TypedArray::getByteLength(array),
+    if (!JS_ReadStructuredClone(cx, (uint64 *) array->data, array->byteLength,
                                 JS_STRUCTURED_CLONE_VERSION, &v, NULL, NULL)) {
         return false;
     }
     JS_SET_RVAL(cx, vp, v);
     return true;
 }
 
 JSBool
--- a/js/src/tests/js1_8_5/extensions/typedarray.js
+++ b/js/src/tests/js1_8_5/extensions/typedarray.js
@@ -371,22 +371,14 @@ function test()
     for (var i = 0; i < a.length; i++)
         check(function() a[i] == 0)
 
     a = new Uint8Array(121);
     check(function() a.byteLength == 121);
     check(function() a.length == 121);
     for (var i = 0; i < a.length; i++)
         check(function() a[i] == 0)
-
-    // check that TM generated byte offset is right (requires run with -j)
-    a = new Uint8Array(100);
-    a[99] = 5;
-    b = new Uint8Array(a.buffer, 9); // force a offset
-    // use a loop to invoke the TM
-    for (var i = 0; i < b.length; i++)
-        check(function() b[90] == 5)
     print ("done");
 
     reportCompare(0, TestFailCount, "typed array tests");
 
     exitFunc ('test');
 }
--- a/js/src/tracejit/Writer.cpp
+++ b/js/src/tracejit/Writer.cpp
@@ -454,38 +454,35 @@ void ValidateWriter::checkAccSet(LOpcode
         // ins         = {ld,st}X.slots base[...]
         ok = couldBeObjectOrString(base) ||
              match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)) ||
              (base->isop(LIR_addp) &&
               match(base->oprnd1(), LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)));
         break;
 
       case ACCSET_TARRAY:
-        // we actually just want the JSObject itself
         // This check is imperfect.
         //
         // base = ldp.objprivate ...[offsetof(JSObject, privateData)]
         // ins = ld{i,p}.tarray base[<disp within TypedArray>]
-        ok = (op == LIR_ldi || op == LIR_ldp); /*&&*/
-             //match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots));
+        ok = (op == LIR_ldi || op == LIR_ldp) &&
+             dispWithin(TypedArray) &&
+             match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
         break;
 
       case ACCSET_TARRAY_DATA:
         // base = ldp.tarray/c ...[TypedArray::dataOffset()]
         // ins  = {ld,st}X.tdata base[...]
         //   OR
         // base_oprnd1 = ldp.tarray/c ...[TypedArray::dataOffset()]
         // base        = addp base_oprnd1, ...
         // ins         = {ld,st}X.tdata base[...]
-        ok = true;
-        //ok = isConstPrivatePtr(base, TypedArray::FIELD_DATA);
-        JS_ASSERT(ok);
-        //ok = match(base, LIR_ldp, ACCSET_TARRAY, LOAD_CONST,  sizeof(js::Value) * js::TypedArray::FIELD_DATA) ||
-                //((base->isop(LIR_addp) &&
-                //match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, sizeof(js::Value) * js::TypedArray::FIELD_DATA)));
+        ok = match(base, LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset()) ||
+             (base->isop(LIR_addp) &&
+              match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset()));
         break;
 
       case ACCSET_ITER:
         // base = ldp.objprivate ...[offsetof(JSObject, privateData)]
         // ins = {ld,st}p.iter base[<disp within NativeIterator>]
         ok = (op == LIR_ldp || op == LIR_stp) &&
              dispWithin(NativeIterator) &&
              match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
--- a/js/src/tracejit/Writer.h
+++ b/js/src/tracejit/Writer.h
@@ -528,51 +528,26 @@ class Writer
                     "capacity");
     }
 
     nj::LIns *ldpObjSlots(nj::LIns *obj) const {
         return name(lir->insLoad(nj::LIR_ldp, obj, JSObject::offsetOfSlots(), ACCSET_OBJ_SLOTS),
                     "slots");
     }
 
-    nj::LIns *ldpObjFixedSlots(nj::LIns *obj) const {
-        //return name(lir->insLoad(nj::LIR_ldp, obj, sizeof(JSObject), ACCSET_SLOTS),
-#if JS_BITS_PER_WORD == 32
-        return name(lir->ins2(nj::LIR_addp, obj, lir->insImmI(sizeof(JSObject))),
-#else
-        return name(lir->ins2(nj::LIR_addp, obj, lir->insImmQ(sizeof(JSObject))),
-#endif
-                "fixed_slots");
-    }
-
     nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const {
-        return name(lir->insLoad(nj::LIR_ldi, array, sizeof(Value) * js::TypedArray::FIELD_LENGTH + sPayloadOffset, ACCSET_TARRAY,
+        return name(lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY,
                                  nj::LOAD_CONST),
                     "typedArrayLength");
     }
 
-    nj::LIns *ldiConstTypedArrayByteOffset(nj::LIns *array) const {
-        return name(lir->insLoad(nj::LIR_ldi, array, sizeof(Value) * js::TypedArray::FIELD_BYTEOFFSET + sPayloadOffset, ACCSET_TARRAY,
+    nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const {
+        return name(lir->insLoad(nj::LIR_ldp, array, js::TypedArray::dataOffset(), ACCSET_TARRAY,
                                  nj::LOAD_CONST),
-                    "typedArrayByteOffset");
-    }
-
-    nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const {
-        //return name(lir->insLoad(nj::LIR_ldp, array, sizeof(Value) * js::TypedArray::FIELD_DATA + sPayloadOffset, ACCSET_TARRAY,
-                                 //nj::LOAD_CONST),
-                    //"typedElems");
-        uint32 offset = sizeof(Value) * js::TypedArray::FIELD_DATA + sPayloadOffset;
-#if JS_BITS_PER_WORD == 32
-        return name(lir->insLoad(nj::LIR_ldi, array, offset, ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayData");
-#elif JS_BITS_PER_WORD == 64
-        /* N.B. On 64-bit, privatized value are encoded differently from other pointers. */
-        nj::LIns *v_ins = lir->insLoad(nj::LIR_ldq, array, offset,
-                                       ACCSET_TARRAY, nj::LOAD_CONST);
-        return name(lshqN(v_ins, 1), "typedArrayData");
-#endif
+                    "typedElems");
     }
 
     nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const {
         return lir->insLoad(nj::LIR_ldc2i, addp(elems, index), 0, ACCSET_TARRAY_DATA);
     }
 
     nj::LIns *lduc2uiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const {
         return lir->insLoad(nj::LIR_lduc2ui, addp(elems, index), 0, ACCSET_TARRAY_DATA);