diff --git a/js/public/TemplateLib.h b/js/public/TemplateLib.h
index 9010b10f72f306a6e8eae1d16b8aaaea288f9573..299547964f882337b64456b4c14cac5e5bed890b 100644
--- a/js/public/TemplateLib.h
+++ b/js/public/TemplateLib.h
@@ -177,7 +177,7 @@ template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T r
 /*
  * Traits class for identifying types that are implicitly barriered.
  */
-template <class T> struct IsPostBarrieredType { static const bool result = false; };
+template <class T> struct IsRelocatableHeapType { static const bool result = true; };
 
 } /* namespace tl */
 } /* namespace js */
diff --git a/js/public/Vector.h b/js/public/Vector.h
index e2d91349ea276ef3ba4f9e50ca99d37c65c25378..8fe787036efac7b4d69d26ca5a6b6fa79a974a53 100644
--- a/js/public/Vector.h
+++ b/js/public/Vector.h
@@ -213,7 +213,7 @@ struct VectorImpl<T, N, AP, true>
 template <class T, size_t N, class AllocPolicy>
 class Vector : private AllocPolicy
 {
-    typedef typename tl::StaticAssert<!tl::IsPostBarrieredType<T>::result>::result _;
+    typedef typename tl::StaticAssert<tl::IsRelocatableHeapType<T>::result>::result _;
 
     /* utilities */
 
diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h
index 61337e18afd13c078861cf10635bcf62a20154fc..afb85e3d3579c8b86cbf3d0ae1d2500d9beaaf67 100644
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -151,31 +151,39 @@ struct JSXML;
 namespace js {
 
 template<class T, typename Unioned = uintptr_t>
-class HeapPtr
+class EncapsulatedPtr
 {
+  protected:
     union {
         T *value;
         Unioned other;
     };
 
   public:
-    HeapPtr() : value(NULL) {}
-    explicit HeapPtr(T *v) : value(v) { post(); }
-    explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
+    EncapsulatedPtr() : value(NULL) {}
+    explicit EncapsulatedPtr(T *v) : value(v) {}
+    explicit EncapsulatedPtr(const EncapsulatedPtr<T> &v) : value(v.value) {}
 
-    ~HeapPtr() { pre(); }
+    ~EncapsulatedPtr() { pre(); }
 
-    /* Use this to install a ptr into a newly allocated object. */
-    void init(T *v) {
+    /* Use to set the pointer to NULL. */
+    void clear() {
+        pre();
+        value = NULL;
+    }
+
+    EncapsulatedPtr<T, Unioned> &operator=(T *v) {
+        pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v));
         value = v;
-        post();
+        return *this;
     }
 
-    /* Use to set the pointer to NULL. */
-    void clear() {
-	pre();
-	value = NULL;
+    EncapsulatedPtr<T, Unioned> &operator=(const EncapsulatedPtr<T> &v) {
+        pre();
+        JS_ASSERT(!IsPoisonedPtr<T>(v.value));
+        value = v.value;
+        return *this;
     }
 
     /* Use this if the automatic coercion to T* isn't working. */
@@ -190,30 +198,48 @@ class HeapPtr
 
     Unioned *unsafeGetUnioned() { return &other; }
 
+    T &operator*() const { return *value; }
+    T *operator->() const { return value; }
+
+    operator T*() const { return value; }
+
+  protected:
+    void pre() { T::writeBarrierPre(value); }
+};
+
+template <class T, class Unioned = uintptr_t>
+class HeapPtr : public EncapsulatedPtr<T, Unioned>
+{
+  public:
+    HeapPtr() : EncapsulatedPtr<T>(NULL) {}
+    explicit HeapPtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
+    explicit HeapPtr(const HeapPtr<T> &v)
+      : EncapsulatedPtr<T>(v) { post(); }
+
+    void init(T *v) {
+        JS_ASSERT(!IsPoisonedPtr<T>(v));
+        this->value = v;
+        post();
+    }
+
     HeapPtr<T, Unioned> &operator=(T *v) {
-        pre();
+        this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v));
-        value = v;
+        this->value = v;
         post();
         return *this;
     }
 
     HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
-        pre();
+        this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v.value));
-        value = v.value;
+        this->value = v.value;
         post();
         return *this;
     }
 
-    T &operator*() const { return *value; }
-    T *operator->() const { return value; }
-
-    operator T*() const { return value; }
-
-  private:
-    void pre() { T::writeBarrierPre(value); }
-    void post() { T::writeBarrierPost(value, (void *)&value); }
+  protected:
+    void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
 
     /* Make this friend so it can access pre() and post(). */
     template<class T1, class T2>
@@ -223,6 +249,41 @@ class HeapPtr
                      HeapPtr<T2> &v2, T2 *val2);
 };
 
+template <class T>
+class RelocatablePtr : public EncapsulatedPtr<T>
+{
+  public:
+    RelocatablePtr() : EncapsulatedPtr<T>(NULL) {}
+    explicit RelocatablePtr(T *v) : EncapsulatedPtr<T>(v) { post(); }
+    explicit RelocatablePtr(const RelocatablePtr<T> &v)
+      : EncapsulatedPtr<T>(v) { post(); }
+
+    ~RelocatablePtr() {
+        this->pre();
+        relocate();
+    }
+
+    RelocatablePtr<T> &operator=(T *v) {
+        this->pre();
+        JS_ASSERT(!IsPoisonedPtr<T>(v));
+        this->value = v;
+        post();
+        return *this;
+    }
+
+    RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
+        this->pre();
+        JS_ASSERT(!IsPoisonedPtr<T>(v.value));
+        this->value = v.value;
+        post();
+        return *this;
+    }
+
+  protected:
+    void post() { T::writeBarrierRelocPost(this->value, (void *)&this->value); }
+    void relocate() { T::writeBarrierRelocated(this->value, (void *)&this->value); }
+};
+
 /*
  * 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.
@@ -247,6 +308,9 @@ struct Shape;
 class BaseShape;
 namespace types { struct TypeObject; }
 
+typedef RelocatablePtr<JSObject> RelocatablePtrObject;
+typedef RelocatablePtr<JSScript> RelocatablePtrScript;
+
 typedef HeapPtr<JSObject> HeapPtrObject;
 typedef HeapPtr<JSFunction> HeapPtrFunction;
 typedef HeapPtr<JSString> HeapPtrString;
@@ -269,7 +333,7 @@ struct HeapPtrHasher
 
 /* Specialized hashing policy for HeapPtrs. */
 template <class T>
-struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
+struct DefaultHasher< HeapPtr<T> > : HeapPtrHasher<T> { };
 
 class EncapsulatedValue
 {
@@ -376,9 +440,6 @@ class RelocatableValue : public EncapsulatedValue
     inline RelocatableValue &operator=(const Value &v);
     inline RelocatableValue &operator=(const RelocatableValue &v);
 
-    static inline void writeBarrierPost(const Value &v, Value *addr);
-    static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr);
-
   private:
     inline void post();
     inline void post(JSCompartment *comp);
@@ -421,7 +482,7 @@ class HeapSlot : public EncapsulatedValue
  * Run a post write barrier that encompasses multiple contiguous slots in a
  * single step.
  */
-static inline void
+inline void
 SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
 {
 }
@@ -556,11 +617,11 @@ class ReadBarrieredValue
 
 namespace tl {
 
-template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
-                                                    static const bool result = true; };
-template <> struct IsPostBarrieredType<HeapSlot>  { static const bool result = true; };
-template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
-template <> struct IsPostBarrieredType<HeapId>    { static const bool result = true; };
+template <class T> struct IsRelocatableHeapType<HeapPtr<T> >
+                                                    { static const bool result = false; };
+template <> struct IsRelocatableHeapType<HeapSlot>  { static const bool result = false; };
+template <> struct IsRelocatableHeapType<HeapValue> { static const bool result = false; };
+template <> struct IsRelocatableHeapType<HeapId>    { static const bool result = false; };
 
 } /* namespace tl */
 } /* namespace js */