Back out 08fd9aa0d6e1 (bug 810102) for turning bug 728834 permaorange
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 12 Nov 2012 21:01:17 -0800
changeset 120963 1b0226622e94b2c7aedc16ade4ac23e98f8e407e
parent 120962 7c8fa27e95be7dfa24a8123b0dfcc6a391446580
child 120996 24babe39cd7e49b531f003478eab98f9e29060bc
push id1997
push userakeybl@mozilla.com
push dateMon, 07 Jan 2013 21:25:26 +0000
treeherdermozilla-beta@4baf45cdcf21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs810102, 728834
milestone19.0a1
backs out08fd9aa0d6e1d9e1493eed9013422bbcd3dcfb60
first release with
nightly linux32
1b0226622e94 / 19.0a1 / 20121113030658 / files
nightly linux64
1b0226622e94 / 19.0a1 / 20121113030658 / files
nightly mac
1b0226622e94 / 19.0a1 / 20121113030658 / files
nightly win32
1b0226622e94 / 19.0a1 / 20121113030658 / files
nightly win64
1b0226622e94 / 19.0a1 / 20121113030658 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Back out 08fd9aa0d6e1 (bug 810102) for turning bug 728834 permaorange
js/src/gc/Marking.cpp
js/src/gc/Root.h
js/src/jsfriendapi.cpp
js/src/jsfriendapi.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsgcinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsscope.cpp
js/src/jsscope.h
js/src/jsscopeinlines.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -261,29 +261,29 @@ DeclMarkerImpl(XML, JSXML)
 void
 MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     JS_ASSERT(thingp);
     JS_ASSERT(*thingp);
     JS_ASSERT(kind == GetGCThingTraceKind(*thingp));
     switch (kind) {
       case JSTRACE_OBJECT:
-        MarkInternal(trc, reinterpret_cast<RawObject *>(thingp));
+        MarkInternal(trc, reinterpret_cast<JSObject **>(thingp));
         break;
       case JSTRACE_STRING:
-        MarkInternal(trc, reinterpret_cast<RawString *>(thingp));
+        MarkInternal(trc, reinterpret_cast<JSString **>(thingp));
         break;
       case JSTRACE_SCRIPT:
-        MarkInternal(trc, reinterpret_cast<RawScript *>(thingp));
+        MarkInternal(trc, reinterpret_cast<JSScript **>(thingp));
         break;
       case JSTRACE_SHAPE:
         MarkInternal(trc, reinterpret_cast<Shape **>(thingp));
         break;
       case JSTRACE_BASE_SHAPE:
-        MarkInternal(trc, reinterpret_cast<RawBaseShape *>(thingp));
+        MarkInternal(trc, reinterpret_cast<BaseShape **>(thingp));
         break;
       case JSTRACE_TYPE_OBJECT:
         MarkInternal(trc, reinterpret_cast<types::TypeObject **>(thingp));
         break;
       case JSTRACE_IONCODE:
         MarkInternal(trc, reinterpret_cast<ion::IonCode **>(thingp));
         break;
 #if JS_HAS_XML_SUPPORT
@@ -628,47 +628,47 @@ PushMarkStack(GCMarker *gcmarker, ion::I
 {
     JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         gcmarker->pushIonCode(thing);
 }
 
 static inline void
-ScanBaseShape(GCMarker *gcmarker, RawBaseShape base);
+ScanBaseShape(GCMarker *gcmarker, BaseShape *base);
 
 static void
-PushMarkStack(GCMarker *gcmarker, RawBaseShape thing)
+PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
 {
     JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
 
     /* We mark base shapes directly rather than pushing on the stack. */
     if (thing->markIfUnmarked(gcmarker->getMarkColor()))
         ScanBaseShape(gcmarker, thing);
 }
 
 static void
 ScanShape(GCMarker *gcmarker, Shape *shape)
 {
   restart:
-    PushMarkStack(gcmarker, shape->base().unsafeGet());
+    PushMarkStack(gcmarker, shape->base());
 
     const EncapsulatedId &id = shape->propidRef();
     if (JSID_IS_STRING(id))
         PushMarkStack(gcmarker, JSID_TO_STRING(id));
     else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
         PushMarkStack(gcmarker, JSID_TO_OBJECT(id));
 
     shape = shape->previous();
     if (shape && shape->markIfUnmarked(gcmarker->getMarkColor()))
         goto restart;
 }
 
 static inline void
-ScanBaseShape(GCMarker *gcmarker, RawBaseShape base)
+ScanBaseShape(GCMarker *gcmarker, BaseShape *base)
 {
     base->assertConsistency();
 
     if (base->hasGetterObject())
         PushMarkStack(gcmarker, base->getterObject());
 
     if (base->hasSetterObject())
         PushMarkStack(gcmarker, base->setterObject());
@@ -811,31 +811,31 @@ MarkChildren(JSTracer *trc, JSScript *sc
 
 static void
 MarkChildren(JSTracer *trc, Shape *shape)
 {
     shape->markChildren(trc);
 }
 
 static void
-MarkChildren(JSTracer *trc, RawBaseShape base)
+MarkChildren(JSTracer *trc, BaseShape *base)
 {
     base->markChildren(trc);
 }
 
 /*
  * This function is used by the cycle collector to trace through the
  * children of a BaseShape (and its baseUnowned(), if any). The cycle
  * collector does not directly care about BaseShapes, so only the
  * getter, setter, and parent are marked. Furthermore, the parent is
  * marked only if it isn't the same as prevParent, which will be
  * updated to the current shape's parent.
  */
 inline void
-MarkCycleCollectorChildren(JSTracer *trc, RawBaseShape base, RawObject *prevParent)
+MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent)
 {
     JS_ASSERT(base);
 
     /*
      * The cycle collector does not need to trace unowned base shapes,
      * as they have the same getter, setter and parent as the original
      * base shape.
      */
@@ -867,19 +867,19 @@ MarkCycleCollectorChildren(JSTracer *trc
  * shapes, so those are not marked. Instead, any shapes or base shapes
  * that are encountered have their children marked. Stack space is
  * bounded. If two shapes in a row have the same parent pointer, the
  * parent pointer will only be marked once.
  */
 void
 MarkCycleCollectorChildren(JSTracer *trc, Shape *shape)
 {
-    RawObject prevParent = NULL;
+    JSObject *prevParent = NULL;
     do {
-        MarkCycleCollectorChildren(trc, shape->base().unsafeGet(), &prevParent);
+        MarkCycleCollectorChildren(trc, shape->base(), &prevParent);
         MarkId(trc, &shape->propidRef(), "propid");
         shape = shape->previous();
     } while (shape);
 }
 
 static void
 ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
 {
@@ -1324,37 +1324,37 @@ GCMarker::drainMarkStack(SliceBudget &bu
     return true;
 }
 
 void
 TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
 {
     switch (kind) {
       case JSTRACE_OBJECT:
-        MarkChildren(trc, static_cast<RawObject>(thing));
+        MarkChildren(trc, static_cast<JSObject *>(thing));
         break;
 
       case JSTRACE_STRING:
-        MarkChildren(trc, static_cast<RawString>(thing));
+        MarkChildren(trc, static_cast<JSString *>(thing));
         break;
 
       case JSTRACE_SCRIPT:
-        MarkChildren(trc, static_cast<RawScript>(thing));
+        MarkChildren(trc, static_cast<JSScript *>(thing));
         break;
 
       case JSTRACE_SHAPE:
         MarkChildren(trc, static_cast<Shape *>(thing));
         break;
 
       case JSTRACE_IONCODE:
         MarkChildren(trc, (js::ion::IonCode *)thing);
         break;
 
       case JSTRACE_BASE_SHAPE:
-        MarkChildren(trc, static_cast<RawBaseShape>(thing));
+        MarkChildren(trc, static_cast<BaseShape *>(thing));
         break;
 
       case JSTRACE_TYPE_OBJECT:
         MarkChildren(trc, (types::TypeObject *)thing);
         break;
 
 #if JS_HAS_XML_SUPPORT
       case JSTRACE_XML:
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -389,18 +389,16 @@ class IntermediateNoGC
  * If Shape::parent were an accessor function returning a Return<Shape*>, this
  * could not happen: Return ensures either immediate rooting or no GC within
  * the same expression.
  */
 template <typename T>
 class Return
 {
     friend class Rooted<T>;
-    typedef void (Return<T>::* ConvertibleToBool)();
-    void nonNull() {}
 
     const T ptr_;
 
   public:
     template <typename S>
     Return(const S &ptr,
            typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
       : ptr_(ptr)
@@ -475,17 +473,16 @@ class Return
      *     JS_ASSERT(myScript == fun->script().unsafeGet());
      *
      * To be rewritten as:
      *     JS_ASSERT(fun->script() == myScript);
      *
      * Note: the new order tells C++ to use |Return<JSScript*>::operator=|
      *       instead of direct pointer comparison.
      */
-    operator ConvertibleToBool() const { return ptr_ ? &Return<T>::nonNull : 0; }
     bool operator==(const T &other) { return ptr_ == other; }
     bool operator!=(const T &other) { return ptr_ != other; }
     bool operator==(const Return<T> &other) { return ptr_ == other.ptr_; }
     bool operator==(const JS::Handle<T> &other) { return ptr_ == other.get(); }
     inline bool operator==(const Rooted<T> &other);
 };
 
 /*
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -904,25 +904,25 @@ IncrementalReferenceBarrier(void *ptr)
 
     gc::Cell *cell = static_cast<gc::Cell *>(ptr);
     JS_ASSERT(!cell->compartment()->rt->isHeapBusy());
 
     AutoMarkInDeadCompartment amn(cell->compartment());
 
     uint32_t kind = gc::GetGCThingTraceKind(ptr);
     if (kind == JSTRACE_OBJECT)
-        JSObject::writeBarrierPre(reinterpret_cast<RawObject>(ptr));
+        JSObject::writeBarrierPre((JSObject *) ptr);
     else if (kind == JSTRACE_STRING)
-        JSString::writeBarrierPre(reinterpret_cast<RawString>(ptr));
+        JSString::writeBarrierPre((JSString *) ptr);
     else if (kind == JSTRACE_SCRIPT)
-        JSScript::writeBarrierPre(reinterpret_cast<RawScript>(ptr));
+        JSScript::writeBarrierPre((JSScript *) ptr);
     else if (kind == JSTRACE_SHAPE)
         Shape::writeBarrierPre((Shape *) ptr);
     else if (kind == JSTRACE_BASE_SHAPE)
-        BaseShape::writeBarrierPre(reinterpret_cast<RawBaseShape>(ptr));
+        BaseShape::writeBarrierPre((BaseShape *) ptr);
     else if (kind == JSTRACE_TYPE_OBJECT)
         types::TypeObject::writeBarrierPre((types::TypeObject *) ptr);
     else
         JS_NOT_REACHED("invalid trace kind");
 }
 
 extern JS_FRIEND_API(void)
 IncrementalValueBarrier(const Value &v)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -294,39 +294,39 @@ IterateGrayObjects(JSCompartment *compar
  * Shadow declarations of JS internal structures, for access by inline access
  * functions below. Do not use these structures in any other way. When adding
  * new fields for access by inline methods, make sure to add static asserts to
  * the original header file to ensure that offsets are consistent.
  */
 namespace shadow {
 
 struct TypeObject {
-    RawObject proto;
+    JSObject    *proto;
 };
 
 struct BaseShape {
-    js::Class *clasp;
-    RawObject parent;
+    js::Class   *clasp;
+    JSObject    *parent;
 };
 
 struct Shape {
-    shadow::BaseShape *base;
-    jsid              _1;
-    uint32_t          slotInfo;
+    BaseShape   *base;
+    jsid        _1;
+    uint32_t    slotInfo;
 
     static const uint32_t FIXED_SLOTS_SHIFT = 27;
 };
 
 struct Object {
-    shadow::Shape      *shape;
-    shadow::TypeObject *type;
-    js::Value          *slots;
-    js::Value          *_1;
+    Shape       *shape;
+    TypeObject  *type;
+    js::Value   *slots;
+    js::Value   *_1;
 
-    size_t numFixedSlots() const { return shape->slotInfo >> shadow::Shape::FIXED_SLOTS_SHIFT; }
+    size_t numFixedSlots() const { return shape->slotInfo >> Shape::FIXED_SLOTS_SHIFT; }
     Value *fixedSlots() const {
         return (Value *)(uintptr_t(this) + sizeof(shadow::Object));
     }
 
     js::Value &slotRef(size_t slot) const {
         size_t nfixed = numFixedSlots();
         if (slot < nfixed)
             return fixedSlots()[slot];
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1008,17 +1008,17 @@ JSFunction::initBoundFunction(JSContext 
      * value and arguments count.
      */
     if (!self->toDictionaryMode(cx))
         return false;
 
     if (!self->setFlag(cx, BaseShape::BOUND_FUNCTION))
         return false;
 
-    if (!JSObject::setSlotSpan(cx, self, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
+    if (!self->setSlotSpan(cx, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
         return false;
 
     self->setSlot(JSSLOT_BOUND_FUNCTION_THIS, thisArg);
     self->setSlot(JSSLOT_BOUND_FUNCTION_ARGS_COUNT, PrivateUint32Value(argslen));
 
     self->initSlotRange(BOUND_FUNCTION_RESERVED_SLOTS, args, argslen);
 
     return true;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -962,17 +962,17 @@ MarkExactStackRooter(JSTracer *trc, Root
     if (!*addr)
         return;
 
     switch (kind) {
       case THING_ROOT_OBJECT:      MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break;
       case THING_ROOT_STRING:      MarkStringRoot(trc, (JSSTring **)addr, "exact-string"); break;
       case THING_ROOT_SCRIPT:      MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break;
       case THING_ROOT_SHAPE:       MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break;
-      case THING_ROOT_BASE_SHAPE:  MarkBaseShapeRoot(trc, (RawBaseShape *)addr, "exact-baseshape"); break;
+      case THING_ROOT_BASE_SHAPE:  MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break;
       case THING_ROOT_TYPE:        MarkTypeRoot(trc, (types::Type *)addr, "exact-type"); break;
       case THING_ROOT_TYPE_OBJECT: MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact-typeobject"); break;
       case THING_ROOT_VALUE:       MarkValueRoot(trc, (Value *)addr, "exact-value"); break;
       case THING_ROOT_ID:          MarkIdRoot(trc, (jsid *)addr, "exact-id"); break;
       case THING_ROOT_PROPERTY_ID: MarkIdRoot(trc, &((js::PropertyId *)addr)->asId(), "exact-propertyid"); break;
       case THING_ROOT_BINDINGS:    ((Bindings *)addr)->trace(trc); break;
       default: JS_NOT_REACHED("Invalid THING_ROOT kind"); break;
     }
@@ -2330,17 +2330,17 @@ AutoGCRooter::trace(JSTracer *trc)
         Shape::Range::AutoRooter *rooter = static_cast<Shape::Range::AutoRooter *>(this);
         rooter->trace(trc);
         return;
       }
 
       case STACKSHAPE: {
         StackShape::AutoRooter *rooter = static_cast<StackShape::AutoRooter *>(this);
         if (rooter->shape->base)
-            MarkBaseShapeRoot(trc, (RawBaseShape*) &rooter->shape->base, "StackShape::AutoRooter base");
+            MarkBaseShapeRoot(trc, (BaseShape**) &rooter->shape->base, "StackShape::AutoRooter base");
         MarkIdRoot(trc, (jsid*) &rooter->shape->propid, "StackShape::AutoRooter id");
         return;
       }
 
       case STACKBASESHAPE: {
         StackBaseShape::AutoRooter *rooter = static_cast<StackBaseShape::AutoRooter *>(this);
         if (rooter->base->parent)
             MarkObjectRoot(trc, (JSObject**) &rooter->base->parent, "StackBaseShape::AutoRooter parent");
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -524,61 +524,69 @@ TryNewGCThing(JSContext *cx, js::gc::All
 }
 
 } /* namespace gc */
 } /* namespace js */
 
 inline JSObject *
 js_NewGCObject(JSContext *cx, js::gc::AllocKind kind)
 {
+    AssertCanGC();
     JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
     return js::gc::NewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
 }
 
 inline JSObject *
 js_TryNewGCObject(JSContext *cx, js::gc::AllocKind kind)
 {
+    AssertCanGC();
     JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
     return js::gc::TryNewGCThing<JSObject>(cx, kind, js::gc::Arena::thingSize(kind));
 }
 
 inline JSString *
 js_NewGCString(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<JSString>(cx, js::gc::FINALIZE_STRING, sizeof(JSString));
 }
 
 inline JSShortString *
 js_NewGCShortString(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<JSShortString>(cx, js::gc::FINALIZE_SHORT_STRING, sizeof(JSShortString));
 }
 
 inline JSExternalString *
 js_NewGCExternalString(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<JSExternalString>(cx, js::gc::FINALIZE_EXTERNAL_STRING,
                                                 sizeof(JSExternalString));
 }
 
 inline JSScript *
 js_NewGCScript(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<JSScript>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
 }
 
 inline js::Shape *
 js_NewGCShape(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<js::Shape>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
 }
 
-inline js::Return<js::BaseShape*>
+inline js::BaseShape *
 js_NewGCBaseShape(JSContext *cx)
 {
+    AssertCanGC();
     return js::gc::NewGCThing<js::BaseShape>(cx, js::gc::FINALIZE_BASE_SHAPE, sizeof(js::BaseShape));
 }
 
 #if JS_HAS_XML_SUPPORT
 extern JSXML *
 js_NewGCXML(JSContext *cx);
 #endif
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3271,29 +3271,29 @@ JSObject::setLastProperty(JSContext *cx,
 
     if (!updateSlotsForSpan(cx, obj, oldSpan, newSpan))
         return false;
 
     obj->shape_ = shape;
     return true;
 }
 
-/* static */ bool
-JSObject::setSlotSpan(JSContext *cx, HandleObject obj, uint32_t span)
+bool
+JSObject::setSlotSpan(JSContext *cx, uint32_t span)
 {
-    AssertCanGC();
-    JS_ASSERT(obj->inDictionaryMode());
-    Rooted<BaseShape*> base(cx, obj->lastProperty()->base());
+    JS_ASSERT(inDictionaryMode());
+    js::BaseShape *base = lastProperty()->base();
 
     size_t oldSpan = base->slotSpan();
 
     if (oldSpan == span)
         return true;
 
-    if (!JSObject::updateSlotsForSpan(cx, obj, oldSpan, span))
+    RootedObject self(cx, this);
+    if (!JSObject::updateSlotsForSpan(cx, self, oldSpan, span))
         return false;
 
     base->setSlotSpan(span);
     return true;
 }
 
 /* static */ bool
 JSObject::growSlots(JSContext *cx, HandleObject obj, uint32_t oldCount, uint32_t newCount)
@@ -3716,26 +3716,24 @@ js_FindClassObject(JSContext *cx, JSProt
     }
     vp.set(v);
     return true;
 }
 
 bool
 JSObject::allocSlot(JSContext *cx, uint32_t *slotp)
 {
-    AssertCanGC();
     uint32_t slot = slotSpan();
     JS_ASSERT(slot >= JSSLOT_FREE(getClass()));
 
     /*
      * If this object is in dictionary mode, try to pull a free slot from the
      * shape table's slot-number freelist.
      */
     if (inDictionaryMode()) {
-        AutoAssertNoGC nogc;
         ShapeTable &table = lastProperty()->table();
         uint32_t last = table.freelist;
         if (last != SHAPE_INVALID_SLOT) {
 #ifdef DEBUG
             JS_ASSERT(last < slot);
             uint32_t next = getSlot(last).toPrivateUint32();
             JS_ASSERT_IF(next != SHAPE_INVALID_SLOT, next < slot);
 #endif
@@ -3751,18 +3749,17 @@ JSObject::allocSlot(JSContext *cx, uint3
 
     if (slot >= SHAPE_MAXIMUM_SLOT) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     *slotp = slot;
 
-    RootedObject self(cx, this);
-    if (inDictionaryMode() && !setSlotSpan(cx, self, slot + 1))
+    if (inDictionaryMode() && !setSlotSpan(cx, slot + 1))
         return false;
 
     return true;
 }
 
 void
 JSObject::freeSlot(uint32_t slot)
 {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -306,17 +306,17 @@ struct JSObject : public js::ObjectImpl
      */
     inline void removeLastProperty(JSContext *cx);
     inline bool canRemoveLastProperty();
 
     /*
      * Update the slot span directly for a dictionary object, and allocate
      * slots to cover the new span if necessary.
      */
-    static bool setSlotSpan(JSContext *cx, JS::HandleObject obj, uint32_t span);
+    bool setSlotSpan(JSContext *cx, uint32_t span);
 
     /* Upper bound on the number of elements in an object. */
     static const uint32_t NELEMENTS_LIMIT = JS_BIT(28);
 
   public:
     inline bool setDelegate(JSContext *cx);
 
     inline bool isBoundFunction() const;
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -68,77 +68,77 @@ ShapeTable::init(JSRuntime *rt, Shape *l
          * (nearest to lastProp) must win. See bug 600067.
          */
         if (!SHAPE_FETCH(spp))
             SHAPE_STORE_PRESERVING_COLLISION(spp, &shape);
     }
     return true;
 }
 
-/* static */ bool
-Shape::makeOwnBaseShape(JSContext *cx, HandleShape shape)
+bool
+Shape::makeOwnBaseShape(JSContext *cx)
 {
-    JS_ASSERT(!shape->base()->isOwned());
-    assertSameCompartment(cx, shape->compartment());
+    JS_ASSERT(!base()->isOwned());
+    assertSameCompartment(cx, compartment());
 
-    Return<BaseShape*> nbase = js_NewGCBaseShape(cx);
+    RootedShape self(cx, this);
+
+    BaseShape *nbase = js_NewGCBaseShape(cx);
     if (!nbase)
         return false;
 
-    AutoAssertNoGC nogc;
+    new (nbase) BaseShape(StackBaseShape(self));
+    nbase->setOwned(self->base()->toUnowned());
 
-    new (nbase.get(nogc)) BaseShape(StackBaseShape(shape));
-    nbase->setOwned(shape->base()->toUnowned());
-
-    shape->base_ = nbase.get(nogc);
+    self->base_ = nbase;
 
     return true;
 }
 
 void
 Shape::handoffTableTo(Shape *shape)
 {
-    AutoAssertNoGC nogc;
     JS_ASSERT(inDictionary() && shape->inDictionary());
 
     if (this == shape)
         return;
 
     JS_ASSERT(base()->isOwned() && !shape->base()->isOwned());
 
-    RawBaseShape nbase = base().get(nogc);
+    BaseShape *nbase = base();
 
     JS_ASSERT_IF(shape->hasSlot(), nbase->slotSpan() > shape->slot());
 
     this->base_ = nbase->baseUnowned();
     nbase->adoptUnowned(shape->base()->toUnowned());
 
     shape->base_ = nbase;
 }
 
-/* static */ bool
-Shape::hashify(JSContext *cx, HandleShape shape)
+bool
+Shape::hashify(JSContext *cx)
 {
-    AssertCanGC();
-    JS_ASSERT(!shape->hasTable());
+    JS_ASSERT(!hasTable());
 
-    if (!shape->ensureOwnBaseShape(cx))
+    RootedShape self(cx, this);
+
+    if (!ensureOwnBaseShape(cx))
         return false;
 
     JSRuntime *rt = cx->runtime;
-    ShapeTable *table = rt->new_<ShapeTable>(shape->entryCount());
+    ShapeTable *table = rt->new_<ShapeTable>(self->entryCount());
     if (!table)
         return false;
 
-    if (!table->init(rt, shape)) {
+    if (!table->init(rt, self)) {
         js_free(table);
         return false;
     }
 
-    shape->base()->setTable(table);
+    self->base()->setTable(table);
     return true;
 }
 
 /*
  * Double hashing needs the second hash code to be relatively prime to table
  * size, so we simply make hash2 odd.
  */
 #define HASH1(hash0,shift)      ((hash0) >> (shift))
@@ -349,17 +349,17 @@ JSObject::getChildProperty(JSContext *cx
 
     if (inDictionaryMode()) {
         JS_ASSERT(parent == lastProperty());
         StackShape::AutoRooter childRoot(cx, &child);
         shape = js_NewGCShape(cx);
         if (!shape)
             return NULL;
         if (child.hasSlot() && child.slot() >= self->lastProperty()->base()->slotSpan()) {
-            if (!JSObject::setSlotSpan(cx, self, child.slot() + 1))
+            if (!self->setSlotSpan(cx, child.slot() + 1))
                 return NULL;
         }
         shape->initDictionaryShape(child, self->numFixedSlots(), &self->shape_);
     } else {
         shape = cx->propertyTree().getChild(cx, parent, self->numFixedSlots(), child);
         if (!shape)
             return NULL;
         //JS_ASSERT(shape->parent == parent);
@@ -409,17 +409,17 @@ JSObject::toDictionaryMode(JSContext *cx
         StackShape child(shape);
         dprop->initDictionaryShape(child, self->numFixedSlots(), listp);
 
         JS_ASSERT(!dprop->hasTable());
         dictionaryShape = dprop;
         shape = shape->previous();
     }
 
-    if (!Shape::hashify(cx, root)) {
+    if (!root->hashify(cx)) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     JS_ASSERT((Shape **) root->listp == root.address());
     root->listp = &self->shape_;
     self->shape_ = root;
 
@@ -816,21 +816,20 @@ JSObject::removeProperty(JSContext *cx, 
              * Get an up to date unowned base shape for the new last property
              * when removing the dictionary's last property. Information in
              * base shapes for non-last properties may be out of sync with the
              * object's state.
              */
             RootedShape previous(cx, self->lastProperty()->parent);
             StackBaseShape base(self->lastProperty()->base());
             base.updateGetterSetter(previous->attrs, previous->getter(), previous->setter());
-            Return<BaseShape*> nbase = BaseShape::getUnowned(cx, base);
+            BaseShape *nbase = BaseShape::getUnowned(cx, base);
             if (!nbase)
                 return false;
-            AutoAssertNoGC nogc;
-            previous->base_ = nbase.get(nogc);
+            previous->base_ = nbase;
         }
     }
 
     /* If shape has a slot, free its slot number. */
     if (shape->hasSlot()) {
         self->freeSlot(shape->slot());
         ++cx->runtime->propertyRemovals;
     }
@@ -1126,25 +1125,22 @@ BaseShape::getUnowned(JSContext *cx, con
 
     BaseShapeSet::AddPtr p = table.lookupForAdd(&base);
 
     if (p)
         return *p;
 
     StackBaseShape::AutoRooter root(cx, &base);
 
-    Return<BaseShape*> nbase_ = js_NewGCBaseShape(cx);
+    BaseShape *nbase_ = js_NewGCBaseShape(cx);
     if (!nbase_)
         return NULL;
-
-    AutoAssertNoGC nogc;
+    new (nbase_) BaseShape(base);
 
-    new (nbase_.get(nogc)) BaseShape(base);
-
-    UnownedBaseShape *nbase = static_cast<UnownedBaseShape *>(nbase_.get(nogc));
+    UnownedBaseShape *nbase = static_cast<UnownedBaseShape *>(nbase_);
 
     if (!table.relookupOrAdd(p, &base, nbase))
         return NULL;
 
     return nbase;
 }
 
 void
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -227,19 +227,16 @@ class PropertyTree;
  * last property (and its base shape). This works because only the object's
  * last property is used to query information about the object. Care must be
  * taken to call JSObject::canRemoveLastProperty when unwinding an object to
  * an earlier property, however.
  */
 
 class UnownedBaseShape;
 
-class BaseShape;
-typedef BaseShape * RawBaseShape;
-
 class BaseShape : public js::gc::Cell
 {
   public:
     friend struct Shape;
     friend struct StackBaseShape;
     friend struct StackShape;
 
     enum Flag {
@@ -348,19 +345,19 @@ class BaseShape : public js::gc::Cell
     /* Check that an owned base shape is consistent with its unowned base. */
     inline void assertConsistency();
 
     /* For JIT usage */
     static inline size_t offsetOfClass() { return offsetof(BaseShape, clasp); }
     static inline size_t offsetOfParent() { return offsetof(BaseShape, parent); }
     static inline size_t offsetOfFlags() { return offsetof(BaseShape, flags); }
 
-    static inline void writeBarrierPre(RawBaseShape shape);
-    static inline void writeBarrierPost(RawBaseShape shape, void *addr);
-    static inline void readBarrier(RawBaseShape shape);
+    static inline void writeBarrierPre(BaseShape *shape);
+    static inline void writeBarrierPost(BaseShape *shape, void *addr);
+    static inline void readBarrier(BaseShape *shape);
 
     static inline ThingRootKind rootKind() { return THING_ROOT_BASE_SHAPE; }
 
     inline void markChildren(JSTracer *trc);
 
   private:
     static void staticAsserts() {
         JS_STATIC_ASSERT(offsetof(BaseShape, clasp) == offsetof(js::shadow::BaseShape, clasp));
@@ -393,17 +390,17 @@ struct StackBaseShape
     typedef const StackBaseShape *Lookup;
 
     uint32_t flags;
     Class *clasp;
     JSObject *parent;
     PropertyOp rawGetter;
     StrictPropertyOp rawSetter;
 
-    StackBaseShape(Return<BaseShape*> base)
+    StackBaseShape(BaseShape *base)
       : flags(base->flags & BaseShape::OBJECT_FLAG_MASK),
         clasp(base->clasp),
         parent(base->parent),
         rawGetter(NULL),
         rawSetter(NULL)
     {}
 
     StackBaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags)
@@ -515,29 +512,28 @@ struct Shape : public js::gc::Cell
                                     HeapPtrShape *dictp);
 
     Shape *getChildBinding(JSContext *cx, const StackShape &child);
 
     /* Replace the base shape of the last shape in a non-dictionary lineage with base. */
     static Shape *replaceLastProperty(JSContext *cx, const StackBaseShape &base,
                                       TaggedProto proto, Shape *shape);
 
-    static bool hashify(JSContext *cx, HandleShape shape);
+    bool hashify(JSContext *cx);
     void handoffTableTo(Shape *newShape);
 
     inline void setParent(js::Shape *p);
 
     bool ensureOwnBaseShape(JSContext *cx) {
         if (base()->isOwned())
             return true;
-        RootedShape self(cx, this);
-        return makeOwnBaseShape(cx, self);
+        return makeOwnBaseShape(cx);
     }
 
-    static bool makeOwnBaseShape(JSContext *cx, HandleShape shape);
+    bool makeOwnBaseShape(JSContext *cx);
 
   public:
     bool hasTable() const { return base()->hasTable(); }
     js::ShapeTable &table() const { return base()->table(); }
 
     void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
                              size_t *propTableSize, size_t *kidsSize) const {
         *propTableSize = hasTable() ? table().sizeOfIncludingThis(mallocSizeOf) : 0;
@@ -690,24 +686,24 @@ struct Shape : public js::gc::Cell
                ? ObjectValue(*base()->setterObj)
                : UndefinedValue();
     }
 
     void update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8_t attrs);
 
     inline bool matches(const Shape *other) const;
     inline bool matches(const StackShape &other) const;
-    inline bool matchesParamsAfterId(RawBaseShape base,
+    inline bool matchesParamsAfterId(BaseShape *base,
                                      uint32_t aslot, unsigned aattrs, unsigned aflags,
                                      int ashortid) const;
 
     bool get(JSContext* cx, HandleObject receiver, JSObject *obj, JSObject *pobj, MutableHandleValue vp);
     bool set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, MutableHandleValue vp);
 
-    Return<BaseShape*> base() const { return base_; }
+    BaseShape *base() const { return base_; }
 
     bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; }
     uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
     uint32_t maybeSlot() const { return slotInfo & SLOT_MASK; }
 
     bool isEmptyShape() const {
         JS_ASSERT_IF(JSID_IS_EMPTY(propid_), hasMissingSlot());
         return JSID_IS_EMPTY(propid_);
@@ -1080,17 +1076,17 @@ Shape::search(JSContext *cx, Shape *star
         Shape **spp = start->table().search(id, adding);
         return SHAPE_FETCH(spp);
     }
 
     if (start->numLinearSearches() == LINEAR_SEARCHES_MAX) {
         if (start->isBigEnoughForAShapeTable()) {
             RootedShape startRoot(cx, start);
             RootedId idRoot(cx, id);
-            if (Shape::hashify(cx, startRoot)) {
+            if (startRoot->hashify(cx)) {
                 Shape **spp = startRoot->table().search(idRoot, adding);
                 return SHAPE_FETCH(spp);
             }
             start = startRoot;
             id = idRoot;
         }
         /*
          * No table built -- there weren't enough entries, or OOM occurred.
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -235,31 +235,30 @@ StackShape::hash() const
     hash = JS_ROTATE_LEFT32(hash, 4) ^ slot_;
     hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid);
     return hash;
 }
 
 inline bool
 Shape::matches(const js::Shape *other) const
 {
-    AutoAssertNoGC nogc;
     return propid_.get() == other->propid_.get() &&
-           matchesParamsAfterId(other->base().get(nogc), other->maybeSlot(), other->attrs,
+           matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
                                 other->flags, other->shortid_);
 }
 
 inline bool
 Shape::matches(const StackShape &other) const
 {
     return propid_.get() == other.propid &&
            matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, other.shortid);
 }
 
 inline bool
-Shape::matchesParamsAfterId(RawBaseShape base, uint32_t aslot,
+Shape::matchesParamsAfterId(BaseShape *base, uint32_t aslot,
                             unsigned aattrs, unsigned aflags, int ashortid) const
 {
     return base->unowned() == this->base()->unowned() &&
            maybeSlot() == aslot &&
            attrs == aattrs &&
            ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
            shortid_ == ashortid;
 }
@@ -439,43 +438,43 @@ Shape::markChildren(JSTracer *trc)
 {
     MarkBaseShape(trc, &base_, "base");
     gc::MarkId(trc, &propidRef(), "propid");
     if (parent)
         MarkShape(trc, &parent, "parent");
 }
 
 inline void
-BaseShape::writeBarrierPre(RawBaseShape base)
+BaseShape::writeBarrierPre(BaseShape *base)
 {
 #ifdef JSGC_INCREMENTAL
     if (!base)
         return;
 
     JSCompartment *comp = base->compartment();
     if (comp->needsBarrier()) {
-        RawBaseShape tmp = base;
+        BaseShape *tmp = base;
         MarkBaseShapeUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
         JS_ASSERT(tmp == base);
     }
 #endif
 }
 
 inline void
-BaseShape::writeBarrierPost(RawBaseShape shape, void *addr)
+BaseShape::writeBarrierPost(BaseShape *shape, void *addr)
 {
 }
 
 inline void
-BaseShape::readBarrier(RawBaseShape base)
+BaseShape::readBarrier(BaseShape *base)
 {
 #ifdef JSGC_INCREMENTAL
     JSCompartment *comp = base->compartment();
     if (comp->needsBarrier()) {
-        RawBaseShape tmp = base;
+        BaseShape *tmp = base;
         MarkBaseShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
         JS_ASSERT(tmp == base);
     }
 #endif
 }
 
 inline void
 BaseShape::markChildren(JSTracer *trc)