Bug 662001 - Move js::RangeCheckedPointer<T> to mozilla::RangedPtr<T>, make it no longer implicitly convert to T*, and adjust users accordingly. r=cjones
authorJeff Walden <jwalden@mit.edu>
Mon, 06 Jun 2011 11:02:34 -0700
changeset 70703 739c0fd21cccb1eae3de374b6d39616048be2e28
parent 70702 955cb37c90b581fcf4ff0a9c7228abf27413c03a
child 70704 21ab818fcdf6816654c2abe64e774b5a6529db2a
push id20389
push userjwalden@mit.edu
push dateTue, 07 Jun 2011 21:29:42 +0000
treeherdermozilla-central@ac8fceaec76c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs662001
milestone7.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 662001 - Move js::RangeCheckedPointer<T> to mozilla::RangedPtr<T>, make it no longer implicitly convert to T*, and adjust users accordingly. r=cjones
js/src/Makefile.in
js/src/jsonparser.cpp
js/src/jsonparser.h
js/src/jstl.h
mfbt/RangedPtr.h
mfbt/Types.h
mfbt/Util.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -291,16 +291,17 @@ EXPORTS_vm = \
 #
 VPATH		+= \
 		$(srcdir)/../../mfbt \
 		$(NULL)
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla = \
+		RangedPtr.h \
 		Types.h		\
 		Util.h          \
 		$(NULL)
 
 ifdef ENABLE_TRACEJIT
 VPATH		+= \
 		$(srcdir)/tracejit \
 		$(srcdir)/nanojit \
--- a/js/src/jsonparser.cpp
+++ b/js/src/jsonparser.cpp
@@ -76,24 +76,24 @@ JSONParser::readString()
         error("unterminated string literal");
         return token(Error);
     }
 
     /*
      * Optimization: if the source contains no escaped characters, create the
      * string directly from the source text.
      */
-    RangeCheckedPointer<const jschar> start = current;
+    RangedPtr<const jschar> start = current;
     for (; current < end; current++) {
         if (*current == '"') {
             size_t length = current - start;
             current++;
             JSFlatString *str = (ST == JSONParser::PropertyName)
-                                ? js_AtomizeChars(cx, start, length)
-                                : js_NewStringCopyN(cx, start, length);
+                                ? js_AtomizeChars(cx, start.get(), length)
+                                : js_NewStringCopyN(cx, start.get(), length);
             if (!str)
                 return token(OOM);
             return stringToken(str);
         }
 
         if (*current == '\\')
             break;
 
@@ -105,17 +105,17 @@ JSONParser::readString()
 
     /*
      * Slow case: string contains escaped characters.  Copy a maximal sequence
      * of unescaped characters into a temporary buffer, then an escaped
      * character, and repeat until the entire string is consumed.
      */
     StringBuffer buffer(cx);
     do {
-        if (start < current && !buffer.append(start, current))
+        if (start < current && !buffer.append(start.get(), current.get()))
             return token(OOM);
 
         if (current >= end)
             break;
 
         jschar c = *current++;
         if (c == '"') {
             JSFlatString *str = (ST == JSONParser::PropertyName)
@@ -195,17 +195,17 @@ JSONParser::readNumber()
     bool negative = *current == '-';
 
     /* -? */
     if (negative && ++current == end) {
         error("no number after minus sign");
         return token(Error);
     }
 
-    const RangeCheckedPointer<const jschar> digitStart = current;
+    const RangedPtr<const jschar> digitStart = current;
 
     /* 0|[1-9][0-9]+ */
     if (!JS7_ISDEC(*current)) {
         error("unexpected non-digit");
         return token(Error);
     }
     if (*current++ != '0') {
         for (; current < end; current++) {
@@ -213,17 +213,17 @@ JSONParser::readNumber()
                 break;
         }
     }
 
     /* Fast path: no fractional or exponent part. */
     if (current == end || (*current != '.' && *current != 'e' && *current != 'E')) {
         const jschar *dummy;
         jsdouble d;
-        if (!GetPrefixInteger(cx, digitStart, current, 10, &dummy, &d))
+        if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
             return token(OOM);
         JS_ASSERT(current == dummy);
         return numberToken(negative ? -d : d);
     }
 
     /* (\.[0-9]+)? */
     if (current < end && *current == '.') {
         if (++current == end) {
@@ -259,17 +259,17 @@ JSONParser::readNumber()
         while (++current < end) {
             if (!JS7_ISDEC(*current))
                 break;
         }
     }
 
     jsdouble d;
     const jschar *finish;
-    if (!js_strtod(cx, digitStart, current, &finish, &d))
+    if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d))
         return token(OOM);
     JS_ASSERT(current == finish);
     return numberToken(negative ? -d : d);
 }
 
 static inline bool
 IsJSONWhitespace(jschar c)
 {
@@ -377,17 +377,17 @@ JSONParser::advanceAfterObjectOpen()
         return token(ObjectClose);
     }
 
     error("expected property name or '}'");
     return token(Error);
 }
 
 static inline void
-AssertPastValue(const RangeCheckedPointer<const jschar> current)
+AssertPastValue(const RangedPtr<const jschar> current)
 {
     /*
      * We're past an arbitrary JSON value, so the previous character is
      * *somewhat* constrained, even if this assertion is pretty broad.  Don't
      * knock it till you tried it: this assertion *did* catch a bug once.
      */
     JS_ASSERT((current[-1] == 'l' &&
                current[-2] == 'l' &&
--- a/js/src/jsonparser.h
+++ b/js/src/jsonparser.h
@@ -36,36 +36,37 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsonparser_h___
 #define jsonparser_h___
 
+#include "mozilla/RangedPtr.h"
+
 #include "jscntxt.h"
 #include "jsstr.h"
-#include "jstl.h"
 #include "jsvalue.h"
 
 /*
  * NB: This class must only be used on the stack as it contains a js::Value.
  */
 class JSONParser
 {
   public:
     enum ErrorHandling { RaiseError, NoError };
     enum ParsingMode { StrictJSON, LegacyJSON };
 
   private:
     /* Data members */
 
     JSContext * const cx;
-    js::RangeCheckedPointer<const jschar> current;
-    const js::RangeCheckedPointer<const jschar> end;
+    mozilla::RangedPtr<const jschar> current;
+    const mozilla::RangedPtr<const jschar> end;
 
     js::Value v;
 
     const ParsingMode parsingMode;
     const ErrorHandling errorHandling;
 
     enum Token { String, Number, True, False, Null,
                  ArrayOpen, ArrayClose,
@@ -84,17 +85,17 @@ class JSONParser
      * certain legacy, non-JSON syntax if decodingMode is LegacyJSON.
      * Description of this syntax is deliberately omitted: new code should only
      * use strict JSON parsing.
      */
     JSONParser(JSContext *cx, const jschar *data, size_t length,
                ParsingMode parsingMode = StrictJSON,
                ErrorHandling errorHandling = RaiseError)
       : cx(cx),
-        current(data, data, length),
+        current(data, length),
         end(data + length, data, length),
         parsingMode(parsingMode),
         errorHandling(errorHandling)
 #ifdef DEBUG
       , lastToken(Error)
 #endif
     {
         JS_ASSERT(current <= end);
--- a/js/src/jstl.h
+++ b/js/src/jstl.h
@@ -216,29 +216,16 @@ JS_ALWAYS_INLINE size_t
 RoundUpPow2(size_t x)
 {
     size_t log2 = JS_CEILING_LOG2W(x);
     JS_ASSERT(log2 < tl::BitSize<size_t>::result);
     size_t result = size_t(1) << log2;
     return result;
 }
 
-/*
- * Safely subtract two pointers when it is known that end > begin.  This avoids
- * the common compiler bug that if (size_t(end) - size_t(begin)) has the MSB
- * set, the unsigned subtraction followed by right shift will produce -1, or
- * size_t(-1), instead of the real difference.
- */
-template <class T>
-JS_ALWAYS_INLINE size_t
-PointerRangeSize(T *begin, T *end)
-{
-    return (size_t(end) - size_t(begin)) / sizeof(T);
-}
-
 template <class T>
 class AlignedPtrAndFlag
 {
     uintptr_t bits;
 
   public:
     AlignedPtrAndFlag(T *t, bool flag) {
         JS_ASSERT((uintptr_t(t) & 1) == 0);
@@ -329,177 +316,16 @@ Max(T t1, T t2)
 /* Allows a const variable to be initialized after its declaration. */
 template <class T>
 static T&
 InitConst(const T &t)
 {
     return const_cast<T &>(t);
 }
 
-/* Smart pointer, restricted to a range defined at construction. */
-template <class T>
-class RangeCheckedPointer
-{
-    T *ptr;
-
-#ifdef DEBUG
-    T * const rangeStart;
-    T * const rangeEnd;
-#endif
-
-    void sanityChecks() {
-        JS_ASSERT(rangeStart <= ptr);
-        JS_ASSERT(ptr <= rangeEnd);
-    }
-
-    /* Creates a new pointer for |ptr|, restricted to this pointer's range. */
-    RangeCheckedPointer<T> create(T *ptr) const {
-#ifdef DEBUG
-        return RangeCheckedPointer<T>(ptr, rangeStart, rangeEnd);
-#else
-        return RangeCheckedPointer<T>(ptr, NULL, size_t(0));
-#endif
-    }
-
-  public:
-    RangeCheckedPointer(T *p, T *start, T *end)
-      : ptr(p)
-#ifdef DEBUG
-      , rangeStart(start), rangeEnd(end)
-#endif
-    {
-        JS_ASSERT(rangeStart <= rangeEnd);
-        sanityChecks();
-    }
-    RangeCheckedPointer(T *p, T *start, size_t length)
-      : ptr(p)
-#ifdef DEBUG
-      , rangeStart(start), rangeEnd(start + length)
-#endif
-    {
-        JS_ASSERT(length <= size_t(-1) / sizeof(T));
-        JS_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
-        sanityChecks();
-    }
-
-    RangeCheckedPointer<T> &operator=(const RangeCheckedPointer<T> &other) {
-        JS_ASSERT(rangeStart == other.rangeStart);
-        JS_ASSERT(rangeEnd == other.rangeEnd);
-        ptr = other.ptr;
-        sanityChecks();
-        return *this;
-    }
-
-    RangeCheckedPointer<T> operator+(size_t inc) {
-        JS_ASSERT(inc <= size_t(-1) / sizeof(T));
-        JS_ASSERT(ptr + inc > ptr);
-        return create(ptr + inc);
-    }
-
-    RangeCheckedPointer<T> operator-(size_t dec) {
-        JS_ASSERT(dec <= size_t(-1) / sizeof(T));
-        JS_ASSERT(ptr - dec < ptr);
-        return create(ptr - dec);
-    }
-
-    template <class U>
-    RangeCheckedPointer<T> &operator=(U *p) {
-        *this = create(p);
-        return *this;
-    }
-
-    template <class U>
-    RangeCheckedPointer<T> &operator=(const RangeCheckedPointer<U> &p) {
-        JS_ASSERT(rangeStart <= p.ptr);
-        JS_ASSERT(p.ptr <= rangeEnd);
-        ptr = p.ptr;
-        sanityChecks();
-        return *this;
-    }
-
-    RangeCheckedPointer<T> &operator++() {
-        return (*this += 1);
-    }
-
-    RangeCheckedPointer<T> operator++(int) {
-        RangeCheckedPointer<T> rcp = *this;
-        ++*this;
-        return rcp;
-    }
-
-    RangeCheckedPointer<T> &operator--() {
-        return (*this -= 1);
-    }
-
-    RangeCheckedPointer<T> operator--(int) {
-        RangeCheckedPointer<T> rcp = *this;
-        --*this;
-        return rcp;
-    }
-
-    RangeCheckedPointer<T> &operator+=(size_t inc) {
-        this->operator=<T>(*this + inc);
-        return *this;
-    }
-
-    RangeCheckedPointer<T> &operator-=(size_t dec) {
-        this->operator=<T>(*this - dec);
-        return *this;
-    }
-
-    T &operator[](int index) const {
-        JS_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
-        return *create(ptr + index);
-    }
-
-    T &operator*() const {
-        return *ptr;
-    }
-
-    operator T*() const {
-        return ptr;
-    }
-
-    template <class U>
-    bool operator==(const RangeCheckedPointer<U> &other) const {
-        return ptr == other.ptr;
-    }
-    template <class U>
-    bool operator!=(const RangeCheckedPointer<U> &other) const {
-        return !(*this == other);
-    }
-
-    template <class U>
-    bool operator<(const RangeCheckedPointer<U> &other) const {
-        return ptr < other.ptr;
-    }
-    template <class U>
-    bool operator<=(const RangeCheckedPointer<U> &other) const {
-        return ptr <= other.ptr;
-    }
-
-    template <class U>
-    bool operator>(const RangeCheckedPointer<U> &other) const {
-        return ptr > other.ptr;
-    }
-    template <class U>
-    bool operator>=(const RangeCheckedPointer<U> &other) const {
-        return ptr >= other.ptr;
-    }
-
-    size_t operator-(const RangeCheckedPointer<T> &other) const {
-        JS_ASSERT(ptr >= other.ptr);
-        return PointerRangeSize(other.ptr, ptr);
-    }
-
-  private:
-    RangeCheckedPointer();
-    T *operator&();
-};
-
 template <class T, class U>
 JS_ALWAYS_INLINE T &
 ImplicitCast(U &u)
 {
     T &t = u;
     return t;
 }
 
new file mode 100644
--- /dev/null
+++ b/mfbt/RangedPtr.h
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jeff Walden <jwalden+code@mit.edu> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_RangedPtr_h_
+#define mozilla_RangedPtr_h_
+
+#include "mozilla/Util.h"
+
+#ifdef __cplusplus
+
+namespace mozilla {
+
+/*
+ * RangedPtr is a smart pointer restricted to an address range specified at
+ * creation.  The pointer (and any smart pointers derived from it) must remain
+ * within the range [start, end] (inclusive of end to facilitate use as
+ * sentinels).  Dereferencing or indexing into the pointer (or pointers derived
+ * from it) must remain within the range [start, end).  All the standard pointer
+ * operators are defined on it; in debug builds these operations assert that the
+ * range specified at construction is respected.
+ *
+ * In theory passing a smart pointer instance as an argument can be slightly
+ * slower than passing a T* (due to ABI requirements for passing structs versus
+ * passing pointers), if the method being called isn't inlined.  If you are in
+ * extremely performance-critical code, you may want to be careful using this
+ * smart pointer as an argument type.
+ *
+ * RangedPtr<T> intentionally does not implicitly convert to T*.  Use get() to
+ * explicitly convert to T*.  Keep in mind that the raw pointer of course won't
+ * implement bounds checking in debug builds.
+ */
+template <typename T>
+class RangedPtr
+{
+    T* ptr;
+
+#ifdef DEBUG
+    T* const rangeStart;
+    T* const rangeEnd;
+#endif
+
+    void checkSanity() {
+        MOZ_ASSERT(rangeStart <= ptr);
+        MOZ_ASSERT(ptr <= rangeEnd);
+    }
+
+    /* Creates a new pointer for |ptr|, restricted to this pointer's range. */
+    RangedPtr<T> create(T *ptr) const {
+#ifdef DEBUG
+        return RangedPtr<T>(ptr, rangeStart, rangeEnd);
+#else
+        return RangedPtr<T>(ptr, NULL, size_t(0));
+#endif
+    }
+
+  public:
+    RangedPtr(T* p, T* start, T* end)
+      : ptr(p)
+#ifdef DEBUG
+      , rangeStart(start), rangeEnd(end)
+#endif
+    {
+        MOZ_ASSERT(rangeStart <= rangeEnd);
+        checkSanity();
+    }
+    RangedPtr(T* p, T* start, size_t length)
+      : ptr(p)
+#ifdef DEBUG
+      , rangeStart(start), rangeEnd(start + length)
+#endif
+    {
+        MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
+        MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
+        checkSanity();
+    }
+
+    /* Equivalent to RangedPtr(p, p, length). */
+    RangedPtr(T* p, size_t length)
+      : ptr(p)
+#ifdef DEBUG
+      , rangeStart(p), rangeEnd(p + length)
+#endif
+    {
+        MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
+        MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
+        checkSanity();
+    }
+
+    T* get() const {
+        return ptr;
+    }
+
+    /*
+     * You can only assign one RangedPtr into another if the two pointers have
+     * the same valid range:
+     *
+     *   char arr1[] = "hi";
+     *   char arr2[] = "bye";
+     *   RangedPtr<char> p1(arr1, 2);
+     *   p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
+     *   p1 = RangedPtr<char>(arr2, 3);                  // asserts
+     */
+    RangedPtr<T>& operator=(const RangedPtr<T>& other) {
+        MOZ_ASSERT(rangeStart == other.rangeStart);
+        MOZ_ASSERT(rangeEnd == other.rangeEnd);
+        ptr = other.ptr;
+        checkSanity();
+        return *this;
+    }
+
+    RangedPtr<T> operator+(size_t inc) {
+        MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
+        MOZ_ASSERT(ptr + inc > ptr);
+        return create(ptr + inc);
+    }
+
+    RangedPtr<T> operator-(size_t dec) {
+        MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
+        MOZ_ASSERT(ptr - dec < ptr);
+        return create(ptr - dec);
+    }
+
+    /*
+     * You can assign a raw pointer into a RangedPtr if the raw pointer is
+     * within the range specified at creation.
+     */
+    template <typename U>
+    RangedPtr<T>& operator=(U* p) {
+        *this = create(p);
+        return *this;
+    }
+
+    template <typename U>
+    RangedPtr<T>& operator=(const RangedPtr<U>& p) {
+        MOZ_ASSERT(rangeStart <= p.ptr);
+        MOZ_ASSERT(p.ptr <= rangeEnd);
+        ptr = p.ptr;
+        checkSanity();
+        return *this;
+    }
+
+    RangedPtr<T>& operator++() {
+        return (*this += 1);
+    }
+
+    RangedPtr<T> operator++(int) {
+        RangedPtr<T> rcp = *this;
+        ++*this;
+        return rcp;
+    }
+
+    RangedPtr<T>& operator--() {
+        return (*this -= 1);
+    }
+
+    RangedPtr<T> operator--(int) {
+        RangedPtr<T> rcp = *this;
+        --*this;
+        return rcp;
+    }
+
+    RangedPtr<T>& operator+=(size_t inc) {
+        this->operator=<T>(*this + inc);
+        return *this;
+    }
+
+    RangedPtr<T>& operator-=(size_t dec) {
+        this->operator=<T>(*this - dec);
+        return *this;
+    }
+
+    T& operator[](int index) const {
+        MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
+        return *create(ptr + index);
+    }
+
+    T& operator*() const {
+        return *ptr;
+    }
+
+    template <typename U>
+    bool operator==(const RangedPtr<U>& other) const {
+        return ptr == other.ptr;
+    }
+    template <typename U>
+    bool operator!=(const RangedPtr<U>& other) const {
+        return !(*this == other);
+    }
+
+    template<typename U>
+    bool operator==(const U* u) const {
+        return ptr == u;
+    }
+    template<typename U>
+    bool operator!=(const U* u) const {
+        return !(*this == u);
+    }
+
+    template <typename U>
+    bool operator<(const RangedPtr<U>& other) const {
+        return ptr < other.ptr;
+    }
+    template <typename U>
+    bool operator<=(const RangedPtr<U>& other) const {
+        return ptr <= other.ptr;
+    }
+
+    template <typename U>
+    bool operator>(const RangedPtr<U>& other) const {
+        return ptr > other.ptr;
+    }
+    template <typename U>
+    bool operator>=(const RangedPtr<U>& other) const {
+        return ptr >= other.ptr;
+    }
+
+    size_t operator-(const RangedPtr<T>& other) const {
+        MOZ_ASSERT(ptr >= other.ptr);
+        return PointerRangeSize(other.ptr, ptr);
+    }
+
+  private:
+    RangedPtr();
+    T* operator&();
+    operator T*() const;
+};
+
+} /* namespace mozilla */
+
+#endif /* __cplusplus */
+
+#endif  /* mozilla_RangedPtr_h_ */
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -13,17 +13,17 @@
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Mozilla Code.
  *
  * The Initial Developer of the Original Code is
  *   The Mozilla Foundation
- * Portions created by the Initial Developer are Copyrigght (C) 2011
+ * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
--- a/mfbt/Util.h
+++ b/mfbt/Util.h
@@ -13,17 +13,17 @@
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Mozilla Code.
  *
  * The Initial Developer of the Original Code is
  *   The Mozilla Foundation
- * Portions created by the Initial Developer are Copyrigght (C) 2011
+ * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
@@ -74,16 +74,69 @@ MOZ_END_EXTERN_C
     ((expr_) ? (void)0 : JS_Assert(#expr_, __FILE__, __LINE__))
 
 #else
 
 # define MOZ_ASSERT(expr_) ((void)0)
 
 #endif  /* DEBUG */
 
+/*
+ * MOZ_INLINE is a macro which expands to tell the compiler that the method
+ * decorated with it should be inlined.  This macro is usable from C and C++
+ * code, even though C89 does not support the |inline| keyword.  The compiler
+ * may ignore this directive if it chooses.
+ */
+#ifndef MOZ_INLINE
+# if defined __cplusplus
+#  define MOZ_INLINE          inline
+# elif defined _MSC_VER
+#  define MOZ_INLINE          __inline
+# elif defined __GNUC__
+#  define MOZ_INLINE          __inline__
+# else
+#  define MOZ_INLINE          inline
+# endif
+#endif
+
+/*
+ * MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must be inlined, even if the compiler thinks
+ * otherwise.  This is only a (much) stronger version of the MOZ_INLINE hint:
+ * compilers are not guaranteed to respect it (although they're much more likely
+ * to do so).
+ */
+#ifndef MOZ_ALWAYS_INLINE
+# if defined DEBUG
+#  define MOZ_ALWAYS_INLINE   MOZ_INLINE
+# elif defined _MSC_VER
+#  define MOZ_ALWAYS_INLINE   __forceinline
+# elif defined __GNUC__
+#  define MOZ_ALWAYS_INLINE   __attribute__((always_inline)) MOZ_INLINE
+# else
+#  define MOZ_ALWAYS_INLINE   MOZ_INLINE
+# endif
+#endif
+
+/*
+ * MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
+ * method decorated with it must never be inlined, even if the compiler would
+ * otherwise choose to inline the method.  Compilers aren't absolutely
+ * guaranteed to support this, but most do.
+ */
+#ifndef MOZ_NEVER_INLINE
+# if defined _MSC_VER
+#  define MOZ_NEVER_INLINE __declspec(noinline)
+# elif defined __GNUC__
+#  define MOZ_NEVER_INLINE __attribute__((noinline))
+# else
+#  define MOZ_NEVER_INLINE
+# endif
+#endif
+
 #ifdef __cplusplus
 
 namespace mozilla {
 
 /**
  * DebugOnly contains a value of type T, but only in debug builds.  In
  * release builds, it does not contain a value.  This helper is
  * intended to be used along with ASSERT()-style macros, allowing one
@@ -245,13 +298,27 @@ class Maybe
     }
 
     void destroyIfConstructed() {
         if (!empty())
             destroy();
     }
 };
 
+/*
+ * Safely subtract two pointers when it is known that end >= begin.  This avoids
+ * the common compiler bug that if (size_t(end) - size_t(begin)) has the MSB
+ * set, the unsigned subtraction followed by right shift will produce -1, or
+ * size_t(-1), instead of the real difference.
+ */
+template <class T>
+MOZ_ALWAYS_INLINE size_t
+PointerRangeSize(T* begin, T* end)
+{
+    MOZ_ASSERT(end >= begin);
+    return (size_t(end) - size_t(begin)) / sizeof(T);
+}
+
 } /* namespace mozilla */
 
 #endif /* __cplusplus */
 
 #endif  /* mozilla_Util_h_ */