Bug 581263 - remove slow natives (r=waldo,mrbkap)
authorLuke Wagner <lw@mozilla.com>
Mon, 16 Aug 2010 12:35:04 -0700
changeset 53557 66c8ad02543b3dc3a10ab329258dceac96095cb2
parent 53556 d008c236ac465199be2678624298f507dda44d38
child 53558 24749e6ae6e941c01a5739d54ae6230892ee2893
push idunknown
push userunknown
push dateunknown
reviewerswaldo, mrbkap
bugs581263
milestone2.0b5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 581263 - remove slow natives (r=waldo,mrbkap)
caps/src/nsSecurityManagerFactory.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsJSEnvironment.cpp
dom/src/threads/nsDOMWorker.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/ipc/ObjectWrapperParent.cpp
js/ipc/ObjectWrapperParent.h
js/jetpack/Handle.h
js/jetpack/JetpackChild.cpp
js/jsd/idl/jsdIDebuggerService.idl
js/jsd/jsd.h
js/jsd/jsd_obj.c
js/jsd/jsd_stak.c
js/jsd/jsd_xpc.cpp
js/jsd/jsdebug.c
js/jsd/jsdebug.h
js/src/ctypes/CTypes.cpp
js/src/ctypes/Library.cpp
js/src/jsapi-tests/testClassGetter.cpp
js/src/jsapi-tests/testContexts.cpp
js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
js/src/jsapi-tests/testNewObject.cpp
js/src/jsapi-tests/testOps.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsbool.cpp
js/src/jsbuiltins.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jsdate.cpp
js/src/jsdbgapi.cpp
js/src/jsdbgapi.h
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsiter.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsprobes.cpp
js/src/jsproxy.cpp
js/src/jsprvtd.h
js/src/jspubtd.h
js/src/jsregexp.cpp
js/src/jsscopeinlines.h
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jsval.h
js/src/jsvalue.h
js/src/jsxml.cpp
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/MonoIC.h
js/src/methodjit/StubCalls.cpp
js/src/perf/jsperf.cpp
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/tests/js1_8_1/trace/trace-test.js
js/src/trace-test/tests/basic/testSlowNativeBail.js
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/shell/xpcshell.cpp
js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
js/src/xpconnect/src/XPCCrossOriginWrapper.cpp
js/src/xpconnect/src/XPCNativeWrapper.cpp
js/src/xpconnect/src/XPCSafeJSObjectWrapper.cpp
js/src/xpconnect/src/XPCSystemOnlyWrapper.cpp
js/src/xpconnect/src/XPCWrapper.cpp
js/src/xpconnect/src/XPCWrapper.h
js/src/xpconnect/src/xpccomponents.cpp
js/src/xpconnect/src/xpcdebug.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcquickstubs.cpp
js/src/xpconnect/src/xpcquickstubs.h
js/src/xpconnect/src/xpcstack.cpp
js/src/xpconnect/src/xpcwrappedjsclass.cpp
js/src/xpconnect/src/xpcwrappednativejsops.cpp
js/src/xpconnect/tests/TestXPC.cpp
modules/plugin/base/src/nsJSNPRuntime.cpp
services/sync/tests/unit/test_utils_stackTrace.js
storage/src/mozStorageStatementJSHelper.cpp
--- 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/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -6522,20 +6522,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,
@@ -8718,26 +8721,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;
   }
@@ -8780,17 +8787,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 = {
@@ -9056,53 +9063,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);
@@ -3156,126 +3156,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>
 
@@ -3348,21 +3353,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/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -69,122 +69,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);
@@ -192,55 +181,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;
   }
 
@@ -251,18 +237,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) {
@@ -292,26 +279,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) {
@@ -334,54 +325,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) {
@@ -406,32 +398,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,
@@ -455,36 +448,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!");
--- 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/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;
@@ -5048,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);
 
@@ -5568,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);
@@ -5603,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]) ||
@@ -5646,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);
@@ -5739,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)) {
@@ -5834,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;
@@ -5872,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.
@@ -5901,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);
@@ -6057,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);
@@ -6226,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/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/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/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.cpp
+++ b/js/src/jsapi.cpp
@@ -2924,16 +2924,25 @@ 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);
 
     /* Nothing to do if obj is already sealed. */
     if (obj->sealed())
@@ -4143,24 +4152,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()) {
         /*
@@ -4188,72 +4197,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);
@@ -4270,40 +4230,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)
 {
@@ -4766,46 +4720,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);
@@ -4888,22 +4842,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();
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -479,32 +479,32 @@ extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
                                            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 */
 
 /*
@@ -1073,19 +1073,21 @@ 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);
@@ -1660,17 +1662,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 */
 
@@ -1793,48 +1794,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
@@ -2581,19 +2567,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.
@@ -3059,16 +3042,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
@@ -1003,18 +1003,17 @@ array_trace(JSTracer *trc, JSObject *obj
         static_cast<GCMarker *>(trc)->arraysToSlowify.append(obj);
     }
 }
 
 Class js_ArrayClass = {
     "Array",
     Class::NON_NATIVE |
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::DENSE_ARRAY_CLASS_RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     js_TryValueOf,
     array_finalize,
@@ -1040,18 +1039,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
 };
@@ -2905,21 +2903,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),
@@ -3033,17 +3031,17 @@ 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.
      */
--- 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;
 
--- 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)
@@ -501,50 +502,50 @@ struct ClosureVarInfo;
         _JS_CTYPE_ACH(at3) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at0),              \
     _JS_CTYPE_FLAGS(rt)
 
 #define JS_DEFINE_TRCINFO_1(name, tn0)                                                            \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1)                                                       \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)                                                  \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     _JS_DEFINE_CALLINFO_n tn2                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn2 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)                                             \
     _JS_DEFINE_CALLINFO_n tn0                                                                     \
     _JS_DEFINE_CALLINFO_n tn1                                                                     \
     _JS_DEFINE_CALLINFO_n tn2                                                                     \
     _JS_DEFINE_CALLINFO_n tn3                                                                     \
     JSSpecializedNative name##_sns[] = {                                                          \
         { _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE },                                                 \
         { _JS_TN_INIT_HELPER_n tn3 }                                                              \
     };                                                                                            \
-    JSNativeTraceInfo name##_trcinfo = { (JSFastNative)name, name##_sns };
+    JSNativeTraceInfo name##_trcinfo = { JS_VALUEIFY_NATIVE(name), name##_sns };
 
 #define _JS_DEFINE_CALLINFO_n(n, args)  JS_DEFINE_CALLINFO_##n args
 
 jsdouble FASTCALL
 js_StringToNumber(JSContext* cx, JSString* str);
 
 /* Extern version of SetBuiltinError. */
 extern JS_FRIEND_API(void)
@@ -606,17 +607,17 @@ JS_DECLARE_CALLINFO(js_CloneFunctionObje
 JS_DECLARE_CALLINFO(js_CreateCallObjectOnTrace)
 JS_DECLARE_CALLINFO(js_Arguments)
 
 /* Defined in jsnum.cpp. */
 JS_DECLARE_CALLINFO(js_NumberToString)
 
 /* Defined in jsobj.cpp. */
 JS_DECLARE_CALLINFO(js_Object_tn)
-JS_DECLARE_CALLINFO(js_NewInstance)
+JS_DECLARE_CALLINFO(js_NewInstanceFromTrace)
 JS_DECLARE_CALLINFO(js_NonEmptyObject)
 
 /* Defined in jsregexp.cpp. */
 JS_DECLARE_CALLINFO(js_CloneRegExpObject)
 
 /* Defined in jsstr.cpp. */
 JS_DECLARE_CALLINFO(js_String_tn)
 JS_DECLARE_CALLINFO(js_CompareStrings)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -336,47 +336,16 @@ FrameGuard::~FrameGuard()
 {
     if (!pushed())
         return;
     JS_ASSERT(cx->activeSegment() == seg);
     JS_ASSERT(cx->maybefp() == fp);
     cx->stack().popFrame(cx);
 }
 
-JS_REQUIRES_STACK void
-StackSpace::getSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *&seg, JSStackFrame *&fp)
-{
-    Value *start = firstUnused();
-    JS_ASSERT(size_t(end - start) >= VALUES_PER_STACK_SEGMENT + VALUES_PER_STACK_FRAME);
-    seg = new(start) StackSegment;
-    fp = reinterpret_cast<JSStackFrame *>(seg + 1);
-}
-
-JS_REQUIRES_STACK void
-StackSpace::pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSFrameRegs &regs)
-{
-    JS_ASSERT(!regs.fp->hasScript() && FUN_SLOW_NATIVE(regs.fp->getFunction()));
-    regs.fp->down = cx->maybefp();
-    seg->setPreviousInMemory(currentSegment);
-    currentSegment = seg;
-    cx->pushSegmentAndFrame(seg, regs);
-    seg->setInitialVarObj(NULL);
-}
-
-JS_REQUIRES_STACK void
-StackSpace::popSynthesizedSlowNativeFrame(JSContext *cx)
-{
-    JS_ASSERT(isCurrentAndActive(cx));
-    JS_ASSERT(cx->hasActiveSegment());
-    JS_ASSERT(currentSegment->getInitialFrame() == cx->fp());
-    JS_ASSERT(!cx->fp()->hasScript() && FUN_SLOW_NATIVE(cx->fp()->getFunction()));
-    cx->popSegmentAndFrame();
-    currentSegment = currentSegment->getPreviousInMemory();
-}
-
 JS_REQUIRES_STACK bool
 StackSpace::pushDummyFrame(JSContext *cx, FrameGuard &fg, JSFrameRegs &regs, JSObject *scopeChain)
 {
     if (!getExecuteFrame(cx, cx->maybefp(), 0, 0, fg))
         return false;
 
     JSStackFrame *fp = fg.getFrame();
     PodZero(fp);
@@ -1942,22 +1911,20 @@ js_TriggerAllOperationCallbacks(JSRuntim
         i.threadData()->triggerOperationCallback();
 }
 
 JSStackFrame *
 js_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
 {
     if (!fp)
         fp = js_GetTopStackFrame(cx);
-    while (fp) {
-        if (fp->hasScript())
-            return fp;
+    while (fp && fp->isDummyFrame())
         fp = fp->down;
-    }
-    return NULL;
+    JS_ASSERT_IF(fp, fp->hasScript());
+    return fp;
 }
 
 jsbytecode*
 js_GetCurrentBytecodePC(JSContext* cx)
 {
     jsbytecode *pc, *imacpc;
 
 #ifdef JS_TRACER
@@ -2190,30 +2157,16 @@ JSContext::checkMallocGCPressure(void *p
              * their manipulation is not thread-safe.
              */
             JS_THREAD_DATA(this)->gcFreeLists.purge();
             js_TriggerGC(this, true);
         }
     }
 }
 
-bool
-JSContext::isConstructing()
-{
-#ifdef JS_TRACER
-    if (JS_ON_TRACE(this)) {
-        JS_ASSERT(bailExit);
-        return *bailExit->pc == JSOP_NEW;
-    }
-#endif
-    JSStackFrame *fp = js_GetTopStackFrame(this);
-    return fp && (fp->flags & JSFRAME_CONSTRUCTING);
-}
-
-
 /*
  * Release pool's arenas if the stackPool has existed for longer than the
  * limit specified by gcEmptyArenaPoolLifespan.
  */
 inline void
 FreeOldArenas(JSRuntime *rt, JSArenaPool *pool)
 {
     JSArena *a = pool->current;
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -805,29 +805,16 @@ class StackSpace
     JS_REQUIRES_STACK
     inline void pushInlineFrame(JSContext *cx, JSStackFrame *fp, jsbytecode *pc,
                                 JSStackFrame *newfp);
 
     JS_REQUIRES_STACK
     inline void popInlineFrame(JSContext *cx, JSStackFrame *up, JSStackFrame *down);
 
     /*
-     * For the special case of the slow native stack frame pushed and popped by
-     * tracing deep bail logic.
-     */
-    JS_REQUIRES_STACK
-    void getSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *&seg, JSStackFrame *&fp);
-
-    JS_REQUIRES_STACK
-    void pushSynthesizedSlowNativeFrame(JSContext *cx, StackSegment *seg, JSFrameRegs &regs);
-
-    JS_REQUIRES_STACK
-    void popSynthesizedSlowNativeFrame(JSContext *cx);
-
-    /*
      * For pushing a bookkeeping frame.
      */
     JS_REQUIRES_STACK
     bool pushDummyFrame(JSContext *cx, FrameGuard &fg, JSFrameRegs &regs, JSObject *scopeChain);
 
     /*
      * Ensure space based on an over-recursion limit.
      */
@@ -2356,18 +2343,16 @@ struct JSContext
 #undef CREATE_BODY
 
     template <class T>
     JS_ALWAYS_INLINE void destroy(T *p) {
         p->~T();
         this->free(p);
     }
 
-    bool isConstructing();
-
     void purge();
 
     js::StackSpace &stack() const {
         return JS_THREAD_DATA(this)->stackSpace;
     }
 
 #ifdef DEBUG
     void assertValidStackDepth(uintN depth) {
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -599,47 +599,63 @@ assertSameCompartment(JSContext *cx, T1 
     c.check(t3);
     c.check(t4);
     c.check(t5);
 #endif
 }
 
 #undef START_ASSERT_SAME_COMPARTMENT
 
-inline JSBool
-CallJSNative(JSContext *cx, js::Native native, JSObject *thisobj, uintN argc, js::Value *argv, js::Value *rval)
+JS_ALWAYS_INLINE bool
+CallJSNative(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
 {
-    assertSameCompartment(cx, thisobj, ValueArray(argv, argc));
-    JSBool ok = native(cx, thisobj, argc, argv, rval);
-    if (ok)
-        assertSameCompartment(cx, *rval);
+#ifdef DEBUG
+    JSBool alreadyThrowing = cx->throwing;
+#endif
+    assertSameCompartment(cx, ValueArray(vp, argc + 2));
+    JSBool ok = native(cx, argc, vp);
+    if (ok) {
+        assertSameCompartment(cx, vp[0]);
+        JS_ASSERT_IF(!alreadyThrowing, !cx->throwing);
+    }
     return ok;
 }
 
-inline JSBool
-CallJSFastNative(JSContext *cx, js::FastNative native, uintN argc, js::Value *vp)
+JS_ALWAYS_INLINE bool
+CallJSNativeConstructor(JSContext *cx, js::Native native, uintN argc, js::Value *vp)
 {
-    assertSameCompartment(cx, ValueArray(vp, argc + 2));
-    JSBool ok = native(cx, argc, vp);
-    if (ok)
-        assertSameCompartment(cx, vp[0]);
-    return ok;
+#ifdef DEBUG
+    JSObject *callee = &vp[0].toObject();
+#endif
+
+    JS_ASSERT(vp[1].isMagic());
+    if (!CallJSNative(cx, native, argc, vp))
+        return false;
+    JS_ASSERT(!vp->isPrimitive());
+
+    /* 
+     * Even though its technically legal, if a native constructor returns the
+     * callee, there is a 99.9999% chance it is a bug. If any valid code
+     * actually wants the constructor to return the callee, this can be removed.
+     */
+    JS_ASSERT(callee != &vp[0].toObject());
+    return true;
 }
 
-inline JSBool
+JS_ALWAYS_INLINE bool
 CallJSPropertyOp(JSContext *cx, js::PropertyOp op, JSObject *obj, jsid id, js::Value *vp)
 {
     assertSameCompartment(cx, obj, id, *vp);
     JSBool ok = op(cx, obj, id, vp);
     if (ok)
         assertSameCompartment(cx, obj, *vp);
     return ok;
 }
 
-inline JSBool
+JS_ALWAYS_INLINE bool
 CallJSPropertyOpSetter(JSContext *cx, js::PropertyOp op, JSObject *obj, jsid id, js::Value *vp)
 {
     assertSameCompartment(cx, obj, id, *vp);
     return op(cx, obj, id, vp);
 }
 
 }  /* namespace js */
 
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -492,18 +492,17 @@ msFromTime(jsdouble t)
 
 /*
  * Other Support routines and definitions
  */
 
 Class js_DateClass = {
     js_Date_str,
     JSCLASS_HAS_RESERVED_SLOTS(JSObject::DATE_CLASS_RESERVED_SLOTS) |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Date) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
@@ -2474,67 +2473,69 @@ static JSFunctionSpec date_methods[] = {
     JS_FN(js_valueOf_str,        date_valueOf,            0,0),
     JS_FS_END
 };
 
 JSBool
 js_Date(JSContext *cx, uintN argc, Value *vp)
 {
     /* Date called as function. */
-    if (!vp[1].isMagic(JS_FAST_CONSTRUCTOR))
+    if (!IsConstructing(vp))
         return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, vp);
 
+    Value *argv = vp + 2;
+
     /* Date called as constructor. */
     jsdouble d;
     if (argc == 0) {
         d = NowAsMillis();
     } else if (argc == 1) {
-        if (!vp[2].isString()) {
+        if (!argv[0].isString()) {
             /* the argument is a millisecond number */
-            if (!ValueToNumber(cx, vp[2], &d))
-                return JS_FALSE;
+            if (!ValueToNumber(cx, argv[0], &d))
+                return false;
             d = TIMECLIP(d);
         } else {
             /* the argument is a string; parse it. */
-            JSString *str = js_ValueToString(cx, vp[2]);
+            JSString *str = js_ValueToString(cx, argv[0]);
             if (!str)
-                return JS_FALSE;
-            vp[2].setString(str);
+                return false;
+            argv[0].setString(str);
 
             if (!date_parseString(str, &d, cx))
                 d = js_NaN;
             else
                 d = TIMECLIP(d);
         }
     } else {
         jsdouble msec_time;
-        if (!date_msecFromArgs(cx, argc, vp + 2, &msec_time))
-            return JS_FALSE;
+        if (!date_msecFromArgs(cx, argc, argv, &msec_time))
+            return false;
 
         if (JSDOUBLE_IS_FINITE(msec_time)) {
             msec_time = UTC(msec_time, cx);
             msec_time = TIMECLIP(msec_time);
         }
         d = msec_time;
     }
 
     JSObject *obj = js_NewDateObjectMsec(cx, d);
     if (!obj)
-        return JS_FALSE;
+        return false;
     vp->setObject(*obj);
 
-    return JS_TRUE;
+    return true;
 }
 
 JSObject *
 js_InitDateClass(JSContext *cx, JSObject *obj)
 {
     /* set static LocalTZA */
     LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, (Native) js_Date, MAXARGS,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
                                    NULL, date_methods, NULL, date_static_methods);
     if (!proto)
         return NULL;
 
     AutoObjectRooter tvr(cx, proto);
 
     SetDateToNaN(cx, proto);
 
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -88,25 +88,27 @@ typedef struct JSTrap {
 #define DBG_LOCK_EVAL(rt,expr)  (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
 
 JS_PUBLIC_API(JSBool)
 JS_GetDebugMode(JSContext *cx)
 {
     return cx->compartment->debugMode;
 }
 
+#ifdef JS_METHODJIT
 static bool
 IsScriptLive(JSContext *cx, JSScript *script)
 {
     for (AllFramesIter i(cx); !i.done(); ++i) {
         if (i.fp()->maybeScript() == script)
             return true;
     }
     return false;
 }
+#endif
 
 JS_FRIEND_API(JSBool)
 js_SetDebugMode(JSContext *cx, JSBool debug)
 {
     cx->compartment->debugMode = debug;
 #ifdef JS_METHODJIT
     for (JSScript *script = (JSScript *)cx->compartment->scripts.next;
          &script->links != &cx->compartment->scripts;
@@ -132,17 +134,17 @@ js_SetDebugMode(JSContext *cx, JSBool de
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebugMode(JSContext *cx, JSBool debug)
 {
 #ifdef DEBUG
     for (AllFramesIter i(cx); !i.done(); ++i)
-        JS_ASSERT(JS_IsNativeFrame(cx, i.fp()));
+        JS_ASSERT(!JS_IsScriptFrame(cx, i.fp()));
 #endif
 
     return js_SetDebugMode(cx, debug);
 }
 
 static JSBool
 CheckDebugMode(JSContext *cx)
 {
@@ -693,54 +695,54 @@ js_watch_set(JSContext *cx, JSObject *ob
             }
 
             /*
              * Pass the output of the handler to the setter. Security wrappers
              * prevent any funny business between watchpoints and setters.
              */
             JSBool ok = !wp->setter ||
                         (shape->hasSetterValue()
-                         ? InternalCall(cx, obj,
-                                        ObjectValue(*CastAsObject(wp->setter)),
-                                        1, vp, vp)
+                         ? ExternalInvoke(cx, obj,
+                                          ObjectValue(*CastAsObject(wp->setter)),
+                                          1, vp, vp)
                          : CallJSPropertyOpSetter(cx, wp->setter, obj, userid, vp));
 
             DBG_LOCK(rt);
             return DropWatchPointAndUnlock(cx, wp, JSWP_HELD) && ok;
         }
     }
     DBG_UNLOCK(rt);
     return JS_TRUE;
 }
 
 JSBool
-js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
-                     Value *rval)
+js_watch_set_wrapper(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *funobj;
-    JSFunction *wrapper;
-    jsid userid;
+    JSObject *obj = ComputeThisFromVp(cx, vp);
+    if (!obj)
+        return false;
 
-    funobj = &argv[-2].toObject();
-    wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
-    userid = ATOM_TO_JSID(wrapper->atom);
-    *rval = argv[0];
-    return js_watch_set(cx, obj, userid, rval);
+    JSObject &funobj = JS_CALLEE(cx, vp).toObject();
+    JSFunction *wrapper = funobj.getFunctionPrivate();
+    jsid userid = ATOM_TO_JSID(wrapper->atom);
+
+    JS_SET_RVAL(cx, vp, argc ? JS_ARGV(cx, vp)[0] : UndefinedValue());
+    return js_watch_set(cx, obj, userid, vp);
 }
 
 static bool
 IsWatchedProperty(JSContext *cx, const Shape &shape)
 {
     if (shape.hasSetterValue()) {
         JSObject *funobj = shape.setterObject();
         if (!funobj || !funobj->isFunction())
             return false;
 
         JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
-        return FUN_NATIVE(fun) == js_watch_set_wrapper;
+        return fun->maybeNative() == js_watch_set_wrapper;
     }
     return shape.setterOp() == js_watch_set;
 }
 
 PropertyOp
 js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, PropertyOp setter)
 {
     JSAtom *atom;
@@ -1053,23 +1055,17 @@ JS_PUBLIC_API(JSScript *)
 JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
 {
     return FUN_SCRIPT(fun);
 }
 
 JS_PUBLIC_API(JSNative)
 JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
 {
-    return Jsvalify(FUN_NATIVE(fun));
-}
-
-JS_PUBLIC_API(JSFastNative)
-JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
-{
-    return Jsvalify(FUN_FAST_NATIVE(fun));
+    return Jsvalify(fun->maybeNative());
 }
 
 JS_PUBLIC_API(JSPrincipals *)
 JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
 {
     return script->principals;
 }
 
@@ -1098,18 +1094,18 @@ JS_GetFramePC(JSContext *cx, JSStackFram
 }
 
 JS_PUBLIC_API(JSStackFrame *)
 JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
 {
     return js_GetScriptedCaller(cx, fp);
 }
 
-JS_PUBLIC_API(JSPrincipals *)
-JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
+JSPrincipals *
+js_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
 {
     JSSecurityCallbacks *callbacks;
 
     if (fp->hasFunction()) {
         callbacks = JS_GetSecurityCallbacks(cx);
         if (callbacks && callbacks->findObjectPrincipals) {
             if (FUN_OBJECT(fp->getFunction()) != fp->callee())
                 return callbacks->findObjectPrincipals(cx, fp->callee());
@@ -1129,34 +1125,28 @@ js_EvalFramePrincipals(JSContext *cx, JS
 
     callbacks = JS_GetSecurityCallbacks(cx);
     if (callbacks && callbacks->findObjectPrincipals)
         principals = callbacks->findObjectPrincipals(cx, callee);
     else
         principals = NULL;
     if (!caller)
         return principals;
-    callerPrincipals = JS_StackFramePrincipals(cx, caller);
+    callerPrincipals = js_StackFramePrincipals(cx, caller);
     return (callerPrincipals && principals &&
             callerPrincipals->subsume(callerPrincipals, principals))
            ? principals
            : callerPrincipals;
 }
 
-JS_PUBLIC_API(JSPrincipals *)
-JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
-{
-    return js_EvalFramePrincipals(cx, fp->callee(), caller);
-}
-
 JS_PUBLIC_API(void *)
 JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
 {
     if (fp->hasAnnotation() && fp->hasScript()) {
-        JSPrincipals *principals = JS_StackFramePrincipals(cx, fp);
+        JSPrincipals *principals = js_StackFramePrincipals(cx, fp);
 
         if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
             /*
              * Give out an annotation only if privileges have not been revoked
              * or disabled globally.
              */
             return fp->getAnnotation();
         }
@@ -1171,26 +1161,26 @@ JS_SetFrameAnnotation(JSContext *cx, JSS
     fp->setAnnotation(annotation);
 }
 
 JS_PUBLIC_API(void *)
 JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
 {
     JSPrincipals *principals;
 
-    principals = JS_StackFramePrincipals(cx, fp);
+    principals = js_StackFramePrincipals(cx, fp);
     if (!principals)
         return NULL;
     return principals->getPrincipalArray(cx, principals);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
+JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp)
 {
-    return !fp->hasScript();
+    return !fp->isDummyFrame();
 }
 
 /* this is deprecated, use JS_GetFrameScopeChain instead */
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
 {
     return fp->maybeScopeChain();
 }
@@ -1351,17 +1341,17 @@ JS_EvaluateUCInStackFrame(JSContext *cx,
         return false;
 
     /*
      * NB: This function breaks the assumption that the compiler can see all
      * calls and properly compute a static level. In order to get around this,
      * we use a static level that will cause us not to attempt to optimize
      * variable references made by this frame.
      */
-    JSScript *script = Compiler::compileScript(cx, scobj, fp, JS_StackFramePrincipals(cx, fp),
+    JSScript *script = Compiler::compileScript(cx, scobj, fp, js_StackFramePrincipals(cx, fp),
                                                TCF_COMPILE_N_GO, chars, length, NULL,
                                                filename, lineno, NULL,
                                                UpvarCookie::UPVAR_LEVEL_LIMIT);
 
     if (!script)
         return false;
 
     bool ok = !!Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL, Valueify(rval));
@@ -1871,104 +1861,105 @@ JS_DisconnectShark()
 {
     if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess))
         return JS_FALSE;
 
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_StartShark(JSContext *cx, JSObject *obj,
-              uintN argc, jsval *argv, jsval *rval)
+js_StartShark(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!JS_StartChudRemote()) {
         JS_ReportError(cx, "Error starting CHUD.");
         return JS_FALSE;
     }
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_StopShark(JSContext *cx, JSObject *obj,
-             uintN argc, jsval *argv, jsval *rval)
+js_StopShark(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!JS_StopChudRemote()) {
         JS_ReportError(cx, "Error stopping CHUD.");
         return JS_FALSE;
     }
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_ConnectShark(JSContext *cx, JSObject *obj,
-                uintN argc, jsval *argv, jsval *rval)
+js_ConnectShark(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!JS_ConnectShark()) {
         JS_ReportError(cx, "Error connecting to Shark.");
         return JS_FALSE;
     }
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_DisconnectShark(JSContext *cx, JSObject *obj,
-                   uintN argc, jsval *argv, jsval *rval)
+js_DisconnectShark(JSContext *cx, uintN argc, jsval *vp)
 {
     if (!JS_DisconnectShark()) {
         JS_ReportError(cx, "Error disconnecting from Shark.");
         return JS_FALSE;
     }
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 #endif /* MOZ_SHARK */
 
 #ifdef MOZ_CALLGRIND
 
 #include <valgrind/callgrind.h>
 
 JS_FRIEND_API(JSBool)
-js_StartCallgrind(JSContext *cx, JSObject *obj,
-                  uintN argc, jsval *argv, jsval *rval)
+js_StartCallgrind(JSContext *cx, uintN argc, jsval *vp)
 {
     CALLGRIND_START_INSTRUMENTATION;
     CALLGRIND_ZERO_STATS;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_StopCallgrind(JSContext *cx, JSObject *obj,
-                 uintN argc, jsval *argv, jsval *rval)
+js_StopCallgrind(JSContext *cx, uintN argc, jsval *vp)
 {
     CALLGRIND_STOP_INSTRUMENTATION;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_FRIEND_API(JSBool)
-js_DumpCallgrind(JSContext *cx, JSObject *obj,
-                 uintN argc, jsval *argv, jsval *rval)
+js_DumpCallgrind(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     char *cstr;
 
+    jsval *argv = JS_ARGV(cx, vp);
     if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
         str = JSVAL_TO_STRING(argv[0]);
         cstr = js_DeflateString(cx, str->chars(), str->length());
         if (cstr) {
             CALLGRIND_DUMP_STATS_AT(cstr);
             cx->free(cstr);
             return JS_TRUE;
         }
     }
     CALLGRIND_DUMP_STATS;
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 #endif /* MOZ_CALLGRIND */
 
 #ifdef MOZ_VTUNE
 #include <VTuneApi.h>
 
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -137,18 +137,17 @@ js_SweepWatchPoints(JSContext *cx);
 
 extern const js::Shape *
 js_FindWatchPoint(JSRuntime *rt, JSObject *obj, jsid id);
 
 extern JSBool
 js_watch_set(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
 
 extern JSBool
-js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
-                     js::Value *rval);
+js_watch_set_wrapper(JSContext *cx, uintN argc, js::Value *vp);
 
 extern js::PropertyOp
 js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, js::PropertyOp setter);
 
 #endif
 
 #endif /* JS_HAS_OBJ_WATCHPOINT */
 
@@ -184,19 +183,16 @@ extern JS_PUBLIC_API(void)
 JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
 
 extern JS_PUBLIC_API(JSNative)
 JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
 
-extern JS_PUBLIC_API(JSFastNative)
-JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
-
 extern JS_PUBLIC_API(JSPrincipals *)
 JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
 
 /*
  * Stack Frame Iterator
  *
  * Used to iterate through the JS stack frames to extract
  * information from the frames.
@@ -216,47 +212,33 @@ JS_GetFramePC(JSContext *cx, JSStackFram
  */
 extern JS_PUBLIC_API(JSStackFrame *)
 JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
 
 /*
  * Return a weak reference to fp's principals.  A null return does not denote
  * an error, it means there are no principals.
  */
-extern JS_PUBLIC_API(JSPrincipals *)
-JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
-
-/*
- * This API is like JS_StackFramePrincipals(cx, caller), except that if
- * cx->runtime->findObjectPrincipals is non-null, it returns the weaker of
- * the caller's principals and the object principals of fp's callee function
- * object (fp->argv[-2]), which is eval, Function, or a similar eval-like
- * method.  The caller parameter should be JS_GetScriptedCaller(cx, fp).
- *
- * All eval-like methods must use JS_EvalFramePrincipals to acquire a weak
- * reference to the correct principals for the eval call to be secure, given
- * an embedding that calls JS_SetObjectPrincipalsFinder (see jsapi.h).
- */
-extern JS_PUBLIC_API(JSPrincipals *)
-JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller);
+extern JSPrincipals *
+js_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
 
 JSPrincipals *
 js_EvalFramePrincipals(JSContext *cx, JSObject *callee, JSStackFrame *caller);
 
 extern JS_PUBLIC_API(void *)
 JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
 
 extern JS_PUBLIC_API(void)
 JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
 
 extern JS_PUBLIC_API(void *)
 JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp);
+JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
 
 /* this is deprecated, use JS_GetFrameScopeChain instead */
 extern JS_PUBLIC_API(JSObject *)
 JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
 
@@ -530,46 +512,39 @@ JS_StopChudRemote();
 
 extern JS_PUBLIC_API(JSBool)
 JS_ConnectShark();
 
 extern JS_PUBLIC_API(JSBool)
 JS_DisconnectShark();
 
 extern JS_FRIEND_API(JSBool)
-js_StopShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-             jsval *rval);
+js_StopShark(JSContext *cx, uintN argc, jsval *vp);
 
 extern JS_FRIEND_API(JSBool)
-js_StartShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-              jsval *rval);
+js_StartShark(JSContext *cx, uintN argc, jsval *vp);
 
 extern JS_FRIEND_API(JSBool)
-js_ConnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                jsval *rval);
+js_ConnectShark(JSContext *cx, uintN argc, jsval *vp);
 
 extern JS_FRIEND_API(JSBool)
-js_DisconnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                   jsval *rval);
+js_DisconnectShark(JSContext *cx, uintN argc, jsval *vp);
 
 #endif /* MOZ_SHARK */
 
 #ifdef MOZ_CALLGRIND
 
 extern JS_FRIEND_API(JSBool)
-js_StopCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                 jsval *rval);
+js_StopCallgrind(JSContext *cx, uintN argc, jsval *vp);
 
 extern JS_FRIEND_API(JSBool)
-js_StartCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                  jsval *rval);
+js_StartCallgrind(JSContext *cx, uintN argc, jsval *vp);
 
 extern JS_FRIEND_API(JSBool)
-js_DumpCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                 jsval *rval);
+js_DumpCallgrind(JSContext *cx, uintN argc, jsval *vp);
 
 #endif /* MOZ_CALLGRIND */
 
 #ifdef MOZ_VTUNE
 
 extern JS_FRIEND_API(JSBool)
 js_StartVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
               jsval *rval);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -64,17 +64,17 @@
 
 #include "jscntxtinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 
 /* Forward declarations for js_ErrorClass's initializer. */
 static JSBool
-Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
+Exception(JSContext *cx, uintN argc, Value *vp);
 
 static void
 exn_trace(JSTracer *trc, JSObject *obj);
 
 static void
 exn_finalize(JSContext *cx, JSObject *obj);
 
 static JSBool
@@ -691,50 +691,47 @@ FilenameToString(JSContext *cx, const ch
 
 static const char *
 StringToFilename(JSContext *cx, JSString *str)
 {
     return js_GetStringBytes(cx, str);
 }
 
 static JSBool
-Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+Exception(JSContext *cx, uintN argc, Value *vp)
 {
     JSString *message, *filename;
     JSStackFrame *fp;
 
-    if (!JS_IsConstructing(cx)) {
-        /*
-         * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
-         * called as functions, without operator new.  But as we do not give
-         * each constructor a distinct JSClass, whose .name member is used by
-         * NewNativeClassInstance to find the class prototype, we must get the
-         * class prototype ourselves.
-         */
-        if (!argv[-2].toObject().getProperty(cx,
-                                             ATOM_TO_JSID(cx->runtime->atomState
-                                                          .classPrototypeAtom),
-                                             rval)) {
-            return JS_FALSE;
-        }
-        JSObject *errProto = &rval->toObject();
-        obj = NewNativeClassInstance(cx, &js_ErrorClass, errProto, errProto->getParent());
-        if (!obj)
-            return JS_FALSE;
-        rval->setObject(*obj);
-    }
+    /*
+     * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
+     * called as functions, without operator new.  But as we do not give
+     * each constructor a distinct JSClass, whose .name member is used by
+     * NewNativeClassInstance to find the class prototype, we must get the
+     * class prototype ourselves.
+     */
+    JSObject &callee = vp[0].toObject();
+    Value protov;
+    if (!callee.getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &protov))
+        return JS_FALSE;
+
+    JSObject *errProto = &protov.toObject();
+    JSObject *obj = NewNativeClassInstance(cx, &js_ErrorClass, errProto, errProto->getParent());
+    if (!obj)
+        return JS_FALSE;
 
     /*
      * If it's a new object of class Exception, then null out the private
      * data so that the finalizer doesn't attempt to free it.
      */
     if (obj->getClass() == &js_ErrorClass)
         obj->setPrivate(NULL);
 
     /* Set the 'message' property. */
+    Value *argv = vp + 2;
     if (argc != 0) {
         message = js_ValueToString(cx, argv[0]);
         if (!message)
             return JS_FALSE;
         argv[0].setString(message);
     } else {
         message = cx->runtime->emptyString;
     }
@@ -763,41 +760,46 @@ Exception(JSContext *cx, JSObject *obj, 
         if (!ValueToECMAUint32(cx, argv[2], &lineno))
             return JS_FALSE;
     } else {
         if (!fp)
             fp = js_GetScriptedCaller(cx, NULL);
         lineno = (fp && fp->pc(cx)) ? js_FramePCToLineNumber(cx, fp) : 0;
     }
 
-    return (obj->getClass() != &js_ErrorClass) ||
-            InitExnPrivate(cx, obj, message, filename, lineno, NULL);
+    if (obj->getClass() == &js_ErrorClass &&
+        !InitExnPrivate(cx, obj, message, filename, lineno, NULL)) {
+        return JS_FALSE;
+    }
+
+    vp->setObject(*obj);
+    return JS_TRUE;
 }
 
 /*
  * Convert to string.
  *
  * This method only uses JavaScript-modifiable properties name, message.  It
  * is left to the host to check for private data and report filename and line
  * number information along with this message.
  */
 static JSBool
-exn_toString(JSContext *cx, uintN argc, jsval *vp)
+exn_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
     jsval v;
     JSString *name, *message, *result;
     jschar *chars, *cp;
     size_t name_length, message_length, length;
 
-    obj = JS_THIS_OBJECT(cx, vp);
+    obj = ComputeThisFromVp(cx, vp);
     if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(&v)))
         return JS_FALSE;
     name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
-    *vp = STRING_TO_JSVAL(name);
+    vp->setString(name);
 
     if (!JS_GetProperty(cx, obj, js_message_str, &v))
         return JS_FALSE;
     message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
                                  : cx->runtime->emptyString;
 
     if (message->length() != 0) {
         name_length = name->length();
@@ -820,40 +822,40 @@ exn_toString(JSContext *cx, uintN argc, 
         if (!result) {
             cx->free(chars);
             return JS_FALSE;
         }
     } else {
         result = name;
     }
 
-    *vp = STRING_TO_JSVAL(result);
+    vp->setString(result);
     return JS_TRUE;
 }
 
 #if JS_HAS_TOSOURCE
 /*
  * Return a string that may eval to something similar to the original object.
  */
 static JSBool
-exn_toSource(JSContext *cx, uintN argc, jsval *vp)
+exn_toSource(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
     JSString *name, *message, *filename, *lineno_as_str, *result;
     jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
     size_t lineno_length, name_length, message_length, filename_length, length;
     jschar *chars, *cp;
 
-    obj = JS_THIS_OBJECT(cx, vp);
-    if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(vp)))
+    obj = ComputeThisFromVp(cx, vp);
+    if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp))
         return false;
-    name = js_ValueToString(cx, Valueify(*vp));
+    name = js_ValueToString(cx, *vp);
     if (!name)
         return false;
-    *vp = STRING_TO_JSVAL(name);
+    vp->setString(name);
 
     {
         AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroots), Valueify(localroots));
 
 #ifdef __GNUC__
         message = filename = NULL;
 #endif
         if (!JS_GetProperty(cx, obj, js_message_str, &localroots[0]) ||
@@ -943,17 +945,17 @@ exn_toSource(JSContext *cx, uintN argc, 
 
         *cp++ = ')'; *cp++ = ')'; *cp = 0;
 
         result = js_NewString(cx, chars, length);
         if (!result) {
             cx->free(chars);
             return false;
         }
-        *vp = STRING_TO_JSVAL(result);
+        vp->setString(result);
         return true;
     }
 }
 #endif
 
 static JSFunctionSpec exception_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,   exn_toSource,           0,0),
@@ -1025,17 +1027,17 @@ js_InitExceptionClasses(JSContext *cx, J
         }
 
         /* So exn_finalize knows whether to destroy private data. */
         proto->setPrivate(NULL);
 
         /* Make a constructor function for the current name. */
         JSProtoKey protoKey = GetExceptionProtoKey(i);
         JSAtom *atom = cx->runtime->atomState.classAtoms[protoKey];
-        JSFunction *fun = js_DefineFunction(cx, obj, atom, Exception, 3, 0);
+        JSFunction *fun = js_DefineFunction(cx, obj, atom, Exception, 3, JSFUN_CONSTRUCTOR);
         if (!fun)
             return NULL;
         roots[2] = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
 
         /* Make this constructor make objects of class Exception. */
         FUN_CLASP(fun) = &js_ErrorClass;
 
         /* Make the prototype and constructor links. */
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2157,18 +2157,16 @@ JS_PUBLIC_DATA(Class) js_FunctionClass =
     NULL,           /* checkAccess */
     NULL,           /* call        */
     NULL,           /* construct   */
     js_XDRFunctionObject,
     fun_hasInstance,
     JS_CLASS_TRACE(fun_trace)
 };
 
-namespace js {
-
 JSString *
 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent)
 {
     if (!obj->isFunction()) {
         if (obj->isFunctionProxy())
             return JSProxy::fun_toString(cx, obj, indent);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_INCOMPATIBLE_PROTO,
@@ -2178,18 +2176,16 @@ fun_toStringHelper(JSContext *cx, JSObje
     }
 
     JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
     if (!fun)
         return NULL;
     return JS_DecompileFunction(cx, fun, indent);
 }
 
-}  /* namespace js */
-
 static JSBool
 fun_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JS_ASSERT(IsFunctionObject(vp[0]));
     uint32_t indent = 0;
 
     if (argc != 0 && !ValueToECMAUint32(cx, vp[2], &indent))
         return false;
@@ -2388,30 +2384,25 @@ js_fun_apply(JSContext *cx, uintN argc, 
     /* Step 9. */
     if (!Invoke(cx, args, 0))
         return false;
     *vp = args.rval();
     return true;
 }
 
 namespace {
-Native
-FastNativeToNative(FastNative fn)
-{
-    return reinterpret_cast<Native>(fn);
-}
 
 JSBool
 CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp);
 }
 
 bool
 JSFunction::isBound() const
 {
-    return isFastNative() && u.n.native == FastNativeToNative(CallOrConstructBoundFunction);
+    return isNative() && u.n.native == CallOrConstructBoundFunction;
 }
 
 inline bool
 JSObject::initBoundFunction(JSContext *cx, const Value &thisArg,
                             const Value *args, uintN argslen)
 {
     JS_ASSERT(isFunction());
     JS_ASSERT(getFunctionPrivate()->isBound());
@@ -2475,17 +2466,17 @@ JSBool
 CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj = &vp[0].toObject();
     JS_ASSERT(obj->isFunction());
     JS_ASSERT(obj->getFunctionPrivate()->isBound());
 
     LeaveTrace(cx);
 
-    bool constructing = vp[1].isMagic(JS_FAST_CONSTRUCTOR);
+    bool constructing = IsConstructing(vp);
 
     /* 15.3.4.5.1 step 1, 15.3.4.5.2 step 3. */
     uintN argslen;
     const Value *boundArgs = obj->getBoundFunctionArguments(argslen);
 
     if (argc + argslen > JS_ARGS_LENGTH_MAX) {
         js_ReportAllocationOverflow(cx);
         return false;
@@ -2569,18 +2560,18 @@ fun_bind(JSContext *cx, uintN argc, Valu
             length = nargs - argslen;
     }
 
     /* Step 4-6, 10-11. */
     JSAtom *name = target->isFunction() ? target->getFunctionPrivate()->atom : NULL;
 
     /* NB: Bound functions abuse |parent| to store their target. */
     JSObject *funobj =
-        js_NewFunction(cx, NULL, FastNativeToNative(CallOrConstructBoundFunction), length,
-                       JSFUN_FAST_NATIVE | JSFUN_FAST_NATIVE_CTOR, target, name);
+        js_NewFunction(cx, NULL, CallOrConstructBoundFunction, length,
+                       JSFUN_CONSTRUCTOR, target, name);
     if (!funobj)
         return false;
 
     /* Steps 7-9. */
     Value thisArg = argc >= 1 ? vp[2] : UndefinedValue();
     if (!funobj->initBoundFunction(cx, thisArg, args, argslen))
         return false;
 
@@ -2601,78 +2592,55 @@ static JSFunctionSpec function_methods[]
     JS_FN(js_toString_str,   fun_toString,   0,0),
     JS_FN(js_apply_str,      js_fun_apply,   2,0),
     JS_FN(js_call_str,       js_fun_call,    1,0),
     JS_FN("bind",            fun_bind,       1,0),
     JS_FS_END
 };
 
 static JSBool
-Function(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+Function(JSContext *cx, uintN argc, Value *vp)
 {
-    JSFunction *fun;
-    JSObject *parent;
-    JSStackFrame *fp, *caller;
-    uintN i, n, lineno;
-    JSAtom *atom;
-    const char *filename;
-    JSBool ok;
-    JSString *str, *arg;
-    TokenStream ts(cx);
-    JSPrincipals *principals;
-    jschar *collected_args, *cp;
-    void *mark;
-    size_t arg_length, args_length, old_args_length;
-    TokenKind tt;
-
-    if (!JS_IsConstructing(cx)) {
-        obj = NewFunction(cx, NULL);
-        if (!obj)
-            return JS_FALSE;
-        rval->setObject(*obj);
-    } else {
-        /*
-         * The constructor is called before the private slot is initialized so
-         * we must use getPrivate, not GET_FUNCTION_PRIVATE here.
-         */
-        if (obj->getPrivate())
-            return JS_TRUE;
-    }
+    JSObject *obj = NewFunction(cx, NULL);
+    if (!obj)
+        return JS_FALSE;
+
+    /* N.B. overwriting callee with return value */
+    JSObject *parent = vp[0].toObject().getParent();
+    vp[0].setObject(*obj);
 
     /*
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      *
      * In older versions, before call objects, a new Function was adopted by
      * its running context's globalObject, which might be different from the
      * top-level reachable from scopeChain (in HTML frames, e.g.).
      */
-    parent = argv[-2].toObject().getParent();
-
-    fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
-                         parent, cx->runtime->atomState.anonymousAtom);
-
+    JSFunction *fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
+                                     parent, cx->runtime->atomState.anonymousAtom);
     if (!fun)
         return JS_FALSE;
 
     /*
      * Function is static and not called directly by other functions in this
      * file, therefore it is callable only as a native function by js_Invoke.
      * Find the scripted caller, possibly skipping other native frames such as
      * are built for Function.prototype.call or .apply activations that invoke
      * Function indirectly from a script.
      */
-    fp = js_GetTopStackFrame(cx);
-    JS_ASSERT(!fp->hasScript() && fp->hasFunction() &&
-              fp->getFunction()->u.n.native == Function);
-    caller = js_GetScriptedCaller(cx, fp);
+    JSStackFrame *caller = js_GetScriptedCaller(cx, NULL);
+    uintN lineno;
+    const char *filename;
+    JSPrincipals *principals;
     if (caller) {
-        principals = JS_EvalFramePrincipals(cx, fp, caller);
+        JSObject *callee = &JS_CALLEE(cx, vp).toObject();
+        principals = js_EvalFramePrincipals(cx, callee, caller);
         filename = js_ComputeFilename(cx, caller, principals, &lineno);
     } else {
         filename = NULL;
         lineno = 0;
         principals = NULL;
     }
 
     /* Belt-and-braces: check that the caller has access to parent. */
@@ -2686,121 +2654,124 @@ Function(JSContext *cx, JSObject *obj, u
      * Report errors via CSP is done in the script security manager.
      * js_CheckContentSecurityPolicy is defined in jsobj.cpp
      */
     if (!js_CheckContentSecurityPolicy(cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
         return JS_FALSE;
     }
 
-    n = argc ? argc - 1 : 0;
+    Value *argv = vp + 2;
+    uintN n = argc ? argc - 1 : 0;
     if (n > 0) {
         enum { OK, BAD, BAD_FORMAL } state;
 
         /*
          * Collect the function-argument arguments into one string, separated
          * by commas, then make a tokenstream from that string, and scan it to
          * get the arguments.  We need to throw the full scanner at the
          * problem, because the argument string can legitimately contain
          * comments and linefeeds.  XXX It might be better to concatenate
          * everything up into a function definition and pass it to the
          * compiler, but doing it this way is less of a delta from the old
          * code.  See ECMA 15.3.2.1.
          */
         state = BAD_FORMAL;
-        args_length = 0;
-        for (i = 0; i < n; i++) {
+        size_t args_length = 0;
+        for (uintN i = 0; i < n; i++) {
             /* Collect the lengths for all the function-argument arguments. */
-            arg = js_ValueToString(cx, argv[i]);
+            JSString *arg = js_ValueToString(cx, argv[i]);
             if (!arg)
                 return JS_FALSE;
             argv[i].setString(arg);
 
             /*
              * Check for overflow.  The < test works because the maximum
              * JSString length fits in 2 fewer bits than size_t has.
              */
-            old_args_length = args_length;
+            size_t old_args_length = args_length;
             args_length = old_args_length + arg->length();
             if (args_length < old_args_length) {
                 js_ReportAllocationOverflow(cx);
                 return JS_FALSE;
             }
         }
 
         /* Add 1 for each joining comma and check for overflow (two ways). */
-        old_args_length = args_length;
+        size_t old_args_length = args_length;
         args_length = old_args_length + n - 1;
         if (args_length < old_args_length ||
             args_length >= ~(size_t)0 / sizeof(jschar)) {
             js_ReportAllocationOverflow(cx);
             return JS_FALSE;
         }
 
         /*
          * Allocate a string to hold the concatenated arguments, including room
          * for a terminating 0.  Mark cx->tempPool for later release, to free
          * collected_args and its tokenstream in one swoop.
          */
-        mark = JS_ARENA_MARK(&cx->tempPool);
+        void *mark = JS_ARENA_MARK(&cx->tempPool);
+        jschar *cp;
         JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,
                                (args_length+1) * sizeof(jschar));
         if (!cp) {
             js_ReportOutOfScriptQuota(cx);
             return JS_FALSE;
         }
-        collected_args = cp;
+        jschar *collected_args = cp;
 
         /*
          * Concatenate the arguments into the new string, separated by commas.
          */
-        for (i = 0; i < n; i++) {
-            arg = argv[i].toString();
-            arg_length = arg->length();
+        for (uintN i = 0; i < n; i++) {
+            JSString *arg = argv[i].toString();
+            size_t arg_length = arg->length();
             (void) js_strncpy(cp, arg->chars(), arg_length);
             cp += arg_length;
 
             /* Add separating comma or terminating 0. */
             *cp++ = (i + 1 < n) ? ',' : 0;
         }
 
         /* Initialize a tokenstream that reads from the given string. */
+        TokenStream ts(cx);
         if (!ts.init(collected_args, args_length, NULL, filename, lineno)) {
             JS_ARENA_RELEASE(&cx->tempPool, mark);
             return JS_FALSE;
         }
 
         /* The argument string may be empty or contain no tokens. */
-        tt = ts.getToken();
+        TokenKind tt = ts.getToken();
         if (tt != TOK_EOF) {
             for (;;) {
                 /*
                  * Check that it's a name.  This also implicitly guards against
                  * TOK_ERROR, which was already reported.
                  */
                 if (tt != TOK_NAME)
                     goto after_args;
 
                 /*
                  * Get the atom corresponding to the name from the token
                  * stream; we're assured at this point that it's a valid
                  * identifier.
                  */
-                atom = ts.currentToken().t_atom;
+                JSAtom *atom = ts.currentToken().t_atom;
 
                 /* Check for a duplicate parameter name. */
                 if (fun->lookupLocal(cx, atom, NULL) != JSLOCAL_NONE) {
                     const char *name;
 
                     name = js_AtomToPrintableString(cx, atom);
-                    ok = name && ReportCompileErrorNumber(cx, &ts, NULL,
+                    if (!name && ReportCompileErrorNumber(cx, &ts, NULL,
                                                           JSREPORT_WARNING | JSREPORT_STRICT,
-                                                          JSMSG_DUPLICATE_FORMAL, name);
-                    if (!ok)
+                                                          JSMSG_DUPLICATE_FORMAL, name)) {
                         goto after_args;
+                    }
                 }
                 if (!fun->addLocal(cx, atom, JSLOCAL_ARG))
                     goto after_args;
 
                 /*
                  * Get the next token.  Stop on end of stream.  Otherwise
                  * insist on a comma, get another name, and iterate.
                  */
@@ -2824,16 +2795,17 @@ Function(JSContext *cx, JSObject *obj, u
                                  JSMSG_BAD_FORMAL);
         }
         ts.close();
         JS_ARENA_RELEASE(&cx->tempPool, mark);
         if (state != OK)
             return JS_FALSE;
     }
 
+    JSString *str;
     if (argc) {
         str = js_ValueToString(cx, argv[argc-1]);
         if (!str)
             return JS_FALSE;
         argv[argc-1].setString(str);
     } else {
         str = cx->runtime->emptyString;
     }
@@ -2867,17 +2839,17 @@ js_InitFunctionClass(JSContext *cx, JSOb
     if (!fun)
         return NULL;
     fun->u.i.script = JSScript::emptyScript();
 
     if (obj->getClass()->flags & JSCLASS_IS_GLOBAL) {
         /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
         JSObject *throwTypeError =
             js_NewFunction(cx, NULL, reinterpret_cast<Native>(ThrowTypeError), 0,
-                           JSFUN_FAST_NATIVE, obj, NULL);
+                           0, obj, NULL);
         if (!throwTypeError)
             return NULL;
 
         JS_ALWAYS_TRUE(js_SetReservedSlot(cx, obj, JSRESERVED_GLOBAL_THROWTYPEERROR,
                                           ObjectValue(*throwTypeError)));
     }
 
     return proto;
@@ -2897,30 +2869,27 @@ js_NewFunction(JSContext *cx, JSObject *
         if (!funobj)
             return NULL;
     }
     JS_ASSERT(!funobj->getPrivate());
     fun = (JSFunction *) funobj;
 
     /* Initialize all function members. */
     fun->nargs = uint16(nargs);
-    fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK |
-                          JSFUN_TRCINFO | JSFUN_FAST_NATIVE_CTOR);
+    fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_KINDMASK | JSFUN_TRCINFO);
     if ((flags & JSFUN_KINDMASK) >= JSFUN_INTERPRETED) {
         JS_ASSERT(!native);
         JS_ASSERT(nargs == 0);
         fun->u.i.nvars = 0;
         fun->u.i.nupvars = 0;
         fun->u.i.skipmin = 0;
         fun->u.i.wrapper = false;
         fun->u.i.script = NULL;
         fun->u.i.names = cx->runtime->emptyCallShape;
     } else {
-        fun->u.n.extra = 0;
-        fun->u.n.spare = 0;
         fun->u.n.clasp = NULL;
         if (flags & JSFUN_TRCINFO) {
 #ifdef JS_TRACER
             JSNativeTraceInfo *trcinfo =
                 JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, native);
             fun->u.n.native = (js::Native) trcinfo->native;
             fun->u.n.trcinfo = trcinfo;
 #else
@@ -3044,17 +3013,18 @@ js_DefineFunction(JSContext *cx, JSObjec
          * for more on this.
          */
         attrs &= ~JSFUN_STUB_GSOPS;
         gsop = PropertyStub;
     } else {
         gsop = NULL;
     }
     fun = js_NewFunction(cx, NULL, native, nargs,
-                         attrs & (JSFUN_FLAGS_MASK | JSFUN_TRCINFO), obj, atom);
+                         attrs & (JSFUN_FLAGS_MASK | JSFUN_TRCINFO),
+                         obj, atom);
     if (!fun)
         return NULL;
     if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), ObjectValue(*fun),
                              gsop, gsop, attrs & ~JSFUN_FLAGS_MASK)) {
         return NULL;
     }
     return fun;
 }
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -81,52 +81,33 @@
  * If we need more bits in the future, all flags for FUN_INTERPRETED functions
  * can move to u.i.script->flags. For now we use function flag bits to minimize
  * pointer-chasing.
  */
 #define JSFUN_JOINABLE      0x0001  /* function is null closure that does not
                                        appear to call itself via its own name
                                        or arguments.callee */
 
-#define JSFUN_FAST_NATIVE_CTOR 0x0002 /* JSFastNative directly invokable
-                                       * during construction. */
-
-/*
- * Extra JSCLASS flag indicating the native passed to JS_InitClass is
- * a fast native constructor.  This is internal for now as the 'this' value passed
- * to such a constructor is a magic value, and there is no way to query this
- * in the API.  See bug 581263.
- */
-#define JSCLASS_FAST_CONSTRUCTOR (1<<4)
-
 #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
 #define JSFUN_TRCINFO       0x2000  /* when set, u.n.trcinfo is non-null,
                                        JSFunctionSpec::call points to a
                                        JSNativeTraceInfo. */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.n */
 #define JSFUN_FLAT_CLOSURE  0x8000  /* flag (aka "display") closure */
 #define JSFUN_NULL_CLOSURE  0xc000  /* null closure entrains no scope chain */
 #define JSFUN_KINDMASK      0xc000  /* encode interp vs. native and closure
                                        optimization level -- see above */
 
 #define FUN_OBJECT(fun)      (static_cast<JSObject *>(fun))
 #define FUN_KIND(fun)        ((fun)->flags & JSFUN_KINDMASK)
 #define FUN_SET_KIND(fun,k)  ((fun)->flags = ((fun)->flags & ~JSFUN_KINDMASK) | (k))
 #define FUN_INTERPRETED(fun) (FUN_KIND(fun) >= JSFUN_INTERPRETED)
 #define FUN_FLAT_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_FLAT_CLOSURE)
 #define FUN_NULL_CLOSURE(fun)(FUN_KIND(fun) == JSFUN_NULL_CLOSURE)
-#define FUN_SLOW_NATIVE(fun) (!FUN_INTERPRETED(fun) && !((fun)->flags & JSFUN_FAST_NATIVE))
 #define FUN_SCRIPT(fun)      (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
-#define FUN_NATIVE(fun)      (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
-#define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE)              \
-                              ? (js::FastNative) (fun)->u.n.native            \
-                              : NULL)
-#define FUN_MINARGS(fun)     (((fun)->flags & JSFUN_FAST_NATIVE)              \
-                              ? 0                                             \
-                              : (fun)->nargs)
 #define FUN_CLASP(fun)       (JS_ASSERT(!FUN_INTERPRETED(fun)),               \
                               fun->u.n.clasp)
 #define FUN_TRCINFO(fun)     (JS_ASSERT(!FUN_INTERPRETED(fun)),               \
                               JS_ASSERT((fun)->flags & JSFUN_TRCINFO),        \
                               fun->u.n.trcinfo)
 
 /*
  * Formal parameters, local variables, and upvars are stored in a shape tree
@@ -153,18 +134,16 @@ enum JSLocalKind {
 
 struct JSFunction : public JSObject
 {
     uint16          nargs;        /* maximum number of specified arguments,
                                      reflected as f.length/f.arity */
     uint16          flags;        /* flags, see JSFUN_* below and in jsapi.h */
     union U {
         struct {
-            uint16      extra;    /* number of arg slots for local GC roots */
-            uint16      spare;    /* reserved for future use */
             js::Native  native;   /* native method pointer or null */
             js::Class   *clasp;   /* class of objects constructed
                                      by this function */
             JSNativeTraceInfo *trcinfo;
         } n;
         struct Scripted {
             uint16      nvars;    /* number of local variables */
             uint16      nupvars;  /* number of upvars (computable from script
@@ -182,20 +161,20 @@ struct JSFunction : public JSObject
             js::Shape   *names;   /* argument and variable names */
         } i;
     } u;
     JSAtom          *atom;        /* name for diagnostics and decompiling */
 
     bool optimizedClosure()  const { return FUN_KIND(this) > JSFUN_INTERPRETED; }
     bool needsWrapper()      const { return FUN_NULL_CLOSURE(this) && u.i.skipmin != 0; }
     bool isInterpreted()     const { return FUN_INTERPRETED(this); }
-    bool isFastNative()      const { return !!(flags & JSFUN_FAST_NATIVE); }
-    bool isFastConstructor() const { return !!(flags & JSFUN_FAST_NATIVE_CTOR); }
+    bool isNative()          const { return !FUN_INTERPRETED(this); }
+    bool isConstructor()     const { return flags & JSFUN_CONSTRUCTOR; }
     bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
-    unsigned minArgs()       const { return FUN_MINARGS(this); }
+    unsigned minArgs()       const { return isInterpreted() ? nargs : 0; }
 
     inline bool inStrictMode() const;
 
     bool isBound() const;
 
     uintN countVars() const {
         JS_ASSERT(FUN_INTERPRETED(this));
         return u.i.nvars;
@@ -304,33 +283,37 @@ struct JSFunction : public JSObject
                : NULL;
     }
 
     void setMethodAtom(JSAtom *atom) {
         JS_ASSERT(joinable());
         fslots[METHOD_ATOM_SLOT].setString(ATOM_TO_STRING(atom));
     }
 
+    js::Native maybeNative() const {
+        return isInterpreted() ? NULL : u.n.native;
+    }
+
     /* Number of extra fixed function object slots besides JSSLOT_PRIVATE. */
     static const uint32 CLASS_RESERVED_SLOTS = JSObject::FUN_CLASS_RESERVED_SLOTS;
     static const uint32 FIRST_FREE_SLOT = JSSLOT_PRIVATE + CLASS_RESERVED_SLOTS + 1;
 };
 
 JS_STATIC_ASSERT(sizeof(JSFunction) % JS_GCTHING_ALIGN == 0);
 
 /*
  * Trace-annotated native. This expands to a JSFunctionSpec initializer (like
  * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a
  * JSNativeTraceInfo*.
  */
 #ifdef JS_TRACER
 /* MSVC demands the intermediate (void *) cast here. */
 # define JS_TN(name,fastcall,nargs,flags,trcinfo)                             \
-    JS_FN(name, JS_DATA_TO_FUNC_PTR(JSNative, trcinfo), nargs,                \
-          (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
+    JS_FN(name, JS_DATA_TO_FUNC_PTR(Native, trcinfo), nargs,                  \
+          (flags) | JSFUN_STUB_GSOPS | JSFUN_TRCINFO)
 #else
 # define JS_TN(name,fastcall,nargs,flags,trcinfo)                             \
     JS_FN(name, fastcall, nargs, flags)
 #endif
 
 /*
  * NB: the Arguments classes are uninitialized internal classes that masquerade
  * (according to Object.prototype.toString.call(arguments)) as "Arguments",
@@ -390,16 +373,25 @@ JSObject::isCall() const
 }
 
 inline bool
 JSObject::isFunction() const
 {
     return getClass() == &js_FunctionClass;
 }
 
+inline JSFunction *
+JSObject::getFunctionPrivate() const
+{
+    JS_ASSERT(isFunction());
+    return reinterpret_cast<JSFunction *>(getPrivate());
+}
+
+namespace js {
+
 /*
  * NB: jsapi.h and jsobj.h must be included before any call to this macro.
  */
 #define VALUE_IS_FUNCTION(cx, v)                                              \
     (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction())
 
 static JS_ALWAYS_INLINE bool
 IsFunctionObject(const js::Value &v)
@@ -408,47 +400,89 @@ IsFunctionObject(const js::Value &v)
 }
 
 static JS_ALWAYS_INLINE bool
 IsFunctionObject(const js::Value &v, JSObject **funobj)
 {
     return v.isObject() && (*funobj = &v.toObject())->isFunction();
 }
 
+static JS_ALWAYS_INLINE bool
+IsFunctionObject(const js::Value &v, JSFunction **fun)
+{
+    JSObject *funobj;
+    bool b = IsFunctionObject(v, &funobj);
+    if (b)
+        *fun = funobj->getFunctionPrivate();
+    return b;
+}
+
 /*
  * Macro to access the private slot of the function object after the slot is
  * initialized.
  */
 #define GET_FUNCTION_PRIVATE(cx, funobj)                                      \
     (JS_ASSERT((funobj)->isFunction()),                                       \
      (JSFunction *) (funobj)->getPrivate())
 
-extern JSFunction *
-js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
-               uintN flags, JSObject *parent, JSAtom *atom);
-
-namespace js {
-
 /*
  * Return true if this is a compiler-created internal function accessed by
  * its own object. Such a function object must not be accessible to script
  * or embedding code.
  */
 inline bool
 IsInternalFunctionObject(JSObject *funobj)
 {
     JS_ASSERT(funobj->isFunction());
     JSFunction *fun = (JSFunction *) funobj->getPrivate();
     return funobj == fun && (fun->flags & JSFUN_LAMBDA) && !funobj->getParent();
 }
     
+/* Valueified JS_IsConstructing. */
+static JS_ALWAYS_INLINE bool
+IsConstructing(const Value *vp)
+{
+#ifdef DEBUG
+    JSObject *callee = &JS_CALLEE(cx, vp).toObject();
+    if (callee->isFunction()) {
+        JSFunction *fun = callee->getFunctionPrivate();
+        JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
+    } else {
+        JS_ASSERT(callee->getClass()->construct != NULL);
+    }
+#endif
+    return vp[1].isMagic();
+}
+
+static JS_ALWAYS_INLINE bool
+IsConstructing_PossiblyWithGivenThisObject(const Value *vp, JSObject **ctorThis)
+{
+#ifdef DEBUG
+    JSObject *callee = &JS_CALLEE(cx, vp).toObject();
+    if (callee->isFunction()) {
+        JSFunction *fun = callee->getFunctionPrivate();
+        JS_ASSERT((fun->flags & JSFUN_CONSTRUCTOR) != 0);
+    } else {
+        JS_ASSERT(callee->getClass()->construct != NULL);
+    }
+#endif
+    bool isCtor = vp[1].isMagic();
+    if (isCtor)
+        *ctorThis = vp[1].getMagicObjectOrNullPayload();
+    return isCtor;
+}
+
+} /* namespace js */
+
 extern JSString *
 fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
 
-} /* namespace js */
+extern JSFunction *
+js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
+               uintN flags, JSObject *parent, JSAtom *atom);
 
 extern JSObject *
 js_InitFunctionClass(JSContext *cx, JSObject *obj);
 
 extern JSObject *
 js_InitArgumentsClass(JSContext *cx, JSObject *obj);
 
 extern void
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -463,67 +463,79 @@ RunScript(JSContext *cx, JSScript *scrip
 
     if (status == mjit::Compile_Okay)
         return mjit::JaegerShot(cx);
 #endif
 
     return Interpret(cx, cx->fp());
 }
 
-static JS_REQUIRES_STACK bool
-CallJSNative(JSContext *cx, CallOp callOp, JSObject *thisp, uintN argc, Value *argv, Value *rval)
-{
-    Value *vp = argv - 2;
-    if (CallJSFastNative(cx, callOp, argc, vp)) {
-        *rval = JS_RVAL(cx, vp);
-        return true;
-    }
-    return false;
-}
-
-template <typename T>
-static JS_REQUIRES_STACK bool
-InvokeCommon(JSContext *cx, JSFunction *fun, JSScript *script, T native,
-             const CallArgs &argsRef, uintN flags)
+/*
+ * Find a function reference and its 'this' value implicit first parameter
+ * under argc arguments on cx's stack, and call the function.  Push missing
+ * required arguments, allocate declared local variables, and pop everything
+ * when done.  Then push the return value.
+ */
+JS_REQUIRES_STACK bool
+Invoke(JSContext *cx, const CallArgs &argsRef, uintN flags)
 {
     CallArgs args = argsRef;
-
-    if (native && fun && fun->isFastNative()) {
-#ifdef DEBUG_NOT_THROWING
-        JSBool alreadyThrowing = cx->throwing;
+    JS_ASSERT(args.argc() <= JS_ARGS_LENGTH_MAX);
+
+    if (args.callee().isPrimitive()) {
+        js_ReportIsNotFunction(cx, &args.callee(), flags & JSINVOKE_FUNFLAGS);
+        return false;
+    }
+
+    JSObject *callee = &args.callee().toObject();
+    Class *clasp = callee->getClass();
+
+    /* Invoke non-functions. */
+    if (JS_UNLIKELY(clasp != &js_FunctionClass)) {
+#if JS_HAS_NO_SUCH_METHOD
+        if (JS_UNLIKELY(clasp == &js_NoSuchMethodClass))
+            return NoSuchMethod(cx, args.argc(), args.base(), 0);
 #endif
-        JSBool ok = CallJSFastNative(cx, (FastNative) native, args.argc(), args.base());
-        JS_RUNTIME_METER(cx->runtime, nativeCalls);
-#ifdef DEBUG_NOT_THROWING
-        if (ok && !alreadyThrowing)
-            ASSERT_NOT_THROWING(cx);
-#endif
-        return ok;
-    }
+        JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, !clasp->construct);
+        if (!clasp->call) {
+            js_ReportIsNotFunction(cx, &args.callee(), flags);
+            return false;
+        }
+        return CallJSNative(cx, clasp->call, args.argc(), args.base());
+    }
+
+    /* Invoke native functions. */
+    JSFunction *fun = callee->getFunctionPrivate();
+    JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, !fun->isConstructor());
+    if (fun->isNative()) {
+        JS_ASSERT(args.thisv().isObjectOrNull() || PrimitiveThisTest(fun, args.thisv()));
+        return CallJSNative(cx, fun->u.n.native, args.argc(), args.base());
+    }
+
+    JS_ASSERT(fun->isInterpreted());
+    JSScript *script = fun->u.i.script;
+
+    /* Handle the empty-script special case. */
+    if (JS_UNLIKELY(script->isEmpty())) {
+        if (flags & JSINVOKE_CONSTRUCT) {
+            JS_ASSERT(args.thisv().isObject());
+            args.rval() = args.thisv();
+        } else {
+            args.rval().setUndefined();
+        }
+        return true;
+    }
+
+    JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, args.thisv().isObject());
 
     /* Calculate slot usage. */
-    uintN nmissing;
-    uintN nvars;
-    if (fun) {
-        if (fun->isInterpreted()) {
-            uintN minargs = fun->nargs;
-            nmissing = minargs > args.argc() ? minargs - args.argc() : 0;
-            nvars = fun->u.i.nvars;
-        } else if (fun->isFastNative()) {
-            nvars = nmissing = 0;
-        } else {
-            uintN minargs = fun->nargs;
-            nmissing = (minargs > args.argc() ? minargs - args.argc() : 0) + fun->u.n.extra;
-            nvars = 0;
-        }
-    } else {
-        nvars = nmissing = 0;
-    }
-
-    uintN nfixed = script ? script->nslots : 0;
+    uintN minargs = fun->nargs;
+    uintN nmissing = minargs > args.argc() ? minargs - args.argc() : 0;
+    uintN nvars = fun->u.i.nvars;
+    uintN nfixed = script->nslots;
 
     /*
      * Get a pointer to new frame/slots. This memory is not "claimed", so the
      * code before pushInvokeFrame must not reenter the interpreter.
      */
     InvokeFrameGuard frame;
     if (!cx->stack().getInvokeFrame(cx, args, nmissing, nfixed, frame))
         return false;
@@ -538,55 +550,37 @@ InvokeCommon(JSContext *cx, JSFunction *
     fp->setThisValue(args.thisv());
     fp->setCallObj(NULL);
     fp->setArgsObj(NULL);
     fp->setScript(script);
     fp->setFunction(fun);
     fp->setNumActualArgs(args.argc());
     fp->argv = args.argv();
     fp->setAnnotation(NULL);
-    fp->setScopeChain(NULL);
+    fp->setScopeChain(callee->getParent());
     fp->setBlockChain(NULL);
     fp->flags = flags;
     JS_ASSERT(!fp->hasIMacroPC());
 
     if (flags & JSINVOKE_CONSTRUCT)
         fp->setReturnValue(fp->getThisValue());
     else
         fp->clearReturnValue();
 
     /* Initialize regs. */
     JSFrameRegs &regs = frame.getRegs();
-    if (script) {
-        regs.pc = script->code;
-        regs.sp = fp->slots() + script->nfixed;
-    } else {
-        regs.pc = NULL;
-        regs.sp = fp->slots();
-    }
-
-    /* Officially push |fp|. |frame|'s destructor pops. */
+    regs.pc = script->code;
+    regs.sp = fp->slots() + script->nfixed;
+
+    /* Officially push fp. frame's destructor pops. */
     cx->stack().pushInvokeFrame(cx, args, frame);
 
     /* Now that the frame has been pushed, fix up the scope chain. */
-    JSObject *parent = args.callee().toObject().getParent();
-    if (native) {
-        /* Slow natives and call ops expect the caller's scopeChain as their scopeChain. */
-        if (JSStackFrame *down = fp->down)
-            fp->setScopeChain(down->maybeScopeChain());
-
-        /* Ensure that we have a scope chain. */
-        if (!fp->hasScopeChain())
-            fp->setScopeChain(parent);
-    } else {
-        /* Use parent scope so js_GetCallObject can find the right "Call". */
-        fp->setScopeChain(parent);
-        if (fun->isHeavyweight() && !js_GetCallObject(cx, fp))
-            return false;
-    }
+    if (fun->isHeavyweight() && !js_GetCallObject(cx, fp))
+        return false;
 
     /*
      * Compute |this|. Currently, this must happen after the frame is pushed
      * and fp->scopeChain is correct because the thisObject hook may call
      * JS_GetScopeChain.
      */
     JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, !args.thisv().isPrimitive());
     if (args.thisv().isObject() && !(flags & JSINVOKE_CONSTRUCT)) {
@@ -603,223 +597,76 @@ InvokeCommon(JSContext *cx, JSFunction *
         thisp = thisp->thisObject(cx);
         if (!thisp)
              return false;
         args.thisv().setObject(*thisp);
         fp->setThisValue(ObjectValue(*thisp));
     }
     JS_ASSERT_IF(!args.thisv().isPrimitive(), IsSaneThisObject(args.thisv().toObject()));
 
-    /* Call the hook if present after we fully initialized the frame. */
     JSInterpreterHook hook = cx->debugHooks->callHook;
     void *hookData = NULL;
-    if (hook)
+    if (JS_UNLIKELY(hook != NULL))
         hookData = hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData);
 
-    Probes::enterJSFun(cx, fun);
-
-    /* Call the function, either a native method or an interpreted script. */
     JSBool ok;
-    if (native) {
-#ifdef DEBUG_NOT_THROWING
-        JSBool alreadyThrowing = cx->throwing;
-#endif
-        /* Primitive |this| should not be passed to slow natives. */
-        JSObject *thisp = fun ? fp->getThisObject(cx) : fp->getThisValue().toObjectOrNull();
-        ok = CallJSNative(cx, native, thisp, fp->numActualArgs(), fp->argv,
-		                  fp->addressReturnValue());
-
-        JS_ASSERT(cx->fp() == fp);
-        JS_RUNTIME_METER(cx->runtime, nativeCalls);
-#ifdef DEBUG_NOT_THROWING
-        if (ok && !alreadyThrowing)
-            ASSERT_NOT_THROWING(cx);
-#endif
-    } else {
-        JS_ASSERT(script);
+    {
         AutoPreserveEnumerators preserve(cx);
+        Probes::enterJSFun(cx, fun);
         ok = RunScript(cx, script, fun, fp->getScopeChain());
-    }
-
-    Probes::exitJSFun(cx, fun);
-
-    if (hookData) {
+        Probes::exitJSFun(cx, fun);
+    }
+
+    if (JS_UNLIKELY(hookData != NULL)) {
         hook = cx->debugHooks->callHook;
         if (hook)
             hook(cx, fp, JS_FALSE, &ok, hookData);
     }
 
     fp->putActivationObjects(cx);
+
     args.rval() = fp->getReturnValue();
     return ok;
 }
 
-static JSBool
-DoConstruct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
-{
-
-    Class *clasp = argv[-2].toObject().getClass();
-    if (!clasp->construct) {
-        js_ReportIsNotFunction(cx, &argv[-2], JSV2F_CONSTRUCT);
-        return JS_FALSE;
-    }
-    return clasp->construct(cx, obj, argc, argv, rval);
-}
-
-static JSBool
-DoSlowCall(JSContext *cx, uintN argc, Value *vp)
-{
-    JSStackFrame *fp = cx->fp();
-    JSObject *obj = fp->getThisObject(cx);
-    if (!obj)
-        return false;
-    JS_ASSERT(ObjectValue(*obj) == fp->getThisValue());
-
-    JSObject *callee = &JS_CALLEE(cx, vp).toObject();
-    Class *clasp = callee->getClass();
-    JS_ASSERT(!(clasp->flags & Class::CALL_IS_FAST));
-    if (!clasp->call) {
-        js_ReportIsNotFunction(cx, &vp[0], 0);
-        return JS_FALSE;
-    }
-    AutoValueRooter rval(cx);
-    JSBool ok = clasp->call(cx, obj, argc, JS_ARGV(cx, vp), rval.addr());
-    if (ok)
-        JS_SET_RVAL(cx, vp, rval.value());
-    return ok;
-}
-
-/*
- * Find a function reference and its 'this' value implicit first parameter
- * under argc arguments on cx's stack, and call the function.  Push missing
- * required arguments, allocate declared local variables, and pop everything
- * when done.  Then push the return value.
- */
-JS_REQUIRES_STACK bool
-Invoke(JSContext *cx, const CallArgs &args, uintN flags)
-{
-    JS_ASSERT(args.argc() <= JS_ARGS_LENGTH_MAX);
-
-    if (args.callee().isPrimitive()) {
-        js_ReportIsNotFunction(cx, &args.callee(), flags & JSINVOKE_FUNFLAGS);
-        return false;
-    }
-
-    JSObject *funobj = &args.callee().toObject();
-    Class *clasp = funobj->getClass();
-
-    if (clasp == &js_FunctionClass) {
-        /* Get private data and set derived locals from it. */
-        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
-        Native native;
-        JSScript *script;
-        if (FUN_INTERPRETED(fun)) {
-            native = NULL;
-            script = fun->u.i.script;
-            JS_ASSERT(script);
-
-            if (script->isEmpty()) {
-                if (flags & JSINVOKE_CONSTRUCT) {
-                    JS_ASSERT(args.thisv().isObject());
-                    args.rval() = args.thisv();
-                } else {
-                    args.rval().setUndefined();
-                }
-                return true;
-            }
-        } else {
-            native = fun->u.n.native;
-            script = NULL;
-        }
-
-        if (!args.thisv().isObjectOrNull()) {
-            JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
-            if (PrimitiveThisTest(fun, args.thisv()))
-                return InvokeCommon(cx, fun, script, native, args, flags);
-        }
-
-        if (flags & JSINVOKE_CONSTRUCT) {
-            JS_ASSERT(args.thisv().isObject());
-        } else {
-            /*
-             * We must call js_ComputeThis in case we are not called from the
-             * interpreter, where a prior bytecode has computed an appropriate
-             * |this| already.
-             *
-             * But we need to compute |this| eagerly only for so-called "slow"
-             * (i.e., not fast) native functions. Fast natives must use either
-             * JS_THIS or JS_THIS_OBJECT, and scripted functions will go through
-             * the appropriate this-computing bytecode, e.g., JSOP_THIS.
-             */
-            if (native && (!fun || !(fun->flags & JSFUN_FAST_NATIVE))) {
-                if (!args.computeThis(cx))
-                    return false;
-            }
-        }
-        return InvokeCommon(cx, fun, script, native, args, flags);
-    }
-
-#if JS_HAS_NO_SUCH_METHOD
-    if (clasp == &js_NoSuchMethodClass)
-        return NoSuchMethod(cx, args.argc(), args.base(), flags);
-#endif
-
-    /* Try a call or construct native object op. */
-    if (flags & JSINVOKE_CONSTRUCT) {
-        if (!args.thisv().isObjectOrNull()) {
-            if (!js_PrimitiveToObject(cx, &args.thisv()))
-                return false;
-        }
-        return InvokeCommon(cx, NULL, NULL, DoConstruct, args, flags);
-    }
-    CallOp callOp = (clasp->flags & Class::CALL_IS_FAST) ? (CallOp) clasp->call : DoSlowCall;
-    return InvokeCommon(cx, NULL, NULL, callOp, args, flags);
-}
-
-extern JS_REQUIRES_STACK JS_FRIEND_API(bool)
-InvokeFriendAPI(JSContext *cx, const InvokeArgsGuard &args, uintN flags)
-{
-    return Invoke(cx, args, flags);
-}
-
-JSBool
-InternalInvoke(JSContext *cx, const Value &thisv, const Value &fval, uintN flags,
-                  uintN argc, Value *argv, Value *rval)
+bool
+ExternalInvoke(JSContext *cx, const Value &thisv, const Value &fval,
+               uintN argc, Value *argv, Value *rval)
 {
     LeaveTrace(cx);
 
     InvokeArgsGuard args;
     if (!cx->stack().pushInvokeArgs(cx, argc, args))
         return JS_FALSE;
 
     args.callee() = fval;
     args.thisv() = thisv;
     memcpy(args.argv(), argv, argc * sizeof(Value));
 
-    if (!Invoke(cx, args, flags))
+    if (!Invoke(cx, args, 0))
         return JS_FALSE;
 
     *rval = args.rval();
 
     return JS_TRUE;
 }
 
 bool
-InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
+ExternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
                  JSAccessMode mode, uintN argc, Value *argv, Value *rval)
 {
     LeaveTrace(cx);
 
     /*
-     * InternalInvoke could result in another try to get or set the same id
+     * ExternalInvoke could result in another try to get or set the same id
      * again, see bug 355497.
      */
     JS_CHECK_RECURSION(cx, return JS_FALSE);
 
-    return InternalCall(cx, obj, fval, argc, argv, rval);
+    return ExternalInvoke(cx, obj, fval, argc, argv, rval);
 }
 
 bool
 Execute(JSContext *cx, JSObject *chain, JSScript *script,
         JSStackFrame *down, uintN flags, Value *result)
 {
     if (script->isEmpty()) {
         if (result)
@@ -1180,76 +1027,92 @@ InstanceOfSlow(JSContext *cx, JSObject *
 }
 
 JS_REQUIRES_STACK bool
 InvokeConstructor(JSContext *cx, const CallArgs &argsRef)
 {
     JS_ASSERT(!js_FunctionClass.construct);
     CallArgs args = argsRef;
 
-    JSObject *obj2;
-    if (args.callee().isPrimitive() || !(obj2 = &args.callee().toObject())->getParent()) {
-        /* Use js_ValueToFunction to report an error. */
-        JS_ALWAYS_TRUE(!js_ValueToFunction(cx, &args.callee(), JSV2F_CONSTRUCT));
+    JSObject *callee;
+    if (args.callee().isPrimitive() || !(callee = &args.callee().toObject())->getParent()) {
+        js_ReportIsNotFunction(cx, &args.callee(), JSV2F_CONSTRUCT);
         return false;
     }
 
-    Class *clasp = &js_ObjectClass;
-
-    /*
-     * Call fast constructors without making the object first.
-     * The native will be able to make the right new object faster.
-     */
-    if (obj2->isFunction()) {
-        JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj2);
-        if (fun->isFastConstructor()) {
-            args.thisv().setMagic(JS_FAST_CONSTRUCTOR);
-
-            FastNative fn = (FastNative)fun->u.n.native;
-            if (!fn(cx, args.argc(), args.base()))
-                return JS_FALSE;
-            JS_ASSERT(!args.rval().isPrimitive());
-            return JS_TRUE;
+    /* Handle the fast-constructors cases before falling into the general case . */
+    Class *clasp = callee->getClass();
+    if (clasp == &js_FunctionClass) {
+        JSFunction *fun = callee->getFunctionPrivate();
+        if (fun->isConstructor()) {
+            args.thisv().setMagicWithObjectOrNullPayload(NULL);
+            return CallJSNativeConstructor(cx, fun->u.n.native, args.argc(), args.base());
         }
-
-        /* Get the class, for natives that aren't fast constructors. */
-        if (!fun->isInterpreted() && fun->u.n.clasp)
-            clasp = fun->u.n.clasp;
-    }
-
-    Value protov;
-    if (!obj2->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &protov))
+    } else if (clasp->construct) {
+        args.thisv().setMagicWithObjectOrNullPayload(NULL);
+        return CallJSNativeConstructor(cx, clasp->construct, args.argc(), args.base());
+    }
+
+    /* Construct 'this'. */
+    JSObject *obj = js_NewInstance(cx, callee);
+    if (!obj)
         return false;
-
-    JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : NULL;
-    JSObject *parent = obj2->getParent();
-
-    JSObject* obj = NewObject<WithProto::Class>(cx, clasp, proto, parent);
-    if (!obj)
-        return JS_FALSE;
-
-    /* Now we have an object with a constructor method; call it. */
     args.thisv().setObject(*obj);
+
     if (!Invoke(cx, args, JSINVOKE_CONSTRUCT))
-        return JS_FALSE;
+        return false;
 
     /* Check the return value and if it's primitive, force it to be obj. */
     if (args.rval().isPrimitive()) {
-        if (obj2->getClass() != &js_FunctionClass) {
+        if (callee->getClass() != &js_FunctionClass) {
             /* native [[Construct]] returning primitive is error */
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_BAD_NEW_RESULT,
                                  js_ValueToPrintableString(cx, args.rval()));
-            return JS_FALSE;
+            return false;
         }
         args.rval().setObject(*obj);
     }
 
     JS_RUNTIME_METER(cx->runtime, constructs);
-    return JS_TRUE;
+    return true;
+}
+
+bool
+InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
+                               uintN argc, Value *argv, Value *rval)
+{
+    LeaveTrace(cx);
+
+    InvokeArgsGuard args;
+    if (!cx->stack().pushInvokeArgs(cx, argc, args))
+        return JS_FALSE;
+
+    args.callee() = fval;
+    /* Initialize args.thisv on all paths below. */
+    memcpy(args.argv(), argv, argc * sizeof(Value));
+
+    /* Handle the fast-constructor cases before calling the general case. */
+    JSObject &callee = fval.toObject();
+    Class *clasp = callee.getClass();
+    JSFunction *fun;
+    bool ok;
+    if (clasp == &js_FunctionClass && (fun = callee.getFunctionPrivate())->isConstructor()) {
+        args.thisv().setMagicWithObjectOrNullPayload(thisobj);
+        ok = CallJSNativeConstructor(cx, fun->u.n.native, args.argc(), args.base());
+    } else if (clasp->construct) {
+        args.thisv().setMagicWithObjectOrNullPayload(thisobj);
+        ok = CallJSNativeConstructor(cx, clasp->construct, args.argc(), args.base());
+    } else {
+        args.thisv().setObjectOrNull(thisobj);
+        ok = Invoke(cx, args, JSINVOKE_CONSTRUCT);
+    }
+
+    *rval = args.rval();
+    return ok;
 }
 
 bool
 ValueToId(JSContext *cx, const Value &v, jsid *idp)
 {
     int32_t i;
     if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
         *idp = INT_TO_JSID(i);
@@ -1668,17 +1531,16 @@ namespace reprmeter {
         DOUBLE,
         BOOLEAN_PROPER,
         BOOLEAN_OTHER,
         STRING,
         OBJECT_NULL,
         OBJECT_PLAIN,
         FUNCTION_INTERPRETED,
         FUNCTION_FASTNATIVE,
-        FUNCTION_SLOWNATIVE,
         ARRAY_SLOW,
         ARRAY_DENSE
     };
 
     // Return the |repr| value giving the representation of the given jsval.
     static Repr
     GetRepr(jsval v)
     {
@@ -1696,34 +1558,32 @@ namespace reprmeter {
 
         JS_ASSERT(JSVAL_IS_OBJECT(v));
 
         JSObject *obj = JSVAL_TO_OBJECT(v);
         if (VALUE_IS_FUNCTION(cx, v)) {
             JSFunction *fun = GET_FUNCTION_PRIVATE(cx, obj);
             if (FUN_INTERPRETED(fun))
                 return FUNCTION_INTERPRETED;
-            if (fun->flags & JSFUN_FAST_NATIVE)
-                return FUNCTION_FASTNATIVE;
-            return FUNCTION_SLOWNATIVE;
+            return FUNCTION_FASTNATIVE;
         }
         // This must come before the general array test, because that
         // one subsumes this one.
         if (!obj)
             return OBJECT_NULL;
         if (obj->isDenseArray())
             return ARRAY_DENSE;
         if (obj->isArray())
             return ARRAY_SLOW;
         return OBJECT_PLAIN;
     }
 
     static const char *reprName[] = { "invalid", "int", "double", "bool", "special",
                                       "string", "null", "object",
-                                      "fun:interp", "fun:fast", "fun:slow",
+                                      "fun:interp", "fun:native"
                                       "array:slow", "array:dense" };
 
     // Logically, a tuple of (JSOp, repr_1, ..., repr_n) where repr_i is
     // the |repr| of the ith input to the JSOp.
     struct OpInput {
         enum { max_uses = 16 };
 
         JSOp op;
@@ -1874,30 +1734,16 @@ namespace reprmeter {
 /* Test whether v is an int in the range [-2^31 + 1, 2^31 - 2] */
 static JS_ALWAYS_INLINE bool
 CanIncDecWithoutOverflow(int32_t i)
 {
     return (i > JSVAL_INT_MIN) && (i < JSVAL_INT_MAX);
 }
 
 /*
- * Conditional assert to detect failure to clear a pending exception that is
- * suppressed (or unintentional suppression of a wanted exception).
- */
-#if defined DEBUG_brendan || defined DEBUG_mrbkap || defined DEBUG_shaver
-# define DEBUG_NOT_THROWING 1
-#endif
-
-#ifdef DEBUG_NOT_THROWING
-# define ASSERT_NOT_THROWING(cx) JS_ASSERT(!(cx)->throwing)
-#else
-# define ASSERT_NOT_THROWING(cx) /* nothing */
-#endif
-
-/*
  * Define JS_OPMETER to instrument bytecode succession, generating a .dot file
  * on shutdown that shows the graph of significant predecessor/successor pairs
  * executed, where the edge labels give the succession counts.  The .dot file
  * is named by the JS_OPMETER_FILE envariable, and defaults to /tmp/ops.dot.
  *
  * Bonus feature: JS_OPMETER also enables counters for stack-addressing ops
  * such as JSOP_GETLOCAL, JSOP_INCARG, via METER_SLOT_OP. The resulting counts
  * are written to JS_OPMETER_HIST, defaulting to /tmp/ops.hist.
@@ -2447,25 +2293,18 @@ Interpret(JSContext *cx, JSStackFrame *e
         JS_ASSERT(prevContextRegs == &cx->generatorFor(fp)->savedRegs);
         JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
         JS_ASSERT((size_t) (regs.sp - fp->base()) <= StackDepth(script));
 
         /*
          * To support generator_throw and to catch ignored exceptions,
          * fail if cx->throwing is set.
          */
-        if (cx->throwing) {
-#ifdef DEBUG_NOT_THROWING
-            if (cx->exception != JSVAL_ARETURN) {
-                printf("JS INTERPRETER CALLED WITH PENDING EXCEPTION %lx\n",
-                       (unsigned long) cx->exception);
-            }
-#endif
+        if (cx->throwing)
             goto error;
-        }
     }
 #endif
 
 #ifdef JS_TRACER
     /*
      * The method JIT may have already initiated a recording, in which case
      * there should already be a valid recorder. Otherwise...
      * we cannot reenter the interpreter while recording.
@@ -2660,17 +2499,16 @@ BEGIN_CASE(JSOP_POPN)
                   <= regs.sp);
     }
 #endif
 }
 END_CASE(JSOP_POPN)
 
 BEGIN_CASE(JSOP_SETRVAL)
 BEGIN_CASE(JSOP_POPV)
-    ASSERT_NOT_THROWING(cx);
     POP_RETURN_VALUE();
 END_CASE(JSOP_POPV)
 
 BEGIN_CASE(JSOP_ENTERWITH)
     if (!js_EnterWith(cx, -1))
         goto error;
 
     /*
@@ -2697,17 +2535,16 @@ BEGIN_CASE(JSOP_RETURN)
 
 BEGIN_CASE(JSOP_RETRVAL)    /* fp return value already set */
 BEGIN_CASE(JSOP_STOP)
 {
     /*
      * When the inlined frame exits with an exception or an error, ok will be
      * false after the inline_return label.
      */
-    ASSERT_NOT_THROWING(cx);
     CHECK_BRANCH();
 
 #ifdef JS_TRACER
     if (fp->hasIMacroPC()) {
         /*
          * If we are at the end of an imacro, return to its caller in the
          * current frame.
          */
@@ -4762,29 +4599,26 @@ BEGIN_CASE(JSOP_APPLY)
             }
 #endif
 
             /* Load first op and dispatch it (safe since JSOP_STOP). */
             op = (JSOp) *regs.pc;
             DO_OP();
         }
 
-        if (fun->flags & JSFUN_FAST_NATIVE) {
-            Probes::enterJSFun(cx, fun);
-
-            JS_ASSERT(fun->u.n.extra == 0);
-            JS_ASSERT(vp[1].isObjectOrNull() || PrimitiveThisTest(fun, vp[1]));
-            JSBool ok = ((FastNative) fun->u.n.native)(cx, argc, vp);
-            Probes::exitJSFun(cx, fun);
-            regs.sp = vp + 1;
-            if (!ok)
-                goto error;
-            TRACE_0(NativeCallComplete);
-            goto end_call;
-        }
+        JS_ASSERT(vp[1].isObjectOrNull() || PrimitiveThisTest(fun, vp[1]));
+
+        Probes::enterJSFun(cx, fun);
+        JSBool ok = fun->u.n.native(cx, argc, vp);
+        Probes::exitJSFun(cx, fun);
+        regs.sp = vp + 1;
+        if (!ok)
+            goto error;
+        TRACE_0(NativeCallComplete);
+        goto end_call;
     }
 
     bool ok;
     ok = Invoke(cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0);
     regs.sp = vp + 1;
     CHECK_INTERRUPT_HANDLER();
     if (!ok)
         goto error;
@@ -5748,24 +5582,22 @@ BEGIN_CASE(JSOP_LAMBDA)
                          * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
                          * is the callee for this JSOP_CALL.
                          */
                         const Value &cref = regs.sp[1 - (iargc + 2)];
                         JSObject *callee;
 
                         if (IsFunctionObject(cref, &callee)) {
                             JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
-                            FastNative fastNative = FUN_FAST_NATIVE(calleeFun);
-
-                            if (fastNative) {
-                                if (iargc == 1 && fastNative == array_sort) {
+                            if (Native native = calleeFun->maybeNative()) {
+                                if (iargc == 1 && native == array_sort) {
                                     JS_FUNCTION_METER(cx, joinedsort);
                                     break;
                                 }
-                                if (iargc == 2 && fastNative == str_replace) {
+                                if (iargc == 2 && native == str_replace) {
                                     JS_FUNCTION_METER(cx, joinedreplace);
                                     break;
                                 }
                             }
                         }
                     } else if (op2 == JSOP_NULL) {
                         pc2 += JSOP_NULL_LENGTH;
                         op2 = JSOp(*pc2);
@@ -6721,31 +6553,31 @@ BEGIN_CASE(JSOP_LEAVEBLOCK)
         JS_ASSERT(fp->base() + blockDepth == regs.sp);
     }
 }
 END_CASE(JSOP_LEAVEBLOCK)
 
 #if JS_HAS_GENERATORS
 BEGIN_CASE(JSOP_GENERATOR)
 {
-    ASSERT_NOT_THROWING(cx);
+    JS_ASSERT(!cx->throwing);
     regs.pc += JSOP_GENERATOR_LENGTH;
     JSObject *obj = js_NewGenerator(cx);
     if (!obj)
         goto error;
     JS_ASSERT(!fp->hasCallObj() && !fp->hasArgsObj());
     fp->setReturnValue(ObjectValue(*obj));
     interpReturnOK = true;
     if (entryFrame != fp)
         goto inline_return;
     goto exit;
 }
 
 BEGIN_CASE(JSOP_YIELD)
-    ASSERT_NOT_THROWING(cx);
+    JS_ASSERT(!cx->throwing);
     if (cx->generatorFor(fp)->state == JSGEN_CLOSING) {
         js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
                             JSDVG_SEARCH_STACK, fp->argv[-2], NULL);
         goto error;
     }
     fp->setReturnValue(regs.sp[-1]);
     fp->flags |= JSFRAME_YIELDING;
     regs.pc += JSOP_YIELD_LENGTH;
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -680,48 +680,62 @@ Invoke(JSContext *cx, const CallArgs &ar
 #define JSINVOKE_CONSTRUCT      JSFRAME_CONSTRUCTING
 
 /*
  * Mask to isolate construct and iterator flags for use with jsfun.h functions.
  */
 #define JSINVOKE_FUNFLAGS       JSINVOKE_CONSTRUCT
 
 /*
- * "Internal" calls may come from C or C++ code using a JSContext on which no
+ * "External" calls may come from C or C++ code using a JSContext on which no
  * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
  */
-extern JSBool
-InternalInvoke(JSContext *cx, const Value &thisv, const Value &fval, uintN flags,
+
+extern bool
+ExternalInvoke(JSContext *cx, const Value &thisv, const Value &fval,
                uintN argc, Value *argv, Value *rval);
 
 static JS_ALWAYS_INLINE bool
-InternalCall(JSContext *cx, JSObject *obj, const Value &fval,
-             uintN argc, Value *argv, Value *rval)
+ExternalInvoke(JSContext *cx, JSObject *obj, const Value &fval,
+               uintN argc, Value *argv, Value *rval)
 {
-    return InternalInvoke(cx, ObjectOrNullValue(obj), fval, 0, argc, argv, rval);
-}
-
-static JS_ALWAYS_INLINE bool
-InternalConstruct(JSContext *cx, JSObject *obj, const Value &fval,
-                  uintN argc, Value *argv, Value *rval)
-{
-    return InternalInvoke(cx, ObjectOrNullValue(obj), fval, JSINVOKE_CONSTRUCT, argc, argv, rval);
+    return ExternalInvoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
 }
 
 extern bool
-InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
+ExternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
                  JSAccessMode mode, uintN argc, Value *argv, Value *rval);
 
+/*
+ * These two functions invoke a function called from a constructor context
+ * (e.g. 'new'). InvokeConstructor handles the general case where a new object
+ * needs to be created for/by the constructor. ConstructWithGivenThis directly
+ * calls the constructor with the given 'this', hence the caller must
+ * understand the semantics of the constructor call.
+ */
+
+extern JS_REQUIRES_STACK bool
+InvokeConstructor(JSContext *cx, const CallArgs &args);
+
+extern JS_REQUIRES_STACK bool
+InvokeConstructorWithGivenThis(JSContext *cx, JSObject *thisobj, const Value &fval,
+                               uintN argc, Value *argv, Value *rval);
+
+/*
+ * Executes a script with the given scope chain in the context of the given
+ * frame.
+ */
 extern JS_FORCES_STACK bool
 Execute(JSContext *cx, JSObject *chain, JSScript *script,
         JSStackFrame *down, uintN flags, Value *result);
 
-extern JS_REQUIRES_STACK bool
-InvokeConstructor(JSContext *cx, const CallArgs &args);
-
+/*
+ * Execute the caller-initialized frame for a user-defined script or function
+ * pointed to by cx->fp until completion or error.
+ */
 extern JS_REQUIRES_STACK bool
 Interpret(JSContext *cx, JSStackFrame *stopFp, uintN inlineCallCount = 0);
 
 extern JS_REQUIRES_STACK bool
 RunScript(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain);
 
 #define JSPROP_INITIALIZER 0x100   /* NB: Not a valid property attribute. */
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -82,17 +82,18 @@
 using namespace js;
 
 static void iterator_finalize(JSContext *cx, JSObject *obj);
 static void iterator_trace(JSTracer *trc, JSObject *obj);
 static JSObject *iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
 
 Class js_IteratorClass = {
     "Iterator",
-    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) | JSCLASS_MARK_IS_TRACE,
+    JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator) |
+    JSCLASS_MARK_IS_TRACE,
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub,
     iterator_finalize,
@@ -402,17 +403,17 @@ GetCustomIterator(JSContext *cx, JSObjec
 
     /* If there is no custom __iterator__ method, we are done here. */
     if (vp->isUndefined())
         return true;
 
     /* Otherwise call it and return that object. */
     LeaveTrace(cx);
     Value arg = BooleanValue((flags & JSITER_FOREACH) == 0);
-    if (!InternalCall(cx, obj, *vp, 1, &arg, vp))
+    if (!ExternalInvoke(cx, obj, *vp, 1, &arg, vp))
         return false;
     if (vp->isPrimitive()) {
         /*
          * We are always coming from js_ValueToIterator, and we are no longer on
          * trace, so the object we are iterating over is on top of the stack (-1).
          */
         js_ReportValueError2(cx, JSMSG_BAD_TRAP_RETURN_VALUE,
                              -1, ObjectValue(*obj), NULL,
@@ -724,25 +725,23 @@ GetIterator(JSContext *cx, JSObject *obj
 
 static JSObject *
 iterator_iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
 {
     return obj;
 }
 
 static JSBool
-Iterator(JSContext *cx, JSObject *iterobj, uintN argc, Value *argv, Value *rval)
+Iterator(JSContext *cx, uintN argc, Value *vp)
 {
-    JSBool keyonly;
-    uintN flags;
-
-    keyonly = js_ValueToBoolean(argv[1]);
-    flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
-    *rval = argv[0];
-    return js_ValueToIterator(cx, flags, rval);
+    Value *argv = JS_ARGV(cx, vp);
+    bool keyonly = argc >= 2 ? js_ValueToBoolean(argv[1]) : false;
+    uintN flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
+    *vp = argc >= 1 ? argv[0] : UndefinedValue();
+    return js_ValueToIterator(cx, flags, vp);
 }
 
 JSBool
 js_ThrowStopIteration(JSContext *cx)
 {
     Value v;
 
     JS_ASSERT(!JS_IsExceptionPending(cx));
@@ -962,17 +961,17 @@ js_IteratorMore(JSContext *cx, JSObject 
         rval->setBoolean(true);
         return true;
     }
 
     /* Fetch and cache the next value from the iterator. */
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);
     if (!js_GetMethod(cx, iterobj, id, JSGET_METHOD_BARRIER, rval))
         return false;
-    if (!InternalCall(cx, iterobj, *rval, 0, NULL, rval)) {
+    if (!ExternalInvoke(cx, iterobj, *rval, 0, NULL, rval)) {
         /* Check for StopIteration. */
         if (!cx->throwing || !js_ValueIsStopIteration(cx->exception))
             return false;
 
         /* Inline JS_ClearPendingException(cx). */
         cx->throwing = JS_FALSE;
         cx->exception.setUndefined();
         cx->iterValue.setMagic(JS_NO_ITER_VALUE);
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -526,28 +526,37 @@ Class js_NumberClass = {
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
 
 static JSBool
-Number(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+Number(JSContext *cx, uintN argc, Value *vp)
 {
-    if (argc != 0) {
-        if (!ValueToNumber(cx, &argv[0]))
-            return JS_FALSE;
+    /* Sample JS_CALLEE before clobbering. */
+    bool isConstructing = IsConstructing(vp);
+
+    if (argc > 0) {
+        if (!ValueToNumber(cx, &vp[2]))
+            return false;
+        vp[0] = vp[2];
     } else {
-        argv[0].setInt32(0);
+        vp[0].setInt32(0);
     }
-    if (!JS_IsConstructing(cx))
-        *rval = argv[0];
-    else
-        obj->setPrimitiveThis(argv[0]);
+
+    if (!isConstructing)
+        return true;
+    
+    JSObject *obj = NewBuiltinClassInstance(cx, &js_NumberClass);
+    if (!obj)
+        return false;
+    obj->setPrimitiveThis(vp[0]);
+    vp->setObject(*obj);
     return true;
 }
 
 #if JS_HAS_TOSOURCE
 static JSBool
 num_toSource(JSContext *cx, uintN argc, Value *vp)
 {
     char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -102,18 +102,17 @@
 #include "jsautooplen.h"
 
 using namespace js;
 
 JS_FRIEND_DATA(const JSObjectMap) JSObjectMap::sharedNonNative(JSObjectMap::SHAPELESS);
 
 Class js_ObjectClass = {
     js_Object_str,
-    JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
@@ -1086,17 +1085,17 @@ obj_eval(JSContext *cx, uintN argc, Valu
      * this so the compiler can make assumptions about what bindings may or
      * may not exist in the current frame if it doesn't see 'eval'.
      */
     if (indirectCall) {
         /* Pretend that we're top level. */
         staticLevel = 0;
 
         if (!js_CheckPrincipalsAccess(cx, obj,
-                                      JS_StackFramePrincipals(cx, caller),
+                                      js_StackFramePrincipals(cx, caller),
                                       cx->runtime->atomState.evalAtom)) {
             return JS_FALSE;
         }
 
         /* NB: We know inner is a global object here. */
         JS_ASSERT(!obj->getParent());
         scopeobj = obj;
     } else {
@@ -1285,17 +1284,17 @@ obj_watch_handler(JSContext *cx, JSObjec
         /* Skip over any obj_watch_* frames between us and the real subject. */
         caller = js_GetScriptedCaller(cx, NULL);
         if (caller) {
             /*
              * Only call the watch handler if the watcher is allowed to watch
              * the currently executing script.
              */
             watcher = callbacks->findObjectPrincipals(cx, callable);
-            subject = JS_StackFramePrincipals(cx, caller);
+            subject = js_StackFramePrincipals(cx, caller);
 
             if (watcher && subject && !watcher->subsume(watcher, subject)) {
                 /* Silently don't call the watch handler. */
                 return JS_TRUE;
             }
         }
     }
 
@@ -1306,17 +1305,17 @@ obj_watch_handler(JSContext *cx, JSObjec
         return JS_FALSE;
     if (!entry)
         return JS_TRUE;
     generation = cx->resolvingTable->generation;
 
     argv[0] = IdToValue(id);
     argv[1] = Valueify(old);
     argv[2] = Valueify(*nvp);
-    ok = InternalCall(cx, obj, ObjectOrNullValue(callable), 3, argv, Valueify(nvp));
+    ok = ExternalInvoke(cx, obj, ObjectOrNullValue(callable), 3, argv, Valueify(nvp));
     js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
     return ok;
 }
 
 static JSBool
 obj_watch(JSContext *cx, uintN argc, Value *vp)
 {
     if (argc <= 1) {
@@ -2579,16 +2578,37 @@ js_Object(JSContext *cx, uintN argc, Val
         obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
         if (!obj)
             return JS_FALSE;
     }
     vp->setObject(*obj);
     return JS_TRUE;
 }
 
+JSObject*
+js_NewInstance(JSContext *cx, JSObject *callee)
+{
+    Class *clasp = callee->getClass();
+
+    Class *newclasp = &js_ObjectClass;
+    if (clasp == &js_FunctionClass) {
+        JSFunction *fun = callee->getFunctionPrivate();
+        if (fun->isNative() && fun->u.n.clasp)
+            newclasp = fun->u.n.clasp;
+    }
+
+    Value protov;
+    if (!callee->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom), &protov))
+        return NULL;
+
+    JSObject *proto = protov.isObjectOrNull() ? protov.toObjectOrNull() : NULL;
+    JSObject *parent = callee->getParent();
+    return NewObject<WithProto::Class>(cx, newclasp, proto, parent);
+}
+
 #ifdef JS_TRACER
 
 JSObject*
 js_NewObjectWithClassProto(JSContext *cx, Class *clasp, JSObject *proto,
                            const Value &privateSlotValue)
 {
     JS_ASSERT(clasp->isNative());
 
@@ -2620,17 +2640,17 @@ js_NonEmptyObject(JSContext* cx, JSObjec
     JSObject *obj = js_NewObjectWithClassProto(cx, &js_ObjectClass, proto, UndefinedValue());
     return (obj && obj->ensureClassReservedSlotsForEmptyObject(cx)) ? obj : NULL;
 }
 
 JS_DEFINE_CALLINFO_2(extern, CONSTRUCTOR_RETRY, js_NonEmptyObject, CONTEXT, CALLEE_PROTOTYPE, 0,
                      nanojit::ACCSET_STORE_ANY)
 
 JSObject* FASTCALL
-js_NewInstance(JSContext *cx, Class *clasp, JSObject *ctor)
+js_NewInstanceFromTrace(JSContext *cx, Class *clasp, JSObject *ctor)
 {
     JS_ASSERT(JS_ON_TRACE(cx));
     JS_ASSERT(ctor->isFunction());
 #ifdef JS_THREADSAFE
     if (ctor->title.ownercx != cx)
         return NULL;
 #endif
 
@@ -2671,17 +2691,17 @@ js_NewInstance(JSContext *cx, Class *cla
 
     /*
      * FIXME: 561785 at least. Quasi-natives including XML objects prevent us
      * from easily or unconditionally calling NewNativeClassInstance here.
      */
     return NewNonFunction<WithProto::Given>(cx, clasp, proto, parent);
 }
 
-JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_NewInstance, CONTEXT, CLASS, OBJECT, 0,
+JS_DEFINE_CALLINFO_3(extern, CONSTRUCTOR_RETRY, js_NewInstanceFromTrace, CONTEXT, CLASS, OBJECT, 0,
                      nanojit::ACCSET_STORE_ANY)
 
 #else  /* !JS_TRACER */
 
 # define js_Object_trcinfo NULL
 
 #endif /* !JS_TRACER */
 
@@ -3239,25 +3259,24 @@ Class js_BlockClass = {
     EnumerateStub,
     ResolveStub,
     ConvertStub
 };
 
 JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj)
 {
-    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, (Native) js_Object, 1,
+    JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
                                    object_props, object_methods, NULL, object_static_methods);
     if (!proto)
         return NULL;
 
     /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
-    if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom,
-                           (Native)obj_eval, 1,
-                           JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS)) {
+    if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom, obj_eval, 1,
+                           JSFUN_STUB_GSOPS)) {
         return NULL;
     }
 
     return proto;
 }
 
 static bool
 DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
@@ -3385,21 +3404,17 @@ js_InitClass(JSContext *cx, JSObject *ob
                            ? JSPROP_READONLY | JSPROP_PERMANENT
                            : 0;
             if (!DefineStandardSlot(cx, obj, key, atom, ObjectValue(*proto), attrs, named))
                 goto bad;
         }
 
         ctor = proto;
     } else {
-        uint16 flags = 0;
-        if (clasp->flags & JSCLASS_FAST_CONSTRUCTOR)
-            flags |= JSFUN_FAST_NATIVE | JSFUN_FAST_NATIVE_CTOR;
-
-        fun = js_NewFunction(cx, NULL, constructor, nargs, flags, obj, atom);
+        fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom);
         if (!fun)
             goto bad;
 
         AutoValueRooter tvr2(cx, ObjectValue(*fun));
         if (!DefineStandardSlot(cx, obj, key, atom, tvr2.value(), 0, named))
             goto bad;
 
         /*
@@ -3413,18 +3428,20 @@ js_InitClass(JSContext *cx, JSObject *ob
          * Optionally construct the prototype object, before the class has
          * been fully initialized.  Allow the ctor to replace proto with a
          * different object, as is done for operator new -- and as at least
          * XML support requires.
          */
         ctor = FUN_OBJECT(fun);
         if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
             Value rval;
-            if (!InternalConstruct(cx, proto, ObjectOrNullValue(ctor), 0, NULL, &rval))
+            if (!InvokeConstructorWithGivenThis(cx, proto, ObjectOrNullValue(ctor),
+                                                0, NULL, &rval)) {
                 goto bad;
+            }
             if (rval.isObject() && &rval.toObject() != proto)
                 proto = &rval.toObject();
         }
 
         /* Connect constructor and prototype by named properties. */
         if (!js_SetClassPrototype(cx, ctor, proto,
                                   JSPROP_READONLY | JSPROP_PERMANENT)) {
             goto bad;
@@ -3830,17 +3847,17 @@ js_ConstructObject(JSContext *cx, Class 
             proto = rval.toObjectOrNull();
     }
 
     JSObject *obj = NewObject<WithProto::Class>(cx, clasp, proto, parent);
     if (!obj)
         return NULL;
 
     Value rval;
-    if (!InternalConstruct(cx, obj, cval, argc, argv, &rval))
+    if (!InvokeConstructorWithGivenThis(cx, obj, cval, argc, argv, &rval))
         return NULL;
 
     if (rval.isPrimitive())
         return obj;
 
     /*
      * If the instance's class differs from what was requested, throw a type
      * error.  If the given class has both the JSCLASS_HAS_PRIVATE and the
@@ -5294,19 +5311,18 @@ DefaultValue(JSContext *cx, JSObject *ob
                 }
             }
 
             if (shape && shape->hasDefaultGetter() && pobj->containsSlot(shape->slot)) {
                 const Value &fval = pobj->lockedGetSlot(shape->slot);
 
                 JSObject *funobj;
                 if (IsFunctionObject(fval, &funobj)) {
-                    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
-
-                    if (FUN_FAST_NATIVE(fun) == js_str_toString) {
+                    JSFunction *fun = funobj->getFunctionPrivate();
+                    if (fun->maybeNative() == js_str_toString) {
                         JS_UNLOCK_OBJ(cx, lockedobj);
                         *vp = obj->getPrimitiveThis();
                         return JS_TRUE;
                     }
                 }
             }
             JS_UNLOCK_OBJ(cx, lockedobj);
         }
@@ -5698,17 +5714,17 @@ js_TryMethod(JSContext *cx, JSObject *ob
     Value fval;
     JSBool ok = js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, &fval);
     JS_SetErrorReporter(cx, older);
     if (!ok)
         return false;
 
     if (fval.isPrimitive())
         return JS_TRUE;
-    return InternalCall(cx, obj, fval, argc, argv, rval);
+    return ExternalInvoke(cx, obj, fval, argc, argv, rval);
 }
 
 #if JS_HAS_XDR
 
 JSBool
 js_XDRObject(JSXDRState *xdr, JSObject **objp)
 {
     JSContext *cx;
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1349,16 +1349,19 @@ js_SetClassObject(JSContext *cx, JSObjec
 extern JSBool
 js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
                    js::Value *vp, js::Class *clasp = NULL);
 
 extern JSObject *
 js_ConstructObject(JSContext *cx, js::Class *clasp, JSObject *proto,
                    JSObject *parent, uintN argc, js::Value *argv);
 
+extern JSObject *
+js_NewInstance(JSContext *cx, JSObject *callee);
+
 extern jsid
 js_CheckForStringIndex(jsid id);
 
 /*
  * js_PurgeScopeChain does nothing if obj is not itself a prototype or parent
  * scope, else it reshapes the scope and prototype chains it links. It calls
  * js_PurgeScopeChainHelper, which asserts that obj is flagged as a delegate
  * (i.e., obj has ever been on a prototype or parent chain).
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -448,23 +448,16 @@ JSObject::getDateUTCTime() const
 
 inline void 
 JSObject::setDateUTCTime(const js::Value &time)
 {
     JS_ASSERT(isDate());
     fslots[JSSLOT_DATE_UTC_TIME] = time;
 }
 
-inline JSFunction *
-JSObject::getFunctionPrivate() const
-{
-    JS_ASSERT(isFunction());
-    return reinterpret_cast<JSFunction *>(getPrivate());
-}
-
 inline js::Value *
 JSObject::getFlatClosureUpvars() const
 {
     JS_ASSERT(isFunction());
     JS_ASSERT(FUN_FLAT_CLOSURE(getFunctionPrivate()));
     return (js::Value *) fslots[JSSLOT_FLAT_CLOSURE_UPVARS].toPrivate();
 }
 
--- a/js/src/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -91,16 +91,17 @@ Probes::FunctionLineNumber(JSContext *cx
  * All are presented as void * for DTrace consumers to use, after shifting or
  * masking out the JavaScript type bits. This allows D scripts to use ints and
  * booleans directly and copyinstr() for string arguments, when types are known
  * beforehand.
  *
  * This is used by the function-args and function-rval probes, which also
  * provide raw (unmasked) jsvals should type info be useful from D scripts.
  */
+#if 0
 static void *
 jsprobes_jsvaltovoid(JSContext *cx, const js::Value &argval)
 {
     if (argval.isNull())
         return (void *)JS_TYPE_STR(JSTYPE_NULL);
 
     if (argval.isUndefined())
         return (void *)JS_TYPE_STR(JSTYPE_VOID);
@@ -115,16 +116,17 @@ jsprobes_jsvaltovoid(JSContext *cx, cons
         if (argval.isInt32())
             return (void *)argval.toInt32();
         // FIXME Now what?
         //return (void *)argval.toDouble();
     }
 
     return argval.asGCThing();
 }
+#endif
 
 const char *
 Probes::FunctionName(JSContext *cx, const JSFunction *fun)
 {
     if (!fun)
         return nullName;
 
     JSAtom *atom = fun->atom;
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -120,17 +120,17 @@ JSProxyHandler::get(JSContext *cx, JSObj
         vp->setUndefined();
         return true;
     }
     if (!desc.getter) {
         *vp = desc.value;
         return true;
     }
     if (desc.attrs & JSPROP_GETTER) {
-        return InternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.getter),
+        return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.getter),
                                 JSACC_READ, 0, 0, vp);
     }
     if (desc.attrs & JSPROP_SHORTID)
         id = INT_TO_JSID(desc.shortid);
     return CallJSPropertyOp(cx, desc.getter, proxy, id, vp);
 }
 
 bool
@@ -139,34 +139,34 @@ JSProxyHandler::set(JSContext *cx, JSObj
     JS_ASSERT(OperationInProgress(cx, proxy));
     AutoPropertyDescriptorRooter desc(cx);
     if (!getOwnPropertyDescriptor(cx, proxy, id, &desc))
         return false;
     /* The control-flow here differs from ::get() because of the fall-through case below. */
     if (desc.obj) {
         if (desc.setter) {
             if (desc.attrs & JSPROP_SETTER) {
-                return InternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter),
+                return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter),
                                         JSACC_READ, 0, 0, vp);
             }
             if (desc.attrs & JSPROP_SHORTID)
                 id = INT_TO_JSID(desc.shortid);
             return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp);
         }
         if (desc.attrs & JSPROP_READONLY)
             return true;
         desc.value = *vp;
         return defineProperty(cx, proxy, id, &desc);
     }
     if (!getPropertyDescriptor(cx, proxy, id, &desc))
         return false;
     if (desc.obj) {
         if (desc.setter) {
             if (desc.attrs & JSPROP_SETTER) {
-                return InternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter),
+                return ExternalGetOrSet(cx, proxy, id, CastAsObjectJsval(desc.setter),
                                         JSACC_READ, 0, 0, vp);
             }
             if (desc.attrs & JSPROP_SHORTID)
                 id = INT_TO_JSID(desc.shortid);
             return CallJSPropertyOpSetter(cx, desc.setter, proxy, id, vp);
         }
         if (desc.attrs & JSPROP_READONLY)
             return true;
@@ -244,17 +244,17 @@ JSProxyHandler::fun_toString(JSContext *
     return fun_toStringHelper(cx, &fval.toObject(), indent);
 }
 
 bool
 JSProxyHandler::call(JSContext *cx, JSObject *proxy, uintN argc, Value *vp)
 {
     JS_ASSERT(OperationInProgress(cx, proxy));
     AutoValueRooter rval(cx);
-    JSBool ok = InternalInvoke(cx, vp[1], GetCall(proxy), 0, argc, JS_ARGV(cx, vp),
+    JSBool ok = ExternalInvoke(cx, vp[1], GetCall(proxy), argc, JS_ARGV(cx, vp),
                                rval.addr());
     if (ok)
         JS_SET_RVAL(cx, vp, rval.value());
     return ok;
 }
 
 bool
 JSProxyHandler::construct(JSContext *cx, JSObject *proxy,
@@ -272,17 +272,17 @@ JSProxyHandler::construct(JSContext *cx,
     }
 
     /*
      * FIXME: The Proxy proposal says to pass undefined as the this argument,
      * but primitive this is not supported yet. See bug 576644.
      */
     JS_ASSERT(fval.isObject());
     JSObject *thisobj = fval.toObject().getGlobal();
-    return InternalCall(cx, thisobj, fval, argc, argv, rval);
+    return ExternalInvoke(cx, thisobj, fval, argc, argv, rval);
 }
 
 void
 JSProxyHandler::finalize(JSContext *cx, JSObject *proxy)
 {
 }
 
 void
@@ -324,17 +324,17 @@ DerivedTrap(JSContext *cx, JSObject *han
     return GetTrap(cx, handler, atom, fvalp);
 }
 
 static bool
 Trap(JSContext *cx, JSObject *handler, Value fval, uintN argc, Value* argv, Value *rval)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    return InternalCall(cx, handler, fval, argc, argv, rval);
+    return ExternalInvoke(cx, handler, fval, argc, argv, rval);
 }
 
 static bool
 Trap1(JSContext *cx, JSObject *handler, Value fval, jsid id, Value *rval)
 {
     JSString *str = js_ValueToString(cx, IdToValue(id));
     if (!str)
         return false;
@@ -943,45 +943,48 @@ JSBool
 proxy_Call(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *proxy = &JS_CALLEE(cx, vp).toObject();
     JS_ASSERT(proxy->isProxy());
     return JSProxy::call(cx, proxy, argc, vp);
 }
 
 JSBool
-proxy_Construct(JSContext *cx, JSObject * /*obj*/, uintN argc, Value *argv, Value *rval)
+proxy_Construct(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *proxy = &argv[-2].toObject();
+    JSObject *proxy = &JS_CALLEE(cx, vp).toObject();
     JS_ASSERT(proxy->isProxy());
-    return JSProxy::construct(cx, proxy, argc, argv, rval);
+    Value rval;
+    bool ok = JSProxy::construct(cx, proxy, argc, JS_ARGV(cx, vp), &rval);
+    *vp = rval;
+    return ok;
 }
 
 static JSType
 proxy_TypeOf_fun(JSContext *cx, JSObject *obj)
 {
     return JSTYPE_FUNCTION;
 }
 
 #define proxy_HasInstance js_FunctionClass.hasInstance
 
 JS_FRIEND_API(Class) FunctionProxyClass = {
     "Proxy",
-    Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(4) | Class::CALL_IS_FAST,
+    Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(4),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     ConvertStub,
     NULL,           /* finalize */
     NULL,           /* reserved0   */
     NULL,           /* checkAccess */
-    CastCallOpAsNative(proxy_Call),
+    proxy_Call,
     proxy_Construct,
     NULL,           /* xdrObject   */
     proxy_HasInstance,
     NULL,           /* mark */
     JS_NULL_CLASS_EXT,
     {
         proxy_LookupProperty,
         proxy_DefineProperty,
@@ -1148,64 +1151,80 @@ static JSFunctionSpec static_methods[] =
 };
 
 extern Class CallableObjectClass;
 
 static const uint32 JSSLOT_CALLABLE_CALL = JSSLOT_PRIVATE;
 static const uint32 JSSLOT_CALLABLE_CONSTRUCT = JSSLOT_PRIVATE + 1;
 
 static JSBool
-callable_Call(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+callable_Call(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *callable = &argv[-2].toObject();
+    JSObject *thisobj = ComputeThisFromVp(cx, vp);
+    if (!thisobj)
+        return false;
+
+    JSObject *callable = &JS_CALLEE(cx, vp).toObject();
     JS_ASSERT(callable->getClass() == &CallableObjectClass);
     const Value &fval = callable->fslots[JSSLOT_CALLABLE_CALL];
-    return InternalCall(cx, obj, fval, argc, argv, rval);
+    Value rval;
+    bool ok = ExternalInvoke(cx, thisobj, fval, argc, JS_ARGV(cx, vp), &rval);
+    *vp = rval;
+    return ok;
 }
 
 static JSBool
-callable_Construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+callable_Construct(JSContext *cx, uintN argc, Value *vp)
 {
-    JSObject *callable = &argv[-2].toObject();
+    JSObject *thisobj = js_NewInstance(cx, &JS_CALLEE(cx, vp).toObject());
+    if (!thisobj)
+        return false;
+
+    JSObject *callable = &vp[0].toObject();
     JS_ASSERT(callable->getClass() == &CallableObjectClass);
     Value fval = callable->fslots[JSSLOT_CALLABLE_CONSTRUCT];
     if (fval.isUndefined()) {
         /* We don't have an explicit constructor so allocate a new object and use the call. */
         fval = callable->fslots[JSSLOT_CALLABLE_CALL];
         JS_ASSERT(fval.isObject());
 
         /* callable is the constructor, so get callable.prototype is the proto of the new object. */
-        if (!callable->getProperty(cx, ATOM_TO_JSID(ATOM(classPrototype)), rval))
+        Value protov;
+        if (!callable->getProperty(cx, ATOM_TO_JSID(ATOM(classPrototype)), &protov))
             return false;
 
         JSObject *proto;
-        if (rval->isObject()) {
-            proto = &rval->toObject();
+        if (protov.isObject()) {
+            proto = &protov.toObject();
         } else {
             if (!js_GetClassPrototype(cx, NULL, JSProto_Object, &proto))
                 return false;
         }
 
         JSObject *newobj = NewNativeClassInstance(cx, &js_ObjectClass, proto, proto->getParent());
         if (!newobj)
             return false;
 
-        rval->setObject(*newobj);
-
         /* If the call returns an object, return that, otherwise the original newobj. */
-        if (!InternalCall(cx, newobj, callable->fslots[JSSLOT_CALLABLE_CALL],
-                          argc, argv, rval)) {
+        Value rval;
+        if (!ExternalInvoke(cx, newobj, callable->fslots[JSSLOT_CALLABLE_CALL],
+                            argc, vp + 2, &rval)) {
             return false;
         }
-        if (rval->isPrimitive())
-            rval->setObject(*newobj);
-
+        if (rval.isPrimitive())
+            vp->setObject(*newobj);
+        else
+            *vp = rval;
         return true;
     }
-    return InternalCall(cx, obj, fval, argc, argv, rval);
+
+    Value rval;
+    bool ok = ExternalInvoke(cx, thisobj, fval, argc, vp + 2, &rval);
+    *vp = rval;
+    return ok;
 }
 
 Class CallableObjectClass = {
     "Function",
     JSCLASS_HAS_RESERVED_SLOTS(2),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -324,24 +324,16 @@ typedef JSBool
 /*
  * Get or set attributes of the property obj[id]. Return false on error or
  * exception, true with current attributes in *attrsp.
  */
 typedef JSBool
 (* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp);
 
 /*
- * The type of ops->call. Same argument types as JSFastNative, but a different
- * contract. A JSCallOp expects a dummy stack frame with the caller's
- * scopeChain.
- */
-typedef JSBool
-(* JSCallOp)(JSContext *cx, uintN argc, jsval *vp);
-
-/*
  * A generic type for functions mapping an object to another object, or null
  * if an error or exception was thrown on cx.
  */
 typedef JSObject *
 (* JSObjectOp)(JSContext *cx, JSObject *obj);
 
 /*
  * Hook that creates an iterator object for a given object. Returns the
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -391,25 +391,24 @@ typedef void
  * a string describing the reference traced with JS_CallTracer.
  */
 typedef void
 (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
 
 typedef JSBool
 (* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
 
-/* Typedef for native functions called by the JS VM. */
+/*
+ * Typedef for native functions called by the JS VM.
+ *
+ * See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
+ */
 
 typedef JSBool
-(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-             jsval *rval);
-
-/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
-typedef JSBool
-(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
+(* JSNative)(JSContext *cx, uintN argc, jsval *vp);
 
 /* Callbacks and their arguments. */
 
 typedef enum JSContextOp {
     JSCONTEXT_NEW,
     JSCONTEXT_DESTROY
 } JSContextOp;
 
--- a/js/src/jsregexp.cpp
+++ b/js/src/jsregexp.cpp
@@ -571,19 +571,19 @@ regexp_finalize(JSContext *cx, JSObject 
     re->decref(cx);
 }
 
 /* Forward static prototype. */
 static JSBool
 regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool test, Value *rval);
 
 static JSBool
-regexp_call(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+regexp_call(JSContext *cx, uintN argc, Value *vp)
 {
-    return regexp_exec_sub(cx, argv[-2].toObjectOrNull(), argc, argv, JS_FALSE, rval);
+    return regexp_exec_sub(cx, &JS_CALLEE(cx, vp).toObject(), argc, JS_ARGV(cx, vp), false, vp);
 }
 
 #if JS_HAS_XDR
 
 #include "jsxdrapi.h"
 
 JSBool
 js_XDRRegExpObject(JSXDRState *xdr, JSObject **objp)
@@ -955,42 +955,36 @@ static JSFunctionSpec regexp_methods[] =
     JS_FN(js_toString_str,  regexp_toString,    0,0),
     JS_FN("compile",        regexp_compile,     2,0),
     JS_FN("exec",           regexp_exec,        1,0),
     JS_FN("test",           regexp_test,        1,0),
     JS_FS_END
 };
 
 static JSBool
-regexp_construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+regexp_construct(JSContext *cx, uintN argc, Value *vp)
 {
-    if (!JS_IsConstructing(cx)) {
-        /*
-         * If first arg is regexp and no flags are given, just return the arg.
-         * (regexp_compile_sub detects the regexp + flags case and throws a
-         * TypeError.)  See 10.15.3.1.
-         */
-        if ((argc < 2 || argv[1].isUndefined()) && !argv[0].isPrimitive() &&
-            argv[0].toObject().getClass() == &js_RegExpClass) {
-            *rval = argv[0];
-            return true;
-        }
+    /*
+     * If first arg is regexp and no flags are given, just return the arg.
+     * (regexp_compile_sub detects the regexp + flags case and throws a
+     * TypeError.)  See 10.15.3.1.
+     */
+    Value *argv = vp + 2;
+    if ((argc < 2 || argv[1].isUndefined()) && argv[0].isObject() &&
+        argv[0].toObject().getClass() == &js_RegExpClass) {
+        *vp = argv[0];
+        return true;
+    }
 
-        /* Otherwise, replace obj with a new RegExp object. */
-        obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
-        if (!obj)
-            return false;
+    /* Otherwise, replace obj with a new RegExp object. */
+    JSObject *obj = NewBuiltinClassInstance(cx, &js_RegExpClass);
+    if (!obj)
+        return false;
 
-        /*
-         * regexp_compile_sub does not use rval to root its temporaries so we
-         * can use it to root obj.
-         */
-        *rval = ObjectValue(*obj);
-    }
-    return regexp_compile_sub(cx, obj, argc, argv, rval);
+    return regexp_compile_sub(cx, obj, argc, argv, vp);
 }
 
 JSObject *
 js_InitRegExpClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto = js_InitClass(cx, obj, NULL, &js_RegExpClass, regexp_construct, 1,
                                    NULL, regexp_methods, regexp_static_props, NULL);
     if (!proto)
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -210,17 +210,17 @@ inline bool
 Shape::get(JSContext* cx, JSObject* obj, JSObject *pobj, js::Value* vp) const
 {
     JS_ASSERT(!JSID_IS_VOID(this->id));
     JS_ASSERT(!hasDefaultGetter());
 
     if (hasGetterValue()) {
         JS_ASSERT(!isMethod());
         js::Value fval = getterValue();
-        return js::InternalGetOrSet(cx, obj, id, fval, JSACC_READ, 0, 0, vp);
+        return js::ExternalGetOrSet(cx, obj, id, fval, JSACC_READ, 0, 0, vp);
     }
 
     if (isMethod()) {
         vp->setObject(methodObject());
         return pobj->methodReadBarrier(cx, *this, vp);
     }
 
     /*
@@ -234,17 +234,17 @@ Shape::get(JSContext* cx, JSObject* obj,
 
 inline bool
 Shape::set(JSContext* cx, JSObject* obj, js::Value* vp) const
 {
     JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
 
     if (attrs & JSPROP_SETTER) {
         js::Value fval = setterValue();
-        return js::InternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
+        return js::ExternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
     }
 
     if (attrs & JSPROP_GETTER)
         return js_ReportGetterOnlyAssignment(cx);
 
     /* See the comment in js::Shape::get as to why we check for With. */
     if (obj->getClass() == &js_WithClass)
         obj = js_UnwrapWithObject(cx, obj);
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -827,18 +827,17 @@ str_resolve(JSContext *cx, JSObject *obj
         *objp = obj;
     }
     return JS_TRUE;
 }
 
 Class js_StringClass = {
     js_String_str,
     JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_RESOLVE |
-    JSCLASS_HAS_CACHED_PROTO(JSProto_String) |
-    JSCLASS_FAST_CONSTRUCTOR,
+    JSCLASS_HAS_CACHED_PROTO(JSProto_String),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     str_getProperty,
     PropertyStub,   /* setProperty */
     str_enumerate,
     (JSResolveOp)str_resolve,
     ConvertStub
 };
@@ -3259,37 +3258,37 @@ const char JSString::deflatedUnitStringT
 };
 
 #undef U
 #undef U8
 
 JSBool
 js_String(JSContext *cx, uintN argc, Value *vp)
 {
+    Value *argv = vp + 2;
+
     JSString *str;
-
     if (argc > 0) {
-        str = js_ValueToString(cx, vp[2]);
+        str = js_ValueToString(cx, argv[0]);
         if (!str)
-            return JS_FALSE;
-        vp[2].setString(str);
+            return false;
     } else {
         str = cx->runtime->emptyString;
     }
 
-    if (vp[1].isMagic(JS_FAST_CONSTRUCTOR)) {
+    if (IsConstructing(vp)) {
         JSObject *obj = NewBuiltinClassInstance(cx, &js_StringClass);
         if (!obj)
-            return JS_FALSE;
+            return false;
         obj->setPrimitiveThis(StringValue(str));
         vp->setObject(*obj);
     } else {
         vp->setString(str);
     }
-    return JS_TRUE;
+    return true;
 }
 
 #ifdef JS_TRACER
 
 JSObject* FASTCALL
 js_String_tn(JSContext* cx, JSObject* proto, JSString* str)
 {
     JS_ASSERT(JS_ON_TRACE(cx));
@@ -3368,17 +3367,17 @@ JSObject *
 js_InitStringClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto;
 
     /* Define the escape, unescape functions in the global object. */
     if (!JS_DefineFunctions(cx, obj, string_functions))
         return NULL;
 
-    proto = js_InitClass(cx, obj, NULL, &js_StringClass, (Native) js_String, 1,
+    proto = js_InitClass(cx, obj, NULL, &js_StringClass, js_String, 1,
                          NULL, string_methods,
                          NULL, string_static_methods);
     if (!proto)
         return NULL;
     proto->setPrimitiveThis(StringValue(cx->runtime->emptyString));
     if (!js_DefineNativeProperty(cx, proto, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
                                  UndefinedValue(), NULL, NULL,
                                  JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0,
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -461,16 +461,18 @@ InitJITStatsClass(JSContext *cx, JSObjec
 #define INS_CONSTOBJ(obj)     addName(insImmObj(obj), #obj)
 #define INS_CONSTFUN(fun)     addName(insImmFun(fun), #fun)
 #define INS_CONSTSTR(str)     addName(insImmStr(str), #str)
 #define INS_CONSTSHAPE(shape) addName(insImmShape(shape), #shape)
 #define INS_CONSTID(id)       addName(insImmId(id), #id)
 #define INS_ATOM(atom)        INS_CONSTSTR(ATOM_TO_STRING(atom))
 #define INS_NULL()            INS_CONSTPTR(NULL)
 #define INS_UNDEFINED()       INS_CONST(0)
+#define INS_MAGIC_WHY(why)    INS_CONSTWORD((size_t)why)
+#define INS_MAGIC_NULL()      INS_NULL()
 
 static const size_t sPayloadOffset = offsetof(jsval_layout, s.payload);
 #if JS_BITS_PER_WORD == 32
 static const size_t sTagOffset = offsetof(jsval_layout, s.tag);
 #endif
 
 static avmplus::AvmCore s_core = avmplus::AvmCore();
 static avmplus::AvmCore* core = &s_core;
@@ -4278,17 +4280,16 @@ TraceRecorder::snapshot(ExitType exitTyp
     exit->exitType = exitType;
     exit->block = fp->maybeBlockChain();
     if (fp->hasBlockChain())
         tree->gcthings.addUnique(ObjectValue(*fp->getBlockChain()));
     exit->pc = pc;
     exit->imacpc = fp->maybeIMacroPC();
     exit->sp_adj = (stackSlots * sizeof(double)) - tree->nativeStackBase;
     exit->rp_adj = exit->calldepth * sizeof(FrameInfo*);
-    exit->nativeCalleeWord = 0;
     exit->lookupFlags = js_InferFlags(cx, 0);
     memcpy(exit->fullTypeMap(), typemap, typemap_size);
 
 #if defined JS_JIT_SPEW
     TreevisLogExit(cx, exit);
 #endif
     return exit;
 }
@@ -5724,56 +5725,16 @@ SynthesizeFrame(JSContext* cx, const Fra
      * everything down to the caller's fp->slots (where vars start) and avoid
      * some of the complexity?
      */
     return (fi.spdist - newfp->down->getFixedCount()) +
           ((fun->nargs > newfp->numActualArgs()) ? fun->nargs - newfp->numActualArgs() : 0) +
            newscript->nfixed + SPECIAL_FRAME_SLOTS;
 }
 
-JS_REQUIRES_STACK static void
-SynthesizeSlowNativeFrame(TracerState& state, JSContext *cx, VMSideExit *exit)
-{
-    /*
-     * StackSpace::getInlineFrame calls js_ReportOutOfScriptQuota if there is
-     * no space (which will try to deep bail, which is bad), however we already
-     * check on entry to ExecuteTree that there is enough space.
-     */
-    StackSegment *seg;
-    JSStackFrame *fp;
-    cx->stack().getSynthesizedSlowNativeFrame(cx, seg, fp);
-
-#ifdef DEBUG
-    JSObject *callee = &state.nativeVp[0].toObject();
-    JSFunction *fun = GET_FUNCTION_PRIVATE(cx, callee);
-    JS_ASSERT(!fun->isInterpreted() && !fun->isFastNative());
-    JS_ASSERT(fun->u.n.extra == 0);
-#endif
-
-    fp->setCallObj(NULL);
-    fp->setArgsObj(NULL);
-    fp->setScript(NULL);
-    fp->setThisValue(state.nativeVp[1]);
-    fp->setNumActualArgs(state.nativeVpLen - 2);
-    fp->argv = state.nativeVp + 2;
-    fp->setFunction(GET_FUNCTION_PRIVATE(cx, fp->callee()));
-    fp->clearReturnValue();
-    fp->setAnnotation(NULL);
-    fp->setScopeChain(cx->fp()->getScopeChain());
-    fp->setBlockChain(NULL);
-    fp->flags = exit->constructing() ? JSFRAME_CONSTRUCTING : 0;
-    JS_ASSERT(!fp->hasIMacroPC());
-
-    state.bailedSlowNativeRegs.fp = fp;
-    state.bailedSlowNativeRegs.pc = NULL;
-    state.bailedSlowNativeRegs.sp = fp->slots();
-
-    cx->stack().pushSynthesizedSlowNativeFrame(cx, seg, state.bailedSlowNativeRegs);
-}
-
 static JS_REQUIRES_STACK bool
 RecordTree(JSContext* cx, TreeFragment* first, jsbytecode* outer,
            uint32 outerArgc, SlotList* globalSlots)
 {
     TraceMonitor* tm = &JS_TRACE_MONITOR(cx);
 
     /* Try to find an unused peer fragment, or allocate a new one. */
     JS_ASSERT(first->first == first);
@@ -6765,25 +6726,17 @@ LeaveTree(TraceMonitor *tm, TracerState&
     bool bailed = innermost->exitType == STATUS_EXIT && (bs & BUILTIN_BAILED);
     if (bailed) {
         /*
          * Deep-bail case.
          *
          * A _FAIL native already called LeaveTree. We already reconstructed
          * the interpreter stack, in pre-call state, with pc pointing to the
          * CALL/APPLY op, for correctness. Then we continued in native code.
-         *
-         * First, if we just returned from a slow native, pop its stack frame.
          */
-        if (!cx->fp()->hasScript()) {
-            JS_ASSERT(cx->regs == &state.bailedSlowNativeRegs);
-            cx->stack().popSynthesizedSlowNativeFrame(cx);
-        }
-        JS_ASSERT(cx->fp()->hasScript());
-
         if (!(bs & (BUILTIN_ERROR | BUILTIN_NO_FIXUP_NEEDED))) {
             /*
              * The builtin or native deep-bailed but finished successfully
              * (no exception or error).
              *
              * After it returned, the JIT code stored the results of the
              * builtin or native at the top of the native stack and then
              * immediately flunked the guard on state->builtinStatus.
@@ -6995,19 +6948,16 @@ LeaveTree(TraceMonitor *tm, TracerState&
 #ifdef DEBUG
     int slots =
 #endif
         FlushNativeStackFrame(cx, innermost->calldepth,
                               innermost->stackTypeMap(),
                               stack, NULL);
     JS_ASSERT(unsigned(slots) == innermost->numStackSlots);
 
-    if (innermost->nativeCalleeWord)
-        SynthesizeSlowNativeFrame(state, cx, innermost);
-
     /* Write back interned globals. */
     JS_ASSERT(state.eos == state.stackBase + MAX_NATIVE_STACK_SLOTS);
     JSObject* globalObj = outermostTree->globalObj;
     FlushNativeGlobalFrame(cx, globalObj, state.eos, ngslots, gslots, globalTypeMap);
 #ifdef DEBUG
     /* Verify that our state restoration worked. */
     for (JSStackFrame* fp = cx->fp(); fp; fp = fp->down) {
         JS_ASSERT_IF(fp->argv, fp->argv[-1].isObjectOrNull());
@@ -9788,17 +9738,17 @@ inline nanojit::LIns*
 TraceRecorder::unbox_non_double_object(LIns* v_ins, JSValueType type, VMSideExit* exit)
 {
     JS_ASSERT(type <= JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET);
     LIns *unboxed_ins;
     if (type == JSVAL_TYPE_UNDEFINED) {
         unboxed_ins = INS_UNDEFINED();
     } else if (type == JSVAL_TYPE_NULL) {
         unboxed_ins = INS_NULL();
-    } else if (type >= JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET) {
+    } else if (type >= JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET) {
         unboxed_ins = unpack_ptr(v_ins);
     } else {
         JS_ASSERT(type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN || type == JSVAL_TYPE_MAGIC);
         unboxed_ins = lir->ins1(LIR_q2i, v_ins);
     }
 
     guard(true, non_double_object_value_has_type(v_ins, type), exit);
     return unboxed_ins;
@@ -9884,17 +9834,17 @@ TraceRecorder::box_value_for_native_call
         return INS_CONSTQWORD(JSVAL_BITS(JSVAL_NULL));
     if (v.isUndefined())
         return INS_CONSTQWORD(JSVAL_BITS(JSVAL_VOID));
 
     JSValueTag tag = v.isObject() ? JSVAL_TAG_OBJECT : v.extractNonDoubleObjectTraceTag();
     uint64 shiftedTag = ((uint64)tag) << JSVAL_TAG_SHIFT;
     LIns *shiftedTag_ins = INS_CONSTQWORD(shiftedTag);
 
-    if (v.isGCThing())
+    if (v.hasPtrPayload())
         return lir->ins2(LIR_orq, v_ins, shiftedTag_ins);
     return lir->ins2(LIR_orq, lir->ins1(LIR_ui2uq, v_ins), shiftedTag_ins);
 }
 
 void
 TraceRecorder::box_value_into(const Value &v, LIns *v_ins, LIns *dstaddr_ins, ptrdiff_t offset,
                               AccSet accSet)
 {
@@ -11005,32 +10955,23 @@ TraceRecorder::emitNativePropertyOp(cons
                                     (int) offsetof(TracerState, builtinStatus), ACCSET_OTHER);
     propagateFailureToBuiltinStatus(ok_ins, status_ins);
     guard(true, lir->insEqI_0(status_ins), STATUS_EXIT);
 }
 
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::emitNativeCall(JSSpecializedNative* sn, uintN argc, LIns* args[], bool rooted)
 {
-    bool constructing = !!(sn->flags & JSTN_CONSTRUCTOR);
-
     if (JSTN_ERRTYPE(sn) == FAIL_STATUS) {
         // This needs to capture the pre-call state of the stack. So do not set
         // pendingSpecializedNative before taking this snapshot.
         JS_ASSERT(!pendingSpecializedNative);
 
         // Take snapshot for DeepBail and store it in cx->bailExit.
-        // If we are calling a slow native, add information to the side exit
-        // for SynthesizeSlowNativeFrame.
-        VMSideExit* exit = enterDeepBailCall();
-        JSObject* funobj = &stackval(0 - (2 + argc)).toObject();
-        if (FUN_SLOW_NATIVE(GET_FUNCTION_PRIVATE(cx, funobj))) {
-            exit->setNativeCallee(funobj, constructing);
-            tree->gcthings.addUnique(ObjectValue(*funobj));
-        }
+        enterDeepBailCall();
     }
 
     LIns* res_ins = lir->insCall(sn->builtin, args);
 
     // Immediately unroot the vp as soon we return since we might deep bail next.
     if (rooted)
         lir->insStore(INS_NULL(), lirbuf->state, offsetof(TracerState, nativeVp), ACCSET_OTHER);
 
@@ -11179,38 +11120,38 @@ TraceRecorder::callNative(uintN argc, JS
 {
     LIns* args[5];
 
     JS_ASSERT(mode == JSOP_CALL || mode == JSOP_NEW || mode == JSOP_APPLY);
 
     Value* vp = &stackval(0 - (2 + argc));
     JSObject* funobj = &vp[0].toObject();
     JSFunction* fun = GET_FUNCTION_PRIVATE(cx, funobj);
-    FastNative native = (FastNative)fun->u.n.native;
+    Native native = fun->u.n.native;
 
     switch (argc) {
       case 1:
         if (vp[2].isNumber() && mode == JSOP_CALL) {
             if (native == js_math_ceil || native == js_math_floor || native == js_math_round) {
                 LIns* a = get(&vp[2]);
                 if (isPromote(a)) {
                     set(&vp[0], a);
                     pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                     return RECORD_CONTINUE;
                 }
             }
             if (vp[1].isString()) {
                 JSString *str = vp[1].toString();
-                if (native == (FastNative)js_str_charAt) {
+                if (native == js_str_charAt) {
                     LIns* str_ins = get(&vp[1]);
                     LIns* idx_ins = get(&vp[2]);
                     set(&vp[0], getCharAt(str, str_ins, idx_ins, mode));
                     pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                     return RECORD_CONTINUE;
-                } else if (native == (FastNative)js_str_charCodeAt) {
+                } else if (native == js_str_charCodeAt) {
                     jsdouble i = vp[2].toNumber();
                     if (i < 0 || i >= str->length())
                         RETURN_STOP("charCodeAt out of bounds");
                     LIns* str_ins = get(&vp[1]);
                     LIns* idx_ins = get(&vp[2]);
                     set(&vp[0], getCharCodeAt(str, str_ins, idx_ins));
                     pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
                     return RECORD_CONTINUE;
@@ -11237,36 +11178,31 @@ TraceRecorder::callNative(uintN argc, JS
                 return RECORD_CONTINUE;
             }
         }
         break;
     }
 
     if (fun->flags & JSFUN_TRCINFO) {
         JSNativeTraceInfo *trcinfo = FUN_TRCINFO(fun);
-        JS_ASSERT(trcinfo && (JSFastNative)fun->u.n.native == trcinfo->native);
+        JS_ASSERT(trcinfo && fun->u.n.native == trcinfo->native);
 
         /* Try to call a type specialized version of the native. */
         if (trcinfo->specializations) {
             RecordingStatus status = callSpecializedNative(trcinfo, argc, mode == JSOP_NEW);
             if (status != RECORD_STOP)
                 return status;
         }
     }
 
     if (native == js_fun_apply || native == js_fun_call)
         RETURN_STOP("trying to call native apply or call");
 
-    if (fun->u.n.extra > 0)
-        RETURN_STOP("trying to trace slow native with fun->u.n.extra > 0");
-
     // Allocate the vp vector and emit code to root it.
-    uintN vplen = 2 + JS_MAX(argc, unsigned(FUN_MINARGS(fun)));
-    if (!(fun->flags & JSFUN_FAST_NATIVE))
-        vplen++; // slow native return value slot
+    uintN vplen = 2 + argc;
     LIns* invokevp_ins = lir->insAlloc(vplen * sizeof(Value));
 
     // vp[0] is the callee.
     box_value_into(vp[0], INS_CONSTOBJ(funobj), invokevp_ins, 0, ACCSET_OTHER);
 
     // Calculate |this|.
     LIns* this_ins;
     if (mode == JSOP_NEW) {
@@ -11280,68 +11216,43 @@ TraceRecorder::callNative(uintN argc, JS
         // sized JSObject, not a Function-sized one. (The Function ctor would
         // deep-bail anyway but let's not go there.)
         if (clasp == &js_FunctionClass)
             RETURN_STOP("new Function");
 
         if (!clasp->isNative())
             RETURN_STOP("new with non-native ops");
 
-        if (fun->isFastConstructor()) {
-            vp[1].setMagic(JS_FAST_CONSTRUCTOR);
-            newobj_ins = INS_CONST(JS_FAST_CONSTRUCTOR);
+        if (fun->isConstructor()) {
+            vp[1].setMagicWithObjectOrNullPayload(NULL);
+            newobj_ins = INS_MAGIC_NULL();
 
             /* Treat this as a regular call, the constructor will behave correctly. */
             mode = JSOP_CALL;
         } else {
             args[0] = INS_CONSTOBJ(funobj);
             args[1] = INS_CONSTPTR(clasp);
             args[2] = cx_ins;
-            newobj_ins = lir->insCall(&js_NewInstance_ci, args);
+            newobj_ins = lir->insCall(&js_NewInstanceFromTrace_ci, args);
             guard(false, lir->insEqP_0(newobj_ins), OOM_EXIT);
 
             /*
              * emitNativeCall may take a snapshot below. To avoid having a type
              * mismatch (e.g., where get(&vp[1]) is an object and vp[1] is
              * null), we make sure vp[1] is some object. The actual object
              * doesn't matter; JSOP_NEW and InvokeConstructor both overwrite
              * vp[1] without observing its value.
              *
              * N.B. tracing specializes for functions, so pick a non-function.
              */
             vp[1].setObject(*globalObj);
         }
         this_ins = newobj_ins;
     } else {
         this_ins = get(&vp[1]);
-
-        /*
-         * For fast natives, 'null' or primitives are fine as as 'this' value.
-         * For slow natives we have to ensure the object is substituted for the
-         * appropriate global object or boxed object value. JSOP_NEW allocates its
-         * own object so it's guaranteed to have a valid 'this' value.
-         */
-        if (!(fun->flags & JSFUN_FAST_NATIVE)) {
-            if (vp[1].isNull()) {
-                JSObject* thisObj = ComputeThisFromVp(cx, vp);
-                if (!thisObj)
-                    RETURN_ERROR("error in js_ComputeGlobalThis");
-                this_ins = INS_CONSTOBJ(thisObj);
-            } else if (!vp[1].isObject()) {
-                RETURN_STOP("slow native(primitive, args)");
-            } else {
-                if (vp[1].toObject().hasClass(&js_WithClass))
-                    RETURN_STOP("can't trace slow native invocation on With object");
-                guardNotClass(this_ins, &js_WithClass, snapshot(MISMATCH_EXIT), LOAD_CONST);
-
-                this_ins = lir->insChoose(lir->insEqP_0(stobj_get_parent(this_ins)),
-                                           INS_CONSTOBJ(globalObj),
-                                           this_ins, avmplus::AvmCore::use_cmov());
-            }
-        }
     }
     set(&vp[1], this_ins);
     box_value_into(vp[1], this_ins, invokevp_ins, 1 * sizeof(Value), ACCSET_OTHER);
 
     // Populate argv.
     for (uintN n = 2; n < 2 + argc; n++) {
         box_value_into(vp[n], get(&vp[n]), invokevp_ins, n * sizeof(Value), ACCSET_OTHER);
         // For a very long argument list we might run out of LIR space, so
@@ -11355,36 +11266,23 @@ TraceRecorder::callNative(uintN argc, JS
         for (uintN n = 2 + argc; n < vplen; n++) {
             box_undefined_into(invokevp_ins, n * sizeof(Value), ACCSET_OTHER);
             if (outOfMemory())
                 RETURN_STOP("out of memory in extra slots");
         }
     }
 
     // Set up arguments for the JSNative or JSFastNative.
-    uint32 typesig;
-    if (fun->flags & JSFUN_FAST_NATIVE) {
-        if (mode == JSOP_NEW && !(fun->flags & JSFUN_FAST_NATIVE_CTOR))
-            RETURN_STOP("untraceable fast native constructor");
-        native_rval_ins = invokevp_ins;
-        args[0] = invokevp_ins;
-        args[1] = lir->insImmI(argc);
-        args[2] = cx_ins;
-        typesig = CallInfo::typeSig3(ARGTYPE_I, ARGTYPE_P, ARGTYPE_I, ARGTYPE_P);
-    } else {
-        int32_t offset = (vplen - 1) * sizeof(Value);
-        native_rval_ins = lir->ins2(LIR_addp, invokevp_ins, INS_CONSTWORD(offset));
-        args[0] = native_rval_ins;
-        args[1] = lir->ins2(LIR_addp, invokevp_ins, INS_CONSTWORD(2 * sizeof(Value)));
-        args[2] = lir->insImmI(argc);
-        args[3] = this_ins;
-        args[4] = cx_ins;
-        typesig = CallInfo::typeSig5(ARGTYPE_I,
-                                     ARGTYPE_P, ARGTYPE_P, ARGTYPE_I, ARGTYPE_P, ARGTYPE_P);
-    }
+    if (mode == JSOP_NEW)
+        RETURN_STOP("untraceable fast native constructor");
+    native_rval_ins = invokevp_ins;
+    args[0] = invokevp_ins;
+    args[1] = lir->insImmI(argc);
+    args[2] = cx_ins;
+    uint32 typesig = CallInfo::typeSig3(ARGTYPE_I, ARGTYPE_P, ARGTYPE_I, ARGTYPE_P);
 
     // Generate CallInfo and a JSSpecializedNative structure on the fly.
     // Do not use JSTN_UNBOX_AFTER for mode JSOP_NEW because
     // record_NativeCallComplete unboxes the result specially.
 
     CallInfo* ci = new (traceAlloc()) CallInfo();
     ci->_address = uintptr_t(fun->u.n.native);
     ci->_isPure = 0;
@@ -11456,24 +11354,24 @@ TraceRecorder::functionCall(uintN argc, 
             guard(false, lir->insEqI_0(call_ins), MISMATCH_EXIT);
         }
     }
 #endif
 
     if (FUN_INTERPRETED(fun)) {
         if (mode == JSOP_NEW) {
             LIns* args[] = { get(&fval), INS_CONSTPTR(&js_ObjectClass), cx_ins };
-            LIns* tv_ins = lir->insCall(&js_NewInstance_ci, args);
+            LIns* tv_ins = lir->insCall(&js_NewInstanceFromTrace_ci, args);
             guard(false, lir->insEqP_0(tv_ins), OOM_EXIT);
             set(&tval, tv_ins);
         }
         return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
     }
 
-    FastNative native = FUN_FAST_NATIVE(fun);
+    Native native = fun->maybeNative();
     Value* argv = &tval + 1;
     if (native == js_Array)
         return newArray(&fval.toObject(), argc, argv, &fval);
     if (native == js_String && argc == 1) {
         if (mode == JSOP_NEW)
             return newString(&fval.toObject(), 1, argv, &fval);
         if (!argv[0].isPrimitive()) {
             CHECK_STATUS(guardNativeConversion(argv[0]));
@@ -13314,18 +13212,18 @@ TraceRecorder::record_JSOP_APPLY()
         return record_JSOP_CALL();
     RETURN_IF_XML_A(vp[0]);
 
     JSObject* obj = &vp[0].toObject();
     JSFunction* fun = GET_FUNCTION_PRIVATE(cx, obj);
     if (FUN_INTERPRETED(fun))
         return record_JSOP_CALL();
 
-    bool apply = (FastNative)fun->u.n.native == js_fun_apply;
-    if (!apply && (FastNative)fun->u.n.native != js_fun_call)
+    bool apply = fun->u.n.native == js_fun_apply;
+    if (!apply && fun->u.n.native != js_fun_call)
         return record_JSOP_CALL();
 
     /*
      * We don't trace apply and call with a primitive 'this', which is the
      * first positional parameter.
      */
     if (argc > 0 && !vp[2].isObject())
         return record_JSOP_CALL();
@@ -14343,18 +14241,18 @@ TraceRecorder::record_JSOP_ENDITER()
 
     return ARECORD_CONTINUE;
 }
 
 #if JS_BITS_PER_WORD == 32
 JS_REQUIRES_STACK void
 TraceRecorder::storeMagic(JSWhyMagic why, nanojit::LIns *addr_ins, ptrdiff_t offset, AccSet accSet)
 {
-    lir->insStore(INS_CONSTU(why), addr_ins, offset + sPayloadOffset, accSet);
-    lir->insStore(INS_CONSTU(JSVAL_TAG_MAGIC), addr_ins, offset + sTagOffset, accSet);
+    lir->insStore(INS_MAGIC_WHY(why), addr_ins, offset + sPayloadOffset, accSet);
+    lir->insStore(INS_MAGIC_WHY(JSVAL_TAG_MAGIC), addr_ins, offset + sTagOffset, accSet);
 }
 #elif JS_BITS_PER_WORD == 64
 JS_REQUIRES_STACK void
 TraceRecorder::storeMagic(JSWhyMagic why, nanojit::LIns *addr_ins, ptrdiff_t offset, AccSet accSet)
 {
     LIns *magic = INS_CONSTQWORD(BUILD_JSVAL(JSVAL_TAG_MAGIC, why));
     lir->insStore(magic, addr_ins, offset, accSet);
 }
@@ -14951,21 +14849,21 @@ TraceRecorder::record_JSOP_LAMBDA()
                  * Note that we have not yet pushed obj as the final argument,
                  * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
                  * is the callee for this JSOP_CALL.
                  */
                 const Value &cref = cx->regs->sp[1 - (iargc + 2)];
                 JSObject *callee;
 
                 if (IsFunctionObject(cref, &callee)) {
-                    JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
-                    FastNative fastNative = FUN_FAST_NATIVE(calleeFun);
-
-                    if ((iargc == 1 && fastNative == array_sort) ||
-                        (iargc == 2 && fastNative == str_replace)) {
+                    JSFunction *calleeFun = callee->getFunctionPrivate();
+                    Native native = calleeFun->maybeNative();
+
+                    if ((iargc == 1 && native == array_sort) ||
+                        (iargc == 2 && native == str_replace)) {
                         stack(0, INS_CONSTOBJ(FUN_OBJECT(fun)));
                         return ARECORD_CONTINUE;
                     }
                 }
             } else if (op2 == JSOP_NULL) {
                 pc2 += JSOP_NULL_LENGTH;
                 op2 = JSOp(*pc2);
 
@@ -15857,17 +15755,17 @@ TraceRecorder::record_JSOP_NEWARRAY()
 
     stack(-int(len), v_ins);
     return ARECORD_CONTINUE;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_HOLE()
 {
-    stack(0, INS_CONST(JS_ARRAY_HOLE));
+    stack(0, INS_MAGIC_WHY(JS_ARRAY_HOLE));
     return ARECORD_CONTINUE;
 }
 
 AbortableRecordingStatus
 TraceRecorder::record_JSOP_TRACE()
 {
     return ARECORD_CONTINUE;
 }
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -409,34 +409,16 @@ struct VMSideExit : public nanojit::Side
     int32_t calldepth;
     uint32 numGlobalSlots;
     uint32 numStackSlots;
     uint32 numStackSlotsBelowCurrentFrame;
     ExitType exitType;
     uintN lookupFlags;
     unsigned hitcount;
 
-    /*
-     * Ordinarily 0.  If a slow native function is atop the stack, the 1 bit is
-     * set if constructing and the other bits are a pointer to the funobj.
-     */
-    uintptr_t nativeCalleeWord;
-
-    JSObject * nativeCallee() {
-        return (JSObject *) (nativeCalleeWord & ~1);
-    }
-
-    bool constructing() {
-        return bool(nativeCalleeWord & 1);
-    }
-
-    void setNativeCallee(JSObject *callee, bool constructing) {
-        nativeCalleeWord = uintptr_t(callee) | (constructing ? 1 : 0);
-    }
-
     inline JSValueType* stackTypeMap() {
         return (JSValueType*)(this + 1);
     }
 
     inline JSValueType& stackType(unsigned i) {
         JS_ASSERT(i < numStackSlots);
         return stackTypeMap()[i];
     }
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -97,39 +97,29 @@ ArrayBuffer::class_finalize(JSContext *c
         abuf->freeStorage(cx);
     delete abuf;
 }
 
 /*
  * new ArrayBuffer(byteLength)
  */
 JSBool
-ArrayBuffer::class_constructor(JSContext *cx, JSObject *obj,
-                               uintN argc, Value *argv, Value *rval)
+ArrayBuffer::class_constructor(JSContext *cx, uintN argc, Value *vp)
 {
-    if (!JS_IsConstructing(cx)) {
-        obj = NewBuiltinClassInstance(cx, &ArrayBuffer::jsclass);
-        if (!obj)
-            return false;
-        rval->setObject(*obj);
-    }
-
-    return create(cx, obj, argc, argv, rval);
+    return create(cx, argc, JS_ARGV(cx, vp), vp);
 }
 
 bool
-ArrayBuffer::create(JSContext *cx, JSObject *obj,
-                    uintN argc, Value *argv, Value *rval)
+ArrayBuffer::create(JSContext *cx, uintN argc, Value *argv, Value *rval)
 {
-    if (!obj) {
-        obj = NewBuiltinClassInstance(cx, &ArrayBuffer::jsclass);
-        if (!obj)
-            return false;
-        rval->setObject(*obj);
-    }
+    /* N.B. there may not be an argv[-2]/argv[-1]. */
+
+    JSObject *obj = NewBuiltinClassInstance(cx, &ArrayBuffer::jsclass);
+    if (!obj)
+        return false;
 
     int32_t nbytes = 0;
     if (argc > 0) {
         if (!ValueToECMAInt32(cx, argv[0], &nbytes))
             return false;
     }
 
     if (nbytes < 0) {
@@ -150,16 +140,17 @@ ArrayBuffer::create(JSContext *cx, JSObj
     }
 
     if (!abuf->allocateStorage(cx, nbytes)) {
         delete abuf;
         return false;
     }
 
     obj->setPrivate(abuf);
+    rval->setObject(*obj);
     return true;
 }
 
 bool
 ArrayBuffer::allocateStorage(JSContext *cx, uint32 nbytes)
 {
     JS_ASSERT(data == 0);
 
@@ -708,42 +699,30 @@ class TypedArrayTemplate
 
     /*
      * new [Type]Array(length)
      * new [Type]Array(otherTypedArray)
      * new [Type]Array(JSArray)
      * new [Type]Array(ArrayBuffer, [optional] byteOffset, [optional] length)
      */
     static JSBool
-    class_constructor(JSContext *cx, JSObject *obj,
-                      uintN argc, Value *argv, Value *rval)
+    class_constructor(JSContext *cx, uintN argc, Value *vp)
     {
-        //
-        // Note: this is a constructor for slowClass, not fastClass!
-        //
-
-        if (!JS_IsConstructing(cx)) {
-            obj = NewBuiltinClassInstance(cx, slowClass());
-            if (!obj)
-                return false;
-            rval->setObject(*obj);
-        }
-
-        return create(cx, obj, argc, argv, rval);
+        /* N.B. this is a constructor for slowClass, not fastClass! */
+        return create(cx, argc, JS_ARGV(cx, vp), vp);
     }
 
-    static bool
-    create(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
+    static JSBool
+    create(JSContext *cx, uintN argc, Value *argv, Value *rval)
     {
-        if (!obj) {
-            obj = NewBuiltinClassInstance(cx, slowClass());
-            if (!obj)
-                return false;
-            rval->setObject(*obj);
-        }
+        /* N.B. there may not be an argv[-2]/argv[-1]. */
+
+        JSObject *obj = NewBuiltinClassInstance(cx, slowClass());
+        if (!obj)
+            return false;
 
         ThisTypeArray *tarray = 0;
 
         // figure out the type of the first argument;
         // no args is treated like an int arg of 0.
         if (argc == 0 || argv[0].isInt32()) {
             int32 len = 0;
 
@@ -802,16 +781,17 @@ class TypedArrayTemplate
             }
         } else {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                                  JSMSG_TYPED_ARRAY_BAD_ARGS);
             return false;
         }
 
         makeFastWithPrivate(cx, obj, tarray);
+        rval->setObject(*obj);
         return true;
     }
 
     static void
     class_finalize(JSContext *cx, JSObject *obj)
     {
         ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
         delete tarray;
@@ -1336,22 +1316,21 @@ class TypedArrayTemplate
 
         length = count;
         return true;
     }
 
     bool
     createBufferWithByteLength(JSContext *cx, int32 bytes)
     {
-        Value argv = Int32Value(bytes);
-        AutoValueRooter tvr(cx);
-        if (!ArrayBuffer::create(cx, NULL, 1, &argv, tvr.addr()))
+        Value arg = Int32Value(bytes), rval;
+        if (!ArrayBuffer::create(cx, 1, &arg, &rval))
             return false;
 
-        JSObject *obj = &tvr.value().toObject();
+        JSObject *obj = &rval.toObject();
 
         bufferJS = obj;
         buffer = ArrayBuffer::fromJSObject(obj);
 
         byteOffset = 0;
         byteLength = bytes;
         data = buffer->data;
 
@@ -1631,57 +1610,52 @@ js_IsTypedArray(JSObject *obj)
     Class *clasp = obj->getClass();
     return clasp >= &TypedArray::fastClasses[0] &&
            clasp <  &TypedArray::fastClasses[TypedArray::TYPE_MAX];
 }
 
 JS_FRIEND_API(JSObject *)
 js_CreateArrayBuffer(JSContext *cx, jsuint nbytes)
 {
-    Value vals[2];
-    vals[0].setNumber(nbytes);
-    vals[1].setUndefined();
-
-    AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vals), vals);
-    if (!ArrayBuffer::create(cx, NULL, 1, &vals[0], &vals[1]))
+    Value arg = NumberValue(nbytes), rval;
+    if (!ArrayBuffer::create(cx, 1, &arg, &rval))
         return NULL;
-
-    return &vals[1].toObject();
+    return &rval.toObject();
 }
 
 static inline JSBool
 TypedArrayConstruct(JSContext *cx, jsint atype, uintN argc, Value *argv, Value *rv)
 {
     switch (atype) {
       case TypedArray::TYPE_INT8:
-        return !!Int8Array::create(cx, NULL, argc, argv, rv);
+        return Int8Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_UINT8:
-        return !!Uint8Array::create(cx, NULL, argc, argv, rv);
+        return Uint8Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_INT16:
-        return !!Int16Array::create(cx, NULL, argc, argv, rv);
+        return Int16Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_UINT16:
-        return !!Uint16Array::create(cx, NULL, argc, argv, rv);
+        return Uint16Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_INT32:
-        return !!Int32Array::create(cx, NULL, argc, argv, rv);
+        return Int32Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_UINT32:
-        return !!Uint32Array::create(cx, NULL, argc, argv, rv);
+        return Uint32Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_FLOAT32:
-        return !!Float32Array::create(cx, NULL, argc, argv, rv);
+        return Float32Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_FLOAT64:
-        return !!Float64Array::create(cx, NULL, argc, argv, rv);
+        return Float64Array::create(cx, argc, argv, rv);
 
       case TypedArray::TYPE_UINT8_CLAMPED:
-        return !!Uint8ClampedArray::create(cx, NULL, argc, argv, rv);
+        return Uint8ClampedArray::create(cx, argc, argv, rv);
 
       default:
         JS_NOT_REACHED("shouldn't have gotten here");
         return false;
     }
 }
 
 JS_FRIEND_API(JSObject *)
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -57,21 +57,19 @@ namespace js {
  */
 struct JS_FRIEND_API(ArrayBuffer) {
     static Class jsclass;
     static JSPropertySpec jsprops[];
 
     static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
     static void class_finalize(JSContext *cx, JSObject *obj);
 
-    static JSBool class_constructor(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
-                                    Value *rval);
+    static JSBool class_constructor(JSContext *cx, uintN argc, Value *vp);
 
-    static bool create(JSContext *cx, JSObject *obj, uintN argc,
-                       Value *argv, Value *rval);
+    static bool create(JSContext *cx, uintN argc, Value *argv, Value *rval);
 
     static ArrayBuffer *fromJSObject(JSObject *obj);
 
     ArrayBuffer()
         : data(0), byteLength()
     {
     }
 
--- a/js/src/jsval.h
+++ b/js/src/jsval.h
@@ -217,17 +217,17 @@ typedef uint64 JSValueShiftedTag;
 #define JSVAL_SHIFTED_TAG_OBJECT     (((uint64)JSVAL_TAG_OBJECT)     << JSVAL_TAG_SHIFT)
 
 #endif  /* JS_BITS_PER_WORD */
 #endif  /* defined(__cplusplus) && !defined(__SUNPRO_CC) */
 
 #define JSVAL_LOWER_INCL_TYPE_OF_OBJ_OR_NULL_SET        JSVAL_TYPE_NULL
 #define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET          JSVAL_TYPE_OBJECT
 #define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET             JSVAL_TYPE_INT32
-#define JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET            JSVAL_TYPE_STRING
+#define JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET        JSVAL_TYPE_MAGIC
 #define JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET              JSVAL_TYPE_OBJECT
 #define JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET            JSVAL_TYPE_FUNOBJ
 
 #if JS_BITS_PER_WORD == 32
 
 #define JSVAL_TYPE_TO_TAG(type)      ((JSValueTag)(JSVAL_TAG_CLEAR | (type)))
 
 #define JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET         JSVAL_TAG_NULL
@@ -240,30 +240,30 @@ typedef uint64 JSValueShiftedTag;
 #define JSVAL_PAYLOAD_MASK           0x00007FFFFFFFFFFFLL
 #define JSVAL_TAG_MASK               0xFFFF800000000000LL
 #define JSVAL_TYPE_TO_TAG(type)      ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
 #define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
 
 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET  JSVAL_SHIFTED_TAG_NULL
 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET    JSVAL_SHIFTED_TAG_OBJECT
 #define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET       JSVAL_SHIFTED_TAG_UNDEFINED
+#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET  JSVAL_SHIFTED_TAG_MAGIC
 #define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET      JSVAL_SHIFTED_TAG_STRING
 
 #endif /* JS_BITS_PER_WORD */
 
 typedef enum JSWhyMagic
 {
     JS_ARRAY_HOLE,               /* a hole in a dense array */
     JS_ARGS_HOLE,                /* a hole in the args object's array */
     JS_NATIVE_ENUMERATE,         /* indicates that a custom enumerate hook forwarded
                                   * to js_Enumerate, which really means the object can be
                                   * enumerated like a native object. */
     JS_NO_ITER_VALUE,            /* there is not a pending iterator value */
     JS_GENERATOR_CLOSING,        /* exception value thrown when closing a generator */
-    JS_FAST_CONSTRUCTOR,         /* 'this' value for fast natives invoked with 'new' */
     JS_NO_CONSTANT,              /* compiler sentinel value */
     JS_THIS_POISON,              /* used in debug builds to catch tracing errors */
     JS_SERIALIZE_NO_NODE,        /* an empty subnode in the AST serializer */
     JS_GENERIC_MAGIC             /* for local use */
 } JSWhyMagic;
 
 typedef struct JSString JSString;
 typedef struct JSObject JSObject;
@@ -429,16 +429,29 @@ BOOLEAN_TO_JSVAL_IMPL(JSBool b)
 {
     jsval_layout l;
     l.s.tag = JSVAL_TAG_BOOLEAN;
     l.s.payload.boo = b;
     return l;
 }
 
 static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_MAGIC_IMPL(jsval_layout l)
+{
+    return l.s.tag == JSVAL_TAG_MAGIC;
+}
+
+static JS_ALWAYS_INLINE JSObject *
+MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
+{
+    JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
+    return l.s.payload.obj;
+}
+
+static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
 {
     return l.s.tag == JSVAL_TAG_OBJECT;
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
 {
@@ -457,16 +470,17 @@ JSVAL_TO_OBJECT_IMPL(jsval_layout l)
 {
     return l.s.payload.obj;
 }
 
 static JS_ALWAYS_INLINE jsval_layout
 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
 {
     jsval_layout l;
+    JS_ASSERT(obj);
     l.s.tag = JSVAL_TAG_OBJECT;
     l.s.payload.obj = obj;
     return l;
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_NULL_IMPL(jsval_layout l)
 {
@@ -605,16 +619,31 @@ static JS_ALWAYS_INLINE jsval_layout
 BOOLEAN_TO_JSVAL_IMPL(JSBool b)
 {
     jsval_layout l;
     l.asBits = ((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
     return l;
 }
 
 static JS_ALWAYS_INLINE JSBool
+JSVAL_IS_MAGIC_IMPL(jsval_layout l)
+{
+    return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
+}
+
+static JS_ALWAYS_INLINE JSObject *
+MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
+{
+    JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
+    uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
+    JS_ASSERT((ptrBits >> JSVAL_TAG_SHIFT) == 0);
+    return (JSObject *)ptrBits;
+}
+
+static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
 {
     return l.asBits < JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET;
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_OBJECT_IMPL(jsval_layout l)
 {
@@ -636,16 +665,17 @@ JSVAL_TO_OBJECT_IMPL(jsval_layout l)
     JS_ASSERT((ptrBits & 0x7) == 0);
     return (JSObject *)ptrBits;
 }
 
 static JS_ALWAYS_INLINE jsval_layout
 OBJECT_TO_JSVAL_IMPL(JSObject *obj)
 {
     jsval_layout l;
+    JS_ASSERT(obj);
     uint64 objBits = (uint64)obj;
     JS_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
     l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
     return l;
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_NULL_IMPL(jsval_layout l)
--- a/js/src/jsvalue.h
+++ b/js/src/jsvalue.h
@@ -130,31 +130,34 @@ JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layou
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
 {
     return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
 }
 
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
-    return l.s.tag == JSVAL_TAG_MAGIC;
-}
-
 static JS_ALWAYS_INLINE jsval_layout
 MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
 {
     jsval_layout l;
     l.s.tag = JSVAL_TAG_MAGIC;
     l.s.payload.why = why;
     return l;
 }
 
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_TO_JSVAL_IMPL(JSObject *obj)
+{
+    jsval_layout l;
+    l.s.tag = JSVAL_TAG_MAGIC;
+    l.s.payload.obj = obj;
+    return l;
+}
+
 static JS_ALWAYS_INLINE JSBool
 JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
 {
     JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
     return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
 }
 
 static JS_ALWAYS_INLINE jsval_layout
@@ -220,30 +223,32 @@ JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layou
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
 {
     return l.asBits == (((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
 }
 
-static JS_ALWAYS_INLINE JSBool
-JSVAL_IS_MAGIC_IMPL(jsval_layout l)
-{
-    return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
-}
-
 static JS_ALWAYS_INLINE jsval_layout
 MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
 {
     jsval_layout l;
     l.asBits = ((uint64)(uint32)why) | JSVAL_SHIFTED_TAG_MAGIC;
     return l;
 }
 
+static JS_ALWAYS_INLINE jsval_layout
+MAGIC_TO_JSVAL_IMPL(JSObject *obj)
+{
+    jsval_layout l;
+    l.asBits = ((uint64)obj) | JSVAL_SHIFTED_TAG_MAGIC;
+    return l;
+}
+
 static JS_ALWAYS_INLINE JSBool
 JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
 {
     uint64 lbits = lhs.asBits, rbits = rhs.asBits;
     return (lbits <= JSVAL_TAG_MAX_DOUBLE && rbits <= JSVAL_TAG_MAX_DOUBLE) ||
            (((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
 }
 
@@ -286,17 +291,17 @@ JS_STATIC_ASSERT((JSVAL_TYPE_FUNOBJ & 0x
 #endif
 
 static JS_ALWAYS_INLINE jsval_layout
 BOX_NON_DOUBLE_JSVAL(JSValueType type, uint64 *slot)
 {
     /* N.B. for 32-bit payloads, the high 32 bits of the slot are trash. */
     jsval_layout l;
     JS_ASSERT(type > JSVAL_TYPE_DOUBLE && type <= JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET);
-    uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_GCTHING_SET);
+    uint32 isI32 = (uint32)(type < JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET);
     uint32 shift = isI32 * 32;
     uint64 mask = ((uint64)-1) >> shift;
     uint64 payload = *slot & mask;
     l.asBits = payload | JSVAL_TYPE_TO_SHIFTED_TAG(type & 0xF);
     return l;
 }
 
 static JS_ALWAYS_INLINE void
@@ -317,60 +322,80 @@ class Value
   public:
     /*
      * N.B. the default constructor leaves Value unitialized. Adding a default
      * constructor prevents Value from being stored in a union.
      */
 
     /*** Mutatators ***/
 
+    JS_ALWAYS_INLINE
     void setNull() {
         data.asBits = JSVAL_BITS(JSVAL_NULL);
     }
 
+    JS_ALWAYS_INLINE
     void setUndefined() {
         data.asBits = JSVAL_BITS(JSVAL_VOID);
     }
 
+    JS_ALWAYS_INLINE
     void setInt32(int32 i) {
         data = INT32_TO_JSVAL_IMPL(i);
     }
 
+    JS_ALWAYS_INLINE
     int32 &getInt32Ref() {
         JS_ASSERT(isInt32());
         return data.s.payload.i32;
     }
 
+    JS_ALWAYS_INLINE
     void setDouble(double d) {
         data = DOUBLE_TO_JSVAL_IMPL(d);
     }
 
+    JS_ALWAYS_INLINE
     double &getDoubleRef() {
         JS_ASSERT(isDouble());
         return data.asDouble;
     }
 
+    JS_ALWAYS_INLINE
     void setString(JSString *str) {
         data = STRING_TO_JSVAL_IMPL(str);
     }
 
+    JS_ALWAYS_INLINE
     void setObject(JSObject &obj) {
         JS_ASSERT(&obj != NULL);
         data = OBJECT_TO_JSVAL_IMPL(&obj);
     }
 
+    JS_ALWAYS_INLINE
     void setBoolean(bool b) {
         data = BOOLEAN_TO_JSVAL_IMPL(b);
     }
 
+    JS_ALWAYS_INLINE
     void setMagic(JSWhyMagic why) {
         data = MAGIC_TO_JSVAL_IMPL(why);
     }
 
     JS_ALWAYS_INLINE
+    void setMagicWithObjectOrNullPayload(JSObject *obj) {
+        data = MAGIC_TO_JSVAL_IMPL(obj);
+    }
+
+    JS_ALWAYS_INLINE
+    JSObject *getMagicObjectOrNullPayload() const {
+        return MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(data);
+    }
+
+    JS_ALWAYS_INLINE
     void setNumber(uint32 ui) {
         if (ui > JSVAL_INT_MAX)
             setDouble((double)ui);
         else
             setInt32((int32)ui);
     }
 
     JS_ALWAYS_INLINE
@@ -393,238 +418,290 @@ class Value
     JS_ALWAYS_INLINE
     void setObjectOrUndefined(JSObject *arg) {
         if (arg)
             setObject(*arg);
         else
             setUndefined();
     }
 
+    JS_ALWAYS_INLINE
     void swap(Value &rhs) {
         uint64 tmp = rhs.data.asBits;
         rhs.data.asBits = data.asBits;
         data.asBits = tmp;
     }
 
     /*** Value type queries ***/
 
+    JS_ALWAYS_INLINE
     bool isUndefined() const {
         return JSVAL_IS_UNDEFINED_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isNull() const {
         return JSVAL_IS_NULL_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isNullOrUndefined() const {
         return isNull() || isUndefined();
     }
 
+    JS_ALWAYS_INLINE
     bool isInt32() const {
         return JSVAL_IS_INT32_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isInt32(int32 i32) const {
         return JSVAL_IS_SPECIFIC_INT32_IMPL(data, i32);
     }
 
+    JS_ALWAYS_INLINE
     bool isDouble() const {
         return JSVAL_IS_DOUBLE_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isNumber() const {
         return JSVAL_IS_NUMBER_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isString() const {
         return JSVAL_IS_STRING_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isObject() const {
         return JSVAL_IS_OBJECT_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isPrimitive() const {
         return JSVAL_IS_PRIMITIVE_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isObjectOrNull() const {
         return JSVAL_IS_OBJECT_OR_NULL_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isGCThing() const {
         return JSVAL_IS_GCTHING_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isBoolean() const {
         return JSVAL_IS_BOOLEAN_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isTrue() const {
         return JSVAL_IS_SPECIFIC_BOOLEAN(data, true);
     }
 
+    JS_ALWAYS_INLINE
     bool isFalse() const {
         return JSVAL_IS_SPECIFIC_BOOLEAN(data, false);
     }
 
+    JS_ALWAYS_INLINE
     bool isMagic() const {
         return JSVAL_IS_MAGIC_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool isMagic(JSWhyMagic why) const {
         JS_ASSERT_IF(isMagic(), data.s.payload.why == why);
         return JSVAL_IS_MAGIC_IMPL(data);
     }
 
+#if JS_BITS_PER_WORD == 64
+    JS_ALWAYS_INLINE
+    bool hasPtrPayload() const {
+        return data.asBits >= JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET;
+    }
+#endif
+
+    JS_ALWAYS_INLINE
     bool isMarkable() const {
         return JSVAL_IS_TRACEABLE_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     int32 gcKind() const {
         JS_ASSERT(isMarkable());
         return JSVAL_TRACE_KIND_IMPL(data);
     }
 
 #ifdef DEBUG
+    JS_ALWAYS_INLINE
     JSWhyMagic whyMagic() const {
         JS_ASSERT(isMagic());
         return data.s.payload.why;
     }
 #endif
 
     /*** Comparison ***/
 
+    JS_ALWAYS_INLINE
     bool operator==(const Value &rhs) const {
         return data.asBits == rhs.data.asBits;
     }
 
+    JS_ALWAYS_INLINE
     bool operator!=(const Value &rhs) const {
         return data.asBits != rhs.data.asBits;
     }
 
+    JS_ALWAYS_INLINE
     friend bool SameType(const Value &lhs, const Value &rhs) {
         return JSVAL_SAME_TYPE_IMPL(lhs.data, rhs.data);
     }
 
     /*** Extract the value's typed payload ***/
 
+    JS_ALWAYS_INLINE
     int32 toInt32() const {
         JS_ASSERT(isInt32());
         return JSVAL_TO_INT32_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     double toDouble() const {
         JS_ASSERT(isDouble());
         return data.asDouble;
     }
 
+    JS_ALWAYS_INLINE
     double toNumber() const {
         JS_ASSERT(isNumber());
         return isDouble() ? toDouble() : double(toInt32());
     }
 
+    JS_ALWAYS_INLINE
     JSString *toString() const {
         JS_ASSERT(isString());
         return JSVAL_TO_STRING_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     JSObject &toObject() const {
         JS_ASSERT(isObject());
         return *JSVAL_TO_OBJECT_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     JSObject *toObjectOrNull() const {
         JS_ASSERT(isObjectOrNull());
         return JSVAL_TO_OBJECT_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     void *asGCThing() const {
         JS_ASSERT(isGCThing());
         return JSVAL_TO_GCTHING_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     bool toBoolean() const {
         JS_ASSERT(isBoolean());
         return JSVAL_TO_BOOLEAN_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     uint32 payloadAsRawUint32() const {
         JS_ASSERT(!isDouble());
         return data.s.payload.u32;
     }
 
+    JS_ALWAYS_INLINE
     uint64 asRawBits() const {
         return data.asBits;
     }
 
     /*
      * In the extract/box/unbox functions below, "NonDouble" means this
      * functions must not be called on a value that is a double. This allows
      * these operations to be implemented more efficiently, since doubles
      * generally already require special handling by the caller.
      */
+    JS_ALWAYS_INLINE
     JSValueType extractNonDoubleType() const {
         return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     JSValueTag extractNonDoubleTag() const {
         return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     void unboxNonDoubleTo(uint64 *out) const {
         UNBOX_NON_DOUBLE_JSVAL(data, out);
     }
 
+    JS_ALWAYS_INLINE
     void boxNonDoubleFrom(JSValueType type, uint64 *out) {
         data = BOX_NON_DOUBLE_JSVAL(type, out);
     }
 
     /*
      * The trace-jit specializes JSVAL_TYPE_OBJECT into JSVAL_TYPE_FUNOBJ and
      * JSVAL_TYPE_NONFUNOBJ. Since these two operations just return the type of
      * a value, the caller must handle JSVAL_TYPE_OBJECT separately.
      */
+    JS_ALWAYS_INLINE
     JSValueType extractNonDoubleObjectTraceType() const {
         JS_ASSERT(!isObject());
         return JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     JSValueTag extractNonDoubleObjectTraceTag() const {
         JS_ASSERT(!isObject());
         return JSVAL_EXTRACT_NON_DOUBLE_TAG_IMPL(data);
     }
 
     /*
      * Private API
      *
      * Private setters/getters allow the caller to read/write arbitrary types
      * that fit in the 64-bit payload. It is the caller's responsibility, after
      * storing to a value with setPrivateX to read only using getPrivateX.
      * Privates values are given a type type which ensures they are not marked.
      */
 
+    JS_ALWAYS_INLINE
     void setPrivate(void *ptr) {
         data = PRIVATE_PTR_TO_JSVAL_IMPL(ptr);
     }
 
+    JS_ALWAYS_INLINE
     void *toPrivate() const {
         JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
         return JSVAL_TO_PRIVATE_PTR_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     void setPrivateUint32(uint32 ui) {
         data = PRIVATE_UINT32_TO_JSVAL_IMPL(ui);
     }
 
+    JS_ALWAYS_INLINE
     uint32 toPrivateUint32() const {
         JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(data));
         return JSVAL_TO_PRIVATE_UINT32_IMPL(data);
     }
 
+    JS_ALWAYS_INLINE
     uint32 &getPrivateUint32Ref() {
         JS_ASSERT(isDouble());
         return data.s.payload.u32;
     }
 
   private:
     void staticAssertions() {
         JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
@@ -759,19 +836,17 @@ static inline Value *        Valueify(js
 static inline const Value *  Valueify(const jsval *v)  { return (const Value *)v; }
 static inline Value **       Valueify(jsval **v)       { return (Value **)v; }
 static inline Value &        Valueify(jsval &v)        { return (Value &)v; }
 static inline const Value &  Valueify(const jsval &v)  { return (const Value &)v; }
 
 struct Class;
 
 typedef JSBool
-(* Native)(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
-typedef JSBool
-(* FastNative)(JSContext *cx, uintN argc, Value *vp);
+(* Native)(JSContext *cx, uintN argc, Value *vp);
 typedef JSBool
 (* PropertyOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 typedef JSBool
 (* ConvertOp)(JSContext *cx, JSObject *obj, JSType type, Value *vp);
 typedef JSBool
 (* NewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                    Value *statep, jsid *idp);
 typedef JSBool
@@ -786,36 +861,32 @@ typedef JSBool
                  PropertyOp getter, PropertyOp setter, uintN attrs);
 typedef JSBool
 (* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
 typedef JSBool
 (* CallOp)(JSContext *cx, uintN argc, Value *vp);
 
 static inline Native            Valueify(JSNative f)          { return (Native)f; }
 static inline JSNative          Jsvalify(Native f)            { return (JSNative)f; }
-static inline FastNative        Valueify(JSFastNative f)      { return (FastNative)f; }
-static inline JSFastNative      Jsvalify(FastNative f)        { return (JSFastNative)f; }
 static inline PropertyOp        Valueify(JSPropertyOp f)      { return (PropertyOp)f; }
 static inline JSPropertyOp      Jsvalify(PropertyOp f)        { return (JSPropertyOp)f; }
 static inline ConvertOp         Valueify(JSConvertOp f)       { return (ConvertOp)f; }
 static inline JSConvertOp       Jsvalify(ConvertOp f)         { return (JSConvertOp)f; }
 static inline NewEnumerateOp    Valueify(JSNewEnumerateOp f)  { return (NewEnumerateOp)f; }
 static inline JSNewEnumerateOp  Jsvalify(NewEnumerateOp f)    { return (JSNewEnumerateOp)f; }
 static inline HasInstanceOp     Valueify(JSHasInstanceOp f)   { return (HasInstanceOp)f; }
 static inline JSHasInstanceOp   Jsvalify(HasInstanceOp f)     { return (JSHasInstanceOp)f; }
 static inline CheckAccessOp     Valueify(JSCheckAccessOp f)   { return (CheckAccessOp)f; }
 static inline JSCheckAccessOp   Jsvalify(CheckAccessOp f)     { return (JSCheckAccessOp)f; }
 static inline EqualityOp        Valueify(JSEqualityOp f);     /* Same type as JSHasInstanceOp */
 static inline JSEqualityOp      Jsvalify(EqualityOp f);       /* Same type as HasInstanceOp */
 static inline DefinePropOp      Valueify(JSDefinePropOp f)    { return (DefinePropOp)f; }
 static inline JSDefinePropOp    Jsvalify(DefinePropOp f)      { return (JSDefinePropOp)f; }
 static inline PropertyIdOp      Valueify(JSPropertyIdOp f);   /* Same type as JSPropertyOp */
 static inline JSPropertyIdOp    Jsvalify(PropertyIdOp f);     /* Same type as PropertyOp */
-static inline CallOp            Valueify(JSCallOp f);         /* Same type as JSFastNative */
-static inline JSCallOp          Jsvalify(CallOp f);           /* Same type as FastNative */
 
 static const PropertyOp    PropertyStub  = (PropertyOp)JS_PropertyStub;
 static const JSEnumerateOp EnumerateStub = JS_EnumerateStub;
 static const JSResolveOp   ResolveStub   = JS_ResolveStub;
 static const ConvertOp     ConvertStub   = (ConvertOp)JS_ConvertStub;
 static const JSFinalizeOp  FinalizeStub  = JS_FinalizeStub;
 
 #define JS_CLASS_MEMBERS                                                      \
@@ -880,34 +951,24 @@ struct ObjectOps {
 
 struct Class {
     JS_CLASS_MEMBERS;
     ClassExtension      ext;
     ObjectOps           ops;
     uint8               pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
                             sizeof(ClassExtension) - sizeof(ObjectOps)];
 
-    /* Flag indicating that Class::call is a fast native. */
-    static const uint32 CALL_IS_FAST = JSCLASS_INTERNAL_FLAG1;
-
     /* Class is not native and its map is not a scope. */
     static const uint32 NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
 
     bool isNative() const {
         return !(flags & NON_NATIVE);
     }
 };
 
-/* Helper to initialize Class::call when Class::CALL_IS_FAST. */
-inline Native
-CastCallOpAsNative(CallOp op)
-{
-    return reinterpret_cast<Native>(op);
-}
-
 JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
 JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
 JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
 JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
 JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
@@ -941,16 +1002,48 @@ JS_STATIC_ASSERT(sizeof(JSPropertyDescri
 static JS_ALWAYS_INLINE JSClass *              Jsvalify(Class *c)                { return (JSClass *)c; }
 static JS_ALWAYS_INLINE Class *                Valueify(JSClass *c)              { return (Class *)c; }
 static JS_ALWAYS_INLINE JSPropertyDescriptor * Jsvalify(PropertyDescriptor *p) { return (JSPropertyDescriptor *) p; }
 static JS_ALWAYS_INLINE PropertyDescriptor *   Valueify(JSPropertyDescriptor *p) { return (PropertyDescriptor *) p; }
 
 /******************************************************************************/
 
 /*
+ * Any cast-via-function-call, inlined or not, will cause initialization to
+ * happen at startup, rather than statically, so just cast in release builds.
+ */
+#ifdef DEBUG
+
+static inline JSNative JsvalifyNative(Native n)   { return (JSNative)n; }
+static inline JSNative JsvalifyNative(JSNative n) { return n; }
+static inline Native ValueifyNative(JSNative n)   { return (Native)n; }
+static inline Native ValueifyNative(Native n)     { return n; }
+
+# define JS_VALUEIFY_NATIVE(n) js::ValueifyNative(n)
+# define JS_JSVALIFY_NATIVE(n) js::JsvalifyNative(n)
+
+#else
+
+# define JS_VALUEIFY_NATIVE(n) ((js::Native)n)
+# define JS_JSVALIFY_NATIVE(n) ((JSNative)n)
+
+#endif
+
+/*
+ * JSFunctionSpec uses JSAPI jsval in function signatures whereas the engine
+ * uses js::Value. To avoid widespread (JSNative) casting, have JS_FN perfom a
+ * type-safe cast.
+ */
+#undef JS_FN
+#define JS_FN(name,call,nargs,flags)                                          \
+     {name, JS_JSVALIFY_NATIVE(call), nargs, (flags) | JSFUN_STUB_GSOPS}
+
+/******************************************************************************/
+
+/*
  * In some cases (quickstubs) we want to take a value in whatever manner is
  * appropriate for the architecture and normalize to a const js::Value &. On
  * x64, passing a js::Value may cause the to unnecessarily be passed through
  * memory instead of registers, so jsval, which is a builtin uint64 is used.
  */
 #if JS_BITS_PER_WORD == 32
 typedef const js::Value *ValueArgType;
 
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -192,20 +192,19 @@ IsDeclared(const JSObject *obj)
 
     JS_ASSERT(obj->getClass() == &js_NamespaceClass);
     v = obj->getNamespaceDeclared();
     JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE);
     return v == JSVAL_TRUE;
 }
 
 static JSBool
-xml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-              jsval *rval)
-{
-    *rval = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argv[0]));
+xml_isXMLName(JSContext *cx, uintN argc, jsval *vp)
+{
+    *vp = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argc ? vp[2] : JSVAL_VOID));
     return JS_TRUE;
 }
 
 static inline bool
 AppendString(JSCharBuffer &cb, JSString *str)
 {
     const jschar *chars, *end;
     str->getCharsAndEnd(chars, end);
@@ -282,24 +281,24 @@ JS_FRIEND_DATA(Class) js_NamespaceClass 
 
 static JSPropertySpec namespace_props[] = {
     {js_prefix_str, 0, NAMESPACE_ATTRS, NamePrefix_getter, 0},
     {js_uri_str,    0, NAMESPACE_ATTRS, NameURI_getter,    0},
     {0,0,0,0,0}
 };
 
 static JSBool
-namespace_toString(JSContext *cx, uintN argc, jsval *vp)
+namespace_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
 
-    obj = JS_THIS_OBJECT(cx, vp);
-    if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass), vp + 2))
+    obj = ComputeThisFromVp(cx, vp);
+    if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass), Jsvalify(vp + 2)))
         return JS_FALSE;
-    *vp = obj->getNameURI();
+    *vp = Valueify(obj->getNameURI());
     return JS_TRUE;
 }
 
 static JSFunctionSpec namespace_methods[] = {
     JS_FN(js_toString_str,  namespace_toString,        0,0),
     JS_FS_END
 };
 
@@ -435,31 +434,31 @@ JS_FRIEND_DATA(Class) js_AnyNameClass = 
 
 static JSPropertySpec qname_props[] = {
     {js_uri_str,       0, QNAME_ATTRS, QNameNameURI_getter,   0},
     {js_localName_str, 0, QNAME_ATTRS, QNameLocalName_getter, 0},
     {0,0,0,0,0}
 };
 
 static JSBool
-qname_toString(JSContext *cx, uintN argc, jsval *vp)
+qname_toString(JSContext *cx, uintN argc, Value *vp)
 {
     JSObject *obj;
     Class *clasp;
     JSString *uri, *str, *qualstr;
     size_t length;
     jschar *chars;
 
-    obj = JS_THIS_OBJECT(cx, vp);
+    obj = ComputeThisFromVp(cx, vp);
     if (!obj)
         return JS_FALSE;
     clasp = obj->getClass();
     if (clasp != &js_AttributeNameClass &&
         clasp != &js_AnyNameClass &&
-        !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass), vp + 2)) {
+        !JS_InstanceOf(cx, obj, Jsvalify(&js_QNameClass), Jsvalify(vp + 2))) {
             return JS_FALSE;
     }
 
     uri = GetURI(obj);
     if (!uri) {
         /* No uri means wildcard qualifier. */
         str = ATOM_TO_STRING(cx->runtime->atomState.starQualifierAtom);
     } else if (uri->empty()) {
@@ -485,17 +484,17 @@ qname_toString(JSContext *cx, uintN argc
         chars[++length] = 0;
         str = js_NewString(cx, chars, length);
         if (!str) {
             cx->free(chars);
             return JS_FALSE;
         }
     }
 
-    *vp = STRING_TO_JSVAL(str);
+    vp->setString(str);
     return JS_TRUE;
 }
 
 static JSFunctionSpec qname_methods[] = {
     JS_FN(js_toString_str,  qname_toString,    0,0),
     JS_FS_END
 };
 
@@ -630,18 +629,18 @@ NamespaceHelper(JSContext *cx, JSObject 
             /* Namespace called with one Namespace argument is identity. */
             *rval = urival;
             return JS_TRUE;
         }
 
         obj = NewBuiltinClassInstance(cx, &js_NamespaceClass);
         if (!obj)
             return JS_FALSE;
-        *rval = OBJECT_TO_JSVAL(obj);
-    }
+    }
+    *rval = OBJECT_TO_JSVAL(obj);
     METER(xml_stats.xmlnamespace);
 
     empty = cx->runtime->emptyString;
     obj->setNamePrefix(STRING_TO_JSVAL(empty));
     obj->setNameURI(STRING_TO_JSVAL(empty));
 
     if (argc == 1 || argc == -1) {
         if (isNamespace) {
@@ -684,26 +683,25 @@ NamespaceHelper(JSContext *cx, JSObject 
             obj->setNamePrefix(JSVAL_VOID);
         } else {
             prefix = js_ValueToString(cx, Valueify(prefixval));
             if (!prefix)
                 return JS_FALSE;
             obj->setNamePrefix(STRING_TO_JSVAL(prefix));
         }
     }
-
     return JS_TRUE;
 }
 
 static JSBool
-Namespace(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
-{
-    return NamespaceHelper(cx,
-                           cx->isConstructing() ? obj : NULL,
-                           argc, Jsvalify(argv), Jsvalify(rval));
+Namespace(JSContext *cx, uintN argc, Value *vp)
+{
+    JSObject *thisobj = NULL;
+    (void)IsConstructing_PossiblyWithGivenThisObject(vp, &thisobj);
+    return NamespaceHelper(cx, thisobj, argc, Jsvalify(vp + 2), Jsvalify(vp));
 }
 
 /*
  * When argc is -1, it indicates argv is empty but the code should behave as
  * if argc is 1 and argv[0] is JSVAL_VOID.
  */
 static JSBool
 QNameHelper(JSContext *cx, JSObject *obj, Class *clasp, intN argc,
@@ -737,18 +735,18 @@ QNameHelper(JSContext *cx, JSObject *obj
 
         /*
          * Create and return a new QName or AttributeName object exactly as if
          * constructed.
          */
         obj = NewBuiltinClassInstance(cx, clasp);
         if (!obj)
             return JS_FALSE;
-        *rval = OBJECT_TO_JSVAL(obj);
-    }
+    }
+    *rval = OBJECT_TO_JSVAL(obj);
     METER(xml_stats.qname);
 
     if (isQName) {
         /* If namespace is not specified and name is a QName, clone it. */
         qn = JSVAL_TO_OBJECT(nameval);
         if (argc == 1) {
             uri = GetURI(qn);
             prefix = GetPrefix(qn);
@@ -824,28 +822,29 @@ QNameHelper(JSContext *cx, JSObject *obj
     }
 
 out:
     InitXMLQName(obj, uri, prefix, name);
     return JS_TRUE;
 }
 
 static JSBool
-QName(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
-{
-    return QNameHelper(cx, cx->isConstructing() ? obj : NULL,
-                       &js_QNameClass, argc, Jsvalify(argv), Jsvalify(rval));
+QName(JSContext *cx, uintN argc, Value *vp)
+{
+    JSObject *thisobj = NULL;
+    (void)IsConstructing_PossiblyWithGivenThisObject(vp, &thisobj);
+    return QNameHelper(cx, thisobj, &js_QNameClass, argc, Jsvalify(vp + 2), Jsvalify(vp));
 }
 
 static JSBool
-AttributeName(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
-              Value *rval)
-{
-    return QNameHelper(cx, cx->isConstructing() ? obj : NULL,
-                       &js_AttributeNameClass, argc, Jsvalify(argv), Jsvalify(rval));
+AttributeName(JSContext *cx, uintN argc, Value *vp)
+{
+    JSObject *thisobj = NULL;
+    (void)IsConstructing_PossiblyWithGivenThisObject(vp, &thisobj);
+    return QNameHelper(cx, thisobj, &js_AttributeNameClass, argc, Jsvalify(vp + 2), Jsvalify(vp));
 }
 
 /*
  * XMLArray library functions.
  */
 static JSBool
 namespace_identity(const void *a, const void *b)
 {
@@ -5066,17 +5065,18 @@ js_ConcatenateXML(JSContext *cx, JSObjec
     vp->setObject(*listobj);
 out:
     js_LeaveLocalRootScopeWithResult(cx, *vp);
     return ok;
 }
 
 JS_FRIEND_DATA(Class) js_XMLClass = {
     js_XML_str,
-    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
+    JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE |
+    JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
     PropertyStub,   /* addProperty */
     PropertyStub,   /* delProperty */
     PropertyStub,   /* getProperty */
     PropertyStub,   /* setProperty */
     EnumerateStub,
     ResolveStub,
     xml_convert,
     xml_finalize,
@@ -6814,85 +6814,84 @@ xml_defaultSettings(JSContext *cx, uintN
 static JSFunctionSpec xml_static_methods[] = {
     JS_FN("settings",         xml_settings,          0,0),
     JS_FN("setSettings",      xml_setSettings,       1,0),
     JS_FN("defaultSettings",  xml_defaultSettings,   0,0),
     JS_FS_END
 };
 
 static JSBool
-XML(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-    jsval v;
+XML(JSContext *cx, uintN argc, Value *vp)
+{
     JSXML *xml, *copy;
     JSObject *xobj, *vobj;
     Class *clasp;
 
-    v = argv[0];
+    jsval v = argc ? Jsvalify(vp[2]) : JSVAL_VOID;
+
     if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
         v = STRING_TO_JSVAL(cx->runtime->emptyString);
 
     xobj = ToXML(cx, v);
     if (!xobj)
         return JS_FALSE;
-    *rval = OBJECT_TO_JSVAL(xobj);
     xml = (JSXML *) xobj->getPrivate();
 
-    if (cx->isConstructing() && !JSVAL_IS_PRIMITIVE(v)) {
+    if (IsConstructing(vp) && !JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         clasp = vobj->getClass();
         if (clasp == &js_XMLClass ||
             (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) {
-            /* No need to lock obj, it's newly constructed and thread local. */
-            copy = DeepCopy(cx, xml, obj, 0);
+            copy = DeepCopy(cx, xml, NULL, 0);
             if (!copy)
                 return JS_FALSE;
-            JS_ASSERT(copy->object == obj);
-            *rval = OBJECT_TO_JSVAL(obj);
+            vp->setObject(*copy->object);
             return JS_TRUE;
         }
     }
+
+    vp->setObject(*xobj);
     return JS_TRUE;
 }
 
 static JSBool
-XMLList(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
-{
-    jsval v;
+XMLList(JSContext *cx, uintN argc, jsval *vp)
+{
     JSObject *vobj, *listobj;
     JSXML *xml, *list;
 
-    v = argv[0];
+    jsval v = argc ? vp[2] : JSVAL_VOID;
+
     if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
         v = STRING_TO_JSVAL(cx->runtime->emptyString);
 
-    if (cx->isConstructing() && !JSVAL_IS_PRIMITIVE(v)) {
+    if (IsConstructing(Valueify(vp)) && !JSVAL_IS_PRIMITIVE(v)) {
         vobj = JSVAL_TO_OBJECT(v);
         if (vobj->isXML()) {
             xml = (JSXML *) vobj->getPrivate();
             if (xml->xml_class == JSXML_CLASS_LIST) {
                 listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
                 if (!listobj)
                     return JS_FALSE;
-                *rval = OBJECT_TO_JSVAL(listobj);
+                *vp = OBJECT_TO_JSVAL(listobj);
 
                 list = (JSXML *) listobj->getPrivate();
                 if (!Append(cx, list, xml))
                     return JS_FALSE;
                 return JS_TRUE;
             }
         }
     }
 
     /* Toggle on XML support since the script has explicitly requested it. */
     listobj = ToXMLList(cx, v);
     if (!listobj)
         return JS_FALSE;
 
-    *rval = OBJECT_TO_JSVAL(listobj);
+    *vp = OBJECT_TO_JSVAL(listobj);
     return JS_TRUE;
 }
 
 #ifdef DEBUG_notme
 JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks);
 uint32  xml_serial;
 #endif
 
@@ -7074,17 +7073,17 @@ js_InitXMLClass(JSContext *cx, JSObject 
     Shape *shape;
     jsval cval, vp[3];
 
     /* Define the isXMLName function. */
     if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0))
         return NULL;
 
     /* Define the XML class constructor and prototype. */
-    proto = js_InitClass(cx, obj, NULL, &js_XMLClass, Valueify(XML), 1,
+    proto = js_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1,
                          NULL, xml_methods,
                          xml_static_props, xml_static_methods);
     if (!proto)
         return NULL;
 
     xml = js_NewXML(cx, JSXML_CLASS_TEXT);
     if (!xml)
         return NULL;
@@ -7113,17 +7112,17 @@ js_InitXMLClass(JSContext *cx, JSObject 
     /* Set default settings. */
     vp[0] = JSVAL_NULL;
     vp[1] = cval;
     vp[2] = JSVAL_VOID;
     if (!xml_setSettings(cx, 1, vp))
         return NULL;
 
     /* Define the XMLList function and give it the same prototype as XML. */
-    fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
+    fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, JSFUN_CONSTRUCTOR);
     if (!fun)
         return NULL;
     if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
                               JSPROP_READONLY | JSPROP_PERMANENT)) {
         return NULL;
     }
     return proto;
 }
@@ -7214,24 +7213,23 @@ js_GetFunctionNamespace(JSContext *cx, V
  * its v argument as the uri of a new Namespace, with "" as the prefix.  See
  * ECMA-357 12.1 and 12.1.1.  Note that if Set is called with a Namespace n,
  * the default XML namespace will be set to ("", n.uri).  So the uri string
  * is really the only usefully stored value of the default namespace.
  */
 JSBool
 js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
 {
-    JSStackFrame *fp;
     JSObject *ns, *obj, *tmp;
     jsval v;
 
-    fp = js_GetTopStackFrame(cx);
+    JSObject *scopeChain = JS_GetScopeChain(cx);
 
     obj = NULL;
-    for (tmp = fp->getScopeChain(); tmp; tmp = tmp->getParent()) {
+    for (tmp = scopeChain; tmp; tmp = tmp->getParent()) {
         Class *clasp = tmp->getClass();
         if (clasp == &js_BlockClass || clasp == &js_WithClass)
             continue;
         if (!tmp->getProperty(cx, JS_DEFAULT_XML_NAMESPACE_ID, Valueify(&v)))
             return JS_FALSE;
         if (!JSVAL_IS_PRIMITIVE(v)) {
             *vp = v;
             return JS_TRUE;
@@ -7332,20 +7330,19 @@ js_EscapeElementValue(JSContext *cx, JSS
 
 JSString *
 js_ValueToXMLString(JSContext *cx, const Value &v)
 {
     return ToXMLString(cx, Jsvalify(v), 0);
 }
 
 static JSBool
-anyname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-                 jsval *rval)
-{
-    *rval = ATOM_TO_JSVAL(cx->runtime->atomState.starAtom);
+anyname_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+    *vp = ATOM_TO_JSVAL(cx->runtime->atomState.starAtom);
     return JS_TRUE;
 }
 
 JSBool
 js_GetAnyName(JSContext *cx, jsid *idp)
 {
     JSRuntime *rt;
     JSObject *obj;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -392,25 +392,24 @@ stubs::SlowCall(VMFrame &f, uint32 argc)
             }
 
             if (!InlineCall(f, 0, &ret, argc))
                 THROWV(NULL);
 
             return ret;
         }
 
-        if (fun->isFastNative()) {
+        if (fun->isNative()) {
 #ifdef JS_MONOIC
 #ifdef JS_CPU_X86
-            ic::CallFastNative(cx, f.fp()->getScript(), mic, fun, false);
+            ic::CallNative(cx, f.fp()->getScript(), mic, fun, false);
 #endif
 #endif
 
-            FastNative fn = (FastNative)fun->u.n.native;
-            if (!fn(cx, argc, vp))
+            if (!fun->u.n.native(cx, argc, vp))
                 THROWV(NULL);
             return NULL;
         }
     }
 
     if (!Invoke(f.cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0))
         THROWV(NULL);
 
@@ -447,27 +446,26 @@ stubs::SlowNew(VMFrame &f, uint32 argc)
             void *ret;
             vp[1].setObject(*obj2);
             if (!InlineCall(f, JSFRAME_CONSTRUCTING, &ret, argc))
                 THROWV(NULL);
 
             return ret;
         }
 
-        if (fun->isFastConstructor()) {
+        if (fun->isConstructor()) {
 #ifdef JS_MONOIC
 #ifdef JS_CPU_X86
-            ic::CallFastNative(cx, f.fp()->getScript(), mic, fun, true);
+            ic::CallNative(cx, f.fp()->getScript(), mic, fun, true);
 #endif
 #endif
 
-            vp[1].setMagic(JS_FAST_CONSTRUCTOR);
+            vp[1].setMagicWithObjectOrNullPayload(NULL);
 
-            FastNative fn = (FastNative)fun->u.n.native;
-            if (!fn(cx, argc, vp))
+            if (!fun->u.n.native(cx, argc, vp))
                 THROWV(NULL);
             JS_ASSERT(!vp->isPrimitive());
 
             return NULL;
         }
     }
 
     if (!InvokeConstructor(cx, InvokeArgsAlreadyOnTheStack(vp, argc)))
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -224,29 +224,29 @@ ic::NativeCallCompiler::finish(JSScript 
     /* Patch all jumps with the correct target. */
     JSC::LinkBuffer linkmasm(result, masm.size());
 
     for (size_t i = 0; i < jumps.length(); i++)
         linkmasm.link(jumps[i].from, JSC::CodeLocationLabel(jumps[i].to));
 }
 
 void
-ic::CallFastNative(JSContext *cx, JSScript *script, MICInfo &mic, JSFunction *fun, bool isNew)
+ic::CallNative(JSContext *cx, JSScript *script, MICInfo &mic, JSFunction *fun, bool isNew)
 {
     if (mic.u.generated) {
         /* Already generated a MIC at this site, don't make another one. */
         return;
     }
     mic.u.generated = true;
 
-    JS_ASSERT(fun->isFastNative());
+    JS_ASSERT(fun->isNative());
     if (isNew)
-        JS_ASSERT(fun->isFastConstructor());
+        JS_ASSERT(fun->isConstructor());
 
-    FastNative fn = (FastNative)fun->u.n.native;
+    Native native = fun->u.n.native;
 
     typedef JSC::MacroAssembler::ImmPtr ImmPtr;
     typedef JSC::MacroAssembler::Imm32 Imm32;
     typedef JSC::MacroAssembler::Address Address;
     typedef JSC::MacroAssembler::Jump Jump;
 
     uint8 *start = (uint8*) mic.knownObject.executableAddress();
     uint8 *stubEntry = (uint8*) mic.stubEntry.executableAddress();
@@ -276,29 +276,31 @@ ic::CallFastNative(JSContext *cx, JSScri
     ncc.masm.sub32(Imm32(stackAdjustment), JSC::X86Registers::esp);
 
     /* Compute and push vp */
     uint32 vpOffset = sizeof(JSStackFrame) + mic.frameDepth * sizeof(jsval);
     ncc.masm.addPtr(Imm32(vpOffset), JSFrameReg, temp);
     ncc.masm.storePtr(temp, Address(JSC::X86Registers::esp, 0x8));
 
     if (isNew) {
-        /* Mark vp[1] as magic. */
-        ncc.masm.storeValue(MagicValue(JS_FAST_CONSTRUCTOR), Address(temp, sizeof(Value)));
+        /* Mark 'this' as magic. */
+        Value magicCtorThis;
+        magicCtorThis.setMagicWithObjectOrNullPayload(NULL);
+        ncc.masm.storeValue(magicCtorThis, Address(temp, sizeof(Value)));
     }
 
     /* Push argc */
     ncc.masm.store32(Imm32(mic.argc), Address(JSC::X86Registers::esp, 0x4));
 
     /* Push cx. The VMFrame is homed at the stack register, so adjust for the amount we pushed. */
     ncc.masm.loadPtr(FrameAddress(stackAdjustment + offsetof(VMFrame, cx)), temp);
     ncc.masm.storePtr(temp, Address(JSC::X86Registers::esp, 0));
 
     /* Do the call. */
-    ncc.masm.call(JS_FUNC_TO_DATA_PTR(void *, fn));
+    ncc.masm.call(JS_FUNC_TO_DATA_PTR(void *, native));
 
     /* Restore stack. */
     ncc.masm.add32(Imm32(stackAdjustment), JSC::X86Registers::esp);
 
 #if defined(JS_NO_FASTCALL) && defined(JS_CPU_X86)
     // Usually JaegerThrowpoline got called from return address.
     // So in JaegerThrowpoline without fastcall, esp was added by 8.
     // If we just want to jump there, we need to sub esp by 8 first.
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -153,17 +153,17 @@ class NativeCallCompiler
 
     /*
      * Finish up this native, and add an incoming jump from start
      * and an outgoing jump to fallthrough.
      */
     void finish(JSScript *script, uint8 *start, uint8 *fallthrough);
 };
 
-void CallFastNative(JSContext *cx, JSScript *script, MICInfo &mic, JSFunction *fun, bool isNew);
+void CallNative(JSContext *cx, JSScript *script, MICInfo &mic, JSFunction *fun, bool isNew);
 
 #endif /* JS_CPU_X86 */
 
 void PurgeMICs(JSContext *cx, JSScript *script);
 
 } /* namespace ic */
 } /* namespace mjit */
 } /* namespace js */
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1604,23 +1604,23 @@ stubs::LambdaJoinableForCall(VMFrame &f,
          * Note that we have not yet pushed obj as the final argument,
          * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
          * is the callee for this JSOP_CALL.
          */
         const Value &cref = f.regs.sp[1 - (iargc + 2)];
         JSObject *callee;
 
         if (IsFunctionObject(cref, &callee)) {
-            JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
-            FastNative fastNative = FUN_FAST_NATIVE(calleeFun);
+            JSFunction *calleeFun = callee->getFunctionPrivate();
+            Native native = calleeFun->maybeNative();
 
-            if (fastNative) {
-                if (iargc == 1 && fastNative == array_sort)
+            if (native) {
+                if (iargc == 1 && native == array_sort)
                     return obj;
-                if (iargc == 2 && fastNative == str_replace)
+                if (iargc == 2 && native == str_replace)
                     return obj;
             }
         }
     }
     return Lambda(f, fun);
 }
 
 JSObject * JS_FASTCALL
--- a/js/src/perf/jsperf.cpp
+++ b/js/src/perf/jsperf.cpp
@@ -45,32 +45,37 @@ using JS::PerfMeasurement;
 // You cannot forward-declare a static object in C++, so instead
 // we have to forward-declare the helper functions that refer to it.
 static PerfMeasurement* GetPM(JSContext* cx, JSObject* obj, const char* fname);
 static PerfMeasurement* GetPMFromThis(JSContext* cx, jsval* vp);
 
 // Constructor and destructor
 
 static JSBool
-pm_construct(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval)
+pm_construct(JSContext* cx, uintN argc, jsval* vp)
 {
     uint32 mask;
-    if (!JS_ConvertArguments(cx, argc, argv, "u", &mask))
+    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "u", &mask))
+        return JS_FALSE;
+
+    JSObject *obj = JS_NewObjectForConstructor(cx, vp);
+    if (!obj)
         return JS_FALSE;
 
     if (!JS_SealObject(cx, obj, JS_FALSE))
         return JS_FALSE;
 
     PerfMeasurement* p = new PerfMeasurement(PerfMeasurement::EventMask(mask));
     if (!p) {
         JS_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
 
     JS_SetPrivate(cx, obj, p);
+    *vp = OBJECT_TO_JSVAL(obj);
     return JS_TRUE;
 }
 
 static void
 pm_finalize(JSContext* cx, JSObject* obj)
 {
     delete (PerfMeasurement*) JS_GetPrivate(cx, obj);
 }
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -859,35 +859,37 @@ ProcessArgs(JSContext *cx, JSObject *obj
     }
 
     if (filename || isInteractive)
         Process(cx, obj, filename, forceTTY);
     return gExitCode;
 }
 
 static JSBool
-Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Version(JSContext *cx, uintN argc, 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])));
+        *vp = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
     else
-        *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+        *vp = INT_TO_JSVAL(JS_GetVersion(cx));
     return JS_TRUE;
 }
 
 static JSBool
-Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Options(JSContext *cx, uintN argc, jsval *vp)
 {
     uint32 optset, flag;
     JSString *str;
     const char *opt;
     char *names;
     JSBool found;
 
     optset = 0;
+    jsval *argv = JS_ARGV(cx, vp);
     for (uintN i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
         opt = JS_GetStringBytes(str);
         if (!opt)
             return JS_FALSE;
@@ -915,46 +917,51 @@ Options(JSContext *cx, JSObject *obj, ui
         JS_ReportOutOfMemory(cx);
         return JS_FALSE;
     }
     str = JS_NewString(cx, names, strlen(names));
     if (!str) {
         free(names);
         return JS_FALSE;
     }
-    *rval = STRING_TO_JSVAL(str);
+    *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
-Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Load(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSString *str;
     const char *filename;
     JSScript *script;
     JSBool ok;
     uint32 oldopts;
 
+    JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
+    if (!thisobj)
+        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);
         errno = 0;
         oldopts = JS_GetOptions(cx);
         JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        script = JS_CompileFile(cx, obj, filename);
+        script = JS_CompileFile(cx, thisobj, filename);
         JS_SetOptions(cx, oldopts);
         if (!script) {
             ok = JS_FALSE;
         } else {
             ok = !compileOnly
-                 ? JS_ExecuteScript(cx, obj, script, NULL)
+                 ? JS_ExecuteScript(cx, thisobj, script, NULL)
                  : JS_TRUE;
             JS_DestroyScript(cx, script);
         }
         if (!ok)
             return JS_FALSE;
     }
 
     return JS_TRUE;
@@ -1097,22 +1104,22 @@ Print(JSContext *cx, uintN argc, jsval *
     fputc('\n', gOutFile);
     fflush(gOutFile);
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+Help(JSContext *cx, uintN argc, jsval *vp);
 
 static JSBool
-Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Quit(JSContext *cx, uintN argc, jsval *vp)
 {
-    JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
+    JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "/ i", &gExitCode);
 
     gQuitting = JS_TRUE;
 #ifdef JS_THREADSAFE
     if (gWorkers)
         js::workers::terminateAll(cx, gWorkers);
 #endif
     return JS_FALSE;
 }
@@ -1467,26 +1474,27 @@ ValueToScript(JSContext *cx, jsval v)
                                  JSSMSG_SCRIPTS_ONLY);
         }
     }
 
     return script;
 }
 
 static JSBool
-SetDebug(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+SetDebug(JSContext *cx, uintN argc, jsval *vp)
 {
+    jsval *argv = JS_ARGV(cx, vp);
     if (argc == 0 || !JSVAL_IS_BOOLEAN(argv[0])) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                              JSSMSG_NOT_ENOUGH_ARGS, "setDebug");
         return JS_FALSE;
     }
     
     js_SetDebugMode(cx, JSVAL_TO_BOOLEAN(argv[0]));
-    *rval = JSVAL_VOID;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
             int32 *ip)
 {
     jsval v;
@@ -1529,129 +1537,132 @@ TrapHandler(JSContext *cx, JSScript *scr
         return JSTRAP_ERROR;
     }
     if (!JSVAL_IS_VOID(*rval))
         return JSTRAP_RETURN;
     return JSTRAP_CONTINUE;
 }
 
 static JSBool
-Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Trap(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     JSScript *script;
     int32 i;
 
+    jsval *argv = JS_ARGV(cx, vp);
     if (argc == 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE);
         return JS_FALSE;
     }
     argc--;
     str = JS_ValueToString(cx, argv[argc]);
     if (!str)
         return JS_FALSE;
     argv[argc] = STRING_TO_JSVAL(str);
     if (!GetTrapArgs(cx, argc, argv, &script, &i))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_SetTrap(cx, script, script->code + i, TrapHandler, STRING_TO_JSVAL(str));
 }
 
 static JSBool
-Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Untrap(JSContext *cx, uintN argc, jsval *vp)
 {
     JSScript *script;
     int32 i;
 
-    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+    if (!GetTrapArgs(cx, argc, JS_ARGV(cx, vp), &script, &i))
         return JS_FALSE;
     JS_ClearTrap(cx, script, script->code + i, NULL, NULL);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSTrapStatus
 DebuggerAndThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
                         void *closure)
 {
     return TrapHandler(cx, script, pc, rval, STRING_TO_JSVAL((JSString *)closure));
 }
 
 static JSBool
-SetDebuggerHandler(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+SetDebuggerHandler(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     if (argc == 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                              JSSMSG_NOT_ENOUGH_ARGS, "setDebuggerHandler");
         return JS_FALSE;
     }
 
-    str = JS_ValueToString(cx, argv[0]);
+    str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
 
     JS_SetDebuggerHandler(cx->runtime, DebuggerAndThrowHandler, str);
-    *rval = JSVAL_VOID;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-SetThrowHook(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+SetThrowHook(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     if (argc == 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                              JSSMSG_NOT_ENOUGH_ARGS, "setThrowHook");
         return JS_FALSE;
     }
 
-    str = JS_ValueToString(cx, argv[0]);
+    str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
 
     JS_SetThrowHook(cx->runtime, DebuggerAndThrowHandler, str);
-    *rval = JSVAL_VOID;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+LineToPC(JSContext *cx, uintN argc, jsval *vp)
 {
     JSScript *script;
     int32 i;
     uintN lineno;
     jsbytecode *pc;
 
     if (argc == 0) {
         JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
         return JS_FALSE;
     }
     script = JS_GetScriptedCaller(cx, NULL)->getScript();
-    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+    if (!GetTrapArgs(cx, argc, JS_ARGV(cx, vp), &script, &i))
         return JS_FALSE;
     lineno = (i == 0) ? script->lineno : (uintN)i;
     pc = JS_LineNumberToPC(cx, script, lineno);
     if (!pc)
         return JS_FALSE;
-    *rval = INT_TO_JSVAL(pc - script->code);
+    *vp = INT_TO_JSVAL(pc - script->code);
     return JS_TRUE;
 }
 
 static JSBool
-PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+PCToLine(JSContext *cx, uintN argc, jsval *vp)
 {
     JSScript *script;
     int32 i;
     uintN lineno;
 
-    if (!GetTrapArgs(cx, argc, argv, &script, &i))
+    if (!GetTrapArgs(cx, argc, JS_ARGV(cx, vp), &script, &i))
         return JS_FALSE;
     lineno = JS_PCToLineNumber(cx, script, script->code + i);
     if (!lineno)
         return JS_FALSE;
-    *rval = INT_TO_JSVAL(lineno);
+    *vp = INT_TO_JSVAL(lineno);
     return JS_TRUE;
 }
 
 #ifdef DEBUG
 
 static void
 UpdateSwitchTableBounds(JSContext *cx, JSScript *script, uintN offset,
                         uintN *start, uintN *end)
@@ -1801,28 +1812,30 @@ SrcNotes(JSContext *cx, JSScript *script
             break;
           default:;
         }
         fputc('\n', gOutFile);
     }
 }
 
 static JSBool
-Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Notes(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSScript *script;
 
+    jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; i < argc; i++) {
         script = ValueToScript(cx, argv[i]);
         if (!script)
             continue;
 
         SrcNotes(cx, script);
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 JS_STATIC_ASSERT(JSTRY_CATCH == 0);
 JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
 JS_STATIC_ASSERT(JSTRY_ITER == 2);
 
 static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
@@ -1922,89 +1935,94 @@ DisassembleValue(JSContext *cx, jsval v,
                 }
             }
         }
     }
     return true;
 }
 
 static JSBool
-Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Disassemble(JSContext *cx, uintN argc, jsval *vp)
 {
     bool lines = false, recursive = false;
 
+    jsval *argv = JS_ARGV(cx, vp);
     while (argc > 0 && JSVAL_IS_STRING(argv[0])) {
         const char *bytes = JS_GetStringBytes(JSVAL_TO_STRING(argv[0]));
         lines = !strcmp(bytes, "-l");
         recursive = !strcmp(bytes, "-r");
         if (!lines && !recursive)
             break;
         argv++, argc--;
     }
 
     for (uintN i = 0; i < argc; i++) {
         if (!DisassembleValue(cx, argv[i], lines, recursive))
             return false;
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSBool
-DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+DisassFile(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     const char *filename;
     JSScript *script;
     JSBool ok;
     uint32 oldopts;
 
     if (!argc)
         return JS_TRUE;
 
-    str = JS_ValueToString(cx, argv[0]);
+    JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
+    if (!thisobj)
+        return JS_FALSE;
+
+    str = JS_ValueToString(cx, vp[2]);
     if (!str)
         return JS_FALSE;
-    argv[0] = STRING_TO_JSVAL(str);
 
     filename = JS_GetStringBytes(str);
     oldopts = JS_GetOptions(cx);
     JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    script = JS_CompileFile(cx, obj, filename);
+    script = JS_CompileFile(cx, thisobj, filename);
     JS_SetOptions(cx, oldopts);
     if (!script)
         return JS_FALSE;
 
     if (script->isEmpty())
         return JS_TRUE;
 
-    obj = JS_NewScriptObject(cx, script);
+    JSObject *obj = JS_NewScriptObject(cx, script);
     if (!obj)
         return JS_FALSE;
 
-    *rval = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
-    ok = Disassemble(cx, obj, 1, rval, rval); /* gross, but works! */
-    *rval = JSVAL_VOID;
+    *vp = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
+    ok = Disassemble(cx, 1, vp); /* gross, but works! */
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
 
     return ok;
 }
 
 static JSBool
-DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-              jsval *rval)
+DisassWithSrc(JSContext *cx, uintN argc, jsval *vp)
 {
 #define LINE_BUF_LEN 512
     uintN i, len, line1, line2, bupline;
     JSScript *script;
     FILE *file;
     char linebuf[LINE_BUF_LEN];
     jsbytecode *pc, *end;
     JSBool ok;
     static char sep[] = ";-------------------------";
 
     ok = JS_TRUE;
+    jsval *argv = JS_ARGV(cx, vp);
     for (i = 0; ok && i < argc; i++) {
         script = ValueToScript(cx, argv[i]);
         if (!script)
            return JS_FALSE;
 
         if (!script->filename) {
             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                                  JSSMSG_FILE_SCRIPTS_ONLY);
@@ -2068,30 +2086,32 @@ DisassWithSrc(JSContext *cx, JSObject *o
                 goto bail;
             }
             pc += len;
         }
 
       bail:
         fclose(file);
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return ok;
 #undef LINE_BUF_LEN
 }
 
 static JSBool
-Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Tracing(JSContext *cx, uintN argc, jsval *vp)
 {
     FILE *file;
 
     if (argc == 0) {
-        *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
+        *vp = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
         return JS_TRUE;
     }
 
+    jsval *argv = JS_ARGV(cx, vp);
     switch (JS_TypeOfValue(cx, argv[0])) {
       case JSTYPE_NUMBER:
       case JSTYPE_BOOLEAN: {
         JSBool bval;
         JS_ValueToBoolean(cx, argv[0], &bval);
         file = bval ? stderr : NULL;
         break;
       }
@@ -2107,16 +2127,17 @@ Tracing(JSContext *cx, JSObject *obj, ui
       }
       default:
           goto bad_argument;
     }
     if (cx->tracefp && cx->tracefp != stderr)
       fclose((FILE *)cx->tracefp);
     cx->tracefp = file;
     cx->tracePrevPc = NULL;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 
  bad_argument:
     JSString *str = JS_ValueToString(cx, argv[0]);
     if (!str)
         return JS_FALSE;
     JS_ReportError(cx, "tracing: illegal argument %s",
                    JS_GetStringBytes(str));
@@ -2129,26 +2150,27 @@ DumpScope(JSContext *cx, JSObject *obj, 
     uintN i = 0;
     for (JSScopeProperty *sprop = NULL; JS_PropertyIterator(obj, &sprop);) {
         fprintf(fp, "%3u %p ", i++, (void *) sprop);
         ((Shape *) sprop)->dump(cx, fp);
     }
 }
 
 static JSBool
-DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+DumpStats(JSContext *cx, uintN argc, jsval *vp)
 {
     uintN i;
     JSString *str;
     const char *bytes;
     jsid id;
     JSObject *obj2;
     JSProperty *prop;
     Value value;
 
+    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);
         bytes = JS_GetStringBytes(str);
         if (strcmp(bytes, "arena") == 0) {
 #ifdef JS_ARENAMETER
@@ -2156,16 +2178,17 @@ DumpStats(JSContext *cx, JSObject *obj, 
 #endif
         } else if (strcmp(bytes, "atom") == 0) {
             js_DumpAtoms(cx, gOutFile);
         } else if (strcmp(bytes, "global") == 0) {
             DumpScope(cx, cx->globalObject, stdout);
         } else {
             if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
                 return JS_FALSE;
+            JSObject *obj;
             if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
                 return JS_FALSE;
             if (prop) {
                 obj2->dropProperty(cx, prop);
                 if (!obj->getProperty(cx, id, &value))
                     return JS_FALSE;
             }
             if (!prop || !value.isObjectOrNull()) {
@@ -2173,16 +2196,17 @@ DumpStats(JSContext *cx, JSObject *obj, 
                         bytes);
                 continue;
             }
             obj = value.toObjectOrNull();
             if (obj)
                 DumpScope(cx, obj, stdout);
         }
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 DumpHeap(JSContext *cx, uintN argc, jsval *vp)
 {
     char *fileName;
     jsval v;
@@ -2274,24 +2298,25 @@ DumpHeap(JSContext *cx, uintN argc, jsva
 
   not_traceable_arg:
     JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
                    badTraceArg);
     return JS_FALSE;
 }
 
 JSBool
-DumpObject(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+DumpObject(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *arg0 = NULL;
-    if (!JS_ConvertArguments(cx, argc, argv, "o", &arg0))
+    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "o", &arg0))
         return JS_FALSE;
 
     js_DumpObject(arg0);
 
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 #endif /* DEBUG */
 
 #ifdef TEST_CVTARGS
 #include <ctype.h>
 
@@ -2366,34 +2391,34 @@ ZZ_formatter(JSContext *cx, const char *
     }
     *vpp = vp + 2;
     *app = ap;
     printf("leaving ZZ_formatter");
     return JS_TRUE;
 }
 
 static JSBool
-ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ConvertArgs(JSContext *cx, uintN argc, jsval *vp)
 {
     JSBool b = JS_FALSE;
     jschar c = 0;
     int32 i = 0, j = 0;
     uint32 u = 0;
     jsdouble d = 0, I = 0, re = 0, im = 0;
     char *s = NULL;
     JSString *str = NULL;
     jschar *w = NULL;
     JSObject *obj2 = NULL;
     JSFunction *fun = NULL;
     jsval v = JSVAL_VOID;
     JSBool ok;
 
     if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
         return JS_FALSE;
-    ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*",
+    ok = JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "b/ciujdIsSWofvZZ*",
                              &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
                              &fun, &v, &re, &im);
     JS_RemoveArgumentFormatter(cx, "ZZ");
     if (!ok)
         return JS_FALSE;
     fprintf(gOutFile,
             "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
             b, c, (char)c, i, u, j);
@@ -2409,16 +2434,17 @@ ConvertArgs(JSContext *cx, JSObject *obj
     }
     fprintf(gOutFile,
             "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
             "v %s, re %g, im %g\n",
             d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
             obj2string.getBytes(),
             fun ? func : "",
             valueString.getBytes(), re, im);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 #endif
 
 static JSBool
 BuildDate(JSContext *cx, uintN argc, jsval *vp)
 {
     char version[20] = "\n";
@@ -2426,21 +2452,23 @@ BuildDate(JSContext *cx, uintN argc, jsv
     sprintf(version, " for version %d\n", JS_VERSION);
 #endif
     fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
-Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Clear(JSContext *cx, uintN argc, jsval *vp)
 {
-    if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
+    JSObject *obj;
+    if (argc != 0 && !JS_ValueToObject(cx, JS_ARGV(cx, vp)[0], &obj))
         return JS_FALSE;
     JS_ClearScope(cx, obj);
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
 Intern(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
 
@@ -2451,20 +2479,24 @@ Intern(JSContext *cx, uintN argc, jsval 
                                 JS_GetStringLength(str))) {
         return JS_FALSE;
     }
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
 
 static JSBool
-Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Clone(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *funobj, *parent, *clone;
 
+    if (!argc)
+        return JS_FALSE;
+
+    jsval *argv = JS_ARGV(cx, vp);
     if (VALUE_IS_FUNCTION(cx, argv[0])) {
         funobj = JSVAL_TO_OBJECT(argv[0]);
     } else {
         JSFunction *fun = JS_ValueToFunction(cx, argv[0]);
         if (!fun)
             return JS_FALSE;
         funobj = JS_GetFunctionObject(fun);
     }
@@ -2472,28 +2504,29 @@ Clone(JSContext *cx, JSObject *obj, uint
         if (!JS_ValueToObject(cx, argv[1], &parent))
             return JS_FALSE;
     } else {
         parent = JS_GetParent(cx, funobj);
     }
     clone = JS_CloneFunctionObject(cx, funobj, parent);
     if (!clone)
         return JS_FALSE;
-    *rval = OBJECT_TO_JSVAL(clone);
+    *vp = OBJECT_TO_JSVAL(clone);
     return JS_TRUE;
 }
 
 static JSBool
-Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Seal(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *target;
     JSBool deep = JS_FALSE;
 
-    if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "o/b", &target, &deep))
         return JS_FALSE;
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     if (!target)
         return JS_TRUE;
     return JS_SealObject(cx, target, deep);
 }
 
 static JSBool
 GetPDA(JSContext *cx, uintN argc, jsval *vp)
 {
@@ -2565,20 +2598,19 @@ ToInt32(JSContext *cx, uintN argc, jsval
     int32 i;
 
     if (!JS_ValueToInt32(cx, argc == 0 ? JSVAL_VOID : vp[2], &i))
         return JS_FALSE;
     return JS_NewNumberValue(cx, i, vp);
 }
 
 static JSBool
-StringsAreUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-               jsval *rval)
+StringsAreUTF8(JSContext *cx, uintN argc, jsval *vp)
 {
-    *rval = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
+    *vp = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
     return JS_TRUE;
 }
 
 static JSBool
 StackQuota(JSContext *cx, uintN argc, jsval *vp)
 {
     uint32 n;
 
@@ -2592,24 +2624,24 @@ StackQuota(JSContext *cx, uintN argc, js
     return JS_TRUE;
 }
 
 static const char* badUTF8 = "...\xC0...";
 static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
 static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
 
 static JSBool
-TestUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+TestUTF8(JSContext *cx, uintN argc, jsval *vp)
 {
     int32 mode = 1;
     jschar chars[20];
     size_t charsLength = 5;
     char bytes[20];
     size_t bytesLength = 20;
-    if (argc && !JS_ValueToInt32(cx, *argv, &mode))
+    if (argc && !JS_ValueToInt32(cx, *JS_ARGV(cx, vp), &mode))
         return JS_FALSE;
 
     /* The following throw errors if compiled with UTF-8. */
     switch (mode) {
       /* mode 1: malformed UTF-8 string. */
       case 1:
         JS_NewStringCopyZ(cx, badUTF8);
         break;
@@ -2624,21 +2656,22 @@ TestUTF8(JSContext *cx, JSObject *obj, u
       /* mode 4: use a too small buffer. */
       case 4:
         JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
         break;
       default:
         JS_ReportError(cx, "invalid mode parameter");
         return JS_FALSE;
     }
+    JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return !JS_IsExceptionPending (cx);
 }
 
 static JSBool
-ThrowError(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+ThrowError(JSContext *cx, uintN argc, jsval *vp)
 {
     JS_ReportError(cx, "This is an error");
     return JS_FALSE;
 }
 
 #define LAZY_STANDARD_CLASSES
 
 /* A class for easily testing the inner/outer object callbacks. */
@@ -3112,22 +3145,21 @@ NewSandbox(JSContext *cx, bool lazy, boo
 
     AutoObjectRooter objroot(cx, obj);
     if (!cx->compartment->wrap(cx, objroot.addr()))
         return NULL;
     return objroot.object();
 }
 
 static JSBool
-EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
-              jsval *rval)
+EvalInContext(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     JSObject *sobj = NULL;
-    if (!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sobj))
+    if (!JS_ConvertArguments(cx, argc, JS_ARGV(cx, vp), "S / o", &str, &sobj))
         return false;
 
     const jschar *src = JS_GetStringChars(str);
     size_t srclen = JS_GetStringLength(str);
     bool split = false, lazy = false;
     if (srclen == 4) {
         if (src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 'y') {
             lazy = true;
@@ -3141,17 +3173,17 @@ EvalInContext(JSContext *cx, JSObject *o
     }
 
     if (!sobj) {
         sobj = NewSandbox(cx, lazy, split);
         if (!sobj)
             return false;
     }
 
-    *rval = OBJECT_TO_JSVAL(sobj);
+    *vp = OBJECT_TO_JSVAL(sobj);
     if (srclen == 0)
         return true;
 
     JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
     {
         JSAutoCrossCompartmentCall ac;
         if (JSCrossCompartmentWrapper::isCrossCompartmentWrapper(sobj)) {
             sobj = sobj->unwrap();
@@ -3164,21 +3196,21 @@ EvalInContext(JSContext *cx, JSObject *o
             return false;
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportError(cx, "Invalid scope argument to evalcx");
             return false;
         }
         if (!JS_EvaluateUCScript(cx, sobj, src, srclen,
                                  fp->getScript()->filename,
                                  JS_PCToLineNumber(cx, fp->getScript(), fp->pc(cx)),
-                                 rval)) {
+                                 vp)) {
             return false;
         }
     }
-    return cx->compartment->wrap(cx, Valueify(rval));
+    return cx->compartment->wrap(cx, Valueify(vp));
 }
 
 static JSBool
 EvalInFrame(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval *argv = JS_ARGV(cx, vp);
     if (argc < 2 ||
         !JSVAL_IS_INT(argv[0]) ||
@@ -3913,28 +3945,31 @@ Parse(JSContext *cx, uintN argc, jsval *
                 NULL, "<string>", 0);
     if (!parser.parse(NULL))