merge m-c to fx-team
authorRob Campbell <rcampbell@mozilla.com>
Tue, 25 Oct 2011 11:07:28 -0300
changeset 79920 5be6d907fa3b609cf8f2561e40e89c34b35cc3db
parent 79919 e60d3779a3b83c67a748244fd925a0269a13d612 (current diff)
parent 79820 0b03882d8edfcea1475f3b1f9c3b5fa7a167217d (diff)
child 79921 2a901edc04a942a2bee08680f3a5cc9697ad2029
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
merge m-c to fx-team
js/src/jscpucfg.cpp
layout/reftests/css-gradients/linear-keywords-ref.html
layout/reftests/css-gradients/linear-keywords.html
layout/reftests/css-gradients/linear-ref.html
layout/reftests/css-gradients/linear.html
security/nss/lib/ssl/sslerrstrs.h
security/nss/lib/ssl/sslutil.h
toolkit/crashreporter/nsExceptionHandler.cpp
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -72,17 +72,17 @@ pref("extensions.blocklist.url", "https:
 pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
 pref("extensions.blocklist.itemURL", "https://addons.mozilla.org/%LOCALE%/%APP%/blocked/%blockID%");
 
 pref("extensions.update.autoUpdateDefault", true);
 
 // Disable add-ons installed into the shared user and shared system areas by
 // default. This does not include the application directory. See the SCOPE
 // constants in AddonManager.jsm for values to use here
-pref("extensions.autoDisableScopes", 10);
+pref("extensions.autoDisableScopes", 15);
 
 // Dictionary download preference
 pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/dictionaries/");
 
 // The minimum delay in seconds for the timer to fire.
 // default=2 minutes
 pref("app.update.timerMinimumDelay", 120);
 
--- a/browser/components/migration/src/nsIEProfileMigrator.h
+++ b/browser/components/migration/src/nsIEProfileMigrator.h
@@ -38,17 +38,17 @@
 /* Private header describing the class to migrate preferences from
    Windows Trident to Gecko. This is a virtual class. */
 
 #ifndef ieprofilemigrator___h___
 #define ieprofilemigrator___h___
 
 #include <time.h>
 #include <windows.h>
-#include <pstore.h>
+#include <ole2.h>
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIObserverService.h"
 #include "nsTArray.h"
 #include "nsINavHistoryService.h"
 
 class nsIFile;
 class nsICookieManager2;
 class nsIRDFResource;
@@ -56,16 +56,89 @@ class nsINavBookmarksService;
 class nsIPrefBranch;
 
 struct SignonData {
   PRUnichar* user;
   PRUnichar* pass;
   char*      realm;
 };
 
+// VC11 doesn't ship with pstore.h, so we go ahead and define the stuff that
+// we need from that file here.
+class IEnumPStoreItems : public IUnknown {
+public:
+  virtual HRESULT STDMETHODCALLTYPE Next(DWORD celt, LPWSTR* rgelt,
+                                         DWORD* pceltFetched) = 0;
+  virtual HRESULT STDMETHODCALLTYPE Skip(DWORD celt) = 0;
+  virtual HRESULT STDMETHODCALLTYPE Reset() = 0;
+  virtual HRESULT STDMETHODCALLTYPE Clone(IEnumPStoreItems** ppenum) = 0;
+};
+
+class IEnumPStoreTypes; // not used
+struct PST_PROVIDERINFO; // not used
+struct PST_TYPEINFO; // not used
+struct PST_PROMPTINFO; // not used
+struct PST_ACCESSRULESET; // not used
+typedef DWORD PST_KEY;
+typedef DWORD PST_ACCESSMODE;
+
+class IPStore : public IUnknown {
+public:
+  virtual HRESULT STDMETHODCALLTYPE GetInfo(PST_PROVIDERINFO** ppProperties) = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetProvParam(DWORD dwParam, DWORD* pcbData,
+                                                 BYTE** ppbData, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE SetProvParam(DWORD dwParam, DWORD cbData,
+                                                 BYTE* pbData, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE CreateType(PST_KEY Key, const GUID* pType,
+                                               PST_TYPEINFO* pInfo, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(PST_KEY Key, const GUID* pType,
+                                                PST_TYPEINFO** ppInfo, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE DeleteType(PST_KEY Key, const GUID* pType,
+                                               DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE CreateSubtype(PST_KEY Key, const GUID* pType,
+                                                  const GUID* pSubtype, PST_TYPEINFO* pInfo,
+                                                  PST_ACCESSRULESET* pRules, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE GetSubtypeInfo(PST_KEY Key, const GUID* pType,
+                                                   const GUID* pSubtype, PST_TYPEINFO** ppInfo,
+                                                   DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE DeleteSubtype(PST_KEY Key, const GUID* pType,
+                                                  const GUID* pSubtype, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE ReadAccessRuleset(PST_KEY Key, const GUID* pType,
+                                                      const GUID* pSubtype, PST_ACCESSRULESET** ppRules,
+                                                      DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE WriteAccessRuleset(PST_KEY Key, const GUID* pType,
+                                                       const GUID* pSubtype, PST_ACCESSRULESET* pRules,
+                                                       DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE EnumTypes(PST_KEY Key, DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
+  virtual HRESULT STDMETHODCALLTYPE EnumSubtypes(PST_KEY Key, const GUID* pType,
+                                                 DWORD dwFlags, IEnumPStoreTypes** ppenum) = 0;
+  virtual HRESULT STDMETHODCALLTYPE DeleteItem(PST_KEY Key, const GUID* pItemType,
+                                               const GUID* pItemSubtype, LPCWSTR szItemName,
+                                               PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE ReadItem(PST_KEY Key, const GUID* pItemType,
+                                             const GUID* pItemSubtype, LPCWSTR szItemName,
+                                             DWORD* pcbData, BYTE** ppbData,
+                                             PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE WriteItem(PST_KEY Key, const GUID* pItemType,
+                                              const GUID* pItemSubtype, LPCWSTR szItemName,
+                                              DWORD cbData, BYTE* pbData,
+                                              PST_PROMPTINFO* pPromptInfo, DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE OpenItem(PST_KEY Key, const GUID* pItemType,
+                                             const GUID* pItemSubtype, LPCWSTR szItemName,
+                                             PST_ACCESSMODE ModeFlags, PST_PROMPTINFO* pPromptInfo,
+                                             DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE CloseItem(PST_KEY Key, const GUID* pItemType,
+                                              const GUID* pItemSubtype, LPCWSTR szItemName,
+                                              DWORD dwFlags) = 0;
+  virtual HRESULT STDMETHODCALLTYPE EnumItems(PST_KEY Key, const GUID* pItemType,
+                                              const GUID* pItemSubtype, DWORD dwFlags,
+                                              IEnumPStoreItems** ppenum) = 0;
+};
+
+
 class nsIEProfileMigrator : public nsIBrowserProfileMigrator,
                             public nsINavHistoryBatchCallback {
 public:
   NS_DECL_NSIBROWSERPROFILEMIGRATOR
   NS_DECL_NSINAVHISTORYBATCHCALLBACK
   NS_DECL_ISUPPORTS
 
   nsIEProfileMigrator();
--- a/browser/components/sessionstore/test/browser/browser_607016.js
+++ b/browser/components/sessionstore/test/browser/browser_607016.js
@@ -79,26 +79,28 @@ function test() {
 
   function progressCallback(aBrowser) {
     // We'll remove the progress listener after the first one because we aren't
     // loading any other tabs
     window.gBrowser.removeTabsProgressListener(progressListener);
 
     let curState = JSON.parse(ss.getBrowserState());
     for (let i = 0; i < curState.windows[0].tabs.length; i++) {
-      if (state.windows[0].tabs[i].extData) {
-        is(curState.windows[0].tabs[i].extData["uniq"],
-           state.windows[0].tabs[i].extData["uniq"],
+      let tabState = state.windows[0].tabs[i];
+      let tabCurState = curState.windows[0].tabs[i];
+      if (tabState.extData) {
+        is(tabCurState.extData["uniq"], tabState.extData["uniq"],
            "sanity check that tab has correct extData");
       }
       else {
-        ok(!("extData" in curState.windows[0].tabs[i]),
-           "sanity check that tab doesn't have extData");
-        //XXXzpao output the tab state to help debug bug 679590
-        info("tabState: " + JSON.stringify(curState.windows[0].tabs[i]));
+        // We aren't expecting there to be any data on extData, but panorama
+        // may be setting something, so we need to make sure that if we do have
+        // data, we just don't have anything for "uniq".
+        ok(!("extData" in tabCurState) || !("uniq" in tabCurState.extData),
+           "sanity check that tab doesn't have extData or extData doesn't have 'uniq'");
       }
     }
 
     // Now we'll set a new unique value on 1 of the tabs
     let newUniq = r();
     ss.setTabValue(gBrowser.tabs[1], "uniq", newUniq);
     gBrowser.removeTab(gBrowser.tabs[1]);
     let closedTabData = (JSON.parse(ss.getClosedTabData(window)))[0];
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -1016,19 +1016,19 @@ user_pref("camino.use_system_proxy_setti
                   this is the name of the folder in the <profileDir>/extensions/<extensionID>
     """
     if not os.path.isdir(profileDir):
       self.log.info("INFO | automation.py | Cannot install extension, invalid profileDir at: %s", profileDir)
       return
 
     installRDFFilename = "install.rdf"
 
-    extensionsRootDir = os.path.join(profileDir, "extensions")
+    extensionsRootDir = os.path.join(profileDir, "extensions", "staged")
     if not os.path.isdir(extensionsRootDir):
-      os.mkdir(extensionsRootDir)
+      os.makedirs(extensionsRootDir)
 
     if os.path.isfile(extensionSource):
       reader = ZipFileReader(extensionSource)
 
       for filename in reader.namelist():
         # Sanity check the zip file.
         if os.path.isabs(filename):
           self.log.info("INFO | automation.py | Cannot install extension, bad files in xpi")
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -367,17 +367,20 @@ nsDOMBlobBuilder::GetFile(const nsAStrin
 NS_IMETHODIMP
 nsDOMBlobBuilder::Append(const jsval& aData, JSContext* aCx)
 {
   // We need to figure out what our jsval is
 
   // Is it an object?
   if (JSVAL_IS_OBJECT(aData)) {
     JSObject* obj = JSVAL_TO_OBJECT(aData);
-    NS_ASSERTION(obj, "Er, what?");
+    if (!obj) {
+      // We got passed null.  Just do nothing.
+      return NS_OK;
+    }
 
     // Is it a Blob?
     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(
       nsContentUtils::XPConnect()->
         GetNativeOfWrapper(aCx, obj));
     if (blob)
       return AppendBlob(blob);
 
--- a/content/base/test/test_blobbuilder.html
+++ b/content/base/test/test_blobbuilder.html
@@ -32,16 +32,19 @@ ok(blobBuilder.getFile, "BlobBuilder sho
 
 try {
 blobBuilder.append();
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "an empty argument to append should throw");
 }
 
+blobBuilder.append(null);
+// Yay we didn't crash.
+
 blobBuilder.append("squiggle");
 let blob1 = blobBuilder.getBlob();
 ok(blob1 instanceof Blob, "getBlob should produce Blobs");
 ok(!(blob1 instanceof File), "getBlob should not produce Files");
 is(blob1.type, "", "getBlob with no argument should return Blob with empty type");
 is(blob1.size, 8, "getBlob should return Blob with correct size");
 
 blobBuilder.append("ohai");
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4037,16 +4037,22 @@ WebGLContext::Viewport(WebGLint x, WebGL
     if (width < 0 || height < 0)
         return ErrorInvalidValue("Viewport: negative size");
 
     MakeContextCurrent();
     gl->fViewport(x, y, width, height);
     return NS_OK;
 }
 
+#ifdef XP_MACOSX
+#define WEBGL_OS_IS_MAC 1
+#else
+#define WEBGL_OS_IS_MAC 0
+#endif
+
 NS_IMETHODIMP
 WebGLContext::CompileShader(nsIWebGLShader *sobj)
 {
     WebGLShader *shader;
     WebGLuint shadername;
     if (!GetConcreteObjectAndGLName("compileShader", sobj, &shader, &shadername))
         return NS_OK;
 
@@ -4088,18 +4094,24 @@ WebGLContext::CompileShader(nsIWebGLShad
         // 7-bit ASCII range, so we can skip the NS_IsAscii() check.
         const nsCString& sourceCString = NS_LossyConvertUTF16toASCII(flatSource);
     
         const PRUint32 maxSourceLength = (PRUint32(1)<<18) - 1;
         if (sourceCString.Length() > maxSourceLength)
             return ErrorInvalidValue("compileShader: source has more than %d characters", maxSourceLength);
 
         const char *s = sourceCString.get();
-
-        if (!ShCompile(compiler, &s, 1, SH_OBJECT_CODE)) {
+        
+        int compileOptions = SH_OBJECT_CODE;
+        
+        // work around bug 665578
+        if (WEBGL_OS_IS_MAC && gl->Vendor() == gl::GLContext::VendorATI)
+            compileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS;
+
+        if (!ShCompile(compiler, &s, 1, compileOptions)) {
             int len = 0;
             ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &len);
 
             if (len) {
                 nsCAutoString info;
                 info.SetLength(len);
                 ShGetInfoLog(compiler, info.BeginWriting());
                 shader->SetTranslationFailure(info);
--- a/content/svg/content/src/SVGPathSegListSMILType.cpp
+++ b/content/svg/content/src/SVGPathSegListSMILType.cpp
@@ -90,31 +90,16 @@ SVGPathSegListSMILType::IsEqual(const ns
 {
   NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
   NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
 
   return *static_cast<const SVGPathDataAndOwner*>(aLeft.mU.mPtr) ==
          *static_cast<const SVGPathDataAndOwner*>(aRight.mU.mPtr);
 }
 
-static bool
-ArcFlagsDiffer(SVGPathDataAndOwner::const_iterator aPathData1,
-               SVGPathDataAndOwner::const_iterator aPathData2)
-{
-  NS_ABORT_IF_FALSE
-    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData1[0])),
-                                "ArcFlagsDiffer called with non-arc segment");
-  NS_ABORT_IF_FALSE
-    (SVGPathSegUtils::IsArcType(SVGPathSegUtils::DecodeType(aPathData2[0])),
-                                "ArcFlagsDiffer called with non-arc segment");
-
-  return aPathData1[LARGE_ARC_FLAG_IDX] != aPathData2[LARGE_ARC_FLAG_IDX] ||
-         aPathData1[SWEEP_FLAG_IDX]     != aPathData2[SWEEP_FLAG_IDX];
-}
-
 enum PathInterpolationResult {
   eCannotInterpolate,
   eRequiresConversion,
   eCanInterpolate
 };
 
 static PathInterpolationResult
 CanInterpolate(const SVGPathDataAndOwner& aStart,
@@ -134,22 +119,16 @@ CanInterpolate(const SVGPathDataAndOwner
   SVGPathDataAndOwner::const_iterator pEnd = aEnd.begin();
   SVGPathDataAndOwner::const_iterator pStartDataEnd = aStart.end();
   SVGPathDataAndOwner::const_iterator pEndDataEnd = aEnd.end();
 
   while (pStart < pStartDataEnd && pEnd < pEndDataEnd) {
     PRUint32 startType = SVGPathSegUtils::DecodeType(*pStart);
     PRUint32 endType = SVGPathSegUtils::DecodeType(*pEnd);
 
-    if (SVGPathSegUtils::IsArcType(startType) &&
-        SVGPathSegUtils::IsArcType(endType) &&
-        ArcFlagsDiffer(pStart, pEnd)) {
-      return eCannotInterpolate;
-    }
-
     if (startType != endType) {
       if (!SVGPathSegUtils::SameTypeModuloRelativeness(startType, endType)) {
         return eCannotInterpolate;
       }
 
       result = eRequiresConversion;
     }
 
@@ -210,35 +189,32 @@ AddWeightedPathSegs(double aCoeff1,
 {
   NS_ABORT_IF_FALSE(aSeg2, "2nd segment must be non-null");
   NS_ABORT_IF_FALSE(aResultSeg, "result segment must be non-null");
 
   PRUint32 segType = SVGPathSegUtils::DecodeType(aSeg2[0]);
   NS_ABORT_IF_FALSE(!aSeg1 || SVGPathSegUtils::DecodeType(*aSeg1) == segType,
                     "unexpected segment type");
 
-  // FIRST: Directly copy the arguments that don't make sense to add.
   aResultSeg[0] = aSeg2[0];  // encoded segment type
 
-  bool isArcType = SVGPathSegUtils::IsArcType(segType);
-  if (isArcType) {
-    // Copy boolean arc flags.
-    NS_ABORT_IF_FALSE(!aSeg1 || !ArcFlagsDiffer(aSeg1, aSeg2),
-                      "Expecting arc flags to match");
-    aResultSeg[LARGE_ARC_FLAG_IDX] = aSeg2[LARGE_ARC_FLAG_IDX];
-    aResultSeg[SWEEP_FLAG_IDX]     = aSeg2[SWEEP_FLAG_IDX];
-  }
-
-  // SECOND: Add the arguments that are supposed to be added.
+  // FIRST: Add all the arguments.
   // (The 1's below are to account for segment type)
   PRUint32 numArgs = SVGPathSegUtils::ArgCountForType(segType);
   for (PRUint32 i = 1; i < 1 + numArgs; ++i) {
-     // Need to skip arc flags for arc-type segments. (already handled them)
-    if (!(isArcType && (i == LARGE_ARC_FLAG_IDX || i == SWEEP_FLAG_IDX))) {
-      aResultSeg[i] = (aSeg1 ? aCoeff1 * aSeg1[i] : 0.0) + aCoeff2 * aSeg2[i];
+    aResultSeg[i] = (aSeg1 ? aCoeff1 * aSeg1[i] : 0.0) + aCoeff2 * aSeg2[i];
+  }
+
+  // SECOND: ensure non-zero flags become 1.
+  if (SVGPathSegUtils::IsArcType(segType)) {
+    if (aResultSeg[LARGE_ARC_FLAG_IDX] != 0.0f) {
+      aResultSeg[LARGE_ARC_FLAG_IDX] = 1.0f;
+    }
+    if (aResultSeg[SWEEP_FLAG_IDX] != 0.0f) {
+      aResultSeg[SWEEP_FLAG_IDX] = 1.0f;
     }
   }
 
   // FINALLY: Shift iterators forward. ("1+" is to include seg-type)
   if (aSeg1) {
     aSeg1 += 1 + numArgs;
   }
   aSeg2 += 1 + numArgs;
--- a/content/svg/content/test/test_pathAnimInterpolation.xhtml
+++ b/content/svg/content/test/test_pathAnimInterpolation.xhtml
@@ -133,20 +133,20 @@ var gSuffixes = {
   LL: [[10, 20], [30, 40], [20, 30], [30, 50]],
   ll: [[10, 20], [30, 40], [20, 30], [30, 50]],
   CC: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
        [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
   cc: [[10, 20, 30, 40, 50, 60], [70, 80, 90, 100, 110, 120],
        [40, 50, 60, 70, 80, 90], [50, 70, 90, 110, 130, 150]],
   QQ: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   qq: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
-  AA: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
-       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
-  aa: [[10, 20, 30, 0, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
-       [35, 45, 55, 0, 0, 65, 75], [45, 65, 85, 0, 0, 105, 125]],
+  AA: [[10, 20, 30, 1, 0, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 1, 0, 65, 75], [45, 65, 85, 1, 0, 105, 125]],
+  aa: [[10, 20, 30, 0, 1, 40, 50], [60, 70, 80, 0, 0, 90, 100],
+       [35, 45, 55, 0, 1, 65, 75], [45, 65, 85, 0, 1, 105, 125]],
   HH: [[10], [20], [15], [25]],
   hh: [[10], [20], [15], [25]],
   VV: [[10], [20], [15], [25]],
   vv: [[10], [20], [15], [25]],
   SS: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   ss: [[10, 20, 30, 40], [50, 60, 70, 80], [30, 40, 50, 60], [40, 60, 80, 100]],
   TT: [[10, 20], [30, 40], [20, 30], [30, 50]],
   tt: [[10, 20], [30, 40], [20, 30], [30, 50]],
@@ -281,27 +281,16 @@ function run()
 
       for each (let prefixEntry in gPrefixes) {
         let [prefixLength, prefix] = prefixEntry;
         addTest(prefixLength, prefix, fromType, fromArguments,
 	        toType, toArguments, toType, expectedArguments, additive);
       }
     }
 
-    // Test that differences in arc flag parameters cause the
-    // interpolation/addition not to occur.
-    addTest(1, "M100,100",
-            "A", [10, 20, 30, 0, 0, 40, 50],
-            "a", [60, 70, 80, 0, 1, 90, 100],
-	    "a", [60, 70, 80, 0, 1, 90, 100], additive);
-    addTest(1, "M100,100",
-            "A", [10, 20, 30, 0, 0, 40, 50],
-            "a", [60, 70, 80, 1, 0, 90, 100],
-	    "a", [60, 70, 80, 1, 0, 90, 100], additive);
-
     // Test all pairs of segment types that cannot be interpolated between.
     for each (let fromType in gTypes) {
       let fromArguments = generatePathSegmentArguments(fromType, 0);
       for each (let toType in gTypes) {
         if (!isValidInterpolation(fromType, toType)) {
           let toArguments = generatePathSegmentArguments(toType, 1000);
           addTest(1, "M100,100", fromType, fromArguments,
 	          toType, toArguments, toType, toArguments, additive);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1638,17 +1638,17 @@ nsJSContext::ExecuteScript(void *aScript
   // operation callback or from ScriptEvaluated.
   jsval val;
   JSBool ok;
 
   JSScript *script = static_cast<JSScript *>(aScriptObject);
   nsCOMPtr<nsIPrincipal> principal;
 
   rv = sSecurityManager->GetObjectPrincipal(mContext,
-                                            JS_GetObjectFromScript(script),
+                                            JS_GetGlobalFromScript(script),
                                             getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsJSContext::TerminationFuncHolder holder(this);
   JSAutoRequest ar(mContext);
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -555,18 +555,18 @@ NS_IMPL_QUERY_INTERFACE1(TransactionPool
 
 NS_IMETHODIMP
 TransactionPoolEventTarget::Dispatch(nsIRunnable* aRunnable,
                                      PRUint32 aFlags)
 {
   NS_ASSERTION(aRunnable, "Null pointer!");
   NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "Unsupported!");
 
-  TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
-  NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);
+  TransactionThreadPool* pool = TransactionThreadPool::Get();
+  NS_ASSERTION(pool, "This should never be null!");
 
   return pool->Dispatch(mTransaction, aRunnable, false, nsnull);
 }
 
 NS_IMETHODIMP
 TransactionPoolEventTarget::IsOnCurrentThread(bool* aResult)
 {
   *aResult = false;
--- a/dom/indexedDB/AsyncConnectionHelper.h
+++ b/dom/indexedDB/AsyncConnectionHelper.h
@@ -120,16 +120,21 @@ public:
   void SetError(nsresult aErrorCode)
   {
     NS_ASSERTION(NS_FAILED(aErrorCode), "Not a failure code!");
     mResultCode = aErrorCode;
   }
 
   static IDBTransaction* GetCurrentTransaction();
 
+  bool HasTransaction()
+  {
+    return mTransaction;
+  }
+
   nsISupports* GetSource()
   {
     return mRequest ? mRequest->Source() : nsnull;
   }
 
   nsresult GetResultCode()
   {
     return mResultCode;
--- a/dom/indexedDB/DatabaseInfo.cpp
+++ b/dom/indexedDB/DatabaseInfo.cpp
@@ -80,17 +80,18 @@ EnumerateObjectStoreNames(const nsAStrin
 }
 
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 DatabaseInfo::DatabaseInfo()
 : id(0),
   nextObjectStoreId(1),
-  nextIndexId(1)
+  nextIndexId(1),
+  runningVersionChange(false)
 {
   MOZ_COUNT_CTOR(DatabaseInfo);
 }
 
 DatabaseInfo::~DatabaseInfo()
 {
   MOZ_COUNT_DTOR(DatabaseInfo);
 }
--- a/dom/indexedDB/DatabaseInfo.h
+++ b/dom/indexedDB/DatabaseInfo.h
@@ -49,17 +49,18 @@ BEGIN_INDEXEDDB_NAMESPACE
 
 struct DatabaseInfo
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   DatabaseInfo();
   ~DatabaseInfo();
 #else
   DatabaseInfo()
-  : id(0), nextObjectStoreId(1), nextIndexId(1) { }
+  : id(0), nextObjectStoreId(1), nextIndexId(1), runningVersionChange(false)
+  { }
 #endif
 
   static bool Get(PRUint32 aId,
                   DatabaseInfo** aInfo);
 
   static bool Put(DatabaseInfo* aInfo);
 
   static void Remove(PRUint32 aId);
@@ -68,16 +69,17 @@ struct DatabaseInfo
   bool ContainsStoreName(const nsAString& aName);
 
   nsString name;
   PRUint64 version;
   PRUint32 id;
   nsString filePath;
   PRInt64 nextObjectStoreId;
   PRInt64 nextIndexId;
+  bool runningVersionChange;
 
   nsAutoRefCnt referenceCount;
 };
 
 struct IndexInfo
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   IndexInfo();
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -424,16 +424,44 @@ IDBDatabase::CloseInternal()
 bool
 IDBDatabase::IsClosed()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   return mClosed;
 }
 
 void
+IDBDatabase::EnterSetVersionTransaction()
+{
+  DatabaseInfo* dbInfo;
+  if (!DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
+    NS_ERROR("This should never fail!");
+  }
+
+  NS_ASSERTION(!dbInfo->runningVersionChange, "How did that happen?");
+  dbInfo->runningVersionChange = true;
+}
+
+void
+IDBDatabase::ExitSetVersionTransaction()
+{
+  DatabaseInfo* dbInfo;
+  if (!DatabaseInfo::Get(mDatabaseId, &dbInfo)) {
+    NS_ERROR("This should never fail!");
+  }
+
+  NS_ASSERTION(dbInfo->runningVersionChange, "How did that happen?");
+  dbInfo->runningVersionChange = false;
+
+  IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
+  NS_ASSERTION(manager, "We should always have a manager here");
+  manager->UnblockSetVersionRunnable(this);
+}
+
+void
 IDBDatabase::OnUnlink()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!mOwner, "Should have been cleared already!");
 
   // We've been unlinked, at the very least we should be able to prevent further
   // transactions from starting and unblock any other SetVersion callers.
   Close();
@@ -705,16 +733,20 @@ IDBDatabase::Transaction(nsIVariant* aSt
   nsresult rv = aStoreNames->GetDataType(&type);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   DatabaseInfo* info;
   if (!DatabaseInfo::Get(mDatabaseId, &info)) {
     NS_ERROR("This should never fail!");
   }
 
+  if (info->runningVersionChange) {
+    return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
+  }
+
   nsTArray<nsString> storesToOpen;
 
   switch (type) {
     case nsIDataType::VTYPE_VOID:
     case nsIDataType::VTYPE_EMPTY:
     case nsIDataType::VTYPE_EMPTY_ARRAY: {
       // Empty, request all object stores
       if (!info->GetObjectStoreNames(storesToOpen)) {
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -130,16 +130,19 @@ public:
   // transactions for this database will be allowed to run.
   bool IsInvalidated();
 
   void CloseInternal();
 
   // Whether or not the database has had Close called on it.
   bool IsClosed();
 
+  void EnterSetVersionTransaction();
+  void ExitSetVersionTransaction();
+
 private:
   IDBDatabase();
   ~IDBDatabase();
 
   void OnUnlink();
 
   PRUint32 mDatabaseId;
   nsString mName;
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -688,47 +688,64 @@ IndexedDatabaseManager::OnDatabaseClosed
       // for other databases the mDatabases array may be empty.
       if (!runnable->mDatabases.IsEmpty() &&
           !runnable->mDatabases.RemoveElement(aDatabase)) {
         NS_ERROR("Didn't have this database in our list!");
       }
 
       // Now run the helper if there are no more live databases.
       if (runnable->mHelper && runnable->mDatabases.IsEmpty()) {
-        // Don't hold the callback alive longer than necessary.
-        nsRefPtr<AsyncConnectionHelper> helper;
-        helper.swap(runnable->mHelper);
+        // At this point, all databases are closed, so no new transactions can
+        // be started.  There may, however, still be outstanding transactions
+        // that have not completed.  We need to wait for those before we
+        // dispatch the helper.
 
-        if (NS_FAILED(helper->DispatchToTransactionPool())) {
-          NS_WARNING("Failed to dispatch to thread pool!");
-        }
+        TransactionThreadPool* pool = TransactionThreadPool::GetOrCreate();
 
-        // Now wait for the transaction to complete. Completing the transaction
-        // will be our cue to remove the SetVersionRunnable from our list and
-        // therefore allow other SetVersion requests to begin.
-        TransactionThreadPool* pool = TransactionThreadPool::Get();
-        NS_ASSERTION(pool, "This should never be null!");
+        nsRefPtr<WaitForTransactionsToFinishRunnable> waitRunnable =
+          new WaitForTransactionsToFinishRunnable(runnable);
 
         // All other databases should be closed, so we only need to wait on this
         // one.
         nsAutoTArray<nsRefPtr<IDBDatabase>, 1> array;
         if (!array.AppendElement(aDatabase)) {
           NS_ERROR("This should never fail!");
         }
 
-        // Use the SetVersionRunnable as the callback.
-        if (!pool->WaitForAllDatabasesToComplete(array, runnable)) {
+        // Use the WaitForTransactionsToFinishRunnable as the callback.
+        if (!pool->WaitForAllDatabasesToComplete(array, waitRunnable)) {
           NS_WARNING("Failed to wait for transaction to complete!");
         }
       }
       break;
     }
   }
 }
 
+void
+IndexedDatabaseManager::UnblockSetVersionRunnable(IDBDatabase* aDatabase)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(aDatabase, "Null pointer!");
+
+  // Check through the list of SetVersionRunnables to find the one we're seeking.
+  for (PRUint32 index = 0; index < mSetVersionRunnables.Length(); index++) {
+    nsRefPtr<SetVersionRunnable>& runnable = mSetVersionRunnables[index];
+
+    if (runnable->mRequestingDatabase->Id() == aDatabase->Id()) {
+      NS_ASSERTION(!runnable->mHelper,
+                 "Why are we unblocking a runnable if the helper didn't run?");
+      NS_DispatchToCurrentThread(runnable);
+      return;
+    }
+  }
+
+  NS_NOTREACHED("How did we get here!");
+}
+
 // static
 bool
 IndexedDatabaseManager::SetCurrentDatabase(IDBDatabase* aDatabase)
 {
   NS_ASSERTION(gCurrentDatabaseIndex != BAD_TLS_INDEX,
                "This should have been set already!");
 
 #ifdef DEBUG
@@ -1278,8 +1295,44 @@ IndexedDatabaseManager::SetVersionRunnab
   NS_ASSERTION(mgr, "This should never be null!");
 
   // Let the IndexedDatabaseManager know that the SetVersion transaction has
   // completed.
   mgr->OnSetVersionRunnableComplete(this);
 
   return NS_OK;
 }
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(IndexedDatabaseManager::WaitForTransactionsToFinishRunnable,
+                              nsIRunnable)
+
+NS_IMETHODIMP
+IndexedDatabaseManager::WaitForTransactionsToFinishRunnable::Run()
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+
+  // Don't hold the callback alive longer than necessary.
+  nsRefPtr<AsyncConnectionHelper> helper;
+  helper.swap(mRunnable->mHelper);
+
+  nsRefPtr<SetVersionRunnable> runnable;
+  runnable.swap(mRunnable);
+
+  // If the helper has a transaction, dispatch it to the transaction
+  // threadpool.
+  if (helper->HasTransaction()) {
+    if (NS_FAILED(helper->DispatchToTransactionPool())) {
+      NS_WARNING("Failed to dispatch to thread pool!");
+    }
+  }
+  // Otherwise, dispatch it to the IO thread.
+  else {
+    IndexedDatabaseManager* manager = IndexedDatabaseManager::Get();
+    NS_ASSERTION(manager, "We should definitely have a manager here");
+
+    helper->Dispatch(manager->IOThread());
+  }
+
+  // The helper is responsible for calling
+  // IndexedDatabaseManager::UnblockSetVersionRunnable.
+
+  return NS_OK;
+}
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -199,16 +199,18 @@ private:
     nsCOMPtr<nsIIndexedDatabaseUsageCallback> mCallback;
     PRUint64 mUsage;
     PRInt32 mCanceled;
   };
 
   // Called when AsyncUsageRunnable has finished its Run() method.
   inline void OnUsageCheckComplete(AsyncUsageRunnable* aRunnable);
 
+  void UnblockSetVersionRunnable(IDBDatabase* aDatabase);
+
   // Responsible for waiting until all databases have been closed before running
   // the version change transaction. Created when
   // IndexedDatabaseManager::SetDatabaseVersion is called. Runs only once on the
   // main thread when the version change transaction has completed.
   class SetVersionRunnable : public nsIRunnable
   {
   public:
     NS_DECL_ISUPPORTS
@@ -222,16 +224,36 @@ private:
     nsTArray<nsRefPtr<IDBDatabase> > mDatabases;
     nsRefPtr<AsyncConnectionHelper> mHelper;
     nsTArray<nsCOMPtr<nsIRunnable> > mDelayedRunnables;
   };
 
   // Called when SetVersionRunnable has finished its Run() method.
   inline void OnSetVersionRunnableComplete(SetVersionRunnable* aRunnable);
 
+
+  // A callback runnable used by the TransactionPool when it's safe to proceed
+  // with a SetVersion/DeleteDatabase/etc.
+  class WaitForTransactionsToFinishRunnable : public nsIRunnable
+  {
+  public:
+    WaitForTransactionsToFinishRunnable(SetVersionRunnable* aRunnable)
+    : mRunnable(aRunnable)
+    {
+      NS_ASSERTION(mRunnable, "Why don't we have a runnable?");
+      NS_ASSERTION(mRunnable->mDatabases.IsEmpty(), "We're here too early!");
+    }
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIRUNNABLE
+
+  private:
+    nsRefPtr<SetVersionRunnable> mRunnable;
+  };
+
   // Maintains a list of live databases per origin.
   nsClassHashtable<nsCStringHashKey, nsTArray<IDBDatabase*> > mLiveDatabases;
 
   // Maintains a list of origins that are currently being cleared.
   nsAutoTArray<nsRefPtr<OriginClearRunnable>, 1> mOriginClearRunnables;
 
   // Maintains a list of origins that we're currently enumerating to gather
   // usage statistics.
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -490,20 +490,23 @@ public:
     mRequestedVersion(aRequestedVersion),
     mCurrentVersion(aCurrentVersion)
   {
     mTransaction->SetTransactionListener(this);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
   nsresult GetSuccessResult(JSContext* aCx,
                             jsval* aVal);
 
+protected:
+  nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
+  nsresult Init();
+
   // SetVersionHelper never fires an error event at the request.  It hands that
   // responsibility back to the OpenDatabaseHelper
   void OnError() { }
 
   // Need an upgradeneeded event here.
   already_AddRefed<nsDOMEvent> CreateSuccessEvent();
 
   nsresult NotifyTransactionComplete(IDBTransaction* aTransaction);
@@ -549,16 +552,18 @@ OpenDatabaseHelper::DoDatabaseWork()
     bool correctThread;
     NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()->
                               IsOnCurrentThread(&correctThread)) &&
                  correctThread,
                  "Running on the wrong thread!");
   }
 #endif
 
+  mState = eFiringEvents; // In case we fail somewhere along the line.
+
   if (IndexedDatabaseManager::IsShuttingDown()) {
     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   nsCOMPtr<nsIFile> dbFile;
   nsresult rv = GetDatabaseFile(mASCIIOrigin, mName, getter_AddRefs(dbFile));
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
@@ -641,19 +646,20 @@ OpenDatabaseHelper::DoDatabaseWork()
     mLastObjectStoreId = NS_MAX(objectStoreInfo->id, mLastObjectStoreId);
   }
 
   // See if we need to do a VERSION_CHANGE transaction
   if (mCurrentVersion > mRequestedVersion) {
     return NS_ERROR_DOM_INDEXEDDB_VERSION_ERR;
   }
 
-  mState = mCurrentVersion != mRequestedVersion ?
-           eSetVersionPending :
-           eFiringEvents;
+  if (mCurrentVersion != mRequestedVersion) {
+    mState = eSetVersionPending;
+  }
+
   return NS_OK;
 }
 
 nsresult
 OpenDatabaseHelper::StartSetVersion()
 {
   NS_ASSERTION(mState == eSetVersionPending, "Why are we here?");
 
@@ -679,16 +685,17 @@ OpenDatabaseHelper::StartSetVersion()
 
   rv = mgr->SetDatabaseVersion(mDatabase, mOpenDBRequest, mCurrentVersion,
                                mRequestedVersion, helper);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   // The SetVersionHelper is responsible for dispatching us back to the
   // main thread again and changing the state to eSetVersionCompleted.
   mState = eSetVersionPending;
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 OpenDatabaseHelper::Run()
 {
   NS_ASSERTION(mState != eCreated, "Dispatch was not called?!?");
 
@@ -706,16 +713,22 @@ OpenDatabaseHelper::Run()
     }
 
     // We've done whatever work we need to do on the DB thread, and any
     // SetVersion stuff is done by now.
     NS_ASSERTION(mState == eFiringEvents ||
                  mState == eSetVersionCompleted, "Why are we here?");
 
     if (mState == eSetVersionCompleted) {
+      // Allow transaction creation/other version change transactions to proceed
+      // before we fire events.  Other version changes will be postd to the end
+      // of the event loop, and will be behind whatever the page does in
+      // its error/success event handlers.
+      mDatabase->ExitSetVersionTransaction();
+
       mState = eFiringEvents;
     } else {
       // Notify the request that we're done, but only if we didn't just finish
       // a SetVersionHelper.  In the SetVersionHelper case, that helper tells
       // the request that it is done, and we avoid calling NotifyHandlerCompleted
       // twice.
 
       nsresult rv = mOpenDBRequest->NotifyHelperCompleted(this);
@@ -861,16 +874,25 @@ OpenDatabaseHelper::NotifySetVersionFini
 
   mState = eSetVersionCompleted;
   
   // Dispatch ourself back to the main thread
   return NS_DispatchToCurrentThread(this);
 }
 
 void
+OpenDatabaseHelper::BlockDatabase()
+{
+  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  NS_ASSERTION(mDatabase, "This is going bad fast.");
+
+  mDatabase->EnterSetVersionTransaction();
+}
+
+void
 OpenDatabaseHelper::DispatchSuccessEvent()
 {
   NS_ASSERTION(mDatabase, "Doesn't seem very successful to me.");
 
   nsRefPtr<nsDOMEvent> event =
     CreateGenericEvent(NS_LITERAL_STRING(SUCCESS_EVT_STR));
   if (!event) {
     NS_ERROR("Failed to create event!");
@@ -912,16 +934,25 @@ OpenDatabaseHelper::ReleaseMainThreadObj
   mDatabase = nsnull;
 
   HelperBase::ReleaseMainThreadObjects();
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(SetVersionHelper, AsyncConnectionHelper);
 
 nsresult
+SetVersionHelper::Init()
+{
+  // Block transaction creation until we are done.
+  mOpenHelper->BlockDatabase();
+
+  return NS_OK;
+}
+
+nsresult
 SetVersionHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(aConnection, "Passing a null connection!");
 
   nsCOMPtr<mozIStorageStatement> stmt;
   nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
     "UPDATE database "
     "SET version = :version"
--- a/dom/indexedDB/OpenDatabaseHelper.h
+++ b/dom/indexedDB/OpenDatabaseHelper.h
@@ -77,16 +77,17 @@ public:
   }
 
   nsresult GetResultCode()
   {
     return mResultCode;
   }
 
   nsresult NotifySetVersionFinished();
+  void BlockDatabase();
 
 protected:
   // Methods only called on the main thread
   nsresult EnsureSuccessResult();
   nsresult StartSetVersion();
   nsresult GetSuccessResult(JSContext* aCx,
                           jsval* aVal);
   void DispatchSuccessEvent();
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -233,17 +233,16 @@ TransactionThreadPool::FinishTransaction
 
   nsTArray<TransactionInfo>& transactionsInProgress =
     dbTransactionInfo->transactions;
 
   PRUint32 transactionCount = transactionsInProgress.Length();
 
 #ifdef DEBUG
   if (aTransaction->mMode == IDBTransaction::VERSION_CHANGE) {
-    NS_ASSERTION(dbTransactionInfo->locked, "Should be locked!");
     NS_ASSERTION(transactionCount == 1,
                  "More transactions running than should be!");
   }
 #endif
 
   if (transactionCount == 1) {
 #ifdef DEBUG
     {
@@ -339,35 +338,27 @@ TransactionThreadPool::TransactionCanRun
   }
 
   nsTArray<TransactionInfo>& transactionsInProgress =
     dbTransactionInfo->transactions;
 
   PRUint32 transactionCount = transactionsInProgress.Length();
   NS_ASSERTION(transactionCount, "Should never be 0!");
 
-  if (mode == IDBTransaction::VERSION_CHANGE) {
-    dbTransactionInfo->lockPending = true;
-  }
-
   for (PRUint32 index = 0; index < transactionCount; index++) {
     // See if this transaction is in out list of current transactions.
     const TransactionInfo& info = transactionsInProgress[index];
     if (info.transaction == aTransaction) {
       *aCanRun = true;
       *aExistingQueue = info.queue;
       return NS_OK;
     }
   }
 
-  if (dbTransactionInfo->locked || dbTransactionInfo->lockPending) {
-    *aCanRun = false;
-    *aExistingQueue = nsnull;
-    return NS_OK;
-  }
+  NS_ASSERTION(mode != IDBTransaction::VERSION_CHANGE, "How did we get here?");
 
   bool writeOverlap;
   nsresult rv =
     CheckOverlapAndMergeObjectStores(dbTransactionInfo->storesWriting,
                                      objectStoreNames,
                                      mode == nsIIDBTransaction::READ_WRITE,
                                      &writeOverlap);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -443,21 +434,16 @@ TransactionThreadPool::Dispatch(IDBTrans
   nsAutoPtr<DatabaseTransactionInfo> autoDBTransactionInfo;
 
   if (!mTransactionsInProgress.Get(databaseId, &dbTransactionInfo)) {
     // Make a new struct for this transaction.
     autoDBTransactionInfo = new DatabaseTransactionInfo();
     dbTransactionInfo = autoDBTransactionInfo;
   }
 
-  if (aTransaction->mMode == IDBTransaction::VERSION_CHANGE) {
-    NS_ASSERTION(!dbTransactionInfo->locked, "Already locked?!");
-    dbTransactionInfo->locked = true;
-  }
-
   const nsTArray<nsString>& objectStoreNames = aTransaction->mObjectStoreNames;
 
   nsTArray<nsString>& storesInUse =
     aTransaction->mMode == nsIIDBTransaction::READ_WRITE ?
     dbTransactionInfo->storesWriting :
     dbTransactionInfo->storesReading;
 
   if (!storesInUse.AppendElements(objectStoreNames)) {
--- a/dom/indexedDB/TransactionThreadPool.h
+++ b/dom/indexedDB/TransactionThreadPool.h
@@ -118,22 +118,16 @@ protected:
   {
     nsRefPtr<IDBTransaction> transaction;
     nsRefPtr<TransactionQueue> queue;
     nsTArray<nsString> objectStoreNames;
   };
 
   struct DatabaseTransactionInfo
   {
-    DatabaseTransactionInfo()
-    : locked(false), lockPending(false)
-    { }
-
-    bool locked;
-    bool lockPending;
     nsTArray<TransactionInfo> transactions;
     nsTArray<nsString> storesReading;
     nsTArray<nsString> storesWriting;
   };
 
   struct QueuedDispatchInfo
   {
     QueuedDispatchInfo()
--- a/dom/indexedDB/test/Makefile.in
+++ b/dom/indexedDB/test/Makefile.in
@@ -93,16 +93,17 @@ TEST_FILES = \
   test_success_events_after_abort.html \
   test_third_party.html \
   test_transaction_abort.html \
   test_transaction_lifetimes.html \
   test_transaction_lifetimes_nested.html \
   test_setVersion.html \
   test_setVersion_abort.html \
   test_setVersion_events.html \
+  test_setVersion_exclusion.html \
   test_writer_starvation.html \
   third_party_iframe1.html \
   third_party_iframe2.html \
   $(NULL)
 
 ifeq (browser,$(MOZ_BUILD_APP))
 BROWSER_TEST_FILES = \
   browser_forgetThisSite.js \
--- a/dom/indexedDB/test/browser_quotaPrompt.html
+++ b/dom/indexedDB/test/browser_quotaPrompt.html
@@ -64,16 +64,19 @@
         let event = yield;
 
         db = event.target.result;
 
         db.onversionchange = function () { db.close(); };
 
         db.createObjectStore("foo", { autoIncrement: true });
 
+        request.onsuccess = grabEventAndContinueHandler;
+        yield;
+
         setTimeout(testFinishedCallback, 0, "ready");
         yield;
       }
     </script>
 
     <script type="text/javascript;version=1.7" src="browserHelpers.js"></script>
 
   </head>
--- a/dom/indexedDB/test/event_propagation_iframe.html
+++ b/dom/indexedDB/test/event_propagation_iframe.html
@@ -99,17 +99,17 @@
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorEventCounter;
       db.addEventListener("error", errorEventCounter, true);
 
-      event.target.transaction.oncomplete = grabEventAndContinueHandler;
+      event.target.onsuccess = grabEventAndContinueHandler;
 
       db.createObjectStore("foo", { autoIncrement: true });
       yield;
 
       let transaction = db.transaction("foo", IDBTransaction.READ_WRITE);
       transaction.addEventListener("error", errorEventCounter, false);
       transaction.addEventListener("error", errorEventCounter, true);
 
--- a/dom/indexedDB/test/leaving_page_iframe.html
+++ b/dom/indexedDB/test/leaving_page_iframe.html
@@ -7,17 +7,17 @@ function startDBWork() {
   mozIndexedDB.open(parent.location, 1).onupgradeneeded = function(e) {
     db = e.target.result;
     var trans = e.target.transaction;
     if (db.objectStoreNames.contains("mystore")) {
       db.deleteObjectStore("mystore");
     }
     var store = db.createObjectStore("mystore");
     store.add({ hello: "world" }, 42);
-    trans.oncomplete = madeMod;
+    e.target.onsuccess = madeMod;
   };
 }
 
 function madeMod() {
   var trans = db.transaction(["mystore"], IDBTransaction.READ_WRITE);
   var store = trans.
               objectStore("mystore");
   trans.oncomplete = function() {
--- a/dom/indexedDB/test/test_autoIncrement_indexes.html
+++ b/dom/indexedDB/test/test_autoIncrement_indexes.html
@@ -28,16 +28,19 @@
 
       let data = { first: "foo", second: "foo", third: "foo" };
 
       objectStore.add(data).onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       let key = event.target.result;
       ok(key, "Added entry");
+      request.onsuccess = grabEventAndContinueHandler;
+
+      event = yield;
 
       let objectStore = db.transaction("foo").objectStore("foo");
       let first = objectStore.index("first");
       let second = objectStore.index("second");
       let third = objectStore.index("third");
 
       first.get("foo").onsuccess = grabEventAndContinueHandler;
       event = yield;
--- a/dom/indexedDB/test/test_clear.html
+++ b/dom/indexedDB/test/test_clear.html
@@ -20,17 +20,17 @@
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = request.result;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       let objectStore = db.createObjectStore("foo", { autoIncrement: true });
 
       let firstKey;
       for (let i = 0; i < entryCount; i++) {
         request = objectStore.add({});
         request.onerror = errorHandler;
         if (!i) {
--- a/dom/indexedDB/test/test_create_index_with_integer_keys.html
+++ b/dom/indexedDB/test/test_create_index_with_integer_keys.html
@@ -18,33 +18,33 @@
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       // Make object store, add data.
       let objectStore = db.createObjectStore("foo", { keyPath: "id" });
       objectStore.add(data);
       yield;
       db.close();
 
       let request = mozIndexedDB.open(window.location.pathname, 2);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db2 = event.target.result;
       db2.onerror = errorHandler;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       // Create index.
       event.target.transaction.objectStore("foo").createIndex("foo", "num");
       yield;
 
       // Make sure our object made it into the index.
       let seenCount = 0;
 
--- a/dom/indexedDB/test/test_cursor_mutation.html
+++ b/dom/indexedDB/test/test_cursor_mutation.html
@@ -30,17 +30,17 @@
       const objectStoreDataNameSort = [ 1, 4, 5, 2, 3 ];
 
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       let objectStore = db.createObjectStore("foo", { keyPath: "ss" });
       objectStore.createIndex("name", "name", { unique: true });
 
       for (let i = 0; i < objectStoreData.length - 1; i++) {
         objectStore.add(objectStoreData[i]);
       }
       yield;
--- a/dom/indexedDB/test/test_getAll.html
+++ b/dom/indexedDB/test/test_getAll.html
@@ -21,16 +21,17 @@
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore("foo", { autoIncrement: true });
 
+      request.onsuccess = grabEventAndContinueHandler;
       request = objectStore.getAll();
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result instanceof Array, true, "Got an array object");
       is(event.target.result.length, 0, "No elements");
 
@@ -41,16 +42,17 @@
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           if (++addedCount == values.length) {
             SimpleTest.executeSoon(function() { testGenerator.next(); });
           }
         }
       }
       yield;
+      yield;
 
       request = db.transaction("foo").objectStore("foo").getAll();
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       is(event.target.result instanceof Array, true, "Got an array object");
       is(event.target.result.length, values.length, "Same length");
--- a/dom/indexedDB/test/test_index_getAll.html
+++ b/dom/indexedDB/test/test_index_getAll.html
@@ -55,16 +55,17 @@
         { key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
         { key: "237-23-7737", value: { name: "Pat", height: 65 } },
         { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
       ];
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore(objectStoreName);
 
       // First, add all our data to the object store.
       let addedData = 0;
@@ -73,27 +74,26 @@
                                   objectStoreData[i].key);
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           if (++addedData == objectStoreData.length) {
             testGenerator.send(event);
           }
         }
       }
-      event = yield;
+      yield;
       ok(true, "1");
 
       // Now create the indexes.
       for (let i in indexData) {
         objectStore.createIndex(indexData[i].name, indexData[i].keyPath,
                                 indexData[i].options);
       }
 
       is(objectStore.indexNames.length, indexData.length, "Good index count");
-      continueToNextStep();
       yield;
 
       ok(true, "2");
       objectStore = db.transaction(objectStoreName)
                       .objectStore(objectStoreName);
 
       request = objectStore.index("height").getAllKeys(65);
       request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_index_getAllObjects.html
+++ b/dom/indexedDB/test/test_index_getAllObjects.html
@@ -55,16 +55,17 @@
         { key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
         { key: "237-23-7737", value: { name: "Pat", height: 65 } },
         { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
       ];
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore(objectStoreName, {});
 
       // First, add all our data to the object store.
       let addedData = 0;
@@ -82,17 +83,16 @@
 
       // Now create the indexes.
       for (let i in indexData) {
         objectStore.createIndex(indexData[i].name, indexData[i].keyPath,
                                 indexData[i].options);
       }
 
       is(objectStore.indexNames.length, indexData.length, "Good index count");
-      continueToNextStep();
       yield;
 
       objectStore = db.transaction(objectStoreName)
                       .objectStore(objectStoreName);
 
       request = objectStore.index("height").getAll(65);
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
--- a/dom/indexedDB/test/test_index_object_cursors.html
+++ b/dom/indexedDB/test/test_index_object_cursors.html
@@ -32,17 +32,17 @@
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       for (let objectStoreIndex in objectStoreData) {
         const objectStoreInfo = objectStoreData[objectStoreIndex];
         let objectStore = db.createObjectStore(objectStoreInfo.name,
                                                objectStoreInfo.options);
         for (let indexIndex in indexData) {
           const indexInfo = indexData[indexIndex];
           let index = objectStore.createIndex(indexInfo.name,
--- a/dom/indexedDB/test/test_indexes.html
+++ b/dom/indexedDB/test/test_indexes.html
@@ -66,16 +66,17 @@
         { key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
         { key: "237-23-7737", value: { name: "Pat", height: 65 } },
         { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
       ];
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore(objectStoreName, { keyPath: "" });
 
       // First, add all our data to the object store.
       let addedData = 0;
@@ -92,17 +93,16 @@
       event = yield;
 
       // Now create the indexes.
       for (let i in indexData) {
         objectStore.createIndex(indexData[i].name, indexData[i].keyPath,
                                 indexData[i].options);
       }
       is(objectStore.indexNames.length, indexData.length, "Good index count");
-      continueToNextStep();
       yield;
 
       objectStore = db.transaction(objectStoreName)
                       .objectStore(objectStoreName);
 
       // Check global properties to make sure they are correct.
       is(objectStore.indexNames.length, indexData.length, "Good index count");
       for (let i in indexData) {
--- a/dom/indexedDB/test/test_indexes_bad_values.html
+++ b/dom/indexedDB/test/test_indexes_bad_values.html
@@ -46,16 +46,17 @@
         { key: "237-23-7735", value: { name: "Sue", height: 58, weight: 130 } },
         { key: "237-23-7736", value: { name: "Joe", height: 65, weight: 150 } },
         { key: "237-23-7734", value: { name: "Ron", height: 73, weight: 180 } }
       ];
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let objectStore = db.createObjectStore(objectStoreName, { } );
 
       let addedData = 0;
       for (let i in objectStoreData) {
@@ -82,16 +83,17 @@
         request.onerror = errorHandler;
         request.onsuccess = function(event) {
           if (++addedData == badObjectStoreData.length) {
             SimpleTest.executeSoon(function() { testGenerator.next() });
           }
         }
       }
       yield;
+      yield;
 
       objectStore = db.transaction(objectStoreName)
                       .objectStore(objectStoreName);
 
       let keyIndex = 0;
 
       request = objectStore.index("weight").openKeyCursor();
       request.onerror = errorHandler;
--- a/dom/indexedDB/test/test_object_identity.html
+++ b/dom/indexedDB/test/test_object_identity.html
@@ -23,17 +23,17 @@
       let objectStore1 = db.createObjectStore("foo");
       let objectStore2 = transaction.objectStore("foo");
       ok(objectStore1 === objectStore2, "Got same objectStores");
 
       let index1 = objectStore1.createIndex("bar", "key");
       let index2 = objectStore2.index("bar");
       ok(index1 === index2, "Got same indexes");
 
-      transaction.oncomplete = continueToNextStep;
+      request.onsuccess = continueToNextStep;
       yield;
 
       transaction = db.transaction("foo");
 
       let objectStore3 = transaction.objectStore("foo");
       let objectStore4 = transaction.objectStore("foo");
       ok(objectStore3 === objectStore4, "Got same objectStores");
 
--- a/dom/indexedDB/test/test_odd_result_order.html
+++ b/dom/indexedDB/test/test_odd_result_order.html
@@ -24,17 +24,17 @@
       ok(db instanceof IDBDatabase, "Got a real database");
 
       db.onerror = errorHandler;
 
       let objectStore = db.createObjectStore("foo", { keyPath: "key",
                                                       autoIncrement: true });
       let index = objectStore.createIndex("foo", "index");
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
       yield;
 
       objectStore = db.transaction("foo", IDBTransaction.READ_WRITE)
                       .objectStore("foo");
       request = objectStore.add(data);
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
--- a/dom/indexedDB/test/test_open_objectStore.html
+++ b/dom/indexedDB/test/test_open_objectStore.html
@@ -15,28 +15,28 @@
       const nsIIDBObjectStore = Components.interfaces.nsIIDBObjectStore;
       const name = window.location.pathname;
       const description = "My Test Database";
       const objectStoreName = "Objects";
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       is(db.objectStoreNames.length, 0, "Bad objectStores list");
 
       let objectStore = db.createObjectStore(objectStoreName,
                                              { keyPath: "foo" });
 
       is(db.objectStoreNames.length, 1, "Bad objectStores list");
       is(db.objectStoreNames.item(0), objectStoreName, "Bad name");
 
-      continueToNextStep();
       yield;
 
       objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
 
       is(objectStore.name, objectStoreName, "Bad name");
       is(objectStore.keyPath, "foo", "Bad keyPath");
       if(objectStore.indexNames.length, 0, "Bad indexNames");
 
--- a/dom/indexedDB/test/test_overlapping_transactions.html
+++ b/dom/indexedDB/test/test_overlapping_transactions.html
@@ -21,17 +21,17 @@
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
 
-      event.target.transaction.oncomplete = grabEventAndContinueHandler;
+      event.target.onsuccess = grabEventAndContinueHandler;
       for (let i in objectStores) {
         db.createObjectStore(objectStores[i], { autoIncrement: true });
       }
       let event = yield;
 
       is(db.objectStoreNames.length, objectStores.length,
          "Correct objectStoreNames list");
 
--- a/dom/indexedDB/test/test_readonly_transactions.html
+++ b/dom/indexedDB/test/test_readonly_transactions.html
@@ -17,23 +17,26 @@
 
       const name = window.location.pathname;
       const description = "My Test Database";
       const osName = "foo";
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       is(db.objectStoreNames.length, 0, "Correct objectStoreNames list");
 
       db.createObjectStore(osName, { autoIncrement: "true" });
 
+      yield;
+
       let key1, key2;
 
       request = db.transaction([osName], READ_WRITE)
                   .objectStore(osName)
                   .add({});
       request.onerror = errorHandler;
       request.onsuccess = function(event) {
         is(event.target.transaction.mode, READ_WRITE, "Correct mode");
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_setVersion_exclusion.html
@@ -0,0 +1,90 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7">
+    function testSteps()
+    {
+      const name = window.location.pathname;
+
+      let request = mozIndexedDB.open(name, 1);
+      request.onerror = errorHandler;
+      request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = unexpectedSuccessHandler;
+
+      let request2 = mozIndexedDB.open(name, 2);
+      request2.onerror = errorHandler;
+      request2.onupgradeneeded = unexpectedSuccessHandler;
+
+      let event = yield;
+      is(event.type, "upgradeneeded", "Expect an upgradeneeded event");
+      is(event.target, request, "Event should be fired on the request");
+      ok(event.target.result instanceof IDBDatabase, "Expect a database here");
+
+      let db = event.target.result;
+      is(db.version, 1, "Database has correct version");
+
+      db.onupgradeneeded = function() {
+        ok(false, "our ongoing VERSION_CHANGE transaction should exclude any others!");
+      }
+
+      db.createObjectStore("foo");
+
+      try {
+        db.transaction("foo");
+        ok(false, "Transactions should be disallowed now!");
+      } catch (e) {
+        ok(e instanceof IDBDatabaseException, "Expect an IDBException");
+        is(e.code, IDBDatabaseException.NOT_ALLOWED_ERR, "Expect a NOT_ALLOWED_ERR");
+      }
+
+      request.transaction.oncomplete = grabEventAndContinueHandler;
+
+      yield;
+
+      // The database is still not fully open here.
+      try {
+        db.transaction("foo");
+        ok(false, "Transactions should be disallowed now!");
+      } catch (e) {
+        ok(e instanceof IDBDatabaseException, "Expect an IDBException");
+        is(e.code, IDBDatabaseException.NOT_ALLOWED_ERR, "Expect a NOT_ALLOWED_ERR");
+      }
+
+      request.onsuccess = grabEventAndContinueHandler;
+
+      yield;
+
+      db.onversionchange = function() {
+        ok(true, "next setVersion was unblocked appropriately");
+        db.close();
+      }
+
+      try {
+        db.transaction("foo");
+        ok(true, "Transactions should be allowed now!");
+      } catch (e) {
+        ok(false, "Transactions should be allowed now!");
+      }
+
+      request2.onupgradeneeded = null;
+
+      finishTest();
+      yield;
+    }
+
+  </script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
--- a/dom/indexedDB/test/test_success_events_after_abort.html
+++ b/dom/indexedDB/test/test_success_events_after_abort.html
@@ -14,17 +14,17 @@
     {
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       let objectStore = db.createObjectStore("foo");
       objectStore.add({}, 1).onerror = errorHandler;
 
       yield;
 
       objectStore = db.transaction("foo").objectStore("foo");
 
--- a/dom/indexedDB/test/test_transaction_abort.html
+++ b/dom/indexedDB/test/test_transaction_abort.html
@@ -24,16 +24,17 @@
 
       const name = window.location.pathname;
       const description = "My Test Database";
 
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       let transaction;
       let objectStore;
 
       transaction = event.target.transaction;
@@ -152,16 +153,18 @@
       try {
         objectStore.deleteIndex("bar");
         ok(false, "Should have thrown");
       }
       catch (e) {
         ok(true, "RemoveIndex threw");
       }
 
+      yield;
+
       request = db.transaction("foo", READ_WRITE).objectStore("foo").add({});
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       event.target.transaction.onabort = function(event) {
         ok(false, "Shouldn't see an abort event!");
       };
--- a/dom/indexedDB/test/test_transaction_lifetimes.html
+++ b/dom/indexedDB/test/test_transaction_lifetimes.html
@@ -15,17 +15,17 @@
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
 
       db.createObjectStore("foo", { autoIncrement: true });
       yield;
 
       let transaction = db.transaction("foo");
       continueToNextStep();
       yield;
 
--- a/dom/indexedDB/test/test_transaction_lifetimes_nested.html
+++ b/dom/indexedDB/test/test_transaction_lifetimes_nested.html
@@ -15,17 +15,17 @@
       let request = mozIndexedDB.open(window.location.pathname, 1);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
       db.onerror = errorHandler;
 
-      event.target.transaction.oncomplete = continueToNextStep;
+      event.target.onsuccess = continueToNextStep;
       db.createObjectStore("foo");
       yield;
 
       let transaction1 = db.transaction("foo");
       is(transaction1.readyState, IDBTransaction.INITIAL, "Correct readyState");
 
       let transaction2;
 
--- a/dom/indexedDB/test/test_writer_starvation.html
+++ b/dom/indexedDB/test/test_writer_starvation.html
@@ -18,33 +18,33 @@
         Components.interfaces.nsIIDBTransaction.VERSION_CHANGE;
 
       const name = window.location.pathname;
       const description = "My Test Database";
 
       let request = mozIndexedDB.open(name, 1, description);
       request.onerror = errorHandler;
       request.onupgradeneeded = grabEventAndContinueHandler;
+      request.onsuccess = grabEventAndContinueHandler;
       let event = yield;
 
       let db = event.target.result;
 
       is(event.target.transaction.mode, VERSION_CHANGE, "Correct mode");
 
       let objectStore = db.createObjectStore("foo", { autoIncrement: true });
 
       request = objectStore.add({});
       request.onerror = errorHandler;
       request.onsuccess = grabEventAndContinueHandler;
       event = yield;
 
       let key = event.target.result;
       ok(key, "Got a key");
 
-      SimpleTest.executeSoon(function() { testGenerator.next(); });
       yield;
 
       let continueReading = true;
       let readerCount = 0;
       let callbackCount = 0;
       let finalCallbackCount = 0;
 
       // Generate a bunch of reads right away without returning to the event
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -177,17 +177,17 @@ CPPSRCS		= \
 		Unicode.cpp \
 		$(NULL)
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 INSTALLED_HEADERS = \
 		js-config.h \
-		jsautocfg.h \
+		jscpucfg.h \
 		$(CURDIR)/jsautokw.h \
 		js.msg \
 		jsalloc.h \
 		jsapi.h \
 		jsatom.h \
 		jsclass.h \
 		jsclist.h \
 		jsclone.h \
@@ -537,20 +537,16 @@ VPATH += $(srcdir)/perf
 INSTALLED_HEADERS += jsperf.h
 CPPSRCS += jsperf.cpp
 ifdef HAVE_LINUX_PERF_EVENT_H
 CPPSRCS += pm_linux.cpp
 else
 CPPSRCS += pm_stub.cpp
 endif
 
-ifeq ($(OS_ARCH),WINNT)
-INSTALLED_HEADERS += jscpucfg.h
-endif
-
 EXPORTS = $(INSTALLED_HEADERS)
 
 DASH_R		= -r
 
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
 SDK_LIBRARY = $(IMPORT_LIBRARY)
 else
 SDK_LIBRARY = $(SHARED_LIBRARY)
@@ -755,22 +751,16 @@ DEFINES		+= -DEXPORT_JS_API
 
 # mfbt is always packed with us, so if we're building a shared object,
 # we need to declare "exported" mfbt symbols on its behalf when we use
 # its headers.
 DEFINES		+= -DIMPL_MFBT
 
 INCLUDES	+= -I$(srcdir)
 
-GARBAGE		+= jscpucfg.o jsautocfg.h jsautocfg.tmp jscpucfg
-
-ifneq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
-TARGETS		+= jscpucfg$(HOST_BIN_SUFFIX)
-endif
-
 ifdef JS_THREADSAFE
 DEFINES		+= -DJS_THREADSAFE
 endif
 
 ifdef JS_HAS_CTYPES
 DEFINES		+= -DJS_HAS_CTYPES
 DEFINES         += -DDLL_PREFIX=\"$(DLL_PREFIX)\" -DDLL_SUFFIX=\"$(DLL_SUFFIX)\"
 endif
@@ -875,44 +865,16 @@ jsatom.o: jsatom.cpp Makefile.in
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 jsdtoa.o: jsdtoa.cpp Makefile.in
 	$(REPORT_BUILD)
 	@$(MAKE_DEPS_AUTO_CXX)
 	$(CXX) -o $@ -c $(filter-out $(MOZ_OPTIMIZE_FLAGS), $(COMPILE_CFLAGS)) $<
 endif
 
-export:: jsautocfg.h
-
-ifeq (,$(CROSS_COMPILE)$(GNU_CC)$(filter-out WINNT,$(OS_ARCH)))
-jsautocfg.h:
-	$(TOUCH) $@
-else
-jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
-	@$(RM) $@ jsautocfg.tmp
-	./jscpucfg > jsautocfg.tmp
-	mv jsautocfg.tmp $@
-endif
-
-# jscpucfg is a strange target
-# Needs to be built with the host compiler but needs to include
-# the mdcpucfg for the target so it needs the appropriate target defines
-ifdef HOST_NSPR_MDCPUCFG
-HOST_CXX := $(HOST_CXX) -DMDCPUCFG=$(TARGET_NSPR_MDCPUCFG)
-HOST_CXXFLAGS := $(patsubst -DXP_%,,$(HOST_CXXFLAGS))
-endif
-
-ifdef CROSS_COMPILE
-# jscpucfg needs to know when it's supposed to produce a config for the target
-JSCPUCFG_DEFINES = $(ACDEFINES)
-endif
-
-jscpucfg$(HOST_BIN_SUFFIX): jscpucfg.cpp Makefile.in
-	$(HOST_CXX) $(HOST_CXXFLAGS) $(JSCPUCFG_DEFINES) $(DEFINES) $(NSPR_CFLAGS) $(HOST_OUTOPTION)$@ $<
-
 # Compute the linker flags that programs linking against SpiderMonkey should
 # pass to get SpiderMonkey and its dependencies, beyond just the -L and -l
 # for the SpiderMonkey library itself.
 # - EXTRA_DSO_LDOPTS includes the NSPR -L and -l flags.
 # - OS_LIBS includes libraries selected by the configure script.
 # - EXTRA_LIBS includes libraries selected by this Makefile.
 JS_CONFIG_LIBS=$(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) 
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2713,16 +2713,21 @@ elif test "$moz_cv_size_of_JS_BYTES_PER_
   AC_DEFINE(JS_BITS_PER_WORD_LOG2, 6)
 else
   AC_MSG_ERROR([Unexpected JS_BYTES_PER_WORD])
 fi
 
 MOZ_ALIGN_OF_TYPE(JS_ALIGN_OF_POINTER, void*, 2 4 8 16)
 MOZ_SIZE_OF_TYPE(JS_BYTES_PER_DOUBLE, double, 6 8 10 12 14)
 
+AC_CHECK_HEADERS(endian.h)
+if test "$ac_cv_header_endian_h" = yes; then
+    AC_DEFINE(JS_HAVE_ENDIAN_H)
+fi
+
 dnl Check for int16_t, int32_t, int64_t, int64, uint, uint_t, and uint16_t.
 dnl ========================================================
 AC_MSG_CHECKING(for int16_t)
 AC_CACHE_VAL(ac_cv_int16_t,
  [AC_TRY_COMPILE([#include <stdio.h>
                   #include <sys/types.h>],
                  [int16_t foo = 0;],
                  [ac_cv_int16_t=true],
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -46,18 +46,16 @@
 #include "frontend/FoldConstants.h"
 #include "vm/GlobalObject.h"
 
 #include "jsinferinlines.h"
 
 using namespace js;
 using namespace js::frontend;
 
-namespace js {
-
 /*
  * Compile a top-level script.
  */
 BytecodeCompiler::BytecodeCompiler(JSContext *cx, JSPrincipals *prin, StackFrame *cfp)
   : parser(cx, prin, cfp), globalScope(NULL)
 {}
 
 JSScript *
@@ -69,17 +67,17 @@ BytecodeCompiler::compileScript(JSContex
                                 uintN staticLevel /* = 0 */)
 {
     TokenKind tt;
     ParseNode *pn;
     JSScript *script;
     bool inDirectivePrologue;
 
     JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL | TCF_NEED_MUTABLE_SCRIPT |
-                            TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_OBJECT)));
+                            TCF_COMPILE_FOR_EVAL | TCF_NEED_SCRIPT_GLOBAL)));
 
     /*
      * The scripted callerFrame can only be given for compile-and-go scripts
      * and non-zero static level requires callerFrame.
      */
     JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
     JS_ASSERT_IF(staticLevel != 0, callerFrame);
 
@@ -471,10 +469,8 @@ BytecodeCompiler::compileFunctionBody(JS
 
             if (!EmitFunctionScript(cx, &funcg, pn))
                 pn = NULL;
         }
     }
 
     return pn != NULL;
 }
-
-} /* namespace js */
--- a/js/src/frontend/BytecodeGenerator.cpp
+++ b/js/src/frontend/BytecodeGenerator.cpp
@@ -88,30 +88,28 @@
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 #ifdef JS_TRACER
 extern uint8 js_opcode2extra[];
 #endif
 
-namespace js {
-namespace frontend {
-
 static JSBool
 NewTryNote(JSContext *cx, CodeGenerator *cg, JSTryNoteKind kind, uintN stackDepth,
            size_t start, size_t end);
 
 static bool
 EmitIndexOp(JSContext *cx, JSOp op, uintN index, CodeGenerator *cg, JSOp *psuffix = NULL);
 
 static JSBool
 EmitLeaveBlock(JSContext *cx, CodeGenerator *cg, JSOp op, ObjectBox *box);
 
-} /* namespace frontend */
+static JSBool
+SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset);
 
 void
 TreeContext::trace(JSTracer *trc)
 {
     bindings.trace(trc);
 }
 
 CodeGenerator::CodeGenerator(Parser *parser, uintN lineno)
@@ -157,18 +155,16 @@ CodeGenerator::~CodeGenerator()
     cx->free_(main.base);
     cx->free_(main.notes);
 
     /* NB: non-null only after OOM. */
     if (spanDeps)
         cx->free_(spanDeps);
 }
 
-namespace frontend {
-
 static ptrdiff_t
 EmitCheck(JSContext *cx, CodeGenerator *cg, ptrdiff_t delta)
 {
     jsbytecode *base = CG_BASE(cg);
     jsbytecode *newbase;
     jsbytecode *next = CG_NEXT(cg);
     jsbytecode *limit = CG_LIMIT(cg);
     ptrdiff_t offset = next - base;
@@ -264,61 +260,61 @@ static inline void
 UpdateDecomposeLength(CodeGenerator *cg, uintN start)
 {
     uintN end = CG_OFFSET(cg);
     JS_ASSERT(uintN(end - start) < 256);
     CG_CODE(cg, start)[-1] = end - start;
 }
 
 ptrdiff_t
-Emit1(JSContext *cx, CodeGenerator *cg, JSOp op)
+frontend::Emit1(JSContext *cx, CodeGenerator *cg, JSOp op)
 {
     ptrdiff_t offset = EmitCheck(cx, cg, 1);
 
     if (offset >= 0) {
         *CG_NEXT(cg)++ = (jsbytecode)op;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
-Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1)
+frontend::Emit2(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1)
 {
     ptrdiff_t offset = EmitCheck(cx, cg, 2);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         CG_NEXT(cg) = next + 2;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
-Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1,
-         jsbytecode op2)
+frontend::Emit3(JSContext *cx, CodeGenerator *cg, JSOp op, jsbytecode op1,
+                    jsbytecode op2)
 {
     ptrdiff_t offset = EmitCheck(cx, cg, 3);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = op1;
         next[2] = op2;
         CG_NEXT(cg) = next + 3;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
-Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
+frontend::Emit5(JSContext *cx, CodeGenerator *cg, JSOp op, uint16 op1, uint16 op2)
 {
     ptrdiff_t offset = EmitCheck(cx, cg, 5);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         next[0] = (jsbytecode)op;
         next[1] = UINT16_HI(op1);
         next[2] = UINT16_LO(op1);
@@ -326,17 +322,17 @@ Emit5(JSContext *cx, CodeGenerator *cg, 
         next[4] = UINT16_LO(op2);
         CG_NEXT(cg) = next + 5;
         UpdateDepth(cx, cg, offset);
     }
     return offset;
 }
 
 ptrdiff_t
-EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra)
+frontend::EmitN(JSContext *cx, CodeGenerator *cg, JSOp op, size_t extra)
 {
     ptrdiff_t length = 1 + (ptrdiff_t)extra;
     ptrdiff_t offset = EmitCheck(cx, cg, length);
 
     if (offset >= 0) {
         jsbytecode *next = CG_NEXT(cg);
         *next = (jsbytecode)op;
         memset(next + 1, 0, BYTECODE_SIZE(extra));
@@ -553,17 +549,18 @@ AddJumpTarget(AddJumpTargetArgs *args, J
 
     jt->balance += balanceDelta;
     return (balanceDelta && jt->balance)
            ? 1 - BalanceJumpTargets(jtp)
            : 0;
 }
 
 #ifdef DEBUG_brendan
-static int AVLCheck(JumpTarget *jt)
+static int
+AVLCheck(JumpTarget *jt)
 {
     int lh, rh;
 
     if (!jt) return 0;
     JS_ASSERT(-1 <= jt->balance && jt->balance <= 1);
     lh = AVLCheck(jt->kids[JT_LEFT]);
     rh = AVLCheck(jt->kids[JT_RIGHT]);
     JS_ASSERT(jt->balance == rh - lh);
@@ -1262,33 +1259,31 @@ GetJumpOffset(CodeGenerator *cg, jsbytec
     ptrdiff_t top = sd->top;
     while (--sd >= cg->spanDeps && sd->top == top)
         continue;
     sd++;
     return JT_CLR_TAG(jt)->offset - sd->offset;
 }
 
 JSBool
-SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off)
+frontend::SetJumpOffset(JSContext *cx, CodeGenerator *cg, jsbytecode *pc, ptrdiff_t off)
 {
     if (!cg->spanDeps) {
         if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) {
             SET_JUMP_OFFSET(pc, off);
             return JS_TRUE;
         }
 
         if (!BuildSpanDepTable(cx, cg))
             return JS_FALSE;
     }
 
     return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off);
 }
 
-} /* namespace frontend */
-
 bool
 TreeContext::inStatement(StmtType type)
 {
     for (StmtInfo *stmt = topStmt; stmt; stmt = stmt->down) {
         if (stmt->type == type)
             return true;
     }
     return false;
@@ -1339,48 +1334,46 @@ TreeContext::skipSpansGenerator(unsigned
         if (!tc)
             return false;
         if (tc->flags & TCF_FUN_IS_GENERATOR)
             return true;
     }
     return false;
 }
 
-namespace frontend {
-
 bool
-SetStaticLevel(TreeContext *tc, uintN staticLevel)
+frontend::SetStaticLevel(TreeContext *tc, uintN staticLevel)
 {
     /*
      * This is a lot simpler than error-checking every UpvarCookie::set, and
      * practically speaking it leaves more than enough room for upvars.
      */
     if (UpvarCookie::isLevelReserved(staticLevel)) {
         JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
                              JSMSG_TOO_DEEP, js_function_str);
         return false;
     }
     tc->staticLevel = staticLevel;
     return true;
 }
 
 bool
-GenerateBlockId(TreeContext *tc, uint32& blockid)
+frontend::GenerateBlockId(TreeContext *tc, uint32& blockid)
 {
     if (tc->blockidGen == JS_BIT(20)) {
         JS_ReportErrorNumber(tc->parser->context, js_GetErrorMessage, NULL,
                              JSMSG_NEED_DIET, "program");
         return false;
     }
     blockid = tc->blockidGen++;
     return true;
 }
 
 void
-PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top)
+frontend::PushStatement(TreeContext *tc, StmtInfo *stmt, StmtType type, ptrdiff_t top)
 {
     stmt->type = type;
     stmt->flags = 0;
     stmt->blockid = tc->blockid();
     SET_STATEMENT_TOP(stmt, top);
     stmt->label = NULL;
     JS_ASSERT(!stmt->blockBox);
     stmt->down = tc->topStmt;
@@ -1389,17 +1382,17 @@ PushStatement(TreeContext *tc, StmtInfo 
         stmt->downScope = tc->topScopeStmt;
         tc->topScopeStmt = stmt;
     } else {
         stmt->downScope = NULL;
     }
 }
 
 void
-PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top)
+frontend::PushBlockScope(TreeContext *tc, StmtInfo *stmt, ObjectBox *blockBox, ptrdiff_t top)
 {
     PushStatement(tc, stmt, STMT_BLOCK, top);
     stmt->flags |= SIF_SCOPE;
     blockBox->parent = tc->blockChainBox;
     blockBox->object->setParent(tc->blockChain());
     stmt->downScope = tc->topScopeStmt;
     tc->topScopeStmt = stmt;
     tc->blockChainBox = blockBox;
@@ -1675,55 +1668,55 @@ BackPatch(JSContext *cx, CodeGenerator *
          */
         *pc = op;
         pc -= delta;
     }
     return JS_TRUE;
 }
 
 void
-PopStatementTC(TreeContext *tc)
+frontend::PopStatementTC(TreeContext *tc)
 {
     StmtInfo *stmt = tc->topStmt;
     tc->topStmt = stmt->down;
     if (STMT_LINKS_SCOPE(stmt)) {
         tc->topScopeStmt = stmt->downScope;
         if (stmt->flags & SIF_SCOPE) {
             tc->blockChainBox = stmt->blockBox->parent;
         }
     }
 }
 
 JSBool
-PopStatementCG(JSContext *cx, CodeGenerator *cg)
+frontend::PopStatementCG(JSContext *cx, CodeGenerator *cg)
 {
     StmtInfo *stmt = cg->topStmt;
     if (!STMT_IS_TRYING(stmt) &&
         (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) ||
          !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update),
                     JSOP_GOTO))) {
         return JS_FALSE;
     }
     PopStatementTC(cg);
     return JS_TRUE;
 }
 
 JSBool
-DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn)
+frontend::DefineCompileTimeConstant(JSContext *cx, CodeGenerator *cg, JSAtom *atom, ParseNode *pn)
 {
     /* XXX just do numbers for now */
     if (pn->isKind(TOK_NUMBER)) {
         if (!cg->constMap.put(atom, NumberValue(pn->pn_dval)))
             return JS_FALSE;
     }
     return JS_TRUE;
 }
 
 StmtInfo *
-LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt)
+frontend::LexicalLookup(TreeContext *tc, JSAtom *atom, jsint *slotp, StmtInfo *stmt)
 {
     if (!stmt)
         stmt = tc->topScopeStmt;
     for (; stmt; stmt = stmt->downScope) {
         if (stmt->type == STMT_WITH)
             break;
 
         /* Skip "maybe scope" statements that don't contain let bindings. */
@@ -1955,26 +1948,22 @@ EmitSlotIndexOp(JSContext *cx, JSOp op, 
         return JS_FALSE;
     pc = CG_CODE(cg, off);
     SET_UINT16(pc, slot);
     pc += 2;
     SET_INDEX(pc, index);
     return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0;
 }
 
-} /* namespace frontend */
-
 bool
 CodeGenerator::shouldNoteClosedName(ParseNode *pn)
 {
     return !callsEval() && pn->isDefn() && pn->isClosed();
 }
 
-namespace frontend {
-
 /*
  * Adjust the slot for a block local to account for the number of variables
  * that share the same index space with locals. Due to the incremental code
  * generation for top-level script, we do the adjustment via code patching in
  * BytecodeCompiler::compileScript; see comments there.
  *
  * The function returns -1 on failures.
  */
@@ -2047,17 +2036,17 @@ EmitEnterBlock(JSContext *cx, ParseNode 
     return true;
 }
 
 static JSBool
 EmitLeaveBlock(JSContext *cx, CodeGenerator *cg, JSOp op, ObjectBox *box)
 {
     JSOp bigSuffix;
     uintN count = OBJ_BLOCK_COUNT(cx, box->object);
-    
+
     bigSuffix = EmitBigIndexPrefix(cx, cg, box->index);
     if (bigSuffix == JSOP_FALSE)
         return JS_FALSE;
     if (Emit5(cx, cg, op, count, box->index) < 0)
         return JS_FALSE;
     return bigSuffix == JSOP_NOP || Emit1(cx, cg, bigSuffix) >= 0;
 }
 
@@ -2080,21 +2069,22 @@ EmitLeaveBlock(JSContext *cx, CodeGenera
  *   {
  *     undeclared = 17; // throws ReferenceError
  *   }
  *   foo();
  */
 static bool
 TryConvertToGname(CodeGenerator *cg, ParseNode *pn, JSOp *op)
 {
-    if (cg->compileAndGo() && 
+    if (cg->compileAndGo() &&
         cg->compiler()->globalScope->globalObj &&
         !cg->mightAliasLocals() &&
         !pn->isDeoptimized() &&
-        !(cg->flags & TCF_STRICT_MODE_CODE)) { 
+        !(cg->flags & TCF_STRICT_MODE_CODE))
+    {
         switch (*op) {
           case JSOP_NAME:     *op = JSOP_GETGNAME; break;
           case JSOP_SETNAME:  *op = JSOP_SETGNAME; break;
           case JSOP_INCNAME:  *op = JSOP_INCGNAME; break;
           case JSOP_NAMEINC:  *op = JSOP_GNAMEINC; break;
           case JSOP_DECNAME:  *op = JSOP_DECGNAME; break;
           case JSOP_NAMEDEC:  *op = JSOP_GNAMEDEC; break;
           case JSOP_SETCONST:
@@ -2518,18 +2508,16 @@ BindNameToSlot(JSContext *cx, CodeGenera
 
     JS_ASSERT(!pn->isOp(op));
     pn->setOp(op);
     pn->pn_cookie.set(0, cookie.slot());
     pn->pn_dflags |= PND_BOUND;
     return JS_TRUE;
 }
 
-} /* namespace frontend */
-
 bool
 CodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie *cookie)
 {
     if (!globalMap.ensureMap(context()))
         return false;
 
     AtomIndexAddPtr p = globalMap->lookupForAdd(atom);
     if (p) {
@@ -2554,18 +2542,16 @@ CodeGenerator::addGlobalUse(JSAtom *atom
 
     GlobalSlotArray::Entry entry = { allAtomIndex, slot };
     if (!globalUses.append(entry))
         return false;
 
     return globalMap->add(p, atom, globalUseIndex);
 }
 
-namespace frontend {
-
 /*
  * If pn contains a useful expression, return true with *answer set to true.
  * If pn contains a useless expression, return true with *answer set to false.
  * Return false on error.
  *
  * The caller should initialize *answer to false and invoke this function on
  * an expression statement or similar subtree to decide whether the tree could
  * produce code that has any side effects.  For an expression statement, we
@@ -2683,16 +2669,19 @@ CheckSideEffects(JSContext *cx, CodeGene
                 if (pn2->isConst()) {
                     *answer = JS_FALSE;
                     break;
                 }
                 /* FALL THROUGH */
               case TOK_DOT:
 #if JS_HAS_XML_SUPPORT
               case TOK_DBLDOT:
+                JS_ASSERT_IF(pn2->getKind() == TOK_DBLDOT, !cg->inStrictMode());
+                /* FALL THROUGH */
+
 #endif
               case TOK_LP:
               case TOK_LB:
                 /* All these delete addressing modes have effects too. */
                 *answer = JS_TRUE;
                 break;
               default:
                 ok = CheckSideEffects(cx, cg, pn2, answer);
@@ -2815,16 +2804,17 @@ EmitNameOp(JSContext *cx, CodeGenerator 
 
     return JS_TRUE;
 }
 
 #if JS_HAS_XML_SUPPORT
 static bool
 EmitXMLName(JSContext *cx, ParseNode *pn, JSOp op, CodeGenerator *cg)
 {
+    JS_ASSERT(!cg->inStrictMode());
     JS_ASSERT(pn->isKind(TOK_UNARYOP));
     JS_ASSERT(pn->isOp(JSOP_XMLNAME));
     JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
 
     ParseNode *pn2 = pn->pn_kid;
     uintN oldflags = cg->flags;
     cg->flags &= ~TCF_IN_FOR_INIT;
     if (!EmitTree(cx, cg, pn2))
@@ -3914,17 +3904,17 @@ out:
     return ok;
 
 bad:
     ok = JS_FALSE;
     goto out;
 }
 
 JSBool
-EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body)
+frontend::EmitFunctionScript(JSContext *cx, CodeGenerator *cg, ParseNode *body)
 {
     /*
      * The decompiler has assumptions about what may occur immediately after
      * script->main (e.g., in the case of destructuring params). Thus, put the
      * following ops into the range [script->code, script->main). Note:
      * execution starts from script->code, so this has no semantic effect.
      */
 
@@ -4617,17 +4607,19 @@ EmitAssignment(JSContext *cx, CodeGenera
 #endif
       case TOK_LP:
         if (!EmitTree(cx, cg, lhs))
             return false;
         offset++;
         break;
 #if JS_HAS_XML_SUPPORT
       case TOK_UNARYOP:
+        JS_ASSERT(!cg->inStrictMode());
         JS_ASSERT(lhs->isOp(JSOP_SETXMLNAME));
+
         if (!EmitTree(cx, cg, lhs->pn_kid))
             return false;
         if (Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
             return false;
         offset++;
         break;
 #endif
       default:
@@ -4744,16 +4736,17 @@ EmitAssignment(JSContext *cx, CodeGenera
       case TOK_RB:
       case TOK_RC:
         if (!EmitDestructuringOps(cx, cg, JSOP_SETNAME, lhs))
             return false;
         break;
 #endif
 #if JS_HAS_XML_SUPPORT
       case TOK_UNARYOP:
+        JS_ASSERT(!cg->inStrictMode());
         if (Emit1(cx, cg, JSOP_SETXMLNAME) < 0)
             return false;
         break;
 #endif
       default:
         JS_ASSERT(0);
     }
     return true;
@@ -4810,18 +4803,16 @@ EmitEndInit(JSContext *cx, CodeGenerator
 #if JS_HAS_SHARP_VARS
     /* Emit an op for sharp array cleanup and decompilation. */
     if (cg->hasSharps() && count != 0)
         EMIT_UINT16_IMM_OP(JSOP_SHARPINIT, cg->sharpSlotBase);
 #endif
     return Emit1(cx, cg, JSOP_ENDINIT) >= 0;
 }
 
-} /* namespace frontend */
-
 bool
 ParseNode::getConstantValue(JSContext *cx, bool strictChecks, Value *vp)
 {
     switch (getKind()) {
       case TOK_NUMBER:
         vp->setNumber(pn_dval);
         return true;
       case TOK_STRING:
@@ -4839,17 +4830,17 @@ ParseNode::getConstantValue(JSContext *c
             vp->setBoolean(true);
             return true;
           default:
             JS_NOT_REACHED("Unexpected node");
             return false;
         }
       case TOK_RB: {
         JS_ASSERT(isOp(JSOP_NEWINIT) && !(pn_xflags & PNX_NONCONST));
- 
+
         JSObject *obj = NewDenseAllocatedArray(cx, pn_count);
         if (!obj)
             return false;
 
         unsigned idx = 0;
         for (ParseNode *pn = pn_head; pn; idx++, pn = pn->pn_next) {
             Value value;
             if (!pn->getConstantValue(cx, strictChecks, &value))
@@ -4903,18 +4894,16 @@ ParseNode::getConstantValue(JSContext *c
         return true;
       }
       default:
         JS_NOT_REACHED("Unexpected node");
     }
     return false;
 }
 
-namespace frontend {
-
 static bool
 EmitSingletonInitialiser(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
 {
     Value value;
     if (!pn->getConstantValue(cx, cg->needStrictChecks(), &value))
         return false;
 
     JS_ASSERT(value.isObject());
@@ -5071,17 +5060,17 @@ EmitTry(JSContext *cx, CodeGenerator *cg
 
     ptrdiff_t tryEnd = CG_OFFSET(cg);
 
     ObjectBox *prevBox = NULL;
     /* If this try has a catch block, emit it. */
     ParseNode *lastCatch = NULL;
     if (ParseNode *pn2 = pn->pn_kid2) {
         uintN count = 0;    /* previous catch block's population */
-        
+
         /*
          * The emitted code for a catch block looks like:
          *
          * blockchain
          * [throwing]                          only if 2nd+ catch block
          * [leaveblock]                        only if 2nd+ catch block
          * enterblock                          with SRC_CATCH
          * exception
@@ -5103,17 +5092,17 @@ EmitTry(JSContext *cx, CodeGenerator *cg
         for (ParseNode *pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
             ptrdiff_t guardJump, catchNote;
 
             JS_ASSERT(cg->stackDepth == depth);
             guardJump = GUARDJUMP(stmtInfo);
             if (guardJump != -1) {
                 if (EmitKnownBlockChain(cx, cg, prevBox) < 0)
                     return false;
-            
+
                 /* Fix up and clean up previous catch block. */
                 CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, guardJump);
 
                 /*
                  * Account for JSOP_ENTERBLOCK (whose block object count
                  * is saved below) and pushed exception object that we
                  * still have after the jumping from the previous guard.
                  */
@@ -5187,17 +5176,17 @@ EmitTry(JSContext *cx, CodeGenerator *cg
      * Last catch guard jumps to the rethrow code sequence if none of the
      * guards match. Target guardJump at the beginning of the rethrow
      * sequence, just in case a guard expression throws and leaves the
      * stack unbalanced.
      */
     if (lastCatch && lastCatch->pn_kid2) {
         if (EmitKnownBlockChain(cx, cg, prevBox) < 0)
             return false;
-        
+
         CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, GUARDJUMP(stmtInfo));
 
         /* Sync the stack to take into account pushed exception. */
         JS_ASSERT(cg->stackDepth == depth);
         cg->stackDepth = depth + 1;
 
         /*
          * Rethrow the exception, delegating executing of finally if any
@@ -5407,24 +5396,27 @@ EmitLet(JSContext *cx, CodeGenerator *cg
     return true;
 }
 #endif
 
 #if JS_HAS_XML_SUPPORT
 static bool
 EmitXMLTag(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
 {
+    JS_ASSERT(!cg->inStrictMode());
+
     if (Emit1(cx, cg, JSOP_STARTXML) < 0)
         return false;
 
     {
         jsatomid index;
-        JSAtom *tmp = (pn->isKind(TOK_XMLETAGO)) ? cx->runtime->atomState.etagoAtom
-                                                 : cx->runtime->atomState.stagoAtom;
-        if (!cg->makeAtomIndex(tmp, &index))
+        JSAtom *tagAtom = (pn->isKind(TOK_XMLETAGO))
+                          ? cx->runtime->atomState.etagoAtom
+                          : cx->runtime->atomState.stagoAtom;
+        if (!cg->makeAtomIndex(tagAtom, &index))
             return false;
         EMIT_INDEX_OP(JSOP_STRING, index);
     }
 
     JS_ASSERT(pn->pn_count != 0);
     ParseNode *pn2 = pn->pn_head;
     if (pn2->isKind(TOK_LC) && Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0)
         return false;
@@ -5462,16 +5454,18 @@ EmitXMLTag(JSContext *cx, CodeGenerator 
         return false;
 
     return true;
 }
 
 static bool
 EmitXMLProcessingInstruction(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
 {
+    JS_ASSERT(!cg->inStrictMode());
+
     jsatomid index;
     if (!cg->makeAtomIndex(pn->pn_pidata, &index))
         return false;
     if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, cg))
         return false;
     if (!EmitAtomOp(cx, pn, JSOP_XMLPI, cg))
         return false;
     return true;
@@ -5840,17 +5834,17 @@ static inline bool
 EmitFor(JSContext *cx, CodeGenerator *cg, ParseNode *pn, ptrdiff_t top)
 {
     return pn->pn_left->isKind(TOK_IN)
            ? EmitForIn(cx, cg, pn, top)
            : EmitNormalFor(cx, cg, pn, top);
 }
 
 JSBool
-EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
+frontend::EmitTree(JSContext *cx, CodeGenerator *cg, ParseNode *pn)
 {
     JSBool useful, wantval;
     StmtInfo stmtInfo;
     StmtInfo *stmt;
     ptrdiff_t top, off, tmp, beq, jmp;
     ParseNode *pn2, *pn3;
     JSAtom *atom;
     jsatomid atomIndex;
@@ -6772,16 +6766,17 @@ EmitTree(JSContext *cx, CodeGenerator *c
             JS_ASSERT(js_CodeSpec[op].format & JOF_ELEM);
             if (Emit1(cx, cg, (JSOp)1) < 0)
                 return JS_FALSE;
             if (Emit1(cx, cg, JSOP_POP) < 0)
                 return JS_FALSE;
             break;
 #if JS_HAS_XML_SUPPORT
           case TOK_UNARYOP:
+            JS_ASSERT(!cg->inStrictMode());
             JS_ASSERT(pn2->isOp(JSOP_SETXMLNAME));
             if (!EmitTree(cx, cg, pn2->pn_kid))
                 return JS_FALSE;
             if (Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
                 return JS_FALSE;
             if (!EmitElemIncDec(cx, NULL, op, cg))
                 return JS_FALSE;
             break;
@@ -6809,16 +6804,17 @@ EmitTree(JSContext *cx, CodeGenerator *c
             }
             break;
           case TOK_DOT:
             if (!EmitPropOp(cx, pn2, JSOP_DELPROP, cg, JS_FALSE))
                 return JS_FALSE;
             break;
 #if JS_HAS_XML_SUPPORT
           case TOK_DBLDOT:
+            JS_ASSERT(!cg->inStrictMode());
             if (!EmitElemOp(cx, pn2, JSOP_DELDESC, cg))
                 return JS_FALSE;
             break;
 #endif
           case TOK_LB:
             if (!EmitElemOp(cx, pn2, JSOP_DELELEM, cg))
                 return JS_FALSE;
             break;
@@ -6848,16 +6844,18 @@ EmitTree(JSContext *cx, CodeGenerator *c
                 if (!SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
                     return JS_FALSE;
             }
         }
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_FILTER:
+        JS_ASSERT(!cg->inStrictMode());
+
         if (!EmitTree(cx, cg, pn->pn_left))
             return JS_FALSE;
         jmp = EmitJump(cx, cg, JSOP_FILTER, 0);
         if (jmp < 0)
             return JS_FALSE;
         top = EmitTraceOp(cx, cg, pn->pn_right);
         if (top < 0)
             return JS_FALSE;
@@ -6877,20 +6875,22 @@ EmitTree(JSContext *cx, CodeGenerator *c
         /*
          * Pop a stack operand, convert it to object, get a property named by
          * this bytecode's immediate-indexed atom operand, and push its value
          * (not a reference to it).
          */
         ok = EmitPropOp(cx, pn, pn->getOp(), cg, JS_FALSE);
         break;
 
-      case TOK_LB:
 #if JS_HAS_XML_SUPPORT
       case TOK_DBLDOT:
+        JS_ASSERT(!cg->inStrictMode());
+        /* FALL THROUGH */
 #endif
+      case TOK_LB:
         /*
          * Pop two operands, convert the left one to object and the right one
          * to property name (atom or tagged int), get the named property, and
          * push its value.  Set the "obj" register to the result of ToObject
          * on the left operand.
          */
         ok = EmitElemOp(cx, pn, pn->getOp(), cg);
         break;
@@ -6984,17 +6984,17 @@ EmitTree(JSContext *cx, CodeGenerator *c
       }
 
       case TOK_LEXICALSCOPE:
         if (!EmitLexicalScope(cx, cg, pn, ok))
             return false;
         break;
 
 #if JS_HAS_BLOCK_SCOPE
-      case TOK_LET: 
+      case TOK_LET:
         if (!EmitLet(cx, cg, pn))
             return false;
         break;
 #endif /* JS_HAS_BLOCK_SCOPE */
 
 #if JS_HAS_GENERATORS
       case TOK_ARRAYPUSH: {
         jsint slot;
@@ -7281,16 +7281,18 @@ EmitTree(JSContext *cx, CodeGenerator *c
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_XMLATTR:
       case TOK_XMLSPACE:
       case TOK_XMLTEXT:
       case TOK_XMLCDATA:
       case TOK_XMLCOMMENT:
+        JS_ASSERT(!cg->inStrictMode());
+        /* FALL THROUGH */
 #endif
       case TOK_STRING:
         ok = EmitAtomOp(cx, pn, pn->getOp(), cg);
         break;
 
       case TOK_NUMBER:
         ok = EmitNumberOp(cx, pn->pn_dval, cg);
         break;
@@ -7311,17 +7313,19 @@ EmitTree(JSContext *cx, CodeGenerator *c
       case TOK_DEBUGGER:
         if (Emit1(cx, cg, JSOP_DEBUGGER) < 0)
             return JS_FALSE;
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_XMLELEM:
       case TOK_XMLLIST:
+        JS_ASSERT(!cg->inStrictMode());
         JS_ASSERT(pn->isKind(TOK_XMLLIST) || pn->pn_count != 0);
+
         switch (pn->pn_head ? pn->pn_head->getKind() : TOK_XMLLIST) {
           case TOK_XMLETAGO:
             JS_ASSERT(0);
             /* FALL THROUGH */
           case TOK_XMLPTAGC:
           case TOK_XMLSTAGO:
             break;
           default:
@@ -7361,16 +7365,18 @@ EmitTree(JSContext *cx, CodeGenerator *c
       case TOK_XMLPTAGC:
       case TOK_XMLSTAGO:
       case TOK_XMLETAGO:
         if (!EmitXMLTag(cx, cg, pn))
             return false;
         break;
 
       case TOK_XMLNAME:
+        JS_ASSERT(!cg->inStrictMode());
+
         if (pn->isArity(PN_LIST)) {
             JS_ASSERT(pn->pn_count != 0);
             for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
                 if (pn2->isKind(TOK_LC) &&
                     Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
                     return JS_FALSE;
                 }
                 if (!EmitTree(cx, cg, pn2))
@@ -7434,17 +7440,17 @@ AllocSrcNote(JSContext *cx, CodeGenerato
         CG_NOTE_LIMIT(cg) = newlength;
     }
 
     CG_NOTE_COUNT(cg) = index + 1;
     return (intN)index;
 }
 
 intN
-NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type)
+frontend::NewSrcNote(JSContext *cx, CodeGenerator *cg, SrcNoteType type)
 {
     intN index, n;
     jssrcnote *sn;
     ptrdiff_t offset, delta, xdelta;
 
     /*
      * Claim a note slot in CG_NOTES(cg) by growing it if necessary and then
      * incrementing CG_NOTE_COUNT(cg).
@@ -7482,30 +7488,30 @@ NewSrcNote(JSContext *cx, CodeGenerator 
     for (n = (intN)js_SrcNoteSpec[type].arity; n > 0; n--) {
         if (NewSrcNote(cx, cg, SRC_NULL) < 0)
             return -1;
     }
     return index;
 }
 
 intN
-NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset)
+frontend::NewSrcNote2(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset)
 {
     intN index;
 
     index = NewSrcNote(cx, cg, type);
     if (index >= 0) {
         if (!SetSrcNoteOffset(cx, cg, index, 0, offset))
             return -1;
     }
     return index;
 }
 
 intN
-NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1,
+frontend::NewSrcNote3(JSContext *cx, CodeGenerator *cg, SrcNoteType type, ptrdiff_t offset1,
             ptrdiff_t offset2)
 {
     intN index;
 
     index = NewSrcNote(cx, cg, type);
     if (index >= 0) {
         if (!SetSrcNoteOffset(cx, cg, index, 0, offset1))
             return -1;
@@ -7525,17 +7531,17 @@ GrowSrcNotes(JSContext *cx, CodeGenerato
         return JS_FALSE;
     }
     CG_NOTES(cg) = newnotes;
     CG_NOTE_LIMIT(cg) = newlength;
     return JS_TRUE;
 }
 
 jssrcnote *
-AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta)
+frontend::AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta)
 {
     ptrdiff_t base, limit, newdelta, diff;
     intN index;
 
     /*
      * Called only from OptimizeSpanDeps and FinishTakingSrcNotes to add to
      * main script note deltas, and only by a small positive amount.
      */
@@ -7558,17 +7564,17 @@ AddToSrcNoteDelta(JSContext *cx, CodeGen
         cg->main.noteCount++;
         memmove(sn + 1, sn, SRCNOTE_SIZE(diff));
         SN_MAKE_XDELTA(sn, delta);
         sn++;
     }
     return sn;
 }
 
-JSBool
+static JSBool
 SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset)
 {
     jssrcnote *sn;
     ptrdiff_t diff;
 
     if ((jsuword)offset >= (jsuword)((ptrdiff_t)SN_3BYTE_OFFSET_FLAG << 16)) {
         ReportStatementTooLarge(cx, cg);
         return JS_FALSE;
@@ -7617,17 +7623,18 @@ SetSrcNoteOffset(JSContext *cx, CodeGene
 #ifdef DEBUG_notme
 #define DEBUG_srcnotesize
 #endif
 
 #ifdef DEBUG_srcnotesize
 #define NBINS 10
 static uint32 hist[NBINS];
 
-static void DumpSrcNoteSizeHist()
+static void
+DumpSrcNoteSizeHist()
 {
     static FILE *fp;
     int i, n;
 
     if (!fp) {
         fp = fopen("/tmp/srcnotes.hist", "w");
         if (!fp)
             return;
@@ -7647,17 +7654,17 @@ static void DumpSrcNoteSizeHist()
 /*
  * Fill in the storage at notes with prolog and main srcnotes; the space at
  * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from
  * BytecodeGenerator.h.  SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST
  * CHECKING WHETHER BytecodeGenerator.h's CG_COUNT_FINAL_SRCNOTES MACRO NEEDS
  * CORRESPONDING CHANGES!
  */
 JSBool
-FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes)
+frontend::FinishTakingSrcNotes(JSContext *cx, CodeGenerator *cg, jssrcnote *notes)
 {
     uintN prologCount, mainCount, totalCount;
     ptrdiff_t offset, delta;
     jssrcnote *sn;
 
     JS_ASSERT(cg->current == &cg->main);
 
     prologCount = cg->prolog.noteCount;
@@ -7728,32 +7735,30 @@ NewTryNote(JSContext *cx, CodeGenerator 
     tryNode->note.length = (uint32)(end - start);
     tryNode->prev = cg->lastTryNode;
     cg->lastTryNode = tryNode;
     cg->ntrynotes++;
     return JS_TRUE;
 }
 
 void
-FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array)
+frontend::FinishTakingTryNotes(CodeGenerator *cg, JSTryNoteArray *array)
 {
     TryNode *tryNode;
     JSTryNote *tn;
 
     JS_ASSERT(array->length > 0 && array->length == cg->ntrynotes);
     tn = array->vector + array->length;
     tryNode = cg->lastTryNode;
     do {
         *--tn = tryNode->note;
     } while ((tryNode = tryNode->prev) != NULL);
     JS_ASSERT(tn == array->vector);
 }
 
-} /* namespace frontend */
-
 /*
  * Find the index of the given object for code generator.
  *
  * Since the emitter refers to each parsed object only once, for the index we
  * use the number of already indexes objects. We also add the object to a list
  * to convert the list to a fixed-size array when we complete code generation,
  * see js::CGObjectList::finish below.
  *
@@ -7822,18 +7827,16 @@ GCConstList::finish(JSConstArray *array)
 {
     JS_ASSERT(array->length == list.length());
     Value *src = list.begin(), *srcend = list.end();
     Value *dst = array->vector;
     for (; src != srcend; ++src, ++dst)
         *dst = *src;
 }
 
-} /* namespace js */
-
 /*
  * We should try to get rid of offsetBias (always 0 or 1, where 1 is
  * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL.
  */
 JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = {
     {"null",            0,      0,      0},
     {"if",              0,      0,      0},
     {"if-else",         2,      0,      1},
--- a/js/src/frontend/BytecodeGenerator.h
+++ b/js/src/frontend/BytecodeGenerator.h
@@ -270,17 +270,17 @@ struct StmtInfo {
  * This flag is *not* inherited by enclosed or enclosing functions; it
  * applies only to the function in whose flags it appears.
  */
 #define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000
 
 /*
  * The caller is JS_Compile*Script*.
  */
-#define TCF_NEED_SCRIPT_OBJECT 0x40000000
+#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
 
 /*
  * Flags to check for return; vs. return expr; in a function.
  */
 #define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
 
 /*
  * Sticky deoptimization flags to propagate from FunctionBody.
@@ -1072,19 +1072,16 @@ NewSrcNote3(JSContext *cx, CodeGenerator
                ptrdiff_t offset2);
 
 /*
  * NB: this function can add at most one extra extended delta note.
  */
 jssrcnote *
 AddToSrcNoteDelta(JSContext *cx, CodeGenerator *cg, jssrcnote *sn, ptrdiff_t delta);
 
-JSBool
-SetSrcNoteOffset(JSContext *cx, CodeGenerator *cg, uintN index, uintN which, ptrdiff_t offset);
-
 /*
  * Finish taking source notes in cx's notePool, copying final notes to the new
  * stable store allocated by the caller and passed in via notes. Return false
  * on malloc failure, which means this function reported an error.
  *
  * To compute the number of jssrcnotes to allocate and pass in via notes, use
  * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
  * FinishTakingSrcNotes, so DON'T CHANGE js::frontend::FinishTakingSrcNotes
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -429,20 +429,18 @@ Boolish(ParseNode *pn)
       case JSOP_FALSE:
         return Falsy;
 
       default:
         return Unknown;
     }
 }
 
-namespace js {
-
 bool
-FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
+js::FoldConstants(JSContext *cx, ParseNode *pn, TreeContext *tc, bool inCond)
 {
     ParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
 
     JS_CHECK_RECURSION(cx, return false);
 
     switch (pn->getArity()) {
       case PN_FUNC:
       {
@@ -903,10 +901,8 @@ FoldConstants(JSContext *cx, ParseNode *
             pn->setKind(TOK_PRIMARY);
             pn->setOp(t == Truthy ? JSOP_TRUE : JSOP_FALSE);
             pn->setArity(PN_NULLARY);
         }
     }
 
     return true;
 }
-
-} /* namespace js */
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -51,18 +51,16 @@ using namespace js;
  * Asserts to verify assumptions behind pn_ macros.
  */
 #define pn_offsetof(m)  offsetof(ParseNode, m)
 
 JS_STATIC_ASSERT(pn_offsetof(pn_link) == pn_offsetof(dn_uses));
 
 #undef pn_offsetof
 
-namespace js {
-
 void
 ParseNode::become(ParseNode *pn2)
 {
     JS_ASSERT(!pn_defn);
     JS_ASSERT(!pn2->isDefn());
 
     JS_ASSERT(!pn_used);
     if (pn2->isUsed()) {
@@ -460,24 +458,20 @@ NameNode::create(JSAtom *atom, TreeConte
     ParseNode *pn = ParseNode::create(PN_NAME, tc);
     if (pn) {
         pn->pn_atom = atom;
         ((NameNode *)pn)->initCommon(tc);
     }
     return (NameNode *)pn;
 }
 
-} /* namespace js */
-
 const char js_argument_str[] = "argument";
 const char js_variable_str[] = "variable";
 const char js_unknown_str[]  = "unknown";
 
-namespace js {
-
 const char *
 Definition::kindString(Kind kind)
 {
     static const char *table[] = {
         js_var_str, js_const_str, js_let_str,
         js_function_str, js_argument_str, js_unknown_str
     };
 
@@ -597,17 +591,17 @@ CloneParseTree(ParseNode *opn, TreeConte
  *
  * opn must be the pn_head of a node produced by Parser::variables, so its form
  * is known to be LHS = NAME | [LHS] | {id:LHS}.
  *
  * The cloned tree is for use only in the same statement and binding context as
  * the original tree.
  */
 ParseNode *
-CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
+js::CloneLeftHandSide(ParseNode *opn, TreeContext *tc)
 {
     ParseNode *pn = tc->parser->new_<ParseNode>(opn->getKind(), opn->getOp(), opn->getArity(),
                                                 opn->pn_pos);
     if (!pn)
         return NULL;
     pn->setInParens(opn->isInParens());
     pn->setDefn(opn->isDefn());
     pn->setUsed(opn->isUsed());
@@ -665,10 +659,8 @@ CloneLeftHandSide(ParseNode *opn, TreeCo
             pn->pn_dflags &= ~PND_BOUND;
             pn->setDefn(false);
 
             LinkUseToDef(pn, (Definition *) opn, tc);
         }
     }
     return pn;
 }
-
-} /* namespace js */
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -581,26 +581,24 @@ static bool
 ReportBadParameter(JSContext *cx, TreeContext *tc, JSAtom *name, uintN errorNumber)
 {
     Definition *dn = tc->decls.lookupFirst(name);
     JSAutoByteString bytes;
     return js_AtomToPrintableString(cx, name, &bytes) &&
            ReportStrictModeError(cx, TS(tc->parser), tc, dn, errorNumber, bytes.ptr());
 }
 
-namespace js {
-
 /*
  * In strict mode code, all parameter names must be distinct, must not be
  * strict mode reserved keywords, and must not be 'eval' or 'arguments'.  We
  * must perform these checks here, and not eagerly during parsing, because a
  * function's body may turn on strict mode for the function head.
  */
 bool
-CheckStrictParameters(JSContext *cx, TreeContext *tc)
+js::CheckStrictParameters(JSContext *cx, TreeContext *tc)
 {
     JS_ASSERT(tc->inFunction());
 
     if (!tc->needStrictChecks() || tc->bindings.countArgs() == 0)
         return true;
 
     JSAtom *argumentsAtom = cx->runtime->atomState.argumentsAtom;
     JSAtom *evalAtom = cx->runtime->atomState.evalAtom;
@@ -644,18 +642,16 @@ CheckStrictParameters(JSContext *cx, Tre
             if (!parameters.add(p, name, false))
                 return false;
         }
     }
 
     return true;
 }
 
-} /* namespace js */
-
 ParseNode *
 Parser::functionBody()
 {
     JS_ASSERT(tc->inFunction());
 
     StmtInfo stmtInfo;
     PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
     stmtInfo.flags = SIF_BODY_BLOCK;
@@ -860,20 +856,18 @@ MakeDefIntoUse(Definition *dn, ParseNode
     dn->setDefn(false);
     dn->setUsed(true);
     dn->pn_lexdef = (Definition *) pn;
     dn->pn_cookie.makeFree();
     dn->pn_dflags &= ~PND_BOUND;
     return dn;
 }
 
-namespace js {
-
 bool
-DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc)
+js::DefineArg(ParseNode *pn, JSAtom *atom, uintN i, TreeContext *tc)
 {
     ParseNode *argpn, *argsbody;
 
     /* Flag tc so we don't have to lookup arguments on every use. */
     if (atom == tc->parser->context->runtime->atomState.argumentsAtom)
         tc->flags |= TCF_FUN_PARAM_ARGUMENTS;
 
     /*
@@ -904,18 +898,16 @@ DefineArg(ParseNode *pn, JSAtom *atom, u
     argsbody->append(argpn);
 
     argpn->setOp(JSOP_GETARG);
     argpn->pn_cookie.set(tc->staticLevel, i);
     argpn->pn_dflags |= PND_BOUND;
     return true;
 }
 
-} /* namespace js */
-
 /*
  * Parameter block types for the several Binder functions.  We use a common
  * helper function signature in order to share code among destructuring and
  * simple variable declaration parsers.  In the destructuring case, the binder
  * function is called indirectly from the variable declaration parser by way
  * of CheckDestructuring and its friends.
  */
 typedef JSBool
@@ -1608,23 +1600,23 @@ Parser::setFunctionKinds(FunctionBox *fu
  * within the top statement list, which don't take effect unless they are
  * evaluated). Such call objects may acquire bindings that shadow variables
  * defined in enclosing scopes, so any enclosed functions must have their
  * bindings' extensibleParents flags set, and enclosed compiler-created blocks
  * must have their OWN_SHAPE flags set; the comments for
  * js::Bindings::extensibleParents explain why.
  */
 void
-Parser::markExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent) 
+Parser::markExtensibleScopeDescendants(FunctionBox *funbox, bool hasExtensibleParent)
 {
     for (; funbox; funbox = funbox->siblings) {
         /*
          * It would be nice to use fun->kind() here to recognize functions
          * that will never consult their parent chains, and thus don't need
-         * their 'extensible parents' flag set. Filed as bug 619750. 
+         * their 'extensible parents' flag set. Filed as bug 619750.
          */
 
         JS_ASSERT(!funbox->bindings.extensibleParents());
         if (hasExtensibleParent)
             funbox->bindings.setExtensibleParents();
 
         if (funbox->kids) {
             markExtensibleScopeDescendants(funbox->kids,
@@ -2204,21 +2196,21 @@ Parser::functionDef(PropertyName *funNam
 #endif
     pn->pn_pos.end = tokenStream.currentToken().pos.end;
 
     /*
      * Fruit of the poisonous tree: if a closure calls eval, we consider the
      * parent to call eval. We need this for two reasons: (1) the Jaegermonkey
      * optimizations really need to know if eval is called transitively, and
      * (2) in strict mode, eval called transitively requires eager argument
-     * creation in strict mode parent functions. 
+     * creation in strict mode parent functions.
      *
-     * For the latter, we really only need to propagate callsEval if both 
-     * functions are strict mode, but we don't lose much by always propagating. 
-     * The only optimization we lose this way is in the case where a function 
+     * For the latter, we really only need to propagate callsEval if both
+     * functions are strict mode, but we don't lose much by always propagating.
+     * The only optimization we lose this way is in the case where a function
      * is strict, does not mutate arguments, does not call eval directly, but
      * calls eval transitively.
      */
     if (funtc.callsEval())
         outertc->noteCallsEval();
 
 #if JS_HAS_DESTRUCTURING
     /*
@@ -2705,17 +2697,17 @@ DefineGlobal(ParseNode *pn, CodeGenerato
             if (funbox ||
                 globalObj != holder ||
                 shape->configurable() ||
                 !shape->hasSlot() ||
                 !shape->hasDefaultGetterOrIsMethod() ||
                 !shape->hasDefaultSetter()) {
                 return true;
             }
-            
+
             def = GlobalScope::GlobalDef(shape->slot);
         } else {
             def = GlobalScope::GlobalDef(name, funbox);
         }
 
         if (!globalScope->defs.append(def))
             return false;
 
@@ -4466,19 +4458,21 @@ Parser::statement()
     ParseNode *pn;
 
     JS_CHECK_RECURSION(context, return NULL);
 
     switch (tokenStream.getToken(TSF_OPERAND)) {
       case TOK_FUNCTION:
       {
 #if JS_HAS_XML_SUPPORT
-        TokenKind tt = tokenStream.peekToken(TSF_KEYWORD_IS_NAME);
-        if (tt == TOK_DBLCOLON)
-            goto expression;
+        if (!tc->inStrictMode()) {
+            TokenKind tt = tokenStream.peekToken(TSF_KEYWORD_IS_NAME);
+            if (tt == TOK_DBLCOLON)
+                return expressionStatement();
+        }
 #endif
         return functionStmt();
       }
 
       case TOK_IF:
       {
         /* An IF node has three kids: condition, then, and optional else. */
         pn = TernaryNode::create(tc);
@@ -4741,16 +4735,19 @@ Parser::statement()
             return NULL;
         pn->setKind(TOK_DEBUGGER);
         tc->flags |= TCF_FUN_HEAVYWEIGHT;
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_DEFAULT:
       {
+        if (tc->inStrictMode())
+            return expressionStatement();
+
         pn = UnaryNode::create(tc);
         if (!pn)
             return NULL;
         if (!tokenStream.matchToken(TOK_NAME) ||
             tokenStream.currentToken().name() != context->runtime->atomState.xmlAtom ||
             !tokenStream.matchToken(TOK_NAME) ||
             tokenStream.currentToken().name() != context->runtime->atomState.namespaceAtom ||
             !tokenStream.matchToken(TOK_ASSIGN) ||
@@ -4770,19 +4767,16 @@ Parser::statement()
         break;
       }
 #endif
 
       case TOK_ERROR:
         return NULL;
 
       default:
-#if JS_HAS_XML_SUPPORT
-      expression:
-#endif
         return expressionStatement();
     }
 
     /* Check termination of this primitive statement. */
     return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
 }
 
 ParseNode *
@@ -5486,17 +5480,17 @@ class CompExprTransplanter {
  * A helper for lazily checking for the presence of illegal |yield| or |arguments|
  * tokens inside of generator expressions. This must be done lazily since we don't
  * know whether we're in a generator expression until we see the "for" token after
  * we've already parsed the body expression.
  *
  * Use in any context which may turn out to be inside a generator expression. This
  * includes parenthesized expressions and argument lists, and it includes the tail
  * of generator expressions.
- * 
+ *
  * The guard will keep track of any |yield| or |arguments| tokens that occur while
  * parsing the body. As soon as the parser reaches the end of the body expression,
  * call endBody() to reset the context's state, and then immediately call:
  *
  * - checkValidBody() if this *did* turn out to be a generator expression
  * - maybeNoteGenerator() if this *did not* turn out to be a generator expression
  */
 class GenexpGuard {
@@ -5735,17 +5729,17 @@ CompExprTransplanter::transplant(ParseNo
                      * generator) a use of a new placeholder in the generator's
                      * lexdeps.
                      */
                     Definition *dn2 = MakePlaceholder(pn, tc);
                     if (!dn2)
                         return false;
                     dn2->pn_pos = root->pn_pos;
 
-                    /* 
+                    /*
                      * Change all uses of |dn| that lie within the generator's
                      * |yield| expression into uses of dn2.
                      */
                     ParseNode **pnup = &dn->dn_uses;
                     ParseNode *pnu;
                     while ((pnu = *pnup) != NULL && pnu->pn_pos >= root->pn_pos) {
                         pnu->pn_lexdef = dn2;
                         dn2->pn_dflags |= pnu->pn_dflags & PND_USE2DEF_FLAGS;
@@ -6225,23 +6219,29 @@ Parser::memberExpr(JSBool allowCallSynta
         }
     }
 
     while ((tt = tokenStream.getToken()) > TOK_EOF) {
         if (tt == TOK_DOT) {
             pn2 = NameNode::create(NULL, tc);
             if (!pn2)
                 return NULL;
+
 #if JS_HAS_XML_SUPPORT
             tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
 
             /* Treat filters as 'with' statements for name deoptimization. */
             ParseNode *oldWith = tc->innermostWith;
             StmtInfo stmtInfo;
             if (tt == TOK_LP) {
+                if (tc->inStrictMode()) {
+                    reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
+                    return NULL;
+                }
+
                 tc->innermostWith = pn;
                 PushStatement(tc, &stmtInfo, STMT_WITH, -1);
             }
 
             pn3 = primaryExpr(tt, JS_TRUE);
             if (!pn3)
                 return NULL;
 
@@ -6259,16 +6259,17 @@ Parser::memberExpr(JSBool allowCallSynta
             } else {
                 if (tt == TOK_LP) {
                     pn2->setKind(TOK_FILTER);
                     pn2->setOp(JSOP_FILTER);
 
                     /* A filtering predicate is like a with statement. */
                     tc->flags |= TCF_FUN_HEAVYWEIGHT;
                 } else if (TokenKindIsXML(pn3->getKind())) {
+                    JS_ASSERT(!tc->inStrictMode());
                     pn2->setKind(TOK_LB);
                     pn2->setOp(JSOP_GETELEM);
                 } else {
                     reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
                     return NULL;
                 }
                 pn2->setArity(PN_BINARY);
                 pn2->pn_left = pn;
@@ -6279,16 +6280,21 @@ Parser::memberExpr(JSBool allowCallSynta
             pn2->setOp(JSOP_GETPROP);
             pn2->pn_expr = pn;
             pn2->pn_atom = tokenStream.currentToken().name();
 #endif
             pn2->pn_pos.begin = pn->pn_pos.begin;
             pn2->pn_pos.end = tokenStream.currentToken().pos.end;
 #if JS_HAS_XML_SUPPORT
         } else if (tt == TOK_DBLDOT) {
+            if (tc->inStrictMode()) {
+                reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NAME_AFTER_DOT);
+                return NULL;
+            }
+
             pn2 = BinaryNode::create(tc);
             if (!pn2)
                 return NULL;
             tt = tokenStream.getToken(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
             pn3 = primaryExpr(tt, JS_TRUE);
             if (!pn3)
                 return NULL;
             tt = pn3->getKind();
@@ -6414,16 +6420,18 @@ Parser::bracketedExpr()
     return pn;
 }
 
 #if JS_HAS_XML_SUPPORT
 
 ParseNode *
 Parser::endBracketedExpr()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn = bracketedExpr();
     if (!pn)
         return NULL;
 
     MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ATTR_EXPR);
     return pn;
 }
 
@@ -6476,16 +6484,18 @@ Parser::endBracketedExpr()
  *              Identifier QualifiedSuffix
  *
  * We hoist the :: match into callers of QualifiedSuffix, in order to tweak
  * PropertySelector vs. Identifier pn_arity, pn_op, and other members.
  */
 ParseNode *
 Parser::propertySelector()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     DebugOnly<const Token *> tp = &tokenStream.currentToken();
     JS_ASSERT(tp->type == TOK_STAR || tp->type == TOK_NAME);
 
     ParseNode *pn = NullaryNode::create(tc);
     if (!pn)
         return NULL;
     if (pn->isKind(TOK_STAR)) {
         pn->setKind(TOK_ANYNAME);
@@ -6499,16 +6509,18 @@ Parser::propertySelector()
         pn->pn_cookie.makeFree();
     }
     return pn;
 }
 
 ParseNode *
 Parser::qualifiedSuffix(ParseNode *pn)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn2, *pn3;
     TokenKind tt;
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_DBLCOLON);
     pn2 = NameNode::create(NULL, tc);
     if (!pn2)
         return NULL;
 
@@ -6544,16 +6556,18 @@ Parser::qualifiedSuffix(ParseNode *pn)
     pn2->pn_left = pn;
     pn2->pn_right = pn3;
     return pn2;
 }
 
 ParseNode *
 Parser::qualifiedIdentifier()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     DebugOnly<const Token *> tp = &tokenStream.currentToken();
     JS_ASSERT(tp->type == TOK_STAR || tp->type == TOK_NAME);
 
     ParseNode *pn = propertySelector();
     if (!pn)
         return NULL;
     if (tokenStream.matchToken(TOK_DBLCOLON)) {
         /* Hack for bug 496316. Slowing down E4X won't make it go away, alas. */
@@ -6561,16 +6575,18 @@ Parser::qualifiedIdentifier()
         pn = qualifiedSuffix(pn);
     }
     return pn;
 }
 
 ParseNode *
 Parser::attributeIdentifier()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn, *pn2;
     TokenKind tt;
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_AT);
     pn = UnaryNode::create(tc);
     if (!pn)
         return NULL;
     pn->setOp(JSOP_TOATTRNAME);
@@ -6590,16 +6606,18 @@ Parser::attributeIdentifier()
 }
 
 /*
  * Make a TOK_LC unary node whose pn_kid is an expression.
  */
 ParseNode *
 Parser::xmlExpr(JSBool inTag)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn, *pn2;
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_LC);
     pn = UnaryNode::create(tc);
     if (!pn)
         return NULL;
 
     /*
@@ -6625,16 +6643,18 @@ Parser::xmlExpr(JSBool inTag)
  * Make a terminal node for one of TOK_XMLNAME, TOK_XMLATTR, TOK_XMLSPACE,
  * TOK_XMLTEXT, TOK_XMLCDATA, TOK_XMLCOMMENT, or TOK_XMLPI.  When converting
  * parse tree to XML, we preserve a TOK_XMLSPACE node only if it's the sole
  * child of a container tag.
  */
 ParseNode *
 Parser::xmlAtomNode()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn = NullaryNode::create(tc);
     if (!pn)
         return NULL;
     const Token &tok = tokenStream.currentToken();
     pn->setOp(tok.t_op);
     if (tok.type == TOK_XMLPI) {
         pn->pn_pitarget = tok.xmlPITarget();
         pn->pn_pidata = tok.xmlPIData();
@@ -6654,16 +6674,18 @@ Parser::xmlAtomNode()
  * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
  * a list of names and/or expressions, a single expression, or a single name.
  * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME; if PN_UNARY, pn_type
  * will be TOK_LC.
  */
 ParseNode *
 Parser::xmlNameExpr()
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn, *pn2, *list;
     TokenKind tt;
 
     pn = list = NULL;
     do {
         tt = tokenStream.currentToken().type;
         if (tt == TOK_LC) {
             pn2 = xmlExpr(JS_TRUE);
@@ -6721,16 +6743,18 @@ Parser::xmlNameExpr()
  * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME for the case where
  * XMLTagContent: XMLNameExpr.  If pn_type is not TOK_XMLNAME but pn_arity is
  * PN_LIST, pn_type will be tagtype.  If PN_UNARY, pn_type will be TOK_LC and
  * we parsed exactly one expression.
  */
 ParseNode *
 Parser::xmlTagContent(TokenKind tagtype, JSAtom **namep)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn, *pn2, *list;
     TokenKind tt;
 
     pn = xmlNameExpr();
     if (!pn)
         return NULL;
     *namep = (pn->isArity(PN_NULLARY)) ? pn->pn_atom : NULL;
     list = NULL;
@@ -6793,16 +6817,18 @@ Parser::xmlTagContent(TokenKind tagtype,
 
 /*
  * Consume XML element tag content, including the TOK_XMLETAGO (</) sequence
  * that opens the end tag for the container.
  */
 JSBool
 Parser::xmlElementContent(ParseNode *pn)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     tokenStream.setXMLTagMode(false);
     for (;;) {
         TokenKind tt = tokenStream.getToken(TSF_XMLTEXTMODE);
         XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
 
         JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT);
         JSAtom *textAtom = tokenStream.currentToken().atom();
         if (textAtom) {
@@ -6846,16 +6872,18 @@ Parser::xmlElementContent(ParseNode *pn)
 }
 
 /*
  * Return a PN_LIST node containing an XML or XMLList Initialiser.
  */
 ParseNode *
 Parser::xmlElementOrList(JSBool allowList)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     ParseNode *pn, *pn2, *list;
     TokenKind tt;
     JSAtom *startAtom, *endAtom;
 
     JS_CHECK_RECURSION(context, return NULL);
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_XMLSTAGO);
     pn = ListNode::create(tc);
@@ -6983,16 +7011,18 @@ Parser::xmlElementOrList(JSBool allowLis
 
     pn->pn_pos.end = tokenStream.currentToken().pos.end;
     return pn;
 }
 
 ParseNode *
 Parser::xmlElementOrListRoot(JSBool allowList)
 {
+    JS_ASSERT(!tc->inStrictMode());
+
     /*
      * Force XML support to be enabled so that comments and CDATA literals
      * are recognized, instead of <! followed by -- starting an HTML comment
      * to end of line (used in script tags to hide content from old browsers
      * that don't recognize <script>).
      */
     bool hadXML = tokenStream.hasXML();
     tokenStream.setXML(true);
@@ -7007,16 +7037,17 @@ Parser::parseXMLText(JSObject *chain, bo
     /*
      * Push a compiler frame if we have no frames, or if the top frame is a
      * lightweight function activation, or if its scope chain doesn't match
      * the one passed to us.
      */
     TreeContext xmltc(this);
     if (!xmltc.init(context))
         return NULL;
+    JS_ASSERT(!xmltc.inStrictMode());
     xmltc.setScopeChain(chain);
 
     /* Set XML-only mode to turn off special treatment of {expr} in XML. */
     tokenStream.setXMLOnlyMode();
     TokenKind tt = tokenStream.getToken(TSF_OPERAND);
 
     ParseNode *pn;
     if (tt != TOK_XMLSTAGO) {
@@ -7072,17 +7103,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
     ParseNode *pn, *pn2, *pn3;
     JSOp op;
 
     JS_CHECK_RECURSION(context, return NULL);
 
     switch (tt) {
       case TOK_FUNCTION:
 #if JS_HAS_XML_SUPPORT
-        if (tokenStream.matchToken(TOK_DBLCOLON, TSF_KEYWORD_IS_NAME)) {
+        if (!tc->inStrictMode() && tokenStream.matchToken(TOK_DBLCOLON, TSF_KEYWORD_IS_NAME)) {
             pn2 = NullaryNode::create(tc);
             if (!pn2)
                 return NULL;
             pn2->setKind(TOK_FUNCTION);
             pn = qualifiedSuffix(pn2);
             if (!pn)
                 return NULL;
             break;
@@ -7243,17 +7274,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
         for (;;) {
             JSAtom *atom;
             tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
             switch (tt) {
               case TOK_NUMBER:
                 pn3 = NullaryNode::create(tc);
                 if (!pn3)
                     return NULL;
-                pn3->pn_dval = tokenStream.currentToken().t_dval;
+                pn3->pn_dval = tokenStream.currentToken().number();
                 if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
                     return NULL;
                 break;
               case TOK_NAME:
                 {
                     atom = tokenStream.currentToken().name();
                     if (atom == context->runtime->atomState.getAtom)
                         op = JSOP_GETTER;
@@ -7269,17 +7300,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
                                : tokenStream.currentToken().atom();
                         pn3 = NameNode::create(atom, tc);
                         if (!pn3)
                             return NULL;
                     } else if (tt == TOK_NUMBER) {
                         pn3 = NullaryNode::create(tc);
                         if (!pn3)
                             return NULL;
-                        pn3->pn_dval = tokenStream.currentToken().t_dval;
+                        pn3->pn_dval = tokenStream.currentToken().number();
                         if (!js_ValueToAtom(context, DoubleValue(pn3->pn_dval), &atom))
                             return NULL;
                     } else {
                         tokenStream.ungetToken();
                         goto property_name;
                     }
 
                     pn->pn_xflags |= PNX_NONCONST;
@@ -7415,17 +7446,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
         break;
 #endif
 
 #if JS_HAS_SHARP_VARS
       case TOK_DEFSHARP:
         pn = UnaryNode::create(tc);
         if (!pn)
             return NULL;
-        pn->pn_num = (jsint) tokenStream.currentToken().t_dval;
+        pn->pn_num = tokenStream.currentToken().sharpNumber();
         tt = tokenStream.getToken(TSF_OPERAND);
         pn->pn_kid = primaryExpr(tt, JS_FALSE);
         if (!pn->pn_kid)
             return NULL;
         if (pn->pn_kid->isKind(TOK_USESHARP) ||
             pn->pn_kid->isKind(TOK_DEFSHARP) ||
             pn->pn_kid->isKind(TOK_STRING) ||
             pn->pn_kid->isKind(TOK_NUMBER) ||
@@ -7439,17 +7470,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
 
       case TOK_USESHARP:
         /* Check for forward/dangling references at runtime, to allow eval. */
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
         if (!tc->ensureSharpSlots())
             return NULL;
-        pn->pn_num = (jsint) tokenStream.currentToken().t_dval;
+        pn->pn_num = tokenStream.currentToken().sharpNumber();
         break;
 #endif /* JS_HAS_SHARP_VARS */
 
       case TOK_LP:
       {
         JSBool genexp;
 
         pn = parenExpr(&genexp);
@@ -7476,30 +7507,33 @@ Parser::primaryExpr(TokenKind tt, JSBool
 
       case TOK_XMLSTAGO:
         pn = xmlElementOrListRoot(JS_TRUE);
         if (!pn)
             return NULL;
         break;
 #endif /* JS_HAS_XML_SUPPORT */
 
-      case TOK_STRING:
 #if JS_HAS_XML_SUPPORT
       case TOK_XMLCDATA:
       case TOK_XMLCOMMENT:
+        JS_ASSERT(!tc->inStrictMode());
+        /* FALL THROUGH */
 #endif
+      case TOK_STRING:
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
         pn->pn_atom = tokenStream.currentToken().atom();
         pn->setOp(tokenStream.currentToken().t_op);
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_XMLPI:
+        JS_ASSERT(!tc->inStrictMode());
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
         pn->pn_pitarget = tokenStream.currentToken().xmlPITarget();
         pn->pn_pidata = tokenStream.currentToken().xmlPIData();
         break;
 #endif
 
@@ -7527,17 +7561,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
              */
             if (!afterDot && !(tc->flags & TCF_DECL_DESTRUCTURING)
                 && !tc->inStatement(STMT_WITH)) {
                 pn->setOp(JSOP_ARGUMENTS);
                 pn->pn_dflags |= PND_BOUND;
             }
         } else if ((!afterDot
 #if JS_HAS_XML_SUPPORT
-                    || tokenStream.peekToken() == TOK_DBLCOLON
+                    || (!tc->inStrictMode() && tokenStream.peekToken() == TOK_DBLCOLON)
 #endif
                    ) && !(tc->flags & TCF_DECL_DESTRUCTURING)) {
             /* In case this is a generator expression outside of any function. */
             if (!tc->inFunction() &&
                 pn->pn_atom == context->runtime->atomState.argumentsAtom) {
                 tc->countArgumentsUse(pn);
             }
 
@@ -7607,17 +7641,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
                 dn->pn_dflags |= PND_FUNARG;
 
             pn->pn_dflags |= (dn->pn_dflags & PND_FUNARG);
             if (stmt && stmt->type == STMT_WITH)
                 pn->pn_dflags |= PND_DEOPTIMIZED;
         }
 
 #if JS_HAS_XML_SUPPORT
-        if (tokenStream.matchToken(TOK_DBLCOLON)) {
+        if (!tc->inStrictMode() && tokenStream.matchToken(TOK_DBLCOLON)) {
             if (afterDot) {
                 /*
                  * Here primaryExpr is called after . or .. followed by a name
                  * followed by ::. This is the only case where a keyword after
                  * . or .. is not treated as a property name.
                  */
                 const KeywordInfo *ki = FindKeyword(pn->pn_atom->charsZ(), pn->pn_atom->length());
                 if (ki) {
@@ -7640,17 +7674,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
       case TOK_REGEXP:
       {
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
 
         const jschar *chars = tokenStream.getTokenbuf().begin();
         size_t length = tokenStream.getTokenbuf().length();
-        RegExpFlag flags = RegExpFlag(tokenStream.currentToken().t_reflags);
+        RegExpFlag flags = tokenStream.currentToken().regExpFlags();
         RegExpStatics *res = context->regExpStatics();
 
         RegExpObject *reobj;
         if (context->hasfp())
             reobj = RegExpObject::create(context, res, chars, length, flags, &tokenStream);
         else
             reobj = RegExpObject::createNoStatics(context, chars, length, flags, &tokenStream);
 
@@ -7670,17 +7704,17 @@ Parser::primaryExpr(TokenKind tt, JSBool
         break;
       }
 
       case TOK_NUMBER:
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
         pn->setOp(JSOP_DOUBLE);
-        pn->pn_dval = tokenStream.currentToken().t_dval;
+        pn->pn_dval = tokenStream.currentToken().number();
         break;
 
       case TOK_PRIMARY:
         pn = NullaryNode::create(tc);
         if (!pn)
             return NULL;
         pn->setOp(tokenStream.currentToken().t_op);
         break;
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -86,20 +86,18 @@ using namespace js::unicode;
 
 static const KeywordInfo keywords[] = {
 #define JS_KEYWORD(keyword, type, op, version) \
     {js_##keyword##_str, type, op, version},
 #include "jskeyword.tbl"
 #undef JS_KEYWORD
 };
 
-namespace js {
-
 const KeywordInfo *
-FindKeyword(const jschar *s, size_t length)
+js::FindKeyword(const jschar *s, size_t length)
 {
     JS_ASSERT(length != 0);
 
     register size_t i;
     const struct KeywordInfo *kw;
     const char *chars;
 
 #define JSKW_LENGTH()           length
@@ -126,17 +124,17 @@ FindKeyword(const jschar *s, size_t leng
     } while (--length != 0);
     return kw;
 
   no_match:
     return NULL;
 }
 
 JSBool
-IsIdentifier(JSLinearString *str)
+js::IsIdentifier(JSLinearString *str)
 {
     const jschar *chars = str->chars();
     size_t length = str->length();
 
     if (length == 0)
         return JS_FALSE;
     jschar c = *chars;
     if (!IsIdentifierStart(c))
@@ -543,18 +541,18 @@ TokenStream::reportCompileErrorNumberVA(
         }
         cx->free_((void *)report.messageArgs);
     }
 
     return warning;
 }
 
 bool
-ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn,
-                      uintN errorNumber, ...)
+js::ReportStrictModeError(JSContext *cx, TokenStream *ts, TreeContext *tc, ParseNode *pn,
+                          uintN errorNumber, ...)
 {
     JS_ASSERT(ts || tc);
     JS_ASSERT(cx == ts->getContext());
 
     /* In strict mode code, this is an error, not merely a warning. */
     uintN flags;
     if ((ts && ts->isStrictMode()) || (tc && (tc->flags & TCF_STRICT_MODE_CODE))) {
         flags = JSREPORT_ERROR;
@@ -568,18 +566,18 @@ ReportStrictModeError(JSContext *cx, Tok
     va_start(ap, errorNumber);
     bool result = ts->reportCompileErrorNumberVA(pn, flags, errorNumber, ap);
     va_end(ap);
 
     return result;
 }
 
 bool
-ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags,
-                         uintN errorNumber, ...)
+js::ReportCompileErrorNumber(JSContext *cx, TokenStream *ts, ParseNode *pn, uintN flags,
+                             uintN errorNumber, ...)
 {
     va_list ap;
 
     /*
      * We don't accept a TreeContext argument, so we can't implement
      * JSREPORT_STRICT_MODE_ERROR here.  Use ReportStrictModeError instead,
      * or do the checks in the caller and pass plain old JSREPORT_ERROR.
      */
@@ -1710,17 +1708,17 @@ TokenStream::getTokenInternal()
         const jschar *dummy;
         if (!hasFracOrExp) {
             if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), 10, &dummy, &dval))
                 goto error;
         } else {
             if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
                 goto error;
         }
-        tp->t_dval = dval;
+        tp->setNumber(dval);
         tt = TOK_NUMBER;
         goto out;
     }
 
     if (c1kind == Colon) {
 #if JS_HAS_XML_SUPPORT
         if (matchChar(':')) {
             tt = TOK_DBLCOLON;
@@ -1796,17 +1794,17 @@ TokenStream::getTokenInternal()
             ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR, JSMSG_IDSTART_AFTER_NUMBER);
             goto error;
         }
 
         jsdouble dval;
         const jschar *dummy;
         if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), radix, &dummy, &dval))
             goto error;
-        tp->t_dval = dval;
+        tp->setNumber(dval);
         tt = TOK_NUMBER;
         goto out;
     }
 
     /*
      * This handles everything else.
      */
     JS_ASSERT(c1kind == Other);
@@ -1864,17 +1862,17 @@ TokenStream::getTokenInternal()
 #if JS_HAS_XML_SUPPORT
       case '@':
         tt = TOK_AT;
         break;
 #endif
 
       case '<':
 #if JS_HAS_XML_SUPPORT
-        if ((flags & TSF_OPERAND) && (hasXML() || peekChar() != '!')) {
+        if ((flags & TSF_OPERAND) && !isStrictMode() && (hasXML() || peekChar() != '!')) {
             if (!getXMLMarkup(&tt, &tp))
                 goto error;
             goto out;
         }
 #endif
 
         /* NB: treat HTML begin-comment as comment-till-end-of-line */
         if (matchChar('!')) {
@@ -1957,68 +1955,72 @@ TokenStream::getTokenInternal()
             cursor = (cursor - 1) & ntokensMask;
             goto retry;
         }
 
         /*
          * Look for a regexp.
          */
         if (flags & TSF_OPERAND) {
-            uintN reflags, length;
-            JSBool inCharClass = JS_FALSE;
+            tokenbuf.clear();
 
-            tokenbuf.clear();
+            bool inCharClass = false;
             for (;;) {
                 c = getChar();
                 if (c == '\\') {
                     if (!tokenbuf.append(c))
                         goto error;
                     c = getChar();
                 } else if (c == '[') {
-                    inCharClass = JS_TRUE;
+                    inCharClass = true;
                 } else if (c == ']') {
-                    inCharClass = JS_FALSE;
+                    inCharClass = false;
                 } else if (c == '/' && !inCharClass) {
                     /* For compat with IE, allow unescaped / in char classes. */
                     break;
                 }
                 if (c == '\n' || c == EOF) {
                     ungetChar(c);
                     ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR,
                                              JSMSG_UNTERMINATED_REGEXP);
                     goto error;
                 }
                 if (!tokenbuf.append(c))
                     goto error;
             }
-            for (reflags = 0, length = tokenbuf.length() + 1; ; length++) {
+
+            RegExpFlag reflags = NoFlags;
+            uintN length = tokenbuf.length() + 1;
+            while (true) {
                 c = peekChar();
-                if (c == 'g' && !(reflags & JSREG_GLOB))
-                    reflags |= JSREG_GLOB;
+                if (c == 'g' && !(reflags & GlobalFlag))
+                    reflags = RegExpFlag(reflags | GlobalFlag);
                 else if (c == 'i' && !(reflags & IgnoreCaseFlag))
-                    reflags |= IgnoreCaseFlag;
+                    reflags = RegExpFlag(reflags | IgnoreCaseFlag);
                 else if (c == 'm' && !(reflags & MultilineFlag))
-                    reflags |= MultilineFlag;
+                    reflags = RegExpFlag(reflags | MultilineFlag);
                 else if (c == 'y' && !(reflags & StickyFlag))
-                    reflags |= StickyFlag;
+                    reflags = RegExpFlag(reflags | StickyFlag);
                 else
                     break;
                 getChar();
+                length++;
             }
+
             c = peekChar();
             if (JS7_ISLET(c)) {
-                char buf[2] = { '\0' };
+                char buf[2] = { '\0', '\0' };
                 tp->pos.begin.index += length + 1;
-                buf[0] = (char)c;
+                buf[0] = char(c);
                 ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR, JSMSG_BAD_REGEXP_FLAG,
                                          buf);
                 (void) getChar();
                 goto error;
             }
-            tp->t_reflags = reflags;
+            tp->setRegExpFlags(reflags);
             tt = TOK_REGEXP;
             break;
         }
 
         tp->t_op = JSOP_DIV;
         tt = matchChar('=') ? TOK_ASSIGN : TOK_DIVOP;
         break;
 
@@ -2064,19 +2066,18 @@ TokenStream::getTokenInternal()
             if (!JS7_ISDEC(c))
                 break;
             n = 10 * n + JS7_UNDEC(c);
             if (n >= UINT16_LIMIT) {
                 ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR, JSMSG_SHARPVAR_TOO_BIG);
                 goto error;
             }
         }
-        tp->t_dval = (jsdouble) n;
-        if (cx->hasStrictOption() &&
-            (c == '=' || c == '#')) {
+        tp->setSharpNumber(uint16(n));
+        if (cx->hasStrictOption() && (c == '=' || c == '#')) {
             char buf[20];
             JS_snprintf(buf, sizeof buf, "#%u%c", n, c);
             if (!ReportCompileErrorNumber(cx, this, NULL, JSREPORT_WARNING | JSREPORT_STRICT,
                                           JSMSG_DEPRECATED_USAGE, buf)) {
                 goto error;
             }
         }
         if (c == '=')
@@ -2123,18 +2124,16 @@ TokenStream::getTokenInternal()
      * call will immediately return the just-gotten TOK_ERROR token again
      * without consulting userbuf, thanks to the lookahead buffer.
      */
     userbuf.poison();
 #endif
     return TOK_ERROR;
 }
 
-} /* namespace js */
-
 JS_FRIEND_API(int)
 js_fgets(char *buf, int size, FILE *file)
 {
     int n, i, c;
     JSBool crflag;
 
     n = size - 1;
     if (n < 0)
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -260,28 +260,36 @@ struct Token {
             JSOp        op;             /* operator, for minimal parser */
             union {
               private:
                 friend struct Token;
                 PropertyName *name;     /* non-numeric atom */
                 JSAtom       *atom;     /* potentially-numeric atom */
             } n;
         } s;
-        uintN           reflags;        /* regexp flags, use tokenbuf to access
-                                           regexp chars */
-        class {                         /* pair for <?target data?> XML PI */
-            friend struct Token;
+
+      private:
+        friend struct Token;
+        struct {                        /* pair for <?target data?> XML PI */
             JSAtom       *data;         /* auxiliary atom table entry */
             PropertyName *target;       /* main atom table entry */
         } xmlpi;
-        jsdouble        dval;           /* floating point number */
+        uint16          sharpNumber;    /* sharp variable number: #1# or #1= */
+        jsdouble        number;         /* floating point number */
+        RegExpFlag      reflags;        /* regexp flags, use tokenbuf to access
+                                           regexp chars */
     } u;
 
     /* Mutators */
 
+    /*
+     * FIXME: Init type early enough such that all mutators can assert
+     *        type-safety.  See bug 697000.
+     */
+
     void setName(JSOp op, PropertyName *name) {
         JS_ASSERT(op == JSOP_NAME);
         u.s.op = op;
         u.s.n.name = name;
     }
 
     void setAtom(JSOp op, JSAtom *atom) {
         JS_ASSERT(op == JSOP_STRING || op == JSOP_XMLCOMMENT || JSOP_XMLCDATA);
@@ -289,16 +297,29 @@ struct Token {
         u.s.n.atom = atom;
     }
 
     void setProcessingInstruction(PropertyName *target, JSAtom *data) {
         u.xmlpi.target = target;
         u.xmlpi.data = data;
     }
 
+    void setRegExpFlags(js::RegExpFlag flags) {
+        JS_ASSERT((flags & AllFlags) == flags);
+        u.reflags = flags;
+    }
+
+    void setSharpNumber(uint16 sharpNum) {
+        u.sharpNumber = sharpNum;
+    }
+
+    void setNumber(jsdouble n) {
+        u.number = n;
+    }
+
     /* Type-safe accessors */
 
     PropertyName *name() const {
         JS_ASSERT(type == TOK_NAME);
         return u.s.n.name->asPropertyName(); /* poor-man's type verification */
     }
 
     JSAtom *atom() const {
@@ -315,21 +336,35 @@ struct Token {
     PropertyName *xmlPITarget() const {
         JS_ASSERT(type == TOK_XMLPI);
         return u.xmlpi.target;
     }
     JSAtom *xmlPIData() const {
         JS_ASSERT(type == TOK_XMLPI);
         return u.xmlpi.data;
     }
+
+    js::RegExpFlag regExpFlags() const {
+        JS_ASSERT(type == TOK_REGEXP);
+        JS_ASSERT((u.reflags & AllFlags) == u.reflags);
+        return u.reflags;
+    }
+
+    uint16 sharpNumber() const {
+        JS_ASSERT(type == TOK_DEFSHARP || type == TOK_USESHARP);
+        return u.sharpNumber;
+    }
+
+    jsdouble number() const {
+        JS_ASSERT(type == TOK_NUMBER);
+        return u.number;
+    }
 };
 
 #define t_op            u.s.op
-#define t_reflags       u.reflags
-#define t_dval          u.dval
 
 enum TokenStreamFlags
 {
     TSF_EOF = 0x02,             /* hit end of file */
     TSF_EOL = 0x04,             /* an EOL was hit in whitespace or a multi-line comment */
     TSF_OPERAND = 0x08,         /* looking for operand, not operator */
     TSF_UNEXPECTED_EOF = 0x10,  /* unexpected end of input, i.e. TOK_EOF not at top-level. */
     TSF_KEYWORD_IS_NAME = 0x20, /* Ignore keywords and return TOK_NAME instead to the parser. */
--- a/js/src/js-config.h.in
+++ b/js/src/js-config.h.in
@@ -54,16 +54,20 @@
 /* Define to 1 if SpiderMonkey should support the ability to perform
    entirely too much GC.  */
 #undef JS_GC_ZEAL
 
 /* Define to 1 if the standard <stdint.h> header is present and
    useable.  See jstypes.h and jsstdint.h.  */
 #undef JS_HAVE_STDINT_H
 
+/* Define to 1 if the <endian.h> header is present and
+   useable.  See jscpucfg.h.  */
+#undef JS_HAVE_ENDIAN_H
+
 /* Define to 1 if the <sys/types.h> defines int8_t, etc. */
 #undef JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES
 
 /* Define to 1 if the N-byte __intN types are defined by the
    compiler.  */
 #undef JS_HAVE___INTN
 
 /* Define to 1 if #including <stddef.h> provides definitions for
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -365,8 +365,9 @@ MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER, 
 MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO,     279, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object")
 MSG_DEF(JSMSG_DEBUG_LOOP,             280, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger")
 MSG_DEF(JSMSG_DEBUG_NOT_IDLE,         281, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
 MSG_DEF(JSMSG_DEBUG_BAD_OFFSET,       282, 0, JSEXN_TYPEERR, "invalid script offset")
 MSG_DEF(JSMSG_DEBUG_BAD_LINE,         283, 0, JSEXN_TYPEERR, "invalid line number")
 MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING,    284, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
 MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 285, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
 MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 286, 0, JSEXN_ERR, "stack frame is not running JavaScript code")
+MSG_DEF(JSMSG_CANT_WATCH_PROP,        287, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched")
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1273,40 +1273,43 @@ JS_EnterCrossCompartmentCall(JSContext *
         return NULL;
     if (!call->enter()) {
         Foreground::delete_(call);
         return NULL;
     }
     return reinterpret_cast<JSCrossCompartmentCall *>(call);
 }
 
+namespace js {
+
 // Declared in jscompartment.h
-JSClass js_dummy_class = {
+Class dummy_class = {
     "jdummy",
     JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,  JS_PropertyStub,
     JS_PropertyStub,  JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub,
-    JS_ConvertStub,   NULL,
-    JSCLASS_NO_OPTIONAL_MEMBERS
+    JS_ConvertStub
 };
 
+} /*namespace js */
+
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target)
 {
     CHECK_REQUEST(cx);
-
-    JSObject *scriptObject = target->u.object;
-    if (!scriptObject) {
+    JS_ASSERT(!target->isCachedEval);
+    GlobalObject *global = target->u.globalObject;
+    if (!global) {
         SwitchToCompartment sc(cx, target->compartment());
-        scriptObject = JS_NewGlobalObject(cx, &js_dummy_class);
-        if (!scriptObject)
+        global = GlobalObject::create(cx, &dummy_class);
+        if (!global)
             return NULL;
     }
-    return JS_EnterCrossCompartmentCall(cx, scriptObject);
+    return JS_EnterCrossCompartmentCall(cx, global);
 }
 
 JS_PUBLIC_API(JSCrossCompartmentCall *)
 JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target)
 {
     CHECK_REQUEST(cx);
 
     return JS_EnterCrossCompartmentCall(cx, Valueify(target)->scopeChain().getGlobal());
@@ -4577,17 +4580,17 @@ CompileUCScriptForPrincipalsCommon(JSCon
                                       const jschar *chars, size_t length,
                                       const char *filename, uintN lineno, JSVersion version)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, principals);
     AutoLastFrameCheck lfc(cx);
 
-    uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
+    uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
     return BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, chars, length,
                                            filename, lineno, version);
 }
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                        JSPrincipals *principals,
                                        const jschar *chars, size_t length,
@@ -4754,17 +4757,17 @@ CompileFileHelper(JSContext *cx, JSObjec
         // The |i < len| is necessary for files that lie about their length,
         // e.g. /dev/zero and /dev/random.  See bug 669434.
         while (i < len && (c = fast_getc(fp)) != EOF)
             buf[i++] = (jschar) (unsigned char) c;
     }
 
     JS_ASSERT(i <= len);
     len = i;
-    uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
+    uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_GLOBAL;
     script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len,
                                              filename, 1, cx->findVersion());
     cx->free_(buf);
     return script;
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
@@ -4815,21 +4818,22 @@ JS_CompileFileHandleForPrincipalsVersion
 JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_GetObjectFromScript(JSScript *script)
-{
-    JS_ASSERT(script->u.object);
-
-    return script->u.object;
+JS_GetGlobalFromScript(JSScript *script)
+{
+    JS_ASSERT(!script->isCachedEval);
+    JS_ASSERT(script->u.globalObject);
+
+    return script->u.globalObject;
 }
 
 static JSFunction *
 CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
                                      JSPrincipals *principals, const char *name,
                                      uintN nargs, const char **argnames,
                                      const jschar *chars, size_t length,
                                      const char *filename, uintN lineno, JSVersion version)
@@ -5013,17 +5017,17 @@ bool
 EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
                                     JSPrincipals *principals,
                                     const jschar *chars, uintN length,
                                     const char *filename, uintN lineno,
                                     jsval *rval, JSVersion compileVersion)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
 
-    uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT;
+    uint32 flags = TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL;
     if (!rval)
         flags |= TCF_NO_SCRIPT_RVAL;
 
     CHECK_REQUEST(cx);
     AutoLastFrameCheck lfc(cx);
     JSScript *script = BytecodeCompiler::compileScript(cx, obj, NULL, principals, flags, chars,
                                                        length, filename, lineno, compileVersion);
     if (!script)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3812,17 +3812,17 @@ JS_CompileFileHandleForPrincipals(JSCont
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                          const char *filename, FILE *fh,
                                          JSPrincipals *principals,
                                          JSVersion version);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_GetObjectFromScript(JSScript *script);
+JS_GetGlobalFromScript(JSScript *script);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
                    uintN nargs, const char **argnames,
                    const char *bytes, size_t length,
                    const char *filename, uintN lineno);
 
 extern JS_PUBLIC_API(JSFunction *)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1512,28 +1512,28 @@ array_toSource(JSContext *cx, uintN argc
         return false;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return false;
 
     for (jsuint index = 0; index < length; index++) {
         JSBool hole;
-        Value tmp;
+        Value elt;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-            !GetElement(cx, obj, index, &hole, &tmp)) {
+            !GetElement(cx, obj, index, &hole, &elt)) {
             return false;
         }
 
         /* Get element's character string. */
         JSString *str;
         if (hole) {
             str = cx->runtime->emptyString;
         } else {
-            str = js_ValueToSource(cx, tmp);
+            str = js_ValueToSource(cx, elt);
             if (!str)
                 return false;
         }
 
         /* Append element to buffer. */
         if (!sb.append(str))
             return false;
         if (index + 1 != length) {
@@ -1602,17 +1602,17 @@ class AutoArrayCycleDetector
 
     bool foundCycle() { return cycle; }
 
   protected:
 };
 
 static JSBool
 array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
-                   JSString *sepstr, Value *rval)
+                   JSString *sepstr, CallArgs &args)
 {
     static const jschar comma = ',';
     const jschar *sep;
     size_t seplen;
     if (sepstr) {
         seplen = sepstr->length();
         sep = sepstr->getChars(cx);
         if (!sep)
@@ -1622,17 +1622,17 @@ array_toString_sub(JSContext *cx, JSObje
         seplen = 1;
     }
 
     AutoArrayCycleDetector detector(cx, obj);
     if (!detector.init())
         return false;
 
     if (detector.foundCycle()) {
-        rval->setString(cx->runtime->atomState.emptyAtom);
+        args.rval().setString(cx->runtime->atomState.emptyAtom);
         return true;
     }
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return false;
 
     StringBuffer sb(cx);
@@ -1651,97 +1651,100 @@ array_toString_sub(JSContext *cx, JSObje
             }
         }
     } else {
         for (jsuint index = 0; index < length; index++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx))
                 return false;
 
             JSBool hole;
-            if (!GetElement(cx, obj, index, &hole, rval))
+            Value elt;
+            if (!GetElement(cx, obj, index, &hole, &elt))
                 return false;
 
-            if (!hole && !rval->isNullOrUndefined()) {
+            if (!hole && !elt.isNullOrUndefined()) {
                 if (locale) {
-                    JSObject *robj = ToObject(cx, rval);
+                    JSObject *robj = ToObject(cx, &elt);
                     if (!robj)
                         return false;
                     jsid id = ATOM_TO_JSID(cx->runtime->atomState.toLocaleStringAtom);
-                    if (!robj->callMethod(cx, id, 0, NULL, rval))
+                    if (!robj->callMethod(cx, id, 0, NULL, &elt))
                         return false;
                 }
-                if (!ValueToStringBuffer(cx, *rval, sb))
+                if (!ValueToStringBuffer(cx, elt, sb))
                     return false;
             }
 
             if (index + 1 != length) {
                 if (!sb.append(sep, seplen))
                     return false;
             }
         }
     }
 
     JSString *str = sb.finishString();
     if (!str)
         return false;
-    rval->setString(str);
+    args.rval().setString(str);
     return true;
 }
 
 /* ES5 15.4.4.2. NB: The algorithm here differs from the one in ES3. */
 static JSBool
 array_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
-    Value &join = vp[0];
+    Value join = args.calleev();
     if (!obj->getProperty(cx, cx->runtime->atomState.joinAtom, &join))
         return false;
 
     if (!js_IsCallable(join)) {
         JSString *str = obj_toStringHelper(cx, obj);
         if (!str)
             return false;
-        vp->setString(str);
+        args.rval().setString(str);
         return true;
     }
 
     LeaveTrace(cx);
-    InvokeArgsGuard args;
-    if (!cx->stack.pushInvokeArgs(cx, 0, &args))
+    InvokeArgsGuard ag;
+    if (!cx->stack.pushInvokeArgs(cx, 0, &ag))
         return false;
 
-    args.calleev() = join;
-    args.thisv().setObject(*obj);
+    ag.calleev() = join;
+    ag.thisv().setObject(*obj);
 
     /* Do the call. */
-    if (!Invoke(cx, args))
+    if (!Invoke(cx, ag))
         return false;
-    *vp = args.rval();
+    args.rval() = ag.rval();
     return true;
 }
 
 static JSBool
 array_toLocaleString(JSContext *cx, uintN argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     /*
      *  Passing comma here as the separator. Need a way to get a
      *  locale-specific version.
      */
-    return array_toString_sub(cx, obj, JS_TRUE, NULL, vp);
+    return array_toString_sub(cx, obj, JS_TRUE, NULL, args);
 }
 
 static inline bool
 InitArrayTypes(JSContext *cx, TypeObject *type, const Value *vector, unsigned count)
 {
     if (cx->typeInferenceEnabled() && !type->unknownProperties()) {
         AutoEnterTypeInference enter(cx);
 
@@ -1866,52 +1869,55 @@ InitArrayObject(JSContext *cx, JSObject 
 /*
  * Perl-inspired join, reverse, and sort.
  */
 static JSBool
 array_join(JSContext *cx, uintN argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
+    CallArgs args = CallArgsFromVp(argc, vp);
     JSString *str;
-    if (argc == 0 || vp[2].isUndefined()) {
+    if (args.length() == 0 || args[0].isUndefined()) {
         str = NULL;
     } else {
-        str = js_ValueToString(cx, vp[2]);
+        str = js_ValueToString(cx, args[0]);
         if (!str)
             return JS_FALSE;
-        vp[2].setString(str);
+        args[0].setString(str);
     }
-    JSObject *obj = ToObject(cx, &vp[1]);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
-    return array_toString_sub(cx, obj, JS_FALSE, str, vp);
+    return array_toString_sub(cx, obj, JS_FALSE, str, args);
 }
 
 static JSBool
 array_reverse(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     jsuint len;
     if (!js_GetLengthProperty(cx, obj, &len))
         return false;
-    vp->setObject(*obj);
 
     do {
         if (!obj->isDenseArray())
             break;
         if (js_PrototypeHasIndexedProperties(cx, obj))
             break;
 
         /* An empty array or an array with no elements is already reversed. */
-        if (len == 0 || obj->getDenseArrayCapacity() == 0)
+        if (len == 0 || obj->getDenseArrayCapacity() == 0) {
+            args.rval().setObject(*obj);
             return true;
+        }
 
         /*
          * It's actually surprisingly complicated to reverse an array due to the
          * orthogonality of array length and array capacity while handling
          * leading and trailing holes correctly.  Reversing seems less likely to
          * be a common operation than other array mass-mutation methods, so for
          * now just take a probably-small memory hit (in the absence of too many
          * holes in the array at its start) and ensure that the capacity is
@@ -1944,31 +1950,32 @@ array_reverse(JSContext *cx, uintN argc,
             }
         }
 
         /*
          * Per ECMA-262, don't update the length of the array, even if the new
          * array has trailing holes (and thus the original array began with
          * holes).
          */
+        args.rval().setObject(*obj);
         return true;
     } while (false);
 
-    AutoValueRooter tvr(cx);
+    Value lowval, hival;
     for (jsuint i = 0, half = len / 2; i < half; i++) {
         JSBool hole, hole2;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-            !GetElement(cx, obj, i, &hole, tvr.addr()) ||
-            !GetElement(cx, obj, len - i - 1, &hole2, vp) ||
-            !SetOrDeleteArrayElement(cx, obj, len - i - 1, hole, tvr.value()) ||
-            !SetOrDeleteArrayElement(cx, obj, i, hole2, *vp)) {
+            !GetElement(cx, obj, i, &hole, &lowval) ||
+            !GetElement(cx, obj, len - i - 1, &hole2, &hival) ||
+            !SetOrDeleteArrayElement(cx, obj, len - i - 1, hole, lowval) ||
+            !SetOrDeleteArrayElement(cx, obj, i, hole2, hival)) {
             return false;
         }
     }
-    vp->setObject(*obj);
+    args.rval().setObject(*obj);
     return true;
 }
 
 typedef struct MSortArgs {
     size_t       elsize;
     JSComparator cmp;
     void         *arg;
     JSBool       isValue;
@@ -2140,31 +2147,31 @@ sort_compare(void *arg, const void *a, c
      * come here.
      */
     JS_ASSERT(!av->isMagic() && !av->isUndefined());
     JS_ASSERT(!av->isMagic() && !bv->isUndefined());
 
     if (!JS_CHECK_OPERATION_LIMIT(cx))
         return JS_FALSE;
 
-    InvokeArgsGuard &args = ca->args;
-    if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, 2, &args))
+    InvokeArgsGuard &ag = ca->args;
+    if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, 2, &ag))
         return JS_FALSE;
         
-    args.calleeHasBeenReset();
-    args.calleev() = ca->fval;
-    args.thisv() = UndefinedValue();
-    args[0] = *av;
-    args[1] = *bv;
-
-    if (!Invoke(cx, args))
+    ag.calleeHasBeenReset();
+    ag.calleev() = ca->fval;
+    ag.thisv() = UndefinedValue();
+    ag[0] = *av;
+    ag[1] = *bv;
+
+    if (!Invoke(cx, ag))
         return JS_FALSE;
 
     jsdouble cmp;
-    if (!ToNumber(cx, args.rval(), &cmp))
+    if (!ToNumber(cx, ag.rval(), &cmp))
         return JS_FALSE;
 
     /* Clamp cmp to -1, 0, 1. */
     *result = 0;
     if (!JSDOUBLE_IS_NaN(cmp) && cmp != 0)
         *result = cmp > 0 ? 1 : -1;
 
     /*
@@ -2195,36 +2202,36 @@ sort_compare_strings(void *arg, const vo
 }
 
 JSBool
 js::array_sort(JSContext *cx, uintN argc, Value *vp)
 {
     jsuint len, newlen, i, undefs;
     size_t elemsize;
     JSString *str;
-
-    Value *argv = JS_ARGV(cx, vp);
+    
+    CallArgs args = CallArgsFromVp(argc, vp);
     Value fval;
-    if (argc > 0 && !argv[0].isUndefined()) {
-        if (argv[0].isPrimitive()) {
+    if (args.length() > 0 && !args[0].isUndefined()) {
+        if (args[0].isPrimitive()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_SORT_ARG);
             return false;
         }
-        fval = argv[0];     /* non-default compare function */
+        fval = args[0];     /* non-default compare function */
     } else {
         fval.setNull();
     }
 
-    JSObject *obj = ToObject(cx, &vp[1]);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
     if (!js_GetLengthProperty(cx, obj, &len))
         return false;
     if (len == 0) {
-        vp->setObject(*obj);
+        args.rval().setObject(*obj);
         return true;
     }
 
     /*
      * We need a temporary array of 2 * len Value to hold the array elements
      * and the scratch space for merge sort. Check that its size does not
      * overflow size_t, which would allow for indexing beyond the end of the
      * malloc'd vector.
@@ -2293,17 +2300,17 @@ js::array_sort(JSContext *cx, uintN argc
             }
 
             allStrings = allStrings && vec[newlen].isString();
 
             ++newlen;
         }
 
         if (newlen == 0) {
-            vp->setObject(*obj);
+            args.rval().setObject(*obj);
             return true; /* The array has only holes and undefs. */
         }
 
         /*
          * The first newlen elements of vec are copied from the array object
          * (above). The remaining newlen positions are used as GC-rooted scratch
          * space for mergesort. We must clear the space before including it to
          * the root set covered by tvr.count.
@@ -2424,62 +2431,59 @@ js::array_sort(JSContext *cx, uintN argc
         }
     }
 
     /* Re-create any holes that sorted to the end of the array. */
     while (len > newlen) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) || DeleteArrayElement(cx, obj, --len, true) < 0)
             return false;
     }
-    vp->setObject(*obj);
+    args.rval().setObject(*obj);
     return true;
 }
 
 /*
  * Perl-inspired push, pop, shift, unshift, and splice methods.
  */
-static JSBool
-array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+static bool
+array_push_slowly(JSContext *cx, JSObject *obj, CallArgs &args)
 {
     jsuint length;
 
     if (!js_GetLengthProperty(cx, obj, &length))
-        return JS_FALSE;
-    if (!InitArrayElements(cx, obj, length, argc, argv, true))
-        return JS_FALSE;
+        return false;
+    if (!InitArrayElements(cx, obj, length, args.length(), args.array(), true))
+        return false;
 
     /* Per ECMA-262, return the new array length. */
-    jsdouble newlength = length + jsdouble(argc);
-    rval->setNumber(newlength);
+    jsdouble newlength = length + jsdouble(args.length());
+    args.rval().setNumber(newlength);
     return js_SetLengthProperty(cx, obj, newlength);
 }
 
-static JSBool
-array_push1_dense(JSContext* cx, JSObject* obj, const Value &v, Value *rval)
+static bool
+array_push1_dense(JSContext* cx, JSObject* obj, CallArgs &args)
 {
+    JS_ASSERT(args.length() == 1);
+
     uint32 length = obj->getArrayLength();
-    do {
-        JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, 1);
-        if (result != JSObject::ED_OK) {
-            if (result == JSObject::ED_FAILED)
-                return false;
-            JS_ASSERT(result == JSObject::ED_SPARSE);
-            break;
-        }
-
-        obj->setDenseArrayLength(length + 1);
-        obj->setDenseArrayElementWithType(cx, length, v);
-        rval->setNumber(obj->getArrayLength());
-        return true;
-    } while (false);
-
-    if (!obj->makeDenseArraySlow(cx))
-        return false;
-    Value tmp = v;
-    return array_push_slowly(cx, obj, 1, &tmp, rval);
+    JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, 1);
+    if (result != JSObject::ED_OK) {
+        if (result == JSObject::ED_FAILED)
+            return false;
+        JS_ASSERT(result == JSObject::ED_SPARSE);
+        if (!obj->makeDenseArraySlow(cx))
+            return false;
+        return array_push_slowly(cx, obj, args);
+    }
+
+    obj->setDenseArrayLength(length + 1);
+    obj->setDenseArrayElementWithType(cx, length, args[0]);
+    args.rval().setNumber(obj->getArrayLength());
+    return true;
 }
 
 JS_ALWAYS_INLINE JSBool
 NewbornArrayPushImpl(JSContext *cx, JSObject *obj, const Value &v)
 {
     JS_ASSERT(!v.isMagic());
 
     uint32 length = obj->getArrayLength();
@@ -2524,81 +2528,91 @@ js_NewbornArrayPush_tn(JSContext *cx, JS
 }
 JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_NewbornArrayPush_tn, CONTEXT, OBJECT,
                      VALUE, 0, nanojit::ACCSET_STORE_ANY)
 #endif
 
 JSBool
 js::array_push(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     /* Insist on one argument and obj of the expected class. */
-    if (argc != 1 || !obj->isDenseArray())
-        return array_push_slowly(cx, obj, argc, vp + 2, vp);
-
-    return array_push1_dense(cx, obj, vp[2], vp);
+    if (args.length() != 1 || !obj->isDenseArray())
+        return array_push_slowly(cx, obj, args);
+
+    return array_push1_dense(cx, obj, args);
 }
 
 static JSBool
-array_pop_slowly(JSContext *cx, JSObject* obj, Value *vp)
+array_pop_slowly(JSContext *cx, JSObject* obj, CallArgs &args)
 {
     jsuint index;
-    JSBool hole;
-
     if (!js_GetLengthProperty(cx, obj, &index))
-        return JS_FALSE;
+        return false;
+
     if (index == 0) {
-        vp->setUndefined();
-    } else {
-        index--;
-
-        /* Get the to-be-deleted property's value into vp. */
-        if (!GetElement(cx, obj, index, &hole, vp))
-            return JS_FALSE;
-        if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
-            return JS_FALSE;
+        args.rval().setUndefined();
+        return js_SetLengthProperty(cx, obj, index);
     }
+
+    index--;
+
+    JSBool hole;
+    Value elt;
+    if (!GetElement(cx, obj, index, &hole, &elt))
+        return false;
+
+    if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
+        return false;
+
+    args.rval() = elt;
     return js_SetLengthProperty(cx, obj, index);
 }
 
 static JSBool
-array_pop_dense(JSContext *cx, JSObject* obj, Value *vp)
+array_pop_dense(JSContext *cx, JSObject* obj, CallArgs &args)
 {
-    jsuint index;
-    JSBool hole;
-
-    index = obj->getArrayLength();
+    jsuint index = obj->getArrayLength();
     if (index == 0) {
-        vp->setUndefined();
+        args.rval().setUndefined();
         return JS_TRUE;
     }
+
     index--;
-    if (!GetElement(cx, obj, index, &hole, vp))
+    
+    JSBool hole;
+    Value elt;
+    if (!GetElement(cx, obj, index, &hole, &elt))
         return JS_FALSE;
+
     if (!hole && DeleteArrayElement(cx, obj, index, true) < 0)
         return JS_FALSE;
-
     if (cx->typeInferenceEnabled() && obj->getDenseArrayInitializedLength() > index)
         obj->setDenseArrayInitializedLength(index);
+
     obj->setArrayLength(cx, index);
+
+    args.rval() = elt;
     return JS_TRUE;
 }
 
 JSBool
 js::array_pop(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
     if (obj->isDenseArray())
-        return array_pop_dense(cx, obj, vp);
-    return array_pop_slowly(cx, obj, vp);
+        return array_pop_dense(cx, obj, args);
+    return array_pop_slowly(cx, obj, args);
 }
 
 #ifdef JS_METHODJIT
 void JS_FASTCALL
 mjit::stubs::ArrayShift(VMFrame &f)
 {
     JSObject *obj = &f.regs.sp[-1].toObject();
     JS_ASSERT(obj->isDenseArray());
@@ -2612,49 +2626,49 @@ mjit::stubs::ArrayShift(VMFrame &f)
     uint32 initlen = obj->getDenseArrayInitializedLength();
     obj->moveDenseArrayElements(0, 1, initlen);
 }
 #endif /* JS_METHODJIT */
 
 JSBool
 js::array_shift(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return JS_FALSE;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
 
     if (length == 0) {
-        vp->setUndefined();
+        args.rval().setUndefined();
     } else {
         length--;
 
         if (obj->isDenseArray() && !js_PrototypeHasIndexedProperties(cx, obj) &&
             length < obj->getDenseArrayCapacity() &&
             0 < obj->getDenseArrayInitializedLength()) {
-            *vp = obj->getDenseArrayElement(0);
-            if (vp->isMagic(JS_ARRAY_HOLE))
-                vp->setUndefined();
+            args.rval() = obj->getDenseArrayElement(0);
+            if (args.rval().isMagic(JS_ARRAY_HOLE))
+                args.rval().setUndefined();
             obj->moveDenseArrayElements(0, 1, length);
             if (cx->typeInferenceEnabled())
                 obj->setDenseArrayInitializedLength(obj->getDenseArrayInitializedLength() - 1);
             else
                 obj->setDenseArrayElement(length, MagicValue(JS_ARRAY_HOLE));
             obj->setArrayLength(cx, length);
             if (!js_SuppressDeletedProperty(cx, obj, INT_TO_JSID(length)))
                 return JS_FALSE;
             return JS_TRUE;
         }
 
-        /* Get the to-be-deleted property's value into vp ASAP. */
         JSBool hole;
-        if (!GetElement(cx, obj, 0, &hole, vp))
+        if (!GetElement(cx, obj, 0, &hole, &args.rval()))
             return JS_FALSE;
 
         /* Slide down the array above the first element. */
         AutoValueRooter tvr(cx);
         for (jsuint i = 0; i < length; i++) {
             if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                 !GetElement(cx, obj, i + 1, &hole, tvr.addr()) ||
                 !SetOrDeleteArrayElement(cx, obj, i, hole, tvr.value())) {
@@ -2667,78 +2681,75 @@ js::array_shift(JSContext *cx, uintN arg
             return JS_FALSE;
     }
     return js_SetLengthProperty(cx, obj, length);
 }
 
 static JSBool
 array_unshift(JSContext *cx, uintN argc, Value *vp)
 {
-    Value *argv;
-    JSBool hole;
-    jsdouble last, newlen;
-
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
 
-    newlen = length;
-    if (argc > 0) {
-        /* Slide up the array to make room for argc at the bottom. */
-        argv = JS_ARGV(cx, vp);
+    jsdouble newlen = length;
+    if (args.length() > 0) {
+        /* Slide up the array to make room for all args at the bottom. */
         if (length > 0) {
             bool optimized = false;
             do {
                 if (!obj->isDenseArray())
                     break;
                 if (js_PrototypeHasIndexedProperties(cx, obj))
                     break;
-                JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, argc);
+                JSObject::EnsureDenseResult result = obj->ensureDenseArrayElements(cx, length, args.length());
                 if (result != JSObject::ED_OK) {
                     if (result == JSObject::ED_FAILED)
                         return false;
                     JS_ASSERT(result == JSObject::ED_SPARSE);
                     break;
                 }
-                obj->moveDenseArrayElements(argc, 0, length);
-                for (uint32 i = 0; i < argc; i++)
+                obj->moveDenseArrayElements(args.length(), 0, length);
+                for (uint32 i = 0; i < args.length(); i++)
                     obj->setDenseArrayElement(i, MagicValue(JS_ARRAY_HOLE));
                 optimized = true;
             } while (false);
 
             if (!optimized) {
-                last = length;
-                jsdouble upperIndex = last + argc;
+                jsdouble last = length;
+                jsdouble upperIndex = last + args.length();
                 AutoValueRooter tvr(cx);
                 do {
                     --last, --upperIndex;
+                    JSBool hole;
                     if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                         !GetElement(cx, obj, last, &hole, tvr.addr()) ||
                         !SetOrDeleteArrayElement(cx, obj, upperIndex, hole, tvr.value())) {
                         return JS_FALSE;
                     }
                 } while (last != 0);
             }
         }
 
-        /* Copy from argv to the bottom of the array. */
-        if (!InitArrayElements(cx, obj, 0, argc, argv, true))
+        /* Copy from args to the bottom of the array. */
+        if (!InitArrayElements(cx, obj, 0, args.length(), args.array(), true))
             return JS_FALSE;
 
-        newlen += argc;
+        newlen += args.length();
     }
     if (!js_SetLengthProperty(cx, obj, newlen))
         return JS_FALSE;
 
     /* Follow Perl by returning the new array length. */
-    vp->setNumber(newlen);
+    args.rval().setNumber(newlen);
     return JS_TRUE;
 }
 
 static inline void
 TryReuseArrayType(JSObject *obj, JSObject *nobj)
 {
     /*
      * Try to change the type of a newly created array nobj to the same type
@@ -3097,47 +3108,46 @@ js::array_concat(JSContext *cx, uintN ar
     }
 
     return js_SetLengthProperty(cx, nobj, length);
 }
 
 static JSBool
 array_slice(JSContext *cx, uintN argc, Value *vp)
 {
-    Value *argv;
     JSObject *nobj;
     jsuint length, begin, end, slot;
     JSBool hole;
 
-    argv = JS_ARGV(cx, vp);
-
-    JSObject *obj = ToObject(cx, &vp[1]);
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
     begin = 0;
     end = length;
 
-    if (argc > 0) {
+    if (args.length() > 0) {
         jsdouble d;
-        if (!ToInteger(cx, argv[0], &d))
+        if (!ToInteger(cx, args[0], &d))
             return false;
         if (d < 0) {
             d += length;
             if (d < 0)
                 d = 0;
         } else if (d > length) {
             d = length;
         }
         begin = (jsuint)d;
 
-        if (argc > 1 && !argv[1].isUndefined()) {
-            if (!ToInteger(cx, argv[1], &d))
+        if (args.length() > 1 && !args[1].isUndefined()) {
+            if (!ToInteger(cx, args[1], &d))
                 return false;
             if (d < 0) {
                 d += length;
                 if (d < 0)
                     d = 0;
             } else if (d > length) {
                 d = length;
             }
@@ -3151,161 +3161,167 @@ array_slice(JSContext *cx, uintN argc, V
     if (obj->isDenseArray() && end <= obj->getDenseArrayInitializedLength() &&
         !js_PrototypeHasIndexedProperties(cx, obj)) {
         nobj = NewDenseCopiedArray(cx, end - begin, obj->getDenseArrayElements() + begin);
         if (!nobj)
             return JS_FALSE;
         TryReuseArrayType(obj, nobj);
         if (!obj->isPackedDenseArray())
             nobj->markDenseArrayNotPacked(cx);
-        vp->setObject(*nobj);
+        args.rval().setObject(*nobj);
         return JS_TRUE;
     }
 
-    /* Create a new Array object and root it using *vp. */
     nobj = NewDenseAllocatedArray(cx, end - begin);
     if (!nobj)
         return JS_FALSE;
     TryReuseArrayType(obj, nobj);
-    vp->setObject(*nobj);
 
     AutoValueRooter tvr(cx);
     for (slot = begin; slot < end; slot++) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
             !GetElement(cx, obj, slot, &hole, tvr.addr())) {
             return JS_FALSE;
         }
         if (!hole && !SetArrayElement(cx, nobj, slot - begin, tvr.value()))
             return JS_FALSE;
     }
 
+    args.rval().setObject(*nobj);
     return JS_TRUE;
 }
 
+enum IndexOfKind {
+    IndexOf,
+    LastIndexOf
+};
+
 static JSBool
-array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, Value *vp)
+array_indexOfHelper(JSContext *cx, IndexOfKind mode, CallArgs &args)
 {
     jsuint length, i, stop;
     Value tosearch;
     jsint direction;
     JSBool hole;
 
-    JSObject *obj = ToObject(cx, &vp[1]);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
     if (length == 0)
         goto not_found;
 
-    if (argc <= 1) {
-        i = isLast ? length - 1 : 0;
-        tosearch = (argc != 0) ? vp[2] : UndefinedValue();
+    if (args.length() <= 1) {
+        i = (mode == LastIndexOf) ? length - 1 : 0;
+        tosearch = (args.length() != 0) ? args[0] : UndefinedValue();
     } else {
         jsdouble start;
 
-        tosearch = vp[2];
-        if (!ToInteger(cx, vp[3], &start))
+        tosearch = args[0];
+        if (!ToInteger(cx, args[1], &start))
             return false;
         if (start < 0) {
             start += length;
             if (start < 0) {
-                if (isLast)
+                if (mode == LastIndexOf)
                     goto not_found;
                 i = 0;
             } else {
                 i = (jsuint)start;
             }
         } else if (start >= length) {
-            if (!isLast)
+            if (mode == IndexOf)
                 goto not_found;
             i = length - 1;
         } else {
             i = (jsuint)start;
         }
     }
 
-    if (isLast) {
+    if (mode == LastIndexOf) {
         stop = 0;
         direction = -1;
     } else {
         stop = length - 1;
         direction = 1;
     }
 
     for (;;) {
+        Value elt;
         if (!JS_CHECK_OPERATION_LIMIT(cx) ||
-            !GetElement(cx, obj, (jsuint)i, &hole, vp)) {
+            !GetElement(cx, obj, (jsuint)i, &hole, &elt)) {
             return JS_FALSE;
         }
         if (!hole) {
             JSBool equal;
-            if (!StrictlyEqual(cx, *vp, tosearch, &equal))
+            if (!StrictlyEqual(cx, elt, tosearch, &equal))
                 return JS_FALSE;
             if (equal) {
-                vp->setNumber(i);
+                args.rval().setNumber(i);
                 return JS_TRUE;
             }
         }
         if (i == stop)
             goto not_found;
         i += direction;
     }
 
   not_found:
-    vp->setInt32(-1);
+    args.rval().setInt32(-1);
     return JS_TRUE;
 }
 
 static JSBool
 array_indexOf(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_indexOfHelper(cx, JS_FALSE, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_indexOfHelper(cx, IndexOf, args);
 }
 
 static JSBool
 array_lastIndexOf(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_indexOfHelper(cx, JS_TRUE, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_indexOfHelper(cx, LastIndexOf, args);
 }
 
 /* Order is important; extras that take a predicate funarg must follow MAP. */
 typedef enum ArrayExtraMode {
     FOREACH,
     REDUCE,
     REDUCE_RIGHT,
     MAP,
     FILTER,
     SOME,
     EVERY
 } ArrayExtraMode;
 
 #define REDUCE_MODE(mode) ((mode) == REDUCE || (mode) == REDUCE_RIGHT)
 
 static JSBool
-array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
+array_extra(JSContext *cx, ArrayExtraMode mode, CallArgs &args)
 {
-    JSObject *obj = ToObject(cx, &vp[1]);
+    JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
 
     /*
      * First, get or compute our callee, so that we error out consistently
      * when passed a non-callable object.
      */
-    if (argc == 0) {
-        js_ReportMissingArg(cx, *vp, 0);
+    if (args.length() == 0) {
+        js_ReportMissingArg(cx, args.calleev(), 0);
         return JS_FALSE;
     }
-    Value *argv = vp + 2;
-    JSObject *callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);
+    JSObject *callable = js_ValueToCallableObject(cx, &args[0], JSV2F_SEARCH_STACK);
     if (!callable)
         return JS_FALSE;
 
     /*
      * Set our initial return condition, used for zero-length array cases
      * (and pre-size our map return to match our known length, for all cases).
      */
     jsuint newlen;
@@ -3318,27 +3334,27 @@ array_extra(JSContext *cx, ArrayExtraMod
     jsuint start = 0, end = length;
     jsint step = 1;
 
     switch (mode) {
       case REDUCE_RIGHT:
         start = length - 1, end = -1, step = -1;
         /* FALL THROUGH */
       case REDUCE:
-        if (length == 0 && argc == 1) {
+        if (length == 0 && args.length() == 1) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_EMPTY_ARRAY_REDUCE);
             return JS_FALSE;
         }
-        if (argc >= 2) {
-            *vp = argv[1];
+        if (args.length() >= 2) {
+            args.rval() = args[1];
         } else {
             JSBool hole;
             do {
-                if (!GetElement(cx, obj, start, &hole, vp))
+                if (!GetElement(cx, obj, start, &hole, &args.rval()))
                     return JS_FALSE;
                 start += step;
             } while (hole && start != end);
 
             if (hole && start == end) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                      JSMSG_EMPTY_ARRAY_REDUCE);
                 return JS_FALSE;
@@ -3350,93 +3366,93 @@ array_extra(JSContext *cx, ArrayExtraMod
         newlen = (mode == MAP) ? length : 0;
         newarr = NewDenseAllocatedArray(cx, newlen);
         if (!newarr)
             return JS_FALSE;
         newtype = GetTypeCallerInitObject(cx, JSProto_Array);
         if (!newtype)
             return JS_FALSE;
         newarr->setType(newtype);
-        vp->setObject(*newarr);
+        args.rval().setObject(*newarr);
         break;
       case SOME:
-        vp->setBoolean(false);
+        args.rval().setBoolean(false);
         break;
       case EVERY:
-        vp->setBoolean(true);
+        args.rval().setBoolean(true);
         break;
       case FOREACH:
-        vp->setUndefined();
+        args.rval().setUndefined();
         break;
     }
 
     if (length == 0)
         return JS_TRUE;
 
-    Value thisv = (argc > 1 && !REDUCE_MODE(mode)) ? argv[1] : UndefinedValue();
+    Value thisv = (args.length() > 1 && !REDUCE_MODE(mode)) ? args[1] : UndefinedValue();
 
     /*
      * For all but REDUCE, we call with 3 args (value, index, array). REDUCE
      * requires 4 args (accum, value, index, array).
      */
-    argc = 3 + REDUCE_MODE(mode);
+    uintN agArgc = 3 + REDUCE_MODE(mode);
 
     MUST_FLOW_THROUGH("out");
     JSBool ok = JS_TRUE;
     JSBool cond;
 
     Value objv = ObjectValue(*obj);
     AutoValueRooter tvr(cx);
-    InvokeArgsGuard args;
+    InvokeArgsGuard ag;
     for (jsuint i = start; i != end; i += step) {
         JSBool hole;
         ok = JS_CHECK_OPERATION_LIMIT(cx) &&
              GetElement(cx, obj, i, &hole, tvr.addr());
         if (!ok)
             goto out;
         if (hole)
             continue;
 
-        if (!args.pushed() && !cx->stack.pushInvokeArgs(cx, argc, &args))
+        if (!ag.pushed() && !cx->stack.pushInvokeArgs(cx, agArgc, &ag))
             return false;
 
         /*
          * Push callable and 'this', then args. We must do this for every
          * iteration around the loop since Invoke clobbers its arguments.
          */
-        args.calleeHasBeenReset();
-        args.calleev() = ObjectValue(*callable);
-        args.thisv() = thisv;
+        ag.calleeHasBeenReset();
+        ag.calleev() = ObjectValue(*callable);
+        ag.thisv() = thisv;
         uintN argi = 0;
         if (REDUCE_MODE(mode))
-            args[argi++] = *vp;
-        args[argi++] = tvr.value();
-        args[argi++] = Int32Value(i);
-        args[argi]   = objv;
+            ag[argi++] = args.rval();
+        ag[argi++] = tvr.value();
+        ag[argi++] = Int32Value(i);
+        ag[argi]   = objv;
 
         /* Do the call. */
-        ok = Invoke(cx, args);
+        ok = Invoke(cx, ag);
         if (!ok)
             break;
 
-        const Value &rval = args.rval();
+        const Value &rval = ag.rval();
 
         if (mode > MAP)
             cond = js_ValueToBoolean(rval);
 #ifdef __GNUC__ /* quell GCC overwarning */
         else
             cond = JS_FALSE;
 #endif
 
         switch (mode) {
           case FOREACH:
             break;
           case REDUCE:
           case REDUCE_RIGHT:
-            *vp = rval;
+            args.rval() = rval;
             break;
           case MAP:
             if (!ok)
                 goto out;
             ok = SetArrayElement(cx, newarr, i, rval);
             if (!ok)
                 goto out;
             break;
@@ -3447,75 +3463,82 @@ array_extra(JSContext *cx, ArrayExtraMod
             if (!ok)
                 goto out;
             ok = SetArrayElement(cx, newarr, newlen++, tvr.value());
             if (!ok)
                 goto out;
             break;
           case SOME:
             if (cond) {
-                vp->setBoolean(true);
+                args.rval().setBoolean(true);
                 goto out;
             }
             break;
           case EVERY:
             if (!cond) {
-                vp->setBoolean(false);
+                args.rval().setBoolean(false);
                 goto out;
             }
             break;
         }
     }
 
   out:
     if (ok && mode == FILTER)
         ok = js_SetLengthProperty(cx, newarr, newlen);
     return ok;
 }
 
 static JSBool
 array_forEach(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, FOREACH, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, FOREACH, args);
 }
 
 static JSBool
 array_map(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, MAP, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, MAP, args);
 }
 
 static JSBool
 array_reduce(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, REDUCE, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, REDUCE, args);
 }
 
 static JSBool
 array_reduceRight(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, REDUCE_RIGHT, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, REDUCE_RIGHT, args);
 }
 
 static JSBool
 array_filter(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, FILTER, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, FILTER, args);
 }
 
 static JSBool
 array_some(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, SOME, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, SOME, args);
 }
 
 static JSBool
 array_every(JSContext *cx, uintN argc, Value *vp)
 {
-    return array_extra(cx, EVERY, argc, vp);
+    CallArgs args = CallArgsFromVp(argc, vp);
+    return array_extra(cx, EVERY, args);
 }
 
 static JSBool
 array_isArray(JSContext *cx, uintN argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     bool isArray = args.length() > 0 &&
                    args[0].isObject() &&
@@ -3564,43 +3587,44 @@ static JSFunctionSpec array_static_metho
     JS_FN("isArray",            array_isArray,      1,0),
     JS_FS_END
 };
 
 /* ES5 15.4.2 */
 JSBool
 js_Array(JSContext *cx, uintN argc, Value *vp)
 {
+    CallArgs args = CallArgsFromVp(argc, vp);
     TypeObject *type = GetTypeCallerInitObject(cx, JSProto_Array);
     if (!type)
         return JS_FALSE;
 
-    if (argc != 1 || !vp[2].isNumber()) {
-        if (!InitArrayTypes(cx, type, vp + 2, argc))
+    if (args.length() != 1 || !args[0].isNumber()) {
+        if (!InitArrayTypes(cx, type, args.array(), args.length()))
             return false;
-        JSObject *obj = (argc == 0)
+        JSObject *obj = (args.length() == 0)
                         ? NewDenseEmptyArray(cx)
-                        : NewDenseCopiedArray(cx, argc, vp + 2);
+                        : NewDenseCopiedArray(cx, args.length(), args.array());
         if (!obj)
             return false;
         obj->setType(type);
-        vp->setObject(*obj);
+        args.rval().setObject(*obj);
         return true;
     }
 
     uint32 length;
-    if (vp[2].isInt32()) {
-        int32_t i = vp[2].toInt32();
+    if (args[0].isInt32()) {
+        int32 i = args[0].toInt32();
         if (i < 0) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
             return false;
         }
         length = uint32(i);
     } else {
-        jsdouble d = vp[2].toDouble();
+        jsdouble d = args[0].toDouble();
         length = js_DoubleToECMAUint32(d);
         if (d != jsdouble(length)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
             return false;
         }
     }
 
     JSObject *obj = NewDenseUnallocatedArray(cx, length);
@@ -3608,17 +3632,17 @@ js_Array(JSContext *cx, uintN argc, Valu
         return false;
 
     obj->setType(type);
 
     /* If the length calculation overflowed, make sure that is marked for the new type. */
     if (obj->getArrayLength() > INT32_MAX)
         obj->setArrayLength(cx, obj->getArrayLength());
 
-    vp->setObject(*obj);
+    args.rval().setObject(*obj);
     return true;
 }
 
 JSObject *
 js_InitArrayClass(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isNative());
 
@@ -3770,21 +3794,21 @@ NewSlowEmptyArray(JSContext *cx)
 
 }
 
 
 #ifdef DEBUG
 JSBool
 js_ArrayInfo(JSContext *cx, uintN argc, jsval *vp)
 {
-    uintN i;
+    CallArgs args = CallArgsFromVp(argc, vp);
     JSObject *array;
 
-    for (i = 0; i < argc; i++) {
-        Value arg = JS_ARGV(cx, vp)[i];
+    for (uintN i = 0; i < args.length(); i++) {
+        Value arg = args[i];
 
         char *bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, arg, NULL);
         if (!bytes)
             return JS_FALSE;
         if (arg.isPrimitive() ||
             !(array = arg.toObjectOrNull())->isArray()) {
             fprintf(stderr, "%s: not array\n", bytes);
             cx->free_(bytes);
@@ -3796,12 +3820,12 @@ js_ArrayInfo(JSContext *cx, uintN argc, 
         if (array->isDenseArray()) {
             fprintf(stderr, ", capacity %u",
                     array->getDenseArrayCapacity());
         }
         fputs(")\n", stderr);
         cx->free_(bytes);
     }
 
-    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+    args.rval().setUndefined();
     return true;
 }
 #endif
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -203,18 +203,18 @@ class CompartmentChecker
                     check(ida->vector[i]);
             }
         }
     }
 
     void check(JSScript *script) {
         if (script) {
             check(script->compartment());
-            if (script->u.object)
-                check(script->u.object);
+            if (!script->isCachedEval && script->u.globalObject)
+                check(script->u.globalObject);
         }
     }
 
     void check(StackFrame *fp) {
         check(&fp->scopeChain());
     }
 };
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -273,17 +273,17 @@ JSCompartment::wrap(JSContext *cx, Value
     }
 
     /* If we already have a wrapper for this value, use it. */
     if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
         *vp = p->value;
         if (vp->isObject()) {
             JSObject *obj = &vp->toObject();
             JS_ASSERT(obj->isCrossCompartmentWrapper());
-            if (global->getJSClass() != &js_dummy_class && obj->getParent() != global) {
+            if (global->getClass() != &dummy_class && obj->getParent() != global) {
                 do {
                     obj->setParent(global);
                     obj = obj->getProto();
                 } while (obj && obj->isCrossCompartmentWrapper());
             }
         }
         return true;
     }
@@ -407,52 +407,16 @@ JSCompartment::wrap(JSContext *cx, AutoI
     jsint length = props.length();
     for (size_t n = 0; n < size_t(length); ++n) {
         if (!wrapId(cx, &vector[n]))
             return false;
     }
     return true;
 }
 
-#if defined JS_METHODJIT && defined JS_MONOIC
-/*
- * Check if the pool containing the code for jit should be destroyed, per the
- * heuristics in JSCompartment::sweep.
- */
-static inline bool
-ScriptPoolDestroyed(JSContext *cx, mjit::JITScript *jit,
-                    uint32 releaseInterval, uint32 &counter)
-{
-    JSC::ExecutablePool *pool = jit->code.m_executablePool;
-    if (pool->m_gcNumber != cx->runtime->gcNumber) {
-        /*
-         * The m_destroy flag may have been set in a previous GC for a pool which had
-         * references we did not remove (e.g. from the compartment's ExecutableAllocator)
-         * and is still around. Forget we tried to destroy it in such cases.
-         */
-        pool->m_destroy = false;
-        pool->m_gcNumber = cx->runtime->gcNumber;
-        if (--counter == 0) {
-            pool->m_destroy = true;
-            counter = releaseInterval;
-        }
-    }
-    return pool->m_destroy;
-}
-
-static inline void
-ScriptTryDestroyCode(JSContext *cx, JSScript *script, bool normal,
-                     uint32 releaseInterval, uint32 &counter)
-{
-    mjit::JITScript *jit = normal ? script->jitNormal : script->jitCtor;
-    if (jit && ScriptPoolDestroyed(cx, jit, releaseInterval, counter))
-        mjit::ReleaseScriptCode(cx, script, !normal);
-}
-#endif // JS_METHODJIT && JS_MONOIC
-
 /*
  * This method marks pointers that cross compartment boundaries. It should be
  * called only for per-compartment GCs, since full GCs naturally follow pointers
  * across compartments.
  */
 void
 JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
 {
@@ -487,17 +451,17 @@ JSCompartment::markTypes(JSTracer *trc)
         }
     }
 
     for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next())
         MarkTypeObject(trc, i.get<types::TypeObject>(), "mark_types_scan");
 }
 
 void
-JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
+JSCompartment::sweep(JSContext *cx, bool releaseTypes)
 {
     /* Remove dead wrappers from the table. */
     for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
         JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key.toGCThing()) &&
                      !IsAboutToBeFinalized(cx, e.front().value.toGCThing()),
                      e.front().key.isString());
         if (IsAboutToBeFinalized(cx, e.front().key.toGCThing()) ||
             IsAboutToBeFinalized(cx, e.front().value.toGCThing())) {
@@ -526,117 +490,63 @@ JSCompartment::sweep(JSContext *cx, uint
 
     sweepBreakpoints(cx);
 
 #ifdef JS_TRACER
     if (hasTraceMonitor())
         traceMonitor()->sweep(cx);
 #endif
 
-#ifdef JS_METHODJIT
     /*
-     * Purge PICs in the compartment, along with native call stubs for
-     * compartments which do not have such stubs on the stack. PICs can
-     * reference shapes and type data, and native call stubs are disassociated
-     * from the PIC or MIC they were generated for.
+     * Kick all frames on the stack into the interpreter, and release all JIT
+     * code in the compartment.
      */
-    bool canPurgeNativeCalls = true;
-    VMFrame *f = hasJaegerCompartment() ? jaegerCompartment()->activeFrame() : NULL;
-    for (; f; f = f->previous) {
-        if (f->stubRejoin)
-            canPurgeNativeCalls = false;
-    }
+#ifdef JS_METHODJIT
+    mjit::ClearAllFrames(this);
+
     for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
-        if (script->hasJITCode()) {
-#ifdef JS_POLYIC
-            mjit::ic::PurgePICs(cx, script);
-#endif
-            if (canPurgeNativeCalls) {
-                if (script->jitNormal)
-                    script->jitNormal->purgeNativeCallStubs();
-                if (script->jitCtor)
-                    script->jitCtor->purgeNativeCallStubs();
-            }
-        }
+        mjit::ReleaseScriptCode(cx, script);
+
+        /*
+         * Use counts for scripts are reset on GC. After discarding code we
+         * need to let it warm back up to get information like which opcodes
+         * are setting array holes or accessing getter properties.
+         */
+        script->resetUseCount();
     }
 #endif
 
-    bool discardScripts = !active && (releaseInterval != 0 || hasDebugModeCodeToDrop);
-
-#if defined JS_METHODJIT && defined JS_MONOIC
-
-    /*
-     * The release interval is the frequency with which we should try to destroy
-     * executable pools by releasing all JIT code in them, zero to never destroy pools.
-     * Initialize counter so that the first pool will be destroyed, and eventually drive
-     * the amount of JIT code in never-used compartments to zero. Don't discard anything
-     * for compartments which currently have active stack frames.
-     */
-    uint32 counter = 1;
-    if (discardScripts)
-        hasDebugModeCodeToDrop = false;
-
-    for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
-        JSScript *script = i.get<JSScript>();
-        if (script->hasJITCode()) {
-            mjit::ic::SweepCallICs(cx, script, discardScripts);
-            if (discardScripts) {
-                ScriptTryDestroyCode(cx, script, true, releaseInterval, counter);
-                ScriptTryDestroyCode(cx, script, false, releaseInterval, counter);
-            }
-        }
-    }
-
-#endif
-
-#ifdef JS_METHODJIT
-    if (types.inferenceEnabled)
-        mjit::ClearAllFrames(this);
-#endif
-
-    if (activeAnalysis) {
-        /*
-         * Analysis information is in use, so don't clear the analysis pool.
-         * jitcode still needs to be released, if this is a shape-regenerating
-         * GC then shape numbers baked into the code may change.
-         */
-#ifdef JS_METHODJIT
-        if (types.inferenceEnabled) {
-            for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
-                JSScript *script = i.get<JSScript>();
-                mjit::ReleaseScriptCode(cx, script);
-            }
-        }
-#endif
-    } else {
+    if (!activeAnalysis) {
         /*
          * Clear the analysis pool, but don't release its data yet. While
          * sweeping types any live data will be allocated into the pool.
          */
         LifoAlloc oldAlloc(typeLifoAlloc.defaultChunkSize());
         oldAlloc.steal(&typeLifoAlloc);
 
         /*
+         * Periodically release observed types for all scripts. This is safe to
+         * do when there are no frames for the compartment on the stack.
+         */
+        if (active)
+            releaseTypes = false;
+
+        /*
          * Sweep analysis information and everything depending on it from the
          * compartment, including all remaining mjit code if inference is
          * enabled in the compartment.
          */
         if (types.inferenceEnabled) {
             for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
                 JSScript *script = i.get<JSScript>();
                 if (script->types) {
                     types::TypeScript::Sweep(cx, script);
 
-                    /*
-                     * On each 1/8 lifetime, release observed types for all scripts.
-                     * This is always safe to do when there are no frames for the
-                     * compartment on the stack.
-                     */
-                    if (discardScripts) {
+                    if (releaseTypes) {
                         script->types->destroy();
                         script->types = NULL;
                         script->typesPurged = true;
                     }
                 }
             }
         }
 
@@ -679,30 +589,16 @@ JSCompartment::purge(JSContext *cx)
     /*
      * If we are about to regenerate shapes, we have to flush the JIT cache,
      * which will eventually abort any current recording.
      */
     if (cx->runtime->gcRegenShapes)
         if (hasTraceMonitor())
             traceMonitor()->needFlush = JS_TRUE;
 #endif
-
-#if defined JS_METHODJIT && defined JS_MONOIC
-    /*
-     * MICs do not refer to data which can be GC'ed and do not generate stubs
-     * which might need to be discarded, but are sensitive to shape regeneration.
-     */
-    if (cx->runtime->gcRegenShapes) {
-        for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
-            JSScript *script = i.get<JSScript>();
-            if (script->hasJITCode())
-                mjit::ic::PurgeMICs(cx, script);
-        }
-    }
-#endif
 }
 
 MathCache *
 JSCompartment::allocMathCache(JSContext *cx)
 {
     JS_ASSERT(!mathCache);
     mathCache = cx->new_<MathCache>();
     if (!mathCache)
@@ -856,39 +752,36 @@ JSCompartment::removeDebuggee(JSContext 
 BreakpointSite *
 JSCompartment::getBreakpointSite(jsbytecode *pc)
 {
     BreakpointSiteMap::Ptr p = breakpointSites.lookup(pc);
     return p ? p->value : NULL;
 }
 
 BreakpointSite *
-JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc, JSObject *scriptObject)
+JSCompartment::getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
+                                         GlobalObject *scriptGlobal)
 {
     JS_ASSERT(script->code <= pc);
     JS_ASSERT(pc < script->code + script->length);
-    JS_ASSERT_IF(scriptObject, scriptObject->isScript() || scriptObject->isFunction());
-    JS_ASSERT_IF(scriptObject && scriptObject->isFunction(),
-                 scriptObject->getFunctionPrivate()->script() == script);
-    JS_ASSERT_IF(scriptObject && scriptObject->isScript(), scriptObject->getScript() == script);
 
     BreakpointSiteMap::AddPtr p = breakpointSites.lookupForAdd(pc);
     if (!p) {
         BreakpointSite *site = cx->runtime->new_<BreakpointSite>(script, pc);
         if (!site || !breakpointSites.add(p, pc, site)) {
             js_ReportOutOfMemory(cx);
             return NULL;
         }
     }
 
     BreakpointSite *site = p->value;
-    if (site->scriptObject)
-        JS_ASSERT_IF(scriptObject, site->scriptObject == scriptObject);
+    if (site->scriptGlobal)
+        JS_ASSERT_IF(scriptGlobal, site->scriptGlobal == scriptGlobal);
     else
-        site->scriptObject = scriptObject;
+        site->scriptGlobal = scriptGlobal;
 
     return site;
 }
 
 void
 JSCompartment::clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSScript *script,
                                   JSObject *handler)
 {
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -288,20 +288,21 @@ struct TraceMonitor {
     JS_FRIEND_API(size_t) getVMAllocatorsMainSize(JSUsableSizeFun usf) const;
     JS_FRIEND_API(size_t) getVMAllocatorsReserveSize(JSUsableSizeFun usf) const;
     JS_FRIEND_API(size_t) getTraceMonitorSize(JSUsableSizeFun usf) const;
 };
 
 namespace mjit {
 class JaegerCompartment;
 }
-}
 
 /* Defined in jsapi.cpp */
-extern JSClass js_dummy_class;
+extern Class dummy_class;
+
+} /* namespace js */
 
 #ifndef JS_EVAL_CACHE_SHIFT
 # define JS_EVAL_CACHE_SHIFT        6
 #endif
 
 /* Number of buckets in the hash of eval scripts. */
 #define JS_EVAL_CACHE_SIZE          JS_BIT(JS_EVAL_CACHE_SHIFT)
 
@@ -528,17 +529,17 @@ struct JS_FRIEND_API(JSCompartment) {
     bool wrap(JSContext *cx, JSObject **objp);
     bool wrapId(JSContext *cx, jsid *idp);
     bool wrap(JSContext *cx, js::PropertyOp *op);
     bool wrap(JSContext *cx, js::StrictPropertyOp *op);
     bool wrap(JSContext *cx, js::PropertyDescriptor *desc);
     bool wrap(JSContext *cx, js::AutoIdVector &props);
 
     void markTypes(JSTracer *trc);
-    void sweep(JSContext *cx, uint32 releaseInterval);
+    void sweep(JSContext *cx, bool releaseTypes);
     void purge(JSContext *cx);
 
     void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(uint32 amount);
 
     js::DtoaCache dtoaCache;
 
   private:
@@ -610,17 +611,17 @@ struct JS_FRIEND_API(JSCompartment) {
     js::GlobalObjectSet &getDebuggees() { return debuggees; }
     bool addDebuggee(JSContext *cx, js::GlobalObject *global);
     void removeDebuggee(JSContext *cx, js::GlobalObject *global,
                         js::GlobalObjectSet::Enum *debuggeesEnum = NULL);
     bool setDebugModeFromC(JSContext *cx, bool b);
 
     js::BreakpointSite *getBreakpointSite(jsbytecode *pc);
     js::BreakpointSite *getOrCreateBreakpointSite(JSContext *cx, JSScript *script, jsbytecode *pc,
-                                                  JSObject *scriptObject);
+                                                  js::GlobalObject *scriptGlobal);
     void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSScript *script, JSObject *handler);
     void clearTraps(JSContext *cx, JSScript *script);
     bool markTrapClosuresIteratively(JSTracer *trc);
 
   private:
     void sweepBreakpoints(JSContext *cx);
 
   public:
deleted file mode 100644
--- a/js/src/jscpucfg.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * Generate CPU-specific bit-size and similar #defines.
- */
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(CROSS_COMPILE) && !defined(FORCE_BIG_ENDIAN) && !defined(FORCE_LITTLE_ENDIAN)
-#include <prtypes.h>
-#endif
-
-/************************************************************************/
-
-int main(int argc, char **argv)
-{
-    printf("#ifndef js_cpucfg___\n");
-    printf("#define js_cpucfg___\n\n");
-
-    printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
-
-#ifdef CROSS_COMPILE
-#if defined(__APPLE__) && !defined(FORCE_BIG_ENDIAN) && !defined(FORCE_LITTLE_ENDIAN)
-    /*
-     * Darwin NSPR uses the same MDCPUCFG (_darwin.cfg) for multiple
-     * processors, and determines which processor to configure for based
-     * on compiler predefined macros.  We do the same thing here.
-     */
-    printf("#ifdef __LITTLE_ENDIAN__\n");
-    printf("#define IS_LITTLE_ENDIAN 1\n");
-    printf("#undef  IS_BIG_ENDIAN\n");
-    printf("#else\n");
-    printf("#undef  IS_LITTLE_ENDIAN\n");
-    printf("#define IS_BIG_ENDIAN 1\n");
-    printf("#endif\n\n");
-#elif defined(IS_LITTLE_ENDIAN) || defined(FORCE_LITTLE_ENDIAN)
-    printf("#define IS_LITTLE_ENDIAN 1\n");
-    printf("#undef  IS_BIG_ENDIAN\n\n");
-#elif defined(IS_BIG_ENDIAN) || defined(FORCE_BIG_ENDIAN)
-    printf("#undef  IS_LITTLE_ENDIAN\n");
-    printf("#define IS_BIG_ENDIAN 1\n\n");
-#else
-#error "Endianess not defined."
-#endif
-
-#else
-
-    /*
-     * We don't handle PDP-endian or similar orders: if a short is big-endian,
-     * so must int and long be big-endian for us to generate the IS_BIG_ENDIAN
-     * #define and the IS_LITTLE_ENDIAN #undef.
-     */
-    {
-        int big_endian = 0, little_endian = 0, ntests = 0;
-
-        if (sizeof(short) == 2) {
-            /* force |volatile| here to get rid of any compiler optimisations
-             * (var in register etc.) which may be appiled to |auto| vars -
-             * even those in |union|s...
-             * (|static| is used to get the same functionality for compilers
-             * which do not honor |volatile|...).
-             */
-            volatile static union {
-                short i;
-                char c[2];
-            } u;
-
-            u.i = 0x0102;
-            big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02);
-            little_endian += (u.c[0] == 0x02 && u.c[1] == 0x01);
-            ntests++;
-        }
-
-        if (sizeof(int) == 4) {
-            /* force |volatile| here ... */
-            volatile static union {
-                int i;
-                char c[4];
-            } u;
-
-            u.i = 0x01020304;
-            big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
-                           u.c[2] == 0x03 && u.c[3] == 0x04);
-            little_endian += (u.c[0] == 0x04 && u.c[1] == 0x03 &&
-                              u.c[2] == 0x02 && u.c[3] == 0x01);
-            ntests++;
-        }
-
-        if (sizeof(long) == 8) {
-            /* force |volatile| here ... */
-            volatile static union {
-                long i;
-                char c[8];
-            } u;
-
-            /*
-             * Write this as portably as possible: avoid 0x0102030405060708L
-             * and <<= 32.
-             */
-            u.i = 0x01020304;
-            u.i <<= 16, u.i <<= 16;
-            u.i |= 0x05060708;
-            big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
-                           u.c[2] == 0x03 && u.c[3] == 0x04 &&
-                           u.c[4] == 0x05 && u.c[5] == 0x06 &&
-                           u.c[6] == 0x07 && u.c[7] == 0x08);
-            little_endian += (u.c[0] == 0x08 && u.c[1] == 0x07 &&
-                              u.c[2] == 0x06 && u.c[3] == 0x05 &&
-                              u.c[4] == 0x04 && u.c[5] == 0x03 &&
-                              u.c[6] == 0x02 && u.c[7] == 0x01);
-            ntests++;
-        }
-
-        if (big_endian && big_endian == ntests) {
-            printf("#undef  IS_LITTLE_ENDIAN\n");
-            printf("#define IS_BIG_ENDIAN 1\n\n");
-        } else if (little_endian && little_endian == ntests) {
-            printf("#define IS_LITTLE_ENDIAN 1\n");
-            printf("#undef  IS_BIG_ENDIAN\n\n");
-        } else {
-            fprintf(stderr, "%s: unknown byte order"
-                    "(big_endian=%d, little_endian=%d, ntests=%d)!\n",
-                    argv[0], big_endian, little_endian, ntests);
-            return EXIT_FAILURE;
-        }
-    }
-
-#endif /* CROSS_COMPILE */
-
-    // PA-RISC is the only platform we try to support on which the stack
-    // grows towards higher addresses. Trying to detect it here has
-    // historically led to portability problems, which aren't worth it
-    // given the near consensus on stack growth direction.
-    printf("#ifdef __hppa\n"
-           "# define JS_STACK_GROWTH_DIRECTION (1)\n"
-           "#else\n"
-           "# define JS_STACK_GROWTH_DIRECTION (-1)\n"
-           "#endif\n");
-
-    printf("#endif /* js_cpucfg___ */\n");
-
-    return EXIT_SUCCESS;
-}
-
--- a/js/src/jscpucfg.h
+++ b/js/src/jscpucfg.h
@@ -63,21 +63,45 @@
 
 #define IS_LITTLE_ENDIAN 1
 #undef  IS_BIG_ENDIAN
 #define JS_BYTES_PER_DOUBLE 8L
 #define JS_BYTES_PER_WORD   4L
 #define JS_BITS_PER_WORD_LOG2   5
 #define JS_ALIGN_OF_POINTER 4L
 
-#else
+#elif defined(__APPLE__)
+#if __LITTLE_ENDIAN__
+#define IS_LITTLE_ENDIAN 1
+#undef  IS_BIG_ENDIAN
+#elif __BIG_ENDIAN__
+#undef  IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#endif
+
+#elif defined(JS_HAVE_ENDIAN_H)
+#include <endian.h>
 
-#error "This file is supposed to be auto-generated on most platforms, but the"
-#error "static version for Windows and OS2 platforms is being used."
-#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
+#if defined(__BYTE_ORDER)
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#undef  IS_BIG_ENDIAN
+#elif __BYTE_ORDER == __BIG_ENDIAN
+#undef  IS_LITTLE_ENDIAN
+#define IS_BIG_ENDIAN 1
+#endif
+#else /* !defined(__BYTE_ORDER) */
+#error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
+#endif
 
+#else /* !defined(HAVE_ENDIAN_H) */
+#error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
 #endif
 
 #ifndef JS_STACK_GROWTH_DIRECTION
-#define JS_STACK_GROWTH_DIRECTION (-1)
+#ifdef __hppa
+# define JS_STACK_GROWTH_DIRECTION (1)
+#else
+# define JS_STACK_GROWTH_DIRECTION (-1)
+#endif
 #endif
 
 #endif /* js_cpucfg___ */
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -292,16 +292,19 @@ JS_SetWatchPoint(JSContext *cx, JSObject
     origobj = obj;
     OBJ_TO_INNER_OBJECT(cx, obj);
     if (!obj)
         return false;
 
     AutoValueRooter idroot(cx);
     if (JSID_IS_INT(id)) {
         propid = id;
+    } else if (JSID_IS_OBJECT(id)) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH_PROP);
+        return false;
     } else {
         if (!js_ValueToStringId(cx, IdToValue(id), &propid))
             return false;
         propid = js_CheckForStringIndex(propid);
         idroot.set(IdToValue(propid));
     }
 
     /*
@@ -323,17 +326,17 @@ JS_SetWatchPoint(JSContext *cx, JSObject
     if (!wpmap) {
         wpmap = cx->runtime->new_<WatchpointMap>();
         if (!wpmap || !wpmap->init()) {
             js_ReportOutOfMemory(cx);
             return false;
         }
         cx->compartment->watchpointMap = wpmap;
     }
-    return wpmap->watch(cx, obj, id, handler, closure);
+    return wpmap->watch(cx, obj, propid, handler, closure);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
                    JSWatchPointHandler *handlerp, JSObject **closurep)
 {
     assertSameCompartment(cx, obj, id);
 
@@ -1041,19 +1044,16 @@ JS_PUBLIC_API(size_t)
 JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
 {
     size_t nbytes, pbytes;
     jssrcnote *sn, *notes;
     JSObjectArray *objarray;
     JSPrincipals *principals;
 
     nbytes = sizeof *script;
-    if (script->u.object)
-        nbytes += JS_GetObjectTotalSize(cx, script->u.object);
-
     nbytes += script->length * sizeof script->code[0];
     nbytes += script->natoms * sizeof script->atoms[0];
     for (size_t i = 0; i < script->natoms; i++)
         nbytes += GetAtomTotalSize(cx, script->atoms[i]);
 
     if (script->filename)
         nbytes += strlen(script->filename) + 1;
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1553,67 +1553,62 @@ js_XDRFunctionObject(JSXDRState *xdr, JS
     JSContext *cx;
     JSFunction *fun;
     uint32 firstword;           /* flag telling whether fun->atom is non-null,
                                    plus for fun->u.i.skipmin, fun->u.i.wrapper,
                                    and 14 bits reserved for future use */
     uint32 flagsword;           /* word for argument count and fun->flags */
 
     cx = xdr->cx;
+    JSScript *script;
     if (xdr->mode == JSXDR_ENCODE) {
         fun = (*objp)->getFunctionPrivate();
         if (!fun->isInterpreted()) {
             JSAutoByteString funNameBytes;
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_SCRIPTED_FUNCTION,
                                      name);
             }
             return false;
         }
         firstword = (fun->u.i.skipmin << 2) | !!fun->atom;
         flagsword = (fun->nargs << 16) | fun->flags;
+        script = fun->script();
     } else {
         fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
         if (!fun)
             return false;
         fun->clearParent();
         fun->clearType();
+        script = NULL;
     }
 
     AutoObjectRooter tvr(cx, fun);
 
     if (!JS_XDRUint32(xdr, &firstword))
         return false;
     if ((firstword & 1U) && !js_XDRAtom(xdr, &fun->atom))
         return false;
     if (!JS_XDRUint32(xdr, &flagsword))
         return false;
 
+    if (!js_XDRScript(xdr, &script))
+        return false;
+
     if (xdr->mode == JSXDR_DECODE) {
         fun->nargs = flagsword >> 16;
         JS_ASSERT((flagsword & JSFUN_KINDMASK) >= JSFUN_INTERPRETED);
         fun->flags = uint16(flagsword);
         fun->u.i.skipmin = uint16(firstword >> 2);
-    }
-
-    /*
-     * Don't directly store into fun->u.i.script because we want this to happen
-     * at the same time as we set the script's owner.
-     */
-    JSScript *script = fun->script();
-    if (!js_XDRScript(xdr, &script))
-        return false;
-
-    if (xdr->mode == JSXDR_DECODE) {
-        *objp = fun;
         fun->setScript(script);
-        if (!fun->script()->typeSetFunction(cx, fun))
+        if (!script->typeSetFunction(cx, fun))
             return false;
         JS_ASSERT(fun->nargs == fun->script()->bindings.countArgs());
         js_CallNewScriptHook(cx, fun->script(), fun);
+        *objp = fun;
     }
 
     return true;
 }
 
 #else  /* !JS_HAS_XDR */
 
 #define js_XDRFunctionObject NULL
@@ -1669,20 +1664,18 @@ fun_trace(JSTracer *trc, JSObject *obj)
                            obj->getFlatClosureUpvars(), "upvars");
         }
         return;
     }
 
     if (fun->atom)
         MarkString(trc, fun->atom, "atom");
 
-    if (fun->isInterpreted() && fun->script()) {
-        CheckScriptOwner(fun->script(), obj);
+    if (fun->isInterpreted() && fun->script())
         MarkScript(trc, fun->script(), "script");
-    }
 }
 
 static void
 fun_finalize(JSContext *cx, JSObject *obj)
 {
     obj->finalizeUpvarsIfFlatClosure();
 }
 
@@ -2416,29 +2409,28 @@ js_CloneFunctionObject(JSContext *cx, JS
         cfun->u = fun->getFunctionPrivate()->u;
         cfun->atom = fun->atom;
         clone->setPrivate(cfun);
         if (cfun->isInterpreted()) {
             JSScript *script = fun->script();
             JS_ASSERT(script);
             JS_ASSERT(script->compartment() == fun->compartment());
             JS_ASSERT(script->compartment() != cx->compartment);
-            JS_OPT_ASSERT(script->ownerObject == fun);
 
             cfun->u.i.script_ = NULL;
             JSScript *cscript = js_CloneScript(cx, script);
             if (!cscript)
                 return NULL;
-
+            cscript->u.globalObject = cfun->getGlobal();
             cfun->setScript(cscript);
-            if (!cfun->script()->typeSetFunction(cx, cfun))
+            if (!cscript->typeSetFunction(cx, cfun))
                 return NULL;
 
             js_CallNewScriptHook(cx, cfun->script(), cfun);
-            Debugger::onNewScript(cx, cfun->script(), cfun, NULL);
+            Debugger::onNewScript(cx, cfun->script(), NULL);
         }
     }
     return clone;
 }
 
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_CloneFunctionObject, CONTEXT, FUNCTION, OBJECT, OBJECT, 0,
                      nanojit::ACCSET_STORE_ANY)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -198,20 +198,19 @@ struct JSFunction : public JSObject_Slot
     JSScript *script() const {
         JS_ASSERT(isInterpreted());
         return u.i.script_;
     }
 
     void setScript(JSScript *script) {
         JS_ASSERT(isInterpreted());
         u.i.script_ = script;
-        script->setOwnerObject(this);
     }
 
-    JSScript * maybeScript() const {
+    JSScript *maybeScript() const {
         return isInterpreted() ? script() : NULL;
     }
 
     JSNative native() const {
         JS_ASSERT(isNative());
         return u.n.native;
     }
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -725,22 +725,18 @@ IsAboutToBeFinalized(JSContext *cx, cons
 JS_FRIEND_API(bool)
 js_GCThingIsMarked(void *thing, uintN color = BLACK)
 {
     JS_ASSERT(thing);
     AssertValidColor(thing, color);
     return reinterpret_cast<Cell *>(thing)->isMarked(color);
 }
 
-/*
- * 1/8 life for JIT code. After this number of microseconds have passed, 1/8 of all
- * JIT code is discarded in inactive compartments, regardless of how often that
- * code runs.
- */
-static const int64 JIT_SCRIPT_EIGHTH_LIFETIME = 60 * 1000 * 1000;
+/* Lifetime for type sets attached to scripts containing observed types. */
+static const int64 JIT_SCRIPT_RELEASE_TYPES_INTERVAL = 60 * 1000 * 1000;
 
 JSBool
 js_InitGC(JSRuntime *rt, uint32 maxbytes)
 {
     if (!rt->gcChunkSet.init(INITIAL_CHUNK_CAPACITY))
         return false;
 
     if (!rt->gcRootsHash.init(256))
@@ -772,17 +768,17 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes
     rt->gcEmptyArenaPoolLifespan = 30000;
 
     /*
      * The assigned value prevents GC from running when GC memory is too low
      * (during JS engine start).
      */
     rt->setGCLastBytes(8192, GC_NORMAL);
 
-    rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_EIGHTH_LIFETIME;
+    rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
     return true;
 }
 
 namespace js {
 
 inline bool
 InFreeList(ArenaHeader *aheader, uintptr_t addr)
 {
@@ -2276,37 +2272,29 @@ GCHelperThread::doSweep()
     }
     freeVector.resize(0);
 }
 
 } /* namespace js */
 
 #endif /* JS_THREADSAFE */
 
-static uint32
-ComputeJitReleaseInterval(JSContext *cx)
+static bool
+ReleaseObservedTypes(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
-    /*
-     * Figure out how much JIT code should be released from inactive compartments.
-     * If multiple eighth-lives have passed, compound the release interval linearly;
-     * if enough time has passed, all inactive JIT code will be released.
-     */
-    uint32 releaseInterval = 0;
+
+    bool releaseTypes = false;
     int64 now = PRMJ_Now();
     if (now >= rt->gcJitReleaseTime) {
-        releaseInterval = 8;
-        while (now >= rt->gcJitReleaseTime) {
-            if (--releaseInterval == 1)
-                rt->gcJitReleaseTime = now;
-            rt->gcJitReleaseTime += JIT_SCRIPT_EIGHTH_LIFETIME;
-        }
+        releaseTypes = true;
+        rt->gcJitReleaseTime = now + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
     }
 
-    return releaseInterval;
+    return releaseTypes;
 }
 
 static void
 SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
     JSCompartmentCallback callback = rt->compartmentCallback;
 
@@ -2447,19 +2435,19 @@ SweepPhase(JSContext *cx, GCMarker *gcma
     js_SweepAtomState(cx);
 
     /* Collect watch points associated with unreachable objects. */
     WatchpointMap::sweepAll(cx);
 
     if (!rt->gcCurrentCompartment)
         Debugger::sweepAll(cx);
 
-    uint32 releaseInterval = rt->gcCurrentCompartment ? 0 : ComputeJitReleaseInterval(cx);
+    bool releaseTypes = !rt->gcCurrentCompartment && ReleaseObservedTypes(cx);
     for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        c->sweep(cx, releaseInterval);
+        c->sweep(cx, releaseTypes);
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_OBJECT);
 
         /*
          * We finalize objects before other GC things to ensure that the object's
          * finalizer can access the other things even if they will be freed.
          */
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -181,17 +181,17 @@ MarkCrossCompartmentObject(JSTracer *trc
     if (rt->gcCurrentCompartment && rt->gcCurrentCompartment != obj.compartment())
         return;
 
     MarkObject(trc, obj, name);
 }
 
 void
 MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer,
-		      const void *arg, size_t index)
+                      const void *arg, size_t index)
 {
     JS_ASSERT(trc);
     JS_ASSERT(&obj);
     JS_SET_TRACING_DETAILS(trc, printer, arg, index);
     Mark(trc, &obj);
 }
 
 void
@@ -827,33 +827,26 @@ MarkChildren(JSTracer *trc, JSScript *sc
         MarkObjectRange(trc, objarray->length, objarray->vector, "objects");
     }
 
     if (JSScript::isValidOffset(script->constOffset)) {
         JSConstArray *constarray = script->consts();
         MarkValueRange(trc, constarray->length, constarray->vector, "consts");
     }
 
-    if (!script->isCachedEval && script->u.object)
-        MarkObject(trc, *script->u.object, "object");
+    if (!script->isCachedEval && script->u.globalObject)
+        MarkObject(trc, *script->u.globalObject, "object");
 
     if (IS_GC_MARKING_TRACER(trc) && script->filename)
         js_MarkScriptFilename(script->filename);
 
     script->bindings.trace(trc);
 
     if (script->types)
         script->types->trace(trc);
-
-#ifdef JS_METHODJIT
-    if (script->jitNormal)
-        script->jitNormal->trace(trc);
-    if (script->jitCtor)
-        script->jitCtor->trace(trc);
-#endif
 }
 
 void
 MarkChildren(JSTracer *trc, const Shape *shape)
 {
 restart:
     MarkId(trc, shape->propid, "propid");
 
@@ -991,29 +984,29 @@ GCMarker::drainMarkStack()
 
 } /* namespace js */
 
 JS_PUBLIC_API(void)
 JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind)
 {
     switch (kind) {
       case JSTRACE_OBJECT:
-	MarkChildren(trc, static_cast<JSObject *>(thing));
+        MarkChildren(trc, static_cast<JSObject *>(thing));
         break;
 
       case JSTRACE_STRING:
-	MarkChildren(trc, static_cast<JSString *>(thing));
+        MarkChildren(trc, static_cast<JSString *>(thing));
         break;
 
       case JSTRACE_SCRIPT:
-	MarkChildren(trc, static_cast<JSScript *>(thing));
+        MarkChildren(trc, static_cast<JSScript *>(thing));
         break;
 
       case JSTRACE_SHAPE:
-	MarkChildren(trc, static_cast<Shape *>(thing));
+        MarkChildren(trc, static_cast<Shape *>(thing));
         break;
 
       case JSTRACE_TYPE_OBJECT:
         MarkChildren(trc, (types::TypeObject *)thing);
         break;
 
 #if JS_HAS_XML_SUPPORT
       case JSTRACE_XML:
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1453,16 +1453,18 @@ GetValueTypeFromTypeFlags(TypeFlags flag
       case TYPE_FLAG_INT32:
         return JSVAL_TYPE_INT32;
       case (TYPE_FLAG_INT32 | TYPE_FLAG_DOUBLE):
         return JSVAL_TYPE_DOUBLE;
       case TYPE_FLAG_STRING:
         return JSVAL_TYPE_STRING;
       case TYPE_FLAG_LAZYARGS:
         return JSVAL_TYPE_MAGIC;
+      case TYPE_FLAG_ANYOBJECT:
+        return JSVAL_TYPE_OBJECT;
       default:
         return JSVAL_TYPE_UNKNOWN;
     }
 }
 
 JSValueType
 TypeSet::getKnownTypeTag(JSContext *cx)
 {
@@ -6079,31 +6081,16 @@ TypeScript::Sweep(JSContext *cx, JSScrip
     /*
      * If the script has nesting state with a most recent activation, we do not
      * need either to mark the call object or clear it if not live. Even with
      * a dead pointer in the nesting, we can't get a spurious match while
      * testing for reentrancy: if previous activations are still live, they
      * cannot alias the most recent one, and future activations will overwrite
      * activeCall on creation.
      */
-
-    /*
-     * Method JIT code depends on the type inference data which is about to
-     * be purged, so purge the jitcode as well.
-     */
-#ifdef JS_METHODJIT
-    mjit::ReleaseScriptCode(cx, script);
-
-    /*
-     * Use counts for scripts are reset on GC. After discarding code we need to
-     * let it warm back up to get information like which opcodes are setting
-     * array holes or accessing getter properties.
-     */
-    script->resetUseCount();
-#endif
 }
 
 void
 TypeScript::destroy()
 {
     while (dynamicList) {
         TypeResult *next = dynamicList->next;
         Foreground::delete_(dynamicList);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1797,40 +1797,22 @@ js::Interpret(JSContext *cx, StackFrame 
      * if it returns false.
      */
 #define CHECK_BRANCH()                                                        \
     JS_BEGIN_MACRO                                                            \
         if (JS_THREAD_DATA(cx)->interruptFlags && !js_HandleExecutionInterrupt(cx)) \
             goto error;                                                       \
     JS_END_MACRO
 
-#if defined(JS_TRACER) && defined(JS_METHODJIT)
-# define LEAVE_ON_SAFE_POINT()                                                \
-    do {                                                                      \
-        JS_ASSERT_IF(leaveOnSafePoint, !TRACE_RECORDER(cx));                  \
-        JS_ASSERT_IF(leaveOnSafePoint, !TRACE_PROFILER(cx));                  \
-        JS_ASSERT_IF(leaveOnSafePoint, interpMode != JSINTERP_NORMAL);        \
-        if (leaveOnSafePoint && !regs.fp()->hasImacropc() &&                  \
-            script->maybeNativeCodeForPC(regs.fp()->isConstructing(), regs.pc)) { \
-            JS_ASSERT(!TRACE_RECORDER(cx));                                   \
-            interpReturnOK = true;                                            \
-            goto leave_on_safe_point;                                         \
-        }                                                                     \
-    } while (0)
-#else
-# define LEAVE_ON_SAFE_POINT() /* nop */
-#endif
-
 #define BRANCH(n)                                                             \
     JS_BEGIN_MACRO                                                            \
         regs.pc += (n);                                                       \
         op = (JSOp) *regs.pc;                                                 \
         if ((n) <= 0)                                                         \
             goto check_backedge;                                              \
-        LEAVE_ON_SAFE_POINT();                                                \
         DO_OP();                                                              \
     JS_END_MACRO
 
 #define SET_SCRIPT(s)                                                         \
     JS_BEGIN_MACRO                                                            \
         script = (s);                                                         \
         if (script->stepModeEnabled())                                        \
             ENABLE_INTERRUPTS();                                              \
@@ -1856,23 +1838,16 @@ js::Interpret(JSContext *cx, StackFrame 
     JSRuntime *const rt = cx->runtime;
     JSScript *script;
     SET_SCRIPT(regs.fp()->script());
     double *pcCounts = script->pcCounters.get(JSPCCounters::INTERP);
     ENABLE_PCCOUNT_INTERRUPTS();
     Value *argv = regs.fp()->maybeFormalArgs();
     CHECK_INTERRUPT_HANDLER();
 
-#if defined(JS_TRACER) && defined(JS_METHODJIT)
-    bool leaveOnSafePoint = (interpMode == JSINTERP_SAFEPOINT);
-# define CLEAR_LEAVE_ON_TRACE_POINT() ((void) (leaveOnSafePoint = false))
-#else
-# define CLEAR_LEAVE_ON_TRACE_POINT() ((void) 0)
-#endif
-
     if (!entryFrame)
         entryFrame = regs.fp();
 
     /*
      * Initialize the index segment register used by LOAD_ATOM and
      * GET_FULL_INDEX macros below. As a register we use a pointer based on
      * the atom map to turn frequently executed LOAD_ATOM into simple array
      * access. For less frequent object and regexp loads we have to recover
@@ -2045,60 +2020,33 @@ js::Interpret(JSContext *cx, StackFrame 
         }
 
 #ifdef JS_TRACER
 #ifdef JS_METHODJIT
         if (TRACE_PROFILER(cx) && interpMode == JSINTERP_PROFILE) {
             LoopProfile *prof = TRACE_PROFILER(cx);
             JS_ASSERT(!TRACE_RECORDER(cx));
             LoopProfile::ProfileAction act = prof->profileOperation(cx, op);
-            switch (act) {
-                case LoopProfile::ProfComplete:
-                    if (interpMode != JSINTERP_NORMAL) {
-                        leaveOnSafePoint = true;
-                        LEAVE_ON_SAFE_POINT();
-                    }
-                    break;
-                default:
-                    moreInterrupts = true;
-                    break;
-            }
+            if (act != LoopProfile::ProfComplete)
+                moreInterrupts = true;
         }
 #endif
         if (TraceRecorder* tr = TRACE_RECORDER(cx)) {
             JS_ASSERT(!TRACE_PROFILER(cx));
             AbortableRecordingStatus status = tr->monitorRecording(op);
             JS_ASSERT_IF(cx->isExceptionPending(), status == ARECORD_ERROR);
 
-            if (interpMode != JSINTERP_NORMAL) {
-                JS_ASSERT(interpMode == JSINTERP_RECORD || JSINTERP_SAFEPOINT);
-                switch (status) {
-                  case ARECORD_IMACRO_ABORTED:
-                  case ARECORD_ABORTED:
-                  case ARECORD_COMPLETED:
-                  case ARECORD_STOP:
-#ifdef JS_METHODJIT
-                    leaveOnSafePoint = true;
-                    LEAVE_ON_SAFE_POINT();
-#endif
-                    break;
-                  default:
-                    break;
-                }
-            }
-
             switch (status) {
               case ARECORD_CONTINUE:
                 moreInterrupts = true;
                 break;
               case ARECORD_IMACRO:
               case ARECORD_IMACRO_ABORTED:
                 atoms = rt->atomState.commonAtomsStart();
                 op = JSOp(*regs.pc);
-                CLEAR_LEAVE_ON_TRACE_POINT();
                 if (status == ARECORD_IMACRO)
                     DO_OP();    /* keep interrupting for op. */
                 break;
               case ARECORD_ERROR:
                 // The code at 'error:' aborts the recording.
                 goto error;
               case ARECORD_ABORTED:
               case ARECORD_COMPLETED:
@@ -2133,34 +2081,33 @@ ADD_EMPTY_CASE(JSOP_TRY)
 ADD_EMPTY_CASE(JSOP_STARTXML)
 ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
 #endif
 ADD_EMPTY_CASE(JSOP_NULLBLOCKCHAIN)
 END_EMPTY_CASES
 
 BEGIN_CASE(JSOP_TRACE)
 BEGIN_CASE(JSOP_NOTRACE)
-    LEAVE_ON_SAFE_POINT();
+    /* No-op */
 END_CASE(JSOP_TRACE)
 
 check_backedge:
 {
     CHECK_BRANCH();
     if (op != JSOP_NOTRACE && op != JSOP_TRACE)
         DO_OP();
 
 #ifdef JS_TRACER
     if (TRACING_ENABLED(cx) && (TRACE_RECORDER(cx) || TRACE_PROFILER(cx) || (op == JSOP_TRACE && !useMethodJIT))) {
         MonitorResult r = MonitorLoopEdge(cx, interpMode);
         if (r == MONITOR_RECORDING) {
             JS_ASSERT(TRACE_RECORDER(cx));
             JS_ASSERT(!TRACE_PROFILER(cx));
             MONITOR_BRANCH_TRACEVIS;
             ENABLE_INTERRUPTS();
-            CLEAR_LEAVE_ON_TRACE_POINT();
         }
         JS_ASSERT_IF(cx->isExceptionPending(), r == MONITOR_ERROR);
         RESTORE_INTERP_VARS_CHECK_EXCEPTION();
         op = (JSOp) *regs.pc;
         DO_OP();
     }
 #endif /* JS_TRACER */
 
@@ -2275,17 +2222,16 @@ BEGIN_CASE(JSOP_STOP)
          */
         JS_ASSERT(op == JSOP_STOP);
         JS_ASSERT((uintN)(regs.sp - regs.fp()->slots()) <= script->nslots);
         jsbytecode *imacpc = regs.fp()->imacropc();
         regs.pc = imacpc + js_CodeSpec[*imacpc].length;
         if (js_CodeSpec[*imacpc].format & JOF_DECOMPOSE)
             regs.pc += GetDecomposeLength(imacpc, js_CodeSpec[*imacpc].length);
         regs.fp()->clearImacropc();
-        LEAVE_ON_SAFE_POINT();
         atoms = script->atoms;
         op = JSOp(*regs.pc);
         DO_OP();
     }
 #endif
 
     interpReturnOK = true;
     if (entryFrame != regs.fp())
@@ -5344,22 +5290,16 @@ BEGIN_CASE(JSOP_RETSUB)
     len = rval.toInt32();
     regs.pc = script->code;
 END_VARLEN_CASE
 }
 
 BEGIN_CASE(JSOP_EXCEPTION)
     PUSH_COPY(cx->getPendingException());
     cx->clearPendingException();
-#if defined(JS_TRACER) && defined(JS_METHODJIT)
-    if (interpMode == JSINTERP_PROFILE) {
-        leaveOnSafePoint = true;
-        LEAVE_ON_SAFE_POINT();
-    }
-#endif
     CHECK_BRANCH();
 END_CASE(JSOP_EXCEPTION)
 
 BEGIN_CASE(JSOP_FINALLY)
     CHECK_BRANCH();
 END_CASE(JSOP_FINALLY)
 
 BEGIN_CASE(JSOP_THROWING)
@@ -5464,131 +5404,157 @@ BEGIN_CASE(JSOP_DEBUGGER)
     }
     CHECK_INTERRUPT_HANDLER();
 }
 END_CASE(JSOP_DEBUGGER)
 
 #if JS_HAS_XML_SUPPORT
 BEGIN_CASE(JSOP_DEFXMLNS)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     if (!js_SetDefaultXMLNamespace(cx, regs.sp[-1]))
         goto error;
     regs.sp--;
 }
 END_CASE(JSOP_DEFXMLNS)
 
 BEGIN_CASE(JSOP_ANYNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     jsid id;
     if (!js_GetAnyName(cx, &id))
         goto error;
     PUSH_COPY(IdToValue(id));
 }
 END_CASE(JSOP_ANYNAME)
 
 BEGIN_CASE(JSOP_QNAMEPART)
 {
+    /*
+     * We do not JS_ASSERT(!script->strictModeCode) here because JSOP_QNAMEPART
+     * is used for __proto__ and (in contexts where we favor JSOP_*ELEM instead
+     * of JSOP_*PROP) obj.prop compiled as obj['prop'].
+     */
+
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     PUSH_STRING(atom);
 }
 END_CASE(JSOP_QNAMEPART)
 
 BEGIN_CASE(JSOP_QNAMECONST)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     Value rval = StringValue(atom);
     Value lval = regs.sp[-1];
     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
     if (!obj)
         goto error;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_QNAMECONST)
 
 BEGIN_CASE(JSOP_QNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     Value lval = regs.sp[-2];
     JSObject *obj = js_ConstructXMLQNameObject(cx, lval, rval);
     if (!obj)
         goto error;
     regs.sp--;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_QNAME)
 
 BEGIN_CASE(JSOP_TOATTRNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval;
     rval = regs.sp[-1];
     if (!js_ToAttributeName(cx, &rval))
         goto error;
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_TOATTRNAME)
 
 BEGIN_CASE(JSOP_TOATTRVAL)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval;
     rval = regs.sp[-1];
     JS_ASSERT(rval.isString());
     JSString *str = js_EscapeAttributeValue(cx, rval.toString(), JS_FALSE);
     if (!str)
         goto error;
     regs.sp[-1].setString(str);
 }
 END_CASE(JSOP_TOATTRVAL)
 
 BEGIN_CASE(JSOP_ADDATTRNAME)
 BEGIN_CASE(JSOP_ADDATTRVAL)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     Value lval = regs.sp[-2];
     JSString *str = lval.toString();
     JSString *str2 = rval.toString();
     str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
     if (!str)
         goto error;
     regs.sp--;
     regs.sp[-1].setString(str);
 }
 END_CASE(JSOP_ADDATTRNAME)
 
 BEGIN_CASE(JSOP_BINDXMLNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value lval;
     lval = regs.sp[-1];
     JSObject *obj;
     jsid id;
     if (!js_FindXMLProperty(cx, lval, &obj, &id))
         goto error;
     regs.sp[-1].setObjectOrNull(obj);
     PUSH_COPY(IdToValue(id));
 }
 END_CASE(JSOP_BINDXMLNAME)
 
 BEGIN_CASE(JSOP_SETXMLNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSObject *obj = &regs.sp[-3].toObject();
     Value rval = regs.sp[-1];
     jsid id;
     FETCH_ELEMENT_ID(obj, -2, id);
     if (!obj->setGeneric(cx, id, &rval, script->strictModeCode))
         goto error;
     rval = regs.sp[-1];
     regs.sp -= 2;
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_SETXMLNAME)
 
 BEGIN_CASE(JSOP_CALLXMLNAME)
 BEGIN_CASE(JSOP_XMLNAME)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value lval = regs.sp[-1];
     JSObject *obj;
     jsid id;
     if (!js_FindXMLProperty(cx, lval, &obj, &id))
         goto error;
     Value rval;
     if (!obj->getGeneric(cx, id, &rval))
         goto error;
@@ -5596,16 +5562,18 @@ BEGIN_CASE(JSOP_XMLNAME)
     if (op == JSOP_CALLXMLNAME)
         PUSH_IMPLICIT_THIS(cx, obj, rval);
 }
 END_CASE(JSOP_XMLNAME)
 
 BEGIN_CASE(JSOP_DESCENDANTS)
 BEGIN_CASE(JSOP_DELDESC)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSObject *obj;
     FETCH_OBJECT(cx, -2, obj);
     jsval rval = regs.sp[-1];
     if (!js_GetXMLDescendants(cx, obj, rval, &rval))
         goto error;
 
     if (op == JSOP_DELDESC) {
         regs.sp[-1] = rval;   /* set local root */
@@ -5614,31 +5582,35 @@ BEGIN_CASE(JSOP_DELDESC)
         rval = JSVAL_TRUE;                  /* always succeed */
     }
 
     regs.sp--;
     regs.sp[-1] = rval;
 }
 END_CASE(JSOP_DESCENDANTS)
 
-{
 BEGIN_CASE(JSOP_FILTER)
+{
+    JS_ASSERT(!script->strictModeCode);
+
     /*
      * We push the hole value before jumping to [enditer] so we can detect the
      * first iteration and direct js_StepXMLListFilter to initialize filter's
      * state.
      */
     PUSH_HOLE();
     len = GET_JUMP_OFFSET(regs.pc);
     JS_ASSERT(len > 0);
+}
 END_VARLEN_CASE
-}
 
 BEGIN_CASE(JSOP_ENDFILTER)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     bool cond = !regs.sp[-1].isMagic();
     if (cond) {
         /* Exit the "with" block left from the previous iteration. */
         LeaveWith(cx);
     }
     if (!js_StepXMLListFilter(cx, cond))
         goto error;
     if (!regs.sp[-1].isNull()) {
@@ -5655,46 +5627,54 @@ BEGIN_CASE(JSOP_ENDFILTER)
         BRANCH(len);
     }
     regs.sp--;
 }
 END_CASE(JSOP_ENDFILTER);
 
 BEGIN_CASE(JSOP_TOXML)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     JSObject *obj = js_ValueToXMLObject(cx, rval);
     if (!obj)
         goto error;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_TOXML)
 
 BEGIN_CASE(JSOP_TOXMLLIST)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     JSObject *obj = js_ValueToXMLListObject(cx, rval);
     if (!obj)
         goto error;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_TOXMLLIST)
 
 BEGIN_CASE(JSOP_XMLTAGEXPR)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     JSString *str = js_ValueToString(cx, rval);
     if (!str)
         goto error;
     regs.sp[-1].setString(str);
 }
 END_CASE(JSOP_XMLTAGEXPR)
 
 BEGIN_CASE(JSOP_XMLELTEXPR)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval = regs.sp[-1];
     JSString *str;
     if (IsXML(rval)) {
         str = js_ValueToXMLString(cx, rval);
     } else {
         str = js_ValueToString(cx, rval);
         if (str)
             str = js_EscapeElementValue(cx, str);
@@ -5702,54 +5682,62 @@ BEGIN_CASE(JSOP_XMLELTEXPR)
     if (!str)
         goto error;
     regs.sp[-1].setString(str);
 }
 END_CASE(JSOP_XMLELTEXPR)
 
 BEGIN_CASE(JSOP_XMLCDATA)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     JSString *str = atom;
     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_XMLCDATA)
 
 BEGIN_CASE(JSOP_XMLCOMMENT)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     JSString *str = atom;
     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_XMLCOMMENT)
 
 BEGIN_CASE(JSOP_XMLPI)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     JSString *str = atom;
     Value rval = regs.sp[-1];
     JSString *str2 = rval.toString();
     JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, str, str2);
     if (!obj)
         goto error;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_XMLPI)
 
 BEGIN_CASE(JSOP_GETFUNNS)
 {
+    JS_ASSERT(!script->strictModeCode);
+
     Value rval;
     if (!cx->fp()->scopeChain().getGlobal()->getFunctionNamespace(cx, &rval))
         goto error;
     PUSH_COPY(rval);
 }
 END_CASE(JSOP_GETFUNNS)
 #endif /* JS_HAS_XML_SUPPORT */
 
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -210,20 +210,19 @@ ExecuteKernel(JSContext *cx, JSScript *s
 extern bool
 Execute(JSContext *cx, JSScript *script, JSObject &scopeChain, Value *rval);
 
 /* Flags to toggle js::Interpret() execution. */
 enum InterpMode
 {
     JSINTERP_NORMAL    = 0, /* interpreter is running normally */
     JSINTERP_RECORD    = 1, /* interpreter has been started to record/run traces */
-    JSINTERP_SAFEPOINT = 2, /* interpreter should leave on a method JIT safe point */
-    JSINTERP_PROFILE   = 3, /* interpreter should profile a loop */
-    JSINTERP_REJOIN    = 4, /* as normal, but the frame has already started */
-    JSINTERP_SKIP_TRAP = 5  /* as REJOIN, but skip trap at first opcode */
+    JSINTERP_PROFILE   = 2, /* interpreter should profile a loop */
+    JSINTERP_REJOIN    = 3, /* as normal, but the frame has already started */
+    JSINTERP_SKIP_TRAP = 4  /* as REJOIN, but skip trap at first opcode */
 };
 
 /*
  * Execute the caller-initialized frame for a user-defined script or function
  * pointed to by cx->fp until completion or error.
  */
 extern JS_REQUIRES_STACK JS_NEVER_INLINE bool
 Interpret(JSContext *cx, StackFrame *stopFp, InterpMode mode = JSINTERP_NORMAL);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1121,17 +1121,16 @@ class EvalScriptGuard
             script_->isCachedEval = false;
             script_->isActiveEval = true;
         }
     }
 
     void setNewScript(JSScript *script) {
         /* NewScriptFromCG has already called js_CallNewScriptHook. */
         JS_ASSERT(!script_ && script);
-        script->setOwnerObject(JS_CACHED_SCRIPT);
         script_ = script;
         script_->isActiveEval = true;
     }
 
     bool foundScript() {
         return !!script_;
     }
 
@@ -6746,34 +6745,30 @@ JSBool
 js_GetClassPrototype(JSContext *cx, JSObject *scopeobj, JSProtoKey protoKey,
                      JSObject **protop, Class *clasp)
 {
     VOUCH_DOES_NOT_REQUIRE_STACK();
     JS_ASSERT(JSProto_Null <= protoKey);
     JS_ASSERT(protoKey < JSProto_LIMIT);
 
     if (protoKey != JSProto_Null) {
-        if (!scopeobj) {
-            if (cx->hasfp())
-                scopeobj = &cx->fp()->scopeChain();
-            if (!scopeobj) {
-                scopeobj = cx->globalObject;
-                if (!scopeobj) {
-                    *protop = NULL;
-                    return true;
-                }
+        GlobalObject *global;
+        if (scopeobj) {
+            global = scopeobj->getGlobal();
+        } else {
+            global = GetCurrentGlobal(cx);
+            if (!global) {
+                *protop = NULL;
+                return true;
             }
         }
-        scopeobj = scopeobj->getGlobal();
-        if (scopeobj->isGlobal()) {
-            const Value &v = scopeobj->getReservedSlot(JSProto_LIMIT + protoKey);
-            if (v.isObject()) {
-                *protop = &v.toObject();
-                return true;
-            }
+        const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
+        if (v.isObject()) {
+            *protop = &v.toObject();
+            return true;
         }
     }
 
     return FindClassPrototype(cx, scopeobj, protoKey, protop, clasp);
 }
 
 JSObject *
 PrimitiveToObject(JSContext *cx, const Value &v)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1180,22 +1180,16 @@ struct JSObject : js::gc::Cell {
     /*
      * Iterator-specific getters and setters.
      */
 
     inline js::NativeIterator *getNativeIterator() const;
     inline void setNativeIterator(js::NativeIterator *);
 
     /*
-     * Script-related getters.
-     */
-
-    inline JSScript *getScript() const;
-
-    /*
      * XML-related getters and setters.
      */
 
     /*
      * Slots for XML-related classes are as follows:
      * - NamespaceClass.base reserves the *_NAME_* and *_NAMESPACE_* slots.
      * - QNameClass.base, AttributeNameClass, AnyNameClass reserve
      *   the *_NAME_* and *_QNAME_* slots.
@@ -1460,17 +1454,16 @@ struct JSObject : js::gc::Cell {
     inline bool isObject() const { return clasp == &js::ObjectClass; }
     inline bool isWith() const { return clasp == &js::WithClass; }
     inline bool isBlock() const { return clasp == &js::BlockClass; }
     inline bool isStaticBlock() const { return isBlock() && !getProto(); }
     inline bool isClonedBlock() const { return isBlock() && !!getProto(); }
     inline bool isCall() const { return clasp == &js::CallClass; }
     inline bool isDeclEnv() const { return clasp == &js::DeclEnvClass; }
     inline bool isRegExp() const { return clasp == &js::RegExpClass; }
-    inline bool isScript() const { return clasp == &js::ScriptClass; }
     inline bool isGenerator() const { return clasp == &js::GeneratorClass; }
     inline bool isIterator() const { return clasp == &js::IteratorClass; }
     inline bool isStopIteration() const { return clasp == &js::StopIterationClass; }
     inline bool isError() const { return clasp == &js::ErrorClass; }
     inline bool isXML() const { return clasp == &js::XMLClass; }
     inline bool isNamespace() const { return clasp == &js::NamespaceClass; }
     inline bool isWeakMap() const { return clasp == &js::WeakMapClass; }
     inline bool isProxy() const;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1467,16 +1467,23 @@ NewNativeClassInstance(JSContext *cx, Cl
 
 static inline JSObject *
 NewNativeClassInstance(JSContext *cx, Class *clasp, JSObject *proto, JSObject *parent)
 {
     gc::AllocKind kind = gc::GetGCObjectKind(JSCLASS_RESERVED_SLOTS(clasp));
     return NewNativeClassInstance(cx, clasp, proto, parent, kind);
 }
 
+inline GlobalObject *
+GetCurrentGlobal(JSContext *cx)
+{
+    JSObject *scopeChain = (cx->hasfp()) ? &cx->fp()->scopeChain() : cx->globalObject;
+    return scopeChain ? scopeChain->getGlobal() : NULL;
+}
+
 bool
 FindClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, JSObject **protop,
                    Class *clasp);
 
 /*
  * Helper used to create Boolean, Date, RegExp, etc. instances of built-in
  * classes with class prototypes of the same Class. See, e.g., jsdate.cpp,
  * jsregexp.cpp, and js_PrimitiveToObject in jsobj.cpp. Use this to get the
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -124,20 +124,23 @@ struct Class;
 
 class RegExpObject;
 class RegExpPrivate;
 class RegExpStatics;
 class MatchPairs;
 
 enum RegExpFlag
 {
-    IgnoreCaseFlag  = JS_BIT(0),
-    GlobalFlag      = JS_BIT(1),
-    MultilineFlag   = JS_BIT(2),
-    StickyFlag      = JS_BIT(3)
+    IgnoreCaseFlag  = 0x01,
+    GlobalFlag      = 0x02,
+    MultilineFlag   = 0x04,
+    StickyFlag      = 0x08,
+
+    NoFlags         = 0x00,
+    AllFlags        = 0x0f
 };
 
 enum RegExpExecType
 {
     RegExpExec,
     RegExpTest
 };
 
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2349,17 +2349,17 @@ ASTSerializer::comprehension(ParseNode *
 
     Value filter = MagicValue(JS_SERIALIZE_NO_NODE);
 
     if (next->isKind(TOK_IF)) {
         if (!optExpression(next->pn_kid1, &filter))
             return false;
         next = next->pn_kid2;
     } else if (next->isKind(TOK_LC) && next->pn_count == 0) {
-        /* js_FoldConstants optimized away the push. */
+        /* FoldConstants optimized away the push. */
         NodeVector empty(cx);
         return builder.arrayExpression(empty, &pn->pn_pos, dst);
     }
 
     LOCAL_ASSERT(next->isKind(TOK_ARRAYPUSH));
 
     Value body;
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -301,24 +301,16 @@ CheckScript(JSScript *script, JSScript *
 {
     if (script->cookie1[0] != JS_SCRIPT_COOKIE || script->cookie2[0] != JS_SCRIPT_COOKIE) {
         crash::StackBuffer<sizeof(JSScript), 0x87> buf1(script);
         crash::StackBuffer<sizeof(JSScript), 0x88> buf2(prev);
         JS_OPT_ASSERT(false);
     }
 }
 
-void
-CheckScriptOwner(JSScript *script, JSObject *owner)
-{
-    JS_OPT_ASSERT(script->ownerObject == owner);
-    if (owner != JS_NEW_SCRIPT && owner != JS_CACHED_SCRIPT)
-        JS_OPT_ASSERT(script->compartment() == owner->compartment());
-}
-
 #endif /* JS_CRASH_DIAGNOSTICS */
 
 } /* namespace js */
 
 #if JS_HAS_XDR
 
 enum ScriptBits {
     NoScriptRval,
@@ -751,47 +743,16 @@ void
 JSPCCounters::destroy(JSContext *cx)
 {
     if (counts) {
         cx->free_(counts);
         counts = NULL;
     }
 }
 
-static void
-script_trace(JSTracer *trc, JSObject *obj)
-{
-    JSScript *script = (JSScript *) obj->getPrivate();
-    if (script) {
-        CheckScriptOwner(script, obj);
-        MarkScript(trc, script, "script");
-    }
-}
-
-JS_FRIEND_DATA(Class) js::ScriptClass = {
-    "Script",
-    JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
-    JS_PropertyStub,         /* addProperty */
-    JS_PropertyStub,         /* delProperty */
-    JS_PropertyStub,         /* getProperty */
-    JS_StrictPropertyStub,   /* setProperty */
-    JS_EnumerateStub,
-    JS_ResolveStub,
-    JS_ConvertStub,
-    NULL,                    /* finalize */
-    NULL,                    /* reserved0   */
-    NULL,                    /* checkAccess */
-    NULL,                    /* call        */
-    NULL,                    /* construct   */
-    NULL,                    /* xdrObject   */
-    NULL,                    /* hasInstance */
-    script_trace
-};
-
 /*
  * Shared script filename management.
  */
 
 static const char *
 SaveScriptFilename(JSContext *cx, const char *filename)
 {
     JSCompartment *comp = cx->compartment;
@@ -960,17 +921,16 @@ JSScript::NewScript(JSContext *cx, uint3
     if (!script) {
         Foreground::free_(data);
         return NULL;
     }
 
     PodZero(script);
 #ifdef JS_CRASH_DIAGNOSTICS
     script->cookie1[0] = script->cookie2[0] = JS_SCRIPT_COOKIE;
-    script->ownerObject = JS_NEW_SCRIPT;
 #endif
 #if JS_SCRIPT_INLINE_DATA_LIMIT
     if (!data)
         data = script->inlineData;
 #endif
     script->data  = data;
     script->length = length;
     script->version = version;
@@ -1236,33 +1196,36 @@ JSScript::NewScriptFromCG(JSContext *cx,
         bool singleton =
             cx->typeInferenceEnabled() && cg->parent && cg->parent->compiling() &&
             cg->parent->asCodeGenerator()->checkSingletonContext();
 
         if (!script->typeSetFunction(cx, fun, singleton))
             return NULL;
 
         fun->setScript(script);
+        script->u.globalObject = fun->getParent() ? fun->getParent()->getGlobal() : NULL;
     } else {
         /*
          * Initialize script->object, if necessary, so that the debugger has a
          * valid holder object.
          */
-        if ((cg->flags & TCF_NEED_SCRIPT_OBJECT) && !js_NewScriptObject(cx, script))
-            return NULL;
+        if (cg->flags & TCF_NEED_SCRIPT_GLOBAL)
+            script->u.globalObject = GetCurrentGlobal(cx);
     }
 
     /* Tell the debugger about this compiled script. */
     js_CallNewScriptHook(cx, script, fun);
     if (!cg->parent) {
-        JSObject *owner = fun ? fun : script->u.object;
         GlobalObject *compileAndGoGlobal = NULL;
-        if (script->compileAndGo)
-            compileAndGoGlobal = (owner ? owner : cg->scopeChain())->getGlobal();
-        Debugger::onNewScript(cx, script, owner, compileAndGoGlobal);
+        if (script->compileAndGo) {
+            compileAndGoGlobal = script->u.globalObject;
+            if (!compileAndGoGlobal)
+                compileAndGoGlobal = cg->scopeChain()->getGlobal();
+        }
+        Debugger::onNewScript(cx, script, compileAndGoGlobal);
     }
 
     return script;
 }
 
 size_t
 JSScript::dataSize()
 {
@@ -1283,25 +1246,16 @@ JSScript::dataSize(JSUsableSizeFun usf)
     if (data == inlineData)
         return 0;
 #endif
 
     size_t usable = usf(data);
     return usable ? usable : dataSize();
 }
 
-void
-JSScript::setOwnerObject(JSObject *owner)
-{
-#ifdef JS_CRASH_DIAGNOSTICS
-    CheckScriptOwner(this, JS_NEW_SCRIPT);
-    ownerObject = owner;
-#endif
-}
-
 /*
  * Nb: srcnotes are variable-length.  This function computes the number of
  * srcnote *slots*, which may be greater than the number of srcnotes.
  */
 uint32
 JSScript::numNotes()
 {
     jssrcnote *sn;
@@ -1366,37 +1320,16 @@ JSScript::finalize(JSContext *cx)
     if (data != inlineData)
 #endif
     {
         JS_POISON(data, 0xdb, dataSize());
         cx->free_(data);
     }
 }
 
-JSObject *
-js_NewScriptObject(JSContext *cx, JSScript *script)
-{
-    JS_ASSERT(!script->u.object);
-
-    JSObject *obj = NewNonFunction<WithProto::Class>(cx, &ScriptClass, NULL, NULL);
-    if (!obj)
-        return NULL;
-    obj->setPrivate(script);
-    script->u.object = obj;
-    script->setOwnerObject(obj);
-
-    /*
-     * Clear the object's type/proto, to avoid entraining stuff. Once we no longer use the parent
-     * for security checks, then we can clear the parent, too.
-     */
-    obj->clearType();
-
-    return obj;
-}
-
 namespace js {
 
 static const uint32 GSN_CACHE_THRESHOLD = 100;
 static const uint32 GSN_CACHE_MAP_INIT_SIZE = 20;
 
 void
 GSNCache::purge()
 {
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -421,19 +421,16 @@ class JSPCCounters {
         JS_ASSERT(offset < numBytecodes);
         JS_ASSERT(counts);
         return get(runmode)[offset];
     }
 };
 
 static const uint32 JS_SCRIPT_COOKIE = 0xc00cee;
 
-static JSObject * const JS_NEW_SCRIPT = (JSObject *)0x12345678;
-static JSObject * const JS_CACHED_SCRIPT = (JSObject *)0x12341234;
-
 struct JSScript : public js::gc::Cell {
     /*
      * Two successively less primitive ways to make a new JSScript.  The first
      * does *not* call a non-null cx->runtime->newScriptHook -- only the second,
      * NewScriptFromCG, calls this optional debugger hook.
      *
      * The NewScript function can't know whether the script it creates belongs
      * to a function, or is top-level or eval code, but the debugger wants access
@@ -556,45 +553,42 @@ struct JSScript : public js::gc::Cell {
   public:
     js::Bindings    bindings;   /* names of top-level variables in this script
                                    (and arguments if this is a function script) */
     JSPrincipals    *principals;/* principals for this script */
     jschar          *sourceMap; /* source map file or null */
 
     union {
         /*
-         * A script object of class ScriptClass, to ensure the script is GC'd.
+         * A global object for the script.
          * - All scripts returned by JSAPI functions (JS_CompileScript,
-         *   JS_CompileFile, etc.) have these objects.
-         * - Function scripts never have script objects; such scripts are owned
-         *   by their function objects.
+         *   JS_CompileFile, etc.) have a non-null globalObject.
+         * - A function script has a globalObject if the function comes from a
+         *   compile-and-go script.
          * - Temporary scripts created by obj_eval, JS_EvaluateScript, and
-         *   similar functions never have these objects; such scripts are
-         *   explicitly destroyed by the code that created them.
+         *   similar functions never have the globalObject field set; for such
+         *   scripts the global should be extracted from the JS frame that
+         *   execute scripts.
          */
-        JSObject    *object;
+        js::GlobalObject    *globalObject;
 
         /* Hash table chaining for JSCompartment::evalCache. */
-        JSScript    *evalHashLink;
+        JSScript            *evalHashLink;
     } u;
 
     uint32          *closedSlots; /* vector of closed slots; args first, then vars. */
 
     /* array of execution counters for every JSOp in the script, by runmode */
     JSPCCounters    pcCounters;
 
 #ifdef JS_CRASH_DIAGNOSTICS
-    JSObject        *ownerObject;
-
     /* All diagnostic fields must be multiples of Cell::CellSize. */
-    uint32          cookie2[sizeof(JSObject *) == 4 ? 1 : 2];
+    uint32          cookie2[Cell::CellSize / sizeof(uint32)];
 #endif
 
-    void setOwnerObject(JSObject *owner);
-
 #ifdef DEBUG
     /*
      * Unique identifier within the compartment for this script, used for
      * printing analysis information.
      */
     uint32 id_;
     uint32 idpad;
     unsigned id();
@@ -633,16 +627,21 @@ struct JSScript : public js::gc::Cell {
     inline bool hasClearedGlobal() const;
 
     inline JSFunction *function() const;
     inline js::GlobalObject *global() const;
     inline js::types::TypeScriptNesting *nesting() const;
 
     inline void clearNesting();
 
+    /* Return creation time global or null. */
+    js::GlobalObject *getGlobalObjectOrNull() const {
+        return isCachedEval ? NULL : u.globalObject;
+    }
+
   private:
     bool makeTypes(JSContext *cx, JSFunction *fun);
     bool makeAnalysis(JSContext *cx);
   public:
 
 #ifdef JS_METHODJIT
     // Fast-cached pointers to make calls faster. These are also used to
     // quickly test whether there is JIT code; a NULL value means no
@@ -680,17 +679,17 @@ struct JSScript : public js::gc::Cell {
             return JITScript_None;
         if (addr == JS_UNJITTABLE_SCRIPT)
             return JITScript_Invalid;
         return JITScript_Valid;
     }
 
     /* Size of the JITScript and all sections.  (This method is implemented in MethodJIT.h.) */
     JS_FRIEND_API(size_t) jitDataSize(JSUsableSizeFun usf);
-    
+
 #endif
 
     jsbytecode *main() {
         return code + mainOffset;
     }
 
     /*
      * The first dataSize() is the in-use size of all the data sections, the
@@ -798,17 +797,17 @@ struct JSScript : public js::gc::Cell {
   public:
     /*
      * Set or clear the single-step flag. If the flag is set or the count
      * (adjusted by changeStepModeCount) is non-zero, then the script is in
      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
      * count-style interface.)
      */
     bool setStepModeFlag(JSContext *cx, bool step);
-    
+
     /*
      * Increment or decrement the single-step count. If the count is non-zero or
      * the flag (set by setStepModeFlag) is set, then the script is in
      * single-step mode. (JSD uses an on/off-style interface; Debugger uses a
      * count-style interface.)
      */
     bool changeStepModeCount(JSContext *cx, int delta);
 
@@ -843,19 +842,16 @@ StackDepth(JSScript *script)
             JS_ASSERT((size_t)(index) < js_common_atom_count);                \
             (atom) = cx->runtime->atomState.commonAtomsStart()[index];        \
         } else {                                                              \
             (atom) = script_->getAtom(index);                                 \
         }                                                                     \
     JS_END_MACRO
 
 
-extern JSObject *
-js_InitScriptClass(JSContext *cx, JSObject *obj);
-
 extern void
 js_MarkScriptFilename(const char *filename);
 
 extern void
 js_SweepScriptFilenames(JSCompartment *comp);
 
 /*
  * New-script-hook calling is factored from js_NewScriptFromCG so that it
@@ -869,40 +865,29 @@ js_CallNewScriptHook(JSContext *cx, JSSc
 extern void
 js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
 
 namespace js {
 
 #ifdef JS_CRASH_DIAGNOSTICS
 
 void
-CheckScriptOwner(JSScript *script, JSObject *owner);
-
-void
 CheckScript(JSScript *script, JSScript *prev);
 
 #else
 
 inline void
-CheckScriptOwner(JSScript *script, JSObject *owner)
-{
-}
-
-inline void
 CheckScript(JSScript *script, JSScript *prev)
 {
 }
 
 #endif /* !JS_CRASH_DIAGNOSTICS */
 
 } /* namespace js */
 
-extern JSObject *
-js_NewScriptObject(JSContext *cx, JSScript *script);
-
 /*
  * To perturb as little code as possible, we introduce a js_GetSrcNote lookup
  * cache without adding an explicit cx parameter.  Thus js_GetSrcNote becomes
  * a macro that uses cx from its calls' lexical environments.
  */
 #define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
 
 extern jssrcnote *
--- a/js/src/jsscriptinlines.h
+++ b/js/src/jsscriptinlines.h
@@ -210,16 +210,9 @@ JSScript::clearNesting()
 {
     js::types::TypeScriptNesting *nesting = this->nesting();
     if (nesting) {
         js::Foreground::delete_(nesting);
         types->nesting = NULL;
     }
 }
 
-inline JSScript *
-JSObject::getScript() const
-{
-    JS_ASSERT(isScript());
-    return static_cast<JSScript *>(getPrivate());
-}
-
 #endif /* jsscriptinlines_h___ */
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1314,24 +1314,18 @@ Blacklist(jsbytecode* pc)
     JS_ASSERT(*pc == JSOP_TRACE || *pc == JSOP_NOTRACE);
     *pc = JSOP_NOTRACE;
 }
 
 static void
 Unblacklist(JSScript *script, jsbytecode *pc)
 {
     JS_ASSERT(*pc == JSOP_NOTRACE || *pc == JSOP_TRACE);
-    if (*pc == JSOP_NOTRACE) {
+    if (*pc == JSOP_NOTRACE)
         *pc = JSOP_TRACE;
-
-#ifdef JS_METHODJIT
-        /* This code takes care of unblacklisting in the method JIT. */
-        js::mjit::ResetTraceHint(script, pc, GET_UINT16(pc), false);
-#endif
-    }
 }
 
 #ifdef JS_METHODJIT
 static bool
 IsBlacklisted(jsbytecode* pc)
 {
     if (*pc == JSOP_NOTRACE)
         return true;
@@ -2683,27 +2677,16 @@ TraceMonitor::flush()
 
     verbose_only(
         for (Seq<Fragment*>* f = branches; f; f = f->tail)
             FragProfiling_FragFinalizer(f->head, this);
     )
 
     flushEpoch++;
 
-#ifdef JS_METHODJIT
-    if (loopProfiles) {
-        for (LoopProfileMap::Enum e(*loopProfiles); !e.empty(); e.popFront()) {
-            jsbytecode *pc = e.front().key;
-            LoopProfile *prof = e.front().value;
-            /* This code takes care of resetting all methodjit state. */
-            js::mjit::ResetTraceHint(prof->entryScript, pc, GET_UINT16(pc), true);
-        }
-    }
-#endif
-
     frameCache->reset();
     dataAlloc->reset();
     traceAlloc->reset();
     codeAlloc->reset();
     tempAlloc->reset();
     oracle->clear();
     loopProfiles->clear();
 
--- a/js/src/jstypes.h
+++ b/js/src/jstypes.h
@@ -285,21 +285,17 @@
 ** DESCRIPTION:
 **      Commonly used macros for operations on compatible types.
 ***********************************************************************/
 #define JS_HOWMANY(x,y) (((x)+(y)-1)/(y))
 #define JS_ROUNDUP(x,y) (JS_HOWMANY(x,y)*(y))
 #define JS_MIN(x,y)     ((x)<(y)?(x):(y))
 #define JS_MAX(x,y)     ((x)>(y)?(x):(y))
 
-#ifdef _MSC_VER
-# include "jscpucfg.h"  /* We can't auto-detect MSVC configuration */
-#else
-# include "jsautocfg.h" /* Use auto-detected configuration */
-#endif
+#include "jscpucfg.h"
 
 /*
  * Define JS_64BIT iff we are building in an environment with 64-bit
  * addresses.
  */
 #ifdef _MSC_VER
 # if defined(_M_X64) || defined(_M_AMD64)
 #  define JS_64BIT
--- a/js/src/jswatchpoint.cpp
+++ b/js/src/jswatchpoint.cpp
@@ -79,16 +79,18 @@ WatchpointMap::init()
     return map.init();
 }
 
 bool
 WatchpointMap::watch(JSContext *cx, JSObject *obj, jsid id,
                      JSWatchPointHandler handler, JSObject *closure)
 {
     JS_ASSERT(id == js_CheckForStringIndex(id));
+    JS_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id));
+
     obj->setWatched(cx);
     Watchpoint w;
     w.handler = handler;
     w.closure = closure;
     w.held = false;
     if (!map.put(WatchKey(obj, id), w)) {
         js_ReportOutOfMemory(cx);
         return false;
--- a/js/src/jsxdrapi.cpp
+++ b/js/src/jsxdrapi.cpp
@@ -718,20 +718,19 @@ JS_XDRScript(JSXDRState *xdr, JSScript *
     if (!JS_XDRCStringOrNull(xdr, (char **) &state.filename))
         return false;
 
     if (!js_XDRScript(xdr, &script))
         return false;
 
     if (xdr->mode == JSXDR_DECODE) {
         JS_ASSERT(!script->compileAndGo);
-        if (!js_NewScriptObject(xdr->cx, script))
-            return false;
+        script->u.globalObject = GetCurrentGlobal(xdr->cx);
         js_CallNewScriptHook(xdr->cx, script, NULL);
-        Debugger::onNewScript(xdr->cx, script, script->u.object, NULL);
+        Debugger::onNewScript(xdr->cx, script, NULL);
         *scriptp = script;
     }
 
     return true;
 }
 
 #define CLASS_REGISTRY_MIN      8
 #define CLASS_INDEX_TO_ID(i)    ((i)+1)
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -107,51 +107,40 @@ mjit::Compiler::Compiler(JSContext *cx, 
     a(NULL), outer(NULL), script(NULL), PC(NULL), loop(NULL),
     inlineFrames(CompilerAllocPolicy(cx, *thisFromCtor())),
     branchPatches(CompilerAllocPolicy(cx, *thisFromCtor())),
 #if defined JS_MONOIC
     getGlobalNames(CompilerAllocPolicy(cx, *thisFromCtor())),
     setGlobalNames(CompilerAllocPolicy(cx, *thisFromCtor())),
     callICs(CompilerAllocPolicy(cx, *thisFromCtor())),
     equalityICs(CompilerAllocPolicy(cx, *thisFromCtor())),
-    traceICs(CompilerAllocPolicy(cx, *thisFromCtor())),
 #endif
 #if defined JS_POLYIC
     pics(CompilerAllocPolicy(cx, *thisFromCtor())),
     getElemICs(CompilerAllocPolicy(cx, *thisFromCtor())),
     setElemICs(CompilerAllocPolicy(cx, *thisFromCtor())),
 #endif
     callPatches(CompilerAllocPolicy(cx, *thisFromCtor())),
     callSites(CompilerAllocPolicy(cx, *thisFromCtor())),
     doubleList(CompilerAllocPolicy(cx, *thisFromCtor())),
     fixedIntToDoubleEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
     fixedDoubleToAnyEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
     jumpTables(CompilerAllocPolicy(cx, *thisFromCtor())),
     jumpTableOffsets(CompilerAllocPolicy(cx, *thisFromCtor())),
     loopEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
-    rootedObjects(CompilerAllocPolicy(cx, *thisFromCtor())),
     stubcc(cx, *thisFromCtor(), frame),
     debugMode_(cx->compartment->debugMode()),
-#if defined JS_TRACER
-    addTraceHints(cx->traceJitEnabled),
-#else
-    addTraceHints(false),
-#endif
     inlining_(false),
     hasGlobalReallocation(false),
     oomInVector(false),
     overflowICSpace(false),
     gcNumber(cx->runtime->gcNumber),
     applyTricks(NoApplyTricks),
     pcLengths(NULL)
 {
-    /* :FIXME: bug 637856 disabling traceJit if inference is enabled */
-    if (cx->typeInferenceEnabled())
-        addTraceHints = false;
-
     /* Once a script starts getting really hot we will inline calls in it. */
     if (!debugMode() && cx->typeInferenceEnabled() && globalObj &&
         (outerScript->getUseCount() >= USES_BEFORE_INLINING ||
          cx->hasRunOption(JSOPTION_METHODJIT_ALWAYS))) {
         inlining_ = true;
     }
 }
 
@@ -755,20 +744,19 @@ mjit::Compiler::generatePrologue()
             stubcc.linkExitDirect(stackCheck, stubcc.masm.label());
             OOL_STUBCALL(stubs::HitStackQuota, REJOIN_NONE);
             stubcc.crossJump(stubcc.masm.jump(), masm.label());
         }
 
         /*
          * Set locals to undefined, as in initCallFrameLatePrologue.
          * Skip locals which aren't closed and are known to be defined before used,
-         * :FIXME: bug 604541: write undefined if we might be using the tracer, so it works.
          */
         for (uint32 i = 0; i < script->nfixed; i++) {
-            if (analysis->localHasUseBeforeDef(i) || addTraceHints) {
+            if (analysis->localHasUseBeforeDef(i)) {
                 Address local(JSFrameReg, sizeof(StackFrame) + i * sizeof(Value));
                 masm.storeValue(UndefinedValue(), local);
             }
         }
 
         types::TypeScriptNesting *nesting = script->nesting();
 
         /*
@@ -963,23 +951,21 @@ mjit::Compiler::finishThisUp(JITScript *
         }
     }
 
     /* Please keep in sync with JITScript::scriptDataSize! */
     size_t dataSize = sizeof(JITScript) +
                       sizeof(NativeMapEntry) * nNmapLive +
                       sizeof(InlineFrame) * inlineFrames.length() +
                       sizeof(CallSite) * callSites.length() +
-                      sizeof(JSObject *) * rootedObjects.length() +
 #if defined JS_MONOIC
                       sizeof(ic::GetGlobalNameIC) * getGlobalNames.length() +
                       sizeof(ic::SetGlobalNameIC) * setGlobalNames.length() +
                       sizeof(ic::CallICInfo) * callICs.length() +
                       sizeof(ic::EqualityICInfo) * equalityICs.length() +
-                      sizeof(ic::TraceICInfo) * traceICs.length() +
 #endif
 #if defined JS_POLYIC
                       sizeof(ic::PICInfo) * pics.length() +
                       sizeof(ic::GetElementIC) * getElemICs.length() +
                       sizeof(ic::SetElementIC) * setElemICs.length() +
 #endif
                       0;
 
@@ -1095,23 +1081,16 @@ mjit::Compiler::finishThisUp(JITScript *
          * Patch stores of the base call's return address for InvariantFailure
          * calls. InvariantFailure will patch its own return address to this
          * pointer before triggering recompilation.
          */
         if (from.loopPatch.hasPatch)
             stubCode.patch(from.loopPatch.codePatch, result + codeOffset);
     }
 
-    /* Build the list of objects rooted by the script. */
-    JSObject **jitRooted = (JSObject **)cursor;
-    jit->nRootedObjects = rootedObjects.length();
-    cursor += sizeof(JSObject *) * jit->nRootedObjects;
-    for (size_t i = 0; i < jit->nRootedObjects; i++)
-        jitRooted[i] = rootedObjects[i];
-
 #if defined JS_MONOIC
     JS_INIT_CLIST(&jit->callers);
 
     if (script->hasFunction && cx->typeInferenceEnabled()) {
         jit->argsCheckStub = stubCode.locationOf(argsCheckStub);
         jit->argsCheckFallthrough = stubCode.locationOf(argsCheckFallthrough);
         jit->argsCheckJump = stubCode.locationOf(argsCheckJump);
         jit->argsCheckPool = NULL;
@@ -1244,53 +1223,16 @@ mjit::Compiler::finishThisUp(JITScript *
         jitEqualityICs[i].tempReg = equalityICs[i].tempReg;
         jitEqualityICs[i].cond = equalityICs[i].cond;
         if (equalityICs[i].jumpToStub.isSet())
             jitEqualityICs[i].jumpToStub = fullCode.locationOf(equalityICs[i].jumpToStub.get());
         jitEqualityICs[i].fallThrough = fullCode.locationOf(equalityICs[i].fallThrough);
 
         stubCode.patch(equalityICs[i].addrLabel, &jitEqualityICs[i]);
     }
-
-    ic::TraceICInfo *jitTraceICs = (ic::TraceICInfo *)cursor;
-    jit->nTraceICs = traceICs.length();
-    cursor += sizeof(ic::TraceICInfo) * jit->nTraceICs;
-    for (size_t i = 0; i < jit->nTraceICs; i++) {
-        jitTraceICs[i].initialized = traceICs[i].initialized;
-        if (!traceICs[i].initialized)
-            continue;
-
-        if (traceICs[i].fastTrampoline) {
-            jitTraceICs[i].fastTarget = stubCode.locationOf(traceICs[i].trampolineStart);
-        } else {
-            uint32 offs = uint32(traceICs[i].jumpTarget - script->code);
-            JS_ASSERT(jumpMap[offs].isSet());
-            jitTraceICs[i].fastTarget = fullCode.locationOf(jumpMap[offs]);
-        }
-        jitTraceICs[i].slowTarget = stubCode.locationOf(traceICs[i].trampolineStart);
-
-        jitTraceICs[i].traceHint = fullCode.locationOf(traceICs[i].traceHint);
-        jitTraceICs[i].stubEntry = stubCode.locationOf(traceICs[i].stubEntry);
-        jitTraceICs[i].traceData = NULL;
-#ifdef DEBUG
-        jitTraceICs[i].jumpTargetPC = traceICs[i].jumpTarget;
-#endif
-
-        jitTraceICs[i].hasSlowTraceHint = traceICs[i].slowTraceHint.isSet();
-        if (traceICs[i].slowTraceHint.isSet())
-            jitTraceICs[i].slowTraceHint = stubCode.locationOf(traceICs[i].slowTraceHint.get());
-#ifdef JS_TRACER
-        uint32 hotloop = GetHotloop(cx);
-        uint32 prevCount = cx->compartment->backEdgeCount(traceICs[i].jumpTarget);
-        jitTraceICs[i].loopCounterStart = hotloop;
-        jitTraceICs[i].loopCounter = hotloop < prevCount ? 1 : hotloop - prevCount;
-#endif
-
-        stubCode.patch(traceICs[i].addrLabel, &jitTraceICs[i]);
-    }
 #endif /* JS_MONOIC */
 
     for (size_t i = 0; i < callPatches.length(); i++) {
         CallPatchInfo &patch = callPatches[i];
 
         CodeLocationLabel joinPoint = patch.joinSlow
             ? stubCode.locationOf(patch.joinPoint)
             : fullCode.locationOf(patch.joinPoint);
@@ -4710,22 +4652,16 @@ mjit::Compiler::jsop_callprop_str(JSAtom
         return true;
     }
 
     /* Bake in String.prototype. This is safe because of compileAndGo. */
     JSObject *obj = globalObj->getOrCreateStringPrototype(cx);
     if (!obj)
         return false;
 
-    /*
-     * Root the proto, since JS_ClearScope might overwrite the global object's
-     * copy.
-     */
-    rootedObjects.append(obj);
-
     /* Force into a register because getprop won't expect a constant. */
     RegisterID reg = frame.allocReg();
 
     masm.move(ImmPtr(obj), reg);
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
 
     /* Get the property. */
     if (!jsop_getprop(atom, knownPushedType(0)))
@@ -6833,160 +6769,60 @@ mjit::Compiler::jumpAndTrace(Jump j, jsb
             alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
             if (!alloc)
                 return false;
         }
         lvtarget = alloc;
         consistent = frame.consistentRegisters(target);
     }
 
-    if (!addTraceHints || target >= PC ||
-        (JSOp(*target) != JSOP_TRACE && JSOp(*target) != JSOP_NOTRACE)
-#ifdef JS_MONOIC
-        || GET_UINT16(target) == BAD_TRACEIC_INDEX
-#endif
-        )
-    {
-        if (!lvtarget || lvtarget->synced()) {
-            JS_ASSERT(consistent);
-            if (!jumpInScript(j, target))
-                return false;
-            if (slow && !stubcc.jumpInScript(*slow, target))
-                return false;
-        } else {
-            if (consistent) {
-                if (!jumpInScript(j, target))
-                    return false;
-            } else {
-                /*
-                 * Make a trampoline to issue remaining loads for the register
-                 * state at target.
-                 */
-                Label start = stubcc.masm.label();
-                stubcc.linkExitDirect(j, start);
-                frame.prepareForJump(target, stubcc.masm, false);
-                if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
-                    return false;
-                if (trampoline)
-                    *trampoline = true;
-                if (pcLengths) {
-                    /*
-                     * This is OOL code but will usually be executed, so track
-                     * it in the CODE_LENGTH for the opcode.
-                     */
-                    uint32 offset = ssa.frameLength(a->inlineIndex) + PC - script->code;
-                    size_t length = stubcc.masm.size() - stubcc.masm.distanceOf(start);
-                    pcLengths[offset].codeLength += length;
-                }
-            }
-
-            if (slow) {
-                slow->linkTo(stubcc.masm.label(), &stubcc.masm);
-                frame.prepareForJump(target, stubcc.masm, true);
-                if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
-                    return false;
-            }
-        }
-
-        if (target < PC)
-            return finishLoop(target);
-        return true;
-    }
-
-    /* The trampoline should not be specified if we need to generate a trace IC. */
-    JS_ASSERT(!trampoline);
-
-#ifndef JS_TRACER
-    JS_NOT_REACHED("Bad addTraceHints");
-    return false;
-#else
-
-# if JS_MONOIC
-    TraceGenInfo ic;
-
-    ic.initialized = true;
-    ic.stubEntry = stubcc.masm.label();
-    ic.traceHint = j;
-    if (slow)
-        ic.slowTraceHint = *slow;
-
-    uint16 index = GET_UINT16(target);
-    if (traceICs.length() <= index)
-        if (!traceICs.resize(index+1))
+    if (!lvtarget || lvtarget->synced()) {
+        JS_ASSERT(consistent);
+        if (!jumpInScript(j, target))
             return false;
-# endif
-
-    Label traceStart = stubcc.masm.label();
-
-    stubcc.linkExitDirect(j, traceStart);
-    if (slow)
-        slow->linkTo(traceStart, &stubcc.masm);
-
-# if JS_MONOIC
-    ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
-
-    Jump nonzero = stubcc.masm.branchSub32(Assembler::NonZero, Imm32(1),
-                                           Address(Registers::ArgReg1,
-                                                   offsetof(TraceICInfo, loopCounter)));
-# endif
-
-    /* Save and restore compiler-tracked PC, so cx->regs is right in InvokeTracer. */
-    {
-        jsbytecode* pc = PC;
-        PC = target;
-
-        OOL_STUBCALL(stubs::InvokeTracer, REJOIN_NONE);
-
-        PC = pc;
-    }
-
-    Jump no = stubcc.masm.branchTestPtr(Assembler::Zero, Registers::ReturnReg,
-                                        Registers::ReturnReg);
-    if (!cx->typeInferenceEnabled())
-        stubcc.masm.loadPtr(FrameAddress(VMFrame::offsetOfFp), JSFrameReg);
-    stubcc.masm.jump(Registers::ReturnReg);
-    no.linkTo(stubcc.masm.label(), &stubcc.masm);
-
-#ifdef JS_MONOIC
-    nonzero.linkTo(stubcc.masm.label(), &stubcc.masm);
-
-    ic.jumpTarget = target;
-    ic.fastTrampoline = !consistent;
-    ic.trampolineStart = stubcc.masm.label();
-
-    traceICs[index] = ic;
-#endif
-
-    /*
-     * Jump past the tracer call if the trace has been blacklisted. We still make
-     * a trace IC in such cases, in case it is un-blacklisted later.
-     */
-    if (JSOp(*target) == JSOP_NOTRACE) {
+        if (slow && !stubcc.jumpInScript(*slow, target))
+            return false;
+    } else {
         if (consistent) {
             if (!jumpInScript(j, target))
                 return false;
         } else {
-            stubcc.linkExitDirect(j, stubcc.masm.label());
+            /*
+             * Make a trampoline to issue remaining loads for the register
+             * state at target.
+             */
+            Label start = stubcc.masm.label();
+            stubcc.linkExitDirect(j, start);
+            frame.prepareForJump(target, stubcc.masm, false);
+            if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
+                return false;
+            if (trampoline)
+                *trampoline = true;
+            if (pcLengths) {
+                /*
+                 * This is OOL code but will usually be executed, so track
+                 * it in the CODE_LENGTH for the opcode.
+                 */
+                uint32 offset = ssa.frameLength(a->inlineIndex) + PC - script->code;
+                size_t length = stubcc.masm.size() - stubcc.masm.distanceOf(start);
+                pcLengths[offset].codeLength += length;
+            }
         }
-        if (slow)
+
+        if (slow) {
             slow->linkTo(stubcc.masm.label(), &stubcc.masm);
-    }
-
-    /*
-     * Reload any registers needed at the head of the loop. Note that we didn't
-     * need to do syncing before calling InvokeTracer, as state is always synced
-     * on backwards jumps.
-     */
-    frame.prepareForJump(target, stubcc.masm, true);
-
-    if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
-        return false;
-#endif
-
-    return finishLoop(target);
+            frame.prepareForJump(target, stubcc.masm, true);
+            if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
+                return false;
+        }
+    }
+
+    if (target < PC)
+        return finishLoop(target);
+    return true;
 }
 
 void
 mjit::Compiler::enterBlock(JSObject *obj)
 {
     /* For now, don't bother doing anything for this opcode. */
     frame.syncAndForgetEverything();
     masm.move(ImmPtr(obj), Registers::ArgReg1);
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -120,29 +120,16 @@ class Compiler : public BaseCompiler
         Label fallThrough;
         jsbytecode *jumpTarget;
         bool trampoline;
         Label trampolineStart;
         ValueRemat lvr, rvr;
         Assembler::Condition cond;
         JSC::MacroAssembler::RegisterID tempReg;
     };
-    
-    struct TraceGenInfo {
-        bool initialized;
-        Label stubEntry;
-        DataLabelPtr addrLabel;
-        jsbytecode *jumpTarget;
-        bool fastTrampoline;
-        Label trampolineStart;
-        Jump traceHint;
-        MaybeJump slowTraceHint;
-
-        TraceGenInfo() : initialized(false) {}
-    };
 
     /* InlineFrameAssembler wants to see this. */
   public:
     struct CallGenInfo {
         /*
          * These members map to members in CallICInfo. See that structure for
          * more comments.
          */
@@ -444,43 +431,40 @@ private:
 
     js::Vector<ActiveFrame*, 4, CompilerAllocPolicy> inlineFrames;
     js::Vector<BranchPatch, 64, CompilerAllocPolicy> branchPatches;
 #if defined JS_MONOIC
     js::Vector<GetGlobalNameICInfo, 16, CompilerAllocPolicy> getGlobalNames;
     js::Vector<SetGlobalNameICInfo, 16, CompilerAllocPolicy> setGlobalNames;
     js::Vector<CallGenInfo, 64, CompilerAllocPolicy> callICs;
     js::Vector<EqualityGenInfo, 64, CompilerAllocPolicy> equalityICs;
-    js::Vector<TraceGenInfo, 64, CompilerAllocPolicy> traceICs;
 #endif
 #if defined JS_POLYIC
     js::Vector<PICGenInfo, 16, CompilerAllocPolicy> pics;
     js::Vector<GetElementICInfo, 16, CompilerAllocPolicy> getElemICs;
     js::Vector<SetElementICInfo, 16, CompilerAllocPolicy> setElemICs;
 #endif
     js::Vector<CallPatchInfo, 64, CompilerAllocPolicy> callPatches;
     js::Vector<InternalCallSite, 64, CompilerAllocPolicy> callSites;
     js::Vector<DoublePatch, 16, CompilerAllocPolicy> doubleList;
     js::Vector<uint32> fixedIntToDoubleEntries;
     js::Vector<uint32> fixedDoubleToAnyEntries;
     js::Vector<JumpTable, 16> jumpTables;
     js::Vector<uint32, 16> jumpTableOffsets;
     js::Vector<LoopEntry, 16> loopEntries;
-    js::Vector<JSObject *, 0, CompilerAllocPolicy> rootedObjects;
     StubCompiler stubcc;
     Label invokeLabel;
     Label arityLabel;
     Label argsCheckLabel;
 #ifdef JS_MONOIC
     Label argsCheckStub;
     Label argsCheckFallthrough;
     Jump argsCheckJump;
 #endif
     bool debugMode_;
-    bool addTraceHints;
     bool inlining_;
     bool hasGlobalReallocation;
     bool oomInVector;       // True if we have OOM'd appending to a vector. 
     bool overflowICSpace;   // True if we added a constant pool in a reserved space.
     uint32 gcNumber;
     enum { NoApplyTricks, LazyArgsObj } applyTricks;
     PCLengthEntry *pcLengths;
 
--- a/js/src/methodjit/FastArithmetic.cpp
+++ b/js/src/methodjit/FastArithmetic.cpp
@@ -1157,17 +1157,17 @@ mjit::Compiler::jsop_equality_int_string
 
         ic.cond = cond;
         ic.tempReg = tempReg;
         ic.lvr = lvr;
         ic.rvr = rvr;
         ic.stubEntry = stubEntry;
         ic.stub = stub;
 
-        bool useIC = (!addTraceHints || target >= PC) && !a->parent;
+        bool useIC = !a->parent;
 
         /* Call the IC stub, which may generate a fast path. */
         if (useIC) {
             /* Adjust for the two values just pushed. */
             ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
             ic.stubCall = OOL_STUBCALL_LOCAL_SLOTS(ic::Equality, REJOIN_BRANCH,
                                                    frame.totalDepth() + 2);
             needStub = false;
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -182,36 +182,16 @@ mjit::Compiler::jsop_bitop(JSOp op)
       case JSOP_URSH:
         stub = stubs::Ursh;
         break;
       default:
         JS_NOT_REACHED("wat");
         return;
     }
 
-    bool lhsIntOrDouble = !(lhs->isNotType(JSVAL_TYPE_DOUBLE) && 
-                            lhs->isNotType(JSVAL_TYPE_INT32));
-
-    /* Fast-path double to int conversion. */
-    if (!lhs->isConstant() && rhs->isConstant() && lhsIntOrDouble &&
-        rhs->isType(JSVAL_TYPE_INT32) && rhs->getValue().toInt32() == 0 &&
-        (op == JSOP_BITOR || op == JSOP_LSH)) {
-        ensureInteger(lhs, Uses(2));
-        RegisterID reg = frame.ownRegForData(lhs);
-
-        stubcc.leave();
-        OOL_STUBCALL(stub, REJOIN_FALLTHROUGH);
-
-        frame.popn(2);
-        frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
-
-        stubcc.rejoin(Changes(1));
-        return;
-    }
-
     /* Convert a double RHS to integer if it's constant for the test below. */
     if (rhs->isConstant() && rhs->getValue().isDouble())
         rhs->convertConstantDoubleToInt32(cx);
 
     /* We only want to handle integers here. */
     if ((lhs->isNotType(JSVAL_TYPE_INT32) && lhs->isNotType(JSVAL_TYPE_DOUBLE)) ||
         (rhs->isNotType(JSVAL_TYPE_INT32) && rhs->isNotType(JSVAL_TYPE_DOUBLE)) ||
         (op == JSOP_URSH && rhs->isConstant() && rhs->getValue().toInt32() % 32 == 0)) {
@@ -277,17 +257,17 @@ mjit::Compiler::jsop_bitop(JSOp op)
 
         reg = frame.ownRegForData(lhs);
         if (rhs->isConstant()) {
             int32 rhsInt = rhs->getValue().toInt32();
             if (op == JSOP_BITAND)
                 masm.and32(Imm32(rhsInt), reg);
             else if (op == JSOP_BITXOR)
                 masm.xor32(Imm32(rhsInt), reg);
-            else
+            else if (rhsInt != 0)
                 masm.or32(Imm32(rhsInt), reg);
         } else if (frame.shouldAvoidDataRemat(rhs)) {
             Address rhsAddr = masm.payloadOf(frame.addressOf(rhs));
             if (op == JSOP_BITAND)
                 masm.and32(rhsAddr, reg);
             else if (op == JSOP_BITXOR)
                 masm.xor32(rhsAddr, reg);
             else
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -1320,21 +1320,17 @@ FrameState::sync(Assembler &masm, Uses u
 
     /*
      * Keep track of free registers using a bitmask. If we have to drop into
      * syncFancy(), then this mask will help avoid eviction.
      */
     Registers avail(freeRegs.freeMask & Registers::AvailRegs);
     Registers temp(Registers::TempAnyRegs);
 
-    FrameEntry *bottom = (cx->typeInferenceEnabled() || cx->compartment->debugMode())
-        ? entries
-        : a->sp - uses.nuses;
-
-    for (FrameEntry *fe = a->sp - 1; fe >= bottom; fe--) {
+    for (FrameEntry *fe = a->sp - 1; fe >= entries; fe--) {
         if (!fe->isTracked())
             continue;
 
         if (fe->isType(JSVAL_TYPE_DOUBLE)) {
             /* Copies of in-memory doubles can be synced without spilling. */
             if (fe->isCopy() || !fe->data.inFPRegister())
                 ensureFeSynced(fe, masm);
             continue;
@@ -1374,17 +1370,17 @@ FrameState::sync(Assembler &masm, Uses u
 
                 masm.storeValue(syncReg, addressOf(fe));
                 continue;
             }
 #elif defined JS_NUNBOX32
             /* Fall back to a slower sync algorithm if load required. */
             if ((!fe->type.synced() && backing->type.inMemory()) ||
                 (!fe->data.synced() && backing->data.inMemory())) {
-                syncFancy(masm, avail, fe, bottom);
+                syncFancy(masm, avail, fe, entries);
                 return;
             }
 #endif
         }
 
         bool copy = fe->isCopy();
 
         /* If a part still needs syncing, it is either a copy or constant. */
@@ -1455,21 +1451,17 @@ FrameState::syncAndKill(Registers kill, 
             JS_ASSERT(fe->type.reg() == reg.reg());
             syncType(fe);
         }
 #endif
     }
 
     uint32 maxvisits = tracker.nentries;
 
-    FrameEntry *bottom = (cx->typeInferenceEnabled() || cx->compartment->debugMode())
-        ? entries
-        : a->sp - uses.nuses;
-
-    for (FrameEntry *fe = a->sp - 1; fe >= bottom && maxvisits; fe--) {
+    for (FrameEntry *fe = a->sp - 1; fe >= entries && maxvisits; fe--) {
         if (!fe->isTracked())
             continue;
 
         maxvisits--;
 
         if (deadEntry(fe, ignore.nuses))
             continue;
 
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -528,31 +528,17 @@ js_InternalThrow(VMFrame &f)
     JSContext *cx = f.cx;
 
     ExpandInlineFrames(cx->compartment);
 
     // The current frame may have an associated orphaned native, if the native
     // or SplatApplyArgs threw an exception.
     RemoveOrphanedNative(cx, f.fp());
 
-    // It's possible that from within RunTracer(), Interpret() returned with
-    // an error and finished the frame (i.e., called ScriptEpilogue), but has
-    // not yet performed an inline return.
-    //
-    // In this case, RunTracer() has no choice but to propagate the error
-    // up to the method JIT, and thus to this function. But ScriptEpilogue()
-    // has already been called. Detect this, and avoid double-finishing the
-    // frame. See HandleErrorInExcessFrame() and bug 624100.
-    if (f.fp()->finishedInInterpreter()) {
-        // If it's the last frame, just propagate the failure up again.
-        if (f.fp() == f.entryfp)
-            return NULL;
-
-        InlineReturn(f);
-    }
+    JS_ASSERT(!f.fp()->finishedInInterpreter());
 
     // Make sure sp is up to date.
     JS_ASSERT(&cx->regs() == &f.regs);
 
     jsbytecode *pc = NULL;
     for (;;) {
         if (cx->isExceptionPending()) {
             // Call the throw hook if necessary
@@ -611,60 +597,56 @@ js_InternalThrow(VMFrame &f)
     JS_ASSERT(f.regs.sp == cx->regs().sp);
 
     if (!pc)
         return NULL;
 
     StackFrame *fp = cx->fp();
     JSScript *script = fp->script();
 
-    if (cx->typeInferenceEnabled() || !fp->jit()) {
-        /*
-         * Fall back to EnterMethodJIT and finish the frame in the interpreter.
-         * With type inference enabled, we may wipe out all JIT code on the
-         * stack without patching ncode values to jump to the interpreter, and
-         * thus can only enter JIT code via EnterMethodJIT (which overwrites
-         * its entry frame's ncode). See ClearAllFrames.
-         */
-        cx->compartment->jaegerCompartment()->setLastUnfinished(Jaeger_Unfinished);
-
-        if (!script->ensureRanAnalysis(cx)) {
-            js_ReportOutOfMemory(cx);
-            return NULL;
-        }
-
-        analyze::AutoEnterAnalysis enter(cx);
-
-        cx->regs().pc = pc;
-        cx->regs().sp = fp->base() + script->analysis()->getCode(pc).stackDepth;
+    /*
+     * Fall back to EnterMethodJIT and finish the frame in the interpreter.
+     * With type inference enabled, we may wipe out all JIT code on the
+     * stack without patching ncode values to jump to the interpreter, and
+     * thus can only enter JIT code via EnterMethodJIT (which overwrites
+     * its entry frame's ncode). See ClearAllFrames.
+     */
+    cx->compartment->jaegerCompartment()->setLastUnfinished(Jaeger_Unfinished);
 
-        /*
-         * Interpret the ENTERBLOCK and EXCEPTION opcodes, so that we don't go
-         * back into the interpreter with a pending exception. This will cause
-         * it to immediately rethrow.
-         */
-        if (cx->isExceptionPending()) {
-            JS_ASSERT(js_GetOpcode(cx, script, pc) == JSOP_ENTERBLOCK);
-            JSObject *obj = script->getObject(GET_SLOTNO(pc));
-            Value *vp = cx->regs().sp + OBJ_BLOCK_COUNT(cx, obj);
-            SetValueRangeToUndefined(cx->regs().sp, vp);
-            cx->regs().sp = vp;
-            JS_ASSERT(js_GetOpcode(cx, script, pc + JSOP_ENTERBLOCK_LENGTH) == JSOP_EXCEPTION);
-            cx->regs().sp[0] = cx->getPendingException();
-            cx->clearPendingException();
-            cx->regs().sp++;
-            cx->regs().pc = pc + JSOP_ENTERBLOCK_LENGTH + JSOP_EXCEPTION_LENGTH;
-        }
-
-        *f.oldregs = f.regs;
-
+    if (!script->ensureRanAnalysis(cx)) {
+        js_ReportOutOfMemory(cx);
         return NULL;
     }
 
-    return script->nativeCodeForPC(fp->isConstructing(), pc);
+    analyze::AutoEnterAnalysis enter(cx);
+
+    cx->regs().pc = pc;
+    cx->regs().sp = fp->base() + script->analysis()->getCode(pc).stackDepth;
+
+    /*
+     * Interpret the ENTERBLOCK and EXCEPTION opcodes, so that we don't go
+     * back into the interpreter with a pending exception. This will cause
+     * it to immediately rethrow.
+     */
+    if (cx->isExceptionPending()) {
+        JS_ASSERT(js_GetOpcode(cx, script, pc) == JSOP_ENTERBLOCK);
+        JSObject *obj = script->getObject(GET_SLOTNO(pc));
+        Value *vp = cx->regs().sp + OBJ_BLOCK_COUNT(cx, obj);
+        SetValueRangeToUndefined(cx->regs().sp, vp);
+        cx->regs().sp = vp;
+        JS_ASSERT(js_GetOpcode(cx, script, pc + JSOP_ENTERBLOCK_LENGTH) == JSOP_EXCEPTION);
+        cx->regs().sp[0] = cx->getPendingException();
+        cx->clearPendingException();
+        cx->regs().sp++;
+        cx->regs().pc = pc + JSOP_ENTERBLOCK_LENGTH + JSOP_EXCEPTION_LENGTH;
+    }
+
+    *f.oldregs = f.regs;
+
+    return NULL;
 }
 
 void JS_FASTCALL
 stubs::CreateThis(VMFrame &f, JSObject *proto)
 {
     JSContext *cx = f.cx;
     StackFrame *fp = f.fp();
     JSObject *callee = &fp->callee();
@@ -696,491 +678,18 @@ stubs::ScriptProbeOnlyPrologue(VMFrame &
 }
 
 void JS_FASTCALL
 stubs::ScriptProbeOnlyEpilogue(VMFrame &f)
 {
     Probes::exitJSFun(f.cx, f.fp()->fun(), f.fp()->script());
 }
 
-#ifdef JS_TRACER
-
-/*
- * Called when an error is in progress and the topmost frame could not handle
- * it. This will unwind to a given frame, or find and align to an exception
- * handler in the process.
- */
-static inline bool
-HandleErrorInExcessFrame(VMFrame &f, StackFrame *stopFp, bool searchedTopmostFrame = true)
-{
-    JSContext *cx = f.cx;
-
-    /*
-     * Callers of this called either Interpret() or JaegerShot(), which would
-     * have searched for exception handlers already. If we see stopFp, just
-     * return false. Otherwise, pop the frame, since it's guaranteed useless.
-     *
-     * Note that this also guarantees ScriptEpilogue() has been called.
-     */
-    StackFrame *fp = cx->fp();
-    if (searchedTopmostFrame) {
-        /*
-         * This is a special case meaning that fp->finishedInInterpreter() is
-         * true. If so, and fp == stopFp, our only choice is to propagate this
-         * error up, back to the method JIT, and then to js_InternalThrow,
-         * where this becomes a special case. See the comment there and bug
-         * 624100.
-         */
-        if (fp == stopFp)
-            return false;
-
-        /*
-         * Otherwise, the protocol here (like Invoke) is to assume that the
-         * execution mode finished the frame, and to just pop it.
-         */
-        InlineReturn(f);
-    }
-
-    /* Remove the bottom frame. */
-    bool returnOK = false;
-    for (;;) {
-        fp = cx->fp();
-
-        /* Clear imacros. */
-        if (fp->hasImacropc()) {
-            cx->regs().pc = fp->imacropc();
-            fp->clearImacropc();
-        }
-        JS_ASSERT(!fp->hasImacropc());
-
-        /* If there's an exception and a handler, set the pc and leave. */
-        if (cx->isExceptionPending()) {
-            jsbytecode *pc = FindExceptionHandler(cx);
-            if (pc) {
-                cx->regs().pc = pc;
-                returnOK = true;
-                break;
-            }
-        }
-
-        /* Don't unwind if this was the entry frame. */
-        if (fp == stopFp)
-            break;
-
-        /* Unwind and return. */
-        returnOK &= UnwindScope(cx, 0, returnOK || cx->isExceptionPending());
-        returnOK = ScriptEpilogue(cx, fp, returnOK);
-        InlineReturn(f);
-    }
-
-    JS_ASSERT(&f.regs == &cx->regs());
-    JS_ASSERT_IF(!returnOK, cx->fp() == stopFp);
-
-    return returnOK;
-}
-
-/* Returns whether the current PC has method JIT'd code. */
-static inline void *
-AtSafePoint(JSContext *cx)
-{
-    StackFrame *fp = cx->fp();
-    if (fp->hasImacropc())
-        return NULL;
-
-    JSScript *script = fp->script();
-    return script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs().pc);
-}
-
-/*
- * Interprets until either a safe point is reached that has method JIT'd
- * code, or the current frame tries to return.
- */
-static inline JSBool
-PartialInterpret(VMFrame &f)
-{
-    JSContext *cx = f.cx;
-    StackFrame *fp = cx->fp();
-
-#ifdef DEBUG
-    JSScript *script = fp->script();
-    JS_ASSERT(!fp->finishedInInterpreter());
-    JS_ASSERT(fp->hasImacropc() ||
-              !script->maybeNativeCodeForPC(fp->isConstructing(), cx->regs().pc));
-#endif
-
-    JSBool ok = JS_TRUE;
-    ok = Interpret(cx, fp, JSINTERP_SAFEPOINT);
-
-    return ok;
-}
-
 JS_STATIC_ASSERT(JSOP_NOP == 0);
 
-/*
- * Returns whether the current PC would return, or if the frame has already
- * been completed. This distinction avoids re-entering the interpreter or JIT
- * to complete a JSOP_RETURN. Instead, that edge case is handled in
- * HandleFinishedFrame. We could consider reducing complexity, and making this
- * function return only "finishedInInterpreter", and always using the full VM
- * machinery to fully finish frames.
- */
-static inline bool
-FrameIsFinished(JSContext *cx)
-{
-    JSOp op = JSOp(*cx->regs().pc);
-    return (op == JSOP_RETURN ||
-            op == JSOP_RETRVAL ||
-            op == JSOP_STOP)
-        ? true
-        : cx->fp()->finishedInInterpreter();
-}
-
-/*
- * Given a frame that is about to return, make sure its return value and
- * activation objects are fixed up. Then, pop the frame and advance the
- * current PC. Note that while we could enter the JIT at this point, the
- * logic would still be necessary for the interpreter, so it's easier
- * (and faster) to finish frames in C++ even if at a safe point here.
- */
-static bool
-HandleFinishedFrame(VMFrame &f, StackFrame *entryFrame)
-{
-    JSContext *cx = f.cx;
-
-    JS_ASSERT(FrameIsFinished(cx));
-
-    /*
-     * This is the most difficult and complicated piece of the tracer
-     * integration, and historically has been very buggy. The problem is that
-     * although this frame has to be popped (see RemoveExcessFrames), it may
-     * be at a JSOP_RETURN opcode, and it might not have ever been executed.
-     * That is, fp->rval may not be set to the top of the stack, and if it
-     * has, the stack has already been decremented. Note that fp->rval is not
-     * the only problem: the epilogue may never have been executed.
-     *
-     * Here are the edge cases and whether the frame has been exited cleanly:
-     *  1. No: A trace exited directly before a RETURN op, and the
-     *         interpreter never ran.
-     *  2. Yes: The interpreter exited cleanly.
-     *  3. No: The interpreter exited on a safe point. LEAVE_ON_SAFE_POINT
-     *         is not used in between JSOP_RETURN and advancing the PC,
-     *         therefore, it cannot have been run if at a safe point.
-     *  4. No: Somewhere in the RunTracer call tree, we removed a frame,
-     *         and we returned to a JSOP_RETURN opcode. Note carefully
-     *         that in this situation, FrameIsFinished() returns true!
-     *  5. Yes: The function exited in the method JIT, during
-     *         FinishExcessFrames() However, in this case, we'll never enter
-     *         HandleFinishedFrame(): we always immediately pop JIT'd frames.
-     *
-     * Since the only scenario where this fixup is NOT needed is a normal exit
-     * from the interpreter, we can cleanly check for this scenario by checking
-     * a bit it sets in the frame.
-     */
-    bool returnOK = true;
-    if (!cx->fp()->finishedInInterpreter()) {
-        if (JSOp(*cx->regs().pc) == JSOP_RETURN)
-            cx->fp()->setReturnValue(f.regs.sp[-1]);
-
-        returnOK = ScriptEpilogue(cx, cx->fp(), true);
-    }
-
-    if (cx->fp() != entryFrame) {
-        InlineReturn(f);
-    }
-
-    return returnOK;
-}
-
-/*
- * Given a frame newer than the entry frame, try to finish it. If it's at a
- * return position, pop the frame. If it's at a safe point, execute it in
- * Jaeger code. Otherwise, try to interpret until a safe point.
- *
- * While this function is guaranteed to make progress, it may not actually
- * finish or pop the current frame. It can either:
- *   1) Finalize a finished frame, or
- *   2) Finish and finalize the frame in the Method JIT, or
- *   3) Interpret, which can:
- *     a) Propagate an error, or
- *     b) Finish the frame, but not finalize it, or
- *     c) Abruptly leave at any point in the frame, or in a newer frame
- *        pushed by a call, that has method JIT'd code.
- */
-static bool
-EvaluateExcessFrame(VMFrame &f, StackFrame *entryFrame)
-{
-    JSContext *cx = f.cx;
-    StackFrame *fp = cx->fp();
-
-    /*
-     * A "finished" frame is when the interpreter rested on a STOP,
-     * RETURN, RETRVAL, etc. We check for finished frames BEFORE looking
-     * for a safe point. If the frame was finished, we could have already
-     * called ScriptEpilogue(), and entering the JIT could call it twice.
-     */
-    if (!fp->hasImacropc() && FrameIsFinished(cx))
-        return HandleFinishedFrame(f, entryFrame);
-
-    if (void *ncode = AtSafePoint(cx)) {
-        if (!JaegerShotAtSafePoint(cx, ncode, false))
-            return false;
-        InlineReturn(f);
-        return true;
-    }
-
-    return PartialInterpret(f);
-}
-
-/*
- * Evaluate frames newer than the entry frame until all are gone. This will
- * always leave f.regs.fp == entryFrame.
- */
-static bool
-FinishExcessFrames(VMFrame &f, StackFrame *entryFrame)
-{
-    JSContext *cx = f.cx;
-
-    while (cx->fp() != entryFrame || entryFrame->hasImacropc()) {
-        if (!EvaluateExcessFrame(f, entryFrame)) {
-            if (!HandleErrorInExcessFrame(f, entryFrame))
-                return false;
-        }
-    }
-
-    return true;
-}
-
-#if defined JS_MONOIC
-static void
-UpdateTraceHintSingle(Repatcher &repatcher, JSC::CodeLocationJump jump, JSC::CodeLocationLabel target)
-{
-    /*
-     * Hack: The value that will be patched is before the executable address,
-     * so to get protection right, just unprotect the general region around
-     * the jump.
-     */
-    repatcher.relink(jump, target);
-
-    JaegerSpew(JSpew_PICs, "relinking trace hint %p to %p\n",
-               jump.executableAddress(), target.executableAddress());
-}
-
-static void
-DisableTraceHint(JITScript *jit, ic::TraceICInfo &ic)
-{
-    Repatcher repatcher(jit);
-    UpdateTraceHintSingle(repatcher, ic.traceHint, ic.fastTarget);
-
-    if (ic.hasSlowTraceHint)
-        UpdateTraceHintSingle(repatcher, ic.slowTraceHint, ic.slowTarget);
-}
-
-static void
-ResetTraceHintAt(JSScript *script, js::mjit::JITScript *jit,
-                 jsbytecode *pc, uint16_t index, bool full)
-{
-    if (index >= jit->nTraceICs)
-        return;
-    ic::TraceICInfo &ic = jit->traceICs()[index];
-    if (!ic.initialized)
-        return;
-    
-    JS_ASSERT(ic.jumpTargetPC == pc);
-
-    JaegerSpew(JSpew_PICs, "Enabling trace IC %u in script %p\n", index,
-               static_cast<void*>(script));
-
-    Repatcher repatcher(jit);
-
-    UpdateTraceHintSingle(repatcher, ic.traceHint, ic.stubEntry);
-
-    if (ic.hasSlowTraceHint)
-        UpdateTraceHintSingle(repatcher, ic.slowTraceHint, ic.stubEntry);
-
-    if (full) {
-        ic.traceData = NULL;
-        ic.loopCounterStart = 1;
-        ic.loopCounter = ic.loopCounterStart;
-    }
-}
-#endif
-
-void
-js::mjit::ResetTraceHint(JSScript *script, jsbytecode *pc, uint16_t index, bool full)
-{
-#if JS_MONOIC
-    if (script->jitNormal)
-        ResetTraceHintAt(script, script->jitNormal, pc, index, full);
-
-    if (script->jitCtor)
-        ResetTraceHintAt(script, script->jitCtor, pc, index, full);
-#endif
-}
-
-#if JS_MONOIC
-void *
-RunTracer(VMFrame &f, ic::TraceICInfo &ic)
-#else
-void *
-RunTracer(VMFrame &f)
-#endif
-{
-    JSContext *cx = f.cx;
-    StackFrame *entryFrame = f.fp();
-    TracePointAction tpa;
-
-    /* :TODO: nuke PIC? */
-    if (!cx->traceJitEnabled)
-        return NULL;
-
-    /*
-     * Force initialization of the entry frame's scope chain and return value,
-     * if necessary.  The tracer can query the scope chain without needing to
-     * check the HAS_SCOPECHAIN flag, and the frame is guaranteed to have the
-     * correct return value stored if we trace/interpret through to the end
-     * of the frame.
-     */
-    entryFrame->scopeChain();
-    entryFrame->returnValue();
-
-    bool blacklist;
-    void **traceData;
-    uintN *traceEpoch;
-    uint32 *loopCounter;
-    uint32 hits;
-#if JS_MONOIC
-    traceData = &ic.traceData;
-    traceEpoch = &ic.traceEpoch;
-    loopCounter = &ic.loopCounter;
-    *loopCounter = 1;
-    hits = ic.loopCounterStart;
-#else
-    traceData = NULL;
-    traceEpoch = NULL;
-    loopCounter = NULL;
-    hits = 1;
-#endif
-
-    {
-        /*
-         * While the tracer is running, redirect the regs to a local variable here.
-         * If the tracer exits during an inlined frame, it will synthesize those
-         * frames, point f.regs.fp at them and then enter the interpreter. If the
-         * interpreter pops the frames it will not be reflected here as a local
-         * set of regs is used by the interpreter, and f->regs end up pointing at
-         * garbage, confusing the recompiler.
-         */
-        FrameRegs regs = f.regs;
-        PreserveRegsGuard regsGuard(cx, regs);
-
-        tpa = MonitorTracePoint(f.cx, &blacklist, traceData, traceEpoch,
-                                loopCounter, hits);
-        JS_ASSERT(!TRACE_RECORDER(cx));
-    }
-
-#if JS_MONOIC
-    ic.loopCounterStart = *loopCounter;
-    if (blacklist)
-        DisableTraceHint(entryFrame->jit(), ic);
-#endif
-
-    // Even though ExecuteTree() bypasses the interpreter, it should propagate
-    // error failures correctly.
-    JS_ASSERT_IF(cx->isExceptionPending(), tpa == TPA_Error);
-
-    JS_ASSERT(f.fp() == cx->fp());
-    switch (tpa) {
-      case TPA_Nothing:
-        return NULL;
-
-      case TPA_Error:
-        if (!HandleErrorInExcessFrame(f, entryFrame, f.fp()->finishedInInterpreter()))
-            THROWV(NULL);
-        JS_ASSERT(!cx->fp()->hasImacropc());
-        break;
-
-      case TPA_RanStuff:
-      case TPA_Recorded:
-        break;
-    }
-
-    /*
-     * The tracer could have dropped us off on any frame at any position.
-     * Well, it could not have removed frames (recursion is disabled).
-     *
-     * Frames after the entryFrame cannot be entered via JaegerShotAtSafePoint()
-     * unless each is at a safe point. We can JaegerShotAtSafePoint these
-     * frames individually, but we must unwind to the entryFrame.
-     *
-     * Note carefully that JaegerShotAtSafePoint can resume methods at
-     * arbitrary safe points whereas JaegerShot cannot.
-     *
-     * If we land on entryFrame without a safe point in sight, we'll end up
-     * at the RETURN op. This is an edge case with two paths:
-     *
-     * 1) The entryFrame is the last inline frame. If it fell on a RETURN,
-     *    move the return value down.
-     * 2) The entryFrame is NOT the last inline frame. Pop the frame.
-     *
-     * In both cases, we hijack the stub to return to the force-return
-     * trampoline. This trampoline simulates the frame-popping portion of
-     * emitReturn (except without the benefit of the FrameState) and will
-     * produce the necessary register state to return to the caller.
-     */
-
-  restart:
-    /* Step 1. Finish frames created after the entry frame. */
-    if (!FinishExcessFrames(f, entryFrame))
-        THROWV(NULL);
-
-    /* IMacros are guaranteed to have been removed by now. */
-    JS_ASSERT(f.fp() == entryFrame);
-    JS_ASSERT(!entryFrame->hasImacropc());
-
-    /* Step 2. If entryFrame is done, use a special path to return to EnterMethodJIT(). */
-    if (FrameIsFinished(cx)) {
-        if (!HandleFinishedFrame(f, entryFrame))
-            THROWV(NULL);
-        *f.returnAddressLocation() = cx->jaegerCompartment()->forceReturnFromFastCall();
-        return NULL;
-    }
-
-    /* Step 3. If entryFrame is at a safe point, just leave. */
-    if (void *ncode = AtSafePoint(cx))
-        return ncode;
-
-    /* Step 4. Do a partial interp, then restart the whole process. */
-    if (!PartialInterpret(f)) {
-        if (!HandleErrorInExcessFrame(f, entryFrame))
-            THROWV(NULL);
-    }
-
-    goto restart;
-}
-
-#endif /* JS_TRACER */
-
-#if defined JS_TRACER
-# if defined JS_MONOIC
-void *JS_FASTCALL
-stubs::InvokeTracer(VMFrame &f, ic::TraceICInfo *ic)
-{
-    return RunTracer(f, *ic);
-}
-
-# else
-
-void *JS_FASTCALL
-stubs::InvokeTracer(VMFrame &f)
-{
-    return RunTracer(f);
-}
-# endif /* JS_MONOIC */
-#endif /* JS_TRACER */
-
 /* :XXX: common out with identical copy in Compiler.cpp */
 #if defined(JS_METHODJIT_SPEW)
 static const char *OpcodeNames[] = {
 # define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) #name,
 # include "jsopcode.tbl"
 # undef OPDEF
 };
 #endif
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1086,26 +1086,20 @@ JITScript::inlineFrames() const
 }
 
 js::mjit::CallSite *
 JITScript::callSites() const
 {
     return (js::mjit::CallSite *)&inlineFrames()[nInlineFrames];
 }
 
-JSObject **
-JITScript::rootedObjects() const
-{
-    return (JSObject **)&callSites()[nCallSites];
-}
-
 char *
 JITScript::commonSectionLimit() const
 {
-    return (char *)&rootedObjects()[nRootedObjects];
+    return (char *)&callSites()[nCallSites];
 }
 
 #ifdef JS_MONOIC
 ic::GetGlobalNameIC *
 JITScript::getGlobalNames() const
 {
     return (ic::GetGlobalNameIC *) commonSectionLimit();
 }
@@ -1124,26 +1118,20 @@ JITScript::callICs() const
 }
 
 ic::EqualityICInfo *
 JITScript::equalityICs() const
 {
     return (ic::EqualityICInfo *)&callICs()[nCallICs];
 }
 
-ic::TraceICInfo *
-JITScript::traceICs() const
-{
-    return (ic::TraceICInfo *)&equalityICs()[nEqualityICs];
-}
-
 char *
 JITScript::monoICSectionsLimit() const
 {
-    return (char *)&traceICs()[nTraceICs];
+    return (char *)&equalityICs()[nEqualityICs];
 }
 #else   // JS_MONOIC
 char *
 JITScript::monoICSectionsLimit() const
 {
     return commonSectionLimit();
 }
 #endif  // JS_MONOIC
@@ -1181,27 +1169,16 @@ JITScript::polyICSectionsLimit() const
 #endif  // JS_POLYIC
 
 template <typename T>
 static inline void Destroy(T &t)
 {
     t.~T();
 }
 
-void
-mjit::JITScript::purgeNativeCallStubs()
-{
-    for (unsigned i = 0; i < nativeCallStubs.length(); i++) {
-        JSC::ExecutablePool *pool = nativeCallStubs[i].pool;
-        if (pool)
-            pool->release();
-    }
-    nativeCallStubs.clear();
-}
-
 mjit::JITScript::~JITScript()
 {
     code.release();
 
     if (pcLengths)
         Foreground::free_(pcLengths);
 
 #if defined JS_POLYIC
@@ -1222,17 +1199,21 @@ mjit::JITScript::~JITScript()
 
     for (JSC::ExecutablePool **pExecPool = execPools.begin();
          pExecPool != execPools.end();
          ++pExecPool)
     {
         (*pExecPool)->release();
     }
 
-    purgeNativeCallStubs();
+    for (unsigned i = 0; i < nativeCallStubs.length(); i++) {
+        JSC::ExecutablePool *pool = nativeCallStubs[i].pool;
+        if (pool)
+            pool->release();
+    }
 
     ic::CallICInfo *callICs_ = callICs();
     for (uint32 i = 0; i < nCallICs; i++) {
         callICs_[i].releasePools();
         if (callICs_[i].fastGuardedObject)
             callICs_[i].purgeGuardedObject();
     }
 
@@ -1267,23 +1248,21 @@ size_t
 mjit::JITScript::scriptDataSize(JSUsableSizeFun usf)
 {
     size_t usable = usf ? usf(this) : 0;
     return usable ? usable :
         sizeof(JITScript) +
         sizeof(NativeMapEntry) * nNmapPairs +
         sizeof(InlineFrame) * nInlineFrames +
         sizeof(CallSite) * nCallSites +
-        sizeof(JSObject *) * nRootedObjects +
 #if defined JS_MONOIC
         sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
         sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +
         sizeof(ic::CallICInfo) * nCallICs +
         sizeof(ic::EqualityICInfo) * nEqualityICs +
-        sizeof(ic::TraceICInfo) * nTraceICs +
 #endif
 #if defined JS_POLYIC
         sizeof(ic::PICInfo) * nPICs +
         sizeof(ic::GetElementIC) * nGetElems +
         sizeof(ic::SetElementIC) * nSetElems +
 #endif
         0;
 }
@@ -1408,25 +1387,9 @@ JITScript::nativeToPC(void *returnAddres
 }
 
 jsbytecode *
 mjit::NativeToPC(JITScript *jit, void *ncode, mjit::CallSite **pinline)
 {
     return jit->nativeToPC(ncode, pinline);
 }
 
-void
-JITScript::trace(JSTracer *trc)
-{
-    /*
-     * MICs and PICs attached to the JITScript are weak references, and either
-     * entirely purged or selectively purged on each GC. We do, however, need
-     * to maintain references to any scripts whose code was inlined into this.
-     */
-    InlineFrame *inlineFrames_ = inlineFrames();
-    for (unsigned i = 0; i < nInlineFrames; i++)
-        MarkObject(trc, *inlineFrames_[i].fun, "jitscript_fun");
-
-    for (uint32 i = 0; i < nRootedObjects; ++i)
-        MarkObject(trc, *rootedObjects()[i], "mjit rooted object");
-}
-
 /* static */ const double mjit::Assembler::oneDouble = 1.0;
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -495,17 +495,16 @@ namespace ic {
     struct PICInfo;
     struct GetElementIC;
     struct SetElementIC;
 # endif
 # if defined JS_MONOIC
     struct GetGlobalNameIC;
     struct SetGlobalNameIC;
     struct EqualityICInfo;
-    struct TraceICInfo;
     struct CallICInfo;
 # endif
 }
 }
 
 typedef void (JS_FASTCALL *VoidStub)(VMFrame &);
 typedef void (JS_FASTCALL *VoidVpStub)(VMFrame &, Value *);
 typedef void (JS_FASTCALL *VoidStubUInt32)(VMFrame &, uint32);
@@ -526,17 +525,16 @@ typedef void (JS_FASTCALL *VoidStubJSObj
 typedef void (JS_FASTCALL *VoidStubPC)(VMFrame &, jsbytecode *);
 typedef JSBool (JS_FASTCALL *BoolStubUInt32)(VMFrame &f, uint32);
 #ifdef JS_MONOIC
 typedef void (JS_FASTCALL *VoidStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
 typedef void * (JS_FASTCALL *VoidPtrStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
 typedef void (JS_FASTCALL *VoidStubGetGlobal)(VMFrame &, js::mjit::ic::GetGlobalNameIC *);
 typedef void (JS_FASTCALL *VoidStubSetGlobal)(VMFrame &, js::mjit::ic::SetGlobalNameIC *);
 typedef JSBool (JS_FASTCALL *BoolStubEqualityIC)(VMFrame &, js::mjit::ic::EqualityICInfo *);
-typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceICInfo *);
 #endif
 #ifdef JS_POLYIC
 typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *);
 typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *);
 typedef void (JS_FASTCALL *VoidStubSetElemIC)(VMFrame &f, js::mjit::ic::SetElementIC *);
 #endif
 
 namespace mjit {
@@ -600,23 +598,21 @@ struct JITScript {
      * Therefore, do not change the section ordering in finishThisUp() without
      * changing nMICs() et al as well.
      */
     uint32          nNmapPairs:31;      /* The NativeMapEntrys are sorted by .bcOff.
                                            .ncode values may not be NULL. */
     bool            singleStepMode:1;   /* compiled in "single step mode" */
     uint32          nInlineFrames;
     uint32          nCallSites;
-    uint32          nRootedObjects;
 #ifdef JS_MONOIC
     uint32          nGetGlobalNames;
     uint32          nSetGlobalNames;
     uint32          nCallICs;
     uint32          nEqualityICs;
-    uint32          nTraceICs;
 #endif
 #ifdef JS_POLYIC
     uint32          nGetElems;
     uint32          nSetElems;
     uint32          nPICs;
 #endif
 
 #ifdef JS_MONOIC
@@ -638,45 +634,37 @@ struct JITScript {
 #endif
 
     // Additional ExecutablePools for native call and getter stubs.
     Vector<NativeCallStub, 0, SystemAllocPolicy> nativeCallStubs;
 
     NativeMapEntry *nmap() const;
     js::mjit::InlineFrame *inlineFrames() const;
     js::mjit::CallSite *callSites() const;
-    JSObject **rootedObjects() const;
 #ifdef JS_MONOIC
     ic::GetGlobalNameIC *getGlobalNames() const;
     ic::SetGlobalNameIC *setGlobalNames() const;
     ic::CallICInfo *callICs() const;
     ic::EqualityICInfo *equalityICs() const;
-    ic::TraceICInfo *traceICs() const;
 #endif
 #ifdef JS_POLYIC
     ic::GetElementIC *getElems() const;
     ic::SetElementIC *setElems() const;
     ic::PICInfo     *pics() const;
 #endif
 
     ~JITScript();
 
     bool isValidCode(void *ptr) {
         char *jitcode = (char *)code.m_code.executableAddress();
         char *jcheck = (char *)ptr;
         return jcheck >= jitcode && jcheck < jitcode + code.m_size;
     }
 
     void nukeScriptDependentICs();
-    void sweepCallICs(JSContext *cx, bool purgeAll);
-    void purgeMICs();
-    void purgePICs();
-    void purgeNativeCallStubs();
-
-    void trace(JSTracer *trc);
 
     /* |usf| can be NULL here, in which case the fallback size computation will be used. */
     size_t scriptDataSize(JSUsableSizeFun usf);
 
     jsbytecode *nativeToPC(void *returnAddress, CallSite **pinline) const;
 
   private:
     /* Helpers used to navigate the variable-length sections. */
@@ -761,23 +749,16 @@ struct CallSite
         this->rejoin = rejoin;
     }
 
     bool isTrap() const {
         return rejoin == REJOIN_TRAP;
     }
 };
 
-/*
- * Re-enables a tracepoint in the method JIT. When full is true, we
- * also reset the iteration counter.
- */
-void
-ResetTraceHint(JSScript *script, jsbytecode *pc, uint16_t index, bool full);
-
 uintN
 GetCallTargetCount(JSScript *script, jsbytecode *pc);
 
 void
 DumpAllProfiles(JSContext *cx);
 
 inline void * bsearch_nmap(NativeMapEntry *nmap, size_t nPairs, size_t bcOff)
 {
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -936,28 +936,37 @@ class CallCompiler : public BaseCompiler
 
         RecompilationMonitor monitor(cx);
 
         if (!CallJSNative(cx, fun->u.n.native, args))
             THROWV(true);
 
         types::TypeScript::Monitor(f.cx, f.script(), f.pc(), args.rval());
 
+        /*
+         * Native stubs are not generated for inline frames. The overhead of
+         * bailing out from the IC is far greater than the time saved by
+         * inlining the parent frame in the first place, so mark the immediate
+         * caller as uninlineable.
+         */
+        if (f.script()->hasFunction) {
+            f.script()->uninlineable = true;
+            MarkTypeObjectFlags(cx, f.script()->function(), types::OBJECT_FLAG_UNINLINEABLE);
+        }
+
         /* Don't touch the IC if the call triggered a recompilation. */
         if (monitor.recompiled())
             return true;
 
+        JS_ASSERT(!f.regs.inlined());
+
         /* Right now, take slow-path for IC misses or multiple stubs. */
         if (ic.fastGuardedNative || ic.hasJsFunCheck)
             return true;
 
-        /* Don't generate native MICs within inlined frames, we can't recompile them yet. */
-        if (f.regs.inlined())
-            return true;
-
         /* Native MIC needs to warm up first. */
         if (!ic.hit) {
             ic.hit = true;
             return true;
         }
 
         /* Generate fast-path for calling this native. */
         Assembler masm;
@@ -1372,173 +1381,10 @@ JITScript::resetArgsCheck()
 {
     argsCheckPool->release();
     argsCheckPool = NULL;
 
     Repatcher repatch(this);
     repatch.relink(argsCheckJump, argsCheckStub);
 }
 
-void
-JITScript::purgeMICs()
-{
-    if (!nGetGlobalNames || !nSetGlobalNames)
-        return;
-
-    Repatcher repatch(this);
-
-    ic::GetGlobalNameIC *getGlobalNames_ = getGlobalNames();
-    for (uint32 i = 0; i < nGetGlobalNames; i++) {
-        ic::GetGlobalNameIC &ic = getGlobalNames_[i];
-        JSC::CodeLocationDataLabel32 label = ic.fastPathStart.dataLabel32AtOffset(ic.shapeOffset);
-        repatch.repatch(label, int(INVALID_SHAPE));
-    }
-
-    ic::SetGlobalNameIC *setGlobalNames_ = setGlobalNames();
-    for (uint32 i = 0; i < nSetGlobalNames; i++) {
-        ic::SetGlobalNameIC &ic = setGlobalNames_[i];
-        ic.patchInlineShapeGuard(repatch, int32(INVALID_SHAPE));
-
-        if (ic.hasExtraStub) {
-            Repatcher repatcher(ic.extraStub);
-            ic.patchExtraShapeGuard(repatcher, int32(INVALID_SHAPE));
-        }
-    }
-}
-
-void
-ic::PurgeMICs(JSContext *cx, JSScript *script)
-{
-    /* MICs are purged during GC to handle changing shapes. */
-    JS_ASSERT(cx->runtime->gcRegenShapes);
-
-    if (script->jitNormal)
-        script->jitNormal->purgeMICs();
-    if (script->jitCtor)
-        script->jitCtor->purgeMICs();
-}
-
-void
-JITScript::nukeScriptDependentICs()
-{
-    if (!nCallICs)
-        return;
-
-    Repatcher repatcher(this);
-
-    ic::CallICInfo *callICs_ = callICs();
-    for (uint32 i = 0; i < nCallICs; i++) {
-        ic::CallICInfo &ic = callICs_[i];
-        if (!ic.fastGuardedObject)
-            continue;
-        repatcher.repatch(ic.funGuard, NULL);
-        repatcher.relink(ic.funJump, ic.slowPathStart);
-        ic.releasePool(CallICInfo::Pool_ClosureStub);
-        ic.fastGuardedObject = NULL;
-        ic.hasJsFunCheck = false;
-    }
-}
-
-void
-JITScript::sweepCallICs(JSContext *cx, bool purgeAll)
-{
-    Repatcher repatcher(this);
-
-    /*
-     * If purgeAll is set, purge stubs in the script except those covered by PurgePICs
-     * (which is always called during GC). We want to remove references which can keep
-     * alive pools that we are trying to destroy (see JSCompartment::sweep).
-     */
-
-    ic::CallICInfo *callICs_ = callICs();
-    for (uint32 i = 0; i < nCallICs; i++) {
-        ic::CallICInfo &ic = callICs_[i];
-
-        /*
-         * If the object is unreachable, we're guaranteed not to be currently
-         * executing a stub generated by a guard on that object. This lets us
-         * precisely GC call ICs while keeping the identity guard safe.
-         */
-        bool fastFunDead = ic.fastGuardedObject &&
-            (purgeAll || IsAboutToBeFinalized(cx, ic.fastGuardedObject));
-        bool hasNative = ic.fastGuardedNative != NULL;
-
-        /*
-         * There are three conditions where we need to relink:
-         * (1) purgeAll is true.
-         * (2) There is a native stub. These have a NativeCallStub, which will
-         *     all be released if the compartment has no code on the stack.
-         * (3) The fastFun is dead *and* there is a closure stub.
-         *
-         * Note although both objects can be non-NULL, there can only be one
-         * of [closure, native] stub per call IC.
-         */
-        if (purgeAll || hasNative || (fastFunDead && ic.hasJsFunCheck)) {
-            repatcher.relink(ic.funJump, ic.slowPathStart);
-            ic.hit = false;
-        }
-
-        if (fastFunDead) {
-            repatcher.repatch(ic.funGuard, NULL);
-            ic.purgeGuardedObject();
-        }
-
-        if (hasNative)
-            ic.fastGuardedNative = NULL;
-
-        if (purgeAll) {
-            ic.releasePool(CallICInfo::Pool_ScriptStub);
-            JSC::CodeLocationJump oolJump = ic.slowPathStart.jumpAtOffset(ic.oolJumpOffset);
-            JSC::CodeLocationLabel icCall = ic.slowPathStart.labelAtOffset(ic.icCallOffset);
-            repatcher.relink(oolJump, icCall);
-        }
-    }
-
-    /* The arguments type check IC can refer to type objects which might be swept. */
-    if (argsCheckPool)
-        resetArgsCheck();
-
-    if (purgeAll) {
-        /* Purge ICs generating stubs into execPools. */
-        uint32 released = 0;
-
-        ic::EqualityICInfo *equalityICs_ = equalityICs();
-        for (uint32 i = 0; i < nEqualityICs; i++) {
-            ic::EqualityICInfo &ic = equalityICs_[i];
-            if (!ic.generated)
-                continue;
-
-            JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, ic::Equality));
-            repatcher.relink(ic.stubCall, fptr);
-            repatcher.relink(ic.jumpToStub, ic.stubEntry);
-
-            ic.generated = false;
-            released++;
-        }
-
-        ic::SetGlobalNameIC *setGlobalNames_ = setGlobalNames();
-        for (uint32 i = 0; i < nSetGlobalNames; i ++) {
-            ic::SetGlobalNameIC &ic = setGlobalNames_[i];
-            if (!ic.hasExtraStub)
-                continue;
-            repatcher.relink(ic.fastPathStart.jumpAtOffset(ic.inlineShapeJump), ic.slowPathStart);
-            ic.hasExtraStub = false;
-            released++;
-        }
-
-        JS_ASSERT(released == execPools.length());
-        for (uint32 i = 0; i < released; i++)
-            execPools[i]->release();
-        execPools.clear();
-    }
-}
-
-void
-ic::SweepCallICs(JSContext *cx, JSScript *script, bool purgeAll)
-{
-    if (script->jitNormal)
-        script->jitNormal->sweepCallICs(cx, purgeAll);
-    if (script->jitCtor)
-        script->jitCtor->sweepCallICs(cx, purgeAll);
-}
-
 #endif /* JS_MONOIC */
 
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -155,40 +155,16 @@ struct SetGlobalNameIC : public GlobalNa
 
     /* SET only. */
     ValueRemat vr;              /* RHS value. */
 
     void patchInlineShapeGuard(Repatcher &repatcher, int32 shape);
     void patchExtraShapeGuard(Repatcher &repatcher, int32 shape);
 };
 
-struct TraceICInfo {
-    TraceICInfo() {}
-
-    JSC::CodeLocationLabel stubEntry;
-    JSC::CodeLocationLabel fastTarget;
-    JSC::CodeLocationLabel slowTarget;
-    JSC::CodeLocationJump traceHint;
-    JSC::CodeLocationJump slowTraceHint;
-#ifdef DEBUG
-    jsbytecode *jumpTargetPC;
-#endif
-    
-    /* This data is used by the tracing JIT. */
-    void *traceData;
-    uintN traceEpoch;
-    uint32 loopCounter;
-    uint32 loopCounterStart;
-
-    bool initialized : 1;
-    bool hasSlowTraceHint : 1;
-};
-
-static const uint16 BAD_TRACEIC_INDEX = (uint16)0xffff;
-
 void JS_FASTCALL GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic);
 void JS_FASTCALL SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic);
 
 struct EqualityICInfo {
     typedef JSC::MacroAssembler::RegisterID RegisterID;
 
     JSC::CodeLocationLabel stubEntry;
     JSC::CodeLocationCall stubCall;
@@ -296,17 +272,14 @@ struct CallICInfo {
 void * JS_FASTCALL New(VMFrame &f, ic::CallICInfo *ic);
 void * JS_FASTCALL Call(VMFrame &f, ic::CallICInfo *ic);
 void * JS_FASTCALL NativeNew(VMFrame &f, ic::CallICInfo *ic);
 void * JS_FASTCALL NativeCall(VMFrame &f, ic::CallICInfo *ic);
 JSBool JS_FASTCALL SplatApplyArgs(VMFrame &f);
 
 void GenerateArgumentCheckStub(VMFrame &f);
 
-void PurgeMICs(JSContext *cx, JSScript *script);
-void SweepCallICs(JSContext *cx, JSScript *script, bool purgeAll);
-
 } /* namespace ic */
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jsjaeger_mono_ic_h__ */
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -809,18 +809,27 @@ struct GetPropertyHelper {
                     return ic.disable(cx, "method valued shape");
             } else {
                 if (shape->hasGetterValue())
                     return ic.disable(cx, "getter value shape");
                 if (shape->hasSlot() && holder != obj)
                     return ic.disable(cx, "slotful getter hook through prototype");
                 if (!ic.canCallHook)
                     return ic.disable(cx, "can't call getter hook");
-                if (f.regs.inlined())
-                    return ic.disable(cx, "hook called from inline frame");
+                if (f.regs.inlined()) {
+                    /*
+                     * As with native stubs, getter hook stubs can't be
+                     * generated for inline frames. Mark the inner function
+                     * as uninlineable and recompile.
+                     */
+                    f.script()->uninlineable = true;
+                    MarkTypeObjectFlags(cx, f.script()->function(),
+                                        types::OBJECT_FLAG_UNINLINEABLE);
+                    return Lookup_Uncacheable;
+                }
             }
         } else if (!shape->hasSlot()) {
             return ic.disable(cx, "no slot");
         }
 
         return Lookup_Cacheable;
     }
 
@@ -3228,62 +3237,10 @@ ic::SetElement(VMFrame &f, ic::SetElemen
     }
 
     stubs::SetElem<strict>(f);
 }
 
 template void JS_FASTCALL ic::SetElement<true>(VMFrame &f, SetElementIC *ic);
 template void JS_FASTCALL ic::SetElement<false>(VMFrame &f, SetElementIC *ic);
 
-void
-JITScript::purgePICs()
-{
-    if (!nPICs && !nGetElems && !nSetElems)
-        return;
-
-    Repatcher repatcher(this);
-
-    ic::PICInfo *pics_ = pics();
-    for (uint32 i = 0; i < nPICs; i++) {
-        ic::PICInfo &pic = pics_[i];
-        switch (pic.kind) {
-          case ic::PICInfo::SET:
-          case ic::PICInfo::SETMETHOD:
-            SetPropCompiler::reset(repatcher, pic);
-            break;
-          case ic::PICInfo::NAME:
-          case ic::PICInfo::XNAME:
-          case ic::PICInfo::CALLNAME:
-            ScopeNameCompiler::reset(repatcher, pic);
-            break;
-          case ic::PICInfo::BIND:
-            BindNameCompiler::reset(repatcher, pic);
-            break;
-          case ic::PICInfo::CALL: /* fall-through */
-          case ic::PICInfo::GET:
-            GetPropCompiler::reset(repatcher, pic);
-            break;
-          default:
-            JS_NOT_REACHED("Unhandled PIC kind");
-            break;
-        }
-        pic.reset();
-    }
-
-    ic::GetElementIC *getElems_ = getElems();
-    ic::SetElementIC *setElems_ = setElems();
-    for (uint32 i = 0; i < nGetElems; i++)
-        getElems_[i].purge(repatcher);
-    for (uint32 i = 0; i < nSetElems; i++)
-        setElems_[i].purge(repatcher);
-}
-
-void
-ic::PurgePICs(JSContext *cx, JSScript *script)
-{
-    if (script->jitNormal)
-        script->jitNormal->purgePICs();
-    if (script->jitCtor)
-        script->jitCtor->purgePICs();
-}
-
 #endif /* JS_POLYIC */
 
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -55,18 +55,16 @@
 namespace js {
 namespace mjit {
 namespace ic {
 
 /* Maximum number of stubs for a given callsite. */
 static const uint32 MAX_PIC_STUBS = 16;
 static const uint32 MAX_GETELEM_IC_STUBS = 17;
 
-void PurgePICs(JSContext *cx);
-
 enum LookupStatus {
     Lookup_Error = 0,
     Lookup_Uncacheable,
     Lookup_Cacheable
 };
 
 struct BaseIC : public MacroAssemblerTypedefs {
     BaseIC() { }
@@ -549,17 +547,16 @@ struct PICInfo : public BasePolyIC {
     void reset() {
         BasePolyIC::reset();
         inlinePathPatched = false;
         shapeRegHasBaseShape = true;
     }
 };
 
 #ifdef JS_POLYIC
-void PurgePICs(JSContext *cx, JSScript *script);
 void JS_FASTCALL GetProp(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL GetPropNoCache(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL SetProp(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL CallProp(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL Name(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL CallName(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL XName(VMFrame &f, ic::PICInfo *);
 void JS_FASTCALL BindName(VMFrame &f, ic::PICInfo *);
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -108,21 +108,16 @@ struct UncachedCallResult {
  * These functions either execute the function, return a native code
  * pointer that can be used to call the function, or throw.
  */
 void UncachedCallHelper(VMFrame &f, uint32 argc, bool lowered, UncachedCallResult *ucr);
 void UncachedNewHelper(VMFrame &f, uint32 argc, UncachedCallResult *ucr);
 
 void JS_FASTCALL CreateThis(VMFrame &f, JSObject *proto);
 void JS_FASTCALL Throw(VMFrame &f);
-#if JS_MONOIC
-void * JS_FASTCALL InvokeTracer(VMFrame &f, ic::TraceICInfo *tic);
-#else
-void * JS_FASTCALL InvokeTracer(VMFrame &f);
-#endif
 
 void * JS_FASTCALL LookupSwitch(VMFrame &f, jsbytecode *pc);
 void * JS_FASTCALL TableSwitch(VMFrame &f, jsbytecode *origPc);
 
 void JS_FASTCALL BindName(VMFrame &f);
 void JS_FASTCALL BindNameNoCache(VMFrame &f, JSAtom *atom);
 JSObject * JS_FASTCALL BindGlobalName(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL SetName(VMFrame &f, JSAtom *atom);
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1557,19 +1557,17 @@ ValueToScript(JSContext *cx, jsval v, JS
 {
     JSScript *script = NULL;
     JSFunction *fun = NULL;
 
     if (!JSVAL_IS_PRIMITIVE(v)) {
         JSObject *obj = JSVAL_TO_OBJECT(v);
         JSClass *clasp = JS_GET_CLASS(cx, obj);
 
-        if (clasp == Jsvalify(&ScriptClass)) {
-            script = (JSScript *) JS_GetPrivate(cx, obj);
-        } else if (clasp == Jsvalify(&GeneratorClass)) {
+        if (clasp == Jsvalify(&GeneratorClass)) {
             JSGenerator *gen = (JSGenerator *) JS_GetPrivate(cx, obj);
             fun = gen->floatingFrame()->fun();
             script = fun->script();
         }
     }
 
     if (!script) {
         fun = JS_ValueToFunction(cx, v);
@@ -1619,18 +1617,17 @@ GetTrapArgs(JSContext *cx, uintN argc, j
     JSScript *script;
 
     *scriptp = JS_GetFrameScript(cx, JS_GetScriptedCaller(cx, NULL));
     *ip = 0;
     if (argc != 0) {
         v = argv[0];
         intarg = 0;
         if (!JSVAL_IS_PRIMITIVE(v) &&
-            (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass) ||
-             JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&ScriptClass))) {
+            JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == Jsvalify(&FunctionClass)) {
             script = ValueToScript(cx, v);
             if (!script)
                 return JS_FALSE;
             *scriptp = script;
             intarg++;
         }
         if (argc > intarg) {
             if (!JS_ValueToInt32(cx, argv[intarg], ip))
--- a/js/src/tests/ecma_5/extensions/jstests.list
+++ b/js/src/tests/ecma_5/extensions/jstests.list
@@ -21,16 +21,17 @@ script getOwnPropertyNames-__proto__.js
 script iterator-in-catch.js
 script JSON-string-replacer-overflow.js
 skip-if(!xulRuntime.shell) script legacy-JSON.js # needs parseLegacyJSON
 fails script nested-delete-name-in-evalcode.js # bug 604301, at a minimum
 script proxy-strict.js
 script regress-bug567606.js
 script regress-bug607284.js
 script regress-bug629723.js
+skip-if(!xulRuntime.shell) script strict-e4x-ban.js
 script strict-function-statements.js
 script strict-option-redeclared-parameter.js
 script string-literal-getter-setter-decompilation.js
 script String-methods-infinite-recursion.js
 script toLocaleString-infinite-recursion.js
 script toSource-infinite-recursion.js
 script uneval-strict-functions.js
 script watch-array-length.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/strict-e4x-ban.js
@@ -0,0 +1,52 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+assertEq(testLenientAndStrict("var o = {m:function(){}}; o.function::m()",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+assertEq(testLenientAndStrict("default xml namespace = 'foo'",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+assertEq(testLenientAndStrict("var x = <x/>",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+assertEq(testLenientAndStrict("var x = <x><p>42</p></x>",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+assertEq(testLenientAndStrict("var x = <x><p>42</p></x>; x.(p == 42)",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+assertEq(testLenientAndStrict("var x = <x><p>42</p></x>; x..p",
+                              parsesSuccessfully,
+                              parseRaisesException(SyntaxError)),
+         true);
+
+if (typeof this.options == "function") {
+    this.options('xml');
+
+    assertEq(testLenientAndStrict("var cdata = <![CDATA[bar]]>",
+                                  parsesSuccessfully,
+                                  parseRaisesException(SyntaxError)),
+             true);
+
+    assertEq(testLenientAndStrict("var comment = <!-- hi -->",
+                                  parsesSuccessfully,
+                                  parseRaisesException(SyntaxError)),
+             true);
+
+    this.options('xml');
+}
+
+reportCompare(true, true);
--- a/js/src/tests/js1_8_5/extensions/jstests.list
+++ b/js/src/tests/js1_8_5/extensions/jstests.list
@@ -53,8 +53,9 @@ script weakmap.js
 script regress-645160.js
 script regress-650753.js
 script regress-668438.js
 require-or(debugMode,skip) script regress-672804-1.js
 require-or(debugMode,skip) script regress-672804-2.js
 require-or(debugMode,skip) script regress-672804-3.js
 skip-if(!xulRuntime.shell) script regress-677589.js
 script regress-677924.js
+script regress-691746.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8_5/extensions/regress-691746.js
@@ -0,0 +1,11 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+var obj = {};
+try {
+    obj.watch(QName(), function () {});
+} catch (exc) {
+}
+gc();
+
+reportCompare(0, 0, 'ok');
--- a/js/src/vm/CallObject.h
+++ b/js/src/vm/CallObject.h
@@ -51,26 +51,26 @@ class CallObject : public ::JSObject
      * private               - the stack frame corresponding to the Call object
      *                         until js_PutCallObject or its on-trace analog
      *                         is called, null thereafter
      * JSSLOT_CALL_CALLEE    - callee function for the stack frame, or null if
      *                         the stack frame is for strict mode eval code
      * JSSLOT_CALL_ARGUMENTS - arguments object for non-strict mode eval stack
      *                         frames (not valid for strict mode eval frames)
      */
-    static const uint32 CALLEE_SLOT = 0;
-    static const uint32 ARGUMENTS_SLOT = 1;
+    static const uintN CALLEE_SLOT = 0;
+    static const uintN ARGUMENTS_SLOT = 1;
 
-public:
+  public:
+    static const uintN RESERVED_SLOTS = 2;
+
     /* Create a CallObject for the given callee function. */
     static CallObject *
     create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObject *callee);
 
-    static const uint32 RESERVED_SLOTS = 2;
-
     /* True if this is for a strict mode eval frame or for a function call. */
     inline bool isForEval() const;
 
     /* The stack frame for this CallObject, if the frame is still active. */
     inline js::StackFrame *maybeStackFrame() const;
     inline void setStackFrame(js::StackFrame *frame);
 
     /*
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -83,17 +83,16 @@ enum {
     JSSLOT_DEBUGOBJECT_OWNER,
     JSSLOT_DEBUGOBJECT_COUNT
 };
 
 extern Class DebuggerScript_class;
 
 enum {
     JSSLOT_DEBUGSCRIPT_OWNER,
-    JSSLOT_DEBUGSCRIPT_HOLDER,  /* PrivateValue, cross-compartment pointer */
     JSSLOT_DEBUGSCRIPT_COUNT
 };
 
 
 /*** Utils ***************************************************************************************/
 
 bool
 ReportMoreArgsNeeded(JSContext *cx, const char *name, uintN required)
@@ -120,53 +119,53 @@ ReportObjectRequired(JSContext *cx)
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
     return false;
 }
 
 
 /*** Breakpoints *********************************************************************************/
 
 BreakpointSite::BreakpointSite(JSScript *script, jsbytecode *pc)
-  : script(script), pc(pc), realOpcode(JSOp(*pc)), scriptObject(NULL), enabledCount(0),
+  : script(script), pc(pc), realOpcode(JSOp(*pc)), scriptGlobal(NULL), enabledCount(0),
     trapHandler(NULL), trapClosure(UndefinedValue())
 {
     JS_ASSERT(realOpcode != JSOP_TRAP);
     JS_INIT_CLIST(&breakpoints);
 }
 
 /*
  * Precondition: script is live, meaning either it is a non-held script that is
  * on the stack or a held script that hasn't been GC'd.
  */
-static JSObject *
-ScriptScope(JSContext *cx, JSScript *script, JSObject *holder)
+static GlobalObject *
+ScriptGlobal(JSContext *cx, JSScript *script, GlobalObject *scriptGlobal)
 {
-    if (holder)
-        return holder;
+    if (scriptGlobal)
+        return scriptGlobal;
 
     /*
      * The referent is a non-held script. There is no direct reference from
      * script to the scope, so find it on the stack.
      */
     for (AllFramesIter i(cx->stack.space()); ; ++i) {
         JS_ASSERT(!i.done());
         if (i.fp()->maybeScript() == script)
-            return &i.fp()->scopeChain();
+            return i.fp()->scopeChain().getGlobal();
     }
-    JS_NOT_REACHED("ScriptScope: live non-held script not on stack");
+    JS_NOT_REACHED("ScriptGlobal: live non-held script not on stack");
 }
 
 bool
 BreakpointSite::recompile(JSContext *cx, bool forTrap)
 {
 #ifdef JS_METHODJIT
     if (script->hasJITCode()) {
         Maybe<AutoCompartment> ac;
         if (!forTrap) {
-            ac.construct(cx, ScriptScope(cx, script, scriptObject));
+            ac.construct(cx, ScriptGlobal(cx, script, scriptGlobal));
             if (!ac.ref().enter())
                 return false;
         }
         js::mjit::Recompiler recompiler(cx, script);
         recompiler.recompile();
     }
 #endif
     return true;
@@ -728,27 +727,27 @@ Debugger::fireEnterFrame(JSContext *cx)
         return;
     }
     Value rv;
     if (!Invoke(cx, ObjectValue(*object), ObjectValue(*hook), 1, argv, &rv))
         handleUncaughtException(ac, NULL, true);
 }
 
 void
-Debugger::fireNewScript(JSContext *cx, JSScript *script, JSObject *obj)
+Debugger::fireNewScript(JSContext *cx, JSScript *script)
 {
     JSObject *hook = getHook(OnNewScript);
     JS_ASSERT(hook);
     JS_ASSERT(hook->isCallable());
 
     AutoCompartment ac(cx, object);
     if (!ac.enter())
         return;
 
-    JSObject *dsobj = wrapScript(cx, script, obj);
+    JSObject *dsobj = wrapScript(cx, script);
     if (!dsobj) {
         handleUncaughtException(ac, NULL, false);
         return;
     }
 
     Value argv[1];
     argv[0].setObject(*dsobj);
     Value rv;
@@ -811,18 +810,17 @@ AddNewScriptRecipients(GlobalObject::Deb
         {
             return false;
         }
     }
     return true;
 }
 
 void
-Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
-                              GlobalObject *compileAndGoGlobal)
+Debugger::slowPathOnNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
 {
     JS_ASSERT(script->compileAndGo == !!compileAndGoGlobal);
 
     /*
      * Build the list of recipients. For compile-and-go scripts, this is the
      * same as the generic Debugger::dispatchHook code, but non-compile-and-go
      * scripts are not tied to particular globals. We deliver them to every
      * debugger observing any global in the script's compartment.
@@ -844,17 +842,17 @@ Debugger::slowPathOnNewScript(JSContext 
     /*
      * Deliver the event to each debugger, checking again as in
      * Debugger::dispatchHook.
      */
     for (Value *p = triggered.begin(); p != triggered.end(); p++) {
         Debugger *dbg = Debugger::fromJSObject(&p->toObject());
         if ((!compileAndGoGlobal || dbg->debuggees.has(compileAndGoGlobal)) &&
             dbg->enabled && dbg->getHook(OnNewScript)) {
-            dbg->fireNewScript(cx, script, obj);
+            dbg->fireNewScript(cx, script);
         }
     }
 }
 
 JSTrapStatus
 Debugger::onTrap(JSContext *cx, Value *vp)
 {
     StackFrame *fp = cx->fp();
@@ -1777,38 +1775,25 @@ JSFunctionSpec Debugger::methods[] = {
 
 
 /*** Debugger.Script *****************************************************************************/
 
 static inline JSScript *
 GetScriptReferent(JSObject *obj)
 {
     JS_ASSERT(obj->getClass() == &DebuggerScript_class);
-    return (JSScript *) obj->getPrivate();
-}
-
-static inline JSObject *
-GetScriptHolder(JSObject *obj)
-{
-    JS_ASSERT(obj->getClass() == &DebuggerScript_class);
-    Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
-    return (JSObject *) v.toPrivate();
+    return static_cast<JSScript *>(obj->getPrivate());
 }
 
 static void
 DebuggerScript_trace(JSTracer *trc, JSObject *obj)
 {
     if (!trc->context->runtime->gcCurrentCompartment) {
         if (JSScript *script = GetScriptReferent(obj))
             MarkScript(trc, script, "Debugger.Script referent");
-        Value v = obj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER);
-        if (!v.isUndefined()) {
-            if (JSObject *obj = (JSObject *) v.toPrivate())
-                MarkObject(trc, *obj, "Debugger.Script referent holder");
-        }
     }
 }
 
 Class DebuggerScript_class = {
     "Script", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGSCRIPT_COUNT),
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
     NULL,                 /* reserved0   */
@@ -1816,83 +1801,73 @@ Class DebuggerScript_class = {
     NULL,                 /* call        */
     NULL,                 /* construct   */
     NULL,                 /* xdrObject   */
     NULL,                 /* hasInstance */
     DebuggerScript_trace
 };
 
 JSObject *
-Debugger::newDebuggerScript(JSContext *cx, JSScript *script, JSObject *holder)
+Debugger::newDebuggerScript(JSContext *cx, JSScript *script)
 {
     assertSameCompartment(cx, object);
 
     JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_SCRIPT_PROTO).toObject();
     JS_ASSERT(proto);
     JSObject *scriptobj = NewNonFunction<WithProto::Given>(cx, &DebuggerScript_class, proto, NULL);
     if (!scriptobj || !scriptobj->ensureClassReservedSlots(cx))
         return NULL;
     scriptobj->setPrivate(script);
     scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_OWNER, ObjectValue(*object));
-    scriptobj->setReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER, PrivateValue(holder));
 
     return scriptobj;
 }
 
 JSObject *
-Debugger::wrapScript(JSContext *cx, JSScript *script, JSObject *obj)
+Debugger::wrapScript(JSContext *cx, JSScript *script)
 {
     assertSameCompartment(cx, object);
     JS_ASSERT(cx->compartment != script->compartment());
-    JS_ASSERT_IF(obj, script->compartment() == obj->compartment());
-
     CellWeakMap::AddPtr p = scripts.lookupForAdd(script);
     if (!p) {
-        JSObject *scriptobj = newDebuggerScript(cx, script, obj);
+        JSObject *scriptobj = newDebuggerScript(cx, script);
 
         /* The allocation may have caused a GC, which can remove table entries. */
         if (!scriptobj || !scripts.relookupOrAdd(p, script, scriptobj))
             return NULL;
     }
 
     JS_ASSERT(GetScriptReferent(p->value) == script);
     return p->value;
 }
 
-JSObject *
-Debugger::wrapFunctionScript(JSContext *cx, JSFunction *fun)
-{
-    return wrapScript(cx, fun->script(), fun);
-}
-
 static JSObject *
 DebuggerScript_check(JSContext *cx, const Value &v, const char *clsname, const char *fnname)
 {
     if (!v.isObject()) {
         ReportObjectRequired(cx);
         return NULL;
     }
     JSObject *thisobj = &v.toObject();
     if (thisobj->getClass() != &DebuggerScript_class) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
                              clsname, fnname, thisobj->getClass()->name);
         return NULL;
     }
 
     /*
      * Check for Debugger.Script.prototype, which is of class DebuggerScript_class
-     * but whose holding object is undefined.
+     * but whose script is null.
      */
-    if (thisobj->getReservedSlot(JSSLOT_DEBUGSCRIPT_HOLDER).isUndefined()) {
+    if (!GetScriptReferent(thisobj)) {
         JS_ASSERT(!GetScriptReferent(thisobj));
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
                              clsname, fnname, "prototype object");
         return NULL;
     }
-    JS_ASSERT(GetScriptReferent(thisobj));
 
     return thisobj;
 }
 
 static JSObject *
 DebuggerScript_checkThis(JSContext *cx, const CallArgs &args, const char *fnname)
 {
     return DebuggerScript_check(cx, args.thisv(), "Debugger.Script", fnname);
@@ -1949,17 +1924,18 @@ DebuggerScript_getChildScripts(JSContext
          * script->savedCallerFun indicates that this is a direct eval script
          * and the calling function is stored as script->objects()->vector[0].
          * It is not really a child script of this script, so skip it.
          */
         JSObjectArray *objects = script->objects();
         for (uint32 i = script->savedCallerFun ? 1 : 0; i < objects->length; i++) {
             JSObject *obj = objects->vector[i];
             if (obj->isFunction()) {
-                JSObject *s = dbg->wrapFunctionScript(cx, (JSFunction *) obj);
+                JSFunction *fun = static_cast<JSFunction *>(obj);
+                JSObject *s = dbg->wrapScript(cx, fun->script());
                 if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
                     return false;
             }
         }
     }
     args.rval().setObject(*result);
     return true;
 }
@@ -2252,33 +2228,33 @@ DebuggerScript_getLineOffsets(JSContext 
 
 static JSBool
 DebuggerScript_setBreakpoint(JSContext *cx, uintN argc, Value *vp)
 {
     REQUIRE_ARGC("Debugger.Script.setBreakpoint", 2);
     THIS_DEBUGSCRIPT_SCRIPT(cx, argc, vp, "setBreakpoint", args, obj, script);
     Debugger *dbg = Debugger::fromChildJSObject(obj);
 
-    JSObject *holder = GetScriptHolder(obj);
-    if (!dbg->observesScope(ScriptScope(cx, script, holder))) {
+    GlobalObject *scriptGlobal = script->getGlobalObjectOrNull();
+    if (!dbg->observesGlobal(ScriptGlobal(cx, script, scriptGlobal))) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_DEBUGGING);
         return false;
     }
 
     size_t offset;
     if (!ScriptOffset(cx, script, args[0], &offset))
         return false;
 
     JSObject *handler = NonNullObject(cx, args[1]);
     if (!handler)
         return false;
 
     JSCompartment *comp = script->compartment();
     jsbytecode *pc = script->code + offset;
-    BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, holder);
+    BreakpointSite *site = comp->getOrCreateBreakpointSite(cx, script, pc, scriptGlobal);
     if (!site)
         return false;
     if (site->inc(cx)) {
         if (cx->runtime->new_<Breakpoint>(dbg, site, handler)) {
             args.rval().setUndefined();
             return true;
         }
         site->dec(cx);
@@ -2623,28 +2599,27 @@ DebuggerFrame_getScript(JSContext *cx, u
 {
     THIS_FRAME(cx, argc, vp, "get script", args, thisobj, fp);
     Debugger *debug = Debugger::fromChildJSObject(thisobj);
 
     JSObject *scriptObject = NULL;
     if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
         JSFunction *callee = fp->callee().getFunctionPrivate();
         if (callee->isInterpreted()) {
-            scriptObject = debug->wrapFunctionScript(cx, callee);
+            scriptObject = debug->wrapScript(cx, callee->script());
             if (!scriptObject)
                 return false;
         }
     } else if (fp->isScriptFrame()) {
         /*
          * We got eval, JS_Evaluate*, or JS_ExecuteScript non-function script
          * frames.
          */
         JSScript *script = fp->script();
-        scriptObject = debug->wrapScript(cx, script,
-                                         script->isCachedEval ? NULL : script->u.object);
+        scriptObject = debug->wrapScript(cx, script);
         if (!scriptObject)
             return false;
     }
     args.rval().setObjectOrNull(scriptObject);
     return true;
 }
 
 static JSBool
@@ -2739,17 +2714,17 @@ EvaluateInScope(JSContext *cx, JSObject 
     /*
      * NB: This function breaks the assumption that the compiler can see all
      * calls and properly compute a static level. In order to get around this,
      * we use a static level that will cause us not to attempt to optimize
      * variable references made by this frame.
      */
     JSScript *script = BytecodeCompiler::compileScript(cx, scobj, fp,
                                                        fp->scopeChain().principals(cx),
-                                                       TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_OBJECT,
+                                                       TCF_COMPILE_N_GO | TCF_NEED_SCRIPT_GLOBAL,
                                                        chars, length, filename, lineno,
                                                        cx->findVersion(), NULL,
                                                        UpvarCookie::UPVAR_LEVEL_LIMIT);
 
     if (!script)
         return false;
 
     return ExecuteKernel(cx, script, *scobj, fp->thisValue(), EXECUTE_DEBUG, fp, rval);
@@ -3051,17 +3026,17 @@ DebuggerObject_getScript(JSContext *cx, 
 
     if (!obj->isFunction())
         return true;
 
     JSFunction *fun = obj->getFunctionPrivate();
     if (!fun->isInterpreted())
         return true;
 
-    JSObject *scriptObject = dbg->wrapFunctionScript(cx, fun);
+    JSObject *scriptObject = dbg->wrapScript(cx, fun->script());
     if (!scriptObject)
         return false;
 
     args.rval().setObject(*scriptObject);
     return true;
 }
 
 static JSBool
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -196,37 +196,35 @@ class Debugger {
     static JSPropertySpec properties[];
     static JSFunctionSpec methods[];
 
     JSObject *getHook(Hook hook) const;
     bool hasAnyLiveHooks(JSContext *cx) const;
 
     static void slowPathOnEnterFrame(JSContext *cx);
     static void slowPathOnLeaveFrame(JSContext *cx);
-    static void slowPathOnNewScript(JSContext *cx, JSScript *script, JSObject *obj,
+    static void slowPathOnNewScript(JSContext *cx, JSScript *script,
                                     GlobalObject *compileAndGoGlobal);
     static JSTrapStatus dispatchHook(JSContext *cx, js::Value *vp, Hook which);
 
     JSTrapStatus fireDebuggerStatement(JSContext *cx, Value *vp);
     JSTrapStatus fireExceptionUnwind(JSContext *cx, Value *vp);
     void fireEnterFrame(JSContext *cx);
 
     /*
-     * Allocate and initialize a Debugger.Script instance whose referent is |script| and
-     * whose holder is |obj|. If |obj| is NULL, this creates a Debugger.Script whose holder
-     * is null, for non-held scripts.
+     * Allocate and initialize a Debugger.Script instance whose referent is
+     * |script|.
      */
-    JSObject *newDebuggerScript(JSContext *cx, JSScript *script, JSObject *obj);
+    JSObject *newDebuggerScript(JSContext *cx, JSScript *script);
 
     /*
      * Receive a "new script" event from the engine. A new script was compiled
-     * or deserialized. For eval scripts obj must be null, otherwise it must be
-     * a script object.
+     * or deserialized.
      */
-    void fireNewScript(JSContext *cx, JSScript *script, JSObject *obj);
+    void fireNewScript(JSContext *cx, JSScript *script);
 
     static inline Debugger *fromLinks(JSCList *links);
     inline Breakpoint *firstBreakpoint() const;
 
   public:
     Debugger(JSContext *cx, JSObject *dbg);
     ~Debugger();
 
@@ -257,26 +255,26 @@ class Debugger {
     static void sweepAll(JSContext *cx);
     static void detachAllDebuggersFromGlobal(JSContext *cx, GlobalObject *global,
                                              GlobalObjectSet::Enum *compartmentEnum);
 
     static inline void onEnterFrame(JSContext *cx);
     static inline void onLeaveFrame(JSContext *cx);
     static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
     static inline JSTrapStatus onExceptionUnwind(JSContext *cx, js::Value *vp);
-    static inline void onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
+    static inline void onNewScript(JSContext *cx, JSScript *script,
                                    GlobalObject *compileAndGoGlobal);
     static JSTrapStatus onTrap(JSContext *cx, Value *vp);
     static JSTrapStatus onSingleStep(JSContext *cx, Value *vp);
 
     /************************************* Functions for use by Debugger.cpp. */
 
     inline bool observesEnterFrame() const;
     inline bool observesNewScript() const;
-    inline bool observesScope(JSObject *obj) const;
+    inline bool observesGlobal(GlobalObject *global) const;
     inline bool observesFrame(StackFrame *fp) const;
 
     /*
      * Like cx->compartment->wrap(cx, vp), but for the debugger compartment.
      *
      * Preconditions: *vp is a value from a debuggee compartment; cx is in the
      * debugger's compartment.
      *
@@ -327,30 +325,21 @@ class Debugger {
      *
      * On success, a completion value is in vp and ac.context does not have a
      * pending exception. (This ordinarily returns true even if the ok argument
      * is false.)
      */
     bool newCompletionValue(AutoCompartment &ac, bool ok, Value val, Value *vp);
 
     /*
-     * Return the Debugger.Script object for |fun|'s script, or create a new
-     * one if needed.  The context |cx| must be in the debugger compartment;
-     * |fun| must be a cross-compartment wrapper referring to the JSFunction in
-     * a debuggee compartment.
+     * Return the Debugger.Script object for |script|, or create a new one if
+     * needed. The context |cx| must be in the debugger compartment; |script|
+     * must be a script in a debuggee compartment.
      */
-    JSObject *wrapFunctionScript(JSContext *cx, JSFunction *fun);
-
-    /*
-     * Return the Debugger.Script object for |script|, or create a new one if
-     * needed. The context |cx| must be in the debugger compartment; |script| must
-     * be a script in a debuggee compartment. |obj| is either the script holder or
-     * null for non-held scripts.
-     */
-    JSObject *wrapScript(JSContext *cx, JSScript *script, JSObject *obj);
+    JSObject *wrapScript(JSContext *cx, JSScript *script);
 
   private:
     /* Prohibit copying. */
     Debugger(const Debugger &);
     Debugger & operator=(const Debugger &);
 };
 
 class BreakpointSite {
@@ -364,31 +353,31 @@ class BreakpointSite {
     const JSOp realOpcode;
 
   private:
     /*
      * The holder object for script, if known, else NULL.  This is NULL for
      * cached eval scripts and for JSD1 traps. It is always non-null for JSD2
      * breakpoints in held scripts.
      */
-    JSObject *scriptObject;
+    GlobalObject *scriptGlobal;
 
     JSCList breakpoints;  /* cyclic list of all js::Breakpoints at this instruction */
     size_t enabledCount;  /* number of breakpoints in the list that are enabled */
     JSTrapHandler trapHandler;  /* jsdbgapi trap state */
     Value trapClosure;
 
     bool recompile(JSContext *cx, bool forTrap);
 
   public:
     BreakpointSite(JSScript *script, jsbytecode *pc);
     Breakpoint *firstBreakpoint() const;
     bool hasBreakpoint(Breakpoint *bp);
     bool hasTrap() const { return !!trapHandler; }
-    JSObject *getScriptObject() const { return scriptObject; }
+    GlobalObject *getScriptGlobal() const { return scriptGlobal; }
 
     bool inc(JSContext *cx);
     void dec(JSContext *cx);
     bool setTrap(JSContext *cx, JSTrapHandler handler, const Value &closure);
     void clearTrap(JSContext *cx, BreakpointSiteMap::Enum *e = NULL,
                    JSTrapHandler *handlerp = NULL, Value *closurep = NULL);
     void destroyIfEmpty(JSRuntime *rt, BreakpointSiteMap::Enum *e);
 };
@@ -470,25 +459,25 @@ Debugger::observesEnterFrame() const
 
 bool
 Debugger::observesNewScript() const
 {
     return enabled && getHook(OnNewScript);
 }
 
 bool
-Debugger::observesScope(JSObject *obj) const
+Debugger::observesGlobal(GlobalObject *global) const
 {
-    return debuggees.has(obj->getGlobal());
+    return debuggees.has(global);
 }
 
 bool
 Debugger::observesFrame(StackFrame *fp) const
 {
-    return observesScope(&fp->scopeChain());
+    return observesGlobal(fp->scopeChain().getGlobal());
 }
 
 void
 Debugger::onEnterFrame(JSContext *cx)
 {
     if (!cx->compartment->getDebuggees().empty())
         slowPathOnEnterFrame(cx);
 }
@@ -512,23 +501,22 @@ JSTrapStatus
 Debugger::onExceptionUnwind(JSContext *cx, js::Value *vp)
 {
     return cx->compartment->getDebuggees().empty()
            ? JSTRAP_CONTINUE
            : dispatchHook(cx, vp, OnExceptionUnwind);
 }
 
 void
-Debugger::onNewScript(JSContext *cx, JSScript *script, JSObject *obj,
-                      GlobalObject *compileAndGoGlobal)
+Debugger::onNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
 {
     JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal);
     JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);
     if (!script->compartment()->getDebuggees().empty())
-        slowPathOnNewScript(cx, script, obj, compileAndGoGlobal);
+        slowPathOnNewScript(cx, script, compileAndGoGlobal);
 }
 
 extern JSBool
 EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *chars,
                 uintN length, const char *filename, uintN lineno, Value *rval);
 
 }
 
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -368,12 +368,12 @@ DefinePropertiesAndBrand(JSContext *cx, 
 typedef HashSet<GlobalObject *, DefaultHasher<GlobalObject *>, SystemAllocPolicy> GlobalObjectSet;
 
 } // namespace js
 
 js::GlobalObject *
 JSObject::asGlobal()
 {
     JS_ASSERT(isGlobal());
-    return reinterpret_cast<js::GlobalObject *>(this);
+    return static_cast<js::GlobalObject *>(this);
 }
 
 #endif /* GlobalObject_h___ */
--- a/js/src/yarr/YarrJIT.cpp
+++ b/js/src/yarr/YarrJIT.cpp
@@ -1200,18 +1200,20 @@ class YarrGenerator : private MacroAssem
             case OpBodyAlternativeNext:
             case OpBodyAlternativeEnd: {
                 PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
                 PatternAlternative* alternative = op.m_alternative;
 
                 // If we get here, the prior alternative matched - return success.
                 
                 // Adjust the stack pointer to remove the pattern's frame.
+#if !WTF_CPU_SPARC
                 if (m_pattern.m_body->m_callFrameSize)
                     addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+#endif
 
                 // Load appropriate values into the return register and the first output
                 // slot, and return. In the case of pattern with a fixed size, we will
                 // not have yet set the value in the first 
                 ASSERT(index != returnRegister);
                 if (m_pattern.m_body->m_hasFixedSize) {
                     move(index, returnRegister);
                     if (priorAlternative->m_minimumSize)
@@ -1508,18 +1510,20 @@ class YarrGenerator : private MacroAssem
                 }
 
                 YarrOp& lastOp = m_ops[op.m_previousOp];
                 m_checked += lastOp.m_checkAdjust;
                 break;
             }
 
             case OpMatchFailed:
+#if !WTF_CPU_SPARC
                 if (m_pattern.m_body->m_callFrameSize)
                     addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+#endif
                 move(TrustedImm32(-1), returnRegister);
                 generateReturn();
                 break;
             }
 
             ++opIndex;
         } while (opIndex < m_ops.size());
     }
@@ -1748,18 +1752,20 @@ class YarrGenerator : private MacroAssem
                     checkInput().linkTo(beginOp->m_reentry, this);
                     jump(firstInputCheckFailed);
                 }
 
                 // We jump to here if we iterate to the point that there is insufficient input to
                 // run any matches, and need to return a failure state from JIT code.
                 matchFailed.link(this);
 
+#if !WTF_CPU_SPARC
                 if (m_pattern.m_body->m_callFrameSize)
                     addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+#endif
                 move(TrustedImm32(-1), returnRegister);
                 generateReturn();
                 break;
             }
             case OpBodyAlternativeEnd: {
                 // We should never backtrack back into a body disjunction.
                 ASSERT(m_backtrackingState.isEmpty());
 
@@ -2321,18 +2327,16 @@ class YarrGenerator : private MacroAssem
         push(ARMRegisters::r8); // scratch register
 #endif
         move(ARMRegisters::r3, output);
 #elif WTF_CPU_SH4
         push(SH4Registers::r11);
         push(SH4Registers::r13);
 #elif WTF_CPU_SPARC
         save(Imm32(-m_pattern.m_body->m_callFrameSize * sizeof(void*)));
-        // set m_callFrameSize to 0 avoid and stack movement later.
-        m_pattern.m_body->m_callFrameSize = 0;
 #elif WTF_CPU_MIPS
         // Do nothing.
 #endif
     }
 
     void generateReturn()
     {
 #if WTF_CPU_X86_64
@@ -2372,18 +2376,20 @@ public:
 
     void compile(JSGlobalData* globalData, YarrCodeBlock& jitObject)
     {
         generateEnter();
 
         if (!m_pattern.m_body->m_hasFixedSize)
             store32(index, Address(output));
 
+#if !WTF_CPU_SPARC
         if (m_pattern.m_body->m_callFrameSize)
             subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+#endif
 
         // Compile the pattern to the internal 'YarrOp' representation.
         opCompileBody(m_pattern.m_body);
 
         // If we encountered anything we can't handle in the JIT code
         // (e.g. backreferences) then return early.
         if (m_shouldFallBack) {
             jitObject.setFallBack(true);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -774,25 +774,16 @@ nsXPConnect::Traverse(void *p, nsCycleCo
             if (IS_PROTO_CLASS(clazz)) {
                 XPCWrappedNativeProto* p =
                     (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
                 si = p->GetScriptableInfo();
             }
             if (si) {
                 JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
                             clazz->name, si->GetJSClass()->name);
-            } else if (clazz == &js::ScriptClass) {
-                JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
-                if (script->filename) {
-                    JS_snprintf(name, sizeof(name),
-                                "JS Object (Script - %s)",
-                                script->filename);
-                } else {
-                    JS_snprintf(name, sizeof(name), "JS Object (Script)");