--- 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 ®s)
-{
- 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 ®s, 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 ®s);
-
- JS_REQUIRES_STACK
- void popSynthesizedSlowNativeFrame(JSContext *cx);
-
- /*
* For pushing a bookkeeping frame.
*/
JS_REQUIRES_STACK
bool pushDummyFrame(JSContext *cx, FrameGuard &fg, JSFrameRegs ®s, 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 ®s = 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_Val