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 id15660
push userrsayre@mozilla.com
push dateSat, 11 Sep 2010 19:16:24 +0000
treeherdermozilla-central@f1bd314e64ac [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarewefastyet
milestone2.0b6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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, t