Bug 1149526 - Check HeapPtrs have GC lifetime r=terrence a=sylvestre
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 08 Apr 2015 10:27:51 +0100
changeset 258458 7ca7e178de40
parent 258453 05508ccf3ae8
child 258459 4c2454564144
push id4673
push userjcoppeard@mozilla.com
push date2015-04-14 12:47 +0000
treeherdermozilla-beta@7ca7e178de40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, sylvestre
bugs1149526
milestone38.0
Bug 1149526 - Check HeapPtrs have GC lifetime r=terrence a=sylvestre
js/src/asmjs/AsmJSModule.h
js/src/gc/Barrier.cpp
js/src/gc/Barrier.h
js/src/gc/GCInternals.h
js/src/jit/BaselineJIT.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsscript.h
js/src/jsweakmap.h
js/src/vm/RegExpObject.h
js/src/vm/RegExpStatics.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/TypeInference.h
--- a/js/src/asmjs/AsmJSModule.h
+++ b/js/src/asmjs/AsmJSModule.h
@@ -839,17 +839,17 @@ class AsmJSModule
     ScriptSource *                        scriptSource_;
     PropertyName *                        globalArgumentName_;
     PropertyName *                        importArgumentName_;
     PropertyName *                        bufferArgumentName_;
     uint8_t *                             code_;
     uint8_t *                             interruptExit_;
     uint8_t *                             outOfBoundsExit_;
     StaticLinkData                        staticLinkData_;
-    HeapPtrArrayBufferObjectMaybeShared   maybeHeap_;
+    RelocatablePtrArrayBufferObjectMaybeShared maybeHeap_;
     AsmJSModule **                        prevLinked_;
     AsmJSModule *                         nextLinked_;
     bool                                  dynamicallyLinked_;
     bool                                  loadedFromCache_;
     bool                                  profilingEnabled_;
     bool                                  interrupted_;
 
     void restoreHeapToInitialState(ArrayBufferObjectMaybeShared* maybePrevBuffer);
--- a/js/src/gc/Barrier.cpp
+++ b/js/src/gc/Barrier.cpp
@@ -61,16 +61,23 @@ RuntimeFromMainThreadIsHeapMajorCollecti
     return shadowZone->runtimeFromMainThread()->isHeapMajorCollecting();
 }
 
 bool
 CurrentThreadIsIonCompiling()
 {
     return TlsPerThreadData.get()->ionCompiling;
 }
+
+bool
+CurrentThreadIsGCSweeping()
+{
+    return js::TlsPerThreadData.get()->gcSweeping;
+}
+
 #endif // DEBUG
 
 bool
 StringIsPermanentAtom(JSString* str)
 {
     return str->isPermanentAtom();
 }
 
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -187,16 +187,19 @@ namespace jit {
 class JitCode;
 }
 
 #ifdef DEBUG
 // Barriers can't be triggered during backend Ion compilation, which may run on
 // a helper thread.
 bool
 CurrentThreadIsIonCompiling();
+
+bool
+CurrentThreadIsGCSweeping();
 #endif
 
 bool
 StringIsPermanentAtom(JSString* str);
 
 namespace gc {
 
 template <typename T> struct MapTypeToTraceKind {};
@@ -487,51 +490,51 @@ class PreBarriered : public BarrieredBas
         MOZ_ASSERT(!GCMethods<T>::poisoned(v));
         this->value = v;
     }
 };
 
 /*
  * A pre- and post-barriered heap pointer, for use inside the JS engine.
  *
+ * It must only be stored in memory that has GC lifetime. HeapPtr must not be
+ * used in contexts where it may be implicitly moved or deleted, e.g. most
+ * containers.
+ *
  * Not to be confused with JS::Heap<T>. This is a different class from the
  * external interface and implements substantially different semantics.
  *
  * The post-barriers implemented by this class are faster than those
  * implemented by RelocatablePtr<T> or JS::Heap<T> at the cost of not
- * automatically handling deletion or movement. It should generally only be
- * stored in memory that has GC lifetime. HeapPtr must not be used in contexts
- * where it may be implicitly moved or deleted, e.g. most containers.
+ * automatically handling deletion or movement.
  */
 template <class T>
 class HeapPtr : public BarrieredBase<T>
 {
   public:
     HeapPtr() : BarrieredBase<T>(GCMethods<T>::initial()) {}
     explicit HeapPtr(T v) : BarrieredBase<T>(v) { post(); }
     explicit HeapPtr(const HeapPtr<T>& v) : BarrieredBase<T>(v) { post(); }
+#ifdef DEBUG
+    ~HeapPtr() {
+        MOZ_ASSERT(CurrentThreadIsGCSweeping());
+    }
+#endif
 
     void init(T v) {
         MOZ_ASSERT(!GCMethods<T>::poisoned(v));
         this->value = v;
         post();
     }
 
     DECLARE_POINTER_ASSIGN_OPS(HeapPtr, T);
 
   protected:
     void post() { InternalGCMethods<T>::postBarrier(&this->value); }
 
-    /* Make this friend so it can access pre() and post(). */
-    template <class T1, class T2>
-    friend inline void
-    BarrieredSetPair(Zone* zone,
-                     HeapPtr<T1*>& v1, T1* val1,
-                     HeapPtr<T2*>& v2, T2* val2);
-
   private:
     void set(const T& v) {
         this->pre();
         MOZ_ASSERT(!GCMethods<T>::poisoned(v));
         this->value = v;
         post();
     }
 
@@ -609,19 +612,30 @@ class RelocatablePtr : public BarrieredB
 
     ~RelocatablePtr() {
         if (GCMethods<T>::needsPostBarrier(this->value))
             relocate();
     }
 
     DECLARE_POINTER_ASSIGN_OPS(RelocatablePtr, T);
 
+    /* Make this friend so it can access pre() and post(). */
+    template <class T1, class T2>
+    friend inline void
+    BarrieredSetPair(Zone* zone,
+                     RelocatablePtr<T1*>& v1, T1* val1,
+                     RelocatablePtr<T2*>& v2, T2* val2);
+
   protected:
     void set(const T& v) {
         this->pre();
+        postBarrieredSet(v);
+    }
+
+    void postBarrieredSet(const T& v) {
         MOZ_ASSERT(!GCMethods<T>::poisoned(v));
         if (GCMethods<T>::needsPostBarrier(v)) {
             this->value = v;
             post();
         } else if (GCMethods<T>::needsPostBarrier(this->value)) {
             relocate();
             this->value = v;
         } else {
@@ -642,27 +656,25 @@ class RelocatablePtr : public BarrieredB
 
 /*
  * This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
  * barriers with only one branch to check if we're in an incremental GC.
  */
 template <class T1, class T2>
 static inline void
 BarrieredSetPair(Zone* zone,
-                 HeapPtr<T1*>& v1, T1* val1,
-                 HeapPtr<T2*>& v2, T2* val2)
+                 RelocatablePtr<T1*>& v1, T1* val1,
+                 RelocatablePtr<T2*>& v2, T2* val2)
 {
     if (T1::needWriteBarrierPre(zone)) {
         v1.pre();
         v2.pre();
     }
-    v1.unsafeSet(val1);
-    v2.unsafeSet(val2);
-    v1.post();
-    v2.post();
+    v1.postBarrieredSet(val1);
+    v2.postBarrieredSet(val2);
 }
 
 /* Useful for hashtables with a HeapPtr as key. */
 template <class T>
 struct HeapPtrHasher
 {
     typedef HeapPtr<T> Key;
     typedef T Lookup;
@@ -746,19 +758,28 @@ class JitCode;
 }
 
 typedef PreBarriered<JSObject*> PreBarrieredObject;
 typedef PreBarriered<JSScript*> PreBarrieredScript;
 typedef PreBarriered<jit::JitCode*> PreBarrieredJitCode;
 typedef PreBarriered<JSAtom*> PreBarrieredAtom;
 
 typedef RelocatablePtr<JSObject*> RelocatablePtrObject;
+typedef RelocatablePtr<JSFunction*> RelocatablePtrFunction;
+typedef RelocatablePtr<PlainObject*> RelocatablePtrPlainObject;
 typedef RelocatablePtr<JSScript*> RelocatablePtrScript;
 typedef RelocatablePtr<NativeObject*> RelocatablePtrNativeObject;
 typedef RelocatablePtr<NestedScopeObject*> RelocatablePtrNestedScopeObject;
+typedef RelocatablePtr<Shape*> RelocatablePtrShape;
+typedef RelocatablePtr<ObjectGroup*> RelocatablePtrObjectGroup;
+typedef RelocatablePtr<jit::JitCode*> RelocatablePtrJitCode;
+typedef RelocatablePtr<JSLinearString*> RelocatablePtrLinearString;
+typedef RelocatablePtr<JSString*> RelocatablePtrString;
+typedef RelocatablePtr<JSAtom*> RelocatablePtrAtom;
+typedef RelocatablePtr<ArrayBufferObjectMaybeShared*> RelocatablePtrArrayBufferObjectMaybeShared;
 
 typedef HeapPtr<NativeObject*> HeapPtrNativeObject;
 typedef HeapPtr<ArrayObject*> HeapPtrArrayObject;
 typedef HeapPtr<ArrayBufferObjectMaybeShared*> HeapPtrArrayBufferObjectMaybeShared;
 typedef HeapPtr<ArrayBufferObject*> HeapPtrArrayBufferObject;
 typedef HeapPtr<BaseShape*> HeapPtrBaseShape;
 typedef HeapPtr<JSAtom*> HeapPtrAtom;
 typedef HeapPtr<JSFlatString*> HeapPtrFlatString;
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -144,12 +144,37 @@ struct MovingTracer : JSTracer {
     explicit MovingTracer(JSRuntime* rt) : JSTracer(rt, Visit, TraceWeakMapKeysValues) {}
 
     static void Visit(JSTracer* jstrc, void** thingp, JSGCTraceKind kind);
     static bool IsMovingTracer(JSTracer* trc) {
         return trc->callback == Visit;
     }
 };
 
+// In debug builds, set/unset the GC sweeping flag for the current thread.
+struct AutoSetThreadIsSweeping
+{
+#ifdef DEBUG
+    explicit AutoSetThreadIsSweeping(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+      : threadData_(js::TlsPerThreadData.get())
+    {
+        MOZ_ASSERT(!threadData_->gcSweeping);
+        threadData_->gcSweeping = true;
+        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+    ~AutoSetThreadIsSweeping() {
+        MOZ_ASSERT(threadData_->gcSweeping);
+        threadData_->gcSweeping = false;
+    }
+
+  private:
+    PerThreadData* threadData_;
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+#else
+    AutoSetThreadIsSweeping() {}
+#endif
+};
+
 } /* namespace gc */
 } /* namespace js */
 
 #endif /* gc_GCInternals_h */
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -114,21 +114,21 @@ struct BaselineScript
 
     // Limit the locals on a given script so that stack check on baseline frames
     // doesn't overflow a uint32_t value.
     // (MAX_JSSCRIPT_SLOTS * sizeof(Value)) must fit within a uint32_t.
     static const uint32_t MAX_JSSCRIPT_SLOTS = 0xffffu;
 
   private:
     // Code pointer containing the actual method.
-    HeapPtrJitCode method_;
+    RelocatablePtrJitCode method_;
 
     // For heavyweight scripts, template objects to use for the call object and
     // decl env object (linked via the call object's enclosing scope).
-    HeapPtrObject templateScope_;
+    RelocatablePtrObject templateScope_;
 
     // Allocated space for fallback stubs.
     FallbackICStubSpace fallbackStubSpace_;
 
     // If non-null, the list of AsmJSModules that contain an optimized call
     // directly to this script.
     Vector<DependentAsmJSModuleExit>* dependentAsmJSModules_;
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3578,16 +3578,18 @@ void
 GCHelperState::doSweep(AutoLockGC& lock)
 {
     // The main thread may call queueZonesForBackgroundSweep() or
     // ShrinkGCBuffers() while this is running so we must check there is no more
     // work to do before exiting.
 
     do {
         while (!rt->gc.backgroundSweepZones.isEmpty()) {
+            AutoSetThreadIsSweeping threadIsSweeping;
+
             ZoneList zones;
             zones.transferFrom(rt->gc.backgroundSweepZones);
             LifoAlloc freeLifoAlloc(JSRuntime::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
             freeLifoAlloc.transferFrom(&rt->gc.freeLifoAlloc);
 
             AutoUnlockGC unlock(lock);
             rt->gc.sweepBackgroundThings(zones, freeLifoAlloc, BackgroundThread);
         }
@@ -4812,31 +4814,43 @@ GCRuntime::endMarkingZoneGroup()
     for (GCZoneGroupIter zone(rt); !zone.done(); zone.next()) {
         MOZ_ASSERT(zone->isGCMarkingGray());
         zone->setGCState(Zone::Mark);
     }
     MOZ_ASSERT(marker.isDrained());
     marker.setMarkColorBlack();
 }
 
-#define MAKE_GC_PARALLEL_TASK(name) \
-    class name : public GCParallelTask {\
-        JSRuntime* runtime;\
-        virtual void run() override;\
-      public:\
-        explicit name (JSRuntime* rt) : runtime(rt) {}\
-    }
-MAKE_GC_PARALLEL_TASK(SweepAtomsTask);
-MAKE_GC_PARALLEL_TASK(SweepInnerViewsTask);
-MAKE_GC_PARALLEL_TASK(SweepCCWrappersTask);
-MAKE_GC_PARALLEL_TASK(SweepBaseShapesTask);
-MAKE_GC_PARALLEL_TASK(SweepInitialShapesTask);
-MAKE_GC_PARALLEL_TASK(SweepObjectGroupsTask);
-MAKE_GC_PARALLEL_TASK(SweepRegExpsTask);
-MAKE_GC_PARALLEL_TASK(SweepMiscTask);
+class GCSweepTask : public GCParallelTask
+{
+    virtual void runFromHelperThread() override {
+        AutoSetThreadIsSweeping threadIsSweeping;
+        GCParallelTask::runFromHelperThread();
+    }
+  protected:
+    JSRuntime* runtime;
+  public:
+    explicit GCSweepTask(JSRuntime* rt) : runtime(rt) {}
+};
+
+#define MAKE_GC_SWEEP_TASK(name)                                              \
+    class name : public GCSweepTask {                                         \
+        virtual void run() override;                                          \
+      public:                                                                 \
+        explicit name (JSRuntime* rt) : GCSweepTask(rt) {}                    \
+    }
+MAKE_GC_SWEEP_TASK(SweepAtomsTask);
+MAKE_GC_SWEEP_TASK(SweepInnerViewsTask);
+MAKE_GC_SWEEP_TASK(SweepCCWrappersTask);
+MAKE_GC_SWEEP_TASK(SweepBaseShapesTask);
+MAKE_GC_SWEEP_TASK(SweepInitialShapesTask);
+MAKE_GC_SWEEP_TASK(SweepObjectGroupsTask);
+MAKE_GC_SWEEP_TASK(SweepRegExpsTask);
+MAKE_GC_SWEEP_TASK(SweepMiscTask);
+#undef MAKE_GC_SWEEP_TASK
 
 /* virtual */ void
 SweepAtomsTask::run()
 {
     runtime->sweepAtoms();
 }
 
 /* virtual */ void
@@ -5116,16 +5130,18 @@ GCRuntime::beginSweepPhase(bool destroyi
      *
      * Finalize as we sweep, outside of lock but with rt->isHeapBusy()
      * true so that any attempt to allocate a GC-thing from a finalizer will
      * fail, rather than nest badly and leave the unmarked newborn to be swept.
      */
 
     MOZ_ASSERT(!abortSweepAfterCurrentGroup);
 
+    AutoSetThreadIsSweeping threadIsSweeping;
+
     releaseHeldRelocatedArenas();
 
     computeNonIncrementalMarkingForValidation();
 
     gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
 
     sweepOnBackgroundThread =
         !destroyingRuntime && !TraceEnabled() && CanUseExtraThreads();
@@ -5216,16 +5232,18 @@ SweepArenaList(ArenaHeader** arenasToSwe
     }
 
     return true;
 }
 
 GCRuntime::IncrementalProgress
 GCRuntime::sweepPhase(SliceBudget& sliceBudget)
 {
+    AutoSetThreadIsSweeping threadIsSweeping;
+
     gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
     FreeOp fop(rt);
 
     if (drainMarkStack(sliceBudget, gcstats::PHASE_SWEEP_MARK) == NotFinished)
         return NotFinished;
 
 
     for (;;) {
@@ -5321,16 +5339,18 @@ GCRuntime::sweepPhase(SliceBudget& slice
         endMarkingZoneGroup();
         beginSweepingZoneGroup();
     }
 }
 
 void
 GCRuntime::endSweepPhase(bool destroyingRuntime)
 {
+    AutoSetThreadIsSweeping threadIsSweeping;
+
     gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP);
     FreeOp fop(rt);
 
     MOZ_ASSERT_IF(destroyingRuntime, !sweepOnBackgroundThread);
 
     /*
      * Recalculate whether GC was full or not as this may have changed due to
      * newly created zones.  Can only change from full to not full.
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1023,17 +1023,17 @@ class GCParallelTask
     }
 
     // Check if a task is actively running.
     bool isRunning() const;
 
     // This should be friended to HelperThread, but cannot be because it
     // would introduce several circular dependencies.
   public:
-    void runFromHelperThread();
+    virtual void runFromHelperThread();
 };
 
 struct GCChunkHasher {
     typedef gc::Chunk* Lookup;
 
     /*
      * Strip zeros for better distribution after multiplying by the golden
      * ratio.
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -196,17 +196,17 @@ typedef InternalHandle<Bindings*> Intern
  * both function and top-level scripts (the latter is needed to track names in
  * strict mode eval code, to give such code its own lexical environment).
  */
 class Bindings
 {
     friend class BindingIter;
     friend class AliasedFormalIter;
 
-    HeapPtrShape callObjShape_;
+    RelocatablePtrShape callObjShape_;
     uintptr_t bindingArrayAndFlag_;
     uint16_t numArgs_;
     uint16_t numBlockScoped_;
     uint16_t numBodyLevelLexicals_;
     uint16_t aliasedBodyLevelLexicalBegin_;
     uint16_t numUnaliasedBodyLevelLexicals_;
     uint32_t numVars_;
     uint32_t numUnaliasedVars_;
--- a/js/src/jsweakmap.h
+++ b/js/src/jsweakmap.h
@@ -87,17 +87,17 @@ class WeakMapBase {
     virtual void nonMarkingTraceValues(JSTracer* tracer) = 0;
     virtual bool markIteratively(JSTracer* tracer) = 0;
     virtual bool findZoneEdges() = 0;
     virtual void sweep() = 0;
     virtual void traceMappings(WeakMapTracer* tracer) = 0;
     virtual void finish() = 0;
 
     // Object that this weak map is part of, if any.
-    HeapPtrObject memberOf;
+    RelocatablePtrObject memberOf;
 
     // Compartment that this weak map is part of.
     JSCompartment* compartment;
 
     // Link in a list of all WeakMaps in a compartment, headed by
     // JSCompartment::gcWeakMapList. The last element of the list has nullptr as
     // its next. Maps not in the list have WeakMapNotInList as their next.
     WeakMapBase* next;
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -114,29 +114,29 @@ class RegExpShared
   private:
     friend class RegExpCompartment;
     friend class RegExpStatics;
 
     typedef frontend::TokenStream TokenStream;
 
     struct RegExpCompilation
     {
-        HeapPtrJitCode jitCode;
+        RelocatablePtrJitCode jitCode;
         uint8_t* byteCode;
 
         RegExpCompilation() : byteCode(nullptr) {}
         ~RegExpCompilation() { js_free(byteCode); }
 
         bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
             return byteCode || (force == DontForceByteCode && jitCode);
         }
     };
 
     /* Source to the RegExp, for lazy compilation. */
-    HeapPtrAtom        source;
+    RelocatablePtrAtom source;
 
     RegExpFlag         flags;
     size_t             parenCount;
     bool               canStringMatch;
     bool               marked_;
 
     RegExpCompilation  compilationArray[4];
 
--- a/js/src/vm/RegExpStatics.h
+++ b/js/src/vm/RegExpStatics.h
@@ -16,29 +16,29 @@ namespace js {
 
 class GlobalObject;
 class RegExpStaticsObject;
 
 class RegExpStatics
 {
     /* The latest RegExp output, set after execution. */
     VectorMatchPairs        matches;
-    HeapPtrLinearString     matchesInput;
+    RelocatablePtrLinearString matchesInput;
 
     /*
      * The previous RegExp input, used to resolve lazy state.
      * A raw RegExpShared cannot be stored because it may be in
      * a different compartment via evalcx().
      */
-    HeapPtrAtom             lazySource;
+    RelocatablePtrAtom      lazySource;
     RegExpFlag              lazyFlags;
     size_t                  lazyIndex;
 
     /* The latest RegExp input, set before execution. */
-    HeapPtrString           pendingInput;
+    RelocatablePtrString    pendingInput;
     RegExpFlag              flags;
 
     /*
      * If non-zero, |matchesInput| and the |lazy*| fields may be used
      * to replay the last executed RegExp, and |matches| is invalid.
      */
     int32_t                 pendingLazyEvaluation;
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -76,16 +76,17 @@ PerThreadData::PerThreadData(JSRuntime* 
 #ifdef JS_TRACE_LOGGING
     traceLogger(nullptr),
 #endif
     autoFlushICache_(nullptr),
     dtoaState(nullptr),
     suppressGC(0),
 #ifdef DEBUG
     ionCompiling(false),
+    gcSweeping(false),
 #endif
     activeCompilations(0)
 {}
 
 PerThreadData::~PerThreadData()
 {
     if (dtoaState)
         js_DestroyDtoaState(dtoaState);
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -514,16 +514,19 @@ class PerThreadData : public PerThreadDa
      * extremely dangerous and should only be used when in an OOM situation or
      * in non-exposed debugging facilities.
      */
     int32_t suppressGC;
 
 #ifdef DEBUG
     // Whether this thread is actively Ion compiling.
     bool ionCompiling;
+
+    // Whether this thread is currently sweeping GC things.
+    bool gcSweeping;
 #endif
 
     // Number of active bytecode compilation on this thread.
     unsigned activeCompilations;
 
     explicit PerThreadData(JSRuntime* runtime);
     ~PerThreadData();
 
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -824,50 +824,50 @@ class TypeNewScript
           : kind(kind), offset(offset)
         {}
     };
 
   private:
     // Scripted function which this information was computed for.
     // If instances of the associated group are created without calling
     // 'new' on this function, the new script information is cleared.
-    HeapPtrFunction function_;
+    RelocatablePtrFunction function_;
 
     // Any preliminary objects with the type. The analyses are not performed
     // until this array is cleared.
     PreliminaryObjectArray* preliminaryObjects;
 
     // After the new script properties analyses have been performed, a template
     // object to use for newly constructed objects. The shape of this object
     // reflects all definite properties the object will have, and the
     // allocation kind to use. This is null if the new objects have an unboxed
     // layout, in which case the UnboxedLayout provides the initial structure
     // of the object.
-    HeapPtrPlainObject templateObject_;
+    RelocatablePtrPlainObject templateObject_;
 
     // Order in which definite properties become initialized. We need this in
     // case the definite properties are invalidated (such as by adding a setter
     // to an object on the prototype chain) while an object is in the middle of
     // being initialized, so we can walk the stack and fixup any objects which
     // look for in-progress objects which were prematurely set with an incorrect
     // shape. Property assignments in inner frames are preceded by a series of
     // SETPROP_FRAME entries specifying the stack down to the frame containing
     // the write.
     Initializer* initializerList;
 
     // If there are additional properties found by the acquired properties
     // analysis which were not found by the definite properties analysis, this
     // shape contains all such additional properties (plus the definite
     // properties). When an object of this group acquires this shape, it is
     // fully initialized and its group can be changed to initializedGroup.
-    HeapPtrShape initializedShape_;
+    RelocatablePtrShape initializedShape_;
 
     // Group with definite properties set for all properties found by
     // both the definite and acquired properties analyses.
-    HeapPtrObjectGroup initializedGroup_;
+    RelocatablePtrObjectGroup initializedGroup_;
 
   public:
     TypeNewScript() { mozilla::PodZero(this); }
     ~TypeNewScript() {
         js_delete(preliminaryObjects);
         js_free(initializerList);
     }