Bug 684526 - Unify jsval and js::Value (r=jorendorff)
authorLuke Wagner <luke@mozilla.com>
Mon, 19 Sep 2011 09:34:49 -0700
changeset 77302 4f9a7183a1973cde3e1804168272729ed4390537
parent 77301 4801c2f7bef8b86f575c951bf0357779d6213039
child 77303 5c29c2e922251dd88637360643cbc78b9b7c3888
push id21194
push usereakhgari@mozilla.com
push dateThu, 22 Sep 2011 15:27:25 +0000
treeherdermozilla-central@45db8c3384e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs684526
milestone9.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 684526 - Unify jsval and js::Value (r=jorendorff)
content/base/public/nsINode.h
content/events/src/nsDOMMessageEvent.h
dom/workers/ListenerManager.h
dom/workers/ScriptLoader.h
dom/workers/XMLHttpRequest.h
ipc/testshell/TestShellParent.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarrayinlines.h
js/src/jsclone.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jsgc.h
js/src/jsnum.cpp
js/src/jsobjinlines.h
js/src/jsprvtd.h
js/src/jspubtd.h
js/src/jstracer.cpp
js/src/jsutil.h
js/src/jsval.h
js/src/jsvalue.h
js/src/jsxml.cpp
js/src/methodjit/FrameEntry.h
js/src/methodjit/NunboxAssembler.h
js/src/methodjit/PunboxAssembler.h
js/src/vm/String.h
js/src/xpconnect/idl/xpcexception.idl
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpcquickstubs.cpp
storage/src/Variant_inl.h
xpcom/ds/nsVariant.cpp
xpcom/idl-parser/xpidl.py
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1356,18 +1356,18 @@ protected:
      NS_IMETHOD because some subclasses implement DOM methods with
      this exact name and signature and then the calling convention
      needs to match.
 
      Note that we include DOCUMENT_ONLY_EVENT events here so that we
      can forward all the document stuff to this implementation.
   */
 #define EVENT(name_, id_, type_, struct_)                         \
-  NS_IMETHOD GetOn##name_(JSContext *cx, jsval *vp);              \
-  NS_IMETHOD SetOn##name_(JSContext *cx, const jsval &v);
+  NS_IMETHOD GetOn##name_(JSContext *cx, JS::Value *vp);          \
+  NS_IMETHOD SetOn##name_(JSContext *cx, const JS::Value &v);
 #define TOUCH_EVENT EVENT
 #define DOCUMENT_ONLY_EVENT EVENT
 #include "nsEventNameList.h"
 #undef DOCUMENT_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef EVENT  
 
   static void Trace(nsINode *tmp, TraceCallback cb, void *closure);
--- a/content/events/src/nsDOMMessageEvent.h
+++ b/content/events/src/nsDOMMessageEvent.h
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsDOMMessageEvent_h__
 #define nsDOMMessageEvent_h__
 
 #include "nsIDOMMessageEvent.h"
 #include "nsDOMEvent.h"
 #include "nsCycleCollectionParticipant.h"
+#include "jsapi.h"
 
 /**
  * Implements the MessageEvent event, used for cross-document messaging and
  * server-sent events.
  *
  * See http://www.whatwg.org/specs/web-apps/current-work/#messageevent for
  * further details.
  */
--- a/dom/workers/ListenerManager.h
+++ b/dom/workers/ListenerManager.h
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_workers_listenermanager_h__
 #define mozilla_dom_workers_listenermanager_h__
 
 #include "Workers.h"
 
-#include "jspubtd.h"
+#include "jsapi.h"
 #include "prclist.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace events {
 
 // XXX Current impl doesn't divide into phases.
 // XXX Current impl doesn't handle event target chains.
--- a/dom/workers/ScriptLoader.h
+++ b/dom/workers/ScriptLoader.h
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_workers_scriptloader_h__
 #define mozilla_dom_workers_scriptloader_h__
 
 #include "Workers.h"
 
-#include "jspubtd.h"
+#include "jsapi.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace scriptloader {
 
 bool LoadWorkerScript(JSContext* aCx);
 
 bool Load(JSContext* aCx, uintN aURLCount, jsval* aURLs);
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_workers_xmlhttprequest_h__
 #define mozilla_dom_workers_xmlhttprequest_h__
 
 #include "Workers.h"
 
-#include "jspubtd.h"
+#include "jsapi.h"
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace xhr {
 
 bool
 InitClasses(JSContext* aCx, JSObject* aGlobal, JSObject* aProto);
 
--- a/ipc/testshell/TestShellParent.cpp
+++ b/ipc/testshell/TestShellParent.cpp
@@ -110,17 +110,17 @@ TestShellCommandParent::SetCallback(JSCo
   mCx = aCx;
 
   return JS_TRUE;
 }
 
 JSBool
 TestShellCommandParent::RunCallback(const nsString& aResponse)
 {
-  NS_ENSURE_TRUE(mCallback != JSVAL_NULL && mCx, JS_FALSE);
+  NS_ENSURE_TRUE(*mCallback.ToJSValPtr() != JSVAL_NULL && mCx, JS_FALSE);
 
   JSAutoRequest ar(mCx);
 
   JSObject* global = JS_GetGlobalObject(mCx);
   NS_ENSURE_TRUE(global, JS_FALSE);
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(mCx, global)) {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -162,30 +162,28 @@ class AutoVersionAPI
 };
 
 #ifdef HAVE_VA_LIST_AS_ARRAY
 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
 #else
 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
 #endif
 
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
-JS_PUBLIC_DATA(jsid) JSID_VOID  = { size_t(JSID_TYPE_VOID) };
-JS_PUBLIC_DATA(jsid) JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
+#ifdef JS_USE_JSID_STRUCT_TYPES
+jsid JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
+jsid JSID_VOID  = { size_t(JSID_TYPE_VOID) };
+jsid JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
 #endif
 
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-JS_PUBLIC_DATA(jsval) JSVAL_NULL  = { BUILD_JSVAL(JSVAL_TAG_NULL,      0) };
-JS_PUBLIC_DATA(jsval) JSVAL_ZERO  = { BUILD_JSVAL(JSVAL_TAG_INT32,     0) };
-JS_PUBLIC_DATA(jsval) JSVAL_ONE   = { BUILD_JSVAL(JSVAL_TAG_INT32,     1) };
-JS_PUBLIC_DATA(jsval) JSVAL_FALSE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_FALSE) };
-JS_PUBLIC_DATA(jsval) JSVAL_TRUE  = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_TRUE) };
-JS_PUBLIC_DATA(jsval) JSVAL_VOID  = { BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0) };
-#endif
+const jsval JSVAL_NULL  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_NULL,      0));
+const jsval JSVAL_ZERO  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32,     0));
+const jsval JSVAL_ONE   = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_INT32,     1));
+const jsval JSVAL_FALSE = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_FALSE));
+const jsval JSVAL_TRUE  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_TRUE));
+const jsval JSVAL_VOID  = IMPL_TO_JSVAL(BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0));
 
 /* Make sure that jschar is two bytes unsigned integer */
 JS_STATIC_ASSERT((jschar)-1 > 0);
 JS_STATIC_ASSERT(sizeof(jschar) == 2);
 
 JS_PUBLIC_API(int64)
 JS_Now()
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -43,115 +43,1287 @@
 /*
  * JavaScript API.
  */
 #include <stddef.h>
 #include <stdio.h>
 #include "js-config.h"
 #include "jspubtd.h"
 #include "jsutil.h"
+#include "jsval.h"
+
+/************************************************************************/
+
+/* JS::Value can store a full int32. */
+#define JSVAL_INT_BITS          32
+#define JSVAL_INT_MIN           ((jsint)0x80000000)
+#define JSVAL_INT_MAX           ((jsint)0x7fffffff)
+
+/************************************************************************/
+
+#ifdef __cplusplus
+namespace JS {
+
+/*
+ * Protecting non-jsval, non-JSObject *, non-JSString * values from collection
+ *
+ * Most of the time, the garbage collector's conservative stack scanner works
+ * behind the scenes, finding all live values and protecting them from being
+ * collected. However, when JSAPI client code obtains a pointer to data the
+ * scanner does not know about, owned by an object the scanner does know about,
+ * Care Must Be Taken.
+ *
+ * The scanner recognizes only a select set of types: pointers to JSObjects and
+ * similar things (JSFunctions, and so on), pointers to JSStrings, and jsvals.
+ * So while the scanner finds all live |JSString| pointers, it does not notice
+ * |jschar| pointers.
+ *
+ * So suppose we have:
+ *
+ *   void f(JSString *str) {
+ *     const jschar *ch = JS_GetStringCharsZ(str);
+ *     ... do stuff with ch, but no uses of str ...;
+ *   }
+ *
+ * After the call to |JS_GetStringCharsZ|, there are no further uses of
+ * |str|, which means that the compiler is within its rights to not store
+ * it anywhere. But because the stack scanner will not notice |ch|, there
+ * is no longer any live value in this frame that would keep the string
+ * alive. If |str| is the last reference to that |JSString|, and the
+ * collector runs while we are using |ch|, the string's array of |jschar|s
+ * may be freed out from under us.
+ *
+ * Note that there is only an issue when 1) we extract a thing X the scanner
+ * doesn't recognize from 2) a thing Y the scanner does recognize, and 3) if Y
+ * gets garbage-collected, then X gets freed. If we have code like this:
+ *
+ *   void g(JSObject *obj) {
+ *     jsval x;
+ *     JS_GetProperty(obj, "x", &x);
+ *     ... do stuff with x ...
+ *   }
+ *
+ * there's no problem, because the value we've extracted, x, is a jsval, a
+ * type that the conservative scanner recognizes.
+ *
+ * Conservative GC frees us from the obligation to explicitly root the types it
+ * knows about, but when we work with derived values like |ch|, we must root
+ * their owners, as the derived value alone won't keep them alive.
+ *
+ * A JS::Anchor is a kind of GC root that allows us to keep the owners of
+ * derived values like |ch| alive throughout the Anchor's lifetime. We could
+ * fix the above code as follows:
+ *
+ *   void f(JSString *str) {
+ *     JS::Anchor<JSString *> a_str(str);
+ *     const jschar *ch = JS_GetStringCharsZ(str);
+ *     ... do stuff with ch, but no uses of str ...;
+ *   }
+ *
+ * This simply ensures that |str| will be live until |a_str| goes out of scope.
+ * As long as we don't retain a pointer to the string's characters for longer
+ * than that, we have avoided all garbage collection hazards.
+ */
+template<typename T> class AnchorPermitted;
+template<> class AnchorPermitted<JSObject *> { };
+template<> class AnchorPermitted<const JSObject *> { };
+template<> class AnchorPermitted<JSFunction *> { };
+template<> class AnchorPermitted<const JSFunction *> { };
+template<> class AnchorPermitted<JSString *> { };
+template<> class AnchorPermitted<const JSString *> { };
+template<> class AnchorPermitted<Value> { };
+
+template<typename T>
+class Anchor: AnchorPermitted<T>
+{
+  public:
+    Anchor() { }
+    explicit Anchor(T t) { hold = t; }
+    inline ~Anchor();
+    T &get() { return hold; }
+    const T &get() const { return hold; }
+    void set(const T &t) { hold = t; }
+    void clear() { hold = 0; }
+  private:
+    T hold;
+    /* Anchors should not be assigned or passed to functions. */
+    Anchor(const Anchor &);
+    const Anchor &operator=(const Anchor &);
+};
+
+#ifdef __GNUC__
+template<typename T>
+inline Anchor<T>::~Anchor()
+{
+    /*
+     * No code is generated for this. But because this is marked 'volatile', G++ will
+     * assume it has important side-effects, and won't delete it. (G++ never looks at
+     * the actual text and notices it's empty.) And because we have passed |hold| to
+     * it, GCC will keep |hold| alive until this point.
+     *
+     * The "memory" clobber operand ensures that G++ will not move prior memory
+     * accesses after the asm --- it's a barrier. Unfortunately, it also means that
+     * G++ will assume that all memory has changed after the asm, as it would for a
+     * call to an unknown function. I don't know of a way to avoid that consequence.
+     */
+    asm volatile("":: "g" (hold) : "memory");
+}
+#else
+template<typename T>
+inline Anchor<T>::~Anchor()
+{
+    /*
+     * An adequate portable substitute, for non-structure types.
+     *
+     * The compiler promises that, by the end of an expression statement, the
+     * last-stored value to a volatile object is the same as it would be in an
+     * unoptimized, direct implementation (the "abstract machine" whose behavior the
+     * language spec describes). However, the compiler is still free to reorder
+     * non-volatile accesses across this store --- which is what we must prevent. So
+     * assigning the held value to a volatile variable, as we do here, is not enough.
+     *
+     * In our case, however, garbage collection only occurs at function calls, so it
+     * is sufficient to ensure that the destructor's store isn't moved earlier across
+     * any function calls that could collect. It is hard to imagine the compiler
+     * analyzing the program so thoroughly that it could prove that such motion was
+     * safe. In practice, compilers treat calls to the collector as opaque operations
+     * --- in particular, as operations which could access volatile variables, across
+     * which this destructor must not be moved.
+     *
+     * ("Objection, your honor!  *Alleged* killer whale!")
+     *
+     * The disadvantage of this approach is that it does generate code for the store.
+     * We do need to use Anchors in some cases where cycles are tight.
+     *
+     * NB: there is a Anchor<Value>::~Anchor() specialization below.
+     */
+    volatile T sink;
+    sink = hold;
+}
+#endif  /* defined(__GNUC__) */
+
+/*
+ * JS::Value is the C++ interface for a single JavaScript Engine value.
+ * A few general notes on JS::Value:
+ *
+ * - JS::Value has setX() and isX() members for X in
+ *
+ *     { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
+ *
+ *   JS::Value also contains toX() for each of the non-singleton types.
+ *
+ * - Magic is a singleton type whose payload contains a JSWhyMagic "reason" for
+ *   the magic value. By providing JSWhyMagic values when creating and checking
+ *   for magic values, it is possible to assert, at runtime, that only magic
+ *   values with the expected reason flow through a particular value. For
+ *   example, if cx->exception has a magic value, the reason must be
+ *   JS_GENERATOR_CLOSING.
+ *
+ * - A key difference between jsval and JS::Value is that JS::Value gives null
+ *   a separate type. Thus
+ *
+ *           JSVAL_IS_OBJECT(v) === v.isObjectOrNull()
+ *       !JSVAL_IS_PRIMITIVE(v) === v.isObject()
+ *
+ *   To help prevent mistakenly boxing a nullable JSObject* as an object,
+ *   Value::setObject takes a JSObject&. (Conversely, Value::asObject returns a
+ *   JSObject&. A convenience member Value::setObjectOrNull is provided.
+ *
+ * - JSVAL_VOID is the same as the singleton value of the Undefined type.
+ *
+ * - Note that JS::Value is 8 bytes on 32 and 64-bit architectures. Thus, on
+ *   32-bit user code should avoid copying jsval/JS::Value as much as possible,
+ *   preferring to pass by const Value &.
+ */
+class Value
+{
+  public:
+    /*
+     * N.B. the default constructor leaves Value unitialized. Adding a default
+     * constructor prevents Value from being stored in a union.
+     */
+
+    /*** Mutatators ***/
+
+    JS_ALWAYS_INLINE
+    void setNull() {
+        data.asBits = BUILD_JSVAL(JSVAL_TAG_NULL, 0).asBits;
+    }
+
+    JS_ALWAYS_INLINE
+    void setUndefined() {
+        data.asBits = BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0).asBits;
+    }
+
+    JS_ALWAYS_INLINE
+    void setInt32(int32 i) {
+        data = INT32_TO_JSVAL_IMPL(i);
+    }
+
+    JS_ALWAYS_INLINE
+    int32 &getInt32Ref() {
+        JS_ASSERT(isInt32());
+        return data.s.payload.i32;
+    }
+
+    JS_ALWAYS_INLINE
+    void setDouble(double d) {
+        data = DOUBLE_TO_JSVAL_IMPL(d);
+    }
+
+    JS_ALWAYS_INLINE
+    double &getDoubleRef() {
+        JS_ASSERT(isDouble());
+        return data.asDouble;
+    }
+
+    JS_ALWAYS_INLINE
+    void setString(JSString *str) {
+        data = STRING_TO_JSVAL_IMPL(str);
+    }
+
+    JS_ALWAYS_INLINE
+    void setString(const JS::Anchor<JSString *> &str) {
+        setString(str.get());
+    }
+
+    JS_ALWAYS_INLINE
+    void setObject(JSObject &obj) {
+        data = OBJECT_TO_JSVAL_IMPL(&obj);
+    }
+
+    JS_ALWAYS_INLINE
+    void setObject(const JS::Anchor<JSObject *> &obj) {
+        setObject(*obj.get());
+    }
+
+    JS_ALWAYS_INLINE
+    void setBoolean(bool b) {
+        data = BOOLEAN_TO_JSVAL_IMPL(b);
+    }
+
+    JS_ALWAYS_INLINE
+    void setMagic(JSWhyMagic why) {
+        data = MAGIC_TO_JSVAL_IMPL(why);
+    }
+
+    JS_ALWAYS_INLINE
+    void setMagicWithObjectOrNullPayload(JSObject *obj) {
+        data = MAGIC_OBJ_TO_JSVAL_IMPL(obj);
+    }
+
+    JS_ALWAYS_INLINE
+    JSObject *getMagicObjectOrNullPayload() const {
+        return MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool setNumber(uint32 ui) {
+        if (ui > JSVAL_INT_MAX) {
+            setDouble((double)ui);
+            return false;
+        } else {
+            setInt32((int32)ui);
+            return true;
+        }
+    }
+
+    JS_ALWAYS_INLINE
+    bool setNumber(double d) {
+        int32 i;
+        if (JSDOUBLE_IS_INT32(d, &i)) {
+            setInt32(i);
+            return true;
+        } else {
+            setDouble(d);
+            return false;
+        }
+    }
+
+    JS_ALWAYS_INLINE
+    void setObjectOrNull(JSObject *arg) {
+        if (arg)
+            setObject(*arg);
+        else
+            setNull();
+    }
+
+    JS_ALWAYS_INLINE
+    void setObjectOrUndefined(JSObject *arg) {
+        if (arg)
+            setObject(*arg);
+        else
+            setUndefined();
+    }
+
+    JS_ALWAYS_INLINE
+    void swap(Value &rhs) {
+        uint64 tmp = rhs.data.asBits;
+        rhs.data.asBits = data.asBits;
+        data.asBits = tmp;
+    }
+
+    /*** Value type queries ***/
+
+    JS_ALWAYS_INLINE
+    bool isUndefined() const {
+        return JSVAL_IS_UNDEFINED_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isNull() const {
+        return JSVAL_IS_NULL_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isNullOrUndefined() const {
+        return isNull() || isUndefined();
+    }
+
+    JS_ALWAYS_INLINE
+    bool isInt32() const {
+        return JSVAL_IS_INT32_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isInt32(int32 i32) const {
+        return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isDouble() const {
+        return JSVAL_IS_DOUBLE_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isNumber() const {
+        return JSVAL_IS_NUMBER_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isString() const {
+        return JSVAL_IS_STRING_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isObject() const {
+        return JSVAL_IS_OBJECT_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isPrimitive() const {
+        return JSVAL_IS_PRIMITIVE_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isObjectOrNull() const {
+        return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isGCThing() const {
+        return JSVAL_IS_GCTHING_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isBoolean() const {
+        return JSVAL_IS_BOOLEAN_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isTrue() const {
+        return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isFalse() const {
+        return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isMagic() const {
+        return JSVAL_IS_MAGIC_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isMagic(JSWhyMagic why) const {
+        JS_ASSERT_IF(isMagic(), data.s.payload.why == why);
+        return JSVAL_IS_MAGIC_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool isMagicCheck(JSWhyMagic why) const {
+        return isMagic() && data.s.payload.why == why;
+    }
+
+#if JS_BITS_PER_WORD == 64
+    JS_ALWAYS_INLINE
+    bool hasPtrPayload() const {
+        return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET;
+    }
+#endif
+
+    JS_ALWAYS_INLINE
+    bool isMarkable() const {
+        return JSVAL_IS_TRACEABLE_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    JSGCTraceKind gcKind() const {
+        JS_ASSERT(isMarkable());
+        return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
+    }
+
+    JS_ALWAYS_INLINE
+    JSWhyMagic whyMagic() const {
+        JS_ASSERT(isMagic());
+        return data.s.payload.why;
+    }
+
+    /*** Comparison ***/
+
+    JS_ALWAYS_INLINE
+    bool operator==(const Value &rhs) const {
+        return data.asBits == rhs.data.asBits;
+    }
+
+    JS_ALWAYS_INLINE
+    bool operator!=(const Value &rhs) const {
+        return data.asBits != rhs.data.asBits;
+    }
+
+    friend inline bool SameType(const Value &lhs, const Value &rhs);
+
+    /*** Extract the value's typed payload ***/
+
+    JS_ALWAYS_INLINE
+    int32 toInt32() const {
+        JS_ASSERT(isInt32());
+        return JSVAL_TO_INT32_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    double toDouble() const {
+        JS_ASSERT(isDouble());
+        return data.asDouble;
+    }
+
+    JS_ALWAYS_INLINE
+    double toNumber() const {
+        JS_ASSERT(isNumber());
+        return isDouble() ? toDouble() : double(toInt32());
+    }
+
+    JS_ALWAYS_INLINE
+    JSString *toString() const {
+        JS_ASSERT(isString());
+        return JSVAL_TO_STRING_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    JSObject &toObject() const {
+        JS_ASSERT(isObject());
+        return *JSVAL_TO_OBJECT_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    JSObject *toObjectOrNull() const {
+        JS_ASSERT(isObjectOrNull());
+        return JSVAL_TO_OBJECT_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    void *toGCThing() const {
+        JS_ASSERT(isGCThing());
+        return JSVAL_TO_GCTHING_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    bool toBoolean() const {
+        JS_ASSERT(isBoolean());
+        return JSVAL_TO_BOOLEAN_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    uint32 payloadAsRawUint32() const {
+        JS_ASSERT(!isDouble());
+        return data.s.payload.u32;
+    }
+
+    JS_ALWAYS_INLINE
+    uint64 asRawBits() const {
+        return data.asBits;
+    }
+
+    JS_ALWAYS_INLINE
+    void setRawBits(uint64 bits) {
+        data.asBits = bits;
+    }
+
+    /*
+     * In the extract/box/unbox functions below, "NonDouble" means this
+     * functions must not be called on a value that is a double. This allows
+     * these operations to be implemented more efficiently, since doubles
+     * generally already require special handling by the caller.
+     */
+    JS_ALWAYS_INLINE
+    JSValueType extractNonDoubleType() const {
+        return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    JSValueTag extractNonDoubleTag() const {
+        return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    void unboxNonDoubleTo(uint64 *out) const {
+        UNBOX_NON_DOUBLE_JSVAL(data, out);
+    }
+
+    JS_ALWAYS_INLINE
+    void boxNonDoubleFrom(JSValueType type, uint64 *out) {
+        data = BOX_NON_DOUBLE_JSVAL(type, out);
+    }
+
+    /*
+     * The trace-jit specializes JSVAL_TYPE_OBJECT into JSVAL_TYPE_FUNOBJ and
+     * JSVAL_TYPE_NONFUNOBJ. Since these two operations just return the type of
+     * a value, the caller must handle JSVAL_TYPE_OBJECT separately.
+     */
+    JS_ALWAYS_INLINE
+    JSValueType extractNonDoubleObjectTraceType() const {
+        JS_ASSERT(!isObject());
+        return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    JSValueTag extractNonDoubleObjectTraceTag() const {
+        JS_ASSERT(!isObject());
+        return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
+    }
+
+    /*
+     * Private API
+     *
+     * Private setters/getters allow the caller to read/write arbitrary types
+     * that fit in the 64-bit payload. It is the caller's responsibility, after
+     * storing to a value with setPrivateX to read only using getPrivateX.
+     * Privates values are given a type type which ensures they are not marked.
+     */
+
+    JS_ALWAYS_INLINE
+    void setPrivate(void *ptr) {
+        data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
+    }
+
+    JS_ALWAYS_INLINE
+    void *toPrivate() const {
+        JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
+        return JSVAL_TO_PRIVATE_PTR_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    void setPrivateUint32(uint32 ui) {
+        data = PRIVATE_UINT32_TO_JSVAL_IMPL(ui);
+    }
+
+    JS_ALWAYS_INLINE
+    uint32 toPrivateUint32() const {
+        JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
+        return JSVAL_TO_PRIVATE_UINT32_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
+    uint32 &getPrivateUint32Ref() {
+        JS_ASSERT(isDouble());
+        return data.s.payload.u32;
+    }
+
+    /*
+     * An unmarked value is just a void* cast as a Value. Thus, the Value is
+     * not safe for GC and must not be marked. This API avoids raw casts
+     * and the ensuing strict-aliasing warnings.
+     */
+
+    JS_ALWAYS_INLINE
+    void setUnmarkedPtr(void *ptr) {
+        data.asPtr = ptr;
+    }
+
+    JS_ALWAYS_INLINE
+    void *toUnmarkedPtr() const {
+        return data.asPtr;
+    }
+
+    const size_t *payloadWord() const {
+#if JS_BITS_PER_WORD == 32
+        return &data.s.payload.word;
+#elif JS_BITS_PER_WORD == 64
+        return &data.asWord;
+#endif
+    }
+
+  private:
+    void staticAssertions() {
+        JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
+        JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
+        JS_STATIC_ASSERT(sizeof(JSBool) == 4);
+        JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
+        JS_STATIC_ASSERT(sizeof(Value) == 8);
+    }
+
+    jsval_layout data;
+
+    friend jsval_layout (::JSVAL_TO_IMPL)(Value);
+    friend Value (::IMPL_TO_JSVAL)(jsval_layout l);
+} JSVAL_ALIGNMENT;
+
+/************************************************************************/
+
+static JS_ALWAYS_INLINE Value
+NullValue()
+{
+    Value v;
+    v.setNull();
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+UndefinedValue()
+{
+    Value v;
+    v.setUndefined();
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+Int32Value(int32 i32)
+{
+    Value v;
+    v.setInt32(i32);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+DoubleValue(double dbl)
+{
+    Value v;
+    v.setDouble(dbl);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+StringValue(JSString *str)
+{
+    Value v;
+    v.setString(str);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+BooleanValue(bool boo)
+{
+    Value v;
+    v.setBoolean(boo);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+ObjectValue(JSObject &obj)
+{
+    Value v;
+    v.setObject(obj);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+MagicValue(JSWhyMagic why)
+{
+    Value v;
+    v.setMagic(why);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+NumberValue(double dbl)
+{
+    Value v;
+    v.setNumber(dbl);
+    return v;
+}
+
+static JS_ALWAYS_INLINE Value
+ObjectOrNullValue(JSObject *obj)
+{
+    Value v;
+    v.setObjectOrNull(obj);
+    return v;
+}
+
+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;
+}
+
+JS_ALWAYS_INLINE bool
+SameType(const Value &lhs, const Value &rhs)
+{
+    return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
+}
+
+/************************************************************************/
+
+/*
+ * The default assignment operator for |struct C| has the signature:
+ *
+ *   C& C::operator=(const C&)
+ *
+ * And in particular requires implicit conversion of |this| to type |C| for the
+ * return value. But |volatile C| cannot thus be converted to |C|, so just
+ * doing |sink = hold| as in the non-specialized version would fail to compile.
+ * Do the assignment on asBits instead, since I don't think we want to give
+ * jsval_layout an assignment operator returning |volatile jsval_layout|.
+ */
+template<>
+inline Anchor<Value>::~Anchor()
+{
+    volatile uint64 bits;
+    bits = hold.asRawBits();
+}
+
+}  /* namespace JS */
+
+/************************************************************************/
+
+/*
+ * JS::Value and jsval are the same type; jsval is the old name, kept around
+ * for backwards compatibility along with all the JSVAL_* operations below.
+ * jsval_layout is an implementation detail and should not be used externally.
+ */
+typedef JS::Value jsval;
+
+static JS_ALWAYS_INLINE jsval_layout
+JSVAL_TO_IMPL(jsval v)
+{
+    return v.data;
+}
+
+static JS_ALWAYS_INLINE jsval
+IMPL_TO_JSVAL(jsval_layout l)
+{
+    JS::Value v;
+    v.data = l;
+    return v;
+}
+
+#else  /* defined(__cplusplus) */
+
+/*
+ * For SpiderMonkey C clients, there is no JS::Value class, only the
+ * traditional jsval with the traditional JSVAL_* operations. Since
+ * SpiderMonkey itself is always compiled as C++, this relies on the binary
+ * compatibility of jsval_layout and JS::Value (statically asserted below).
+ */
+typedef union jsval_layout jsval;
+
+static JS_ALWAYS_INLINE jsval_layout
+JSVAL_TO_IMPL(jsval v)
+{
+    return v;
+}
+
+static JS_ALWAYS_INLINE jsval
+IMPL_TO_JSVAL(jsval_layout l)
+{
+    return l;
+}
+
+#endif  /* defined(__cplusplus) */
+
+JS_STATIC_ASSERT(sizeof(jsval_layout) == sizeof(jsval));
+
+/************************************************************************/
+
+/* JSClass (and ObjectOps where appropriate) function pointer typedefs. */
+
+/*
+ * Add, delete, or get a property named by id in obj.  Note the jsid id
+ * type -- id may be a string (Unicode property identifier) or an int (element
+ * index).  The *vp out parameter, on success, is the new property value after
+ * an add or get.  After a successful delete, *vp is JSVAL_FALSE iff
+ * obj[id] can't be deleted (because it's permanent).
+ */
+typedef JSBool
+(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+/*
+ * Set a property named by id in obj, treating the assignment as strict
+ * mode code if strict is true. Note the jsid id type -- id may be a string
+ * (Unicode property identifier) or an int (element index). The *vp out
+ * parameter, on success, is the new property value after the
+ * set.
+ */
+typedef JSBool
+(* JSStrictPropertyOp)(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
+
+/*
+ * This function type is used for callbacks that enumerate the properties of
+ * a JSObject.  The behavior depends on the value of enum_op:
+ *
+ *  JSENUMERATE_INIT
+ *    A new, opaque iterator state should be allocated and stored in *statep.
+ *    (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
+ *
+ *    The number of properties that will be enumerated should be returned as
+ *    an integer jsval in *idp, if idp is non-null, and provided the number of
+ *    enumerable properties is known.  If idp is non-null and the number of
+ *    enumerable properties can't be computed in advance, *idp should be set
+ *    to JSVAL_ZERO.
+ *
+ *  JSENUMERATE_INIT_ALL
+ *    Used identically to JSENUMERATE_INIT, but exposes all properties of the
+ *    object regardless of enumerability.
+ *
+ *  JSENUMERATE_NEXT
+ *    A previously allocated opaque iterator state is passed in via statep.
+ *    Return the next jsid in the iteration using *idp.  The opaque iterator
+ *    state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
+ *    if there are no properties left to enumerate.
+ *
+ *  JSENUMERATE_DESTROY
+ *    Destroy the opaque iterator state previously allocated in *statep by a
+ *    call to this function when enum_op was JSENUMERATE_INIT or
+ *    JSENUMERATE_INIT_ALL.
+ *
+ * The return value is used to indicate success, with a value of JS_FALSE
+ * indicating failure.
+ */
+typedef JSBool
+(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+                     jsval *statep, jsid *idp);
+
+/*
+ * The old-style JSClass.enumerate op should define all lazy properties not
+ * yet reflected in obj.
+ */
+typedef JSBool
+(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Resolve a lazy property named by id in obj by defining it directly in obj.
+ * Lazy properties are those reflected from some peer native property space
+ * (e.g., the DOM attributes for a given node reflected as obj) on demand.
+ *
+ * JS looks for a property in an object, and if not found, tries to resolve
+ * the given id.  If resolve succeeds, the engine looks again in case resolve
+ * defined obj[id].  If no such property exists directly in obj, the process
+ * is repeated with obj's prototype, etc.
+ *
+ * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
+ */
+typedef JSBool
+(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
+
+/*
+ * Like JSResolveOp, but flags provide contextual information as follows:
+ *
+ *  JSRESOLVE_QUALIFIED   a qualified property id: obj.id or obj[id], not id
+ *  JSRESOLVE_ASSIGNING   obj[id] is on the left-hand side of an assignment
+ *  JSRESOLVE_DETECTING   'if (o.p)...' or similar detection opcode sequence
+ *  JSRESOLVE_DECLARING   var, const, or function prolog declaration opcode
+ *  JSRESOLVE_CLASSNAME   class name used when constructing
+ *
+ * The *objp out parameter, on success, should be null to indicate that id
+ * was not resolved; and non-null, referring to obj or one of its prototypes,
+ * if id was resolved.
+ *
+ * This hook instead of JSResolveOp is called via the JSClass.resolve member
+ * if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
+ *
+ * Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
+ * extends this hook by passing in the starting object on the prototype chain
+ * via *objp.  Thus a resolve hook implementation may define the property id
+ * being resolved in the object in which the id was first sought, rather than
+ * in a prototype object whose class led to the resolve hook being called.
+ *
+ * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
+ * null *objp to signify "not resolved".  With only JSCLASS_NEW_RESOLVE and no
+ * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
+ * This is not good practice, but enough existing hook implementations count
+ * on it that we can't break compatibility by passing the starting object in
+ * *objp without a new JSClass flag.
+ */
+typedef JSBool
+(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+                   JSObject **objp);
+
+/*
+ * Convert obj to the given type, returning true with the resulting value in
+ * *vp on success, and returning false on error or exception.
+ */
+typedef JSBool
+(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+
+/*
+ * Delegate typeof to an object so it can cloak a primitive or another object.
+ */
+typedef JSType
+(* JSTypeOfOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Finalize obj, which the garbage collector has determined to be unreachable
+ * from other live objects or from GC roots.  Obviously, finalizers must never
+ * store a reference to obj.
+ */
+typedef void
+(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
+ * to extend and reduce the set of string types finalized by the GC.
+ */
+typedef void
+(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
+
+/*
+ * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
+ * returning false on error/exception, true on success with obj[id]'s last-got
+ * value in *vp, and its attributes in *attrsp.  As for JSPropertyOp above, id
+ * is either a string or an int jsval.
+ */
+typedef JSBool
+(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+                    jsval *vp);
+
+/*
+ * Encode or decode an object, given an XDR state record representing external
+ * data.  See jsxdrapi.h.
+ */
+typedef JSBool
+(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
+
+/*
+ * Check whether v is an instance of obj.  Return false on error or exception,
+ * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
+ * *bp otherwise.
+ */
+typedef JSBool
+(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+
+/*
+ * Function type for trace operation of the class called to enumerate all
+ * traceable things reachable from obj's private data structure. For each such
+ * thing, a trace implementation must call
+ *
+ *    JS_CallTracer(trc, thing, kind);
+ *
+ * or one of its convenience macros as described in jsapi.h.
+ *
+ * JSTraceOp implementation can assume that no other threads mutates object
+ * state. It must not change state of the object or corresponding native
+ * structures. The only exception for this rule is the case when the embedding
+ * needs a tight integration with GC. In that case the embedding can check if
+ * the traversal is a part of the marking phase through calling
+ * JS_IsGCMarkingTracer and apply a special code like emptying caches or
+ * marking its native structures.
+ */
+typedef void
+(* JSTraceOp)(JSTracer *trc, JSObject *obj);
+
+/*
+ * DEBUG only callback that JSTraceOp implementation can provide to return
+ * a string describing the reference traced with JS_CallTracer.
+ */
+typedef void
+(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
+
+typedef JSBool
+(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
+
+/*
+ * Typedef for native functions called by the JS VM.
+ *
+ * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
+ */
+
+typedef JSBool
+(* JSNative)(JSContext *cx, uintN argc, jsval *vp);
+
+/* Callbacks and their arguments. */
+
+typedef enum JSContextOp {
+    JSCONTEXT_NEW,
+    JSCONTEXT_DESTROY
+} JSContextOp;
+
+/*
+ * The possible values for contextOp when the runtime calls the callback are:
+ *   JSCONTEXT_NEW      JS_NewContext successfully created a new JSContext
+ *                      instance. The callback can initialize the instance as
+ *                      required. If the callback returns false, the instance
+ *                      will be destroyed and JS_NewContext returns null. In
+ *                      this case the callback is not called again.
+ *   JSCONTEXT_DESTROY  One of JS_DestroyContext* methods is called. The
+ *                      callback may perform its own cleanup and must always
+ *                      return true.
+ *   Any other value    For future compatibility the callback must do nothing
+ *                      and return true in this case.
+ */
+typedef JSBool
+(* JSContextCallback)(JSContext *cx, uintN contextOp);
+
+typedef enum JSGCStatus {
+    JSGC_BEGIN,
+    JSGC_END,
+    JSGC_MARK_END,
+    JSGC_FINALIZE_END
+} JSGCStatus;
+
+typedef JSBool
+(* JSGCCallback)(JSContext *cx, JSGCStatus status);
+
+/*
+ * Generic trace operation that calls JS_CallTracer on each traceable thing
+ * stored in data.
+ */
+typedef void
+(* JSTraceDataOp)(JSTracer *trc, void *data);
+
+typedef JSBool
+(* JSOperationCallback)(JSContext *cx);
+
+typedef void
+(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
+
+/*
+ * Possible exception types. These types are part of a JSErrorFormatString
+ * structure. They define which error to throw in case of a runtime error.
+ * JSEXN_NONE marks an unthrowable error.
+ */
+typedef enum JSExnType {
+    JSEXN_NONE = -1,
+      JSEXN_ERR,
+        JSEXN_INTERNALERR,
+        JSEXN_EVALERR,
+        JSEXN_RANGEERR,
+        JSEXN_REFERENCEERR,
+        JSEXN_SYNTAXERR,
+        JSEXN_TYPEERR,
+        JSEXN_URIERR,
+        JSEXN_LIMIT
+} JSExnType;
+
+typedef struct JSErrorFormatString {
+    /* The error format string (UTF-8 if js_CStringsAreUTF8). */
+    const char *format;
+
+    /* The number of arguments to expand in the formatted error message. */
+    uint16 argCount;
+
+    /* One of the JSExnType constants above. */
+    int16 exnType;
+} JSErrorFormatString;
+
+typedef const JSErrorFormatString *
+(* JSErrorCallback)(void *userRef, const char *locale,
+                    const uintN errorNumber);
+
+#ifdef va_start
+#define JS_ARGUMENT_FORMATTER_DEFINED 1
+
+typedef JSBool
+(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
+                        jsval **vpp, va_list *app);
+#endif
+
+typedef JSBool
+(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
+                    jsval *rval);
+
+typedef JSBool
+(* JSLocaleToUnicode)(JSContext *cx, const char *src, jsval *rval);
+
+/*
+ * Security protocol types.
+ */
+
+/*
+ * XDR-encode or -decode a principals instance, based on whether xdr->mode is
+ * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
+ * in which case implementations must return a held (via JSPRINCIPALS_HOLD),
+ * non-null *principalsp out parameter.  Return true on success, false on any
+ * error, which the implementation must have reported.
+ */
+typedef JSBool
+(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
+
+/*
+ * Return a weak reference to the principals associated with obj, possibly via
+ * the immutable parent chain leading from obj to a top-level container (e.g.,
+ * a window object in the DOM level 0).  If there are no principals associated
+ * with obj, return null.  Therefore null does not mean an error was reported;
+ * in no event should an error be reported or an exception be thrown by this
+ * callback's implementation.
+ */
+typedef JSPrincipals *
+(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
+
+/*
+ * Used to check if a CSP instance wants to disable eval() and friends.
+ * See js_CheckCSPPermitsJSAction() in jsobj.
+ */
+typedef JSBool
+(* JSCSPEvalChecker)(JSContext *cx);
+
+/*
+ * Callback used to ask the embedding for the cross compartment wrapper handler
+ * that implements the desired prolicy for this kind of object in the
+ * destination compartment.
+ */
+typedef JSObject *
+(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
+                         uintN flags);
+
+/*
+ * Callback used by the wrap hook to ask the embedding to prepare an object
+ * for wrapping in a context. This might include unwrapping other wrappers
+ * or even finding a more suitable object for the new compartment.
+ */
+typedef JSObject *
+(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags);
+
+typedef enum {
+    JSCOMPARTMENT_DESTROY
+} JSCompartmentOp;
+
+typedef JSBool
+(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, uintN compartmentOp);
+
+/*
+ * Read structured data from the reader r. This hook is used to read a value
+ * previously serialized by a call to the WriteStructuredCloneOp hook.
+ *
+ * tag and data are the pair of uint32 values from the header. The callback may
+ * use the JS_Read* APIs to read any other relevant parts of the object from
+ * the reader r. closure is any value passed to the JS_ReadStructuredClone
+ * function. Return the new object on success, NULL on error/exception.
+ */
+typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
+                                           uint32 tag, uint32 data, void *closure);
+
+/*
+ * Structured data serialization hook. The engine can write primitive values,
+ * Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other
+ * type of object requires application support. This callback must first use
+ * the JS_WriteUint32Pair API to write an object header, passing a value
+ * greater than JS_SCTAG_USER to the tag parameter. Then it can use the
+ * JS_Write* APIs to write any other relevant parts of the value v to the
+ * writer w. closure is any value passed to the JS_WriteStructuredCLone function.
+ *
+ * Return true on success, false on error/exception.
+ */
+typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
+                                         JSObject *obj, void *closure);
+
+/*
+ * This is called when JS_WriteStructuredClone finds that the object to be
+ * written is recursive. To follow HTML5, the application must throw a
+ * DATA_CLONE_ERR DOMException. errorid is always JS_SCERR_RECURSION.
+ */
+typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32 errorid);
+
+/************************************************************************/
 
 JS_BEGIN_EXTERN_C
 
 /*
- * In release builds, jsval and jsid are defined to be integral types. This
- * prevents many bugs from being caught at compile time. E.g.:
- *
- *  jsval v = ...
- *  if (v == JS_TRUE)  // error
- *    ...
- *
- *  jsid id = v;       // error
- *
- * To catch more errors, jsval and jsid are given struct types in debug builds.
- * Struct assignment and (in C++) operator== allow correct code to be mostly
- * oblivious to the change. This feature can be explicitly disabled in debug
- * builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
+ * Silence warning about returning JS::Value (aka jsval) from functions with C
+ * linkage. For C JSAPI clients, jsval will be jsval_layout, which should be
+ * ABI compatible.
  */
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-
-/* Well-known JS values. N.B. These constants are initialized at startup. */
-extern JS_PUBLIC_DATA(jsval) JSVAL_NULL;
-extern JS_PUBLIC_DATA(jsval) JSVAL_ZERO;
-extern JS_PUBLIC_DATA(jsval) JSVAL_ONE;
-extern JS_PUBLIC_DATA(jsval) JSVAL_FALSE;
-extern JS_PUBLIC_DATA(jsval) JSVAL_TRUE;
-extern JS_PUBLIC_DATA(jsval) JSVAL_VOID;
-
-#else
-
-/* Well-known JS values. */
-#define JSVAL_NULL   BUILD_JSVAL(JSVAL_TAG_NULL,      0)
-#define JSVAL_ZERO   BUILD_JSVAL(JSVAL_TAG_INT32,     0)
-#define JSVAL_ONE    BUILD_JSVAL(JSVAL_TAG_INT32,     1)
-#define JSVAL_FALSE  BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_FALSE)
-#define JSVAL_TRUE   BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_TRUE)
-#define JSVAL_VOID   BUILD_JSVAL(JSVAL_TAG_UNDEFINED, 0)
-
+#ifdef _MSC_VER
+# pragma warning(disable:4190)
 #endif
 
 /************************************************************************/
 
+/*
+ * JS constants. For efficiency, prefer predicates (e.g., JSVAL_IS_NULL).
+ * N.B. These constants are initialized at startup.
+ */
+extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL;
+extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO;
+extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE;
+extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE;
+extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE;
+extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID;
+
+/************************************************************************/
+
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_NULL(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_NULL_IMPL(l);
+    return JSVAL_IS_NULL_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_VOID(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_UNDEFINED_IMPL(l);
+    return JSVAL_IS_UNDEFINED_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_INT(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_INT32_IMPL(l);
+    return JSVAL_IS_INT32_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE jsint
 JSVAL_TO_INT(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_INT(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_INT32_IMPL(l);
+    return JSVAL_TO_INT32_IMPL(JSVAL_TO_IMPL(v));
 }
 
-#define JSVAL_INT_BITS          32
-#define JSVAL_INT_MIN           ((jsint)0x80000000)
-#define JSVAL_INT_MAX           ((jsint)0x7fffffff)
-
 static JS_ALWAYS_INLINE jsval
 INT_TO_JSVAL(int32 i)
 {
     return IMPL_TO_JSVAL(INT32_TO_JSVAL_IMPL(i));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_DOUBLE(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_DOUBLE_IMPL(l);
+    return JSVAL_IS_DOUBLE_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE jsdouble
 JSVAL_TO_DOUBLE(jsval v)
 {
     jsval_layout l;
     JS_ASSERT(JSVAL_IS_DOUBLE(v));
-    l.asBits = JSVAL_BITS(v);
+    l = JSVAL_TO_IMPL(v);
     return l.asDouble;
 }
 
 static JS_ALWAYS_INLINE jsval
 DOUBLE_TO_JSVAL(jsdouble d)
 {
     d = JS_CANONICALIZE_NAN(d);
     return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
@@ -163,132 +1335,110 @@ UINT_TO_JSVAL(uint32 i)
     if (i <= JSVAL_INT_MAX)
         return INT_TO_JSVAL((int32)i);
     return DOUBLE_TO_JSVAL((jsdouble)i);
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_NUMBER(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_NUMBER_IMPL(l);
+    return JSVAL_IS_NUMBER_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_STRING(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_STRING_IMPL(l);
+    return JSVAL_IS_STRING_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSString *
 JSVAL_TO_STRING(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_STRING(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_STRING_IMPL(l);
+    return JSVAL_TO_STRING_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE jsval
 STRING_TO_JSVAL(JSString *str)
 {
     return IMPL_TO_JSVAL(STRING_TO_JSVAL_IMPL(str));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_OBJECT(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_OBJECT_OR_NULL_IMPL(l);
+    return JSVAL_IS_OBJECT_OR_NULL_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSObject *
 JSVAL_TO_OBJECT(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_OBJECT(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_OBJECT_IMPL(l);
+    return JSVAL_TO_OBJECT_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE jsval
 OBJECT_TO_JSVAL(JSObject *obj)
 {
     if (obj)
         return IMPL_TO_JSVAL(OBJECT_TO_JSVAL_IMPL(obj));
     return JSVAL_NULL;
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_BOOLEAN(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_BOOLEAN_IMPL(l);
+    return JSVAL_IS_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_TO_BOOLEAN(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_BOOLEAN(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_BOOLEAN_IMPL(l);
+    return JSVAL_TO_BOOLEAN_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE jsval
 BOOLEAN_TO_JSVAL(JSBool b)
 {
     return IMPL_TO_JSVAL(BOOLEAN_TO_JSVAL_IMPL(b));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_PRIMITIVE(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_PRIMITIVE_IMPL(l);
+    return JSVAL_IS_PRIMITIVE_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_GCTHING(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_GCTHING_IMPL(l);
+    return JSVAL_IS_GCTHING_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE void *
 JSVAL_TO_GCTHING(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_GCTHING(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_GCTHING_IMPL(l);
+    return JSVAL_TO_GCTHING_IMPL(JSVAL_TO_IMPL(v));
 }
 
 /* To be GC-safe, privates are tagged as doubles. */
 
 static JS_ALWAYS_INLINE jsval
 PRIVATE_TO_JSVAL(void *ptr)
 {
     return IMPL_TO_JSVAL(PRIVATE_PTR_TO_JSVAL_IMPL(ptr));
 }
 
 static JS_ALWAYS_INLINE void *
 JSVAL_TO_PRIVATE(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_DOUBLE(v));
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_TO_PRIVATE_PTR_IMPL(l);
+    return JSVAL_TO_PRIVATE_PTR_IMPL(JSVAL_TO_IMPL(v));
 }
 
 /************************************************************************/
 
 /*
  * A jsid is an identifier for a property or method of an object which is
  * either a 31-bit signed integer, interned string or object. If XML is
  * enabled, there is an additional singleton jsid value; see
@@ -318,17 +1468,17 @@ JSID_IS_STRING(jsid id)
 {
     return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
 }
 
 static JS_ALWAYS_INLINE JSString *
 JSID_TO_STRING(jsid id)
 {
     JS_ASSERT(JSID_IS_STRING(id));
-    return (JSString *)(JSID_BITS(id));
+    return (JSString *)JSID_BITS(id);
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSID_IS_ZERO(jsid id)
 {
     return JSID_BITS(id) == 0;
 }
 
@@ -433,20 +1583,20 @@ JSID_TO_GCTHING(jsid id)
 static JS_ALWAYS_INLINE JSBool
 JSID_IS_DEFAULT_XML_NAMESPACE(jsid id)
 {
     JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_DEFAULT_XML_NAMESPACE,
                  JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
     return ((size_t)JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
 }
 
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
+#ifdef JS_USE_JSID_STRUCT_TYPES
 extern JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID;
 #else
-#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid)JSID_TYPE_DEFAULT_XML_NAMESPACE)
+# define JS_DEFAULT_XML_NAMESPACE_ID ((jsid)JSID_TYPE_DEFAULT_XML_NAMESPACE)
 #endif
 
 /*
  * A void jsid is not a valid id and only arises as an exceptional API return
  * value, such as in JS_NextProperty. Embeddings must not pass JSID_VOID into
  * JSAPI entry points expecting a jsid and do not need to handle JSID_VOID in
  * hooks receiving a jsid except when explicitly noted in the API contract.
  */
@@ -462,22 +1612,22 @@ JSID_IS_VOID(jsid id)
 static JS_ALWAYS_INLINE JSBool
 JSID_IS_EMPTY(jsid id)
 {
     return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
 }
 
 #undef id
 
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
+#ifdef JS_USE_JSID_STRUCT_TYPES
 extern JS_PUBLIC_DATA(jsid) JSID_VOID;
 extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
 #else
-# define JSID_VOID      ((jsid)JSID_TYPE_VOID)
-# define JSID_EMPTY     ((jsid)JSID_TYPE_OBJECT)
+# define JSID_VOID ((jsid)JSID_TYPE_VOID)
+# define JSID_EMPTY ((jsid)JSID_TYPE_OBJECT)
 #endif
 
 /************************************************************************/
 
 /* Lock and unlock the GC thing held by a jsval. */
 #define JSVAL_LOCK(cx,v)        (JSVAL_IS_GCTHING(v)                          \
                                  ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v))    \
                                  : JS_TRUE)
@@ -597,17 +1747,17 @@ extern JS_PUBLIC_API(JSBool)
 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
                       const char *format, va_list ap);
 #endif
 
 #ifdef JS_ARGUMENT_FORMATTER_DEFINED
 
 /*
  * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}.
- * The handler function has this signature (see jspubtd.h):
+ * The handler function has this signature:
  *
  *   JSBool MyArgumentFormatter(JSContext *cx, const char *format,
  *                              JSBool fromJS, jsval **vpp, va_list *app);
  *
  * It should return true on success, and return false after reporting an error
  * or detecting an already-reported error.
  *
  * For a given format string, for example "AA", the formatter is called from
@@ -1349,178 +2499,16 @@ extern JS_FRIEND_API(JSBool)
 js_AddRootRT(JSRuntime *rt, jsval *vp, const char *name);
 
 extern JS_FRIEND_API(JSBool)
 js_AddGCThingRootRT(JSRuntime *rt, void **rp, const char *name);
 
 extern JS_FRIEND_API(JSBool)
 js_RemoveRoot(JSRuntime *rt, void *rp);
 
-#ifdef __cplusplus
-JS_END_EXTERN_C
-
-namespace JS {
-
-/*
- * Protecting non-jsval, non-JSObject *, non-JSString * values from collection
- *
- * Most of the time, the garbage collector's conservative stack scanner works
- * behind the scenes, finding all live values and protecting them from being
- * collected. However, when JSAPI client code obtains a pointer to data the
- * scanner does not know about, owned by an object the scanner does know about,
- * Care Must Be Taken.
- *
- * The scanner recognizes only a select set of types: pointers to JSObjects and
- * similar things (JSFunctions, and so on), pointers to JSStrings, and jsvals.
- * So while the scanner finds all live |JSString| pointers, it does not notice
- * |jschar| pointers.
- *
- * So suppose we have:
- *
- *   void f(JSString *str) {
- *     const jschar *ch = JS_GetStringCharsZ(str);
- *     ... do stuff with ch, but no uses of str ...;
- *   }
- *
- * After the call to |JS_GetStringCharsZ|, there are no further uses of
- * |str|, which means that the compiler is within its rights to not store
- * it anywhere. But because the stack scanner will not notice |ch|, there
- * is no longer any live value in this frame that would keep the string
- * alive. If |str| is the last reference to that |JSString|, and the
- * collector runs while we are using |ch|, the string's array of |jschar|s
- * may be freed out from under us.
- *
- * Note that there is only an issue when 1) we extract a thing X the scanner
- * doesn't recognize from 2) a thing Y the scanner does recognize, and 3) if Y
- * gets garbage-collected, then X gets freed. If we have code like this:
- *
- *   void g(JSObject *obj) {
- *     jsval x;
- *     JS_GetProperty(obj, "x", &x);
- *     ... do stuff with x ...
- *   }
- *
- * there's no problem, because the value we've extracted, x, is a jsval, a
- * type that the conservative scanner recognizes.
- *
- * Conservative GC frees us from the obligation to explicitly root the types it
- * knows about, but when we work with derived values like |ch|, we must root
- * their owners, as the derived value alone won't keep them alive.
- *
- * A JS::Anchor is a kind of GC root that allows us to keep the owners of
- * derived values like |ch| alive throughout the Anchor's lifetime. We could
- * fix the above code as follows:
- *
- *   void f(JSString *str) {
- *     JS::Anchor<JSString *> a_str(str);
- *     const jschar *ch = JS_GetStringCharsZ(str);
- *     ... do stuff with ch, but no uses of str ...;
- *   }
- *
- * This simply ensures that |str| will be live until |a_str| goes out of scope.
- * As long as we don't retain a pointer to the string's characters for longer
- * than that, we have avoided all garbage collection hazards.
- */
-template<typename T> class AnchorPermitted;
-template<> class AnchorPermitted<JSObject *> { };
-template<> class AnchorPermitted<const JSObject *> { };
-template<> class AnchorPermitted<JSFunction *> { };
-template<> class AnchorPermitted<const JSFunction *> { };
-template<> class AnchorPermitted<JSString *> { };
-template<> class AnchorPermitted<const JSString *> { };
-template<> class AnchorPermitted<jsval> { };
-
-template<typename T>
-class Anchor: AnchorPermitted<T> {
-  public:
-    Anchor() { }
-    explicit Anchor(T t) { hold = t; }
-    inline ~Anchor();
-    T &get() { return hold; }
-    const T &get() const { return hold; }
-    void set(const T &t) { hold = t; }
-    void clear() { hold = 0; }
-  private:
-    T hold;
-    /* Anchors should not be assigned or passed to functions. */
-    Anchor(const Anchor &);
-    const Anchor &operator=(const Anchor &);
-};
-
-#ifdef __GNUC__
-template<typename T>
-inline Anchor<T>::~Anchor() {
-    /*
-     * No code is generated for this. But because this is marked 'volatile', G++ will
-     * assume it has important side-effects, and won't delete it. (G++ never looks at
-     * the actual text and notices it's empty.) And because we have passed |hold| to
-     * it, GCC will keep |hold| alive until this point.
-     *
-     * The "memory" clobber operand ensures that G++ will not move prior memory
-     * accesses after the asm --- it's a barrier. Unfortunately, it also means that
-     * G++ will assume that all memory has changed after the asm, as it would for a
-     * call to an unknown function. I don't know of a way to avoid that consequence.
-     */
-    asm volatile("":: "g" (hold) : "memory");
-}
-#else
-template<typename T>
-inline Anchor<T>::~Anchor() {
-    /*
-     * An adequate portable substitute, for non-structure types.
-     *
-     * The compiler promises that, by the end of an expression statement, the
-     * last-stored value to a volatile object is the same as it would be in an
-     * unoptimized, direct implementation (the "abstract machine" whose behavior the
-     * language spec describes). However, the compiler is still free to reorder
-     * non-volatile accesses across this store --- which is what we must prevent. So
-     * assigning the held value to a volatile variable, as we do here, is not enough.
-     *
-     * In our case, however, garbage collection only occurs at function calls, so it
-     * is sufficient to ensure that the destructor's store isn't moved earlier across
-     * any function calls that could collect. It is hard to imagine the compiler
-     * analyzing the program so thoroughly that it could prove that such motion was
-     * safe. In practice, compilers treat calls to the collector as opaque operations
-     * --- in particular, as operations which could access volatile variables, across
-     * which this destructor must not be moved.
-     *
-     * ("Objection, your honor!  *Alleged* killer whale!")
-     *
-     * The disadvantage of this approach is that it does generate code for the store.
-     * We do need to use Anchors in some cases where cycles are tight.
-     */
-    volatile T sink;
-    sink = hold;
-}
-
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-/*
- * The default assignment operator for |struct C| has the signature:
- *
- *   C& C::operator=(const C&)
- *
- * And in particular requires implicit conversion of |this| to type |C| for the return
- * value. But |volatile C| cannot thus be converted to |C|, so just doing |sink = hold| as
- * in the non-specialized version would fail to compile. Do the assignment on asBits
- * instead, since I don't think we want to give jsval_layout an assignment operator
- * returning |volatile jsval_layout|.
- */
-template<>
-inline Anchor<jsval>::~Anchor() {
-    volatile jsval sink;
-    sink.asBits = hold.asBits;
-}
-#endif
-#endif
-
-}  /* namespace JS */
-
-JS_BEGIN_EXTERN_C
-#endif
-
 /*
  * C-compatible version of the Anchor class. It should be called after the last
  * use of the variable it protects.
  */
 extern JS_NEVER_INLINE JS_PUBLIC_API(void)
 JS_AnchorPtr(void *p);
 
 /*
@@ -1602,61 +2590,40 @@ extern JS_PUBLIC_API(void)
 JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
 
 /*
  * JS_CallTracer API and related macros for implementors of JSTraceOp, to
  * enumerate all references to traceable things reachable via a property or
  * other strong ref identified for debugging purposes by name or index or
  * a naming callback.
  *
- * See the JSTraceOp typedef in jspubtd.h.
+ * See the JSTraceOp typedef.
  */
 
-typedef enum {
-    JSTRACE_OBJECT,
-    JSTRACE_STRING,
-    JSTRACE_SCRIPT,
-
-    /*
-     * Trace kinds internal to the engine. The embedding can only them if it
-     * implements JSTraceCallback.
-     */ 
-#if JS_HAS_XML_SUPPORT
-    JSTRACE_XML,
-#endif
-    JSTRACE_SHAPE,
-    JSTRACE_TYPE_OBJECT,
-    JSTRACE_LAST = JSTRACE_TYPE_OBJECT
-} JSGCTraceKind;
-
 /*
  * Use the following macros to check if a particular jsval is a traceable
  * thing and to extract the thing and its kind to pass to JS_CallTracer.
  */
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_TRACEABLE(jsval v)
 {
-    jsval_layout l;
-    l.asBits = JSVAL_BITS(v);
-    return JSVAL_IS_TRACEABLE_IMPL(l);
+    return JSVAL_IS_TRACEABLE_IMPL(JSVAL_TO_IMPL(v));
 }
 
 static JS_ALWAYS_INLINE void *
 JSVAL_TO_TRACEABLE(jsval v)
 {
     return JSVAL_TO_GCTHING(v);
 }
 
 static JS_ALWAYS_INLINE JSGCTraceKind
 JSVAL_TRACE_KIND(jsval v)
 {
-    jsval_layout l;
     JS_ASSERT(JSVAL_IS_GCTHING(v));
-    l.asBits = JSVAL_BITS(v);
-    return (JSGCTraceKind) JSVAL_TRACE_KIND_IMPL(l);
+    return (JSGCTraceKind) JSVAL_TRACE_KIND_IMPL(JSVAL_TO_IMPL(v));
 }
 
 /*
  * Tracer callback, called for each traceable thing directly referenced by a
  * particular object or runtime structure. It is the callback responsibility
  * to ensure the traversal of the full object graph via calling eventually
  * JS_TraceChildren on the passed thing. In this case the callback must be
  * prepared to deal with cycles in the traversal graph.
@@ -1977,17 +2944,16 @@ JS_SetNativeStackQuota(JSContext *cx, si
 
 /************************************************************************/
 
 /*
  * Classes, objects, and properties.
  */
 typedef void (*JSClassInternal)();
 
-/* For detailed comments on the function pointer types, see jspubtd.h. */
 struct JSClass {
     const char          *name;
     uint32              flags;
 
     /* Mandatory non-null function pointer members. */
     JSPropertyOp        addProperty;
     JSPropertyOp        delProperty;
     JSPropertyOp        getProperty;
@@ -3515,18 +4481,17 @@ JS_GetLocaleCallbacks(JSContext *cx);
 
 /*
  * Error reporting.
  */
 
 /*
  * Report an exception represented by the sprintf-like conversion of format
  * and its arguments.  This exception message string is passed to a pre-set
- * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for
- * the JSErrorReporter typedef).
+ * JSErrorReporter function (set by JS_SetErrorReporter).
  */
 extern JS_PUBLIC_API(void)
 JS_ReportError(JSContext *cx, const char *format, ...);
 
 /*
  * Use an errorNumber to retrieve the format string, args are char *
  */
 extern JS_PUBLIC_API(void)
@@ -3770,30 +4735,27 @@ JS_ClearContextThread(JSContext *cx);
  * native's original cx and vp arguments. If JS_IsConstructing is true,
  * JS_THIS must not be used; the constructor should construct and return a
  * new object. Otherwise, the native is called as an ordinary function and
  * JS_THIS may be used.
  */
 static JS_ALWAYS_INLINE JSBool
 JS_IsConstructing(JSContext *cx, const jsval *vp)
 {
-    jsval_layout l;
-
 #ifdef DEBUG
     JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
     if (JS_ObjectIsFunction(cx, callee)) {
         JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
         JS_ASSERT((JS_GetFunctionFlags(fun) & JSFUN_CONSTRUCTOR) != 0);
     } else {
         JS_ASSERT(JS_GET_CLASS(cx, callee)->construct != NULL);
     }
 #endif
 
-    l.asBits = JSVAL_BITS(vp[1]);
-    return JSVAL_IS_MAGIC_IMPL(l);
+    return JSVAL_IS_MAGIC_IMPL(JSVAL_TO_IMPL(vp[1]));
 }
 
 /*
  * In the case of a constructor called from JS_ConstructObject and
  * JS_InitClass where the class has the JSCLASS_CONSTRUCT_PROTOTYPE flag set,
  * the JS engine passes the constructor a non-standard 'this' object. In such
  * cases, the following query provides the additional information of whether a
  * special 'this' was supplied. E.g.:
@@ -3824,18 +4786,17 @@ JS_IsConstructing_PossiblyWithGivenThisO
     if (JS_ObjectIsFunction(cx, callee)) {
         JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
         JS_ASSERT((JS_GetFunctionFlags(fun) & JSFUN_CONSTRUCTOR) != 0);
     } else {
         JS_ASSERT(JS_GET_CLASS(cx, callee)->construct != NULL);
     }
 #endif
 
-    l.asBits = JSVAL_BITS(vp[1]);
-    isCtor = JSVAL_IS_MAGIC_IMPL(l);
+    isCtor = JSVAL_IS_MAGIC_IMPL(JSVAL_TO_IMPL(vp[1]));
     if (isCtor)
         *maybeThis = MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(l);
     return isCtor;
 }
 
 /*
  * If a constructor does not have any static knowledge about the type of
  * object to create, it can request that the JS engine create a default new
--- a/js/src/jsarrayinlines.h
+++ b/js/src/jsarrayinlines.h
@@ -65,17 +65,17 @@ JSObject::ensureDenseArrayInitializedLen
     /*
      * Ensure that the array's contents have been initialized up to index, and
      * mark the elements through 'index + extra' as initialized in preparation
      * for a write.
      */
     JS_ASSERT(index + extra <= capacity);
     if (initializedLength < index) {
         markDenseArrayNotPacked(cx);
-        ClearValueRange(slots + initializedLength, index - initializedLength, true);
+        js::ClearValueRange(slots + initializedLength, index - initializedLength, true);
     }
     if (initializedLength < index + extra)
         initializedLength = index + extra;
 }
 
 inline JSObject::EnsureDenseResult
 JSObject::ensureDenseArrayElements(JSContext *cx, uintN index, uintN extra)
 {
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -600,17 +600,17 @@ JSStructuredCloneWriter::write(const Val
     return true;
 }
 
 bool
 JSStructuredCloneReader::checkDouble(jsdouble d)
 {
     jsval_layout l;
     l.asDouble = d;
-    if (!JSVAL_IS_DOUBLE(JSVAL_FROM_LAYOUT(l))) {
+    if (!JSVAL_IS_DOUBLE_IMPL(l)) {
         JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL,
                              JSMSG_SC_BAD_SERIALIZED_DATA, "unrecognized NaN");
         return false;
     }
     return true;
 }
 
 class Chars {
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1514,39 +1514,27 @@ class AutoValueRooter : private AutoGCRo
 
     AutoValueRooter(JSContext *cx, const Value &v
                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : AutoGCRooter(cx, JSVAL), val(v)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
     }
 
-    AutoValueRooter(JSContext *cx, jsval v
-                    JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, JSVAL), val(js::Valueify(v))
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
-    }
-
     /*
      * If you are looking for Object* overloads, use AutoObjectRooter instead;
      * rooting Object*s as a js::Value requires discerning whether or not it is
      * a function object. Also, AutoObjectRooter is smaller.
      */
 
     void set(Value v) {
         JS_ASSERT(tag == JSVAL);
         val = v;
     }
 
-    void set(jsval v) {
-        JS_ASSERT(tag == JSVAL);
-        val = js::Valueify(v);
-    }
-
     const Value &value() const {
         JS_ASSERT(tag == JSVAL);
         return val;
     }
 
     Value *addr() {
         JS_ASSERT(tag == JSVAL);
         return &val;
@@ -1632,24 +1620,16 @@ class AutoArrayRooter : private AutoGCRo
     AutoArrayRooter(JSContext *cx, size_t len, Value *vec
                     JS_GUARD_OBJECT_NOTIFIER_PARAM)
       : AutoGCRooter(cx, len), array(vec)
     {
         JS_GUARD_OBJECT_NOTIFIER_INIT;
         JS_ASSERT(tag >= 0);
     }
 
-    AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
-                    JS_GUARD_OBJECT_NOTIFIER_PARAM)
-      : AutoGCRooter(cx, len), array(Valueify(vec))
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
-        JS_ASSERT(tag >= 0);
-    }
-
     void changeLength(size_t newLength) {
         tag = ptrdiff_t(newLength);
         JS_ASSERT(tag >= 0);
     }
 
     void changeArray(Value *newArray, size_t newLength) {
         changeLength(newLength);
         array = newArray;
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -170,20 +170,16 @@ class CompartmentChecker
 
     void check(const js::Value &v) {
         if (v.isObject())
             check(&v.toObject());
         else if (v.isString())
             check(v.toString());
     }
 
-    void check(jsval v) {
-        check(Valueify(v));
-    }
-
     void check(const ValueArray &arr) {
         for (size_t i = 0; i < arr.length; i++)
             check(arr.array[i]);
     }
 
     void check(const JSValueArray &arr) {
         for (size_t i = 0; i < arr.length; i++)
             check(arr.array[i]);
@@ -425,17 +421,17 @@ JSContext::regExpStatics()
 {
     return js::RegExpStatics::extractFrom(js::GetGlobalForScopeChain(this));
 }
 
 inline void
 JSContext::setPendingException(js::Value v) {
     this->throwing = true;
     this->exception = v;
-    assertSameCompartment(this, v);
+    js::assertSameCompartment(this, v);
 }
 
 inline bool
 JSContext::ensureParseMapPool()
 {
     if (parseMapPool_)
         return true;
     parseMapPool_ = js::OffTheBooks::new_<js::ParseMapPool>(this);
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1145,17 +1145,17 @@ typedef js::HashMap<void *,
 /* If HashNumber grows, need to change WrapperHasher. */
 JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
 
 struct WrapperHasher
 {
     typedef Value Lookup;
 
     static HashNumber hash(Value key) {
-        uint64 bits = JSVAL_BITS(Jsvalify(key));
+        uint64 bits = key.asRawBits();
         return (uint32)bits ^ (uint32)(bits >> 32);
     }
 
     static bool match(const Value &l, const Value &k) { return l == k; }
 };
 
 typedef HashMap<Value, Value, WrapperHasher, SystemAllocPolicy> WrapperMap;
 
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -81,17 +81,16 @@
 #include "jsnuminlines.h"
 #include "jsobjinlines.h"
 #include "jsstrinlines.h"
 
 #include "vm/String-inl.h"
 
 using namespace js;
 using namespace js::types;
-using namespace mozilla;
 
 #ifndef JS_HAVE_STDINT_H /* Native support is innocent until proven guilty. */
 
 JS_STATIC_ASSERT(uint8_t(-1) == UINT8_MAX);
 JS_STATIC_ASSERT(uint16_t(-1) == UINT16_MAX);
 JS_STATIC_ASSERT(uint32_t(-1) == UINT32_MAX);
 JS_STATIC_ASSERT(uint64_t(-1) == UINT64_MAX);
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -630,17 +630,17 @@ JSObject::setFlatClosureUpvar(uint32 i, 
     getFlatClosureUpvars()[i] = v;
 }
 
 inline void
 JSObject::setFlatClosureUpvars(js::Value *upvars)
 {
     JS_ASSERT(isFunction());
     JS_ASSERT(getFunctionPrivate()->isFlatClosure());
-    setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, PrivateValue(upvars));
+    setFixedSlot(JSSLOT_FLAT_CLOSURE_UPVARS, js::PrivateValue(upvars));
 }
 
 inline bool
 JSObject::hasMethodObj(const JSObject& obj) const
 {
     return JSSLOT_FUN_METHOD_OBJ < numSlots() &&
            getFixedSlot(JSSLOT_FUN_METHOD_OBJ).isObject() &&
            getFixedSlot(JSSLOT_FUN_METHOD_OBJ).toObject() == obj;
@@ -859,17 +859,17 @@ JSObject::init(JSContext *cx, js::Class 
      * is disabled, NewArray will backfill holes up to the array's capacity
      * and unset the PACKED_ARRAY flag.
      */
     slots = NULL;
     if (denseArray) {
         slots = fixedSlots();
         flags |= PACKED_ARRAY;
     } else {
-        ClearValueRange(fixedSlots(), capacity, denseArray);
+        js::ClearValueRange(fixedSlots(), capacity, denseArray);
     }
 
     newType = NULL;
     JS_ASSERT(initializedLength == 0);
 
     setType(type);
     setParent(parent);
 }
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -49,17 +49,17 @@
  * all .h files that include this file may use the same typedef name, whether
  * declaring a pointer to struct type, or defining a member of struct type.
  *
  * A few fundamental scalar types are defined here too.  Neither the scalar
  * nor the struct typedefs should change much, therefore the nearly-global
  * make dependency induced by this file should not prove painful.
  */
 
-#include "jspubtd.h"
+#include "jsapi.h"
 #include "jsstaticcheck.h"
 #include "jsutil.h"
 
 JS_BEGIN_EXTERN_C
 
 /*
  * Convenience constants.
  */
@@ -117,16 +117,17 @@ class JSDependentString;
 class JSExtensibleString;
 class JSExternalString;
 class JSLinearString;
 class JSFixedString;
 class JSStaticAtom;
 class JSRope;
 class JSAtom;
 struct JSDefinition;
+class JSWrapper;
 
 namespace js {
 
 struct ArgumentsData;
 
 class RegExp;
 class RegExpStatics;
 class AutoStringRooter;
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -39,33 +39,77 @@
 
 #ifndef jspubtd_h___
 #define jspubtd_h___
 /*
  * JS public API typedefs.
  */
 #include "jstypes.h"
 #include "jscompat.h"
-#include "jsval.h"
+
+/*
+ * Allow headers to reference JS::Value without #including the whole jsapi.h.
+ * Unfortunately, typedefs (hence jsval) cannot be declared.
+ */
+#ifdef __cplusplus
+namespace JS { class Value; }
+#endif
+
+/*
+ * In release builds, jsid is defined to be an integral type. This
+ * prevents many bugs from being caught at compile time. E.g.:
+ *
+ *  jsid id = ...
+ *  if (id == JS_TRUE)  // error
+ *    ...
+ *
+ *  size_t n = id;      // error
+ *
+ * To catch more errors, jsid is given a struct type in C++ debug builds.
+ * Struct assignment and (in C++) operator== allow correct code to be mostly
+ * oblivious to the change. This feature can be explicitly disabled in debug
+ * builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
+ */
+#ifdef __cplusplus
+
+# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
+#  define JS_USE_JSID_STRUCT_TYPES
+# endif
+
+# ifdef JS_USE_JSID_STRUCT_TYPES
+struct jsid
+{
+    size_t asBits;
+    bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
+    bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
+};
+#  define JSID_BITS(id) (id.asBits)
+# else  /* defined(JS_USE_JSID_STRUCT_TYPES) */
+typedef ptrdiff_t jsid;
+#  define JSID_BITS(id) (id)
+# endif  /* defined(JS_USE_JSID_STRUCT_TYPES) */
+#else  /* defined(__cplusplus) */
+typedef ptrdiff_t jsid;
+# define JSID_BITS(id) (id)
+#endif
 
 JS_BEGIN_EXTERN_C
 
 /* Scalar typedefs. */
 typedef JSInt32   jsint;
 typedef JSUint32  jsuint;
 typedef float64   jsdouble;
 typedef JSInt32   jsrefcount;   /* PRInt32 if JS_THREADSAFE, see jslock.h */
 
 #ifdef WIN32
 typedef wchar_t   jschar;
 #else
 typedef JSUint16  jschar;
 #endif
 
-
 /*
  * Run-time version enumeration.  See jsversion.h for compile-time counterparts
  * to these values that may be selected by the JS_VERSION macro, and tested by
  * #if expressions.
  */
 typedef enum JSVersion {
     JSVERSION_1_0     = 100,
     JSVERSION_1_1     = 110,
@@ -138,442 +182,65 @@ typedef enum JSIterateOp {
 
     /* Iterate once. */
     JSENUMERATE_NEXT,
 
     /* Destroy iterator state. */
     JSENUMERATE_DESTROY
 } JSIterateOp;
 
+/* See JSVAL_TRACE_KIND and JSTraceCallback in jsapi.h. */
+typedef enum {
+    JSTRACE_OBJECT,
+    JSTRACE_STRING,
+    JSTRACE_SCRIPT,
+
+    /*
+     * Trace kinds internal to the engine. The embedding can only them if it
+     * implements JSTraceCallback.
+     */
+#if JS_HAS_XML_SUPPORT
+    JSTRACE_XML,
+#endif
+    JSTRACE_SHAPE,
+    JSTRACE_TYPE_OBJECT,
+    JSTRACE_LAST = JSTRACE_TYPE_OBJECT
+} JSGCTraceKind;
+
 /* Struct typedefs. */
-typedef struct JSClass           JSClass;
-typedef struct JSConstDoubleSpec JSConstDoubleSpec;
-typedef struct JSContext         JSContext;
-typedef struct JSErrorReport     JSErrorReport;
-typedef struct JSFunction        JSFunction;
-typedef struct JSFunctionSpec    JSFunctionSpec;
-typedef struct JSTracer          JSTracer;
-typedef struct JSIdArray         JSIdArray;
-typedef struct JSPropertyDescriptor JSPropertyDescriptor;
-typedef struct JSPropertySpec    JSPropertySpec;
-typedef struct JSObjectMap       JSObjectMap;
-typedef struct JSRuntime         JSRuntime;
-typedef struct JSStackFrame      JSStackFrame;
-typedef struct JSXDRState        JSXDRState;
-typedef struct JSExceptionState  JSExceptionState;
-typedef struct JSLocaleCallbacks JSLocaleCallbacks;
-typedef struct JSSecurityCallbacks JSSecurityCallbacks;
-typedef struct JSCompartment     JSCompartment;
-typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
+typedef struct JSClass                      JSClass;
+typedef struct JSCompartment                JSCompartment;
+typedef struct JSConstDoubleSpec            JSConstDoubleSpec;
+typedef struct JSContext                    JSContext;
+typedef struct JSCrossCompartmentCall       JSCrossCompartmentCall;
+typedef struct JSErrorReport                JSErrorReport;
+typedef struct JSExceptionState             JSExceptionState;
+typedef struct JSFunction                   JSFunction;
+typedef struct JSFunctionSpec               JSFunctionSpec;
+typedef struct JSIdArray                    JSIdArray;
+typedef struct JSLocaleCallbacks            JSLocaleCallbacks;
+typedef struct JSObject                     JSObject;
+typedef struct JSObjectMap                  JSObjectMap;
+typedef struct JSPrincipals                 JSPrincipals;
+typedef struct JSPropertyDescriptor         JSPropertyDescriptor;
+typedef struct JSPropertyName               JSPropertyName;
+typedef struct JSPropertySpec               JSPropertySpec;
+typedef struct JSRuntime                    JSRuntime;
+typedef struct JSSecurityCallbacks          JSSecurityCallbacks;
+typedef struct JSStackFrame                 JSStackFrame;
 typedef struct JSScript          JSScript;
-typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
-typedef struct JSStructuredCloneReader JSStructuredCloneReader;
-typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
-typedef struct JSPropertyName    JSPropertyName;
+typedef struct JSStructuredCloneCallbacks   JSStructuredCloneCallbacks;
+typedef struct JSStructuredCloneReader      JSStructuredCloneReader;
+typedef struct JSStructuredCloneWriter      JSStructuredCloneWriter;
+typedef struct JSTracer                     JSTracer;
+typedef struct JSXDRState                   JSXDRState;
 
 #ifdef __cplusplus
-typedef class JSWrapper          JSWrapper;
-typedef class JSCrossCompartmentWrapper JSCrossCompartmentWrapper;
+class                                       JSFlatString;
+class                                       JSString;
+#else
+typedef struct JSFlatString                 JSFlatString;
+typedef struct JSString                     JSString;
 #endif
 
-/* JSClass (and js::ObjectOps where appropriate) function pointer typedefs. */
-
-/*
- * Add, delete, or get a property named by id in obj.  Note the jsid id
- * type -- id may be a string (Unicode property identifier) or an int (element
- * index).  The *vp out parameter, on success, is the new property value after
- * an add or get.  After a successful delete, *vp is JSVAL_FALSE iff
- * obj[id] can't be deleted (because it's permanent).
- */
-typedef JSBool
-(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
-
-/*
- * Set a property named by id in obj, treating the assignment as strict
- * mode code if strict is true. Note the jsid id type -- id may be a string
- * (Unicode property identifier) or an int (element index). The *vp out
- * parameter, on success, is the new property value after the
- * set.
- */
-typedef JSBool
-(* JSStrictPropertyOp)(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
-
-/*
- * This function type is used for callbacks that enumerate the properties of
- * a JSObject.  The behavior depends on the value of enum_op:
- *
- *  JSENUMERATE_INIT
- *    A new, opaque iterator state should be allocated and stored in *statep.
- *    (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
- *
- *    The number of properties that will be enumerated should be returned as
- *    an integer jsval in *idp, if idp is non-null, and provided the number of
- *    enumerable properties is known.  If idp is non-null and the number of
- *    enumerable properties can't be computed in advance, *idp should be set
- *    to JSVAL_ZERO.
- *
- *  JSENUMERATE_INIT_ALL
- *    Used identically to JSENUMERATE_INIT, but exposes all properties of the
- *    object regardless of enumerability.
- *
- *  JSENUMERATE_NEXT
- *    A previously allocated opaque iterator state is passed in via statep.
- *    Return the next jsid in the iteration using *idp.  The opaque iterator
- *    state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
- *    if there are no properties left to enumerate.
- *
- *  JSENUMERATE_DESTROY
- *    Destroy the opaque iterator state previously allocated in *statep by a
- *    call to this function when enum_op was JSENUMERATE_INIT or
- *    JSENUMERATE_INIT_ALL.
- *
- * The return value is used to indicate success, with a value of JS_FALSE
- * indicating failure.
- */
-typedef JSBool
-(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
-                     jsval *statep, jsid *idp);
-
-/*
- * The old-style JSClass.enumerate op should define all lazy properties not
- * yet reflected in obj.
- */
-typedef JSBool
-(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
-
-/*
- * Resolve a lazy property named by id in obj by defining it directly in obj.
- * Lazy properties are those reflected from some peer native property space
- * (e.g., the DOM attributes for a given node reflected as obj) on demand.
- *
- * JS looks for a property in an object, and if not found, tries to resolve
- * the given id.  If resolve succeeds, the engine looks again in case resolve
- * defined obj[id].  If no such property exists directly in obj, the process
- * is repeated with obj's prototype, etc.
- *
- * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
- */
-typedef JSBool
-(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
-
-/*
- * Like JSResolveOp, but flags provide contextual information as follows:
- *
- *  JSRESOLVE_QUALIFIED   a qualified property id: obj.id or obj[id], not id
- *  JSRESOLVE_ASSIGNING   obj[id] is on the left-hand side of an assignment
- *  JSRESOLVE_DETECTING   'if (o.p)...' or similar detection opcode sequence
- *  JSRESOLVE_DECLARING   var, const, or function prolog declaration opcode
- *  JSRESOLVE_CLASSNAME   class name used when constructing
- *
- * The *objp out parameter, on success, should be null to indicate that id
- * was not resolved; and non-null, referring to obj or one of its prototypes,
- * if id was resolved.
- *
- * This hook instead of JSResolveOp is called via the JSClass.resolve member
- * if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
- *
- * Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
- * extends this hook by passing in the starting object on the prototype chain
- * via *objp.  Thus a resolve hook implementation may define the property id
- * being resolved in the object in which the id was first sought, rather than
- * in a prototype object whose class led to the resolve hook being called.
- *
- * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
- * null *objp to signify "not resolved".  With only JSCLASS_NEW_RESOLVE and no
- * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
- * This is not good practice, but enough existing hook implementations count
- * on it that we can't break compatibility by passing the starting object in
- * *objp without a new JSClass flag.
- */
-typedef JSBool
-(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
-                   JSObject **objp);
-
-/*
- * Convert obj to the given type, returning true with the resulting value in
- * *vp on success, and returning false on error or exception.
- */
-typedef JSBool
-(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
-
-/*
- * Delegate typeof to an object so it can cloak a primitive or another object.
- */
-typedef JSType
-(* JSTypeOfOp)(JSContext *cx, JSObject *obj);
-
-/*
- * Finalize obj, which the garbage collector has determined to be unreachable
- * from other live objects or from GC roots.  Obviously, finalizers must never
- * store a reference to obj.
- */
-typedef void
-(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
-
-/*
- * Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
- * to extend and reduce the set of string types finalized by the GC.
- */
-typedef void
-(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
-
-/*
- * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
- * returning false on error/exception, true on success with obj[id]'s last-got
- * value in *vp, and its attributes in *attrsp.  As for JSPropertyOp above, id
- * is either a string or an int jsval.
- */
-typedef JSBool
-(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
-                    jsval *vp);
-
-/*
- * Encode or decode an object, given an XDR state record representing external
- * data.  See jsxdrapi.h.
- */
-typedef JSBool
-(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
-
-/*
- * Check whether v is an instance of obj.  Return false on error or exception,
- * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
- * *bp otherwise.
- */
-typedef JSBool
-(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
-
-/*
- * Function type for trace operation of the class called to enumerate all
- * traceable things reachable from obj's private data structure. For each such
- * thing, a trace implementation must call
- *
- *    JS_CallTracer(trc, thing, kind);
- *
- * or one of its convenience macros as described in jsapi.h.
- *
- * JSTraceOp implementation can assume that no other threads mutates object
- * state. It must not change state of the object or corresponding native
- * structures. The only exception for this rule is the case when the embedding
- * needs a tight integration with GC. In that case the embedding can check if
- * the traversal is a part of the marking phase through calling
- * JS_IsGCMarkingTracer and apply a special code like emptying caches or
- * marking its native structures.
- */
-typedef void
-(* JSTraceOp)(JSTracer *trc, JSObject *obj);
-
-/*
- * DEBUG only callback that JSTraceOp implementation can provide to return
- * a string describing the reference traced with JS_CallTracer.
- */
-typedef void
-(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
-
-typedef JSBool
-(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
-
-/*
- * Typedef for native functions called by the JS VM.
- *
- * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
- */
-
-typedef JSBool
-(* JSNative)(JSContext *cx, uintN argc, jsval *vp);
-
-/* Callbacks and their arguments. */
-
-typedef enum JSContextOp {
-    JSCONTEXT_NEW,
-    JSCONTEXT_DESTROY
-} JSContextOp;
-
-/*
- * The possible values for contextOp when the runtime calls the callback are:
- *   JSCONTEXT_NEW      JS_NewContext successfully created a new JSContext
- *                      instance. The callback can initialize the instance as
- *                      required. If the callback returns false, the instance
- *                      will be destroyed and JS_NewContext returns null. In
- *                      this case the callback is not called again.
- *   JSCONTEXT_DESTROY  One of JS_DestroyContext* methods is called. The
- *                      callback may perform its own cleanup and must always
- *                      return true.
- *   Any other value    For future compatibility the callback must do nothing
- *                      and return true in this case.
- */
-typedef JSBool
-(* JSContextCallback)(JSContext *cx, uintN contextOp);
-
-#ifndef JS_THREADSAFE
-typedef void
-(* JSHeartbeatCallback)(JSRuntime *rt);
-#endif
-
-typedef enum JSGCStatus {
-    JSGC_BEGIN,
-    JSGC_END,
-    JSGC_MARK_END,
-    JSGC_FINALIZE_END
-} JSGCStatus;
-
-typedef JSBool
-(* JSGCCallback)(JSContext *cx, JSGCStatus status);
-
-/*
- * Generic trace operation that calls JS_CallTracer on each traceable thing
- * stored in data.
- */
-typedef void
-(* JSTraceDataOp)(JSTracer *trc, void *data);
-
-typedef JSBool
-(* JSOperationCallback)(JSContext *cx);
-
-typedef void
-(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
-
-/*
- * Possible exception types. These types are part of a JSErrorFormatString
- * structure. They define which error to throw in case of a runtime error.
- * JSEXN_NONE marks an unthrowable error.
- */
-typedef enum JSExnType {
-    JSEXN_NONE = -1,
-      JSEXN_ERR,
-        JSEXN_INTERNALERR,
-        JSEXN_EVALERR,
-        JSEXN_RANGEERR,
-        JSEXN_REFERENCEERR,
-        JSEXN_SYNTAXERR,
-        JSEXN_TYPEERR,
-        JSEXN_URIERR,
-        JSEXN_LIMIT
-} JSExnType;
-
-typedef struct JSErrorFormatString {
-    /* The error format string (UTF-8 if js_CStringsAreUTF8). */
-    const char *format;
-
-    /* The number of arguments to expand in the formatted error message. */
-    uint16 argCount;
-
-    /* One of the JSExnType constants above. */
-    int16 exnType;
-} JSErrorFormatString;
-
-typedef const JSErrorFormatString *
-(* JSErrorCallback)(void *userRef, const char *locale,
-                    const uintN errorNumber);
-
-#ifdef va_start
-#define JS_ARGUMENT_FORMATTER_DEFINED 1
-
-typedef JSBool
-(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
-                        jsval **vpp, va_list *app);
-#endif
-
-typedef JSBool
-(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
-
-typedef JSBool
-(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
-
-typedef JSBool
-(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
-                    jsval *rval);
-
-typedef JSBool
-(* JSLocaleToUnicode)(JSContext *cx, const char *src, jsval *rval);
-
-/*
- * Security protocol types.
- */
-typedef struct JSPrincipals JSPrincipals;
-
-/*
- * XDR-encode or -decode a principals instance, based on whether xdr->mode is
- * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
- * in which case implementations must return a held (via JSPRINCIPALS_HOLD),
- * non-null *principalsp out parameter.  Return true on success, false on any
- * error, which the implementation must have reported.
- */
-typedef JSBool
-(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
-
-/*
- * Return a weak reference to the principals associated with obj, possibly via
- * the immutable parent chain leading from obj to a top-level container (e.g.,
- * a window object in the DOM level 0).  If there are no principals associated
- * with obj, return null.  Therefore null does not mean an error was reported;
- * in no event should an error be reported or an exception be thrown by this
- * callback's implementation.
- */
-typedef JSPrincipals *
-(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
-
-/*
- * Used to check if a CSP instance wants to disable eval() and friends.
- * See js_CheckCSPPermitsJSAction() in jsobj.
- */
-typedef JSBool
-(* JSCSPEvalChecker)(JSContext *cx);
-
-/*
- * Callback used to ask the embedding for the cross compartment wrapper handler
- * that implements the desired prolicy for this kind of object in the
- * destination compartment.
- */
-typedef JSObject *
-(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
-                         uintN flags);
-
-/*
- * Callback used by the wrap hook to ask the embedding to prepare an object
- * for wrapping in a context. This might include unwrapping other wrappers
- * or even finding a more suitable object for the new compartment.
- */
-typedef JSObject *
-(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags);
-
-typedef enum {
-    JSCOMPARTMENT_DESTROY
-} JSCompartmentOp;
-
-typedef JSBool
-(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, uintN compartmentOp);
-
-/*
- * Read structured data from the reader r. This hook is used to read a value
- * previously serialized by a call to the WriteStructuredCloneOp hook.
- *
- * tag and data are the pair of uint32 values from the header. The callback may
- * use the JS_Read* APIs to read any other relevant parts of the object from
- * the reader r. closure is any value passed to the JS_ReadStructuredClone
- * function. Return the new object on success, NULL on error/exception.
- */
-typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
-                                           uint32 tag, uint32 data, void *closure);
-
-/*
- * Structured data serialization hook. The engine can write primitive values,
- * Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other
- * type of object requires application support. This callback must first use
- * the JS_WriteUint32Pair API to write an object header, passing a value
- * greater than JS_SCTAG_USER to the tag parameter. Then it can use the
- * JS_Write* APIs to write any other relevant parts of the value v to the
- * writer w. closure is any value passed to the JS_WriteStructuredCLone function.
- *
- * Return true on success, false on error/exception.
- */
-typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
-                                         JSObject *obj, void *closure);
-
-/*
- * This is called when JS_WriteStructuredClone finds that the object to be
- * written is recursive. To follow HTML5, the application must throw a
- * DATA_CLONE_ERR DOMException. errorid is always JS_SCERR_RECURSION.
- */
-typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32 errorid);
-
 JS_END_EXTERN_C
 
 #endif /* jspubtd_h___ */
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -9936,17 +9936,17 @@ TraceRecorder::box_value_for_native_call
     return box_value_into_alloc(v, v_ins);
 }
 
 #elif JS_BITS_PER_WORD == 64
 
 void
 TraceRecorder::box_undefined_into(Address addr)
 {
-    w.stq(w.nameImmq(JSVAL_BITS(JSVAL_VOID)), addr);
+    w.stq(w.nameImmq(JSVAL_VOID.asRawBits()), addr);
 }
 
 inline LIns *
 TraceRecorder::non_double_object_value_has_type(LIns *v_ins, JSValueType type)
 {
     return w.eqi(w.q2i(w.rshuqN(v_ins, JSVAL_TAG_SHIFT)),
                  w.nameImmui(JSVAL_TYPE_TO_TAG(type)));
 }
@@ -10038,24 +10038,24 @@ TraceRecorder::unbox_any_object(Address 
     *is_obj_ins = w.geuq(v_ins, w.nameImmq(JSVAL_TYPE_OBJECT));
     *obj_ins = unpack_ptr(v_ins);
 }
 
 LIns*
 TraceRecorder::is_boxed_true(Address addr)
 {
     LIns *v_ins = w.ldq(addr);
-    return w.eqq(v_ins, w.immq(JSVAL_BITS(JSVAL_TRUE)));
+    return w.eqq(v_ins, w.immq(JSVAL_TRUE.asRawBits()));
 }
 
 LIns*
 TraceRecorder::is_boxed_magic(Address addr, JSWhyMagic why)
 {
     LIns *v_ins = w.ldq(addr);
-    return w.eqq(v_ins, w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why)));
+    return w.eqq(v_ins, w.nameImmq(MagicValue(why).asRawBits()));
 }
 
 LIns*
 TraceRecorder::box_value_for_native_call(const Value &v, LIns *v_ins)
 {
     if (v.isNumber()) {
         JS_ASSERT(v_ins->isD());
         if (fcallinfo(v_ins) == &js_UnboxNumberAsDouble_ci)
@@ -10063,19 +10063,19 @@ TraceRecorder::box_value_for_native_call
         if (IsPromotedInt32(v_ins)) {
             return w.orq(w.ui2uq(w.demoteToInt32(v_ins)),
                          w.nameImmq(JSVAL_SHIFTED_TAG_INT32));
         }
         return w.dasq(v_ins);
     }
 
     if (v.isNull())
-        return w.nameImmq(JSVAL_BITS(JSVAL_NULL));
+        return w.nameImmq(JSVAL_NULL.asRawBits());
     if (v.isUndefined())
-        return w.nameImmq(JSVAL_BITS(JSVAL_VOID));
+        return w.nameImmq(JSVAL_VOID.asRawBits());
 
     JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag();
     uint64 shiftedTag = ((uint64)tag) << JSVAL_TAG_SHIFT;
     LIns *shiftedTag_ins = w.nameImmq(shiftedTag);
 
     if (v.hasPtrPayload())
         return w.orq(v_ins, shiftedTag_ins);
     return w.orq(w.ui2uq(v_ins), shiftedTag_ins);
@@ -14844,17 +14844,17 @@ TraceRecorder::storeMagic(JSWhyMagic why
 {
     w.stiValuePayload(w.immpMagicWhy(why), addr);
     w.stiValueTag(w.immpMagicWhy(JSVAL_TAG_MAGIC), addr);
 }
 #elif JS_BITS_PER_WORD == 64
 JS_REQUIRES_STACK void
 TraceRecorder::storeMagic(JSWhyMagic why, Address addr)
 {
-    LIns *magic = w.nameImmq(BUILD_JSVAL(JSVAL_TAG_MAGIC, why));
+    LIns *magic = w.nameImmq(MagicValue(why).asRawBits());
     w.stq(magic, addr);
 }
 #endif
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::unboxNextValue(Value &iterobj_val, LIns* &v_ins)
 {
     JSObject *iterobj = &iterobj_val.toObject();
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -44,16 +44,35 @@
 #ifndef jsutil_h___
 #define jsutil_h___
 
 #include "jstypes.h"
 #include "mozilla/Util.h"
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef __cplusplus
+
+/* The public JS engine namespace. */
+namespace JS {}
+
+/* The mozilla-shared reusable template/utility namespace. */
+namespace mozilla {}
+
+/* The private JS engine namespace. */
+namespace js {
+
+/* The private namespace is a superset of the public/shared namespaces. */
+using namespace JS;
+using namespace mozilla;
+
+}  /* namespace js */
+
+#endif  /* defined __cplusplus */
+
 JS_BEGIN_EXTERN_C
 
 #define JS_CRASH_UNLESS(__cond)                                                 \
     JS_BEGIN_MACRO                                                              \
         if (!(__cond)) {                                                        \
             *(int *)(uintptr_t)0xccadbeef = 0;                                  \
             ((void(*)())0)(); /* More reliable, but doesn't say CCADBEEF */     \
         }                                                                       \
@@ -479,18 +498,16 @@ JS_END_EXTERN_C
 
 /*
  * In general, all allocations should go through a JSContext or JSRuntime, so
  * that the garbage collector knows how much memory has been allocated. In
  * cases where it is difficult to use a JSContext or JSRuntime, OffTheBooks can
  * be used, though this is undesirable.
  */
 namespace js {
-/* Import common mfbt declarations into "js". */
-using namespace mozilla;
 
 class OffTheBooks {
 public:
     JS_DECLARE_NEW_METHODS(::js_malloc, JS_ALWAYS_INLINE static)
 
     static JS_INLINE void* malloc_(size_t bytes) {
         return ::js_malloc(bytes);
     }
--- a/js/src/jsval.h
+++ b/js/src/jsval.h
@@ -35,25 +35,60 @@
  * 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 jsvalimpl_h__
 #define jsvalimpl_h__
 /*
- * JS value implementation details for operations on jsval and jsid.
- * Embeddings should not rely on any of the definitions in this file. For a
- * description of the value representation and the engine-internal C++ value
- * interface, js::Value, see jsvalue.h.
+ * Implementation details for js::Value in jsapi.h.
  */
 #include "jsutil.h"
 
 JS_BEGIN_EXTERN_C
 
+/******************************************************************************/
+
+/* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
+
+#define JSDOUBLE_SIGNBIT (((uint64) 1) << 63)
+#define JSDOUBLE_EXPMASK (((uint64) 0x7ff) << 52)
+#define JSDOUBLE_MANTMASK ((((uint64) 1) << 52) - 1)
+#define JSDOUBLE_HI32_SIGNBIT   0x80000000
+
+static JS_ALWAYS_INLINE JSBool
+JSDOUBLE_IS_NEGZERO(double d)
+{
+    union {
+        struct {
+#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
+            uint32 lo, hi;
+#else
+            uint32 hi, lo;
+#endif
+        } s;
+        double d;
+    } x;
+    if (d != 0)
+        return JS_FALSE;
+    x.d = d;
+    return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSDOUBLE_IS_INT32(double d, int32* pi)
+{
+    if (JSDOUBLE_IS_NEGZERO(d))
+        return JS_FALSE;
+    return d == (*pi = (int32)d);
+}
+
+/******************************************************************************/
+
 /*
  * Try to get jsvals 64-bit aligned. We could almost assert that all values are
  * aligned, but MSVC and GCC occasionally break alignment.
  */
 #if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
 # define JSVAL_ALIGNMENT        __attribute__((aligned (8)))
 #elif defined(_MSC_VER)
   /*
@@ -266,40 +301,31 @@ typedef enum JSWhyMagic
     JS_NO_CONSTANT,              /* compiler sentinel value */
     JS_THIS_POISON,              /* used in debug builds to catch tracing errors */
     JS_ARG_POISON,               /* used in debug builds to catch tracing errors */
     JS_SERIALIZE_NO_NODE,        /* an empty subnode in the AST serializer */
     JS_LAZY_ARGUMENTS,           /* lazy arguments value on the stack */
     JS_GENERIC_MAGIC             /* for local use */
 } JSWhyMagic;
 
-#ifdef __cplusplus
-class                       JSString;
-class                       JSFlatString;
-#else
-typedef struct JSString     JSString;
-typedef struct JSFlatString JSFlatString;
-#endif
-typedef struct JSObject     JSObject;
-
 #if defined(IS_LITTLE_ENDIAN)
 # if JS_BITS_PER_WORD == 32
 typedef union jsval_layout
 {
     uint64 asBits;
     struct {
         union {
             int32          i32;
             uint32         u32;
             JSBool         boo;
             JSString       *str;
             JSObject       *obj;
             void           *ptr;
             JSWhyMagic     why;
-            jsuword        word;
+            size_t         word;
         } payload;
         JSValueTag tag;
     } s;
     double asDouble;
     void *asPtr;
 } jsval_layout;
 # elif JS_BITS_PER_WORD == 64
 typedef union jsval_layout
@@ -316,17 +342,17 @@ typedef union jsval_layout
         union {
             int32          i32;
             uint32         u32;
             JSWhyMagic     why;
         } payload;
     } s;
     double asDouble;
     void *asPtr;
-    jsuword asWord;
+    size_t asWord;
 } jsval_layout;
 # endif  /* JS_BITS_PER_WORD */
 #else   /* defined(IS_LITTLE_ENDIAN) */
 # if JS_BITS_PER_WORD == 32
 typedef union jsval_layout
 {
     uint64 asBits;
     struct {
@@ -334,17 +360,17 @@ typedef union jsval_layout
         union {
             int32          i32;
             uint32         u32;
             JSBool         boo;
             JSString       *str;
             JSObject       *obj;
             void           *ptr;
             JSWhyMagic     why;
-            jsuword        word;
+            size_t         word;
         } payload;
     } s;
     double asDouble;
     void *asPtr;
 } jsval_layout;
 # elif JS_BITS_PER_WORD == 64
 typedef union jsval_layout
 {
@@ -358,33 +384,38 @@ typedef union jsval_layout
         union {
             int32          i32;
             uint32         u32;
             JSWhyMagic     why;
         } payload;
     } s;
     double asDouble;
     void *asPtr;
-    jsuword asWord;
+    size_t asWord;
 } jsval_layout;
 # endif /* JS_BITS_PER_WORD */
 #endif  /* defined(IS_LITTLE_ENDIAN) */
 
 JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
 
 #if JS_BITS_PER_WORD == 32
 
 /*
  * N.B. GCC, in some but not all cases, chooses to emit signed comparison of
  * JSValueTag even though its underlying type has been forced to be uint32.
  * Thus, all comparisons should explicitly cast operands to uint32.
  */
 
-#define BUILD_JSVAL(tag, payload) \
-    ((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
+static JS_ALWAYS_INLINE jsval_layout
+BUILD_JSVAL(JSValueTag tag, uint32 payload)
+{
+    jsval_layout l;
+    l.asBits = (((uint64)(uint32)tag) << 32) | payload;
+    return l;
+}
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
 {
     return (uint32)l.s.tag <= (uint32)JSVAL_TAG_CLEAR;
 }
 
 static JS_ALWAYS_INLINE jsval_layout
@@ -566,20 +597,122 @@ JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
 }
 
 static JS_ALWAYS_INLINE uint32
 JSVAL_TRACE_KIND_IMPL(jsval_layout l)
 {
     return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
 }
 
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
+{
+    return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
+{
+    return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
+{
+    jsval_layout l;
+    l.s.tag = JSVAL_TAG_MAGIC;
+    l.s.payload.why = why;
+    return l;
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_OBJ_TO_JSVAL_IMPL(JSObject *obj)
+{
+    jsval_layout l;
+    l.s.tag = JSVAL_TAG_MAGIC;
+    l.s.payload.obj = obj;
+    return l;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
+{
+    JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
+    return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
+{
+    jsval_layout l;
+    l.s.tag = (JSValueTag)0;
+    l.s.payload.u32 = ui;
+    JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
+    return l;
+}
+
+static JS_ALWAYS_INLINE uint32
+JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
+{
+    return l.s.payload.u32;
+}
+
+static JS_ALWAYS_INLINE JSValueType
+JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
+{
+    uint32 type = l.s.tag & 0xF;
+    JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
+    return (JSValueType)type;
+}
+
+static JS_ALWAYS_INLINE JSValueTag
+JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
+{
+    JSValueTag tag = l.s.tag;
+    JS_ASSERT(tag >= JSVAL_TAG_INT32);
+    return tag;
+}
+
+#ifdef __cplusplus
+JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
+JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
+#endif
+
+static JS_ALWAYS_INLINE jsval_layout
+BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
+{
+    jsval_layout l;
+    JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
+    JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
+                 type == JSVAL_TYPE_OBJECT ||
+                 type == JSVAL_TYPE_NONFUNOBJ ||
+                 type == JSVAL_TYPE_FUNOBJ,
+                 *(uint32 *)slot != 0);
+    l.s.tag = JSVAL_TYPE_TO_TAG(type & 0xF);
+    /* A 32-bit value in a 64-bit slot always occupies the low-addressed end. */
+    l.s.payload.u32 = *(uint32 *)slot;
+    return l;
+}
+
+static JS_ALWAYS_INLINE void
+UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
+{
+    JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
+    *(uint32 *)out = l.s.payload.u32;
+}
+
 #elif JS_BITS_PER_WORD == 64
 
-#define BUILD_JSVAL(tag, payload) \
-    ((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
+static JS_ALWAYS_INLINE jsval_layout
+BUILD_JSVAL(JSValueTag tag, uint64 payload)
+{
+    jsval_layout l;
+    l.asBits = (((uint64)(uint32)tag) << JSVAL_TAG_SHIFT) | payload;
+    return l;
+}
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
 {
     return l.asBits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE;
 }
 
 static JS_ALWAYS_INLINE jsval_layout
@@ -766,83 +899,130 @@ PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
 
 static JS_ALWAYS_INLINE void *
 JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
 {
     JS_ASSERT((l.asBits & 0x8000000000000000LL) == 0);
     return (void *)(l.asBits << 1);
 }
 
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
+{
+    return l.asBits == (((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32);
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
+{
+    return l.asBits == (((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
+{
+    jsval_layout l;
+    l.asBits = ((uint64)(uint32)why) | JSVAL_SHIFTED_TAG_MAGIC;
+    return l;
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_OBJ_TO_JSVAL_IMPL(JSObject *obj)
+{
+    jsval_layout l;
+    l.asBits = ((uint64)obj) | JSVAL_SHIFTED_TAG_MAGIC;
+    return l;
+}
+
+static JS_ALWAYS_INLINE JSBool
+JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
+{
+    uint64 lbits = lhs.asBits, rbits = rhs.asBits;
+    return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
+           (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
+}
+
+static JS_ALWAYS_INLINE jsval_layout
+PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
+{
+    jsval_layout l;
+    l.asBits = (uint64)ui;
+    JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
+    return l;
+}
+
+static JS_ALWAYS_INLINE uint32
+JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
+{
+    JS_ASSERT((l.asBits >> 32) == 0);
+    return (uint32)l.asBits;
+}
+
+static JS_ALWAYS_INLINE JSValueType
+JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
+{
+   uint64 type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
+   JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
+   return (JSValueType)type;
+}
+
+static JS_ALWAYS_INLINE JSValueTag
+JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
+{
+    uint64 tag = l.asBits >> JSVAL_TAG_SHIFT;
+    JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE);
+    return (JSValueTag)tag;
+}
+
+#ifdef __cplusplus
+JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
+JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
 #endif
 
+static JS_ALWAYS_INLINE jsval_layout
+BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
+{
+    uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET);
+    uint32 shift = isI32 * 32;
+    uint64 mask = ((uint64)-1) >> shift;
+    uint64 payload = *slot & mask;
+    jsval_layout l;
+
+    /* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
+    JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
+    JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
+                 type == JSVAL_TYPE_OBJECT ||
+                 type == JSVAL_TYPE_NONFUNOBJ ||
+                 type == JSVAL_TYPE_FUNOBJ,
+                 payload != 0);
+
+    l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
+    return l;
+}
+
+static JS_ALWAYS_INLINE void
+UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
+{
+    JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
+    *out = (l.asBits & JSVAL_PAYLOAD_MASK);
+}
+
+#endif  /* JS_BITS_PER_WORD */
+
 static JS_ALWAYS_INLINE double
 JS_CANONICALIZE_NAN(double d)
 {
     if (JS_UNLIKELY(d != d)) {
         jsval_layout l;
         l.asBits = 0x7FF8000000000000LL;
         return l.asDouble;
     }
     return d;
 }
 
-/* See JS_USE_JSVAL_JSID_STRUCT_TYPES comment in jsapi.h. */
-#if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
-# define JS_USE_JSVAL_JSID_STRUCT_TYPES
+JS_END_EXTERN_C
+
+#ifdef __cplusplus
+static jsval_layout JSVAL_TO_IMPL(JS::Value);
+static JS::Value IMPL_TO_JSVAL(jsval_layout);
 #endif
 
-#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-
-typedef JSVAL_ALIGNMENT jsval_layout   jsval;
-typedef struct jsid { size_t asBits; } jsid;
-
-#if defined(__cplusplus)
-extern "C++"
-{
-    static JS_ALWAYS_INLINE bool
-    operator==(jsid lhs, jsid rhs)
-    {
-        return lhs.asBits == rhs.asBits;
-    }
-
-    static JS_ALWAYS_INLINE bool
-    operator!=(jsid lhs, jsid rhs)
-    {
-        return lhs.asBits != rhs.asBits;
-    }
-
-    static JS_ALWAYS_INLINE bool
-    operator==(jsval lhs, jsval rhs)
-    {
-        return lhs.asBits == rhs.asBits;
-    }
-
-    static JS_ALWAYS_INLINE bool
-    operator!=(jsval lhs, jsval rhs)
-    {
-        return lhs.asBits != rhs.asBits;
-    }
-}
-# endif /* defined(__cplusplus) */
-
-/* Internal helper macros */
-#define JSVAL_BITS(v)    ((v).asBits)
-#define JSVAL_FROM_LAYOUT(l) (l)
-#define IMPL_TO_JSVAL(v) (v)
-#define JSID_BITS(id)    ((id).asBits)
-
-#else /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
-
-/* Use different primitive types so overloading works. */
-typedef JSVAL_ALIGNMENT JSUint64 jsval;
-typedef ptrdiff_t                jsid;
-
-/* Internal helper macros */
-#define JSVAL_BITS(v)    (v)
-#define JSVAL_FROM_LAYOUT(l) ((l).asBits)
-#define IMPL_TO_JSVAL(v) ((v).asBits)
-#define JSID_BITS(id)    (id)
-
-#endif /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
-
-JS_END_EXTERN_C
-
 #endif /* jsvalimpl_h__ */
--- a/js/src/jsvalue.h
+++ b/js/src/jsvalue.h
@@ -38,864 +38,19 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsvalue_h__
 #define jsvalue_h__
 /*
  * Private value interface.
  */
 #include "jsprvtd.h"
-#include "jsstdint.h"
-
-/*
- * js::Value is a C++-ified version of jsval that provides more information and
- * helper functions than the basic jsval interface exposed by jsapi.h. A few
- * general notes on js::Value:
- *
- * - Since js::Value and jsval have the same representation, values of these
- *   types, function pointer types differing only in these types, and structs
- *   differing only in these types can be converted back and forth at no cost
- *   using the Jsvalify() and Valueify(). See Jsvalify comment below.
- *
- * - js::Value has setX() and isX() members for X in
- *
- *     { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
- *
- *   js::Value also contains toX() for each of the non-singleton types.
- *
- * - Magic is a singleton type whose payload contains a JSWhyMagic "reason" for
- *   the magic value. By providing JSWhyMagic values when creating and checking
- *   for magic values, it is possible to assert, at runtime, that only magic
- *   values with the expected reason flow through a particular value. For
- *   example, if cx->exception has a magic value, the reason must be
- *   JS_GENERATOR_CLOSING.
- *
- * - A key difference between jsval and js::Value is that js::Value gives null
- *   a separate type. Thus
- *
- *           JSVAL_IS_OBJECT(v) === v.isObjectOrNull()
- *       !JSVAL_IS_PRIMITIVE(v) === v.isObject()
- *
- *   To help prevent mistakenly boxing a nullable JSObject* as an object,
- *   Value::setObject takes a JSObject&. (Conversely, Value::asObject returns a
- *   JSObject&. A convenience member Value::setObjectOrNull is provided.
- *
- * - JSVAL_VOID is the same as the singleton value of the Undefined type.
- *
- * - Note that js::Value is always 64-bit. Thus, on 32-bit user code should
- *   avoid copying jsval/js::Value as much as possible, preferring to pass by
- *   const Value &.
- */
-
-/******************************************************************************/
-
-/* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
-
-#define JSDOUBLE_SIGNBIT (((uint64) 1) << 63)
-#define JSDOUBLE_EXPMASK (((uint64) 0x7ff) << 52)
-#define JSDOUBLE_MANTMASK ((((uint64) 1) << 52) - 1)
-#define JSDOUBLE_HI32_SIGNBIT   0x80000000
-
-static JS_ALWAYS_INLINE JSBool
-JSDOUBLE_IS_NEGZERO(jsdouble d)
-{
-    if (d != 0)
-        return false;
-    union {
-        struct {
-#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
-            uint32 lo, hi;
-#else
-            uint32 hi, lo;
-#endif
-        } s;
-        jsdouble d;
-    } x;
-    x.d = d;
-    return (x.s.hi & JSDOUBLE_HI32_SIGNBIT) != 0;
-}
-
-static inline bool
-JSDOUBLE_IS_INT32(jsdouble d, int32_t* pi)
-{
-    if (JSDOUBLE_IS_NEGZERO(d))
-        return false;
-    return d == (*pi = int32_t(d));
-}
-
-/******************************************************************************/
-
-/* Additional value operations used in js::Value but not in jsapi.h. */
-
-#if JS_BITS_PER_WORD == 32
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
-{
-    return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
-}
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
-{
-    return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
-    jsval_layout l;
-    l.s.tag = JSVAL_TAG_MAGIC;
-    l.s.payload.why = why;
-    return l;
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSObject *obj)
-{
-    jsval_layout l;
-    l.s.tag = JSVAL_TAG_MAGIC;
-    l.s.payload.obj = obj;
-    return l;
-}
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
-    JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
-    return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
-{
-    jsval_layout l;
-    l.s.tag = (JSValueTag)0;
-    l.s.payload.u32 = ui;
-    JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
-    return l;
-}
-
-static JS_ALWAYS_INLINE uint32
-JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
-{
-    return l.s.payload.u32;
-}
-
-static JS_ALWAYS_INLINE JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
-    uint32 type = l.s.tag & 0xF;
-    JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
-    return (JSValueType)type;
-}
-
-static JS_ALWAYS_INLINE JSValueTag
-JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
-{
-    JSValueTag tag = l.s.tag;
-    JS_ASSERT(tag >= JSVAL_TAG_INT32);
-    return tag;
-}
-
-#ifdef __cplusplus
-JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
-JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
-#endif
-
-static JS_ALWAYS_INLINE jsval_layout
-BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
-{
-    jsval_layout l;
-    JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
-    JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
-                 type == JSVAL_TYPE_OBJECT ||
-                 type == JSVAL_TYPE_NONFUNOBJ ||
-                 type == JSVAL_TYPE_FUNOBJ,
-                 *(uint32 *)slot != 0);
-    l.s.tag = JSVAL_TYPE_TO_TAG(type & 0xF);
-    /* A 32-bit value in a 64-bit slot always occupies the low-addressed end. */
-    l.s.payload.u32 = *(uint32 *)slot;
-    return l;
-}
-
-static JS_ALWAYS_INLINE void
-UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
-{
-    JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
-    *(uint32 *)out = l.s.payload.u32;
-}
-
-#elif JS_BITS_PER_WORD == 64
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32 i32)
-{
-    return l.asBits == (((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32);
-}
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
-{
-    return l.asBits == (((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
-{
-    jsval_layout l;
-    l.asBits = ((uint64)(uint32)why) | JSVAL_SHIFTED_TAG_MAGIC;
-    return l;
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-MAGIC_TO_JSVAL_IMPL(JSObject *obj)
-{
-    jsval_layout l;
-    l.asBits = ((uint64)obj) | JSVAL_SHIFTED_TAG_MAGIC;
-    return l;
-}
-
-static JS_ALWAYS_INLINE JSBool
-JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
-{
-    uint64 lbits = lhs.asBits, rbits = rhs.asBits;
-    return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
-           (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
-}
-
-static JS_ALWAYS_INLINE jsval_layout
-PRIVATE_UINT32_TO_JSVAL_IMPL(uint32 ui)
-{
-    jsval_layout l;
-    l.asBits = (uint64)ui;
-    JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
-    return l;
-}
-
-static JS_ALWAYS_INLINE uint32
-JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
-{
-    JS_ASSERT((l.asBits >> 32) == 0);
-    return (uint32)l.asBits;
-}
-
-static JS_ALWAYS_INLINE JSValueType
-JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
-{
-   uint64 type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
-   JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
-   return (JSValueType)type;
-}
-
-static JS_ALWAYS_INLINE JSValueTag
-JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(jsval_layout l)
-{
-    uint64 tag = l.asBits >> JSVAL_TAG_SHIFT;
-    JS_ASSERT(tag > JSVAL_TAG_MAX_DOUBLE);
-    return (JSValueTag)tag;
-}
-
-#ifdef __cplusplus
-JS_STATIC_ASSERT((JSVAL_TYPE_NONFUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
-JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0xF) == JSVAL_TYPE_OBJECT);
-#endif
-
-static JS_ALWAYS_INLINE jsval_layout
-BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
-{
-    /* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
-    jsval_layout l;
-    JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
-    uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET);
-    uint32 shift = isI32 * 32;
-    uint64 mask = ((uint64)-1) >> shift;
-    uint64 payload = *slot & mask;
-    JS_ASSERT_IF(type == JSVAL_TYPE_STRING ||
-                 type == JSVAL_TYPE_OBJECT ||
-                 type == JSVAL_TYPE_NONFUNOBJ ||
-                 type == JSVAL_TYPE_FUNOBJ,
-                 payload != 0);
-    l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
-    return l;
-}
-
-static JS_ALWAYS_INLINE void
-UNBOX_NON_DOUBLE_JSVAL(jsval_layout l, uint64 *out)
-{
-    JS_ASSERT(!JSVAL_IS_DOUBLE_IMPL(l));
-    *out = (l.asBits & JSVAL_PAYLOAD_MASK);
-}
-
-#endif
-
-/******************************************************************************/
 
 namespace js {
 
-class Value
-{
-  public:
-    /*
-     * N.B. the default constructor leaves Value unitialized. Adding a default
-     * constructor prevents Value from being stored in a union.
-     */
-
-    /*** Mutatators ***/
-
-    JS_ALWAYS_INLINE
-    void setNull() {
-        data.asBits = JSVAL_BITS(JSVAL_NULL);
-    }
-
-    JS_ALWAYS_INLINE
-    void setUndefined() {
-        data.asBits = JSVAL_BITS(JSVAL_VOID);
-    }
-
-    JS_ALWAYS_INLINE
-    void setInt32(int32 i) {
-        data = INT32_TO_JSVAL_IMPL(i);
-    }
-
-    JS_ALWAYS_INLINE
-    int32 &getInt32Ref() {
-        JS_ASSERT(isInt32());
-        return data.s.payload.i32;
-    }
-
-    JS_ALWAYS_INLINE
-    void setDouble(double d) {
-        data = DOUBLE_TO_JSVAL_IMPL(d);
-    }
-
-    JS_ALWAYS_INLINE
-    double &getDoubleRef() {
-        JS_ASSERT(isDouble());
-        return data.asDouble;
-    }
-
-    JS_ALWAYS_INLINE
-    void setString(JSString *str) {
-        data = STRING_TO_JSVAL_IMPL(str);
-    }
-
-    JS_ALWAYS_INLINE
-    void setString(const JS::Anchor<JSString *> &str) {
-        setString(str.get());
-    }
-
-    JS_ALWAYS_INLINE
-    void setObject(JSObject &obj) {
-        data = OBJECT_TO_JSVAL_IMPL(&obj);
-    }
-
-    JS_ALWAYS_INLINE
-    void setObject(const JS::Anchor<JSObject *> &obj) {
-        setObject(*obj.get());
-    }
-
-    JS_ALWAYS_INLINE
-    void setBoolean(bool b) {
-        data = BOOLEAN_TO_JSVAL_IMPL(b);
-    }
-
-    JS_ALWAYS_INLINE
-    void setMagic(JSWhyMagic why) {
-        data = MAGIC_TO_JSVAL_IMPL(why);
-    }
-
-    JS_ALWAYS_INLINE
-    void setMagicWithObjectOrNullPayload(JSObject *obj) {
-        data = MAGIC_TO_JSVAL_IMPL(obj);
-    }
-
-    JS_ALWAYS_INLINE
-    JSObject *getMagicObjectOrNullPayload() const {
-        return MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool setNumber(uint32 ui) {
-        if (ui > JSVAL_INT_MAX) {
-            setDouble((double)ui);
-            return false;
-        } else {
-            setInt32((int32)ui);
-            return true;
-        }
-    }
-
-    JS_ALWAYS_INLINE
-    bool setNumber(double d) {
-        int32_t i;
-        if (JSDOUBLE_IS_INT32(d, &i)) {
-            setInt32(i);
-            return true;
-        } else {
-            setDouble(d);
-            return false;
-        }
-    }
-
-    JS_ALWAYS_INLINE
-    void setObjectOrNull(JSObject *arg) {
-        if (arg)
-            setObject(*arg);
-        else
-            setNull();
-    }
-
-    JS_ALWAYS_INLINE
-    void setObjectOrUndefined(JSObject *arg) {
-        if (arg)
-            setObject(*arg);
-        else
-            setUndefined();
-    }
-
-    JS_ALWAYS_INLINE
-    void swap(Value &rhs) {
-        uint64 tmp = rhs.data.asBits;
-        rhs.data.asBits = data.asBits;
-        data.asBits = tmp;
-    }
-
-    /*** Value type queries ***/
-
-    JS_ALWAYS_INLINE
-    bool isUndefined() const {
-        return JSVAL_IS_UNDEFINED_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isNull() const {
-        return JSVAL_IS_NULL_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isNullOrUndefined() const {
-        return isNull() || isUndefined();
-    }
-
-    JS_ALWAYS_INLINE
-    bool isInt32() const {
-        return JSVAL_IS_INT32_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isInt32(int32 i32) const {
-        return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isDouble() const {
-        return JSVAL_IS_DOUBLE_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isNumber() const {
-        return JSVAL_IS_NUMBER_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isString() const {
-        return JSVAL_IS_STRING_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isObject() const {
-        return JSVAL_IS_OBJECT_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isPrimitive() const {
-        return JSVAL_IS_PRIMITIVE_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isObjectOrNull() const {
-        return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isGCThing() const {
-        return JSVAL_IS_GCTHING_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isBoolean() const {
-        return JSVAL_IS_BOOLEAN_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isTrue() const {
-        return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isFalse() const {
-        return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isMagic() const {
-        return JSVAL_IS_MAGIC_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isMagic(JSWhyMagic why) const {
-        JS_ASSERT_IF(isMagic(), data.s.payload.why == why);
-        return JSVAL_IS_MAGIC_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool isMagicCheck(JSWhyMagic why) const {
-        return isMagic() && data.s.payload.why == why;
-    }
-
-#if JS_BITS_PER_WORD == 64
-    JS_ALWAYS_INLINE
-    bool hasPtrPayload() const {
-        return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET;
-    }
-#endif
-
-    JS_ALWAYS_INLINE
-    bool isMarkable() const {
-        return JSVAL_IS_TRACEABLE_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    JSGCTraceKind gcKind() const {
-        JS_ASSERT(isMarkable());
-        return JSGCTraceKind(JSVAL_TRACE_KIND_IMPL(data));
-    }
-
-    JS_ALWAYS_INLINE
-    JSWhyMagic whyMagic() const {
-        JS_ASSERT(isMagic());
-        return data.s.payload.why;
-    }
-
-    /*** Comparison ***/
-
-    JS_ALWAYS_INLINE
-    bool operator==(const Value &rhs) const {
-        return data.asBits == rhs.data.asBits;
-    }
-
-    JS_ALWAYS_INLINE
-    bool operator!=(const Value &rhs) const {
-        return data.asBits != rhs.data.asBits;
-    }
-
-    /* This function used to be inlined here, but this triggered a gcc bug
-       due to SameType being used in a template method.
-       See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38850 */
-    friend bool SameType(const Value &lhs, const Value &rhs);
-
-    /*** Extract the value's typed payload ***/
-
-    JS_ALWAYS_INLINE
-    int32 toInt32() const {
-        JS_ASSERT(isInt32());
-        return JSVAL_TO_INT32_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    double toDouble() const {
-        JS_ASSERT(isDouble());
-        return data.asDouble;
-    }
-
-    JS_ALWAYS_INLINE
-    double toNumber() const {
-        JS_ASSERT(isNumber());
-        return isDouble() ? toDouble() : double(toInt32());
-    }
-
-    JS_ALWAYS_INLINE
-    JSString *toString() const {
-        JS_ASSERT(isString());
-        return JSVAL_TO_STRING_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    JSObject &toObject() const {
-        JS_ASSERT(isObject());
-        return *JSVAL_TO_OBJECT_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    JSObject *toObjectOrNull() const {
-        JS_ASSERT(isObjectOrNull());
-        return JSVAL_TO_OBJECT_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    void *toGCThing() const {
-        JS_ASSERT(isGCThing());
-        return JSVAL_TO_GCTHING_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    bool toBoolean() const {
-        JS_ASSERT(isBoolean());
-        return JSVAL_TO_BOOLEAN_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    uint32 payloadAsRawUint32() const {
-        JS_ASSERT(!isDouble());
-        return data.s.payload.u32;
-    }
-
-    JS_ALWAYS_INLINE
-    uint64 asRawBits() const {
-        return data.asBits;
-    }
-
-    JS_ALWAYS_INLINE
-    void setRawBits(uint64 bits) {
-        data.asBits = bits;
-    }
-
-    /*
-     * In the extract/box/unbox functions below, "NonDouble" means this
-     * functions must not be called on a value that is a double. This allows
-     * these operations to be implemented more efficiently, since doubles
-     * generally already require special handling by the caller.
-     */
-    JS_ALWAYS_INLINE
-    JSValueType extractNonDoubleType() const {
-        return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    JSValueTag extractNonDoubleTag() const {
-        return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    void unboxNonDoubleTo(uint64 *out) const {
-        UNBOX_NON_DOUBLE_JSVAL(data, out);
-    }
-
-    JS_ALWAYS_INLINE
-    void boxNonDoubleFrom(JSValueType type, uint64 *out) {
-        data = BOX_NON_DOUBLE_JSVAL(type, out);
-    }
-
-    /*
-     * The trace-jit specializes JSVAL_TYPE_OBJECT into JSVAL_TYPE_FUNOBJ and
-     * JSVAL_TYPE_NONFUNOBJ. Since these two operations just return the type of
-     * a value, the caller must handle JSVAL_TYPE_OBJECT separately.
-     */
-    JS_ALWAYS_INLINE
-    JSValueType extractNonDoubleObjectTraceType() const {
-        JS_ASSERT(!isObject());
-        return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    JSValueTag extractNonDoubleObjectTraceTag() const {
-        JS_ASSERT(!isObject());
-        return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
-    }
-
-    /*
-     * Private API
-     *
-     * Private setters/getters allow the caller to read/write arbitrary types
-     * that fit in the 64-bit payload. It is the caller's responsibility, after
-     * storing to a value with setPrivateX to read only using getPrivateX.
-     * Privates values are given a type type which ensures they are not marked.
-     */
-
-    JS_ALWAYS_INLINE
-    void setPrivate(void *ptr) {
-        data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
-    }
-
-    JS_ALWAYS_INLINE
-    void *toPrivate() const {
-        JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
-        return JSVAL_TO_PRIVATE_PTR_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    void setPrivateUint32(uint32 ui) {
-        data = PRIVATE_UINT32_TO_JSVAL_IMPL(ui);
-    }
-
-    JS_ALWAYS_INLINE
-    uint32 toPrivateUint32() const {
-        JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
-        return JSVAL_TO_PRIVATE_UINT32_IMPL(data);
-    }
-
-    JS_ALWAYS_INLINE
-    uint32 &getPrivateUint32Ref() {
-        JS_ASSERT(isDouble());
-        return data.s.payload.u32;
-    }
-
-    /*
-     * An unmarked value is just a void* cast as a Value. Thus, the Value is
-     * not safe for GC and must not be marked. This API avoids raw casts
-     * and the ensuing strict-aliasing warnings.
-     */
-
-    JS_ALWAYS_INLINE
-    void setUnmarkedPtr(void *ptr) {
-        data.asPtr = ptr;
-    }
-
-    JS_ALWAYS_INLINE
-    void *toUnmarkedPtr() const {
-        return data.asPtr;
-    }
-
-    const jsuword *payloadWord() const {
-#if JS_BITS_PER_WORD == 32
-        return &data.s.payload.word;
-#elif JS_BITS_PER_WORD == 64
-        return &data.asWord;
-#endif
-    }
-
-  private:
-    void staticAssertions() {
-        JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
-        JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
-        JS_STATIC_ASSERT(sizeof(JSBool) == 4);
-        JS_STATIC_ASSERT(sizeof(JSWhyMagic) <= 4);
-        JS_STATIC_ASSERT(sizeof(jsval) == 8);
-    }
-
-    jsval_layout data;
-} JSVAL_ALIGNMENT;
-
-JS_ALWAYS_INLINE bool
-SameType(const Value &lhs, const Value &rhs)
-{
-    return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
-}
-
-static JS_ALWAYS_INLINE Value
-NullValue()
-{
-    Value v;
-    v.setNull();
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-UndefinedValue()
-{
-    Value v;
-    v.setUndefined();
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-Int32Value(int32 i32)
-{
-    Value v;
-    v.setInt32(i32);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-DoubleValue(double dbl)
-{
-    Value v;
-    v.setDouble(dbl);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-StringValue(JSString *str)
-{
-    Value v;
-    v.setString(str);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-BooleanValue(bool boo)
-{
-    Value v;
-    v.setBoolean(boo);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-ObjectValue(JSObject &obj)
-{
-    Value v;
-    v.setObject(obj);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-MagicValue(JSWhyMagic why)
-{
-    Value v;
-    v.setMagic(why);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-NumberValue(double dbl)
-{
-    Value v;
-    v.setNumber(dbl);
-    return v;
-}
-
-static JS_ALWAYS_INLINE Value
-ObjectOrNullValue(JSObject *obj)
-{
-    Value v;
-    v.setObjectOrNull(obj);
-    return v;
-}
-
-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++)
-            vec[i].setUndefined();
-    }
-}
-
-/******************************************************************************/
-
 /*
  * As asserted above, js::Value and jsval are layout equivalent. This means:
  *  - an instance of jsval may be reinterpreted as a js::Value and vice versa;
  *  - a pointer to a function taking jsval arguments may be reinterpreted as a
  *    function taking the same arguments, s/jsval/js::Value/, and vice versa;
  *  - a struct containing jsval members may be reinterpreted as a struct with
  *    the same members, s/jsval/js::Value/, and vice versa.
  *
@@ -910,25 +65,25 @@ ClearValueRange(Value *vec, uintN len, b
  *   JsvalT *z = js::Jsvalify(y);
  *   assert(x == z);
  *
  * Conversions between references is also provided for some types. If it seems
  * like a cast is needed to convert between jsval/js::Value, consider adding a
  * new safe overload to Jsvalify/Valueify.
  */
 
-static inline jsval *        Jsvalify(Value *v)        { return (jsval *)v; }
-static inline const jsval *  Jsvalify(const Value *v)  { return (const jsval *)v; }
-static inline jsval &        Jsvalify(Value &v)        { return (jsval &)v; }
-static inline const jsval &  Jsvalify(const Value &v)  { return (const jsval &)v; }
-static inline Value *        Valueify(jsval *v)        { return (Value *)v; }
-static inline const Value *  Valueify(const jsval *v)  { return (const Value *)v; }
-static inline Value **       Valueify(jsval **v)       { return (Value **)v; }
-static inline Value &        Valueify(jsval &v)        { return (Value &)v; }
-static inline const Value &  Valueify(const jsval &v)  { return (const Value &)v; }
+static inline jsval *        Jsvalify(Value *v)        { return v; }
+static inline const jsval *  Jsvalify(const Value *v)  { return v; }
+static inline jsval &        Jsvalify(Value &v)        { return v; }
+static inline const jsval &  Jsvalify(const Value &v)  { return v; }
+static inline Value *        Valueify(jsval *v)        { return v; }
+static inline const Value *  Valueify(const jsval *v)  { return v; }
+static inline Value **       Valueify(jsval **v)       { return v; }
+static inline Value &        Valueify(jsval &v)        { return v; }
+static inline const Value &  Valueify(const jsval &v)  { return v; }
 
 struct Class;
 
 typedef JSBool
 (* Native)(JSContext *cx, uintN argc, Value *vp);
 typedef JSBool
 (* PropertyOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 typedef JSBool
@@ -1158,20 +313,18 @@ static JS_ALWAYS_INLINE PropertyDescript
  * Any cast-via-function-call, inlined or not, will cause initialization to
  * happen at startup, rather than statically, so just cast in release builds.
  */
 #ifdef DEBUG
 
 # define JS_VALUEIFY(type, v) js::Valueify(v)
 # define JS_JSVALIFY(type, v) js::Jsvalify(v)
 
-static inline JSNative JsvalifyNative(Native n)   { return (JSNative) n; }
-static inline JSNative JsvalifyNative(JSNative n) { return n; }
-static inline Native ValueifyNative(JSNative n)   { return (Native) n; }
-static inline Native ValueifyNative(Native n)     { return n; }
+static inline JSNative JsvalifyNative(Native n)   { return n; }
+static inline Native ValueifyNative(JSNative n)   { return n; }
 static inline JSPropertyOp CastNativeToJSPropertyOp(Native n) { return (JSPropertyOp) n; }
 static inline JSStrictPropertyOp CastNativeToJSStrictPropertyOp(Native n) {
     return (JSStrictPropertyOp) n;
 }
 
 # define JS_VALUEIFY_NATIVE(n) js::ValueifyNative(n)
 # define JS_JSVALIFY_NATIVE(n) js::JsvalifyNative(n)
 # define JS_CAST_NATIVE_TO_JSPROPERTYOP(n) js::CastNativeToJSPropertyOp(n)
@@ -1239,16 +392,28 @@ ValueArgToConstRef(const Value &v)
 {
     return v;
 }
 #endif
 
 /******************************************************************************/
 
 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++)
+            vec[i].setUndefined();
+    }
+}
+
+static JS_ALWAYS_INLINE void
 MakeRangeGCSafe(Value *vec, size_t len)
 {
     PodZero(vec, len);
 }
 
 static JS_ALWAYS_INLINE void
 MakeRangeGCSafe(Value *beg, Value *end)
 {
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -106,21 +106,16 @@ js_EnterLocalRootScope(JSContext *cx)
 }
 
 static inline void
 js_LeaveLocalRootScope(JSContext *cx)
 {
 }
 
 static inline void
-js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
-{
-}
-
-static inline void
 js_LeaveLocalRootScopeWithResult(JSContext *cx, Value rval)
 {
 }
 
 static inline void
 js_LeaveLocalRootScopeWithResult(JSContext *cx, void *rval)
 {
 }
--- a/js/src/methodjit/FrameEntry.h
+++ b/js/src/methodjit/FrameEntry.h
@@ -65,19 +65,19 @@ class FrameEntry
         return data.isConstant();
     }
 
     const jsval_layout &getConstant() const {
         JS_ASSERT(isConstant());
         return v_;
     }
 
-    const Value &getValue() const {
+    Value getValue() const {
         JS_ASSERT(isConstant());
-        return Valueify(JSVAL_FROM_LAYOUT(v_));
+        return IMPL_TO_JSVAL(v_);
     }
 
 #if defined JS_NUNBOX32
     uint32 getPayload() const {
         //JS_ASSERT(!Valueify(v_.asBits).isDouble() || type.synced());
         JS_ASSERT(isConstant());
         return v_.s.payload.u32;
     }
@@ -207,28 +207,27 @@ class FrameEntry
         clear();
         type.setMemory();
         data.setMemory();
     }
 
     /*
      * Marks the FE as having a constant.
      */
-    void setConstant(const jsval &v) {
+    void setConstant(const Value &v) {
         clear();
         type.unsync();
         data.unsync();
         type.setConstant();
         data.setConstant();
-        v_.asBits = JSVAL_BITS(v);
-        Value cv = Valueify(v);
-        if (cv.isDouble())
+        v_ = JSVAL_TO_IMPL(v);
+        if (v.isDouble())
             knownType = JSVAL_TYPE_DOUBLE;
         else
-            knownType = cv.extractNonDoubleType();
+            knownType = v.extractNonDoubleType();
     }
 
     FrameEntry *copyOf() const {
         JS_ASSERT(isCopy());
         JS_ASSERT_IF(!copy->temporary, copy < this);
         return copy;
     }
 
--- a/js/src/methodjit/NunboxAssembler.h
+++ b/js/src/methodjit/NunboxAssembler.h
@@ -159,25 +159,25 @@ class NunboxAssembler : public JSC::Macr
         loadTypeTag(address, type);
         Label l = label();
         loadPayload(address, payload);
         return l;
     }
 
     void loadValueAsComponents(const Value &val, RegisterID type, RegisterID payload) {
         jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(val));
+        jv.asBits = val.asRawBits();
 
         move(ImmTag(jv.s.tag), type);
         move(Imm32(jv.s.payload.u32), payload);
     }
 
     void loadValuePayload(const Value &val, RegisterID payload) {
         jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(val));
+        jv.asBits = val.asRawBits();
 
         move(Imm32(jv.s.payload.u32), payload);
     }
 
     /*
      * Load a (64b) js::Value from 'address' into 'type' and 'payload', and
      * return a label which can be used by
      * ICRepatcher::patchAddressOffsetForValueLoad to patch the address'
@@ -253,17 +253,17 @@ class NunboxAssembler : public JSC::Macr
 #elif defined JS_CPU_ARM || defined JS_CPU_SPARC
         return store64WithAddressOffsetPatch(type, dreg, address);
 #endif
     }
 
     /* Overloaded for storing constant type and data. */
     DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
         jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(v));
+        jv.asBits = v.asRawBits();
         ImmTag type(jv.s.tag);
         Imm32 payload(jv.s.payload.u32);
         DataLabel32 start = dataLabel32();
 #if defined JS_CPU_X86
         store32(type, tagOf(address));
         DBGLABEL_NOMASM(endType);
         store32(payload, payloadOf(address));
         DBGLABEL_NOMASM(endPayload);
@@ -292,17 +292,17 @@ class NunboxAssembler : public JSC::Macr
     }
 
     /*
      * Stores type first, then payload.
      */
     template <typename T>
     Label storeValue(const Value &v, T address) {
         jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(v));
+        jv.asBits = v.asRawBits();
 
         store32(ImmTag(jv.s.tag), tagOf(address));
         Label l = label();
         store32(Imm32(jv.s.payload.u32), payloadOf(address));
         return l;
     }
 
     template <typename T>
--- a/js/src/methodjit/PunboxAssembler.h
+++ b/js/src/methodjit/PunboxAssembler.h
@@ -175,20 +175,17 @@ class PunboxAssembler : public JSC::Macr
     DataLabel32 storeValueWithAddressOffsetPatch(ImmTag type, RegisterID payload, Address address) {
         move(type, Registers::ValueReg);
         orPtr(payload, Registers::ValueReg);
         return storePtrWithAddressOffsetPatch(Registers::ValueReg, address);
     }
 
     /* Overload for constant type and constant data. */
     DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
-        jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(v));
-
-        move(ImmPtr(reinterpret_cast<void*>(jv.asBits)), Registers::ValueReg);
+        move(ImmPtr(reinterpret_cast<void*>(v.asRawBits())), Registers::ValueReg);
         return storePtrWithAddressOffsetPatch(Registers::ValueReg, valueOf(address));
     }
 
     /* Overloaded for store with value remat info. */
     DataLabel32 storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
         JS_ASSERT(!vr.isFPRegister());
         if (vr.isConstant()) {
             return storeValueWithAddressOffsetPatch(vr.value(), address);
@@ -246,20 +243,17 @@ class PunboxAssembler : public JSC::Macr
 
     template <typename T>
     void storeValue(RegisterID reg, T address) {
         storePtr(reg, valueOf(address));
     }
 
     template <typename T>
     void storeValue(const Value &v, T address) {
-        jsval_layout jv;
-        jv.asBits = JSVAL_BITS(Jsvalify(v));
-
-        storePtr(Imm64(jv.asBits), valueOf(address));
+        storePtr(Imm64(v.asRawBits()), valueOf(address));
     }
 
     template <typename T>
     void storeValue(const ValueRemat &vr, T address) {
         if (vr.isConstant())
             storeValue(vr.value(), address);
         else if (vr.isFPRegister())
             storeDouble(vr.fpReg(), address);
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -36,16 +36,17 @@
  * 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 String_h_
 #define String_h_
 
+#include "jsapi.h"
 #include "jscell.h"
 
 class JSString;
 class JSDependentString;
 class JSExtensibleString;
 class JSExternalString;
 class JSLinearString;
 class JSFixedString;
--- a/js/src/xpconnect/idl/xpcexception.idl
+++ b/js/src/xpconnect/idl/xpcexception.idl
@@ -38,17 +38,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIException.idl"
 
 %{ C++
-#include "jspubtd.h"
+#include "jsapi.h"
 %}
 
 [ptr] native xpcexJSContextPtr(JSContext);
       native xpcexJSVal(jsval);
 
 [scriptable, uuid(cac29630-7bf2-4e22-811b-46855a7d5af0)]
 interface nsIXPCException : nsIException
 {
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -2952,17 +2952,17 @@ JS_EXPORT_API(void) DumpJSEval(PRUint32 
 
 JS_EXPORT_API(void) DumpJSObject(JSObject* obj)
 {
     xpc_DumpJSObject(obj);
 }
 
 JS_EXPORT_API(void) DumpJSValue(jsval val)
 {
-    printf("Dumping 0x%llu.\n", (long long) JSVAL_BITS(val));
+    printf("Dumping 0x%llu.\n", (long long) val.asRawBits());
     if(JSVAL_IS_NULL(val)) {
         printf("Value is null\n");
     }
     else if(JSVAL_IS_OBJECT(val) || JSVAL_IS_NULL(val)) {
         printf("Value is an object\n");
         JSObject* obj = JSVAL_TO_OBJECT(val);
         DumpJSObject(obj);
     }
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -356,18 +356,17 @@ DefineGetterOrSetter(JSContext *cx, uint
     JSObject *obj2;
     jsval v;
     jsid id;
 
     XPC_QS_ASSERT_CONTEXT_OK(cx);
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
-    JSNative forward = wantGetter ? Jsvalify(js_obj_defineGetter)
-                                  : Jsvalify(js_obj_defineSetter);
+    JSNative forward = wantGetter ? js_obj_defineGetter : js_obj_defineSetter;
     jsval idval = (argc >= 1) ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
     if(!JSVAL_IS_STRING(idval))
         return forward(cx, argc, vp);
 
     if(!JS_ValueToId(cx, idval, &id) ||
        !JS_LookupPropertyWithFlagsById(cx, obj, id,
                                        JSRESOLVE_QUALIFIED, &obj2, &v) ||
        (obj2 &&
--- a/storage/src/Variant_inl.h
+++ b/storage/src/Variant_inl.h
@@ -248,15 +248,15 @@ NS_IMETHODIMP
 Variant_base::GetAsWStringWithSize(PRUint32 *,
                                    PRUnichar **)
 {
   return NS_ERROR_CANNOT_CONVERT_DATA;
 }
 
 inline
 NS_IMETHODIMP
-Variant_base::GetAsJSVal(jsval *)
+Variant_base::GetAsJSVal(JS::Value *)
 {
   return NS_ERROR_CANNOT_CONVERT_DATA;
 }
 
 } // namespace storage
 } // namespace mozilla
--- a/xpcom/ds/nsVariant.cpp
+++ b/xpcom/ds/nsVariant.cpp
@@ -1882,17 +1882,17 @@ NS_IMETHODIMP nsVariant::GetAsWString(PR
 
 /* nsISupports getAsISupports (); */
 NS_IMETHODIMP nsVariant::GetAsISupports(nsISupports **_retval)
 {
     return nsVariant::ConvertToISupports(mData, _retval);
 }
 
 /* jsval getAsJSVal() */
-NS_IMETHODIMP nsVariant::GetAsJSVal(jsval *_retval)
+NS_IMETHODIMP nsVariant::GetAsJSVal(JS::Value *_retval)
 {
     // Can only get the jsval from an XPCVariant.
     return NS_ERROR_CANNOT_CONVERT_DATA;
 }
 
 /* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
 NS_IMETHODIMP nsVariant::GetAsInterface(nsIID * *iid, void * *iface)
 {
--- a/xpcom/idl-parser/xpidl.py
+++ b/xpcom/idl-parser/xpidl.py
@@ -412,17 +412,17 @@ class Native(object):
     specialtype = None
 
     specialtypes = {
         'nsid': None,
         'domstring': 'nsAString',
         'utf8string': 'nsACString',
         'cstring': 'nsACString',
         'astring': 'nsAString',
-        'jsval': 'jsval'
+        'jsval': 'JS::Value'
         }
 
     def __init__(self, name, nativename, attlist, location):
         self.name = name
         self.nativename = nativename
         self.location = location
 
         for name, value, aloc in attlist: