jaegermonkey. what. a=arewefastyet
authorRobert Sayre <sayrer@gmail.com>
Sat, 11 Sep 2010 15:06:33 -0400
changeset 53642 09b657f24840aab9984395370900cfdcd6f33272
parent 52483 84baf90b040c7d5912724461c6e9e1d104ce5a18 (current diff)
parent 53641 3a6f15524d13d806e8d014e6318c5dcfd2fdcfb5 (diff)
child 53643 f1bd314e64ac8ad717746fd72667300460b9cf38
push idunknown
push userunknown
push dateunknown
reviewersarewefastyet
milestone2.0b6pre
jaegermonkey. what. a=arewefastyet
js/src/Makefile.in
js/src/config/autoconf.mk.in
js/src/config/rules.mk
js/src/configure.in
js/src/jsdtracef.cpp
js/src/jsdtracef.h
js/src/jsrecursion.cpp
js/src/jstask.cpp
js/src/jstask.h
js/src/trace-test/tests/basic/testBug552248.js
js/src/trace-test/tests/basic/testCrossGlobalCall.js
js/src/trace-test/tests/bug579740.js
js/src/trace-test/tests/testPutOnEmptyArgsObject.js
modules/libpref/src/init/all.js
--- a/browser/components/places/tests/unit/bookmarks.glue.json
+++ b/browser/components/places/tests/unit/bookmarks.glue.json
@@ -1,1 +1,1 @@
-{"title":"","id":1,"dateAdded":1233157910552624,"lastModified":1233157955206833,"type":"text/x-moz-place-container","root":"placesRoot","children":[{"title":"Bookmarks Menu","id":2,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157993171424,"type":"text/x-moz-place-container","root":"bookmarksMenuFolder","children":[{"title":"examplejson","id":27,"parent":2,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":1,"title":"Bookmarks Toolbar","id":3,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157972101126,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar"}],"type":"text/x-moz-place-container","root":"toolbarFolder","children":[{"title":"examplejson","id":26,"parent":3,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":2,"title":"Tags","id":4,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157910582667,"type":"text/x-moz-place-container","root":"tagsFolder","children":[]},{"index":3,"title":"Unsorted Bookmarks","id":5,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157911033315,"type":"text/x-moz-place-container","root":"unfiledBookmarksFolder","children":[]}]}
\ No newline at end of file
+{"title":"","id":1,"dateAdded":1233157910552624,"lastModified":1233157955206833,"type":"text/x-moz-place-container","root":"placesRoot","children":[{"title":"Bookmarks Menu","id":2,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157993171424,"type":"text/x-moz-place-container","root":"bookmarksMenuFolder","children":[{"title":"examplejson","id":27,"parent":2,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":1,"title":"Bookmarks Toolbar","id":3,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157972101126,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar"}],"type":"text/x-moz-place-container","root":"toolbarFolder","children":[{"title":"examplejson","id":26,"parent":3,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":2,"title":"Tags","id":4,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157910582667,"type":"text/x-moz-place-container","root":"tagsFolder","children":[]},{"index":3,"title":"Unsorted Bookmarks","id":5,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157911033315,"type":"text/x-moz-place-container","root":"unfiledBookmarksFolder","children":[]},]}
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -340,17 +340,18 @@ user_pref("signed.applets.codebase_princ
 user_pref("security.warn_submit_insecure", false);
 user_pref("browser.shell.checkDefaultBrowser", false);
 user_pref("shell.checkDefaultClient", false);
 user_pref("browser.warnOnQuit", false);
 user_pref("accessibility.typeaheadfind.autostart", false);
 user_pref("javascript.options.showInConsole", true);
 user_pref("layout.debug.enable_data_xbl", true);
 user_pref("browser.EULA.override", true);
-user_pref("javascript.options.jit.content", true);
+user_pref("javascript.options.tracejit.content", true);
+user_pref("javascript.options.methodjit.content", true);
 user_pref("gfx.color_management.force_srgb", true);
 user_pref("network.manage-offline-status", false);
 user_pref("test.mousescroll", true);
 user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
 user_pref("network.http.prompt-temp-redirect", false);
 user_pref("media.cache_size", 100);
 user_pref("security.warn_viewing_mixed", false);
 user_pref("app.update.enabled", false);
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -106,165 +106,188 @@ getUTF8StringArgument(JSContext *cx, JSO
         return;
     }
 
     PRUnichar *data = (PRUnichar*)JS_GetStringChars(str);
     CopyUTF16toUTF8(data, aRetval);
 }
 
 static JSBool
-netscape_security_isPrivilegeEnabled(JSContext *cx, JSObject *obj, uintN argc,
-                                     jsval *argv, jsval *rval)
+netscape_security_isPrivilegeEnabled(JSContext *cx, uintN argc, jsval *vp)
 {
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
     JSBool result = JS_FALSE;
-    char *cap = getStringArgument(cx, obj, 0, argc, argv);
+    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
     if (cap) {
         nsresult rv;
         nsCOMPtr<nsIScriptSecurityManager> securityManager = 
                  do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
         if (NS_SUCCEEDED(rv)) {
             //            NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
             rv = securityManager->IsCapabilityEnabled(cap, &result);
             if (NS_FAILED(rv)) 
                 result = JS_FALSE;
         }
     }
-    *rval = BOOLEAN_TO_JSVAL(result);
+    JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(result));
     return JS_TRUE;
 }
 
 
 static JSBool
-netscape_security_enablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
-                                  jsval *argv, jsval *rval)
+netscape_security_enablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *cap = getStringArgument(cx, obj, 0, argc, argv);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
     if (!cap)
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
     rv = securityManager->EnableCapability(cap);
     if (NS_FAILED(rv))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-netscape_security_disablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
-                                   jsval *argv, jsval *rval)
+netscape_security_disablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *cap = getStringArgument(cx, obj, 0, argc, argv);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
     if (!cap)
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
     rv = securityManager->DisableCapability(cap);
     if (NS_FAILED(rv))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-netscape_security_revertPrivilege(JSContext *cx, JSObject *obj, uintN argc,
-                                  jsval *argv, jsval *rval)
+netscape_security_revertPrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
-    char *cap = getStringArgument(cx, obj, 0, argc, argv);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    char *cap = getStringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp));
     if (!cap)
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
     rv = securityManager->RevertCapability(cap);
     if (NS_FAILED(rv))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-netscape_security_setCanEnablePrivilege(JSContext *cx, JSObject *obj, uintN argc,
-                                        jsval *argv, jsval *rval)
+netscape_security_setCanEnablePrivilege(JSContext *cx, uintN argc, jsval *vp)
 {
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
     if (argc < 2) return JS_FALSE;
     nsCAutoString principalFingerprint;
-    getUTF8StringArgument(cx, obj, 0, argc, argv, principalFingerprint);
-    char *cap = getStringArgument(cx, obj, 1, argc, argv);
+    getUTF8StringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), principalFingerprint);
+    char *cap = getStringArgument(cx, obj, 1, argc, JS_ARGV(cx, vp));
     if (principalFingerprint.IsEmpty() || !cap)
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
     rv = securityManager->SetCanEnableCapability(principalFingerprint, cap, 
                                                  nsIPrincipal::ENABLE_GRANTED);
     if (NS_FAILED(rv))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-netscape_security_invalidate(JSContext *cx, JSObject *obj, uintN argc,
-                             jsval *argv, jsval *rval)
+netscape_security_invalidate(JSContext *cx, uintN argc, jsval *vp)
 {
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
     nsCAutoString principalFingerprint;
-    getUTF8StringArgument(cx, obj, 0, argc, argv, principalFingerprint);
+    getUTF8StringArgument(cx, obj, 0, argc, JS_ARGV(cx, vp), principalFingerprint);
     if (principalFingerprint.IsEmpty())
         return JS_FALSE;
 
     nsresult rv;
     nsCOMPtr<nsIScriptSecurityManager> securityManager = 
              do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     if (NS_FAILED(rv)) 
         return JS_FALSE;
 
     //    NS_ASSERTION(cx == GetCurrentContext(), "unexpected context");
 
     rv = securityManager->SetCanEnableCapability(principalFingerprint,
                                                  nsPrincipal::sInvalid,
                                                  nsIPrincipal::ENABLE_GRANTED);
     if (NS_FAILED(rv))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec PrivilegeManager_static_methods[] = {
-    { "isPrivilegeEnabled", netscape_security_isPrivilegeEnabled,   1,0,0},
-    { "enablePrivilege",    netscape_security_enablePrivilege,      1,0,0},
-    { "disablePrivilege",   netscape_security_disablePrivilege,     1,0,0},
-    { "revertPrivilege",    netscape_security_revertPrivilege,      1,0,0},
+    { "isPrivilegeEnabled", netscape_security_isPrivilegeEnabled,   1,0},
+    { "enablePrivilege",    netscape_security_enablePrivilege,      1,0},
+    { "disablePrivilege",   netscape_security_disablePrivilege,     1,0},
+    { "revertPrivilege",    netscape_security_revertPrivilege,      1,0},
     //-- System Cert Functions
     { "setCanEnablePrivilege", netscape_security_setCanEnablePrivilege,
-                                                                    2,0,0},
-    { "invalidate",            netscape_security_invalidate,        1,0,0},
-    {nsnull,nsnull,0,0,0}
+                                                                    2,0},
+    { "invalidate",            netscape_security_invalidate,        1,0},
+    {nsnull,nsnull,0,0}
 };
 
 /*
  * "Steal" calls to netscape.security.PrivilegeManager.enablePrivilege,
  * et. al. so that code that worked with 4.0 can still work.
  */
 NS_IMETHODIMP 
 nsSecurityNameSet::InitializeNameSet(nsIScriptContext* aScriptContext)
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1536,35 +1536,27 @@ nsContentUtils::GetWindowFromCaller()
 
   return nsnull;
 }
 
 nsIDOMDocument *
 nsContentUtils::GetDocumentFromCaller()
 {
   JSContext *cx = nsnull;
-  sThreadJSContextStack->Peek(&cx);
-
-  nsIDOMDocument *doc = nsnull;
-
-  if (cx) {
-    JSObject *callee = nsnull;
-    JSStackFrame *fp = nsnull;
-    while (!callee && (fp = ::JS_FrameIterator(cx, &fp))) {
-      callee = ::JS_GetFrameCalleeObject(cx, fp);
-    }
-
-    nsCOMPtr<nsPIDOMWindow> win =
-      do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, callee));
-    if (win) {
-      doc = win->GetExtantDocument();
-    }
-  }
-
-  return doc;
+  JSObject *obj = nsnull;
+  sXPConnect->GetCaller(&cx, &obj);
+  NS_ASSERTION(cx && obj, "Caller ensures something is running");
+
+  nsCOMPtr<nsPIDOMWindow> win =
+    do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj));
+  if (!win) {
+    return nsnull;
+  }
+
+  return win->GetExtantDocument();
 }
 
 nsIDOMDocument *
 nsContentUtils::GetDocumentFromContext()
 {
   JSContext *cx = nsnull;
   sThreadJSContextStack->Peek(&cx);
 
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -41,16 +41,18 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = content/events/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 # Disabled due to timeouts.
 # 		test_bug563329.html
+# Disabled due to lack of present support for JSD in JM
+#		test_bug448602.html
 _TEST_FILES = \
 		test_bug226361.xhtml \
 		     bug226361_iframe.xhtml \
 		test_bug238987.html \
 		test_bug288392.html \
 		test_bug299673-1.html \
 		test_bug299673-2.html \
 		     bug299673.js \
@@ -67,17 +69,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug391568.xhtml \
 		test_bug402089.html \
 		test_bug405632.html \
 		test_bug409604.html \
 		test_bug412567.html \
 		test_bug426082.html \
 		test_bug443985.html \
 		test_bug447736.html \
-		test_bug448602.html \
 		test_bug450876.html \
 		test_bug456273.html \
 		test_bug457672.html \
 		test_bug428988.html \
 		bug457672.html \
 		test_draggableprop.html \
 		test_bug489671.html \
 		test_bug493251.html \
--- a/content/media/test/test_play_events.html
+++ b/content/media/test/test_play_events.html
@@ -20,17 +20,21 @@ var tokens = {
   "canplay":        ["playing"],
   "playing":        ["canplay", "canplaythrough"],
   "canplaythrough": ["canplay", "canplaythrough"]
 };
 
 function gotPlayEvent(event) {
   var v = event.target;
   ok(tokens[v._state].indexOf(event.type) >= 0,
-     "Check expected event got " + event.type + " at " + v._state + " for " + v.src);
+     "Check expected event got " + event.type + " at " + v._state + " for " + v.src +
+     " uneval(event.type)=" + uneval(event.type) + " typeof(event.type)=" + typeof(event.type) +
+     " uneval(v._state)=" + uneval(v._state) + " typeof(v._state)=" + typeof(v._state) + 
+     " tokens["+v._state+"]=" + tokens[v._state] +
+     " tokens["+v._state+"].indexOf(event.type)=" + tokens[v._state].indexOf(event.type));
   v._state = event.type;
 }
 
 function ended(event) {
   var v = event.target;
   is(v._state, "canplaythrough", "Last event should be canplaythrough for " + v.src);
   v.parentNode.removeChild(v);
   manager.finished(v.token);
--- a/content/xbl/src/nsXBLDocumentInfo.cpp
+++ b/content/xbl/src/nsXBLDocumentInfo.cpp
@@ -50,16 +50,17 @@
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIChromeRegistry.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsDOMJSUtils.h"
 #include "mozilla/Services.h"
+#include "xpcpublic.h"
  
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 // An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile 
 // properties and methods of XBL bindings against.
 class nsXBLDocGlobalObject : public nsIScriptGlobalObject,
                              public nsIScriptObjectPrincipal
 {
@@ -319,19 +320,25 @@ nsXBLDocGlobalObject::EnsureScriptEnviro
 
   JSContext *cx = (JSContext *)mScriptContext->GetNativeContext();
   JSAutoRequest ar(cx);
 
   // nsJSEnvironment set the error reporter to NS_ScriptErrorReporter so
   // we must apparently override that with our own (although it isn't clear 
   // why - see bug 339647)
   JS_SetErrorReporter(cx, XBL_ProtoErrorReporter);
-  mJSObject = ::JS_NewGlobalObject(cx, &gSharedGlobalClass);
-  if (!mJSObject)
-    return nsnull;
+
+  nsIPrincipal *principal = GetPrincipal();
+  nsCString origin;
+  JSCompartment *compartment;
+
+  principal->GetOrigin(getter_Copies(origin));
+  rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
+                              &mJSObject, &compartment);
+  NS_ENSURE_SUCCESS(rv, nsnull);
 
   ::JS_SetGlobalObject(cx, mJSObject);
 
   // Add an owning reference from JS back to us. This'll be
   // released when the JSObject is finalized.
   ::JS_SetPrivate(cx, mJSObject, this);
   NS_ADDREF(this);
   return NS_OK;
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -60,16 +60,17 @@
 #include "nsIScriptError.h"
 #include "mozilla/FunctionTimer.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsDOMCID.h"
 #include "nsNodeInfoManager.h"
 #include "nsContentUtils.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
+#include "xpcpublic.h"
 
 static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
                      NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 
 class nsXULPDGlobalObject : public nsIScriptGlobalObject,
                             public nsIScriptObjectPrincipal
 {
@@ -724,19 +725,26 @@ nsXULPDGlobalObject::EnsureScriptEnviron
     rv = languageRuntime->CreateContext(getter_AddRefs(ctxNew));
     // For JS, we have to setup a special global object.  We do this then
     // attach it as the global for this context.  Then, ::SetScriptContext
     // will re-fetch the global and set it up in our language globals array.
     if (lang_id == nsIProgrammingLanguage::JAVASCRIPT) {
       // some special JS specific code we should abstract
       JSContext *cx = (JSContext *)ctxNew->GetNativeContext();
       JSAutoRequest ar(cx);
-      JSObject *newGlob = ::JS_NewGlobalObject(cx, &gSharedGlobalClass);
-      if (!newGlob)
-        return nsnull;
+
+      nsIPrincipal *principal = GetPrincipal();
+      nsCString origin;
+      JSObject *newGlob;
+      JSCompartment *compartment;
+
+      principal->GetOrigin(getter_Copies(origin));
+      rv = xpc_CreateGlobalObject(cx, &gSharedGlobalClass, origin, principal,
+                                  &newGlob, &compartment);
+      NS_ENSURE_SUCCESS(rv, nsnull);
 
       ::JS_SetGlobalObject(cx, newGlob);
 
       // Add an owning reference from JS back to us. This'll be
       // released when the JSObject is finalized.
       ::JS_SetPrivate(cx, newGlob, this);
       NS_ADDREF(this);
     }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -6548,20 +6548,23 @@ nsCommonWindowSH::GlobalResolve(nsGlobal
   }
 
   return rv;
 }
 
 // Native code for window._content getter, this simply maps
 // window._content to window.content for backwards compatibility only.
 static JSBool
-ContentWindowGetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                    jsval *rval)
-{
-  return ::JS_GetProperty(cx, obj, "content", rval);
+ContentWindowGetter(JSContext *cx, uintN argc, jsval *vp)
+{
+  JSObject *obj = JS_THIS_OBJECT(cx, vp);
+  if (!obj)
+    return JS_FALSE;
+
+  return ::JS_GetProperty(cx, obj, "content", vp);
 }
 
 PRBool
 nsOuterWindowSH::sResolving = PR_FALSE;
 
 NS_IMETHODIMP
 nsOuterWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                             JSObject *obj, jsid id, PRUint32 flags,
@@ -8744,26 +8747,30 @@ ResolveImpl(JSContext *cx, nsIXPConnectW
   JSString *str = IdToString(cx, id);
   NS_ENSURE_TRUE(str, NS_ERROR_UNEXPECTED);
 
   return doc->ResolveName(nsDependentJSString(str), nsnull, result, aCache);
 }
 
 // static
 JSBool
-nsHTMLDocumentSH::DocumentOpen(JSContext *cx, JSObject *obj, uintN argc,
-                               jsval *argv, jsval *rval)
-{
+nsHTMLDocumentSH::DocumentOpen(JSContext *cx, uintN argc, jsval *vp)
+{
+  JSObject *obj = JS_THIS_OBJECT(cx, vp);
+  if (!obj)
+    return JS_FALSE;
+
+  jsval *argv = JS_ARGV(cx, vp);
   if (argc > 2) {
     JSObject *global = ::JS_GetGlobalForObject(cx, obj);
 
     // DOM0 quirk that makes document.open() call window.open() if
     // called with 3 or more arguments.
 
-    return ::JS_CallFunctionName(cx, global, "open", argc, argv, rval);
+    return ::JS_CallFunctionName(cx, global, "open", argc, JS_ARGV(cx, vp), vp);
   }
 
   nsCOMPtr<nsISupports> native = do_QueryWrapper(cx, obj);
   if (!native) {
     nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_FAILURE);
 
     return JS_FALSE;
   }
@@ -8806,17 +8813,17 @@ nsHTMLDocumentSH::DocumentOpen(JSContext
   nsresult rv = doc->Open(contentType, replace, getter_AddRefs(retval));
   if (NS_FAILED(rv)) {
     nsDOMClassInfo::ThrowJSException(cx, rv);
 
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  rv = WrapNative(cx, obj, retval, PR_FALSE, rval,
+  rv = WrapNative(cx, obj, retval, PR_FALSE, vp,
                   getter_AddRefs(holder));
   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to wrap native!");
 
   return NS_SUCCEEDED(rv);
 }
 
 
 static JSClass sHTMLDocumentAllClass = {
@@ -9082,53 +9089,54 @@ void
 nsHTMLDocumentSH::ReleaseDocument(JSContext *cx, JSObject *obj)
 {
   nsIHTMLDocument *doc = (nsIHTMLDocument *)::JS_GetPrivate(cx, obj);
 
   NS_IF_RELEASE(doc);
 }
 
 JSBool
-nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, JSObject *obj, uintN argc,
-                                      jsval *argv, jsval *rval)
+nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, uintN argc, jsval *vp)
 {
   // Handle document.all("foo") style access to document.all.
 
   if (argc != 1) {
     // XXX: Should throw NS_ERROR_XPC_NOT_ENOUGH_ARGS for argc < 1,
     // and create a new NS_ERROR_XPC_TOO_MANY_ARGS for argc > 1? IE
     // accepts nothing other than one arg.
     nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_INVALID_ARG);
 
     return JS_FALSE;
   }
 
   // Convert all types to string.
-  JSString *str = ::JS_ValueToString(cx, argv[0]);
+  JSString *str = ::JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
   if (!str) {
     return JS_FALSE;
   }
 
   JSObject *self;
 
-  if (::JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION) {
-    // If argv[-2] is a function, we're called through
+  if (::JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
+    // If the callee is a function, we're called through
     // document.all.item() or something similar. In such a case, self
     // is passed as obj.
 
-    self = obj;
+    self = JS_THIS_OBJECT(cx, vp);
+    if (!self)
+      return JS_FALSE;
   } else {
     // In other cases (i.e. document.all("foo")), self is passed as
-    // argv[-2].
-
-    self = JSVAL_TO_OBJECT(argv[-2]);
+    // the callee
+
+    self = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
   }
 
   return ::JS_GetUCProperty(cx, self, ::JS_GetStringChars(str),
-                            ::JS_GetStringLength(str), rval);
+                            ::JS_GetStringLength(str), vp);
 }
 
 
 static inline JSObject *
 GetDocumentAllHelper(JSContext *cx, JSObject *obj)
 {
   while (obj && JS_GET_CLASS(cx, obj) != &sHTMLDocumentAllHelperClass) {
     obj = ::JS_GetPrototype(cx, obj);
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -994,30 +994,28 @@ protected:
   nsHTMLDocumentSH(nsDOMClassInfoData* aData) : nsDocumentSH(aData)
   {
   }
 
   virtual ~nsHTMLDocumentSH()
   {
   }
 
-  static JSBool DocumentOpen(JSContext *cx, JSObject *obj, uintN argc,
-                             jsval *argv, jsval *rval);
+  static JSBool DocumentOpen(JSContext *cx, uintN argc, jsval *vp);
   static JSBool GetDocumentAllNodeList(JSContext *cx, JSObject *obj,
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 
 public:
   static JSBool DocumentAllGetProperty(JSContext *cx, JSObject *obj, jsid id,
                                        jsval *vp);
   static JSBool DocumentAllNewResolve(JSContext *cx, JSObject *obj, jsid id,
                                       uintN flags, JSObject **objp);
   static void ReleaseDocument(JSContext *cx, JSObject *obj);
-  static JSBool CallToGetPropMapper(JSContext *cx, JSObject *obj, uintN argc,
-                                    jsval *argv, jsval *rval);
+  static JSBool CallToGetPropMapper(JSContext *cx, uintN argc, jsval *vp);
   static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSObject *obj,
                                              jsid id, jsval *vp);
   static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSObject *obj,
                                             jsid id, uintN flags,
                                             JSObject **objp);
   static JSBool DocumentAllTagsNewResolve(JSContext *cx, JSObject *obj,
                                           jsid id, uintN flags,
                                           JSObject **objp);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -554,17 +554,17 @@ NS_ScriptErrorReporter(JSContext *cx,
                        const char *message,
                        JSErrorReport *report)
 {
   // We don't want to report exceptions too eagerly, but warnings in the
   // absence of werror are swallowed whole, so report those now.
   if (!JSREPORT_IS_WARNING(report->flags)) {
     JSStackFrame * fp = nsnull;
     while ((fp = JS_FrameIterator(cx, &fp))) {
-      if (!JS_IsNativeFrame(cx, fp)) {
+      if (JS_IsScriptFrame(cx, fp)) {
         return;
       }
     }
 
     nsIXPConnect* xpc = nsContentUtils::XPConnect();
     if (xpc) {
       nsAXPCNativeCallContext *cc = nsnull;
       xpc->GetCurrentNativeCallContext(&cc);
@@ -1213,18 +1213,20 @@ static const char js_strict_option_str[]
 #ifdef DEBUG
 static const char js_strict_debug_option_str[] = JS_OPTIONS_DOT_STR "strict.debug";
 #endif
 static const char js_werror_option_str[] = JS_OPTIONS_DOT_STR "werror";
 static const char js_relimit_option_str[]= JS_OPTIONS_DOT_STR "relimit";
 #ifdef JS_GC_ZEAL
 static const char js_zeal_option_str[]   = JS_OPTIONS_DOT_STR "gczeal";
 #endif
-static const char js_jit_content_str[]   = JS_OPTIONS_DOT_STR "jit.content";
-static const char js_jit_chrome_str[]    = JS_OPTIONS_DOT_STR "jit.chrome";
+static const char js_tracejit_content_str[]   = JS_OPTIONS_DOT_STR "tracejit.content";
+static const char js_tracejit_chrome_str[]    = JS_OPTIONS_DOT_STR "tracejit.chrome";
+static const char js_methodjit_content_str[]   = JS_OPTIONS_DOT_STR "methodjit.content";
+static const char js_methodjit_chrome_str[]    = JS_OPTIONS_DOT_STR "methodjit.chrome";
 
 int
 nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
 {
   nsJSContext *context = reinterpret_cast<nsJSContext *>(data);
   PRUint32 oldDefaultJSOptions = context->mDefaultJSOptions;
   PRUint32 newDefaultJSOptions = oldDefaultJSOptions;
 
@@ -1234,32 +1236,42 @@ nsJSContext::JSOptionChangedCallback(con
   else
     newDefaultJSOptions &= ~JSOPTION_STRICT;
 
   nsIScriptGlobalObject *global = context->GetGlobalObject();
   // XXX should we check for sysprin instead of a chrome window, to make
   // XXX components be covered by the chrome pref instead of the content one?
   nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(global));
 
-  PRBool useJIT = nsContentUtils::GetBoolPref(chromeWindow ?
-                                              js_jit_chrome_str :
-                                              js_jit_content_str);
+  PRBool useTraceJIT = nsContentUtils::GetBoolPref(chromeWindow ?
+                                                   js_tracejit_chrome_str :
+                                                   js_tracejit_content_str);
+  PRBool useMethodJIT = nsContentUtils::GetBoolPref(chromeWindow ?
+                                                    js_methodjit_chrome_str :
+                                                    js_methodjit_content_str);
   nsCOMPtr<nsIXULRuntime> xr = do_GetService(XULRUNTIME_SERVICE_CONTRACTID);
   if (xr) {
     PRBool safeMode = PR_FALSE;
     xr->GetInSafeMode(&safeMode);
-    if (safeMode)
-      useJIT = PR_FALSE;
+    if (safeMode) {
+      useTraceJIT = PR_FALSE;
+      useMethodJIT = PR_FALSE;
+    }
   }    
 
-  if (useJIT)
+  if (useTraceJIT)
     newDefaultJSOptions |= JSOPTION_JIT;
   else
     newDefaultJSOptions &= ~JSOPTION_JIT;
 
+  if (useMethodJIT)
+    newDefaultJSOptions |= JSOPTION_METHODJIT;
+  else
+    newDefaultJSOptions &= ~JSOPTION_METHODJIT;
+
 #ifdef DEBUG
   // In debug builds, warnings are enabled in chrome context if javascript.options.strict.debug is true
   PRBool strictDebug = nsContentUtils::GetBoolPref(js_strict_debug_option_str);
   // Note this callback is also called from context's InitClasses thus we don't
   // need to enable this directly from InitContext
   if (strictDebug && (newDefaultJSOptions & JSOPTION_STRICT) == 0) {
     if (chromeWindow)
       newDefaultJSOptions |= JSOPTION_STRICT;
@@ -3070,126 +3082,131 @@ static JSClass OptionsClass = {
 #include <unistd.h>
 #endif
 #ifdef XP_WIN32
 #include <io.h>
 #endif
 #include "nsTraceMalloc.h"
 
 static JSBool
-TraceMallocDisable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocDisable(JSContext *cx, uintN argc, jsval *vp)
 {
     NS_TraceMallocDisable();
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocEnable(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocEnable(JSContext *cx, uintN argc, jsval *vp)
 {
     NS_TraceMallocEnable();
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocOpenLogFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocOpenLogFile(JSContext *cx, uintN argc, jsval *vp)
 {
     int fd;
     JSString *str;
     char *filename;
 
     if (argc == 0) {
         fd = -1;
     } else {
-        str = JS_ValueToString(cx, argv[0]);
+        str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
         if (!str)
             return JS_FALSE;
         filename = JS_GetStringBytes(str);
         fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
         if (fd < 0) {
             JS_ReportError(cx, "can't open %s: %s", filename, strerror(errno));
             return JS_FALSE;
         }
     }
-    *rval = INT_TO_JSVAL(fd);
+    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(fd));
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocChangeLogFD(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocChangeLogFD(JSContext *cx, uintN argc, jsval *vp)
 {
     int32 fd, oldfd;
 
     if (argc == 0) {
         oldfd = -1;
     } else {
-        if (!JS_ValueToECMAInt32(cx, argv[0], &fd))
+        if (!JS_ValueToECMAInt32(cx, JS_ARGV(cx, vp)[0], &fd))
             return JS_FALSE;
         oldfd = NS_TraceMallocChangeLogFD(fd);
         if (oldfd == -2) {
             JS_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
     }
-    *rval = INT_TO_JSVAL(oldfd);
+    JS_SET_RVAL(cx, vp, INT_TO_JSVAL(oldfd));
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocCloseLogFD(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocCloseLogFD(JSContext *cx, uintN argc, jsval *vp)
 {
     int32 fd;
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     if (argc == 0)
         return JS_TRUE;
-    if (!JS_ValueToECMAInt32(cx, argv[0], &fd))
+    if (!JS_ValueToECMAInt32(cx, JS_ARGV(cx, vp)[0], &fd))
         return JS_FALSE;
     NS_TraceMallocCloseLogFD((int) fd);
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocLogTimestamp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocLogTimestamp(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     const char *caption;
 
-    str = JS_ValueToString(cx, argv[0]);
+    str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
     if (!str)
         return JS_FALSE;
     caption = JS_GetStringBytes(str);
     NS_TraceMallocLogTimestamp(caption);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-TraceMallocDumpAllocations(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TraceMallocDumpAllocations(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     const char *pathname;
 
-    str = JS_ValueToString(cx, argv[0]);
+    str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
     if (!str)
         return JS_FALSE;
     pathname = JS_GetStringBytes(str);
     if (NS_TraceMallocDumpAllocations(pathname) < 0) {
         JS_ReportError(cx, "can't dump to %s: %s", pathname, strerror(errno));
         return JS_FALSE;
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec TraceMallocFunctions[] = {
-    {"TraceMallocDisable",         TraceMallocDisable,         0, 0, 0},
-    {"TraceMallocEnable",          TraceMallocEnable,          0, 0, 0},
-    {"TraceMallocOpenLogFile",     TraceMallocOpenLogFile,     1, 0, 0},
-    {"TraceMallocChangeLogFD",     TraceMallocChangeLogFD,     1, 0, 0},
-    {"TraceMallocCloseLogFD",      TraceMallocCloseLogFD,      1, 0, 0},
-    {"TraceMallocLogTimestamp",    TraceMallocLogTimestamp,    1, 0, 0},
-    {"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0, 0},
-    {nsnull,                       nsnull,                     0, 0, 0}
+    {"TraceMallocDisable",         TraceMallocDisable,         0, 0},
+    {"TraceMallocEnable",          TraceMallocEnable,          0, 0},
+    {"TraceMallocOpenLogFile",     TraceMallocOpenLogFile,     1, 0},
+    {"TraceMallocChangeLogFD",     TraceMallocChangeLogFD,     1, 0},
+    {"TraceMallocCloseLogFD",      TraceMallocCloseLogFD,      1, 0},
+    {"TraceMallocLogTimestamp",    TraceMallocLogTimestamp,    1, 0},
+    {"TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0},
+    {nsnull,                       nsnull,                     0, 0}
 };
 
 #endif /* NS_TRACE_MALLOC */
 
 #ifdef MOZ_JPROF
 
 #include <signal.h>
 
@@ -3262,21 +3279,21 @@ static JSFunctionSpec JProfFunctions[] =
     {"JProfStopProfiling",         JProfStopProfilingJS,       0, 0, 0},
     {nsnull,                       nsnull,                     0, 0, 0}
 };
 
 #endif /* defined(MOZ_JPROF) */
 
 #ifdef MOZ_SHARK
 static JSFunctionSpec SharkFunctions[] = {
-    {"startShark",                 js_StartShark,              0, 0, 0},
-    {"stopShark",                  js_StopShark,               0, 0, 0},
-    {"connectShark",               js_ConnectShark,            0, 0, 0},
-    {"disconnectShark",            js_DisconnectShark,         0, 0, 0},
-    {nsnull,                       nsnull,                     0, 0, 0}
+    {"startShark",                 js_StartShark,              0, 0},
+    {"stopShark",                  js_StopShark,               0, 0},
+    {"connectShark",               js_ConnectShark,            0, 0},
+    {"disconnectShark",            js_DisconnectShark,         0, 0},
+    {nsnull,                       nsnull,                     0, 0}
 };
 #endif
 
 #ifdef MOZ_CALLGRIND
 static JSFunctionSpec CallgrindFunctions[] = {
     {"startCallgrind",             js_StartCallgrind,          0, 0, 0},
     {"stopCallgrind",              js_StopCallgrind,           0, 0, 0},
     {"dumpCallgrind",              js_DumpCallgrind,           1, 0, 0},
--- a/dom/interfaces/json/nsIJSON.idl
+++ b/dom/interfaces/json/nsIJSON.idl
@@ -47,17 +47,17 @@ interface nsIScriptGlobalObject;
 %}
 
 [ptr] native JSValPtr(jsval);
 [ptr] native JSContext(JSContext);
 
 /**
  * Encode and decode JSON text.
  */
-[scriptable, uuid(6fcf09ee-87d0-42ec-a72a-8d60114e974f)]
+[scriptable, uuid(a4d68b4e-0c0b-4c7c-b540-ef2f9834171f)]
 interface nsIJSON : nsISupports
 {
   AString encode(/* in JSObject value */);
 
   void encodeToStream(in nsIOutputStream stream,
                       in string charset,
                       in boolean writeBOM
                       /* in JSObject value */);
@@ -66,9 +66,30 @@ interface nsIJSON : nsISupports
 
   void /* JSObject */ decodeFromStream(in nsIInputStream stream,
                                        in long contentLength);
 
   [noscript] AString  encodeFromJSVal(in JSValPtr value, in JSContext cx);
 
   // Make sure you GCroot the result of this function before using it.
   [noscript] jsval    decodeToJSVal(in AString str, in JSContext cx);
+
+
+  /*
+   * Decode a JSON string, but also accept some strings in non-JSON format, as
+   * the decoding methods here did previously before tightening.
+   *
+   * This method is provided only as a temporary transition path for users of
+   * the old code who depended on the ability to decode leniently; new users
+   * should use the non-legacy decoding methods.
+   *
+   * @param str the string to parse
+   */
+  void /* JSObject */ legacyDecode(in AString str);
+
+  /* Identical to legacyDecode, but decode the contents of stream. */
+  void /* JSObject */ legacyDecodeFromStream(in nsIInputStream stream,
+                                             in long contentLength);
+
+  /* Identical to legacyDecode, but decode into a jsval. */
+  // Make sure you GCroot the result of this function before using it.
+  [noscript] jsval    legacyDecodeToJSVal(in AString str, in JSContext cx);
 };
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -412,29 +412,30 @@ nsJSON::DecodeToJSVal(const nsAString &s
 
   JSBool ok = JS_ConsumeJSONText(cx, parser,
                                  (jschar*)PromiseFlatString(str).get(),
                                  (uint32)str.Length());
 
   // Since we've called JS_BeginJSONParse, we have to call JS_FinishJSONParse,
   // even if JS_ConsumeJSONText fails.  But if either fails, we'll report an
   // error.
-  ok = ok && JS_FinishJSONParse(cx, parser, JSVAL_NULL);
+  ok &= JS_FinishJSONParse(cx, parser, JSVAL_NULL);
 
   if (!ok) {
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsJSON::DecodeInternal(nsIInputStream *aStream,
                        PRInt32 aContentLength,
-                       PRBool aNeedsConverter)
+                       PRBool aNeedsConverter,
+                       DecodingMode mode /* = STRICT */)
 {
   nsresult rv;
   nsIXPConnect *xpc = nsContentUtils::XPConnect();
   if (!xpc)
     return NS_ERROR_FAILURE;
 
   nsAXPCNativeCallContext *cc = nsnull;
   rv = xpc->GetCurrentNativeCallContext(&cc);
@@ -459,17 +460,17 @@ nsJSON::DecodeInternal(nsIInputStream *a
   }
 
   rv = NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream,
                                 NS_LITERAL_CSTRING("application/json"));
   if (!jsonChannel || NS_FAILED(rv))
     return NS_ERROR_FAILURE;
 
   nsRefPtr<nsJSONListener>
-    jsonListener(new nsJSONListener(cx, retvalPtr, aNeedsConverter));
+    jsonListener(new nsJSONListener(cx, retvalPtr, aNeedsConverter, mode));
 
   if (!jsonListener)
     return NS_ERROR_OUT_OF_MEMORY;
 
   //XXX this stream pattern should be consolidated in netwerk
   rv = jsonListener->OnStartRequest(jsonChannel, nsnull);
   if (NS_FAILED(rv)) {
     jsonChannel->Cancel(rv);
@@ -509,35 +510,83 @@ nsJSON::DecodeInternal(nsIInputStream *a
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = cc->SetReturnValueWasSet(PR_TRUE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+
+NS_IMETHODIMP
+nsJSON::LegacyDecode(const nsAString& json)
+{
+  const PRUnichar *data;
+  PRUint32 len = NS_StringGetData(json, &data);
+  nsCOMPtr<nsIInputStream> stream;
+  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
+                                      (const char*) data,
+                                      len * sizeof(PRUnichar),
+                                      NS_ASSIGNMENT_DEPEND);
+  NS_ENSURE_SUCCESS(rv, rv);
+  return DecodeInternal(stream, len, PR_FALSE, LEGACY);
+}
+
+NS_IMETHODIMP
+nsJSON::LegacyDecodeFromStream(nsIInputStream *aStream, PRInt32 aContentLength)
+{
+  return DecodeInternal(aStream, aContentLength, PR_TRUE, LEGACY);
+}
+
+NS_IMETHODIMP
+nsJSON::LegacyDecodeToJSVal(const nsAString &str, JSContext *cx, jsval *result)
+{
+  JSAutoRequest ar(cx);
+
+  JSONParser *parser = JS_BeginJSONParse(cx, result);
+  NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED);
+
+  JSBool ok = js_ConsumeJSONText(cx, parser,
+                                 (jschar*)PromiseFlatString(str).get(),
+                                 (uint32)str.Length(),
+                                 LEGACY);
+
+  // Since we've called JS_BeginJSONParse, we have to call JS_FinishJSONParse,
+  // even if js_ConsumeJSONText fails.  But if either fails, we'll report an
+  // error.
+  ok &= JS_FinishJSONParse(cx, parser, JSVAL_NULL);
+
+  if (!ok) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  return NS_OK;
+}
+
 nsresult
 NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult)
 {
   nsJSON* json = new nsJSON();
   if (!json)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(json);
   *aResult = json;
 
   return NS_OK;
 }
 
 nsJSONListener::nsJSONListener(JSContext *cx, jsval *rootVal,
-                               PRBool needsConverter)
+                               PRBool needsConverter,
+                               DecodingMode mode /* = STRICT */)
   : mNeedsConverter(needsConverter), 
     mJSONParser(nsnull),
     mCx(cx),
-    mRootVal(rootVal)
+    mRootVal(rootVal),
+    mDecodingMode(mode)
 {
 }
 
 nsJSONListener::~nsJSONListener()
 {
   Cleanup();
 }
 
@@ -701,15 +750,16 @@ void nsJSONListener::Cleanup()
 }
 
 nsresult
 nsJSONListener::Consume(const PRUnichar* aBuffer, PRUint32 aByteLength)
 {
   if (!mJSONParser)
     return NS_ERROR_FAILURE;
 
-  if (!JS_ConsumeJSONText(mCx, mJSONParser, (jschar*) aBuffer, aByteLength)) {
+  if (!js_ConsumeJSONText(mCx, mJSONParser, (jschar*) aBuffer, aByteLength,
+                          mDecodingMode)) {
     Cleanup();
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
--- a/dom/src/json/nsJSON.h
+++ b/dom/src/json/nsJSON.h
@@ -35,16 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsJSON_h__
 #define nsJSON_h__
 
 #include "jsapi.h"
+#include "json.h"
 #include "nsIJSON.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIOutputStream.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsIRequestObserver.h"
 #include "nsIStreamListener.h"
@@ -81,41 +82,45 @@ public:
   nsJSON();
   virtual ~nsJSON();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIJSON
 
 protected:
   nsresult EncodeInternal(nsJSONWriter *writer);
+
   nsresult DecodeInternal(nsIInputStream *aStream,
                           PRInt32 aContentLength,
-                          PRBool aNeedsConverter);
+                          PRBool aNeedsConverter,
+                          DecodingMode mode = STRICT);
   nsCOMPtr<nsIURI> mURI;
 };
 
 nsresult
 NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
 class nsJSONListener : public nsIStreamListener
 {
 public:
-  nsJSONListener(JSContext *cx, jsval *rootVal, PRBool needsConverter);
+  nsJSONListener(JSContext *cx, jsval *rootVal, PRBool needsConverter,
+                 DecodingMode mode);
   virtual ~nsJSONListener();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
 
 protected:
   PRBool mNeedsConverter;
   JSONParser *mJSONParser;
   JSContext *mCx;
   jsval *mRootVal;
   nsCOMPtr<nsIUnicodeDecoder> mDecoder;
   nsCString mSniffBuffer;
+  DecodingMode mDecodingMode;
   nsresult ProcessBytes(const char* aBuffer, PRUint32 aByteLength);
   nsresult ConsumeConverted(const char* aBuffer, PRUint32 aByteLength);
   nsresult Consume(const PRUnichar *data, PRUint32 len);
   void Cleanup();
 };
 
 #endif
--- a/dom/src/json/test/unit/test_decode.js
+++ b/dom/src/json/test/unit/test_decode.js
@@ -162,39 +162,32 @@ function test_files() {
   //
   // Section 4 of RFC 4627 allows this tolerance.
   //
   for (var i = 1; i <= 34; ++i) {
     var path = "fail" + i + ".json";
     try {
       dump(path +"\n");
       x = read_file(path);
-      if (i == 4) {
-        // ["extra comma",]
-        do_check_eq(x[0], "extra comma");
-        do_check_eq(x.length, 1);
-      } else if (i == 9) {
-        // {"Extra comma": true,}
-        do_check_eq(x["Extra comma"], true);
-      } else if (i == 13) {
+      if (i == 13) {
         // {"Numbers cannot have leading zeroes": 013}
         do_check_eq(x["Numbers cannot have leading zeroes"], 13);
       } else if (i == 18) {
         // [[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
         var t = x[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0];
         do_check_eq(t, "Too deep");
       } else {
 
         do_throw("UNREACHED");
 
       }
 
     } catch (ex) {
       // expected from parsing invalid JSON
-      if (i == 4 || i == 9 || i == 13 || i == 18) {
+      if (i == 13 || i == 18) {
         do_throw("Unexpected pass in " + path);
       }
     }
   }
   
 }
 
 function run_test() {
--- a/dom/src/threads/nsDOMThreadService.cpp
+++ b/dom/src/threads/nsDOMThreadService.cpp
@@ -390,45 +390,51 @@ public:
     JS_SetContextPrivate(cx, mWorker);
 
     // Go ahead and trigger the operation callback for this context before we
     // try to run any JS. That way we'll be sure to cancel or suspend as soon as
     // possible if the compilation takes too long.
     JS_TriggerOperationCallback(cx);
 
     PRBool killWorkerWhenDone;
-
-    // Tell the worker which context it will be using
-    if (mWorker->SetGlobalForContext(cx)) {
-      RunQueue(cx, &killWorkerWhenDone);
-
-      // Code in XPConnect assumes that the context's global object won't be
-      // replaced outside of a request.
-      JSAutoRequest ar(cx);
+    {
+      nsLazyAutoRequest ar;
+      JSAutoCrossCompartmentCall axcc;
 
-      // Remove the global object from the context so that it might be garbage
-      // collected.
-      JS_SetGlobalObject(cx, NULL);
-      JS_SetContextPrivate(cx, NULL);
-    }
-    else {
-      {
-        // Code in XPConnect assumes that the context's global object won't be
-        // replaced outside of a request.
-        JSAutoRequest ar(cx);
+      // Tell the worker which context it will be using
+      if (mWorker->SetGlobalForContext(cx, &ar, &axcc)) {
+        NS_ASSERTION(ar.entered(), "SetGlobalForContext must enter request on success");
+        NS_ASSERTION(axcc.entered(), "SetGlobalForContext must enter xcc on success");
 
-        // This is usually due to a parse error in the worker script...
+        RunQueue(cx, &killWorkerWhenDone);
+
+        // Remove the global object from the context so that it might be garbage
+        // collected.
         JS_SetGlobalObject(cx, NULL);
         JS_SetContextPrivate(cx, NULL);
       }
+      else {
+        NS_ASSERTION(!ar.entered(), "SetGlobalForContext must not enter request on failure");
+        NS_ASSERTION(!axcc.entered(), "SetGlobalForContext must not enter xcc on failure");
 
-      nsAutoMonitor mon(gDOMThreadService->mMonitor);
-      killWorkerWhenDone = mKillWorkerWhenDone;
-      gDOMThreadService->WorkerComplete(this);
-      mon.NotifyAll();
+        {
+          // Code in XPConnect assumes that the context's global object won't be
+          // replaced outside of a request.
+          JSAutoRequest ar2(cx);
+
+          // This is usually due to a parse error in the worker script...
+          JS_SetGlobalObject(cx, NULL);
+          JS_SetContextPrivate(cx, NULL);
+        }
+
+        nsAutoMonitor mon(gDOMThreadService->mMonitor);
+        killWorkerWhenDone = mKillWorkerWhenDone;
+        gDOMThreadService->WorkerComplete(this);
+        mon.NotifyAll();
+      }
     }
 
     if (killWorkerWhenDone) {
       nsCOMPtr<nsIRunnable> runnable = new nsDOMWorkerKillRunnable(mWorker);
       NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
 
       nsresult rv = NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
       NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -70,122 +70,111 @@
 
 class nsDOMWorkerFunctions
 {
 public:
   typedef nsDOMWorker::WorkerPrivilegeModel WorkerPrivilegeModel;
 
   // Same as window.dump().
   static JSBool
-  Dump(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv, jsval* aRval);
+  Dump(JSContext* aCx, uintN aArgc, jsval* aVp);
 
   // Same as window.setTimeout().
   static JSBool
-  SetTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-             jsval* aRval) {
-    return MakeTimeout(aCx, aObj, aArgc, aArgv, aRval, PR_FALSE);
+  SetTimeout(JSContext* aCx, uintN aArgc, jsval* aVp) {
+    return MakeTimeout(aCx, aArgc, aVp, PR_FALSE);
   }
 
   // Same as window.setInterval().
   static JSBool
-  SetInterval(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-              jsval* aRval) {
-    return MakeTimeout(aCx, aObj, aArgc, aArgv, aRval, PR_TRUE);
+  SetInterval(JSContext* aCx, uintN aArgc, jsval* aVp) {
+    return MakeTimeout(aCx, aArgc, aVp, PR_TRUE);
   }
 
   // Used for both clearTimeout() and clearInterval().
   static JSBool
-  KillTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-              jsval* aRval);
+  KillTimeout(JSContext* aCx, uintN aArgc, jsval* aVp);
 
   static JSBool
-  LoadScripts(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-              jsval* aRval);
+  LoadScripts(JSContext* aCx, uintN aArgc, jsval* aVp);
 
   static JSBool
-  NewXMLHttpRequest(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-                    jsval* aRval);
+  NewXMLHttpRequest(JSContext* aCx, uintN aArgc, jsval* aVp);
 
   static JSBool
-  NewWorker(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-            jsval* aRval) {
-    return MakeNewWorker(aCx, aObj, aArgc, aArgv, aRval, nsDOMWorker::CONTENT);
+  NewWorker(JSContext* aCx, uintN aArgc, jsval* aVp) {
+    return MakeNewWorker(aCx, aArgc, aVp, nsDOMWorker::CONTENT);
   }
 
   // Chrome-only functions
   static JSBool
-  NewChromeWorker(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-                  jsval* aRval);
+  NewChromeWorker(JSContext* aCx, uintN aArgc, jsval* aVp);
 
 #ifdef BUILD_CTYPES
   static JSBool
   CTypesLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp);
 #endif
 
 private:
   // Internal helper for SetTimeout and SetInterval.
   static JSBool
-  MakeTimeout(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-              jsval* aRval, PRBool aIsInterval);
+  MakeTimeout(JSContext* aCx, uintN aArgc, jsval* aVp, PRBool aIsInterval);
 
   static JSBool
-  MakeNewWorker(JSContext* aCx, JSObject* aObj, uintN aArgc, jsval* aArgv,
-                jsval* aRval, WorkerPrivilegeModel aPrivilegeModel);
+  MakeNewWorker(JSContext* aCx, uintN aArgc, jsval* aVp,
+                WorkerPrivilegeModel aPrivilegeModel);
 };
 
 JSBool
 nsDOMWorkerFunctions::Dump(JSContext* aCx,
-                           JSObject* /* aObj */,
                            uintN aArgc,
-                           jsval* aArgv,
-                           jsval* /* aRval */)
+                           jsval* aVp)
 {
+  JS_SET_RVAL(cx, aVp, JSVAL_VOID);
   if (!nsGlobalWindow::DOMWindowDumpEnabled()) {
     return JS_TRUE;
   }
 
   JSString* str;
-  if (aArgc && (str = JS_ValueToString(aCx, aArgv[0])) && str) {
+  if (aArgc && (str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0])) && str) {
     nsDependentJSString string(str);
     fputs(NS_ConvertUTF16toUTF8(nsDependentJSString(str)).get(), stderr);
     fflush(stderr);
   }
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::MakeTimeout(JSContext* aCx,
-                                  JSObject* /* aObj */,
                                   uintN aArgc,
-                                  jsval* aArgv,
-                                  jsval* aRval,
+                                  jsval* aVp,
                                   PRBool aIsInterval)
 {
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   PRUint32 id = worker->NextTimeoutId();
 
   if (worker->IsClosing()) {
     // Timeouts won't run in the close handler, fake success and bail.
-    *aRval = INT_TO_JSVAL(id);
+    JS_SET_RVAL(aCx, aVp, INT_TO_JSVAL(id));
     return JS_TRUE;
   }
 
   nsRefPtr<nsDOMWorkerTimeout> timeout = new nsDOMWorkerTimeout(worker, id);
   if (!timeout) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
-  nsresult rv = timeout->Init(aCx, aArgc, aArgv, aIsInterval);
+  nsresult rv = timeout->Init(aCx, aArgc, JS_ARGV(aCx, aVp), aIsInterval);
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to initialize timeout!");
     return JS_FALSE;
   }
 
   rv = worker->AddFeature(timeout, aCx);
   if (NS_FAILED(rv)) {
     JS_ReportOutOfMemory(aCx);
@@ -193,55 +182,52 @@ nsDOMWorkerFunctions::MakeTimeout(JSCont
   }
 
   rv = timeout->Start();
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to start timeout!");
     return JS_FALSE;
   }
 
-  *aRval = INT_TO_JSVAL(id);
+  JS_SET_RVAL(aCx, aVp, INT_TO_JSVAL(id));
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::KillTimeout(JSContext* aCx,
-                                  JSObject* /* aObj */,
                                   uintN aArgc,
-                                  jsval* aArgv,
-                                  jsval* /* aRval */)
+                                  jsval* aVp)
 {
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   if (!aArgc) {
     JS_ReportError(aCx, "Function requires at least 1 parameter");
     return JS_FALSE;
   }
 
   uint32 id;
-  if (!JS_ValueToECMAUint32(aCx, aArgv[0], &id)) {
+  if (!JS_ValueToECMAUint32(aCx, JS_ARGV(aCx, aVp)[0], &id)) {
     JS_ReportError(aCx, "First argument must be a timeout id");
     return JS_FALSE;
   }
 
   worker->CancelTimeoutWithId(PRUint32(id));
+  JS_SET_RVAL(aCx, aVp, JSVAL_VOID);
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::LoadScripts(JSContext* aCx,
-                                  JSObject* /* aObj */,
                                   uintN aArgc,
-                                  jsval* aArgv,
-                                  jsval* /* aRval */)
+                                  jsval* aVp)
 {
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
@@ -252,18 +238,19 @@ nsDOMWorkerFunctions::LoadScripts(JSCont
 
   nsAutoTArray<nsString, 10> urls;
 
   if (!urls.SetCapacity((PRUint32)aArgc)) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
+  jsval* argv = JS_ARGV(aCx, aVp);
   for (uintN index = 0; index < aArgc; index++) {
-    jsval val = aArgv[index];
+    jsval val = argv[index];
 
     if (!JSVAL_IS_STRING(val)) {
       JS_ReportError(aCx, "Argument %d must be a string", index);
       return JS_FALSE;
     }
 
     JSString* str = JS_ValueToString(aCx, val);
     if (!str) {
@@ -293,26 +280,30 @@ nsDOMWorkerFunctions::LoadScripts(JSCont
   rv = loader->LoadScripts(aCx, urls, PR_FALSE);
   if (NS_FAILED(rv)) {
     if (!JS_IsExceptionPending(aCx)) {
       JS_ReportError(aCx, "Failed to load scripts");
     }
     return JS_FALSE;
   }
 
+  JS_SET_RVAL(aCx, aVp, JSVAL_VOID);
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::NewXMLHttpRequest(JSContext* aCx,
-                                        JSObject* aObj,
                                         uintN aArgc,
-                                        jsval* /* aArgv */,
-                                        jsval* aRval)
+                                        jsval* aVp)
 {
+  JSObject *obj = JS_THIS_OBJECT(aCx, aVp);
+  if (!obj) {
+    return JS_FALSE;
+  }
+
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   if (aArgc) {
@@ -335,54 +326,55 @@ nsDOMWorkerFunctions::NewXMLHttpRequest(
   rv = worker->AddFeature(xhr, aCx);
   if (NS_FAILED(rv)) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> xhrWrapped;
   jsval v;
-  rv = nsContentUtils::WrapNative(aCx, aObj,
+  rv = nsContentUtils::WrapNative(aCx, obj,
                                   static_cast<nsIXMLHttpRequest*>(xhr), &v,
                                   getter_AddRefs(xhrWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap XMLHttpRequest!");
     return JS_FALSE;
   }
 
-  *aRval = v;
+  JS_SET_RVAL(aCs, aVp, v);
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::NewChromeWorker(JSContext* aCx,
-                                      JSObject* aObj,
                                       uintN aArgc,
-                                      jsval* aArgv,
-                                      jsval* aRval)
+                                      jsval* aVp)
 {
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (!worker->IsPrivileged()) {
     JS_ReportError(aCx, "Cannot create a priviliged worker!");
     return JS_FALSE;
   }
 
-  return MakeNewWorker(aCx, aObj, aArgc, aArgv, aRval, nsDOMWorker::CHROME);
+  return MakeNewWorker(aCx, aArgc, aVp, nsDOMWorker::CHROME);
 }
 
 JSBool
 nsDOMWorkerFunctions::MakeNewWorker(JSContext* aCx,
-                                    JSObject* aObj,
                                     uintN aArgc,
-                                    jsval* aArgv,
-                                    jsval* aRval,
+                                    jsval* aVp,
                                     WorkerPrivilegeModel aPrivilegeModel)
 {
+  JSObject *obj = JS_THIS_OBJECT(aCx, aVp);
+  if (!obj) {
+    return JS_FALSE;
+  }
+
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   if (!aArgc) {
@@ -407,32 +399,33 @@ nsDOMWorkerFunctions::MakeNewWorker(JSCo
 
   nsRefPtr<nsDOMWorker> newWorker =
     new nsDOMWorker(worker, wrappedWorker, aPrivilegeModel);
   if (!newWorker) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
-  nsresult rv = newWorker->InitializeInternal(owner, aCx, aObj, aArgc, aArgv);
+  nsresult rv = newWorker->InitializeInternal(owner, aCx, obj, aArgc,
+                                              JS_ARGV(aCx, aVp));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Couldn't initialize new worker!");
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> workerWrapped;
   jsval v;
-  rv = nsContentUtils::WrapNative(aCx, aObj, static_cast<nsIWorker*>(newWorker),
+  rv = nsContentUtils::WrapNative(aCx, obj, static_cast<nsIWorker*>(newWorker),
                                   &v, getter_AddRefs(workerWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap new worker!");
     return JS_FALSE;
   }
 
-  *aRval = v;
+  JS_SET_RVAL(aCx, aVp, v);
   return JS_TRUE;
 }
 
 #ifdef BUILD_CTYPES
 JSBool
 nsDOMWorkerFunctions::CTypesLazyGetter(JSContext* aCx,
                                        JSObject* aObj,
                                        jsid aId,
@@ -456,36 +449,36 @@ nsDOMWorkerFunctions::CTypesLazyGetter(J
 
   return JS_DeletePropertyById(aCx, aObj, aId) &&
          JS_InitCTypesClass(aCx, aObj) &&
          JS_GetPropertyById(aCx, aObj, aId, aVp);
 }
 #endif
 
 JSFunctionSpec gDOMWorkerFunctions[] = {
-  { "dump",                nsDOMWorkerFunctions::Dump,                1, 0, 0 },
-  { "setTimeout",          nsDOMWorkerFunctions::SetTimeout,          1, 0, 0 },
-  { "clearTimeout",        nsDOMWorkerFunctions::KillTimeout,         1, 0, 0 },
-  { "setInterval",         nsDOMWorkerFunctions::SetInterval,         1, 0, 0 },
-  { "clearInterval",       nsDOMWorkerFunctions::KillTimeout,         1, 0, 0 },
-  { "importScripts",       nsDOMWorkerFunctions::LoadScripts,         1, 0, 0 },
-  { "XMLHttpRequest",      nsDOMWorkerFunctions::NewXMLHttpRequest,   0, 0, 0 },
-  { "Worker",              nsDOMWorkerFunctions::NewWorker,           1, 0, 0 },
+  { "dump",                nsDOMWorkerFunctions::Dump,                1, 0 },
+  { "setTimeout",          nsDOMWorkerFunctions::SetTimeout,          1, 0 },
+  { "clearTimeout",        nsDOMWorkerFunctions::KillTimeout,         1, 0 },
+  { "setInterval",         nsDOMWorkerFunctions::SetInterval,         1, 0 },
+  { "clearInterval",       nsDOMWorkerFunctions::KillTimeout,         1, 0 },
+  { "importScripts",       nsDOMWorkerFunctions::LoadScripts,         1, 0 },
+  { "XMLHttpRequest",      nsDOMWorkerFunctions::NewXMLHttpRequest,   0, 0 },
+  { "Worker",              nsDOMWorkerFunctions::NewWorker,           1, 0 },
 #ifdef MOZ_SHARK
-  { "startShark",          js_StartShark,                             0, 0, 0 },
-  { "stopShark",           js_StopShark,                              0, 0, 0 },
-  { "connectShark",        js_ConnectShark,                           0, 0, 0 },
-  { "disconnectShark",     js_DisconnectShark,                        0, 0, 0 },
+  { "startShark",          js_StartShark,                             0, 0 },
+  { "stopShark",           js_StopShark,                              0, 0 },
+  { "connectShark",        js_ConnectShark,                           0, 0 },
+  { "disconnectShark",     js_DisconnectShark,                        0, 0 },
 #endif
-  { nsnull,                nsnull,                                    0, 0, 0 }
+  { nsnull,                nsnull,                                    0, 0 }
 };
 
 JSFunctionSpec gDOMWorkerChromeFunctions[] = {
-  { "ChromeWorker",        nsDOMWorkerFunctions::NewChromeWorker,     1, 0, 0 },
-  { nsnull,                nsnull,                                    0, 0, 0 }
+  { "ChromeWorker",        nsDOMWorkerFunctions::NewChromeWorker,     1, 0 },
+  { nsnull,                nsnull,                                    0, 0 }
 };
 
 nsDOMWorkerScope::nsDOMWorkerScope(nsDOMWorker* aWorker)
 : mWorker(aWorker),
   mWrappedNative(nsnull),
   mHasOnerror(PR_FALSE)
 {
   NS_ASSERTION(aWorker, "Null pointer!");
@@ -1562,49 +1555,62 @@ nsDOMWorker::PostMessageInternal(PRBool 
     rv = nsDOMThreadService::get()->Dispatch(target, runnable);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 PRBool
-nsDOMWorker::SetGlobalForContext(JSContext* aCx)
+nsDOMWorker::SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest,
+                                 JSAutoCrossCompartmentCall *aCall)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
-  if (!CompileGlobalObject(aCx)) {
+  if (!CompileGlobalObject(aCx, aRequest, aCall)) {
     return PR_FALSE;
   }
 
-  JSAutoRequest ar(aCx);
-
   JS_SetGlobalObject(aCx, mGlobal);
   return PR_TRUE;
 }
 
 PRBool
-nsDOMWorker::CompileGlobalObject(JSContext* aCx)
+nsDOMWorker::CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest,
+                                 JSAutoCrossCompartmentCall *aCall)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
+  // On success, we enter a request and a cross-compartment call that both
+  // belong to the caller. But on failure, we must not remain in a request or
+  // cross-compartment call. So we enter both only locally at first. On
+  // failure, the local request and call will automatically get cleaned
+  // up. Once success is certain, we swap them into *aRequest and *aCall.
+  nsLazyAutoRequest localRequest;
+  JSAutoCrossCompartmentCall localCall;
+  localRequest.enter(aCx);
+
+  PRBool success;
   if (mGlobal) {
+    success = localCall.enter(aCx, mGlobal);
+    NS_ENSURE_TRUE(success, PR_FALSE);
+
+    aRequest->swap(localRequest);
+    aCall->swap(localCall);
     return PR_TRUE;
   }
 
   if (mCompileAttempted) {
     // Don't try to recompile a bad script.
     return PR_FALSE;
   }
   mCompileAttempted = PR_TRUE;
 
   NS_ASSERTION(!mScriptURL.IsEmpty(), "Must have a url here!");
 
-  JSAutoRequest ar(aCx);
-
   NS_ASSERTION(!JS_GetGlobalObject(aCx), "Global object should be unset!");
 
   nsRefPtr<nsDOMWorkerScope> scope = new nsDOMWorkerScope(this);
   NS_ENSURE_TRUE(scope, PR_FALSE);
 
   nsISupports* scopeSupports = NS_ISUPPORTS_CAST(nsIWorkerScope*, scope);
 
   nsIXPConnect* xpc = nsContentUtils::XPConnect();
@@ -1624,28 +1630,31 @@ nsDOMWorker::CompileGlobalObject(JSConte
   NS_ENSURE_SUCCESS(rv, PR_FALSE);
 
   JSObject* global;
   rv = globalWrapper->GetJSObject(&global);
   NS_ENSURE_SUCCESS(rv, PR_FALSE);
 
   NS_ASSERTION(JS_GetGlobalObject(aCx) == global, "Global object mismatch!");
 
+  success = localCall.enter(aCx, global);
+  NS_ENSURE_TRUE(success, PR_FALSE);
+
 #ifdef DEBUG
   {
     jsval components;
     if (JS_GetProperty(aCx, global, "Components", &components)) {
       NS_ASSERTION(components == JSVAL_VOID,
                    "Components property still defined!");
     }
   }
 #endif
 
   // Set up worker thread functions.
-  PRBool success = JS_DefineFunctions(aCx, global, gDOMWorkerFunctions);
+  success = JS_DefineFunctions(aCx, global, gDOMWorkerFunctions);
   NS_ENSURE_TRUE(success, PR_FALSE);
 
   if (mPrivilegeModel == CHROME) {
     // Add chrome functions.
     success = JS_DefineFunctions(aCx, global, gDOMWorkerChromeFunctions);
     NS_ENSURE_TRUE(success, PR_FALSE);
 
 #ifdef BUILD_CTYPES
@@ -1692,16 +1701,18 @@ nsDOMWorker::CompileGlobalObject(JSConte
     mGlobal = NULL;
     mInnerScope = nsnull;
     mScopeWN = nsnull;
     return PR_FALSE;
   }
 
   NS_ASSERTION(mPrincipal && mURI, "Script loader didn't set our principal!");
 
+  aRequest->swap(localRequest);
+  aCall->swap(localCall);
   return PR_TRUE;
 }
 
 void
 nsDOMWorker::SetPool(nsDOMWorkerPool* aPool)
 {
   NS_ASSERTION(!mPool, "Shouldn't ever set pool more than once!");
   mPool = aPool;
--- a/dom/src/threads/nsDOMWorker.h
+++ b/dom/src/threads/nsDOMWorker.h
@@ -100,16 +100,43 @@ private:
   nsDOMWorker* mWorker;
   nsIXPConnectWrappedNative* mWrappedNative;
 
   nsRefPtr<nsDOMWorkerNavigator> mNavigator;
 
   PRPackedBool mHasOnerror;
 };
 
+class nsLazyAutoRequest
+{
+public:
+  nsLazyAutoRequest() : mCx(nsnull) {}
+
+  ~nsLazyAutoRequest() {
+    if (mCx)
+      JS_EndRequest(mCx);
+  }
+
+  void enter(JSContext *aCx) {
+    JS_BeginRequest(aCx);
+    mCx = aCx;
+  }
+
+  bool entered() const { return mCx != nsnull; }
+
+  void swap(nsLazyAutoRequest &other) {
+    JSContext *tmp = mCx;
+    mCx = other.mCx;
+    other.mCx = tmp;
+  }
+
+private:
+  JSContext *mCx;
+};
+
 class nsDOMWorker : public nsDOMWorkerMessageHandler,
                     public nsIChromeWorker,
                     public nsITimerCallback,
                     public nsIJSNativeInitializer,
                     public nsIXPCScriptable
 {
   friend class nsDOMWorkerFeature;
   friend class nsDOMWorkerFunctions;
@@ -169,17 +196,17 @@ public:
   void Resume();
 
   // This just calls IsCanceledNoLock with an autolock around the call.
   PRBool IsCanceled();
 
   PRBool IsClosing();
   PRBool IsSuspended();
 
-  PRBool SetGlobalForContext(JSContext* aCx);
+  PRBool SetGlobalForContext(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoCrossCompartmentCall *aCall);
 
   void SetPool(nsDOMWorkerPool* aPool);
 
   nsDOMWorkerPool* Pool() {
     return mPool;
   }
 
   PRLock* Lock() {
@@ -253,17 +280,17 @@ public:
     eKilled
   };
 
 private:
   ~nsDOMWorker();
 
   nsresult PostMessageInternal(PRBool aToInner);
 
-  PRBool CompileGlobalObject(JSContext* aCx);
+  PRBool CompileGlobalObject(JSContext* aCx, nsLazyAutoRequest *aRequest, JSAutoCrossCompartmentCall *aCall);
 
   PRUint32 NextTimeoutId() {
     return ++mNextTimeoutId;
   }
 
   nsresult AddFeature(nsDOMWorkerFeature* aFeature,
                       JSContext* aCx);
   void RemoveFeature(nsDOMWorkerFeature* aFeature,
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -135,17 +135,17 @@ ScriptErrorReporter(JSContext *cx,
     char *prefix = NULL, *tmp;
     const char *ctmp;
     JSStackFrame * fp = nsnull;
     nsCOMPtr<nsIXPConnect> xpc;
 
     // Don't report an exception from inner JS frames as the callers may intend
     // to handle it.
     while ((fp = JS_FrameIterator(cx, &fp))) {
-        if (!JS_IsNativeFrame(cx, fp)) {
+        if (JS_IsScriptFrame(cx, fp)) {
             return;
         }
     }
 
     // In some cases cx->fp is null here so use XPConnect to tell us about inner
     // frames.
     if ((xpc = do_GetService(nsIXPConnect::GetCID()))) {
         nsAXPCNativeCallContext *cc = nsnull;
@@ -238,34 +238,34 @@ ContextCallback(JSContext *cx,
         JS_SetErrorReporter(cx, ScriptErrorReporter);
         JS_SetVersion(cx, JSVERSION_LATEST);
     }
     return JS_TRUE;
 }
 
 static JSBool
 Print(JSContext *cx,
-      JSObject *obj,
       uintN argc,
-      jsval *argv,
-      jsval *rval)
+      jsval *vp)
 {
     uintN i, n;
     JSString *str;
 
+    jsval *argv = JS_ARGV(cx, vp);
     for (i = n = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         fprintf(stdout, "%s%s", i ? " " : "", JS_GetStringBytes(str));
         fflush(stdout);
     }
     n++;
     if (n)
         fputc('\n', stdout);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 GetLine(char *bufp,
         FILE *file,
         const char *prompt)
 {
@@ -275,49 +275,52 @@ GetLine(char *bufp,
     if (!fgets(line, sizeof line, file))
         return JS_FALSE;
     strcpy(bufp, line);
     return JS_TRUE;
 }
 
 static JSBool
 Dump(JSContext *cx,
-     JSObject *obj,
      uintN argc,
-     jsval *argv,
-     jsval *rval)
+     jsval *vp)
 {
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+
     JSString *str;
     if (!argc)
         return JS_TRUE;
 
-    str = JS_ValueToString(cx, argv[0]);
+    str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
 
     fputs(JS_GetStringBytes(str), stdout);
     fflush(stdout);
     return JS_TRUE;
 }
 
 static JSBool
 Load(JSContext *cx,
-     JSObject *obj,
      uintN argc,
-     jsval *argv,
-     jsval *rval)
+     jsval *vp)
 {
     uintN i;
     JSString *str;
     const char *filename;
     JSScript *script;
     JSBool ok;
     jsval result;
     FILE *file;
 
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
         filename = JS_GetStringBytes(str);
         file = fopen(filename, "r");
         if (!file) {
@@ -332,83 +335,78 @@ Load(JSContext *cx,
 
         ok = !Environment(cx)->ShouldCompileOnly()
              ? JS_ExecuteScript(cx, obj, script, &result)
              : JS_TRUE;
         JS_DestroyScript(cx, script);
         if (!ok)
             return JS_FALSE;
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 Version(JSContext *cx,
-        JSObject *obj,
         uintN argc,
-        jsval *argv,
-        jsval *rval)
+        jsval *vp)
 {
+    jsval *argv = JS_ARGV(cx, vp);
     if (argc > 0 && JSVAL_IS_INT(argv[0]))
-        *rval = INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(argv[0]))));
+        JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_SetVersion(cx, JSVersion(JSVAL_TO_INT(argv[0])))));
     else
-        *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+        JS_SET_RVAL(cx, vp, INT_TO_JSVAL(JS_GetVersion(cx)));
     return JS_TRUE;
 }
 
 static JSBool
-BuildDate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+BuildDate(JSContext *cx, uintN argc, jsval *vp)
 {
     fprintf(stdout, "built on %s at %s\n", __DATE__, __TIME__);
     return JS_TRUE;
 }
 
 static JSBool
 Quit(JSContext *cx,
-     JSObject *obj,
      uintN argc,
-     jsval *argv,
-     jsval *rval)
+     jsval *vp)
 {
     int exitCode = 0;
-    JS_ConvertArguments(cx, argc, argv, "/ i", &exitCode);
+    JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &exitCode);
 
     XPCShellEnvironment* env = Environment(cx);
     env->SetExitCode(exitCode);
     env->SetIsQuitting();
 
     return JS_FALSE;
 }
 
 static JSBool
 DumpXPC(JSContext *cx,
-        JSObject *obj,
         uintN argc,
-        jsval *argv,
-        jsval *rval)
+        jsval *vp)
 {
     int32 depth = 2;
 
     if (argc > 0) {
-        if (!JS_ValueToInt32(cx, argv[0], &depth))
+        if (!JS_ValueToInt32(cx, JS_ARGV(cx, vp)[0], &depth))
             return JS_FALSE;
     }
 
     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID());
     if(xpc)
         xpc->DebugDump((int16)depth);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 GC(JSContext *cx,
-   JSObject *obj,
    uintN argc,
-   jsval *argv,
-   jsval *rval)
+   jsval *vp)
 {
     JSRuntime *rt;
     uint32 preBytes;
 
     rt = cx->runtime;
     preBytes = rt->gcBytes;
     JS_GC(cx);
     fprintf(stdout, "before %lu, after %lu, break %08lx\n",
@@ -417,75 +415,76 @@ GC(JSContext *cx,
            (unsigned long)sbrk(0)
 #else
            0
 #endif
            );
 #ifdef JS_GCMETER
     js_DumpGCStats(rt, stdout);
 #endif
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 #ifdef DEBUG
 
 static JSBool
 DumpHeap(JSContext *cx,
-         JSObject *obj,
          uintN argc,
-         jsval *argv,
-         jsval *rval)
+         jsval *vp)
 {
     char *fileName = NULL;
     void* startThing = NULL;
     uint32 startTraceKind = 0;
     void *thingToFind = NULL;
     size_t maxDepth = (size_t)-1;
     void *thingToIgnore = NULL;
-    jsval *vp;
     FILE *dumpFile;
     JSBool ok;
 
-    vp = &argv[0];
-    if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
+    jsval *argv = JS_ARGV(cx, vp);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
+
+    vp = argv + 0;
+    if (argc > 0 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         JSString *str;
 
         str = JS_ValueToString(cx, *vp);
         if (!str)
             return JS_FALSE;
         *vp = STRING_TO_JSVAL(str);
         fileName = JS_GetStringBytes(str);
     }
 
-    vp = &argv[1];
-    if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
+    vp = argv + 1;
+    if (argc > 1 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         startThing = JSVAL_TO_TRACEABLE(*vp);
         startTraceKind = JSVAL_TRACE_KIND(*vp);
     }
 
-    vp = &argv[2];
-    if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
+    vp = argv + 2;
+    if (argc > 2 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         thingToFind = JSVAL_TO_TRACEABLE(*vp);
     }
 
-    vp = &argv[3];
-    if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
+    vp = argv + 3;
+    if (argc > 3 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         uint32 depth;
 
         if (!JS_ValueToECMAUint32(cx, *vp, &depth))
             return JS_FALSE;
         maxDepth = depth;
     }
 
-    vp = &argv[4];
-    if (*vp != JSVAL_NULL && *vp != JSVAL_VOID) {
+    vp = argv + 4;
+    if (argc > 4 && *vp != JSVAL_NULL && *vp != JSVAL_VOID) {
         if (!JSVAL_IS_TRACEABLE(*vp))
             goto not_traceable_arg;
         thingToIgnore = JSVAL_TO_TRACEABLE(*vp);
     }
 
     if (!fileName) {
         dumpFile = stdout;
     } else {
@@ -509,87 +508,68 @@ DumpHeap(JSContext *cx,
             (unsigned)(vp - argv));
     return JS_FALSE;
 }
 
 #endif /* DEBUG */
 
 static JSBool
 Clear(JSContext *cx,
-      JSObject *obj,
       uintN argc,
-      jsval *argv,
-      jsval *rval)
+      jsval *vp)
 {
+    jsval *argv = JS_ARGV(cx, vp);
     if (argc > 0 && !JSVAL_IS_PRIMITIVE(argv[0])) {
         JS_ClearScope(cx, JSVAL_TO_OBJECT(argv[0]));
     } else {
         JS_ReportError(cx, "'clear' requires an object");
         return JS_FALSE;
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JSFunctionSpec gGlobalFunctions[] =
 {
-    {"print",           Print,          0,0,0},
-    {"load",            Load,           1,0,0},
-    {"quit",            Quit,           0,0,0},
-    {"version",         Version,        1,0,0},
-    {"build",           BuildDate,      0,0,0},
-    {"dumpXPC",         DumpXPC,        1,0,0},
-    {"dump",            Dump,           1,0,0},
-    {"gc",              GC,             0,0,0},
-    {"clear",           Clear,          1,0,0},
+    {"print",           Print,          0,0},
+    {"load",            Load,           1,0},
+    {"quit",            Quit,           0,0},
+    {"version",         Version,        1,0},
+    {"build",           BuildDate,      0,0},
+    {"dumpXPC",         DumpXPC,        1,0},
+    {"dump",            Dump,           1,0},
+    {"gc",              GC,             0,0},
+    {"clear",           Clear,          1,0},
 #ifdef DEBUG
-    {"dumpHeap",        DumpHeap,       5,0,0},
+    {"dumpHeap",        DumpHeap,       5,0},
 #endif
 #ifdef MOZ_SHARK
-    {"startShark",      js_StartShark,      0,0,0},
-    {"stopShark",       js_StopShark,       0,0,0},
-    {"connectShark",    js_ConnectShark,    0,0,0},
-    {"disconnectShark", js_DisconnectShark, 0,0,0},
+    {"startShark",      js_StartShark,      0,0},
+    {"stopShark",       js_StopShark,       0,0},
+    {"connectShark",    js_ConnectShark,    0,0},
+    {"disconnectShark", js_DisconnectShark, 0,0},
 #endif
 #ifdef MOZ_CALLGRIND
-    {"startCallgrind",  js_StartCallgrind,  0,0,0},
-    {"stopCallgrind",   js_StopCallgrind,   0,0,0},
-    {"dumpCallgrind",   js_DumpCallgrind,   1,0,0},
+    {"startCallgrind",  js_StartCallgrind,  0,0},
+    {"stopCallgrind",   js_StopCallgrind,   0,0},
+    {"dumpCallgrind",   js_DumpCallgrind,   1,0},
 #endif
-    {nsnull,nsnull,0,0,0}
+    {nsnull,nsnull,0,0}
 };
 
 typedef enum JSShellErrNum
 {
 #define MSG_DEF(name, number, count, exception, format) \
     name = number,
 #include "jsshell.msg"
 #undef MSG_DEF
     JSShellErr_Limit
 #undef MSGDEF
 } JSShellErrNum;
 
-JSErrorFormatString gErrorFormatString[JSErr_Limit] =
-{
-#define MSG_DEF(name, number, count, exception, format) \
-    { format, count } ,
-#include "jsshell.msg"
-#undef MSG_DEF
-};
-
-static const JSErrorFormatString *
-GetErrorMessage(void *userRef,
-                const char *locale,
-                const uintN errorNumber)
-{
-    if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
-        return &gErrorFormatString[errorNumber];
-
-    return NULL;
-}
-
 static void
 ProcessFile(JSContext *cx,
             JSObject *obj,
             const char *filename,
             FILE *file,
             JSBool forceTTY)
 {
     XPCShellEnvironment* env = Environment(cx);
--- a/js/ipc/ObjectWrapperParent.cpp
+++ b/js/ipc/ObjectWrapperParent.cpp
@@ -637,76 +637,78 @@ ObjectWrapperParent::CPOW_Finalize(JSCon
     ObjectWrapperParent* self = Unwrap(cx, obj);
     if (self) {
         self->mObj = NULL;
         unused << ObjectWrapperParent::Send__delete__(self);
     }
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_Call(JSContext* cx, JSObject* obj, uintN argc,
-                               jsval* argv, jsval* rval)
+ObjectWrapperParent::CPOW_Call(JSContext* cx, uintN argc, jsval* vp)
 {
     CPOW_LOG(("Calling CPOW_Call..."));
 
+    JSObject* thisobj = JS_THIS_OBJECT(cx, vp);
+    if (!thisobj)
+        return JS_FALSE;
+
     ObjectWrapperParent* function =
-        Unwrap(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)));
+        Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!function)
         return with_error(cx, JS_FALSE, "Could not unwrap CPOW function");
 
     AutoCheckOperation aco(cx, function);
 
-    ObjectWrapperParent* receiver = Unwrap(cx, obj);
+    ObjectWrapperParent* receiver = Unwrap(cx, thisobj);
     if (!receiver) {
         // Substitute child global for parent global object.
         // TODO First make sure we're really replacing the global object?
         ContextWrapperParent* manager =
             static_cast<ContextWrapperParent*>(function->Manager());
         receiver = manager->GetGlobalObjectWrapper();
     }
 
     nsTArray<JSVariant> in_argv(argc);
+    jsval* argv = JS_ARGV(cx, vp);
     for (uintN i = 0; i < argc; i++)
         if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
             return JS_FALSE;
 
     JSVariant out_rval;
 
     return (function->Manager()->RequestRunToCompletion() &&
             function->CallCall(receiver, in_argv,
                                aco.StatusPtr(), &out_rval) &&
             aco.Ok() &&
-            jsval_from_JSVariant(cx, out_rval, rval));
+            jsval_from_JSVariant(cx, out_rval, vp));
 }
 
 /*static*/ JSBool
-ObjectWrapperParent::CPOW_Construct(JSContext *cx, JSObject *obj, uintN argc,
-                                    jsval *argv, jsval *rval)
+ObjectWrapperParent::CPOW_Construct(JSContext* cx, uintN argc, jsval* vp)
 {
     CPOW_LOG(("Calling CPOW_Construct..."));
     
-    ObjectWrapperParent* constructor =
-        Unwrap(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)));
+    ObjectWrapperParent* constructor = Unwrap(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
     if (!constructor)
         return with_error(cx, JS_FALSE, "Could not unwrap CPOW constructor function");
 
     AutoCheckOperation aco(cx, constructor);
 
     nsTArray<JSVariant> in_argv(argc);
+    jsval* argv = JS_ARGV(cx, vp);
     for (uintN i = 0; i < argc; i++)
         if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
             return JS_FALSE;
 
     PObjectWrapperParent* out_powp;
 
     return (constructor->Manager()->RequestRunToCompletion() &&
-            constructor->CallConstruct(in_argv,
-                                       aco.StatusPtr(), &out_powp) &&
+            constructor->CallConstruct(in_argv, aco.StatusPtr(), &out_powp) &&
             aco.Ok() &&
-            jsval_from_PObjectWrapperParent(cx, out_powp, rval));
+            jsval_from_PObjectWrapperParent(cx, out_powp, vp));
 }
 
 /*static*/ JSBool
 ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSObject *obj, const jsval *v,
                                       JSBool *bp)
 {
     CPOW_LOG(("Calling CPOW_HasInstance..."));
 
--- a/js/ipc/ObjectWrapperParent.h
+++ b/js/ipc/ObjectWrapperParent.h
@@ -113,22 +113,20 @@ private:
 
     static JSBool
     CPOW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
 
     static void
     CPOW_Finalize(JSContext* cx, JSObject* obj);
 
     static JSBool
-    CPOW_Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
-              jsval* rval);
+    CPOW_Call(JSContext* cx, uintN argc, jsval* vp);
 
     static JSBool
-    CPOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                   jsval *rval);
+    CPOW_Construct(JSContext *cx, uintN argc, jsval *vp);
     
     static JSBool
     CPOW_HasInstance(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
 
     static JSBool
     CPOW_Equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
 
     static bool jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to);
--- a/js/jetpack/Handle.h
+++ b/js/jetpack/Handle.h
@@ -342,18 +342,17 @@ Handle<BaseType>::sHandle_Properties[] =
   { "parent",  0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetParent,  NULL },
   { "isValid", 0, HANDLE_PROP_FLAGS | JSPROP_READONLY, GetIsValid, NULL },
   { "isRooted", 0, HANDLE_PROP_FLAGS, GetIsRooted, SetIsRooted },
   { 0, 0, 0, NULL, NULL }
 };
 
 #undef HANDLE_PROP_FLAGS
 
-#define HANDLE_FUN_FLAGS (JSFUN_FAST_NATIVE |   \
-                          JSPROP_READONLY |     \
+#define HANDLE_FUN_FLAGS (JSPROP_READONLY |     \
                           JSPROP_PERMANENT)
 
 template <class BaseType>
 const JSFunctionSpec
 Handle<BaseType>::sHandle_Functions[] = {
   JS_FN("invalidate",   Invalidate,   0, HANDLE_FUN_FLAGS),
   JS_FN("createHandle", CreateHandle, 0, HANDLE_FUN_FLAGS),
   JS_FS_END
--- a/js/jetpack/JetpackChild.cpp
+++ b/js/jetpack/JetpackChild.cpp
@@ -52,18 +52,17 @@ namespace jetpack {
 JetpackChild::JetpackChild()
 {
 }
 
 JetpackChild::~JetpackChild()
 {
 }
 
-#define IMPL_METHOD_FLAGS (JSFUN_FAST_NATIVE |  \
-                           JSPROP_ENUMERATE | \
+#define IMPL_METHOD_FLAGS (JSPROP_ENUMERATE | \
                            JSPROP_READONLY | \
                            JSPROP_PERMANENT)
 const JSFunctionSpec
 JetpackChild::sImplMethods[] = {
   JS_FN("sendMessage", SendMessage, 3, IMPL_METHOD_FLAGS),
   JS_FN("callMessage", CallMessage, 2, IMPL_METHOD_FLAGS),
   JS_FN("registerReceiver", RegisterReceiver, 2, IMPL_METHOD_FLAGS),
   JS_FN("unregisterReceiver", UnregisterReceiver, 2, IMPL_METHOD_FLAGS),
--- a/js/jsd/idl/jsdIDebuggerService.idl
+++ b/js/jsd/idl/jsdIDebuggerService.idl
@@ -788,20 +788,16 @@ interface jsdIStackFrame : jsdIEphemeral
     /** Internal use only. */
     [noscript] readonly attribute JSDContext        JSDContext;
     /** Internal use only. */
     [noscript] readonly attribute JSDThreadState    JSDThreadState;
     /** Internal use only. */
     [noscript] readonly attribute JSDStackFrameInfo JSDStackFrameInfo;
    
     /**
-     * True if stack frame represents a native frame.
-     */
-    readonly attribute boolean isNative;
-    /**
      * True if stack frame represents a frame created as a result of a debugger
      * evaluation.
      */
     readonly attribute boolean isDebugger;
     /**
      * True if stack frame is constructing a new object.
      */
     readonly attribute boolean isConstructing;
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -703,21 +703,16 @@ jsd_GetCallObjectForStackFrame(JSDContex
                                JSDStackFrameInfo* jsdframe);
 
 extern JSDValue*
 jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
                                JSDThreadState* jsdthreadstate,
                                JSDStackFrameInfo* jsdframe);
 
 extern JSBool
-jsd_IsStackFrameNative(JSDContext* jsdc, 
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe);
-
-extern JSBool
 jsd_IsStackFrameDebugger(JSDContext* jsdc, 
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe);
 
 extern JSBool
 jsd_IsStackFrameConstructing(JSDContext* jsdc, 
                              JSDThreadState* jsdthreadstate,
                              JSDStackFrameInfo* jsdframe);
--- a/js/jsd/jsd_obj.c
+++ b/js/jsd/jsd_obj.c
@@ -139,17 +139,17 @@ jsd_Constructing(JSDContext* jsdc, JSCon
     JSDObject* jsdobj;
     JSScript* script;
     JSDScript* jsdscript;
     const char* ctorURL;
     const char* ctorName;
 
     JSD_LOCK_OBJECTS(jsdc);
     jsdobj = jsd_GetJSDObjectForJSObject(jsdc, obj);
-    if( jsdobj && !jsdobj->ctorURL && !JS_IsNativeFrame(cx, fp) )
+    if( jsdobj && !jsdobj->ctorURL && JS_IsScriptFrame(cx, fp) )
     {
         script = JS_GetFrameScript(cx, fp);
         if( script )
         {
             ctorURL = JS_GetScriptFilename(cx, script);
             if( ctorURL )
                 jsdobj->ctorURL = jsd_AddAtom(jsdc, ctorURL);
 
--- a/js/jsd/jsd_stak.c
+++ b/js/jsd/jsd_stak.c
@@ -60,17 +60,17 @@ static JSDStackFrameInfo*
              JSDThreadState*    jsdthreadstate,
              JSScript*          script,
              jsuword            pc,
              JSStackFrame*      fp)
 {
     JSDStackFrameInfo* jsdframe;
     JSDScript*         jsdscript = NULL;
 
-    if (!JS_IsNativeFrame(jsdthreadstate->context, fp))
+    if (JS_IsScriptFrame(jsdthreadstate->context, fp))
     {
         JSD_LOCK_SCRIPTS(jsdc);
         jsdscript = jsd_FindJSDScript(jsdc, script);
         JSD_UNLOCK_SCRIPTS(jsdc);
         if (!jsdscript || (jsdc->flags & JSD_HIDE_DISABLED_FRAMES &&
                            !JSD_IS_DEBUG_ENABLED(jsdc, jsdscript)))
         {
             return NULL;
@@ -128,17 +128,17 @@ jsd_NewThreadState(JSDContext* jsdc, JSC
 
         /*
          * don't construct a JSDStackFrame for dummy frames (those without a
          * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
          * isn't set.
          */
         if (JS_GetFrameThis(cx, fp) &&
             ((jsdc->flags & JSD_INCLUDE_NATIVE_FRAMES) ||
-             !JS_IsNativeFrame(cx, fp)))
+             JS_IsScriptFrame(cx, fp)))
         {
             JSDStackFrameInfo *frame;
 
             frame = _addNewFrame( jsdc, jsdthreadstate, script, pc, fp );
 
             if ((jsdthreadstate->stackDepth == 0 && !frame) ||
                 (jsdthreadstate->stackDepth == 1 && frame &&
                  frame->jsdscript && !JSD_IS_DEBUG_ENABLED(jsdc, frame->jsdscript)))
@@ -370,38 +370,16 @@ jsd_GetNameForStackFrame(JSDContext* jsd
             rv = JS_GetFunctionName (fun);
     }
     
     JSD_UNLOCK_THREADSTATES(jsdc);
     return rv;
 }
 
 JSBool
-jsd_IsStackFrameNative(JSDContext* jsdc, 
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe)
-{
-    JSBool rv;
-    
-    JSD_LOCK_THREADSTATES(jsdc);
-
-    if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
-    {
-        rv = JS_IsNativeFrame(jsdthreadstate->context, jsdframe->fp);
-    }
-    else
-    {
-        rv = JS_FALSE;
-    }
-
-    JSD_UNLOCK_THREADSTATES(jsdc);
-    return rv;
-}
-
-JSBool
 jsd_IsStackFrameDebugger(JSDContext* jsdc, 
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe)
 {
     JSBool rv = JS_TRUE;
     JSD_LOCK_THREADSTATES(jsdc);
 
     if( jsd_IsValidFrameInThreadState(jsdc, jsdthreadstate, jsdframe) )
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -1836,24 +1836,16 @@ NS_IMETHODIMP
 jsdStackFrame::GetFunctionName(nsACString &_rval)
 {
     ASSERT_VALID_EPHEMERAL;
     _rval.Assign(JSD_GetNameForStackFrame(mCx, mThreadState, mStackFrameInfo));
     return NS_OK;
 }
 
 NS_IMETHODIMP
-jsdStackFrame::GetIsNative(PRBool *_rval)
-{
-    ASSERT_VALID_EPHEMERAL;
-    *_rval = JSD_IsStackFrameNative (mCx, mThreadState, mStackFrameInfo);
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 jsdStackFrame::GetIsDebugger(PRBool *_rval)
 {
     ASSERT_VALID_EPHEMERAL;
     *_rval = JSD_IsStackFrameDebugger (mCx, mThreadState, mStackFrameInfo);
     return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1897,19 +1889,17 @@ jsdStackFrame::GetLine(PRUint32 *_rval)
 {
     ASSERT_VALID_EPHEMERAL;
     JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
                                                     mStackFrameInfo);
     if (script) {
         jsuword pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
         *_rval = JSD_GetClosestLine (mCx, script, pc);
     } else {
-        if (!JSD_IsStackFrameNative(mCx, mThreadState, mStackFrameInfo))
-            return NS_ERROR_FAILURE;
-        *_rval = 1;
+        return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
 jsdStackFrame::GetCallee(jsdIValue **_rval)
 {
     ASSERT_VALID_EPHEMERAL;
--- a/js/jsd/jsdebug.c
+++ b/js/jsd/jsdebug.c
@@ -746,25 +746,16 @@ JSD_GetNameForStackFrame(JSDContext* jsd
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetNameForStackFrame(jsdc, jsdthreadstate, jsdframe);
 }
 
 JSD_PUBLIC_API(JSBool)
-JSD_IsStackFrameNative(JSDContext* jsdc,
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe)
-{
-    JSD_ASSERT_VALID_CONTEXT(jsdc);
-    return jsd_IsStackFrameNative(jsdc, jsdthreadstate, jsdframe);
-}
-
-JSD_PUBLIC_API(JSBool)
 JSD_IsStackFrameDebugger(JSDContext* jsdc,
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_IsStackFrameDebugger(jsdc, jsdthreadstate, jsdframe);
 }
 
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -946,24 +946,16 @@ JSD_GetThisForStackFrame(JSDContext* jsd
 * for native frames (without script objects.)
 */
 extern JSD_PUBLIC_API(const char*)
 JSD_GetNameForStackFrame(JSDContext* jsdc,
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe);
 
 /*
-* True if stack frame represents a native frame.
-*/
-extern JSD_PUBLIC_API(JSBool)
-JSD_IsStackFrameNative(JSDContext* jsdc,
-                       JSDThreadState* jsdthreadstate,
-                       JSDStackFrameInfo* jsdframe);
-
-/*
 * True if stack frame represents a frame created as a result of a debugger
 * evaluation.
 */
 extern JSD_PUBLIC_API(JSBool)
 JSD_IsStackFrameDebugger(JSDContext* jsdc,
                          JSDThreadState* jsdthreadstate,
                          JSDStackFrameInfo* jsdframe);
 
--- a/js/narcissus/jsdefs.js
+++ b/js/narcissus/jsdefs.js
@@ -39,20 +39,46 @@
  * Narcissus - JS implemented in JS.
  *
  * Well-known constants and lookup tables.  Many consts are generated from the
  * tokens table via eval to minimize redundancy, so consumers must be compiled
  * separately to take advantage of the simple switch-case constant propagation
  * done by SpiderMonkey.
  */
 
-Narcissus = {
-    options: { version: 185 },
-    hostGlobal: this
-};
+(function() {
+    var builderTypes = Object.create(null, {
+        "default": { value: function() {
+            return new narcissus.parser.DefaultBuilder;
+        } },
+        "ssa": { value: function() {
+            return new narcissus.parser.SSABuilder;
+        } }
+    });
+
+    var builderType;
+
+    var narcissus = {
+        options: {
+            version: 185,
+            get builderType() { return builderType },
+            set builderType(type) {
+                var ctor = builderTypes[type];
+
+                if (!ctor)
+                    throw new Error("expected builder type ('default' or 'ssa'), got " + type);
+
+                builderType = type;
+                narcissus.definitions.Builder = ctor;
+            }
+        },
+        hostGlobal: this
+    };
+    Narcissus = narcissus;
+})();
 
 Narcissus.definitions = (function() {
 
     var tokens = [
         // End of source.
         "END",
 
         // Operators and punctuators.  Some pair-wise order matters, e.g. (+, -)
@@ -265,12 +291,16 @@ Narcissus.definitions = (function() {
         opTypeNames: opTypeNames,
         keywords: keywords,
         tokenIds: tokenIds,
         consts: consts,
         assignOps: assignOps,
         defineGetter: defineGetter,
         defineProperty: defineProperty,
         isNativeCode: isNativeCode,
-        makePassthruHandler: makePassthruHandler
+        makePassthruHandler: makePassthruHandler,
+        Builder: function() {
+            throw new Error("no Builder type selected");
+        }
     };
 }());
 
+Narcissus.options.builderType = "default";
--- a/js/narcissus/jsexec.js
+++ b/js/narcissus/jsexec.js
@@ -80,17 +80,17 @@ Narcissus.interpreter = (function() {
 
             var x = ExecutionContext.current;
             var x2 = new ExecutionContext(EVAL_CODE);
             x2.thisObject = x.thisObject;
             x2.caller = x.caller;
             x2.callee = x.callee;
             x2.scope = x.scope;
             try {
-                x2.execute(parser.parse(new parser.DefaultBuilder, s));
+                x2.execute(parser.parse(new definitions.Builder, s));
                 return x2.result;
             } catch (e if e instanceof SyntaxError || isStackOverflow(e)) {
                 /*
                  * If we get an internal error during parsing we need to reify
                  * the exception as a Narcissus THROW.
                  *
                  * See bug 152646.
                  */
@@ -114,17 +114,17 @@ Narcissus.interpreter = (function() {
             }
 
             // XXX We want to pass a good file and line to the tokenizer.
             // Note the anonymous name to maintain parity with Spidermonkey.
             var t = new parser.Tokenizer("anonymous(" + p + ") {" + b + "}");
 
             // NB: Use the STATEMENT_FORM constant since we don't want to push this
             // function onto the fake compilation context.
-            var x = { builder: new parser.DefaultBuilder };
+            var x = { builder: new definitions.Builder };
             var f = parser.FunctionDefinition(t, x, false, parser.STATEMENT_FORM);
             var s = {object: global, parent: null};
             return newFunction(f,{scope:s});
         },
         Array: function (dummy) {
             // Array when called as a function acts as a constructor.
             return Array.apply(this, arguments);
         },
@@ -342,17 +342,18 @@ Narcissus.interpreter = (function() {
             for (i = 0, j = a.length; i < j; i++) {
                 u = a[i];
                 s = u.name;
                 if (u.readOnly && hasDirectProperty(t, s)) {
                     throw new TypeError("Redeclaration of const " + s,
                                         u.filename, u.lineno);
                 }
                 if (u.readOnly || !hasDirectProperty(t, s)) {
-                    definitions.defineProperty(t, s, undefined, x.type !== EVAL_CODE, u.readOnly);
+                    // Does not correctly handle 'const x;' -- see bug 592335.
+                    definitions.defineProperty(t, s, undefined, x.type !== EVAL_CODE, false);
                 }
             }
             // FALL THROUGH
 
           case BLOCK:
             for (i = 0, j = n.length; i < j; i++)
                 execute(n[i], x);
             break;
@@ -493,17 +494,18 @@ Narcissus.interpreter = (function() {
             }
             break;
 
           case THROW:
             x.result = getValue(execute(n.exception, x));
             throw THROW;
 
           case RETURN:
-            x.result = getValue(execute(n.value, x));
+            // Check for returns with no return value
+            x.result = n.value ? getValue(execute(n.value, x)) : undefined;
             throw RETURN;
 
           case WITH:
             r = execute(n.object, x);
             t = toObject(getValue(r), r, n.object);
             x.scope = {object: t, parent: x.scope};
             try {
                 execute(n.body, x);
@@ -1018,17 +1020,17 @@ Narcissus.interpreter = (function() {
         return function () { return f.__call__(this, arguments, x); };
     }
 
     function evaluate(s, f, l) {
         if (typeof s !== "string")
             return s;
 
         var x = new ExecutionContext(GLOBAL_CODE);
-        x.execute(parser.parse(new parser.DefaultBuilder, s, f, l));
+        x.execute(parser.parse(new definitions.Builder, s, f, l));
         return x.result;
     }
 
     // A read-eval-print-loop that roughly tracks the behavior of the js shell.
     function repl() {
 
         // Display a value similarly to the js shell.
         function display(x) {
@@ -1054,17 +1056,17 @@ Narcissus.interpreter = (function() {
         function string(x) {
             try {
                 return String(x);
             } catch (e) {
                 return "unknown (can't convert to string)";
             }
         }
 
-        var b = new parser.DefaultBuilder;
+        var b = new definitions.Builder;
         var x = new ExecutionContext(GLOBAL_CODE);
 
         ExecutionContext.current = x;
         for (;;) {
             x.result = undefined;
             putstr("njs> ");
             var line = readline();
             // If readline receives EOF it returns null.
--- a/js/narcissus/jsparse.js
+++ b/js/narcissus/jsparse.js
@@ -100,16 +100,27 @@ Narcissus.parser = (function() {
     /*
      * The vanilla AST builder.
      */
 
     function DefaultBuilder() {
         bindSubBuilders(this, DefaultBuilder.prototype);
     }
 
+    function pushDestructuringVarDecls(n, x) {
+        for (var i in n) {
+            var sub = n[i];
+            if (sub.type === IDENTIFIER) {
+                x.varDecls.push(sub);
+            } else {
+                pushDestructuringVarDecls(sub, x);
+            }
+        }
+    }
+
     function mkBinopBuilder(type) {
         return {
             build: !type ? function(t) { return new Node(t); }
                           : function(t) { return new Node(t, type); },
             addOperand: function(n, n2) { n.push(n2); },
             finish: function(n) { }
         };
     }
@@ -376,17 +387,19 @@ Narcissus.parser = (function() {
             },
 
             finish: function(n) {
             }
         },
 
         RETURN: {
             build: function(t) {
-                return new Node(t, RETURN);
+                var n = new Node(t, RETURN);
+                n.value = undefined;
+                return n;
             },
 
             setValue: function(n, e) {
                 n.value = e;
             },
 
             finish: function(n) {
             }
@@ -503,44 +516,62 @@ Narcissus.parser = (function() {
             }
         },
 
         VAR: {
             build: function(t) {
                 return new Node(t, VAR);
             },
 
+            addDestructuringDecl: function(n, n2, x) {
+                n.push(n2);
+                pushDestructuringVarDecls(n2.name.destructuredNames, x);
+            },
+
             addDecl: function(n, n2, x) {
                 n.push(n2);
+                x.varDecls.push(n2);
             },
 
             finish: function(n) {
             }
         },
 
         CONST: {
             build: function(t) {
-                return new Node(t, VAR);
+                return new Node(t, CONST);
+            },
+
+            addDestructuringDecl: function(n, n2, x) {
+                n.push(n2);
+                pushDestructuringVarDecls(n2.name.destructuredNames, x);
             },
 
             addDecl: function(n, n2, x) {
                 n.push(n2);
+                x.varDecls.push(n2);
             },
 
             finish: function(n) {
             }
         },
 
         LET: {
             build: function(t) {
                 return new Node(t, LET);
             },
 
+            addDestructuringDecl: function(n, n2, x) {
+                n.push(n2);
+                pushDestructuringVarDecls(n2.name.destructuredNames, x);
+            },
+
             addDecl: function(n, n2, x) {
                 n.push(n2);
+                x.varDecls.push(n2);
             },
 
             finish: function(n) {
             }
         },
 
         DECL: {
             build: function(t) {
@@ -560,17 +591,17 @@ Narcissus.parser = (function() {
             },
 
             finish: function(n) {
             }
         },
 
         LET_BLOCK: {
             build: function(t) {
-                var n = Node(t, LET_BLOCK);
+                var n = new Node(t, LET_BLOCK);
                 n.varDecls = [];
                 return n;
             },
 
             setVariables: function(n, n2) {
                 n.variables = n2;
             },
 
@@ -600,29 +631,16 @@ Narcissus.parser = (function() {
             addStatement: function(n, n2) {
                 n.push(n2);
             },
 
             finish: function(n) {
             }
         },
 
-        EXPRESSION: {
-            build: function(t, tt) {
-                return new Node(t, tt);
-            },
-
-            addOperand: function(n, n2) {
-                n.push(n2);
-            },
-
-            finish: function(n) {
-            }
-        },
-
         ASSIGN: {
             build: function(t) {
                 return new Node(t, ASSIGN);
             },
 
             addOperand: function(n, n2) {
                 n.push(n2);
             },
@@ -705,18 +723,18 @@ Narcissus.parser = (function() {
             },
 
             finish: function(n) {
             }
         },
 
         PRIMARY: {
             build: function(t, tt) {
-                // NB t.token.type must be NULL, THIS, TRUIE, FALSE, IDENTIFIER,
-                // NUMBER, STRING, or REGEXP.
+                // NULL | THIS | TRUE | FALSE | IDENTIFIER | NUMBER
+                // STRING | REGEXP.
                 return new Node(t, tt);
             },
 
             finish: function(n) {
             }
         },
 
         ARRAY_INIT: {
@@ -774,16 +792,25 @@ Narcissus.parser = (function() {
             addProperty: function(n, n2) {
                 n.push(n2);
             },
 
             finish: function(n) {
             }
         },
 
+        PROPERTY_NAME: {
+            build: function(t) {
+                return new Node(t, IDENTIFIER);
+            },
+
+            finish: function(n) {
+            }
+        },
+
         PROPERTY_INIT: {
             build: function(t) {
                 return new Node(t, PROPERTY_INIT);
             },
 
             addOperand: function(n, n2) {
                 n.push(n2);
             },
@@ -1101,47 +1128,70 @@ Narcissus.parser = (function() {
                         n2 = Variables(t, x, forBlock);
                     }
                 } else {
                     n2 = Expression(t, x);
                 }
                 x.inForLoopInit = false;
             }
             if (n2 && t.match(IN)) {
+                // for-ins always get a for block to help desugaring.
+                if (!forBlock) {
+                    var forBlock = builder.BLOCK.build(t, x.blockId++);
+                    forBlock.isInternalForInBlock = true;
+                    x.stmtStack.push(forBlock);
+                }
+
                 b.rebuildForIn(n);
-                b.setObject(n, Expression(t, x), forBlock);
+                b.setObject(n, Expression(t, x));
                 if (n2.type === VAR || n2.type === LET) {
-                    if (n2.length !== 1) {
+                    // Destructuring turns one decl into multiples, so either
+                    // there must be only one destructuring or only one
+                    // decl.
+                    if (n2.length !== 1 && n2.destructurings.length !== 1) {
                         throw new SyntaxError("Invalid for..in left-hand side",
                                               t.filename, n2.lineno);
                     }
-                    b.setIterator(n, n2[0], n2, forBlock);
+                    if (n2.destructurings.length > 0) {
+                        b.setIterator(n, n2.destructurings[0], n2, forBlock);
+                    } else {
+                        b.setIterator(n, n2[0], n2, forBlock);
+                    }
                 } else {
+                    if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
+                        n2.destructuredNames = checkDestructuring(t, x, n2);
+                    }
                     b.setIterator(n, n2, null, forBlock);
                 }
             } else {
                 b.setSetup(n, n2);
                 t.mustMatch(SEMICOLON);
                 if (n.isEach)
                     throw t.newSyntaxError("Invalid for each..in loop");
                 b.setCondition(n, (t.peek() === SEMICOLON)
                                   ? null
                                   : Expression(t, x));
                 t.mustMatch(SEMICOLON);
                 b.setUpdate(n, (t.peek() === RIGHT_PAREN)
-                                   ? null
-                                   : Expression(t, x));
+                               ? null
+                               : Expression(t, x));
             }
             t.mustMatch(RIGHT_PAREN);
             b.setBody(n, nest(t, x, n, Statement));
+            b.finish(n);
+
+            // In case desugaring statements were added to the imaginary
+            // block.
             if (forBlock) {
                 builder.BLOCK.finish(forBlock);
                 x.stmtStack.pop();
+                for (var i = 0, j = forBlock.length; i < j; i++) {
+                    n.body.unshift(forBlock[i]);
+                }
             }
-            b.finish(n);
             return n;
 
           case WHILE:
             b = builder.WHILE;
             n = b.build(t);
             b.setCondition(n, ParenExpression(t, x));
             b.setBody(n, nest(t, x, n, Statement));
             b.finish(n);
@@ -1192,16 +1242,19 @@ Narcissus.parser = (function() {
                  * a loop, then break targets its labeled statement. Labels can be
                  * nested so we skip all labels immediately enclosing the nearest
                  * non-label statement.
                  */
                 while (i < ss.length - 1 && ss[i+1].type === LABEL)
                     i++;
                 if (i < ss.length - 1 && ss[i+1].isLoop)
                     i++;
+                else if (i < ss.length - 1 && ss[i+1].isInternalForInBlock
+                                           && ss[i+2].isLoop)
+                    i++;
                 else if (tt === CONTINUE)
                     throw t.newSyntaxError("Invalid continue");
             } else {
                 do {
                     if (--i < 0) {
                         throw t.newSyntaxError("Invalid " + ((tt === BREAK)
                                                              ? "break"
                                                              : "continue"));
@@ -1220,17 +1273,18 @@ Narcissus.parser = (function() {
             while (t.match(CATCH)) {
                 n2 = b2.build(t);
                 t.mustMatch(LEFT_PAREN);
                 switch (t.get()) {
                   case LEFT_BRACKET:
                   case LEFT_CURLY:
                     // Destructured catch identifiers.
                     t.unget();
-                    b2.setVarName(n2, DestructuringExpression(t, x, true));
+                    b2.setVarName(n2, DestructuringExpressionNoHoist(t, x, true));
+                    break;
                   case IDENTIFIER:
                     b2.setVarName(n2, t.token.value);
                     break;
                   default:
                     throw t.newSyntaxError("missing identifier in catch");
                     break;
                 }
                 if (t.match(IF)) {
@@ -1350,26 +1404,27 @@ Narcissus.parser = (function() {
 
     function returnOrYield(t, x) {
         var n, b, tt = t.token.type, tt2;
 
         if (tt === RETURN) {
             if (!x.inFunction)
                 throw t.newSyntaxError("Return not in function");
             b = x.builder.RETURN;
-        } else /* (tt === YIELD) */ {
+        } else /* if (tt === YIELD) */ {
             if (!x.inFunction)
                 throw t.newSyntaxError("Yield not in function");
             x.isGenerator = true;
             b = x.builder.YIELD;
         }
         n = b.build(t);
 
         tt2 = t.peek(true);
-        if (tt2 !== END && tt2 !== NEWLINE && tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY
+        if (tt2 !== END && tt2 !== NEWLINE &&
+            tt2 !== SEMICOLON && tt2 !== RIGHT_CURLY
             && (tt !== YIELD ||
                 (tt2 !== tt && tt2 !== RIGHT_BRACKET && tt2 !== RIGHT_PAREN &&
                  tt2 !== COLON && tt2 !== COMMA))) {
             if (tt === RETURN) {
                 b.setValue(n, Expression(t, x));
                 x.hasReturnWithValue = true;
             } else {
                 b.setValue(n, AssignExpression(t, x));
@@ -1491,20 +1546,18 @@ Narcissus.parser = (function() {
          *
          * The list of declarations can be tied to block ids to aid talking
          * about declarations of blocks that have not yet been fully parsed.
          *
          * Blocks are already uniquely numbered; see the comment in
          * Statements.
          */
         if (x2.needsHoisting) {
-            /*
-             * Order is important here! Builders expect funDecls to come after
-             * varDecls!
-             */
+            // Order is important here! Builders expect funDecls to come
+            // after varDecls!
             builder.setHoists(f.body.id, x2.varDecls.concat(x2.funDecls));
 
             if (x.inFunction) {
                 /*
                  * If an inner function needs hoisting, we need to propagate
                  * this flag up to the parent function.
                  */
                 x.needsHoisting = true;
@@ -1536,20 +1589,19 @@ Narcissus.parser = (function() {
 
     /*
      * Variables :: (tokenizer, compiler context) -> node
      *
      * Parses a comma-separated list of var declarations (and maybe
      * initializations).
      */
     function Variables(t, x, letBlock) {
-        var b, bDecl, bAssign, n, n2, n3, ss, i, s, tt, id, data;
+        var b, n, n2, ss, i, s, tt;
         var builder = x.builder;
         var bDecl = builder.DECL;
-        var bAssign = builder.ASSIGN;
 
         switch (t.token.type) {
           case VAR:
             b = builder.VAR;
             s = x;
             break;
           case CONST:
             b = builder.CONST;
@@ -1574,81 +1626,63 @@ Narcissus.parser = (function() {
                 }
             } else {
                 s = letBlock;
             }
             break;
         }
 
         n = b.build(t);
-        initializers = [];
+        n.destructurings = [];
 
         do {
             tt = t.get();
-            /*
-             * FIXME Should have a special DECLARATION node instead of overloading
-             * IDENTIFIER to mean both identifier declarations and destructured
-             * declarations.
-             */
-            n2 = bDecl.build(t);
             if (tt === LEFT_BRACKET || tt === LEFT_CURLY) {
-                // Pass in s if we need to add each pattern matched into
-                // its varDecls, else pass in x.
-                data = null;
                 // Need to unget to parse the full destructured expression.
                 t.unget();
-                bDecl.setName(n2, DestructuringExpression(t, x, true, s));
+
+                var dexp = DestructuringExpressionNoHoist(t, x, true, s);
+
+                n2 = bDecl.build(t);
+                bDecl.setName(n2, dexp);
+                bDecl.setReadOnly(n2, n.type === CONST);
+                b.addDestructuringDecl(n, n2, s);
+
+                n.destructurings.push({ exp: dexp, decl: n2 });
+
                 if (x.inForLoopInit && t.peek() === IN) {
-                    b.addDecl(n, n2, s);
                     continue;
                 }
 
                 t.mustMatch(ASSIGN);
                 if (t.token.assignOp)
                     throw t.newSyntaxError("Invalid variable initialization");
 
-                // Parse the init as a normal assignment.
-                n3 = bAssign.build(t);
-                bAssign.addOperand(n3, n2.name);
-                bAssign.addOperand(n3, AssignExpression(t, x));
-                bAssign.finish(n3);
+                bDecl.setInitializer(n2, AssignExpression(t, x));
+                bDecl.finish(n2);
 
-                // But only add the rhs as the initializer.
-                bDecl.setInitializer(n2, n3[1]);
-                bDecl.finish(n2);
-                b.addDecl(n, n2, s);
                 continue;
             }
 
             if (tt !== IDENTIFIER)
                 throw t.newSyntaxError("missing variable name");
 
+            n2 = bDecl.build(t);
             bDecl.setName(n2, t.token.value);
             bDecl.setReadOnly(n2, n.type === CONST);
             b.addDecl(n, n2, s);
 
             if (t.match(ASSIGN)) {
                 if (t.token.assignOp)
                     throw t.newSyntaxError("Invalid variable initialization");
 
-                // Parse the init as a normal assignment.
-                id = new Node(n2.tokenizer, IDENTIFIER);
-                n3 = bAssign.build(t);
-                id.name = id.value = n2.name;
-                bAssign.addOperand(n3, id);
-                bAssign.addOperand(n3, AssignExpression(t, x));
-                bAssign.finish(n3);
-                initializers.push(n3);
-
-                // But only add the rhs as the initializer.
-                bDecl.setInitializer(n2, n3[1]);
+                bDecl.setInitializer(n2, AssignExpression(t, x));
             }
 
             bDecl.finish(n2);
-            s.varDecls.push(n2);
         } while (t.match(COMMA));
         b.finish(n);
         return n;
     }
 
     /*
      * LetBlock :: (tokenizer, compiler context, boolean) -> node
      *
@@ -1692,50 +1726,69 @@ Narcissus.parser = (function() {
     }
 
     function checkDestructuring(t, x, n, simpleNamesOnly, data) {
         if (n.type === ARRAY_COMP)
             throw t.newSyntaxError("Invalid array comprehension left-hand side");
         if (n.type !== ARRAY_INIT && n.type !== OBJECT_INIT)
             return;
 
-        var nn, n2, lhs, rhs, b = x.builder.DECL;
+        var lhss = {};
+        var nn, n2, idx, sub;
         for (var i = 0, j = n.length; i < j; i++) {
-            nn = n[i];
-            if (!nn)
+            if (!(nn = n[i]))
                 continue;
-            if (nn.type === PROPERTY_INIT)
-                lhs = nn[0], rhs = nn[1];
-            else
-                lhs = null, rhs = null;
-            if (rhs && (rhs.type === ARRAY_INIT || rhs.type === OBJECT_INIT))
-                checkDestructuring(t, x, rhs, simpleNamesOnly, data);
-            if (lhs && simpleNamesOnly) {
-                // In declarations, lhs must be simple names
-                if (lhs.type !== IDENTIFIER) {
+            if (nn.type === PROPERTY_INIT) {
+                sub = nn[1];
+                idx = nn[0].value;
+            } else if (n.type === OBJECT_INIT) {
+                // Do we have destructuring shorthand {foo, bar}?
+                sub = nn;
+                idx = nn.value;
+            } else {
+                sub = nn;
+                idx = i;
+            }
+
+            if (sub.type === ARRAY_INIT || sub.type === OBJECT_INIT) {
+                lhss[idx] = checkDestructuring(t, x, sub,
+                                               simpleNamesOnly, data);
+            } else {
+                if (simpleNamesOnly && sub.type !== IDENTIFIER) {
+                    // In declarations, lhs must be simple names
                     throw t.newSyntaxError("missing name in pattern");
-                } else if (data) {
-                    n2 = b.build(t);
-                    b.setName(n2, lhs.value);
-                    // Don't need to set initializer because it's just for
-                    // hoisting anyways.
-                    b.finish(n2);
-                    // Each pattern needs to be added to varDecls.
-                    data.varDecls.push(n2);
                 }
+
+                lhss[idx] = sub;
             }
         }
+
+        return lhss;
     }
 
     function DestructuringExpression(t, x, simpleNamesOnly, data) {
         var n = PrimaryExpression(t, x);
-        checkDestructuring(t, x, n, simpleNamesOnly, data);
+        // Keep the list of lefthand sides in case the builder wants to
+        // desugar.
+        n.destructuredNames = checkDestructuring(t, x, n,
+                                                 simpleNamesOnly, data);
         return n;
     }
 
+    function DestructuringExpressionNoHoist(t, x, simpleNamesOnly, data) {
+        // Sometimes we don't want to flag the pattern as possible hoists, so
+        // pretend it's the second pass.
+        var builder = x.builder;
+        var oldSP = builder.secondPass;
+        builder.secondPass = true;
+        var dexp = DestructuringExpression(t, x, simpleNamesOnly, data);
+        builder.secondPass = oldSP;
+        return dexp;
+    }
+
     function GeneratorExpression(t, x, e) {
         var n, b = x.builder.GENERATOR;
 
         n = b.build(t);
         b.setExpression(n, e);
         b.setTail(n, comprehensionTail(t, x));
         b.finish(n);
 
@@ -1765,32 +1818,30 @@ Narcissus.parser = (function() {
                     t.unget();
             }
             t.mustMatch(LEFT_PAREN);
             switch(t.get()) {
               case LEFT_BRACKET:
               case LEFT_CURLY:
                 t.unget();
                 // Destructured left side of for in comprehension tails.
-                b2.setIterator(n, DestructuringExpression(t, x), null);
+                b2.setIterator(n, DestructuringExpressionNoHoist(t, x), null);
                 break;
 
               case IDENTIFIER:
                 var n3 = bDecl.build(t);
                 bDecl.setName(n3, n3.value);
                 bDecl.finish(n3);
                 var n2 = bVar.build(t);
-                bVar.addDecl(n2, n3);
+                bVar.addDecl(n2, n3, x);
                 bVar.finish(n2);
                 bFor.setIterator(n, n3, n2);
-                /*
-                 * Don't add to varDecls since the semantics of comprehensions is
-                 * such that the variables are in their own function when
-                 * desugared.
-                 */
+                // Don't add to varDecls since the semantics of comprehensions is
+                // such that the variables are in their own function when
+                // desugared.
                 break;
 
               default:
                 throw t.newSyntaxError("missing identifier");
             }
             t.mustMatch(IN);
             bFor.setObject(n, Expression(t, x));
             t.mustMatch(RIGHT_PAREN);
@@ -1871,17 +1922,17 @@ Narcissus.parser = (function() {
         if (!t.match(ASSIGN)) {
             b.finish(n);
             return lhs;
         }
 
         switch (lhs.type) {
           case OBJECT_INIT:
           case ARRAY_INIT:
-            checkDestructuring(t, x, lhs);
+            lhs.destructuredNames = checkDestructuring(t, x, lhs);
             // FALL THROUGH
           case IDENTIFIER: case DOT: case INDEX: case CALL:
             break;
           default:
             throw t.newSyntaxError("Bad left-hand side of assignment");
             break;
         }
 
@@ -2114,17 +2165,20 @@ Narcissus.parser = (function() {
             break;
         }
 
         b.finish(n);
         return n;
     }
 
     function MemberExpression(t, x, allowCallSyntax) {
-        var n, n2, tt, b = x.builder.MEMBER;
+        var n, n2, name, tt;
+        var builder = x.builder;
+        var b = builder.MEMBER
+        var b2 = builder.PROPERTY_NAME;
 
         if (t.match(NEW)) {
             n = b.build(t);
             b.addOperand(n, MemberExpression(t, x, false));
             if (t.match(LEFT_PAREN)) {
                 b.rebuildNewWithArgs(n);
                 b.addOperand(n, ArgumentList(t, x));
             }
@@ -2134,17 +2188,19 @@ Narcissus.parser = (function() {
         }
 
         while ((tt = t.get()) !== END) {
             switch (tt) {
               case DOT:
                 n2 = b.build(t);
                 b.addOperand(n2, n);
                 t.mustMatch(IDENTIFIER);
-                b.addOperand(n2, b.build(t));
+                name = b2.build(t);
+                b2.finish(name);
+                b.addOperand(n2, name);
                 break;
 
               case LEFT_BRACKET:
                 n2 = b.build(t, INDEX);
                 b.addOperand(n2, n);
                 b.addOperand(n2, Expression(t, x));
                 t.mustMatch(RIGHT_BRACKET);
                 break;
@@ -2195,16 +2251,17 @@ Narcissus.parser = (function() {
     }
 
     function PrimaryExpression(t, x) {
         var n, n2, n3, tt = t.get(true);
         var builder = x.builder;
         var bArrayInit = builder.ARRAY_INIT;
         var bArrayComp = builder.ARRAY_COMP;
         var bPrimary = builder.PRIMARY;
+        var bPropName = builder.PROPERTY_NAME;
         var bObjInit = builder.OBJECT_INIT;
         var bPropInit = builder.PROPERTY_INIT;
 
         switch (tt) {
           case FUNCTION:
             n = FunctionDefinition(t, x, false, EXPRESSED_FORM);
             break;
 
@@ -2225,17 +2282,17 @@ Narcissus.parser = (function() {
             // array comprehension.
             if (n.length === 1 && t.match(FOR)) {
                 n2 = bArrayComp.build(t);
                 bArrayComp.setExpression(n2, n[0]);
                 bArrayComp.setTail(n2, comprehensionTail(t, x));
                 n = n2;
             }
             t.mustMatch(RIGHT_BRACKET);
-            bPrimary.finish(n);
+            bArrayInit.finish(n);
             break;
 
           case LEFT_CURLY:
             var id, fd;
             n = bObjInit.build(t);
 
           object_init:
             if (!t.match(RIGHT_CURLY)) {
@@ -2245,27 +2302,27 @@ Narcissus.parser = (function() {
                         t.peek() === IDENTIFIER) {
                         if (x.ecma3OnlyMode)
                             throw t.newSyntaxError("Illegal property accessor");
                         fd = FunctionDefinition(t, x, true, EXPRESSED_FORM);
                         bObjInit.addProperty(n, fd);
                     } else {
                         switch (tt) {
                           case IDENTIFIER: case NUMBER: case STRING:
-                            id = bPrimary.build(t, IDENTIFIER);
-                            bPrimary.finish(id);
+                            id = bPropName.build(t);
+                            bPropName.finish(id);
                             break;
                           case RIGHT_CURLY:
                             if (x.ecma3OnlyMode)
                                 throw t.newSyntaxError("Illegal trailing ,");
                             break object_init;
                           default:
                             if (t.token.value in definitions.keywords) {
-                                id = bPrimary.build(t, IDENTIFIER);
-                                bPrimary.finish(id);
+                                id = bPropName.build(t);
+                                bPropName.finish(id);
                                 break;
                             }
                             throw t.newSyntaxError("Invalid property name");
                         }
                         if (t.match(COLON)) {
                             n2 = bPropInit.build(t);
                             bPropInit.addOperand(n2, id);
                             bPropInit.addOperand(n2, AssignExpression(t, x));
@@ -2323,16 +2380,19 @@ Narcissus.parser = (function() {
 
         return n;
     }
 
     return {
         parse: parse,
         Node: Node,
         DefaultBuilder: DefaultBuilder,
+        get SSABuilder() {
+            throw new Error("SSA builder not yet supported");
+        },
         bindSubBuilders: bindSubBuilders,
         DECLARED_FORM: DECLARED_FORM,
         EXPRESSED_FORM: EXPRESSED_FORM,
         STATEMENT_FORM: STATEMENT_FORM,
         Tokenizer: lexer.Tokenizer,
         FunctionDefinition: FunctionDefinition
     };
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -145,38 +145,33 @@ CPPSRCS		= \
 		jsnativestack.cpp \
 		jsnum.cpp \
 		jsobj.cpp \
 		json.cpp \
 		jsopcode.cpp \
 		jsparse.cpp \
 		jsproxy.cpp \
 		jsprf.cpp \
+		jsprobes.cpp \
 		jspropertycache.cpp \
 		jspropertytree.cpp \
 		jsreflect.cpp \
 		jsregexp.cpp \
 		jsscan.cpp \
 		jsscope.cpp \
 		jsscript.cpp \
 		jsstr.cpp \
-		jstask.cpp \
 		jstypedarray.cpp \
 		jsutil.cpp \
 		jswrapper.cpp \
 		jsxdrapi.cpp \
 		jsxml.cpp \
 		prmjtime.cpp \
 		$(NULL)
 
-ifdef HAVE_DTRACE
-CPPSRCS 	+= \
-		jsdtracef.cpp
-endif
-
 INSTALLED_HEADERS = \
 		js-config.h \
 		jsautocfg.h \
 		$(CURDIR)/jsautokw.h \
 		js.msg \
 		jsapi.h \
 		jsarray.h \
 		jsarena.h \
@@ -206,32 +201,32 @@ INSTALLED_HEADERS = \
 		jsobjinlines.h \
 		json.h \
 		jsopcode.tbl \
 		jsopcode.h \
 		jsotypes.h \
 		jsparse.h \
 		jsproxy.h \
 		jsprf.h \
+		jsprobes.h \
 		jspropertycache.h \
 		jspropertycacheinlines.h \
 		jspropertytree.h \
 		jsproto.tbl \
 		jsprvtd.h \
 		jspubtd.h \
 		jsreflect.h \
 		jsregexp.h \
 		jsscan.h \
 		jsscope.h \
 		jsscript.h \
 		jsscriptinlines.h \
 		jsstaticcheck.h \
 		jsstdint.h \
 		jsstr.h \
-		jstask.h \
 		jstracer.h \
 		jstypedarray.h \
 		jstypes.h \
 		jsutil.h \
 		jsvector.h \
 		jstl.h \
 		jshashtable.h \
 		jsversion.h \
@@ -282,18 +277,66 @@ CPPSRCS += \
 ifdef WINCE
 # don't need -c
 AS_DASH_C_FLAG =
 ASFLAGS += -arch 6
 ASFILES += jswince.asm
 endif
 
 endif # ENABLE_TRACEJIT
+ifdef ENABLE_METHODJIT
 
-ifeq ($(TARGET_CPU), powerpc)
+###############################################
+# BEGIN include sources for the method JIT
+#
+VPATH += 	$(srcdir)/methodjit
+
+CPPSRCS += 	MethodJIT.cpp \
+		BytecodeAnalyzer.cpp \
+		StubCalls.cpp \
+		Compiler.cpp \
+		FrameState.cpp \
+		FastArithmetic.cpp \
+		FastOps.cpp \
+		StubCompiler.cpp \
+		MonoIC.cpp \
+		PolyIC.cpp \
+		ImmutableSync.cpp \
+		InvokeHelpers.cpp \
+		Retcon.cpp \
+		TrampolineCompiler.cpp \
+		$(NULL)
+#		PICStubCompiler.cpp \
+
+ifeq (86, $(findstring 86,$(TARGET_CPU)))
+ifeq (x86_64, $(TARGET_CPU))
+ifdef _MSC_VER
+ASFILES +=	TrampolineMasmX64.asm
+endif
+ifdef SOLARIS_SUNPRO_CXX
+ASFILES +=	TrampolineSUNWX64.s
+endif
+#CPPSRCS		+= only_on_x86_64.cpp
+else
+#CPPSRCS		+= only_on_x86.cpp
+ifdef SOLARIS_SUNPRO_CXX
+ASFILES +=	TrampolineSUNWX86.s
+endif
+endif
+endif
+ifeq (arm, $(TARGET_CPU))
+#CPPSRCS		+= only_on_arm.cpp
+endif
+#
+# END enclude sources for the method JIT
+#############################################
+
+endif
+
+ifeq (,$(filter-out powerpc sparc,$(TARGET_CPU)))
 
 VPATH +=	$(srcdir)/assembler \
 		$(srcdir)/assembler/wtf \
 		$(srcdir)/yarr/pcre \
 		$(NULL)
 
 CPPSRCS += 	pcre_compile.cpp \
                 pcre_exec.cpp \
@@ -372,17 +415,16 @@ SHARED_LIBRARY_LIBS += \
     ctypes/libffi/.libs/libffi.$(LIB_SUFFIX) \
     $(NULL)
 endif
 
 endif # JS_HAS_CTYPES
 
 ifdef HAVE_DTRACE
 INSTALLED_HEADERS += \
-		jsdtracef.h \
 		$(CURDIR)/javascript-trace.h \
 		$(NULL)
 endif
 
 # PerfMeasurement is available regardless of low-level support for it;
 # it just doesn't necessarily do anything useful.  There is one
 # implementation source file per supported operating system, plus a stub
 # for unsupported OSes, plus the Javascript wrapper.
@@ -776,17 +818,17 @@ host_jsoplengen.$(OBJ_SUFFIX): jsopcode.
 ifdef HAVE_DTRACE
 $(CURDIR)/javascript-trace.h: $(srcdir)/javascript-trace.d
 	dtrace -h -s $(srcdir)/javascript-trace.d -o javascript-trace.h.in
 	sed 's/if _DTRACE_VERSION/ifdef INCLUDE_MOZILLA_DTRACE/' \
 	    javascript-trace.h.in > javascript-trace.h
 
 # We can't automatically generate dependencies on auto-generated headers;
 # we have to list them explicitly.
-$(addsuffix .$(OBJ_SUFFIX),jsdtracef jsinterp jsobj): $(CURDIR)/javascript-trace.h
+$(addsuffix .$(OBJ_SUFFIX),jsprobes jsinterp jsobj): $(CURDIR)/javascript-trace.h
 endif
 
 ifdef ENABLE_TRACEJIT
 # Imacro compilation.
 $(CURDIR)/imacros.c.out: $(srcdir)/imacro_asm.py $(srcdir)/imacros.jsasm
 	$(PYTHON) $< $(srcdir)/imacros.jsasm $(CURDIR)/imacros.c.out
 $(addsuffix .$(OBJ_SUFFIX),jstracer): $(CURDIR)/imacros.c.out
 
@@ -825,11 +867,29 @@ endif
 
 # Needed to "configure" it correctly.  Unfortunately these
 # flags wind up being applied to all code in js/src, not just
 # the code in js/src/assembler.
 CXXFLAGS += -DUSE_SYSTEM_MALLOC=1 -DENABLE_ASSEMBLER=1 -DENABLE_JIT=1
 
 INCLUDES +=	-I$(srcdir)/assembler -I$(srcdir)/yarr
 
+ifdef ENABLE_METHODJIT
+# Build a standalone test program that exercises the assembler
+# sources a bit.
+TESTMAIN_OBJS = \
+		Assertions.$(OBJ_SUFFIX) \
+		ExecutableAllocatorPosix.$(OBJ_SUFFIX) \
+		ExecutableAllocatorWin.$(OBJ_SUFFIX) \
+		ExecutableAllocator.$(OBJ_SUFFIX) \
+		ARMAssembler.$(OBJ_SUFFIX) \
+		MacroAssemblerARM.$(OBJ_SUFFIX) \
+		TestMain.$(OBJ_SUFFIX) \
+		jsutil.$(OBJ_SUFFIX) \
+		jslog2.$(OBJ_SUFFIX)
+TestMain$(HOST_BIN_SUFFIX): $(TESTMAIN_OBJS)
+	$(CXX) -o TestMain$(HOST_BIN_SUFFIX) $(TESTMAIN_OBJS)
+endif
+
 #
 # END kludges for the Nitro assembler
 ###############################################
+
new file mode 100644
--- /dev/null
+++ b/js/src/assembler/TestMain.cpp
@@ -0,0 +1,929 @@
+
+// A short test program with which to experiment with the assembler.
+
+//satisfies  CPU(X86_64)
+//#define WTF_CPU_X86_64
+
+// satisfies  ENABLE(ASSEMBLER)
+#define ENABLE_ASSEMBLER 1
+
+// satisfies  ENABLE(JIT)
+#define ENABLE_JIT 1
+
+#define USE_SYSTEM_MALLOC 1
+// leads to FORCE_SYSTEM_MALLOC in wtf/FastMalloc.cpp
+
+#include <jit/ExecutableAllocator.h>
+#include <assembler/LinkBuffer.h>
+#include <assembler/CodeLocation.h>
+#include <assembler/RepatchBuffer.h>
+
+#include <assembler/MacroAssembler.h>
+
+#include <stdio.h>
+
+/////////////////////////////////////////////////////////////////
+// Temporary scaffolding for selecting the arch
+#undef ARCH_x86
+#undef ARCH_amd64
+#undef ARCH_arm
+
+#if defined(__APPLE__) && defined(__i386__)
+#  define ARCH_x86 1
+#elif defined(__APPLE__) && defined(__x86_64__)
+#  define ARCH_amd64 1
+#elif defined(__linux__) && defined(__i386__)
+#  define ARCH_x86 1
+#elif defined(__linux__) && defined(__x86_64__)
+#  define ARCH_amd64 1
+#elif defined(__linux__) && defined(__arm__)
+#  define ARCH_arm 1
+#elif defined(_MSC_VER) && defined(_M_IX86)
+#  define ARCH_x86 1
+#endif
+/////////////////////////////////////////////////////////////////
+
+// just somewhere convenient to put a breakpoint, before
+// running gdb
+#if WTF_COMPILER_GCC
+__attribute__((noinline))
+#endif
+void pre_run ( void ) { }
+
+/////////////////////////////////////////////////////////////////
+//// test1 (simple straight line code) 
+#if WTF_COMPILER_GCC
+
+void test1 ( void )
+{
+  printf("\n------------ Test 1 (straight line code) ------------\n\n" );
+
+  // Create new assembler
+  JSC::MacroAssembler* am = new JSC::MacroAssembler();
+
+#if defined(ARCH_amd64)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
+  // dump some instructions into it
+  //    xor    %r15,%r15
+  //    add    $0x7b,%r15
+  //    add    $0x141,%r15
+  //    retq
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+  am->ret();
+#endif
+
+#if defined(ARCH_x86)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
+  // dump some instructions into it
+  //    xor    %edi,%edi
+  //    add    $0x7b,%edi
+  //    add    $0x141,%edi
+  //    ret
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+  am->ret();
+#endif
+
+#if defined(ARCH_arm)
+  JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
+  //    eors    r8, r8, r8
+  //    adds    r8, r8, #123    ; 0x7b
+  //    mov     r3, #256        ; 0x100
+  //    orr     r3, r3, #65     ; 0x41
+  //    adds    r8, r8, r3
+  //    mov     pc, lr
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+  am->ret();
+#endif
+
+  // prepare a link buffer, into which we can copy the completed insns
+  JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
+
+  // intermediate step .. get the pool suited for the size of code in 'am'
+  //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
+  JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
+
+  // constructor for LinkBuffer asks ep to allocate r-x memory,
+  // then copies it there.
+  JSC::LinkBuffer patchBuffer(am, ep);
+
+  // finalize
+  JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
+
+  // cr now holds a pointer to the final runnable code.
+  void* entry = cr.m_code.executableAddress();
+
+  printf("disas %p %p\n",
+         entry, (char*)entry + cr.m_size);
+  pre_run();
+
+  unsigned long result = 0x55555555;
+
+#if defined(ARCH_amd64)
+  // call the generated piece of code.  It puts its result in r15.
+  __asm__ __volatile__(
+     "callq *%1"           "\n\t"
+     "movq  %%r15, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r15","cc"
+  );
+#endif
+#if defined(ARCH_x86)
+  // call the generated piece of code.  It puts its result in edi.
+  __asm__ __volatile__(
+     "calll *%1"           "\n\t"
+     "movl  %%edi, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "edi","cc"
+  );
+#endif
+#if defined(ARCH_arm)
+  // call the generated piece of code.  It puts its result in r8.
+  __asm__ __volatile__(
+     "blx   %1"            "\n\t"
+     "mov   %0, %%r8"      "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r8","cc"
+  );
+#endif
+
+  printf("\n");
+  printf("value computed is %lu (expected 444)\n", result);
+  printf("\n");
+
+  delete eal;
+  delete am;
+}
+
+#endif /* WTF_COMPILER_GCC */
+
+/////////////////////////////////////////////////////////////////
+//// test2 (a simple counting-down loop) 
+#if WTF_COMPILER_GCC
+
+void test2 ( void )
+{
+  printf("\n------------ Test 2 (mini loop) ------------\n\n" );
+
+  // Create new assembler
+  JSC::MacroAssembler* am = new JSC::MacroAssembler();
+
+#if defined(ARCH_amd64)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
+  //    xor    %r15,%r15
+  //    add    $0x7b,%r15
+  //    add    $0x141,%r15
+  //    sub    $0x1,%r15
+  //    mov    $0x0,%r11
+  //    cmp    %r11,%r15
+  //    jne    0x7ff6d3e6a00e
+  //    retq
+  // so r15 always winds up being zero
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+
+  JSC::MacroAssembler::Label loopHeadLabel(am);
+  am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
+
+  JSC::MacroAssembler::Jump j
+     = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                     areg, JSC::MacroAssembler::ImmPtr(0));
+  j.linkTo(loopHeadLabel, am);
+
+  am->ret();
+#endif
+
+#if defined(ARCH_x86)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
+  //    xor    %edi,%edi
+  //    add    $0x7b,%edi
+  //    add    $0x141,%edi
+  //    sub    $0x1,%edi
+  //    test   %edi,%edi
+  //    jne    0xf7f9700b
+  //    ret
+  // so edi always winds up being zero
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+
+  JSC::MacroAssembler::Label loopHeadLabel(am);
+  am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
+
+  JSC::MacroAssembler::Jump j
+     = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                     areg, JSC::MacroAssembler::ImmPtr(0));
+  j.linkTo(loopHeadLabel, am);
+
+  am->ret();
+#endif
+
+#if defined(ARCH_arm)
+  JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
+  //    eors    r8, r8, r8
+  //    adds    r8, r8, #123    ; 0x7b
+  //    mov     r3, #256        ; 0x100
+  //    orr     r3, r3, #65     ; 0x41
+  //    adds    r8, r8, r3
+  //    subs    r8, r8, #1      ; 0x1
+  //    ldr     r3, [pc, #8]    ; 0x40026028
+  //    cmp     r8, r3
+  //    bne     0x40026014
+  //    mov     pc, lr
+  //    andeq   r0, r0, r0         // DATA (0)
+  //    andeq   r0, r0, r4, lsl r0 // DATA (?? what's this for?)
+  // so r8 always winds up being zero
+  am->xorPtr(areg,areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), areg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), areg);
+
+  JSC::MacroAssembler::Label loopHeadLabel(am);
+  am->subPtr(JSC::MacroAssembler::Imm32(1), areg);
+
+  JSC::MacroAssembler::Jump j
+     = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                     areg, JSC::MacroAssembler::ImmPtr(0));
+  j.linkTo(loopHeadLabel, am);
+
+  am->ret();
+#endif
+
+  // prepare a link buffer, into which we can copy the completed insns
+  JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
+
+  // intermediate step .. get the pool suited for the size of code in 'am'
+  //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
+  JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
+
+  // constructor for LinkBuffer asks ep to allocate r-x memory,
+  // then copies it there.
+  JSC::LinkBuffer patchBuffer(am, ep);
+
+  // finalize
+  JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
+
+  // cr now holds a pointer to the final runnable code.
+  void* entry = cr.m_code.executableAddress();
+
+  printf("disas %p %p\n",
+         entry, (char*)entry + cr.m_size);
+  pre_run();
+
+  unsigned long result = 0x55555555;
+
+#if defined(ARCH_amd64)
+  // call the generated piece of code.  It puts its result in r15.
+  __asm__ __volatile__(
+     "callq *%1"           "\n\t"
+     "movq  %%r15, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r15","cc"
+  );
+#endif
+#if defined(ARCH_x86)
+  // call the generated piece of code.  It puts its result in edi.
+  __asm__ __volatile__(
+     "calll *%1"           "\n\t"
+     "movl  %%edi, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "edi","cc"
+  );
+#endif
+#if defined(ARCH_arm)
+  // call the generated piece of code.  It puts its result in r8.
+  __asm__ __volatile__(
+     "blx   %1"            "\n\t"
+     "mov   %0, %%r8"      "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r8","cc"
+  );
+#endif
+
+  printf("\n");
+  printf("value computed is %lu (expected 0)\n", result);
+  printf("\n");
+
+  delete eal;
+  delete am;
+}
+
+#endif /* WTF_COMPILER_GCC */
+
+/////////////////////////////////////////////////////////////////
+//// test3 (if-then-else) 
+#if WTF_COMPILER_GCC
+
+void test3 ( void )
+{
+  printf("\n------------ Test 3 (if-then-else) ------------\n\n" );
+
+  // Create new assembler
+  JSC::MacroAssembler* am = new JSC::MacroAssembler();
+
+#if defined(ARCH_amd64)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::r15;
+  //    mov    $0x64,%r15d
+  //    mov    $0x0,%r11
+  //    cmp    %r11,%r15
+  //    jne    0x7ff6d3e6a024
+  //    mov    $0x40,%r15d
+  //    jmpq   0x7ff6d3e6a02a
+  //    mov    $0x4,%r15d
+  //    retq
+  // so r15 ends up being 4
+
+  // put a value in reg
+  am->move(JSC::MacroAssembler::Imm32(100), areg);
+
+  // test, and conditionally jump to 'else' branch
+  JSC::MacroAssembler::Jump jToElse
+    = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                    areg, JSC::MacroAssembler::ImmPtr(0));
+
+  // 'then' branch
+  am->move(JSC::MacroAssembler::Imm32(64), areg);
+  JSC::MacroAssembler::Jump jToAfter
+    = am->jump();
+
+  // 'else' branch
+  JSC::MacroAssembler::Label elseLbl(am);
+  am->move(JSC::MacroAssembler::Imm32(4), areg);
+
+  // after
+  JSC::MacroAssembler::Label afterLbl(am);
+
+  am->ret();
+#endif
+
+#if defined(ARCH_x86)
+  JSC::X86Registers::RegisterID areg = JSC::X86Registers::edi;
+  //    mov    $0x64,%edi
+  //    test   %edi,%edi
+  //    jne    0xf7f22017
+  //    mov    $0x40,%edi
+  //    jmp    0xf7f2201c
+  //    mov    $0x4,%edi
+  //    ret
+  // so edi ends up being 4
+
+  // put a value in reg
+  am->move(JSC::MacroAssembler::Imm32(100), areg);
+
+  // test, and conditionally jump to 'else' branch
+  JSC::MacroAssembler::Jump jToElse
+    = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                    areg, JSC::MacroAssembler::ImmPtr(0));
+
+  // 'then' branch
+  am->move(JSC::MacroAssembler::Imm32(64), areg);
+  JSC::MacroAssembler::Jump jToAfter
+    = am->jump();
+
+  // 'else' branch
+  JSC::MacroAssembler::Label elseLbl(am);
+  am->move(JSC::MacroAssembler::Imm32(4), areg);
+
+  // after
+  JSC::MacroAssembler::Label afterLbl(am);
+
+  am->ret();
+#endif
+
+#if defined(ARCH_arm)
+  JSC::ARMRegisters::RegisterID areg = JSC::ARMRegisters::r8;
+  //    mov     r8, #100        ; 0x64
+  //    ldr     r3, [pc, #20]   ; 0x40026020
+  //    cmp     r8, r3
+  //    bne     0x40026018
+  //    mov     r8, #64 ; 0x40
+  //    b       0x4002601c
+  //    mov     r8, #4  ; 0x4
+  //    mov     pc, lr
+  //    andeq   r0, r0, r0           // DATA
+  //    andeq   r0, r0, r8, lsl r0   // DATA
+  //    andeq   r0, r0, r12, lsl r0  // DATA
+  //    ldr     r3, [r3, -r3]        // DATA
+  // so r8 ends up being 4
+
+  // put a value in reg
+  am->move(JSC::MacroAssembler::Imm32(100), areg);
+
+  // test, and conditionally jump to 'else' branch
+  JSC::MacroAssembler::Jump jToElse
+    = am->branchPtr(JSC::MacroAssembler::NotEqual,
+                    areg, JSC::MacroAssembler::ImmPtr(0));
+
+  // 'then' branch
+  am->move(JSC::MacroAssembler::Imm32(64), areg);
+  JSC::MacroAssembler::Jump jToAfter
+    = am->jump();
+
+  // 'else' branch
+  JSC::MacroAssembler::Label elseLbl(am);
+  am->move(JSC::MacroAssembler::Imm32(4), areg);
+
+  // after
+  JSC::MacroAssembler::Label afterLbl(am);
+
+  am->ret();
+#endif
+
+  // set branch targets appropriately
+  jToElse.linkTo(elseLbl, am);
+  jToAfter.linkTo(afterLbl, am);
+
+  // prepare a link buffer, into which we can copy the completed insns
+  JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
+
+  // intermediate step .. get the pool suited for the size of code in 'am'
+  //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
+  JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
+
+  // constructor for LinkBuffer asks ep to allocate r-x memory,
+  // then copies it there.
+  JSC::LinkBuffer patchBuffer(am, ep);
+
+  // finalize
+  JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
+
+  // cr now holds a pointer to the final runnable code.
+  void* entry = cr.m_code.executableAddress();
+
+  printf("disas %p %p\n",
+         entry, (char*)entry + cr.m_size);
+  pre_run();
+
+  unsigned long result = 0x55555555;
+
+#if defined(ARCH_amd64)
+  // call the generated piece of code.  It puts its result in r15.
+  __asm__ __volatile__(
+     "callq *%1"           "\n\t"
+     "movq  %%r15, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r15","cc"
+  );
+#endif
+#if defined(ARCH_x86)
+  // call the generated piece of code.  It puts its result in edi.
+  __asm__ __volatile__(
+     "calll *%1"           "\n\t"
+     "movl  %%edi, %0"     "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "edi","cc"
+  );
+#endif
+#if defined(ARCH_arm)
+  // call the generated piece of code.  It puts its result in r8.
+  __asm__ __volatile__(
+     "blx   %1"            "\n\t"
+     "mov   %0, %%r8"      "\n"
+     :/*out*/   "=r"(result)
+     :/*in*/    "r"(entry)
+     :/*trash*/ "r8","cc"
+  );
+#endif
+
+  printf("\n");
+  printf("value computed is %lu (expected 4)\n", result);
+  printf("\n");
+
+  delete eal;
+  delete am;
+}
+
+#endif /* WTF_COMPILER_GCC */
+
+/////////////////////////////////////////////////////////////////
+//// test4 (callable function) 
+
+void test4 ( void )
+{
+  printf("\n------------ Test 4 (callable fn) ------------\n\n" );
+
+  // Create new assembler
+  JSC::MacroAssembler* am = new JSC::MacroAssembler();
+
+#if defined(ARCH_amd64)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  //    push   %rbp
+  //    mov    %rsp,%rbp
+  //    push   %rbx
+  //    push   %r12
+  //    push   %r13
+  //    push   %r14
+  //    push   %r15
+  //    xor    %rax,%rax
+  //    add    $0x7b,%rax
+  //    add    $0x141,%rax
+  //    pop    %r15
+  //    pop    %r14
+  //    pop    %r13
+  //    pop    %r12
+  //    pop    %rbx
+  //    mov    %rbp,%rsp
+  //    pop    %rbp
+  //    retq
+  // callable as a normal function, returns 444
+
+  JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
+  am->push(JSC::X86Registers::ebp);
+  am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
+  am->push(JSC::X86Registers::ebx);
+  am->push(JSC::X86Registers::r12);
+  am->push(JSC::X86Registers::r13);
+  am->push(JSC::X86Registers::r14);
+  am->push(JSC::X86Registers::r15);
+
+  am->xorPtr(rreg,rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
+
+  am->pop(JSC::X86Registers::r15);
+  am->pop(JSC::X86Registers::r14);
+  am->pop(JSC::X86Registers::r13);
+  am->pop(JSC::X86Registers::r12);
+  am->pop(JSC::X86Registers::ebx);
+  am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
+  am->pop(JSC::X86Registers::ebp);
+  am->ret();
+#endif
+
+#if defined(ARCH_x86)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  //    push   %ebp
+  //    mov    %esp,%ebp
+  //    push   %ebx
+  //    push   %esi
+  //    push   %edi
+  //    xor    %eax,%eax
+  //    add    $0x7b,%eax
+  //    add    $0x141,%eax
+  //    pop    %edi
+  //    pop    %esi
+  //    pop    %ebx
+  //    mov    %ebp,%esp
+  //    pop    %ebp
+  //    ret
+  // callable as a normal function, returns 444
+
+  JSC::X86Registers::RegisterID rreg = JSC::X86Registers::eax;
+
+  am->push(JSC::X86Registers::ebp);
+  am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
+  am->push(JSC::X86Registers::ebx);
+  am->push(JSC::X86Registers::esi);
+  am->push(JSC::X86Registers::edi);
+
+  am->xorPtr(rreg,rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
+
+  am->pop(JSC::X86Registers::edi);
+  am->pop(JSC::X86Registers::esi);
+  am->pop(JSC::X86Registers::ebx);
+  am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
+  am->pop(JSC::X86Registers::ebp);
+  am->ret();
+#endif
+
+#if defined(ARCH_arm)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  //    push    {r4}            ; (str r4, [sp, #-4]!)
+  //    push    {r5}            ; (str r5, [sp, #-4]!)
+  //    push    {r6}            ; (str r6, [sp, #-4]!)
+  //    push    {r7}            ; (str r7, [sp, #-4]!)
+  //    push    {r8}            ; (str r8, [sp, #-4]!)
+  //    push    {r9}            ; (str r9, [sp, #-4]!)
+  //    push    {r10}           ; (str r10, [sp, #-4]!)
+  //    push    {r11}           ; (str r11, [sp, #-4]!)
+  //    eors    r0, r0, r0
+  //    adds    r0, r0, #123    ; 0x7b
+  //    mov     r3, #256        ; 0x100
+  //    orr     r3, r3, #65     ; 0x41
+  //    adds    r0, r0, r3
+  //    pop     {r11}           ; (ldr r11, [sp], #4)
+  //    pop     {r10}           ; (ldr r10, [sp], #4)
+  //    pop     {r9}            ; (ldr r9, [sp], #4)
+  //    pop     {r8}            ; (ldr r8, [sp], #4)
+  //    pop     {r7}            ; (ldr r7, [sp], #4)
+  //    pop     {r6}            ; (ldr r6, [sp], #4)
+  //    pop     {r5}            ; (ldr r5, [sp], #4)
+  //    pop     {r4}            ; (ldr r4, [sp], #4)
+  //    mov     pc, lr
+  // callable as a normal function, returns 444
+
+  JSC::ARMRegisters::RegisterID rreg = JSC::ARMRegisters::r0;
+
+  am->push(JSC::ARMRegisters::r4);
+  am->push(JSC::ARMRegisters::r5);
+  am->push(JSC::ARMRegisters::r6);
+  am->push(JSC::ARMRegisters::r7);
+  am->push(JSC::ARMRegisters::r8);
+  am->push(JSC::ARMRegisters::r9);
+  am->push(JSC::ARMRegisters::r10);
+  am->push(JSC::ARMRegisters::r11);
+
+  am->xorPtr(rreg,rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(123), rreg);
+  am->addPtr(JSC::MacroAssembler::Imm32(321), rreg);
+
+  am->pop(JSC::ARMRegisters::r11);
+  am->pop(JSC::ARMRegisters::r10);
+  am->pop(JSC::ARMRegisters::r9);
+  am->pop(JSC::ARMRegisters::r8);
+  am->pop(JSC::ARMRegisters::r7);
+  am->pop(JSC::ARMRegisters::r6);
+  am->pop(JSC::ARMRegisters::r5);
+  am->pop(JSC::ARMRegisters::r4);
+
+  am->ret();
+#endif
+
+  // prepare a link buffer, into which we can copy the completed insns
+  JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
+
+  // intermediate step .. get the pool suited for the size of code in 'am'
+  //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
+  JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
+
+  // constructor for LinkBuffer asks ep to allocate r-x memory,
+  // then copies it there.
+  JSC::LinkBuffer patchBuffer(am, ep);
+
+  // now fix up any branches/calls
+  //JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
+
+  // finalize
+  JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
+
+  // cr now holds a pointer to the final runnable code.
+  void* entry = cr.m_code.executableAddress();
+
+  printf("disas %p %p\n",
+         entry, (char*)entry + cr.m_size);
+  pre_run();
+
+  // call the function
+  unsigned long (*fn)(void) = (unsigned long (*)())entry;
+  unsigned long result = fn();
+
+  printf("\n");
+  printf("value computed is %lu (expected 444)\n", result);
+  printf("\n");
+
+  delete eal;
+  delete am;
+}
+
+
+/////////////////////////////////////////////////////////////////
+//// test5 (call in, out, repatch) 
+
+// a function which we will call from the JIT generated code
+unsigned long cube   ( unsigned long x ) { return x * x * x; }
+unsigned long square ( unsigned long x ) { return x * x; }
+
+void test5 ( void )
+{
+  printf("\n--------- Test 5 (call in, out, repatch) ---------\n\n" );
+
+  // Create new assembler
+  JSC::MacroAssembler* am = new JSC::MacroAssembler();
+  JSC::MacroAssembler::Call cl;
+  ptrdiff_t offset_of_call_insn;
+
+#if defined(ARCH_amd64)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  // and then call a non-JIT-generated helper from within
+  // this code
+  //    push   %rbp
+  //    mov    %rsp,%rbp
+  //    push   %rbx
+  //    push   %r12
+  //    push   %r13
+  //    push   %r14
+  //    push   %r15
+  //    mov    $0x9,%edi
+  //    mov    $0x40187e,%r11
+  //    callq  *%r11
+  //    pop    %r15
+  //    pop    %r14
+  //    pop    %r13
+  //    pop    %r12
+  //    pop    %rbx
+  //    mov    %rbp,%rsp
+  //    pop    %rbp
+  //    retq
+  JSC::MacroAssembler::Label startOfFnLbl(am);
+  am->push(JSC::X86Registers::ebp);
+  am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
+  am->push(JSC::X86Registers::ebx);
+  am->push(JSC::X86Registers::r12);
+  am->push(JSC::X86Registers::r13);
+  am->push(JSC::X86Registers::r14);
+  am->push(JSC::X86Registers::r15);
+
+  // let's compute cube(9).  Move $9 to the first arg reg.
+  am->move(JSC::MacroAssembler::Imm32(9), JSC::X86Registers::edi);
+  cl = am->JSC::MacroAssembler::call();
+
+  // result is now in %rax.  Leave it ther and just return.
+
+  am->pop(JSC::X86Registers::r15);
+  am->pop(JSC::X86Registers::r14);
+  am->pop(JSC::X86Registers::r13);
+  am->pop(JSC::X86Registers::r12);
+  am->pop(JSC::X86Registers::ebx);
+  am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
+  am->pop(JSC::X86Registers::ebp);
+  am->ret();
+
+  offset_of_call_insn
+     = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
+  if (0) printf("XXXXXXXX offset = %lu\n", offset_of_call_insn);
+#endif
+
+#if defined(ARCH_x86)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  // and then call a non-JIT-generated helper from within
+  // this code
+  //    push   %ebp
+  //    mov    %esp,%ebp
+  //    push   %ebx
+  //    push   %esi
+  //    push   %edi
+  //    push   $0x9
+  //    call   0x80490e9 <_Z4cubem>
+  //    add    $0x4,%esp
+  //    pop    %edi
+  //    pop    %esi
+  //    pop    %ebx
+  //    mov    %ebp,%esp
+  //    pop    %ebp
+  //    ret
+  JSC::MacroAssembler::Label startOfFnLbl(am);
+  am->push(JSC::X86Registers::ebp);
+  am->move(JSC::X86Registers::esp, JSC::X86Registers::ebp);
+  am->push(JSC::X86Registers::ebx);
+  am->push(JSC::X86Registers::esi);
+  am->push(JSC::X86Registers::edi);
+
+  // let's compute cube(9).  Push $9 on the stack.
+  am->push(JSC::MacroAssembler::Imm32(9));
+  cl = am->JSC::MacroAssembler::call();
+  am->addPtr(JSC::MacroAssembler::Imm32(4), JSC::X86Registers::esp);
+  // result is now in %eax.  Leave it there and just return.
+
+  am->pop(JSC::X86Registers::edi);
+  am->pop(JSC::X86Registers::esi);
+  am->pop(JSC::X86Registers::ebx);
+  am->move(JSC::X86Registers::ebp, JSC::X86Registers::esp);
+  am->pop(JSC::X86Registers::ebp);
+  am->ret();
+
+  offset_of_call_insn
+     = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
+  if (0) printf("XXXXXXXX offset = %lu\n",
+                (unsigned long)offset_of_call_insn);
+#endif
+
+#if defined(ARCH_arm)
+  // ADD FN PROLOGUE/EPILOGUE so as to make a mini-function
+  //    push    {r4}            ; (str r4, [sp, #-4]!)
+  //    push    {r5}            ; (str r5, [sp, #-4]!)
+  //    push    {r6}            ; (str r6, [sp, #-4]!)
+  //    push    {r7}            ; (str r7, [sp, #-4]!)
+  //    push    {r8}            ; (str r8, [sp, #-4]!)
+  //    push    {r9}            ; (str r9, [sp, #-4]!)
+  //    push    {r10}           ; (str r10, [sp, #-4]!)
+  //    push    {r11}           ; (str r11, [sp, #-4]!)
+  //    eors    r0, r0, r0
+  //    adds    r0, r0, #123    ; 0x7b
+  //    mov     r3, #256        ; 0x100
+  //    orr     r3, r3, #65     ; 0x41
+  //    adds    r0, r0, r3
+  //    pop     {r11}           ; (ldr r11, [sp], #4)
+  //    pop     {r10}           ; (ldr r10, [sp], #4)
+  //    pop     {r9}            ; (ldr r9, [sp], #4)
+  //    pop     {r8}            ; (ldr r8, [sp], #4)
+  //    pop     {r7}            ; (ldr r7, [sp], #4)
+  //    pop     {r6}            ; (ldr r6, [sp], #4)
+  //    pop     {r5}            ; (ldr r5, [sp], #4)
+  //    pop     {r4}            ; (ldr r4, [sp], #4)
+  //    mov     pc, lr
+  // callable as a normal function, returns 444
+  JSC::MacroAssembler::Label startOfFnLbl(am);
+  am->push(JSC::ARMRegisters::r4);
+  am->push(JSC::ARMRegisters::r5);
+  am->push(JSC::ARMRegisters::r6);
+  am->push(JSC::ARMRegisters::r7);
+  am->push(JSC::ARMRegisters::r8);
+  am->push(JSC::ARMRegisters::r9);
+  am->push(JSC::ARMRegisters::r10);
+  am->push(JSC::ARMRegisters::r11);
+  am->push(JSC::ARMRegisters::lr);
+
+  // let's compute cube(9).  Get $9 into r0.
+  am->move(JSC::MacroAssembler::Imm32(9), JSC::ARMRegisters::r0);
+  cl = am->JSC::MacroAssembler::call();
+  // result is now in r0.  Leave it there and just return.
+
+  am->pop(JSC::ARMRegisters::lr);
+  am->pop(JSC::ARMRegisters::r11);
+  am->pop(JSC::ARMRegisters::r10);
+  am->pop(JSC::ARMRegisters::r9);
+  am->pop(JSC::ARMRegisters::r8);
+  am->pop(JSC::ARMRegisters::r7);
+  am->pop(JSC::ARMRegisters::r6);
+  am->pop(JSC::ARMRegisters::r5);
+  am->pop(JSC::ARMRegisters::r4);
+  am->ret();
+
+  offset_of_call_insn
+     = am->JSC::MacroAssembler::differenceBetween(startOfFnLbl, cl);
+  if (0) printf("XXXXXXXX offset = %lu\n",
+                (unsigned long)offset_of_call_insn);
+#endif
+
+  // prepare a link buffer, into which we can copy the completed insns
+  JSC::ExecutableAllocator* eal = new JSC::ExecutableAllocator();
+
+  // intermediate step .. get the pool suited for the size of code in 'am'
+  //WTF::PassRefPtr<JSC::ExecutablePool> ep = eal->poolForSize( am->size() );
+  JSC::ExecutablePool* ep = eal->poolForSize( am->size() );
+
+  // constructor for LinkBuffer asks ep to allocate r-x memory,
+  // then copies it there.
+  JSC::LinkBuffer patchBuffer(am, ep);
+
+  // now fix up any branches/calls
+  JSC::FunctionPtr target = JSC::FunctionPtr::FunctionPtr( &cube );
+  patchBuffer.link(cl, target);
+
+  JSC::MacroAssemblerCodeRef cr = patchBuffer.finalizeCode();
+
+  // cr now holds a pointer to the final runnable code.
+  void* entry = cr.m_code.executableAddress();
+
+  printf("disas %p %p\n",
+         entry, (char*)entry + cr.m_size);
+
+
+  pre_run();
+
+  printf("\n");
+
+  unsigned long (*fn)() = (unsigned long(*)())entry;
+  unsigned long result = fn();
+
+  printf("value computed is %lu (expected 729)\n", result);
+  printf("\n");
+
+  // now repatch the call in the JITted code to go elsewhere
+  JSC::JITCode jc = JSC::JITCode::JITCode(entry, cr.m_size);
+  JSC::CodeBlock cb = JSC::CodeBlock::CodeBlock(jc);
+
+  // the address of the call insn, that we want to prod
+  JSC::MacroAssemblerCodePtr cp
+     = JSC::MacroAssemblerCodePtr( ((char*)entry) + offset_of_call_insn );
+
+  JSC::RepatchBuffer repatchBuffer(&cb);
+  repatchBuffer.relink( JSC::CodeLocationCall(cp),
+                        JSC::FunctionPtr::FunctionPtr( &square ));
+ 
+  result = fn();
+  printf("value computed is %lu (expected 81)\n", result);
+  printf("\n\n");
+
+  delete eal;
+  delete am;
+}
+
+/////////////////////////////////////////////////////////////////
+
+int main ( void )
+{
+#if WTF_COMPILER_GCC
+  test1();
+  test2();
+  test3();
+#endif
+  test4();
+  test5();
+  return 0;
+}
--- a/js/src/assembler/assembler/ARMAssembler.cpp
+++ b/js/src/assembler/assembler/ARMAssembler.cpp
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
 
 #include "ARMAssembler.h"
 
 namespace JSC {
@@ -266,55 +270,55 @@ void ARMAssembler::dataTransfer32(bool i
 {
     if (offset >= 0) {
         if (offset <= 0xfff)
             dtr_u(isLoad, srcDst, base, offset);
         else if (offset <= 0xfffff) {
             add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtr_u(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff));
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtr_ur(isLoad, srcDst, base, reg);
+            moveImm(offset, ARMRegisters::S0);
+            dtr_ur(isLoad, srcDst, base, ARMRegisters::S0);
         }
     } else {
         offset = -offset;
         if (offset <= 0xfff)
             dtr_d(isLoad, srcDst, base, offset);
         else if (offset <= 0xfffff) {
             sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff));
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtr_dr(isLoad, srcDst, base, reg);
+            moveImm(offset, ARMRegisters::S0);
+            dtr_dr(isLoad, srcDst, base, ARMRegisters::S0);
         }
     }
 }
 
 void ARMAssembler::dataTransfer8(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset)
 {
     if (offset >= 0) {
         if (offset <= 0xfff)
             dtrb_u(isLoad, srcDst, base, offset);
         else if (offset <= 0xfffff) {
             add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtrb_u(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff));
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtrb_ur(isLoad, srcDst, base, reg);
+            moveImm(offset, ARMRegisters::S0);
+            dtrb_ur(isLoad, srcDst, base, ARMRegisters::S0);
         }
     } else {
         offset = -offset;
         if (offset <= 0xfff)
             dtrb_d(isLoad, srcDst, base, offset);
         else if (offset <= 0xfffff) {
             sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtrb_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff));
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtrb_dr(isLoad, srcDst, base, reg);
+            moveImm(offset, ARMRegisters::S0);
+            dtrb_dr(isLoad, srcDst, base, ARMRegisters::S0);
         }
     }
 }
 
 void ARMAssembler::baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
 {
     ARMWord op2;
 
@@ -381,24 +385,29 @@ inline void ARMAssembler::fixUpOffsets(v
 {
     char * data = reinterpret_cast<char *>(buffer);
     for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
         // The last bit is set if the constant must be placed on constant pool.
         int pos = (*iter) & (~0x1);
         ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
         ARMWord* addr = getLdrImmAddress(ldrAddr);
         if (*addr != InvalidBranchTarget) {
+// The following is disabled for JM because we patch some branches after
+// calling fixUpOffset, and the branch patcher doesn't know how to handle 'B'
+// instructions.
+#if 0
             if (!(*iter & 1)) {
                 int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
 
                 if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
                     *ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK);
                     continue;
                 }
             }
+#endif
             *addr = reinterpret_cast<ARMWord>(data + *addr);
         }
     }
 }
 
 void* ARMAssembler::executableCopy(ExecutablePool* allocator)
 {
     // 64-bit alignment is required for next constant pool and JIT code as well
--- a/js/src/assembler/assembler/ARMAssembler.h
+++ b/js/src/assembler/assembler/ARMAssembler.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009, 2010 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef ARMAssembler_h
 #define ARMAssembler_h
 
 #include "assembler/wtf/Platform.h"
 
 // Some debug code uses s(n)printf for instruction logging.
 #include <stdio.h>
@@ -200,16 +204,17 @@ namespace JSC {
             BL = 0x0b000000
 #if WTF_ARM_ARCH_VERSION >= 5 || defined(__ARM_ARCH_4T__)
            ,BX = 0x012fff10
 #endif
            ,FMSR = 0x0e000a10,
             FMRS = 0x0e100a10,
             FSITOD = 0x0eb80bc0,
             FTOSID = 0x0ebd0b40,
+            FTOSIZD = 0x0ebd0bc0,
             FMSTAT = 0x0ef1fa10
 #if WTF_ARM_ARCH_VERSION >= 5
            ,CLZ = 0x016f0f10,
             BKPT = 0xe120070,
             BLX = 0x012fff30
 #endif
 #if WTF_ARM_ARCH_VERSION >= 7
            ,MOVW = 0x03000000,
@@ -421,16 +426,22 @@ namespace JSC {
         }
 
         void cmp_r(int rn, ARMWord op2, Condition cc = AL)
         {
             spewInsWithOp2("cmp", cc, rn, op2);
             emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
         }
 
+        void cmn_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            spewInsWithOp2("cmn", cc, rn, op2);
+            emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2);
+        }
+
         void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
             spewInsWithOp2("orr", cc, rd, rn, op2);
             emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
         }
 
         void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
@@ -712,26 +723,28 @@ namespace JSC {
         {
             js::JaegerSpew(js::JSpew_Insns,
                     IPFX   "%-15s %s, [%s, +%s]\n", MAYBE_PAD, "strh", nameGpReg(rd), nameGpReg(rb), nameGpReg(rm));
             emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rb, rm);
         }
 
         void fdtr_u(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL)
         {
+            char const * ins = isLoad ? "vldr.f64" : "vstr.f64";
             js::JaegerSpew(js::JSpew_Insns,
-                    IPFX   "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset);
+                    IPFX   "%-15s %s, [%s, #+%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset);
             ASSERT(offset <= 0xff);
             emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), dd, rn, offset);
         }
 
         void fdtr_d(bool isLoad, int dd, int rn, ARMWord offset, Condition cc = AL)
         {
+            char const * ins = isLoad ? "vldr.f64" : "vstr.f64";
             js::JaegerSpew(js::JSpew_Insns,
-                    IPFX   "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, "vldr.f64", nameFpRegD(dd), nameGpReg(rn), offset);
+                    IPFX   "%-15s %s, [%s, #-%u]\n", MAYBE_PAD, ins, nameFpRegD(dd), nameGpReg(rn), offset);
             ASSERT(offset <= 0xff);
             emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), dd, rn, offset);
         }
 
         void push_r(int reg, Condition cc = AL)
         {
             js::JaegerSpew(js::JSpew_Insns,
                     IPFX   "%-15s {%s}\n", MAYBE_PAD, "push", nameGpReg(reg));
@@ -780,16 +793,23 @@ namespace JSC {
 
         void ftosid_r(int fd, int dm, Condition cc = AL)
         {
             // TODO: emitInst doesn't work for VFP instructions, though it
             // seems to work for current usage.
             emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
         }
 
+        void ftosizd_r(int fd, int dm, Condition cc = AL)
+        {
+            // TODO: emitInst doesn't work for VFP instructions, though it
+            // seems to work for current usage.
+            emitInst(static_cast<ARMWord>(cc) | FTOSIZD, fd, 0, dm);
+        }
+
         void fmstat(Condition cc = AL)
         {
             // TODO: emitInst doesn't work for VFP instructions, though it
             // seems to work for current usage.
             m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
         }
 
 #if WTF_ARM_ARCH_VERSION >= 5
@@ -1215,19 +1235,26 @@ namespace JSC {
         }
 
         // Decodes operand 2 immediate values (for debug output and assertions).
         inline uint32_t decOp2Imm(uint32_t op2)
         {
             ASSERT((op2 & ~0xfff) == 0);
 
             uint32_t    imm8 = op2 & 0xff;
-            uint32_t    rot = 32 - ((op2 >> 7) & 0x1e);
+            uint32_t    rot = ((op2 >> 7) & 0x1e);
+
+            // 'rot' is a right-rotate count.
 
-            return imm8 << (rot & 0x1f);
+            uint32_t    imm = (imm8 >> rot);
+            if (rot > 0) {
+                imm |= (imm8 << (32-rot));
+            }
+
+            return imm;
         }
 
         // Format the operand 2 argument for debug spew. The operand can be
         // either an immediate or a register specifier.
         void fmtOp2(char * out, ARMWord op2)
         {
             static char const * const shifts[4] = {"LSL", "LSR", "ASR", "ROR"};
 
--- a/js/src/assembler/assembler/ARMv7Assembler.h
+++ b/js/src/assembler/assembler/ARMv7Assembler.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  * Copyright (C) 2010 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef ARMAssembler_h
 #define ARMAssembler_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2)
 
--- a/js/src/assembler/assembler/AbstractMacroAssembler.h
+++ b/js/src/assembler/assembler/AbstractMacroAssembler.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
 #include "assembler/wtf/Platform.h"
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 #include "assembler/assembler/CodeLocation.h"
 #include "jsstdint.h"
@@ -273,18 +277,18 @@ public:
         }
         
     private:
         JmpDst m_label;
     };
 
     // DataLabel32:
     //
-    // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
-    // patched after the code has been generated.
+    // A DataLabel32 is used to refer to a location in the code containing a
+    // 32-bit constant to be patched after the code has been generated.
     class DataLabel32 {
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
         friend class LinkBuffer;
     public:
         DataLabel32()
         {
         }
@@ -478,16 +482,21 @@ public:
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
     ptrdiff_t differenceBetween(Label from, DataLabel32 to)
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
+    ptrdiff_t differenceBetween(DataLabel32 from, Label to)
+    {
+        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+    }
+
     ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
     }
 
     ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
--- a/js/src/assembler/assembler/AssemblerBuffer.h
+++ b/js/src/assembler/assembler/AssemblerBuffer.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef AssemblerBuffer_h
 #define AssemblerBuffer_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
--- a/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
+++ b/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef AssemblerBufferWithConstantPool_h
 #define AssemblerBufferWithConstantPool_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
--- a/js/src/assembler/assembler/CodeLocation.h
+++ b/js/src/assembler/assembler/CodeLocation.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef CodeLocation_h
 #define CodeLocation_h
 
 #include "assembler/wtf/Platform.h"
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 
 #if ENABLE_ASSEMBLER
--- a/js/src/assembler/assembler/LinkBuffer.h
+++ b/js/src/assembler/assembler/LinkBuffer.h
@@ -1,9 +1,12 @@
-/* vim: set ts=4 sw=4 tw=99 et:
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef LinkBuffer_h
 #define LinkBuffer_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
--- a/js/src/assembler/assembler/MacroAssembler.h
+++ b/js/src/assembler/assembler/MacroAssembler.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssembler_h
 #define MacroAssembler_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
--- a/js/src/assembler/assembler/MacroAssemblerARM.cpp
+++ b/js/src/assembler/assembler/MacroAssemblerARM.cpp
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
 
 #include "MacroAssemblerARM.h"
 
 #if WTF_PLATFORM_LINUX || WTF_PLATFORM_ANDROID
--- a/js/src/assembler/assembler/MacroAssemblerARM.h
+++ b/js/src/assembler/assembler/MacroAssemblerARM.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc.
  * Copyright (C) 2009, 2010 University of Szeged
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
@@ -18,17 +21,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerARM_h
 #define MacroAssemblerARM_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && WTF_CPU_ARM_TRADITIONAL
 
@@ -274,16 +278,26 @@ public:
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
         DataLabel32 dataLabel(this);
         m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
         m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
         return dataLabel;
     }
 
+    DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID hi, RegisterID lo)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
+        m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
+        m_assembler.dtr_u(true, lo, ARMRegisters::S0, 0);
+        m_assembler.dtr_u(true, hi, ARMRegisters::S0, 4);
+        return dataLabel;
+    }
+
     Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
     {
         Label label(this);
         load32(address, dest);
         return label;
     }
 
     void load16(BaseIndex address, RegisterID dest)
@@ -303,16 +317,37 @@ public:
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
         DataLabel32 dataLabel(this);
         m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
         m_assembler.dtr_ur(false, src, address.base, ARMRegisters::S0);
         return dataLabel;
     }
 
+    DataLabel32 store64WithAddressOffsetPatch(RegisterID hi, RegisterID lo, Address address)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
+        m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
+        m_assembler.dtr_u(false, lo, ARMRegisters::S0, 0);
+        m_assembler.dtr_u(false, hi, ARMRegisters::S0, 4);
+        return dataLabel;
+    }
+
+    DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, RegisterID lo, Address address)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
+        m_assembler.getImm(hi.m_value, ARMRegisters::S1);
+        m_assembler.add_r(ARMRegisters::S0, ARMRegisters::S0, address.base);
+        m_assembler.dtr_u(false, lo, ARMRegisters::S0, 0);
+        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 4);
+        return dataLabel;
+    }
+
     void store32(RegisterID src, ImplicitAddress address)
     {
         m_assembler.dataTransfer32(false, src, address.base, address.offset);
     }
 
     void store32(RegisterID src, BaseIndex address)
     {
         m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
@@ -428,16 +463,23 @@ public:
         if (right.m_isPointer) {
             m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
             m_assembler.cmp_r(left, ARMRegisters::S0);
         } else
             m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
         return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
     }
 
+    // As branch32, but allow the value ('right') to be patched.
+    Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
+    {
+        dataLabel = moveWithPatch(right, ARMRegisters::S1);
+        return branch32(cond, left, ARMRegisters::S1, true);
+    }
+
     Jump branch32(Condition cond, RegisterID left, Address right)
     {
         load32(right, ARMRegisters::S1);
         return branch32(cond, left, ARMRegisters::S1);
     }
 
     Jump branch32(Condition cond, Address left, RegisterID right)
     {
@@ -813,16 +855,23 @@ public:
 
     DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
     {
         DataLabelPtr dataLabel(this);
         m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
         return dataLabel;
     }
 
+    DataLabel32 moveWithPatch(Imm32 initialValue, RegisterID dest)
+    {
+        DataLabel32 dataLabel(this);
+        m_assembler.ldr_un_imm(dest, initialValue.m_value);
+        return dataLabel;
+    }
+
     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
     {
         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
         Jump jump = branch32(cond, left, ARMRegisters::S1, true);
         return jump;
     }
 
     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
@@ -848,17 +897,17 @@ public:
     // Floating point operators
     bool supportsFloatingPoint() const
     {
         return s_isVFPPresent;
     }
 
     bool supportsFloatingPointTruncate() const
     {
-        return false;
+        return true;
     }
 
     bool supportsFloatingPointSqrt() const
     {
         return s_isVFPPresent;
     }
 
     void moveDouble(FPRegisterID src, FPRegisterID dest)
@@ -967,23 +1016,26 @@ public:
         if (cond & DoubleConditionBitSpecial)
             m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
         return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
     }
 
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits
-    // (specifically, in this case, INT_MIN).
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
-        (void)(src);
-        (void)(dest);
-        ASSERT_NOT_REACHED();
-        return jump();
+        m_assembler.ftosizd_r(ARMRegisters::SD0, src);
+        // If FTOSIZD (VCVT.S32.F64) can't fit the result into a 32-bit
+        // integer, it saturates at INT_MAX or INT_MIN. Testing this is
+        // probably quicker than testing FPSCR for exception.
+        m_assembler.fmrs_r(dest, ARMRegisters::SD0);
+        m_assembler.cmn_r(dest, ARMAssembler::getOp2(-0x7fffffff));
+        m_assembler.cmp_r(dest, ARMAssembler::getOp2(0x80000000), ARMCondition(NonZero));
+        return Jump(m_assembler.jmp(ARMCondition(Zero)));
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits
     // (specifically, in this case, 0).
     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
     {
@@ -1104,29 +1156,29 @@ protected:
 
         if (offset >= 0) {
             if (offset <= 0xfff) {
                 m_assembler.dtr_u(true, ARMRegisters::S0, base, offset);
             } else if (offset <= 0xfffff) {
                 m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
                 m_assembler.dtr_u(true, ARMRegisters::S0, ARMRegisters::S0, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
-                m_assembler.dtr_ur(true, ARMRegisters::S0, base, reg);
+                m_assembler.moveImm(offset, ARMRegisters::S0);
+                m_assembler.dtr_ur(true, ARMRegisters::S0, base, ARMRegisters::S0);
             }
         } else  {
             offset = -offset;
             if (offset <= 0xfff) {
                 m_assembler.dtr_d(true, ARMRegisters::S0, base, offset);
             } else if (offset <= 0xfffff) {
                 m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
                 m_assembler.dtr_d(true, ARMRegisters::S0, ARMRegisters::S0, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
-                m_assembler.dtr_dr(true, ARMRegisters::S0, base, reg);
+                m_assembler.moveImm(offset, ARMRegisters::S0);
+                m_assembler.dtr_dr(true, ARMRegisters::S0, base, ARMRegisters::S0);
             }
         }
         m_assembler.blx(ARMRegisters::S0);
     }
 #endif
 
 private:
     friend class LinkBuffer;
--- a/js/src/assembler/assembler/MacroAssemblerARMv7.h
+++ b/js/src/assembler/assembler/MacroAssemblerARMv7.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  * Copyright (C) 2010 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
@@ -17,17 +20,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerARMv7_h
 #define MacroAssemblerARMv7_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE(ASSEMBLER)
 
--- a/js/src/assembler/assembler/MacroAssemblerCodeRef.h
+++ b/js/src/assembler/assembler/MacroAssemblerCodeRef.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerCodeRef_h
 #define MacroAssemblerCodeRef_h
 
 #include "assembler/wtf/Platform.h"
 #include "assembler/jit/ExecutableAllocator.h"
 
 #if ENABLE_ASSEMBLER
@@ -150,16 +154,23 @@ public:
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
     bool operator!()
     {
         return !m_value;
     }
 
+    ptrdiff_t operator -(const MacroAssemblerCodePtr &other) const
+    {
+        JS_ASSERT(m_value);
+        return reinterpret_cast<uint8 *>(m_value) -
+               reinterpret_cast<uint8 *>(other.m_value);
+    }
+
 private:
     void* m_value;
 };
 
 // MacroAssemblerCodeRef:
 //
 // A reference to a section of JIT generated code.  A CodeRef consists of a
 // pointer to the code, and a ref pointer to the pool from within which it
--- a/js/src/assembler/assembler/MacroAssemblerX86.h
+++ b/js/src/assembler/assembler/MacroAssemblerX86.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerX86_h
 #define MacroAssemblerX86_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && WTF_CPU_X86
 
--- a/js/src/assembler/assembler/MacroAssemblerX86Common.cpp
+++ b/js/src/assembler/assembler/MacroAssemblerX86Common.cpp
@@ -1,11 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * ***** 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 SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation
+ *
+ * Contributor(s):
+ *   Alex Miller <amiller@mozilla.com>
+ *
+ * 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 ***** */
+
 #include "assembler/wtf/Platform.h"
 
-#if WTF_CPU_X86 && !WTF_PLATFORM_MAC
+/* SSE checks only make sense on Intel platforms. */
+#if WTF_CPU_X86 || WTF_CPU_X86_64
 
 #include "MacroAssemblerX86Common.h"
 
 using namespace JSC;
+MacroAssemblerX86Common::SSECheckState MacroAssemblerX86Common::s_sseCheckState = NotCheckedSSE;
 
-MacroAssemblerX86Common::SSE2CheckState MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
+#endif /* WTF_CPU_X86 || WTF_CPU_X86_64 */
 
-#endif
--- a/js/src/assembler/assembler/MacroAssemblerX86Common.h
+++ b/js/src/assembler/assembler/MacroAssemblerX86Common.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerX86Common_h
 #define MacroAssemblerX86Common_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
@@ -714,21 +718,21 @@ public:
     // immediate operand to 32 bits in the native code stream.
     Jump branch32_force32(Condition cond, RegisterID left, Imm32 right)
     {
         m_assembler.cmpl_ir_force32(right.m_value, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
     // Branch and record a label after the comparison.
-    Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, Label &clabel)
+    Jump branch32WithPatch(Condition cond, RegisterID left, Imm32 right, DataLabel32 &dataLabel)
     {
         // Always use cmpl, since the value is to be patched.
         m_assembler.cmpl_ir(right.m_value, left);
-        clabel = label();
+        dataLabel = DataLabel32(this);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
     Jump branch32(Condition cond, RegisterID left, Address right)
     {
         m_assembler.cmpl_mr(right.offset, right.base, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
@@ -1069,89 +1073,149 @@ public:
         if (mask.m_value == -1)
             m_assembler.cmpl_im(0, address.offset, address.base);
         else
             m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
         m_assembler.setCC_r(x86Condition(cond), dest);
         m_assembler.movzbl_rr(dest, dest);
     }
 
+    enum SSECheckState {
+        NotCheckedSSE = 0,
+        NoSSE = 1,
+        HasSSE2 = 2,
+        HasSSE4_1 = 3, // implies HasSSE2
+        HasSSE4_2 = 4  // implies HasSSE4_1
+    };
+
+    static SSECheckState getSSEState()
+    {
+        if (s_sseCheckState == NotCheckedSSE) {
+            MacroAssemblerX86Common::setSSECheckState();
+        }
+        // Only check once.
+        ASSERT(s_sseCheckState != NotCheckedSSE);
+
+        return s_sseCheckState;
+    }
+
 protected:
     X86Assembler::Condition x86Condition(Condition cond)
     {
         return static_cast<X86Assembler::Condition>(cond);
     }
 
 private:
-    // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on
-    // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
     friend class MacroAssemblerX86;
 
+    static SSECheckState s_sseCheckState;
+
+    static void setSSECheckState()
+    {
+        // Default the flags value to zero; if the compiler is
+        // not MSVC or GCC we will read this as SSE2 not present.
+        int flags_edx = 0;
+        int flags_ecx = 0;
+#if WTF_COMPILER_MSVC
+#if WTF_CPU_X86_64
+        extern void __cpuid(int a[4], int b);
+        int cpuinfo[4];
+
+        __cpuid(cpuinfo, 1);
+        flags_ecx = cpuinfo[2];
+        flags_edx = cpuinfo[3];
+#else
+        _asm {
+            mov eax, 1 // cpuid function 1 gives us the standard feature set
+            cpuid;
+            mov flags_ecx, ecx;
+            mov flags_edx, edx;
+        }
+#endif
+#elif WTF_COMPILER_GCC
+        asm (
+             "movl $0x1, %%eax;"
+             "pushl %%ebx;"
+             "cpuid;"
+             "popl %%ebx;"
+             "movl %%ecx, %0;"
+             "movl %%edx, %1;"
+             : "=g" (flags_ecx), "=g" (flags_edx)
+             :
+             : "%eax", "%ecx", "%edx"
+             );
+#endif
+        static const int SSE2FeatureBit = 1 << 26;
+        static const int SSE41FeatureBit = 1 << 19;
+        static const int SSE42FeatureBit = 1 << 20;
+        if (flags_ecx & SSE42FeatureBit)
+            s_sseCheckState = HasSSE4_2;
+        else if (flags_ecx & SSE41FeatureBit)
+            s_sseCheckState = HasSSE4_1;
+        else if (flags_edx & SSE2FeatureBit)
+            s_sseCheckState = HasSSE2;
+        else
+            s_sseCheckState = NoSSE;
+    }
+
 #if WTF_CPU_X86
 #if WTF_PLATFORM_MAC
 
     // All X86 Macs are guaranteed to support at least SSE2,
     static bool isSSE2Present()
     {
         return true;
     }
 
 #else // PLATFORM(MAC)
 
-    enum SSE2CheckState {
-        NotCheckedSSE2,
-        HasSSE2,
-        NoSSE2
-    };
-
     static bool isSSE2Present()
     {
-        if (s_sse2CheckState == NotCheckedSSE2) {
-            // Default the flags value to zero; if the compiler is
-            // not MSVC or GCC we will read this as SSE2 not present.
-            int flags = 0;
-#if WTF_COMPILER_MSVC
-            _asm {
-                mov eax, 1 // cpuid function 1 gives us the standard feature set
-                cpuid;
-                mov flags, edx;
-            }
-#elif WTF_COMPILER_GCC
-            asm (
-                 "movl $0x1, %%eax;"
-                 "pushl %%ebx;"
-                 "cpuid;"
-                 "popl %%ebx;"
-                 "movl %%edx, %0;"
-                 : "=g" (flags)
-                 :
-                 : "%eax", "%ecx", "%edx"
-                 );
-#endif
-            static const int SSE2FeatureBit = 1 << 26;
-            s_sse2CheckState = (flags & SSE2FeatureBit) ? HasSSE2 : NoSSE2;
+        if (s_sseCheckState == NotCheckedSSE) {
+            setSSECheckState();
         }
         // Only check once.
-        ASSERT(s_sse2CheckState != NotCheckedSSE2);
+        ASSERT(s_sseCheckState != NotCheckedSSE);
 
-        return s_sse2CheckState == HasSSE2;
+        return s_sseCheckState >= HasSSE2;
     }
     
-    static SSE2CheckState s_sse2CheckState;
 
 #endif // PLATFORM(MAC)
 #elif !defined(NDEBUG) // CPU(X86)
 
     // On x86-64 we should never be checking for SSE2 in a non-debug build,
     // but non debug add this method to keep the asserts above happy.
     static bool isSSE2Present()
     {
         return true;
     }
 
 #endif
+
+    static bool isSSE41Present()
+    {
+        if (s_sseCheckState == NotCheckedSSE) {
+            setSSECheckState();
+        }
+        // Only check once.
+        ASSERT(s_sseCheckState != NotCheckedSSE);
+
+        return s_sseCheckState >= HasSSE4_1;
+    }
+
+    static bool isSSE42Present()
+    {
+        if (s_sseCheckState == NotCheckedSSE) {
+            setSSECheckState();
+        }
+        // Only check once.
+        ASSERT(s_sseCheckState != NotCheckedSSE);
+
+        return s_sseCheckState >= HasSSE4_2;
+    }
 };
 
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
 
 #endif // MacroAssemblerX86Common_h
--- a/js/src/assembler/assembler/MacroAssemblerX86_64.h
+++ b/js/src/assembler/assembler/MacroAssemblerX86_64.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef MacroAssemblerX86_64_h
 #define MacroAssemblerX86_64_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && WTF_CPU_X86_64
 
--- a/js/src/assembler/assembler/RepatchBuffer.h
+++ b/js/src/assembler/assembler/RepatchBuffer.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2009 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef RepatchBuffer_h
 #define RepatchBuffer_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -1,9 +1,12 @@
-/*
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Copyright (C) 2008 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
@@ -16,17 +19,18 @@
  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
+ * 
+ * ***** END LICENSE BLOCK ***** */
 
 #ifndef X86Assembler_h
 #define X86Assembler_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64)
 
@@ -176,16 +180,17 @@ public:
 
 private:
     typedef enum {
         OP_ADD_EvGv                     = 0x01,
         OP_ADD_GvEv                     = 0x03,
         OP_OR_EvGv                      = 0x09,
         OP_OR_GvEv                      = 0x0B,
         OP_2BYTE_ESCAPE                 = 0x0F,
+        OP_3BYTE_ESCAPE                 = 0x3A,
         OP_AND_EvGv                     = 0x21,
         OP_AND_GvEv                     = 0x23,
         OP_SUB_EvGv                     = 0x29,
         OP_SUB_GvEv                     = 0x2B,
         PRE_PREDICT_BRANCH_NOT_TAKEN    = 0x2E,
         OP_XOR_EvGv                     = 0x31,
         OP_XOR_GvEv                     = 0x33,
         OP_CMP_EvGv                     = 0x39,
@@ -253,16 +258,20 @@ private:
         OP2_JCC_rel32       = 0x80,
         OP_SETCC            = 0x90,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_MOVZX_GvEb      = 0xB6,
         OP2_MOVZX_GvEw      = 0xB7,
         OP2_PEXTRW_GdUdIb   = 0xC5
     } TwoByteOpcodeID;
 
+    typedef enum {
+        OP3_PINSRD_VsdWsd   = 0x22
+    } ThreeByteOpcodeID;
+
     TwoByteOpcodeID jccRel32(Condition cond)
     {
         return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond);
     }
 
     TwoByteOpcodeID setccOpcode(Condition cond)
     {
         return (TwoByteOpcodeID)(OP_SETCC + cond);
@@ -835,17 +844,19 @@ public:
             m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
             m_formatter.immediate32(imm);
         }
     }
 
 #if WTF_CPU_X86_64
     void xorq_rr(RegisterID src, RegisterID dst)
     {
-        FIXME_INSN_PRINTING;
+        js::JaegerSpew(js::JSpew_Insns,
+                       IPFX "xorq       %s, %s\n", MAYBE_PAD,
+                       nameIReg(4,src), nameIReg(4, dst));
         m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
     }
 
     void xorq_ir(int imm, RegisterID dst)
     {
         js::JaegerSpew(js::JSpew_Insns,
                        IPFX "xorq       %d, %s\n", MAYBE_PAD,
                        imm, nameIReg(8,dst));
@@ -2001,16 +2012,26 @@ public:
     {
         js::JaegerSpew(js::JSpew_Insns,
                        IPFX "sqrtsd     %s, %s\n", MAYBE_PAD,
                        nameFPReg(src), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
 
+    void pinsrd_rr(RegisterID src, XMMRegisterID dst)
+    {
+        js::JaegerSpew(js::JSpew_Insns,
+                       IPFX "pinsrd     $1, %s, %s\n", MAYBE_PAD,
+                       nameIReg(src), nameFPReg(dst));
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+        m_formatter.immediate8(0x01); // the $1
+    }
+
     // Misc instructions:
 
     void int3()
     {
         js::JaegerSpew(js::JSpew_Insns, IPFX "int3\n", MAYBE_PAD);
         m_formatter.oneByteOp(OP_INT3);
     }
     
@@ -2356,16 +2377,26 @@ private:
         {
             m_buffer.ensureSpace(maxInstructionSize);
             m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
             m_buffer.putByteUnchecked(opcode);
             memoryModRM(reg, address);
         }
 #endif
 
+        void threeByteOp(ThreeByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, rm);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(OP_3BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
+
 #if WTF_CPU_X86_64
         // Quad-word-sized operands:
         //
         // Used to format 64-bit operantions, planting a REX.w prefix.
         // When planting d64 or f64 instructions, not requiring a REX.w prefix,
         // the normal (non-'64'-postfixed) formatters should be used.
 
         void oneByteOp64(OneByteOpcodeID opcode)
--- a/js/src/assembler/wtf/Platform.h
+++ b/js/src/assembler/wtf/Platform.h
@@ -95,16 +95,20 @@
 #define WTF_COMPILER_MINGW 1
 #endif
 
 /* COMPILER(WINSCW) - CodeWarrior for Symbian emulator */
 #if defined(__WINSCW__)
 #define WTF_COMPILER_WINSCW 1
 #endif
 
+/* COMPILER(SUNPRO) - Sun Studio for Solaris */
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+#define WTF_COMPILER_SUNPRO 1
+#endif
 
 
 /* ==== CPU() - the target CPU architecture ==== */
 
 /* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */
 
 
 /* CPU(ALPHA) - DEC Alpha */
@@ -830,16 +834,36 @@ on MinGW. See https://bugs.webkit.org/sh
     #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
 #elif WTF_CPU_ARM_THUMB2 && WTF_PLATFORM_IPHONE
     #define ENABLE_JIT 1
 /* The JIT is tested & working on x86 Windows */
 #elif WTF_CPU_X86 && WTF_PLATFORM_WIN
     #define ENABLE_JIT 1
 #endif
 
+#if WTF_PLATFORM_QT
+#if WTF_CPU_X86_64 && WTF_PLATFORM_DARWIN
+    #define ENABLE_JIT 1
+#elif WTF_CPU_X86 && WTF_PLATFORM_DARWIN
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif WTF_CPU_X86 && WTF_PLATFORM_WIN_OS && WTF_COMPILER_MINGW && GCC_VERSION >= 40100
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif WTF_CPU_X86 && WTF_PLATFORM_WIN_OS && WTF_COMPILER_MSVC
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+#elif WTF_CPU_X86 && WTF_PLATFORM_LINUX && GCC_VERSION >= 40100
+    #define ENABLE_JIT 1
+    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
+#elif WTF_CPU_ARM_TRADITIONAL && WTF_PLATFORM_LINUX
+    #define ENABLE_JIT 1
+#endif
+#endif /* PLATFORM(QT) */
+
 #endif /* !defined(ENABLE_JIT) */
 
 #if ENABLE_JIT
 #ifndef ENABLE_JIT_OPTIMIZE_CALL
 #define ENABLE_JIT_OPTIMIZE_CALL 1
 #endif
 #ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL
 #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1
@@ -873,16 +897,17 @@ on MinGW. See https://bugs.webkit.org/sh
 /* Yet Another Regex Runtime. */
 #if !defined(ENABLE_YARR_JIT)
 
 /* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
 #if (WTF_CPU_X86 \
  || WTF_CPU_X86_64 \
  || WTF_CPU_ARM_THUMB2 \
  || WTF_CPU_ARM_TRADITIONAL \
+ || WTF_CPU_ARM_TRADITIONAL \
  || WTF_CPU_X86)
 #define ENABLE_YARR_JIT 1
 #else
 #define ENABLE_YARR_JIT 0
 #endif
 
 #endif /* !defined(ENABLE_YARR_JIT) */
 
--- a/js/src/config/autoconf.mk.in
+++ b/js/src/config/autoconf.mk.in
@@ -331,13 +331,14 @@ XCODEBUILD_VERSION= @XCODEBUILD_VERSION@
 HAS_XCODE_2_1	= @HAS_XCODE_2_1@
 UNIVERSAL_BINARY= @UNIVERSAL_BINARY@
 HAVE_DTRACE= @HAVE_DTRACE@
 
 VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
 WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
 
 ENABLE_TRACEJIT = @ENABLE_TRACEJIT@
+ENABLE_METHODJIT = @ENABLE_METHODJIT@
 NANOJIT_ARCH = @NANOJIT_ARCH@
 HAVE_ARM_SIMD= @HAVE_ARM_SIMD@
 
 JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
 HAVE_LINUX_PERF_EVENT_H = @HAVE_LINUX_PERF_EVENT_H@
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2053,26 +2053,30 @@ ia64*-hpux*)
         DLL_PREFIX=
         IMPORT_LIB_SUFFIX=dll.a
         GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'`
     else
         TARGET_COMPILER_ABI=msvc
         HOST_CC='$(CC)'
         HOST_CXX='$(CXX)'
         HOST_LD='$(LD)'
+        if test "$AS_BIN"; then
+          AS="$(basename "$AS_BIN")"
+        fi
         AR='lib -NOLOGO -OUT:"$@"'
         AR_FLAGS=
         RANLIB='echo not_ranlib'
         STRIP='echo not_strip'
         PKG_SKIP_STRIP=1
         XARGS=xargs
         ZIP=zip
         UNZIP=unzip
         DOXYGEN=:
         GARBAGE='$(OBJDIR)/vc20.pdb $(OBJDIR)/vc40.pdb'
+        ASM_SUFFIX=asm
         OBJ_SUFFIX=obj
         LIB_SUFFIX=lib
         DLL_PREFIX=
         LIB_PREFIX=
         IMPORT_LIB_SUFFIX=lib
         MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         MKSHLIB_FORCE_ALL=
@@ -2584,35 +2588,85 @@ if test -z "$COMPILE_ENVIRONMENT"; then
 fi
 
 dnl Configure JIT support
 
 case "$target" in
 i?86-*)
     ENABLE_TRACEJIT=1
     NANOJIT_ARCH=i386
+    ENABLE_METHODJIT=1
+    ENABLE_MONOIC=1
+    ENABLE_POLYIC=1
+    AC_DEFINE(JS_CPU_X86)
+    AC_DEFINE(JS_NUNBOX32)
     ;;
 x86_64*-*)
     ENABLE_TRACEJIT=1
     NANOJIT_ARCH=X64
+    ENABLE_METHODJIT=1
+    ENABLE_MONOIC=1
+    ENABLE_POLYIC=1
+    AC_DEFINE(JS_CPU_X64)
+    AC_DEFINE(JS_PUNBOX64)
     ;;
 arm*-*)
     ENABLE_TRACEJIT=1
     NANOJIT_ARCH=ARM
+    AC_DEFINE(JS_CPU_ARM)
+    AC_DEFINE(JS_NUNBOX32)
     ;;
 sparc*-*)
     ENABLE_TRACEJIT=1
     NANOJIT_ARCH=Sparc
+    AC_DEFINE(JS_CPU_SPARC)
     ;;
 esac
 
+MOZ_ARG_DISABLE_BOOL(methodjit,
+[  --disable-methodjit           Disable method JIT support],
+  ENABLE_METHODJIT= )
+
+MOZ_ARG_DISABLE_BOOL(monoic,
+[  --disable-monoic      Disable use of MICs by JIT compiler],
+  ENABLE_MONOIC= )
+
+MOZ_ARG_DISABLE_BOOL(polyic,
+[  --disable-polyic      Disable use of PICs by JIT compiler],
+  ENABLE_POLYIC= )
+
 MOZ_ARG_DISABLE_BOOL(tracejit,
 [  --disable-tracejit      Disable tracing JIT support],
   ENABLE_TRACEJIT=)
 
+MOZ_ARG_ENABLE_BOOL(methodjit-spew,
+[  --enable-methodjit-spew      Enable method JIT spew support],
+  ENABLE_METHODJIT_SPEW=1,
+  ENABLE_METHODJIT_SPEW= )
+
+AC_SUBST(ENABLE_METHODJIT)
+
+if test "$ENABLE_METHODJIT"; then
+    AC_DEFINE(JS_METHODJIT)
+else
+    ENABLE_TRACEJIT= 
+fi
+
+if test "$ENABLE_MONOIC"; then
+    AC_DEFINE(JS_MONOIC)
+fi
+
+if test "$ENABLE_POLYIC"; then
+    AC_DEFINE(JS_POLYIC)
+fi
+
+if test "$ENABLE_METHODJIT_SPEW"; then
+    AC_DEFINE(JS_METHODJIT_SPEW)
+fi
+
 if test "$ENABLE_TRACEJIT"; then
 
 AC_DEFINE(FEATURE_NANOJIT)
 AC_DEFINE(JS_TRACER)
 
 case "$target" in
 i?86-*)
     AC_DEFINE(AVMPLUS_IA32)
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -71,92 +71,85 @@ public:
 private:
   JSContext* mCx;
 };
 
 /*******************************************************************************
 ** JSAPI function prototypes
 *******************************************************************************/
 
-static JSBool ConstructAbstract(JSContext* cx, JSObject* obj, uintN argc,
-  jsval* argv, jsval* rval);
+static JSBool ConstructAbstract(JSContext* cx, uintN argc, jsval* vp);
 
 namespace CType {
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
-    jsval* argv, jsval* rval);
-  static JSBool ConstructBasic(JSContext* cx, JSObject* obj, uintN argc,
-    jsval* argv, jsval* rval);
+  static JSBool ConstructData(JSContext* cx, uintN argc, jsval* vp);
+  static JSBool ConstructBasic(JSContext* cx, JSObject* obj, uintN argc, jsval* vp);
 
   static void Trace(JSTracer* trc, JSObject* obj);
   static void Finalize(JSContext* cx, JSObject* obj);
   static void FinalizeProtoClass(JSContext* cx, JSObject* obj);
 
   static JSBool PrototypeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool NameGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
   static JSBool CreateArray(JSContext* cx, uintN argc, jsval* vp);
   static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
-  static JSBool HasInstance(JSContext* cx, JSObject* obj, const jsval *v, JSBool* bp);
+  static JSBool HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp);
 }
 
 namespace PointerType {
   static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
-    jsval* argv, jsval* rval);
+  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* vp);
 
   static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool ContentsGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool ContentsSetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool IsNull(JSContext* cx, uintN argc, jsval* vp);
 }
 
 namespace ArrayType {
   static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
-    jsval* argv, jsval* rval);
+  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* vp);
 
   static JSBool ElementTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool LengthGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool Getter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
   static JSBool Setter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
   static JSBool AddressOfElement(JSContext* cx, uintN argc, jsval* vp);
 }
 
 namespace StructType {
   static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
-  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc,
-    jsval* argv, jsval* rval);
+  static JSBool ConstructData(JSContext* cx, JSObject* obj, uintN argc, jsval* vp);
 
   static JSBool FieldsArrayGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool FieldGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool FieldSetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool AddressOfField(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Define(JSContext* cx, uintN argc, jsval* vp);
 }
 
 namespace FunctionType {
   static JSBool Create(JSContext* cx, uintN argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSObject* typeObj,
     JSObject* dataObj, JSObject* fnObj, JSObject* thisObj);
 
-  static JSBool Call(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
-    jsval* rval);
+  static JSBool Call(JSContext* cx, uintN argc, jsval* vp);
 
   static JSBool ArgTypesGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool ReturnTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool ABIGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
   static JSBool IsVariadicGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
@@ -195,31 +188,29 @@ namespace Int64Base {
 
   JSBool ToSource(JSContext* cx, JSObject* obj, uintN argc, jsval* vp,
     bool isUnsigned);
 
   static void Finalize(JSContext* cx, JSObject* obj);
 }
 
 namespace Int64 {
-  static JSBool Construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
-    jsval* rval);
+  static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
 
   static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
 
   static JSBool Compare(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Lo(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Hi(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Join(JSContext* cx, uintN argc, jsval* vp);
 }
 
 namespace UInt64 {
-  static JSBool Construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv,
-    jsval* rval);
+  static JSBool Construct(JSContext* cx, uintN argc, jsval* vp);
 
   static JSBool ToString(JSContext* cx, uintN argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, uintN argc, jsval* vp);
 
   static JSBool Compare(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Lo(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Hi(JSContext* cx, uintN argc, jsval* vp);
   static JSBool Join(JSContext* cx, uintN argc, jsval* vp);
@@ -279,23 +270,26 @@ static JSClass sCClosureClass = {
   "CClosure",
   JSCLASS_HAS_RESERVED_SLOTS(CCLOSURE_SLOTS) | JSCLASS_MARK_IS_TRACE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, CClosure::Finalize,
   NULL, NULL, NULL, NULL, NULL, NULL, JS_CLASS_TRACE(CClosure::Trace), NULL
 };
 
 #define CTYPESFN_FLAGS \
-  (JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
+  (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
+
+#define CTYPESCTOR_FLAGS \
+  (CTYPESFN_FLAGS | JSFUN_CONSTRUCTOR)
 
 #define CTYPESPROP_FLAGS \
   (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
 
 #define CDATAFN_FLAGS \
-  (JSFUN_FAST_NATIVE | JSPROP_READONLY | JSPROP_PERMANENT)
+  (JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSPropertySpec sCTypeProps[] = {
   { "name", 0, CTYPESPROP_FLAGS, CType::NameGetter, NULL },
   { "size", 0, CTYPESPROP_FLAGS, CType::SizeGetter, NULL },
   { "ptr", 0, CTYPESPROP_FLAGS, CType::PtrGetter, NULL },
   { "prototype", 0, CTYPESPROP_FLAGS, CType::PrototypeGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
@@ -317,17 +311,17 @@ static JSFunctionSpec sCDataFunctions[] 
   JS_FN("address", CData::Address, 0, CDATAFN_FLAGS),
   JS_FN("readString", CData::ReadString, 0, CDATAFN_FLAGS),
   JS_FN("toSource", CData::ToSource, 0, CDATAFN_FLAGS),
   JS_FN("toString", CData::ToSource, 0, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSFunctionSpec sPointerFunction =
-  JS_FN("PointerType", PointerType::Create, 1, CTYPESFN_FLAGS);
+  JS_FN("PointerType", PointerType::Create, 1, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sPointerProps[] = {
   { "targetType", 0, CTYPESPROP_FLAGS, PointerType::TargetTypeGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSFunctionSpec sPointerInstanceFunctions[] = {
   JS_FN("isNull", PointerType::IsNull, 0, CTYPESFN_FLAGS),
@@ -336,17 +330,17 @@ static JSFunctionSpec sPointerInstanceFu
   
 static JSPropertySpec sPointerInstanceProps[] = {
   { "contents", 0, JSPROP_SHARED | JSPROP_PERMANENT,
     PointerType::ContentsGetter, PointerType::ContentsSetter },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSFunctionSpec sArrayFunction =
-  JS_FN("ArrayType", ArrayType::Create, 1, CTYPESFN_FLAGS);
+  JS_FN("ArrayType", ArrayType::Create, 1, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sArrayProps[] = {
   { "elementType", 0, CTYPESPROP_FLAGS, ArrayType::ElementTypeGetter, NULL },
   { "length", 0, CTYPESPROP_FLAGS, ArrayType::LengthGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSFunctionSpec sArrayInstanceFunctions[] = {
@@ -356,17 +350,17 @@ static JSFunctionSpec sArrayInstanceFunc
 
 static JSPropertySpec sArrayInstanceProps[] = {
   { "length", 0, JSPROP_SHARED | JSPROP_READONLY | JSPROP_PERMANENT,
     ArrayType::LengthGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSFunctionSpec sStructFunction =
-  JS_FN("StructType", StructType::Create, 2, CTYPESFN_FLAGS);
+  JS_FN("StructType", StructType::Create, 2, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sStructProps[] = {
   { "fields", 0, CTYPESPROP_FLAGS, StructType::FieldsArrayGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
 
 static JSFunctionSpec sStructFunctions[] = {
   JS_FN("define", StructType::Define, 1, CDATAFN_FLAGS),
@@ -374,17 +368,17 @@ static JSFunctionSpec sStructFunctions[]
 };
 
 static JSFunctionSpec sStructInstanceFunctions[] = {
   JS_FN("addressOfField", StructType::AddressOfField, 1, CDATAFN_FLAGS),
   JS_FS_END
 };
 
 static JSFunctionSpec sFunctionFunction =
-  JS_FN("FunctionType", FunctionType::Create, 2, CTYPESFN_FLAGS);
+  JS_FN("FunctionType", FunctionType::Create, 2, CTYPESCTOR_FLAGS);
 
 static JSPropertySpec sFunctionProps[] = {
   { "argTypes", 0, CTYPESPROP_FLAGS, FunctionType::ArgTypesGetter, NULL },
   { "returnType", 0, CTYPESPROP_FLAGS, FunctionType::ReturnTypeGetter, NULL },
   { "abi", 0, CTYPESPROP_FLAGS, FunctionType::ABIGetter, NULL },
   { "isVariadic", 0, CTYPESPROP_FLAGS, FunctionType::IsVariadicGetter, NULL },
   { 0, 0, 0, NULL, NULL }
 };
@@ -531,17 +525,17 @@ TypeError(JSContext* cx, const char* exp
                        CTYPESMSG_TYPE_ERROR, expected, src);
   return false;
 }
 
 static JSObject*
 InitCTypeClass(JSContext* cx, JSObject* parent)
 {
   JSFunction* fun = JS_DefineFunction(cx, parent, "CType", ConstructAbstract, 0,
-                      CTYPESFN_FLAGS);
+                      CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
   JSObject* ctor = JS_GetFunctionObject(fun);
   JSObject* fnproto = JS_GetPrototype(cx, ctor);
   JS_ASSERT(ctor);
   JS_ASSERT(fnproto);
 
@@ -569,17 +563,17 @@ InitCTypeClass(JSContext* cx, JSObject* 
 
   return prototype;
 }
 
 static JSObject*
 InitCDataClass(JSContext* cx, JSObject* parent, JSObject* CTypeProto)
 {
   JSFunction* fun = JS_DefineFunction(cx, parent, "CData", ConstructAbstract, 0,
-                      CTYPESFN_FLAGS);
+                      CTYPESCTOR_FLAGS);
   if (!fun)
     return NULL;
 
   JSObject* ctor = JS_GetFunctionObject(fun);
   JS_ASSERT(ctor);
 
   // Set up ctypes.CData.__proto__ === ctypes.CType.prototype.
   // (Note that 'ctypes.CData instanceof Function' is still true, thanks to the
@@ -2478,39 +2472,35 @@ BuildDataSource(JSContext* cx,
 }
 
 /*******************************************************************************
 ** JSAPI callback function implementations
 *******************************************************************************/
 
 JSBool
 ConstructAbstract(JSContext* cx,
-                  JSObject* obj,
                   uintN argc,
-                  jsval* argv,
-                  jsval* rval)
+                  jsval* vp)
 {
   // Calling an abstract base class constructor is disallowed.
   JS_ReportError(cx, "cannot construct from abstract type");
   return JS_FALSE;
 }
 
 /*******************************************************************************
 ** CType implementation
 *******************************************************************************/
 
 JSBool
 CType::ConstructData(JSContext* cx,
-                     JSObject* obj,
                      uintN argc,
-                     jsval* argv,
-                     jsval* rval)
+                     jsval* vp)
 {
   // get the callee object...
-  obj = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
+  JSObject* obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
   if (!CType::IsCType(cx, obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
 
   // How we construct the CData object depends on what type we represent.
   // An instance 'd' of a CData object of type 't' has:
   //   * [[Class]] "CData"
@@ -2518,50 +2508,48 @@ CType::ConstructData(JSContext* cx,
   switch (GetTypeCode(cx, obj)) {
   case TYPE_void_t:
     JS_ReportError(cx, "cannot construct from void_t");
     return JS_FALSE;
   case TYPE_function:
     JS_ReportError(cx, "cannot construct from FunctionType; use FunctionType.ptr instead");
     return JS_FALSE;
   case TYPE_pointer:
-    return PointerType::ConstructData(cx, obj, argc, argv, rval);
+    return PointerType::ConstructData(cx, obj, argc, vp);
   case TYPE_array:
-    return ArrayType::ConstructData(cx, obj, argc, argv, rval);
+    return ArrayType::ConstructData(cx, obj, argc, vp);
   case TYPE_struct:
-    return StructType::ConstructData(cx, obj, argc, argv, rval);
+    return StructType::ConstructData(cx, obj, argc, vp);
   default:
-    return ConstructBasic(cx, obj, argc, argv, rval);
+    return ConstructBasic(cx, obj, argc, vp);
   }
 }
 
 JSBool
 CType::ConstructBasic(JSContext* cx,
                       JSObject* obj,
                       uintN argc,
-                      jsval* argv,
-                      jsval* rval)
+                      jsval* vp)
 {
   if (argc > 1) {
     JS_ReportError(cx, "CType constructor takes zero or one argument");
     return JS_FALSE;
   }
 
   // construct a CData object
   JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
-
   if (argc == 1) {
-    if (!ExplicitConvert(cx, argv[0], obj, CData::GetData(cx, result)))
+    if (!ExplicitConvert(cx, JS_ARGV(cx, vp)[0], obj, CData::GetData(cx, result)))
       return JS_FALSE;
   }
 
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSObject*
 CType::Create(JSContext* cx,
               JSObject* typeProto,
               JSObject* dataProto,
               TypeCode type,
@@ -3060,17 +3048,17 @@ CType::PtrGetter(JSContext* cx, JSObject
   if (!pointerType)
     return JS_FALSE;
 
   *vp = OBJECT_TO_JSVAL(pointerType);
   return JS_TRUE;
 }
 
 JSBool
-CType::CreateArray(JSContext* cx, uintN argc, jsval *vp)
+CType::CreateArray(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* baseType = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(baseType);
 
   if (!CType::IsCType(cx, baseType)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
@@ -3093,17 +3081,17 @@ CType::CreateArray(JSContext* cx, uintN 
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CType::ToString(JSContext* cx, uintN argc, jsval *vp)
+CType::ToString(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
 
   if (!CType::IsCType(cx, obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
@@ -3116,17 +3104,17 @@ CType::ToString(JSContext* cx, uintN arg
   if (!result)
     return JS_FALSE;
   
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CType::ToSource(JSContext* cx, uintN argc, jsval *vp)
+CType::ToSource(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
 
   if (!CType::IsCType(cx, obj)) {
     JS_ReportError(cx, "not a CType");
     return JS_FALSE;
   }
@@ -3137,17 +3125,17 @@ CType::ToSource(JSContext* cx, uintN arg
   if (!result)
     return JS_FALSE;
   
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CType::HasInstance(JSContext* cx, JSObject* obj, const jsval *v, JSBool* bp)
+CType::HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp)
 {
   JS_ASSERT(CType::IsCType(cx, obj));
 
   jsval slot;
   ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_PROTO, &slot));
   JSObject* prototype = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(prototype);
   JS_ASSERT(JS_GET_CLASS(cx, prototype) == &sCDataProtoClass);
@@ -3228,40 +3216,41 @@ PointerType::CreateInternal(JSContext* c
 
   return typeObj;
 }
 
 JSBool
 PointerType::ConstructData(JSContext* cx,
                            JSObject* obj,
                            uintN argc,
-                           jsval* argv,
-                           jsval* rval)
+                           jsval* vp)
 {
   if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_pointer) {
     JS_ReportError(cx, "not a PointerType");
     return JS_FALSE;
   }
 
   if (argc > 2) {
     JS_ReportError(cx, "constructor takes 0, 1, or 2 arguments");
     return JS_FALSE;
   }
 
   JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
+  // Set return value early, must not observe *vp after
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   if (argc == 0) {
     // Construct a null pointer.
     return JS_TRUE;
   }
 
+  jsval* argv = JS_ARGV(cx, vp);
   if (argc >= 1) {
     JSObject* baseObj = PointerType::GetBaseType(cx, obj);
     if (CType::GetTypeCode(cx, baseObj) == TYPE_function &&
         JSVAL_IS_OBJECT(argv[0]) &&
         JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(argv[0]))) {
       // Construct a FunctionType.ptr from a JS function, and allow an
       // optional 'this' argument.
       JSObject* thisObj = NULL;
@@ -3498,18 +3487,17 @@ ArrayType::CreateInternal(JSContext* cx,
 
   return typeObj;
 }
 
 JSBool
 ArrayType::ConstructData(JSContext* cx,
                          JSObject* obj,
                          uintN argc,
-                         jsval* argv,
-                         jsval* rval)
+                         jsval* vp)
 {
   if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_array) {
     JS_ReportError(cx, "not an ArrayType");
     return JS_FALSE;
   }
 
   // Decide whether we have an object to initialize from. We'll override this
   // if we get a length argument instead.
@@ -3526,16 +3514,17 @@ ArrayType::ConstructData(JSContext* cx,
   } else {
     if (argc != 1) {
       JS_ReportError(cx, "constructor takes one argument");
       return JS_FALSE;
     }
 
     JSObject* baseType = GetBaseType(cx, obj);
 
+    jsval* argv = JS_ARGV(cx, vp);
     size_t length;
     if (jsvalToSize(cx, argv[0], false, &length)) {
       // Have a length, rather than an object to initialize from.
       convertObject = false;
 
     } else if (!JSVAL_IS_PRIMITIVE(argv[0])) {
       // We were given an object with a .length property.
       // This could be a JS array, or a CData array.
@@ -3586,20 +3575,20 @@ ArrayType::ConstructData(JSContext* cx,
 
   // Root the CType object, in case we created one above.
   js::AutoObjectRooter root(cx, obj);
 
   JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   if (convertObject) {
-    if (!ExplicitConvert(cx, argv[0], obj, CData::GetData(cx, result)))
+    if (!ExplicitConvert(cx, JS_ARGV(cx, vp)[0], obj, CData::GetData(cx, result)))
       return JS_FALSE;
   }
 
   return JS_TRUE;
 }
 
 JSObject*
 ArrayType::GetBaseType(JSContext* cx, JSObject* obj)
@@ -3796,17 +3785,17 @@ ArrayType::Setter(JSContext* cx, JSObjec
 
   JSObject* baseType = GetBaseType(cx, typeObj);
   size_t elementSize = CType::GetSize(cx, baseType);
   char* data = static_cast<char*>(CData::GetData(cx, obj)) + elementSize * index;
   return ImplicitConvert(cx, *vp, baseType, data, false, NULL);
 }
 
 JSBool
-ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval *vp)
+ArrayType::AddressOfElement(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
 
   if (!CData::IsCData(cx, obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
@@ -4212,41 +4201,41 @@ StructType::Define(JSContext* cx, uintN 
 
   return DefineInternal(cx, obj, JSVAL_TO_OBJECT(arg));
 }
 
 JSBool
 StructType::ConstructData(JSContext* cx,
                           JSObject* obj,
                           uintN argc,
-                          jsval* argv,
-                          jsval* rval)
+                          jsval* vp)
 {
   if (!CType::IsCType(cx, obj) || CType::GetTypeCode(cx, obj) != TYPE_struct) {
     JS_ReportError(cx, "not a StructType");
     return JS_FALSE;
   }
 
   if (!CType::IsSizeDefined(cx, obj)) {
     JS_ReportError(cx, "cannot construct an opaque StructType");
     return JS_FALSE;
   }
 
   JSObject* result = CData::Create(cx, obj, NULL, NULL, true);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
 
   if (argc == 0)
     return JS_TRUE;
 
   char* buffer = static_cast<char*>(CData::GetData(cx, result));
   const FieldInfoHash* fields = GetFieldInfo(cx, obj);
 
+  jsval* argv = JS_ARGV(cx, vp);
   if (argc == 1) {
     // There are two possible interpretations of the argument:
     // 1) It may be an object '{ ... }' with properties representing the
     //    struct fields intended to ExplicitConvert wholesale to our StructType.
     // 2) If the struct contains one field, the arg may be intended to
     //    ImplicitConvert directly to that arg's CType.
     // Thankfully, the conditions for these two possibilities to succeed
     // are mutually exclusive, so we can pick the right one.
@@ -4424,17 +4413,17 @@ StructType::FieldSetter(JSContext* cx, J
   if (!field)
     return JS_FALSE;
 
   char* data = static_cast<char*>(CData::GetData(cx, obj)) + field->mOffset;
   return ImplicitConvert(cx, *vp, field->mType, data, false, NULL);
 }
 
 JSBool
-StructType::AddressOfField(JSContext* cx, uintN argc, jsval *vp)
+StructType::AddressOfField(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
 
   if (!CData::IsCData(cx, obj)) {
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
@@ -4920,23 +4909,21 @@ ConvertArgument(JSContext* cx,
     strings->back().mData = *static_cast<char**>(value->mData);
   }
 
   return true;
 }
 
 JSBool
 FunctionType::Call(JSContext* cx,
-                   JSObject* obj,
                    uintN argc,
-                   jsval* argv,
-                   jsval* rval)
+                   jsval* vp)
 {
   // get the callee object...
-  obj = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
+  JSObject* obj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
   if (!CData::IsCData(cx, obj)) {
     JS_ReportError(cx, "not a CData");
     return false;
   }
 
   JSObject* typeObj = CData::GetCType(cx, obj);
   if (CType::GetTypeCode(cx, typeObj) != TYPE_pointer) {
     JS_ReportError(cx, "not a FunctionType.ptr");
@@ -4972,16 +4959,17 @@ FunctionType::Call(JSContext* cx,
   // prepare the values for each argument
   AutoValueAutoArray values;
   AutoValueAutoArray strings;
   if (!values.resize(argc)) {
     JS_ReportOutOfMemory(cx);
     return false;
   }
 
+  jsval* argv = JS_ARGV(cx, vp);
   for (jsuint i = 0; i < argcFixed; ++i)
     if (!ConvertArgument(cx, argv[i], fninfo->mArgTypes[i], &values[i], &strings))
       return false;
 
   if (fninfo->mIsVariadic) {
     if (!fninfo->mFFITypes.resize(argc)) {
       JS_ReportOutOfMemory(cx);
       return false;
@@ -5021,22 +5009,21 @@ FunctionType::Call(JSContext* cx,
     JS_ReportAllocationOverflow(cx);
     return false;
   }
 
   uintptr_t fn = *reinterpret_cast<uintptr_t*>(CData::GetData(cx, obj));
 
   // suspend the request before we call into the function, since the call
   // may block or otherwise take a long time to return.
-  jsrefcount rc = JS_SuspendRequest(cx);
-
-  ffi_call(&fninfo->mCIF, FFI_FN(fn), returnValue.mData,
-    reinterpret_cast<void**>(values.begin()));
-
-  JS_ResumeRequest(cx, rc);
+  {
+    JSAutoSuspendRequest suspend(cx);
+    ffi_call(&fninfo->mCIF, FFI_FN(fn), returnValue.mData,
+             reinterpret_cast<void**>(values.begin()));
+  }
 
   // Small integer types get returned as a word-sized ffi_arg. Coerce it back
   // into the correct size for ConvertToJS.
   switch (typeCode) {
 #define DEFINE_INT_TYPE(name, type, ffiType)                                   \
   case TYPE_##name:                                                            \
     if (sizeof(type) < sizeof(ffi_arg)) {                                      \
       ffi_arg data = *static_cast<ffi_arg*>(returnValue.mData);                \
@@ -5049,17 +5036,17 @@ FunctionType::Call(JSContext* cx,
 #define DEFINE_JSCHAR_TYPE(x, y, z) DEFINE_INT_TYPE(x, y, z)
 #include "typedefs.h"
   default:
     break;
   }
 
   // prepare a JS object from the result
   return ConvertToJS(cx, fninfo->mReturnType, NULL, returnValue.mData,
-                     false, true, rval);
+                     false, true, vp);
 }
 
 FunctionInfo*
 FunctionType::GetFunctionInfo(JSContext* cx, JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(cx, obj));
   JS_ASSERT(CType::GetTypeCode(cx, obj) == TYPE_function);
 
@@ -5569,17 +5556,17 @@ CData::ValueSetter(JSContext* cx, JSObje
     JS_ReportError(cx, "not a CData");
     return JS_FALSE;
   }
 
   return ImplicitConvert(cx, *vp, GetCType(cx, obj), GetData(cx, obj), false, NULL);
 }
 
 JSBool
-CData::Address(JSContext* cx, uintN argc, jsval *vp)
+CData::Address(JSContext* cx, uintN argc, jsval* vp)
 {
   if (argc != 0) {
     JS_ReportError(cx, "address takes zero arguments");
     return JS_FALSE;
   }
 
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
@@ -5604,17 +5591,17 @@ CData::Address(JSContext* cx, uintN argc
 
   // Manually set the pointer inside the object, so we skip the conversion step.
   void** data = static_cast<void**>(GetData(cx, result));
   *data = GetData(cx, obj);
   return JS_TRUE;
 }
 
 JSBool
-CData::Cast(JSContext* cx, uintN argc, jsval *vp)
+CData::Cast(JSContext* cx, uintN argc, jsval* vp)
 {
   if (argc != 2) {
     JS_ReportError(cx, "cast takes two arguments");
     return JS_FALSE;
   }
 
   jsval* argv = JS_ARGV(cx, vp);
   if (JSVAL_IS_PRIMITIVE(argv[0]) ||
@@ -5647,17 +5634,17 @@ CData::Cast(JSContext* cx, uintN argc, j
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CData::ReadString(JSContext* cx, uintN argc, jsval *vp)
+CData::ReadString(JSContext* cx, uintN argc, jsval* vp)
 {
   if (argc != 0) {
     JS_ReportError(cx, "readString takes zero arguments");
     return JS_FALSE;
   }
 
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   JS_ASSERT(obj);
@@ -5740,17 +5727,17 @@ CData::ReadString(JSContext* cx, uintN a
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
-CData::ToSource(JSContext* cx, uintN argc, jsval *vp)
+CData::ToSource(JSContext* cx, uintN argc, jsval* vp)
 {
   if (argc != 0) {
     JS_ReportError(cx, "toSource takes zero arguments");
     return JS_FALSE;
   }
 
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!CData::IsCData(cx, obj)) {
@@ -5835,17 +5822,17 @@ Int64Base::GetInt(JSContext* cx, JSObjec
   ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_INT64, &slot));
   return *static_cast<JSUint64*>(JSVAL_TO_PRIVATE(slot));
 }
 
 JSBool
 Int64Base::ToString(JSContext* cx,
                     JSObject* obj,
                     uintN argc,
-                    jsval *vp,
+                    jsval* vp,
                     bool isUnsigned)
 {
   if (argc > 1) {
     JS_ReportError(cx, "toString takes zero or one argument");
     return JS_FALSE;
   }
 
   jsuint radix = 10;
@@ -5873,17 +5860,17 @@ Int64Base::ToString(JSContext* cx,
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
 Int64Base::ToSource(JSContext* cx,
                     JSObject* obj,
                     uintN argc,
-                    jsval *vp,
+                    jsval* vp,
                     bool isUnsigned)
 {
   if (argc != 0) {
     JS_ReportError(cx, "toSource takes zero arguments");
     return JS_FALSE;
   }
 
   // Return a decimal string suitable for constructing the number.
@@ -5902,66 +5889,65 @@ Int64Base::ToSource(JSContext* cx,
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
 Int64::Construct(JSContext* cx,
-                 JSObject* obj,
                  uintN argc,
-                 jsval* argv,
-                 jsval* rval)
+                 jsval* vp)
 {
   // Construct and return a new Int64 object.
   if (argc != 1) {
     JS_ReportError(cx, "Int64 takes one argument");
     return JS_FALSE;
   }
 
+  jsval* argv = JS_ARGV(cx, vp);
   JSInt64 i = 0;
   if (!jsvalToBigInteger(cx, argv[0], true, &i))
     return TypeError(cx, "int64", argv[0]);
 
   // Get ctypes.Int64.prototype from the 'prototype' property of the ctor.
   jsval slot;
-  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)),
+  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)),
     "prototype", &slot));
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, i, false);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 bool
 Int64::IsInt64(JSContext* cx, JSObject* obj)
 {
   return JS_GET_CLASS(cx, obj) == &sInt64Class;
 }
 
 JSBool
-Int64::ToString(JSContext* cx, uintN argc, jsval *vp)
+Int64::ToString(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!Int64::IsInt64(cx, obj)) {
     JS_ReportError(cx, "not an Int64");
     return JS_FALSE;
   }
 
   return Int64Base::ToString(cx, obj, argc, vp, false);
 }
 
 JSBool
-Int64::ToSource(JSContext* cx, uintN argc, jsval *vp)
+Int64::ToSource(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!Int64::IsInt64(cx, obj)) {
     JS_ReportError(cx, "not an Int64");
     return JS_FALSE;
   }
 
   return Int64Base::ToSource(cx, obj, argc, vp, false);
@@ -6058,83 +6044,82 @@ Int64::Join(JSContext* cx, uintN argc, j
   if (!jsvalToInteger(cx, argv[0], &hi))
     return TypeError(cx, "int32", argv[0]);
   if (!jsvalToInteger(cx, argv[1], &lo))
     return TypeError(cx, "uint32", argv[1]);
 
   JSInt64 i = (JSInt64(hi) << 32) + JSInt64(lo);
 
   // Get Int64.prototype from the function's reserved slot.
-  JSObject* callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
+  JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
   jsval slot;
   ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, i, false);
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 JSBool
 UInt64::Construct(JSContext* cx,
-                  JSObject* obj,
                   uintN argc,
-                  jsval* argv,
-                  jsval* rval)
+                  jsval* vp)
 {
   // Construct and return a new UInt64 object.
   if (argc != 1) {
     JS_ReportError(cx, "UInt64 takes one argument");
     return JS_FALSE;
   }
 
+  jsval* argv = JS_ARGV(cx, vp);
   JSUint64 u = 0;
   if (!jsvalToBigInteger(cx, argv[0], true, &u))
     return TypeError(cx, "uint64", argv[0]);
 
   // Get ctypes.UInt64.prototype from the 'prototype' property of the ctor.
   jsval slot;
-  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)),
+  ASSERT_OK(JS_GetProperty(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)),
     "prototype", &slot));
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, u, true);
   if (!result)
     return JS_FALSE;
 
-  *rval = OBJECT_TO_JSVAL(result);
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(result));
   return JS_TRUE;
 }
 
 bool
 UInt64::IsUInt64(JSContext* cx, JSObject* obj)
 {
   return JS_GET_CLASS(cx, obj) == &sUInt64Class;
 }
 
 JSBool
-UInt64::ToString(JSContext* cx, uintN argc, jsval *vp)
+UInt64::ToString(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!UInt64::IsUInt64(cx, obj)) {
     JS_ReportError(cx, "not a UInt64");
     return JS_FALSE;
   }
 
   return Int64Base::ToString(cx, obj, argc, vp, true);
 }
 
 JSBool
-UInt64::ToSource(JSContext* cx, uintN argc, jsval *vp)
+UInt64::ToSource(JSContext* cx, uintN argc, jsval* vp)
 {
   JSObject* obj = JS_THIS_OBJECT(cx, vp);
   if (!UInt64::IsUInt64(cx, obj)) {
     JS_ReportError(cx, "not a UInt64");
     return JS_FALSE;
   }
 
   return Int64Base::ToSource(cx, obj, argc, vp, true);
@@ -6227,17 +6212,17 @@ UInt64::Join(JSContext* cx, uintN argc, 
   if (!jsvalToInteger(cx, argv[0], &hi))
     return TypeError(cx, "uint32_t", argv[0]);
   if (!jsvalToInteger(cx, argv[1], &lo))
     return TypeError(cx, "uint32_t", argv[1]);
 
   JSUint64 u = (JSUint64(hi) << 32) + JSUint64(lo);
 
   // Get UInt64.prototype from the function's reserved slot.
-  JSObject* callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
+  JSObject* callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
 
   jsval slot;
   ASSERT_OK(JS_GetReservedSlot(cx, callee, SLOT_FN_INT64PROTO, &slot));
   JSObject* proto = JSVAL_TO_OBJECT(slot);
   JS_ASSERT(JS_GET_CLASS(cx, proto) == &sUInt64ProtoClass);
 
   JSObject* result = Int64Base::Construct(cx, proto, u, true);
   if (!result)
--- a/js/src/ctypes/Library.cpp
+++ b/js/src/ctypes/Library.cpp
@@ -66,17 +66,17 @@ static JSClass sLibraryClass = {
   "Library",
   JSCLASS_HAS_RESERVED_SLOTS(LIBRARY_SLOTS) | JSCLASS_MARK_IS_TRACE,
   JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
   JS_EnumerateStub,JS_ResolveStub, JS_ConvertStub, Library::Finalize,
   JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 #define CTYPESFN_FLAGS \
-  (JSFUN_FAST_NATIVE | JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
+  (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSFunctionSpec sLibraryFunctions[] = {
   JS_FN("close",   Library::Close,   0, CTYPESFN_FLAGS),
   JS_FN("declare", Library::Declare, 0, CTYPESFN_FLAGS),
   JS_FS_END
 };
 
 JSBool
--- a/js/src/javascript-trace.d
+++ b/js/src/javascript-trace.d
@@ -27,47 +27,33 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * javascript provider probes
  *
  * function-entry       (filename, classname, funcname)
- * function-info        (filename, classname, funcname, lineno,
- *                      runfilename, runlineno)
- * function-args        (filename, classname, funcname, argc, argv, argv0,
- *                      argv1, argv2, argv3, argv4)
- * function-rval        (filename, classname, funcname, lineno, rval, rval0)
  * function-return      (filename, classname, funcname)
- * object-create-start  (filename, classname)
- * object-create        (filename, classname, *object, rlineno)
- * object-create-done   (filename, classname)
+ * object-create        (classname, *object)
  * object-finalize      (NULL, classname, *object)
  * execute-start        (filename, lineno)
  * execute-done         (filename, lineno)
  */
 
 provider javascript {
  probe function__entry(char *, char *, char *);
- probe function__info(char *, char *, char *, int, char *, int);
- probe function__args(char *, char *, char *, int, void *, void *, void *,
-     void *, void *, void *);
- probe function__rval(char *, char *, char *, int, void *, void *);
  probe function__return(char *, char *, char *);
- probe object__create__start(char *, char *);
- probe object__create__done(char *, char *);
  /* XXX must use unsigned longs here instead of uintptr_t for OS X 
     (Apple radar: 5194316 & 5565198) */
- probe object__create(char *, char *, unsigned long, int);
+ probe object__create(char *, unsigned long);
  probe object__finalize(char *, char *, unsigned long);
  probe execute__start(char *, int);
  probe execute__done(char *, int);
 };
 
 /*
 #pragma D attributes Unstable/Unstable/Common provider mozilla provider
 #pragma D attributes Private/Private/Unknown provider mozilla module
 #pragma D attributes Private/Private/Unknown provider mozilla function
 #pragma D attributes Unstable/Unstable/Common provider mozilla name
-#pragma D attributes Unstable/Unstable/Common provider mozilla args
 */
 
--- a/js/src/js-config.h.in
+++ b/js/src/js-config.h.in
@@ -78,13 +78,14 @@
    JS_HAVE_STDINT_H.  */
 #undef JS_INT8_TYPE
 #undef JS_INT16_TYPE
 #undef JS_INT32_TYPE
 #undef JS_INT64_TYPE
 #undef JS_INTPTR_TYPE
 #undef JS_BYTES_PER_WORD
 
-/* Some mozilla code uses JS-friend APIs that depend on JS_TRACER being
-   correct. */
+/* Some mozilla code uses JS-friend APIs that depend on JS_TRACER and
+   JS_METHODJIT being correct. */
 #undef JS_TRACER
+#undef JS_METHODJIT
 
 #endif /* js_config_h___ */
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -330,8 +330,10 @@ MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION,   24
 MSG_DEF(JSMSG_BAD_GET_SET_FIELD,      248, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
 MSG_DEF(JSMSG_BAD_PROXY_FIX,          249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler")
 MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument")
 MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS,    251, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
 MSG_DEF(JSMSG_THROW_TYPE_ERROR,       252, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
 MSG_DEF(JSMSG_BAD_TOISOSTRING_PROP,   253, 0, JSEXN_TYPEERR, "toISOString property is not callable")
 MSG_DEF(JSMSG_BAD_PARSE_NODE,         254, 0, JSEXN_INTERNALERR, "bad parse node")
 MSG_DEF(JSMSG_NOT_EXPECTED_TYPE,      255, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
+MSG_DEF(JSMSG_CALLER_IS_STRICT,       256, 0, JSEXN_TYPEERR, "access to strict mode caller function is censored")
+MSG_DEF(JSMSG_NEED_DEBUG_MODE,        257, 0, JSEXN_ERR, "function can be called only in debug mode")
--- a/js/src/jsapi-tests/testClassGetter.cpp
+++ b/js/src/jsapi-tests/testClassGetter.cpp
@@ -11,18 +11,22 @@ int called_test_prop_get;
 
 static JSBool test_prop_get( JSContext *cx, JSObject *obj, jsid id, jsval *vp )
 {
     called_test_prop_get++;
     return JS_TRUE;
 }
 
 static JSBool
-PTest(JSContext* cx, JSObject* obj, uintN argc, jsval *argv, jsval* rval)
+PTest(JSContext* cx, uintN argc, jsval *vp)
 {
+    JSObject *obj = JS_NewObjectForConstructor(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(obj));
     return JS_TRUE;
 }
 
 static JSClass ptestClass = {
     "PTest",
     JSCLASS_HAS_PRIVATE,
 
     JS_PropertyStub, // add
@@ -31,24 +35,24 @@ static JSClass ptestClass = {
     JS_PropertyStub, // set
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     JS_FinalizeStub,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
-static JSBool test_fn(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+static JSBool test_fn(JSContext *cx, uintN argc, jsval *vp)
 {
     called_test_fn++;
     return JS_TRUE;
 }
 
 static JSFunctionSpec ptestFunctions[] = {
-    JS_FS( "test_fn", test_fn, 0, 0, 0 ),
+    JS_FS( "test_fn", test_fn, 0, 0 ),
     JS_FS_END
 };
 
 BEGIN_TEST(testClassGetter_isCalled)
 {
     JSObject *my_proto;
 
     my_proto = JS_InitClass(cx, JS_GetGlobalObject(cx), NULL, &ptestClass, PTest, 0,
--- a/js/src/jsapi-tests/testConservativeGC.cpp
+++ b/js/src/jsapi-tests/testConservativeGC.cpp
@@ -26,22 +26,35 @@ BEGIN_TEST(testConservativeGC)
     JSString str2Copy = *str2;
 
     tmp = JSVAL_NULL;
 
     JS_GC(cx);
 
     EVAL("var a = [];\n"
          "for (var i = 0; i != 10000; ++i) {\n"
-         "a.push(i + 0.1, [1, 2], String(Math.sqrt(i)));\n"
+         "a.push(i + 0.1, [1, 2], String(Math.sqrt(i)), {a: i});\n"
          "}", &tmp);
 
     JS_GC(cx);
 
-    CHECK(!memcmp(&objCopy,  JSVAL_TO_OBJECT(v2), sizeof(objCopy)));
-    CHECK(!memcmp(&strCopy,  JSVAL_TO_STRING(v3), sizeof(strCopy)));
+    checkObjectFields(&objCopy, JSVAL_TO_OBJECT(v2));
+    CHECK(!memcmp(&strCopy, JSVAL_TO_STRING(v3), sizeof(strCopy)));
 
-    CHECK(!memcmp(&obj2Copy,  obj2, sizeof(obj2Copy)));
-    CHECK(!memcmp(&str2Copy,  str2, sizeof(str2Copy)));
+    checkObjectFields(&obj2Copy, obj2);
+    CHECK(!memcmp(&str2Copy, str2, sizeof(str2Copy)));
 
     return true;
 }
+
+bool checkObjectFields(JSObject *savedCopy, JSObject *obj)
+{
+    /*
+     * The GC can change the shape and shrink dslots so we update them before
+     * doing memcmp.
+     */
+    savedCopy->objShape = obj->objShape;
+    savedCopy->dslots = obj->dslots;
+    CHECK(!memcmp(savedCopy, obj, sizeof(*obj)));
+    return true;
+}
+
 END_TEST(testConservativeGC)
--- a/js/src/jsapi-tests/testContexts.cpp
+++ b/js/src/jsapi-tests/testContexts.cpp
@@ -6,17 +6,17 @@
 
 BEGIN_TEST(testContexts_IsRunning)
     {
         CHECK(JS_DefineFunction(cx, global, "chk", chk, 0, 0));
         EXEC("for (var i = 0; i < 9; i++) chk();");
         return true;
     }
 
-    static JSBool chk(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+    static JSBool chk(JSContext *cx, uintN argc, jsval *vp)
     {
         JSRuntime *rt = JS_GetRuntime(cx);
         JSContext *acx = JS_NewContext(rt, 8192);
         if (!acx) {
             JS_ReportOutOfMemory(cx);
             return JS_FALSE;
         }
 
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sw=4 et tw=99:
  */
 
 #include "tests.h"
 #include "jsxdrapi.h"
 
 static JSBool
-native(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+native(JSContext *cx, uintN argc, jsval *vp)
 {
     return JS_TRUE;
 }
 
 static const char PROPERTY_NAME[] = "foo";
 
 BEGIN_TEST(testDefineGetterSetterNonEnumerable)
 {
--- a/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp
+++ b/js/src/jsapi-tests/testIsAboutToBeFinalized.cpp
@@ -32,17 +32,17 @@ TestAboutToBeFinalizedCallback(JSContext
  */
 volatile void *ptrSink;
 
 static JS_NEVER_INLINE void
 NativeFrameCleaner()
 {
     char buffer[1 << 16];
     memset(buffer, 0, sizeof buffer);
-    ptrSink = buffer; 
+    ptrSink = buffer;
 }
 
 BEGIN_TEST(testIsAboutToBeFinalized_bug528645)
 {
     /*
      * Due to the conservative GC we use separated never-inline function to
      * test rooted elements.
      */
@@ -78,17 +78,17 @@ cls_testIsAboutToBeFinalized_bug528645::
 {
     jsvalRoot root(cx);
 
     /*
      * Check various types of GC things against JS_IsAboutToBeFinalized.
      * Make sure to include unit and numeric strings to the set.
      */
     EVAL("var x = 1.1; "
-         "[''+x, 'a', '42', 'something'.substring(1), "
+         "[''+x, 'a', '123456789', 'something'.substring(1), "
          "{}, [], new Function('return 10;'), <xml/>];",
          root.addr());
 
     JSObject *array = JSVAL_TO_OBJECT(root.value());
     JS_ASSERT(JS_IsArrayObject(cx, array));
 
     JSBool ok = JS_GetArrayLength(cx, array, &checkPointersLength);
     CHECK(ok);
@@ -112,11 +112,25 @@ cls_testIsAboutToBeFinalized_bug528645::
     JS_GC(cx);
 
     /*
      * All GC things are rooted via the root holding the array containing them
      * and TestAboutToBeFinalizedCallback must keep them as is.
      */
     for (jsuint i = 0; i != checkPointersLength; ++i)
         CHECK(checkPointers[i]);
+
+    /*
+     * Overwrite the registers and stack with new GC things to avoid false
+     * positives with the finalization test.
+     */
+    EVAL("[]", root.addr());
+
+    array = JSVAL_TO_OBJECT(root.value());
+    JS_ASSERT(JS_IsArrayObject(cx, array));
+
+    jsuint tmp;
+    CHECK(JS_GetArrayLength(cx, array, &tmp));
+    CHECK(ok);
+
     return true;
 }
 
--- a/js/src/jsapi-tests/testNewObject.cpp
+++ b/js/src/jsapi-tests/testNewObject.cpp
@@ -3,46 +3,48 @@
  */
 
 #include "tests.h"
 
 const size_t N = 1000;
 static jsval argv[N];
 
 static JSBool
-constructHook(JSContext *cx, JSObject *thisobj, uintN argc, jsval *argv, jsval *rval)
+constructHook(JSContext *cx, uintN argc, jsval *vp)
 {
     // Check that arguments were passed properly from JS_New.
-    JSObject *callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv));
-    if (!thisobj) {
-        JS_ReportError(cx, "test failed, null 'this'");
+    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+
+    JSObject *obj = JS_NewObjectForConstructor(cx, vp);
+    if (!obj) {
+        JS_ReportError(cx, "test failed, could not construct object");
         return false;
     }
-    if (strcmp(JS_GET_CLASS(cx, thisobj)->name, "Object") != 0) {
+    if (strcmp(JS_GET_CLASS(cx, obj)->name, "Object") != 0) {
         JS_ReportError(cx, "test failed, wrong class for 'this'");
         return false;
     }
     if (argc != 3) {
         JS_ReportError(cx, "test failed, argc == %d", argc);
         return false;
     }
     if (!JSVAL_IS_INT(argv[2]) || JSVAL_TO_INT(argv[2]) != 2) {
         JS_ReportError(cx, "test failed, wrong value in argv[2]");
         return false;
     }
-    if (!JS_IsConstructing(cx)) {
+    if (!JS_IsConstructing(cx, vp)) {
         JS_ReportError(cx, "test failed, not constructing");
         return false;
     }
 
     // Perform a side-effect to indicate that this hook was actually called.
     if (!JS_SetElement(cx, callee, 0, &argv[0]))
         return false;
 
-    *rval = OBJECT_TO_JSVAL(callee); // return the callee, perversely
+    *vp = OBJECT_TO_JSVAL(obj);
     argv[0] = argv[1] = argv[2] = JSVAL_VOID;  // trash the argv, perversely
     return true;
 }
 
 BEGIN_TEST(testNewObject_1)
 {
     jsval v;
     EVAL("Array", &v);
@@ -86,16 +88,13 @@ BEGIN_TEST(testNewObject_1)
         JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
         NULL, NULL, NULL, constructHook, NULL, NULL, NULL, NULL
     };
     JSObject *ctor = JS_NewObject(cx, &cls, NULL, NULL);
     CHECK(ctor);
     jsvalRoot rt2(cx, OBJECT_TO_JSVAL(ctor));
     obj = JS_New(cx, ctor, 3, argv);
     CHECK(obj);
-    CHECK(obj == ctor);  // constructHook returns ctor, perversely
     CHECK(JS_GetElement(cx, ctor, 0, &v));
     CHECK_SAME(v, JSVAL_ZERO);
-    CHECK_SAME(argv[0], JSVAL_ZERO);  // original argv should not have been trashed
-    CHECK_SAME(argv[1], JSVAL_ONE);
     return true;
 }
 END_TEST(testNewObject_1)
--- a/js/src/jsapi-tests/testOps.cpp
+++ b/js/src/jsapi-tests/testOps.cpp
@@ -18,34 +18,34 @@ static JSClass myClass = {
     "MyClass",
     0,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub, my_convert, JS_FinalizeStub,
     JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 static JSBool
-createMyObject(JSContext* context, JSObject* obj, uintN argc, jsval *argv, jsval* rval)
+createMyObject(JSContext* context, uintN argc, jsval *vp)
 {
     JS_BeginRequest(context);
 
     //JS_GC(context); //<- if we make GC here, all is ok
 
     JSObject* myObject = JS_NewObject(context, &myClass, NULL, NULL);
-    *rval = OBJECT_TO_JSVAL(myObject);
+    *vp = OBJECT_TO_JSVAL(myObject);
 
     JS_EndRequest(context);
 
     return JS_TRUE;
 }
 
 static JSFunctionSpec s_functions[] =
 {
     { "createMyObject", createMyObject, 0 },
-    { 0,0,0,0,0 }
+    { 0,0,0,0 }
 };
 
 BEGIN_TEST(testOps_bug559006)
 {
     CHECK(JS_DefineFunctions(cx, global, s_functions));
 
     EXEC("function main() { while(1) return 0 + createMyObject(); }");
 
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -40,16 +40,19 @@ BEGIN_TEST(testTrap_gc)
     jsvalRoot v2(cx);
     CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
     CHECK(JSVAL_IS_OBJECT(v2));
     CHECK(emptyTrapCallCount == 0);
 
     // Disable JIT for debugging
     JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
 
+    // Enable debug mode
+    CHECK(JS_SetDebugMode(cx, JS_TRUE));
+
     jsbytecode *line2 = JS_LineNumberToPC(cx, script, 1);
     CHECK(line2);
 
     jsbytecode *line6 = JS_LineNumberToPC(cx, script, 5);
     CHECK(line2);
 
     static const char trapClosureText[] = "some trap closure";
     JSString *trapClosure = JS_NewStringCopyZ(cx, trapClosureText);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -75,17 +75,16 @@
 #include "jsopcode.h"
 #include "jsparse.h"
 #include "jsproxy.h"
 #include "jsregexp.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
-#include "jstask.h"
 #include "jstracer.h"
 #include "jsdbgapi.h"
 #include "prmjtime.h"
 #include "jsstaticcheck.h"
 #include "jsvector.h"
 #include "jswrapper.h"
 #include "jstypedarray.h"
 
@@ -110,18 +109,19 @@ using namespace js;
 
 #ifdef HAVE_VA_LIST_AS_ARRAY
 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
 #else
 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
 #endif
 
 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
-JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID = { (size_t)JSID_TYPE_DEFAULT_XML_NAMESPACE };
-JS_PUBLIC_DATA(jsid) JSID_VOID = { (size_t)JSID_TYPE_VOID };
+JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID = { size_t(JSID_TYPE_DEFAULT_XML_NAMESPACE) };
+JS_PUBLIC_DATA(jsid) JSID_VOID  = { size_t(JSID_TYPE_VOID) };
+JS_PUBLIC_DATA(jsid) JSID_EMPTY = { size_t(JSID_TYPE_OBJECT) };
 #endif
 
 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
 JS_PUBLIC_DATA(jsval) JSVAL_NULL  = { BUILD_JSVAL(JSVAL_TAG_NULL,      0) };
 JS_PUBLIC_DATA(jsval) JSVAL_ZERO  = { BUILD_JSVAL(JSVAL_TAG_INT32,     0) };
 JS_PUBLIC_DATA(jsval) JSVAL_ONE   = { BUILD_JSVAL(JSVAL_TAG_INT32,     1) };
 JS_PUBLIC_DATA(jsval) JSVAL_FALSE = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_FALSE) };
 JS_PUBLIC_DATA(jsval) JSVAL_TRUE  = { BUILD_JSVAL(JSVAL_TAG_BOOLEAN,   JS_TRUE) };
@@ -571,16 +571,22 @@ JSRuntime::init(uint32 maxbytes)
 #ifdef DEBUG
     functionMeterFilename = getenv("JS_FUNCTION_STATFILE");
     if (functionMeterFilename) {
         if (!methodReadBarrierCountMap.init())
             return false;
         if (!unjoinedFunctionCountMap.init())
             return false;
     }
+    propTreeStatFilename = getenv("JS_PROPTREE_STATFILE");
+    propTreeDumpFilename = getenv("JS_PROPTREE_DUMPFILE");
+    if (meterEmptyShapes()) {
+        if (!emptyShapes.init())
+            return false;
+    }
 #endif
 
     if (!(defaultCompartment = new JSCompartment(this)) ||
         !defaultCompartment->init() ||
         !compartments.append(defaultCompartment)) {
         return false;
     }
 
@@ -595,25 +601,16 @@ JSRuntime::init(uint32 maxbytes)
 
     deflatedStringCache = new js::DeflatedStringCache();
     if (!deflatedStringCache || !deflatedStringCache->init())
         return false;
 
     wrapObjectCallback = js::TransparentObjectWrapper;
 
 #ifdef JS_THREADSAFE
-    gcLock = JS_NEW_LOCK();
-    if (!gcLock)
-        return false;
-    gcDone = JS_NEW_CONDVAR(gcLock);
-    if (!gcDone)
-        return false;
-    requestDone = JS_NEW_CONDVAR(gcLock);
-    if (!requestDone)
-        return false;
     /* this is asymmetric with JS_ShutDown: */
     if (!js_SetupLocks(8, 16))
         return false;
     rtLock = JS_NEW_LOCK();
     if (!rtLock)
         return false;
     stateChange = JS_NEW_CONDVAR(gcLock);
     if (!stateChange)
@@ -780,178 +777,140 @@ JS_GetRuntimePrivate(JSRuntime *rt)
 }
 
 JS_PUBLIC_API(void)
 JS_SetRuntimePrivate(JSRuntime *rt, void *data)
 {
     rt->data = data;
 }
 
-JS_PUBLIC_API(void)
-JS_BeginRequest(JSContext *cx)
-{
 #ifdef JS_THREADSAFE
-    JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
-    JS_ASSERT(cx->requestDepth <= cx->outstandingRequests);
-    if (cx->requestDepth) {
-        JS_ASSERT(cx->thread->requestContext == cx);
-        cx->requestDepth++;
-        cx->outstandingRequests++;
-    } else if (JSContext *old = cx->thread->requestContext) {
-        JS_ASSERT(!cx->prevRequestContext);
-        JS_ASSERT(cx->prevRequestDepth == 0);
-        JS_ASSERT(old != cx);
-        JS_ASSERT(old->requestDepth != 0);
-        JS_ASSERT(old->requestDepth <= old->outstandingRequests);
-
-        /* Serialize access to JSContext::requestDepth from other threads. */
-        AutoLockGC lock(cx->runtime);
-        cx->prevRequestContext = old;
-        cx->prevRequestDepth = old->requestDepth;
-        cx->requestDepth = 1;
-        cx->outstandingRequests++;
-        old->requestDepth = 0;
-        cx->thread->requestContext = cx;
+static void
+StartRequest(JSContext *cx)
+{
+    JSThread *t = cx->thread;
+    JS_ASSERT(CURRENT_THREAD_IS_ME(t));
+   
+    if (t->requestDepth) {
+        t->requestDepth++;
     } else {
         JSRuntime *rt = cx->runtime;
         AutoLockGC lock(rt);
 
         /* Wait until the GC is finished. */
         if (rt->gcThread != cx->thread) {
             while (rt->gcThread)
                 JS_AWAIT_GC_DONE(rt);
         }
 
         /* Indicate that a request is running. */
-        cx->requestDepth = 1;
-        cx->outstandingRequests++;
-        cx->thread->requestContext = cx;
         rt->requestCount++;
+        t->requestDepth = 1;
 
         if (rt->requestCount == 1 && rt->activityCallback)
             rt->activityCallback(rt->activityCallbackArg, true);
     }
-#endif
-}
-
-#ifdef JS_THREADSAFE
+}
+
 static void
 StopRequest(JSContext *cx)
 {
-    JSRuntime *rt;
-
-    JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
-    JS_ASSERT(cx->requestDepth > 0);
-    JS_ASSERT(cx->outstandingRequests >= cx->requestDepth);
-    JS_ASSERT(cx->thread->requestContext == cx);
-    if (cx->requestDepth >= 2) {
-        cx->requestDepth--;
-        cx->outstandingRequests--;
-    } else if (JSContext *old = cx->prevRequestContext) {
-        JS_ASSERT(cx != old);
-        JS_ASSERT(old->requestDepth == 0);
-        JS_ASSERT(old->outstandingRequests >= cx->prevRequestDepth);
-        
-        /* Serialize access to JSContext::requestDepth from other threads. */
-        AutoLockGC lock(cx->runtime);
-        
-        cx->outstandingRequests--;
-        cx->requestDepth = 0;
-        old->requestDepth = cx->prevRequestDepth;
-        cx->prevRequestContext = NULL;
-        cx->prevRequestDepth = 0;
-        cx->thread->requestContext = old;
+    JSThread *t = cx->thread;
+    JS_ASSERT(CURRENT_THREAD_IS_ME(t));
+    JS_ASSERT(t->requestDepth != 0);
+    if (t->requestDepth != 1) {
+        t->requestDepth--;
     } else {
-        JS_ASSERT(cx->prevRequestDepth == 0);
         LeaveTrace(cx);  /* for GC safety */
 
+        t->data.conservativeGC.updateForRequestEnd(t->suspendCount);
+
         /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
-        rt = cx->runtime;
+        JSRuntime *rt = cx->runtime;
         AutoLockGC lock(rt);
 
-        cx->requestDepth = 0;
-        cx->outstandingRequests--;
-        cx->thread->requestContext = NULL;
+        t->requestDepth = 0;
 
         js_ShareWaitingTitles(cx);
 
         /* Give the GC a chance to run if this was the last request running. */
         JS_ASSERT(rt->requestCount > 0);
         rt->requestCount--;
         if (rt->requestCount == 0) {
             JS_NOTIFY_REQUEST_DONE(rt);
             if (rt->activityCallback)
                 rt->activityCallback(rt->activityCallbackArg, false);
         }
     }
 }
+#endif /* JS_THREADSAFE */
+
+JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+    cx->outstandingRequests++;
+    StartRequest(cx);
 #endif
+}
 
 JS_PUBLIC_API(void)
 JS_EndRequest(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
-    /*
-     * We do not allow to use JS_EndRequest to exit the request when there are
-     * native frames on the stack that insist that the request must be on. But
-     * we do allow to call the API if the request was suspended.
-     */
-    JS_ASSERT_IF(cx->requestDepth == 1 && cx->outstandingRequests == 1,
-                 cx->checkRequestDepth == 0);
+    JS_ASSERT(cx->outstandingRequests != 0);
+    cx->outstandingRequests--;
     StopRequest(cx);
 #endif
 }
 
 /* Yield to pending GC operations, regardless of request depth */
 JS_PUBLIC_API(void)
 JS_YieldRequest(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
-    JS_ASSERT(cx->thread);
     CHECK_REQUEST(cx);
-    cx = cx->thread->requestContext;
-    if (!cx)
-        return;
     JS_ResumeRequest(cx, JS_SuspendRequest(cx));
 #endif
 }
 
 JS_PUBLIC_API(jsrefcount)
 JS_SuspendRequest(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
-    jsrefcount saveDepth = cx->requestDepth;
-    if (saveDepth == 0)
+    JSThread *t = cx->thread;
+    JS_ASSERT(CURRENT_THREAD_IS_ME(t));
+
+    jsrefcount saveDepth = t->requestDepth;
+    if (!saveDepth)
         return 0;
 
-    JS_THREAD_DATA(cx)->conservativeGC.enable();
-    do {
-        cx->outstandingRequests++;  /* compensate for StopRequest */
-        StopRequest(cx);
-    } while (cx->requestDepth);
-
+    t->suspendCount++;
+    t->requestDepth = 1;
+    StopRequest(cx);
     return saveDepth;
 #else
     return 0;
 #endif
 }
 
 JS_PUBLIC_API(void)
 JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
 {
 #ifdef JS_THREADSAFE
+    JSThread *t = cx->thread;
+    JS_ASSERT(CURRENT_THREAD_IS_ME(t));
     if (saveDepth == 0)
         return;
-
-    JS_ASSERT(cx->outstandingRequests != 0);
-    do {
-        JS_BeginRequest(cx);
-        cx->outstandingRequests--;  /* compensate for JS_BeginRequest */
-    } while (--saveDepth != 0);
-    JS_THREAD_DATA(cx)->conservativeGC.disable();
+    JS_ASSERT(saveDepth >= 1);
+    JS_ASSERT(!t->requestDepth);
+    JS_ASSERT(t->suspendCount);
+    StartRequest(cx);
+    t->requestDepth = saveDepth;
+    t->suspendCount--;
 #endif
 }
 
 JS_PUBLIC_API(void)
 JS_Lock(JSRuntime *rt)
 {
     JS_LOCK_RUNTIME(rt);
 }
@@ -1605,19 +1564,18 @@ JS_ResolveStandardClass(JSContext *cx, J
     }
     return JS_TRUE;
 }
 
 static JSBool
 AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
 {
     JS_LOCK_OBJ(cx, obj);
-    JSScope *scope = obj->scope();
-    bool found = scope->hasProperty(ATOM_TO_JSID(atom));
-    JS_UNLOCK_SCOPE(cx, scope);
+    bool found = obj->nativeContains(ATOM_TO_JSID(atom));
+    JS_UNLOCK_OBJ(cx, obj);
     return found;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
 {
     JSRuntime *rt;
     JSAtom *atom;
@@ -1873,17 +1831,17 @@ JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p)
 {
     return cx->free(p);
 }
 
 JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext *cx, size_t nbytes)
 {
-    return cx->updateMallocCounter(nbytes);
+    return cx->runtime->updateMallocCounter(nbytes);
 }
 
 JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s)
 {
     size_t n;
     void *p;
 
@@ -2044,18 +2002,17 @@ JS_SetExtraGCRoots(JSRuntime *rt, JSTrac
 {
     rt->gcExtraRootsTraceOp = traceOp;
     rt->gcExtraRootsData = data;
 }
 
 JS_PUBLIC_API(void)
 JS_TraceRuntime(JSTracer *trc)
 {
-    LeaveTrace(trc->context);
-    js_TraceRuntime(trc);
+    TraceRuntime(trc);
 }
 
 JS_PUBLIC_API(void)
 JS_CallTracer(JSTracer *trc, void *thing, uint32 kind)
 {
     JS_ASSERT(thing);
     Mark(trc, thing, kind);
 }
@@ -2132,18 +2089,17 @@ JS_PrintTraceThingInfo(char *buf, size_t
             if (clasp == &js_FunctionClass) {
                 JSFunction *fun = GET_FUNCTION_PRIVATE(trc->context, obj);
                 if (!fun) {
                     JS_snprintf(buf, bufsize, "<newborn>");
                 } else if (FUN_OBJECT(fun) != obj) {
                     JS_snprintf(buf, bufsize, "%p", fun);
                 } else {
                     if (fun->atom)
-                        js_PutEscapedString(buf, bufsize,
-                                            ATOM_TO_STRING(fun->atom), 0);
+                        js_PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0);
                 }
             } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
                 JS_snprintf(buf, bufsize, "%p", obj->getPrivate());
             } else {
                 JS_snprintf(buf, bufsize, "<no private>");
             }
             break;
           }
@@ -2361,17 +2317,17 @@ JS_DumpHeap(JSContext *cx, FILE *fp, voi
     dtrc.startThing = startThing;
     dtrc.thingToFind = thingToFind;
     dtrc.thingToIgnore = thingToIgnore;
     dtrc.parentNode = NULL;
     node = NULL;
     dtrc.lastNodep = &node;
     if (!startThing) {
         JS_ASSERT(startKind == 0);
-        JS_TraceRuntime(&dtrc.base);
+        TraceRuntime(&dtrc.base);
     } else {
         JS_TraceChildren(&dtrc.base, startThing, startKind);
     }
 
     depth = 1;
     if (!node)
         goto dump_out;
 
@@ -2643,17 +2599,17 @@ JS_NewExternalString(JSContext *cx, jsch
 {
     CHECK_REQUEST(cx);
     JS_ASSERT(uintN(type) < JS_EXTERNAL_STRING_LIMIT);
 
     JSString *str = js_NewGCExternalString(cx, uintN(type));
     if (!str)
         return NULL;
     str->initFlat(chars, length);
-    cx->updateMallocCounter((length + 1) * sizeof(jschar));
+    cx->runtime->updateMallocCounter((length + 1) * sizeof(jschar));
     return str;
 }
 
 JS_PUBLIC_API(intN)
 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
 {
     /*
      * No need to test this in js_GetExternalStringGCType, which asserts its
@@ -2958,83 +2914,72 @@ JS_NewObjectWithGivenProto(JSContext *cx
         clasp = &js_ObjectClass;    /* default class is Object */
 
     JS_ASSERT(clasp != &js_FunctionClass);
     JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
 
     return NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
 }
 
+JS_PUBLIC_API(JSObject *)
+JS_NewObjectForConstructor(JSContext *cx, const jsval *vp)
+{
+    CHECK_REQUEST(cx);
+    assertSameCompartment(cx, *vp);
+
+    return js_NewInstance(cx, JSVAL_TO_OBJECT(*vp));
+}
+
 JS_PUBLIC_API(JSBool)
 JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
-    JSScope *scope;
-    JSIdArray *ida;
-    uint32 nslots, i;
+    /* Nothing to do if obj is already sealed. */
+    if (obj->sealed())
+        return true;
 
     if (obj->isDenseArray() && !obj->makeDenseArraySlow(cx))
-        return JS_FALSE;
+        return false;
 
     if (!obj->isNative()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_SEAL_OBJECT,
                              obj->getClass()->name);
-        return JS_FALSE;
+        return false;
     }
 
-    scope = obj->scope();
-
-#if defined JS_THREADSAFE && defined DEBUG
+#ifdef JS_THREADSAFE
     /* Insist on scope being used exclusively by cx's thread. */
-    if (scope->title.ownercx != cx) {
-        JS_LOCK_OBJ(cx, obj);
-        JS_ASSERT(obj->scope() == scope);
-        JS_ASSERT(scope->title.ownercx == cx);
-        JS_UNLOCK_SCOPE(cx, scope);
-    }
+    JS_ASSERT(obj->title.ownercx == cx);
 #endif
 
-    /* Nothing to do if obj's scope is already sealed. */
-    if (scope->sealed())
-        return JS_TRUE;
-
     /* XXX Enumerate lazy properties now, as they can't be added later. */
-    ida = JS_Enumerate(cx, obj);
+    JSIdArray *ida = JS_Enumerate(cx, obj);
     if (!ida)
-        return JS_FALSE;
+        return false;
     JS_DestroyIdArray(cx, ida);
 
-    /* Ensure that obj has its own, mutable scope, and seal that scope. */
-    JS_LOCK_OBJ(cx, obj);
-    scope = js_GetMutableScope(cx, obj);
-    if (scope)
-        scope->seal(cx);
-    JS_UNLOCK_OBJ(cx, obj);
-    if (!scope)
-        return JS_FALSE;
-
-    /* If we are not sealing an entire object graph, we're done. */
+    /* If not sealing an entire object graph, we're done after sealing obj. */
+    obj->seal(cx);
     if (!deep)
-        return JS_TRUE;
+        return true;
 
     /* Walk slots in obj and if any value is a non-null object, seal it. */
-    nslots = scope->freeslot;
-    for (i = 0; i != nslots; ++i) {
+    for (uint32 i = 0, n = obj->freeslot; i != n; ++i) {
         const Value &v = obj->getSlot(i);
         if (i == JSSLOT_PRIVATE && (obj->getClass()->flags & JSCLASS_HAS_PRIVATE))
             continue;
         if (v.isPrimitive())
             continue;
         if (!JS_SealObject(cx, &v.toObject(), deep))
-            return JS_FALSE;
+            return false;
     }
-    return JS_TRUE;
+    return true;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_ConstructObject(JSContext *cx, JSClass *jsclasp, JSObject *proto, JSObject *parent)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, proto, parent);
     Class *clasp = Valueify(jsclasp);
@@ -3075,28 +3020,28 @@ LookupResult(JSContext *cx, JSObject *ob
 {
     if (!prop) {
         /* XXX bad API: no way to tell "not defined" from "void value" */
         vp->setUndefined();
         return JS_TRUE;
     }
 
     if (obj2->isNative()) {
-        JSScopeProperty *sprop = (JSScopeProperty *) prop;
-
-        if (sprop->isMethod()) {
-            AutoScopePropertyRooter root(cx, sprop);
+        Shape *shape = (Shape *) prop;
+
+        if (shape->isMethod()) {
+            AutoShapeRooter root(cx, shape);
             JS_UNLOCK_OBJ(cx, obj2);
-            vp->setObject(sprop->methodObject());
-            return obj2->scope()->methodReadBarrier(cx, sprop, vp);
+            vp->setObject(shape->methodObject());
+            return obj2->methodReadBarrier(cx, *shape, vp);
         }
 
         /* Peek at the native property's slot value, without doing a Get. */
-        if (SPROP_HAS_VALID_SLOT(sprop, obj2->scope()))
-            *vp = obj2->lockedGetSlot(sprop->slot);
+        if (obj2->containsSlot(shape->slot))
+            *vp = obj2->lockedGetSlot(shape->slot);
         else
             vp->setBoolean(true);
         JS_UNLOCK_OBJ(cx, obj2);
     } else if (obj2->isDenseArray()) {
         return js_GetDenseArrayElementValue(cx, obj2, id, vp);
     } else {
         /* XXX bad API: no way to return "defined but value unknown" */
         vp->setBoolean(true);
@@ -3211,19 +3156,18 @@ JS_AlreadyHasOwnPropertyById(JSContext *
         }
         *foundp = (obj == obj2);
         if (prop)
             obj2->dropProperty(cx, prop);
         return JS_TRUE;
     }
 
     JS_LOCK_OBJ(cx, obj);
-    JSScope *scope = obj->scope();
-    *foundp = scope->hasProperty(id);
-    JS_UNLOCK_SCOPE(cx, scope);
+    *foundp = obj->nativeContains(id);
+    JS_UNLOCK_OBJ(cx, obj);
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
 {
     return JS_AlreadyHasOwnPropertyById(cx, obj, INT_TO_JSID(index), foundp);
 }
@@ -3310,17 +3254,17 @@ JS_DefineProperty(JSContext *cx, JSObjec
                           Valueify(setter), attrs, 0, 0);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8 tinyid,
                             jsval value, JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
 {
     return DefineProperty(cx, obj, name, Valueify(value), Valueify(getter),
-                          Valueify(setter), attrs, JSScopeProperty::HAS_SHORTID, tinyid);
+                          Valueify(setter), attrs, Shape::HAS_SHORTID, tinyid);
 }
 
 static JSBool
 DefineUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
                  const Value &value, PropertyOp getter, PropertyOp setter, uintN attrs,
                  uintN flags, intN tinyid)
 {
     JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
@@ -3337,17 +3281,17 @@ JS_DefineUCProperty(JSContext *cx, JSObj
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen,
                               int8 tinyid, jsval value, JSPropertyOp getter, JSPropertyOp setter,
                               uintN attrs)
 {
     return DefineUCProperty(cx, obj, name, namelen, Valueify(value), Valueify(getter),
-                            Valueify(setter), attrs, JSScopeProperty::HAS_SHORTID, tinyid);
+                            Valueify(setter), attrs, Shape::HAS_SHORTID, tinyid);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id, descriptor);
     return js_DefineOwnProperty(cx, obj, id, Valueify(descriptor), bp);
@@ -3396,30 +3340,30 @@ JS_DefineConstDoubles(JSContext *cx, JSO
 JS_PUBLIC_API(JSBool)
 JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
 {
     JSBool ok;
 
     for (ok = true; ps->name; ps++) {
         ok = DefineProperty(cx, obj, ps->name, UndefinedValue(),
                             Valueify(ps->getter), Valueify(ps->setter),
-                            ps->flags, JSScopeProperty::HAS_SHORTID, ps->tinyid);
+                            ps->flags, Shape::HAS_SHORTID, ps->tinyid);
         if (!ok)
             break;
     }
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, const char *alias)
 {
     JSObject *obj2;
     JSProperty *prop;
     JSBool ok;
-    JSScopeProperty *sprop;
+    Shape *shape;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
     if (!atom)
         return JS_FALSE;
     if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED, &obj2, &prop))
@@ -3433,33 +3377,33 @@ JS_AliasProperty(JSContext *cx, JSObject
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
                              alias, name, obj2->getClass()->name);
         return JS_FALSE;
     }
     atom = js_Atomize(cx, alias, strlen(alias), 0);
     if (!atom) {
         ok = JS_FALSE;
     } else {
-        sprop = (JSScopeProperty *)prop;
+        shape = (Shape *)prop;
         ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
-                                   sprop->getter(), sprop->setter(), sprop->slot,
-                                   sprop->attributes(), sprop->getFlags() | JSScopeProperty::ALIAS,
-                                   sprop->shortid)
+                                   shape->getter(), shape->setter(), shape->slot,
+                                   shape->attributes(), shape->getFlags() | Shape::ALIAS,
+                                   shape->shortid)
               != NULL);
     }
     JS_UNLOCK_OBJ(cx, obj);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
 {
     JSObject *obj2;
     JSProperty *prop;
-    JSScopeProperty *sprop;
+    Shape *shape;
     JSBool ok;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
     if (!atom)
         return JS_FALSE;
@@ -3472,21 +3416,21 @@ JS_AliasElement(JSContext *cx, JSObject 
     if (obj2 != obj || !obj->isNative()) {
         char numBuf[12];
         obj2->dropProperty(cx, prop);
         JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
                              numBuf, name, obj2->getClass()->name);
         return JS_FALSE;
     }
-    sprop = (JSScopeProperty *)prop;
+    shape = (Shape *)prop;
     ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
-                               sprop->getter(), sprop->setter(), sprop->slot,
-                               sprop->attributes(), sprop->getFlags() | JSScopeProperty::ALIAS,
-                               sprop->shortid)
+                               shape->getter(), shape->setter(), shape->slot,
+                               shape->attributes(), shape->getFlags() | Shape::ALIAS,
+                               shape->shortid)
           != NULL);
     JS_UNLOCK_OBJ(cx, obj);
     return ok;
 }
 
 static JSBool
 GetPropertyDescriptorById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
                           JSBool own, PropertyDescriptor *desc)
@@ -3505,37 +3449,38 @@ GetPropertyDescriptorById(JSContext *cx,
         desc->value.setUndefined();
         if (prop)
             obj2->dropProperty(cx, prop);
         return JS_TRUE;
     }
 
     desc->obj = obj2;
     if (obj2->isNative()) {
-        JSScopeProperty *sprop = (JSScopeProperty *) prop;
-        desc->attrs = sprop->attributes();
-
-        if (sprop->isMethod()) {
+        Shape *shape = (Shape *) prop;
+        desc->attrs = shape->attributes();
+
+        if (shape->isMethod()) {
             desc->getter = desc->setter = PropertyStub;
-            desc->value.setObject(sprop->methodObject());
+            desc->value.setObject(shape->methodObject());
         } else {
-            desc->getter = sprop->getter();
-            desc->setter = sprop->setter();
-            if (SPROP_HAS_VALID_SLOT(sprop, obj2->scope()))
-                desc->value = obj2->lockedGetSlot(sprop->slot);
+            desc->getter = shape->getter();
+            desc->setter = shape->setter();
+            if (obj2->containsSlot(shape->slot))
+                desc->value = obj2->lockedGetSlot(shape->slot);
             else
                 desc->value.setUndefined();
         }
         JS_UNLOCK_OBJ(cx, obj2);
-    } else if (obj2->isProxy()) {
-        JSAutoResolveFlags rf(cx, flags);
-        return own
-            ? JSProxy::getOwnPropertyDescriptor(cx, obj2, id, desc)
-            : JSProxy::getPropertyDescriptor(cx, obj2, id, desc);
     } else {
+        if (obj2->isProxy()) {
+            JSAutoResolveFlags rf(cx, flags);
+            return own
+                   ? JSProxy::getOwnPropertyDescriptor(cx, obj2, id, desc)
+                   : JSProxy::getPropertyDescriptor(cx, obj2, id, desc);
+        }
         if (!obj2->getAttributes(cx, id, &desc->attrs))
             return false;
         desc->getter = NULL;
         desc->setter = NULL;
         desc->value.setUndefined();
     }
     return true;
 }
@@ -3621,17 +3566,17 @@ SetPropertyAttributesById(JSContext *cx,
         return false;
     if (!prop || obj != obj2) {
         *foundp = false;
         if (prop)
             obj2->dropProperty(cx, prop);
         return true;
     }
     JSBool ok = obj->isNative()
-                ? js_SetNativeAttributes(cx, obj, (JSScopeProperty *) prop, attrs)
+                ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs)
                 : obj->setAttributes(cx, id, &attrs);
     if (ok)
         *foundp = true;
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
@@ -3814,17 +3759,17 @@ JS_Enumerate(JSContext *cx, JSObject *ob
         JS_ASSERT(js_CheckForStringIndex(ida->vector[n]) == ida->vector[n]);
     return ida;
 }
 
 /*
  * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
  *     prop_iterator_class somehow...
  * + preserve the obj->enumerate API while optimizing the native object case
- * + native case here uses a JSScopeProperty *, but that iterates in reverse!
+ * + native case here uses a Shape *, but that iterates in reverse!
  * + so we make non-native match, by reverse-iterating after JS_Enumerating
  */
 const uint32 JSSLOT_ITER_INDEX = JSSLOT_PRIVATE + 1;
 JS_STATIC_ASSERT(JSSLOT_ITER_INDEX < JS_INITIAL_NSLOTS);
 
 static void
 prop_iter_finalize(JSContext *cx, JSObject *obj)
 {
@@ -3843,17 +3788,17 @@ static void
 prop_iter_trace(JSTracer *trc, JSObject *obj)
 {
     void *pdata = obj->getPrivate();
     if (!pdata)
         return;
 
     if (obj->fslots[JSSLOT_ITER_INDEX].toInt32() < 0) {
         /* Native case: just mark the next property to visit. */
-        ((JSScopeProperty *) pdata)->trace(trc);
+        ((Shape *) pdata)->trace(trc);
     } else {
         /* Non-native case: mark each id in the JSIdArray private. */
         JSIdArray *ida = (JSIdArray *) pdata;
         MarkIdRange(trc, ida->length, ida->vector, "prop iter");
     }
 }
 
 static Class prop_iter_class = {
@@ -3876,31 +3821,29 @@ static Class prop_iter_class = {
     NULL,           /* hasInstance */
     JS_CLASS_TRACE(prop_iter_trace)
 };
 
 JS_PUBLIC_API(JSObject *)
 JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
 {
     JSObject *iterobj;
-    JSScope *scope;
-    void *pdata;
+    const void *pdata;
     jsint index;
     JSIdArray *ida;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     iterobj = NewNonFunction<WithProto::Class>(cx, &prop_iter_class, NULL, obj);
     if (!iterobj)
         return NULL;
 
     if (obj->isNative()) {
-        /* Native case: start with the last property in obj's own scope. */
-        scope = obj->scope();
-        pdata = scope->lastProperty();
+        /* Native case: start with the last property in obj. */
+        pdata = obj->lastProperty();
         index = -1;
     } else {
         /*
          * Non-native case: enumerate a JSIdArray and keep it via private.
          *
          * Note: we have to make sure that we root obj around the call to
          * JS_Enumerate to protect against multiple allocations under it.
          */
@@ -3908,51 +3851,52 @@ JS_NewPropertyIterator(JSContext *cx, JS
         ida = JS_Enumerate(cx, obj);
         if (!ida)
             return NULL;
         pdata = ida;
         index = ida->length;
     }
 
     /* iterobj cannot escape to other threads here. */
-    iterobj->setPrivate(pdata);
+    iterobj->setPrivate(const_cast<void *>(pdata));
     iterobj->fslots[JSSLOT_ITER_INDEX].setInt32(index);
     return iterobj;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
 {
     jsint i;
     JSObject *obj;
-    JSScopeProperty *sprop;
+    const Shape *shape;
     JSIdArray *ida;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
     i = iterobj->fslots[JSSLOT_ITER_INDEX].toInt32();
     if (i < 0) {
         /* Native case: private data is a property tree node pointer. */
         obj = iterobj->getParent();
         JS_ASSERT(obj->isNative());
-        sprop = (JSScopeProperty *) iterobj->getPrivate();
+        shape = (Shape *) iterobj->getPrivate();
 
         /*
-         * If the next property in the property tree ancestor line is
-         * not enumerable, or it's an alias, skip it and keep on trying
-         * to find an enumerable property that is still in scope.
+         * If the next property mapped by obj in the property tree ancestor
+         * line is not enumerable, or it's an alias, skip it and keep on trying
+         * to find an enumerable property that is still in obj.
          */
-        while (sprop && (!sprop->enumerable() || sprop->isAlias()))
-            sprop = sprop->parent;
-
-        if (!sprop) {
+        while (shape->previous() && (!shape->enumerable() || shape->isAlias()))
+            shape = shape->previous();
+
+        if (!shape->previous()) {
+            JS_ASSERT(JSID_IS_EMPTY(shape->id));
             *idp = JSID_VOID;
         } else {
-            iterobj->setPrivate(sprop->parent);
-            *idp = sprop->id;
+            iterobj->setPrivate(const_cast<Shape *>(shape->previous()));
+            *idp = shape->id;
         }
     } else {
         /* Non-native case: use the ida enumerated when iterobj was created. */
         ida = (JSIdArray *) iterobj->getPrivate();
         JS_ASSERT(i <= ida->length);
         if (i == 0) {
             *idp = JSID_VOID;
         } else {
@@ -4117,68 +4061,52 @@ JS_CloneFunctionObject(JSContext *cx, JS
          * idea, but we changed incompatibly to teach any abusers a lesson!).
          */
         Value v = ObjectValue(*funobj);
         js_ReportIsNotFunction(cx, &v, 0);
         return NULL;
     }
 
     JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
-    JSObject *clone = CloneFunctionObject(cx, fun, parent);
-    if (!clone)
-        return NULL;
+    if (!FUN_FLAT_CLOSURE(fun))
+        return CloneFunctionObject(cx, fun, parent);
 
     /*
      * A flat closure carries its own environment, so why clone it? In case
      * someone wants to mutate its fixed slots or add ad-hoc properties. API
      * compatibility suggests we not return funobj and let callers mutate the
      * returned object at will.
      *
      * But it's worse than that: API compatibility according to the test for
      * bug 300079 requires we get "upvars" from parent and its ancestors! So
      * we do that (grudgingly!). The scope chain ancestors are searched as if
      * they were activations, respecting the skip field in each upvar's cookie
      * but looking up the property by name instead of frame slot.
      */
-    if (FUN_FLAT_CLOSURE(fun)) {
-        JS_ASSERT(funobj->dslots);
-        if (!js_EnsureReservedSlots(cx, clone,
-                                    fun->countInterpretedReservedSlots())) {
-            return NULL;
+    JSObject *clone = js_AllocFlatClosure(cx, fun, parent);
+    if (!clone)
+        return NULL;
+
+    JSUpvarArray *uva = fun->u.i.script->upvars();
+    uint32 i = uva->length;
+    JS_ASSERT(i != 0);
+
+    for (Shape::Range r(fun->lastUpvar()); i-- != 0; r.popFront()) {
+        JSObject *obj = parent;
+        int skip = uva->vector[i].level();
+        while (--skip > 0) {
+            if (!obj) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                     JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
+                return NULL;
+            }
+            obj = obj->getParent();
         }
 
-        JSUpvarArray *uva = fun->u.i.script->upvars();
-        JS_ASSERT(uva->length <= clone->dslots[-1].toPrivateUint32());
-
-        void *mark = JS_ARENA_MARK(&cx->tempPool);
-        jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
-        if (!names)
-            return NULL;
-
-        uint32 i = 0, n = uva->length;
-        for (; i < n; i++) {
-            JSObject *obj = parent;
-            int skip = uva->vector[i].level();
-            while (--skip > 0) {
-                if (!obj) {
-                    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                         JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
-                    goto break2;
-                }
-                obj = obj->getParent();
-            }
-
-            JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]);
-            if (!obj->getProperty(cx, ATOM_TO_JSID(atom), &clone->dslots[i]))
-                break;
-        }
-
-      break2:
-        JS_ARENA_RELEASE(&cx->tempPool, mark);
-        if (i < n)
+        if (!obj->getProperty(cx, r.front().id, clone->getFlatClosureUpvars() + i))
             return NULL;
     }
 
     return clone;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFunctionObject(JSFunction *fun)
@@ -4214,24 +4142,24 @@ JS_GetFunctionArity(JSFunction *fun)
 
 JS_PUBLIC_API(JSBool)
 JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
 {
     return obj->getClass() == &js_FunctionClass;
 }
 
 static JSBool
-js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
+js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
 {
     JSFunctionSpec *fs;
     JSObject *tmp;
-    FastNative native;
+    Native native;
 
     fs = (JSFunctionSpec *) vp->toObject().getReservedSlot(0).toPrivate();
-    JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
+    JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
 
     if (argc < 1) {
         js_ReportMissingArg(cx, *vp, 0);
         return JS_FALSE;
     }
 
     if (vp[2].isPrimitive()) {
         /*
@@ -4259,72 +4187,23 @@ js_generic_fast_native_method_dispatcher
         return JS_FALSE;
 
     /* Clear the last parameter in case too few arguments were passed. */
     vp[2 + --argc].setUndefined();
 
     native =
 #ifdef JS_TRACER
              (fs->flags & JSFUN_TRCINFO)
-             ? (FastNative) JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
+             ? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
              :
 #endif
-               (FastNative) fs->call;
+               Valueify(fs->call);
     return native(cx, argc, vp);
 }
 
-static JSBool
-js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
-                                    uintN argc, Value *argv, Value *rval)
-{
-    JSFunctionSpec *fs;
-    JSObject *tmp;
-
-    fs = (JSFunctionSpec *) argv[-2].toObject().getReservedSlot(0).toPrivate();
-    JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
-              JSFUN_GENERIC_NATIVE);
-
-    if (argc < 1) {
-        js_ReportMissingArg(cx, *(argv - 2), 0);
-        return JS_FALSE;
-    }
-
-    if (argv[0].isPrimitive()) {
-        /*
-         * Make sure that this is an object or null, as required by the generic
-         * functions.
-         */
-        if (!js_ValueToObjectOrNull(cx, argv[0], &tmp))
-            return JS_FALSE;
-        argv[0].setObjectOrNull(tmp);
-    }
-
-    /*
-     * Copy all actual (argc) arguments down over our |this| parameter,
-     * argv[-1], which is almost always the class constructor object, e.g.
-     * Array.  Then call the corresponding prototype native method with our
-     * first argument passed as |this|.
-     */
-    memmove(argv - 1, argv, argc * sizeof(jsval));
-
-    /*
-     * Follow Function.prototype.apply and .call by using the global object as
-     * the 'this' param if no args.
-     */
-    if (!ComputeThisFromArgv(cx, argv))
-        return JS_FALSE;
-    js_GetTopStackFrame(cx)->setThisValue(argv[-1]);
-    JS_ASSERT(cx->fp()->argv == argv);
-
-    /* Clear the last parameter in case too few arguments were passed. */
-    argv[--argc].setUndefined();
-
-    return fs->call(cx, &argv[-1].toObject(), argc, Jsvalify(argv), Jsvalify(rval));
-}
-
 JS_PUBLIC_API(JSBool)
 JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
 {
     uintN flags;
     JSObject *ctor;
     JSFunction *fun;
 
     CHECK_REQUEST(cx);
@@ -4341,40 +4220,34 @@ JS_DefineFunctions(JSContext *cx, JSObje
             if (!ctor) {
                 ctor = JS_GetConstructor(cx, obj);
                 if (!ctor)
                     return JS_FALSE;
             }
 
             flags &= ~JSFUN_GENERIC_NATIVE;
             fun = JS_DefineFunction(cx, ctor, fs->name,
-                                    (flags & JSFUN_FAST_NATIVE)
-                                    ? (JSNative) js_generic_fast_native_method_dispatcher
-                                    : Jsvalify(js_generic_native_method_dispatcher),
+                                    Jsvalify(js_generic_native_method_dispatcher),
                                     fs->nargs + 1,
                                     flags & ~JSFUN_TRCINFO);
             if (!fun)
                 return JS_FALSE;
-            fun->u.n.extra = (uint16)fs->extra;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             Value priv = PrivateValue(fs);
             if (!js_SetReservedSlot(cx, FUN_OBJECT(fun), 0, priv))
                 return JS_FALSE;
         }
 
-        JS_ASSERT(!(flags & JSFUN_FAST_NATIVE) ||
-                  (uint16)(fs->extra >> 16) <= fs->nargs);
         fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
         if (!fun)
             return JS_FALSE;
-        fun->u.n.extra = (uint16)fs->extra;
     }
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                   uintN nargs, uintN attrs)
 {
@@ -4643,17 +4516,17 @@ JS_CompileUCFunctionForPrincipals(JSCont
         MUST_FLOW_THROUGH("out");
 
         for (i = 0; i < nargs; i++) {
             argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
             if (!argAtom) {
                 fun = NULL;
                 goto out2;
             }
-            if (!js_AddLocal(cx, fun, argAtom, JSLOCAL_ARG)) {
+            if (!fun->addLocal(cx, argAtom, JSLOCAL_ARG)) {
                 fun = NULL;
                 goto out2;
             }
         }
 
         if (!Compiler::compileFunctionBody(cx, fun, principals,
                                            chars, length, filename, lineno)) {
             fun = NULL;
@@ -4837,46 +4710,46 @@ JS_EvaluateScript(JSContext *cx, JSObjec
 JS_PUBLIC_API(JSBool)
 JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, jsval *argv,
                 jsval *rval)
 {
     JSBool ok;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
-    ok = InternalCall(cx, obj, ObjectValue(*fun), argc, Valueify(argv), Valueify(rval));
+    ok = ExternalInvoke(cx, obj, ObjectValue(*fun), argc, Valueify(argv), Valueify(rval));
     LAST_FRAME_CHECKS(cx, ok);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc, jsval *argv,
                     jsval *rval)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, JSValueArray(argv, argc));
 
     AutoValueRooter tvr(cx);
     JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
     JSBool ok = atom &&
                 js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, tvr.addr()) &&
-                InternalCall(cx, obj, tvr.value(), argc, Valueify(argv), Valueify(rval));
+                ExternalInvoke(cx, obj, tvr.value(), argc, Valueify(argv), Valueify(rval));
     LAST_FRAME_CHECKS(cx, ok);
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, jsval *argv,
                      jsval *rval)
 {
     JSBool ok;
 
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
-    ok = InternalCall(cx, obj, Valueify(fval), argc, Valueify(argv), Valueify(rval));
+    ok = ExternalInvoke(cx, obj, Valueify(fval), argc, Valueify(argv), Valueify(rval));
     LAST_FRAME_CHECKS(cx, ok);
     return ok;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_New(JSContext *cx, JSObject *ctor, uintN argc, jsval *argv)
 {
     CHECK_REQUEST(cx);
@@ -4937,17 +4810,20 @@ JS_TriggerOperationCallback(JSContext *c
     td = JS_THREAD_DATA(cx);
 #endif
     td->triggerOperationCallback();
 }
 
 JS_PUBLIC_API(void)
 JS_TriggerAllOperationCallbacks(JSRuntime *rt)
 {
-    js_TriggerAllOperationCallbacks(rt, JS_FALSE);
+#ifdef JS_THREADSAFE
+    AutoLockGC lock(rt);
+#endif
+    TriggerAllOperationCallbacks(rt);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsRunning(JSContext *cx)
 {
     /*
      * The use of cx->fp below is safe. Rationale: Here we don't care if the
      * interpreter state is stale. We just want to know if there *is* any
@@ -4959,22 +4835,16 @@ JS_IsRunning(JSContext *cx)
     JS_ASSERT_IF(JS_TRACE_MONITOR(cx).tracecx == cx, cx->hasfp());
 #endif
     JSStackFrame *fp = cx->maybefp();
     while (fp && fp->isDummyFrame())
         fp = fp->down;
     return fp != NULL;
 }
 
-JS_PUBLIC_API(JSBool)
-JS_IsConstructing(JSContext *cx)
-{
-    return cx->isConstructing();
-}
-
 JS_PUBLIC_API(JSStackFrame *)
 JS_SaveFrameChain(JSContext *cx)
 {
     CHECK_REQUEST(cx);
     JSStackFrame *fp = js_GetTopStackFrame(cx);
     if (!fp)
         return NULL;
     cx->saveActiveSegment();
@@ -5645,17 +5515,17 @@ JS_GetContextThread(JSContext *cx)
 /*
  * Set the current thread as the owning thread of a context. Returns the
  * old owning thread id, or -1 if the operation failed.
  */
 JS_PUBLIC_API(jsword)
 JS_SetContextThread(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
-    JS_ASSERT(cx->requestDepth == 0);
+    JS_ASSERT(!cx->outstandingRequests);
     if (cx->thread) {
         JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
         return reinterpret_cast<jsword>(cx->thread->id);
     }
 
     if (!js_InitContextThread(cx)) {
         js_ReportOutOfMemory(cx);
         return -1;
@@ -5667,35 +5537,41 @@ JS_SetContextThread(JSContext *cx)
     return 0;
 }
 
 JS_PUBLIC_API(jsword)
 JS_ClearContextThread(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
     /*
-     * This must be called outside a request and, if cx is associated with a
-     * thread, this must be called only from that thread.  If not, this is a
-     * harmless no-op.
+     * cx must have exited all requests it entered and, if cx is associated
+     * with a thread, this must be called only from that thread.  If not, this
+     * is a harmless no-op.
      */
-    JS_ASSERT(cx->requestDepth == 0);
-    if (!cx->thread)
+    JS_ASSERT(cx->outstandingRequests == 0);
+    JSThread *t = cx->thread;
+    if (!t)
         return 0;
-    JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
-    void *old = cx->thread->id;
+    JS_ASSERT(CURRENT_THREAD_IS_ME(t));
 
     /*
      * We must not race with a GC that accesses cx->thread for all threads,
      * see bug 476934.
      */
     JSRuntime *rt = cx->runtime;
     AutoLockGC lock(rt);
     js_WaitForGC(rt);
     js_ClearContextThread(cx);
-    return reinterpret_cast<jsword>(old);
+    JS_ASSERT_IF(JS_CLIST_IS_EMPTY(&t->contextList), !t->requestDepth);
+   
+    /*
+     * We can access t->id as long as the GC lock is held and we cannot race
+     * with the GC that may delete t.
+     */
+    return reinterpret_cast<jsword>(t->id);
 #else
     return 0;
 #endif
 }
 
 #ifdef MOZ_TRACE_JSCALLS
 JS_PUBLIC_API(void)
 JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb)
@@ -5717,17 +5593,17 @@ JS_SetGCZeal(JSContext *cx, uint8 zeal)
     cx->runtime->gcZeal = zeal;
 }
 #endif
 
 /************************************************************************/
 
 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
 
-#include <windows.h>
+#include "jswin.h"
 
 /*
  * Initialization routine for the JS DLL.
  */
 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
 {
     return TRUE;
 }
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -303,152 +303,164 @@ JSVAL_TO_PRIVATE(jsval v)
 #define JSID_TYPE_STRING                 0x0
 #define JSID_TYPE_INT                    0x1
 #define JSID_TYPE_VOID                   0x2
 #define JSID_TYPE_OBJECT                 0x4
 #define JSID_TYPE_DEFAULT_XML_NAMESPACE  0x6
 #define JSID_TYPE_MASK                   0x7
 
 /*
- * Do not use canonical 'id' for jsid parameters since this is a magic word in
+ * Avoid using canonical 'id' for jsid parameters since this is a magic word in
  * Objective-C++ which, apparently, wants to be able to #include jsapi.h.
  */
+#define id iden
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_STRING(jsid iden)
+JSID_IS_STRING(jsid id)
 {
-    return (JSID_BITS(iden) & JSID_TYPE_MASK) == 0;
+    return (JSID_BITS(id) & JSID_TYPE_MASK) == 0;
 }
 
 static JS_ALWAYS_INLINE JSString *
-JSID_TO_STRING(jsid iden)
+JSID_TO_STRING(jsid id)
 {
-    JS_ASSERT(JSID_IS_STRING(iden));
-    return (JSString *)(JSID_BITS(iden));
+    JS_ASSERT(JSID_IS_STRING(id));
+    return (JSString *)(JSID_BITS(id));
 }
 
 JS_PUBLIC_API(JSBool)
 JS_StringHasBeenInterned(JSString *str);
 
 /* A jsid may only hold an interned JSString. */
 static JS_ALWAYS_INLINE jsid
 INTERNED_STRING_TO_JSID(JSString *str)
 {
-    jsid iden;
+    jsid id;
     JS_ASSERT(JS_StringHasBeenInterned(str));
     JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
-    JSID_BITS(iden) = (size_t)str;
-    return iden;
+    JSID_BITS(id) = (size_t)str;
+    return id;
 }
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_INT(jsid iden)
+JSID_IS_INT(jsid id)
 {
-    return !!(JSID_BITS(iden) & JSID_TYPE_INT);
+    return !!(JSID_BITS(id) & JSID_TYPE_INT);
 }
 
 static JS_ALWAYS_INLINE int32
-JSID_TO_INT(jsid iden)
+JSID_TO_INT(jsid id)
 {
-    JS_ASSERT(JSID_IS_INT(iden));
-    return ((int32)JSID_BITS(iden)) >> 1;
+    JS_ASSERT(JSID_IS_INT(id));
+    return ((int32)JSID_BITS(id)) >> 1;
 }
 
 #define JSID_INT_MIN  (-(1 << 30))
 #define JSID_INT_MAX  ((1 << 30) - 1)
 
 static JS_ALWAYS_INLINE JSBool
 INT_FITS_IN_JSID(int32 i)
 {
     return ((jsuint)(i) - (jsuint)JSID_INT_MIN <=
             (jsuint)(JSID_INT_MAX - JSID_INT_MIN));
 }
 
 static JS_ALWAYS_INLINE jsid
 INT_TO_JSID(int32 i)
 {
-    jsid iden;
+    jsid id;
     JS_ASSERT(INT_FITS_IN_JSID(i));
-    JSID_BITS(iden) = ((i << 1) | JSID_TYPE_INT);
-    return iden;
+    JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT);
+    return id;
 }
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_OBJECT(jsid iden)
+JSID_IS_OBJECT(jsid id)
 {
-    return (JSID_BITS(iden) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT;
+    return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT &&
+           (size_t)JSID_BITS(id) != JSID_TYPE_OBJECT;
 }
 
 static JS_ALWAYS_INLINE JSObject *
-JSID_TO_OBJECT(jsid iden)
+JSID_TO_OBJECT(jsid id)
 {
-    JS_ASSERT(JSID_IS_OBJECT(iden));
-    return (JSObject *)(JSID_BITS(iden) & ~(size_t)JSID_TYPE_MASK);
+    JS_ASSERT(JSID_IS_OBJECT(id));
+    return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
 }
 
 static JS_ALWAYS_INLINE jsid
 OBJECT_TO_JSID(JSObject *obj)
 {
-    jsid iden;
+    jsid id;
     JS_ASSERT(obj != NULL);
     JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
-    JSID_BITS(iden) = ((size_t)obj | JSID_TYPE_OBJECT);
-    return iden;
+    JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
+    return id;
 }
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_GCTHING(jsid iden)
+JSID_IS_GCTHING(jsid id)
 {
-    return JSID_IS_STRING(iden) || JSID_IS_OBJECT(iden);
+    return JSID_IS_STRING(id) || JSID_IS_OBJECT(id);
 }
 
 static JS_ALWAYS_INLINE void *
-JSID_TO_GCTHING(jsid iden)
+JSID_TO_GCTHING(jsid id)
 {
-    return (void *)(JSID_BITS(iden) & ~(size_t)JSID_TYPE_MASK);
+    return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK);
 }
 
 /*
  * The magic XML namespace id is not a valid jsid. Global object classes in
  * embeddings that enable JS_HAS_XML_SUPPORT (E4X) should handle this id.
  */
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_DEFAULT_XML_NAMESPACE(jsid iden)
+JSID_IS_DEFAULT_XML_NAMESPACE(jsid id)
 {
-    JS_ASSERT_IF(((size_t)JSID_BITS(iden) & JSID_TYPE_MASK) == JSID_TYPE_DEFAULT_XML_NAMESPACE,
-                 JSID_BITS(iden) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
-    return ((size_t)JSID_BITS(iden) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
+    JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_DEFAULT_XML_NAMESPACE,
+                 JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
+    return ((size_t)JSID_BITS(id) == JSID_TYPE_DEFAULT_XML_NAMESPACE);
 }
 
 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
 extern JS_PUBLIC_DATA(jsid) JS_DEFAULT_XML_NAMESPACE_ID;
 #else
 #define JS_DEFAULT_XML_NAMESPACE_ID ((jsid)JSID_TYPE_DEFAULT_XML_NAMESPACE)
 #endif
 
 /*
  * A void jsid is not a valid id and only arises as an exceptional API return
  * value, such as in JS_NextProperty. Embeddings must not pass JSID_VOID into
  * JSAPI entry points expecting a jsid and do not need to handle JSID_VOID in
  * hooks receiving a jsid except when explicitly noted in the API contract.
  */
 
 static JS_ALWAYS_INLINE JSBool
-JSID_IS_VOID(jsid iden)
+JSID_IS_VOID(jsid id)
 {
-    JS_ASSERT_IF(((size_t)JSID_BITS(iden) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
-                 JSID_BITS(iden) == JSID_TYPE_VOID);
-    return ((size_t)JSID_BITS(iden) == JSID_TYPE_VOID);
+    JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID,
+                 JSID_BITS(id) == JSID_TYPE_VOID);
+    return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID);
 }
 
+static JS_ALWAYS_INLINE JSBool
+JSID_IS_EMPTY(jsid id)
+{
+    return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT);
+}
+
+#undef id
+
 #ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
 extern JS_PUBLIC_DATA(jsid) JSID_VOID;
+extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
 #else
-#define JSID_VOID  ((jsid)JSID_TYPE_VOID)
+# define JSID_VOID      ((jsid)JSID_TYPE_VOID)
+# define JSID_EMPTY     ((jsid)JSID_TYPE_OBJECT)
 #endif
 
 /************************************************************************/
 
 /* Lock and unlock the GC thing held by a jsval. */
 #define JSVAL_LOCK(cx,v)        (JSVAL_IS_GCTHING(v)                          \
                                  ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v))    \
                                  : JS_TRUE)
@@ -467,32 +479,32 @@ extern JS_PUBLIC_DATA(jsid) JSID_VOID;
                                            set of the same-named property in an
                                            object that delegates to a prototype
                                            containing this property */
 #define JSPROP_INDEX            0x80    /* name is actually (jsint) index */
 #define JSPROP_SHORTID          0x100   /* set in JSPropertyDescriptor.attrs
                                            if getters/setters use a shortid */
 
 /* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */
+#define JSFUN_CONSTRUCTOR       0x02    /* native that can be called as a ctor
+                                           without creating a this object */
 #define JSFUN_LAMBDA            0x08    /* expressed, not declared, function */
 #define JSFUN_HEAVYWEIGHT       0x80    /* activation requires a Call object */
 
 #define JSFUN_HEAVYWEIGHT_TEST(f)  ((f) & JSFUN_HEAVYWEIGHT)
 
 #define JSFUN_THISP_FLAGS(f)  (f)
 #define JSFUN_THISP_TEST(f,t) ((f) & t)
 
 #define JSFUN_THISP_STRING    0x0100    /* |this| may be a primitive string */
 #define JSFUN_THISP_NUMBER    0x0200    /* |this| may be a primitive number */
 #define JSFUN_THISP_BOOLEAN   0x0400    /* |this| may be a primitive boolean */
 #define JSFUN_THISP_PRIMITIVE 0x0700    /* |this| may be any primitive value */
 
-#define JSFUN_FAST_NATIVE     0x0800    /* JSFastNative needs no JSStackFrame */
-
-#define JSFUN_FLAGS_MASK      0x0ff8    /* overlay JSFUN_* attributes --
+#define JSFUN_FLAGS_MASK      0x07fa    /* overlay JSFUN_* attributes --
                                            bits 12-15 are used internally to
                                            flag interpreted functions */
 
 #define JSFUN_STUB_GSOPS      0x1000    /* use JS_PropertyStub getter/setter
                                            instead of defaulting to class gsops
                                            for property holding function */
 
 /*
@@ -902,16 +914,18 @@ JS_StringToVersion(const char *string);
                                                    will be passed to each call
                                                    to JS_ExecuteScript. */
 #define JSOPTION_UNROOTED_GLOBAL JS_BIT(13)     /* The GC will not root the
                                                    contexts' global objects
                                                    (see JS_GetGlobalObject),
                                                    leaving that up to the
                                                    embedding. */
 
+#define JSOPTION_METHODJIT      JS_BIT(14)      /* Whole-method JIT. */
+
 extern JS_PUBLIC_API(uint32)
 JS_GetOptions(JSContext *cx);
 
 extern JS_PUBLIC_API(uint32)
 JS_SetOptions(JSContext *cx, uint32 options);
 
 extern JS_PUBLIC_API(uint32)
 JS_ToggleOptions(JSContext *cx, uint32 options);
@@ -949,20 +963,28 @@ JS_END_EXTERN_C
 class JS_PUBLIC_API(JSAutoCrossCompartmentCall)
 {
     JSCrossCompartmentCall *call;
   public:
     JSAutoCrossCompartmentCall() : call(NULL) {}
 
     bool enter(JSContext *cx, JSObject *target);
 
+    bool entered() const { return call != NULL; }
+
     ~JSAutoCrossCompartmentCall() {
         if (call)
             JS_LeaveCrossCompartmentCall(call);
     }
+
+    void swap(JSAutoCrossCompartmentCall &other) {
+        JSCrossCompartmentCall *tmp = call;
+        call = other.call;
+        other.call = tmp;
+    }
 };
 
 class JS_FRIEND_API(JSAutoEnterCompartment)
 {
     JSContext *cx;
     JSCompartment *compartment;
   public:
     JSAutoEnterCompartment(JSContext *cx, JSCompartment *newCompartment);
@@ -1059,28 +1081,39 @@ JS_InitCTypesClass(JSContext *cx, JSObje
  * NB: there is an anti-dependency between JS_CALLEE and JS_SET_RVAL: native
  * methods that may inspect their callee must defer setting their return value
  * until after any such possible inspection. Otherwise the return value will be
  * inspected instead of the callee function object.
  *
  * WARNING: These are not (yet) mandatory macros, but new code outside of the
  * engine should use them. In the Mozilla 2.0 milestone their definitions may
  * change incompatibly.
+ *
+ * N.B. constructors must not use JS_THIS, as no 'this' object has been created.
  */
+
 #define JS_CALLEE(cx,vp)        ((vp)[0])
-#define JS_ARGV_CALLEE(argv)    ((argv)[-2])
 #define JS_THIS(cx,vp)          JS_ComputeThis(cx, vp)
 #define JS_THIS_OBJECT(cx,vp)   (JSVAL_TO_OBJECT(JS_THIS(cx,vp)))
 #define JS_ARGV(cx,vp)          ((vp) + 2)
 #define JS_RVAL(cx,vp)          (*(vp))
 #define JS_SET_RVAL(cx,vp,v)    (*(vp) = (v))
 
 extern JS_PUBLIC_API(jsval)
 JS_ComputeThis(JSContext *cx, jsval *vp);
 
+#ifdef __cplusplus
+#undef JS_THIS
+static inline jsval
+JS_THIS(JSContext *cx, jsval *vp)
+{
+    return JSVAL_IS_PRIMITIVE(vp[1]) ? JS_ComputeThis(cx, vp) : vp[1];
+}
+#endif
+
 extern JS_PUBLIC_API(void *)
 JS_malloc(JSContext *cx, size_t nbytes);
 
 extern JS_PUBLIC_API(void *)
 JS_realloc(JSContext *cx, void *p, size_t nbytes);
 
 extern JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p);
@@ -1625,17 +1658,16 @@ struct JSClass {
     JSClassInternal     reserved1;
     void                *reserved[19];
 };
 
 #define JSCLASS_HAS_PRIVATE             (1<<0)  /* objects have private slot */
 #define JSCLASS_NEW_ENUMERATE           (1<<1)  /* has JSNewEnumerateOp hook */
 #define JSCLASS_NEW_RESOLVE             (1<<2)  /* has JSNewResolveOp hook */
 #define JSCLASS_PRIVATE_IS_NSISUPPORTS  (1<<3)  /* private is (nsISupports *) */
-/* (1<<4) was JSCLASS_SHARE_ALL_PROPERTIES, now obsolete. See bug 527805. */
 #define JSCLASS_NEW_RESOLVE_GETS_START  (1<<5)  /* JSNewResolveOp gets starting
                                                    object in prototype chain
                                                    passed in via *objp in/out
                                                    parameter */
 #define JSCLASS_CONSTRUCT_PROTOTYPE     (1<<6)  /* call constructor on class
                                                    prototype */
 #define JSCLASS_DOCUMENT_OBSERVER       (1<<7)  /* DOM document observer */
 
@@ -1758,48 +1790,33 @@ struct JSPropertySpec {
     JSPropertyOp    setter;
 };
 
 struct JSFunctionSpec {
     const char      *name;
     JSNative        call;
     uint16          nargs;
     uint16          flags;
-
-    /*
-     * extra & 0xFFFF:  Number of extra argument slots for local GC roots.
-     *                  If fast native, must be zero.
-     * extra >> 16:     Reserved for future use (must be 0).
-     */
-    uint32          extra;
 };
 
 /*
  * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
  * that's passed to JS_DefineFunctions or JS_InitClass.
  */
-#define JS_FS_END JS_FS(NULL,NULL,0,0,0)
+#define JS_FS_END JS_FS(NULL,NULL,0,0)
 
 /*
- * Initializer macro for a JSFunctionSpec array element. This is the original
- * kind of native function specifier initializer. Use JS_FN ("fast native", see
- * JSFastNative in jspubtd.h) for all functions that do not need a stack frame
- * when activated.
+ * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name
+ * pays homage to the old JSNative/JSFastNative split) simply adds the flag
+ * JSFUN_STUB_GSOPS.
  */
-#define JS_FS(name,call,nargs,flags,extra)                                    \
-    {name, call, nargs, flags, extra}
-
-/*
- * "Fast native" initializer macro for a JSFunctionSpec array element. Use this
- * in preference to JS_FS if the native in question does not need its own stack
- * frame when activated.
- */
-#define JS_FN(name,fastcall,nargs,flags)                                      \
-    JS_FS(name, (JSNative)(fastcall), nargs,                                  \
-          (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS, 0)
+#define JS_FS(name,call,nargs,flags)                                          \
+    {name, call, nargs, flags}
+#define JS_FN(name,call,nargs,flags)                                          \
+    {name, call, nargs, (flags) | JSFUN_STUB_GSOPS}
 
 extern JS_PUBLIC_API(JSObject *)
 JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
              JSClass *clasp, JSNative constructor, uintN nargs,
              JSPropertySpec *ps, JSFunctionSpec *fs,
              JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
 
 #ifdef JS_THREADSAFE
@@ -2546,19 +2563,16 @@ extern JS_PUBLIC_API(void)
 JS_TriggerOperationCallback(JSContext *cx);
 
 extern JS_PUBLIC_API(void)
 JS_TriggerAllOperationCallbacks(JSRuntime *rt);
 
 extern JS_PUBLIC_API(JSBool)
 JS_IsRunning(JSContext *cx);
 
-extern JS_PUBLIC_API(JSBool)
-JS_IsConstructing(JSContext *cx);
-
 /*
  * Saving and restoring frame chains.
  *
  * These two functions are used to set aside cx's call stack while that stack
  * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
  * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
  * must be balanced and all nested calls to JS_SaveFrameChain must have had
  * matching JS_RestoreFrameChain calls.
@@ -3024,16 +3038,97 @@ extern JS_PUBLIC_API(void)
 JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb);
 
 extern JS_PUBLIC_API(JSFunctionCallback)
 JS_GetFunctionCallback(JSContext *cx);
 #endif
 
 /************************************************************************/
 
+/*
+ * JS_IsConstructing must be called from within a native given the
+ * native's original cx and vp arguments. If JS_IsConstructing is true,
+ * JS_THIS must not be used; the constructor should construct and return a
+ * new object. Otherwise, the native is called as an ordinary function and
+ * JS_THIS may be used.
+ */
+static JS_ALWAYS_INLINE JSBool
+JS_IsConstructing(JSContext *cx, const jsval *vp)
+{
+    jsval_layout l;
+
+#ifdef DEBUG
+    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    if (JS_ObjectIsFunction(cx, callee)) {
+        JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
+        JS_ASSERT((JS_GetFunctionFlags(fun) & JSFUN_CONSTRUCTOR) != 0);
+    } else {
+        JS_ASSERT(JS_GET_CLASS(cx, callee)->construct != NULL);
+    }
+#endif
+
+    l.asBits = JSVAL_BITS(vp[1]);
+    return JSVAL_IS_MAGIC_IMPL(l);
+}
+
+/*
+ * In the case of a constructor called from JS_ConstructObject and
+ * JS_InitClass where the class has the JSCLASS_CONSTRUCT_PROTOTYPE flag set,
+ * the JS engine passes the constructor a non-standard 'this' object. In such
+ * cases, the following query provides the additional information of whether a
+ * special 'this' was supplied. E.g.:
+ *
+ *   JSBool foo_native(JSContext *cx, uintN argc, jsval *vp) {
+ *     JSObject *maybeThis;
+ *     if (JS_IsConstructing_PossiblyWithGivenThisObject(cx, vp, &maybeThis)) {
+ *       // native called as a constructor
+ *       if (maybeThis)
+ *         // native called as a constructor with maybeThis as 'this'
+ *     } else {
+ *       // native called as function, maybeThis is still uninitialized
+ *     }
+ *   }
+ *
+ * Note that embeddings do not need to use this query unless they use the
+ * aforementioned API/flags.
+ */
+static JS_ALWAYS_INLINE JSBool
+JS_IsConstructing_PossiblyWithGivenThisObject(JSContext *cx, const jsval *vp,
+                                              JSObject **maybeThis)
+{
+    jsval_layout l;
+    JSBool isCtor;
+
+#ifdef DEBUG
+    JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
+    if (JS_ObjectIsFunction(cx, callee)) {
+        JSFunction *fun = JS_ValueToFunction(cx, JS_CALLEE(cx, vp));
+        JS_ASSERT((JS_GetFunctionFlags(fun) & JSFUN_CONSTRUCTOR) != 0);
+    } else {
+        JS_ASSERT(JS_GET_CLASS(cx, callee)->construct != NULL);
+    }
+#endif
+
+    l.asBits = JSVAL_BITS(vp[1]);
+    isCtor = JSVAL_IS_MAGIC_IMPL(l);
+    if (isCtor)
+        *maybeThis = MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(l);
+    return isCtor;
+}
+
+/*
+ * If a constructor does not have any static knowledge about the type of
+ * object to create, it can request that the JS engine create a default new
+ * 'this' object, as is done for non-constructor natives when called with new.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewObjectForConstructor(JSContext *cx, const jsval *vp);
+
+/************************************************************************/
+
 #ifdef DEBUG
 #define JS_GC_ZEAL 1
 #endif
 
 #ifdef JS_GC_ZEAL
 extern JS_PUBLIC_API(void)
 JS_SetGCZeal(JSContext *cx, uint8 zeal);
 #endif
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -512,16 +512,33 @@ SetArrayElement(JSContext *cx, JSObject 
     if (!IndexToId(cx, obj, index, NULL, idr.addr(), JS_TRUE))
         return JS_FALSE;
     JS_ASSERT(!JSID_IS_VOID(idr.id()));
 
     Value tmp = v;
     return obj->setProperty(cx, idr.id(), &tmp);
 }
 
+#ifdef JS_TRACER
+JSBool JS_FASTCALL
+js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i)
+{
+    jsuint u = jsuint(i);
+    jsuint capacity = obj->getDenseArrayCapacity();
+    if (u < capacity)
+        return true;
+    if (INDEX_TOO_SPARSE(obj, u))
+        return false;
+    return obj->ensureDenseArrayElements(cx, u + 1);    
+
+}
+JS_DEFINE_CALLINFO_3(extern, BOOL, js_EnsureDenseArrayCapacity, CONTEXT, OBJECT, INT32, 0,
+                     nanojit::ACCSET_STORE_ANY)
+#endif
+
 static JSBool
 DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index)
 {
     JS_ASSERT(index >= 0);
     if (obj->isDenseArray()) {
         if (index <= jsuint(-1)) {
             jsuint idx = jsuint(index);
             if (idx < obj->getDenseArrayCapacity()) {
@@ -750,32 +767,32 @@ array_getProperty(JSContext *cx, JSObjec
 
     if (!obj->isDenseArray())
         return js_GetProperty(cx, obj, id, vp);
 
     if (!js_IdIsIndex(id, &i) || i >= obj->getDenseArrayCapacity() ||
         obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
         JSObject *obj2;
         JSProperty *prop;
-        JSScopeProperty *sprop;
+        const Shape *shape;
 
         JSObject *proto = obj->getProto();
         if (!proto) {
             vp->setUndefined();
             return JS_TRUE;
         }
 
         vp->setUndefined();
         if (js_LookupPropertyWithFlags(cx, proto, id, cx->resolveFlags,
                                        &obj2, &prop) < 0)
             return JS_FALSE;
 
         if (prop && obj2->isNative()) {
-            sprop = (JSScopeProperty *) prop;
-            if (!js_NativeGet(cx, obj, obj2, sprop, JSGET_METHOD_BARRIER, vp))
+            shape = (const Shape *) prop;
+            if (!js_NativeGet(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, vp))
                 return JS_FALSE;
             JS_UNLOCK_OBJ(cx, obj2);
         }
         return JS_TRUE;
     }
 
     *vp = obj->getDenseArrayElement(i);
     return JS_TRUE;
@@ -806,17 +823,18 @@ array_setProperty(JSContext *cx, JSObjec
     uint32 i;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
         return array_length_setter(cx, obj, id, vp);
 
     if (!obj->isDenseArray())
         return js_SetProperty(cx, obj, id, vp);
 
-    if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
+    if (!js_IdIsIndex(id, &i) || js_PrototypeHasIndexedProperties(cx, obj) ||
+        INDEX_TOO_SPARSE(obj, i)) {
         if (!obj->makeDenseArraySlow(cx))
             return JS_FALSE;
         return js_SetProperty(cx, obj, id, vp);
     }
 
     if (!obj->ensureDenseArrayElements(cx, i + 1))
         return JS_FALSE;
 
@@ -837,84 +855,36 @@ js_PrototypeHasIndexedProperties(JSConte
     while ((obj = obj->getProto()) != NULL) {
         /*
          * If the prototype is a non-native object (possibly a dense array), or
          * a native object (possibly a slow array) that has indexed properties,
          * return true.
          */
         if (!obj->isNative())
             return JS_TRUE;
-        if (obj->scope()->hadIndexedProperties())
+        if (obj->isIndexed())
             return JS_TRUE;
     }
     return JS_FALSE;
 }
 
 #ifdef JS_TRACER
 
-static JS_ALWAYS_INLINE JSBool FASTCALL
-dense_grow(JSContext* cx, JSObject* obj, jsint i, const Value &v)
+JSBool FASTCALL
+js_Array_dense_setelem_hole(JSContext* cx, JSObject* obj, jsint i)
 {
-    JS_ASSERT(obj->isDenseArray());
-
-    /*
-     * Let the interpreter worry about negative array indexes.
-     */
-    JS_ASSERT((MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32) == (sizeof(intptr_t) != sizeof(uint32)));
-    if (MAX_DSLOTS_LENGTH > MAX_DSLOTS_LENGTH32) {
-        /*
-         * Have to check for negative values bleeding through on 64-bit machines only,
-         * since we can't allocate large enough arrays for this on 32-bit machines.
-         */
-        if (i < 0)
-            return JS_FALSE;
-    }
-
-    /*
-     * If needed, grow the array as long it remains dense, otherwise fall off trace.
-     */
+    if (js_PrototypeHasIndexedProperties(cx, obj))
+        return false;
+
     jsuint u = jsuint(i);
-    jsuint capacity = obj->getDenseArrayCapacity();
-    if ((u >= capacity) && (INDEX_TOO_SPARSE(obj, u) || !obj->ensureDenseArrayElements(cx, u + 1)))
-        return JS_FALSE;
-
-    if (obj->getDenseArrayElement(u).isMagic()) {
-        if (js_PrototypeHasIndexedProperties(cx, obj))
-            return JS_FALSE;
-
-        if (u >= obj->getArrayLength())
-            obj->setArrayLength(u + 1);
-    }
-
-    obj->setDenseArrayElement(u, v);
-    return JS_TRUE;
+    if (u >= obj->getArrayLength())
+        obj->setArrayLength(u + 1);
+    return true;
 }
-
-JSBool FASTCALL
-js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, ValueArgType v)
-{
-    return dense_grow(cx, obj, i, ValueArgToConstRef(v));
-}
-JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, VALUE,
-                     0, nanojit::ACCSET_STORE_ANY)
-
-JSBool FASTCALL
-js_Array_dense_setelem_int(JSContext* cx, JSObject* obj, jsint i, int32 j)
-{
-    return dense_grow(cx, obj, i, Int32Value(j));
-}
-JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_int, CONTEXT, OBJECT, INT32, INT32,
-                     0, nanojit::ACCSET_STORE_ANY)
-
-JSBool FASTCALL
-js_Array_dense_setelem_double(JSContext* cx, JSObject* obj, jsint i, jsdouble d)
-{
-    return dense_grow(cx, obj, i, NumberValue(d));
-}
-JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem_double, CONTEXT, OBJECT, INT32, DOUBLE,
+JS_DEFINE_CALLINFO_3(extern, BOOL, js_Array_dense_setelem_hole, CONTEXT, OBJECT, INT32,
                      0, nanojit::ACCSET_STORE_ANY)
 #endif
 
 static JSBool
 array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                      PropertyOp getter, PropertyOp setter, uintN attrs)
 {
     uint32 i = 0;       // init to shut GCC up
@@ -1001,19 +971,18 @@ array_trace(JSTracer *trc, JSObject *obj
         /* This might fail, in which case we don't slowify it. */
         static_cast<GCMarker *>(trc)->arraysToSlowify.append(obj);
     }
 }
 
 Class js_ArrayClass = {
     "Array",
     Class::NON_NATIVE |
-    JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_FIXED_RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_CLASS_RESERVED_SLOTS) |
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     js_TryValueOf,
     array_finalize,
@@ -1039,18 +1008,17 @@ Class js_ArrayClass = {
         NULL,       /* thisObject     */
         NULL,       /* clear          */
     }
 };
 
 Class js_SlowArrayClass = {
     "Array",
     JSCLASS_HAS_PRIVATE |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
     slowarray_addProperty,
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     js_TryValueOf
 };
@@ -1059,86 +1027,95 @@ Class js_SlowArrayClass = {
  * Convert an array object from fast-and-dense to slow-and-flexible.
  */
 JSBool
 JSObject::makeDenseArraySlow(JSContext *cx)
 {
     JS_ASSERT(isDenseArray());
 
     /*
+     * Save old map now, before calling InitScopeForObject. We'll have to undo
+     * on error. This is gross, but a better way is not obvious.
+     */
+    JSObjectMap *oldMap = map;
+
+    /*
      * Create a native scope. All slow arrays other than Array.prototype get
      * the same initial shape.
      */
-    uint32 emptyShape;
-    JSObject *obj = this;
-    JSObject *arrayProto = obj->getProto();
-    if (arrayProto->getClass() == &js_ObjectClass) {
-        /* obj is Array.prototype. */
-        emptyShape = js_GenerateShape(cx, false);
-    } else {
-        /* arrayProto is Array.prototype. */
-        JS_ASSERT(arrayProto->getClass() == &js_SlowArrayClass);
-        emptyShape = arrayProto->scope()->emptyScope->shape;
-    }
-    JSScope *scope = JSScope::create(cx, &js_SlowArrayClass, obj, emptyShape);
-    if (!scope)
-        return JS_FALSE;
+    JSObject *arrayProto = getProto();
+    if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto))
+        return false;
 
     uint32 capacity;
 
-    if (obj->dslots) {
-        capacity = obj->getDenseArrayCapacity();
-        obj->dslots[-1].setPrivateUint32(JS_INITIAL_NSLOTS + capacity);
+    if (dslots) {
+        capacity = getDenseArrayCapacity();
+        dslots[-1].setPrivateUint32(JS_INITIAL_NSLOTS + capacity);
     } else {
         /*
          * Array.prototype is constructed as a dense array, but is immediately slowified before
          * we have time to set capacity.
          */
         capacity = 0;
     }
 
-    scope->freeslot = obj->numSlots();
+    uint32 nslots = numSlots();
+    if (nslots >= JS_NSLOTS_LIMIT) {
+        setMap(oldMap);
+        JS_ReportOutOfMemory(cx);
+        return false;
+    }
+
+    freeslot = nslots;
 
     /* Begin with the length property to share more of the property tree. */
-    if (!scope->addProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
-                            array_length_getter, array_length_setter,
-                            JSSLOT_ARRAY_LENGTH, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0)) {
-        goto out_bad;
+    if (!addProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
+                     array_length_getter, array_length_setter,
+                     JSSLOT_ARRAY_LENGTH, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0)) {
+        setMap(oldMap);
+        return false;
     }
 
     /* Create new properties pointing to existing elements. */
     for (uint32 i = 0; i < capacity; i++) {
         jsid id;
-        if (!ValueToId(cx, Int32Value(i), &id))
-            goto out_bad;
-
-        if (obj->getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
-            obj->setDenseArrayElement(i, UndefinedValue());
+        if (!ValueToId(cx, Int32Value(i), &id)) {
+            setMap(oldMap);
+            return false;
+        }
+
+        if (getDenseArrayElement(i).isMagic(JS_ARRAY_HOLE)) {
+            setDenseArrayElement(i, UndefinedValue());
             continue;
         }
 
-        if (!scope->addDataProperty(cx, id, JS_INITIAL_NSLOTS + i, JSPROP_ENUMERATE))
-            goto out_bad;
+        if (!addDataProperty(cx, id, JS_INITIAL_NSLOTS + i, JSPROP_ENUMERATE)) {
+            setMap(oldMap);
+            return false;
+        }
     }
 
     /*
      * Render our formerly-reserved non-private properties GC-safe.  We do not
      * need to make the length slot GC-safe because it is the private slot
      * (this is statically asserted within JSObject) where the implementation
      * can store an arbitrary value.
      */
     JS_ASSERT(js_SlowArrayClass.flags & JSCLASS_HAS_PRIVATE);
-    obj->voidDenseOnlyArraySlots();
-    obj->clasp = &js_SlowArrayClass;
-    obj->map = scope;
-    return JS_TRUE;
-
-  out_bad:
-    scope->destroy(cx);
-    return JS_FALSE;
+    voidDenseOnlyArraySlots();
+
+    /*
+     * Finally, update class. If |this| is Array.prototype, then js_InitClass
+     * will create an emptyShape whose class is &js_SlowArrayClass, to ensure
+     * that delegating instances can share shapes in the tree rooted at the
+     * proto's empty shape.
+     */
+    clasp = &js_SlowArrayClass;
+    return true;
 }
 
 /* Transfer ownership of buffer to returned string. */
 static inline JSBool
 BufferToString(JSContext *cx, JSCharBuffer &cb, Value *rval)
 {
     JSString *str = js_NewStringFromCharBuffer(cx, cb);
     if (!str)
@@ -2895,21 +2872,21 @@ array_some(JSContext *cx, uintN argc, Va
 static JSBool
 array_every(JSContext *cx, uintN argc, Value *vp)
 {
     return array_extra(cx, EVERY, argc, vp);
 }
 #endif
 
 static JSBool
-array_isArray(JSContext *cx, uintN argc, jsval *vp)
+array_isArray(JSContext *cx, uintN argc, Value *vp)
 {
-    *vp = BOOLEAN_TO_JSVAL(argc > 0 &&
-                           !JSVAL_IS_PRIMITIVE(vp[2]) &&
-                           JSVAL_TO_OBJECT(vp[2])->wrappedObject(cx)->isArray());
+    vp->setBoolean(argc > 0 &&
+                   vp[2].isObject() &&
+                   vp[2].toObject().wrappedObject(cx)->isArray());
     return JS_TRUE;
 }
 
 static JSFunctionSpec array_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,      array_toSource,     0,0),
 #endif
     JS_FN(js_toString_str,      array_toString,     0,0),
@@ -2993,19 +2970,19 @@ js_NewEmptyArray(JSContext* cx, JSObject
         return NULL;
 
     JS_ASSERT(proto->isArray());
 
     JSObject* obj = js_NewGCObject(cx);
     if (!obj)
         return NULL;
 
-    /* Initialize all fields of JSObject. */
-    obj->map = const_cast<JSObjectMap *>(&JSObjectMap::sharedNonNative);
-    obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue());
+    /* Initialize all fields, calling init before setting obj->map. */
+    obj->init(&js_ArrayClass, proto, proto->getParent(), NullValue(), cx);
+    obj->setSharedNonNativeMap();
     obj->setArrayLength(len);
     obj->setDenseArrayCapacity(0);
     return obj;
 }
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewEmptyArray, CONTEXT, OBJECT, INT32, 0,
                      nanojit::ACCSET_STORE_ANY)
 #endif
@@ -3023,22 +3000,28 @@ js_NewPreallocatedArray(JSContext* cx, J
 #ifdef JS_TRACER
 JS_DEFINE_CALLINFO_3(extern, OBJECT, js_NewPreallocatedArray, CONTEXT, OBJECT, INT32,
                      0, nanojit::ACCSET_STORE_ANY)
 #endif
 
 JSObject *
 js_InitArrayClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, (Native) js_Array, 1,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
                                    NULL, array_methods, NULL, array_static_methods);
     if (!proto)
         return NULL;
+
+    /*
+     * Assert that js_InitClass used the correct (slow array, not dense array)
+     * class for proto's emptyShape class.
+     */
+    JS_ASSERT(proto->emptyShape->getClass() == proto->getClass());
+
     proto->setArrayLength(0);
-
     return proto;
 }
 
 JSObject *
 js_NewArrayObject(JSContext *cx, jsuint length, const Value *vector)
 {
     JSObject *obj = NewDenseArrayObject(cx);
     if (!obj)
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -105,17 +105,17 @@ JSObject::isSlowArray() const
 inline bool
 JSObject::isArray() const
 {
     return isDenseArray() || isSlowArray();
 }
 
 /*
  * Dense arrays are not native -- aobj->isNative() for a dense array aobj
- * results in false, meaning aobj->map does not point to a JSScope.
+ * results in false, meaning aobj->map does not point to a js::Shape.
  *
  * But Array methods are called via aobj.sort(), e.g., and the interpreter and
  * the trace recorder must consult the property cache in order to perform well.
  * The cache works only for native objects.
  *
  * Therefore the interpreter (js_Interpret in JSOP_GETPROP and JSOP_CALLPROP)
  * and js_GetPropertyHelper use this inline function to skip up one link in the
  * prototype chain when obj is a dense array, in order to find a native object
@@ -244,18 +244,18 @@ js_Array(JSContext *cx, uintN argc, js::
 /*
  * Friend api function that allows direct creation of an array object with a
  * given capacity.  Non-null return value means allocation of the internal
  * buffer for a capacity of at least |capacity| succeeded.  A pointer to the
  * first element of this internal buffer is returned in the |vector| out
  * parameter.  The caller promises to fill in the first |capacity| values
  * starting from that pointer immediately after this function returns and
  * without triggering GC (so this method is allowed to leave those
- * uninitialized) and to set them to non-JSVAL_HOLE values, so that the
- * resulting array has length and count both equal to |capacity|.
+ * uninitialized) and to set them to non-JS_ARRAY_HOLE-magic-why values, so
+ * that the resulting array has length and count both equal to |capacity|.
  *
  * FIXME: for some strange reason, when this file is included from
  * dom/ipc/TabParent.cpp in MSVC, jsuint resolves to a slightly different
  * builtin than when mozjs.dll is built, resulting in a link error in xul.dll.
  * It would be useful to find out what is causing this insanity.
  */
 JS_FRIEND_API(JSObject *)
 js_NewArrayObjectWithCapacity(JSContext *cx, uint32_t capacity, jsval **vector);
@@ -275,9 +275,12 @@ js_CloneDensePrimitiveArray(JSContext *c
 
 /*
  * Returns JS_TRUE if the given object is a dense array that contains only
  * primitive values.
  */
 JS_FRIEND_API(JSBool)
 js_IsDensePrimitiveArray(JSObject *obj);
 
+extern JSBool JS_FASTCALL
+js_EnsureDenseArrayCapacity(JSContext *cx, JSObject *obj, jsint i);
+
 #endif /* jsarray_h___ */
--- a/js/src/jsast.tbl
+++ b/js/src/jsast.tbl
@@ -63,16 +63,17 @@ ASTDEF(AST_FUNC_EXPR,             "Funct
 ASTDEF(AST_ARRAY_EXPR,            "ArrayExpression")
 ASTDEF(AST_OBJECT_EXPR,           "ObjectExpression")
 ASTDEF(AST_THIS_EXPR,             "ThisExpression")
 ASTDEF(AST_GRAPH_EXPR,            "GraphExpression")
 ASTDEF(AST_GRAPH_IDX_EXPR,        "GraphIndexExpression")
 ASTDEF(AST_COMP_EXPR,             "ComprehensionExpression")
 ASTDEF(AST_GENERATOR_EXPR,        "GeneratorExpression")
 ASTDEF(AST_YIELD_EXPR,            "YieldExpression")
+ASTDEF(AST_LET_EXPR,              "LetExpression")
 
 ASTDEF(AST_EMPTY_STMT,            "EmptyStatement")
 ASTDEF(AST_BLOCK_STMT,            "BlockStatement")
 ASTDEF(AST_EXPR_STMT,             "ExpressionStatement")
 ASTDEF(AST_LAB_STMT,              "LabeledStatement")
 ASTDEF(AST_IF_STMT,               "IfStatement")
 ASTDEF(AST_SWITCH_STMT,           "SwitchStatement")
 ASTDEF(AST_WHILE_STMT,            "WhileStatement")
@@ -81,30 +82,32 @@ ASTDEF(AST_FOR_STMT,              "ForSt
 ASTDEF(AST_FOR_IN_STMT,           "ForInStatement")
 ASTDEF(AST_BREAK_STMT,            "BreakStatement")
 ASTDEF(AST_CONTINUE_STMT,         "ContinueStatement")
 ASTDEF(AST_WITH_STMT,             "WithStatement")
 ASTDEF(AST_RETURN_STMT,           "ReturnStatement")
 ASTDEF(AST_TRY_STMT,              "TryStatement")
 ASTDEF(AST_THROW_STMT,            "ThrowStatement")
 ASTDEF(AST_DEBUGGER_STMT,         "DebuggerStatement")
+ASTDEF(AST_LET_STMT,              "LetStatement")
 
 ASTDEF(AST_CASE,                  "SwitchCase")
 ASTDEF(AST_CATCH,                 "CatchClause")
 ASTDEF(AST_COMP_BLOCK,            "ComprehensionBlock")
 
 ASTDEF(AST_ARRAY_PATT,            "ArrayPattern")
 ASTDEF(AST_OBJECT_PATT,           "ObjectPattern")
 
 ASTDEF(AST_XMLANYNAME,            "XMLAnyName")
 ASTDEF(AST_XMLATTR_SEL,           "XMLAttributeSelector")
 ASTDEF(AST_XMLESCAPE,             "XMLEscape")
 ASTDEF(AST_XMLFILTER,             "XMLFilterExpression")
 ASTDEF(AST_XMLDEFAULT,            "XMLDefaultDeclaration")
 ASTDEF(AST_XMLQUAL,               "XMLQualifiedIdentifier")
+ASTDEF(AST_XMLFUNCQUAL,           "XMLFunctionQualifiedIdentifier")
 ASTDEF(AST_XMLELEM,               "XMLElement")
 ASTDEF(AST_XMLTEXT,               "XMLText")
 ASTDEF(AST_XMLLIST,               "XMLList")
 ASTDEF(AST_XMLSTART,              "XMLStartTag")
 ASTDEF(AST_XMLEND,                "XMLEndTag")
 ASTDEF(AST_XMLPOINT,              "XMLPointTag")
 ASTDEF(AST_XMLNAME,               "XMLName")
 ASTDEF(AST_XMLATTR,               "XMLAttribute")
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -171,16 +171,17 @@ const char *const js_common_atom_names[]
     js_toUTCString_str,         /* toUTCStringAtom              */
     js_valueOf_str,             /* valueOfAtom                  */
     js_toJSON_str,              /* toJSONAtom                   */
     "(void 0)",                 /* void0Atom                    */
     js_enumerable_str,          /* enumerableAtom               */
     js_configurable_str,        /* configurableAtom             */
     js_writable_str,            /* writableAtom                 */
     js_value_str,               /* valueAtom                    */
+    js_test_str,                /* testAtom                     */
     "use strict",               /* useStrictAtom                */
 
 #if JS_HAS_XML_SUPPORT
     js_etago_str,               /* etagoAtom                    */
     js_namespace_str,           /* namespaceAtom                */
     js_ptagc_str,               /* ptagcAtom                    */
     js_qualifier_str,           /* qualifierAtom                */
     js_space_str,               /* spaceAtom                    */
@@ -260,16 +261,17 @@ const char js_toString_str[]        = "t
 const char js_toUTCString_str[]     = "toUTCString";
 const char js_undefined_str[]       = "undefined";
 const char js_valueOf_str[]         = "valueOf";
 const char js_toJSON_str[]          = "toJSON";
 const char js_enumerable_str[]      = "enumerable";
 const char js_configurable_str[]    = "configurable";
 const char js_writable_str[]        = "writable";
 const char js_value_str[]           = "value";
+const char js_test_str[]            = "test";
 
 #if JS_HAS_XML_SUPPORT
 const char js_etago_str[]           = "</";
 const char js_namespace_str[]       = "namespace";
 const char js_ptagc_str[]           = "/>";
 const char js_qualifier_str[]       = "::";
 const char js_space_str[]           = " ";
 const char js_stago_str[]           = "<";
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -363,16 +363,17 @@ struct JSAtomState
     JSAtom              *toUTCStringAtom;
     JSAtom              *valueOfAtom;
     JSAtom              *toJSONAtom;
     JSAtom              *void0Atom;
     JSAtom              *enumerableAtom;
     JSAtom              *configurableAtom;
     JSAtom              *writableAtom;
     JSAtom              *valueAtom;
+    JSAtom              *testAtom;
     JSAtom              *useStrictAtom;
 
 #if JS_HAS_XML_SUPPORT
     JSAtom              *etagoAtom;
     JSAtom              *namespaceAtom;
     JSAtom              *ptagcAtom;
     JSAtom              *qualifierAtom;
     JSAtom              *spaceAtom;
@@ -519,16 +520,17 @@ extern const char   js_toUTCString_str[]
 extern const char   js_undefined_str[];
 extern const char   js_valueOf_str[];
 extern const char   js_toJSON_str[];
 extern const char   js_xml_str[];
 extern const char   js_enumerable_str[];
 extern const char   js_configurable_str[];
 extern const char   js_writable_str[];
 extern const char   js_value_str[];
+extern const char   js_test_str[];
 
 /*
  * Initialize atom state. Return true on success, false on failure to allocate
  * memory. The caller must zero rt->atomState before calling this function and
  * only call it after js_InitGC successfully returns.
  */
 extern JSBool
 js_InitAtomState(JSRuntime *rt);
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -55,17 +55,18 @@
 #include "jsvector.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 
 Class js_BooleanClass = {
     "Boolean",
-    JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
+    JSCLASS_HAS_RESERVED_SLOTS(1) |
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
@@ -121,28 +122,30 @@ static JSFunctionSpec boolean_methods[] 
 #endif
     JS_FN(js_toString_str,  bool_toString,  0, JSFUN_THISP_BOOLEAN),
     JS_FN(js_valueOf_str,   bool_valueOf,   0, JSFUN_THISP_BOOLEAN),
     JS_FN(js_toJSON_str,    bool_valueOf,   0, JSFUN_THISP_BOOLEAN),
     JS_FS_END
 };
 
 static JSBool
-Boolean(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+Boolean(JSContext *cx, uintN argc, Value *vp)
 {
-    Value bval;
+    Value *argv = vp + 2;
+    bool b = argc != 0 ? js_ValueToBoolean(argv[0]) : false;
 
-    if (argc != 0)
-        bval.setBoolean(!!js_ValueToBoolean(argv[0]));
-    else
-        bval.setBoolean(false);
-    if (!JS_IsConstructing(cx))
-        *rval = bval;
-    else
-        obj->setPrimitiveThis(bval);
+    if (IsConstructing(vp)) {
+        JSObject *obj = NewBuiltinClassInstance(cx, &js_BooleanClass);
+        if (!obj)
+            return false;
+        obj->setPrimitiveThis(BooleanValue(b));
+        vp->setObject(*obj);
+    } else {
+        vp->setBoolean(b);
+    }
     return true;
 }
 
 JSObject *
 js_InitBooleanClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto;
 
@@ -165,24 +168,24 @@ JSBool
 js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb)
 {
     return b ? js_AppendLiteral(cb, "true") : js_AppendLiteral(cb, "false");
 }
 
 JSBool
 js_ValueToBoolean(const Value &v)
 {
-    if (v.isNullOrUndefined())
-        return JS_FALSE;
+    if (v.isInt32())
+        return v.toInt32() != 0;
+    if (v.isString())
+        return v.toString()->length() != 0;
     if (v.isObject())
         return JS_TRUE;
-    if (v.isString())
-        return v.toString()->length() != 0;
-    if (v.isInt32())
-        return v.toInt32() != 0;
+    if (v.isNullOrUndefined())
+        return JS_FALSE;
     if (v.isDouble()) {
         jsdouble d;
 
         d = v.toDouble();
         return !JSDOUBLE_IS_NaN(d) && d != 0;
     }
     JS_ASSERT(v.isBoolean());
     return v.toBoolean();
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -178,83 +178,65 @@ int32 FASTCALL
 js_StringToInt32(JSContext* cx, JSString* str)
 {
     return StringToNumberType<int32>(cx, str);
 }
 JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, ACCSET_NONE)
 
 /* Nb: it's always safe to set isDefinitelyAtom to false if you're unsure or don't know. */
 static inline JSBool
-AddPropertyHelper(JSContext* cx, JSObject* obj, JSScopeProperty* sprop, bool isDefinitelyAtom)
+AddPropertyHelper(JSContext* cx, JSObject* obj, Shape* shape, bool isDefinitelyAtom)
 {
     JS_LOCK_OBJ(cx, obj);
-
-    uint32 slot = sprop->slot;
-    JSScope* scope = obj->scope();
-    if (slot != scope->freeslot)
-        return false;
-    JS_ASSERT(sprop->parent == scope->lastProperty());
-
-    if (scope->isSharedEmpty()) {
-        scope = js_GetMutableScope(cx, obj);
-        if (!scope)
-            return false;
-    } else {
-        JS_ASSERT(!scope->hasProperty(sprop));
-    }
+    JS_ASSERT(shape->previous() == obj->lastProperty());
 
-    if (!scope->table) {
-        if (slot < obj->numSlots()) {
-            JS_ASSERT(obj->getSlot(scope->freeslot).isUndefined());
-            ++scope->freeslot;
-        } else {
-            if (!js_AllocSlot(cx, obj, &slot))
-                goto exit_trace;
-
-            if (slot != sprop->slot) {
-                js_FreeSlot(cx, obj, slot);
-                goto exit_trace;
-            }
-        }
-
-        scope->extend(cx, sprop, isDefinitelyAtom);
-    } else {
-        JSScopeProperty *sprop2 =
-            scope->addProperty(cx, sprop->id, sprop->getter(), sprop->setter(),
-                               SPROP_INVALID_SLOT, sprop->attributes(), sprop->getFlags(),
-                               sprop->shortid);
-        if (sprop2 != sprop)
+    if (obj->nativeEmpty()) {
+        if (!obj->ensureClassReservedSlotsForEmptyObject(cx))
             goto exit_trace;
     }
 
+    uint32 slot;
+    slot = shape->slot;
+    JS_ASSERT(slot == obj->freeslot);
+
+    if (slot < obj->numSlots()) {
+        JS_ASSERT(obj->getSlot(slot).isUndefined());
+        ++obj->freeslot;
+        JS_ASSERT(obj->freeslot != 0);
+    } else {
+        if (!obj->allocSlot(cx, &slot))
+            goto exit_trace;
+        JS_ASSERT(slot == shape->slot);
+    }
+
+    obj->extend(cx, shape, isDefinitelyAtom);
     if (js_IsPropertyCacheDisabled(cx))
         goto exit_trace;
 
-    JS_UNLOCK_SCOPE(cx, scope);
+    JS_UNLOCK_OBJ(cx, obj);
     return true;
 
   exit_trace:
-    JS_UNLOCK_SCOPE(cx, scope);
+    JS_UNLOCK_OBJ(cx, obj);
     return false;
 }
 
 JSBool FASTCALL
-js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+js_AddProperty(JSContext* cx, JSObject* obj, Shape* shape)
 {
-    return AddPropertyHelper(cx, obj, sprop, /* isDefinitelyAtom = */false);
+    return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */false);
 }
-JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, ACCSET_STORE_ANY)
+JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
 
 JSBool FASTCALL
-js_AddAtomProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+js_AddAtomProperty(JSContext* cx, JSObject* obj, Shape* shape)
 {
-    return AddPropertyHelper(cx, obj, sprop, /* isDefinitelyAtom = */true);
+    return AddPropertyHelper(cx, obj, shape, /* isDefinitelyAtom = */true);
 }
-JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SCOPEPROP,
-                     0, ACCSET_STORE_ANY)
+JS_DEFINE_CALLINFO_3(extern, BOOL, js_AddAtomProperty, CONTEXT, OBJECT, SHAPE, 0, ACCSET_STORE_ANY)
 
 static JSBool
 HasProperty(JSContext* cx, JSObject* obj, jsid id)
 {
     // Check that we know how the lookup op will behave.
     for (JSObject* pobj = obj; pobj; pobj = pobj->getProto()) {
         if (pobj->getOps()->lookupProperty)
             return JS_NEITHER;
@@ -321,46 +303,14 @@ js_NewNullClosure(JSContext* cx, JSObjec
 
     JSFunction *fun = (JSFunction*) funobj;
     JS_ASSERT(GET_FUNCTION_PRIVATE(cx, funobj) == fun);
 
     JSObject* closure = js_NewGCObject(cx);
     if (!closure)
         return NULL;
 
-    closure->initSharingEmptyScope(&js_FunctionClass, proto, parent, PrivateValue(fun));
+    closure->initSharingEmptyShape(&js_FunctionClass, proto, parent, fun, cx);
     return closure;
 }
 JS_DEFINE_CALLINFO_4(extern, OBJECT, js_NewNullClosure, CONTEXT, OBJECT, OBJECT, OBJECT,
                      0, ACCSET_STORE_ANY)
 
-JS_REQUIRES_STACK JSBool FASTCALL
-js_PopInterpFrame(JSContext* cx, TracerState* state)
-{
-    JS_ASSERT(cx->hasfp() && cx->fp()->down);
-    JSStackFrame* const fp = cx->fp();
-
-    /*
-     * Mirror frame popping code from inline_return in js_Interpret. There are
-     * some things we just don't want to handle. In those cases, the trace will
-     * MISMATCH_EXIT.
-     */
-    if (fp->hasHookData())
-        return JS_FALSE;
-    if (cx->version != fp->getCallerVersion())
-        return JS_FALSE;
-    if (fp->flags & JSFRAME_CONSTRUCTING)
-        return JS_FALSE;
-    if (fp->hasIMacroPC())
-        return JS_FALSE;
-    if (fp->hasBlockChain())
-        return JS_FALSE;
-
-    fp->putActivationObjects(cx);
-    
-    /* Pop the frame and its memory. */
-    cx->stack().popInlineFrame(cx, fp, fp->down);
-
-    /* Update the inline call count. */
-    *state->inlineCallCountp = *state->inlineCallCountp - 1;
-    return JS_TRUE;
-}
-JS_DEFINE_CALLINFO_2(extern, BOOL, js_PopInterpFrame, CONTEXT, TRACERSTATE, 0, ACCSET_STORE_ANY)
--- a/js/src/jsbuiltins.h
+++ b/js/src/jsbuiltins.h
@@ -38,16 +38,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsbuiltins_h___
 #define jsbuiltins_h___
 
 #ifdef JS_TRACER
 
 #include "nanojit/nanojit.h"
+#include "jsvalue.h"
 
 #ifdef THIS
 #undef THIS
 #endif
 
 enum JSTNErrType { INFALLIBLE, FAIL_STATUS, FAIL_NULL, FAIL_NEG, FAIL_NEITHER };
 enum { 
     JSTN_ERRTYPE_MASK        = 0x07,
@@ -56,17 +57,17 @@ enum {
     JSTN_CONSTRUCTOR         = 0x20,
     JSTN_RETURN_NULLABLE_STR = 0x40,
     JSTN_RETURN_NULLABLE_OBJ = 0x80
 };
 
 #define JSTN_ERRTYPE(jstn)  ((jstn)->flags & JSTN_ERRTYPE_MASK)
 
 /*
- * Type describing a type specialization of a JSFastNative.
+ * Type describing a type specialization of a js::Native.
  *
  * |prefix| and |argtypes| declare what arguments should be passed to the
  * native function.  |prefix| can contain the following characters:
  *
  * 'C': a JSContext* argument
  * 'T': |this| as a JSObject* argument (bails if |this| is not an object)
  * 'S': |this| as a JSString* argument (bails if |this| is not a string)
  * 'R': a JSRuntime* argument
@@ -98,17 +99,17 @@ struct JSSpecializedNative {
 
 /*
  * Type holding extra trace-specific information about a fast native.
  *
  * 'specializations' points to a static array of available specializations
  * terminated by the lack of having the JSTN_MORE flag set.
  */
 struct JSNativeTraceInfo {
-    JSFastNative            native;
+    js::Native              native;
     JSSpecializedNative     *specializations;
 };
 
 /* Macros used by JS_DEFINE_CALLINFOn. */
 #ifdef DEBUG
 #define _JS_CI_NAME(op) ,#op
 #else
 #define _JS_CI_NAME(op)
@@ -217,17 +218,17 @@ struct ClosureVarInfo;
 #define _JS_CTYPE_OBJECT_RETRY      _JS_CTYPE(JSObject *,             _JS_PTR, --, --, FAIL_NULL)
 #define _JS_CTYPE_OBJECT_FAIL       _JS_CTYPE(JSObject *,             _JS_PTR, --, --, FAIL_STATUS)
 #define _JS_CTYPE_OBJECT_OR_NULL_FAIL _JS_CTYPE(JSObject *,           _JS_PTR, --, --, FAIL_STATUS | \
                                                                               JSTN_RETURN_NULLABLE_OBJ)
 #define _JS_CTYPE_OBJECTPTR         _JS_CTYPE(JSObject **,            _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_CONSTRUCTOR_RETRY _JS_CTYPE(JSObject *,             _JS_PTR, --, --, FAIL_NULL | \
                                                                                   JSTN_CONSTRUCTOR)
 #define _JS_CTYPE_REGEXP            _JS_CTYPE(JSObject *,             _JS_PTR, "","r", INFALLIBLE)
-#define _JS_CTYPE_SCOPEPROP         _JS_CTYPE(JSScopeProperty *,      _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_SHAPE             _JS_CTYPE(js::Shape *,            _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_TRACERSTATE       _JS_CTYPE(TracerState *,          _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_FRAGMENT          _JS_CTYPE(nanojit::Fragment *,    _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_CLASS             _JS_CTYPE(js::Class *,            _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_DOUBLEPTR         _JS_CTYPE(double *,               _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_CHARPTR           _JS_CTYPE(char *,                 _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_CVIPTR            _JS_CTYPE(const ClosureVarInfo *, _JS_PTR, --, --, INFALLIBLE)
 #define _JS_CTYPE_FRAMEINFO         _JS_CTYPE(FrameInfo *,            _JS_PTR, --, --, INFALLIBLE)
 
@@ -501,50 +502,50 @@ struct ClosureVarInfo;
         _JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0),              \
     _JS_CTYPE_FLAGS(rt)
 
 #define JS_DEFINE_TRCINFO_1(name, tn0)                                                            \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1)                                                       \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)                                                  \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     _JS_DEFINE_CALLINFO_n tn2                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn2 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)                                             \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     _JS_DEFINE_CALLINFO_n tn2                                                                     \
     _JS_DEFINE_CALLINFO_n tn3                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn3 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define _JS_DEFINE_CALLINFO_n(n, args)  JS_DEFINE_CALLINFO_##n args
 
 jsdouble FASTCALL
 js_StringToNumber(JSContext* cx, JSString* str);
 
 /* Extern version of SetBuiltinError. */
 extern JS_FRIEND_API(void)
@@ -567,22 +568,21 @@ js_dmod(jsdouble a, jsdouble b);
 #define JS_DEFINE_TRCINFO_1(name, tn0)
 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
 
 #endif /* !JS_TRACER */
 
 /* Defined in jsarray.cpp. */
-JS_DECLARE_CALLINFO(js_Array_dense_setelem)
-JS_DECLARE_CALLINFO(js_Array_dense_setelem_int)
-JS_DECLARE_CALLINFO(js_Array_dense_setelem_double)
+JS_DECLARE_CALLINFO(js_Array_dense_setelem_hole)
 JS_DECLARE_CALLINFO(js_NewEmptyArray)
 JS_DECLARE_CALLINFO(js_NewPreallocatedArray)
 JS_DECLARE_CALLINFO(js_ArrayCompPush_tn)
+JS_DECLARE_CALLINFO(js_EnsureDenseArrayCapacity)
 
 /* Defined in jsbuiltins.cpp. */
 JS_DECLARE_CALLINFO(js_UnboxDouble)
 JS_DECLARE_CALLINFO(js_UnboxInt32)
 JS_DECLARE_CALLINFO(js_dmod)
 JS_DECLARE_CALLINFO(js_imod)
 JS_DECLARE_CALLINFO(js_DoubleToInt32)
 JS_DECLARE_CALLINFO(js_DoubleToUint32)
@@ -590,34 +590,33 @@ JS_DECLARE_CALLINFO(js_StringToNumber)
 JS_DECLARE_CALLINFO(js_StringToInt32)
 JS_DECLARE_CALLINFO(js_AddProperty)
 JS_DECLARE_CALLINFO(js_AddAtomProperty)
 JS_DECLARE_CALLINFO(js_HasNamedProperty)
 JS_DECLARE_CALLINFO(js_HasNamedPropertyInt32)
 JS_DECLARE_CALLINFO(js_TypeOfObject)
 JS_DECLARE_CALLINFO(js_BooleanIntToString)
 JS_DECLARE_CALLINFO(js_New