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
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))
         return JS_FALSE;
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
-Snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Snarf(JSContext *cx, uintN argc, jsval *vp)
 {
     JSString *str;
     const char *filename;
     const char *pathname;
     JSStackFrame *fp;
     JSBool ok;
     size_t cc, len;
     char *buf;
     FILE *file;
 
-    str = JS_ValueToString(cx, argv[0]);
+    if (!argc)
+        return JS_FALSE;
+
+    str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     if (!str)
         return JS_FALSE;
     filename = JS_GetStringBytes(str);
 
     /* Get the currently executing script's name. */
     fp = JS_GetScriptedCaller(cx, NULL);
     JS_ASSERT(fp && fp->getScript()->filename);
 #ifdef XP_UNIX
@@ -3981,44 +4016,49 @@ Snarf(JSContext *cx, JSObject *obj, uint
     }
 
     buf[len] = '\0';
     str = JS_NewString(cx, buf, len);
     if (!str) {
         JS_free(cx, buf);
         return JS_FALSE;
     }
-    *rval = STRING_TO_JSVAL(str);
+    *vp = STRING_TO_JSVAL(str);
     return JS_TRUE;
 }
 
 static JSBool
-Snarl(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+Snarl(JSContext *cx, uintN argc, jsval *vp)
 {
     if (argc < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "compile", "0", "s");