Bug 828753 - jsid rooting, mostly in jsinfer.*. Also switch JSObject from struct to class. r=terrence
☠☠ backed out by 7a3c7b85898c ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Mon, 31 Dec 2012 12:40:21 -0800
changeset 125381 fce4e0f8a553d8edb52b30a67093749b268f3705
parent 125380 03c71f6fa4b81dee98b6139c348a2af61bacab93
child 125382 49257701082059c72f498e3578c8173b10fe13f3
push idunknown
push userunknown
push dateunknown
reviewersterrence
bugs828753
milestone21.0a1
Bug 828753 - jsid rooting, mostly in jsinfer.*. Also switch JSObject from struct to class. r=terrence
content/base/src/nsFrameMessageManager.h
content/base/src/nsNodeUtils.h
content/events/src/nsDOMEvent.h
content/html/content/public/nsIHTMLCollection.h
content/media/webaudio/AudioBuffer.h
content/xbl/src/nsXBLBinding.h
content/xul/document/src/nsXULDocument.h
dom/base/nsIScriptGlobalObject.h
dom/base/nsPerformance.h
dom/base/nsWrapperCache.h
dom/bindings/Codegen.py
dom/bluetooth/BluetoothUtils.h
dom/ipc/TabParent.h
dom/network/src/TCPSocketChild.h
dom/network/src/TCPSocketParent.h
dom/plugins/base/nsNPAPIPluginInstance.h
embedding/components/windowwatcher/src/nsWindowWatcher.h
gfx/skia/include/xml/SkJS.h
ipc/testshell/TestShellParent.h
ipc/testshell/XPCShellEnvironment.h
js/src/builtin/Intl.h
js/src/frontend/SharedContext-inl.h
js/src/gc/Marking.h
js/src/gc/Root.h
js/src/ion/IonBuilder.cpp
js/src/ion/TypeOracle.cpp
js/src/ion/TypeOracle.h
js/src/jsanalyze.h
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscompartment.h
js/src/jsdate.h
js/src/jsfun.h
js/src/jsinfer.cpp
js/src/jsinfer.h
js/src/jsinferinlines.h
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jspubtd.h
js/src/jsscope.h
js/src/jsstr.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/LoopState.cpp
js/src/methodjit/LoopState.h
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/vm/ObjectImpl-inl.h
js/src/vm/ObjectImpl.cpp
js/src/vm/ObjectImpl.h
js/src/vm/String.h
xpcom/build/nsXULAppAPI.h
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -79,17 +79,17 @@ public:
 };
 
 } // namespace ipc
 } // namespace dom
 } // namespace mozilla
 
 class nsAXPCNativeCallContext;
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 struct nsMessageListenerInfo
 {
   nsCOMPtr<nsIMessageListener> mListener;
   nsCOMPtr<nsIAtom> mMessage;
 };
 
 
--- a/content/base/src/nsNodeUtils.h
+++ b/content/base/src/nsNodeUtils.h
@@ -6,17 +6,17 @@
 #ifndef nsNodeUtils_h___
 #define nsNodeUtils_h___
 
 #include "nsIContent.h"          // for use in inline function (ParentChainChanged)
 #include "nsIMutationObserver.h" // for use in inline function (ParentChainChanged)
 
 struct CharacterDataChangeInfo;
 struct JSContext;
-struct JSObject;
+class JSObject;
 class nsIVariant;
 class nsIDOMNode;
 class nsIDOMUserDataHandler;
 template<class E> class nsCOMArray;
 class nsCycleCollectionTraversalCallback;
 
 class nsNodeUtils
 {
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -15,17 +15,17 @@
 #include "nsGUIEvent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsIJSNativeInitializer.h"
 
 class nsIContent;
 class nsPresContext;
 struct JSContext;
-struct JSObject;
+class JSObject;
  
 class nsDOMEvent : public nsIDOMEvent,
                    public nsIJSNativeInitializer
 {
 public:
 
   nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent);
   virtual ~nsDOMEvent();
--- a/content/html/content/public/nsIHTMLCollection.h
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -5,17 +5,17 @@
 
 #ifndef nsIHTMLCollection_h___
 #define nsIHTMLCollection_h___
 
 #include "nsIDOMHTMLCollection.h"
 #include "nsWrapperCache.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 class nsINode;
 namespace mozilla {
 class ErrorResult;
 
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
--- a/content/media/webaudio/AudioBuffer.h
+++ b/content/media/webaudio/AudioBuffer.h
@@ -11,17 +11,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/Attributes.h"
 #include "EnableWebAudioCheck.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "AudioContext.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 class AudioBuffer MOZ_FINAL : public nsISupports,
--- a/content/xbl/src/nsXBLBinding.h
+++ b/content/xbl/src/nsXBLBinding.h
@@ -19,17 +19,17 @@ class nsXBLPrototypeBinding;
 class nsIContent;
 class nsIAtom;
 class nsIDocument;
 class nsIScriptContext;
 class nsObjectHashtable;
 class nsXBLInsertionPoint;
 typedef nsTArray<nsRefPtr<nsXBLInsertionPoint> > nsInsertionPointList;
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 // *********************************************************************/
 // The XBLBinding class
 
 class nsXBLBinding
 {
 public:
   nsXBLBinding(nsXBLPrototypeBinding* aProtoBinding);
--- a/content/xul/document/src/nsXULDocument.h
+++ b/content/xul/document/src/nsXULDocument.h
@@ -36,17 +36,17 @@ class nsIXULPrototypeScript;
 #else
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsXULElement.h"
 #endif
 #include "nsURIHashKey.h"
 #include "nsInterfaceHashtable.h"
 
-struct JSObject;
+class JSObject;
 struct JSTracer;
 struct PRLogModuleInfo;
 
 class nsRefMapEntry : public nsStringHashKey
 {
 public:
   nsRefMapEntry(const nsAString& aKey) :
     nsStringHashKey(&aKey)
--- a/dom/base/nsIScriptGlobalObject.h
+++ b/dom/base/nsIScriptGlobalObject.h
@@ -12,17 +12,17 @@
 #include "nsIProgrammingLanguage.h"
 
 class nsIScriptContext;
 class nsIDOMEvent;
 class nsIScriptGlobalObjectOwner;
 class nsIArray;
 class nsScriptErrorEvent;
 class nsIScriptGlobalObject;
-struct JSObject; // until we finally remove GetGlobalJSObject...
+class JSObject; // until we finally remove GetGlobalJSObject...
 
 // XXXbz can we just remove all this script type id stuff?
 // Some helpers for working with integer "script type IDs", and specifically
 // for working with arrays of such objects. For example, it is common for
 // implementations supporting multiple script languages to keep each
 // language's nsIScriptContext in an array indexed by the language ID.
 
 #define NS_STID_FIRST nsIProgrammingLanguage::JAVASCRIPT
--- a/dom/base/nsPerformance.h
+++ b/dom/base/nsPerformance.h
@@ -11,17 +11,17 @@
 #include "mozilla/Attributes.h"
 #include "nsWrapperCache.h"
 #include "nsDOMNavigationTiming.h"
 
 class nsIURI;
 class nsITimedChannel;
 class nsIDOMWindow;
 class nsPerformance;
-struct JSObject;
+class JSObject;
 struct JSContext;
 
 // Script "performance.timing" object
 class nsPerformanceTiming MOZ_FINAL : public nsISupports,
                                       public nsWrapperCache
 {
 public:
   nsPerformanceTiming(nsPerformance* aPerformance,
--- a/dom/base/nsWrapperCache.h
+++ b/dom/base/nsWrapperCache.h
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsWrapperCache_h___
 #define nsWrapperCache_h___
 
 #include "nsCycleCollectionParticipant.h"
 
-struct JSObject;
+class JSObject;
 struct JSContext;
 class XPCWrappedNativeScope;
 
 namespace mozilla {
 namespace dom {
 namespace workers {
 
 class DOMBindingBase;
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6915,17 +6915,17 @@ class CGBindingRoot(CGThing):
             except NoSuchDescriptorError:
                 # just move along
                 pass
 
         def declareNativeType(nativeType):
             components = nativeType.split('::')
             className = components[-1]
             # JSObject is a struct, not a class
-            declare = CGClassForwardDeclare(className, className == "JSObject")
+            declare = CGClassForwardDeclare(className)
             if len(components) > 1:
                 declare = CGNamespace.build(components[:-1],
                                             CGWrapper(declare, declarePre='\n',
                                                       declarePost='\n'),
                                             declareOnly=True)
             return CGWrapper(declare, declarePost='\n')
 
         for x in descriptorsForForwardDeclaration:
--- a/dom/bluetooth/BluetoothUtils.h
+++ b/dom/bluetooth/BluetoothUtils.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_bluetooth_bluetoothutils_h__
 #define mozilla_dom_bluetooth_bluetoothutils_h__
 
 #include "BluetoothCommon.h"
 #include "nsTArray.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothNamedValue;
 class BluetoothValue;
 class BluetoothReplyRunnable;
 
 bool
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -19,17 +19,17 @@
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDialogParamBlock.h"
 #include "nsISecureBrowserUI.h"
 #include "nsITabParent.h"
 #include "nsWeakReference.h"
 
 struct gfxMatrix;
 struct JSContext;
-struct JSObject;
+class JSObject;
 class mozIApplication;
 class nsFrameLoader;
 class nsIDOMElement;
 class nsIURI;
 
 namespace mozilla {
 
 namespace layers {
--- a/dom/network/src/TCPSocketChild.h
+++ b/dom/network/src/TCPSocketChild.h
@@ -7,17 +7,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 
 #define TCPSOCKETCHILD_CID \
   { 0xa589d96f, 0x7e09, 0x4edf, { 0xa0, 0x1a, 0xeb, 0x49, 0x51, 0xf4, 0x2f, 0x37 } }
 
 class nsITCPSocketInternal;
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 namespace mozilla {
 namespace dom {
 
 class TCPSocketChildBase : public nsITCPSocketChild {
 public:
   NS_DECL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase)
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
--- a/dom/network/src/TCPSocketParent.h
+++ b/dom/network/src/TCPSocketParent.h
@@ -4,17 +4,17 @@
 
 #include "mozilla/net/PTCPSocketParent.h"
 #include "nsITCPSocketParent.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMTCPSocket.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 namespace mozilla {
 namespace dom {
 
 class PBrowserParent;
 
 class TCPSocketParent : public mozilla::net::PTCPSocketParent
                       , public nsITCPSocketParent
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -23,17 +23,17 @@
 #include <map>
 class PluginEventRunnable;
 class SharedPluginTexture;
 #endif
 
 #include "mozilla/TimeStamp.h"
 #include "mozilla/PluginLibrary.h"
 
-struct JSObject;
+class JSObject;
 
 class nsPluginStreamListenerPeer; // browser-initiated stream class
 class nsNPAPIPluginStreamListener; // plugin-initiated stream class
 class nsIPluginInstanceOwner;
 class nsIOutputStream;
 class nsPluginInstanceOwner;
 
 #if defined(OS_WIN)
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.h
@@ -23,17 +23,17 @@ class  nsIURI;
 class  nsIDocShellTreeItem;
 class  nsIDocShellTreeOwner;
 class  nsIWebBrowserChrome;
 class  nsString;
 class  nsWatcherWindowEnumerator;
 class  nsIScriptContext;
 class  nsPromptService;
 struct JSContext;
-struct JSObject;
+class JSObject;
 struct nsWatcherWindowEntry;
 struct SizeSpec;
 
 class nsWindowWatcher :
       public nsIWindowWatcher,
       public nsPIWindowWatcher,
       public nsIPromptFactory
 {
--- a/gfx/skia/include/xml/SkJS.h
+++ b/gfx/skia/include/xml/SkJS.h
@@ -11,17 +11,17 @@
 #include "SkWindow.h"
 
 extern "C" {
     typedef long JSWord;
     typedef JSWord jsword;
     typedef jsword  jsval;
     typedef struct JSRuntime JSRuntime;
     typedef struct JSContext JSContext;
-    typedef struct JSObject JSObject;
+    typedef class JSObject JSObject;
 }
 
 class SkString;
 
 class SkJS : public SkOSWindow {
 public:
     SkJS(void* hwnd);
     ~SkJS();
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -11,17 +11,17 @@
 #include "mozilla/ipc/PTestShellParent.h"
 #include "mozilla/ipc/PTestShellCommandParent.h"
 
 #include "jsapi.h"
 #include "nsAutoJSValHolder.h"
 #include "nsStringGlue.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 namespace mozilla {
 
 namespace jsipc {
 class PContextWrapperParent;
 }
 
 namespace ipc {
--- a/ipc/testshell/XPCShellEnvironment.h
+++ b/ipc/testshell/XPCShellEnvironment.h
@@ -11,17 +11,17 @@
 #include <stdio.h>
 
 #include "nsAutoJSValHolder.h"
 #include "nsCOMPtr.h"
 #include "nsDebug.h"
 #include "nsStringGlue.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 struct JSPrincipals;
 
 class nsIJSContextStack;
 
 namespace mozilla {
 namespace ipc {
 
 class XPCShellEnvironment
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef Intl_h___
 #define Intl_h___
 
 #include "gc/Root.h"
 
 struct JSContext;
-struct JSObject;
+class JSObject;
 
 /*
  * The Intl module specified by standard ECMA-402,
  * ECMAScript Internationalization API Specification.
  */
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
--- a/js/src/frontend/SharedContext-inl.h
+++ b/js/src/frontend/SharedContext-inl.h
@@ -108,33 +108,35 @@ frontend::FinishPopStatement(ContextT *c
  * which the bindings for that scope are stored. LexicalLookup either returns
  * the innermost statement which has a scope object containing a binding with
  * the given name, or NULL.
  */
 template <class ContextT>
 typename ContextT::StmtInfo *
 frontend::LexicalLookup(ContextT *ct, HandleAtom atom, int *slotp, typename ContextT::StmtInfo *stmt)
 {
+    RootedId id(ct->sc->context, AtomToId(atom));
+
     if (!stmt)
         stmt = ct->topScopeStmt;
     for (; stmt; stmt = stmt->downScope) {
         /*
          * With-statements introduce dynamic bindings. Since dynamic bindings
          * can potentially override any static bindings introduced by statements
          * further up the stack, we have to abort the search.
          */
         if (stmt->type == STMT_WITH)
             break;
 
         // Skip statements that do not introduce a new scope
         if (!stmt->isBlockScope)
             continue;
 
         StaticBlockObject &blockObj = *stmt->blockObj;
-        UnrootedShape shape = blockObj.nativeLookup(ct->sc->context, AtomToId(atom));
+        UnrootedShape shape = blockObj.nativeLookup(ct->sc->context, id);
         if (shape) {
             JS_ASSERT(shape->hasShortID());
 
             if (slotp)
                 *slotp = blockObj.stackDepth() + shape->shortid();
             return stmt;
         }
     }
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -14,17 +14,17 @@
 
 #include "gc/Barrier.h"
 #include "js/TemplateLib.h"
 #include "ion/IonCode.h"
 
 extern "C" {
 struct JSContext;
 class JSFunction;
-struct JSObject;
+class JSObject;
 class JSScript;
 }
 
 class JSAtom;
 class JSLinearString;
 
 namespace js {
 
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -245,16 +245,17 @@ class Handle : public js::HandleBase<T>
 
     const T *address() const { return ptr; }
     T get() const { return *ptr; }
 
     operator T() const { return get(); }
     T operator->() const { return get(); }
 
     bool operator!=(const T &other) { return *ptr != other; }
+    bool operator==(const T &other) { return *ptr == other; }
 
   private:
     Handle() {}
 
     const T *ptr;
 
     template <typename S>
     void operator=(S v) MOZ_DELETE;
@@ -659,16 +660,19 @@ class Rooted : public RootedBase<T>
         return ptr;
     }
 
     T &operator=(const Rooted &value) {
         ptr = value;
         return ptr;
     }
 
+    bool operator!=(const T &other) { return ptr != other; }
+    bool operator==(const T &other) { return ptr == other; }
+
   private:
     void commonInit(Rooted<void*> **thingGCRooters) {
 #if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING)
         ThingRootKind kind = RootMethods<T>::kind();
         this->stack = reinterpret_cast<Rooted<T>**>(&thingGCRooters[kind]);
         this->prev = *stack;
         *stack = this;
 
@@ -896,10 +900,11 @@ class CompilerRootNode
   protected:
     js::gc::Cell *ptr;
 };
 
 }  /* namespace js */
 
 ForwardDeclareJS(Script);
 ForwardDeclareJS(Function);
+ForwardDeclareJS(Object);
 
 #endif  /* jsgc_root_h___ */
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -4405,17 +4405,17 @@ IonBuilder::jsop_initprop(HandleProperty
         MInitProp *init = MInitProp::New(obj, name, value);
         current->add(init);
         return resumeAfter(init);
     }
 
     bool needsBarrier = true;
     TypeOracle::BinaryTypes b = oracle->binaryTypes(script(), pc);
     if (b.lhsTypes &&
-        ((jsid)id == types::MakeTypeId(cx, id)) &&
+        (id == types::IdToTypeId(id)) &&
         !b.lhsTypes->propertyNeedsBarrier(cx, id))
     {
         needsBarrier = false;
     }
 
     if (templateObject->isFixedSlot(shape->slot())) {
         MStoreFixedSlot *store = MStoreFixedSlot::New(obj, shape->slot(), value);
         if (needsBarrier)
@@ -5233,27 +5233,29 @@ IonBuilder::jsop_bindname(PropertyName *
     current->push(ins);
 
     return resumeAfter(ins);
 }
 
 bool
 IonBuilder::jsop_getelem()
 {
-    if (oracle->elementReadIsDenseArray(script(), pc))
+    RootedScript script(cx, this->script());
+
+    if (oracle->elementReadIsDenseArray(script, pc))
         return jsop_getelem_dense();
 
     int arrayType = TypedArray::TYPE_MAX;
-    if (oracle->elementReadIsTypedArray(script(), pc, &arrayType))
+    if (oracle->elementReadIsTypedArray(script, pc, &arrayType))
         return jsop_getelem_typed(arrayType);
 
-    if (oracle->elementReadIsString(script(), pc))
+    if (oracle->elementReadIsString(script, pc))
         return jsop_getelem_string();
 
-    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script(), pc);
+    LazyArgumentsType isArguments = oracle->elementReadMagicArguments(script, pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_getelem();
 
     MDefinition *rhs = current->pop();
     MDefinition *lhs = current->pop();
 
@@ -5261,32 +5263,31 @@ IonBuilder::jsop_getelem()
 
     // TI does not account for GETELEM with string indexes, so we have to monitor
     // the result of MGetElementCache if it's expected to access string properties.
     // If the result of MGetElementCache is not monitored, we won't generate any
     // getprop stubs.
     bool mustMonitorResult = false;
     bool cacheable = false;
 
-    oracle->elementReadGeneric(script(), pc, &cacheable, &mustMonitorResult);
+    oracle->elementReadGeneric(script, pc, &cacheable, &mustMonitorResult);
 
     if (cacheable)
         ins = MGetElementCache::New(lhs, rhs, mustMonitorResult);
     else
         ins = MCallGetElement::New(lhs, rhs);
 
     current->add(ins);
     current->push(ins);
 
     if (!resumeAfter(ins))
         return false;
 
-    RootedScript scriptRoot(cx, script());
-    types::StackTypeSet *barrier = oracle->propertyReadBarrier(scriptRoot, pc);
-    types::StackTypeSet *types = oracle->propertyRead(script(), pc);
+    types::StackTypeSet *barrier = oracle->propertyReadBarrier(script, pc);
+    types::StackTypeSet *types = oracle->propertyRead(script, pc);
 
     if (mustMonitorResult)
         monitorResult(ins, barrier, types);
     return pushTypeBarrier(ins, types, barrier);
 }
 
 bool
 IonBuilder::jsop_getelem_dense()
@@ -5500,27 +5501,28 @@ IonBuilder::jsop_getelem_string()
     current->add(result);
     current->push(result);
     return true;
 }
 
 bool
 IonBuilder::jsop_setelem()
 {
-    if (oracle->propertyWriteCanSpecialize(script(), pc)) {
-        RootedScript scriptRoot(cx, script());
-        if (oracle->elementWriteIsDenseArray(scriptRoot, pc))
+    RootedScript script(cx, this->script());
+
+    if (oracle->propertyWriteCanSpecialize(script, pc)) {
+        if (oracle->elementWriteIsDenseArray(script, pc))
             return jsop_setelem_dense();
 
         int arrayType = TypedArray::TYPE_MAX;
-        if (oracle->elementWriteIsTypedArray(script(), pc, &arrayType))
+        if (oracle->elementWriteIsTypedArray(script, pc, &arrayType))
             return jsop_setelem_typed(arrayType);
     }
 
-    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script(), pc);
+    LazyArgumentsType isArguments = oracle->elementWriteMagicArguments(script, pc);
     if (isArguments == MaybeArguments)
         return abort("Type is not definitely lazy arguments.");
     if (isArguments == DefinitelyArguments)
         return jsop_arguments_setelem();
 
     MDefinition *value = current->pop();
     MDefinition *index = current->pop();
     MDefinition *object = current->pop();
@@ -5764,18 +5766,18 @@ GetDefiniteSlot(JSContext *cx, types::St
 {
     if (!types || types->unknownObject() || types->getObjectCount() != 1)
         return NULL;
 
     types::TypeObject *type = types->getTypeObject(0);
     if (!type || type->unknownProperties())
         return NULL;
 
-    jsid id = AtomToId(atom);
-    if (id != types::MakeTypeId(cx, id))
+    RawId id = AtomToId(atom);
+    if (id != types::IdToTypeId(id))
         return NULL;
 
     types::HeapTypeSet *propertyTypes = type->getProperty(cx, id, false);
     if (!propertyTypes ||
         !propertyTypes->definiteProperty() ||
         propertyTypes->isOwnProperty(cx, type, true))
     {
         return NULL;
@@ -5827,18 +5829,17 @@ IonBuilder::TestCommonPropFunc(JSContext
             if (!typeObj)
                 continue;
 
             if (typeObj->unknownProperties())
                 return true;
 
             // If the type has an own property, we can't be sure we don't shadow
             // the chain.
-            jsid typeId = types::MakeTypeId(cx, id);
-            types::HeapTypeSet *propSet = typeObj->getProperty(cx, typeId, false);
+            types::HeapTypeSet *propSet = typeObj->getProperty(cx, types::IdToTypeId(id), false);
             if (!propSet)
                 return false;
             if (propSet->ownProperty(false))
                 return true;
 
             // Check the DOM status of the instance type
             thinkDOM = thinkDOM && !typeObj->hasAnyFlags(types::OBJECT_FLAG_NON_DOM);
 
@@ -5915,18 +5916,17 @@ IonBuilder::TestCommonPropFunc(JSContext
             // marked as having the property as an "own property". This can
             // happen in cases of |delete| having been used, or cases with
             // watched objects. If TI ever decides to be more accurate about
             // |delete| handling, this should go back to curObj->watched().
 
             // Even though we are not directly accessing the properties on the whole
             // prototype chain, we need to fault in the sets anyway, as we need
             // to freeze on them.
-            jsid typeId = types::MakeTypeId(cx, id);
-            types::HeapTypeSet *propSet = typeObj->getProperty(cx, typeId, false);
+            types::HeapTypeSet *propSet = typeObj->getProperty(cx, types::IdToTypeId(id), false);
             if (!propSet)
                 return false;
             if (propSet->ownProperty(false))
                 return true;
 
             curObj = curObj->getProto();
         }
     }
@@ -5973,17 +5973,17 @@ IonBuilder::TestCommonPropFunc(JSContext
             JS_ASSERT(!wasntDOM);
         }
 
         // If we found a Singleton object's own-property, there's nothing to
         // freeze.
         if (obj != foundProto) {
             // Walk the prototype chain. Everyone has to have the property, since we
             // just checked, so propSet cannot be NULL.
-            jsid typeId = types::MakeTypeId(cx, id);
+            RawId typeId = types::IdToTypeId(id);
             while (true) {
                 types::HeapTypeSet *propSet = curType->getProperty(cx, typeId, false);
                 // This assert is now assured, since we have faulted them in
                 // above.
                 JS_ASSERT(propSet);
                 // Asking, freeze by asking.
                 DebugOnly<bool> isOwn = propSet->isOwnProperty(cx, curType, false);
                 JS_ASSERT(!isOwn);
@@ -6003,17 +6003,17 @@ IonBuilder::TestCommonPropFunc(JSContext
     return true;
 }
 
 bool
 IonBuilder::annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
                                     types::StackTypeSet *objTypes, types::StackTypeSet *pushedTypes)
 {
     RootedId id(cx, NameToId(getPropCache->name()));
-    if ((jsid)id != types::MakeTypeId(cx, id))
+    if (id != types::IdToTypeId(id))
         return true;
 
     // Ensure every pushed value is a singleton.
     if (pushedTypes->unknownObject() || pushedTypes->baseFlags() != 0)
         return true;
 
     for (unsigned i = 0; i < pushedTypes->getObjectCount(); i++) {
         if (pushedTypes->getTypeObject(i) != NULL)
@@ -6532,35 +6532,33 @@ IonBuilder::jsop_setprop(HandlePropertyN
     }
 
     oracle->binaryOp(script(), pc);
 
     MSetPropertyInstruction *ins;
     if (monitored) {
         ins = MCallSetProperty::New(obj, value, name, script()->strict);
     } else {
-        UnrootedShape objShape;
-        if ((objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing())) &&
-            !objShape->inDictionary())
-        {
+        RawShape objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing());
+        if (objShape && !objShape->inDictionary()) {
             // The JM IC was monomorphic, so we inline the property access as
             // long as the shape is not in dictionary mode. We cannot be sure
             // that the shape is still a lastProperty, and calling Shape::search
             // on dictionary mode shapes that aren't lastProperty is invalid.
             obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
 
-            UnrootedShape shape = DropUnrooted(objShape)->search(cx, NameToId(name));
+            RootedShape shape(cx, objShape->search(cx, NameToId(name)));
             JS_ASSERT(shape);
 
             spew("Inlining monomorphic SETPROP");
 
-            jsid typeId = types::MakeTypeId(cx, id);
+            RawId typeId = types::IdToTypeId(id);
             bool needsBarrier = oracle->propertyWriteNeedsBarrier(script(), pc, typeId);
 
-            return storeSlot(obj, DropUnrooted(shape), value, needsBarrier);
+            return storeSlot(obj, shape, value, needsBarrier);
         }
 
         spew("SETPROP not monomorphic");
 
         ins = MSetPropertyCache::New(obj, value, name, script()->strict);
 
         if (!binaryTypes.lhsTypes || binaryTypes.lhsTypes->propertyNeedsBarrier(cx, id))
             ins->setNeedsBarrier();
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -226,17 +226,17 @@ TypeInferenceOracle::propertyReadBarrier
 }
 
 bool
 TypeInferenceOracle::propertyReadIdempotent(HandleScript script, jsbytecode *pc, HandleId id)
 {
     if (script->analysis()->getCode(pc).notIdempotent)
         return false;
 
-    if (id != MakeTypeId(cx, id))
+    if (id != IdToTypeId(id))
         return false;
 
     StackTypeSet *types = script->analysis()->poppedTypes(pc, 0);
     if (!types || types->unknownObject())
         return false;
 
     for (unsigned i = 0; i < types->getObjectCount(); i++) {
         if (types->getSingleObject(i))
@@ -278,22 +278,22 @@ TypeInferenceOracle::inObjectIsDenseArra
         return false;
 
     return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY);
 }
 
 bool
 TypeInferenceOracle::inArrayIsPacked(UnrootedScript script, jsbytecode *pc)
 {
-    StackTypeSet *types = script->analysis()->poppedTypes(pc, 0);
+    StackTypeSet *types = DropUnrooted(script)->analysis()->poppedTypes(pc, 0);
     return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
 }
 
 bool
-TypeInferenceOracle::elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc)
+TypeInferenceOracle::elementReadIsDenseArray(RawScript script, jsbytecode *pc)
 {
     // Check whether the object is a dense array and index is int32 or double.
     StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1);
     StackTypeSet *id = script->analysis()->poppedTypes(pc, 0);
 
     JSValueType objType = obj->getKnownTypeTag();
     if (objType != JSVAL_TYPE_OBJECT)
         return false;
@@ -301,21 +301,21 @@ TypeInferenceOracle::elementReadIsDenseA
     JSValueType idType = id->getKnownTypeTag();
     if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
 
     return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY);
 }
 
 bool
-TypeInferenceOracle::elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType)
+TypeInferenceOracle::elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *arrayType)
 {
     // Check whether the object is a typed array and index is int32 or double.
     StackTypeSet *obj = script->analysis()->poppedTypes(pc, 1);
-    StackTypeSet *id = script->analysis()->poppedTypes(pc, 0);
+    StackTypeSet *id = DropUnrooted(script)->analysis()->poppedTypes(pc, 0);
 
     JSValueType objType = obj->getKnownTypeTag();
     if (objType != JSVAL_TYPE_OBJECT)
         return false;
 
     JSValueType idType = id->getKnownTypeTag();
     if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
@@ -367,17 +367,17 @@ TypeInferenceOracle::elementReadIsString
         return false;
 
     return true;
 }
 
 bool
 TypeInferenceOracle::elementReadIsPacked(UnrootedScript script, jsbytecode *pc)
 {
-    StackTypeSet *types = script->analysis()->poppedTypes(pc, 1);
+    StackTypeSet *types = DropUnrooted(script)->analysis()->poppedTypes(pc, 1);
     return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
 }
 
 void
 TypeInferenceOracle::elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult)
 {
     MIRType obj = getMIRType(script->analysis()->poppedTypes(pc, 1));
     MIRType id = getMIRType(script->analysis()->poppedTypes(pc, 0));
@@ -410,57 +410,58 @@ TypeInferenceOracle::elementWriteIsDense
     JSValueType idType = id->getKnownTypeTag();
     if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
 
     return !obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY);
 }
 
 bool
-TypeInferenceOracle::elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType)
+TypeInferenceOracle::elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType)
 {
     // Check whether the object is a dense array and index is int32 or double.
     StackTypeSet *obj = script->analysis()->poppedTypes(pc, 2);
     StackTypeSet *id = script->analysis()->poppedTypes(pc, 1);
 
     JSValueType objType = obj->getKnownTypeTag();
     if (objType != JSVAL_TYPE_OBJECT)
         return false;
 
     JSValueType idType = id->getKnownTypeTag();
     if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
 
+    AssertCanGC();
     if (obj->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY))
         return false;
 
     *arrayType = obj->getTypedArrayType();
     if (*arrayType == TypedArray::TYPE_MAX)
         return false;
 
     return true;
 }
 
 bool
 TypeInferenceOracle::elementWriteIsPacked(UnrootedScript script, jsbytecode *pc)
 {
-    StackTypeSet *types = script->analysis()->poppedTypes(pc, 2);
+    StackTypeSet *types = DropUnrooted(script)->analysis()->poppedTypes(pc, 2);
     return !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY);
 }
 
 bool
 TypeInferenceOracle::setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc)
 {
     return script->analysis()->getCode(pc).arrayWriteHole;
 }
 
 MIRType
 TypeInferenceOracle::elementWrite(UnrootedScript script, jsbytecode *pc)
 {
-    StackTypeSet *objTypes = script->analysis()->poppedTypes(pc, 2);
+    StackTypeSet *objTypes = DropUnrooted(script)->analysis()->poppedTypes(pc, 2);
     MIRType elementType = MIRType_None;
     unsigned count = objTypes->getObjectCount();
 
     for (unsigned i = 0; i < count; i++) {
         if (objTypes->getSingleObject(i))
             return MIRType_None;
 
         if (TypeObject *object = objTypes->getTypeObject(i)) {
@@ -497,28 +498,28 @@ TypeInferenceOracle::canInlineCalls()
 
 bool
 TypeInferenceOracle::propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc)
 {
     return !script->analysis()->getCode(pc).monitoredTypes;
 }
 
 bool
-TypeInferenceOracle::propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id)
+TypeInferenceOracle::propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, RawId id)
 {
-    StackTypeSet *types = script->analysis()->poppedTypes(pc, 1);
+    StackTypeSet *types = DropUnrooted(script)->analysis()->poppedTypes(pc, 1);
     return types->propertyNeedsBarrier(cx, id);
 }
 
 bool
 TypeInferenceOracle::elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc)
 {
     // Return true if SETELEM-like instructions need a write barrier before modifying
     // a property. The object is the third value popped by SETELEM.
-    StackTypeSet *types = script->analysis()->poppedTypes(pc, 2);
+    StackTypeSet *types = DropUnrooted(script)->analysis()->poppedTypes(pc, 2);
     return types->propertyNeedsBarrier(cx, JSID_VOID);
 }
 
 StackTypeSet *
 TypeInferenceOracle::getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc)
 {
     JS_ASSERT(caller == this->script());
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL);
@@ -578,17 +579,17 @@ TypeInferenceOracle::canEnterInlinedFunc
 HeapTypeSet *
 TypeInferenceOracle::globalPropertyWrite(UnrootedScript script, jsbytecode *pc, jsid id,
                                          bool *canSpecialize)
 {
     *canSpecialize = !script->analysis()->getCode(pc).monitoredTypes;
     if (!*canSpecialize)
         return NULL;
 
-    return globalPropertyTypeSet(script, pc, id);
+    return globalPropertyTypeSet(DropUnrooted(script), pc, id);
 }
 
 StackTypeSet *
 TypeInferenceOracle::returnTypeSet(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier)
 {
     if (script->analysis()->getCode(pc).monitoredTypesReturn)
         *barrier = script->analysis()->bytecodeTypes(pc);
     else
@@ -601,17 +602,17 @@ TypeInferenceOracle::aliasedVarBarrier(U
 {
     *barrier = script->analysis()->bytecodeTypes(pc);
     return script->analysis()->pushedTypes(pc, 0);
 }
 
 HeapTypeSet *
 TypeInferenceOracle::globalPropertyTypeSet(UnrootedScript script, jsbytecode *pc, jsid id)
 {
-    TypeObject *type = script->global().getType(cx);
+    TypeObject *type = DropUnrooted(script)->global().getType(cx);
     if (type->unknownProperties())
         return NULL;
 
     return type->getProperty(cx, id, false);
 }
 
 LazyArgumentsType
 TypeInferenceOracle::isArgumentObject(types::StackTypeSet *obj)
--- a/js/src/ion/TypeOracle.h
+++ b/js/src/ion/TypeOracle.h
@@ -76,20 +76,20 @@ class TypeOracle
         return NULL;
     }
     virtual bool inObjectIsDenseArray(HandleScript script, jsbytecode *pc) {
         return false;
     }
     virtual bool inArrayIsPacked(UnrootedScript script, jsbytecode *pc) {
         return false;
     }
-    virtual bool elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc) {
+    virtual bool elementReadIsDenseArray(RawScript script, jsbytecode *pc) {
         return false;
     }
-    virtual bool elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) {
+    virtual bool elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *arrayType) {
         return false;
     }
     virtual bool elementReadIsString(UnrootedScript script, jsbytecode *pc) {
         return false;
     }
     virtual bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc) {
         return false;
     }
@@ -98,26 +98,26 @@ class TypeOracle
         *monitorResult = true;
     }
     virtual bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc) {
         return true;
     }
     virtual bool elementWriteIsDenseArray(HandleScript script, jsbytecode *pc) {
         return false;
     }
-    virtual bool elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType) {
+    virtual bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType) {
         return false;
     }
     virtual bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc) {
         return false;
     }
     virtual bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc) {
         return true;
     }
-    virtual bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id) {
+    virtual bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, RawId id) {
         return true;
     }
     virtual bool elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc) {
         return true;
     }
     virtual MIRType elementWrite(UnrootedScript script, jsbytecode *pc) {
         return MIRType_None;
     }
@@ -226,27 +226,27 @@ class TypeInferenceOracle : public TypeO
     bool propertyReadAccessGetter(UnrootedScript script, jsbytecode *pc);
     types::HeapTypeSet *globalPropertyWrite(UnrootedScript script, jsbytecode *pc, jsid id, bool *canSpecialize);
     types::StackTypeSet *returnTypeSet(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier);
     types::StackTypeSet *getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc);
     types::StackTypeSet *getCallArg(UnrootedScript caller, uint32_t argc, uint32_t arg, jsbytecode *pc);
     types::StackTypeSet *getCallReturn(UnrootedScript caller, jsbytecode *pc);
     bool inObjectIsDenseArray(HandleScript script, jsbytecode *pc);
     bool inArrayIsPacked(UnrootedScript script, jsbytecode *pc);
-    bool elementReadIsDenseArray(UnrootedScript script, jsbytecode *pc);
-    bool elementReadIsTypedArray(UnrootedScript script, jsbytecode *pc, int *atype);
+    bool elementReadIsDenseArray(RawScript script, jsbytecode *pc);
+    bool elementReadIsTypedArray(HandleScript script, jsbytecode *pc, int *atype);
     bool elementReadIsString(UnrootedScript script, jsbytecode *pc);
     bool elementReadIsPacked(UnrootedScript script, jsbytecode *pc);
     void elementReadGeneric(UnrootedScript script, jsbytecode *pc, bool *cacheable, bool *monitorResult);
     bool elementWriteIsDenseArray(HandleScript script, jsbytecode *pc);
-    bool elementWriteIsTypedArray(UnrootedScript script, jsbytecode *pc, int *arrayType);
+    bool elementWriteIsTypedArray(RawScript script, jsbytecode *pc, int *arrayType);
     bool elementWriteIsPacked(UnrootedScript script, jsbytecode *pc);
     bool setElementHasWrittenHoles(UnrootedScript script, jsbytecode *pc);
     bool propertyWriteCanSpecialize(UnrootedScript script, jsbytecode *pc);
-    bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, jsid id);
+    bool propertyWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc, RawId id);
     bool elementWriteNeedsBarrier(UnrootedScript script, jsbytecode *pc);
     MIRType elementWrite(UnrootedScript script, jsbytecode *pc);
     bool arrayPrototypeHasIndexedProperty();
     bool canInlineCalls();
     bool canInlineCall(HandleScript caller, jsbytecode *pc);
     bool canEnterInlinedFunction(JSFunction *callee);
     types::StackTypeSet *aliasedVarBarrier(UnrootedScript script, jsbytecode *pc, types::StackTypeSet **barrier);
 
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -988,17 +988,18 @@ class ScriptAnalysis
         return getCode(offset).typeBarriers;
     }
     types::TypeBarrier *typeBarriers(JSContext *cx, const jsbytecode *pc) {
         return typeBarriers(cx, pc - script_->code);
     }
     void addTypeBarrier(JSContext *cx, const jsbytecode *pc,
                         types::TypeSet *target, types::Type type);
     void addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc,
-                                 types::TypeSet *target, HandleObject singleton, jsid singletonId);
+                                 types::TypeSet *target,
+                                 HandleObject singleton, HandleId singletonId);
 
     /* Remove obsolete type barriers at the given offset. */
     void pruneTypeBarriers(JSContext *cx, uint32_t offset);
 
     /*
      * Remove still-active type barriers at the given offset. If 'all' is set,
      * then all barriers are removed, otherwise only those deemed excessive
      * are removed.
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2527,25 +2527,25 @@ extern JS_PUBLIC_DATA(jsid) JS_DEFAULT_X
 /*
  * 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.
  */
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_VOID(jsid id)
+JSID_IS_VOID(const js::RawId id)
 {
     JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
                  JSID_BITS(id) == JSID_TYPE_VOID);
     return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID);
 }
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_EMPTY(jsid id)
+JSID_IS_EMPTY(const js::RawId id)
 {
     return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
 }
 
 #undef id
 
 #ifdef JS_USE_JSID_STRUCT_TYPES
 extern JS_PUBLIC_DATA(jsid) JSID_VOID;
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -632,17 +632,18 @@ js_ReportErrorVA(JSContext *cx, unsigned
 }
 
 /* |callee| requires a usage string provided by JS_DefineFunctionsWithHelp. */
 void
 js::ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
 {
     const char *usageStr = "usage";
     PropertyName *usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
-    DebugOnly<RawShape> shape = static_cast<RawShape>(callee->nativeLookup(cx, NameToId(usageAtom)));
+    RootedId id(cx, NameToId(usageAtom));
+    DebugOnly<RawShape> shape = static_cast<RawShape>(callee->nativeLookup(cx, id));
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(!shape->writable());
     JS_ASSERT(shape->hasDefaultGetter());
 
     RootedValue usage(cx);
     if (!JS_LookupProperty(cx, callee, "usage", usage.address()))
         return;
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -339,17 +339,17 @@ struct JSCompartment : private JS::shado
     void sweepInitialShapeTable();
 
     /* Set of default 'new' or lazy types in the compartment. */
     js::types::TypeObjectSet     newTypeObjects;
     js::types::TypeObjectSet     lazyTypeObjects;
     void sweepNewTypeObjectTable(js::types::TypeObjectSet &table);
 
     js::types::TypeObject *getNewType(JSContext *cx, js::TaggedProto proto,
-                                      JSFunction *fun = NULL, bool isDOM = false);
+                                      js::UnrootedFunction fun = NULL, bool isDOM = false);
 
     js::types::TypeObject *getLazyType(JSContext *cx, js::Handle<js::TaggedProto> proto);
 
     /*
      * Hash table of all manually call site-cloned functions from within
      * self-hosted code. Cloning according to call site provides extra
      * sensitivity for type specialization and inlining.
      */
--- a/js/src/jsdate.h
+++ b/js/src/jsdate.h
@@ -13,17 +13,17 @@
 
 #include "mozilla/FloatingPoint.h"
 
 #include <math.h>
 
 #include "jstypes.h"
 
 extern "C" {
-struct JSObject;
+class JSObject;
 struct JSContext;
 }
 
 extern JSObject *
 js_InitDateClass(JSContext *cx, js::HandleObject obj);
 
 /*
  * These functions provide a C interface to the date/time object
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -13,17 +13,16 @@
 #include "jspubtd.h"
 #include "jsobj.h"
 #include "jsatom.h"
 #include "jsstr.h"
 
 #include "gc/Barrier.h"
 
 ForwardDeclareJS(Atom);
-ForwardDeclareJS(Script);
 
 namespace js { class FunctionExtended; }
 
 class JSFunction : public JSObject
 {
   public:
     enum Flags {
         INTERPRETED      = 0x0001,  /* function has a JSScript and environment. */
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -37,16 +37,17 @@
 # include "assembler/assembler/MacroAssembler.h"
 #endif
 
 #include "jsatominlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
+
 #include "vm/Stack-inl.h"
 
 #ifdef JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #ifdef __SUNPRO_CC
 #include <alloca.h>
@@ -80,17 +81,17 @@ id_constructor(JSContext *cx) {
 
 static inline jsid
 id_caller(JSContext *cx) {
     return NameToId(cx->names().caller);
 }
 
 #ifdef DEBUG
 const char *
-types::TypeIdStringImpl(jsid id)
+types::TypeIdStringImpl(RawId id)
 {
     if (JSID_IS_VOID(id))
         return "(index)";
     if (JSID_IS_EMPTY(id))
         return "(new)";
     static char bufs[4][100];
     static unsigned which = 0;
     which = (which + 1) & 3;
@@ -248,17 +249,17 @@ types::InferSpew(SpewChannel channel, co
 bool
 types::TypeHasProperty(JSContext *cx, TypeObject *obj, jsid id, const Value &value)
 {
     /*
      * Check the correctness of the type information in the object's property
      * against an actual value.
      */
     if (cx->typeInferenceEnabled() && !obj->unknownProperties() && !value.isUndefined()) {
-        id = MakeTypeId(cx, id);
+        id = IdToTypeId(id);
 
         /* Watch for properties which inference does not monitor. */
         if (id == id___proto__(cx) || id == id_constructor(cx) || id == id_caller(cx))
             return true;
 
         /*
          * If we called in here while resolving a type constraint, we may be in the
          * middle of resolving a standard class and the type sets will not be updated
@@ -271,17 +272,17 @@ types::TypeHasProperty(JSContext *cx, Ty
 
         AutoEnterAnalysis enter(cx);
 
         /*
          * We don't track types for properties inherited from prototypes which
          * haven't yet been accessed during analysis of the inheriting object.
          * Don't do the property instantiation now.
          */
-        TypeSet *types = obj->maybeGetProperty(cx, id);
+        TypeSet *types = obj->maybeGetProperty(id, cx);
         if (!types)
             return true;
 
         /*
          * If the types inherited from prototypes are not being propagated into
          * this set (because we haven't analyzed code which accesses the
          * property), skip.
          */
@@ -320,16 +321,18 @@ types::TypeFailure(JSContext *cx, const 
 
 /////////////////////////////////////////////////////////////////////
 // TypeSet
 /////////////////////////////////////////////////////////////////////
 
 inline void
 TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
 {
+    AssertCanGC();
+
     /*
      * Build all types in the set into a vector before triggering the
      * constraint, as doing so may modify this type set.
      */
     Vector<Type> types(cx);
 
     /* If any type is possible, there's no need to worry about specifics. */
     if (flags & TYPE_FLAG_UNKNOWN) {
@@ -536,57 +539,57 @@ class TypeConstraintProp : public TypeCo
     jsbytecode *pc;
 
     /*
      * If assign is true, the target is used to update a property of the object.
      * If assign is false, the target is assigned the value of the property.
      */
     StackTypeSet *target;
 
-    /* Property being accessed. */
-    jsid id;
-
-    TypeConstraintProp(UnrootedScript script, jsbytecode *pc, StackTypeSet *target, jsid id)
+    /* Property being accessed. This is unrooted. */
+    RawId id;
+
+    TypeConstraintProp(UnrootedScript script, jsbytecode *pc, StackTypeSet *target, RawId id)
         : script_(script), pc(pc), target(target), id(id)
     {
         JS_ASSERT(script && pc && target);
     }
 
     const char *kind() { return "prop"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
 };
 
 typedef TypeConstraintProp<PROPERTY_WRITE> TypeConstraintSetProperty;
 typedef TypeConstraintProp<PROPERTY_READ>  TypeConstraintGetProperty;
 typedef TypeConstraintProp<PROPERTY_READ_EXISTING> TypeConstraintGetPropertyExisting;
 
 void
 StackTypeSet::addGetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                             StackTypeSet *target, jsid id)
+                             StackTypeSet *target, RawId id)
 {
     /*
      * GetProperty constraints are normally used with property read input type
      * sets, except for array_pop/array_shift special casing.
      */
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE);
 
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintGetProperty>(script, pc, target, id));
 }
 
 void
 StackTypeSet::addSetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                             StackTypeSet *target, jsid id)
+                             StackTypeSet *target, RawId id)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintSetProperty>(script, pc, target, id));
 }
 
 void
 HeapTypeSet::addGetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                            StackTypeSet *target, jsid id)
+                            StackTypeSet *target, RawId id)
 {
     JS_ASSERT(!target->purged());
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintGetProperty>(script, pc, target, id));
 }
 
 /*
  * Constraints for updating the 'this' types of callees on CALLPROP/CALLELEM.
  * These are derived from the types on the properties themselves, rather than
@@ -807,22 +810,23 @@ class TypeConstraintFilterPrimitive : pu
 void
 HeapTypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target)
 {
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFilterPrimitive>(target));
 }
 
 /* If id is a normal slotful 'own' property of an object, get its shape. */
 static inline UnrootedShape
-GetSingletonShape(JSContext *cx, RawObject obj, RawId id)
+GetSingletonShape(JSContext *cx, RawObject obj, RawId idArg)
 {
     AssertCanGC();
     if (!obj->isNative())
         return UnrootedShape(NULL);
-    UnrootedShape shape = DropUnrooted(obj)->nativeLookup(cx, DropUnrooted(id));
+    RootedId id(cx, idArg);
+    UnrootedShape shape = DropUnrooted(obj)->nativeLookup(cx, id);
     if (shape && shape->hasDefaultGetter() && shape->hasSlot())
         return shape;
     return UnrootedShape(NULL);
 }
 
 void
 ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32_t offset)
 {
@@ -1022,21 +1026,21 @@ MarkPropertyAccessUnknown(JSContext *cx,
 }
 
 /*
  * Get a value for reading id from obj or its prototypes according to the
  * current VM state, returning the unknown type on failure or an undefined
  * property.
  */
 static inline Type
-GetSingletonPropertyType(JSContext *cx, RawObject rawObjArg, jsid id)
+GetSingletonPropertyType(JSContext *cx, RawObject rawObjArg, HandleId id)
 {
     RootedObject obj(cx, rawObjArg);    // Root this locally because it's assigned to.
 
-    JS_ASSERT(id == MakeTypeId(cx, id));
+    JS_ASSERT(id == IdToTypeId(id));
 
     if (JSID_IS_VOID(id))
         return Type::UnknownType();
 
     if (obj->isTypedArray()) {
         if (id == id_length(cx))
             return Type::Int32Type();
         obj = obj->getProto();
@@ -1061,18 +1065,20 @@ GetSingletonPropertyType(JSContext *cx, 
 
 /*
  * Handle a property access on a specific object. All property accesses go through
  * here, whether via x.f, x[f], or global name accesses.
  */
 template <PropertyAccessKind access>
 static inline void
 PropertyAccess(JSContext *cx, HandleScript script, jsbytecode *pc, TypeObject *object,
-               StackTypeSet *target, jsid id)
-{
+               StackTypeSet *target, RawId idArg)
+{
+    RootedId id(cx, idArg);
+
     /* Reads from objects with unknown properties are unknown, writes to such objects are ignored. */
     if (object->unknownProperties()) {
         if (access != PROPERTY_WRITE)
             MarkPropertyAccessUnknown(cx, script, pc, target);
         return;
     }
 
     /*
@@ -1808,17 +1814,17 @@ static inline void
 ObjectStateChange(JSContext *cx, TypeObject *object, bool markingUnknown, bool force)
 {
     AutoAssertNoGC nogc;
 
     if (object->unknownProperties())
         return;
 
     /* All constraints listening to state changes are on the empty id. */
-    TypeSet *types = object->maybeGetProperty(cx, JSID_EMPTY);
+    TypeSet *types = object->maybeGetProperty(JSID_EMPTY, cx);
 
     /* Mark as unknown after getting the types, to avoid assertion. */
     if (markingUnknown)
         object->flags |= OBJECT_FLAG_DYNAMIC_MASK | OBJECT_FLAG_UNKNOWN_PROPERTIES;
 
     if (types) {
         TypeConstraint *constraint = types->constraintList;
         while (constraint) {
@@ -1868,31 +1874,32 @@ class TypeConstraintFreezeOwnProperty : 
         if (source->ownProperty(configurable)) {
             updated = true;
             cx->compartment->types.addPendingRecompile(cx, info);
         }
     }
 };
 
 static void
-CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun);
+CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, HandleFunction fun);
 
 bool
 HeapTypeSet::isOwnProperty(JSContext *cx, TypeObject *object, bool configurable)
 {
     /*
      * Everywhere compiled code depends on definite properties associated with
      * a type object's newScript, we need to make sure there are constraints
      * in place which will mark those properties as configured should the
      * definite properties be invalidated.
      */
     if (object->flags & OBJECT_FLAG_NEW_SCRIPT_REGENERATE) {
         if (object->newScript) {
             Rooted<TypeObject*> typeObj(cx, object);
-            CheckNewScriptProperties(cx, typeObj, object->newScript->fun);
+            RootedFunction fun(cx, object->newScript->fun);
+            CheckNewScriptProperties(cx, typeObj, fun);
         } else {
             JS_ASSERT(object->flags & OBJECT_FLAG_NEW_SCRIPT_CLEARED);
             object->flags &= ~OBJECT_FLAG_NEW_SCRIPT_REGENERATE;
         }
     }
 
     if (ownProperty(configurable))
         return true;
@@ -2045,41 +2052,44 @@ HeapTypeSet::getSingleton(JSContext *cx)
         addFreeze(cx);
 
     return obj;
 }
 
 bool
 HeapTypeSet::needsBarrier(JSContext *cx)
 {
+    AssertCanGC();
+
     bool result = unknownObject()
                || getObjectCount() > 0
                || hasAnyFlag(TYPE_FLAG_STRING);
     if (!result)
         addFreeze(cx);
     return result;
 }
 
 bool
-StackTypeSet::propertyNeedsBarrier(JSContext *cx, jsid id)
-{
-    id = MakeTypeId(cx, id);
+StackTypeSet::propertyNeedsBarrier(JSContext *cx, RawId id)
+{
+    AssertCanGC();
+    RootedId typeId(cx, IdToTypeId(id));
 
     if (unknownObject())
         return true;
 
     for (unsigned i = 0; i < getObjectCount(); i++) {
         if (getSingleObject(i))
             return true;
 
         if (types::TypeObject *otype = getTypeObject(i)) {
             if (otype->unknownProperties())
                 return true;
 
-            if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(cx, id)) {
+            if (types::HeapTypeSet *propTypes = otype->maybeGetProperty(typeId, cx)) {
                 if (propTypes->needsBarrier(cx))
                     return true;
             }
         }
     }
 
     return false;
 }
@@ -2093,17 +2103,17 @@ enum RecompileKind {
 /*
  * Whether all jitcode for a given pc was compiled with monitoring or barriers.
  * If we reanalyze the script after generating jitcode, new monitoring and
  * barriers will be added which may be duplicating information available when
  * the script was originally compiled, and which should not invalidate that
  * compilation.
  */
 static inline bool
-JITCodeHasCheck(HandleScript script, jsbytecode *pc, RecompileKind kind)
+JITCodeHasCheck(UnrootedScript script, jsbytecode *pc, RecompileKind kind)
 {
     if (kind == RECOMPILE_NONE)
         return false;
 
 #ifdef JS_METHODJIT
     for (int constructing = 0; constructing <= 1; constructing++) {
         for (int barriers = 0; barriers <= 1; barriers++) {
             mjit::JITScript *jit = script->getJIT((bool) constructing, (bool) barriers);
@@ -2135,17 +2145,17 @@ JITCodeHasCheck(HandleScript script, jsb
     return true;
 }
 
 /*
  * Force recompilation of any jitcode for script at pc, or of any other script
  * which this script was inlined into.
  */
 static inline void
-AddPendingRecompile(JSContext *cx, HandleScript script, jsbytecode *pc,
+AddPendingRecompile(JSContext *cx, UnrootedScript script, jsbytecode *pc,
                     RecompileKind kind = RECOMPILE_NONE)
 {
     /*
      * Trigger recompilation of the script itself, if code was not previously
      * compiled with the specified information.
      */
     if (!JITCodeHasCheck(script, pc, kind))
         cx->compartment->types.addPendingRecompile(cx, script, pc);
@@ -2412,21 +2422,21 @@ TypeCompartment::addAllocationSiteTypeOb
     if (!allocationSiteTable->add(p, key, res)) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return NULL;
     }
 
     return res;
 }
 
-static inline jsid
+static inline RawId
 GetAtomId(JSContext *cx, UnrootedScript script, const jsbytecode *pc, unsigned offset)
 {
     PropertyName *name = script->getName(GET_UINT32_INDEX(pc + offset));
-    return MakeTypeId(cx, NameToId(name));
+    return IdToTypeId(NameToId(name));
 }
 
 bool
 types::UseNewType(JSContext *cx, UnrootedScript script, jsbytecode *pc)
 {
     JS_ASSERT(cx->typeInferenceEnabled());
 
     /*
@@ -2675,17 +2685,17 @@ TypeCompartment::addPendingRecompile(JSC
         cx->compartment->types.setPendingNukeTypes(cx);
         return;
     }
 
     co->setPendingRecompilation();
 }
 
 void
-TypeCompartment::addPendingRecompile(JSContext *cx, HandleScript script, jsbytecode *pc)
+TypeCompartment::addPendingRecompile(JSContext *cx, UnrootedScript script, jsbytecode *pc)
 {
     AutoAssertNoGC nogc;
     JS_ASSERT(script);
     if (!constrainedOutputs)
         return;
 
 #ifdef JS_METHODJIT
     for (int constructing = 0; constructing <= 1; constructing++) {
@@ -2888,19 +2898,19 @@ ScriptAnalysis::addTypeBarrier(JSContext
     }
 
     barrier->next = code.typeBarriers;
     code.typeBarriers = barrier;
 }
 
 void
 ScriptAnalysis::addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc, TypeSet *target,
-                                        HandleObject singleton, jsid singletonId)
-{
-    JS_ASSERT(singletonId == MakeTypeId(cx, singletonId) && !JSID_IS_VOID(singletonId));
+                                        HandleObject singleton, HandleId singletonId)
+{
+    JS_ASSERT(singletonId == IdToTypeId(singletonId) && !JSID_IS_VOID(singletonId));
 
     Bytecode &code = getCode(pc);
 
     if (!code.typeBarriers) {
         /* Trigger recompilation as for normal type barriers. */
         RootedScript script(cx, script_);
         AddPendingRecompile(cx, script, const_cast<jsbytecode*>(pc), RECOMPILE_CHECK_BARRIERS);
     }
@@ -3169,20 +3179,18 @@ TypeCompartment::fixObjectType(JSContext
             if (ntype != types[i]) {
                 if (NumberTypes(ntype, types[i])) {
                     if (types[i].isPrimitive(JSVAL_TYPE_INT32)) {
                         types[i] = Type::DoubleType();
                         RootedShape shape(cx, baseShape);
                         while (!shape->isEmptyShape()) {
                             if (shape->slot() == i) {
                                 Type type = Type::DoubleType();
-                                if (!p->value.object->unknownProperties()) {
-                                    jsid id = MakeTypeId(cx, shape->propid());
-                                    p->value.object->addPropertyType(cx, id, type);
-                                }
+                                if (!p->value.object->unknownProperties())
+                                    p->value.object->addPropertyType(cx, IdToTypeId(shape->propid()), type);
                                 break;
                             }
                             shape = shape->previous();
                         }
                     }
                 } else {
                     return;
                 }
@@ -3210,20 +3218,18 @@ TypeCompartment::fixObjectType(JSContext
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
 
         RootedShape shape(cx, baseShape);
         while (!shape->isEmptyShape()) {
             ids[shape->slot()] = shape->propid();
             types[shape->slot()] = GetValueTypeForTable(cx, obj->getSlot(shape->slot()));
-            if (!objType->unknownProperties()) {
-                jsid id = MakeTypeId(cx, shape->propid());
-                objType->addPropertyType(cx, id, types[shape->slot()]);
-            }
+            if (!objType->unknownProperties())
+                objType->addPropertyType(cx, IdToTypeId(shape->propid()), types[shape->slot()]);
             shape = shape->previous();
         }
 
         ObjectTableKey key;
         key.ids = ids;
         key.nslots = obj->slotSpan();
         key.nfixed = obj->numFixedSlots();
         key.proto = obj->getTaggedProto();
@@ -3273,17 +3279,18 @@ TypeObject::getFromPrototypes(JSContext 
         return;
 
     protoTypes->addSubset(cx, types);
 
     proto->getType(cx)->getFromPrototypes(cx, id, protoTypes);
 }
 
 static inline void
-UpdatePropertyType(JSContext *cx, TypeSet *types, RawObject obj, UnrootedShape shape, bool force)
+UpdatePropertyType(JSContext *cx, TypeSet *types, UnrootedObject obj, UnrootedShape shape,
+                   bool force)
 {
     types->setOwnProperty(cx, false);
     if (!shape->writable())
         types->setOwnProperty(cx, true);
 
     if (shape->hasGetterValue() || shape->hasSetterValue()) {
         types->setOwnProperty(cx, true);
         types->addType(cx, Type::UnknownType());
@@ -3297,17 +3304,17 @@ UpdatePropertyType(JSContext *cx, TypeSe
         if (force || !value.isUndefined()) {
             Type type = GetValueType(cx, value);
             types->addType(cx, type);
         }
     }
 }
 
 bool
-TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
+TypeObject::addProperty(JSContext *cx, RawId id, Property **pprop)
 {
     JS_ASSERT(!*pprop);
     Property *base = cx->typeLifoAlloc().new_<Property>(id);
     if (!base) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return false;
     }
 
@@ -3319,32 +3326,33 @@ TypeObject::addProperty(JSContext *cx, j
          * or jitcode.
          */
 
         RootedObject rSingleton(cx, singleton);
         if (JSID_IS_VOID(id)) {
             /* Go through all shapes on the object to get integer-valued properties. */
             UnrootedShape shape = singleton->lastProperty();
             while (!shape->isEmptyShape()) {
-                if (JSID_IS_VOID(MakeTypeId(cx, shape->propid())))
+                if (JSID_IS_VOID(IdToTypeId(shape->propid())))
                     UpdatePropertyType(cx, &base->types, rSingleton, shape, true);
                 shape = shape->previous();
             }
 
             /* Also get values of any dense elements in the object. */
             for (size_t i = 0; i < singleton->getDenseInitializedLength(); i++) {
                 const Value &value = singleton->getDenseElement(i);
                 if (!value.isMagic(JS_ELEMENTS_HOLE)) {
                     Type type = GetValueType(cx, value);
                     base->types.setOwnProperty(cx, false);
                     base->types.addType(cx, type);
                 }
             }
         } else if (!JSID_IS_EMPTY(id)) {
-            UnrootedShape shape = singleton->nativeLookup(cx, id);
+            RootedId rootedId(cx, id);
+            UnrootedShape shape = singleton->nativeLookup(cx, rootedId);
             if (shape)
                 UpdatePropertyType(cx, &base->types, rSingleton, shape, false);
         }
 
         if (singleton->watched()) {
             /*
              * Mark the property as configured, to inhibit optimizations on it
              * and avoid bypassing the watchpoint handler.
@@ -3368,17 +3376,17 @@ TypeObject::addDefiniteProperties(JSCont
     if (unknownProperties())
         return true;
 
     /* Mark all properties of obj as definite properties of this type. */
     AutoEnterAnalysis enter(cx);
 
     RootedShape shape(cx, obj->lastProperty());
     while (!shape->isEmptyShape()) {
-        jsid id = MakeTypeId(cx, shape->propid());
+        RawId id = IdToTypeId(shape->propid());
         if (!JSID_IS_VOID(id) && obj->isFixedSlot(shape->slot()) &&
             shape->slot() <= (TYPE_FLAG_DEFINITE_MASK >> TYPE_FLAG_DEFINITE_SHIFT)) {
             TypeSet *types = getProperty(cx, id, true);
             if (!types)
                 return false;
             types->setDefinite(shape->slot());
         }
         shape = shape->previous();
@@ -3414,17 +3422,17 @@ TypeObject::matchDefiniteProperties(Hand
 
     return true;
 }
 
 inline void
 InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type)
 {
     AssertCanGC();
-    JS_ASSERT(id == MakeTypeId(cx, id));
+    JS_ASSERT(id == IdToTypeId(id));
 
     AutoEnterAnalysis enter(cx);
 
     TypeSet *types = obj->getProperty(cx, id, true);
     if (!types || types->hasType(type))
         return;
 
     InferSpew(ISpewOps, "externalType: property %s %s: %s",
@@ -3443,17 +3451,17 @@ TypeObject::addPropertyType(JSContext *c
 {
     InlineAddTypeProperty(cx, this, id, GetValueType(cx, value));
 }
 
 void
 TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
 {
     AssertCanGC();
-    jsid id = JSID_VOID;
+    RawId id = JSID_VOID;
     if (name) {
         JSAtom *atom = Atomize(cx, name, strlen(name));
         if (!atom) {
             AutoEnterAnalysis enter(cx);
             cx->compartment->types.setPendingNukeTypes(cx);
             return;
         }
         id = AtomToId(atom);
@@ -3467,33 +3475,33 @@ TypeObject::addPropertyType(JSContext *c
     addPropertyType(cx, name, GetValueType(cx, value));
 }
 
 void
 TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
 {
     AutoEnterAnalysis enter(cx);
 
-    id = MakeTypeId(cx, id);
+    id = IdToTypeId(id);
 
     TypeSet *types = getProperty(cx, id, true);
     if (types)
         types->setOwnProperty(cx, true);
 }
 
 void
 TypeObject::markStateChange(JSContext *cx)
 {
     AutoAssertNoGC nogc;
 
     if (unknownProperties())
         return;
 
     AutoEnterAnalysis enter(cx);
-    TypeSet *types = maybeGetProperty(cx, JSID_EMPTY);
+    TypeSet *types = maybeGetProperty(JSID_EMPTY, cx);
     if (types) {
         TypeConstraint *constraint = types->constraintList;
         while (constraint) {
             constraint->newObjectState(cx, this, true);
             constraint = constraint->next;
         }
     }
 }
@@ -3945,17 +3953,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         poppedTypes(pc, pickedDepth)->addSubset(cx, &pushed[pickedDepth]);
         for (unsigned i = 0; i < pickedDepth; i++)
             poppedTypes(pc, i)->addSubset(cx, &pushed[pickedDepth - 1 - i]);
         break;
       }
 
       case JSOP_GETGNAME:
       case JSOP_CALLGNAME: {
-        jsid id = GetAtomId(cx, script, pc, 0);
+        RawId id = GetAtomId(cx, script, pc, 0);
 
         StackTypeSet *seen = bytecodeTypes(pc);
         seen->addSubset(cx, &pushed[0]);
 
         /*
          * Normally we rely on lazy standard class initialization to fill in
          * the types of global properties the script can access. In a few cases
          * the method JIT will bypass this, and we need to add the types
@@ -4725,21 +4733,21 @@ class TypeConstraintClearDefiniteSingle 
 
         if (source->baseFlags() || source->getObjectCount() > 1)
             object->clearNewScript(cx);
     }
 };
 
 static bool
 AnalyzePoppedThis(JSContext *cx, Vector<SSAUseChain *> *pendingPoppedThis,
-                  TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj,
+                  TypeObject *type, HandleFunction fun, MutableHandleObject pbaseobj,
                   Vector<TypeNewScript::Initializer> *initializerList);
 
 static bool
-AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun,
+AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, HandleFunction fun,
                            MutableHandleObject pbaseobj,
                            Vector<TypeNewScript::Initializer> *initializerList)
 {
     AssertCanGC();
 
     /*
      * When invoking 'new' on the specified script, try to find some properties
      * which will definitely be added to the created object before it has a
@@ -4888,17 +4896,17 @@ AnalyzeNewScriptProperties(JSContext *cx
     }
 
     /* Will have hit a STOP or similar, unless the script always throws. */
     return entirelyAnalyzed;
 }
 
 static bool
 AnalyzePoppedThis(JSContext *cx, Vector<SSAUseChain *> *pendingPoppedThis,
-                  TypeObject *type, JSFunction *fun, MutableHandleObject pbaseobj,
+                  TypeObject *type, HandleFunction fun, MutableHandleObject pbaseobj,
                   Vector<TypeNewScript::Initializer> *initializerList)
 {
     RootedScript script(cx, fun->nonLazyScript());
     ScriptAnalysis *analysis = script->analysis();
 
     while (!pendingPoppedThis->empty()) {
         SSAUseChain *uses = pendingPoppedThis->back();
         pendingPoppedThis->popBack();
@@ -4908,17 +4916,17 @@ AnalyzePoppedThis(JSContext *cx, Vector<
 
         if (op == JSOP_SETPROP && uses->u.which == 1) {
             /*
              * Don't use GetAtomId here, we need to watch for SETPROP on
              * integer properties and bail out. We can't mark the aggregate
              * JSID_VOID type property as being in a definite slot.
              */
             RootedId id(cx, NameToId(script->getName(GET_UINT32_INDEX(pc))));
-            if (MakeTypeId(cx, id) != id)
+            if (IdToTypeId(id) != id)
                 return false;
             if (id_prototype(cx) == id || id___proto__(cx) == id || id_constructor(cx) == id)
                 return false;
 
             /*
              * Ensure that if the properties named here could have a setter or
              * a permanent property in any transitive prototype, the definite
              * properties get cleared from the shape.
@@ -4992,17 +5000,17 @@ AnalyzePoppedThis(JSContext *cx, Vector<
              */
             analysis->breakTypeBarriersSSA(cx, analysis->poppedValue(calleepc, 0));
             analysis->breakTypeBarriers(cx, calleepc - script->code, true);
 
             StackTypeSet *funcallTypes = analysis->poppedTypes(pc, GET_ARGC(pc) + 1);
             StackTypeSet *scriptTypes = analysis->poppedTypes(pc, GET_ARGC(pc));
 
             /* Need to definitely be calling Function.call on a specific script. */
-            JSFunction *function;
+            RootedFunction function(cx);
             {
                 RawObject funcallObj = funcallTypes->getSingleton();
                 RawObject scriptObj = scriptTypes->getSingleton();
                 if (!funcallObj || !scriptObj || !scriptObj->isFunction() ||
                     !scriptObj->toFunction()->isInterpreted()) {
                     return false;
                 }
                 function = scriptObj->toFunction();
@@ -5050,17 +5058,17 @@ AnalyzePoppedThis(JSContext *cx, Vector<
 }
 
 /*
  * Either make the newScript information for type when it is constructed
  * by the specified script, or regenerate the constraints for an existing
  * newScript on the type after they were cleared by a GC.
  */
 static void
-CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun)
+CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, HandleFunction fun)
 {
     if (type->unknownProperties())
         return;
 
     /* Strawman object to add properties to and watch for duplicates. */
     RootedObject baseobj(cx, NewBuiltinClassInstance(cx, &ObjectClass, gc::FINALIZE_OBJECT16));
     if (!baseobj) {
         if (type->newScript)
@@ -5937,19 +5945,18 @@ JSObject::setNewTypeUnknown(JSContext *c
         if (TypeObjectSet::Ptr p = table.lookup(obj.get()))
             MarkTypeObjectUnknownProperties(cx, *p);
     }
 
     return true;
 }
 
 TypeObject *
-JSCompartment::getNewType(JSContext *cx, TaggedProto proto_, JSFunction *fun_, bool isDOM)
-{
-    AssertCanGC();
+JSCompartment::getNewType(JSContext *cx, TaggedProto proto_, UnrootedFunction fun_, bool isDOM)
+{
     JS_ASSERT_IF(fun_, proto_.isObject());
     JS_ASSERT_IF(proto_.isObject(), cx->compartment == proto_.toObject()->compartment());
 
     if (!newTypeObjects.initialized() && !newTypeObjects.init())
         return NULL;
 
     TypeObjectSet::AddPtr p = newTypeObjects.lookupForAdd(proto_);
     if (p) {
@@ -5970,29 +5977,28 @@ JSCompartment::getNewType(JSContext *cx,
             type->clearNewScript(cx);
 
         if (!isDOM && !type->hasAnyFlags(OBJECT_FLAG_NON_DOM))
             type->setFlags(cx, OBJECT_FLAG_NON_DOM);
 
         return type;
     }
 
-    RootedFunction fun(cx, fun_);
     Rooted<TaggedProto> proto(cx, proto_);
-
+    RootedFunction fun(cx, DropUnrooted(fun_));
+    AssertCanGC();
     if (proto.isObject() && !proto.toObject()->setDelegate(cx))
         return NULL;
 
     bool markUnknown =
         proto.isObject()
         ? proto.toObject()->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN)
         : true;
 
-    RootedTypeObject type(cx);
-    type = types.newTypeObject(cx, JSProto_Object, proto, markUnknown, isDOM);
+    RootedTypeObject type(cx, types.newTypeObject(cx, JSProto_Object, proto, markUnknown, isDOM));
     if (!type)
         return NULL;
 
     if (!newTypeObjects.relookupOrAdd(p, proto, type.get()))
         return NULL;
 
     if (!cx->typeInferenceEnabled())
         return type;
@@ -6000,17 +6006,17 @@ JSCompartment::getNewType(JSContext *cx,
     AutoEnterAnalysis enter(cx);
 
     /*
      * Set the special equality flag for types whose prototype also has the
      * flag set. This is a hack, :XXX: need a real correspondence between
      * types and the possible js::Class of objects with that type.
      */
     if (proto.isObject()) {
-        JSObject *obj = proto.toObject();
+        RootedObject obj(cx, proto.toObject());
 
         if (obj->hasSpecialEquality())
             type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
 
         if (fun)
             CheckNewScriptProperties(cx, type, fun);
 
 #if JS_HAS_XML_SUPPORT
@@ -6042,19 +6048,19 @@ JSCompartment::getNewType(JSContext *cx,
      */
     if (type->unknownProperties())
         type->flags |= OBJECT_FLAG_SETS_MARKED_UNKNOWN;
 
     return type;
 }
 
 TypeObject *
-JSObject::getNewType(JSContext *cx, JSFunction *fun_, bool isDOM)
-{
-    return cx->compartment->getNewType(cx, this, fun_, isDOM);
+JSObject::getNewType(JSContext *cx, RawFunction fun, bool isDOM)
+{
+    return cx->compartment->getNewType(cx, this, fun, isDOM);
 }
 
 TypeObject *
 JSCompartment::getLazyType(JSContext *cx, Handle<TaggedProto> proto)
 {
     JS_ASSERT(cx->compartment == this);
     JS_ASSERT_IF(proto.isObject(), cx->compartment == proto.toObject()->compartment());
 
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -541,19 +541,19 @@ class StackTypeSet : public TypeSet
      * another structure.
      */
     static StackTypeSet *make(JSContext *cx, const char *name);
 
     /* Constraints for type inference. */
 
     void addSubset(JSContext *cx, TypeSet *target);
     void addGetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                        StackTypeSet *target, jsid id);
+                        StackTypeSet *target, RawId id);
     void addSetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                        StackTypeSet *target, jsid id);
+                        StackTypeSet *target, RawId id);
     void addSetElement(JSContext *cx, HandleScript script, jsbytecode *pc,
                        StackTypeSet *objectTypes, StackTypeSet *valueTypes);
     void addCall(JSContext *cx, TypeCallsite *site);
     void addArith(JSContext *cx, HandleScript script, jsbytecode *pc,
                   TypeSet *target, TypeSet *other = NULL);
     void addTransformThis(JSContext *cx, HandleScript script, TypeSet *target);
     void addPropagateThis(JSContext *cx, HandleScript script, jsbytecode *pc,
                           Type type, StackTypeSet *types = NULL);
@@ -597,17 +597,17 @@ class StackTypeSet : public TypeSet
      * TypedArray::TYPE_MAX if the set contains different array types.
      */
     int getTypedArrayType();
 
     /* Get the single value which can appear in this type set, otherwise NULL. */
     RawObject getSingleton();
 
     /* Whether any objects in the type set needs a barrier on id. */
-    bool propertyNeedsBarrier(JSContext *cx, jsid id);
+    bool propertyNeedsBarrier(JSContext *cx, RawId id);
 
     /*
      * Whether this set contains all types in other, except (possibly) the
      * specified type.
      */
     bool filtersType(const StackTypeSet *other, Type type) const;
 
     /*
@@ -636,17 +636,17 @@ class StackTypeSet : public TypeSet
 class HeapTypeSet : public TypeSet
 {
   public:
 
     /* Constraints for type inference. */
 
     void addSubset(JSContext *cx, TypeSet *target);
     void addGetProperty(JSContext *cx, HandleScript script, jsbytecode *pc,
-                        StackTypeSet *target, jsid id);
+                        StackTypeSet *target, RawId id);
     void addCallProperty(JSContext *cx, HandleScript script, jsbytecode *pc, jsid id);
     void addFilterPrimitives(JSContext *cx, TypeSet *target);
     void addSubsetBarrier(JSContext *cx, HandleScript script, jsbytecode *pc, TypeSet *target);
 
     /* Constraints for JIT compilation. */
 
     /* Completely freeze the contents of this type set. */
     void addFreeze(JSContext *cx);
@@ -815,17 +815,17 @@ struct Property
     HeapId id;
 
     /* Possible types for this property, including types inherited from prototypes. */
     HeapTypeSet types;
 
     inline Property(jsid id);
     inline Property(const Property &o);
 
-    static uint32_t keyBits(jsid id) { return uint32_t(JSID_BITS(id)); }
+    static uint32_t keyBits(RawId id) { return uint32_t(JSID_BITS(id)); }
     static jsid getKey(Property *p) { return p->id; }
 };
 
 /*
  * Information attached to a TypeObject if it is always constructed using 'new'
  * on a particular script. This is used to manage state related to the definite
  * properties on the type object: these definite properties depend on type
  * information which could change as the script executes (e.g. a scripted
@@ -1004,36 +1004,36 @@ struct TypeObject : gc::Cell
     }
 
     /*
      * Get or create a property of this object. Only call this for properties which
      * a script accesses explicitly. 'assign' indicates whether this is for an
      * assignment, and the own types of the property will be used instead of
      * aggregate types.
      */
-    inline HeapTypeSet *getProperty(JSContext *cx, jsid id, bool own);
+    inline HeapTypeSet *getProperty(JSContext *cx, RawId id, bool own);
 
     /* Get a property only if it already exists. */
-    inline HeapTypeSet *maybeGetProperty(JSContext *cx, jsid id);
+    inline HeapTypeSet *maybeGetProperty(RawId id, JSContext *cx);
 
     inline unsigned getPropertyCount();
     inline Property *getProperty(unsigned i);
 
     /* Set flags on this object which are implied by the specified key. */
     inline void setFlagsFromKey(JSContext *cx, JSProtoKey kind);
 
     /*
      * Get the global object which all objects of this type are parented to,
      * or NULL if there is none known.
      */
     //inline JSObject *getGlobal();
 
     /* Helpers */
 
-    bool addProperty(JSContext *cx, jsid id, Property **pprop);
+    bool addProperty(JSContext *cx, RawId id, Property **pprop);
     bool addDefiniteProperties(JSContext *cx, HandleObject obj);
     bool matchDefiniteProperties(HandleObject obj);
     void addPrototype(JSContext *cx, TypeObject *proto);
     void addPropertyType(JSContext *cx, jsid id, Type type);
     void addPropertyType(JSContext *cx, jsid id, const Value &value);
     void addPropertyType(JSContext *cx, const char *name, Type type);
     void addPropertyType(JSContext *cx, const char *name, const Value &value);
     void markPropertyConfigured(JSContext *cx, jsid id);
@@ -1393,17 +1393,17 @@ struct TypeCompartment
     void processPendingRecompiles(FreeOp *fop);
 
     /* Mark all types as needing destruction once inference has 'finished'. */
     void setPendingNukeTypes(JSContext *cx);
     void setPendingNukeTypesNoReport();
 
     /* Mark a script as needing recompilation once inference has finished. */
     void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
-    void addPendingRecompile(JSContext *cx, HandleScript script, jsbytecode *pc);
+    void addPendingRecompile(JSContext *cx, UnrootedScript script, jsbytecode *pc);
 
     /* Monitor future effects on a bytecode. */
     void monitorBytecode(JSContext *cx, HandleScript script, uint32_t offset,
                          bool returnOnly = false);
 
     /* Mark any type set containing obj as having a generic object type. */
     void markSetsUnknown(JSContext *cx, TypeObject *obj);
 
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -267,18 +267,18 @@ TypeFlagPrimitive(TypeFlags flags)
     }
 }
 
 /*
  * Get the canonical representation of an id to use when doing inference.  This
  * maintains the constraint that if two different jsids map to the same property
  * in JS (e.g. 3 and "3"), they have the same type representation.
  */
-inline jsid
-MakeTypeId(JSContext *cx, jsid id)
+inline RawId
+IdToTypeId(RawId id)
 {
     AutoAssertNoGC nogc;
     JS_ASSERT(!JSID_IS_EMPTY(id));
 
     /*
      * All integers must map to the aggregate property for index types, including
      * negative integers.
      */
@@ -304,17 +304,17 @@ MakeTypeId(JSContext *cx, jsid id)
 
     return JSID_VOID;
 }
 
 const char * TypeIdStringImpl(jsid id);
 
 /* Convert an id for printing during debug. */
 static inline const char *
-TypeIdString(jsid id)
+TypeIdString(RawId id)
 {
 #ifdef DEBUG
     return TypeIdStringImpl(id);
 #else
     return "(missing)";
 #endif
 }
 
@@ -547,46 +547,46 @@ TypeMonitorCall(JSContext *cx, const js:
                 TypeMonitorCallSlow(cx, callee, args, constructing);
         }
     }
 
     return true;
 }
 
 inline bool
-TrackPropertyTypes(JSContext *cx, HandleObject obj, jsid id)
+TrackPropertyTypes(JSContext *cx, UnrootedObject obj, RawId id)
 {
     AutoAssertNoGC nogc;
 
     if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties())
         return false;
 
-    if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(cx, id))
+    if (obj->hasSingletonType() && !obj->type()->maybeGetProperty(id, cx))
         return false;
 
     return true;
 }
 
 /* Add a possible type for a property of obj. */
 inline void
-AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, Type type)
+AddTypePropertyId(JSContext *cx, HandleObject obj, RawId id, Type type)
 {
     AssertCanGC();
     if (cx->typeInferenceEnabled())
-        id = MakeTypeId(cx, id);
+        id = IdToTypeId(id);
     if (TrackPropertyTypes(cx, obj, id))
         obj->type()->addPropertyType(cx, id, type);
 }
 
 inline void
-AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, const Value &value)
+AddTypePropertyId(JSContext *cx, HandleObject obj, RawId id, const Value &value)
 {
     AssertCanGC();
     if (cx->typeInferenceEnabled())
-        id = MakeTypeId(cx, id);
+        id = IdToTypeId(id);
     if (TrackPropertyTypes(cx, obj, id))
         obj->type()->addPropertyType(cx, id, value);
 }
 
 inline void
 AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, Type type)
 {
     AssertCanGC();
@@ -628,20 +628,20 @@ MarkTypeObjectUnknownProperties(JSContex
     }
 }
 
 /*
  * Mark any property which has been deleted or configured to be non-writable or
  * have a getter/setter.
  */
 inline void
-MarkTypePropertyConfigured(JSContext *cx, HandleObject obj, jsid id)
+MarkTypePropertyConfigured(JSContext *cx, HandleObject obj, RawId id)
 {
     if (cx->typeInferenceEnabled())
-        id = MakeTypeId(cx, id);
+        id = IdToTypeId(id);
     if (TrackPropertyTypes(cx, obj, id))
         obj->type()->markPropertyConfigured(cx, id);
 }
 
 /* Mark a state change on a particular object. */
 inline void
 MarkObjectStateChange(JSContext *cx, RawObject obj)
 {
@@ -1530,21 +1530,23 @@ inline void
 TypeObject::setBasePropertyCount(uint32_t count)
 {
     JS_ASSERT(count <= OBJECT_FLAG_PROPERTY_COUNT_LIMIT);
     flags = (flags & ~OBJECT_FLAG_PROPERTY_COUNT_MASK)
           | (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
 }
 
 inline HeapTypeSet *
-TypeObject::getProperty(JSContext *cx, jsid id, bool own)
+TypeObject::getProperty(JSContext *cx, RawId id, bool own)
 {
     JS_ASSERT(cx->compartment->activeAnalysis);
+    AssertCanGC();
+
     JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
-    JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == MakeTypeId(cx, id));
+    JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
     JS_ASSERT(!unknownProperties());
 
     uint32_t propertyCount = basePropertyCount();
     Property **pprop = HashSetInsert<jsid,Property,Property>
                            (cx->compartment->typeLifoAlloc, propertySet, propertyCount, id);
     if (!pprop) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return NULL;
@@ -1552,16 +1554,17 @@ TypeObject::getProperty(JSContext *cx, j
 
     if (!*pprop) {
         setBasePropertyCount(propertyCount);
         if (!addProperty(cx, id, pprop)) {
             setBasePropertyCount(0);
             propertySet = NULL;
             return NULL;
         }
+        AutoAssertNoGC nogc;
         if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
             markUnknown(cx);
 
             /*
              * Return an arbitrary property in the object, as all have unknown
              * type and are treated as configured.
              */
             unsigned count = getPropertyCount();
@@ -1578,24 +1581,24 @@ TypeObject::getProperty(JSContext *cx, j
     HeapTypeSet *types = &(*pprop)->types;
     if (own)
         types->setOwnProperty(cx, false);
 
     return types;
 }
 
 inline HeapTypeSet *
-TypeObject::maybeGetProperty(JSContext *cx, jsid id)
+TypeObject::maybeGetProperty(RawId id, JSContext *cx)
 {
     AutoAssertNoGC nogc;
     JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
-    JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == MakeTypeId(cx, id));
+    JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id));
     JS_ASSERT(!unknownProperties());
 
-    Property *prop = HashSetLookup<jsid,Property,Property>
+    Property *prop = HashSetLookup<RawId,Property,Property>
         (propertySet, basePropertyCount(), id);
 
     return prop ? &prop->types : NULL;
 }
 
 inline unsigned
 TypeObject::getPropertyCount()
 {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4024,17 +4024,18 @@ baseops::SetElementAttributes(JSContext 
     RootedShape shape(cx);
     if (!baseops::LookupElement(cx, obj, index, &nobj, &shape))
         return false;
     if (!shape)
         return true;
     if (nobj->isNative() && IsImplicitDenseElement(shape)) {
         if (!JSObject::sparsifyDenseElement(cx, obj, index))
             return false;
-        shape = obj->nativeLookup(cx, INT_TO_JSID(index));
+        RawId id = INT_TO_JSID(index);
+        shape = obj->nativeLookup(cx, HandleId::fromMarkedLocation(&id)); // not a gcthing
     }
     return nobj->isNative()
            ? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
            : JSObject::setElementAttributes(cx, nobj, index, attrsp);
 }
 
 JSBool
 baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue rval, JSBool strict)
@@ -4106,17 +4107,17 @@ JSBool
 baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
                        MutableHandleValue rval, JSBool strict)
 {
     Rooted<jsid> id(cx, SPECIALID_TO_JSID(sid));
     return baseops::DeleteGeneric(cx, obj, id, rval, strict);
 }
 
 bool
-js::HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp)
+js::HasDataProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp)
 {
     if (JSID_IS_INT(id) && obj->containsDenseElement(JSID_TO_INT(id))) {
         *vp = obj->getDenseElement(JSID_TO_INT(id));
         return true;
     }
 
     if (UnrootedShape shape = obj->nativeLookup(cx, id)) {
         if (shape->hasDefaultGetter() && shape->hasSlot()) {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -266,17 +266,17 @@ class WithObject;
  *
  * Implementation of the underlying structure occurs in ObjectImpl, from which
  * this struct inherits.  This inheritance is currently public, but it will
  * eventually be made protected.  For full details, see vm/ObjectImpl.{h,cpp}.
  *
  * The JSFunction struct is an extension of this struct allocated from a larger
  * GC size-class.
  */
-struct JSObject : public js::ObjectImpl
+class JSObject : public js::ObjectImpl
 {
   private:
     friend class js::Shape;
     friend struct js::GCMarker;
     friend class  js::NewObjectCache;
 
     /* Make the type object to use for LAZY_TYPE objects. */
     js::types::TypeObject *makeLazyType(JSContext *cx);
@@ -1337,22 +1337,23 @@ GetMethod(JSContext *cx, HandleObject ob
     return GetMethod(cx, obj, id, getHow, vp);
 }
 
 /*
  * If obj has an already-resolved data property for id, return true and
  * store the property value in *vp.
  */
 extern bool
-HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp);
+HasDataProperty(JSContext *cx, HandleObject obj, HandleId id, Value *vp);
 
 inline bool
 HasDataProperty(JSContext *cx, HandleObject obj, PropertyName *name, Value *vp)
 {
-    return HasDataProperty(cx, obj, NameToId(name), vp);
+    RootedId id(cx, NameToId(name));
+    return HasDataProperty(cx, obj, id, vp);
 }
 
 extern JSBool
 CheckAccess(JSContext *cx, JSObject *obj, HandleId id, JSAccessMode mode,
             MutableHandleValue v, unsigned *attrsp);
 
 extern bool
 IsDelegate(JSContext *cx, HandleObject obj, const Value &v, bool *result);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -184,17 +184,17 @@ JSObject::getProperty(JSContext *cx, js:
     js::RootedId id(cx, js::NameToId(name));
     return getGeneric(cx, obj, receiver, id, vp);
 }
 
 /* static */ inline bool
 JSObject::deleteProperty(JSContext *cx, js::HandleObject obj,
                          js::HandlePropertyName name, js::MutableHandleValue rval, bool strict)
 {
-    jsid id = js::NameToId(name);
+    js::RootedId id(cx, js::NameToId(name));
     js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, obj, id);
     js::DeletePropertyOp op = obj->getOps()->deleteProperty;
     return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, rval, strict);
 }
 
 /* static */ inline bool
 JSObject::deleteElement(JSContext *cx, js::HandleObject obj,
@@ -208,17 +208,17 @@ JSObject::deleteElement(JSContext *cx, j
     js::DeleteElementOp op = obj->getOps()->deleteElement;
     return (op ? op : js::baseops::DeleteElement)(cx, obj, index, rval, strict);
 }
 
 /* static */ inline bool
 JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj,
                         js::HandleSpecialId sid, js::MutableHandleValue rval, bool strict)
 {
-    jsid id = SPECIALID_TO_JSID(sid);
+    js::RootedId id(cx, SPECIALID_TO_JSID(sid));
     js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
     js::types::MarkTypePropertyConfigured(cx, obj, id);
     js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
     return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, rval, strict);
 }
 
 inline void
 JSObject::finalize(js::FreeOp *fop)
@@ -1688,17 +1688,17 @@ PreallocateObjectDynamicSlots(JSContext 
 inline bool
 DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
                               JSProtoKey key, JSObject *ctor, JSObject *proto)
 {
     JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
     JS_ASSERT(ctor);
     JS_ASSERT(proto);
 
-    jsid id = NameToId(ClassName(key, cx));
+    RootedId id(cx, NameToId(ClassName(key, cx)));
     JS_ASSERT(!global->nativeLookupNoAllocation(id));
 
     /* Set these first in case AddTypePropertyId looks for this class. */
     global->setSlot(key, ObjectValue(*ctor));
     global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
     global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
 
     types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -169,39 +169,40 @@ typedef struct JSCompartment            
 typedef struct JSConstDoubleSpec            JSConstDoubleSpec;
 typedef struct JSContext                    JSContext;
 typedef struct JSCrossCompartmentCall       JSCrossCompartmentCall;
 typedef struct JSErrorReport                JSErrorReport;
 typedef struct JSExceptionState             JSExceptionState;
 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 JSStructuredCloneCallbacks   JSStructuredCloneCallbacks;
 typedef struct JSStructuredCloneReader      JSStructuredCloneReader;
 typedef struct JSStructuredCloneWriter      JSStructuredCloneWriter;
 typedef struct JSTracer                     JSTracer;
 
 #ifdef __cplusplus
 class                                       JSFlatString;
 class                                       JSFunction;
+class                                       JSObject;
 class                                       JSScript;
 class                                       JSStableString;  // long story
 class                                       JSString;
 #else
 typedef struct JSFlatString                 JSFlatString;
 typedef struct JSFunction                   JSFunction;
+typedef struct JSObject                     JSObject;
 typedef struct JSScript                     JSScript;
 typedef struct JSString                     JSString;
 #endif /* !__cplusplus */
 
 #ifdef JS_THREADSAFE
 typedef struct PRCallOnceType    JSCallOnceType;
 #else
 typedef JSBool                   JSCallOnceType;
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -86,17 +86,17 @@
  * trees are more space-efficient than alternatives.  This was removed in bug
  * 631138; see that bug for the full details.
  *
  * Because many Shapes have similar data, there is actually a secondary type
  * called a BaseShape that holds some of a Shape's data.  Many shapes can share
  * a single BaseShape.
  */
 
-struct JSObject;
+class JSObject;
 
 namespace js {
 
 class Bindings;
 
 /* Limit on the number of slotful properties in an object. */
 static const uint32_t SHAPE_INVALID_SLOT = JS_BIT(24) - 1;
 static const uint32_t SHAPE_MAXIMUM_SLOT = JS_BIT(24) - 2;
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2012,17 +2012,18 @@ FindReplaceLength(JSContext *cx, RegExpS
             atom = &str->asAtom();
         } else {
             atom = AtomizeString(cx, str);
             if (!atom)
                 return false;
         }
 
         Value v;
-        if (HasDataProperty(cx, base, AtomToId(atom), &v) && v.isString()) {
+        RootedId id(cx, AtomToId(atom));
+        if (HasDataProperty(cx, base, id, &v) && v.isString()) {
             rdata.repstr = v.toString()->ensureLinear(cx);
             if (!rdata.repstr)
                 return false;
             *sizep = rdata.repstr->length();
             return true;
         }
 
         /*
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -5171,17 +5171,18 @@ mjit::Compiler::jsop_getprop(HandlePrope
 
             return true;
         }
     }
 
     /* Check if this is a property access we can make a loop invariant entry for. */
     if (loop && loop->generatingInvariants() && !hasTypeBarriers(PC)) {
         CrossSSAValue topv(a->inlineIndex, analysis->poppedValue(PC, 0));
-        if (FrameEntry *fe = loop->invariantProperty(topv, NameToId(name))) {
+        RootedId id(cx, NameToId(name));
+        if (FrameEntry *fe = loop->invariantProperty(topv, id)) {
             if (knownType != JSVAL_TYPE_UNKNOWN && knownType != JSVAL_TYPE_DOUBLE)
                 frame.learnType(fe, knownType, false);
             frame.pop();
             frame.pushCopyOf(fe);
             if (script_->hasScriptCounts)
                 bumpPropCount(PC, PCCounts::PROP_STATIC);
             return true;
         }
@@ -5195,23 +5196,24 @@ mjit::Compiler::jsop_getprop(HandlePrope
 
     frame.forgetMismatchedObject(top);
 
     /*
      * Check if we are accessing a known type which always has the property
      * in a particular inline slot. Get the property directly in this case,
      * without using an IC.
      */
-    jsid id = NameToId(name);
+    RootedId id(cx, NameToId(name));
     types::TypeSet *types = frame.extra(top).types;
     if (types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties() &&
-        id == types::MakeTypeId(cx, id)) {
+        id == types::IdToTypeId(id))
+    {
         JS_ASSERT(!forPrototype);
         types::TypeObject *object = types->getTypeObject(0);
         types::HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
         if (!propertyTypes)
             return false;
         if (propertyTypes->definiteProperty() &&
             !propertyTypes->isOwnProperty(cx, object, true)) {
             uint32_t slot = propertyTypes->definiteSlot();
@@ -5476,17 +5478,17 @@ mjit::Compiler::jsop_getprop_dispatch(Ha
      * the object being accessed. Return true if the CALLPROP has been fully
      * processed, false if no code was generated.
      */
     FrameEntry *top = frame.peek(-1);
     if (top->isNotType(JSVAL_TYPE_OBJECT))
         return false;
 
     RootedId id(cx, NameToId(name));
-    if (id.get() != types::MakeTypeId(cx, id))
+    if (id.get() != types::IdToTypeId(id))
         return false;
 
     types::TypeSet *pushedTypes = pushedTypeSet(0);
     if (pushedTypes->unknownObject() || pushedTypes->baseFlags() != 0)
         return false;
 
     /* Check every pushed value is a singleton. */
     for (unsigned i = 0; i < pushedTypes->getObjectCount(); i++) {
@@ -5624,19 +5626,19 @@ mjit::Compiler::jsop_setprop(HandlePrope
         jsop_setprop_slow(name);
         return true;
     }
 
     /*
      * Set the property directly if we are accessing a known object which
      * always has the property in a particular inline slot.
      */
-    jsid id = NameToId(name);
+    RootedId id(cx, NameToId(name));
     types::StackTypeSet *types = frame.extra(lhs).types;
-    if (JSOp(*PC) == JSOP_SETPROP && id == types::MakeTypeId(cx, id) &&
+    if (JSOp(*PC) == JSOP_SETPROP && id == types::IdToTypeId(id) &&
         types && !types->unknownObject() &&
         types->getObjectCount() == 1 &&
         types->getTypeObject(0) != NULL &&
         !types->getTypeObject(0)->unknownProperties())
     {
         types::TypeObject *object = types->getTypeObject(0);
         types::HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
         if (!propertyTypes)
@@ -6493,30 +6495,31 @@ mjit::Compiler::jsop_getgname(uint32_t i
     if (obj && !hasTypeBarriers(PC)) {
         Rooted<jsid> id(cx, NameToId(name));
         if (testSingletonProperty(globalObj, id)) {
             frame.push(ObjectValue(*obj));
             return true;
         }
     }
 
-    jsid id = NameToId(name);
+    RootedId id(cx, NameToId(name));
     JSValueType type = knownPushedType(0);
-    if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
+    if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::IdToTypeId(id) &&
         !globalObj->getType(cx)->unknownProperties()) {
         types::HeapTypeSet *propertyTypes = globalObj->getType(cx)->getProperty(cx, id, false);
         if (!propertyTypes)
             return false;
 
         /*
          * If we are accessing a defined global which is a normal data property
          * then bake its address into the jitcode and guard against future
          * reallocation of the global object's slots.
          */
-        UnrootedShape shape = globalObj->nativeLookup(cx, NameToId(name));
+        RootedId id(cx, NameToId(name));
+        UnrootedShape shape = globalObj->nativeLookup(cx, id);
         if (shape && shape->hasDefaultGetter() && shape->hasSlot()) {
             HeapSlot *value = &globalObj->getSlotRef(DropUnrooted(shape)->slot());
             if (!value->isUndefined() &&
                 !propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
                 watchGlobalReallocation();
                 RegisterID reg = frame.allocReg();
                 masm.move(ImmPtr(value), reg);
 
@@ -6620,32 +6623,34 @@ mjit::Compiler::jsop_setgname(HandleProp
         if (script_ == outerScript)
             monitoredBytecodes.append(PC - script_->code);
 
         /* Global accesses are monitored only for a few names like __proto__. */
         jsop_setgname_slow(name);
         return true;
     }
 
-    jsid id = NameToId(name);
-    if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
+    RootedId id(cx, NameToId(name));
+    if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::IdToTypeId(id) &&
         !globalObj->getType(cx)->unknownProperties()) {
         /*
          * Note: object branding is disabled when inference is enabled. With
          * branding there is no way to ensure that a non-function property
          * can't get a function later and cause the global object to become
          * branded, requiring a shape change if it changes again.
          */
         types::HeapTypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
         if (!types)
             return false;
-        UnrootedShape shape = globalObj->nativeLookup(cx, NameToId(name));
+        RootedId id(cx, NameToId(name));
+        RootedShape shape(cx, globalObj->nativeLookup(cx, id));
         if (shape && shape->hasDefaultSetter() &&
             shape->writable() && shape->hasSlot() &&
-            !types->isOwnProperty(cx, globalObj->getType(cx), true)) {
+            !types->isOwnProperty(cx, globalObj->getType(cx), true))
+        {
             watchGlobalReallocation();
             HeapSlot *value = &globalObj->getSlotRef(shape->slot());
             RegisterID reg = frame.allocReg();
 #ifdef JSGC_INCREMENTAL_MJ
             /* Write barrier. */
             if (cx->compartment->compileBarriers() && types->needsBarrier(cx)) {
                 stubcc.linkExit(masm.jump(), Uses(0));
                 stubcc.leave();
@@ -7388,17 +7393,17 @@ mjit::Compiler::constructThis()
         if (!cx->typeInferenceEnabled() ||
             !fun->hasSingletonType() ||
             fun->getType(cx)->unknownProperties())
         {
             break;
         }
 
         Rooted<jsid> id(cx, NameToId(cx->names().classPrototype));
-        types::HeapTypeSet *protoTypes = fun->getType(cx)->getProperty(cx, id, false);
+        types::HeapTypeSet *protoTypes = fun->getType(cx)->getProperty(cx, HandleId(id), false);
 
         JSObject *proto = protoTypes->getSingleton(cx);
         if (!proto)
             break;
 
         /*
          * Generate an inline path to create a 'this' object with the given
          * prototype. Only do this if the type is actually known as a possible
--- a/js/src/methodjit/LoopState.cpp
+++ b/js/src/methodjit/LoopState.cpp
@@ -837,17 +837,17 @@ LoopState::invariantLength(const CrossSS
     entry.u.array.arraySlot = objSlot;
     entry.u.array.temporary = which;
     invariantEntries.append(entry);
 
     return fe;
 }
 
 FrameEntry *
-LoopState::invariantProperty(const CrossSSAValue &obj, jsid id)
+LoopState::invariantProperty(const CrossSSAValue &obj, RawId id)
 {
     if (skipAnalysis)
         return NULL;
 
     if (id == NameToId(cx->names().length))
         return NULL;
 
     uint32_t objSlot;
@@ -867,17 +867,17 @@ LoopState::invariantProperty(const Cross
     if (!loopInvariantEntry(objSlot))
         return NULL;
 
     /* Check that the property is definite and not written anywhere in the loop. */
     TypeSet *objTypes = ssa->getValueTypes(obj);
     if (objTypes->unknownObject() || objTypes->getObjectCount() != 1)
         return NULL;
     TypeObject *object = objTypes->getTypeObject(0);
-    if (!object || object->unknownProperties() || hasModifiedProperty(object, id) || id != MakeTypeId(cx, id))
+    if (!object || object->unknownProperties() || hasModifiedProperty(object, id) || id != IdToTypeId(id))
         return NULL;
     HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
     if (!propertyTypes)
         return NULL;
     if (!propertyTypes->definiteProperty() || propertyTypes->isOwnProperty(cx, object, true))
         return NULL;
 
     uint32_t which = frame.allocTemporary();
@@ -1584,17 +1584,17 @@ LoopState::analyzeLoopBody(unsigned fram
 
             if (constrainedLoop && !definiteArrayAccess(objValue, elemValue))
                 constrainedLoop = false;
             break;
           }
 
           case JSOP_SETPROP: {
             PropertyName *name = script->getName(GET_UINT32_INDEX(pc));
-            jsid id = MakeTypeId(cx, NameToId(name));
+            RawId id = IdToTypeId(NameToId(name));
 
             TypeSet *objTypes = analysis->poppedTypes(pc, 1);
             if (objTypes->unknownObject()) {
                 unknownModset = true;
                 break;
             }
 
             for (unsigned i = 0; i < objTypes->getObjectCount(); i++) {
@@ -1738,17 +1738,17 @@ LoopState::hasGrowArray(TypeObject *obje
     return false;
 }
 
 bool
 LoopState::hasModifiedProperty(TypeObject *object, jsid id)
 {
     if (unknownModset)
         return true;
-    id = MakeTypeId(cx, id);
+    id = IdToTypeId(id);
     for (unsigned i = 0; i < modifiedProperties.length(); i++) {
         if (modifiedProperties[i].object == object && modifiedProperties[i].id == id)
             return true;
     }
     return false;
 }
 
 uint32_t
--- a/js/src/methodjit/LoopState.h
+++ b/js/src/methodjit/LoopState.h
@@ -264,17 +264,17 @@ class LoopState : public MacroAssemblerT
                                const analyze::CrossSSAValue &index);
     FrameEntry *invariantArraySlots(const analyze::CrossSSAValue &obj);
 
     /* Methods for accesses on lazy arguments. */
     bool hoistArgsLengthCheck(const analyze::CrossSSAValue &index);
     FrameEntry *invariantArguments();
 
     FrameEntry *invariantLength(const analyze::CrossSSAValue &obj);
-    FrameEntry *invariantProperty(const analyze::CrossSSAValue &obj, jsid id);
+    FrameEntry *invariantProperty(const analyze::CrossSSAValue &obj, RawId id);
 
     /* Whether a binary or inc/dec op's result cannot overflow. */
     bool cannotIntegerOverflow(const analyze::CrossSSAValue &pushed);
 
     /*
      * Whether integer overflow in addition or negative zeros in multiplication
      * at a binary op can be safely ignored.
      */
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -65,17 +65,18 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlo
 
     RootedObject obj(f.cx, &f.fp()->global());
     PropertyName *name = f.script()->getName(GET_UINT32_INDEX(f.pc()));
 
     RecompilationMonitor monitor(f.cx);
 
     uint32_t slot;
     {
-        RootedShape shape(f.cx, obj->nativeLookup(f.cx, NameToId(name)));
+        RootedId id(f.cx, NameToId(name));
+        RootedShape shape(f.cx, obj->nativeLookup(f.cx, id));
 
         if (monitor.recompiled()) {
             stubs::Name(f);
             return;
         }
 
         if (!shape ||
             !shape->hasDefaultGetter() ||
@@ -161,17 +162,18 @@ ic::SetGlobalName(VMFrame &f, ic::SetGlo
     AssertCanGC();
 
     RootedObject obj(f.cx, &f.fp()->global());
     RootedPropertyName name(f.cx, f.script()->getName(GET_UINT32_INDEX(f.pc())));
 
     RecompilationMonitor monitor(f.cx);
 
     {
-        UnrootedShape shape = obj->nativeLookup(f.cx, NameToId(name));
+        RootedId id(f.cx, NameToId(name));
+        UnrootedShape shape = obj->nativeLookup(f.cx, id);
 
         if (!monitor.recompiled()) {
             LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
             if (status == Lookup_Error)
                 THROW();
         }
     }
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -403,25 +403,25 @@ class SetPropCompiler : public PICStubCo
         return Lookup_Cacheable;
     }
 
     bool updateMonitoredTypes()
     {
         JS_ASSERT(pic.typeMonitored);
 
         RecompilationMonitor monitor(cx);
-        jsid id = NameToId(name);
 
         types::TypeObject *type = obj->getType(cx);
         if (monitor.recompiled())
             return false;
 
         if (!type->unknownProperties()) {
             types::AutoEnterAnalysis enter(cx);
-            types::TypeSet *types = type->getProperty(cx, types::MakeTypeId(cx, id), true);
+            RootedId id(cx, NameToId(name));
+            types::TypeSet *types = type->getProperty(cx, types::IdToTypeId(id), true);
             if (!types)
                 return false;
 
             jsbytecode *pc;
             RootedScript script(cx, cx->stack.currentScript(&pc));
 
             if (!JSScript::ensureRanInference(cx, script) || monitor.recompiled())
                 return false;
--- a/js/src/vm/ObjectImpl-inl.h
+++ b/js/src/vm/ObjectImpl-inl.h
@@ -38,17 +38,18 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlo
 #endif
 }
 
 } // namespace js
 
 inline js::UnrootedShape
 js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
 {
-    return nativeLookup(cx, pid.asId());
+    RootedId id(cx, pid.asId());
+    return nativeLookup(cx, id);
 }
 
 inline js::UnrootedShape
 js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
 {
     return nativeLookup(cx, PropertyId(name));
 }
 
@@ -74,17 +75,18 @@ inline bool
 js::ObjectImpl::nativeContains(JSContext *cx, JS::Handle<PropertyName*> name)
 {
     return nativeLookup(cx, name) != NULL;
 }
 
 inline bool
 js::ObjectImpl::nativeContains(JSContext *cx, JS::Handle<Shape*> shape)
 {
-    return nativeLookup(cx, shape->propid()) == shape;
+    RootedId id(cx, shape->propid());
+    return nativeLookup(cx, id) == shape;
 }
 
 inline bool
 js::ObjectImpl::nativeContainsNoAllocation(jsid id)
 {
     return nativeLookupNoAllocation(id) != NULL;
 }
 
--- a/js/src/vm/ObjectImpl.cpp
+++ b/js/src/vm/ObjectImpl.cpp
@@ -259,22 +259,21 @@ js::ObjectImpl::slotInRange(uint32_t slo
 /*
  * Work around a compiler bug in MSVC9 and above, where inlining this function
  * causes stack pointer offsets to go awry and spp to refer to something higher
  * up the stack.
  */
 MOZ_NEVER_INLINE
 #endif
 UnrootedShape
-js::ObjectImpl::nativeLookup(JSContext *cx, jsid idArg)
+js::ObjectImpl::nativeLookup(JSContext *cx, HandleId id)
 {
     AssertCanGC();
     MOZ_ASSERT(isNative());
     Shape **spp;
-    RootedId id(cx, idArg);
     return Shape::search(cx, lastProperty(), id, &spp);
 }
 
 UnrootedShape
 js::ObjectImpl::nativeLookupNoAllocation(jsid id)
 {
     MOZ_ASSERT(isNative());
     return Shape::searchNoAllocation(lastProperty(), id);
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -1200,17 +1200,17 @@ class ObjectImpl : public gc::Cell
      */
     bool hasLazyType() const { return type_->lazy(); }
 
     inline uint32_t slotSpan() const;
 
     /* Compute dynamicSlotsCount() for this object. */
     inline uint32_t numDynamicSlots() const;
 
-    UnrootedShape nativeLookup(JSContext *cx, jsid id);
+    UnrootedShape nativeLookup(JSContext *cx, HandleId id);
     inline UnrootedShape nativeLookup(JSContext *cx, PropertyId pid);
     inline UnrootedShape nativeLookup(JSContext *cx, PropertyName *name);
 
     UnrootedShape nativeLookupNoAllocation(jsid id);
     inline UnrootedShape nativeLookupNoAllocation(PropertyId pid);
     inline UnrootedShape nativeLookupNoAllocation(PropertyName *name);
 
     inline bool nativeContains(JSContext *cx, Handle<jsid> id);
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -835,17 +835,17 @@ class StaticStrings
  *     jsids, JSID_EMPTY, JSID_VOID, E4X's default XML namespace, and maybe in
  *     the future Harmony-proposed private names).
  */
 class PropertyName : public JSAtom
 {};
 
 JS_STATIC_ASSERT(sizeof(PropertyName) == sizeof(JSString));
 
-static JS_ALWAYS_INLINE jsid
+static JS_ALWAYS_INLINE RawId
 NameToId(PropertyName *name)
 {
     return NON_INTEGER_ATOM_TO_JSID(name);
 }
 
 typedef HeapPtr<JSAtom> HeapPtrAtom;
 
 class AutoNameVector : public AutoVectorRooter<PropertyName *>
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -428,17 +428,17 @@ XRE_API(MessageLoop*,
 
 struct JSContext;
 class JSString;
 
 XRE_API(bool,
         XRE_SendTestShellCommand, (JSContext* aCx,
                                    JSString* aCommand,
                                    void* aCallback))
-struct JSObject;
+class JSObject;
 
 XRE_API(bool,
         XRE_GetChildGlobalObject, (JSContext* aCx,
                                    JSObject** globalp))
 
 XRE_API(bool,
         XRE_ShutdownTestShell, ())