Bug 673451 - Add getters and setters to make JS write barriers easier to implement (r=cdleary)
authorBill McCloskey <wmccloskey@mozilla.com>
Wed, 13 Jul 2011 15:43:33 -0700
changeset 73439 ed434f4c233eee7090fb9b38229bdc1354f1555f
parent 73438 0737efca777e16746dd9435bad830164d3f2f5fd
child 73440 dbefaf7244f1885b217e37e7f3716282b23b2ea8
push id20871
push usereakhgari@mozilla.com
push dateThu, 28 Jul 2011 14:37:48 +0000
treeherdermozilla-central@fe48bbfeff94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscdleary
bugs673451
milestone8.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 673451 - Add getters and setters to make JS write barriers easier to implement (r=cdleary)
js/src/jsapi-tests/testConservativeGC.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jscntxtinlines.h
js/src/jsdate.cpp
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsfuninlines.h
js/src/jsinterp.cpp
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsscope.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jstypedarray.cpp
js/src/jstypedarrayinlines.h
js/src/jsvalue.h
js/src/methodjit/BaseAssembler.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/tracejit/Writer.h
js/src/vm/ArgumentsObject-inl.h
js/src/vm/ArgumentsObject.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Stack-inl.h
--- a/js/src/jsapi-tests/testConservativeGC.cpp
+++ b/js/src/jsapi-tests/testConservativeGC.cpp
@@ -47,17 +47,17 @@ BEGIN_TEST(testConservativeGC)
 
 bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
 {
     /*
      * The GC can change the shape and shrink dslots so we update them before
      * doing memcmp.
      */
     savedCopy->objShape = obj->objShape;
-    savedCopy->slots = obj->slots;
+    savedCopy->setSlotsPtr(obj->getSlotsPtr());
     CHECK(!memcmp(savedCopy, obj, sizeof(*obj)));
     return true;
 }
 
 END_TEST(testConservativeGC)
 
 BEGIN_TEST(testDerivedValues)
 {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4000,17 +4000,17 @@ JS_NewPropertyIterator(JSContext *cx, JS
         if (!ida)
             return NULL;
         pdata = ida;
         index = ida->length;
     }
 
     /* iterobj cannot escape to other threads here. */
     iterobj->setPrivate(const_cast<void *>(pdata));
-    iterobj->getSlotRef(JSSLOT_ITER_INDEX).setInt32(index);
+    iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
 {
     jsint i;
     const Shape *shape;
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -268,17 +268,17 @@ JSObject::willBeSparseDenseArray(uintN r
     uintN minimalDenseCount = requiredCapacity / 4;
     if (newElementsHint >= minimalDenseCount)
         return false;
     minimalDenseCount -= newElementsHint;
 
     if (minimalDenseCount > cap)
         return true;
 
-    Value *elems = getDenseArrayElements();
+    const Value *elems = getDenseArrayElements();
     for (uintN i = 0; i < cap; i++) {
         if (!elems[i].isMagic(JS_ARRAY_HOLE) && !--minimalDenseCount)
             return false;
     }
     return true;
 }
 
 static bool
@@ -368,19 +368,20 @@ GetElementsSlow(JSContext *cx, JSObject 
 }
 
 bool
 GetElements(JSContext *cx, JSObject *aobj, jsuint length, Value *vp)
 {
     if (aobj->isDenseArray() && length <= aobj->getDenseArrayCapacity() &&
         !js_PrototypeHasIndexedProperties(cx, aobj)) {
         /* The prototype does not have indexed properties so hole = undefined */
-        Value *srcbeg = aobj->getDenseArrayElements();
-        Value *srcend = srcbeg + length;
-        for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src)
+        const Value *srcbeg = aobj->getDenseArrayElements();
+        const Value *srcend = srcbeg + length;
+        const Value *src = srcbeg;
+        for (Value *dst = vp; src < srcend; ++dst, ++src)
             *dst = src->isMagic(JS_ARRAY_HOLE) ? UndefinedValue() : *src;
         return true;
     }
 
     if (aobj->isArguments()) {
         ArgumentsObject *argsobj = aobj->asArguments();
         if (!argsobj->hasOverriddenLength()) {
             if (argsobj->getElements(0, length, vp))
@@ -892,17 +893,17 @@ array_deleteProperty(JSContext *cx, JSOb
 } // namespace js
 
 static void
 array_trace(JSTracer *trc, JSObject *obj)
 {
     JS_ASSERT(obj->isDenseArray());
 
     uint32 capacity = obj->getDenseArrayCapacity();
-    MarkValueRange(trc, capacity, obj->slots, "element");
+    MarkValueRange(trc, capacity, obj->getSlotsPtr(), "element");
 }
 
 static JSBool
 array_fix(JSContext *cx, JSObject *obj, bool *success, AutoIdVector *props)
 {
     JS_ASSERT(obj->isDenseArray());
 
     /*
@@ -1264,19 +1265,19 @@ array_toString_sub(JSContext *cx, JSObje
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return false;
 
     StringBuffer sb(cx);
 
     if (!locale && !seplen && obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj)) {
         /* Elements beyond 'capacity' are 'undefined' and thus can be ignored. */
-        Value *beg = obj->getDenseArrayElements();
-        Value *end = beg + Min(length, obj->getDenseArrayCapacity());
-        for (Value *vp = beg; vp != end; ++vp) {
+        const Value *beg = obj->getDenseArrayElements();
+        const Value *end = beg + Min(length, obj->getDenseArrayCapacity());
+        for (const Value *vp = beg; vp != end; ++vp) {
             if (!JS_CHECK_OPERATION_LIMIT(cx))
                 return false;
 
             if (!vp->isMagic(JS_ARRAY_HOLE) && !vp->isNullOrUndefined()) {
                 if (!ValueToStringBuffer(cx, *vp, sb))
                     return false;
             }
         }
@@ -1391,17 +1392,17 @@ InitArrayElements(JSContext *cx, JSObjec
             JS_ASSERT(result == JSObject::ED_SPARSE);
             break;
         }
         jsuint newlen = start + count;
         if (newlen > obj->getArrayLength())
             obj->setArrayLength(newlen);
 
         JS_ASSERT(count < uint32(-1) / sizeof(Value));
-        memcpy(obj->getDenseArrayElements() + start, vector, sizeof(jsval) * count);
+        obj->copyDenseArrayElements(start, vector, count);
         JS_ASSERT_IF(count != 0, !obj->getDenseArrayElement(newlen - 1).isMagic(JS_ARRAY_HOLE));
         return true;
     } while (false);
 
     Value* end = vector + count;
     while (vector != end && start < MAXINDEX) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !SetArrayElement(cx, obj, start++, *vector++)) {
@@ -1440,17 +1441,17 @@ InitArrayObject(JSContext *cx, JSObject 
     JS_ASSERT(obj->isDenseArray());
     obj->setArrayLength(length);
     if (!vector || !length)
         return true;
 
     /* Avoid ensureDenseArrayElements to skip sparse array checks there. */
     if (!obj->ensureSlots(cx, length))
         return false;
-    memcpy(obj->getDenseArrayElements(), vector, length * sizeof(Value));
+    obj->copyDenseArrayElements(0, vector, length);
     return true;
 }
 
 /*
  * Perl-inspired join, reverse, and sort.
  */
 static JSBool
 array_join(JSContext *cx, uintN argc, Value *vp)
@@ -2188,18 +2189,17 @@ array_shift(JSContext *cx, uintN argc, V
     } else {
         length--;
 
         if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
             length < obj->getDenseArrayCapacity()) {
             *vp = obj->getDenseArrayElement(0);
             if (vp->isMagic(JS_ARRAY_HOLE))
                 vp->setUndefined();
-            Value *elems = obj->getDenseArrayElements();
-            memmove(elems, elems + 1, length * sizeof(jsval));
+            obj->moveDenseArrayElements(0, 1, length);
             obj->setDenseArrayElement(length, MagicValue(JS_ARRAY_HOLE));
             obj->setArrayLength(length);
             if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length)))
                 return JS_FALSE;
             return JS_TRUE;
         }
 
         /* Get the to-be-deleted property's value into vp ASAP. */
@@ -2251,18 +2251,17 @@ array_unshift(JSContext *cx, uintN argc,
                     break;
                 JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, argc);
                 if (result != JSObject::ED_OK) {
                     if (result == JSObject::ED_FAILED)
                         return false;
                     JS_ASSERT(result == JSObject::ED_SPARSE);
                     break;
                 }
-                Value *elems = obj->getDenseArrayElements();
-                memmove(elems + argc, elems, length * sizeof(jsval));
+                obj->moveDenseArrayElements(argc, 0, length);
                 for (uint32 i = 0; i < argc; i++)
                     obj->setDenseArrayElement(i, MagicValue(JS_ARRAY_HOLE));
                 optimized = true;
             } while (false);
 
             if (!optimized) {
                 last = length;
                 jsdouble upperIndex = last + argc;
@@ -2390,22 +2389,17 @@ array_splice(JSContext *cx, uintN argc, 
                 break;
             JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, delta);
             if (result != JSObject::ED_OK) {
                 if (result == JSObject::ED_FAILED)
                     return false;
                 JS_ASSERT(result == JSObject::ED_SPARSE);
                 break;
             }
-            Value *arraybeg = obj->getDenseArrayElements();
-            Value *srcbeg = arraybeg + last - 1;
-            Value *srcend = arraybeg + end - 1;
-            Value *dstbeg = srcbeg + delta;
-            for (Value *src = srcbeg, *dst = dstbeg; src > srcend; --src, --dst)
-                *dst = *src;
+            obj->moveDenseArrayElements(end + delta, end, last - end);
 
             obj->setArrayLength(obj->getArrayLength() + delta);
             optimized = true;
         } while (false);
 
         if (!optimized) {
             /* (uint) end could be 0, so we can't use a vanilla >= test. */
             while (last-- > end) {
@@ -2417,22 +2411,17 @@ array_splice(JSContext *cx, uintN argc, 
             }
         }
         length += delta;
     } else if (argc < count) {
         delta = count - (jsuint)argc;
         if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
             length <= obj->getDenseArrayCapacity()) {
 
-            Value *arraybeg = obj->getDenseArrayElements();
-            Value *srcbeg = arraybeg + end;
-            Value *srcend = arraybeg + length;
-            Value *dstbeg = srcbeg - delta;
-            for (Value *src = srcbeg, *dst = dstbeg; src < srcend; ++src, ++dst)
-                *dst = *src;
+            obj->moveDenseArrayElements(end - delta, end, length - end);
         } else {
             for (last = end; last < length; last++) {
                 if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                     !GetElement(cx, obj, last, &hole, tvr.addr()) ||
                     !SetOrDeleteArrayElement(cx, obj, last - delta, hole, tvr.value())) {
                     return JS_FALSE;
                 }
             }
@@ -3086,26 +3075,26 @@ NewDenseAllocatedArray(JSContext *cx, ui
 
 JSObject * JS_FASTCALL
 NewDenseUnallocatedArray(JSContext *cx, uint32 length, JSObject *proto)
 {
     return NewArray<false>(cx, length, proto);
 }
 
 JSObject *
-NewDenseCopiedArray(JSContext *cx, uintN length, Value *vp, JSObject *proto)
+NewDenseCopiedArray(JSContext *cx, uintN length, const Value *vp, JSObject *proto)
 {
     JSObject* obj = NewArray<true>(cx, length, proto);
     if (!obj)
         return NULL;
 
     JS_ASSERT(obj->getDenseArrayCapacity() >= length);
 
     if (vp)
-        memcpy(obj->getDenseArrayElements(), vp, length * sizeof(Value));
+        obj->copyDenseArrayElements(0, vp, length);
 
     return obj;
 }
 
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_2(extern, OBJECT, NewDenseEmptyArray, CONTEXT, OBJECT, 0,
                      nanojit::ACCSET_STORE_ANY)
 JS_DEFINE_CALLINFO_3(extern, OBJECT, NewDenseAllocatedArray, CONTEXT, UINT32, OBJECT, 0,
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -174,17 +174,17 @@ NewDenseAllocatedArray(JSContext *cx, ui
  * Create a dense array with a set length, but without allocating space for the
  * contents. This is useful, e.g., when accepting length from the user.
  */
 extern JSObject * JS_FASTCALL
 NewDenseUnallocatedArray(JSContext *cx, uint length, JSObject *proto=NULL);
 
 /* Create a dense array with a copy of vp. */
 extern JSObject *
-NewDenseCopiedArray(JSContext *cx, uint length, Value *vp, JSObject *proto=NULL);
+NewDenseCopiedArray(JSContext *cx, uint length, const Value *vp, JSObject *proto=NULL);
 
 /* Create a sparse array. */
 extern JSObject *
 NewSlowEmptyArray(JSContext *cx);
 
 }
 
 extern JSBool
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -369,17 +369,17 @@ CallSetter(JSContext *cx, JSObject *obj,
  */
 JS_FORCES_STACK JS_FRIEND_API(void)
 DeepBail(JSContext *cx);
 #endif
 
 static JS_INLINE void
 LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
 {
-    if (!obj->parent)
+    if (!obj->getParent())
         LeaveTrace(cx);
 }
 
 static JS_INLINE void
 LeaveTraceIfArgumentsObject(JSContext *cx, JSObject *obj)
 {
     if (obj->isArguments())
         LeaveTrace(cx);
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1236,17 +1236,17 @@ GetUTCTime(JSContext *cx, JSObject *obj,
  */
 static JSBool
 SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, Value *vp = NULL)
 {
     JS_ASSERT(obj->isDate());
 
     size_t slotCap = JS_MIN(obj->numSlots(), JSObject::DATE_CLASS_RESERVED_SLOTS);
     for (size_t ind = JSObject::JSSLOT_DATE_COMPONENTS_START; ind < slotCap; ind++)
-        obj->getSlotRef(ind).setUndefined();
+        obj->setSlot(ind, UndefinedValue());
 
     obj->setDateUTCTime(DoubleValue(t));
     if (vp)
         vp->setDouble(t);
     return true;
 }
 
 static void
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -1032,17 +1032,17 @@ js_InitExceptionClasses(JSContext *cx, J
         JSObject *proto =
             DefineConstructorAndPrototype(cx, obj, protoKey, atom,
                                           (i == JSEXN_ERR) ? obj_proto : error_proto,
                                           &js_ErrorClass, Exception, 1,
                                           NULL, (i == JSEXN_ERR) ? exception_methods : NULL,
                                           NULL, NULL);
         if (!proto)
             return NULL;
-        JS_ASSERT(proto->privateData == NULL);
+        JS_ASSERT(proto->getPrivate() == NULL);
 
         if (i == JSEXN_ERR)
             error_proto = proto;
 
         /* Add properties to the prototype. */
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
         if (!DefineNativeProperty(cx, proto, nameId, StringValue(atom),
                                   PropertyStub, StrictPropertyStub, 0, 0, 0) ||
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -865,19 +865,18 @@ js_CreateCallObjectOnTrace(JSContext *cx
 
 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CreateCallObjectOnTrace, CONTEXT, FUNCTION, OBJECT, OBJECT,
                      0, nanojit::ACCSET_STORE_ANY)
 
 inline static void
 CopyValuesToCallObject(JSObject &callobj, uintN nargs, Value *argv, uintN nvars, Value *slots)
 {
     JS_ASSERT(callobj.numSlots() >= JSObject::CALL_RESERVED_SLOTS + nargs + nvars);
-    Value *base = callobj.getSlots() + JSObject::CALL_RESERVED_SLOTS;
-    memcpy(base, argv, nargs * sizeof(Value));
-    memcpy(base + nargs, slots, nvars * sizeof(Value));
+    callobj.copySlots(JSObject::CALL_RESERVED_SLOTS, argv, nargs);
+    callobj.copySlots(JSObject::CALL_RESERVED_SLOTS + nargs, slots, nvars);
 }
 
 void
 js_PutCallObject(StackFrame *fp)
 {
     JSObject &callobj = fp->callObj();
     JS_ASSERT(callobj.getPrivate() == fp);
     JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
@@ -1009,24 +1008,21 @@ GetCallArg(JSContext *cx, JSObject *obj,
 }
 
 JSBool
 SetCallArg(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
 {
     JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
     uintN i = (uint16) JSID_TO_INT(id);
 
-    Value *argp;
     if (StackFrame *fp = obj->maybeCallObjStackFrame())
-        argp = &fp->formalArg(i);
+        fp->formalArg(i) = *vp;
     else
-        argp = &obj->callObjArg(i);
-
-    GCPoke(cx, *argp);
-    *argp = *vp;
+        obj->setCallObjArg(i, *vp);
+
     return true;
 }
 
 JSBool
 GetCallUpvar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
     uintN i = (uint16) JSID_TO_INT(id);
@@ -1036,20 +1032,17 @@ GetCallUpvar(JSContext *cx, JSObject *ob
 }
 
 JSBool
 SetCallUpvar(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
 {
     JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
     uintN i = (uint16) JSID_TO_INT(id);
 
-    Value *up = &obj->getCallObjCallee()->getFlatClosureUpvar(i);
-
-    GCPoke(cx, *up);
-    *up = *vp;
+    obj->getCallObjCallee()->setFlatClosureUpvar(i, *vp);
     return true;
 }
 
 JSBool
 GetCallVar(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT((int16) JSID_TO_INT(id) == JSID_TO_INT(id));
     uintN i = (uint16) JSID_TO_INT(id);
@@ -1079,24 +1072,21 @@ SetCallVar(JSContext *cx, JSObject *obj,
 #ifdef JS_TRACER
     if (JS_ON_TRACE(cx)) {
         TraceMonitor *tm = JS_TRACE_MONITOR_ON_TRACE(cx);
         if (tm->recorder && tm->tracecx)
             AbortRecording(cx, "upvar write in nested tree");
     }
 #endif
 
-    Value *varp;
     if (StackFrame *fp = obj->maybeCallObjStackFrame())
-        varp = &fp->varSlot(i);
+        fp->varSlot(i) = *vp;
     else
-        varp = &obj->callObjVar(i);
-
-    GCPoke(cx, *varp);
-    *varp = *vp;
+        obj->setCallObjVar(i, *vp);
+
     return true;
 }
 
 } // namespace js
 
 #if JS_TRACER
 JSBool JS_FASTCALL
 js_SetCallArg(JSContext *cx, JSObject *obj, jsid slotid, ValueArgType arg)
@@ -1169,17 +1159,17 @@ call_trace(JSTracer *trc, JSObject *obj)
          * for JS objects (including Call objects), so is unable to collect
          * cycles involving Call objects whose frames are active without this
          * hiding hack.
          */
         uintN first = JSObject::CALL_RESERVED_SLOTS;
         uintN count = fp->script()->bindings.countArgsAndVars();
 
         JS_ASSERT(obj->numSlots() >= first + count);
-        SetValueRangeToUndefined(obj->getSlots() + first, count);
+        obj->setSlotsUndefined(first, count);
     }
 
     MaybeMarkGenerator(trc, obj);
 }
 
 JS_PUBLIC_DATA(Class) js_CallClass = {
     "Call",
     JSCLASS_HAS_PRIVATE |
@@ -1918,32 +1908,32 @@ CallOrConstructBoundFunction(JSContext *
 
 inline bool
 JSObject::initBoundFunction(JSContext *cx, const Value &thisArg,
                             const Value *args, uintN argslen)
 {
     JS_ASSERT(isFunction());
 
     flags |= JSObject::BOUND_FUNCTION;
-    getSlotRef(JSSLOT_BOUND_FUNCTION_THIS) = thisArg;
-    getSlotRef(JSSLOT_BOUND_FUNCTION_ARGS_COUNT).setPrivateUint32(argslen);
+    setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg);
+    setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen));
     if (argslen != 0) {
         /* FIXME? Burn memory on an empty scope whose shape covers the args slots. */
-        EmptyShape *empty = EmptyShape::create(cx, clasp);
+        EmptyShape *empty = EmptyShape::create(cx, getClass());
         if (!empty)
             return false;
 
         empty->slotSpan += argslen;
         setMap(empty);
 
         if (!ensureInstanceReservedSlots(cx, argslen))
             return false;
 
         JS_ASSERT(numSlots() >= argslen + FUN_CLASS_RESERVED_SLOTS);
-        memcpy(getSlots() + FUN_CLASS_RESERVED_SLOTS, args, argslen * sizeof(Value));
+        copySlots(FUN_CLASS_RESERVED_SLOTS, args, argslen);
     }
     return true;
 }
 
 inline JSObject *
 JSObject::getBoundFunctionTarget() const
 {
     JS_ASSERT(isFunction());
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -185,37 +185,30 @@ struct JSFunction : public JSObject_Slot
      * a compiler-created function object use the first one to hold a mutable
      * methodAtom() state variable, needed for correct foo.caller handling.
      */
     enum {
         METHOD_ATOM_SLOT  = JSSLOT_FUN_METHOD_ATOM
     };
 
   public:
-    void setJoinable() {
-        JS_ASSERT(FUN_INTERPRETED(this));
-        getSlotRef(METHOD_ATOM_SLOT).setNull();
-        flags |= JSFUN_JOINABLE;
-    }
+    inline void setJoinable();
 
     /*
      * Method name imputed from property uniquely assigned to or initialized,
      * where the function does not need to be cloned to carry a scope chain or
      * flattened upvars.
      */
     JSAtom *methodAtom() const {
         return (joinable() && getSlot(METHOD_ATOM_SLOT).isString())
                ? &getSlot(METHOD_ATOM_SLOT).toString()->asAtom()
                : NULL;
     }
 
-    void setMethodAtom(JSAtom *atom) {
-        JS_ASSERT(joinable());
-        getSlotRef(METHOD_ATOM_SLOT).setString(atom);
-    }
+    inline void setMethodAtom(JSAtom *atom);
 
     JSScript *script() const {
         JS_ASSERT(isInterpreted());
         return u.i.script;
     }
 
     js::Native native() const {
         JS_ASSERT(isNative());
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -44,9 +44,24 @@
 #include "jsscript.h"
 
 inline bool
 JSFunction::inStrictMode() const
 {
     return script()->strictModeCode;
 }
 
+inline void
+JSFunction::setJoinable()
+{
+    JS_ASSERT(FUN_INTERPRETED(this));
+    setSlot(METHOD_ATOM_SLOT, js::NullValue());
+    flags |= JSFUN_JOINABLE;
+}
+
+inline void
+JSFunction::setMethodAtom(JSAtom *atom)
+{
+    JS_ASSERT(joinable());
+    setSlot(METHOD_ATOM_SLOT, js::StringValue(atom));
+}
+
 #endif /* jsfuninlines_h___ */
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3269,23 +3269,23 @@ BEGIN_CASE(JSOP_GNAMEDEC)
 
     JSObject *obj2;
     PropertyCacheEntry *entry;
     JS_PROPERTY_CACHE(cx).test(cx, regs.pc, obj, obj2, entry, atom);
     if (!atom) {
         ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
         if (obj == obj2 && entry->vword.isSlot()) {
             uint32 slot = entry->vword.toSlot();
-            Value &rref = obj->nativeGetSlotRef(slot);
+            const Value &rref = obj->nativeGetSlot(slot);
             int32_t tmp;
             if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) {
                 int32_t inc = tmp + ((js_CodeSpec[op].format & JOF_INC) ? 1 : -1);
                 if (!(js_CodeSpec[op].format & JOF_POST))
                     tmp = inc;
-                rref.getInt32Ref() = inc;
+                obj->nativeSetSlot(slot, Int32Value(inc));
                 PUSH_INT32(tmp);
                 len = JSOP_INCNAME_LENGTH;
                 DO_NEXT_OP(len);
             }
         }
         LOAD_ATOM(0, atom);
     }
 
@@ -3848,26 +3848,26 @@ BEGIN_CASE(JSOP_GETELEM)
     Value rval;
     jsid id;
     if (rref.isInt32()) {
         int32_t i = rref.toInt32();
         if (obj->isDenseArray()) {
             jsuint idx = jsuint(i);
 
             if (idx < obj->getDenseArrayCapacity()) {
-                copyFrom = obj->addressOfDenseArrayElement(idx);
+                copyFrom = &obj->getDenseArrayElement(idx);
                 if (!copyFrom->isMagic())
                     goto end_getelem;
             }
         } else if (obj->isArguments()) {
             uint32 arg = uint32(i);
             ArgumentsObject *argsobj = obj->asArguments();
 
             if (arg < argsobj->initialLength()) {
-                copyFrom = argsobj->addressOfElement(arg);
+                copyFrom = &argsobj->element(arg);
                 if (!copyFrom->isMagic(JS_ARGS_HOLE)) {
                     if (StackFrame *afp = reinterpret_cast<StackFrame *>(argsobj->getPrivate()))
                         copyFrom = &afp->canonicalActualArg(arg);
                     goto end_getelem;
                 }
             }
         }
         if (JS_LIKELY(INT_FITS_IN_JSID(i)))
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -225,17 +225,17 @@ EnumerateDenseArrayProperties(JSContext 
 {
     if (!Enumerate(cx, obj, pobj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), false,
                    flags, ht, props)) {
         return false;
     }
 
     if (pobj->getArrayLength() > 0) {
         size_t capacity = pobj->getDenseArrayCapacity();
-        Value *vp = pobj->getDenseArrayElements();
+        const Value *vp = pobj->getDenseArrayElements();
         for (size_t i = 0; i < capacity; ++i, ++vp) {
             if (!vp->isMagic(JS_ARRAY_HOLE)) {
                 /* Dense arrays never get so large that i would not fit into an integer id. */
                 if (!Enumerate(cx, obj, pobj, INT_TO_JSID(i), true, flags, ht, props))
                     return false;
             }
         }
     }
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2925,17 +2925,17 @@ js_CreateThisFromTrace(JSContext *cx, JS
     const Shape *shape = ctor->nativeLookup(id);
     JS_ASSERT(shape->slot == protoSlot);
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(!shape->isMethod());
 #endif
 
     JSObject *parent = ctor->getParent();
     JSObject *proto;
-    const Value &protov = ctor->getSlotRef(protoSlot);
+    const Value &protov = ctor->getSlot(protoSlot);
     if (protov.isObject()) {
         proto = &protov.toObject();
     } else {
         /*
          * GetInterpretedFunctionPrototype found that ctor.prototype is
          * primitive. Use Object.prototype for proto, per ES5 13.2.2 step 7.
          */
         if (!js_GetClassPrototype(cx, parent, JSProto_Object, &proto))
@@ -3252,17 +3252,17 @@ js_PutBlockObject(JSContext *cx, JSBool 
     JS_ASSERT(count <= size_t(cx->regs().sp - fp->base() - depth));
 
     /* See comments in CheckDestructuring from jsparse.cpp. */
     JS_ASSERT(count >= 1);
 
     if (normalUnwind) {
         uintN slot = JSSLOT_BLOCK_FIRST_FREE_SLOT;
         depth += fp->numFixed();
-        memcpy(obj->getSlots() + slot, fp->slots() + depth, count * sizeof(Value));
+        obj->copySlots(slot, fp->slots() + depth, count);
     }
 
     /* We must clear the private slot even with errors. */
     obj->setPrivate(NULL);
     fp->setScopeChainNoCallObj(*obj->getParent());
     return normalUnwind;
 }
 
@@ -3380,26 +3380,26 @@ CopySlots(JSContext *cx, JSObject *from,
     JS_ASSERT(!from->isNative() && !to->isNative());
     size_t nslots = from->numSlots();
     if (to->ensureSlots(cx, nslots))
         return false;
 
     size_t n = 0;
     if (to->isWrapper() &&
         (JSWrapper::wrapperHandler(to)->flags() & JSWrapper::CROSS_COMPARTMENT)) {
-        to->slots[0] = from->slots[0];
-        to->slots[1] = from->slots[1];
+        to->setSlot(0, from->getSlot(0));
+        to->setSlot(1, from->getSlot(1));
         n = 2;
     }
 
     for (; n < nslots; ++n) {
-        Value v = from->slots[n];
+        Value v = from->getSlot(n);
         if (!cx->compartment->wrap(cx, &v))
             return false;
-        to->slots[n] = v;
+        to->setSlot(n, v);
     }
     return true;
 }
 
 JSObject *
 JSObject::clone(JSContext *cx, JSObject *proto, JSObject *parent)
 {
     /*
@@ -3466,19 +3466,19 @@ TradeGuts(JSObject *a, JSObject *b)
         JS_ASSERT(size <= sizeof(tmp));
 
         memcpy(tmp, a, size);
         memcpy(a, b, size);
         memcpy(b, tmp, size);
 
         /* Fixup pointers for inline slots on the objects. */
         if (aInline)
-            b->slots = b->fixedSlots();
+            b->setSlotsPtr(b->fixedSlots());
         if (bInline)
-            a->slots = a->fixedSlots();
+            a->setSlotsPtr(a->fixedSlots());
     } else {
         /*
          * If the objects are of differing sizes, then we only copy over the
          * JSObject portion (things like class, etc.) and leave it to
          * JSObject::clone to copy over the dynamic slots for us.
          */
         if (a->isFunction()) {
             JSFunction tmp;
@@ -3782,17 +3782,17 @@ DefineConstructorAndPrototype(JSContext 
     /*
      * Create the prototype object.  (GlobalObject::createBlankPrototype isn't
      * used because it parents the prototype object to the global and because
      * it uses WithProto::Given.  FIXME: Undo dependencies on this parentage
      * [which already needs to happen for bug 638316], figure out nicer
      * semantics for null-protoProto, and use createBlankPrototype.)
      */
     JSObject *proto = NewObject<WithProto::Class>(cx, clasp, protoProto, obj);
-    if (!proto || !proto->getEmptyShape(cx, proto->clasp, gc::FINALIZE_OBJECT0))
+    if (!proto || !proto->getEmptyShape(cx, proto->getClass(), gc::FINALIZE_OBJECT0))
         return NULL;
 
     proto->syncSpecialEquality();
 
     /* After this point, control must exit via label bad or out. */
     JSObject *ctor;
     bool named = false;
     if (!constructor) {
@@ -4060,17 +4060,17 @@ JSObject::shrinkSlots(JSContext *cx, siz
 }
 
 bool
 JSObject::ensureInstanceReservedSlots(JSContext *cx, size_t nreserved)
 {
     JS_ASSERT_IF(isNative(),
                  isBlock() || isCall() || (isFunction() && isBoundFunction()));
 
-    uintN nslots = JSSLOT_FREE(clasp) + nreserved;
+    uintN nslots = JSSLOT_FREE(getClass()) + nreserved;
     return nslots <= numSlots() || allocSlots(cx, nslots);
 }
 
 static JSObject *
 js_InitNullClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(0);
     return NULL;
@@ -4314,36 +4314,37 @@ js_ConstructObject(JSContext *cx, Class 
     }
     return obj;
 }
 
 bool
 JSObject::allocSlot(JSContext *cx, uint32 *slotp)
 {
     uint32 slot = slotSpan();
-    JS_ASSERT(slot >= JSSLOT_FREE(clasp));
+    JS_ASSERT(slot >= JSSLOT_FREE(getClass()));
 
     /*
      * If this object is in dictionary mode and it has a property table, try to
      * pull a free slot from the property table's slot-number freelist.
      */
     if (inDictionaryMode() && lastProp->hasTable()) {
-        uint32 &last = lastProp->getTable()->freelist;
+        PropertyTable *table = lastProp->getTable();
+        uint32 last = table->freelist;
         if (last != SHAPE_INVALID_SLOT) {
 #ifdef DEBUG
             JS_ASSERT(last < slot);
             uint32 next = getSlot(last).toPrivateUint32();
             JS_ASSERT_IF(next != SHAPE_INVALID_SLOT, next < slot);
 #endif
 
             *slotp = last;
 
-            Value &vref = getSlotRef(last);
-            last = vref.toPrivateUint32();
-            vref.setUndefined();
+            const Value &vref = getSlot(last);
+            table->freelist = vref.toPrivateUint32();
+            setSlot(last, UndefinedValue());
             return true;
         }
     }
 
     if (slot >= numSlots() && !growSlots(cx, slot + 1))
         return false;
 
     /* JSObject::growSlots or JSObject::freeSlot should set the free slots to void. */
@@ -4353,37 +4354,36 @@ JSObject::allocSlot(JSContext *cx, uint3
 }
 
 bool
 JSObject::freeSlot(JSContext *cx, uint32 slot)
 {
     uint32 limit = slotSpan();
     JS_ASSERT(slot < limit);
 
-    Value &vref = getSlotRef(slot);
     if (inDictionaryMode() && lastProp->hasTable()) {
         uint32 &last = lastProp->getTable()->freelist;
 
         /* Can't afford to check the whole freelist, but let's check the head. */
         JS_ASSERT_IF(last != SHAPE_INVALID_SLOT, last < limit && last != slot);
 
         /*
          * Freeing a slot other than the last one mapped by this object's
          * shape (and not a reserved slot; see bug 595230): push the slot onto
          * the dictionary property table's freelist. We want to let the last
          * slot be freed by shrinking the dslots vector; see js_TraceObject.
          */
-        if (JSSLOT_FREE(clasp) <= slot && slot + 1 < limit) {
+        if (JSSLOT_FREE(getClass()) <= slot && slot + 1 < limit) {
             JS_ASSERT_IF(last != SHAPE_INVALID_SLOT, last < slotSpan());
-            vref.setPrivateUint32(last);
+            setSlot(slot, PrivateUint32Value(last));
             last = slot;
             return true;
         }
     }
-    vref.setUndefined();
+    setSlot(slot, UndefinedValue());
     return false;
 }
 
 /* JSBOXEDWORD_INT_MAX as a string */
 #define JSBOXEDWORD_INT_MAX_STRING "1073741823"
 
 /*
  * Convert string indexes that convert to int jsvals as ints to save memory.
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -388,18 +388,23 @@ struct JSObject : js::gc::Cell {
     /* If prototype, lazily filled array of empty shapes for each object size. */
     js::EmptyShape **emptyShapes;
 
     JSObject    *proto;                     /* object's prototype */
     JSObject    *parent;                    /* object's parent */
     void        *privateData;               /* private data */
     jsuword     capacity;                   /* number of slots; for ArrayBuffer the number 
                                                may be be non-integral, so this may underestimate */
+  private:
     js::Value   *slots;                     /* dynamically allocated slots,
                                                or pointer to fixedSlots() */
+  public:
+    static size_t offsetOfSlots() {
+        return offsetof(JSObject, slots);
+    }
 
     /*
      * Return an immutable, shareable, empty shape with the same clasp as this
      * and the same slotSpan as this had when empty.
      *
      * If |this| is the scope of an object |proto|, the resulting scope can be
      * used as the scope of a new object whose prototype is |proto|.
      */
@@ -637,18 +642,29 @@ struct JSObject : js::gc::Cell {
      * their initial map.
      */
     bool ensureInstanceReservedSlots(JSContext *cx, size_t nreserved);
 
     /*
      * Get a direct pointer to the object's slots.
      * This can be reallocated if the object is modified, watch out!
      */
-    js::Value *getSlots() const {
-        return slots;
+    const js::Value *getSlots() const { return slots; }
+
+    js::Value *getSlotsPtr() { return slots; }
+    void setSlotsPtr(js::Value *vp) { slots = vp; }
+
+    void copySlots(uint32 dstStart, const js::Value *src, uint32 count) {
+        JS_ASSERT(dstStart + count <= capacity);
+        memcpy(slots + dstStart, src, count * sizeof(js::Value));
+    }
+
+    void setSlotsUndefined(uint32 start, uint32 count) {
+        JS_ASSERT(start + count <= capacity);
+        js::SetValueRangeToUndefined(slots + start, count);
     }
 
     /*
      * NB: ensureClassReservedSlotsForEmptyObject asserts that nativeEmpty()
      * Use ensureClassReservedSlots for any object, either empty or already
      * extended with properties.
      */
     bool ensureClassReservedSlotsForEmptyObject(JSContext *cx);
@@ -780,20 +796,21 @@ struct JSObject : js::gc::Cell {
     /*
      * Array-specific getters and setters (for both dense and slow arrays).
      */
 
     inline uint32 getArrayLength() const;
     inline void setArrayLength(uint32 length);
 
     inline uint32 getDenseArrayCapacity();
-    inline js::Value* getDenseArrayElements();
+    inline const js::Value* getDenseArrayElements();
     inline const js::Value &getDenseArrayElement(uintN idx);
-    inline js::Value* addressOfDenseArrayElement(uintN idx);
     inline void setDenseArrayElement(uintN idx, const js::Value &val);
+    inline void copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count);
+    inline void moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count);
     inline void shrinkDenseArrayElements(JSContext *cx, uintN cap);
 
     /*
      * ensureDenseArrayElements ensures that the dense array can hold at least
      * index + extra elements. It returns ED_OK on success, ED_FAILED on
      * failure to grow the array, ED_SPARSE when the array is too sparse to
      * grow (this includes the case of index + extra overflow). In the last
      * two cases the array is kept intact.
@@ -847,21 +864,21 @@ struct JSObject : js::gc::Cell {
     inline JSFunction *getCallObjCalleeFunction() const; 
     inline void setCallObjCallee(JSObject *callee);
 
     inline const js::Value &getCallObjArguments() const;
     inline void setCallObjArguments(const js::Value &v);
 
     /* Returns the formal argument at the given index. */
     inline const js::Value &callObjArg(uintN i) const;
-    inline js::Value &callObjArg(uintN i);
+    inline void setCallObjArg(uintN i, const js::Value &v);
 
     /* Returns the variable at the given index. */
     inline const js::Value &callObjVar(uintN i) const;
-    inline js::Value &callObjVar(uintN i);
+    inline void setCallObjVar(uintN i, const js::Value &v);
 
     /*
      * Date-specific getters and setters.
      */
 
     static const uint32 JSSLOT_DATE_UTC_TIME = 0;
 
     /*
@@ -912,17 +929,18 @@ struct JSObject : js::gc::Cell {
 
   public:
     static const uint32 FUN_CLASS_RESERVED_SLOTS = 2;
 
     inline JSFunction *getFunctionPrivate() const;
 
     inline js::Value *getFlatClosureUpvars() const;
     inline js::Value getFlatClosureUpvar(uint32 i) const;
-    inline js::Value &getFlatClosureUpvar(uint32 i);
+    inline const js::Value &getFlatClosureUpvar(uint32 i);
+    inline void setFlatClosureUpvar(uint32 i, const js::Value &v);
     inline void setFlatClosureUpvars(js::Value *upvars);
 
     inline bool hasMethodObj(const JSObject& obj) const;
     inline void setMethodObj(JSObject& obj);
 
     inline bool initBoundFunction(JSContext *cx, const js::Value &thisArg,
                                   const js::Value *args, uintN argslen);
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -119,17 +119,17 @@ JSObject::unbrand(JSContext *cx)
     }
     setGeneric();
     return true;
 }
 
 inline void
 JSObject::syncSpecialEquality()
 {
-    if (clasp->ext.equality)
+    if (getClass()->ext.equality)
         flags |= JSObject::HAS_EQUALITY;
 }
 
 inline void
 JSObject::finalize(JSContext *cx)
 {
     /* Cope with stillborn objects that have no map. */
     if (isNewborn())
@@ -355,45 +355,54 @@ JSObject::setArrayLength(uint32 length)
 
 inline uint32
 JSObject::getDenseArrayCapacity()
 {
     JS_ASSERT(isDenseArray());
     return numSlots();
 }
 
-inline js::Value*
+inline const js::Value *
 JSObject::getDenseArrayElements()
 {
     JS_ASSERT(isDenseArray());
     return getSlots();
 }
 
 inline const js::Value &
 JSObject::getDenseArrayElement(uintN idx)
 {
     JS_ASSERT(isDenseArray());
     return getSlot(idx);
 }
 
-inline js::Value *
-JSObject::addressOfDenseArrayElement(uintN idx)
-{
-    JS_ASSERT(isDenseArray());
-    return &getSlotRef(idx);
-}
-
 inline void
 JSObject::setDenseArrayElement(uintN idx, const js::Value &val)
 {
     JS_ASSERT(isDenseArray());
     setSlot(idx, val);
 }
 
 inline void
+JSObject::copyDenseArrayElements(uintN dstStart, const js::Value *src, uintN count)
+{
+    JS_ASSERT(isDenseArray());
+    copySlots(dstStart, src, count);
+}
+
+inline void
+JSObject::moveDenseArrayElements(uintN dstStart, uintN srcStart, uintN count)
+{
+    JS_ASSERT(isDenseArray());
+    JS_ASSERT(dstStart + count <= capacity);
+    JS_ASSERT(srcStart + count <= capacity);
+    memmove(slots + dstStart, getSlots() + srcStart, count * sizeof(js::Value));
+}
+
+inline void
 JSObject::shrinkDenseArrayElements(JSContext *cx, uintN cap)
 {
     JS_ASSERT(isDenseArray());
     shrinkSlots(cx, cap);
 }
 
 inline bool
 JSObject::callIsForEval() const
@@ -412,17 +421,17 @@ JSObject::maybeCallObjStackFrame() const
     return reinterpret_cast<js::StackFrame *>(getPrivate());
 }
 
 inline void
 JSObject::setCallObjCallee(JSObject *callee)
 {
     JS_ASSERT(isCall());
     JS_ASSERT_IF(callee, callee->isFunction());
-    return getSlotRef(JSSLOT_CALL_CALLEE).setObjectOrNull(callee);
+    setSlot(JSSLOT_CALL_CALLEE, js::ObjectOrNullValue(callee));
 }
 
 inline JSObject *
 JSObject::getCallObjCallee() const
 {
     JS_ASSERT(isCall());
     return getSlot(JSSLOT_CALL_CALLEE).toObjectOrNull();
 }
@@ -453,40 +462,40 @@ JSObject::setCallObjArguments(const js::
 inline const js::Value &
 JSObject::callObjArg(uintN i) const
 {
     JS_ASSERT(isCall());
     JS_ASSERT(i < getCallObjCalleeFunction()->nargs);
     return getSlot(JSObject::CALL_RESERVED_SLOTS + i);
 }
 
-inline js::Value &
-JSObject::callObjArg(uintN i)
+inline void
+JSObject::setCallObjArg(uintN i, const js::Value &v)
 {
     JS_ASSERT(isCall());
     JS_ASSERT(i < getCallObjCalleeFunction()->nargs);
-    return getSlotRef(JSObject::CALL_RESERVED_SLOTS + i);
+    setSlot(JSObject::CALL_RESERVED_SLOTS + i, v);
 }
 
 inline const js::Value &
 JSObject::callObjVar(uintN i) const
 {
     JSFunction *fun = getCallObjCalleeFunction();
     JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
     JS_ASSERT(i < fun->script()->bindings.countVars());
     return getSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i);
 }
 
-inline js::Value &
-JSObject::callObjVar(uintN i)
+inline void
+JSObject::setCallObjVar(uintN i, const js::Value &v)
 {
     JSFunction *fun = getCallObjCalleeFunction();
     JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
     JS_ASSERT(i < fun->script()->bindings.countVars());
-    return getSlotRef(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i);
+    setSlot(JSObject::CALL_RESERVED_SLOTS + fun->nargs + i, v);
 }
 
 inline const js::Value &
 JSObject::getDateUTCTime() const
 {
     JS_ASSERT(isDate());
     return getSlot(JSSLOT_DATE_UTC_TIME);
 }
@@ -511,43 +520,50 @@ JSObject::getFlatClosureUpvars() const
 
 inline js::Value
 JSObject::getFlatClosureUpvar(uint32 i) const
 {
     JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars());
     return getFlatClosureUpvars()[i];
 }
 
-inline js::Value &
+inline const js::Value &
 JSObject::getFlatClosureUpvar(uint32 i)
 {
     JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars());
     return getFlatClosureUpvars()[i];
 }
 
 inline void
+JSObject::setFlatClosureUpvar(uint32 i, const js::Value &v)
+{
+    JS_ASSERT(i < getFunctionPrivate()->script()->bindings.countUpvars());
+    getFlatClosureUpvars()[i] = v;
+}
+
+inline void
 JSObject::setFlatClosureUpvars(js::Value *upvars)
 {
     JS_ASSERT(isFunction());
     JS_ASSERT(FUN_FLAT_CLOSURE(getFunctionPrivate()));
-    getSlotRef(JSSLOT_FLAT_CLOSURE_UPVARS).setPrivate(upvars);
+    setSlot(JSSLOT_FLAT_CLOSURE_UPVARS, PrivateValue(upvars));
 }
 
 inline bool
 JSObject::hasMethodObj(const JSObject& obj) const
 {
     return JSSLOT_FUN_METHOD_OBJ < numSlots() &&
            getSlot(JSSLOT_FUN_METHOD_OBJ).isObject() &&
            getSlot(JSSLOT_FUN_METHOD_OBJ).toObject() == obj;
 }
 
 inline void
 JSObject::setMethodObj(JSObject& obj)
 {
-    getSlotRef(JSSLOT_FUN_METHOD_OBJ).setObject(obj);
+    setSlot(JSSLOT_FUN_METHOD_OBJ, js::ObjectValue(obj));
 }
 
 inline js::NativeIterator *
 JSObject::getNativeIterator() const
 {
     return (js::NativeIterator *) getPrivate();
 }
 
@@ -648,17 +664,17 @@ inline JSObject *
 JSObject::getWithThis() const
 {
     return &getSlot(JSSLOT_WITH_THIS).toObject();
 }
 
 inline void
 JSObject::setWithThis(JSObject *thisp)
 {
-    getSlotRef(JSSLOT_WITH_THIS).setObject(*thisp);
+    setSlot(JSSLOT_WITH_THIS, js::ObjectValue(*thisp));
 }
 
 inline void
 JSObject::init(JSContext *cx, js::Class *aclasp, JSObject *proto, JSObject *parent,
                void *priv, bool useHoles)
 {
     clasp = aclasp;
     flags = 0;
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -582,17 +582,17 @@ JSObject::checkShapeConsistency()
 
     Shape *shape = lastProp;
     Shape *prev = NULL;
 
     if (inDictionaryMode()) {
         if (shape->hasTable()) {
             PropertyTable *table = shape->getTable();
             for (uint32 fslot = table->freelist; fslot != SHAPE_INVALID_SLOT;
-                 fslot = getSlotRef(fslot).toPrivateUint32()) {
+                 fslot = getSlot(fslot).toPrivateUint32()) {
                 JS_ASSERT(fslot < shape->slotSpan);
             }
 
             for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
                 JS_ASSERT_IF(shape != lastProp, !shape->hasTable());
 
                 Shape **spp = table->search(shape->propid, false);
                 JS_ASSERT(SHAPE_FETCH(spp) == shape);
@@ -901,17 +901,17 @@ JSObject::putProperty(JSContext *cx, jsi
      * has no slot. But we do not need to free oldSlot (and must not, as trying
      * to will botch an assertion in JSObject::freeSlot) if the new lastProp
      * (shape here) has a slotSpan that does not cover it.
      */
     if (hadSlot && !shape->hasSlot()) {
         if (oldSlot < shape->slotSpan)
             freeSlot(cx, oldSlot);
         else
-            getSlotRef(oldSlot).setUndefined();
+            setSlot(oldSlot, UndefinedValue());
         JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
     }
 
     CHECK_SHAPE_CONSISTENCY(this);
 
     return js_UpdateWatchpointsForShape(cx, this, shape);
 }
 
@@ -1097,17 +1097,17 @@ JSObject::removeProperty(JSContext *cx, 
                 if (table->freelist != SHAPE_INVALID_SLOT) {
                     lastProp->slotSpan = shape->slotSpan;
 
                     /*
                      * Add the slot to the freelist if it wasn't added in
                      * freeSlot and it is not a reserved slot.
                      */
                     if (hadSlot && !addedToFreelist && JSSLOT_FREE(clasp) <= shape->slot) {
-                        getSlotRef(shape->slot).setPrivateUint32(table->freelist);
+                        setSlot(shape->slot, PrivateUint32Value(table->freelist));
                         table->freelist = shape->slot;
                     }
                 }
             }
 
             /* Hand off table from old to new lastProp. */
             oldLastProp->setTable(NULL);
             lastProp->setTable(table);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -3043,17 +3043,17 @@ TraceMonitor::mark(JSTracer *trc)
 
 /*
  * Box a value from the native stack back into the Value format.
  */
 static inline void
 NativeToValue(JSContext* cx, Value& v, JSValueType type, double* slot)
 {
     if (type == JSVAL_TYPE_DOUBLE) {
-        v.setNumber(*slot);
+        v = NumberValue(*slot);
     } else if (JS_LIKELY(type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET)) {
         v.boxNonDoubleFrom(type, (uint64 *)slot);
     } else if (type == JSVAL_TYPE_STRORNULL) {
         JSString *str = *(JSString **)slot;
         v = str ? StringValue(str) : NullValue();
     } else if (type == JSVAL_TYPE_OBJORNULL) {
         JSObject *obj = *(JSObject **)slot;
         v = obj ? ObjectValue(*obj) : NullValue();
@@ -3832,17 +3832,17 @@ TraceRecorder::isValidSlot(JSObject *obj
 
 /* Lazily import a global slot if we don't already have it in the tracker. */
 JS_REQUIRES_STACK void
 TraceRecorder::importGlobalSlot(unsigned slot)
 {
     JS_ASSERT(slot == uint16(slot));
     JS_ASSERT(globalObj->numSlots() <= MAX_GLOBAL_SLOTS);
 
-    Value* vp = &globalObj->getSlotRef(slot);
+    const Value* vp = &globalObj->getSlot(slot);
     JS_ASSERT(!known(vp));
 
     /* Add the slot to the list of interned global slots. */
     JSValueType type;
     int index = tree->globalSlots->offsetOf(uint16(slot));
     if (index == -1) {
         type = getCoercedType(*vp);
         if (type == JSVAL_TYPE_INT32 && (!oracle || oracle->isGlobalSlotUndemotable(cx, slot)))
@@ -3865,17 +3865,17 @@ TraceRecorder::lazilyImportGlobalSlot(un
     if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */
         return false;
     /*
      * If the global object grows too large, alloca in ExecuteTree might fail,
      * so abort tracing on global objects with unreasonably many slots.
      */
     if (globalObj->numSlots() > MAX_GLOBAL_SLOTS)
         return false;
-    Value* vp = &globalObj->getSlotRef(slot);
+    const Value* vp = &globalObj->getSlot(slot);
     if (known(vp))
         return true; /* we already have it */
     importGlobalSlot(slot);
     return true;
 }
 
 /* Write back a value onto the stack or global frames. */
 LIns*
@@ -3898,17 +3898,17 @@ TraceRecorder::writeBack(LIns* ins, LIns
         unsigned slot = unsigned(offset / sizeof(double));
         (void)pendingGlobalSlotsToSet.append(slot);  /* OOM is safe. */
     }
     return w.st(ins, addr);
 }
 
 /* Update the tracker, then issue a write back store. */
 JS_REQUIRES_STACK void
-TraceRecorder::setImpl(void* p, LIns* i, bool shouldDemoteToInt32)
+TraceRecorder::setImpl(const void* p, LIns* i, bool shouldDemoteToInt32)
 {
     JS_ASSERT(i != NULL);
     checkForGlobalObjectReallocation();
     tracker.set(p, i);
 
     /*
      * If we are writing to this location for the first time, calculate the
      * offset into the native frame manually. Otherwise just look up the last
@@ -3943,17 +3943,17 @@ TraceRecorder::setImpl(void* p, LIns* i,
                             ? nativespOffsetImpl(p)
                             : nativeGlobalOffset((Value *)p)));
 
         writeBack(i, base, disp, shouldDemoteToInt32);
     }
 }
 
 JS_REQUIRES_STACK inline void
-TraceRecorder::set(Value* p, LIns* i, bool shouldDemoteToInt32)
+TraceRecorder::set(const Value* p, LIns* i, bool shouldDemoteToInt32)
 {
     return setImpl(p, i, shouldDemoteToInt32);
 }
 
 JS_REQUIRES_STACK void
 TraceRecorder::setFrameObjPtr(void* p, LIns* i, bool shouldDemoteToInt32)
 {
     JS_ASSERT(isValidFrameObjPtr(p));
@@ -4066,18 +4066,18 @@ TraceRecorder::known(JSObject** p)
  * The slots of the global object are sometimes reallocated by the interpreter.
  * This function check for that condition and re-maps the entries of the tracker
  * accordingly.
  */
 JS_REQUIRES_STACK void
 TraceRecorder::checkForGlobalObjectReallocationHelper()
 {
     debug_only_print0(LC_TMTracer, "globalObj->slots relocated, updating tracker\n");
-    Value* src = global_slots;
-    Value* dst = globalObj->getSlots();
+    const Value* src = global_slots;
+    const Value* dst = globalObj->getSlots();
     jsuint length = globalObj->capacity;
     LIns** map = (LIns**)alloca(sizeof(LIns*) * length);
     for (jsuint n = 0; n < length; ++n) {
         map[n] = tracker.get(src);
         tracker.set(src++, NULL);
     }
     for (jsuint n = 0; n < length; ++n)
         tracker.set(dst++, map[n]);
@@ -5453,17 +5453,17 @@ TraceRecorder::emitTreeCall(TreeFragment
 #endif
 
     /* The inner tree may modify currently-tracked upvars, so flush everything. */
     ClearSlotsVisitor visitor(tracker);
     VisitStackSlots(visitor, cx, callDepth);
     SlotList& gslots = *tree->globalSlots;
     for (unsigned i = 0; i < gslots.length(); i++) {
         unsigned slot = gslots[i];
-        Value* vp = &globalObj->getSlotRef(slot);
+        const Value* vp = &globalObj->getSlot(slot);
         tracker.set(vp, NULL);
     }
 
     /* Set stack slots from the innermost frame. */
     importTypeMap.setLength(NativeStackSlots(cx, callDepth));
     unsigned startOfInnerFrame = importTypeMap.length() - exit->numStackSlots;
     for (unsigned i = 0; i < exit->numStackSlots; i++)
         importTypeMap[startOfInnerFrame + i] = exit->stackTypeMap()[i];
@@ -8144,17 +8144,17 @@ JS_DEFINE_CALLINFO_4(extern, UINT32, Get
  * generate LIR to access the given property. Return RECORD_CONTINUE on success,
  * otherwise abort and return RECORD_STOP. There are 3 outparams:
  *
  *     vp           the address of the current property value
  *     ins          LIR instruction representing the property value on trace
  *     NameResult   describes how to look up name; see comment for NameResult in jstracer.h
  */
 JS_REQUIRES_STACK AbortableRecordingStatus
-TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameResult& nr,
+TraceRecorder::scopeChainProp(JSObject* chainHead, const Value*& vp, LIns*& ins, NameResult& nr,
                               JSObject** scopeObjp)
 {
     JS_ASSERT(chainHead == &cx->fp()->scopeChain());
     JS_ASSERT(chainHead != globalObj);
 
     TraceMonitor &localtm = *traceMonitor;
 
     JSAtom* atom = atoms[GET_INDEX(cx->regs().pc)];
@@ -8194,17 +8194,17 @@ TraceRecorder::scopeChainProp(JSObject* 
         if (obj2 != obj)
             RETURN_STOP_A("prototype property");
 
         Shape* shape = (Shape*) prop;
         if (!isValidSlot(obj, shape))
             return ARECORD_STOP;
         if (!lazilyImportGlobalSlot(shape->slot))
             RETURN_STOP_A("lazy import of global slot failed");
-        vp = &obj->getSlotRef(shape->slot);
+        vp = &obj->getSlot(shape->slot);
         ins = get(vp);
         nr.tracked = true;
         return ARECORD_CONTINUE;
     }
 
     if (obj == obj2 && obj->isCall()) {
         AbortableRecordingStatus status =
             InjectStatus(callProp(obj, prop, ATOM_TO_JSID(atom), vp, ins, nr));
@@ -8213,17 +8213,17 @@ TraceRecorder::scopeChainProp(JSObject* 
 
     RETURN_STOP_A("fp->scopeChain is not global or active call object");
 }
 
 /*
  * Generate LIR to access a property of a Call object.
  */
 JS_REQUIRES_STACK RecordingStatus
-TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, Value*& vp,
+TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, const Value*& vp,
                         LIns*& ins, NameResult& nr)
 {
     Shape *shape = (Shape*) prop;
 
     JSOp op = JSOp(*cx->regs().pc);
     uint32 setflags = (js_CodeSpec[op].format & (JOF_SET | JOF_INCDEC | JOF_FOR));
     if (setflags && !shape->writable())
         RETURN_STOP("writing to a read-only property");
@@ -8921,31 +8921,31 @@ TraceRecorder::incProp(jsint incr, bool 
 
     uint32 slot;
     LIns* v_ins;
     CHECK_STATUS_A(prop(obj, obj_ins, &slot, &v_ins, NULL));
 
     if (slot == SHAPE_INVALID_SLOT)
         RETURN_STOP_A("incProp on invalid slot");
 
-    Value& v = obj->getSlotRef(slot);
+    const Value& v = obj->getSlot(slot);
     Value v_after;
     CHECK_STATUS_A(inc(v, v_ins, v_after, incr, pre));
 
     LIns* slots_ins = NULL;
     stobj_set_slot(obj, obj_ins, slot, slots_ins, v_after, v_ins);
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::incElem(jsint incr, bool pre)
 {
     Value& r = stackval(-1);
     Value& l = stackval(-2);
-    Value* vp;
+    const Value* vp;
     LIns* v_ins;
     LIns* addr_ins;
 
     if (!l.isPrimitive() && l.toObject().isDenseArray() && r.isInt32()) {
         guardDenseArray(get(&l), MISMATCH_EXIT);
         CHECK_STATUS(denseArrayElement(l, r, vp, v_ins, addr_ins, snapshot(BRANCH_EXIT)));
         if (!addr_ins) // if we read a hole, abort
             return RECORD_STOP;
@@ -11921,17 +11921,17 @@ JS_REQUIRES_STACK AbortableRecordingStat
 TraceRecorder::record_JSOP_DECELEM()
 {
     return InjectStatus(incElem(-1));
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::incName(jsint incr, bool pre)
 {
-    Value* vp;
+    const Value* vp;
     LIns* v_ins;
     LIns* v_ins_after;
     NameResult nr;
 
     CHECK_STATUS_A(name(vp, v_ins, nr));
     Value v = nr.tracked ? *vp : nr.v;
     Value v_after;
     CHECK_STATUS_A(incHelper(v, v_ins, v_after, v_ins_after, incr));
@@ -13015,17 +13015,17 @@ TraceRecorder::record_JSOP_GETELEM()
                 set(&idx, obj_ins);
             return ARECORD_CONTINUE;
         }
         RETURN_STOP_A("can't reach arguments object's frame");
     }
 
     if (obj->isDenseArray()) {
         // Fast path for dense arrays accessed with a integer index.
-        Value* vp;
+        const Value* vp;
         LIns* addr_ins;
 
         VMSideExit* branchExit = snapshot(BRANCH_EXIT);
         guardDenseArray(obj_ins, branchExit);
         CHECK_STATUS_A(denseArrayElement(lval, idx, vp, v_ins, addr_ins, branchExit));
         set(&lval, v_ins);
         if (call)
             set(&idx, obj_ins);
@@ -13387,17 +13387,17 @@ JS_DEFINE_CALLINFO_2(static, BOOL, Check
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_CALLNAME()
 {
     JSObject* scopeObj = &cx->fp()->scopeChain();
     LIns *funobj_ins;
     JSObject *funobj;
     if (scopeObj != globalObj) {
-        Value* vp;
+        const Value* vp;
         NameResult nr;
         CHECK_STATUS_A(scopeChainProp(scopeObj, vp, funobj_ins, nr, &scopeObj));
         if (!nr.tracked)
             vp = &nr.v;
         if (!vp->isObject())
             RETURN_STOP_A("callee is not an object");
         funobj = &vp->toObject();
         if (!funobj->isFunction())
@@ -13964,17 +13964,17 @@ TraceRecorder::record_NativeCallComplete
     }
 
     // We'll null pendingSpecializedNative in monitorRecording, on the next op
     // cycle.  There must be a next op since the stack is non-empty.
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
-TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr)
+TraceRecorder::name(const Value*& vp, LIns*& ins, NameResult& nr)
 {
     JSObject* obj = &cx->fp()->scopeChain();
     JSOp op = JSOp(*cx->regs().pc);
     if (js_CodeSpec[op].format & JOF_GNAME)
         obj = obj->getGlobal();
     if (obj != globalObj)
         return scopeChainProp(obj, vp, ins, nr);
 
@@ -14206,17 +14206,17 @@ TraceRecorder::propTail(JSObject* obj, L
     return RECORD_CONTINUE;
 }
 
 /*
  * When we end up with a hole, read it as undefined, and make sure to set
  * addr_ins to null.
  */
 JS_REQUIRES_STACK RecordingStatus
-TraceRecorder::denseArrayElement(Value& oval, Value& ival, Value*& vp, LIns*& v_ins,
+TraceRecorder::denseArrayElement(Value& oval, Value& ival, const Value*& vp, LIns*& v_ins,
                                  LIns*& addr_ins, VMSideExit* branchExit)
 {
     JS_ASSERT(oval.isObject() && ival.isInt32());
 
     JSObject* obj = &oval.toObject();
     LIns* obj_ins = get(&oval);
     jsint idx = ival.toInt32();
     LIns* idx_ins;
@@ -14242,18 +14242,18 @@ TraceRecorder::denseArrayElement(Value& 
         addr_ins = NULL;
         return RECORD_CONTINUE;
     }
 
     /* Guard that index is within capacity. */
     guard(true, w.name(w.ltui(idx_ins, capacity_ins), "inRange"), branchExit);
 
     /* Load the value and guard on its type to unbox it. */
-    vp = &obj->slots[jsuint(idx)];
-	JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
+    vp = &obj->getSlot(jsuint(idx));
+    JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
     addr_ins = w.name(w.getDslotAddress(obj_ins, idx_ins), "elemp");
     v_ins = unbox_value(*vp, DSlotsAddress(addr_ins), branchExit);
 
     /* Don't let the hole value escape. Turn it into an undefined. */
     if (vp->isMagic()) {
         CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT)));
         v_ins = w.immiUndefined();
         addr_ins = NULL;
@@ -14363,17 +14363,17 @@ TraceRecorder::getProp(Value& v)
         RETURN_STOP_A("primitive lhs");
 
     return getProp(&v.toObject(), get(&v));
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_NAME()
 {
-    Value* vp;
+    const Value* vp;
     LIns* v_ins;
     NameResult nr;
     CHECK_STATUS_A(name(vp, v_ins, nr));
     stack(0, v_ins);
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
@@ -16105,17 +16105,17 @@ TraceRecorder::record_JSOP_STOP()
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_GETXPROP()
 {
     Value& l = stackval(-1);
     if (l.isPrimitive())
         RETURN_STOP_A("primitive-this for GETXPROP?");
 
-    Value* vp;
+    const Value* vp;
     LIns* v_ins;
     NameResult nr;
     CHECK_STATUS_A(name(vp, v_ins, nr));
     stack(-1, v_ins);
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
@@ -16422,17 +16422,17 @@ TraceRecorder::record_JSOP_GETGLOBAL()
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_CALLGLOBAL()
 {
     uint32 slot = cx->fp()->script()->getGlobalSlot(GET_SLOTNO(cx->regs().pc));
     if (!lazilyImportGlobalSlot(slot))
          RETURN_STOP_A("lazy import of global slot failed");
 
-    Value &v = globalObj->getSlotRef(slot);
+    const Value &v = globalObj->getSlot(slot);
     stack(0, get(&v));
     stack(1, w.immiUndefined());
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_GETGNAME()
 {
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -1058,17 +1058,17 @@ class TraceRecorder
 
     /* Maps interpreter stack values to the instruction generating that value. */
     Tracker                         tracker;
 
     /* Maps interpreter stack values to the instruction writing back to the native stack. */
     Tracker                         nativeFrameTracker;
 
     /* The start of the global object's slots we assume for the trackers. */
-    Value*                          global_slots;
+    const Value*                    global_slots;
 
     /* The number of interpreted calls entered (and not yet left) since recording began. */
     unsigned                        callDepth;
 
     /* The current atom table, mirroring the interpreter loop's variable of the same name. */
     JSAtom**                        atoms;
     Value*                          consts;
 
@@ -1216,18 +1216,18 @@ class TraceRecorder
     nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset,
                              bool shouldDemoteToInt32);
 
 #ifdef DEBUG
     bool isValidFrameObjPtr(void *obj);
 #endif
     void assertInsideLoop();
 
-    JS_REQUIRES_STACK void setImpl(void* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true);
-    JS_REQUIRES_STACK void set(Value* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true);
+    JS_REQUIRES_STACK void setImpl(const void* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true);
+    JS_REQUIRES_STACK void set(const Value* p, nanojit::LIns* l, bool shouldDemoteToInt32 = true);
     JS_REQUIRES_STACK void setFrameObjPtr(void* p, nanojit::LIns* l,
                                           bool shouldDemoteToInt32 = true);
     nanojit::LIns* getFromTrackerImpl(const void *p);
     nanojit::LIns* getFromTracker(const Value* p);
     JS_REQUIRES_STACK nanojit::LIns* getImpl(const void* p);
     JS_REQUIRES_STACK nanojit::LIns* get(const Value* p);
     JS_REQUIRES_STACK nanojit::LIns* getFrameObjPtr(void* p);
     JS_REQUIRES_STACK nanojit::LIns* attemptImport(const Value* p);
@@ -1269,18 +1269,18 @@ class TraceRecorder
         js::Shape        *shape;         // shape name was resolved to
     };
 
     JS_REQUIRES_STACK nanojit::LIns* scopeChain();
     JS_REQUIRES_STACK nanojit::LIns* entryScopeChain() const;
     JS_REQUIRES_STACK nanojit::LIns* entryFrameIns() const;
     JS_REQUIRES_STACK StackFrame* frameIfInRange(JSObject* obj, unsigned* depthp = NULL) const;
     JS_REQUIRES_STACK RecordingStatus traverseScopeChain(JSObject *obj, nanojit::LIns *obj_ins, JSObject *obj2, nanojit::LIns *&obj2_ins);
-    JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL);
-    JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, Value*& vp, nanojit::LIns*& ins, NameResult& nr);
+    JS_REQUIRES_STACK AbortableRecordingStatus scopeChainProp(JSObject* obj, const Value*& vp, nanojit::LIns*& ins, NameResult& nr, JSObject **scopeObjp = NULL);
+    JS_REQUIRES_STACK RecordingStatus callProp(JSObject* obj, JSProperty* shape, jsid id, const Value*& vp, nanojit::LIns*& ins, NameResult& nr);
 
     JS_REQUIRES_STACK nanojit::LIns* arg(unsigned n);
     JS_REQUIRES_STACK void arg(unsigned n, nanojit::LIns* i);
     JS_REQUIRES_STACK nanojit::LIns* var(unsigned n);
     JS_REQUIRES_STACK void var(unsigned n, nanojit::LIns* i);
     JS_REQUIRES_STACK nanojit::LIns* upvar(JSScript* script, JSUpvarArray* uva, uintN index, Value& v);
     nanojit::LIns* stackLoad(tjit::Address addr, uint8 type);
     JS_REQUIRES_STACK nanojit::LIns* stack(int n);
@@ -1349,25 +1349,25 @@ class TraceRecorder
     void stobj_set_dslot(nanojit::LIns *obj_ins, unsigned slot,
                          nanojit::LIns*& slots_ins, const Value &v, nanojit::LIns* v_ins);
     void stobj_set_slot(JSObject *obj, nanojit::LIns* obj_ins, unsigned slot,
                         nanojit::LIns*& slots_ins, const Value &v, nanojit::LIns* v_ins);
 
     nanojit::LIns* unbox_slot(JSObject *obj, nanojit::LIns *obj_ins, uint32 slot,
                               VMSideExit *exit);
 
-    JS_REQUIRES_STACK AbortableRecordingStatus name(Value*& vp, nanojit::LIns*& ins, NameResult& nr);
+    JS_REQUIRES_STACK AbortableRecordingStatus name(const Value*& vp, nanojit::LIns*& ins, NameResult& nr);
     JS_REQUIRES_STACK AbortableRecordingStatus prop(JSObject* obj, nanojit::LIns* obj_ins,
                                                     uint32 *slotp, nanojit::LIns** v_insp,
                                                     Value* outp);
     JS_REQUIRES_STACK RecordingStatus propTail(JSObject* obj, nanojit::LIns* obj_ins,
                                                JSObject* obj2, PCVal pcval,
                                                uint32 *slotp, nanojit::LIns** v_insp,
                                                Value* outp);
-    JS_REQUIRES_STACK RecordingStatus denseArrayElement(Value& oval, Value& idx, Value*& vp,
+    JS_REQUIRES_STACK RecordingStatus denseArrayElement(Value& oval, Value& idx, const Value*& vp,
                                                         nanojit::LIns*& v_ins,
                                                         nanojit::LIns*& addr_ins,
                                                         VMSideExit* exit);
     JS_REQUIRES_STACK nanojit::LIns *canonicalizeNaNs(nanojit::LIns *dval_ins);
     JS_REQUIRES_STACK AbortableRecordingStatus typedArrayElement(Value& oval, Value& idx, Value*& vp,
                                                                  nanojit::LIns*& v_ins);
     JS_REQUIRES_STACK AbortableRecordingStatus getProp(JSObject* obj, nanojit::LIns* obj_ins);
     JS_REQUIRES_STACK AbortableRecordingStatus getProp(Value& v);
@@ -1633,17 +1633,17 @@ class TraceRecorder
 
     bool globalSetExpected(unsigned slot) {
         unsigned *pi = Find(pendingGlobalSlotsToSet, slot);
         if (pi == pendingGlobalSlotsToSet.end()) {
             /*
              * Do slot arithmetic manually to avoid getSlotRef assertions which
              * do not need to be satisfied for this purpose.
              */
-            Value *vp = globalObj->getSlots() + slot;
+            const Value *vp = &globalObj->getSlot(slot);
 
             /* If this global is definitely being tracked, then the write is unexpected. */
             if (tracker.has(vp))
                 return false;
             
             /*
              * Otherwise, only abort if the global is not present in the
              * import typemap. Just deep aborting false here is not acceptable,
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -153,27 +153,27 @@ static inline JSBool
 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->slots = tmpslots;
+        obj->setSlotsPtr(tmpslots);
         /*
          * Note that |bytes| may not be a multiple of |sizeof(Value)|, so
          * |capacity * sizeof(Value)| may underestimate the size by up to
          * |sizeof(Value) - 1| bytes.
          */
         obj->capacity = bytes / sizeof(Value);
     } else {
-        memset(obj->slots, 0, bytes);
+        memset(obj->getSlotsPtr(), 0, bytes);
     }
-    *((uint32*)obj->slots) = size;
+    *((uint32*)obj->getSlotsPtr()) = size;
     return true;
 }
 
 static JSObject *
 DelegateObject(JSContext *cx, JSObject *obj)
 {
     if (!obj->getPrivate()) {
         JSObject *delegate = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, obj->getProto(), NULL);
@@ -1317,17 +1317,17 @@ class TypedArrayTemplate
 
         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);
 
-            Value *src = ar->getDenseArrayElements();
+            const Value *src = ar->getDenseArrayElements();
 
             for (uintN i = 0; i < len; ++i)
                 *dest++ = nativeFromValue(cx, *src++);
         } else {
             // slow path
             Value v;
 
             for (uintN i = 0; i < len; ++i) {
@@ -1837,24 +1837,23 @@ js_IsArrayBuffer(JSObject *obj)
 {
     JS_ASSERT(obj);
     return obj->getClass() == &ArrayBuffer::fastClass;
 }
 
 JSUint32
 JS_GetArrayBufferByteLength(JSObject *obj)
 {
-    return *((JSUint32*) obj->slots);
+    return ArrayBuffer::getByteLength(obj);
 }
 
 uint8 *
 JS_GetArrayBufferData(JSObject *obj)
 {
-    uint64 *base = ((uint64*)obj->slots) + 1;
-    return (uint8*) base;
+    return ArrayBuffer::getDataOffset(obj);
 }
 
 JS_FRIEND_API(JSBool)
 js_IsTypedArray(JSObject *obj)
 {
     JS_ASSERT(obj);
     Class *clasp = obj->getClass();
     return clasp >= &TypedArray::fastClasses[0] &&
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -43,18 +43,18 @@
 #include "jsapi.h"
 #include "jsvalue.h"
 #include "jsobj.h"
 
 namespace js {
 inline JSUint32
 ArrayBuffer::getByteLength(JSObject *obj)
 {
-    return *((JSUint32*) obj->slots);
+    return *((JSUint32*) obj->getSlotsPtr());
 }
 
 inline uint8 *
 ArrayBuffer::getDataOffset(JSObject *obj) {
-    uint64 *base = ((uint64*)obj->slots) + 1;
+    uint64 *base = ((uint64*)obj->getSlotsPtr()) + 1;
     return (uint8*) base;
 }
 }
 #endif /* jstypedarrayinlines_h */
--- a/js/src/jsvalue.h
+++ b/js/src/jsvalue.h
@@ -847,16 +847,24 @@ ObjectOrNullValue(JSObject *obj)
 static JS_ALWAYS_INLINE Value
 PrivateValue(void *ptr)
 {
     Value v;
     v.setPrivate(ptr);
     return v;
 }
 
+static JS_ALWAYS_INLINE Value
+PrivateUint32Value(uint32 ui)
+{
+    Value v;
+    v.setPrivateUint32(ui);
+    return v;
+}
+
 static JS_ALWAYS_INLINE void
 ClearValueRange(Value *vec, uintN len, bool useHoles)
 {
     if (useHoles) {
         for (uintN i = 0; i < len; i++)
             vec[i].setMagic(JS_ARRAY_HOLE);
     } else {
         for (uintN i = 0; i < len; i++)
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -254,17 +254,17 @@ static const JSC::MacroAssembler::Regist
         return branchPtr(cond, Address(fun, offsetof(JSObject, clasp)),
                          ImmPtr(&js_FunctionClass));
     }
 
     /*
      * Finds and returns the address of a known object and slot.
      */
     Address objSlotRef(JSObject *obj, RegisterID reg, uint32 slot) {
-        move(ImmPtr(&obj->slots), reg);
+        move(ImmPtr((char *)obj + JSObject::offsetOfSlots()), reg);
         loadPtr(reg, reg);
         return Address(reg, slot * sizeof(Value));
     }
 
     /* Prepare for a call that might THROW. */
     void *getFallibleCallTarget(void *fun) {
 #ifdef JS_CPU_ARM
         /*
@@ -667,17 +667,17 @@ static const JSC::MacroAssembler::Regist
     FastArrayLoadFails fastArrayLoad(RegisterID objReg, const Int32Key &key,
                                      RegisterID typeReg, RegisterID dataReg) {
         JS_ASSERT(objReg != typeReg);
 
         FastArrayLoadFails fails;
         fails.rangeCheck = guardArrayCapacity(objReg, key);
 
         RegisterID dslotsReg = objReg;
-        loadPtr(Address(objReg, offsetof(JSObject, slots)), dslotsReg);
+        loadPtr(Address(objReg, JSObject::offsetOfSlots()), dslotsReg);
 
         // Load the slot out of the array.
         if (key.isConstant()) {
             Address slot(objReg, key.index() * sizeof(Value));
             fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg);
         } else {
             BaseIndex slot(objReg, key.reg(), JSVAL_SCALE);
             fails.holeCheck = fastArrayLoadSlot(slot, typeReg, dataReg);
@@ -702,17 +702,17 @@ static const JSC::MacroAssembler::Regist
         if (remat.inMemory())
             loadPayload(remat.address(), reg);
         else
             move(remat.reg(), reg);
     }
 
     void loadDynamicSlot(RegisterID objReg, uint32 slot,
                          RegisterID typeReg, RegisterID dataReg) {
-        loadPtr(Address(objReg, offsetof(JSObject, slots)), dataReg);
+        loadPtr(Address(objReg, JSObject::offsetOfSlots()), dataReg);
         loadValueAsComponents(Address(dataReg, slot * sizeof(Value)), typeReg, dataReg);
     }
 
     void loadObjProp(JSObject *obj, RegisterID objReg,
                      const js::Shape *shape,
                      RegisterID typeReg, RegisterID dataReg)
     {
         if (shape->isMethod())
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -4834,17 +4834,17 @@ mjit::Compiler::enterBlock(JSObject *obj
     uint32 n = js_GetEnterBlockStackDefs(cx, script, PC);
     INLINE_STUBCALL(stubs::EnterBlock);
     frame.enterBlock(n);
 
     uintN base = JSSLOT_FREE(&js_BlockClass);
     uintN count = OBJ_BLOCK_COUNT(cx, obj);
     uintN limit = base + count;
     for (uintN slot = base, i = 0; slot < limit; slot++, i++) {
-        const Value &v = obj->getSlotRef(slot);
+        const Value &v = obj->getSlot(slot);
         if (v.isBoolean() && v.toBoolean())
             frame.setClosedVar(oldFrameDepth + i);
     }
 }
 
 void
 mjit::Compiler::leaveBlock()
 {
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -195,30 +195,30 @@ AttachSetGlobalNameStub(VMFrame &f, ic::
         masm.move(ImmPtr(obj), ic->objReg);
 
     JS_ASSERT(obj->branded());
 
     /*
      * Load obj->slots. If ic->objConst, then this clobbers objReg, because
      * ic->objReg == ic->shapeReg.
      */
-    masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg);
+    masm.loadPtr(Address(ic->objReg, JSObject::offsetOfSlots()), ic->shapeReg);
 
     /* Test if overwriting a function-tagged slot. */
     Address slot(ic->shapeReg, sizeof(Value) * shape->slot);
     Jump isNotObject = masm.testObject(Assembler::NotEqual, slot);
 
     /* Now, test if the object is a function object. */
     masm.loadPayload(slot, ic->shapeReg);
     Jump isFun = masm.testFunction(Assembler::Equal, ic->shapeReg);
 
     /* Restore shapeReg to obj->slots, since we clobbered it. */
     if (ic->objConst)
         masm.move(ImmPtr(obj), ic->objReg);
-    masm.loadPtr(Address(ic->objReg, offsetof(JSObject, slots)), ic->shapeReg);
+    masm.loadPtr(Address(ic->objReg, JSObject::offsetOfSlots()), ic->shapeReg);
 
     /* If the object test fails, shapeReg is still obj->slots. */
     isNotObject.linkTo(masm.label(), &masm);
     DataLabel32 store = masm.storeValueWithAddressOffsetPatch(ic->vr, slot);
 
     Jump done = masm.jump();
 
     JITScript *jit = f.jit();
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -232,17 +232,17 @@ class SetPropCompiler : public PICStubCo
             //
             // We've patched | mov dslots, [obj + DSLOTS_OFFSET]
             // To:           | lea fslots, [obj + DSLOTS_OFFSET]
             //
             // Because the offset is wrong, it's necessary to correct it
             // below.
             //
             int32 diff = int32(JSObject::getFixedSlotOffset(0)) -
-                         int32(offsetof(JSObject, slots));
+                         int32(JSObject::offsetOfSlots());
             JS_ASSERT(diff != 0);
             offset  = (int32(shape->slot) * sizeof(Value)) + diff;
         } else {
             offset = shape->slot * sizeof(Value);
         }
 
         repatcher.repatch(labels.getInlineShapeData(pic.fastPathStart, pic.shapeGuard),
                           obj->shape());
@@ -348,17 +348,17 @@ class SetPropCompiler : public PICStubCo
                 /* Check capacity. */
                 Address capacity(pic.objReg, offsetof(JSObject, capacity));
                 masm.load32(capacity, pic.shapeReg);
                 Jump overCapacity = masm.branch32(Assembler::LessThanOrEqual, pic.shapeReg,
                                                   Imm32(shape->slot));
                 if (!slowExits.append(overCapacity))
                     return error();
 
-                masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.shapeReg);
+                masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.shapeReg);
                 Address address(pic.shapeReg, shape->slot * sizeof(Value));
                 masm.storeValue(pic.u.vr, address);
             }
 
             uint32 newShape = obj->shape();
             JS_ASSERT(newShape != initialShape);
 
             /* Write the object's new shape. */
@@ -372,17 +372,17 @@ class SetPropCompiler : public PICStubCo
                 /* Use shapeReg to load, bitwise-or, and store flags. */
                 masm.load32(flags, pic.shapeReg);
                 masm.or32(Imm32(JSObject::METHOD_BARRIER), pic.shapeReg);
                 masm.store32(pic.shapeReg, flags);
             }
         } else if (shape->hasDefaultSetter()) {
             Address address(pic.objReg, JSObject::getFixedSlotOffset(shape->slot));
             if (!inlineSlot) {
-                masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg);
+                masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg);
                 address = Address(pic.objReg, shape->slot * sizeof(Value));
             }
 
             // If the scope is branded, or has a method barrier. It's now necessary
             // to guard that we're not overwriting a function-valued property.
             if (obj->brandedOrHasMethodBarrier()) {
                 masm.loadTypeTag(address, pic.shapeReg);
                 Jump skip = masm.testObject(Assembler::NotEqual, pic.shapeReg);
@@ -417,17 +417,17 @@ class SetPropCompiler : public PICStubCo
                 masm.storeValue(pic.u.vr, addr);
                 skipOver = masm.jump();
             }
 
             escapedFrame.linkTo(masm.label(), &masm);
             {
                 if (shape->setterOp() == SetCallVar)
                     slot += fun->nargs;
-                masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg);
+                masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg);
 
                 Address dslot(pic.objReg, (slot + JSObject::CALL_RESERVED_SLOTS) * sizeof(Value));
                 masm.storeValue(pic.u.vr, dslot);
             }
 
             pic.shapeRegHasBaseShape = false;
         }
 
@@ -1413,17 +1413,17 @@ class ScopeNameCompiler : public PICStub
             masm.loadPayload(addr, pic.objReg);
             masm.loadTypeTag(addr, pic.shapeReg);
             skipOver = masm.jump();
         }
 
         escapedFrame.linkTo(masm.label(), &masm);
 
         {
-            masm.loadPtr(Address(pic.objReg, offsetof(JSObject, slots)), pic.objReg);
+            masm.loadPtr(Address(pic.objReg, JSObject::offsetOfSlots()), pic.objReg);
 
             if (kind == VAR)
                 slot += fun->nargs;
             Address dslot(pic.objReg, (slot + JSObject::CALL_RESERVED_SLOTS) * sizeof(Value));
 
             /* Safe because type is loaded first. */
             masm.loadValueAsComponents(dslot, pic.shapeReg, pic.objReg);
         }
@@ -2750,17 +2750,17 @@ SetElementIC::attachHoleStub(JSContext *
         skipUpdate = masm.branch32(Assembler::Above, arrayLength, keyReg);
         masm.add32(Imm32(1), keyReg);
         masm.store32(keyReg, arrayLength);
         masm.sub32(Imm32(1), keyReg);
     }
     skipUpdate.linkTo(masm.label(), &masm);
 
     // Store the value back.
-    masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
+    masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg);
     if (hasConstantKey) {
         Address slot(objReg, keyValue * sizeof(Value));
         masm.storeValue(vr, slot);
     } else {
         BaseIndex slot(objReg, keyReg, Assembler::JSVAL_SCALE);
         masm.storeValue(vr, slot);
     }
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -439,26 +439,26 @@ stubs::GetElem(VMFrame &f)
     jsid id;
     if (rref.isInt32()) {
         int32_t i = rref.toInt32();
         if (obj->isDenseArray()) {
             jsuint idx = jsuint(i);
 
             if (idx < obj->getArrayLength() &&
                 idx < obj->getDenseArrayCapacity()) {
-                copyFrom = obj->addressOfDenseArrayElement(idx);
+                copyFrom = &obj->getDenseArrayElement(idx);
                 if (!copyFrom->isMagic())
                     goto end_getelem;
             }
         } else if (obj->isArguments()) {
             uint32 arg = uint32(i);
             ArgumentsObject *argsobj = obj->asArguments();
 
             if (arg < argsobj->initialLength()) {
-                copyFrom = argsobj->addressOfElement(arg);
+                copyFrom = &argsobj->element(arg);
                 if (!copyFrom->isMagic()) {
                     if (StackFrame *afp = (StackFrame *) argsobj->getPrivate())
                         copyFrom = &afp->canonicalActualArg(arg);
                     goto end_getelem;
                 }
             }
         }
         if (JS_LIKELY(INT_FITS_IN_JSID(i)))
@@ -1541,23 +1541,23 @@ NameIncDec(VMFrame &f, JSObject *obj, JS
     JSAtom *atom;
     JSObject *obj2;
     JSProperty *prop;
     PropertyCacheEntry *entry;
     JS_PROPERTY_CACHE(cx).test(cx, f.regs.pc, obj, obj2, entry, atom);
     if (!atom) {
         if (obj == obj2 && entry->vword.isSlot()) {
             uint32 slot = entry->vword.toSlot();
-            Value &rref = obj->nativeGetSlotRef(slot);
+            const Value &rval = obj->nativeGetSlot(slot);
             int32_t tmp;
-            if (JS_LIKELY(rref.isInt32() && CanIncDecWithoutOverflow(tmp = rref.toInt32()))) {
+            if (JS_LIKELY(rval.isInt32() && CanIncDecWithoutOverflow(tmp = rval.toInt32()))) {
                 int32_t inc = tmp + N;
                 if (!POST)
                     tmp = inc;
-                rref.getInt32Ref() = inc;
+                obj->nativeSetSlot(slot, Int32Value(inc));
                 f.regs.sp[0].setInt32(tmp);
                 return true;
             }
         }
         atom = origAtom;
     }
 
     jsid id = ATOM_TO_JSID(atom);
--- a/js/src/tracejit/Writer.h
+++ b/js/src/tracejit/Writer.h
@@ -524,17 +524,17 @@ class Writer
 
     nj::LIns *ldiDenseArrayCapacity(nj::LIns *array) const {
         return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, capacity),
                                  ACCSET_OBJ_CAPACITY),
                     "capacity");
     }
 
     nj::LIns *ldpObjSlots(nj::LIns *obj) const {
-        return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS),
+        return name(lir->insLoad(nj::LIR_ldp, obj, JSObject::offsetOfSlots(), ACCSET_OBJ_SLOTS),
                     "slots");
     }
 
     nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const {
         return name(lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY,
                                  nj::LOAD_CONST),
                     "typedArrayLength");
     }
--- a/js/src/vm/ArgumentsObject-inl.h
+++ b/js/src/vm/ArgumentsObject-inl.h
@@ -60,17 +60,18 @@ ArgumentsObject::initialLength() const
     uint32 argc = uint32(getSlot(INITIAL_LENGTH_SLOT).toInt32()) >> PACKED_BITS_COUNT;
     JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
     return argc;
 }
 
 inline void
 ArgumentsObject::markLengthOverridden()
 {
-    getSlotRef(INITIAL_LENGTH_SLOT).getInt32Ref() |= LENGTH_OVERRIDDEN_BIT;
+    uint32 v = getSlot(INITIAL_LENGTH_SLOT).toInt32() | LENGTH_OVERRIDDEN_BIT;
+    setSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
 }
 
 inline bool
 ArgumentsObject::hasOverriddenLength() const
 {
     const js::Value &v = getSlot(INITIAL_LENGTH_SLOT);
     return v.toInt32() & LENGTH_OVERRIDDEN_BIT;
 }
@@ -91,29 +92,22 @@ ArgumentsObject::data() const
 
 inline const js::Value &
 ArgumentsObject::element(uint32 i) const
 {
     JS_ASSERT(i < initialLength());
     return data()->slots[i];
 }
 
-inline js::Value *
+inline const js::Value *
 ArgumentsObject::elements() const
 {
     return data()->slots;
 }
 
-inline Value *
-ArgumentsObject::addressOfElement(uint32 i)
-{
-    JS_ASSERT(i < initialLength());
-    return &data()->slots[i];
-}
-
 inline void
 ArgumentsObject::setElement(uint32 i, const js::Value &v)
 {
     JS_ASSERT(i < initialLength());
     data()->slots[i] = v;
 }
 
 inline const js::Value &
--- a/js/src/vm/ArgumentsObject.h
+++ b/js/src/vm/ArgumentsObject.h
@@ -222,18 +222,17 @@ class ArgumentsObject : public ::JSObjec
      *
      * NB: Returning false does not indicate error!
      */
     inline bool getElements(uint32 start, uint32 count, js::Value *vp);
 
     inline js::ArgumentsData *data() const;
 
     inline const js::Value &element(uint32 i) const;
-    inline js::Value *elements() const;
-    inline js::Value *addressOfElement(uint32 i);
+    inline const js::Value *elements() const;
     inline void setElement(uint32 i, const js::Value &v);
 };
 
 /*
  * Non-strict arguments have a private: the function's stack frame until the
  * function returns, when it is replaced with null.  When an arguments object
  * is created on-trace its private is JS_ARGUMENTS_OBJECT_ON_TRACE, and when
  * the trace exits its private is replaced with the stack frame or null, as
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -191,18 +191,18 @@ GlobalObject::isRuntimeCodeGenEnabled(JS
     Value &v = getSlotRef(RUNTIME_CODEGEN_ENABLED);
     if (v.isUndefined()) {
         JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
 
         /*
          * If there are callbacks, make sure that the CSP callback is installed
          * and that it permits runtime code generation, then cache the result.
          */
-        v.setBoolean((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
-                     callbacks->contentSecurityPolicyAllows(cx));
+        v = BooleanValue((!callbacks || !callbacks->contentSecurityPolicyAllows) ||
+                         callbacks->contentSecurityPolicyAllows(cx));
     }
     return !v.isFalse();
 }
 
 JSFunction *
 GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name,
                                 uintN length)
 {
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -124,21 +124,21 @@ class GlobalObject : public ::JSObject {
      * prototype objects with particular internal structure (e.g. reserved
      * slots guaranteed to contain values of particular types) must immediately
      * complete the minimal initialization to make the returned object safe to
      * touch.
      */
     JSObject *createBlankPrototype(JSContext *cx, js::Class *clasp);
 
     void setThrowTypeError(JSFunction *fun) {
-        Value &v = getSlotRef(THROWTYPEERROR);
         // Our bootstrapping code is currently too convoluted to correctly and
         // confidently assert this.
         // JS_ASSERT(v.isUndefined());
-        v.setObject(*fun);
+        // JS_ASSERT(getSlot(THROWTYPEERROR).isUndefined());
+        setSlot(THROWTYPEERROR, ObjectValue(*fun));
     }
 
     JSObject *getThrowTypeError() const {
         return &getSlot(THROWTYPEERROR).toObject();
     }
 
     Value getRegExpStatics() const {
         return getSlot(REGEXP_STATICS);
@@ -152,21 +152,21 @@ class GlobalObject : public ::JSObject {
 
     bool isRuntimeCodeGenEnabled(JSContext *cx);
 
     const Value &getOriginalEval() const {
         return getSlot(EVAL);
     }
 
     void setOriginalEval(JSObject *evalobj) {
-        Value &v = getSlotRef(EVAL);
         // Our bootstrapping code is currently too convoluted to correctly and
         // confidently assert this.
         // JS_ASSERT(v.isUndefined());
-        v.setObject(*evalobj);
+        // JS_ASSERT(getSlot(EVAL).isUndefined());
+        setSlot(EVAL, ObjectValue(*evalobj));
     }
 
     bool getFunctionNamespace(JSContext *cx, Value *vp);
 
     bool initStandardClasses(JSContext *cx);
 };
 
 /*
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -595,19 +595,20 @@ ArgumentsObject::getElements(uint32 star
     uint32 length = initialLength();
     if (start > length || start + count > length)
         return false;
 
     StackFrame *fp = reinterpret_cast<StackFrame *>(getPrivate());
 
     /* If there's no stack frame for this, argument values are in elements(). */
     if (!fp) {
-        Value *srcbeg = elements() + start;
-        Value *srcend = srcbeg + count;
-        for (Value *dst = vp, *src = srcbeg; src < srcend; ++dst, ++src) {
+        const Value *srcbeg = elements() + start;
+        const Value *srcend = srcbeg + count;
+        const Value *src = srcbeg;
+        for (Value *dst = vp; src < srcend; ++dst, ++src) {
             if (src->isMagic(JS_ARGS_HOLE))
                 return false;
             *dst = *src;
         }
         return true;
     }
 
     /* If we're on trace, there's no canonical location for elements: fail. */