(unrebased) fat value patch

This commit is contained in:
Luke Wagner 2010-05-10 22:01:31 -07:00
parent 2ea3056f2b
commit 55e7f5e2d3
62 changed files with 7364 additions and 5518 deletions

View File

@ -717,7 +717,7 @@ JSTrapStatus
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure) void *closure)
{ {
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure)); JSDExecHook* jsdhook = (JSDExecHook*)closure;
JSD_ExecutionHookProc hook; JSD_ExecutionHookProc hook;
void* hookData; void* hookData;
JSDContext* jsdc; JSDContext* jsdc;
@ -800,7 +800,7 @@ jsd_SetExecutionHook(JSDContext* jsdc,
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script, if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, jsd_TrapHandler, (jsbytecode*)pc, jsd_TrapHandler,
(void*) PRIVATE_TO_JSVAL(jsdhook)) ) PRIVATE_TO_JSVAL(jsdhook)) )
{ {
free(jsdhook); free(jsdhook);
JSD_UNLOCK(); JSD_UNLOCK();

View File

@ -206,10 +206,9 @@ jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
jsdouble* jsdouble*
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval) jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
{ {
jsval val = jsdval->val; if(!JSVAL_IS_DOUBLE(jsdval->val))
if(!JSVAL_IS_DOUBLE(val))
return 0; return 0;
return JSVAL_TO_DOUBLE(val); return JSVAL_PTR_TO_DOUBLE_PTR(&jsdval->val);
} }
JSString* JSString*
@ -342,14 +341,14 @@ static JSDProperty* _newProperty(JSDContext* jsdc, JSPropertyDesc* pd,
jsdprop->flags = pd->flags | additionalFlags; jsdprop->flags = pd->flags | additionalFlags;
jsdprop->slot = pd->slot; jsdprop->slot = pd->slot;
if(!(jsdprop->name = jsd_NewValue(jsdc, pd->id))) if(!(jsdprop->name = jsd_NewValue(jsdc, JSID_TO_JSVAL(pd->id))))
goto new_prop_fail; goto new_prop_fail;
if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value))) if(!(jsdprop->val = jsd_NewValue(jsdc, pd->value)))
goto new_prop_fail; goto new_prop_fail;
if((jsdprop->flags & JSDPD_ALIAS) && if((jsdprop->flags & JSDPD_ALIAS) &&
!(jsdprop->alias = jsd_NewValue(jsdc, pd->alias))) !(jsdprop->alias = jsd_NewValue(jsdc, JSID_TO_JSVAL(pd->alias))))
goto new_prop_fail; goto new_prop_fail;
return jsdprop; return jsdprop;
@ -492,7 +491,7 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
JSPropertyDesc pd; JSPropertyDesc pd;
const jschar * nameChars; const jschar * nameChars;
size_t nameLen; size_t nameLen;
jsval val; jsval val, nameval;
if(!jsd_IsValueObject(jsdc, jsdval)) if(!jsd_IsValueObject(jsdc, jsdval))
return NULL; return NULL;
@ -548,8 +547,11 @@ jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name)
JS_EndRequest(cx); JS_EndRequest(cx);
pd.id = STRING_TO_JSVAL(name); nameval = STRING_TO_JSVAL(name);
pd.alias = pd.slot = pd.spare = 0; if (!JS_ValueToId(cx, &nameval, &pd.id))
return NULL;
pd.slot = pd.spare = 0;
pd.alias = JSID_NULL;
pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0 pd.flags |= (attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0
| (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0 | (attrs & JSPROP_READONLY) ? JSPD_READONLY : 0
| (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0; | (attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0;

View File

@ -38,8 +38,6 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include "jsdbgapi.h" #include "jsdbgapi.h"
#include "jscntxt.h"
#include "jsfun.h"
#include "jsd_xpc.h" #include "jsd_xpc.h"
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
@ -1014,7 +1012,8 @@ jsdScript::CreatePPLineMap()
PRBool scriptOwner = PR_FALSE; PRBool scriptOwner = PR_FALSE;
if (fun) { if (fun) {
if (fun->nargs > 12) uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
if (nargs > 12)
return nsnull; return nsnull;
JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4); JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4);
if (!jsstr) if (!jsstr)
@ -1023,7 +1022,7 @@ jsdScript::CreatePPLineMap()
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4", const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
"arg5", "arg6", "arg7", "arg8", "arg5", "arg6", "arg7", "arg8",
"arg9", "arg10", "arg11", "arg12" }; "arg9", "arg10", "arg11", "arg12" };
fun = JS_CompileUCFunction (cx, obj, "ppfun", fun->nargs, argnames, fun = JS_CompileUCFunction (cx, obj, "ppfun", nargs, argnames,
JS_GetStringChars(jsstr), JS_GetStringChars(jsstr),
JS_GetStringLength(jsstr), JS_GetStringLength(jsstr),
"x-jsd:ppbuffer?type=function", 3); "x-jsd:ppbuffer?type=function", 3);
@ -1232,37 +1231,32 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
JSAutoRequest ar(cx); JSAutoRequest ar(cx);
if (!fun || !fun->hasLocalNames() || fun->nargs == 0) { uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
if (!fun || !JS_FunctionHasLocalNames(cx, fun) || nargs == 0) {
*count = 0; *count = 0;
*paramNames = nsnull; *paramNames = nsnull;
return NS_OK; return NS_OK;
} }
PRUnichar **ret = PRUnichar **ret =
static_cast<PRUnichar**>(NS_Alloc(fun->nargs * sizeof(PRUnichar*))); static_cast<PRUnichar**>(NS_Alloc(nargs * sizeof(PRUnichar*)));
if (!ret) if (!ret)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
void *mark = JS_ARENA_MARK(&cx->tempPool); void *mark;
jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool); jsuword *names = JS_GetFunctionLocalNameArray(cx, fun, &mark);
if (!names) { if (!names) {
NS_Free(ret); NS_Free(ret);
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsresult rv = NS_OK; nsresult rv = NS_OK;
for (uintN i = 0; i < fun->nargs; ++i) { for (uintN i = 0; i < nargs; ++i) {
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]); JSAtom *atom = JS_LocalNameToAtom(names[i]);
if (!atom) { if (!atom) {
ret[i] = 0; ret[i] = 0;
} else { } else {
jsval atomVal = ATOM_KEY(atom); JSString *str = JS_AtomKey(atom);
if (!JSVAL_IS_STRING(atomVal)) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, ret);
rv = NS_ERROR_UNEXPECTED;
break;
}
JSString *str = JSVAL_TO_STRING(atomVal);
ret[i] = NS_strndup(reinterpret_cast<PRUnichar*>(JS_GetStringChars(str)), ret[i] = NS_strndup(reinterpret_cast<PRUnichar*>(JS_GetStringChars(str)),
JS_GetStringLength(str)); JS_GetStringLength(str));
if (!ret[i]) { if (!ret[i]) {
@ -1272,10 +1266,10 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
} }
} }
} }
JS_ARENA_RELEASE(&cx->tempPool, mark); JS_ReleaseFunctionLocalNameArray(cx, mark);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
*count = fun->nargs; *count = nargs;
*paramNames = ret; *paramNames = ret;
return NS_OK; return NS_OK;
} }
@ -1484,8 +1478,7 @@ jsdScript::SetBreakpoint(PRUint32 aPC)
{ {
ASSERT_VALID_EPHEMERAL; ASSERT_VALID_EPHEMERAL;
jsuword pc = mFirstPC + aPC; jsuword pc = mFirstPC + aPC;
JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc, JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc, NULL);
reinterpret_cast<void *>(PRIVATE_TO_JSVAL(NULL)));
return NS_OK; return NS_OK;
} }
@ -1989,7 +1982,7 @@ jsdStackFrame::Eval (const nsAString &bytes, const nsACString &fileName,
if (JS_IsExceptionPending(cx)) if (JS_IsExceptionPending(cx))
JS_GetPendingException (cx, &jv); JS_GetPendingException (cx, &jv);
else else
jv = 0; jv = JSVAL_NULL;
} }
JS_RestoreExceptionState (cx, estate); JS_RestoreExceptionState (cx, estate);
@ -2436,8 +2429,8 @@ jsdService::SetInitAtStartup (PRBool state)
return rv; return rv;
} }
if (state && mInitAtStartup == triYes || if ((state && mInitAtStartup == triYes) ||
!state && mInitAtStartup == triNo) { (!state && mInitAtStartup == triNo)) {
/* already in the requested state */ /* already in the requested state */
return NS_OK; return NS_OK;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -46,14 +46,12 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "jsobj.h" #include "jsobj.h"
JS_BEGIN_EXTERN_C
#define ARRAY_CAPACITY_MIN 7 #define ARRAY_CAPACITY_MIN 7
extern JSBool extern JSBool
js_IdIsIndex(jsval id, jsuint *indexp); js_IdIsIndex(jsid id, jsuint *indexp);
extern JSClass js_ArrayClass, js_SlowArrayClass; extern js::Class js_ArrayClass, js_SlowArrayClass;
inline bool inline bool
JSObject::isDenseArray() const JSObject::isDenseArray() const
@ -112,7 +110,7 @@ extern JSObject * JS_FASTCALL
js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len); js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len);
extern JSObject * extern JSObject *
js_NewArrayObject(JSContext *cx, jsuint length, const jsval *vector, bool holey = false); js_NewArrayObject(JSContext *cx, jsuint length, const js::Value *vector, bool holey = false);
/* Create an array object that starts out already made slow/sparse. */ /* Create an array object that starts out already made slow/sparse. */
extern JSObject * extern JSObject *
@ -125,7 +123,7 @@ static JS_INLINE uint32
js_DenseArrayCapacity(JSObject *obj) js_DenseArrayCapacity(JSObject *obj)
{ {
JS_ASSERT(obj->isDenseArray()); JS_ASSERT(obj->isDenseArray());
return obj->dslots ? (uint32) obj->dslots[-1] : 0; return obj->dslots ? obj->dslotLength() : 0;
} }
static JS_INLINE void static JS_INLINE void
@ -133,7 +131,7 @@ js_SetDenseArrayCapacity(JSObject *obj, uint32 capacity)
{ {
JS_ASSERT(obj->isDenseArray()); JS_ASSERT(obj->isDenseArray());
JS_ASSERT(obj->dslots); JS_ASSERT(obj->dslots);
obj->dslots[-1] = (jsval) capacity; obj->dslots[-1].setPrivateUint32(capacity);
} }
extern JSBool extern JSBool
@ -167,21 +165,23 @@ typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b,
* NB: vec is the array to be sorted, tmp is temporary space at least as big * NB: vec is the array to be sorted, tmp is temporary space at least as big
* as vec. Both should be GC-rooted if appropriate. * as vec. Both should be GC-rooted if appropriate.
* *
* isValue should true iff vec points to an array of js::Value
*
* The sorted result is in vec. vec may be in an inconsistent state if the * The sorted result is in vec. vec may be in an inconsistent state if the
* comparator function cmp returns an error inside a comparison, so remember * comparator function cmp returns an error inside a comparison, so remember
* to check the return value of this function. * to check the return value of this function.
*/ */
extern JSBool extern bool
js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp, js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp,
void *arg, void *tmp); void *arg, void *tmp, bool isValue);
#ifdef DEBUG_ARRAYS #ifdef DEBUG_ARRAYS
extern JSBool extern JSBool
js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
#endif #endif
extern JSBool JS_FASTCALL extern JSBool JS_FASTCALL
js_ArrayCompPush(JSContext *cx, JSObject *obj, jsval v); js_ArrayCompPush(JSContext *cx, JSObject *obj, const js::Value &v);
/* /*
* Fast dense-array-to-buffer conversion for use by canvas. * Fast dense-array-to-buffer conversion for use by canvas.
@ -211,11 +211,11 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj);
*/ */
JSBool JSBool
js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop, js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop,
jsval *vp); js::Value *vp);
/* Array constructor native. Exposed only so the JIT can know its address. */ /* Array constructor native. Exposed only so the JIT can know its address. */
JSBool JSBool
js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval); js_Array(JSContext* cx, JSObject* obj, uintN argc, js::Value* argv, js::Value* rval);
/* /*
* Friend api function that allows direct creation of an array object with a * Friend api function that allows direct creation of an array object with a
@ -229,8 +229,6 @@ js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
* resulting array has length and count both equal to |capacity|. * resulting array has length and count both equal to |capacity|.
*/ */
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector); js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, js::Value **vector);
JS_END_EXTERN_C
#endif /* jsarray_h___ */ #endif /* jsarray_h___ */

View File

@ -37,6 +37,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS atom table. * JS atom table.
*/ */
@ -58,7 +60,13 @@
#include "jsscan.h" #include "jsscan.h"
#include "jsstr.h" #include "jsstr.h"
#include "jsversion.h" #include "jsversion.h"
#include "jsxml.h"
#include "jsstrinlines.h" #include "jsstrinlines.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
using namespace js;
/* /*
* ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems. * ATOM_HASH assumes that JSHashNumber is 32-bit even on 64-bit systems.
@ -85,7 +93,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
const char * const char *
js_AtomToPrintableString(JSContext *cx, JSAtom *atom) js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
{ {
return js_ValueToPrintableString(cx, ATOM_KEY(atom)); return js_ValueToPrintableString(cx, Value(ATOM_TO_STRING(atom)));
} }
#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name; #define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
@ -269,12 +277,12 @@ const char js_current_str[] = "current";
*/ */
typedef struct JSAtomHashEntry { typedef struct JSAtomHashEntry {
JSDHashEntryHdr hdr; JSDHashEntryHdr hdr;
jsuword keyAndFlags; jsboxedword keyAndFlags;
} JSAtomHashEntry; } JSAtomHashEntry;
#define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED) #define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED)
JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSVAL_ALIGN); JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSBOXEDWORD_ALIGN);
/* /*
* Helper macros to access and modify JSAtomHashEntry. * Helper macros to access and modify JSAtomHashEntry.
@ -536,8 +544,8 @@ js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT; return JS_DHASH_NEXT;
} }
JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number); JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry), CallGCMarker(trc, ATOM_ENTRY_KEY(entry),
IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE); IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
return JS_DHASH_NEXT; return JS_DHASH_NEXT;
} }
@ -556,7 +564,7 @@ js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
? "pinned_atom" ? "pinned_atom"
: "interned_atom", : "interned_atom",
(size_t)number); (size_t)number);
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING); CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
} }
return JS_DHASH_NEXT; return JS_DHASH_NEXT;
} }
@ -619,7 +627,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
JSAtomHashEntry *entry; JSAtomHashEntry *entry;
uint32 gen; uint32 gen;
jsdouble *key; jsdouble *key;
jsval v; jsboxedword w;
state = &cx->runtime->atomState; state = &cx->runtime->atomState;
table = &state->doubleAtoms; table = &state->doubleAtoms;
@ -632,7 +640,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
gen = ++table->generation; gen = ++table->generation;
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
key = js_NewWeaklyRootedDouble(cx, d); key = js_NewWeaklyRootedDoubleAtom(cx, d);
if (!key) if (!key)
return NULL; return NULL;
@ -652,11 +660,11 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
} }
finish: finish:
v = DOUBLE_TO_JSVAL((jsdouble *)ATOM_ENTRY_KEY(entry)); w = DOUBLE_TO_JSBOXEDWORD((jsdouble *)ATOM_ENTRY_KEY(entry));
cx->weakRoots.lastAtom = v; cx->weakRoots.lastAtom = (JSAtom *)w;
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
return (JSAtom *)v; return (JSAtom *)w;
failed_hash_add: failed_hash_add:
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
@ -667,7 +675,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
JSAtom * JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags) js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{ {
jsval v; JSAtom *atom;
JSAtomState *state; JSAtomState *state;
JSDHashTable *table; JSDHashTable *table;
JSAtomHashEntry *entry; JSAtomHashEntry *entry;
@ -678,13 +686,13 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR); JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
if (str->isAtomized()) if (str->isAtomized())
return (JSAtom *) STRING_TO_JSVAL(str); return STRING_TO_ATOM(str);
size_t length = str->length(); size_t length = str->length();
if (length == 1) { if (length == 1) {
jschar c = str->chars()[0]; jschar c = str->chars()[0];
if (c < UNIT_STRING_LIMIT) if (c < UNIT_STRING_LIMIT)
return (JSAtom *) STRING_TO_JSVAL(JSString::unitString(c)); return STRING_TO_ATOM(JSString::unitString(c));
} }
/* /*
@ -705,7 +713,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
if (length == 3) if (length == 3)
i = i * 10 + chars[2] - '0'; i = i * 10 + chars[2] - '0';
if (jsuint(i) < INT_STRING_LIMIT) if (jsuint(i) < INT_STRING_LIMIT)
return (JSAtom *) STRING_TO_JSVAL(JSString::intString(i)); return STRING_TO_ATOM(JSString::intString(i));
} }
} }
@ -775,10 +783,10 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
finish: finish:
ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED)); ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED));
JS_ASSERT(key->isAtomized()); JS_ASSERT(key->isAtomized());
v = STRING_TO_JSVAL(key); atom = STRING_TO_ATOM(key);
cx->weakRoots.lastAtom = v; cx->weakRoots.lastAtom = atom;
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
return (JSAtom *)v; return atom;
failed_hash_add: failed_hash_add:
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
@ -842,7 +850,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
if (length == 1) { if (length == 1) {
jschar c = *chars; jschar c = *chars;
if (c < UNIT_STRING_LIMIT) if (c < UNIT_STRING_LIMIT)
return (JSAtom *) STRING_TO_JSVAL(JSString::unitString(c)); return STRING_TO_ATOM(JSString::unitString(c));
} }
str.initFlat((jschar *)chars, length); str.initFlat((jschar *)chars, length);
@ -855,26 +863,26 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
: NULL; : NULL;
JS_UNLOCK(cx, &state->lock); JS_UNLOCK(cx, &state->lock);
return str2 ? (JSAtom *)STRING_TO_JSVAL(str2) : NULL; return str2 ? STRING_TO_ATOM(str2) : NULL;
} }
JSBool JSBool
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp) js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp)
{ {
JSAtom *atom; JSAtom *atom;
if (JSVAL_IS_STRING(v)) { if (JSBOXEDWORD_IS_STRING(w)) {
atom = js_AtomizeString(cx, JSVAL_TO_STRING(v), 0); atom = js_AtomizeString(cx, JSBOXEDWORD_TO_STRING(w), 0);
if (!atom) if (!atom)
return JS_FALSE; return JS_FALSE;
} else if (JSVAL_IS_DOUBLE(v)) { } else if (JSBOXEDWORD_IS_DOUBLE(w)) {
atom = js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v)); atom = js_AtomizeDouble(cx, *JSBOXEDWORD_TO_DOUBLE(w));
if (!atom) if (!atom)
return JS_FALSE; return JS_FALSE;
} else { } else {
JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_BOOLEAN(v) || JS_ASSERT(JSBOXEDWORD_IS_INT(w) || JSBOXEDWORD_IS_BOOLEAN(w) ||
JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)); JSBOXEDWORD_IS_NULL(w) || JSBOXEDWORD_IS_VOID(w));
atom = (JSAtom *)v; atom = (JSAtom *)w;
} }
*atomp = atom; *atomp = atom;
return JS_TRUE; return JS_TRUE;
@ -1265,3 +1273,96 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
} }
al->clear(); al->clear();
} }
#if JS_HAS_XML_SUPPORT
bool
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
jsid *idp)
{
JS_ASSERT(idval.isObject());
if (obj->isXML()) {
*idp = OBJECT_TO_JSID(&idval.asObject());
return true;
}
if (!js_IsFunctionQName(cx, &idval.asObject(), idp))
return JS_FALSE;
if (*idp != 0)
return true;
return js_ValueToStringId(cx, idval, idp);
}
bool
js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval,
jsid *idp, Value *vp)
{
JS_ASSERT(idval.isObject());
if (obj->isXML()) {
JSObject &idobj = idval.asObject();
*idp = OBJECT_TO_JSID(&idobj);
SetObject(vp, idobj);
return true;
}
if (!js_IsFunctionQName(cx, &idval.asObject(), idp))
return JS_FALSE;
if (*idp != 0) {
vp->copy(IdToValue(*idp));
return true;
}
if (js_ValueToStringId(cx, idval, idp)) {
vp->setString(ATOM_TO_STRING(JSID_TO_ATOM(*idp)));
return true;
}
return false;
}
#endif
namespace js {
bool
ValueToId(JSContext *cx, const Value *vp, jsid *idp)
{
int32_t i;
if (ValueFitsInInt32(*vp, &i) && INT32_FITS_IN_JSID(i)) {
*idp = INT_TO_JSID(i);
return true;
}
#if JS_HAS_XML_SUPPORT
if (vp->isObject()) {
Class *clasp = vp->asObject().getClass();
if (JS_UNLIKELY(clasp == &js_QNameClass.base ||
clasp == &js_AttributeNameClass ||
clasp == &js_AnyNameClass)) {
*idp = OBJECT_TO_JSID(&vp->asObject());
return true;
}
}
#endif
return js_ValueToStringId(cx, *vp, idp);
}
/*
* Normally, js::Value should not be passed by value, but this function should
* only be used on cold paths, so ease of use wins out.
*/
Value
IdToValue(jsid id)
{
ExplicitlyConstructedValue v;
if (JSID_IS_INT(id))
v.setInt32(JSID_TO_INT(id));
else if (JSID_IS_ATOM(id))
v.setString(ATOM_TO_STRING(JSID_TO_ATOM(id)));
else if (JSID_IS_NULL(id))
v.setNull();
else
SetObject(&v, *JSID_TO_OBJECT(id));
return v;
}
} /* namespace js */

View File

@ -52,18 +52,18 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "jslock.h" #include "jslock.h"
JS_BEGIN_EXTERN_C
#define ATOM_PINNED 0x1 /* atom is pinned against GC */ #define ATOM_PINNED 0x1 /* atom is pinned against GC */
#define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */ #define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */
#define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */ #define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */ #define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */
#define ATOM_KEY(atom) ((jsval)(atom)) #define ATOM_KEY(atom) ((jsboxedword)(atom))
#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom)) #define ATOM_IS_DOUBLE(atom) JSBOXEDWORD_IS_DOUBLE(ATOM_KEY(atom))
#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom)) #define ATOM_TO_DOUBLE(atom) JSBOXEDWORD_TO_DOUBLE(ATOM_KEY(atom))
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom)) #define ATOM_IS_STRING(atom) JSBOXEDWORD_IS_STRING(ATOM_KEY(atom))
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom)) #define ATOM_TO_STRING(atom) JSBOXEDWORD_TO_STRING(ATOM_KEY(atom))
#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \
(JSAtom *)STRING_TO_JSBOXEDWORD(str))
#if JS_BYTES_PER_WORD == 4 #if JS_BYTES_PER_WORD == 4
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2) # define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
@ -88,7 +88,7 @@ struct JSAtomListElement {
#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key) #define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key)
#define ALE_INDEX(ale) (jsatomid(uintptr_t((ale)->entry.value))) #define ALE_INDEX(ale) (jsatomid(uintptr_t((ale)->entry.value)))
#define ALE_VALUE(ale) ((jsval) (ale)->entry.value) #define ALE_VALUE(ale) ((jsboxedword) (ale)->entry.value)
#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next) #define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next)
/* /*
@ -119,8 +119,6 @@ struct JSAtomSet {
jsuint count; /* count of indexed literals */ jsuint count; /* count of indexed literals */
}; };
#ifdef __cplusplus
struct JSAtomList : public JSAtomSet struct JSAtomList : public JSAtomSet
{ {
#ifdef DEBUG #ifdef DEBUG
@ -198,8 +196,6 @@ class JSAtomListIterator {
JSAtomListElement* operator ()(); JSAtomListElement* operator ()();
}; };
#endif /* __cplusplus */
struct JSAtomMap { struct JSAtomMap {
JSAtom **vector; /* array of ptrs to indexed atoms */ JSAtom **vector; /* array of ptrs to indexed atoms */
jsatomid length; /* count of (to-be-)indexed atoms */ jsatomid length; /* count of (to-be-)indexed atoms */
@ -485,7 +481,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
* This variant handles all primitive values. * This variant handles all primitive values.
*/ */
JSBool JSBool
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp); js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp);
#ifdef DEBUG #ifdef DEBUG
@ -494,6 +490,18 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
#endif #endif
inline bool
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
inline bool
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp);
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp, js::Value *vp);
/* /*
* For all unmapped atoms recorded in al, add a mapping from the atom's index * For all unmapped atoms recorded in al, add a mapping from the atom's index
* to its address. map->length must already be set to the number of atoms in * to its address. map->length must already be set to the number of atoms in
@ -502,6 +510,14 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
extern void extern void
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al); js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
JS_END_EXTERN_C namespace js {
Value
IdToValue(jsid id);
bool
ValueToId(JSContext *cx, const Value &v, jsid *idp);
} /* namespace js */
#endif /* jsatom_h___ */ #endif /* jsatom_h___ */

View File

@ -46,8 +46,8 @@
/* /*
* Convert v to an atomized string and wrap it as an id. * Convert v to an atomized string and wrap it as an id.
*/ */
inline JSBool inline bool
js_ValueToStringId(JSContext *cx, jsval v, jsid *idp) js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp)
{ {
JSString *str; JSString *str;
JSAtom *atom; JSAtom *atom;
@ -59,37 +59,85 @@ js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
* done in js_js_AtomizeString) ensures the caller that the resulting id at * done in js_js_AtomizeString) ensures the caller that the resulting id at
* is least weakly rooted. * is least weakly rooted.
*/ */
if (JSVAL_IS_STRING(v)) { if (v.isString()) {
str = JSVAL_TO_STRING(v); str = v.asString();
if (str->isAtomized()) { if (str->isAtomized()) {
cx->weakRoots.lastAtom = v; cx->weakRoots.lastAtom = *atomp = STRING_TO_ATOM(str);
*idp = ATOM_TO_JSID((JSAtom *) v); return true;
return JS_TRUE;
} }
} else { } else {
str = js_ValueToString(cx, v); str = js_ValueToString(cx, v);
if (!str) if (!str)
return JS_FALSE; return false;
} }
atom = js_AtomizeString(cx, str, 0); atom = js_AtomizeString(cx, str, 0);
if (!atom) if (!atom)
return JS_FALSE; return false;
*idp = ATOM_TO_JSID(atom); *atomp = atom;
return JS_TRUE; return true;
} }
inline JSBool inline bool
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp)
{
JSAtom *atom;
if (js_ValueToAtom(cx, v, &atom)) {
*idp = ATOM_TO_JSID(atom);
return true;
}
return false;
}
inline bool
js_Int32ToId(JSContext* cx, int32 index, jsid* id) js_Int32ToId(JSContext* cx, int32 index, jsid* id)
{ {
if (INT_FITS_IN_JSVAL(index)) { if (INT32_FITS_IN_JSID(index)) {
*id = INT_TO_JSID(index); *id = INT_TO_JSID(index);
JS_ASSERT(INT_JSID_TO_JSVAL(*id) == INT_TO_JSVAL(index)); return true;
return JS_TRUE;
} }
JSString* str = js_NumberToString(cx, index); JSString* str = js_NumberToString(cx, index);
if (!str) if (!str)
return JS_FALSE; return false;
return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id); return js_ValueToStringId(cx, js::Value(str), id);
}
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp)
{
JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32()));
#if JS_HAS_XML_SUPPORT
extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *,
const js::Value &, jsid *);
if (idval.isObject())
return js_InternNonIntElementIdSlow(cx, obj, idval, idp);
#endif
return js_ValueToStringId(cx, idval, idp);
}
inline bool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
jsid *idp, js::Value *vp)
{
JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32()));
#if JS_HAS_XML_SUPPORT
extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *,
const js::Value &,
jsid *, js::Value *);
if (idval.isObject())
return js_InternNonIntElementIdSlow(cx, obj, idval, idp, vp);
#endif
JSAtom *atom;
if (js_ValueToAtom(cx, idval, &atom)) {
*idp = ATOM_TO_JSID(atom);
vp->setString(ATOM_TO_STRING(atom));
return true;
}
return false;
} }
#endif /* jsatominlines_h___ */ #endif /* jsatominlines_h___ */

View File

@ -37,6 +37,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS boolean implementation. * JS boolean implementation.
*/ */
@ -54,20 +56,15 @@
#include "jsstr.h" #include "jsstr.h"
#include "jsvector.h" #include "jsvector.h"
#include "jsobjinlines.h"
/* Check pseudo-booleans values. */ using namespace js;
JS_STATIC_ASSERT(!(JSVAL_TRUE & JSVAL_HOLE_FLAG));
JS_STATIC_ASSERT(!(JSVAL_FALSE & JSVAL_HOLE_FLAG));
JS_STATIC_ASSERT(!(JSVAL_VOID & JSVAL_HOLE_FLAG));
JS_STATIC_ASSERT((JSVAL_HOLE & JSVAL_HOLE_FLAG));
JS_STATIC_ASSERT((JSVAL_HOLE & ~JSVAL_HOLE_FLAG) == JSVAL_VOID);
JS_STATIC_ASSERT(!(JSVAL_ARETURN & JSVAL_HOLE_FLAG));
JSClass js_BooleanClass = { Class js_BooleanClass = {
"Boolean", "Boolean",
JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean), JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, PropertyStub, PropertyStub, PropertyStub, PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL, EnumerateStub, ResolveStub, ConvertStub, NULL,
JSCLASS_NO_OPTIONAL_MEMBERS JSCLASS_NO_OPTIONAL_MEMBERS
}; };
@ -75,46 +72,46 @@ JSClass js_BooleanClass = {
#include "jsprf.h" #include "jsprf.h"
static JSBool static JSBool
bool_toSource(JSContext *cx, uintN argc, jsval *vp) bool_toSource(JSContext *cx, uintN argc, Value *vp)
{ {
jsval v; Value v;
char buf[32]; char buf[32];
JSString *str; JSString *str;
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v)) if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
return JS_FALSE; return JS_FALSE;
JS_ASSERT(JSVAL_IS_BOOLEAN(v)); JS_ASSERT(v.isBoolean());
JS_snprintf(buf, sizeof buf, "(new %s(%s))", JS_snprintf(buf, sizeof buf, "(new %s(%s))",
js_BooleanClass.name, js_BooleanClass.name,
JS_BOOLEAN_STR(JSVAL_TO_BOOLEAN(v))); JS_BOOLEAN_STR(v.asBoolean()));
str = JS_NewStringCopyZ(cx, buf); str = JS_NewStringCopyZ(cx, buf);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
*vp = STRING_TO_JSVAL(str); vp->setString(str);
return JS_TRUE; return JS_TRUE;
} }
#endif #endif
static JSBool static JSBool
bool_toString(JSContext *cx, uintN argc, jsval *vp) bool_toString(JSContext *cx, uintN argc, Value *vp)
{ {
jsval v; Value v;
JSAtom *atom; JSAtom *atom;
JSString *str; JSString *str;
if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v)) if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
return JS_FALSE; return JS_FALSE;
JS_ASSERT(JSVAL_IS_BOOLEAN(v)); JS_ASSERT(v.isBoolean());
atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0]; atom = cx->runtime->atomState.booleanAtoms[v.asBoolean() ? 1 : 0];
str = ATOM_TO_STRING(atom); str = ATOM_TO_STRING(atom);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
*vp = STRING_TO_JSVAL(str); vp->setString(str);
return JS_TRUE; return JS_TRUE;
} }
static JSBool static JSBool
bool_valueOf(JSContext *cx, uintN argc, jsval *vp) bool_valueOf(JSContext *cx, uintN argc, Value *vp)
{ {
return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp); return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
} }
@ -130,17 +127,18 @@ static JSFunctionSpec boolean_methods[] = {
}; };
static JSBool static JSBool
Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) Boolean(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
{ {
jsval bval; Value bval;
bval = (argc != 0) if (argc != 0)
? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0])) bval.setBoolean(js_ValueToBoolean(argv[0]));
: JSVAL_FALSE;
if (!JS_IsConstructing(cx))
*rval = bval;
else else
obj->fslots[JSSLOT_PRIMITIVE_THIS] = bval; bval.setBoolean(false);
if (!JS_IsConstructing(cx))
rval->copy(bval);
else
obj->fslots[JSSLOT_PRIMITIVE_THIS].copy(bval);
return true; return true;
} }
@ -149,11 +147,11 @@ js_InitBooleanClass(JSContext *cx, JSObject *obj)
{ {
JSObject *proto; JSObject *proto;
proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1, proto = js_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
NULL, boolean_methods, NULL, NULL); NULL, boolean_methods, NULL, NULL);
if (!proto) if (!proto)
return NULL; return NULL;
proto->fslots[JSSLOT_PRIMITIVE_THIS] = JSVAL_FALSE; proto->fslots[JSSLOT_PRIMITIVE_THIS].setBoolean(false);
return proto; return proto;
} }
@ -171,22 +169,22 @@ js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb)
} }
JSBool JSBool
js_ValueToBoolean(jsval v) js_ValueToBoolean(const Value &v)
{ {
if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) if (v.isNullOrUndefined())
return JS_FALSE; return JS_FALSE;
if (JSVAL_IS_OBJECT(v)) if (v.isObject())
return JS_TRUE; return JS_TRUE;
if (JSVAL_IS_STRING(v)) if (v.isString())
return JSVAL_TO_STRING(v)->length() != 0; return v.asString()->length() != 0;
if (JSVAL_IS_INT(v)) if (v.isInt32())
return JSVAL_TO_INT(v) != 0; return v.asInt32() != 0;
if (JSVAL_IS_DOUBLE(v)) { if (v.isDouble()) {
jsdouble d; jsdouble d;
d = *JSVAL_TO_DOUBLE(v); d = v.asDouble();
return !JSDOUBLE_IS_NaN(d) && d != 0; return !JSDOUBLE_IS_NaN(d) && d != 0;
} }
JS_ASSERT(JSVAL_IS_BOOLEAN(v)); JS_ASSERT(v.isBoolean());
return JSVAL_TO_BOOLEAN(v); return v.asBoolean();
} }

View File

@ -45,27 +45,7 @@
#include "jsapi.h" #include "jsapi.h"
JS_BEGIN_EXTERN_C extern js::Class js_BooleanClass;
/*
* Special values, not visible to script but used internally by the engine.
*
* JSVAL_HOLE is a useful value for identifying a hole in an array. It's also
* used in the interpreter to represent "no exception pending". In general it
* can be used to represent "no value".
*
* A JSVAL_HOLE can be cheaply converted to undefined without affecting any
* other boolean (or special value) by masking out JSVAL_HOLE_FLAG.
*
* JSVAL_ARETURN is used to throw asynchronous return for generator.close().
*
* NB: SPECIAL_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
*/
#define JSVAL_HOLE_FLAG jsval(4 << JSVAL_TAGBITS)
#define JSVAL_HOLE (JSVAL_VOID | JSVAL_HOLE_FLAG)
#define JSVAL_ARETURN SPECIAL_TO_JSVAL(8)
extern JSClass js_BooleanClass;
extern JSObject * extern JSObject *
js_InitBooleanClass(JSContext *cx, JSObject *obj); js_InitBooleanClass(JSContext *cx, JSObject *obj);
@ -77,8 +57,6 @@ extern JSBool
js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb); js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb);
extern JSBool extern JSBool
js_ValueToBoolean(jsval v); js_ValueToBoolean(const js::Value &v);
JS_END_EXTERN_C
#endif /* jsbool_h___ */ #endif /* jsbool_h___ */

View File

@ -222,7 +222,7 @@ struct ClosureVarInfo;
#define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CLASS _JS_CTYPE(JSClass *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_CLASS _JS_CTYPE(js::Class *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_APNPTR _JS_CTYPE(ArgsPrivateNative *, _JS_PTR, --, --, INFALLIBLE) #define _JS_CTYPE_APNPTR _JS_CTYPE(ArgsPrivateNative *, _JS_PTR, --, --, INFALLIBLE)

View File

@ -38,6 +38,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS execution context. * JS execution context.
*/ */
@ -104,7 +106,7 @@ CallStack::contains(const JSStackFrame *fp) const
JSStackFrame *start; JSStackFrame *start;
JSStackFrame *stop; JSStackFrame *stop;
if (isSuspended()) { if (isSuspended()) {
start = suspendedFrame; start = suspendedFrame();
stop = initialFrame->down; stop = initialFrame->down;
} else { } else {
start = cx->fp; start = cx->fp;
@ -129,7 +131,7 @@ StackSpace::init()
void *check = VirtualAlloc(p, sCommitBytes, MEM_COMMIT, PAGE_READWRITE); void *check = VirtualAlloc(p, sCommitBytes, MEM_COMMIT, PAGE_READWRITE);
if (p != check) if (p != check)
return false; return false;
base = reinterpret_cast<jsval *>(p); base = reinterpret_cast<Value *>(p);
commitEnd = base + sCommitVals; commitEnd = base + sCommitVals;
end = base + sCapacityVals; end = base + sCapacityVals;
#else #else
@ -137,7 +139,7 @@ StackSpace::init()
p = mmap(NULL, sCapacityBytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); p = mmap(NULL, sCapacityBytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (p == MAP_FAILED) if (p == MAP_FAILED)
return false; return false;
base = reinterpret_cast<jsval *>(p); base = reinterpret_cast<Value *>(p);
end = base + sCapacityVals; end = base + sCapacityVals;
#endif #endif
return true; return true;
@ -147,7 +149,7 @@ void
StackSpace::finish() StackSpace::finish()
{ {
#ifdef XP_WIN #ifdef XP_WIN
VirtualFree(base, (commitEnd - base) * sizeof(jsval), MEM_DECOMMIT); VirtualFree(base, (commitEnd - base) * sizeof(Value), MEM_DECOMMIT);
VirtualFree(base, 0, MEM_RELEASE); VirtualFree(base, 0, MEM_RELEASE);
#else #else
munmap(base, sCapacityBytes); munmap(base, sCapacityBytes);
@ -156,11 +158,11 @@ StackSpace::finish()
#ifdef XP_WIN #ifdef XP_WIN
JS_FRIEND_API(bool) JS_FRIEND_API(bool)
StackSpace::bumpCommit(jsval *from, ptrdiff_t nvals) const StackSpace::bumpCommit(Value *from, ptrdiff_t nvals) const
{ {
JS_ASSERT(end - from >= nvals); JS_ASSERT(end - from >= nvals);
jsval *newCommit = commitEnd; Value *newCommit = commitEnd;
jsval *request = from + nvals; Value *request = from + nvals;
/* Use a dumb loop; will probably execute once. */ /* Use a dumb loop; will probably execute once. */
JS_ASSERT((end - newCommit) % sCommitVals == 0); JS_ASSERT((end - newCommit) % sCommitVals == 0);
@ -170,7 +172,7 @@ StackSpace::bumpCommit(jsval *from, ptrdiff_t nvals) const
} while(newCommit < request); } while(newCommit < request);
/* Cast safe because sCapacityBytes is small. */ /* Cast safe because sCapacityBytes is small. */
int32 size = (int32)(newCommit - commitEnd) * sizeof(jsval); int32 size = (int32)(newCommit - commitEnd) * sizeof(Value);
if (!VirtualAlloc(commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) if (!VirtualAlloc(commitEnd, size, MEM_COMMIT, PAGE_READWRITE))
return false; return false;
@ -186,7 +188,7 @@ StackSpace::mark(JSTracer *trc)
* The correctness/completeness of marking depends on the continuity * The correctness/completeness of marking depends on the continuity
* invariants described by the CallStack and StackSpace definitions. * invariants described by the CallStack and StackSpace definitions.
*/ */
jsval *end = firstUnused(); Value *end = firstUnused();
for (CallStack *cs = currentCallStack; cs; cs = cs->getPreviousInThread()) { for (CallStack *cs = currentCallStack; cs; cs = cs->getPreviousInThread()) {
if (!cs->inContext()) { if (!cs->inContext()) {
/* Mark slots/args trailing off callstack. */ /* Mark slots/args trailing off callstack. */
@ -219,14 +221,14 @@ StackSpace::mark(JSTracer *trc)
JS_REQUIRES_STACK bool JS_REQUIRES_STACK bool
StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard &ag) StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard &ag)
{ {
jsval *start = firstUnused(); Value *start = firstUnused();
uintN vplen = 2 + argc; uintN vplen = 2 + argc;
ptrdiff_t nvals = ValuesPerCallStack + vplen; ptrdiff_t nvals = ValuesPerCallStack + vplen;
if (!ensureSpace(cx, start, nvals)) if (!ensureSpace(cx, start, nvals))
return false; return false;
jsval *vp = start + ValuesPerCallStack; Value *vp = start + ValuesPerCallStack;
jsval *vpend = vp + vplen; Value *vpend = vp + vplen;
memset(vp, 0, vplen * sizeof(jsval)); /* Init so GC-safe on exit. */ memset(vp, 0, vplen * sizeof(*vp)); /* Init so GC-safe on exit. */
CallStack *cs = new(start) CallStack; CallStack *cs = new(start) CallStack;
cs->setInitialArgEnd(vpend); cs->setInitialArgEnd(vpend);
@ -264,7 +266,7 @@ StackSpace::getInvokeFrame(JSContext *cx, const InvokeArgsGuard &ag,
{ {
if (ag.cs) { if (ag.cs) {
JS_ASSERT(ag.cs == currentCallStack && !ag.cs->inContext()); JS_ASSERT(ag.cs == currentCallStack && !ag.cs->inContext());
jsval *start = ag.cs->getInitialArgEnd(); Value *start = ag.cs->getInitialArgEnd();
ptrdiff_t nvals = nmissing + ValuesPerStackFrame + nslots; ptrdiff_t nvals = nmissing + ValuesPerStackFrame + nslots;
if (!ensureSpace(cx, start, nvals)) if (!ensureSpace(cx, start, nvals))
return false; return false;
@ -273,7 +275,7 @@ StackSpace::getInvokeFrame(JSContext *cx, const InvokeArgsGuard &ag,
} }
JS_ASSERT(isCurrent(cx) && currentCallStack->isActive()); JS_ASSERT(isCurrent(cx) && currentCallStack->isActive());
jsval *start = cx->regs->sp; Value *start = cx->regs->sp;
ptrdiff_t nvals = nmissing + ValuesPerCallStack + ValuesPerStackFrame + nslots; ptrdiff_t nvals = nmissing + ValuesPerCallStack + ValuesPerStackFrame + nslots;
if (!ensureSpace(cx, start, nvals)) if (!ensureSpace(cx, start, nvals))
return false; return false;
@ -342,7 +344,7 @@ StackSpace::getExecuteFrame(JSContext *cx, JSStackFrame *down,
uintN vplen, uintN nslots, uintN vplen, uintN nslots,
ExecuteFrameGuard &fg) const ExecuteFrameGuard &fg) const
{ {
jsval *start = firstUnused(); Value *start = firstUnused();
ptrdiff_t nvals = ValuesPerCallStack + vplen + ValuesPerStackFrame + nslots; ptrdiff_t nvals = ValuesPerCallStack + vplen + ValuesPerStackFrame + nslots;
if (!ensureSpace(cx, start, nvals)) if (!ensureSpace(cx, start, nvals))
return false; return false;
@ -378,7 +380,7 @@ StackSpace::popExecuteFrame(JSContext *cx)
JS_REQUIRES_STACK void JS_REQUIRES_STACK void
StackSpace::getSynthesizedSlowNativeFrame(JSContext *cx, CallStack *&cs, JSStackFrame *&fp) StackSpace::getSynthesizedSlowNativeFrame(JSContext *cx, CallStack *&cs, JSStackFrame *&fp)
{ {
jsval *start = firstUnused(); Value *start = firstUnused();
JS_ASSERT(size_t(end - start) >= ValuesPerCallStack + ValuesPerStackFrame); JS_ASSERT(size_t(end - start) >= ValuesPerCallStack + ValuesPerStackFrame);
cs = new(start) CallStack; cs = new(start) CallStack;
fp = reinterpret_cast<JSStackFrame *>(cs + 1); fp = reinterpret_cast<JSStackFrame *>(cs + 1);
@ -412,16 +414,16 @@ StackSpace::popSynthesizedSlowNativeFrame(JSContext *cx)
* up-frame's address is the top of the down-frame's stack, modulo missing * up-frame's address is the top of the down-frame's stack, modulo missing
* arguments. * arguments.
*/ */
static inline jsval * static inline Value *
InlineDownFrameSP(JSStackFrame *up) InlineDownFrameSP(JSStackFrame *up)
{ {
JS_ASSERT(up->fun && up->script); JS_ASSERT(up->fun && up->script);
jsval *sp = up->argv + up->argc; Value *sp = up->argv + up->argc;
#ifdef DEBUG #ifdef DEBUG
uint16 nargs = up->fun->nargs; uint16 nargs = up->fun->nargs;
uintN argc = up->argc; uintN argc = up->argc;
uintN missing = argc < nargs ? nargs - argc : 0; uintN missing = argc < nargs ? nargs - argc : 0;
JS_ASSERT(sp == (jsval *)up - missing); JS_ASSERT(sp == (Value *)up - missing);
#endif #endif
return sp; return sp;
} }
@ -1351,7 +1353,7 @@ resolving_HashKey(JSDHashTable *table, const void *ptr)
{ {
const JSResolvingKey *key = (const JSResolvingKey *)ptr; const JSResolvingKey *key = (const JSResolvingKey *)ptr;
return (JSDHashNumber(uintptr_t(key->obj)) >> JSVAL_TAGBITS) ^ key->id; return (JSDHashNumber(uintptr_t(key->obj)) >> JSBOXEDWORD_TAGBITS) ^ key->id;
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
@ -1468,7 +1470,7 @@ js_EnterLocalRootScope(JSContext *cx)
} }
/* Push lrs->scopeMark to save it for restore when leaving. */ /* Push lrs->scopeMark to save it for restore when leaving. */
int mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark)); int mark = js_PushLocalRoot(cx, lrs, (void *)lrs->scopeMark);
if (mark < 0) if (mark < 0)
return JS_FALSE; return JS_FALSE;
lrs->scopeMark = (uint32) mark; lrs->scopeMark = (uint32) mark;
@ -1476,7 +1478,7 @@ js_EnterLocalRootScope(JSContext *cx)
} }
void void
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval) js_LeaveLocalRootScopeWithResult(JSContext *cx, const Value &rval)
{ {
JSLocalRootStack *lrs; JSLocalRootStack *lrs;
uint32 mark, m, n; uint32 mark, m, n;
@ -1512,10 +1514,10 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
*/ */
lrc = lrs->topChunk; lrc = lrs->topChunk;
m = mark & JSLRS_CHUNK_MASK; m = mark & JSLRS_CHUNK_MASK;
lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]); lrs->scopeMark = (uint32) lrc->roots[m];
if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) { if (rval.isGCThing()) {
if (mark == 0) { if (mark == 0) {
cx->weakRoots.lastInternalResult = rval; cx->weakRoots.lastInternalResult = rval.asGCThing();
} else { } else {
/* /*
* Increment m to avoid the "else if (m == 0)" case below. If * Increment m to avoid the "else if (m == 0)" case below. If
@ -1523,7 +1525,7 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
* any chunk that contained only the old mark. Since rval *is* * any chunk that contained only the old mark. Since rval *is*
* a GC-thing here, we want to reuse that old mark's slot. * a GC-thing here, we want to reuse that old mark's slot.
*/ */
lrc->roots[m++] = rval; lrc->roots[m++] = rval.asGCThing();
++mark; ++mark;
} }
} }
@ -1551,41 +1553,36 @@ js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
} }
void void
js_ForgetLocalRoot(JSContext *cx, jsval v) js_ForgetLocalRoot(JSContext *cx, void *thing)
{ {
JSLocalRootStack *lrs; JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack;
uint32 i, j, m, n, mark;
JSLocalRootChunk *lrc, *lrc2;
jsval top;
lrs = JS_THREAD_DATA(cx)->localRootStack;
JS_ASSERT(lrs && lrs->rootCount); JS_ASSERT(lrs && lrs->rootCount);
if (!lrs || lrs->rootCount == 0) if (!lrs || lrs->rootCount == 0)
return; return;
/* Prepare to pop the top-most value from the stack. */ /* Prepare to pop the top-most value from the stack. */
n = lrs->rootCount - 1; uint32 n = lrs->rootCount - 1;
m = n & JSLRS_CHUNK_MASK; uint32 m = n & JSLRS_CHUNK_MASK;
lrc = lrs->topChunk; JSLocalRootChunk *lrc = lrs->topChunk;
top = lrc->roots[m]; void *top = lrc->roots[m];
/* Be paranoid about calls on an empty scope. */ /* Be paranoid about calls on an empty scope. */
mark = lrs->scopeMark; uint32 mark = lrs->scopeMark;
JS_ASSERT(mark < n); JS_ASSERT(mark < n);
if (mark >= n) if (mark >= n)
return; return;
/* If v was not the last root pushed in the top scope, find it. */ /* If thing was not the last root pushed in the top scope, find it. */
if (top != v) { if (top != thing) {
/* Search downward in case v was recently pushed. */ /* Search downward in case thing was recently pushed. */
i = n; uint32 i = n;
j = m; uint32 j = m;
lrc2 = lrc; JSLocalRootChunk *lrc2 = lrc;
while (--i > mark) { while (--i > mark) {
if (j == 0) if (j == 0)
lrc2 = lrc2->down; lrc2 = lrc2->down;
j = i & JSLRS_CHUNK_MASK; j = i & JSLRS_CHUNK_MASK;
if (lrc2->roots[j] == v) if (lrc2->roots[j] == thing)
break; break;
} }
@ -1599,7 +1596,7 @@ js_ForgetLocalRoot(JSContext *cx, jsval v)
} }
/* Pop the last value from the stack. */ /* Pop the last value from the stack. */
lrc->roots[m] = JSVAL_NULL; lrc->roots[m] = NULL;
lrs->rootCount = n; lrs->rootCount = n;
if (m == 0) { if (m == 0) {
JS_ASSERT(n != 0); JS_ASSERT(n != 0);
@ -1610,7 +1607,7 @@ js_ForgetLocalRoot(JSContext *cx, jsval v)
} }
int int
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v) js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, void *thing)
{ {
uint32 n, m; uint32 n, m;
JSLocalRootChunk *lrc; JSLocalRootChunk *lrc;
@ -1643,35 +1640,32 @@ js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
lrs->topChunk = lrc; lrs->topChunk = lrc;
} }
lrs->rootCount = n + 1; lrs->rootCount = n + 1;
lrc->roots[m] = v; lrc->roots[m] = thing;
return (int) n; return (int) n;
} }
static void static void
MarkLocalRoots(JSTracer *trc, JSLocalRootStack *lrs) MarkLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
{ {
uint32 n, m, mark; uint32 n = lrs->rootCount;
JSLocalRootChunk *lrc;
jsval v;
n = lrs->rootCount;
if (n == 0) if (n == 0)
return; return;
mark = lrs->scopeMark; uint32 mark = lrs->scopeMark;
lrc = lrs->topChunk; JSLocalRootChunk *lrc = lrs->topChunk;
do { do {
uint32 m;
while (--n > mark) { while (--n > mark) {
m = n & JSLRS_CHUNK_MASK; m = n & JSLRS_CHUNK_MASK;
v = lrc->roots[m]; void *thing = lrc->roots[m];
JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL); JS_ASSERT(thing != NULL);
JS_SET_TRACING_INDEX(trc, "local_root", n); JS_SET_TRACING_INDEX(trc, "local_root", n);
js_CallValueTracerIfGCThing(trc, v); CallGCMarkerForGCThing(trc, thing);
if (m == 0) if (m == 0)
lrc = lrc->down; lrc = lrc->down;
} }
m = n & JSLRS_CHUNK_MASK; m = n & JSLRS_CHUNK_MASK;
mark = JSVAL_TO_INT(lrc->roots[m]); mark = (uint32)lrc->roots[m];
if (m == 0) if (m == 0)
lrc = lrc->down; lrc = lrc->down;
} while (n != 0); } while (n != 0);
@ -2114,13 +2108,13 @@ js_ReportIsNotDefined(JSContext *cx, const char *name)
} }
JSBool JSBool
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v, js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const Value &v,
JSString *fallback) JSString *fallback)
{ {
char *bytes; char *bytes;
JSBool ok; JSBool ok;
bytes = js_DecompileValueGenerator(cx, spindex, v, fallback); bytes = js_DecompileValueGenerator(cx, spindex, Jsvalify(&v), fallback);
if (!bytes) if (!bytes)
return JS_FALSE; return JS_FALSE;
@ -2130,13 +2124,13 @@ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
js_GetErrorMessage, NULL, js_GetErrorMessage, NULL,
JSMSG_NO_PROPERTIES, bytes, JSMSG_NO_PROPERTIES, bytes,
NULL, NULL); NULL, NULL);
} else if (JSVAL_IS_VOID(v)) { } else if (v.isUndefined()) {
ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
js_GetErrorMessage, NULL, js_GetErrorMessage, NULL,
JSMSG_UNEXPECTED_TYPE, bytes, JSMSG_UNEXPECTED_TYPE, bytes,
js_undefined_str, NULL); js_undefined_str, NULL);
} else { } else {
JS_ASSERT(JSVAL_IS_NULL(v)); JS_ASSERT(v.isNull());
ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
js_GetErrorMessage, NULL, js_GetErrorMessage, NULL,
JSMSG_UNEXPECTED_TYPE, bytes, JSMSG_UNEXPECTED_TYPE, bytes,
@ -2148,7 +2142,7 @@ js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
} }
void void
js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg) js_ReportMissingArg(JSContext *cx, const Value &v, uintN arg)
{ {
char argbuf[11]; char argbuf[11];
char *bytes; char *bytes;
@ -2156,9 +2150,10 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
JS_snprintf(argbuf, sizeof argbuf, "%u", arg); JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
bytes = NULL; bytes = NULL;
if (VALUE_IS_FUNCTION(cx, *vp)) { if (v.isFunObj()) {
atom = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp))->atom; atom = GET_FUNCTION_PRIVATE(cx, &v.asFunObj())->atom;
bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp, bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK,
Jsvalify(&v),
ATOM_TO_STRING(atom)); ATOM_TO_STRING(atom));
if (!bytes) if (!bytes)
return; return;
@ -2171,7 +2166,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
JSBool JSBool
js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber, js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
intN spindex, jsval v, JSString *fallback, intN spindex, const Value &v, JSString *fallback,
const char *arg1, const char *arg2) const char *arg1, const char *arg2)
{ {
char *bytes; char *bytes;
@ -2179,7 +2174,7 @@ js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1); JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3); JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
bytes = js_DecompileValueGenerator(cx, spindex, v, fallback); bytes = js_DecompileValueGenerator(cx, spindex, Jsvalify(&v), fallback);
if (!bytes) if (!bytes)
return JS_FALSE; return JS_FALSE;

View File

@ -285,62 +285,71 @@ class CallStack
/* The first frame executed in this callstack. null iff cx is null */ /* The first frame executed in this callstack. null iff cx is null */
JSStackFrame *initialFrame; JSStackFrame *initialFrame;
/* If this callstack is suspended, the top of the callstack. */ /*
JSStackFrame *suspendedFrame; * Two values packed together to get sizeof(Value) alignment.
* suspendedFrame: if this callstack is suspended, the top of the callstack.
* saved: if this callstack is suspended, whether it is also saved.
*/
AlignedPtrAndFlag<JSStackFrame> suspendedFrameAndSaved;
/* If this callstack is suspended, |cx->regs| when it was suspended. */ /* If this callstack is suspended, |cx->regs| when it was suspended. */
JSFrameRegs *suspendedRegs; JSFrameRegs *suspendedRegs;
/* This callstack was suspended by JS_SaveFrameChain. */
bool saved;
/* End of arguments before the first frame. See StackSpace comment. */ /* End of arguments before the first frame. See StackSpace comment. */
jsval *initialArgEnd; js::Value *initialArgEnd;
/* The varobj on entry to initialFrame. */ /* The varobj on entry to initialFrame. */
JSObject *initialVarObj; JSObject *initialVarObj;
JSStackFrame *suspendedFrame() const {
return suspendedFrameAndSaved.ptr();
}
bool saved() const {
return suspendedFrameAndSaved.flag();
}
public: public:
CallStack() CallStack()
: cx(NULL), previousInContext(NULL), previousInThread(NULL), : cx(NULL), previousInContext(NULL), previousInThread(NULL),
initialFrame(NULL), suspendedFrame(NULL), saved(false), initialFrame(NULL), suspendedFrameAndSaved(NULL, false),
initialArgEnd(NULL), initialVarObj(NULL) initialArgEnd(NULL), initialVarObj(NULL)
{} {}
/* Safe casts guaranteed by the contiguous-stack layout. */ /* Safe casts guaranteed by the contiguous-stack layout. */
jsval *previousCallStackEnd() const { Value *previousCallStackEnd() const {
return (jsval *)this; return (Value *)this;
} }
jsval *getInitialArgBegin() const { Value *getInitialArgBegin() const {
return (jsval *)(this + 1); return (Value *)(this + 1);
} }
/* The three mutually exclusive states of a callstack */ /* The three mutually exclusive states of a callstack */
bool inContext() const { bool inContext() const {
JS_ASSERT(!!cx == !!initialFrame); JS_ASSERT(!!cx == !!initialFrame);
JS_ASSERT_IF(!initialFrame, !suspendedFrame && !saved); JS_ASSERT_IF(!initialFrame, !suspendedFrame() && !saved());
return cx; return cx;
} }
bool isActive() const { bool isActive() const {
JS_ASSERT_IF(suspendedFrame, inContext()); JS_ASSERT_IF(suspendedFrame(), inContext());
return initialFrame && !suspendedFrame; return initialFrame && !suspendedFrame();
} }
bool isSuspended() const { bool isSuspended() const {
JS_ASSERT_IF(!suspendedFrame, !saved); JS_ASSERT_IF(!suspendedFrame(), !saved());
JS_ASSERT_IF(suspendedFrame, inContext()); JS_ASSERT_IF(suspendedFrame(), inContext());
return suspendedFrame; return !!suspendedFrame();
} }
/* Substate of suspended, queryable in any state. */ /* Substate of suspended, queryable in any state. */
bool isSaved() const { bool isSaved() const {
JS_ASSERT_IF(saved, isSuspended()); JS_ASSERT_IF(saved(), isSuspended());
return saved; return saved();
} }
/* Transitioning between inContext <--> isActive */ /* Transitioning between inContext <--> isActive */
@ -365,37 +374,37 @@ class CallStack
void suspend(JSStackFrame *fp, JSFrameRegs *regs) { void suspend(JSStackFrame *fp, JSFrameRegs *regs) {
JS_ASSERT(fp && isActive() && contains(fp)); JS_ASSERT(fp && isActive() && contains(fp));
suspendedFrame = fp; suspendedFrameAndSaved.set(fp, false);
suspendedRegs = regs; suspendedRegs = regs;
} }
void resume() { void resume() {
JS_ASSERT(suspendedFrame); JS_ASSERT(suspendedFrame());
suspendedFrame = NULL; suspendedFrameAndSaved.set(NULL, false);
} }
/* When isSuspended, transitioning isSaved <--> !isSaved */ /* When isSuspended, transitioning isSaved <--> !isSaved */
void save(JSStackFrame *fp, JSFrameRegs *regs) { void save(JSStackFrame *fp, JSFrameRegs *regs) {
JS_ASSERT(!saved); JS_ASSERT(!saved());
suspend(fp, regs); suspend(fp, regs);
saved = true; suspendedFrameAndSaved.setFlag();
} }
void restore() { void restore() {
JS_ASSERT(saved); JS_ASSERT(saved());
saved = false; suspendedFrameAndSaved.unsetFlag();
resume(); resume();
} }
/* Data available when !inContext */ /* Data available when !inContext */
void setInitialArgEnd(jsval *v) { void setInitialArgEnd(Value *v) {
JS_ASSERT(!inContext() && !initialArgEnd); JS_ASSERT(!inContext() && !initialArgEnd);
initialArgEnd = v; initialArgEnd = v;
} }
jsval *getInitialArgEnd() const { Value *getInitialArgEnd() const {
JS_ASSERT(!inContext() && initialArgEnd); JS_ASSERT(!inContext() && initialArgEnd);
return initialArgEnd; return initialArgEnd;
} }
@ -413,7 +422,7 @@ class CallStack
JSStackFrame *getSuspendedFrame() const { JSStackFrame *getSuspendedFrame() const {
JS_ASSERT(isSuspended()); JS_ASSERT(isSuspended());
return suspendedFrame; return suspendedFrame();
} }
JSFrameRegs *getSuspendedRegs() const { JSFrameRegs *getSuspendedRegs() const {
@ -421,7 +430,7 @@ class CallStack
return suspendedRegs; return suspendedRegs;
} }
jsval *getSuspendedSP() const { js::Value *getSuspendedSP() const {
JS_ASSERT(isSuspended()); JS_ASSERT(isSuspended());
return suspendedRegs->sp; return suspendedRegs->sp;
} }
@ -460,8 +469,8 @@ class CallStack
}; };
JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(jsval) == 0); JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(Value) == 0);
static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(jsval); static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(Value);
/* /*
* The ternary constructor is used when arguments are already pushed on the * The ternary constructor is used when arguments are already pushed on the
@ -473,13 +482,13 @@ class InvokeArgsGuard
friend class StackSpace; friend class StackSpace;
JSContext *cx; JSContext *cx;
CallStack *cs; /* null implies nothing pushed */ CallStack *cs; /* null implies nothing pushed */
jsval *vp; Value *vp;
uintN argc; uintN argc;
public: public:
inline InvokeArgsGuard(); inline InvokeArgsGuard();
inline InvokeArgsGuard(jsval *vp, uintN argc); inline InvokeArgsGuard(Value *vp, uintN argc);
inline ~InvokeArgsGuard(); inline ~InvokeArgsGuard();
jsval *getvp() const { return vp; } Value *getvp() const { return vp; }
uintN getArgc() const { JS_ASSERT(vp != NULL); return argc; } uintN getArgc() const { JS_ASSERT(vp != NULL); return argc; }
}; };
@ -502,13 +511,13 @@ class ExecuteFrameGuard
friend class StackSpace; friend class StackSpace;
JSContext *cx; /* null implies nothing pushed */ JSContext *cx; /* null implies nothing pushed */
CallStack *cs; CallStack *cs;
jsval *vp; Value *vp;
JSStackFrame *fp; JSStackFrame *fp;
JSStackFrame *down; JSStackFrame *down;
public: public:
ExecuteFrameGuard(); ExecuteFrameGuard();
JS_REQUIRES_STACK ~ExecuteFrameGuard(); JS_REQUIRES_STACK ~ExecuteFrameGuard();
jsval *getvp() const { return vp; } Value *getvp() const { return vp; }
JSStackFrame *getFrame() const { return fp; } JSStackFrame *getFrame() const { return fp; }
}; };
@ -537,7 +546,7 @@ class ExecuteFrameGuard
* ? <----' `----------' `----------' * ? <----' `----------' `----------'
* *
* Moreover, the bytes between a callstack and its first frame and between two * Moreover, the bytes between a callstack and its first frame and between two
* adjacent frames in a callstack are GC-able jsvals. If the current frame's * adjacent frames in a callstack are GC-able Values. If the current frame's
* regs pointer is null (e.g., native frame), there are no final slots. * regs pointer is null (e.g., native frame), there are no final slots.
* *
* An empty callstack roots the initial slots before the initial frame is * An empty callstack roots the initial slots before the initial frame is
@ -570,16 +579,16 @@ class ExecuteFrameGuard
*/ */
class StackSpace class StackSpace
{ {
jsval *base; Value *base;
#ifdef XP_WIN #ifdef XP_WIN
mutable jsval *commitEnd; mutable Value *commitEnd;
#endif #endif
jsval *end; Value *end;
CallStack *currentCallStack; CallStack *currentCallStack;
/* Although guards are friends, XGuard should only call popX(). */ /* Although guards are friends, XGuard should only call popX(). */
friend class InvokeArgsGuard; friend class InvokeArgsGuard;
JS_REQUIRES_STACK inline void popInvokeArgs(JSContext *cx, jsval *vp); JS_REQUIRES_STACK inline void popInvokeArgs(JSContext *cx, Value *vp);
friend class InvokeFrameGuard; friend class InvokeFrameGuard;
JS_REQUIRES_STACK void popInvokeFrame(JSContext *cx, CallStack *maybecs); JS_REQUIRES_STACK void popInvokeFrame(JSContext *cx, CallStack *maybecs);
friend class ExecuteFrameGuard; friend class ExecuteFrameGuard;
@ -587,7 +596,7 @@ class StackSpace
/* Return a pointer to the first unused slot. */ /* Return a pointer to the first unused slot. */
JS_REQUIRES_STACK JS_REQUIRES_STACK
inline jsval *firstUnused() const; inline Value *firstUnused() const;
#ifdef DEBUG #ifdef DEBUG
inline bool isCurrent(JSContext *cx) const; inline bool isCurrent(JSContext *cx) const;
@ -598,18 +607,18 @@ class StackSpace
* Return whether nvals can be allocated from the top of the stack. * Return whether nvals can be allocated from the top of the stack.
* N.B. the caller must ensure |from == firstUnused()|. * N.B. the caller must ensure |from == firstUnused()|.
*/ */
inline bool ensureSpace(JSContext *maybecx, jsval *from, ptrdiff_t nvals) const; inline bool ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const;
#ifdef XP_WIN #ifdef XP_WIN
/* Commit more memory from the reserved stack space. */ /* Commit more memory from the reserved stack space. */
JS_FRIEND_API(bool) bumpCommit(jsval *from, ptrdiff_t nvals) const; JS_FRIEND_API(bool) bumpCommit(Value *from, ptrdiff_t nvals) const;
#endif #endif
public: public:
static const size_t sCapacityVals = 512 * 1024; static const size_t sCapacityVals = 512 * 1024;
static const size_t sCapacityBytes = sCapacityVals * sizeof(jsval); static const size_t sCapacityBytes = sCapacityVals * sizeof(Value);
static const size_t sCommitVals = 16 * 1024; static const size_t sCommitVals = 16 * 1024;
static const size_t sCommitBytes = sCommitVals * sizeof(jsval); static const size_t sCommitBytes = sCommitVals * sizeof(Value);
JS_STATIC_ASSERT(sCapacityVals % sCommitVals == 0); JS_STATIC_ASSERT(sCapacityVals % sCommitVals == 0);
@ -694,7 +703,7 @@ class StackSpace
* call pushInlineFrame/popInlineFrame. * call pushInlineFrame/popInlineFrame.
*/ */
JS_REQUIRES_STACK JS_REQUIRES_STACK
inline JSStackFrame *getInlineFrame(JSContext *cx, jsval *sp, inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp,
uintN nmissing, uintN nslots) const; uintN nmissing, uintN nslots) const;
JS_REQUIRES_STACK JS_REQUIRES_STACK
@ -737,7 +746,7 @@ class FrameRegsIter
{ {
CallStack *curcs; CallStack *curcs;
JSStackFrame *curfp; JSStackFrame *curfp;
jsval *cursp; Value *cursp;
jsbytecode *curpc; jsbytecode *curpc;
public: public:
@ -747,7 +756,7 @@ class FrameRegsIter
FrameRegsIter &operator++(); FrameRegsIter &operator++();
JSStackFrame *fp() const { return curfp; } JSStackFrame *fp() const { return curfp; }
jsval *sp() const { return cursp; } Value *sp() const { return cursp; }
jsbytecode *pc() const { return curpc; } jsbytecode *pc() const { return curpc; }
}; };
@ -923,7 +932,7 @@ struct JSLocalRootChunk;
#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT) #define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT)
struct JSLocalRootChunk { struct JSLocalRootChunk {
jsval roots[JSLRS_CHUNK_SIZE]; void *roots[JSLRS_CHUNK_SIZE];
JSLocalRootChunk *down; JSLocalRootChunk *down;
}; };
@ -1141,12 +1150,24 @@ struct JSClassProtoCache {
#endif #endif
friend JSBool js_GetClassPrototype(JSContext *cx, JSObject *scope, friend JSBool js_GetClassPrototype(JSContext *cx, JSObject *scope,
JSProtoKey protoKey, JSObject **protop, JSProtoKey protoKey, JSObject **protop,
JSClass *clasp); js::Class *clasp);
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC visibility pop # pragma GCC visibility pop
#endif #endif
}; };
struct JSRootInfo {
JSRootInfo() {}
JSRootInfo(const char *name, JSGCRootType type) : name(name), type(type) {}
const char *name;
JSGCRootType type;
};
typedef js::HashMap<void *,
JSRootInfo,
js::DefaultHasher<void *>,
js::SystemAllocPolicy> JSRootedValueMap;
struct JSRuntime { struct JSRuntime {
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */ /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
JSRuntimeState state; JSRuntimeState state;
@ -1172,7 +1193,7 @@ struct JSRuntime {
JSGCChunkInfo *gcChunkList; JSGCChunkInfo *gcChunkList;
JSGCArenaList gcArenaList[FINALIZE_LIMIT]; JSGCArenaList gcArenaList[FINALIZE_LIMIT];
JSGCDoubleArenaList gcDoubleArenaList; JSGCDoubleArenaList gcDoubleArenaList;
JSDHashTable gcRootsHash; JSRootedValueMap gcRootsHash;
JSDHashTable gcLocksHash; JSDHashTable gcLocksHash;
jsrefcount gcKeepAtoms; jsrefcount gcKeepAtoms;
size_t gcBytes; size_t gcBytes;
@ -1249,9 +1270,9 @@ struct JSRuntime {
JSSetSlotRequest *setSlotRequests; JSSetSlotRequest *setSlotRequests;
/* Well-known numbers held for use by this runtime's contexts. */ /* Well-known numbers held for use by this runtime's contexts. */
jsval NaNValue; js::Value NaNValue;
jsval negativeInfinityValue; js::Value negativeInfinityValue;
jsval positiveInfinityValue; js::Value positiveInfinityValue;
js::DeflatedStringCache *deflatedStringCache; js::DeflatedStringCache *deflatedStringCache;
@ -1640,7 +1661,7 @@ struct JSContext
/* /*
* cx->resolvingTable is non-null and non-empty if we are initializing * cx->resolvingTable is non-null and non-empty if we are initializing
* standard classes lazily, or if we are otherwise recursing indirectly * standard classes lazily, or if we are otherwise recursing indirectly
* from js_LookupProperty through a JSClass.resolve hook. It is used to * from js_LookupProperty through a Class.resolve hook. It is used to
* limit runaway recursion (see jsapi.c and jsobj.c). * limit runaway recursion (see jsapi.c and jsobj.c).
*/ */
JSDHashTable *resolvingTable; JSDHashTable *resolvingTable;
@ -1656,7 +1677,7 @@ struct JSContext
/* Exception state -- the exception member is a GC root by definition. */ /* Exception state -- the exception member is a GC root by definition. */
JSPackedBool throwing; /* is there a pending exception? */ JSPackedBool throwing; /* is there a pending exception? */
jsval exception; /* most-recently-thrown exception */ js::Value exception; /* most-recently-thrown exception */
/* Limit pointer for checking native stack consumption during recursion. */ /* Limit pointer for checking native stack consumption during recursion. */
jsuword stackLimit; jsuword stackLimit;
@ -1680,7 +1701,7 @@ struct JSContext
private: private:
friend class js::StackSpace; friend class js::StackSpace;
friend JSBool js_Interpret(JSContext *); friend bool js::Interpret(JSContext *);
/* 'fp' and 'regs' must only be changed by calling these functions. */ /* 'fp' and 'regs' must only be changed by calling these functions. */
void setCurrentFrame(JSStackFrame *fp) { void setCurrentFrame(JSStackFrame *fp) {
@ -2034,8 +2055,8 @@ struct JSContext
#ifdef DEBUG #ifdef DEBUG
void assertValidStackDepth(uintN depth) { void assertValidStackDepth(uintN depth) {
JS_ASSERT(0 <= regs->sp - StackBase(fp)); JS_ASSERT(0 <= regs->sp - fp->base());
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(fp))); JS_ASSERT(depth <= uintptr_t(regs->sp - fp->base()));
} }
#else #else
void assertValidStackDepth(uintN /*depth*/) {} void assertValidStackDepth(uintN /*depth*/) {}
@ -2124,7 +2145,7 @@ class AutoGCRooter {
/* /*
* Discriminates actual subclass of this being used. If non-negative, the * Discriminates actual subclass of this being used. If non-negative, the
* subclass roots an array of jsvals of the length stored in this field. * subclass roots an array of values of the length stored in this field.
* If negative, meaning is indicated by the corresponding value in the enum * If negative, meaning is indicated by the corresponding value in the enum
* below. Any other negative value indicates some deeper problem such as * below. Any other negative value indicates some deeper problem such as
* memory corruption. * memory corruption.
@ -2171,48 +2192,49 @@ class AutoSaveWeakRoots : private AutoGCRooter
class AutoValueRooter : private AutoGCRooter class AutoValueRooter : private AutoGCRooter
{ {
public: public:
explicit AutoValueRooter(JSContext *cx, jsval v = JSVAL_NULL explicit AutoValueRooter(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM) JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(v) : AutoGCRooter(cx, JSVAL), val(js::NullValue())
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
} }
AutoValueRooter(JSContext *cx, const Value &v
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL)
{
val.copy(v);
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
AutoValueRooter(JSContext *cx, JSString *str AutoValueRooter(JSContext *cx, JSString *str
JS_GUARD_OBJECT_NOTIFIER_PARAM) JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(STRING_TO_JSVAL(str)) : AutoGCRooter(cx, JSVAL), val(str)
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
} }
AutoValueRooter(JSContext *cx, JSObject *obj /*
JS_GUARD_OBJECT_NOTIFIER_PARAM) * If you are looking for Object* overloads, use AutoObjectRooter instead;
: AutoGCRooter(cx, JSVAL), val(OBJECT_TO_JSVAL(obj)) * rooting Object*s as a js::Value requires discerning whether or not it is
{ * a function object. Also, AutoObjectRooter is smaller.
JS_GUARD_OBJECT_NOTIFIER_INIT; */
}
void setObject(JSObject *obj) {
JS_ASSERT(tag == JSVAL);
val = OBJECT_TO_JSVAL(obj);
}
void setString(JSString *str) { void setString(JSString *str) {
JS_ASSERT(tag == JSVAL); JS_ASSERT(tag == JSVAL);
JS_ASSERT(str); JS_ASSERT(str);
val = STRING_TO_JSVAL(str); val.setString(str);
} }
void setDouble(jsdouble *dp) { void setDouble(jsdouble d) {
JS_ASSERT(tag == JSVAL); JS_ASSERT(tag == JSVAL);
JS_ASSERT(dp); JS_ASSERT(d);
val = DOUBLE_TO_JSVAL(dp); val.setDouble(d);
} }
jsval value() const { const Value &value() const {
JS_ASSERT(tag == JSVAL); JS_ASSERT(tag == JSVAL);
return val; return val;
} }
jsval *addr() { Value *addr() {
JS_ASSERT(tag == JSVAL); JS_ASSERT(tag == JSVAL);
return &val; return &val;
} }
@ -2220,7 +2242,7 @@ class AutoValueRooter : private AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc); friend void AutoGCRooter::trace(JSTracer *trc);
private: private:
jsval val; Value val;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER JS_DECL_USE_GUARD_OBJECT_NOTIFIER
}; };
@ -2254,7 +2276,7 @@ class AutoObjectRooter : private AutoGCRooter {
class AutoArrayRooter : private AutoGCRooter { class AutoArrayRooter : private AutoGCRooter {
public: public:
AutoArrayRooter(JSContext *cx, size_t len, jsval *vec AutoArrayRooter(JSContext *cx, size_t len, Value *vec
JS_GUARD_OBJECT_NOTIFIER_PARAM) JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, len), array(vec) : AutoGCRooter(cx, len), array(vec)
{ {
@ -2267,12 +2289,12 @@ class AutoArrayRooter : private AutoGCRooter {
JS_ASSERT(tag >= 0); JS_ASSERT(tag >= 0);
} }
void changeArray(jsval *newArray, size_t newLength) { void changeArray(Value *newArray, size_t newLength) {
changeLength(newLength); changeLength(newLength);
array = newArray; array = newArray;
} }
jsval *array; Value *array;
friend void AutoGCRooter::trace(JSTracer *trc); friend void AutoGCRooter::trace(JSTracer *trc);
@ -2385,14 +2407,14 @@ class AutoEnumStateRooter : private AutoGCRooter
public: public:
AutoEnumStateRooter(JSContext *cx, JSObject *obj AutoEnumStateRooter(JSContext *cx, JSObject *obj
JS_GUARD_OBJECT_NOTIFIER_PARAM) JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue(JSVAL_NULL) : AutoGCRooter(cx, ENUMERATOR), obj(obj), stateValue()
{ {
JS_GUARD_OBJECT_NOTIFIER_INIT; JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_ASSERT(obj); JS_ASSERT(obj);
} }
~AutoEnumStateRooter() { ~AutoEnumStateRooter() {
if (!JSVAL_IS_NULL(stateValue)) { if (!stateValue.isNull()) {
#ifdef DEBUG #ifdef DEBUG
JSBool ok = JSBool ok =
#endif #endif
@ -2403,8 +2425,8 @@ class AutoEnumStateRooter : private AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc); friend void AutoGCRooter::trace(JSTracer *trc);
jsval state() const { return stateValue; } const Value &state() const { return stateValue; }
jsval * addr() { return &stateValue; } Value *addr() { return &stateValue; }
protected: protected:
void trace(JSTracer *trc) { void trace(JSTracer *trc) {
@ -2415,7 +2437,7 @@ class AutoEnumStateRooter : private AutoGCRooter
JSObject * const obj; JSObject * const obj;
private: private:
jsval stateValue; Value stateValue;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER JS_DECL_USE_GUARD_OBJECT_NOTIFIER
}; };
@ -2624,7 +2646,7 @@ js_WaitForGC(JSRuntime *rt);
#endif #endif
/* /*
* JSClass.resolve and watchpoint recursion damping machinery. * Class.resolve and watchpoint recursion damping machinery.
*/ */
extern JSBool extern JSBool
js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag, js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
@ -2636,26 +2658,21 @@ js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
/* /*
* Local root set management. * Local root set management.
*
* NB: the jsval parameters below may be properly tagged jsvals, or GC-thing
* pointers cast to (jsval). This relies on JSObject's tag being zero, but
* on the up side it lets us push int-jsval-encoded scopeMark values on the
* local root stack.
*/ */
extern JSBool extern JSBool
js_EnterLocalRootScope(JSContext *cx); js_EnterLocalRootScope(JSContext *cx);
#define js_LeaveLocalRootScope(cx) \ #define js_LeaveLocalRootScope(cx) \
js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL) js_LeaveLocalRootScopeWithResult(cx, sNullValue)
extern void extern void
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval); js_LeaveLocalRootScopeWithResult(JSContext *cx, const js::Value &rval);
extern void extern void
js_ForgetLocalRoot(JSContext *cx, jsval v); js_ForgetLocalRoot(JSContext *cx, void *thing);
extern int extern int
js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v); js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, void *thing);
/* /*
* Report an exception, which is currently realized as a printf-style format * Report an exception, which is currently realized as a printf-style format
@ -2727,11 +2744,11 @@ js_ReportIsNotDefined(JSContext *cx, const char *name);
* Report an attempt to access the property of a null or undefined value (v). * Report an attempt to access the property of a null or undefined value (v).
*/ */
extern JSBool extern JSBool
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v, js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
JSString *fallback); JSString *fallback);
extern void extern void
js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg); js_ReportMissingArg(JSContext *cx, const js::Value &v, uintN arg);
/* /*
* Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
@ -2740,7 +2757,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
*/ */
extern JSBool extern JSBool
js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber, js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
intN spindex, jsval v, JSString *fallback, intN spindex, const js::Value &v, JSString *fallback,
const char *arg1, const char *arg2); const char *arg1, const char *arg2);
#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \ #define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
@ -2825,7 +2842,7 @@ LeaveTrace(JSContext *cx)
static JS_INLINE void static JS_INLINE void
LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj) LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
{ {
if (!obj->fslots[JSSLOT_PARENT]) if (obj->fslots[JSSLOT_PARENT].isNull())
LeaveTrace(cx); LeaveTrace(cx);
} }
@ -2916,10 +2933,10 @@ class AutoValueVector : private AutoGCRooter
size_t length() const { return vector.length(); } size_t length() const { return vector.length(); }
bool push(jsval v) { return vector.append(v); } bool push(const js::Value &v) { return vector.append(v); }
bool push(JSString *str) { return push(STRING_TO_JSVAL(str)); } bool push(JSString *str) { return push(str); }
bool push(JSObject *obj) { return push(OBJECT_TO_JSVAL(obj)); } bool push(JSObject *obj) { return push(obj); }
bool push(jsdouble *dp) { return push(DOUBLE_TO_JSVAL(dp)); } bool push(jsdouble d) { return push(d); }
void pop() { vector.popBack(); } void pop() { vector.popBack(); }
@ -2933,16 +2950,16 @@ class AutoValueVector : private AutoGCRooter
return vector.reserve(newLength); return vector.reserve(newLength);
} }
jsval &operator[](size_t i) { return vector[i]; } const js::Value &operator[](size_t i) { return vector[i]; }
jsval operator[](size_t i) const { return vector[i]; } const js::Value &operator[](size_t i) const { return vector[i]; }
const jsval *buffer() const { return vector.begin(); } const js::Value *buffer() const { return vector.begin(); }
jsval *buffer() { return vector.begin(); } const js::Value *buffer() { return vector.begin(); }
friend void AutoGCRooter::trace(JSTracer *trc); friend void AutoGCRooter::trace(JSTracer *trc);
private: private:
Vector<jsval, 8> vector; Vector<js::Value, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER JS_DECL_USE_GUARD_OBJECT_NOTIFIER
}; };

View File

@ -55,7 +55,7 @@ CallStack::getCurrentFrame() const
return isSuspended() ? getSuspendedFrame() : cx->fp; return isSuspended() ? getSuspendedFrame() : cx->fp;
} }
JS_REQUIRES_STACK inline jsval * JS_REQUIRES_STACK inline Value *
StackSpace::firstUnused() const StackSpace::firstUnused() const
{ {
CallStack *ccs = currentCallStack; CallStack *ccs = currentCallStack;
@ -82,7 +82,7 @@ StackSpace::isCurrent(JSContext *cx) const
#endif #endif
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
StackSpace::ensureSpace(JSContext *maybecx, jsval *from, ptrdiff_t nvals) const StackSpace::ensureSpace(JSContext *maybecx, Value *from, ptrdiff_t nvals) const
{ {
JS_ASSERT(from == firstUnused()); JS_ASSERT(from == firstUnused());
#ifdef XP_WIN #ifdef XP_WIN
@ -120,14 +120,14 @@ StackSpace::ensureEnoughSpaceToEnterTrace()
} }
JS_ALWAYS_INLINE void JS_ALWAYS_INLINE void
StackSpace::popInvokeArgs(JSContext *cx, jsval *vp) StackSpace::popInvokeArgs(JSContext *cx, Value *vp)
{ {
JS_ASSERT(!currentCallStack->inContext()); JS_ASSERT(!currentCallStack->inContext());
currentCallStack = currentCallStack->getPreviousInThread(); currentCallStack = currentCallStack->getPreviousInThread();
} }
JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame * JS_REQUIRES_STACK JS_ALWAYS_INLINE JSStackFrame *
StackSpace::getInlineFrame(JSContext *cx, jsval *sp, StackSpace::getInlineFrame(JSContext *cx, Value *sp,
uintN nmissing, uintN nslots) const uintN nmissing, uintN nslots) const
{ {
JS_ASSERT(isCurrent(cx) && cx->hasActiveCallStack()); JS_ASSERT(isCurrent(cx) && cx->hasActiveCallStack());
@ -182,7 +182,7 @@ InvokeArgsGuard::InvokeArgsGuard()
{} {}
JS_ALWAYS_INLINE JS_ALWAYS_INLINE
InvokeArgsGuard::InvokeArgsGuard(jsval *vp, uintN argc) InvokeArgsGuard::InvokeArgsGuard(Value *vp, uintN argc)
: cx(NULL), cs(NULL), vp(vp), argc(argc) : cx(NULL), cs(NULL), vp(vp), argc(argc)
{} {}
@ -198,7 +198,7 @@ InvokeArgsGuard::~InvokeArgsGuard()
void void
AutoIdArray::trace(JSTracer *trc) { AutoIdArray::trace(JSTracer *trc) {
JS_ASSERT(tag == IDARRAY); JS_ASSERT(tag == IDARRAY);
js::TraceValues(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray"); TraceIds(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
} }
class AutoNamespaces : protected AutoGCRooter { class AutoNamespaces : protected AutoGCRooter {
@ -218,7 +218,7 @@ AutoGCRooter::trace(JSTracer *trc)
switch (tag) { switch (tag) {
case JSVAL: case JSVAL:
JS_SET_TRACING_NAME(trc, "js::AutoValueRooter.val"); JS_SET_TRACING_NAME(trc, "js::AutoValueRooter.val");
js_CallValueTracerIfGCThing(trc, static_cast<AutoValueRooter *>(this)->val); CallGCMarkerIfGCThing(trc, static_cast<AutoValueRooter *>(this)->val);
return; return;
case SPROP: case SPROP:
@ -244,7 +244,7 @@ AutoGCRooter::trace(JSTracer *trc)
case IDARRAY: { case IDARRAY: {
JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray; JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
TraceValues(trc, ida->length, ida->vector, "js::AutoIdArray.idArray"); TraceIds(trc, ida->length, ida->vector, "js::AutoIdArray.idArray");
return; return;
} }
@ -254,9 +254,12 @@ AutoGCRooter::trace(JSTracer *trc)
for (size_t i = 0, len = descriptors.length(); i < len; i++) { for (size_t i = 0, len = descriptors.length(); i < len; i++) {
PropertyDescriptor &desc = descriptors[i]; PropertyDescriptor &desc = descriptors[i];
JS_CALL_VALUE_TRACER(trc, desc.value, "PropertyDescriptor::value"); JS_SET_TRACING_NAME(trc, "PropertyDescriptor::value");
JS_CALL_VALUE_TRACER(trc, desc.get, "PropertyDescriptor::get"); CallGCMarkerIfGCThing(trc, desc.value);
JS_CALL_VALUE_TRACER(trc, desc.set, "PropertyDescriptor::set"); JS_SET_TRACING_NAME(trc, "PropertyDescriptor::get");
CallGCMarkerIfGCThing(trc, desc.get);
JS_SET_TRACING_NAME(trc, "PropertyDescriptor::set");
CallGCMarkerIfGCThing(trc, desc.set);
js_TraceId(trc, desc.id); js_TraceId(trc, desc.id);
} }
return; return;
@ -276,18 +279,18 @@ AutoGCRooter::trace(JSTracer *trc)
case OBJECT: case OBJECT:
if (JSObject *obj = static_cast<AutoObjectRooter *>(this)->obj) { if (JSObject *obj = static_cast<AutoObjectRooter *>(this)->obj) {
JS_SET_TRACING_NAME(trc, "js::AutoObjectRooter.obj"); JS_SET_TRACING_NAME(trc, "js::AutoObjectRooter.obj");
js_CallGCMarker(trc, obj, JSTRACE_OBJECT); CallGCMarker(trc, obj, JSTRACE_OBJECT);
} }
return; return;
case ID: case ID:
JS_SET_TRACING_NAME(trc, "js::AutoIdRooter.val"); JS_SET_TRACING_NAME(trc, "js::AutoIdRooter.val");
js_CallValueTracerIfGCThing(trc, static_cast<AutoIdRooter *>(this)->idval); CallGCMarkerIfGCThing(trc, static_cast<AutoIdRooter *>(this)->idval);
return; return;
case VECTOR: { case VECTOR: {
js::Vector<jsval, 8> &vector = static_cast<js::AutoValueVector *>(this)->vector; Vector<Value, 8> &vector = static_cast<AutoValueVector *>(this)->vector;
js::TraceValues(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); TraceValues(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
return; return;
} }
} }
@ -296,6 +299,6 @@ AutoGCRooter::trace(JSTracer *trc)
TraceValues(trc, tag, static_cast<AutoArrayRooter *>(this)->array, "js::AutoArrayRooter.array"); TraceValues(trc, tag, static_cast<AutoArrayRooter *>(this)->array, "js::AutoArrayRooter.array");
} }
} } /* namespace js */
#endif /* jscntxtinlines_h___ */ #endif /* jscntxtinlines_h___ */

View File

@ -38,6 +38,9 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS date methods. * JS date methods.
*/ */
@ -71,6 +74,8 @@
#include "jsobj.h" #include "jsobj.h"
#include "jsstr.h" #include "jsstr.h"
#include "jsobjinlines.h"
using namespace js; using namespace js;
/* /*
@ -499,12 +504,12 @@ const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
const uint32 DATE_RESERVED_SLOTS = 2; const uint32 DATE_RESERVED_SLOTS = 2;
JSClass js_DateClass = { Class js_DateClass = {
js_Date_str, js_Date_str,
JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) | JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Date), JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, PropertyStub, PropertyStub, PropertyStub, PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL, EnumerateStub, ResolveStub, ConvertStub, NULL,
JSCLASS_NO_OPTIONAL_MEMBERS JSCLASS_NO_OPTIONAL_MEMBERS
}; };
@ -583,7 +588,7 @@ date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
#define MAXARGS 7 #define MAXARGS 7
static JSBool static JSBool
date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval) date_msecFromArgs(JSContext *cx, uintN argc, Value *argv, jsdouble *rval)
{ {
uintN loop; uintN loop;
jsdouble array[MAXARGS]; jsdouble array[MAXARGS];
@ -592,7 +597,7 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
for (loop = 0; loop < MAXARGS; loop++) { for (loop = 0; loop < MAXARGS; loop++) {
if (loop < argc) { if (loop < argc) {
jsdouble d; jsdouble d;
if (!ValueToNumber(cx, argv[loop], &d)) if (!ValueToNumber(cx, &argv[loop], &d))
return JS_FALSE; return JS_FALSE;
/* return NaN if any arg is not finite */ /* return NaN if any arg is not finite */
if (!JSDOUBLE_IS_FINITE(d)) { if (!JSDOUBLE_IS_FINITE(d)) {
@ -623,7 +628,7 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
* See ECMA 15.9.4.[3-10]; * See ECMA 15.9.4.[3-10];
*/ */
static JSBool static JSBool
date_UTC(JSContext *cx, uintN argc, jsval *vp) date_UTC(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble msec_time; jsdouble msec_time;
@ -632,7 +637,8 @@ date_UTC(JSContext *cx, uintN argc, jsval *vp)
msec_time = TIMECLIP(msec_time); msec_time = TIMECLIP(msec_time);
return js_NewNumberInRootedValue(cx, msec_time, vp); vp->setDouble(msec_time);
return JS_TRUE;
} }
/* /*
@ -1159,26 +1165,27 @@ syntax:
} }
static JSBool static JSBool
date_parse(JSContext *cx, uintN argc, jsval *vp) date_parse(JSContext *cx, uintN argc, Value *vp)
{ {
JSString *str; JSString *str;
jsdouble result; jsdouble result;
if (argc == 0) { if (argc == 0) {
*vp = cx->runtime->NaNValue; vp->setDouble(js_NaN);
return true; return true;
} }
str = js_ValueToString(cx, vp[2]); str = js_ValueToString(cx, vp[2]);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
vp[2] = STRING_TO_JSVAL(str); vp[2].setString(str);
if (!date_parseString(str, &result)) { if (!date_parseString(str, &result)) {
*vp = cx->runtime->NaNValue; vp->setDouble(js_NaN);
return true; return true;
} }
result = TIMECLIP(result); result = TIMECLIP(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return true;
} }
static inline jsdouble static inline jsdouble
@ -1188,9 +1195,10 @@ NowAsMillis()
} }
static JSBool static JSBool
date_now(JSContext *cx, uintN argc, jsval *vp) date_now(JSContext *cx, uintN argc, Value *vp)
{ {
return js_NewDoubleInRootedValue(cx, NowAsMillis(), vp); vp->setDouble(NowAsMillis());
return JS_TRUE;
} }
#ifdef JS_TRACER #ifdef JS_TRACER
@ -1206,38 +1214,37 @@ date_now_tn(JSContext*)
* Date type. * Date type.
*/ */
static JSBool static JSBool
GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp) GetUTCTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *dp)
{ {
if (!JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL)) if (!InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
return JS_FALSE; return JS_FALSE;
*dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]); *dp = obj->fslots[JSSLOT_UTC_TIME].asDouble();
return JS_TRUE; return JS_TRUE;
} }
static void static void
SetDateToNaN(JSContext *cx, JSObject *obj, jsval *vp = NULL) SetDateToNaN(JSContext *cx, JSObject *obj, Value *vp = NULL)
{ {
JS_ASSERT(obj->getClass() == &js_DateClass); JS_ASSERT(obj->getClass() == &js_DateClass);
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue; obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
obj->fslots[JSSLOT_UTC_TIME] = cx->runtime->NaNValue; obj->fslots[JSSLOT_UTC_TIME].setDouble(js_NaN);
if (vp) if (vp)
*vp = cx->runtime->NaNValue; vp->setDouble(js_NaN);
} }
/* /*
* Set UTC time to a given time and invalidate cached local time. * Set UTC time to a given time and invalidate cached local time.
*/ */
static JSBool static JSBool
SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, jsval *vp = NULL) SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, Value *vp = NULL)
{ {
JS_ASSERT(obj->getClass() == &js_DateClass); JS_ASSERT(obj->getClass() == &js_DateClass);
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue; obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
if (!js_NewDoubleInRootedValue(cx, t, &obj->fslots[JSSLOT_UTC_TIME])) obj->fslots[JSSLOT_UTC_TIME].setDouble(t);
return false;
if (vp) if (vp)
*vp = obj->fslots[JSSLOT_UTC_TIME]; vp->setDouble(t);
return true; return true;
} }
@ -1246,22 +1253,21 @@ SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, jsval *vp = NULL)
* (e.g., NaN), the local time slot is set to the UTC time without conversion. * (e.g., NaN), the local time slot is set to the UTC time without conversion.
*/ */
static JSBool static JSBool
GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp) GetAndCacheLocalTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *dp)
{ {
if (!obj || !JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL)) if (!obj || !InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
return false; return false;
jsval *slotp = &obj->fslots[JSSLOT_LOCAL_TIME]; Value &slot = obj->fslots[JSSLOT_LOCAL_TIME];
jsdouble result = *JSVAL_TO_DOUBLE(*slotp); jsdouble result = slot.asDouble();
if (JSDOUBLE_IS_NaN(result)) { if (JSDOUBLE_IS_NaN(result)) {
result = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]); result = obj->fslots[JSSLOT_UTC_TIME].asDouble();
/* if result is NaN, it couldn't be finite. */ /* if result is NaN, it couldn't be finite. */
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = LocalTime(result); result = LocalTime(result);
if (!js_NewDoubleInRootedValue(cx, result, slotp)) slot.setDouble(result);
return false;
} }
*dp = result; *dp = result;
@ -1272,20 +1278,22 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
* See ECMA 15.9.5.4 thru 15.9.5.23 * See ECMA 15.9.5.4 thru 15.9.5.23
*/ */
static JSBool static JSBool
date_getTime(JSContext *cx, uintN argc, jsval *vp) date_getTime(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) && if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
js_NewNumberInRootedValue(cx, result, vp); return JS_FALSE;
vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
GetYear(JSContext *cx, JSBool fullyear, jsval *vp) GetYear(JSContext *cx, JSBool fullyear, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) { if (JSDOUBLE_IS_FINITE(result)) {
@ -1296,214 +1304,228 @@ GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
result -= 1900; result -= 1900;
} }
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getYear(JSContext *cx, uintN argc, jsval *vp) date_getYear(JSContext *cx, uintN argc, Value *vp)
{ {
return GetYear(cx, JS_FALSE, vp); return GetYear(cx, JS_FALSE, vp);
} }
static JSBool static JSBool
date_getFullYear(JSContext *cx, uintN argc, jsval *vp) date_getFullYear(JSContext *cx, uintN argc, Value *vp)
{ {
return GetYear(cx, JS_TRUE, vp); return GetYear(cx, JS_TRUE, vp);
} }
static JSBool static JSBool
date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp) date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = YearFromTime(result); result = YearFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getMonth(JSContext *cx, uintN argc, jsval *vp) date_getMonth(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result); result = MonthFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp) date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result); result = MonthFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getDate(JSContext *cx, uintN argc, jsval *vp) date_getDate(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result); result = DateFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getUTCDate(JSContext *cx, uintN argc, jsval *vp) date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result); result = DateFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getDay(JSContext *cx, uintN argc, jsval *vp) date_getDay(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result); result = WeekDay(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getUTCDay(JSContext *cx, uintN argc, jsval *vp) date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result); result = WeekDay(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getHours(JSContext *cx, uintN argc, jsval *vp) date_getHours(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result); result = HourFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getUTCHours(JSContext *cx, uintN argc, jsval *vp) date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result); result = HourFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getMinutes(JSContext *cx, uintN argc, jsval *vp) date_getMinutes(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result); result = MinFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp) date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result); result = MinFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
/* Date.getSeconds is mapped to getUTCSeconds */ /* Date.getSeconds is mapped to getUTCSeconds */
static JSBool static JSBool
date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp) date_getUTCSeconds(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = SecFromTime(result); result = SecFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
/* Date.getMilliseconds is mapped to getUTCMilliseconds */ /* Date.getMilliseconds is mapped to getUTCMilliseconds */
static JSBool static JSBool
date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp) date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE; return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) if (JSDOUBLE_IS_FINITE(result))
result = msFromTime(result); result = msFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp) date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
{ {
JSObject *obj; JSObject *obj;
jsdouble utctime, localtime, result; jsdouble utctime, localtime, result;
obj = JS_THIS_OBJECT(cx, vp); obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime)) if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE; return JS_FALSE;
if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime)) if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
@ -1515,14 +1537,15 @@ date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
* daylight savings time. * daylight savings time.
*/ */
result = (utctime - localtime) / msPerMinute; result = (utctime - localtime) / msPerMinute;
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return JS_TRUE;
} }
static JSBool static JSBool
date_setTime(JSContext *cx, uintN argc, jsval *vp) date_setTime(JSContext *cx, uintN argc, Value *vp)
{ {
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = ComputeThisObjectFromVp(cx, vp);
if (!JS_InstanceOf(cx, obj, &js_DateClass, vp + 2)) if (!InstanceOf(cx, obj, &js_DateClass, vp + 2))
return false; return false;
if (argc == 0) { if (argc == 0) {
@ -1531,17 +1554,17 @@ date_setTime(JSContext *cx, uintN argc, jsval *vp)
} }
jsdouble result; jsdouble result;
if (!ValueToNumber(cx, vp[2], &result)) if (!ValueToNumber(cx, &vp[2], &result))
return false; return false;
return SetUTCTime(cx, obj, TIMECLIP(result), vp); return SetUTCTime(cx, obj, TIMECLIP(result), vp);
} }
static JSBool static JSBool
date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp) date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{ {
JSObject *obj; JSObject *obj;
jsval *argv; Value *argv;
uintN i; uintN i;
jsdouble args[4], *argp, *stop; jsdouble args[4], *argp, *stop;
jsdouble hour, min, sec, msec; jsdouble hour, min, sec, msec;
@ -1550,13 +1573,15 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
jsdouble msec_time; jsdouble msec_time;
jsdouble result; jsdouble result;
obj = JS_THIS_OBJECT(cx, vp); obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &result)) if (!GetUTCTime(cx, obj, vp, &result))
return false; return false;
/* just return NaN if the date is already NaN */ /* just return NaN if the date is already NaN */
if (!JSDOUBLE_IS_FINITE(result)) if (!JSDOUBLE_IS_FINITE(result)) {
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return true;
}
/* /*
* Satisfy the ECMA rule that if a function is called with * Satisfy the ECMA rule that if a function is called with
@ -1577,7 +1602,7 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
argv = vp + 2; argv = vp + 2;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (!ValueToNumber(cx, argv[i], &args[i])) if (!ValueToNumber(cx, &argv[i], &args[i]))
return false; return false;
if (!JSDOUBLE_IS_FINITE(args[i])) { if (!JSDOUBLE_IS_FINITE(args[i])) {
SetDateToNaN(cx, obj, vp); SetDateToNaN(cx, obj, vp);
@ -1627,65 +1652,65 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
} }
static JSBool static JSBool
date_setMilliseconds(JSContext *cx, uintN argc, jsval *vp) date_setMilliseconds(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 1, JS_TRUE, argc, vp); return date_makeTime(cx, 1, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp) date_setUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 1, JS_FALSE, argc, vp); return date_makeTime(cx, 1, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setSeconds(JSContext *cx, uintN argc, jsval *vp) date_setSeconds(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 2, JS_TRUE, argc, vp); return date_makeTime(cx, 2, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCSeconds(JSContext *cx, uintN argc, jsval *vp) date_setUTCSeconds(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 2, JS_FALSE, argc, vp); return date_makeTime(cx, 2, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setMinutes(JSContext *cx, uintN argc, jsval *vp) date_setMinutes(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 3, JS_TRUE, argc, vp); return date_makeTime(cx, 3, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCMinutes(JSContext *cx, uintN argc, jsval *vp) date_setUTCMinutes(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 3, JS_FALSE, argc, vp); return date_makeTime(cx, 3, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setHours(JSContext *cx, uintN argc, jsval *vp) date_setHours(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 4, JS_TRUE, argc, vp); return date_makeTime(cx, 4, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCHours(JSContext *cx, uintN argc, jsval *vp) date_setUTCHours(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeTime(cx, 4, JS_FALSE, argc, vp); return date_makeTime(cx, 4, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp) date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{ {
JSObject *obj; JSObject *obj;
jsval *argv; Value *argv;
uintN i; uintN i;
jsdouble lorutime; /* local or UTC version of *date */ jsdouble lorutime; /* local or UTC version of *date */
jsdouble args[3], *argp, *stop; jsdouble args[3], *argp, *stop;
jsdouble year, month, day; jsdouble year, month, day;
jsdouble result; jsdouble result;
obj = JS_THIS_OBJECT(cx, vp); obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &result)) if (!GetUTCTime(cx, obj, vp, &result))
return false; return false;
@ -1700,7 +1725,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
argv = vp + 2; argv = vp + 2;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (!ValueToNumber(cx, argv[i], &args[i])) if (!ValueToNumber(cx, &argv[i], &args[i]))
return JS_FALSE; return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) { if (!JSDOUBLE_IS_FINITE(args[i])) {
SetDateToNaN(cx, obj, vp); SetDateToNaN(cx, obj, vp);
@ -1712,8 +1737,10 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
/* return NaN if date is NaN and we're not setting the year, /* return NaN if date is NaN and we're not setting the year,
* If we are, use 0 as the time. */ * If we are, use 0 as the time. */
if (!(JSDOUBLE_IS_FINITE(result))) { if (!(JSDOUBLE_IS_FINITE(result))) {
if (maxargs < 3) if (maxargs < 3) {
return js_NewNumberInRootedValue(cx, result, vp); vp->setDouble(result);
return true;
}
lorutime = +0.; lorutime = +0.;
} else { } else {
lorutime = local ? LocalTime(result) : result; lorutime = local ? LocalTime(result) : result;
@ -1746,45 +1773,45 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
} }
static JSBool static JSBool
date_setDate(JSContext *cx, uintN argc, jsval *vp) date_setDate(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 1, JS_TRUE, argc, vp); return date_makeDate(cx, 1, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCDate(JSContext *cx, uintN argc, jsval *vp) date_setUTCDate(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 1, JS_FALSE, argc, vp); return date_makeDate(cx, 1, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setMonth(JSContext *cx, uintN argc, jsval *vp) date_setMonth(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 2, JS_TRUE, argc, vp); return date_makeDate(cx, 2, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCMonth(JSContext *cx, uintN argc, jsval *vp) date_setUTCMonth(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 2, JS_FALSE, argc, vp); return date_makeDate(cx, 2, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setFullYear(JSContext *cx, uintN argc, jsval *vp) date_setFullYear(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 3, JS_TRUE, argc, vp); return date_makeDate(cx, 3, JS_TRUE, argc, vp);
} }
static JSBool static JSBool
date_setUTCFullYear(JSContext *cx, uintN argc, jsval *vp) date_setUTCFullYear(JSContext *cx, uintN argc, Value *vp)
{ {
return date_makeDate(cx, 3, JS_FALSE, argc, vp); return date_makeDate(cx, 3, JS_FALSE, argc, vp);
} }
static JSBool static JSBool
date_setYear(JSContext *cx, uintN argc, jsval *vp) date_setYear(JSContext *cx, uintN argc, Value *vp)
{ {
JSObject *obj = JS_THIS_OBJECT(cx, vp); JSObject *obj = ComputeThisObjectFromVp(cx, vp);
jsdouble result; jsdouble result;
if (!GetUTCTime(cx, obj, vp, &result)) if (!GetUTCTime(cx, obj, vp, &result))
@ -1797,7 +1824,7 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
} }
jsdouble year; jsdouble year;
if (!ValueToNumber(cx, vp[2], &year)) if (!ValueToNumber(cx, &vp[2], &year))
return false; return false;
if (!JSDOUBLE_IS_FINITE(year)) { if (!JSDOUBLE_IS_FINITE(year)) {
SetDateToNaN(cx, obj, vp); SetDateToNaN(cx, obj, vp);
@ -1856,14 +1883,14 @@ print_iso_string(char* buf, size_t size, jsdouble utctime)
} }
static JSBool static JSBool
date_utc_format(JSContext *cx, jsval *vp, date_utc_format(JSContext *cx, Value *vp,
void (*printFunc)(char*, size_t, jsdouble)) void (*printFunc)(char*, size_t, jsdouble))
{ {
char buf[100]; char buf[100];
JSString *str; JSString *str;
jsdouble utctime; jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE; return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(utctime)) { if (!JSDOUBLE_IS_FINITE(utctime)) {
@ -1874,18 +1901,18 @@ date_utc_format(JSContext *cx, jsval *vp,
str = JS_NewStringCopyZ(cx, buf); str = JS_NewStringCopyZ(cx, buf);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
*vp = STRING_TO_JSVAL(str); vp->setString(str);
return JS_TRUE; return JS_TRUE;
} }
static JSBool static JSBool
date_toGMTString(JSContext *cx, uintN argc, jsval *vp) date_toGMTString(JSContext *cx, uintN argc, Value *vp)
{ {
return date_utc_format(cx, vp, print_gmt_string); return date_utc_format(cx, vp, print_gmt_string);
} }
static JSBool static JSBool
date_toISOString(JSContext *cx, uintN argc, jsval *vp) date_toISOString(JSContext *cx, uintN argc, Value *vp)
{ {
return date_utc_format(cx, vp, print_iso_string); return date_utc_format(cx, vp, print_iso_string);
} }
@ -1918,7 +1945,7 @@ typedef enum formatspec {
/* helper function */ /* helper function */
static JSBool static JSBool
date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval) date_format(JSContext *cx, jsdouble date, formatspec format, Value *rval)
{ {
char buf[100]; char buf[100];
JSString *str; JSString *str;
@ -2026,12 +2053,12 @@ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
str = JS_NewStringCopyZ(cx, buf); str = JS_NewStringCopyZ(cx, buf);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
*rval = STRING_TO_JSVAL(str); rval->setString(str);
return JS_TRUE; return JS_TRUE;
} }
static JSBool static JSBool
date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp) date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
{ {
JSObject *obj; JSObject *obj;
char buf[100]; char buf[100];
@ -2039,7 +2066,7 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
PRMJTime split; PRMJTime split;
jsdouble utctime; jsdouble utctime;
obj = JS_THIS_OBJECT(cx, vp); obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime)) if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE; return JS_FALSE;
@ -2073,17 +2100,17 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
} }
if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode) if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
return cx->localeCallbacks->localeToUnicode(cx, buf, vp); return cx->localeCallbacks->localeToUnicode(cx, buf, Jsvalify(vp));
str = JS_NewStringCopyZ(cx, buf); str = JS_NewStringCopyZ(cx, buf);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
*vp = STRING_TO_JSVAL(str); vp->setString(str);
return JS_TRUE; return JS_TRUE;
} }
static JSBool static JSBool
date_toLocaleString(JSContext *cx, uintN argc, jsval *vp) date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
{ {
/* Use '%#c' for windows, because '%c' is /* Use '%#c' for windows, because '%c' is
* backward-compatible and non-y2k with msvc; '%#c' requests that a * backward-compatible and non-y2k with msvc; '%#c' requests that a
@ -2099,7 +2126,7 @@ date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
} }
static JSBool static JSBool
date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp) date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
{ {
/* Use '%#x' for windows, because '%x' is /* Use '%#x' for windows, because '%x' is
* backward-compatible and non-y2k with msvc; '%#x' requests that a * backward-compatible and non-y2k with msvc; '%#x' requests that a
@ -2115,13 +2142,13 @@ date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
} }
static JSBool static JSBool
date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp) date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
{ {
return date_toLocaleHelper(cx, "%X", vp); return date_toLocaleHelper(cx, "%X", vp);
} }
static JSBool static JSBool
date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp) date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
{ {
JSString *fmt; JSString *fmt;
const char *fmtbytes; const char *fmtbytes;
@ -2132,7 +2159,7 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
fmt = js_ValueToString(cx, vp[2]); fmt = js_ValueToString(cx, vp[2]);
if (!fmt) if (!fmt)
return JS_FALSE; return JS_FALSE;
vp[2] = STRING_TO_JSVAL(fmt); vp[2].setString(fmt);
fmtbytes = js_GetStringBytes(cx, fmt); fmtbytes = js_GetStringBytes(cx, fmt);
if (!fmtbytes) if (!fmtbytes)
return JS_FALSE; return JS_FALSE;
@ -2141,21 +2168,21 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
} }
static JSBool static JSBool
date_toTimeString(JSContext *cx, uintN argc, jsval *vp) date_toTimeString(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble utctime; jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE; return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_TIME, vp); return date_format(cx, utctime, FORMATSPEC_TIME, vp);
} }
static JSBool static JSBool
date_toDateString(JSContext *cx, uintN argc, jsval *vp) date_toDateString(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble utctime; jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE; return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_DATE, vp); return date_format(cx, utctime, FORMATSPEC_DATE, vp);
} }
@ -2165,13 +2192,13 @@ date_toDateString(JSContext *cx, uintN argc, jsval *vp)
#include "jsdtoa.h" #include "jsdtoa.h"
static JSBool static JSBool
date_toSource(JSContext *cx, uintN argc, jsval *vp) date_toSource(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble utctime; jsdouble utctime;
char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes; char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
JSString *str; JSString *str;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE; return JS_FALSE;
numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf, DTOSTR_STANDARD, 0, utctime); numStr = js_dtostr(JS_THREAD_DATA(cx)->dtoaState, buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
@ -2191,17 +2218,17 @@ date_toSource(JSContext *cx, uintN argc, jsval *vp)
js_free(bytes); js_free(bytes);
return JS_FALSE; return JS_FALSE;
} }
*vp = STRING_TO_JSVAL(str); vp->setString(str);
return JS_TRUE; return JS_TRUE;
} }
#endif #endif
static JSBool static JSBool
date_toString(JSContext *cx, uintN argc, jsval *vp) date_toString(JSContext *cx, uintN argc, Value *vp)
{ {
jsdouble utctime; jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime)) if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE; return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_FULL, vp); return date_format(cx, utctime, FORMATSPEC_FULL, vp);
} }
@ -2210,7 +2237,7 @@ date_toString(JSContext *cx, uintN argc, jsval *vp)
static jsval FASTCALL static jsval FASTCALL
date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str) date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
{ {
JS_ASSERT(JS_InstanceOf(cx, obj, &js_DateClass, NULL)); JS_ASSERT(InstanceOf(cx, obj, &js_DateClass, NULL));
jsdouble t = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]); jsdouble t = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]); JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
@ -2227,7 +2254,7 @@ date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
#endif #endif
static JSBool static JSBool
date_valueOf(JSContext *cx, uintN argc, jsval *vp) date_valueOf(JSContext *cx, uintN argc, Value *vp)
{ {
JSString *str, *number_str; JSString *str, *number_str;
@ -2319,7 +2346,7 @@ static JSFunctionSpec date_methods[] = {
}; };
JSBool JSBool
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) js_Date(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
{ {
/* Date called as function. */ /* Date called as function. */
if (!JS_IsConstructing(cx)) if (!JS_IsConstructing(cx))
@ -2330,9 +2357,9 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (argc == 0) { if (argc == 0) {
d = NowAsMillis(); d = NowAsMillis();
} else if (argc == 1) { } else if (argc == 1) {
if (!JSVAL_IS_STRING(argv[0])) { if (!argv[0].isString()) {
/* the argument is a millisecond number */ /* the argument is a millisecond number */
if (!ValueToNumber(cx, argv[0], &d)) if (!ValueToNumber(cx, &argv[0], &d))
return JS_FALSE; return JS_FALSE;
d = TIMECLIP(d); d = TIMECLIP(d);
} else { } else {
@ -2340,7 +2367,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSString *str = js_ValueToString(cx, argv[0]); JSString *str = js_ValueToString(cx, argv[0]);
if (!str) if (!str)
return JS_FALSE; return JS_FALSE;
argv[0] = STRING_TO_JSVAL(str); argv[0].setString(str);
if (!date_parseString(str, &d)) if (!date_parseString(str, &d))
d = js_NaN; d = js_NaN;
@ -2368,8 +2395,9 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
/* set static LocalTZA */ /* set static LocalTZA */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond); LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS, proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date,
NULL, date_methods, NULL, date_static_methods); MAXARGS, NULL, date_methods, NULL,
date_static_methods);
if (!proto) if (!proto)
return NULL; return NULL;

View File

@ -44,9 +44,7 @@
#ifndef jsdate_h___ #ifndef jsdate_h___
#define jsdate_h___ #define jsdate_h___
JS_BEGIN_EXTERN_C extern js::Class js_DateClass;
extern JSClass js_DateClass;
extern JSObject * extern JSObject *
js_InitDateClass(JSContext *cx, JSObject *obj); js_InitDateClass(JSContext *cx, JSObject *obj);
@ -126,8 +124,6 @@ js_IntervalNow();
/* Date constructor native. Exposed only so the JIT can know its address. */ /* Date constructor native. Exposed only so the JIT can know its address. */
JSBool JSBool
js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); js_Date(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
JS_END_EXTERN_C
#endif /* jsdate_h___ */ #endif /* jsdate_h___ */

View File

@ -38,6 +38,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS debugging API. * JS debugging API.
*/ */
@ -77,7 +79,7 @@ typedef struct JSTrap {
jsbytecode *pc; jsbytecode *pc;
JSOp op; JSOp op;
JSTrapHandler handler; JSTrapHandler handler;
void *closure; jsval closure;
} JSTrap; } JSTrap;
#define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock) #define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
@ -142,7 +144,7 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script)
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler handler, void *closure) JSTrapHandler handler, jsval closure)
{ {
JSTrap *junk, *trap, *twin; JSTrap *junk, *trap, *twin;
JSRuntime *rt; JSRuntime *rt;
@ -168,7 +170,7 @@ JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
trap = (JSTrap *) cx->malloc(sizeof *trap); trap = (JSTrap *) cx->malloc(sizeof *trap);
if (!trap) if (!trap)
return JS_FALSE; return JS_FALSE;
trap->closure = NULL; trap->closure = JSVAL_NULL;
DBG_LOCK(rt); DBG_LOCK(rt);
twin = (rt->debuggerMutations != sample) twin = (rt->debuggerMutations != sample)
? FindTrap(rt, script, pc) ? FindTrap(rt, script, pc)
@ -220,7 +222,7 @@ DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, void **closurep) JSTrapHandler *handlerp, jsval *closurep)
{ {
JSTrap *trap; JSTrap *trap;
@ -229,7 +231,7 @@ JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
if (handlerp) if (handlerp)
*handlerp = trap ? trap->handler : NULL; *handlerp = trap ? trap->handler : NULL;
if (closurep) if (closurep)
*closurep = trap ? trap->closure : NULL; *closurep = trap ? trap->closure : JSVAL_NULL;
if (trap) if (trap)
DestroyTrapAndUnlock(cx, trap); DestroyTrapAndUnlock(cx, trap);
else else
@ -295,10 +297,8 @@ js_MarkTraps(JSTracer *trc)
for (JSTrap *trap = (JSTrap *) rt->trapList.next; for (JSTrap *trap = (JSTrap *) rt->trapList.next;
&trap->links != &rt->trapList; &trap->links != &rt->trapList;
trap = (JSTrap *) trap->links.next) { trap = (JSTrap *) trap->links.next) {
if (trap->closure) { JS_SET_TRACING_NAME(trc, "trap->closure");
JS_SET_TRACING_NAME(trc, "trap->closure"); CallGCMarkerIfGCThing(trc, Valueify(trap->closure));
js_CallValueTracerIfGCThing(trc, (jsval) trap->closure);
}
} }
} }
@ -375,15 +375,15 @@ LeaveTraceRT(JSRuntime *rt)
#endif #endif
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure) JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure)
{ {
#ifdef JS_TRACER #ifdef JS_TRACER
{ {
AutoLockGC lock(rt); AutoLockGC lock(rt);
bool wasInhibited = rt->debuggerInhibitsJIT(); bool wasInhibited = rt->debuggerInhibitsJIT();
#endif #endif
rt->globalDebugHooks.interruptHandler = handler; rt->globalDebugHooks.interruptHook = handler;
rt->globalDebugHooks.interruptHandlerData = closure; rt->globalDebugHooks.interruptHookData = closure;
#ifdef JS_TRACER #ifdef JS_TRACER
JITInhibitingHookChange(rt, wasInhibited); JITInhibitingHookChange(rt, wasInhibited);
} }
@ -393,18 +393,18 @@ JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep) JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep)
{ {
#ifdef JS_TRACER #ifdef JS_TRACER
AutoLockGC lock(rt); AutoLockGC lock(rt);
bool wasInhibited = rt->debuggerInhibitsJIT(); bool wasInhibited = rt->debuggerInhibitsJIT();
#endif #endif
if (handlerp) if (handlerp)
*handlerp = rt->globalDebugHooks.interruptHandler; *handlerp = rt->globalDebugHooks.interruptHook;
if (closurep) if (closurep)
*closurep = rt->globalDebugHooks.interruptHandlerData; *closurep = rt->globalDebugHooks.interruptHookData;
rt->globalDebugHooks.interruptHandler = 0; rt->globalDebugHooks.interruptHook = 0;
rt->globalDebugHooks.interruptHandlerData = 0; rt->globalDebugHooks.interruptHookData = 0;
#ifdef JS_TRACER #ifdef JS_TRACER
JITInhibitingHookChange(rt, wasInhibited); JITInhibitingHookChange(rt, wasInhibited);
#endif #endif
@ -417,7 +417,7 @@ typedef struct JSWatchPoint {
JSCList links; JSCList links;
JSObject *object; /* weak link, see js_FinalizeObject */ JSObject *object; /* weak link, see js_FinalizeObject */
JSScopeProperty *sprop; JSScopeProperty *sprop;
JSPropertyOp setter; PropertyOp setter;
JSWatchPointHandler handler; JSWatchPointHandler handler;
JSObject *closure; JSObject *closure;
uintN flags; uintN flags;
@ -438,7 +438,7 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
JSBool ok; JSBool ok;
JSScopeProperty *sprop; JSScopeProperty *sprop;
JSScope *scope; JSScope *scope;
JSPropertyOp setter; PropertyOp setter;
ok = JS_TRUE; ok = JS_TRUE;
wp->flags &= ~flag; wp->flags &= ~flag;
@ -507,11 +507,11 @@ js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
if (wp->object == obj) { if (wp->object == obj) {
wp->sprop->trace(trc); wp->sprop->trace(trc);
if (wp->sprop->hasSetterValue() && wp->setter) { if (wp->sprop->hasSetterValue() && wp->setter) {
JS_CALL_OBJECT_TRACER(trc, js_CastAsObject(wp->setter), JS_CALL_OBJECT_TRACER(trc, CastAsObject(wp->setter),
"wp->setter"); "wp->setter");
} }
JS_SET_TRACING_NAME(trc, "wp->closure"); JS_SET_TRACING_NAME(trc, "wp->closure");
js_CallValueTracerIfGCThing(trc, OBJECT_TO_JSVAL(wp->closure)); CallGCMarkerForGCThing(trc, Value(wp->closure));
} }
} }
} }
@ -578,11 +578,11 @@ js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
* Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
* caller has acquired rt->debuggerLock, so we don't have to. * caller has acquired rt->debuggerLock, so we don't have to.
*/ */
JSPropertyOp PropertyOp
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope, js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
const JSScopeProperty *sprop) const JSScopeProperty *sprop)
{ {
JSPropertyOp setter; PropertyOp setter;
JSWatchPoint *wp; JSWatchPoint *wp;
setter = NULL; setter = NULL;
@ -602,7 +602,7 @@ js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
} }
JSBool JSBool
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp) js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
{ {
JSRuntime *rt = cx->runtime; JSRuntime *rt = cx->runtime;
DBG_LOCK(rt); DBG_LOCK(rt);
@ -616,17 +616,17 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
DBG_UNLOCK(rt); DBG_UNLOCK(rt);
JS_LOCK_OBJ(cx, obj); JS_LOCK_OBJ(cx, obj);
jsval propid = ID_TO_VALUE(sprop->id); jsid propid = sprop->id;
jsval userid = SPROP_USERID(sprop); jsid userid = SPROP_USERID(sprop);
JSScope *scope = obj->scope(); JSScope *scope = obj->scope();
JS_UNLOCK_OBJ(cx, obj); JS_UNLOCK_OBJ(cx, obj);
/* NB: wp is held, so we can safely dereference it still. */ /* NB: wp is held, so we can safely dereference it still. */
if (!wp->handler(cx, obj, propid, if (!wp->handler(cx, obj, propid,
SPROP_HAS_VALID_SLOT(sprop, scope) SPROP_HAS_VALID_SLOT(sprop, scope)
? obj->getSlotMT(cx, sprop->slot) ? Jsvalify(obj->getSlotMT(cx, sprop->slot))
: JSVAL_VOID, : JSVAL_VOID,
vp, wp->closure)) { Jsvalify(vp), wp->closure)) {
DBG_LOCK(rt); DBG_LOCK(rt);
DropWatchPointAndUnlock(cx, wp, JSWP_HELD); DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
return JS_FALSE; return JS_FALSE;
@ -644,7 +644,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
* trusted. * trusted.
*/ */
JSObject *closure = wp->closure; JSObject *closure = wp->closure;
JSClass *clasp = closure->getClass(); Class *clasp = closure->getClass();
JSFunction *fun; JSFunction *fun;
JSScript *script; JSScript *script;
if (clasp == &js_FunctionClass) { if (clasp == &js_FunctionClass) {
@ -682,12 +682,12 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
} }
/* Initialize slots/frame. */ /* Initialize slots/frame. */
jsval *vp = frame.getvp(); Value *vp = frame.getvp();
memset(vp, 0, vplen * sizeof(jsval)); PodZero(vp, vplen);
vp[0] = OBJECT_TO_JSVAL(closure); SetObject(&vp[0], *closure);
JSStackFrame *fp = frame.getFrame(); JSStackFrame *fp = frame.getFrame();
memset(fp->slots(), 0, nslots * sizeof(jsval)); PodZero(fp->slots(), nslots);
memset(fp, 0, sizeof(JSStackFrame)); PodZero(fp);
fp->script = script; fp->script = script;
fp->fun = fun; fp->fun = fun;
fp->argv = vp + 2; fp->argv = vp + 2;
@ -712,9 +712,9 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
JSBool ok = !wp->setter || JSBool ok = !wp->setter ||
(sprop->hasSetterValue() (sprop->hasSetterValue()
? js_InternalCall(cx, obj, ? InternalCall(cx, obj,
js_CastAsObjectJSVal(wp->setter), ToValue(CastAsObject(wp->setter)),
1, vp, vp) 1, vp, vp)
: wp->setter(cx, obj, userid, vp)); : wp->setter(cx, obj, userid, vp));
/* Evil code can cause us to have an arguments object. */ /* Evil code can cause us to have an arguments object. */
@ -730,17 +730,17 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
} }
JSBool JSBool
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, Value *argv,
jsval *rval) Value *rval)
{ {
JSObject *funobj; JSObject *funobj;
JSFunction *wrapper; JSFunction *wrapper;
jsval userid; jsid userid;
funobj = JSVAL_TO_OBJECT(argv[-2]); funobj = &argv[-2].asObject();
wrapper = GET_FUNCTION_PRIVATE(cx, funobj); wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
userid = ATOM_KEY(wrapper->atom); userid = ATOM_TO_JSID(wrapper->atom);
*rval = argv[0]; rval->copy(argv[0]);
return js_watch_set(cx, obj, userid, rval); return js_watch_set(cx, obj, userid, rval);
} }
@ -758,8 +758,8 @@ IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop)
return sprop->setterOp() == js_watch_set; return sprop->setterOp() == js_watch_set;
} }
JSPropertyOp PropertyOp
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, PropertyOp setter)
{ {
JSAtom *atom; JSAtom *atom;
JSFunction *wrapper; JSFunction *wrapper;
@ -770,26 +770,25 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
if (JSID_IS_ATOM(id)) { if (JSID_IS_ATOM(id)) {
atom = JSID_TO_ATOM(id); atom = JSID_TO_ATOM(id);
} else if (JSID_IS_INT(id)) { } else if (JSID_IS_INT(id)) {
if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id)) if (!js_ValueToStringId(cx, IdToValue(id), &id))
return NULL; return NULL;
atom = JSID_TO_ATOM(id); atom = JSID_TO_ATOM(id);
} else { } else {
atom = NULL; atom = NULL;
} }
wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0, wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
js_CastAsObject(setter)->getParent(), CastAsObject(setter)->getParent(), atom);
atom);
if (!wrapper) if (!wrapper)
return NULL; return NULL;
return js_CastAsPropertyOp(FUN_OBJECT(wrapper)); return CastAsPropertyOp(FUN_OBJECT(wrapper));
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
JSWatchPointHandler handler, void *closure) JSWatchPointHandler handler, void *closure)
{ {
JSObject *origobj; JSObject *origobj;
jsval v; Value v;
uintN attrs; uintN attrs;
jsid propid; jsid propid;
JSObject *pobj; JSObject *pobj;
@ -798,18 +797,18 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
JSRuntime *rt; JSRuntime *rt;
JSBool ok; JSBool ok;
JSWatchPoint *wp; JSWatchPoint *wp;
JSPropertyOp watcher; PropertyOp watcher;
origobj = obj; origobj = obj;
obj = js_GetWrappedObject(cx, obj); obj = js_GetWrappedObject(cx, obj);
OBJ_TO_INNER_OBJECT(cx, obj); Innerize(cx, &obj);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
if (JSVAL_IS_INT(idval)) { if (JSID_IS_INT(id)) {
propid = INT_JSVAL_TO_JSID(idval); propid = id;
} else { } else {
if (!js_ValueToStringId(cx, idval, &propid)) if (!js_ValueToStringId(cx, IdToValue(id), &propid))
return JS_FALSE; return JS_FALSE;
propid = js_CheckForStringIndex(propid); propid = js_CheckForStringIndex(propid);
} }
@ -836,7 +835,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
sprop = js_FindWatchPoint(rt, obj->scope(), propid); sprop = js_FindWatchPoint(rt, obj->scope(), propid);
if (!sprop) { if (!sprop) {
/* Make a new property in obj so we can watch for the first set. */ /* Make a new property in obj so we can watch for the first set. */
if (!js_DefineNativeProperty(cx, obj, propid, JSVAL_VOID, NULL, NULL, if (!js_DefineNativeProperty(cx, obj, propid, sUndefinedValue, NULL, NULL,
JSPROP_ENUMERATE, 0, 0, &prop)) { JSPROP_ENUMERATE, 0, 0, &prop)) {
return JS_FALSE; return JS_FALSE;
} }
@ -844,15 +843,15 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
} }
} else if (pobj != obj) { } else if (pobj != obj) {
/* Clone the prototype property so we can watch the right object. */ /* Clone the prototype property so we can watch the right object. */
jsval value; Value value;
JSPropertyOp getter, setter; PropertyOp getter, setter;
uintN attrs, flags; uintN attrs, flags;
intN shortid; intN shortid;
if (pobj->isNative()) { if (pobj->isNative()) {
value = SPROP_HAS_VALID_SLOT(sprop, pobj->scope()) value.copy(SPROP_HAS_VALID_SLOT(sprop, pobj->scope())
? pobj->lockedGetSlot(sprop->slot) ? pobj->lockedGetSlot(sprop->slot)
: JSVAL_VOID; : sUndefinedValue);
getter = sprop->getter(); getter = sprop->getter();
setter = sprop->setter(); setter = sprop->setter();
attrs = sprop->attributes(); attrs = sprop->attributes();
@ -938,7 +937,7 @@ out:
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id, JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
JSWatchPointHandler *handlerp, void **closurep) JSWatchPointHandler *handlerp, void **closurep)
{ {
JSRuntime *rt; JSRuntime *rt;
@ -1029,6 +1028,43 @@ JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
return js_LineNumberToPC(script, lineno); return js_LineNumberToPC(script, lineno);
} }
JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
{
return fun->nargs;
}
JS_PUBLIC_API(JSBool)
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
{
return fun->hasLocalNames();
}
extern JS_PUBLIC_API(jsuword *)
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
{
*markp = JS_ARENA_MARK(&cx->tempPool);
return js_GetLocalNameArray(cx, fun, &cx->tempPool);
}
extern JS_PUBLIC_API(JSAtom *)
JS_LocalNameToAtom(jsuword w)
{
return JS_LOCAL_NAME_TO_ATOM(w);
}
extern JS_PUBLIC_API(JSString *)
JS_AtomKey(JSAtom *atom)
{
return ATOM_TO_STRING(atom);
}
extern JS_PUBLIC_API(void)
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
{
JS_ARENA_RELEASE(&cx->tempPool, mark);
}
JS_PUBLIC_API(JSScript *) JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JSFunction *fun) JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
{ {
@ -1038,7 +1074,7 @@ JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
JS_PUBLIC_API(JSNative) JS_PUBLIC_API(JSNative)
JS_GetFunctionNative(JSContext *cx, JSFunction *fun) JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
{ {
return FUN_NATIVE(fun); return Jsvalify(FUN_NATIVE(fun));
} }
JS_PUBLIC_API(JSFastNative) JS_PUBLIC_API(JSFastNative)
@ -1247,13 +1283,13 @@ JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(jsval) JS_PUBLIC_API(jsval)
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp) JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
{ {
return fp->rval; return Jsvalify(fp->rval);
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval) JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
{ {
fp->rval = rval; fp->rval.copy(Valueify(rval));
} }
/************************************************************************/ /************************************************************************/
@ -1367,8 +1403,8 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
} }
} }
ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL, ok = Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
rval); Valueify(rval));
if (cx->fp != fp) if (cx->fp != fp)
memcpy(cx->display, displayCopy, sizeof cx->display); memcpy(cx->display, displayCopy, sizeof cx->display);
@ -1420,19 +1456,19 @@ JS_PUBLIC_API(JSBool)
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
JSPropertyDesc *pd) JSPropertyDesc *pd)
{ {
pd->id = ID_TO_VALUE(sprop->id); pd->id = Jsvalify(IdToValue(sprop->id));
JSBool wasThrowing = cx->throwing; JSBool wasThrowing = cx->throwing;
AutoValueRooter lastException(cx, cx->exception); AutoValueRooter lastException(cx, cx->exception);
cx->throwing = JS_FALSE; cx->throwing = JS_FALSE;
if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) { if (!js_GetProperty(cx, obj, sprop->id, Valueify(&pd->value))) {
if (!cx->throwing) { if (!cx->throwing) {
pd->flags = JSPD_ERROR; pd->flags = JSPD_ERROR;
pd->value = JSVAL_VOID; pd->value = JSVAL_VOID;
} else { } else {
pd->flags = JSPD_EXCEPTION; pd->flags = JSPD_EXCEPTION;
pd->value = cx->exception; pd->value = Jsvalify(cx->exception);
} }
} else { } else {
pd->flags = 0; pd->flags = 0;
@ -1440,7 +1476,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
cx->throwing = wasThrowing; cx->throwing = wasThrowing;
if (wasThrowing) if (wasThrowing)
cx->exception = lastException.value(); cx->exception.copy(lastException.value());
pd->flags |= (sprop->enumerable() ? JSPD_ENUMERATE : 0) pd->flags |= (sprop->enumerable() ? JSPD_ENUMERATE : 0)
| (!sprop->writable() ? JSPD_READONLY : 0) | (!sprop->writable() ? JSPD_READONLY : 0)
@ -1462,7 +1498,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
JSScopeProperty *aprop; JSScopeProperty *aprop;
for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) { for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) {
if (aprop != sprop && aprop->slot == sprop->slot) { if (aprop != sprop && aprop->slot == sprop->slot) {
pd->alias = ID_TO_VALUE(aprop->id); pd->alias = Jsvalify(IdToValue(aprop->id));
break; break;
} }
} }
@ -1473,13 +1509,12 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda) JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
{ {
JSClass *clasp;
JSScope *scope; JSScope *scope;
uint32 i, n; uint32 i, n;
JSPropertyDesc *pd; JSPropertyDesc *pd;
JSScopeProperty *sprop; JSScopeProperty *sprop;
clasp = obj->getClass(); Class *clasp = obj->getClass();
if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) { if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_CANT_DESCRIBE_PROPS, clasp->name); JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
@ -1502,13 +1537,13 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
return JS_FALSE; return JS_FALSE;
i = 0; i = 0;
for (sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { for (sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
if (!js_AddRoot(cx, &pd[i].id, NULL)) if (!js_AddRoot(cx, Valueify(&pd[i].id), NULL))
goto bad; goto bad;
if (!js_AddRoot(cx, &pd[i].value, NULL)) if (!js_AddRoot(cx, Valueify(&pd[i].value), NULL))
goto bad; goto bad;
if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i])) if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i]))
goto bad; goto bad;
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL)) if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, Valueify(&pd[i].alias), NULL))
goto bad; goto bad;
if (++i == n) if (++i == n)
break; break;
@ -1543,7 +1578,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
/************************************************************************/ /************************************************************************/
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure) JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
{ {
rt->globalDebugHooks.debuggerHandler = handler; rt->globalDebugHooks.debuggerHandler = handler;
rt->globalDebugHooks.debuggerHandlerData = closure; rt->globalDebugHooks.debuggerHandlerData = closure;
@ -1605,7 +1640,7 @@ JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
} }
JS_PUBLIC_API(JSBool) JS_PUBLIC_API(JSBool)
JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure) JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
{ {
rt->globalDebugHooks.throwHook = hook; rt->globalDebugHooks.throwHook = hook;
rt->globalDebugHooks.throwHookData = closure; rt->globalDebugHooks.throwHookData = closure;
@ -1630,7 +1665,7 @@ JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
nbytes = sizeof *obj; nbytes = sizeof *obj;
if (obj->dslots) { if (obj->dslots) {
nbytes += ((uint32)obj->dslots[-1] - JS_INITIAL_NSLOTS + 1) nbytes += (obj->dslotLength() - JS_INITIAL_NSLOTS + 1)
* sizeof obj->dslots[0]; * sizeof obj->dslots[0];
} }
if (obj->isNative()) { if (obj->isNative()) {
@ -1775,9 +1810,7 @@ JS_PUBLIC_API(JSObject *)
JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto, JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, JSBool system) JSObject *parent, JSBool system)
{ {
JSObject *obj; JSObject *obj = js_NewObject(cx, Valueify(clasp), proto, parent);
obj = js_NewObject(cx, clasp, proto, parent);
if (obj && system) if (obj && system)
obj->setSystem(); obj->setSystem();
return obj; return obj;

View File

@ -45,7 +45,6 @@
*/ */
#include "jsapi.h" #include "jsapi.h"
#include "jsopcode.h" #include "jsopcode.h"
#include "jsprvtd.h"
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
@ -59,14 +58,14 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler handler, void *closure); JSTrapHandler handler, jsval closure);
extern JS_PUBLIC_API(JSOp) extern JS_PUBLIC_API(JSOp)
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc); JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(void) extern JS_PUBLIC_API(void)
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, void **closurep); JSTrapHandler *handlerp, jsval *closurep);
extern JS_PUBLIC_API(void) extern JS_PUBLIC_API(void)
JS_ClearScriptTraps(JSContext *cx, JSScript *script); JS_ClearScriptTraps(JSContext *cx, JSScript *script);
@ -78,19 +77,19 @@ extern JS_PUBLIC_API(JSTrapStatus)
JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval); JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure); JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep); JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
/************************************************************************/ /************************************************************************/
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
JSWatchPointHandler handler, void *closure); JSWatchPointHandler handler, void *closure);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id, JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
JSWatchPointHandler *handlerp, void **closurep); JSWatchPointHandler *handlerp, void **closurep);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
@ -113,19 +112,23 @@ js_SweepWatchPoints(JSContext *cx);
extern JSScopeProperty * extern JSScopeProperty *
js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id); js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id);
#ifdef __cplusplus
/* /*
* NB: callers outside of jsdbgapi.c must pass non-null scope. * NB: callers outside of jsdbgapi.c must pass non-null scope.
*/ */
extern JSPropertyOp extern js::PropertyOp
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope, js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
const JSScopeProperty *sprop); const JSScopeProperty *sprop);
extern JSBool extern JSBool
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp); js_watch_set(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
jsval *rval); js::Value *rval);
#endif
extern JSPropertyOp extern JSPropertyOp
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter); js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter);
@ -140,14 +143,39 @@ JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(jsbytecode *) extern JS_PUBLIC_API(jsbytecode *)
JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno); JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
extern JS_PUBLIC_API(uintN)
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);
extern JS_PUBLIC_API(JSBool)
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun);
/*
* N.B. The mark is in the context temp pool and thus the caller must take care
* to call JS_ReleaseFunctionLocalNameArray in a LIFO manner (wrt to any other
* call that may use the temp pool.
*/
extern JS_PUBLIC_API(jsuword *)
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp);
extern JS_PUBLIC_API(JSAtom *)
JS_LocalNameToAtom(jsuword w);
extern JS_PUBLIC_API(JSString *)
JS_AtomKey(JSAtom *atom);
extern JS_PUBLIC_API(void)
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark);
extern JS_PUBLIC_API(JSScript *) extern JS_PUBLIC_API(JSScript *)
JS_GetFunctionScript(JSContext *cx, JSFunction *fun); JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
extern JS_PUBLIC_API(JSNative) extern JS_PUBLIC_API(JSNative)
JS_GetFunctionNative(JSContext *cx, JSFunction *fun); JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
#ifdef __cpluscplus
extern JS_PUBLIC_API(JSFastNative) extern JS_PUBLIC_API(JSFastNative)
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun); JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
#endif
extern JS_PUBLIC_API(JSPrincipals *) extern JS_PUBLIC_API(JSPrincipals *)
JS_GetScriptPrincipals(JSContext *cx, JSScript *script); JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
@ -297,7 +325,7 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
/************************************************************************/ /************************************************************************/
typedef struct JSPropertyDesc { typedef struct JSPropertyDesc {
jsval id; /* primary id, a string or int */ jsval id; /* primary id, atomized string, or int */
jsval value; /* property value */ jsval value; /* property value */
uint8 flags; /* flags, see below */ uint8 flags; /* flags, see below */
uint8 spare; /* unused */ uint8 spare; /* unused */
@ -337,7 +365,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
/************************************************************************/ /************************************************************************/
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure); JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure); JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);

View File

@ -37,6 +37,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* Portable double to alphanumeric string and back converters. * Portable double to alphanumeric string and back converters.
*/ */

View File

@ -59,13 +59,13 @@ extern void
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun); jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
extern void extern void
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp); jsdtrace_object_create_start(JSStackFrame *fp, js::Class *clasp);
extern void extern void
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp); jsdtrace_object_create_done(JSStackFrame *fp, js::Class *clasp);
extern void extern void
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj); jsdtrace_object_create(JSContext *cx, js::Class *clasp, JSObject *obj);
extern void extern void
jsdtrace_object_finalize(JSObject *obj); jsdtrace_object_finalize(JSObject *obj);

View File

@ -38,6 +38,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS bytecode generation. * JS bytecode generation.
*/ */
@ -69,6 +71,8 @@
#include "jsautooplen.h" #include "jsautooplen.h"
#include "jsstaticcheck.h" #include "jsstaticcheck.h"
#include "jsobjinlines.h"
/* Allocation chunk counts, must be powers of two in general. */ /* Allocation chunk counts, must be powers of two in general. */
#define BYTECODE_CHUNK 256 /* code allocation increment */ #define BYTECODE_CHUNK 256 /* code allocation increment */
#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */ #define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */
@ -96,7 +100,8 @@ JSCodeGenerator::JSCodeGenerator(JSCompiler *jsc,
spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL), spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL),
numSpanDeps(0), numJumpTargets(0), spanDepTodo(0), numSpanDeps(0), numJumpTargets(0), spanDepTodo(0),
arrayCompDepth(0), arrayCompDepth(0),
emitLevel(0) emitLevel(0),
constMap(jsc->context)
{ {
flags = TCF_COMPILING; flags = TCF_COMPILING;
memset(&prolog, 0, sizeof prolog); memset(&prolog, 0, sizeof prolog);
@ -107,6 +112,11 @@ JSCodeGenerator::JSCodeGenerator(JSCompiler *jsc,
memset(&upvarMap, 0, sizeof upvarMap); memset(&upvarMap, 0, sizeof upvarMap);
} }
bool JSCodeGenerator::init()
{
return constMap.init();
}
JSCodeGenerator::~JSCodeGenerator() JSCodeGenerator::~JSCodeGenerator()
{ {
JS_ARENA_RELEASE(codePool, codeMark); JS_ARENA_RELEASE(codePool, codeMark);
@ -205,7 +215,7 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
JS_ASSERT(nuses == 0); JS_ASSERT(nuses == 0);
blockObj = cg->objectList.lastbox->object; blockObj = cg->objectList.lastbox->object;
JS_ASSERT(blockObj->getClass() == &js_BlockClass); JS_ASSERT(blockObj->getClass() == &js_BlockClass);
JS_ASSERT(JSVAL_IS_VOID(blockObj->fslots[JSSLOT_BLOCK_DEPTH])); JS_ASSERT(blockObj->fslots[JSSLOT_BLOCK_DEPTH].isUndefined());
OBJ_SET_BLOCK_DEPTH(cx, blockObj, cg->stackDepth); OBJ_SET_BLOCK_DEPTH(cx, blockObj, cg->stackDepth);
ndefs = OBJ_BLOCK_COUNT(cx, blockObj); ndefs = OBJ_BLOCK_COUNT(cx, blockObj);
@ -1536,6 +1546,13 @@ js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg)
return JS_TRUE; return JS_TRUE;
} }
static JS_ALWAYS_INLINE JSAtom *
JSBOXEDWORD_TO_ATOM(jsboxedword w)
{
JS_STATIC_ASSERT(sizeof(jsboxedword) == sizeof(JSAtom *));
return (JSAtom *)w;
}
JSBool JSBool
js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
JSParseNode *pn) JSParseNode *pn)
@ -1543,29 +1560,24 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
jsdouble dval; jsdouble dval;
jsint ival; jsint ival;
JSAtom *valueAtom; JSAtom *valueAtom;
jsval v;
JSAtomListElement *ale;
/* XXX just do numbers for now */ /* XXX just do numbers for now */
if (pn->pn_type == TOK_NUMBER) { if (pn->pn_type == TOK_NUMBER) {
dval = pn->pn_dval; dval = pn->pn_dval;
if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) { if (JSDOUBLE_IS_INT32(dval, ival) && INT32_FITS_IN_JSBOXEDWORD(ival)) {
v = INT_TO_JSVAL(ival); valueAtom = JSBOXEDWORD_TO_ATOM(INT_TO_JSBOXEDWORD(ival));
} else { } else {
/* /*
* We atomize double to root a jsdouble instance that we wrap as * We atomize double to root a jsdouble instance that we wrap as
* jsval and store in cg->constList. This works because atoms are * jsboxedword and store in cg->constList. This works because atoms
* protected from GC during compilation. * are protected from GC during compilation.
*/ */
valueAtom = js_AtomizeDouble(cx, dval); valueAtom = js_AtomizeDouble(cx, dval);
if (!valueAtom) if (!valueAtom)
return JS_FALSE; return JS_FALSE;
v = ATOM_KEY(valueAtom);
} }
ale = cg->constList.add(cg->compiler, atom); if (!cg->constMap.put(atom, valueAtom))
if (!ale)
return JS_FALSE; return JS_FALSE;
ALE_SET_VALUE(ale, v);
} }
return JS_TRUE; return JS_TRUE;
} }
@ -1595,8 +1607,8 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
JS_ASSERT(sprop->hasShortID()); JS_ASSERT(sprop->hasShortID());
if (slotp) { if (slotp) {
JS_ASSERT(JSVAL_IS_INT(obj->fslots[JSSLOT_BLOCK_DEPTH])); JS_ASSERT(obj->fslots[JSSLOT_BLOCK_DEPTH].isInt32());
*slotp = JSVAL_TO_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]) + *slotp = obj->fslots[JSSLOT_BLOCK_DEPTH].asInt32() +
sprop->shortid; sprop->shortid;
} }
return stmt; return stmt;
@ -1616,17 +1628,46 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
(((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \ (((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \
(JSPROP_READONLY | JSPROP_PERMANENT)) (JSPROP_READONLY | JSPROP_PERMANENT))
static JSAtom *NO_CONSTANT = (JSAtom *)SPECIAL_TO_JSBOXEDWORD(0xabcd);
/* /*
* The function sets vp to JSVAL_HOLE when the atom does not corresponds to a * Outside of the compiler (specifically, switch statements), atoms can only be
* interned strings. Thus, this conversion is specific to the compiler.
*/
static bool
ValueToCompilerConstant(JSContext *cx, const Value &v, JSAtom **constp)
{
jsboxedword w;
if (v.isNull())
w = JSBOXEDWORD_NULL;
else if (v.isUndefined())
w = JSBOXEDWORD_VOID;
else if (v.isInt32() && INT32_FITS_IN_JSBOXEDWORD(v.asInt32()))
w = INT_TO_JSBOXEDWORD(v.asInt32());
else if (v.isNumber())
return (*constp = js_AtomizeDouble(cx, v.asNumber())) != NULL;
else if (v.isString())
w = STRING_TO_JSBOXEDWORD(v.asString());
else if (v.isObject())
w = OBJECT_TO_JSBOXEDWORD(&v.asObject());
else if (v.isBoolean())
w = BOOLEAN_TO_JSBOXEDWORD(v.asBoolean());
else
JS_NOT_REACHED("invalid value");
*constp = JSBOXEDWORD_TO_ATOM(w);
return true;
}
/*
* The function sets vp to NO_CONSTANT when the atom does not corresponds to a
* name defining a constant. * name defining a constant.
*/ */
static JSBool static JSBool
LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
jsval *vp) JSAtom **constp)
{ {
JSBool ok; JSBool ok;
JSStmtInfo *stmt; JSStmtInfo *stmt;
JSAtomListElement *ale;
JSObject *obj, *objbox; JSObject *obj, *objbox;
JSProperty *prop; JSProperty *prop;
uintN attrs; uintN attrs;
@ -1636,7 +1677,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
* This enables propagating consts from top-level into switch cases in a * This enables propagating consts from top-level into switch cases in a
* function compiled along with the top-level script. * function compiled along with the top-level script.
*/ */
*vp = JSVAL_HOLE; *constp = NO_CONSTANT;
do { do {
if (cg->flags & (TCF_IN_FUNCTION | TCF_COMPILE_N_GO)) { if (cg->flags & (TCF_IN_FUNCTION | TCF_COMPILE_N_GO)) {
/* XXX this will need revising if 'const' becomes block-scoped. */ /* XXX this will need revising if 'const' becomes block-scoped. */
@ -1644,10 +1685,9 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
if (stmt) if (stmt)
return JS_TRUE; return JS_TRUE;
ale = cg->constList.lookup(atom); if (JSCodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) {
if (ale) { JS_ASSERT(p->value != NO_CONSTANT);
JS_ASSERT(ALE_VALUE(ale) != JSVAL_HOLE); *constp = p->value;
*vp = ALE_VALUE(ale);
return JS_TRUE; return JS_TRUE;
} }
@ -1676,8 +1716,10 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
*/ */
ok = obj->getAttributes(cx, ATOM_TO_JSID(atom), prop, &attrs); ok = obj->getAttributes(cx, ATOM_TO_JSID(atom), prop, &attrs);
if (ok && IS_CONSTANT_PROPERTY(attrs)) { if (ok && IS_CONSTANT_PROPERTY(attrs)) {
ok = obj->getProperty(cx, ATOM_TO_JSID(atom), vp); Value v;
JS_ASSERT_IF(ok, *vp != JSVAL_HOLE); ok = obj->getProperty(cx, ATOM_TO_JSID(atom), &v);
if (ok)
ok = ValueToCompilerConstant(cx, v, constp);
} }
} }
if (prop) if (prop)
@ -1859,15 +1901,15 @@ EmitEnterBlock(JSContext *cx, JSParseNode *pn, JSCodeGenerator *cg)
for (uintN slot = JSSLOT_FREE(&js_BlockClass), for (uintN slot = JSSLOT_FREE(&js_BlockClass),
limit = slot + OBJ_BLOCK_COUNT(cx, blockObj); limit = slot + OBJ_BLOCK_COUNT(cx, blockObj);
slot < limit; slot++) { slot < limit; slot++) {
jsval v = blockObj->getSlot(slot); const Value &v = blockObj->getSlot(slot);
/* Beware the empty destructuring dummy. */ /* Beware the empty destructuring dummy. */
if (JSVAL_IS_VOID(v)) { if (v.isUndefined()) {
JS_ASSERT(slot + 1 <= limit); JS_ASSERT(slot + 1 <= limit);
continue; continue;
} }
JSDefinition *dn = (JSDefinition *) JSVAL_TO_PRIVATE(v); JSDefinition *dn = (JSDefinition *) v.asPrivateVoidPtr();
JS_ASSERT(dn->pn_defn); JS_ASSERT(dn->pn_defn);
JS_ASSERT(uintN(dn->frameSlot() + depth) < JS_BIT(16)); JS_ASSERT(uintN(dn->frameSlot() + depth) < JS_BIT(16));
dn->pn_cookie += depth; dn->pn_cookie += depth;
@ -2856,7 +2898,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
if (!BindNameToSlot(cx, cg, left)) if (!BindNameToSlot(cx, cg, left))
return JS_FALSE; return JS_FALSE;
if (left->pn_op == JSOP_ARGUMENTS && if (left->pn_op == JSOP_ARGUMENTS &&
JSDOUBLE_IS_INT(next->pn_dval, slot) && JSDOUBLE_IS_INT32(next->pn_dval, slot) &&
(jsuint)slot < JS_BIT(16)) { (jsuint)slot < JS_BIT(16)) {
/* /*
* arguments[i]() requires arguments object as "this". * arguments[i]() requires arguments object as "this".
@ -2931,7 +2973,7 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
if (!BindNameToSlot(cx, cg, left)) if (!BindNameToSlot(cx, cg, left))
return JS_FALSE; return JS_FALSE;
if (left->pn_op == JSOP_ARGUMENTS && if (left->pn_op == JSOP_ARGUMENTS &&
JSDOUBLE_IS_INT(right->pn_dval, slot) && JSDOUBLE_IS_INT32(right->pn_dval, slot) &&
(jsuint)slot < JS_BIT(16)) { (jsuint)slot < JS_BIT(16)) {
left->pn_offset = right->pn_offset = top; left->pn_offset = right->pn_offset = top;
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot); EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
@ -2963,7 +3005,7 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
JSAtom *atom; JSAtom *atom;
JSAtomListElement *ale; JSAtomListElement *ale;
if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) { if (JSDOUBLE_IS_INT32(dval, ival)) {
if (ival == 0) if (ival == 0)
return js_Emit1(cx, cg, JSOP_ZERO) >= 0; return js_Emit1(cx, cg, JSOP_ZERO) >= 0;
if (ival == 1) if (ival == 1)
@ -3012,7 +3054,6 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
JSParseNode **table; JSParseNode **table;
jsdouble d; jsdouble d;
jsint i, low, high; jsint i, low, high;
jsval v;
JSAtom *atom; JSAtom *atom;
JSAtomListElement *ale; JSAtomListElement *ale;
intN noteIndex; intN noteIndex;
@ -3130,8 +3171,8 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
switch (pn4->pn_type) { switch (pn4->pn_type) {
case TOK_NUMBER: case TOK_NUMBER:
d = pn4->pn_dval; d = pn4->pn_dval;
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { if (JSDOUBLE_IS_INT32(d, i) && INT32_FITS_IN_JSBOXEDWORD(i)) {
pn3->pn_val = INT_TO_JSVAL(i); pn3->pn_val = INT_TO_JSBOXEDWORD(i);
} else { } else {
atom = js_AtomizeDouble(cx, d); atom = js_AtomizeDouble(cx, d);
if (!atom) { if (!atom) {
@ -3146,11 +3187,11 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
break; break;
case TOK_NAME: case TOK_NAME:
if (!pn4->maybeExpr()) { if (!pn4->maybeExpr()) {
ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &v); ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &atom);
if (!ok) if (!ok)
goto release; goto release;
if (v != JSVAL_HOLE) { if (atom != NO_CONSTANT) {
if (!JSVAL_IS_PRIMITIVE(v)) { if (!JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(atom))) {
/* /*
* XXX JSOP_LOOKUPSWITCH does not support const- * XXX JSOP_LOOKUPSWITCH does not support const-
* propagated object values, see bug 407186. * propagated object values, see bug 407186.
@ -3158,7 +3199,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
switchOp = JSOP_CONDSWITCH; switchOp = JSOP_CONDSWITCH;
continue; continue;
} }
pn3->pn_val = v; pn3->pn_val = ATOM_KEY(atom);
constPropagated = JS_TRUE; constPropagated = JS_TRUE;
break; break;
} }
@ -3166,15 +3207,15 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
/* FALL THROUGH */ /* FALL THROUGH */
case TOK_PRIMARY: case TOK_PRIMARY:
if (pn4->pn_op == JSOP_TRUE) { if (pn4->pn_op == JSOP_TRUE) {
pn3->pn_val = JSVAL_TRUE; pn3->pn_val = JSBOXEDWORD_TRUE;
break; break;
} }
if (pn4->pn_op == JSOP_FALSE) { if (pn4->pn_op == JSOP_FALSE) {
pn3->pn_val = JSVAL_FALSE; pn3->pn_val = JSBOXEDWORD_FALSE;
break; break;
} }
if (pn4->pn_op == JSOP_NULL) { if (pn4->pn_op == JSOP_NULL) {
pn3->pn_val = JSVAL_NULL; pn3->pn_val = JSBOXEDWORD_NULL;
break; break;
} }
/* FALL THROUGH */ /* FALL THROUGH */
@ -3183,15 +3224,15 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
continue; continue;
} }
JS_ASSERT(JSVAL_IS_PRIMITIVE(pn3->pn_val)); JS_ASSERT(JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(pn3->pn_val)));
if (switchOp != JSOP_TABLESWITCH) if (switchOp != JSOP_TABLESWITCH)
continue; continue;
if (!JSVAL_IS_INT(pn3->pn_val)) { if (!JSBOXEDWORD_IS_INT(ATOM_KEY(pn3->pn_val))) {
switchOp = JSOP_LOOKUPSWITCH; switchOp = JSOP_LOOKUPSWITCH;
continue; continue;
} }
i = JSVAL_TO_INT(pn3->pn_val); i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val));
if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) { if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {
switchOp = JSOP_LOOKUPSWITCH; switchOp = JSOP_LOOKUPSWITCH;
continue; continue;
@ -3386,7 +3427,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
if (pn3->pn_type == TOK_DEFAULT) if (pn3->pn_type == TOK_DEFAULT)
continue; continue;
i = JSVAL_TO_INT(pn3->pn_val); i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val));
i -= low; i -= low;
JS_ASSERT((uint32)i < tableLength); JS_ASSERT((uint32)i < tableLength);
table[i] = pn3; table[i] = pn3;
@ -3529,7 +3570,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
if (pn3->pn_type == TOK_DEFAULT) if (pn3->pn_type == TOK_DEFAULT)
continue; continue;
if (!js_AtomizePrimitiveValue(cx, pn3->pn_val, &atom)) if (!js_AtomizePrimitiveValue(cx, ATOM_KEY(pn3->pn_val), &atom))
goto bad; goto bad;
ale = cg->atomList.add(cg->compiler, atom); ale = cg->atomList.add(cg->compiler, atom);
if (!ale) if (!ale)
@ -4396,6 +4437,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
new (cg2space) JSCodeGenerator(cg->compiler, new (cg2space) JSCodeGenerator(cg->compiler,
cg->codePool, cg->notePool, cg->codePool, cg->notePool,
pn->pn_pos.begin.lineno); pn->pn_pos.begin.lineno);
if (!cg2->init())
return JS_FALSE;
cg2->flags = pn->pn_funbox->tcflags | TCF_IN_FUNCTION; cg2->flags = pn->pn_funbox->tcflags | TCF_IN_FUNCTION;
#if JS_HAS_SHARP_VARS #if JS_HAS_SHARP_VARS
if (cg2->flags & TCF_HAS_SHARPS) { if (cg2->flags & TCF_HAS_SHARPS) {

View File

@ -455,7 +455,9 @@ struct JSCodeGenerator : public JSTreeContext
uintN arrayCompDepth; /* stack depth of array in comprehension */ uintN arrayCompDepth; /* stack depth of array in comprehension */
uintN emitLevel; /* js_EmitTree recursion level */ uintN emitLevel; /* js_EmitTree recursion level */
JSAtomList constList; /* compile time constants */
typedef js::HashMap<JSAtom *, JSAtom *> ConstMap;
ConstMap constMap; /* compile time constants */
JSCGObjectList objectList; /* list of emitted objects */ JSCGObjectList objectList; /* list of emitted objects */
JSCGObjectList regexpList; /* list of emitted regexp that will be JSCGObjectList regexpList; /* list of emitted regexp that will be
@ -473,6 +475,8 @@ struct JSCodeGenerator : public JSTreeContext
JSArenaPool *codePool, JSArenaPool *notePool, JSArenaPool *codePool, JSArenaPool *notePool,
uintN lineno); uintN lineno);
bool init();
/* /*
* Release cg->codePool, cg->notePool, and compiler->context->tempPool to * Release cg->codePool, cg->notePool, and compiler->context->tempPool to
* marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own * marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own

View File

@ -38,10 +38,11 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS standard exception implementation. * JS standard exception implementation.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "jstypes.h" #include "jstypes.h"
@ -63,11 +64,13 @@
#include "jsscript.h" #include "jsscript.h"
#include "jsstaticcheck.h" #include "jsstaticcheck.h"
#include "jscntxtinlines.h"
using namespace js; using namespace js;
/* Forward declarations for js_ErrorClass's initializer. */ /* Forward declarations for js_ErrorClass's initializer. */
static JSBool static JSBool
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
static void static void
exn_trace(JSTracer *trc, JSObject *obj); exn_trace(JSTracer *trc, JSObject *obj);
@ -82,12 +85,12 @@ static JSBool
exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
JSObject **objp); JSObject **objp);
JSClass js_ErrorClass = { Class js_ErrorClass = {
js_Error_str, js_Error_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE |
JSCLASS_HAS_CACHED_PROTO(JSProto_Error), JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, PropertyStub, PropertyStub, PropertyStub, PropertyStub,
exn_enumerate, (JSResolveOp)exn_resolve, JS_ConvertStub, exn_finalize, exn_enumerate, (JSResolveOp)exn_resolve, ConvertStub, exn_finalize,
NULL, NULL, NULL, Exception, NULL, NULL, NULL, Exception,
NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL
}; };
@ -249,10 +252,10 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
JSString *filename, uintN lineno, JSErrorReport *report) JSString *filename, uintN lineno, JSErrorReport *report)
{ {
JSSecurityCallbacks *callbacks; JSSecurityCallbacks *callbacks;
JSCheckAccessOp checkAccess; CheckAccessOp checkAccess;
JSErrorReporter older; JSErrorReporter older;
JSExceptionState *state; JSExceptionState *state;
jsval callerid, v; jsid callerid;
JSStackFrame *fp, *fpstop; JSStackFrame *fp, *fpstop;
size_t stackDepth, valueCount, size; size_t stackDepth, valueCount, size;
JSBool overflow; JSBool overflow;
@ -271,17 +274,17 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
*/ */
callbacks = JS_GetSecurityCallbacks(cx); callbacks = JS_GetSecurityCallbacks(cx);
checkAccess = callbacks checkAccess = callbacks
? callbacks->checkObjectAccess ? Valueify(callbacks->checkObjectAccess)
: NULL; : NULL;
older = JS_SetErrorReporter(cx, NULL); older = JS_SetErrorReporter(cx, NULL);
state = JS_SaveExceptionState(cx); state = JS_SaveExceptionState(cx);
callerid = ATOM_KEY(cx->runtime->atomState.callerAtom); callerid = ATOM_TO_JSID(cx->runtime->atomState.callerAtom);
stackDepth = 0; stackDepth = 0;
valueCount = 0; valueCount = 0;
for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) { for (fp = js_GetTopStackFrame(cx); fp; fp = fp->down) {
if (fp->fun && fp->argv) { if (fp->fun && fp->argv) {
v = JSVAL_NULL; NullValue v;
if (checkAccess && if (checkAccess &&
!checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) { !checkAccess(cx, fp->callee(), callerid, JSACC_READ, &v)) {
break; break;
@ -526,13 +529,13 @@ ValueToShortSource(JSContext *cx, jsval v)
/* Avoid toSource bloat and fallibility for object types. */ /* Avoid toSource bloat and fallibility for object types. */
if (JSVAL_IS_PRIMITIVE(v)) { if (JSVAL_IS_PRIMITIVE(v)) {
str = js_ValueToSource(cx, v); str = js_ValueToSource(cx, Valueify(v));
} else if (VALUE_IS_FUNCTION(cx, v)) { } else if (VALUE_IS_FUNCTION(cx, v)) {
/* /*
* XXX Avoid function decompilation bloat for now. * XXX Avoid function decompilation bloat for now.
*/ */
str = JS_GetFunctionId(JS_ValueToFunction(cx, v)); str = JS_GetFunctionId(JS_ValueToFunction(cx, v));
if (!str && !(str = js_ValueToSource(cx, v))) { if (!str && !(str = js_ValueToSource(cx, Valueify(v)))) {
/* /*
* Continue to soldier on if the function couldn't be * Continue to soldier on if the function couldn't be
* converted into a string. * converted into a string.
@ -683,7 +686,7 @@ StringToFilename(JSContext *cx, JSString *str)
} }
static JSBool static JSBool
Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) Exception(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
{ {
JSString *message, *filename; JSString *message, *filename;
JSStackFrame *fp; JSStackFrame *fp;
@ -696,16 +699,16 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
* js_NewObject to find the class prototype, we must get the class * js_NewObject to find the class prototype, we must get the class
* prototype ourselves. * prototype ourselves.
*/ */
if (!JSVAL_TO_OBJECT(argv[-2])->getProperty(cx, if (!argv[-2].asObject().getProperty(cx,
ATOM_TO_JSID(cx->runtime->atomState ATOM_TO_JSID(cx->runtime->atomState
.classPrototypeAtom), .classPrototypeAtom),
rval)) { rval)) {
return JS_FALSE; return JS_FALSE;
} }
obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL); obj = js_NewObject(cx, &js_ErrorClass, &rval->asObject(), NULL);
if (!obj) if (!obj)
return JS_FALSE; return JS_FALSE;
*rval = OBJECT_TO_JSVAL(obj); rval->setNonFunObj(*obj);
} }
/* /*
@ -720,7 +723,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
message = js_ValueToString(cx, argv[0]); message = js_ValueToString(cx, argv[0]);
if (!message) if (!message)
return JS_FALSE; return JS_FALSE;
argv[0] = STRING_TO_JSVAL(message); argv[0].setString(message);
} else { } else {
message = cx->runtime->emptyString; message = cx->runtime->emptyString;
} }
@ -730,7 +733,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
filename = js_ValueToString(cx, argv[1]); filename = js_ValueToString(cx, argv[1]);
if (!filename) if (!filename)
return JS_FALSE; return JS_FALSE;
argv[1] = STRING_TO_JSVAL(filename); argv[1].setString(filename);
fp = NULL; fp = NULL;
} else { } else {
fp = js_GetScriptedCaller(cx, NULL); fp = js_GetScriptedCaller(cx, NULL);
@ -746,7 +749,7 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
/* Set the 'lineNumber' property. */ /* Set the 'lineNumber' property. */
uint32_t lineno; uint32_t lineno;
if (argc > 2) { if (argc > 2) {
if (!ValueToECMAUint32(cx, argv[2], &lineno)) if (!ValueToECMAUint32(cx, &argv[2], &lineno))
return JS_FALSE; return JS_FALSE;
} else { } else {
if (!fp) if (!fp)
@ -775,7 +778,7 @@ exn_toString(JSContext *cx, uintN argc, jsval *vp)
size_t name_length, message_length, length; size_t name_length, message_length, length;
obj = JS_THIS_OBJECT(cx, vp); obj = JS_THIS_OBJECT(cx, vp);
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), &v)) if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(&v)))
return JS_FALSE; return JS_FALSE;
name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString; name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
*vp = STRING_TO_JSVAL(name); *vp = STRING_TO_JSVAL(name);
@ -824,32 +827,32 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
{ {
JSObject *obj; JSObject *obj;
JSString *name, *message, *filename, *lineno_as_str, *result; JSString *name, *message, *filename, *lineno_as_str, *result;
jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL}; jsval localroots[4] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
size_t lineno_length, name_length, message_length, filename_length, length; size_t lineno_length, name_length, message_length, filename_length, length;
jschar *chars, *cp; jschar *chars, *cp;
obj = JS_THIS_OBJECT(cx, vp); obj = JS_THIS_OBJECT(cx, vp);
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp)) if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(vp)))
return false; return false;
name = js_ValueToString(cx, *vp); name = js_ValueToString(cx, Valueify(*vp));
if (!name) if (!name)
return false; return false;
*vp = STRING_TO_JSVAL(name); *vp = STRING_TO_JSVAL(name);
{ {
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroots), localroots); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroots), Valueify(localroots));
#ifdef __GNUC__ #ifdef __GNUC__
message = filename = NULL; message = filename = NULL;
#endif #endif
if (!JS_GetProperty(cx, obj, js_message_str, &localroots[0]) || if (!JS_GetProperty(cx, obj, js_message_str, &localroots[0]) ||
!(message = js_ValueToSource(cx, localroots[0]))) { !(message = js_ValueToSource(cx, Valueify(localroots[0])))) {
return false; return false;
} }
localroots[0] = STRING_TO_JSVAL(message); localroots[0] = STRING_TO_JSVAL(message);
if (!JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) || if (!JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) ||
!(filename = js_ValueToSource(cx, localroots[1]))) { !(filename = js_ValueToSource(cx, Valueify(localroots[1])))) {
return false; return false;
} }
localroots[1] = STRING_TO_JSVAL(filename); localroots[1] = STRING_TO_JSVAL(filename);
@ -857,11 +860,12 @@ exn_toSource(JSContext *cx, uintN argc, jsval *vp)
if (!JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2])) if (!JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]))
return false; return false;
uint32_t lineno; uint32_t lineno;
if (!ValueToECMAUint32(cx, localroots[2], &lineno)) localroots[3] = localroots[2]; /* ValueToECMAUint32 mutates localroots[2] */
if (!ValueToECMAUint32(cx, Valueify(&localroots[2]), &lineno))
return false; return false;
if (lineno != 0) { if (lineno != 0) {
lineno_as_str = js_ValueToString(cx, localroots[2]); lineno_as_str = js_ValueToString(cx, Valueify(localroots[3]));
if (!lineno_as_str) if (!lineno_as_str)
return false; return false;
lineno_length = lineno_as_str->length(); lineno_length = lineno_as_str->length();
@ -987,7 +991,7 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
return NULL; return NULL;
PodArrayZero(roots); PodArrayZero(roots);
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));
#ifdef __GNUC__ #ifdef __GNUC__
error_proto = NULL; /* quell GCC overwarning */ error_proto = NULL; /* quell GCC overwarning */
@ -1036,7 +1040,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj)
} }
/* Add the name property to the prototype. */ /* Add the name property to the prototype. */
if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_KEY(atom), if (!JS_DefineProperty(cx, proto, js_name_str,
STRING_TO_JSVAL(ATOM_TO_STRING(atom)),
NULL, NULL, JSPROP_ENUMERATE)) { NULL, NULL, JSPROP_ENUMERATE)) {
return NULL; return NULL;
} }
@ -1145,7 +1150,7 @@ js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp,
/* Protect the newly-created strings below from nesting GCs. */ /* Protect the newly-created strings below from nesting GCs. */
PodArrayZero(tv); PodArrayZero(tv);
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(tv), tv); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(tv), Valueify(tv));
/* /*
* Try to get an appropriate prototype by looking up the corresponding * Try to get an appropriate prototype by looking up the corresponding
@ -1210,7 +1215,7 @@ js_ReportUncaughtException(JSContext *cx)
return false; return false;
PodArrayZero(roots); PodArrayZero(roots);
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), roots); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));
/* /*
* Because js_ValueToString below could error and an exception object * Because js_ValueToString below could error and an exception object
@ -1229,7 +1234,7 @@ js_ReportUncaughtException(JSContext *cx)
reportp = js_ErrorFromException(cx, exn); reportp = js_ErrorFromException(cx, exn);
/* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */ /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
str = js_ValueToString(cx, exn); str = js_ValueToString(cx, Valueify(exn));
if (!str) { if (!str) {
bytes = "unknown (can't convert to string)"; bytes = "unknown (can't convert to string)";
} else { } else {
@ -1252,7 +1257,7 @@ js_ReportUncaughtException(JSContext *cx)
if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3])) if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]))
return false; return false;
str = js_ValueToString(cx, roots[3]); str = js_ValueToString(cx, Valueify(roots[3]));
if (!str) if (!str)
return false; return false;
filename = StringToFilename(cx, str); filename = StringToFilename(cx, str);
@ -1262,7 +1267,7 @@ js_ReportUncaughtException(JSContext *cx)
if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4])) if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
return false; return false;
uint32_t lineno; uint32_t lineno;
if (!ValueToECMAUint32 (cx, roots[4], &lineno)) if (!ValueToECMAUint32 (cx, Valueify(&roots[4]), &lineno))
return false; return false;
reportp = &report; reportp = &report;

View File

@ -44,9 +44,7 @@
#ifndef jsexn_h___ #ifndef jsexn_h___
#define jsexn_h___ #define jsexn_h___
JS_BEGIN_EXTERN_C extern js::Class js_ErrorClass;
extern JSClass js_ErrorClass;
/* /*
* Initialize the exception constructor/prototype hierarchy. * Initialize the exception constructor/prototype hierarchy.
@ -92,6 +90,4 @@ extern const JSErrorFormatString *
js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale, js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
const uintN errorNumber); const uintN errorNumber);
JS_END_EXTERN_C
#endif /* jsexn_h___ */ #endif /* jsexn_h___ */

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,6 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "jsobj.h" #include "jsobj.h"
JS_BEGIN_EXTERN_C
typedef struct JSLocalNameMap JSLocalNameMap; typedef struct JSLocalNameMap JSLocalNameMap;
/* /*
@ -137,8 +135,8 @@ struct JSFunction : public JSObject
struct { struct {
uint16 extra; /* number of arg slots for local GC roots */ uint16 extra; /* number of arg slots for local GC roots */
uint16 spare; /* reserved for future use */ uint16 spare; /* reserved for future use */
JSNative native; /* native method pointer or null */ js::Native native; /* native method pointer or null */
JSClass *clasp; /* class of objects constructed js::Class *clasp; /* class of objects constructed
by this function */ by this function */
JSNativeTraceInfo *trcinfo; JSNativeTraceInfo *trcinfo;
} n; } n;
@ -231,7 +229,7 @@ struct JSFunction : public JSObject
* Yes, this is an incompatible change, which prefigures the impending move to * Yes, this is an incompatible change, which prefigures the impending move to
* single-threaded objects and GC heaps. * single-threaded objects and GC heaps.
*/ */
extern JSClass js_ArgumentsClass; extern js::Class js_ArgumentsClass;
inline bool inline bool
JSObject::isArguments() const JSObject::isArguments() const
@ -239,12 +237,12 @@ JSObject::isArguments() const
return getClass() == &js_ArgumentsClass; return getClass() == &js_ArgumentsClass;
} }
extern JS_FRIEND_DATA(JSClass) js_CallClass; extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern JSClass js_DeclEnvClass; extern js::Class js_DeclEnvClass;
extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS; extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */ /* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
extern JS_FRIEND_DATA(JSClass) js_FunctionClass; extern JS_FRIEND_DATA(js::Class) js_FunctionClass;
inline bool inline bool
JSObject::isFunction() const JSObject::isFunction() const
@ -253,6 +251,7 @@ JSObject::isFunction() const
} }
/* /*
* TODO: remove once all internal jsval use goes away.
* NB: jsapi.h and jsobj.h must be included before any call to this macro. * NB: jsapi.h and jsobj.h must be included before any call to this macro.
*/ */
#define VALUE_IS_FUNCTION(cx, v) \ #define VALUE_IS_FUNCTION(cx, v) \
@ -300,7 +299,7 @@ extern JSObject *
js_InitArgumentsClass(JSContext *cx, JSObject *obj); js_InitArgumentsClass(JSContext *cx, JSObject *obj);
extern JSFunction * extern JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, js_NewFunction(JSContext *cx, JSObject *funobj, js::Native native, uintN nargs,
uintN flags, JSObject *parent, JSAtom *atom); uintN flags, JSObject *parent, JSAtom *atom);
extern void extern void
@ -309,9 +308,9 @@ js_TraceFunction(JSTracer *trc, JSFunction *fun);
extern void extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun); js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSObject * JS_FASTCALL extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, js_CloneFunctionObject(JSContext *cx, JSFunction *fun, const js::Value &parent,
JSObject *proto); const js::Value &proto);
inline JSObject * inline JSObject *
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent) CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
@ -320,8 +319,8 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
JSObject *proto; JSObject *proto;
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto)) if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
return NULL; return NULL;
JS_ASSERT(proto); return js_CloneFunctionObject(cx, fun, js::NonFunObjValue(*parent),
return js_CloneFunctionObject(cx, fun, parent, proto); js::FunObjValue(*proto));
} }
extern JS_REQUIRES_STACK JSObject * extern JS_REQUIRES_STACK JSObject *
@ -331,7 +330,7 @@ extern JS_REQUIRES_STACK JSObject *
js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun); js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
extern JSFunction * extern JSFunction *
js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native, js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, js::Native native,
uintN nargs, uintN flags); uintN nargs, uintN flags);
/* /*
@ -344,16 +343,16 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
#define JSV2F_SEARCH_STACK 0x10000 #define JSV2F_SEARCH_STACK 0x10000
extern JSFunction * extern JSFunction *
js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags); js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject * extern JSObject *
js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags); js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
extern JSObject * extern JSObject *
js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags); js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
extern void extern void
js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags); js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject * extern JSObject *
js_GetCallObject(JSContext *cx, JSStackFrame *fp); js_GetCallObject(JSContext *cx, JSStackFrame *fp);
@ -365,23 +364,23 @@ extern void
js_PutCallObject(JSContext *cx, JSStackFrame *fp); js_PutCallObject(JSContext *cx, JSStackFrame *fp);
extern JSBool JS_FASTCALL extern JSBool JS_FASTCALL
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs, jsval *argv, js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
uint32 nvars, jsval *slots); js::Value *argv, uint32 nvars, js::Value *slots);
extern JSFunction * extern JSFunction *
js_GetCallObjectFunction(JSObject *obj); js_GetCallObjectFunction(JSObject *obj);
extern JSBool extern JSBool
js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp); SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp); SetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
/* /*
* js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter * js_SetCallArg and js_SetCallVar are extern fastcall copies of the setter
@ -390,23 +389,23 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
* property ops map. * property ops map.
*/ */
extern JSBool JS_FASTCALL extern JSBool JS_FASTCALL
js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval v); js_SetCallArg(JSContext *cx, JSObject *obj, jsid id, const js::Value &v);
extern JSBool JS_FASTCALL extern JSBool JS_FASTCALL
js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval v); js_SetCallVar(JSContext *cx, JSObject *obj, jsid id, const js::Value &v);
/* /*
* Slower version of js_GetCallVar used when call_resolve detects an attempt to * Slower version of js_GetCallVar used when call_resolve detects an attempt to
* leak an optimized closure via indirect or debugger eval. * leak an optimized closure via indirect or debugger eval.
*/ */
extern JSBool extern JSBool
js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetCallVarChecked(JSContext *cx, JSObject *obj, jsid id, const js::Value *vp);
extern JSBool extern JSBool
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp); js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);
extern JSBool extern JSBool
js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp); js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, js::Value *vp);
extern JSObject * extern JSObject *
js_GetArgsObject(JSContext *cx, JSStackFrame *fp); js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
@ -455,34 +454,30 @@ const uint32 ARGS_FIXED_RESERVED_SLOTS = JSSLOT_ARGS_START - JSSLOT_ARGS_LENGTH;
const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(19) - 1024; const uint32 JS_ARGS_LENGTH_MAX = JS_BIT(19) - 1024;
/* /*
* JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int jsval. * JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int value.
* Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must fit JSVAL_INT_MAX. To assert that * Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must into an int32.
* we check first that the shift does not overflow uint32.
*/ */
JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30)); JS_STATIC_ASSERT(JS_ARGS_LENGTH_MAX <= JS_BIT(30));
JS_STATIC_ASSERT(jsval((JS_ARGS_LENGTH_MAX << 1) | 1) <= JSVAL_INT_MAX);
namespace js { namespace js {
inline jsval inline const Value &
GetArgsSlot(JSObject *argsobj, uint32 arg) GetArgsSlot(JSObject *argsobj, uint32 arg)
{ {
return argsobj->dslots[arg]; return argsobj->dslots[arg];
} }
inline void inline void
SetArgsSlot(JSObject *argsobj, uint32 arg, jsval v) SetArgsSlot(JSObject *argsobj, uint32 arg, const Value &v)
{ {
argsobj->dslots[arg] = v; argsobj->dslots[arg].copy(v);
} }
inline bool inline bool
IsOverriddenArgsLength(JSObject *obj) IsOverriddenArgsLength(JSObject *obj)
{ {
JS_ASSERT(obj->isArguments()); JS_ASSERT(obj->isArguments());
return (obj->fslots[JSSLOT_ARGS_LENGTH].asInt32() & 1) != 0;
jsval v = obj->fslots[JSSLOT_ARGS_LENGTH];
return (JSVAL_TO_INT(v) & 1) != 0;
} }
inline uint32 inline uint32
@ -490,7 +485,7 @@ GetArgsLength(JSObject *obj)
{ {
JS_ASSERT(obj->isArguments()); JS_ASSERT(obj->isArguments());
uint32 argc = uint32(JSVAL_TO_INT(obj->fslots[JSSLOT_ARGS_LENGTH])) >> 1; uint32 argc = uint32(obj->fslots[JSSLOT_ARGS_LENGTH].asInt32()) >> 1;
JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX); JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
return argc; return argc;
} }
@ -538,7 +533,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
* If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to * If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
* check if nameWord corresponds to the const declaration. * check if nameWord corresponds to the const declaration.
*/ */
extern JS_FRIEND_API(jsuword *) extern jsuword *
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool); js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \ #define JS_LOCAL_NAME_TO_ATOM(nameWord) \
@ -551,12 +546,9 @@ extern void
js_FreezeLocalNames(JSContext *cx, JSFunction *fun); js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
extern JSBool extern JSBool
js_fun_apply(JSContext *cx, uintN argc, jsval *vp); js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
extern JSBool extern JSBool
js_fun_call(JSContext *cx, uintN argc, jsval *vp); js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
JS_END_EXTERN_C
#endif /* jsfun_h___ */ #endif /* jsfun_h___ */

View File

@ -38,6 +38,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JS Mark-and-Sweep Garbage Collector. * JS Mark-and-Sweep Garbage Collector.
* *
@ -115,20 +117,15 @@ using namespace js;
* JSTRACE_STRING. * JSTRACE_STRING.
*/ */
JS_STATIC_ASSERT(JSTRACE_OBJECT == 0); JS_STATIC_ASSERT(JSTRACE_OBJECT == 0);
JS_STATIC_ASSERT(JSTRACE_DOUBLE == 1); JS_STATIC_ASSERT(JSTRACE_STRING == 1);
JS_STATIC_ASSERT(JSTRACE_STRING == 2); JS_STATIC_ASSERT(JSTRACE_DOUBLE == 2);
JS_STATIC_ASSERT(JSTRACE_XML == 3); JS_STATIC_ASSERT(JSTRACE_XML == 3);
/* /*
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml * JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
* trace kind when JS_HAS_XML_SUPPORT is false. * trace kind when JS_HAS_XML_SUPPORT is false.
*/ */
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML); JS_STATIC_ASSERT(JSTRACE_DOUBLE + 1 == JSTRACE_XML);
/*
* Check that we can use memset(p, 0, ...) to implement JS_CLEAR_WEAK_ROOTS.
*/
JS_STATIC_ASSERT(JSVAL_NULL == 0);
/* /*
* Check consistency of external string constants from JSFinalizeGCThingKind. * Check consistency of external string constants from JSFinalizeGCThingKind.
@ -900,13 +897,6 @@ js_IsAboutToBeFinalized(void *thing)
return !IsMarkedGCThing(a, thing); return !IsMarkedGCThing(a, thing);
} }
/* This is compatible with JSDHashEntryStub. */
typedef struct JSGCRootHashEntry {
JSDHashEntryHdr hdr;
void *root;
const char *name;
} JSGCRootHashEntry;
/* /*
* Initial size of the gcRootsHash and gcLocksHash tables (SWAG, small enough * Initial size of the gcRootsHash and gcLocksHash tables (SWAG, small enough
* to amortize). * to amortize).
@ -923,11 +913,8 @@ JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes) js_InitGC(JSRuntime *rt, uint32 maxbytes)
{ {
InitGCArenaLists(rt); InitGCArenaLists(rt);
if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL, if (!rt->gcRootsHash.init(GC_ROOTS_SIZE))
sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
rt->gcRootsHash.ops = NULL;
return false; return false;
}
if (!JS_DHashTableInit(&rt->gcLocksHash, JS_DHashGetStubOps(), NULL, if (!JS_DHashTableInit(&rt->gcLocksHash, JS_DHashGetStubOps(), NULL,
sizeof(JSGCLockHashEntry), GC_ROOTS_SIZE)) { sizeof(JSGCLockHashEntry), GC_ROOTS_SIZE)) {
rt->gcLocksHash.ops = NULL; rt->gcLocksHash.ops = NULL;
@ -1150,12 +1137,10 @@ js_FinishGC(JSRuntime *rt)
rt->gcIteratorTable.clear(); rt->gcIteratorTable.clear();
FinishGCArenaLists(rt); FinishGCArenaLists(rt);
if (rt->gcRootsHash.ops) { if (rt->gcRootsHash.initialized()) {
#ifdef DEBUG #ifdef DEBUG
CheckLeakedRoots(rt); CheckLeakedRoots(rt);
#endif #endif
JS_DHashTableFinish(&rt->gcRootsHash);
rt->gcRootsHash.ops = NULL;
} }
if (rt->gcLocksHash.ops) { if (rt->gcLocksHash.ops) {
JS_DHashTableFinish(&rt->gcLocksHash); JS_DHashTableFinish(&rt->gcLocksHash);
@ -1164,20 +1149,26 @@ js_FinishGC(JSRuntime *rt)
} }
JSBool JSBool
js_AddRoot(JSContext *cx, void *rp, const char *name) js_AddRoot(JSContext *cx, Value *vp, const char *name)
{ {
JSBool ok = js_AddRootRT(cx->runtime, rp, name); JSBool ok = js_AddRootRT(cx->runtime, vp, name);
if (!ok) if (!ok)
JS_ReportOutOfMemory(cx); JS_ReportOutOfMemory(cx);
return ok; return ok;
} }
JSBool JSBool
js_AddRootRT(JSRuntime *rt, void *rp, const char *name) js_AddGCThingRoot(JSContext *cx, void **rp, const char *name)
{ {
JSBool ok; JSBool ok = js_AddGCThingRootRT(cx->runtime, rp, name);
JSGCRootHashEntry *rhe; if (!ok)
JS_ReportOutOfMemory(cx);
return ok;
}
JSBool
js_AddRootRT(JSRuntime *rt, Value *vp, const char *name)
{
/* /*
* Due to the long-standing, but now removed, use of rt->gcLock across the * Due to the long-standing, but now removed, use of rt->gcLock across the
* bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking * bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
@ -1187,16 +1178,26 @@ js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
*/ */
AutoLockGC lock(rt); AutoLockGC lock(rt);
js_WaitForGC(rt); js_WaitForGC(rt);
rhe = (JSGCRootHashEntry *)
JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_ADD); void *key = vp;
if (rhe) { return !!rt->gcRootsHash.put(key, JSRootInfo(name, JS_GC_ROOT_VALUE_PTR));
rhe->root = rp; }
rhe->name = name;
ok = JS_TRUE; JSBool
} else { js_AddRootRT(JSRuntime *rt, void **rp, const char *name)
ok = JS_FALSE; {
} /*
return ok; * Due to the long-standing, but now removed, use of rt->gcLock across the
* bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
* properly with a racing GC, without calling JS_AddRoot from a request.
* We have to preserve API compatibility here, now that we avoid holding
* rt->gcLock across the mark phase (including the root hashtable mark).
*/
AutoLockGC lock(rt);
js_WaitForGC(rt);
void *key = rp;
return !!rt->gcRootsHash.put(key, JSRootInfo(name, JS_GC_ROOT_GCTHING_PTR));
} }
JSBool JSBool
@ -1208,35 +1209,31 @@ js_RemoveRoot(JSRuntime *rt, void *rp)
*/ */
AutoLockGC lock(rt); AutoLockGC lock(rt);
js_WaitForGC(rt); js_WaitForGC(rt);
(void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE); rt->gcRootsHash.remove(rp);
rt->gcPoke = JS_TRUE; rt->gcPoke = JS_TRUE;
return JS_TRUE; return JS_TRUE;
} }
typedef JSRootedValueMap::Range RootRange;
typedef JSRootedValueMap::Entry RootEntry;
typedef JSRootedValueMap::Enum RootEnum;
#ifdef DEBUG #ifdef DEBUG
static JSDHashOperator
js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg)
{
uint32 *leakedroots = (uint32 *)arg;
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
(*leakedroots)++;
fprintf(stderr,
"JS engine warning: leaking GC root \'%s\' at %p\n",
rhe->name ? (char *)rhe->name : "", rhe->root);
return JS_DHASH_NEXT;
}
static void static void
CheckLeakedRoots(JSRuntime *rt) CheckLeakedRoots(JSRuntime *rt)
{ {
uint32 leakedroots = 0; uint32 leakedroots = 0;
/* Warn (but don't assert) debug builds of any remaining roots. */ /* Warn (but don't assert) debug builds of any remaining roots. */
JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer, for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
&leakedroots); RootEntry &entry = r.front();
leakedroots++;
fprintf(stderr,
"JS engine warning: leaking GC root \'%s\' at %p\n",
entry.value.name ? entry.value.name : "", entry.key);
}
if (leakedroots > 0) { if (leakedroots > 0) {
if (leakedroots == 1) { if (leakedroots == 1) {
fprintf(stderr, fprintf(stderr,
@ -1254,74 +1251,38 @@ CheckLeakedRoots(JSRuntime *rt)
} }
} }
typedef struct NamedRootDumpArgs {
void (*dump)(const char *name, void *rp, void *data);
void *data;
} NamedRootDumpArgs;
static JSDHashOperator
js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
void *arg)
{
NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
if (rhe->name)
args->dump(rhe->name, rhe->root, args->data);
return JS_DHASH_NEXT;
}
void void
js_DumpNamedRoots(JSRuntime *rt, js_DumpNamedRoots(JSRuntime *rt,
void (*dump)(const char *name, void *rp, void *data), void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
void *data) void *data)
{ {
NamedRootDumpArgs args; for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
RootEntry &entry = r.front();
args.dump = dump; if (const char *name = entry.value.name)
args.data = data; dump(name, entry.key, entry.value.type, data);
JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args); }
} }
#endif /* DEBUG */ #endif /* DEBUG */
typedef struct GCRootMapArgs {
JSGCRootMapFun map;
void *data;
} GCRootMapArgs;
static JSDHashOperator
js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
void *arg)
{
GCRootMapArgs *args = (GCRootMapArgs *) arg;
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
intN mapflags;
int op;
mapflags = args->map(rhe->root, rhe->name, args->data);
#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \
JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \
JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
op = (JSDHashOperator)mapflags;
#else
op = JS_DHASH_NEXT;
if (mapflags & JS_MAP_GCROOT_STOP)
op |= JS_DHASH_STOP;
if (mapflags & JS_MAP_GCROOT_REMOVE)
op |= JS_DHASH_REMOVE;
#endif
return (JSDHashOperator) op;
}
uint32 uint32
js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data) js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
{ {
GCRootMapArgs args = {map, data};
AutoLockGC lock(rt); AutoLockGC lock(rt);
return JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args); int ct = 0;
for (RootEnum e(rt->gcRootsHash); !e.empty(); e.popFront()) {
RootEntry &entry = e.front();
ct++;
intN mapflags = map(entry.key, entry.value.type, entry.value.name, data);
if (mapflags & JS_MAP_GCROOT_REMOVE)
e.removeFront();
if (mapflags & JS_MAP_GCROOT_STOP)
break;
}
return ct;
} }
JSBool JSBool
@ -1582,7 +1543,7 @@ js_NewFinalizableGCThing(JSContext *cx, unsigned thingKind)
* this reference, allowing thing to be GC'd if it has no other refs. * this reference, allowing thing to be GC'd if it has no other refs.
* See JS_EnterLocalRootScope and related APIs. * See JS_EnterLocalRootScope and related APIs.
*/ */
if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0) { if (js_PushLocalRoot(cx, lrs, thing) < 0) {
JS_ASSERT(thing->link == *freeListp); JS_ASSERT(thing->link == *freeListp);
*freeListp = thing; *freeListp = thing;
return NULL; return NULL;
@ -1728,8 +1689,8 @@ RefillDoubleFreeList(JSContext *cx)
return MakeNewArenaFreeList(a, sizeof(jsdouble)); return MakeNewArenaFreeList(a, sizeof(jsdouble));
} }
JSBool jsdouble *
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp) js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d)
{ {
/* Updates of metering counters here are not thread-safe. */ /* Updates of metering counters here are not thread-safe. */
METER(cx->runtime->gcStats.doubleArenaStats.alloc++); METER(cx->runtime->gcStats.doubleArenaStats.alloc++);
@ -1744,8 +1705,8 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
jsdouble *dp = reinterpret_cast<jsdouble *>(thing); jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
*dp = d; *dp = d;
*vp = DOUBLE_TO_JSVAL(dp); cx->weakRoots.newbornDouble = dp;
return true; return dp;
} }
JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack; JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack;
@ -1769,7 +1730,7 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
js_ReportOutOfMemory(cx); js_ReportOutOfMemory(cx);
METER(cx->runtime->gcStats.doubleArenaStats.fail++); METER(cx->runtime->gcStats.doubleArenaStats.fail++);
} }
return false; return NULL;
} }
CheckGCFreeListLink(thing); CheckGCFreeListLink(thing);
@ -1777,19 +1738,11 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
jsdouble *dp = reinterpret_cast<jsdouble *>(thing); jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
*dp = d; *dp = d;
*vp = DOUBLE_TO_JSVAL(dp);
return !lrs || js_PushLocalRoot(cx, lrs, *vp) >= 0;
}
jsdouble *
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
{
jsval v;
if (!js_NewDoubleInRootedValue(cx, d, &v))
return NULL;
jsdouble *dp = JSVAL_TO_DOUBLE(v);
cx->weakRoots.newbornDouble = dp; cx->weakRoots.newbornDouble = dp;
/*
* N.B. We any active local root scope, since this function is called only
* from the compiler to create double atoms.
*/
return dp; return dp;
} }
@ -2049,8 +2002,10 @@ MarkDelayedChildren(JSTracer *trc)
JS_ASSERT(rt->gcMarkLaterCount == 0); JS_ASSERT(rt->gcMarkLaterCount == 0);
} }
namespace js {
void void
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind) CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
{ {
JSContext *cx; JSContext *cx;
JSRuntime *rt; JSRuntime *rt;
@ -2152,40 +2107,42 @@ js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
} }
void void
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v) CallGCMarkerForGCThing(JSTracer *trc, void *thing)
{ {
void *thing; #ifdef DEBUG
uint32 kind; /*
* The incoming thing should be a real gc-thing, not a boxed, word-sized
if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) { * primitive value.
thing = JSVAL_TO_TRACEABLE(v); */
kind = JSVAL_TRACE_KIND(v); jsboxedword w = (jsboxedword)thing;
JS_ASSERT(kind == js_GetGCThingTraceKind(thing)); JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
} else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) { #endif
/* v can be an arbitrary GC thing reinterpreted as an object. */
thing = JSVAL_TO_OBJECT(v); if (!thing)
kind = js_GetGCThingTraceKind(thing);
} else {
return; return;
}
js_CallGCMarker(trc, thing, kind); uint32 kind = js_GetGCThingTraceKind(thing);
CallGCMarker(trc, thing, kind);
} }
static JSDHashOperator } /* namespace js */
gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
void *arg)
{
JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
JSTracer *trc = (JSTracer *)arg;
jsval *rp = (jsval *)rhe->root;
jsval v = *rp;
/* Ignore null reference, scalar values, and static strings. */ static void
if (JSVAL_IS_TRACEABLE(v)) { gc_root_traversal(JSTracer *trc, const RootEntry &entry)
{
#ifdef DEBUG #ifdef DEBUG
if (!JSString::isStatic(JSVAL_TO_GCTHING(v))) { void *ptr;
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR) {
ptr = entry.key;
} else {
Value *vp = static_cast<Value *>(entry.key);
ptr = vp->isGCThing() ? vp->asGCThing() : NULL;
}
if (ptr) {
if (!JSString::isStatic(ptr)) {
bool root_points_to_gcArenaList = false; bool root_points_to_gcArenaList = false;
jsuword thing = (jsuword) JSVAL_TO_GCTHING(v); jsuword thing = (jsuword) ptr;
JSRuntime *rt = trc->context->runtime; JSRuntime *rt = trc->context->runtime;
for (unsigned i = 0; i != FINALIZE_LIMIT; i++) { for (unsigned i = 0; i != FINALIZE_LIMIT; i++) {
JSGCArenaList *arenaList = &rt->gcArenaList[i]; JSGCArenaList *arenaList = &rt->gcArenaList[i];
@ -2209,21 +2166,23 @@ gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
} }
} }
} }
if (!root_points_to_gcArenaList && rhe->name) { if (!root_points_to_gcArenaList && entry.value.name) {
fprintf(stderr, fprintf(stderr,
"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n" "JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n" "invalid gcthing. This is usually caused by a missing call to JS_RemoveRoot.\n"
"The root's name is \"%s\".\n", "The root's name is \"%s\".\n",
rhe->name); entry.value.name);
} }
JS_ASSERT(root_points_to_gcArenaList); JS_ASSERT(root_points_to_gcArenaList);
} }
#endif
JS_SET_TRACING_NAME(trc, rhe->name ? rhe->name : "root");
js_CallValueTracerIfGCThing(trc, v);
} }
#endif
return JS_DHASH_NEXT; JS_SET_TRACING_NAME(trc, entry.value.name ? entry.value.name : "root");
if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
CallGCMarkerForGCThing(trc, entry.key);
else
CallGCMarkerIfGCThing(trc, *static_cast<Value *>(entry.key));
} }
static JSDHashOperator static JSDHashOperator
@ -2249,7 +2208,7 @@ TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len)
for (uint32 i = 0; i < len; i++) { for (uint32 i = 0; i < len; i++) {
if (JSObject *obj = vec[i]) { if (JSObject *obj = vec[i]) {
JS_SET_TRACING_INDEX(trc, "vector", i); JS_SET_TRACING_INDEX(trc, "vector", i);
js_CallGCMarker(trc, obj, JSTRACE_OBJECT); CallGCMarker(trc, obj, JSTRACE_OBJECT);
} }
} }
} }
@ -2263,14 +2222,13 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
if (fp->callobj) if (fp->callobj)
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call"); JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
if (fp->argsobj) if (fp->argsobj)
JS_CALL_OBJECT_TRACER(trc, JSVAL_TO_OBJECT(fp->argsobj), "arguments"); JS_CALL_OBJECT_TRACER(trc, fp->argsobj, "arguments");
if (fp->script) if (fp->script)
js_TraceScript(trc, fp->script); js_TraceScript(trc, fp->script);
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */ /* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
JS_CALL_VALUE_TRACER(trc, fp->thisv, "this"); CallGCMarkerIfGCThing(trc, fp->thisv, "this");
CallGCMarkerIfGCThing(trc, fp->rval, "rval");
JS_CALL_VALUE_TRACER(trc, fp->rval, "rval");
if (fp->scopeChain) if (fp->scopeChain)
JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain"); JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
} }
@ -2305,9 +2263,8 @@ JSWeakRoots::mark(JSTracer *trc)
} }
if (newbornDouble) if (newbornDouble)
JS_CALL_DOUBLE_TRACER(trc, newbornDouble, "newborn_double"); JS_CALL_DOUBLE_TRACER(trc, newbornDouble, "newborn_double");
JS_CALL_VALUE_TRACER(trc, lastAtom, "lastAtom"); CallGCMarkerIfGCThing(trc, ATOM_TO_JSID(lastAtom), "lastAtom");
JS_SET_TRACING_NAME(trc, "lastInternalResult"); CallGCMarkerForGCThing(trc, lastInternalResult, "lastInternalResult");
js_CallValueTracerIfGCThing(trc, lastInternalResult);
} }
void void
@ -2320,10 +2277,10 @@ js_TraceContext(JSTracer *trc, JSContext *acx)
JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object"); JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object");
acx->weakRoots.mark(trc); acx->weakRoots.mark(trc);
if (acx->throwing) { if (acx->throwing) {
JS_CALL_VALUE_TRACER(trc, acx->exception, "exception"); CallGCMarkerIfGCThing(trc, acx->exception, "exception");
} else { } else {
/* Avoid keeping GC-ed junk stored in JSContext.exception. */ /* Avoid keeping GC-ed junk stored in JSContext.exception. */
acx->exception = JSVAL_NULL; acx->exception.setNull();
} }
for (js::AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down) for (js::AutoGCRooter *gcr = acx->autoGCRooters; gcr; gcr = gcr->down)
@ -2350,7 +2307,9 @@ js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
JSRuntime *rt = trc->context->runtime; JSRuntime *rt = trc->context->runtime;
JSContext *iter, *acx; JSContext *iter, *acx;
JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_traversal, trc); for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront())
gc_root_traversal(trc, r.front());
JS_DHashTableEnumerate(&rt->gcLocksHash, gc_lock_traversal, trc); JS_DHashTableEnumerate(&rt->gcLocksHash, gc_lock_traversal, trc);
js_TraceAtomState(trc, allAtoms); js_TraceAtomState(trc, allAtoms);
js_TraceRuntimeNumberState(trc); js_TraceRuntimeNumberState(trc);
@ -2406,12 +2365,12 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
ssr->cycle = true; ssr->cycle = true;
return; return;
} }
pobj = JSVAL_TO_OBJECT(pobj->getSlot(slot)); pobj = pobj->getSlot(slot).asObjectOrNull();
} }
pobj = ssr->pobj; pobj = ssr->pobj;
if (slot == JSSLOT_PROTO) { if (slot == JSSLOT_PROTO) {
obj->setProto(pobj); obj->setProto(ToObjPtr(pobj));
} else { } else {
JS_ASSERT(slot == JSSLOT_PARENT); JS_ASSERT(slot == JSSLOT_PARENT);
obj->setParent(pobj); obj->setParent(pobj);
@ -2443,7 +2402,7 @@ FinalizeObject(JSContext *cx, JSObject *obj, unsigned thingKind)
return; return;
/* Finalize obj first, in case it needs map and slots. */ /* Finalize obj first, in case it needs map and slots. */
JSClass *clasp = obj->getClass(); Class *clasp = obj->getClass();
if (clasp->finalize) if (clasp->finalize)
clasp->finalize(cx, obj); clasp->finalize(cx, obj);

View File

@ -50,6 +50,7 @@
#include "jstask.h" #include "jstask.h"
#include "jsversion.h" #include "jsversion.h"
#define JSTRACE_DOUBLE 2
#define JSTRACE_XML 3 #define JSTRACE_XML 3
/* /*
@ -98,10 +99,16 @@ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop); JSStringFinalizeOp newop);
extern JSBool extern JSBool
js_AddRoot(JSContext *cx, void *rp, const char *name); js_AddRoot(JSContext *cx, js::Value *vp, const char *name);
extern JSBool extern JSBool
js_AddRootRT(JSRuntime *rt, void *rp, const char *name); js_AddRootRT(JSRuntime *rt, js::Value *vp, const char *name);
extern JSBool
js_AddGCThingRoot(JSContext *cx, void **rp, const char *name);
extern JSBool
js_AddGCThingRootRT(JSRuntime *rt, void **rp, const char *name);
extern JSBool extern JSBool
js_RemoveRoot(JSRuntime *rt, void *rp); js_RemoveRoot(JSRuntime *rt, void *rp);
@ -109,7 +116,7 @@ js_RemoveRoot(JSRuntime *rt, void *rp);
#ifdef DEBUG #ifdef DEBUG
extern void extern void
js_DumpNamedRoots(JSRuntime *rt, js_DumpNamedRoots(JSRuntime *rt,
void (*dump)(const char *name, void *rp, void *data), void (*dump)(const char *name, void *rp, JSGCRootType type, void *data),
void *data); void *data);
#endif #endif
@ -125,19 +132,12 @@ typedef struct JSPtrTable {
extern JSBool extern JSBool
js_RegisterCloseableIterator(JSContext *cx, JSObject *obj); js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
/*
* Allocate a new double jsval and store the result in *vp. vp must be a root.
* The function does not copy the result into any weak root.
*/
extern JSBool
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
/* /*
* Return a pointer to a new GC-allocated and weakly-rooted jsdouble number, * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
* or null when the allocation fails. * or null when the allocation fails.
*/ */
extern jsdouble * extern jsdouble *
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d); js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d);
#ifdef JS_TRACER #ifdef JS_TRACER
extern JSBool extern JSBool
@ -162,17 +162,9 @@ js_IsAboutToBeFinalized(void *thing);
#if JS_HAS_XML_SUPPORT #if JS_HAS_XML_SUPPORT
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT) # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
#else #else
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING) # define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_DOUBLE)
#endif #endif
/*
* Trace jsval when JSVAL_IS_OBJECT(v) can be a GC thing pointer tagged as a
* jsval. NB: punning an arbitrary JSString * as an untagged (object-tagged)
* jsval no longer works due to static int and unit strings!
*/
extern void
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
extern void extern void
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp); js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
@ -229,9 +221,6 @@ typedef enum JSGCInvocationKind {
extern void extern void
js_GC(JSContext *cx, JSGCInvocationKind gckind); js_GC(JSContext *cx, JSGCInvocationKind gckind);
extern void
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind);
/* /*
* The kind of GC thing with a finalizer. The external strings follow the * The kind of GC thing with a finalizer. The external strings follow the
* ordinary string to simplify js_GetExternalStringGCType. * ordinary string to simplify js_GetExternalStringGCType.
@ -346,14 +335,14 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data);
struct JSWeakRoots { struct JSWeakRoots {
/* Most recently created things by type, members of the GC's root set. */ /* Most recently created things by type, members of the GC's root set. */
void *finalizableNewborns[FINALIZE_LIMIT]; void *finalizableNewborns[FINALIZE_LIMIT];
jsdouble *newbornDouble; jsdouble *newbornDouble;
/* Atom root for the last-looked-up atom on this context. */ /* Atom root for the last-looked-up atom on this context. */
jsval lastAtom; JSAtom *lastAtom;
/* Root for the result of the most recent js_InternalInvoke call. */ /* Root for the result of the most recent js_InternalInvoke call. */
jsval lastInternalResult; void *lastInternalResult;
void mark(JSTracer *trc); void mark(JSTracer *trc);
}; };
@ -453,29 +442,87 @@ js_MarkTraps(JSTracer *trc);
namespace js { namespace js {
void
CallGCMarker(JSTracer *trc, void *thing, uint32 kind);
static inline void
CallGCMarkerForGCThing(JSTracer *trc, const js::Value &v)
{
CallGCMarker(trc, v.asGCThing(), v.traceKind());
}
void
CallGCMarkerForGCThing(JSTracer *trc, void *thing);
static inline void
CallGCMarkerForGCThing(JSTracer *trc, void *thing, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
CallGCMarkerForGCThing(trc, thing);
}
static inline void
CallGCMarkerIfGCThing(JSTracer *trc, const js::Value &v)
{
if (v.isGCThing())
CallGCMarkerForGCThing(trc, v);
}
static inline void
CallGCMarkerIfGCThing(JSTracer *trc, const js::Value &v, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
if (v.isGCThing())
CallGCMarkerForGCThing(trc, v);
}
static inline void
CallGCMarkerIfGCThing(JSTracer *trc, jsid id)
{
if (JSID_IS_GCTHING(id))
CallGCMarker(trc, JSID_TO_GCTHING(id), JSID_TRACE_KIND(id));
}
static inline void
CallGCMarkerIfGCThing(JSTracer *trc, jsid id, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
if (JSID_IS_GCTHING(id))
CallGCMarker(trc, JSID_TO_GCTHING(id), JSID_TRACE_KIND(id));
}
void void
TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len); TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len);
inline void inline void
TraceValues(JSTracer *trc, jsval *beg, jsval *end, const char *name) TraceValues(JSTracer *trc, Value *beg, Value *end, const char *name)
{ {
for (jsval *vp = beg; vp < end; ++vp) { for (Value *vp = beg; vp < end; ++vp) {
jsval v = *vp; if (vp->isGCThing()) {
if (JSVAL_IS_TRACEABLE(v)) {
JS_SET_TRACING_INDEX(trc, name, vp - beg); JS_SET_TRACING_INDEX(trc, name, vp - beg);
js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); CallGCMarkerForGCThing(trc, *vp);
} }
} }
} }
inline void inline void
TraceValues(JSTracer *trc, size_t len, jsval *vec, const char *name) TraceValues(JSTracer *trc, size_t len, Value *vec, const char *name)
{ {
for (jsval *vp = vec, *end = vp + len; vp < end; vp++) { for (Value *vp = vec, *end = vp + len; vp < end; vp++) {
jsval v = *vp; if (vp->isGCThing()) {
if (JSVAL_IS_TRACEABLE(v)) {
JS_SET_TRACING_INDEX(trc, name, vp - vec); JS_SET_TRACING_INDEX(trc, name, vp - vec);
js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v)); CallGCMarkerForGCThing(trc, *vp);
}
}
}
inline void
TraceIds(JSTracer *trc, size_t len, jsid *vec, const char *name)
{
for (jsid *idp = vec, *end = idp + len; idp < end; idp++) {
if (JSID_IS_GCTHING(*idp)) {
JS_SET_TRACING_INDEX(trc, name, idp - vec);
CallGCMarker(trc, JSID_TO_GCTHING(*idp), JSID_TRACE_KIND(*idp));
} }
} }
} }

View File

@ -149,7 +149,7 @@ class HashTable : AllocPolicy
return cur == end; return cur == end;
} }
const T &front() const { T &front() const {
JS_ASSERT(!empty()); JS_ASSERT(!empty());
return cur->t; return cur->t;
} }
@ -313,6 +313,8 @@ class HashTable : AllocPolicy
return true; return true;
} }
bool initialized() const { return table; }
~HashTable() ~HashTable()
{ {
if (table) if (table)
@ -721,6 +723,7 @@ class HashMap
*/ */
HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {} HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {}
bool init(uint32 cap = 0) { return impl.init(cap); } bool init(uint32 cap = 0) { return impl.init(cap); }
bool initialized() const { return impl.initialized(); }
/* /*
* Return whether the given lookup value is present in the map. E.g.: * Return whether the given lookup value is present in the map. E.g.:
@ -868,6 +871,7 @@ class HashSet
*/ */
HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {} HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {}
bool init(uint32 cap = 0) { return impl.init(cap); } bool init(uint32 cap = 0) { return impl.init(cap); }
bool initialized() const { return impl.initialized(); }
/* /*
* Return whether the given lookup value is present in the map. E.g.: * Return whether the given lookup value is present in the map. E.g.:

File diff suppressed because it is too large Load Diff

View File

@ -49,11 +49,9 @@
#include "jsopcode.h" #include "jsopcode.h"
#include "jsscript.h" #include "jsscript.h"
JS_BEGIN_EXTERN_C
typedef struct JSFrameRegs { typedef struct JSFrameRegs {
jsbytecode *pc; /* program counter */ jsbytecode *pc; /* program counter */
jsval *sp; /* stack pointer */ js::Value *sp; /* stack pointer */
} JSFrameRegs; } JSFrameRegs;
/* JS stack frame flags. */ /* JS stack frame flags. */
@ -82,16 +80,17 @@ typedef struct JSFrameRegs {
*/ */
struct JSStackFrame struct JSStackFrame
{ {
/* N.B. alignment (TODO: remove these members) */
js::Value thisv; /* "this" pointer if in method */
js::Value rval; /* function return value */
jsbytecode *imacpc; /* null or interpreter macro call pc */ jsbytecode *imacpc; /* null or interpreter macro call pc */
JSObject *callobj; /* lazily created Call object */ JSObject *callobj; /* lazily created Call object */
jsval argsobj; /* lazily created arguments object, must be JSObject *argsobj; /* lazily created arguments object */
JSVAL_OBJECT */
JSScript *script; /* script being interpreted */ JSScript *script; /* script being interpreted */
JSFunction *fun; /* function being called or null */ JSFunction *fun; /* function being called or null */
jsval thisv; /* "this" pointer if in method */
uintN argc; /* actual argument count */ uintN argc; /* actual argument count */
jsval *argv; /* base of argument stack slots */ js::Value *argv; /* base of argument stack slots */
jsval rval; /* function return value */
void *annotation; /* used by Java security */ void *annotation; /* used by Java security */
/* Maintained by StackSpace operations */ /* Maintained by StackSpace operations */
@ -138,10 +137,7 @@ struct JSStackFrame
* also used in some other cases --- entering 'with' blocks, for * also used in some other cases --- entering 'with' blocks, for
* example. * example.
*/ */
union { JSObject *scopeChain;
JSObject *scopeChain;
jsval scopeChainVal;
};
JSObject *blockChain; JSObject *blockChain;
uint32 flags; /* frame flags -- see below */ uint32 flags; /* frame flags -- see below */
@ -168,26 +164,25 @@ struct JSStackFrame
/* Get the frame's current bytecode, assuming |this| is in |cx|. */ /* Get the frame's current bytecode, assuming |this| is in |cx|. */
jsbytecode *pc(JSContext *cx) const; jsbytecode *pc(JSContext *cx) const;
jsval *argEnd() const { js::Value *argEnd() const {
return (jsval *)this; return (js::Value *)this;
} }
jsval *slots() const { js::Value *slots() const {
return (jsval *)(this + 1); return (js::Value *)(this + 1);
} }
jsval calleeValue() { js::Value *base() const {
return slots() + script->nfixed;
}
const js::Value &calleeValue() {
JS_ASSERT(argv); JS_ASSERT(argv);
return argv[-2]; return argv[-2];
} }
JSObject *calleeObject() {
JS_ASSERT(argv);
return JSVAL_TO_OBJECT(argv[-2]);
}
JSObject *callee() { JSObject *callee() {
return argv ? JSVAL_TO_OBJECT(argv[-2]) : NULL; return argv ? &argv[-2].asObject() : NULL;
} }
/* /*
@ -200,7 +195,7 @@ struct JSStackFrame
/* Short for: varobj(cx->activeCallStack()). */ /* Short for: varobj(cx->activeCallStack()). */
JSObject *varobj(JSContext *cx) const; JSObject *varobj(JSContext *cx) const;
inline JSObject *getThisObject(JSContext *cx); inline js::ObjPtr getThisObject(JSContext *cx);
bool isGenerator() const { return flags & JSFRAME_GENERATOR; } bool isGenerator() const { return flags & JSFRAME_GENERATOR; }
bool isFloatingGenerator() const { bool isFloatingGenerator() const {
@ -211,16 +206,10 @@ struct JSStackFrame
namespace js { namespace js {
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(jsval) == 0); JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(Value) == 0);
static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(jsval); static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(Value);
} } /* namespace js */
static JS_INLINE jsval *
StackBase(JSStackFrame *fp)
{
return fp->slots() + fp->script->nfixed;
}
static JS_INLINE uintN static JS_INLINE uintN
GlobalVarCount(JSStackFrame *fp) GlobalVarCount(JSStackFrame *fp)
@ -246,10 +235,12 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
* instance of clasp and extract its private slot value to return via *thisvp. * instance of clasp and extract its private slot value to return via *thisvp.
* *
* NB: this function loads and uses *vp before storing *thisvp, so the two may * NB: this function loads and uses *vp before storing *thisvp, so the two may
* alias the same jsval. * alias the same Value.
*/ */
extern JSBool extern JSBool
js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp); js_GetPrimitiveThis(JSContext *cx, js::Value *vp, js::Class *clasp, js::Value *thisvp);
namespace js {
/* /*
* For a call with arguments argv including argv[-1] (nominal |this|) and * For a call with arguments argv including argv[-1] (nominal |this|) and
@ -258,15 +249,43 @@ js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
* objects as, per ECMA-262, they may not be referred to by |this|. argv[-1] * objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
* must not be a JSVAL_VOID. * must not be a JSVAL_VOID.
*/ */
extern JSObject * extern bool
js_ComputeThis(JSContext *cx, jsval *argv); ComputeThisFromArgv(JSContext *cx, js::Value *argv);
extern const uint16 js_PrimitiveTestFlags[]; JS_ALWAYS_INLINE JSObject *
ComputeThisObjectFromVp(JSContext *cx, js::Value *vp)
{
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
return ComputeThisFromArgv(cx, vp + 2) ? &vp->asObject() : NULL;
}
#define PRIMITIVE_THIS_TEST(fun,thisv) \ JS_ALWAYS_INLINE bool
(JS_ASSERT(!JSVAL_IS_VOID(thisv)), \ ComputeThisValueFromVp(JSContext *cx, js::Value *vp, js::Value **thisvpp)
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \ {
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1])) extern bool ComputeThisFromArgv(JSContext *, js::Value *);
if (ComputeThisFromArgv(cx, vp + 2)) {
*thisvpp = vp + 1;
return true;
}
return false;
}
class PrimitiveValue
{
static const unsigned THISP_MASK = 0x7;
static const unsigned THISP_ARRAY_SIZE = 8;
static const unsigned THISP_SHIFT = 8;
JS_STATIC_ASSERT(JSFUN_THISP_PRIMITIVE >> THISP_SHIFT == THISP_MASK);
JS_STATIC_ASSERT(THISP_MASK == THISP_ARRAY_SIZE - 1);
static const Value::MaskType Masks[THISP_ARRAY_SIZE];
public:
static bool test(JSFunction *fun, const Value &v) {
return bool(Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK] & v.mask);
}
};
/* /*
* The js::InvokeArgumentsGuard passed to js_Invoke must come from an * The js::InvokeArgumentsGuard passed to js_Invoke must come from an
@ -276,8 +295,11 @@ extern const uint16 js_PrimitiveTestFlags[];
* and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should * and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
* be initialized actual arguments. * be initialized actual arguments.
*/ */
extern JS_REQUIRES_STACK JS_FRIEND_API(JSBool) extern JS_REQUIRES_STACK bool
js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags); Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
extern JS_REQUIRES_STACK JS_FRIEND_API(bool)
InvokeFriendAPI(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
/* /*
* Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
@ -300,56 +322,79 @@ js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags);
*/ */
#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR) #define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
/* extern bool
* "Internal" calls may come from C or C++ code using a JSContext on which no InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
* JS is running (!cx->fp), so they may need to push a dummy JSStackFrame. uintN argc, const Value *argv, Value *rval);
*/
#define js_InternalCall(cx,obj,fval,argc,argv,rval) \
js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval)
#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \ static JS_ALWAYS_INLINE bool
js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval) InternalCall(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
const Value *argv, Value *rval)
{
return InternalInvoke(cx, obj, fval, 0, argc, argv, rval);
}
extern JSBool static JS_ALWAYS_INLINE bool
js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags, InternalConstruct(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
uintN argc, jsval *argv, jsval *rval); const Value *argv, Value *rval)
{
return InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval);
}
extern JSBool extern bool
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval); JSAccessMode mode, uintN argc, const Value *argv, Value *rval);
extern JS_FORCES_STACK JSBool extern JS_FORCES_STACK bool
js_Execute(JSContext *cx, JSObject *chain, JSScript *script, Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSStackFrame *down, uintN flags, jsval *result); JSStackFrame *down, uintN flags, Value *result);
extern JS_REQUIRES_STACK JSBool extern JS_REQUIRES_STACK bool
js_InvokeConstructor(JSContext *cx, const js::InvokeArgsGuard &args, InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args,
JSBool clampReturn); JSBool clampReturn);
extern JS_REQUIRES_STACK JSBool extern JS_REQUIRES_STACK bool
js_Interpret(JSContext *cx); Interpret(JSContext *cx);
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */ #define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
extern JSBool extern bool
js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
JSObject **objp, JSProperty **propp); JSObject **objp, JSProperty **propp);
extern JSBool extern bool
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval); StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval);
/* === except that NaN is the same as NaN and -0 is not the same as +0. */ /* === except that NaN is the same as NaN and -0 is not the same as +0. */
extern JSBool extern bool
js_SameValue(jsval v1, jsval v2, JSContext *cx); SameValue(JSContext *cx, const Value &v1, const Value &v2);
extern JSBool JSType
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp); TypeOfValue(JSContext *cx, const js::Value &v);
inline bool
InstanceOf(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
{
if (obj && obj->getClass() == clasp)
return true;
extern bool InstanceOfSlow(JSContext *, JSObject *, Class *, Value *);
return InstanceOfSlow(cx, obj, clasp, argv);
}
inline void *
GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
{
if (!InstanceOf(cx, obj, clasp, argv))
return NULL;
return obj->getPrivate();
}
} /* namespace js */
/* /*
* Given an active context, a static scope level, and an upvar cookie, return * Given an active context, a static scope level, and an upvar cookie, return
* the value of the upvar. * the value of the upvar.
*/ */
extern jsval& extern const js::Value &
js_GetUpvar(JSContext *cx, uintN level, uintN cookie); js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
/* /*
@ -378,31 +423,13 @@ js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
#else #else
# define JS_STATIC_INTERPRET # define JS_STATIC_INTERPRET
/*
* ECMA requires "the global object", but in embeddings such as the browser,
* which have multiple top-level objects (windows, frames, etc. in the DOM),
* we prefer fun's parent. An example that causes this code to run:
*
* // in window w1
* function f() { return this }
* function g() { return f }
*
* // in window w2
* var h = w1.g()
* alert(h() == w1)
*
* The alert should display "true".
*/
extern JSObject *
js_ComputeGlobalThis(JSContext *cx, jsval *argv);
extern JS_REQUIRES_STACK JSBool extern JS_REQUIRES_STACK JSBool
js_EnterWith(JSContext *cx, jsint stackIndex); js_EnterWith(JSContext *cx, jsint stackIndex);
extern JS_REQUIRES_STACK void extern JS_REQUIRES_STACK void
js_LeaveWith(JSContext *cx); js_LeaveWith(JSContext *cx);
extern JS_REQUIRES_STACK JSClass * extern JS_REQUIRES_STACK js::Class *
js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth); js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
/* /*
@ -413,7 +440,7 @@ extern JS_REQUIRES_STACK JSBool
js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind); js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
extern JSBool extern JSBool
js_OnUnknownMethod(JSContext *cx, jsval *vp); js_OnUnknownMethod(JSContext *cx, js::Value *vp);
/* /*
* Find the results of incrementing or decrementing *vp. For pre-increments, * Find the results of incrementing or decrementing *vp. For pre-increments,
@ -422,7 +449,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp);
* the result. Both vp and vp2 must be roots. * the result. Both vp and vp2 must be roots.
*/ */
extern JSBool extern JSBool
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2); js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2);
/* /*
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
@ -442,19 +469,16 @@ js_MeterSlotOpcode(JSOp op, uint32 slot);
#endif /* JS_LONE_INTERPRET */ #endif /* JS_LONE_INTERPRET */
JS_END_EXTERN_C inline js::ObjPtr
inline JSObject *
JSStackFrame::getThisObject(JSContext *cx) JSStackFrame::getThisObject(JSContext *cx)
{ {
if (flags & JSFRAME_COMPUTED_THIS) if (flags & JSFRAME_COMPUTED_THIS)
return JSVAL_TO_OBJECT(thisv); /* JSVAL_COMPUTED_THIS invariant */ return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */
JSObject* obj = js_ComputeThis(cx, argv); if (!js::ComputeThisFromArgv(cx, argv))
if (!obj) return js::NullObjPtr();
return NULL; thisv.copy(argv[-1]);
thisv = OBJECT_TO_JSVAL(obj);
flags |= JSFRAME_COMPUTED_THIS; flags |= JSFRAME_COMPUTED_THIS;
return obj; return thisv.asObjPtr();
} }
#endif /* jsinterp_h___ */ #endif /* jsinterp_h___ */

View File

@ -38,6 +38,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/* /*
* JavaScript iterators. * JavaScript iterators.
*/ */

View File

@ -71,17 +71,17 @@ const uint32 JSSLOT_ITER_FLAGS = JSSLOT_PRIVATE + 1;
* iterator will never be exposed to scripts. * iterator will never be exposed to scripts.
*/ */
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp); js_ValueToIterator(JSContext *cx, uintN flags, js::Value *vp);
extern JS_FRIEND_API(JSBool) JS_FASTCALL extern JS_FRIEND_API(JSBool) JS_FASTCALL
js_CloseIterator(JSContext *cx, jsval v); js_CloseIterator(JSContext *cx, const js::Value &v);
/* /*
* Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to * Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to
* JSVAL_HOLE. Otherwise set it to the result of the next call. * JSVAL_HOLE. Otherwise set it to the result of the next call.
*/ */
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval); js_CallIteratorNext(JSContext *cx, JSObject *iterobj, js::Value *rval);
/* /*
* Close iterobj, whose class must be js_IteratorClass. * Close iterobj, whose class must be js_IteratorClass.
@ -160,15 +160,14 @@ js_LiveFrameIfGenerator(JSStackFrame *fp)
} }
#endif #endif
extern JS_FRIEND_API(JSClass) js_GeneratorClass; extern JS_FRIEND_API(js::Class) js_GeneratorClass;
extern JSClass js_IteratorClass; extern js::Class js_IteratorClass;
extern JSClass js_StopIterationClass; extern js::Class js_StopIterationClass;
static inline bool static inline bool
js_ValueIsStopIteration(jsval v) js_ValueIsStopIteration(const js::Value &v)
{ {
return !JSVAL_IS_PRIMITIVE(v) && return v.isObject() && v.asObject().getClass() == &js_StopIterationClass;
JSVAL_TO_OBJECT(v)->getClass() == &js_StopIterationClass;
} }
extern JSObject * extern JSObject *

View File

@ -43,9 +43,7 @@
* JS math functions. * JS math functions.
*/ */
JS_BEGIN_EXTERN_C extern js::Class js_MathClass;
extern JSClass js_MathClass;
extern JSObject * extern JSObject *
js_InitMathClass(JSContext *cx, JSObject *obj); js_InitMathClass(JSContext *cx, JSObject *obj);
@ -68,6 +66,4 @@ js_math_min(JSContext *cx, uintN argc, jsval *vp);
extern JSBool extern JSBool
js_math_round(JSContext *cx, uintN argc, jsval *vp); js_math_round(JSContext *cx, uintN argc, jsval *vp);
JS_END_EXTERN_C
#endif /* jsmath_h___ */ #endif /* jsmath_h___ */

View File

@ -800,29 +800,6 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
return proto; return proto;
} }
JSBool
js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
{
jsint i;
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
*vp = INT_TO_JSVAL(i);
return JS_TRUE;
}
return js_NewDoubleInRootedValue(cx, d, vp);
}
JSBool
js_NewWeaklyRootedNumber(JSContext *cx, jsdouble d, jsval *rval)
{
jsint i;
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
*rval = INT_TO_JSVAL(i);
return JS_TRUE;
}
return JS_NewDoubleValue(cx, d, rval);
}
/* /*
* Convert a number to C string. The buf must be large enough to accommodate * Convert a number to C string. The buf must be large enough to accommodate
* the result, including '-' and '\0', if base == 10 or d is an integer that * the result, including '-' and '\0', if base == 10 or d is an integer that
@ -936,8 +913,8 @@ js_NumberValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
namespace js { namespace js {
jsval bool
ValueToNumberSlow(JSContext *cx, jsval v, double *out) ValueToNumberSlow(JSContext *cx, Value *vp, double *out)
{ {
JS_ASSERT(!JSVAL_IS_INT(v) && !JSVAL_IS_DOUBLE(v)); JS_ASSERT(!JSVAL_IS_INT(v) && !JSVAL_IS_DOUBLE(v));
goto skip_int_double; goto skip_int_double;
@ -999,24 +976,7 @@ ValueToNumberSlow(JSContext *cx, jsval v, double *out)
} }
bool bool
ValueToNumberValueSlow(JSContext *cx, jsval *vp, double *out) ValueToECMAInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
{
jsval v = *vp = ValueToNumberSlow(cx, *vp, out);
return !JSVAL_IS_NULL(v) &&
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, *out, vp));
}
bool
ValueToNumberValueSlow(JSContext *cx, jsval *vp)
{
double d;
jsval v = *vp = ValueToNumberSlow(cx, *vp, &d);
return !JSVAL_IS_NULL(v) &&
(v != JSVAL_TRUE || js_NewNumberInRootedValue(cx, d, vp));
}
bool
ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
{ {
JS_ASSERT(!JSVAL_IS_INT(v)); JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d; jsdouble d;
@ -1031,7 +991,7 @@ ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
} }
bool bool
ValueToECMAUint32Slow(JSContext *cx, jsval v, uint32_t *out) ValueToECMAUint32Slow(JSContext *cx, js::Value *vp, uint32_t *out)
{ {
JS_ASSERT(!JSVAL_IS_INT(v)); JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d; jsdouble d;
@ -1079,7 +1039,7 @@ js_DoubleToECMAUint32(jsdouble d)
namespace js { namespace js {
bool bool
ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out) ValueToInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
{ {
JS_ASSERT(!JSVAL_IS_INT(v)); JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d; jsdouble d;
@ -1105,7 +1065,7 @@ ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
} }
bool bool
ValueToUint16Slow(JSContext *cx, jsval v, uint16_t *out) ValueToUint16Slow(JSContext *cx, js::Value *vp, uint16_t *out)
{ {
JS_ASSERT(!JSVAL_IS_INT(v)); JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d; jsdouble d;

View File

@ -132,15 +132,15 @@ JSDOUBLE_IS_NEGZERO(jsdouble d)
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 #define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff #define JSDOUBLE_HI32_MANTMASK 0x000fffff
static inline int static inline bool
JSDOUBLE_IS_INT(jsdouble d, jsint& i) JSDOUBLE_IS_INT32(jsdouble d, int32_t& i)
{ {
if (JSDOUBLE_IS_NEGZERO(d)) if (JSDOUBLE_IS_NEGZERO(d))
return false; return false;
return d == (i = jsint(d)); return d == (i = int32_t(d));
} }
static inline int static inline bool
JSDOUBLE_IS_NEG(jsdouble d) JSDOUBLE_IS_NEG(jsdouble d)
{ {
#ifdef WIN32 #ifdef WIN32
@ -184,9 +184,9 @@ extern void
js_FinishRuntimeNumberState(JSContext *cx); js_FinishRuntimeNumberState(JSContext *cx);
/* Initialize the Number class, returning its prototype object. */ /* Initialize the Number class, returning its prototype object. */
extern JSClass js_NumberClass; extern js::Class js_NumberClass;
extern "C" JSObject * extern JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj); js_InitNumberClass(JSContext *cx, JSObject *obj);
/* /*
@ -199,19 +199,6 @@ extern const char js_isFinite_str[];
extern const char js_parseFloat_str[]; extern const char js_parseFloat_str[];
extern const char js_parseInt_str[]; extern const char js_parseInt_str[];
/*
* vp must be a root.
*/
extern JSBool
js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
/*
* Create a weakly rooted integer or double jsval as appropriate for the given
* jsdouble.
*/
extern JSBool
js_NewWeaklyRootedNumber(JSContext *cx, jsdouble d, jsval *vp);
/* Convert a number to a GC'ed string. */ /* Convert a number to a GC'ed string. */
extern JSString * JS_FASTCALL extern JSString * JS_FASTCALL
js_NumberToString(JSContext *cx, jsdouble d); js_NumberToString(JSContext *cx, jsdouble d);
@ -227,106 +214,77 @@ namespace js {
/* /*
* Convert a value to a number, returning the converted value in 'out' if the * Convert a value to a number, returning the converted value in 'out' if the
* conversion succeeds. v most be a copy of a rooted jsval. * conversion succeeds. As a side effect, *vp will be mutated to match *out.
*/ */
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToNumber(JSContext *cx, jsval v, double *out) ValueToNumber(JSContext *cx, js::Value *vp, double *out)
{ {
if (JSVAL_IS_INT(v)) { if (vp->isInt32()) {
*out = JSVAL_TO_INT(v); *out = vp->asInt32();
return true; return true;
} }
if (JSVAL_IS_DOUBLE(v)) { if (vp->isDouble()) {
*out = *JSVAL_TO_DOUBLE(v); *out = vp->asDouble();
return true; return true;
} }
extern jsval ValueToNumberSlow(JSContext *, jsval, double *); extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
return !JSVAL_IS_NULL(ValueToNumberSlow(cx, v, out)); return ValueToNumberSlow(cx, vp, out);
} }
/* /* Convert a value to a number, replacing 'vp' with the converted value. */
* Convert a value to a number, replacing 'vp' with the converted value and
* returning the value as a double in 'out'. vp must point to a rooted jsval.
*
* N.B. this function will allocate a new double if needed; callers needing
* only a double, not a value, should use ValueToNumber instead.
*/
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToNumberValue(JSContext *cx, jsval *vp, double *out) ValueToNumber(JSContext *cx, js::Value *vp)
{ {
jsval v = *vp; if (vp->isInt32())
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
return true; return true;
} if (vp->isDouble())
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
return true; return true;
} double _;
extern bool ValueToNumberValueSlow(JSContext *, jsval *, double *); extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
return ValueToNumberValueSlow(cx, vp, out); return ValueToNumberSlow(cx, vp, &_);
}
/*
* Convert a value to a number, replacing 'vp' with the converted value. vp
* must point to a rooted jsval.
*
* N.B. this function will allocate a new double if needed; callers needing
* only a double, not a value, should use ValueToNumber instead.
*/
JS_ALWAYS_INLINE bool
ValueToNumberValue(JSContext *cx, jsval *vp)
{
jsval v = *vp;
if (JSVAL_IS_INT(v))
return true;
if (JSVAL_IS_DOUBLE(v))
return true;
extern bool ValueToNumberValueSlow(JSContext *, jsval *);
return ValueToNumberValueSlow(cx, vp);
} }
/* /*
* Convert a value to an int32 or uint32, according to the ECMA rules for * Convert a value to an int32 or uint32, according to the ECMA rules for
* ToInt32 and ToUint32. Return converted value on success, !ok on failure. v * ToInt32 and ToUint32. Return converted value in *out on success, !ok on
* must be a copy of a rooted jsval. * failure. As a side effect, *vp will be mutated to match *out.
*/ */
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToECMAInt32(JSContext *cx, jsval v, int32_t *out) ValueToECMAInt32(JSContext *cx, js::Value *vp, int32_t *out)
{ {
if (JSVAL_IS_INT(v)) { if (vp->isInt32()) {
*out = JSVAL_TO_INT(v); *out = vp->asInt32();
return true; return true;
} }
extern bool ValueToECMAInt32Slow(JSContext *, jsval, int32_t *); extern bool ValueToECMAInt32Slow(JSContext *, js::Value *, int32_t *);
return ValueToECMAInt32Slow(cx, v, out); return ValueToECMAInt32Slow(cx, vp, out);
} }
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *out) ValueToECMAUint32(JSContext *cx, js::Value *vp, uint32_t *out)
{ {
if (JSVAL_IS_INT(v)) { if (vp->isInt32()) {
*out = (uint32_t)JSVAL_TO_INT(v); *out = (uint32_t)vp->asInt32();
return true; return true;
} }
extern bool ValueToECMAUint32Slow(JSContext *, jsval, uint32_t *); extern bool ValueToECMAUint32Slow(JSContext *, js::Value *, uint32_t *);
return ValueToECMAUint32Slow(cx, v, out); return ValueToECMAUint32Slow(cx, vp, out);
} }
/* /*
* Convert a value to a number, then to an int32 if it fits by rounding to * Convert a value to a number, then to an int32 if it fits by rounding to
* nearest. Return converted value on success, !ok on failure. v must be a copy * nearest. Return converted value in *out on success, !ok on failure. As a
* of a rooted jsval. * side effect, *vp will be mutated to match *out.
*/ */
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToInt32(JSContext *cx, jsval v, int32_t *out) ValueToInt32(JSContext *cx, js::Value *vp, int32_t *out)
{ {
if (JSVAL_IS_INT(v)) { if (vp->isInt32()) {
*out = JSVAL_TO_INT(v); *out = vp->asInt32();
return true; return true;
} }
extern bool ValueToInt32Slow(JSContext *, jsval, int32_t *); extern bool ValueToInt32Slow(JSContext *, js::Value *, int32_t *);
return ValueToInt32Slow(cx, v, out); return ValueToInt32Slow(cx, vp, out);
} }
/* /*
@ -335,14 +293,14 @@ ValueToInt32(JSContext *cx, jsval v, int32_t *out)
* copy of a rooted jsval. * copy of a rooted jsval.
*/ */
JS_ALWAYS_INLINE bool JS_ALWAYS_INLINE bool
ValueToUint16(JSContext *cx, jsval v, uint16_t *out) ValueToUint16(JSContext *cx, js::Value *vp, uint16_t *out)
{ {
if (JSVAL_IS_INT(v)) { if (vp->isInt32()) {
*out = (uint16_t)JSVAL_TO_INT(v); *out = (uint16_t)vp->asInt32();
return true; return true;
} }
extern bool ValueToUint16Slow(JSContext *, jsval, uint16_t *); extern bool ValueToUint16Slow(JSContext *, js::Value *, uint16_t *);
return ValueToUint16Slow(cx, v, out); return ValueToUint16Slow(cx, vp, out);
} }
} /* namespace js */ } /* namespace js */
@ -508,6 +466,25 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
namespace js { namespace js {
static JS_ALWAYS_INLINE bool
ValueFitsInInt32(const Value &v, int32_t *pi)
{
if (v.isInt32()) {
*pi = v.asInt32();
return true;
}
return v.isDouble() && JSDOUBLE_IS_INT32(v.asDouble(), *pi);
}
static JS_ALWAYS_INLINE void
Uint32ToValue(uint32_t u, Value *vp)
{
if (JS_UNLIKELY(u > INT32_MAX))
vp->setDouble(u);
else
vp->setInt32((int32_t)u);
}
template<typename T> struct NumberTraits { }; template<typename T> struct NumberTraits { };
template<> struct NumberTraits<int32> { template<> struct NumberTraits<int32> {
static JS_ALWAYS_INLINE int32 NaN() { return 0; } static JS_ALWAYS_INLINE int32 NaN() { return 0; }

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,38 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "jsprvtd.h" #include "jsprvtd.h"
namespace js { class AutoDescriptorArray; } namespace js {
class AutoDescriptorArray;
static inline PropertyOp
CastAsPropertyOp(JSObject *object)
{
return JS_DATA_TO_FUNC_PTR(PropertyOp, object);
}
inline JSObject *
CastAsObject(PropertyOp op)
{
return JS_FUNC_TO_DATA_PTR(JSObject *, op);
}
extern JSBool
PropertyStub(JSContext *cx, JSObject *obj, jsid id, Value *vp);
extern JSBool
EnumerateStub(JSContext *cx, JSObject *obj);
extern JSBool
ResolveStub(JSContext *cx, JSObject *obj, jsid id);
extern JSBool
ConvertStub(JSContext *cx, JSObject *obj, JSType type, Value *vp);
extern void
FinalizeStub(JSContext *cx, JSObject *obj);
} /* namespace js */
/* /*
* A representation of ECMA-262 ed. 5's internal property descriptor data * A representation of ECMA-262 ed. 5's internal property descriptor data
@ -66,7 +97,7 @@ struct PropertyDescriptor {
public: public:
/* 8.10.5 ToPropertyDescriptor(Obj) */ /* 8.10.5 ToPropertyDescriptor(Obj) */
bool initialize(JSContext* cx, jsid id, jsval v); bool initialize(JSContext* cx, jsid id, const js::Value &v);
/* 8.10.1 IsAccessorDescriptor(desc) */ /* 8.10.1 IsAccessorDescriptor(desc) */
bool isAccessorDescriptor() const { bool isAccessorDescriptor() const {
@ -96,31 +127,31 @@ struct PropertyDescriptor {
} }
JSObject* getterObject() const { JSObject* getterObject() const {
return get != JSVAL_VOID ? JSVAL_TO_OBJECT(get) : NULL; return get.isUndefined() ? NULL : &get.asObject();
} }
JSObject* setterObject() const { JSObject* setterObject() const {
return set != JSVAL_VOID ? JSVAL_TO_OBJECT(set) : NULL; return set.isUndefined() ? NULL : &set.asObject();
} }
jsval getterValue() const { const js::Value &getterValue() const {
return get; return get;
} }
jsval setterValue() const { const js::Value &setterValue() const {
return set; return set;
} }
JSPropertyOp getter() const { js::PropertyOp getter() const {
return js_CastAsPropertyOp(getterObject()); return js::CastAsPropertyOp(getterObject());
} }
JSPropertyOp setter() const { js::PropertyOp setter() const {
return js_CastAsPropertyOp(setterObject()); return js::CastAsPropertyOp(setterObject());
} }
static void traceDescriptorArray(JSTracer* trc, JSObject* obj); static void traceDescriptorArray(JSTracer* trc, JSObject* obj);
static void finalizeDescriptorArray(JSContext* cx, JSObject* obj); static void finalizeDescriptorArray(JSContext* cx, JSObject* obj);
jsid id; jsid id;
jsval value, get, set; js::Value value, get, set;
/* Property descriptor boolean fields. */ /* Property descriptor boolean fields. */
uint8 attrs; uint8 attrs;
@ -134,8 +165,6 @@ struct PropertyDescriptor {
bool hasConfigurable : 1; bool hasConfigurable : 1;
}; };
JS_BEGIN_EXTERN_C
/* For detailed comments on these function pointer types, see jsprvtd.h. */ /* For detailed comments on these function pointer types, see jsprvtd.h. */
struct JSObjectOps { struct JSObjectOps {
/* /*
@ -147,24 +176,24 @@ struct JSObjectOps {
/* Mandatory non-null function pointer members. */ /* Mandatory non-null function pointer members. */
JSLookupPropOp lookupProperty; JSLookupPropOp lookupProperty;
JSDefinePropOp defineProperty; js::DefinePropOp defineProperty;
JSPropertyIdOp getProperty; js::PropertyIdOp getProperty;
JSPropertyIdOp setProperty; js::PropertyIdOp setProperty;
JSAttributesOp getAttributes; JSAttributesOp getAttributes;
JSAttributesOp setAttributes; JSAttributesOp setAttributes;
JSPropertyIdOp deleteProperty; js::PropertyIdOp deleteProperty;
JSConvertOp defaultValue; js::ConvertOp defaultValue;
JSNewEnumerateOp enumerate; js::NewEnumerateOp enumerate;
JSCheckAccessIdOp checkAccess; js::CheckAccessIdOp checkAccess;
JSTypeOfOp typeOf; JSTypeOfOp typeOf;
JSTraceOp trace; JSTraceOp trace;
/* Optionally non-null members start here. */ /* Optionally non-null members start here. */
JSObjectOp thisObject; JSObjectOp thisObject;
JSPropertyRefOp dropProperty; JSPropertyRefOp dropProperty;
JSNative call; js::Native call;
JSNative construct; js::Native construct;
JSHasInstanceOp hasInstance; js::HasInstanceOp hasInstance;
JSFinalizeOp clear; JSFinalizeOp clear;
bool inline isNative() const; bool inline isNative() const;
@ -204,7 +233,7 @@ const uint32 JSSLOT_PARENT = 1;
/* /*
* The first available slot to store generic value. For JSCLASS_HAS_PRIVATE * The first available slot to store generic value. For JSCLASS_HAS_PRIVATE
* classes the slot stores a pointer to private data reinterpreted as jsval. * classes the slot stores a pointer to private data stuffed in a Value.
* Such pointer is stored as is without an overhead of PRIVATE_TO_JSVAL * Such pointer is stored as is without an overhead of PRIVATE_TO_JSVAL
* tagging and should be accessed using the (get|set)Private methods of * tagging and should be accessed using the (get|set)Private methods of
* JSObject. * JSObject.
@ -213,18 +242,11 @@ const uint32 JSSLOT_PRIVATE = 2;
const uint32 JSSLOT_PRIMITIVE_THIS = JSSLOT_PRIVATE; const uint32 JSSLOT_PRIMITIVE_THIS = JSSLOT_PRIVATE;
const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
/* /*
* JSObject struct, with members sized to fit in 32 bytes on 32-bit targets, * JSObject struct, with members sized to fit in 32 bytes on 32-bit targets,
* 64 bytes on 64-bit systems. The JSFunction struct is an extension of this * 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
* struct allocated from a larger GC size-class. * struct allocated from a larger GC size-class.
* *
* The classword member stores the JSClass pointer for this object, with the
* least two bits encoding whether this object is a "delegate" or a "system"
* object. We do *not* synchronize updates of classword -- API clients must
* take care.
*
* An object is a delegate if it is on another object's prototype (linked by * An object is a delegate if it is on another object's prototype (linked by
* JSSLOT_PROTO) or scope (JSSLOT_PARENT) chain, and therefore the delegate * JSSLOT_PROTO) or scope (JSSLOT_PARENT) chain, and therefore the delegate
* might be asked implicitly to get or set a property on behalf of another * might be asked implicitly to get or set a property on behalf of another
@ -240,11 +262,11 @@ const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
* to be complementary to this bit, but it is up to the API client to implement * to be complementary to this bit, but it is up to the API client to implement
* any such association. * any such association.
* *
* Both these classword tag bits are initially zero; they may be set or queried * Both these flags are initially zero; they may be set or queried using the
* using the (is|set)(Delegate|System) inline methods. * (is|set)(Delegate|System) inline methods.
* *
* The dslots member is null or a pointer into a dynamically allocated vector * The dslots member is null or a pointer into a dynamically allocated vector
* of jsvals for reserved and dynamic slots. If dslots is not null, dslots[-1] * of Values for reserved and dynamic slots. If dslots is not null, dslots[-1]
* records the number of available slots. * records the number of available slots.
*/ */
struct JSObject { struct JSObject {
@ -255,29 +277,32 @@ struct JSObject {
friend class js::TraceRecorder; friend class js::TraceRecorder;
JSObjectMap *map; /* property map, see jsscope.h */ JSObjectMap *map; /* property map, see jsscope.h */
jsuword classword; /* JSClass ptr | bits, see above */ private:
jsval fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */ js::Class *clasp; /* class pointer */
jsval *dslots; /* dynamically allocated slots */ jsuword flags; /* see above */
public:
js::Value *dslots; /* dynamically allocated slots */
js::Value fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
bool isNative() const { return map->ops->isNative(); } bool isNative() const { return map->ops->isNative(); }
JSClass *getClass() const { js::Class *getClass() const {
return (JSClass *) (classword & ~JSSLOT_CLASS_MASK_BITS); return clasp;
} }
bool hasClass(const JSClass *clasp) const { bool hasClass(const js::Class *c) const {
return clasp == getClass(); return c == clasp;
} }
inline JSScope *scope() const; inline JSScope *scope() const;
inline uint32 shape() const; inline uint32 shape() const;
bool isDelegate() const { bool isDelegate() const {
return (classword & jsuword(1)) != jsuword(0); return (flags & jsuword(1)) != jsuword(0);
} }
void setDelegate() { void setDelegate() {
classword |= jsuword(1); flags |= jsuword(1);
} }
static void setDelegateNullSafe(JSObject *obj) { static void setDelegateNullSafe(JSObject *obj) {
@ -286,42 +311,46 @@ struct JSObject {
} }
bool isSystem() const { bool isSystem() const {
return (classword & jsuword(2)) != jsuword(0); return (flags & jsuword(2)) != jsuword(0);
} }
void setSystem() { void setSystem() {
classword |= jsuword(2); flags |= jsuword(2);
}
uint32 dslotLength() const {
return dslots[-1].asPrivateUint32();
} }
uint32 numSlots(void) { uint32 numSlots(void) {
return dslots ? (uint32)dslots[-1] : (uint32)JS_INITIAL_NSLOTS; return dslots ? dslotLength() : (uint32)JS_INITIAL_NSLOTS;
} }
jsval& getSlotRef(uintN slot) { js::Value& getSlotRef(uintN slot) {
return (slot < JS_INITIAL_NSLOTS) return (slot < JS_INITIAL_NSLOTS)
? fslots[slot] ? fslots[slot]
: (JS_ASSERT(slot < (uint32)dslots[-1]), : (JS_ASSERT(slot < dslotLength()),
dslots[slot - JS_INITIAL_NSLOTS]); dslots[slot - JS_INITIAL_NSLOTS]);
} }
jsval getSlot(uintN slot) const { const js::Value &getSlot(uintN slot) const {
return (slot < JS_INITIAL_NSLOTS) return (slot < JS_INITIAL_NSLOTS)
? fslots[slot] ? fslots[slot]
: (JS_ASSERT(slot < (uint32)dslots[-1]), : (JS_ASSERT(slot < dslotLength()),
dslots[slot - JS_INITIAL_NSLOTS]); dslots[slot - JS_INITIAL_NSLOTS]);
} }
void setSlot(uintN slot, jsval value) { void setSlot(uintN slot, const js::Value &value) {
if (slot < JS_INITIAL_NSLOTS) { if (slot < JS_INITIAL_NSLOTS) {
fslots[slot] = value; fslots[slot].copy(value);
} else { } else {
JS_ASSERT(slot < (uint32)dslots[-1]); JS_ASSERT(slot < dslotLength());
dslots[slot - JS_INITIAL_NSLOTS] = value; dslots[slot - JS_INITIAL_NSLOTS].copy(value);
} }
} }
inline jsval lockedGetSlot(uintN slot) const; inline const js::Value &lockedGetSlot(uintN slot) const;
inline void lockedSetSlot(uintN slot, jsval value); inline void lockedSetSlot(uintN slot, const js::Value &value);
/* /*
* These ones are for multi-threaded ("MT") objects. Use getSlot(), * These ones are for multi-threaded ("MT") objects. Use getSlot(),
@ -329,33 +358,41 @@ struct JSObject {
* one thread can access obj, or when accessing read-only slots within * one thread can access obj, or when accessing read-only slots within
* JS_INITIAL_NSLOTS. * JS_INITIAL_NSLOTS.
*/ */
inline jsval getSlotMT(JSContext *cx, uintN slot); inline const js::Value &getSlotMT(JSContext *cx, uintN slot);
inline void setSlotMT(JSContext *cx, uintN slot, jsval value); inline void setSlotMT(JSContext *cx, uintN slot, const js::Value &value);
JSObject *getProto() const { JSObject *getProto() const {
return JSVAL_TO_OBJECT(fslots[JSSLOT_PROTO]); return fslots[JSSLOT_PROTO].asObjectOrNull();
}
const js::Value &getProtoValue() const {
return fslots[JSSLOT_PROTO];
} }
void clearProto() { void clearProto() {
fslots[JSSLOT_PROTO] = JSVAL_NULL; fslots[JSSLOT_PROTO].setNull();
} }
void setProto(JSObject *newProto) { void setProto(js::ObjPtr newProto) {
setDelegateNullSafe(newProto); setDelegateNullSafe(newProto);
fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(newProto); fslots[JSSLOT_PROTO].copy(newProto);
} }
JSObject *getParent() const { JSObject *getParent() const {
return JSVAL_TO_OBJECT(fslots[JSSLOT_PARENT]); return fslots[JSSLOT_PARENT].asObjectOrNull();
}
const js::Value &getParentValue() const {
return fslots[JSSLOT_PARENT];
} }
void clearParent() { void clearParent() {
fslots[JSSLOT_PARENT] = JSVAL_NULL; fslots[JSSLOT_PARENT].setNull();
} }
void setParent(JSObject *newParent) { void setParent(JSObject *newParent) {
setDelegateNullSafe(newParent); setDelegateNullSafe(newParent);
fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(newParent); fslots[JSSLOT_PARENT].setNonFunObjOrNull(newParent);
} }
void traceProtoAndParent(JSTracer *trc) const { void traceProtoAndParent(JSTracer *trc) const {
@ -372,22 +409,21 @@ struct JSObject {
void *getPrivate() const { void *getPrivate() const {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
jsval v = fslots[JSSLOT_PRIVATE]; void *priv = fslots[JSSLOT_PRIVATE].asPrivateVoidPtr();
JS_ASSERT((v & jsval(1)) == jsval(0)); JS_ASSERT((size_t(priv) & 1) == 0);
return reinterpret_cast<void *>(v); return priv;
} }
void setPrivate(void *data) { void setPrivate(void *data) {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE); JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
jsval v = reinterpret_cast<jsval>(data); JS_ASSERT((size_t(data) & 1) == 0);
JS_ASSERT((v & jsval(1)) == jsval(0)); fslots[JSSLOT_PRIVATE].setPrivateVoidPtr(data);
fslots[JSSLOT_PRIVATE] = v;
} }
static jsval defaultPrivate(JSClass *clasp) { static const js::Value &defaultPrivate(js::Class *clasp) {
return (clasp->flags & JSCLASS_HAS_PRIVATE) return (clasp->flags & JSCLASS_HAS_PRIVATE)
? JSVAL_NULL ? js::sNullValue
: JSVAL_VOID; : js::sUndefinedValue;
} }
/* /*
@ -413,7 +449,6 @@ struct JSObject {
inline void voidDenseArrayCount(); inline void voidDenseArrayCount();
inline void incArrayCountBy(uint32 posDelta); inline void incArrayCountBy(uint32 posDelta);
inline void decArrayCountBy(uint32 negDelta); inline void decArrayCountBy(uint32 negDelta);
inline void voidArrayUnused();
/* /*
* Back to generic stuff. * Back to generic stuff.
@ -422,22 +457,22 @@ struct JSObject {
bool isCallable(); bool isCallable();
/* The map field is not initialized here and should be set separately. */ /* The map field is not initialized here and should be set separately. */
void init(JSClass *clasp, JSObject *proto, JSObject *parent, void init(js::Class *c, js::ObjPtr proto, JSObject *parent,
jsval privateSlotValue) { const js::Value &privateSlotValue) {
JS_ASSERT(((jsuword) clasp & 3) == 0); JS_ASSERT(((jsuword) clasp & 3) == 0);
JS_STATIC_ASSERT(JSSLOT_PRIVATE + 3 == JS_INITIAL_NSLOTS); JS_STATIC_ASSERT(JSSLOT_PRIVATE + 3 == JS_INITIAL_NSLOTS);
JS_ASSERT_IF(clasp->flags & JSCLASS_HAS_PRIVATE, JS_ASSERT_IF(clasp->flags & JSCLASS_HAS_PRIVATE,
(privateSlotValue & jsval(1)) == jsval(0)); (size_t(privateSlotValue.asPrivateVoidPtr()) & 1) == 0);
classword = jsuword(clasp); clasp = c;
JS_ASSERT(!isDelegate()); JS_ASSERT(!isDelegate());
JS_ASSERT(!isSystem()); JS_ASSERT(!isSystem());
setProto(proto); setProto(proto);
setParent(parent); setParent(parent);
fslots[JSSLOT_PRIVATE] = privateSlotValue; fslots[JSSLOT_PRIVATE].copy(privateSlotValue);
fslots[JSSLOT_PRIVATE + 1] = JSVAL_VOID; fslots[JSSLOT_PRIVATE + 1].setUndefined();
fslots[JSSLOT_PRIVATE + 2] = JSVAL_VOID; fslots[JSSLOT_PRIVATE + 2].setUndefined();
dslots = NULL; dslots = NULL;
} }
@ -445,8 +480,9 @@ struct JSObject {
* Like init, but also initializes map. The catch: proto must be the result * Like init, but also initializes map. The catch: proto must be the result
* of a call to js_InitClass(...clasp, ...). * of a call to js_InitClass(...clasp, ...).
*/ */
inline void initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent, inline void initSharingEmptyScope(js::Class *clasp,
jsval privateSlotValue); js::ObjPtr proto, JSObject *parent,
const js::Value &privateSlotValue);
inline bool hasSlotsArray() const { return !!dslots; } inline bool hasSlotsArray() const { return !!dslots; }
@ -458,18 +494,18 @@ struct JSObject {
return map->ops->lookupProperty(cx, this, id, objp, propp); return map->ops->lookupProperty(cx, this, id, objp, propp);
} }
JSBool defineProperty(JSContext *cx, jsid id, jsval value, JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value,
JSPropertyOp getter = JS_PropertyStub, js::PropertyOp getter = js::PropertyStub,
JSPropertyOp setter = JS_PropertyStub, js::PropertyOp setter = js::PropertyStub,
uintN attrs = JSPROP_ENUMERATE) { uintN attrs = JSPROP_ENUMERATE) {
return map->ops->defineProperty(cx, this, id, value, getter, setter, attrs); return map->ops->defineProperty(cx, this, id, &value, getter, setter, attrs);
} }
JSBool getProperty(JSContext *cx, jsid id, jsval *vp) { JSBool getProperty(JSContext *cx, jsid id, js::Value *vp) {
return map->ops->getProperty(cx, this, id, vp); return map->ops->getProperty(cx, this, id, vp);
} }
JSBool setProperty(JSContext *cx, jsid id, jsval *vp) { JSBool setProperty(JSContext *cx, jsid id, js::Value *vp) {
return map->ops->setProperty(cx, this, id, vp); return map->ops->setProperty(cx, this, id, vp);
} }
@ -483,20 +519,20 @@ struct JSObject {
return map->ops->setAttributes(cx, this, id, prop, attrsp); return map->ops->setAttributes(cx, this, id, prop, attrsp);
} }
JSBool deleteProperty(JSContext *cx, jsid id, jsval *rval) { JSBool deleteProperty(JSContext *cx, jsid id, js::Value *rval) {
return map->ops->deleteProperty(cx, this, id, rval); return map->ops->deleteProperty(cx, this, id, rval);
} }
JSBool defaultValue(JSContext *cx, JSType hint, jsval *vp) { JSBool defaultValue(JSContext *cx, JSType hint, js::Value *vp) {
return map->ops->defaultValue(cx, this, hint, vp); return map->ops->defaultValue(cx, this, hint, vp);
} }
JSBool enumerate(JSContext *cx, JSIterateOp op, jsval *statep, JSBool enumerate(JSContext *cx, JSIterateOp op, js::Value *statep,
jsid *idp) { jsid *idp) {
return map->ops->enumerate(cx, this, op, statep, idp); return map->ops->enumerate(cx, this, op, statep, idp);
} }
JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, jsval *vp, JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, js::Value *vp,
uintN *attrsp) { uintN *attrsp) {
return map->ops->checkAccess(cx, this, id, mode, vp, attrsp); return map->ops->checkAccess(cx, this, id, mode, vp, attrsp);
} }
@ -505,10 +541,8 @@ struct JSObject {
return map->ops->typeOf(cx, this); return map->ops->typeOf(cx, this);
} }
/* These four are time-optimized to avoid stub calls. */ inline JSObject *thisObject(JSContext *cx);
JSObject *thisObject(JSContext *cx) { static inline js::ObjPtr thisObject(JSContext *cx, js::ObjPtr obj);
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
}
void dropProperty(JSContext *cx, JSProperty *prop) { void dropProperty(JSContext *cx, JSProperty *prop) {
if (map->ops->dropProperty) if (map->ops->dropProperty)
@ -524,6 +558,10 @@ struct JSObject {
inline bool isXML() const; inline bool isXML() const;
inline bool unbrand(JSContext *cx); inline bool unbrand(JSContext *cx);
inline void initArrayClass();
inline void changeClassToSlowArray();
inline void changeClassToFastArray();
}; };
#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \ #define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
@ -538,8 +576,8 @@ struct JSObject {
* obj->dslots[-1] that is used to store the length of the vector biased by * obj->dslots[-1] that is used to store the length of the vector biased by
* JS_INITIAL_NSLOTS (and again net of the slot at index -1). * JS_INITIAL_NSLOTS (and again net of the slot at index -1).
*/ */
#define MAX_DSLOTS_LENGTH (JS_MAX(~uint32(0), ~size_t(0)) / sizeof(jsval) - 1) #define MAX_DSLOTS_LENGTH (JS_MAX(~uint32(0), ~size_t(0)) / sizeof(js::Value) - 1)
#define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(jsval) - 1) #define MAX_DSLOTS_LENGTH32 (~uint32(0) / sizeof(js::Value) - 1)
#define OBJ_CHECK_SLOT(obj,slot) \ #define OBJ_CHECK_SLOT(obj,slot) \
(JS_ASSERT((obj)->isNative()), JS_ASSERT(slot < (obj)->scope()->freeslot)) (JS_ASSERT((obj)->isNative()), JS_ASSERT(slot < (obj)->scope()->freeslot))
@ -559,37 +597,22 @@ struct JSObject {
#endif /* JS_THREADSAFE */ #endif /* JS_THREADSAFE */
#ifdef __cplusplus /* N.B. There is a corresponding OBJ_TO_OUTER_OBJ in jsd/jsd_val.c. */
inline void inline void
OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj) Innerize(JSContext *cx, JSObject **ppobj)
{ {
JSClass *clasp = obj->getClass(); JSObject *pobj = *ppobj;
js::Class *clasp = pobj->getClass();
if (clasp->flags & JSCLASS_IS_EXTENDED) { if (clasp->flags & JSCLASS_IS_EXTENDED) {
JSExtendedClass *xclasp = (JSExtendedClass *) clasp; JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
if (xclasp->innerObject) if (xclasp->innerObject)
obj = xclasp->innerObject(cx, obj); *ppobj = xclasp->innerObject(cx, pobj);
} }
} }
/* extern js::Class js_ObjectClass;
* The following function has been copied to jsd/jsd_val.c. If making changes to extern js::Class js_WithClass;
* OBJ_TO_OUTER_OBJECT, please update jsd/jsd_val.c as well. extern js::Class js_BlockClass;
*/
inline void
OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
{
JSClass *clasp = obj->getClass();
if (clasp->flags & JSCLASS_IS_EXTENDED) {
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
if (xclasp->outerObject)
obj = xclasp->outerObject(cx, obj);
}
}
#endif
extern JSClass js_ObjectClass;
extern JSClass js_WithClass;
extern JSClass js_BlockClass;
/* /*
* Block scope object macros. The slots reserved by js_BlockClass are: * Block scope object macros. The slots reserved by js_BlockClass are:
@ -620,9 +643,9 @@ js_DefineBlockVariable(JSContext *cx, JSObject *obj, jsid id, intN index);
#define OBJ_BLOCK_COUNT(cx,obj) \ #define OBJ_BLOCK_COUNT(cx,obj) \
((OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->scope()->entryCount) ((OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->scope()->entryCount)
#define OBJ_BLOCK_DEPTH(cx,obj) \ #define OBJ_BLOCK_DEPTH(cx,obj) \
JSVAL_TO_INT(obj->getSlot(JSSLOT_BLOCK_DEPTH)) obj->getSlot(JSSLOT_BLOCK_DEPTH).asInt32()
#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \ #define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
obj->setSlot(JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth)) obj->setSlot(JSSLOT_BLOCK_DEPTH, Value((int32_t)depth))
/* /*
* To make sure this slot is well-defined, always call js_NewWithObject to * To make sure this slot is well-defined, always call js_NewWithObject to
@ -684,14 +707,14 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
extern JSBool extern JSBool
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc, js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
jsval *vp); js::Value *vp);
extern JSBool extern JSBool
js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id, js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp); JSObject **objp, JSProperty **propp);
extern JSBool extern JSBool
js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSObject * extern JSObject *
js_InitEval(JSContext *cx, JSObject *obj); js_InitEval(JSContext *cx, JSObject *obj);
@ -701,7 +724,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj);
extern JSObject * extern JSObject *
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
JSClass *clasp, JSNative constructor, uintN nargs, js::Class *clasp, js::Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs); JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
@ -719,14 +742,14 @@ extern const char js_lookupGetter_str[];
extern const char js_lookupSetter_str[]; extern const char js_lookupSetter_str[];
extern JSObject * extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, js_NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
JSObject *parent, size_t objectSize = 0); size_t objectSize = 0);
/* /*
* See jsapi.h, JS_NewObjectWithGivenProto. * See jsapi.h, JS_NewObjectWithGivenProto.
*/ */
extern JSObject * extern JSObject *
js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto, js_NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0); JSObject *parent, size_t objectSize = 0);
/* /*
@ -742,8 +765,8 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
* object, not by the parent of its .prototype object value. * object, not by the parent of its .prototype object value.
*/ */
extern JSObject* extern JSObject*
js_NewObjectWithClassProto(JSContext *cx, JSClass *clasp, JSObject *proto, js_NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto,
jsval privateSlotValue); const js::Value &privateSlotValue);
/* /*
* Fast access to immutable standard objects (constructors and prototypes). * Fast access to immutable standard objects (constructors and prototypes).
@ -753,19 +776,20 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **objp); JSObject **objp);
extern JSBool extern JSBool
js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj); js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject *cobj);
/* /*
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
* JSProto_Null, clasp must non-null. * JSProto_Null, clasp must non-null.
*/ */
extern JSBool extern JSBool
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key, jsval *vp, js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
JSClass *clasp = NULL); js::Value *vp, js::Class *clasp = NULL);
extern JSObject * extern JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto, js_ConstructObject(JSContext *cx, js::Class *clasp, JSObject *proto,
JSObject *parent, uintN argc, jsval *argv); JSObject *parent, uintN argc, js::Value *argv);
extern JSBool extern JSBool
js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp); js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
@ -784,7 +808,7 @@ js_ShrinkSlots(JSContext *cx, JSObject *obj, size_t nslots);
* slots. The function can be called only for native objects just created with * slots. The function can be called only for native objects just created with
* js_NewObject or its forms. In particular, the object should not be shared * js_NewObject or its forms. In particular, the object should not be shared
* between threads and its dslots array must be null. nreserved must match the * between threads and its dslots array must be null. nreserved must match the
* value that JSClass.reserveSlots (if any) would return after the object is * value that Class.reserveSlots (if any) would return after the object is
* fully initialized. * fully initialized.
*/ */
bool bool
@ -817,7 +841,7 @@ js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
*/ */
extern JSScopeProperty * extern JSScopeProperty *
js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id, js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
JSPropertyOp getter, JSPropertyOp setter, uint32 slot, js::PropertyOp getter, js::PropertyOp setter, uint32 slot,
uintN attrs, uintN flags, intN shortid); uintN attrs, uintN flags, intN shortid);
/* /*
@ -828,14 +852,15 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
extern JSScopeProperty * extern JSScopeProperty *
js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj, js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
JSScopeProperty *sprop, uintN attrs, uintN mask, JSScopeProperty *sprop, uintN attrs, uintN mask,
JSPropertyOp getter, JSPropertyOp setter); js::PropertyOp getter, js::PropertyOp setter);
extern JSBool extern JSBool
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs); js::PropertyOp getter, js::PropertyOp setter, uintN attrs);
extern JSBool extern JSBool
js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, jsval descriptor, JSBool *bp); js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
const js::Value &descriptor, JSBool *bp);
/* /*
* Flags for the defineHow parameter of js_DefineNativeProperty. * Flags for the defineHow parameter of js_DefineNativeProperty.
@ -854,8 +879,8 @@ const uintN JSDNP_SET_METHOD = 4; /* js_{DefineNativeProperty,SetPropertyHelpe
* the held property, and to release the lock on obj. * the held property, and to release the lock on obj.
*/ */
extern JSBool extern JSBool
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs, js::PropertyOp getter, js::PropertyOp setter, uintN attrs,
uintN flags, intN shortid, JSProperty **propp, uintN flags, intN shortid, JSProperty **propp,
uintN defineHow = 0); uintN defineHow = 0);
@ -888,11 +913,11 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
static inline bool static inline bool
js_IsCacheableNonGlobalScope(JSObject *obj) js_IsCacheableNonGlobalScope(JSObject *obj)
{ {
extern JS_FRIEND_DATA(JSClass) js_CallClass; extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern JS_FRIEND_DATA(JSClass) js_DeclEnvClass; extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
JS_ASSERT(obj->getParent()); JS_ASSERT(obj->getParent());
JSClass *clasp = obj->getClass(); js::Class *clasp = obj->getClass();
bool cacheable = (clasp == &js_CallClass || bool cacheable = (clasp == &js_CallClass ||
clasp == &js_BlockClass || clasp == &js_BlockClass ||
clasp == &js_DeclEnvClass); clasp == &js_DeclEnvClass);
@ -947,24 +972,24 @@ const uintN JSGET_NO_METHOD_BARRIER = 2; // call to joined function can't leak
*/ */
extern JSBool extern JSBool
js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
JSScopeProperty *sprop, uintN getHow, jsval *vp); JSScopeProperty *sprop, uintN getHow, js::Value *vp);
extern JSBool extern JSBool
js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added, js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
jsval *vp); js::Value *vp);
extern JSBool extern JSBool
js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow,
jsval *vp); js::Value *vp);
extern JSBool extern JSBool
js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, jsval *vp); js_GetMethod(JSContext *cx, JSObject *obj, jsid id, uintN getHow, js::Value *vp);
/* /*
* Check whether it is OK to assign an undeclared property of the global * Check whether it is OK to assign an undeclared property of the global
@ -975,10 +1000,10 @@ js_CheckUndeclaredVarAssignment(JSContext *cx);
extern JSBool extern JSBool
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow, js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
jsval *vp); js::Value *vp);
extern JSBool extern JSBool
js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_SetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop, js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
@ -989,44 +1014,45 @@ js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
uintN *attrsp); uintN *attrsp);
extern JSBool extern JSBool
js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval); js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *rval);
extern JSBool extern JSBool
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp); js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, js::Value *vp);
extern JSBool extern JSBool
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp); js::Value *statep, jsid *idp);
extern void extern void
js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, jsval state); js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, const js::Value &v);
extern void extern void
js_PurgeCachedNativeEnumerators(JSContext *cx, JSThreadData *data); js_PurgeCachedNativeEnumerators(JSContext *cx, JSThreadData *data);
extern JSBool extern JSBool
js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp, uintN *attrsp); js::Value *vp, uintN *attrsp);
extern JSType extern JSType
js_TypeOf(JSContext *cx, JSObject *obj); js_TypeOf(JSContext *cx, JSObject *obj);
extern JSBool extern JSBool
js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); js_Call(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
js::Value *rval);
extern JSBool extern JSBool
js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js_Construct(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
jsval *rval); js::Value *rval);
extern JSBool extern JSBool
js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); js_HasInstance(JSContext *cx, JSObject *obj, const js::Value *v, JSBool *bp);
extern JSBool extern JSBool
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj, js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
JSBool checkForCycles); JSBool checkForCycles);
extern JSBool extern bool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
/* /*
* If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
@ -1034,7 +1060,7 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
*/ */
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey, js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
JSObject **protop, JSClass *clasp = NULL); JSObject **protop, js::Class *clasp = NULL);
extern JSBool extern JSBool
js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
@ -1045,20 +1071,28 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
* *vp must not be an object, null or undefined. * *vp must not be an object, null or undefined.
*/ */
extern JSBool extern JSBool
js_PrimitiveToObject(JSContext *cx, jsval *vp); js_PrimitiveToObject(JSContext *cx, js::Value *vp);
/*
* v and vp may alias. On successful return, vp->isObjectOrNull(). If vp is not
* rooted, the caller must root vp before the next possible GC.
*/
extern JSBool
js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, js::Value *vp);
/*
* v and vp may alias. On successful return, vp->isObject(). If vp is not
* rooted, the caller must root vp before the next possible GC.
*/
extern JSBool
js_ValueToNonNullObject(JSContext *cx, const js::Value &v, js::Value *vp);
extern JSBool extern JSBool
js_ValueToObject(JSContext *cx, jsval v, JSObject **objp); js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, js::Value *rval);
extern JSObject *
js_ValueToNonNullObject(JSContext *cx, jsval v);
extern JSBool
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
extern JSBool extern JSBool
js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom, js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN argc, jsval *argv, jsval *rval); uintN argc, js::Value *argv, js::Value *rval);
extern JSBool extern JSBool
js_XDRObject(JSXDRState *xdr, JSObject **objp); js_XDRObject(JSXDRState *xdr, JSObject **objp);
@ -1082,10 +1116,10 @@ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
#endif #endif
extern bool extern bool
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp); js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, js::Value *vp);
bool bool
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v); js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, const js::Value &v);
/* /*
* Precondition: obj must be locked. * Precondition: obj must be locked.
@ -1115,24 +1149,26 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
JSPrincipals *principals, uintN *linenop); JSPrincipals *principals, uintN *linenop);
static inline bool static inline bool
js_IsCallable(jsval v) { js_IsCallable(const js::Value &v) {
return !JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isCallable(); return v.isObject() && v.asObject().isCallable();
} }
extern JSBool extern JSBool
js_ReportGetterOnlyAssignment(JSContext *cx); js_ReportGetterOnlyAssignment(JSContext *cx);
extern JS_FRIEND_API(JSBool) extern JS_FRIEND_API(JSBool)
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp); js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
#ifdef DEBUG #ifdef DEBUG
JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n); namespace js {
JS_FRIEND_API(void) js_DumpString(JSString *str); JS_FRIEND_API(void) DumpChars(const jschar *s, size_t n);
JS_FRIEND_API(void) js_DumpAtom(JSAtom *atom); JS_FRIEND_API(void) DumpString(JSString *str);
JS_FRIEND_API(void) js_DumpValue(jsval val); JS_FRIEND_API(void) DumpAtom(JSAtom *atom);
JS_FRIEND_API(void) js_DumpId(jsid id); JS_FRIEND_API(void) DumpValue(const js::Value &val);
JS_FRIEND_API(void) js_DumpObject(JSObject *obj); JS_FRIEND_API(void) DumpId(jsid id);
JS_FRIEND_API(void) js_DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL); JS_FRIEND_API(void) DumpObject(JSObject *obj);
JS_FRIEND_API(void) DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL);
}
#endif #endif
extern uintN extern uintN
@ -1140,8 +1176,23 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
/* Object constructor native. Exposed only so the JIT can know its address. */ /* Object constructor native. Exposed only so the JIT can know its address. */
JSBool JSBool
js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); js_Object(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv, js::Value *rval);
JS_END_EXTERN_C namespace js {
/*
* Convenience functions for manipulating objects and values. To be inlined,
* these functions need to be in jsobj.h, so they cannot be member functions.
*/
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject *pobj);
JS_ALWAYS_INLINE ObjPtr ToObjPtr(JSObject &obj);
JS_ALWAYS_INLINE Value ToValue(JSObject *pobj);
JS_ALWAYS_INLINE Value ToValue(JSObject &obj);
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject *pobj);
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject *pobj);
JS_ALWAYS_INLINE void SetObject(ObjPtr *vp, JSObject &obj);
JS_ALWAYS_INLINE void SetObject(Value *vp, JSObject &obj);
} /* namespace js */
#endif /* jsobj_h___ */ #endif /* jsobj_h___ */

View File

@ -44,7 +44,7 @@
#include "jsobj.h" #include "jsobj.h"
#include "jsscope.h" #include "jsscope.h"
inline jsval inline const js::Value &
JSObject::getSlotMT(JSContext *cx, uintN slot) JSObject::getSlotMT(JSContext *cx, uintN slot)
{ {
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
@ -54,7 +54,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
* (obj->scope()->ownercx == cx), to avoid needlessly switching from * (obj->scope()->ownercx == cx), to avoid needlessly switching from
* lock-free to lock-full scope when doing GC on a different context * lock-free to lock-full scope when doing GC on a different context
* from the last one to own the scope. The caller in this case is * from the last one to own the scope. The caller in this case is
* probably a JSClass.mark function, e.g., fun_mark, or maybe a * probably a Class.mark function, e.g., fun_mark, or maybe a
* finalizer. * finalizer.
*/ */
OBJ_CHECK_SLOT(this, slot); OBJ_CHECK_SLOT(this, slot);
@ -67,7 +67,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
} }
inline void inline void
JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value) JSObject::setSlotMT(JSContext *cx, uintN slot, const js::Value &value)
{ {
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
/* Thread-safe way to set a slot. */ /* Thread-safe way to set a slot. */
@ -90,61 +90,55 @@ inline uint32
JSObject::getArrayLength() const JSObject::getArrayLength() const
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_LENGTH]); return fslots[JSSLOT_ARRAY_LENGTH].asPrivateUint32();
} }
inline uint32 inline uint32
JSObject::getArrayCount() const JSObject::getArrayCount() const
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_COUNT]); return fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32();
} }
inline void inline void
JSObject::setArrayLength(uint32 length) JSObject::setArrayLength(uint32 length)
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_LENGTH] = length; fslots[JSSLOT_ARRAY_LENGTH].setPrivateUint32(length);
} }
inline void inline void
JSObject::setArrayCount(uint32 count) JSObject::setArrayCount(uint32 count)
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] = count; fslots[JSSLOT_ARRAY_COUNT].setPrivateUint32(count);
} }
inline void inline void
JSObject::voidDenseArrayCount() JSObject::voidDenseArrayCount()
{ {
JS_ASSERT(isDenseArray()); JS_ASSERT(isDenseArray());
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID; fslots[JSSLOT_ARRAY_COUNT].setUndefined();
} }
inline void inline void
JSObject::incArrayCountBy(uint32 posDelta) JSObject::incArrayCountBy(uint32 posDelta)
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] += posDelta; fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() += posDelta;
} }
inline void inline void
JSObject::decArrayCountBy(uint32 negDelta) JSObject::decArrayCountBy(uint32 negDelta)
{ {
JS_ASSERT(isArray()); JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] -= negDelta; fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() -= negDelta;
} }
inline void inline void
JSObject::voidArrayUnused() JSObject::initSharingEmptyScope(js::Class *clasp,
{ js::ObjPtr proto, JSObject *parent,
JS_ASSERT(isArray()); const js::Value &privateSlotValue)
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
}
inline void
JSObject::initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
jsval privateSlotValue)
{ {
init(clasp, proto, parent, privateSlotValue); init(clasp, proto, parent, privateSlotValue);
@ -158,7 +152,7 @@ inline void
JSObject::freeSlotsArray(JSContext *cx) JSObject::freeSlotsArray(JSContext *cx)
{ {
JS_ASSERT(hasSlotsArray()); JS_ASSERT(hasSlotsArray());
JS_ASSERT(size_t(dslots[-1]) > JS_INITIAL_NSLOTS); JS_ASSERT(dslotLength() > JS_INITIAL_NSLOTS);
cx->free(dslots - 1); cx->free(dslots - 1);
} }
@ -181,6 +175,46 @@ JSObject::unbrand(JSContext *cx)
return true; return true;
} }
inline void
JSObject::initArrayClass()
{
clasp = &js_ArrayClass;
}
inline void
JSObject::changeClassToSlowArray()
{
JS_ASSERT(clasp == &js_ArrayClass);
clasp = &js_SlowArrayClass;
}
inline void
JSObject::changeClassToFastArray()
{
JS_ASSERT(clasp == &js_SlowArrayClass);
clasp = &js_ArrayClass;
}
inline JSObject *
JSObject::thisObject(JSContext *cx)
{
if (JSObjectOp thisOp = map->ops->thisObject)
return thisOp(cx, this);
return this;
}
inline js::ObjPtr
JSObject::thisObject(JSContext *cx, js::ObjPtr obj)
{
if (JSObjectOp thisOp = obj->map->ops->thisObject) {
JSObject *o = thisOp(cx, obj);
if (!o)
return js::NullObjPtr();
SetObject(&obj, *o);
}
return obj;
}
namespace js { namespace js {
typedef Vector<PropertyDescriptor, 1> PropertyDescriptorArray; typedef Vector<PropertyDescriptor, 1> PropertyDescriptorArray;
@ -209,6 +243,82 @@ class AutoDescriptorArray : private AutoGCRooter
PropertyDescriptorArray descriptors; PropertyDescriptorArray descriptors;
}; };
JS_ALWAYS_INLINE ObjPtr
ToObjPtr(JSObject *pobj)
{
if (pobj)
return NullObjPtr();
if (pobj->isFunction())
return FunObjPtr(*pobj);
return NonFunObjPtr(*pobj);
} }
JS_ALWAYS_INLINE ObjPtr
ToObjPtr(JSObject &obj)
{
if (obj.isFunction())
return FunObjPtr(obj);
return NonFunObjPtr(obj);
}
JS_ALWAYS_INLINE Value
ToValue(JSObject *pobj)
{
if (pobj)
return NullValue();
if (pobj->isFunction())
return FunObjValue(*pobj);
return NonFunObjValue(*pobj);
}
JS_ALWAYS_INLINE Value
ToValue(JSObject &obj)
{
if (obj.isFunction())
return FunObjValue(obj);
return NonFunObjValue(obj);
}
JS_ALWAYS_INLINE void
SetObject(ObjPtr *vp, JSObject *pobj)
{
if (!pobj)
vp->setNull();
else if (pobj->isFunction())
vp->setFunObj(*pobj);
else
vp->setNonFunObj(*pobj);
}
JS_ALWAYS_INLINE void
SetObject(Value *vp, JSObject *pobj)
{
if (!pobj)
vp->setNull();
if (pobj->isFunction())
vp->setFunObj(*pobj);
else
vp->setNonFunObj(*pobj);
}
JS_ALWAYS_INLINE void
SetObject(ObjPtr *vp, JSObject &obj)
{
if (obj.isFunction())
vp->setFunObj(obj);
else
vp->setNonFunObj(obj);
}
JS_ALWAYS_INLINE void
SetObject(Value *vp, JSObject &obj)
{
if (obj.isFunction())
vp->setFunObj(obj);
else
vp->setNonFunObj(obj);
}
} /* namespace js */
#endif /* jsobjinlines_h___ */ #endif /* jsobjinlines_h___ */

View File

@ -47,7 +47,7 @@
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
extern JSClass js_JSONClass; extern js::Class js_JSONClass;
extern JSObject * extern JSObject *
js_InitJSONClass(JSContext *cx, JSObject *obj); js_InitJSONClass(JSContext *cx, JSObject *obj);

View File

@ -100,7 +100,7 @@ typedef enum JSOp {
#define JOF_INCDEC (3U<<10) /* increment or decrement opcode */ #define JOF_INCDEC (3U<<10) /* increment or decrement opcode */
#define JOF_POST (1U<<12) /* postorder increment or decrement */ #define JOF_POST (1U<<12) /* postorder increment or decrement */
#define JOF_FOR (1U<<13) /* for-in property op (akin to JOF_SET) */ #define JOF_FOR (1U<<13) /* for-in property op (akin to JOF_SET) */
#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops #define JOF_ASSIGNING JOF_SET /* hint for Class.resolve, used for ops
that do simplex assignment */ that do simplex assignment */
#define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */ #define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */
#define JOF_BACKPATCH (1U<<15) /* backpatch placeholder during codegen */ #define JOF_BACKPATCH (1U<<15) /* backpatch placeholder during codegen */
@ -457,7 +457,7 @@ js_DecompileToString(JSContext *cx, const char *name, JSFunction *fun,
* The caller must call JS_free on the result after a succsesful call. * The caller must call JS_free on the result after a succsesful call.
*/ */
extern char * extern char *
js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v, js_DecompileValueGenerator(JSContext *cx, intN spindex, const jsval *v,
JSString *fallback); JSString *fallback);
#define JSDVG_IGNORE_STACK 0 #define JSDVG_IGNORE_STACK 0

File diff suppressed because it is too large Load Diff

View File

@ -760,7 +760,6 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
JSString *source /* = NULL */, JSString *source /* = NULL */,
unsigned staticLevel /* = 0 */) unsigned staticLevel /* = 0 */)
{ {
JSCompiler jsc(cx, principals, callerFrame);
JSArenaPool codePool, notePool; JSArenaPool codePool, notePool;
TokenKind tt; TokenKind tt;
JSParseNode *pn; JSParseNode *pn;
@ -780,6 +779,7 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO); JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
JS_ASSERT_IF(staticLevel != 0, callerFrame); JS_ASSERT_IF(staticLevel != 0, callerFrame);
JSCompiler jsc(cx, principals, callerFrame);
if (!jsc.init(chars, length, file, filename, lineno)) if (!jsc.init(chars, length, file, filename, lineno))
return NULL; return NULL;
@ -789,6 +789,8 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
&cx->scriptStackQuota); &cx->scriptStackQuota);
JSCodeGenerator cg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno()); JSCodeGenerator cg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno());
if (!cg.init())
return NULL;
MUST_FLOW_THROUGH("out"); MUST_FLOW_THROUGH("out");
@ -1561,6 +1563,9 @@ JSCompiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *pr
&cx->scriptStackQuota); &cx->scriptStackQuota);
JSCodeGenerator funcg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno()); JSCodeGenerator funcg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno());
if (!funcg.init())
return NULL;
funcg.flags |= TCF_IN_FUNCTION; funcg.flags |= TCF_IN_FUNCTION;
funcg.fun = fun; funcg.fun = fun;
if (!GenerateBlockId(&funcg, funcg.bodyid)) if (!GenerateBlockId(&funcg, funcg.bodyid))

View File

@ -320,7 +320,7 @@ struct JSParseNode {
struct { /* two kids if binary */ struct { /* two kids if binary */
JSParseNode *left; JSParseNode *left;
JSParseNode *right; JSParseNode *right;
jsval val; /* switch case value */ jsboxedword val; /* switch case value */
uintN iflags; /* JSITER_* flags for TOK_FOR node */ uintN iflags; /* JSITER_* flags for TOK_FOR node */
} binary; } binary;
struct { /* one kid if unary */ struct { /* one kid if unary */

View File

@ -94,10 +94,9 @@ class PCVal
bool isNull() const { return v == 0; } bool isNull() const { return v == 0; }
void setNull() { v = 0; } void setNull() { v = 0; }
bool isObject() const { return (v & TAG) == OBJECT; } bool isFunObj() const { return (v & TAG) == OBJECT; }
JSObject *toObject() const { JS_ASSERT(isObject()); return reinterpret_cast<JSObject *>(v); } JSObject &toFunObj() const { JS_ASSERT(isFunObj()); return *reinterpret_cast<JSObject *>(v); }
jsval toJsval() const { return OBJECT_TO_JSVAL(toObject()); } void setFunObj(JSObject &obj) { v = reinterpret_cast<jsuword>(&obj); }
void setObject(JSObject *obj) { v = reinterpret_cast<jsuword>(obj); }
bool isSlot() const { return v & SLOT; } bool isSlot() const { return v & SLOT; }
uint32 toSlot() const { JS_ASSERT(isSlot()); return uint32(v) >> 1; } uint32 toSlot() const { JS_ASSERT(isSlot()); return uint32(v) >> 1; }

View File

@ -57,26 +57,6 @@
#include "jspubtd.h" #include "jspubtd.h"
#include "jsutil.h" #include "jsutil.h"
/* Internal identifier (jsid) macros. */
#define JSID_IS_ATOM(id) JSVAL_IS_STRING((jsval)(id))
#define JSID_TO_ATOM(id) ((JSAtom *)(id))
#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
(jsid)(atom))
#define JSID_IS_INT(id) JSVAL_IS_INT((jsval)(id))
#define JSID_TO_INT(id) JSVAL_TO_INT((jsval)(id))
#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i))
#define INT_JSVAL_TO_JSID(v) ((jsid)(v))
#define INT_JSID_TO_JSVAL(id) ((jsval)(id))
#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id))
#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id))
#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSVAL(obj))
#define OBJECT_JSVAL_TO_JSID(v) ((jsid)v)
#define ID_TO_VALUE(id) ((jsval)(id))
/* /*
* Convenience constants. * Convenience constants.
*/ */
@ -179,17 +159,12 @@ class DeflatedStringCache;
class PropertyCache; class PropertyCache;
struct PropertyCacheEntry; struct PropertyCacheEntry;
} /* namespace js */ } /* namespace js */
/* Common instantiations. */ /* Common instantiations. */
typedef js::Vector<jschar, 32> JSCharBuffer; typedef js::Vector<jschar, 32> JSCharBuffer;
static inline JSPropertyOp
js_CastAsPropertyOp(JSObject *object)
{
return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
}
} /* export "C++" */ } /* export "C++" */
#endif /* __cplusplus */ #endif /* __cplusplus */
@ -204,10 +179,21 @@ typedef enum JSTrapStatus {
typedef JSTrapStatus typedef JSTrapStatus
(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, (* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure); jsval closure);
typedef JSTrapStatus
(* JSInterruptHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSTrapStatus
(* JSDebuggerHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSTrapStatus
(* JSThrowHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
void *closure);
typedef JSBool typedef JSBool
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old, (* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsid id, jsval old,
jsval *newp, void *closure); jsval *newp, void *closure);
/* called just after script creation */ /* called just after script creation */
@ -266,13 +252,13 @@ typedef JSBool
void *closure); void *closure);
typedef struct JSDebugHooks { typedef struct JSDebugHooks {
JSTrapHandler interruptHandler; JSInterruptHook interruptHook;
void *interruptHandlerData; void *interruptHookData;
JSNewScriptHook newScriptHook; JSNewScriptHook newScriptHook;
void *newScriptHookData; void *newScriptHookData;
JSDestroyScriptHook destroyScriptHook; JSDestroyScriptHook destroyScriptHook;
void *destroyScriptHookData; void *destroyScriptHookData;
JSTrapHandler debuggerHandler; JSDebuggerHandler debuggerHandler;
void *debuggerHandlerData; void *debuggerHandlerData;
JSSourceHandler sourceHandler; JSSourceHandler sourceHandler;
void *sourceHandlerData; void *sourceHandlerData;
@ -282,7 +268,7 @@ typedef struct JSDebugHooks {
void *callHookData; void *callHookData;
JSObjectHook objectHook; JSObjectHook objectHook;
void *objectHookData; void *objectHookData;
JSTrapHandler throwHook; JSThrowHook throwHook;
void *throwHookData; void *throwHookData;
JSDebugErrorHook debugErrorHook; JSDebugErrorHook debugErrorHook;
void *debugErrorHookData; void *debugErrorHookData;
@ -316,7 +302,7 @@ typedef JSBool
* value, with the specified getter, setter, and attributes. * value, with the specified getter, setter, and attributes.
*/ */
typedef JSBool typedef JSBool
(* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, jsval value, (* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const jsval *value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs); JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
/* /*
@ -368,4 +354,57 @@ typedef void
extern JSBool js_CStringsAreUTF8; extern JSBool js_CStringsAreUTF8;
#endif #endif
#ifdef __cplusplus
namespace js {
class Value;
typedef JSBool
(* DefinePropOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
PropertyOp getter, PropertyOp setter, uintN attrs);
typedef JSBool
(* CheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
Value *vp, uintN *attrsp);
typedef JSBool
(* WatchPointHandler)(JSContext *cx, JSObject *obj, jsid id,
const Value *old, Value *newp, void *closure);
typedef JSBool
(* PropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
/*
* Since jsval and Value are layout-compatible, pointers to otherwise-identical
* functions can be cast back and forth. To avoid widespread casting, the
* following safe casts are provided.
*
* See also Valueify and Jsvalify overloads in jspubtd.h.
*/
static inline DefinePropOp Valueify(JSDefinePropOp f) { return (DefinePropOp)f; }
static inline JSDefinePropOp Jsvalify(DefinePropOp f) { return (JSDefinePropOp)f; }
static inline CheckAccessIdOp Valueify(JSCheckAccessIdOp f) { return (CheckAccessIdOp)f; }
static inline JSCheckAccessIdOp Jsvalify(CheckAccessIdOp f) { return (JSCheckAccessIdOp)f; }
static inline WatchPointHandler Valueify(JSWatchPointHandler f) { return (WatchPointHandler)f; }
static inline JSWatchPointHandler Jsvalify(WatchPointHandler f) { return (JSWatchPointHandler)f; }
static inline PropertyIdOp Valueify(JSPropertyIdOp f); /* Same type as JSPropertyOp */
static inline JSPropertyIdOp Jsvalify(PropertyIdOp f); /* Same type as PropertyOp */
/*
* Internal utilities
*/
static JS_ALWAYS_INLINE void
SetValueRangeToUndefined(Value *vec, Value *end)
{
for (Value *v = vec; v != end; ++v)
v->setUndefined();
}
static JS_ALWAYS_INLINE void
SetValueRangeToUndefined(Value *vec, uintN len)
{
return SetValueRangeToUndefined(vec, vec + len);
}
} /* namespace js */
#endif /* __cplusplus */
#endif /* jsprvtd_h___ */ #endif /* jsprvtd_h___ */

View File

@ -42,8 +42,8 @@
/* /*
* JS public API typedefs. * JS public API typedefs.
*/ */
#include "jstypes.h"
#include "jscompat.h" #include "jscompat.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
@ -52,8 +52,6 @@ typedef uint16 jschar;
typedef int32 jsint; typedef int32 jsint;
typedef uint32 jsuint; typedef uint32 jsuint;
typedef float64 jsdouble; typedef float64 jsdouble;
typedef jsword jsval;
typedef jsword jsid;
typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */ typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
/* /*
@ -155,6 +153,340 @@ typedef struct JSLocaleCallbacks JSLocaleCallbacks;
typedef struct JSSecurityCallbacks JSSecurityCallbacks; typedef struct JSSecurityCallbacks JSSecurityCallbacks;
typedef struct JSONParser JSONParser; typedef struct JSONParser JSONParser;
/*
* JavaScript engine unboxed value representation
*/
/*
* A jsval has an abstract type which is represented by a mask which assigns a
* bit to each type. This allows fast set-membership queries. However, we give
* one type (null) a mask of 0 for two reasons:
* 1. memset'ing values to 0 produces a valid value. This was true of the old,
* boxed jsvals (and now jsboxedwords) and eases the transition.
* 2. Testing for null can often be compiled to slightly shorter/faster code.
*
* The down-side is that set-membership queries need to be done more carefully.
* E.g., to test whether a value v is undefined or null, the correct test is:
* (v.mask & ~UndefinedMask) == 0
* instead of the intuitive (but incorrect) test:
* (v.mask & (NullMask | UndefinedMask)) != 0
* Since the value representation is kept a private detail of js::Value and
* only exposed to a few functions through friendship, this type of error
* should be hidden behind simple inline methods like v.isNullOrUndefined().
*/
/*
* Types are unsigned machine-words. On 32-bit systems, values are padded with
* an extra word so that double payloads are aligned properly.
*/
#if JS_BITS_PER_WORD == 32
typedef uint32 JSValueMaskType;
# define JSVAL_TYPE_BITS 32
# define JS_INSERT_VALUE_PADDING() uint32 padding;
#elif JS_BITS_PER_WORD == 64
typedef JSUint64 JSValueMaskType;
# define JSVAL_TYPE_BITS 32
# define JS_INSERT_VALUE_PADDING()
#else
# error "Unsupported word size"
#endif
#define JSVAL_NULL_MASK ((JSValueMaskType)0x00)
#define JSVAL_UNDEFINED_MASK ((JSValueMaskType)0x01)
#define JSVAL_INT32_MASK ((JSValueMaskType)0x02)
#define JSVAL_DOUBLE_MASK ((JSValueMaskType)0x04)
#define JSVAL_STRING_MASK ((JSValueMaskType)0x08)
#define JSVAL_NONFUNOBJ_MASK ((JSValueMaskType)0x10)
#define JSVAL_FUNOBJ_MASK ((JSValueMaskType)0x20)
#define JSVAL_BOOLEAN_MASK ((JSValueMaskType)0x40)
#define JSVAL_MAGIC_MASK ((JSValueMaskType)0x80)
/*
* Magic value enumeration (private engine detail)
*
* This enumeration provides a debug-only code describing the source of an
* invalid value. These codes can be used to assert that the different sources
* of invalid never mix.
*/
typedef enum JSWhyMagic
{
JS_ARRAY_HOLE, /* a hole in a dense array */
JS_ARGS_HOLE, /* a hole in the args object's array */
JS_STOP_ITERATION, /* value returned by iterator to stop */
JS_STOP_ITERATION_EXCEPTION /* value of cx->exception for a StopIteration exception */
} JSWhyMagic;
typedef union jsval_data
{
int32 i32;
uint32 u32;
double dbl;
JSString * str;
JSObject * obj;
void * ptr;
JSBool boo;
#ifdef DEBUG
JSWhyMagic why;
#endif
struct { int32 first; int32 second; } bits;
} jsval_data;
/* See js::Value. */
typedef struct jsval
{
JSValueMaskType mask;
JS_INSERT_VALUE_PADDING()
jsval_data data;
} jsval;
/*
* Boxed word macros (private engine detail)
*
* N.B. jsboxedword and the JSBOXEDWORD macros are engine-private. Callers
* should use only JSID macros (below) instead.
*
* The jsboxedword type is used by atoms and jsids. Eventually, the ability to
* atomize any primitive will be removed and atoms will simply be unboxed,
* interned JSString*s. However, jsids will always need boxing. Using a
* one-word boxing scheme instead of the normal jsval 16-byte unboxed scheme
* allows jsids to be passed by value without penalty, since jsids never are
* doubles nor are jsids used to build typemaps for entering/leaving trace.
*/
typedef jsword jsboxedword;
#define JSBOXEDWORD_TYPE_OBJECT 0x0
#define JSBOXEDWORD_TYPE_INT 0x1
#define JSBOXEDWORD_TYPE_DOUBLE 0x2
#define JSBOXEDWORD_TYPE_STRING 0x4
#define JSBOXEDWORD_TYPE_SPECIAL 0x6
/* Type tag bitfield length and derived macros. */
#define JSBOXEDWORD_TAGBITS 3
#define JSBOXEDWORD_TAGMASK ((jsboxedword) JS_BITMASK(JSBOXEDWORD_TAGBITS))
#define JSBOXEDWORD_ALIGN JS_BIT(JSBOXEDWORD_TAGBITS)
static const jsboxedword JSBOXEDWORD_NULL = (jsboxedword)0x0;
static const jsboxedword JSBOXEDWORD_FALSE = (jsboxedword)0x6;
static const jsboxedword JSBOXEDWORD_TRUE = (jsboxedword)0xe;
static const jsboxedword JSBOXEDWORD_VOID = (jsboxedword)0x16;
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_NULL(jsboxedword w)
{
return w == JSBOXEDWORD_NULL;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_VOID(jsboxedword w)
{
return w == JSBOXEDWORD_VOID;
}
static JS_ALWAYS_INLINE unsigned
JSBOXEDWORD_TAG(jsboxedword w)
{
return (unsigned)(w & JSBOXEDWORD_TAGMASK);
}
static JS_ALWAYS_INLINE jsboxedword
JSBOXEDWORD_SETTAG(jsboxedword w, unsigned t)
{
return w | t;
}
static JS_ALWAYS_INLINE jsboxedword
JSBOXEDWORD_CLRTAG(jsboxedword w)
{
return w & ~(jsboxedword)JSBOXEDWORD_TAGMASK;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_DOUBLE(jsboxedword w)
{
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_DOUBLE;
}
static JS_ALWAYS_INLINE double *
JSBOXEDWORD_TO_DOUBLE(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_DOUBLE(w));
return (double *)JSBOXEDWORD_CLRTAG(w);
}
static JS_ALWAYS_INLINE jsboxedword
DOUBLE_TO_JSBOXEDWORD(double *d)
{
JS_ASSERT(((JSUword)d & JSBOXEDWORD_TAGMASK) == 0);
return (jsboxedword)((JSUword)d | JSBOXEDWORD_TYPE_DOUBLE);
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_STRING(jsboxedword w)
{
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_STRING;
}
static JS_ALWAYS_INLINE JSString *
JSBOXEDWORD_TO_STRING(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_STRING(w));
return (JSString *)JSBOXEDWORD_CLRTAG(w);
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_SPECIAL(jsboxedword w)
{
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_SPECIAL;
}
static JS_ALWAYS_INLINE jsint
JSBOXEDWORD_TO_SPECIAL(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w));
return w >> JSBOXEDWORD_TAGBITS;
}
static JS_ALWAYS_INLINE jsboxedword
SPECIAL_TO_JSBOXEDWORD(jsint i)
{
return (i << JSBOXEDWORD_TAGBITS) | JSBOXEDWORD_TYPE_SPECIAL;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_BOOLEAN(jsboxedword w)
{
return (w & ~((jsboxedword)1 << JSBOXEDWORD_TAGBITS)) == JSBOXEDWORD_TYPE_SPECIAL;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_TO_BOOLEAN(jsboxedword w)
{
JS_ASSERT(w == JSBOXEDWORD_TRUE || w == JSBOXEDWORD_FALSE);
return JSBOXEDWORD_TO_SPECIAL(w);
}
static JS_ALWAYS_INLINE jsboxedword
BOOLEAN_TO_JSBOXEDWORD(JSBool b)
{
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
return SPECIAL_TO_JSBOXEDWORD(b);
}
static JS_ALWAYS_INLINE jsboxedword
STRING_TO_JSBOXEDWORD(JSString *str)
{
JS_ASSERT(((JSUword)str & JSBOXEDWORD_TAGMASK) == 0);
return (jsboxedword)str | JSBOXEDWORD_TYPE_STRING;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_GCTHING(jsboxedword w)
{
return !(w & JSBOXEDWORD_TYPE_INT) &&
JSBOXEDWORD_TAG(w) != JSBOXEDWORD_TYPE_SPECIAL;
}
static JS_ALWAYS_INLINE void *
JSBOXEDWORD_TO_GCTHING(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_GCTHING(w));
return (void *)JSBOXEDWORD_CLRTAG(w);
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_OBJECT(jsboxedword w)
{
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_OBJECT;
}
static JS_ALWAYS_INLINE JSObject *
JSBOXEDWORD_TO_OBJECT(jsboxedword w)
{
JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
return (JSObject *)JSBOXEDWORD_TO_GCTHING(w);
}
static JS_ALWAYS_INLINE jsboxedword
OBJECT_TO_JSBOXEDWORD(JSObject *obj)
{
JS_ASSERT(((JSUword)obj & JSBOXEDWORD_TAGMASK) == 0);
return (jsboxedword)obj | JSBOXEDWORD_TYPE_OBJECT;
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_PRIMITIVE(jsboxedword w)
{
return !JSBOXEDWORD_IS_OBJECT(w) || JSBOXEDWORD_IS_NULL(w);
}
/* Domain limits for the jsboxedword int type. */
#define JSBOXEDWORD_INT_BITS 31
#define JSBOXEDWORD_INT_POW2(n) ((jsboxedword)1 << (n))
#define JSBOXEDWORD_INT_MIN (-JSBOXEDWORD_INT_POW2(30))
#define JSBOXEDWORD_INT_MAX (JSBOXEDWORD_INT_POW2(30) - 1)
static JS_ALWAYS_INLINE JSBool
INT32_FITS_IN_JSBOXEDWORD(jsint i)
{
return ((jsuint)(i) - (jsuint)JSBOXEDWORD_INT_MIN <=
(jsuint)(JSBOXEDWORD_INT_MAX - JSBOXEDWORD_INT_MIN));
}
static JS_ALWAYS_INLINE JSBool
JSBOXEDWORD_IS_INT(jsboxedword w)
{
return w & JSBOXEDWORD_TYPE_INT;
}
static JS_ALWAYS_INLINE jsint
JSBOXEDWORD_TO_INT(jsboxedword v)
{
JS_ASSERT(JSBOXEDWORD_IS_INT(v));
return (jsint)(v >> 1);
}
static JS_ALWAYS_INLINE jsboxedword
INT_TO_JSBOXEDWORD(jsint i)
{
JS_ASSERT(INT32_FITS_IN_JSBOXEDWORD(i));
return (i << 1) | JSBOXEDWORD_TYPE_INT;
}
/*
* Identifier (jsid) macros.
*/
typedef jsboxedword jsid;
#define JSID_NULL ((jsid)JSBOXEDWORD_NULL)
#define JSID_VOID ((jsid)JSBOXEDWORD_VOID)
#define JSID_IS_NULL(id) JSBOXEDWORD_IS_NULL((jsboxedword)(id))
#define JSID_IS_VOID(id) JSBOXEDWORD_IS_VOID((jsboxedword)(id))
#define JSID_IS_ATOM(id) JSBOXEDWORD_IS_STRING((jsboxedword)(id))
#define JSID_TO_ATOM(id) ((JSAtom *)(id))
#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
(jsid)(atom))
#define INT32_FITS_IN_JSID(id) INT32_FITS_IN_JSBOXEDWORD(id)
#define JSID_IS_INT(id) JSBOXEDWORD_IS_INT((jsboxedword)(id))
#define JSID_TO_INT(id) JSBOXEDWORD_TO_INT((jsboxedword)(id))
#define INT_TO_JSID(i) ((jsid)INT_TO_JSBOXEDWORD((i)))
#define JSID_IS_OBJECT(id) JSBOXEDWORD_IS_OBJECT((jsboxedword)(id))
#define JSID_TO_OBJECT(id) JSBOXEDWORD_TO_OBJECT((jsboxedword)(id))
#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSBOXEDWORD((obj)))
/* Objects and strings (no doubles in jsids). */
#define JSID_IS_GCTHING(id) (((id) & 0x3) == 0)
#define JSID_TO_GCTHING(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
JSBOXEDWORD_TO_GCTHING((jsboxedword)(id)))
#define JSID_TRACE_KIND(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
(JSBOXEDWORD_TAG((jsboxedword)(id)) == JSBOXEDWORD_TYPE_STRING))
JS_PUBLIC_API(jsval)
JSID_TO_JSVAL(jsid id);
/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */ /* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
/* /*
@ -165,7 +497,7 @@ typedef struct JSONParser JSONParser;
* obj[id] can't be deleted (because it's permanent). * obj[id] can't be deleted (because it's permanent).
*/ */
typedef JSBool typedef JSBool
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp); (* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
/* /*
* This function type is used for callbacks that enumerate the properties of * This function type is used for callbacks that enumerate the properties of
@ -218,7 +550,7 @@ typedef JSBool
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
*/ */
typedef JSBool typedef JSBool
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id); (* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
/* /*
* Like JSResolveOp, but flags provide contextual information as follows: * Like JSResolveOp, but flags provide contextual information as follows:
@ -250,7 +582,7 @@ typedef JSBool
* *objp without a new JSClass flag. * *objp without a new JSClass flag.
*/ */
typedef JSBool typedef JSBool
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags, (* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp); JSObject **objp);
/* /*
@ -317,7 +649,7 @@ typedef JSObjectOps *
* specialize access checks. * specialize access checks.
*/ */
typedef JSBool typedef JSBool
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode, (* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp); jsval *vp);
/* /*
@ -333,7 +665,7 @@ typedef JSBool
* *bp otherwise. * *bp otherwise.
*/ */
typedef JSBool typedef JSBool
(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); (* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
/* /*
* Deprecated function type for JSClass.mark. All new code should define * Deprecated function type for JSClass.mark. All new code should define
@ -420,7 +752,7 @@ typedef uint32
/* JSExtendedClass function pointer typedefs. */ /* JSExtendedClass function pointer typedefs. */
typedef JSBool typedef JSBool
(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); (* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
/* /*
* A generic type for functions mapping an object to another object, or null * A generic type for functions mapping an object to another object, or null
@ -443,7 +775,6 @@ typedef JSBool
(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, (* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval); jsval *rval);
/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
typedef JSBool typedef JSBool
(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp); (* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
@ -593,4 +924,60 @@ typedef JSBool
JS_END_EXTERN_C JS_END_EXTERN_C
#ifdef __cplusplus
namespace js {
class Value;
class Class;
typedef JSBool
(* Native)(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval);
typedef JSBool
(* FastNative)(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
(* HasInstanceOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
typedef JSBool
(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
Value *vp);
typedef JSObjectOps *
(* GetObjectOps)(JSContext *cx, Class *clasp);
typedef JSBool
(* EqualityOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
/*
* Since jsval and Value are layout-compatible, pointers to otherwise-identical
* functions can be cast back and forth. To avoid widespread casting, the
* following safe casts are provided.
*
* See also Valueify and Jsvalify overloads in jsprvtd.h.
*/
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 GetObjectOps Valueify(JSGetObjectOps f) { return (GetObjectOps)f; }
static inline JSGetObjectOps Jsvalify(GetObjectOps f) { return (JSGetObjectOps)f; }
static inline EqualityOp Valueify(JSEqualityOp f); /* Same type as JSHasInstanceOp */
static inline JSEqualityOp Jsvalify(EqualityOp f); /* Same type as HasInstanceOp */
} /* namespace js */
#endif /* __cplusplus */
#endif /* jspubtd_h___ */ #endif /* jspubtd_h___ */

View File

@ -50,8 +50,6 @@
#include "jsdhash.h" #include "jsdhash.h"
#endif #endif
JS_BEGIN_EXTERN_C
struct JSRegExpStatics { struct JSRegExpStatics {
JSString *input; /* input string to match (perl $_, GC root) */ JSString *input; /* input string to match (perl $_, GC root) */
JSBool multiline; /* whether input contains newlines (perl $*) */ JSBool multiline; /* whether input contains newlines (perl $*) */
@ -153,7 +151,7 @@ js_FreeRegExpStatics(JSContext *cx);
#define VALUE_IS_REGEXP(cx, v) \ #define VALUE_IS_REGEXP(cx, v) \
(!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isRegExp()) (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isRegExp())
extern JSClass js_RegExpClass; extern js::Class js_RegExpClass;
inline bool inline bool
JSObject::isRegExp() const JSObject::isRegExp() const
@ -202,13 +200,11 @@ static inline void
js_ClearRegExpLastIndex(JSObject *obj) js_ClearRegExpLastIndex(JSObject *obj)
{ {
JS_ASSERT(obj->getClass() == &js_RegExpClass); JS_ASSERT(obj->getClass() == &js_RegExpClass);
obj->fslots[JSSLOT_REGEXP_LAST_INDEX] = JSVAL_ZERO; obj->fslots[JSSLOT_REGEXP_LAST_INDEX].setInt32(0);
} }
/* Return whether the given character array contains RegExp meta-characters. */ /* Return whether the given character array contains RegExp meta-characters. */
extern bool extern bool
js_ContainsRegExpMetaChars(const jschar *chars, size_t length); js_ContainsRegExpMetaChars(const jschar *chars, size_t length);
JS_END_EXTERN_C
#endif /* jsregexp_h___ */ #endif /* jsregexp_h___ */

View File

@ -63,8 +63,6 @@
#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */ #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
#endif #endif
JS_BEGIN_EXTERN_C
/* /*
* Given P independent, non-unique properties each of size S words mapped by * Given P independent, non-unique properties each of size S words mapped by
* all scopes in a runtime, construct a property tree of N nodes each of size * all scopes in a runtime, construct a property tree of N nodes each of size
@ -281,10 +279,10 @@ struct JSScope : public JSObjectMap
void generateOwnShape(JSContext *cx); void generateOwnShape(JSContext *cx);
JSScopeProperty **searchTable(jsid id, bool adding); JSScopeProperty **searchTable(jsid id, bool adding);
inline JSScopeProperty **search(jsid id, bool adding); inline JSScopeProperty **search(jsid id, bool adding);
inline JSEmptyScope *createEmptyScope(JSContext *cx, JSClass *clasp); inline JSEmptyScope *createEmptyScope(JSContext *cx, js::Class *clasp);
JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id, JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id,
JSPropertyOp getter, JSPropertyOp setter, js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs, uint32 slot, uintN attrs,
uintN flags, intN shortid, uintN flags, intN shortid,
JSScopeProperty **spp); JSScopeProperty **spp);
@ -295,7 +293,7 @@ struct JSScope : public JSObjectMap
/* Create a mutable, owned, empty scope. */ /* Create a mutable, owned, empty scope. */
static JSScope *create(JSContext *cx, const JSObjectOps *ops, static JSScope *create(JSContext *cx, const JSObjectOps *ops,
JSClass *clasp, JSObject *obj, uint32 shape); js::Class *clasp, JSObject *obj, uint32 shape);
void destroy(JSContext *cx); void destroy(JSContext *cx);
@ -306,11 +304,11 @@ struct JSScope : public JSObjectMap
* If |this| is the scope of an object |proto|, the resulting scope can be * If |this| is the scope of an object |proto|, the resulting scope can be
* used as the scope of a new object whose prototype is |proto|. * used as the scope of a new object whose prototype is |proto|.
*/ */
inline JSEmptyScope *getEmptyScope(JSContext *cx, JSClass *clasp); inline JSEmptyScope *getEmptyScope(JSContext *cx, js::Class *clasp);
inline bool ensureEmptyScope(JSContext *cx, JSClass *clasp); inline bool ensureEmptyScope(JSContext *cx, js::Class *clasp);
inline bool canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp); inline bool canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp);
JSScopeProperty *lookup(jsid id); JSScopeProperty *lookup(jsid id);
@ -319,7 +317,7 @@ struct JSScope : public JSObjectMap
/* Add a property whose id is not yet in this scope. */ /* Add a property whose id is not yet in this scope. */
JSScopeProperty *addProperty(JSContext *cx, jsid id, JSScopeProperty *addProperty(JSContext *cx, jsid id,
JSPropertyOp getter, JSPropertyOp setter, js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs, uint32 slot, uintN attrs,
uintN flags, intN shortid); uintN flags, intN shortid);
@ -331,14 +329,14 @@ struct JSScope : public JSObjectMap
/* Add or overwrite a property for id in this scope. */ /* Add or overwrite a property for id in this scope. */
JSScopeProperty *putProperty(JSContext *cx, jsid id, JSScopeProperty *putProperty(JSContext *cx, jsid id,
JSPropertyOp getter, JSPropertyOp setter, js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs, uint32 slot, uintN attrs,
uintN flags, intN shortid); uintN flags, intN shortid);
/* Change the given property into a sibling with the same id in this scope. */ /* Change the given property into a sibling with the same id in this scope. */
JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop, JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop,
uintN attrs, uintN mask, uintN attrs, uintN mask,
JSPropertyOp getter, JSPropertyOp setter); js::PropertyOp getter, js::PropertyOp setter);
/* Remove id from this scope. */ /* Remove id from this scope. */
bool removeProperty(JSContext *cx, jsid id); bool removeProperty(JSContext *cx, jsid id);
@ -354,7 +352,7 @@ struct JSScope : public JSObjectMap
* Defined in jsscopeinlines.h, but not declared inline per standard style * Defined in jsscopeinlines.h, but not declared inline per standard style
* in order to avoid gcc warnings. * in order to avoid gcc warnings.
*/ */
bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp); bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp);
/* /*
* Write barrier to check for a method value change. Defined inline below * Write barrier to check for a method value change. Defined inline below
@ -363,14 +361,14 @@ struct JSScope : public JSObjectMap
* flags show this is necessary. The methodShapeChange overload (directly * flags show this is necessary. The methodShapeChange overload (directly
* below) parallels this. * below) parallels this.
*/ */
bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v); bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, const js::Value &v);
bool methodWriteBarrier(JSContext *cx, uint32 slot, jsval v); bool methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v);
void trace(JSTracer *trc); void trace(JSTracer *trc);
void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop); void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop);
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval); bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, const js::Value &toval);
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval); bool methodShapeChange(JSContext *cx, uint32 slot, const js::Value &toval);
void protoShapeChange(JSContext *cx); void protoShapeChange(JSContext *cx);
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop); void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
@ -420,7 +418,7 @@ struct JSScope : public JSObjectMap
*/ */
bool branded() { JS_ASSERT(!generic()); return flags & BRANDED; } bool branded() { JS_ASSERT(!generic()); return flags & BRANDED; }
bool brand(JSContext *cx, uint32 slot, jsval v) { bool brand(JSContext *cx, uint32 slot) {
JS_ASSERT(!branded()); JS_ASSERT(!branded());
generateOwnShape(cx); generateOwnShape(cx);
if (js_IsPropertyCacheDisabled(cx)) // check for rt->shapeGen overflow if (js_IsPropertyCacheDisabled(cx)) // check for rt->shapeGen overflow
@ -501,10 +499,10 @@ struct JSScope : public JSObjectMap
struct JSEmptyScope : public JSScope struct JSEmptyScope : public JSScope
{ {
JSClass * const clasp; js::Class * const clasp;
jsrefcount nrefs; /* count of all referencing objects */ jsrefcount nrefs; /* count of all referencing objects */
JSEmptyScope(JSContext *cx, const JSObjectOps *ops, JSClass *clasp); JSEmptyScope(JSContext *cx, const JSObjectOps *ops, js::Class *clasp);
void hold() { void hold() {
/* The method is only called for already held objects. */ /* The method is only called for already held objects. */
@ -554,7 +552,7 @@ JSObject::shape() const
return map->shape; return map->shape;
} }
inline jsval inline const js::Value &
JSObject::lockedGetSlot(uintN slot) const JSObject::lockedGetSlot(uintN slot) const
{ {
OBJ_CHECK_SLOT(this, slot); OBJ_CHECK_SLOT(this, slot);
@ -562,28 +560,12 @@ JSObject::lockedGetSlot(uintN slot) const
} }
inline void inline void
JSObject::lockedSetSlot(uintN slot, jsval value) JSObject::lockedSetSlot(uintN slot, const js::Value &value)
{ {
OBJ_CHECK_SLOT(this, slot); OBJ_CHECK_SLOT(this, slot);
this->setSlot(slot, value); this->setSlot(slot, value);
} }
/*
* Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
* and setters.
*/
inline JSObject *
js_CastAsObject(JSPropertyOp op)
{
return JS_FUNC_TO_DATA_PTR(JSObject *, op);
}
inline jsval
js_CastAsObjectJSVal(JSPropertyOp op)
{
return OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, op));
}
namespace js { namespace js {
class PropertyTree; class PropertyTree;
} }
@ -595,23 +577,23 @@ struct JSScopeProperty {
uint32 number, void *arg); uint32 number, void *arg);
friend void js::SweepScopeProperties(JSContext *cx); friend void js::SweepScopeProperties(JSContext *cx);
jsid id; /* int-tagged jsval/untagged JSAtom* */ jsid id;
private: private:
union { union {
JSPropertyOp rawGetter; /* getter and setter hooks or objects */ js::PropertyOp rawGetter; /* getter and setter hooks or objects */
JSScopeProperty *next; /* next node in freelist */ JSScopeProperty *next; /* next node in freelist */
}; };
union { union {
JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0 js::PropertyOp rawSetter; /* getter is JSObject* and setter is 0
if sprop->isMethod() */ if sprop->isMethod() */
JSScopeProperty **prevp; /* pointer to previous node's next, or JSScopeProperty **prevp; /* pointer to previous node's next, or
pointer to head of freelist */ pointer to head of freelist */
}; };
void insertFree(JSScopeProperty *&list) { void insertFree(JSScopeProperty *&list) {
id = JSVAL_NULL; id = JSID_NULL;
next = list; next = list;
prevp = &list; prevp = &list;
if (list) if (list)
@ -620,7 +602,7 @@ struct JSScopeProperty {
} }
void removeFree() { void removeFree() {
JS_ASSERT(JSVAL_IS_NULL(id)); JS_ASSERT(JSID_IS_NULL(id));
*prevp = next; *prevp = next;
if (next) if (next)
next->prevp = prevp; next->prevp = prevp;
@ -665,15 +647,15 @@ struct JSScopeProperty {
IN_DICTIONARY = 0x20 IN_DICTIONARY = 0x20
}; };
JSScopeProperty(jsid id, JSPropertyOp getter, JSPropertyOp setter, uint32 slot, JSScopeProperty(jsid id, js::PropertyOp getter, js::PropertyOp setter, uint32 slot,
uintN attrs, uintN flags, intN shortid) uintN attrs, uintN flags, intN shortid)
: id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)), : id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)),
flags(uint8(flags)), shortid(int16(shortid)) flags(uint8(flags)), shortid(int16(shortid))
{ {
JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER),
JSVAL_TO_OBJECT(getterValue())->isCallable()); getterObject()->isCallable());
JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER), JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER),
JSVAL_TO_OBJECT(setterValue())->isCallable()); setterObject()->isCallable());
} }
bool marked() const { return (flags & MARK) != 0; } bool marked() const { return (flags & MARK) != 0; }
@ -702,50 +684,55 @@ struct JSScopeProperty {
JSObject *methodObject() const { JSObject *methodObject() const {
JS_ASSERT(isMethod()); JS_ASSERT(isMethod());
return js_CastAsObject(rawGetter); return CastAsObject(rawGetter);
} }
jsval methodValue() const { js::Value methodValue() const {
JS_ASSERT(isMethod()); JS_ASSERT(isMethod());
return js_CastAsObjectJSVal(rawGetter); return js::FunObjValue(*CastAsObject(rawGetter));
} }
JSPropertyOp getter() const { return rawGetter; } js::PropertyOp getter() const { return rawGetter; }
bool hasDefaultGetter() const { return !rawGetter; } bool hasDefaultGetter() const { return !rawGetter; }
JSPropertyOp getterOp() const { js::PropertyOp getterOp() const {
JS_ASSERT(!hasGetterValue()); JS_ASSERT(!hasGetterValue());
return rawGetter; return rawGetter;
} }
JSObject *getterObject() const { JSObject *getterObject() const {
JS_ASSERT(hasGetterValue()); JS_ASSERT(hasGetterValue());
return js_CastAsObject(rawGetter); return CastAsObject(rawGetter);
} }
jsval getterValue() const { js::Value getterValue() const {
JS_ASSERT(hasGetterValue()); JS_ASSERT(hasGetterValue());
return rawGetter ? js_CastAsObjectJSVal(rawGetter) : JSVAL_VOID; if (rawGetter)
return js::FunObjValue(*CastAsObject(rawGetter));
return js::UndefinedValue();
} }
JSPropertyOp setter() const { return rawSetter; } js::PropertyOp setter() const { return rawSetter; }
bool hasDefaultSetter() const { return !rawSetter; } bool hasDefaultSetter() const { return !rawSetter; }
JSPropertyOp setterOp() const { js::PropertyOp setterOp() const {
JS_ASSERT(!hasSetterValue()); JS_ASSERT(!hasSetterValue());
return rawSetter; return rawSetter;
} }
JSObject *setterObject() const { JSObject *setterObject() const {
JS_ASSERT(hasSetterValue() && rawSetter); JS_ASSERT(hasSetterValue() && rawSetter);
return js_CastAsObject(rawSetter); return CastAsObject(rawSetter);
} }
jsval setterValue() const { js::Value setterValue() const {
JS_ASSERT(hasSetterValue()); JS_ASSERT(hasSetterValue());
return rawSetter ? js_CastAsObjectJSVal(rawSetter) : JSVAL_VOID; if (rawSetter)
return js::FunObjValue(*CastAsObject(rawSetter));
return js::UndefinedValue();
} }
inline JSDHashNumber hash() const; inline JSDHashNumber hash() const;
inline bool matches(const JSScopeProperty *p) const; inline bool matches(const JSScopeProperty *p) const;
inline bool matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot, inline bool matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter,
uintN aattrs, uintN aflags, intN ashortid) const; uint32 aslot, uintN aattrs, uintN aflags,
intN ashortid) const;
bool get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp); bool get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp);
bool set(JSContext* cx, JSObject* obj, jsval* vp); bool set(JSContext* cx, JSObject *obj, js::Value* vp);
inline bool isSharedPermanent() const; inline bool isSharedPermanent() const;
@ -815,7 +802,7 @@ JSScope::hasProperty(JSScopeProperty *sprop)
inline JSScopeProperty * inline JSScopeProperty *
JSScope::lastProperty() const JSScope::lastProperty() const
{ {
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
return lastProp; return lastProp;
} }
@ -826,8 +813,8 @@ JSScope::lastProperty() const
inline void inline void
JSScope::setLastProperty(JSScopeProperty *sprop) JSScope::setLastProperty(JSScopeProperty *sprop)
{ {
JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT(!JSID_IS_NULL(sprop->id));
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
lastProp = sprop; lastProp = sprop;
} }
@ -836,7 +823,7 @@ inline void
JSScope::removeLastProperty() JSScope::removeLastProperty()
{ {
JS_ASSERT(!inDictionaryMode()); JS_ASSERT(!inDictionaryMode());
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); JS_ASSERT_IF(lastProp->parent, !JSID_IS_NULL(lastProp->parent->id));
lastProp = lastProp->parent; lastProp = lastProp->parent;
--entryCount; --entryCount;
@ -848,12 +835,12 @@ JSScope::removeDictionaryProperty(JSScopeProperty *sprop)
JS_ASSERT(inDictionaryMode()); JS_ASSERT(inDictionaryMode());
JS_ASSERT(sprop->inDictionary()); JS_ASSERT(sprop->inDictionary());
JS_ASSERT(sprop->childp); JS_ASSERT(sprop->childp);
JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT(!JSID_IS_NULL(sprop->id));
JS_ASSERT(lastProp->inDictionary()); JS_ASSERT(lastProp->inDictionary());
JS_ASSERT(lastProp->childp == &lastProp); JS_ASSERT(lastProp->childp == &lastProp);
JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id)); JS_ASSERT_IF(lastProp != sprop, !JSID_IS_NULL(lastProp->id));
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); JS_ASSERT_IF(lastProp->parent, !JSID_IS_NULL(lastProp->parent->id));
if (sprop->parent) if (sprop->parent)
sprop->parent->childp = sprop->childp; sprop->parent->childp = sprop->childp;
@ -871,12 +858,12 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
*/ */
JS_ASSERT(sprop->inDictionary()); JS_ASSERT(sprop->inDictionary());
JS_ASSERT(!sprop->childp); JS_ASSERT(!sprop->childp);
JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT(!JSID_IS_NULL(sprop->id));
JS_ASSERT_IF(*childp, (*childp)->inDictionary()); JS_ASSERT_IF(*childp, (*childp)->inDictionary());
JS_ASSERT_IF(lastProp, lastProp->inDictionary()); JS_ASSERT_IF(lastProp, lastProp->inDictionary());
JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp); JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp);
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
sprop->parent = *childp; sprop->parent = *childp;
*childp = sprop; *childp = sprop;
@ -891,8 +878,8 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
* than id when calling sprop's getter or setter. * than id when calling sprop's getter or setter.
*/ */
#define SPROP_USERID(sprop) \ #define SPROP_USERID(sprop) \
((sprop)->hasShortID() ? INT_TO_JSVAL((sprop)->shortid) \ ((sprop)->hasShortID() ? INT_TO_JSID((sprop)->shortid) \
: ID_TO_VALUE((sprop)->id)) : (sprop)->id)
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot) #define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope) #define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
@ -961,7 +948,7 @@ JSScope::search(jsid id, bool adding)
#undef METER #undef METER
inline bool inline bool
JSScope::canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp) JSScope::canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp)
{ {
/* /*
* An empty scope cannot provide another empty scope, or wrongful two-level * An empty scope cannot provide another empty scope, or wrongful two-level
@ -973,19 +960,18 @@ JSScope::canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp)
} }
inline bool inline bool
JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp) JSScopeProperty::get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp)
{ {
JS_ASSERT(!JSVAL_IS_NULL(this->id)); JS_ASSERT(!JSID_IS_NULL(this->id));
JS_ASSERT(!hasDefaultGetter()); JS_ASSERT(!hasDefaultGetter());
if (hasGetterValue()) { if (hasGetterValue()) {
JS_ASSERT(!isMethod()); JS_ASSERT(!isMethod());
jsval fval = getterValue(); return js::InternalGetOrSet(cx, obj, id, getterValue(), JSACC_READ, 0, 0, vp);
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_READ, 0, 0, vp);
} }
if (isMethod()) { if (isMethod()) {
*vp = methodValue(); vp->copy(methodValue());
JSScope *scope = pobj->scope(); JSScope *scope = pobj->scope();
JS_ASSERT(scope->object == pobj); JS_ASSERT(scope->object == pobj);
@ -999,19 +985,17 @@ JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp)
* but with objects do. * but with objects do.
*/ */
if (obj->getClass() == &js_WithClass) if (obj->getClass() == &js_WithClass)
obj = obj->map->ops->thisObject(cx, obj); obj = obj->thisObject(cx);
return getterOp()(cx, obj, SPROP_USERID(this), vp); return getterOp()(cx, obj, SPROP_USERID(this), vp);
} }
inline bool inline bool
JSScopeProperty::set(JSContext* cx, JSObject* obj, jsval* vp) JSScopeProperty::set(JSContext* cx, JSObject *obj, js::Value* vp)
{ {
JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue()); JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
if (attrs & JSPROP_SETTER) { if (attrs & JSPROP_SETTER)
jsval fval = setterValue(); return js::InternalGetOrSet(cx, obj, id, setterValue(), JSACC_WRITE, 1, vp, vp);
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
}
if (attrs & JSPROP_GETTER) if (attrs & JSPROP_GETTER)
return !!js_ReportGetterOnlyAssignment(cx); return !!js_ReportGetterOnlyAssignment(cx);
@ -1034,8 +1018,6 @@ js_GetMutableScope(JSContext *cx, JSObject *obj);
extern void extern void
js_TraceId(JSTracer *trc, jsid id); js_TraceId(JSTracer *trc, jsid id);
JS_END_EXTERN_C
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#pragma warning(pop) #pragma warning(pop)

View File

@ -47,7 +47,7 @@
#include "jsscope.h" #include "jsscope.h"
inline JSEmptyScope * inline JSEmptyScope *
JSScope::createEmptyScope(JSContext *cx, JSClass *clasp) JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
{ {
JS_ASSERT(!emptyScope); JS_ASSERT(!emptyScope);
emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp); emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
@ -55,7 +55,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
} }
inline JSEmptyScope * inline JSEmptyScope *
JSScope::getEmptyScope(JSContext *cx, JSClass *clasp) JSScope::getEmptyScope(JSContext *cx, js::Class *clasp)
{ {
if (emptyScope) { if (emptyScope) {
JS_ASSERT(clasp == emptyScope->clasp); JS_ASSERT(clasp == emptyScope->clasp);
@ -66,7 +66,7 @@ JSScope::getEmptyScope(JSContext *cx, JSClass *clasp)
} }
inline bool inline bool
JSScope::ensureEmptyScope(JSContext *cx, JSClass *clasp) JSScope::ensureEmptyScope(JSContext *cx, js::Class *clasp)
{ {
if (emptyScope) { if (emptyScope) {
JS_ASSERT(clasp == emptyScope->clasp); JS_ASSERT(clasp == emptyScope->clasp);
@ -114,44 +114,50 @@ JSScope::extend(JSContext *cx, JSScopeProperty *sprop)
* objects optimized as typically non-escaping, ad-hoc methods in obj. * objects optimized as typically non-escaping, ad-hoc methods in obj.
*/ */
inline bool inline bool
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp) JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp)
{ {
JS_ASSERT(hasMethodBarrier()); JS_ASSERT(hasMethodBarrier());
JS_ASSERT(hasProperty(sprop)); JS_ASSERT(hasProperty(sprop));
JS_ASSERT(sprop->isMethod()); JS_ASSERT(sprop->isMethod());
JS_ASSERT(sprop->methodValue() == *vp); JS_ASSERT(sprop->methodValue().isSame(*vp));
JS_ASSERT(object->getClass() == &js_ObjectClass); JS_ASSERT(object->getClass() == &js_ObjectClass);
JSObject *funobj = JSVAL_TO_OBJECT(*vp); JSObject *funobj = &vp->asFunObj();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun)); JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun));
funobj = CloneFunctionObject(cx, fun, funobj->getParent()); funobj = CloneFunctionObject(cx, fun, funobj->getParent());
if (!funobj) if (!funobj)
return false; return false;
*vp = OBJECT_TO_JSVAL(funobj); vp->setFunObj(*funobj);
return !!js_SetPropertyHelper(cx, object, sprop->id, 0, vp); return !!js_SetPropertyHelper(cx, object, sprop->id, 0, vp);
} }
static JS_ALWAYS_INLINE bool
ChangesMethodValue(const js::Value &prev, const js::Value &v)
{
return prev.isFunObj() &&
(!v.isFunObj() || &v.asFunObj() != &prev.asFunObj());
}
inline bool inline bool
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v) JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop,
const js::Value &v)
{ {
if (flags & (BRANDED | METHOD_BARRIER)) { if (flags & (BRANDED | METHOD_BARRIER)) {
jsval prev = object->lockedGetSlot(sprop->slot); const js::Value &prev = object->lockedGetSlot(sprop->slot);
if (ChangesMethodValue(prev, v))
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
return methodShapeChange(cx, sprop, v); return methodShapeChange(cx, sprop, v);
} }
return true; return true;
} }
inline bool inline bool
JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, jsval v) JSScope::methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v)
{ {
if (flags & (BRANDED | METHOD_BARRIER)) { if (flags & (BRANDED | METHOD_BARRIER)) {
jsval prev = object->lockedGetSlot(slot); const js::Value &prev = object->lockedGetSlot(slot);
if (ChangesMethodValue(prev, v))
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
return methodShapeChange(cx, slot, v); return methodShapeChange(cx, slot, v);
} }
return true; return true;
@ -231,18 +237,18 @@ JSScopeProperty::hash() const
inline bool inline bool
JSScopeProperty::matches(const JSScopeProperty *p) const JSScopeProperty::matches(const JSScopeProperty *p) const
{ {
JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT(!JSID_IS_NULL(id));
JS_ASSERT(!JSVAL_IS_NULL(p->id)); JS_ASSERT(!JSID_IS_NULL(p->id));
return id == p->id && return id == p->id &&
matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags, matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags,
p->shortid); p->shortid);
} }
inline bool inline bool
JSScopeProperty::matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot, JSScopeProperty::matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter, uint32 aslot,
uintN aattrs, uintN aflags, intN ashortid) const uintN aattrs, uintN aflags, intN ashortid) const
{ {
JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT(!JSID_IS_NULL(id));
return rawGetter == agetter && return rawGetter == agetter &&
rawSetter == asetter && rawSetter == asetter &&
slot == aslot && slot == aslot &&

View File

@ -402,7 +402,7 @@ script_trace(JSTracer *trc, JSObject *obj)
js_TraceScript(trc, script); js_TraceScript(trc, script);
} }
JSClass js_ScriptClass = { Class js_ScriptClass = {
"Script", "Script",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSCRIPT_RESERVED_SLOTS) | JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSCRIPT_RESERVED_SLOTS) |
JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object), JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),

View File

@ -227,7 +227,7 @@ StackDepth(JSScript *script)
} \ } \
JS_END_MACRO JS_END_MACRO
extern JS_FRIEND_DATA(JSClass) js_ScriptClass; extern JS_FRIEND_DATA(js::Class) js_ScriptClass;
extern JSObject * extern JSObject *
js_InitScriptClass(JSContext *cx, JSObject *obj); js_InitScriptClass(JSContext *cx, JSObject *obj);

View File

@ -799,7 +799,7 @@ str_substring(JSContext *cx, uintN argc, jsval *vp)
static JSString* FASTCALL static JSString* FASTCALL
String_p_toString(JSContext* cx, JSObject* obj) String_p_toString(JSContext* cx, JSObject* obj)
{ {
if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL)) if (!InstanceOf(cx, obj, &js_StringClass, NULL))
return NULL; return NULL;
jsval v = obj->fslots[JSSLOT_PRIMITIVE_THIS]; jsval v = obj->fslots[JSSLOT_PRIMITIVE_THIS];
JS_ASSERT(JSVAL_IS_STRING(v)); JS_ASSERT(JSVAL_IS_STRING(v));
@ -3230,8 +3230,8 @@ js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
return js_GetStringBytes(cx, str); return js_GetStringBytes(cx, str);
} }
JS_FRIEND_API(JSString *) JSString *
js_ValueToString(JSContext *cx, jsval v) js_ValueToString(JSContext *cx, const Value &v)
{ {
JSString *str; JSString *str;
@ -3265,7 +3265,7 @@ AppendAtom(JSAtom *atom, JSCharBuffer &cb)
} }
/* This function implements E-262-3 section 9.8, toString. */ /* This function implements E-262-3 section 9.8, toString. */
JS_FRIEND_API(JSBool) JSBool
js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb) js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb)
{ {
if (!JSVAL_IS_PRIMITIVE(v) && !JSVAL_TO_OBJECT(v)->defaultValue(cx, JSTYPE_STRING, &v)) if (!JSVAL_IS_PRIMITIVE(v) && !JSVAL_TO_OBJECT(v)->defaultValue(cx, JSTYPE_STRING, &v))

View File

@ -54,8 +54,6 @@
#include "jshashtable.h" #include "jshashtable.h"
#include "jslock.h" #include "jslock.h"
JS_BEGIN_EXTERN_C
#define JSSTRING_BIT(n) ((size_t)1 << (n)) #define JSSTRING_BIT(n) ((size_t)1 << (n))
#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1) #define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
@ -471,7 +469,7 @@ JS_ISSPACE(jschar c)
#define JS7_ISLET(c) ((c) < 128 && isalpha(c)) #define JS7_ISLET(c) ((c) < 128 && isalpha(c))
/* Initialize the String class, returning its prototype object. */ /* Initialize the String class, returning its prototype object. */
extern JSClass js_StringClass; extern js::Class js_StringClass;
extern JSObject * extern JSObject *
js_InitStringClass(JSContext *cx, JSObject *obj); js_InitStringClass(JSContext *cx, JSObject *obj);
@ -511,10 +509,10 @@ js_NewStringCopyZ(JSContext *cx, const jschar *s);
/* /*
* Convert a value to a printable C string. * Convert a value to a printable C string.
*/ */
typedef JSString *(*JSValueToStringFun)(JSContext *cx, jsval v); typedef JSString *(*JSValueToStringFun)(JSContext *cx, const js::Value &v);
extern JS_FRIEND_API(const char *) extern JS_FRIEND_API(const char *)
js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun); js_ValueToPrintable(JSContext *cx, const js::Value &, JSValueToStringFun v2sfun);
#define js_ValueToPrintableString(cx,v) \ #define js_ValueToPrintableString(cx,v) \
js_ValueToPrintable(cx, v, js_ValueToString) js_ValueToPrintable(cx, v, js_ValueToString)
@ -526,23 +524,23 @@ js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun);
* Convert a value to a string, returning null after reporting an error, * Convert a value to a string, returning null after reporting an error,
* otherwise returning a new string reference. * otherwise returning a new string reference.
*/ */
extern JS_FRIEND_API(JSString *) extern JSString *
js_ValueToString(JSContext *cx, jsval v); js_ValueToString(JSContext *cx, const js::Value &v);
/* /*
* This function implements E-262-3 section 9.8, toString. Convert the given * This function implements E-262-3 section 9.8, toString. Convert the given
* value to a string of jschars appended to the given buffer. On error, the * value to a string of jschars appended to the given buffer. On error, the
* passed buffer may have partial results appended. * passed buffer may have partial results appended.
*/ */
extern JS_FRIEND_API(JSBool) extern JSBool
js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb); js_ValueToCharBuffer(JSContext *cx, const js::Value &v, JSCharBuffer &cb);
/* /*
* Convert a value to its source expression, returning null after reporting * Convert a value to its source expression, returning null after reporting
* an error, otherwise returning a new string reference. * an error, otherwise returning a new string reference.
*/ */
extern JS_FRIEND_API(JSString *) extern JS_FRIEND_API(JSString *)
js_ValueToSource(JSContext *cx, jsval v); js_ValueToSource(JSContext *cx, const js::Value &v);
/* /*
* Compute a hash function from str. The caller can call this function even if * Compute a hash function from str. The caller can call this function even if
@ -713,8 +711,6 @@ js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
extern JSBool extern JSBool
js_String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); js_String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JS_END_EXTERN_C
namespace js { namespace js {
class DeflatedStringCache { class DeflatedStringCache {

View File

@ -343,6 +343,44 @@ PodArrayZero(T (&t)[N])
memset(t, 0, N * sizeof(T)); memset(t, 0, N * sizeof(T));
} }
template <class T>
class AlignedPtrAndFlag
{
uintptr_t bits;
public:
AlignedPtrAndFlag(T *t, bool flag) {
JS_ASSERT((uintptr_t(t) & 1) == 0);
bits = uintptr_t(t) | flag;
}
T *ptr() const {
return (T *)(bits & ~uintptr_t(1));
}
bool flag() const {
return (bits & 1) != 0;
}
void setPtr(T *t) const {
JS_ASSERT((uintptr_t(t) & 1) == 0);
bits = uintptr_t(t) | flag();
}
void setFlag() {
bits |= 1;
}
void unsetFlag() {
bits &= ~uintptr_t(1);
}
void set(T *t, bool flag) {
JS_ASSERT((uintptr_t(t) & 1) == 0);
bits = uintptr_t(t) | flag;
}
};
} /* namespace js */ } /* namespace js */
#endif /* jstl_h_ */ #endif /* jstl_h_ */

View File

@ -11976,7 +11976,7 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
LIns* idx_ins = get(&idx); LIns* idx_ins = get(&idx);
LIns* v_ins = get(&v); LIns* v_ins = get(&v);
if (JS_InstanceOf(cx, obj, &js_ArgumentsClass, NULL)) if (InstanceOf(cx, obj, &js_ArgumentsClass, NULL))
RETURN_STOP_A("can't trace setting elements of the |arguments| object"); RETURN_STOP_A("can't trace setting elements of the |arguments| object");
if (!JSVAL_IS_INT(idx)) { if (!JSVAL_IS_INT(idx)) {
@ -14564,7 +14564,7 @@ TraceRecorder::record_JSOP_CALLPROP()
if (JSVAL_IS_PRIMITIVE(l)) { if (JSVAL_IS_PRIMITIVE(l)) {
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, pcval.toObject()); JSFunction* fun = GET_FUNCTION_PRIVATE(cx, pcval.toObject());
if (!PRIMITIVE_THIS_TEST(fun, l)) if (!PrimitiveThisTest(fun, l))
RETURN_STOP_A("callee does not accept primitive |this|"); RETURN_STOP_A("callee does not accept primitive |this|");
} }

View File

@ -55,7 +55,7 @@ namespace js {
* TypedArray with a size. * TypedArray with a size.
*/ */
struct JS_FRIEND_API(ArrayBuffer) { struct JS_FRIEND_API(ArrayBuffer) {
static JSClass jsclass; static js::Class jsclass;
static JSPropertySpec jsprops[]; static JSPropertySpec jsprops[];
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsval id, jsval *vp); static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
@ -113,11 +113,11 @@ struct JS_FRIEND_API(TypedArray) {
}; };
// and MUST NOT be used to construct new objects. // and MUST NOT be used to construct new objects.
static JSClass fastClasses[TYPE_MAX]; static js::Class fastClasses[TYPE_MAX];
// These are the slow/original classes, used // These are the slow/original classes, used
// fo constructing new objects // fo constructing new objects
static JSClass slowClasses[TYPE_MAX]; static js::Class slowClasses[TYPE_MAX];
static JSPropertySpec jsprops[]; static JSPropertySpec jsprops[];

View File

@ -103,6 +103,18 @@
# ifdef HAVE_VISIBILITY_ATTRIBUTE # ifdef HAVE_VISIBILITY_ATTRIBUTE
# define JS_EXTERNAL_VIS __attribute__((visibility ("default"))) # define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
# if defined(__GNUC__) && __GNUC__ <= 4 && __GNUC_MINOR__ < 5
/*
* GCC wrongly produces a warning when a type with hidden visibility
* (e.g. js::Value) is a member of a local class of a static function.
* This is apparently fixed with GCC 4.5 and above. See:
*
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40145.
*/
# define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION(Name) class __attribute__((visibility ("hidden"))) Name
# else
# define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION class Name
# endif
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) # elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# define JS_EXTERNAL_VIS __global # define JS_EXTERNAL_VIS __global
# else # else

View File

@ -110,7 +110,7 @@ struct JSXDRState {
JSXDRMode mode; JSXDRMode mode;
JSXDROps *ops; JSXDROps *ops;
JSContext *cx; JSContext *cx;
JSClass **registry; js::Class **registry;
uintN numclasses; uintN numclasses;
uintN maxclasses; uintN maxclasses;
void *reghash; void *reghash;
@ -173,12 +173,12 @@ extern JS_PUBLIC_API(JSBool)
JS_XDRScript(JSXDRState *xdr, JSScript **scriptp); JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
extern JS_PUBLIC_API(JSBool) extern JS_PUBLIC_API(JSBool)
JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp); JS_XDRRegisterClass(JSXDRState *xdr, js::Class *clasp, uint32 *lp);
extern JS_PUBLIC_API(uint32) extern JS_PUBLIC_API(uint32)
JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name); JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
extern JS_PUBLIC_API(JSClass *) extern JS_PUBLIC_API(js::Class *)
JS_XDRFindClassById(JSXDRState *xdr, uint32 id); JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
/* /*

View File

@ -41,8 +41,6 @@
#include "jspubtd.h" #include "jspubtd.h"
JS_BEGIN_EXTERN_C
extern const char js_AnyName_str[]; extern const char js_AnyName_str[];
extern const char js_AttributeName_str[]; extern const char js_AttributeName_str[];
extern const char js_isXMLName_str[]; extern const char js_isXMLName_str[];
@ -59,7 +57,7 @@ typedef JSBool
struct JSXMLArray { struct JSXMLArray {
uint32 length; uint32 length;
uint32 capacity; uint32 capacity;
void **vector; js::Value *vector;
JSXMLArrayCursor *cursors; JSXMLArrayCursor *cursors;
}; };
@ -69,11 +67,12 @@ struct JSXMLArrayCursor
uint32 index; uint32 index;
JSXMLArrayCursor *next; JSXMLArrayCursor *next;
JSXMLArrayCursor **prevp; JSXMLArrayCursor **prevp;
void *root; js::Value root;
js::Value null;
JSXMLArrayCursor(JSXMLArray *array) JSXMLArrayCursor(JSXMLArray *array)
: array(array), index(0), next(array->cursors), prevp(&array->cursors), : array(array), index(0), next(array->cursors), prevp(&array->cursors),
root(NULL) root(), null()
{ {
if (next) if (next)
next->prevp = &next; next->prevp = &next;
@ -91,16 +90,18 @@ struct JSXMLArrayCursor
array = NULL; array = NULL;
} }
void *getNext() { const js::Value &getNext() {
if (!array || index >= array->length) if (!array || index >= array->length)
return NULL; return null;
return root = array->vector[index++]; root.copy(array->vector[index++]);
return root;
} }
void *getCurrent() { const js::Value &getCurrent() {
if (!array || index >= array->length) if (!array || index >= array->length)
return NULL; return null;
return root = array->vector[index]; root.copy(array->vector[index]);
return root;
} }
void trace(JSTracer *trc) { void trace(JSTracer *trc) {
@ -108,9 +109,8 @@ struct JSXMLArrayCursor
size_t index = 0; size_t index = 0;
#endif #endif
for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) { for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) {
void *root = cursor->root;
JS_SET_TRACING_INDEX(trc, "cursor_root", index++); JS_SET_TRACING_INDEX(trc, "cursor_root", index++);
js_CallValueTracerIfGCThing(trc, jsval(root)); CallGCMarkerIfGCThing(trc, cursor->root);
} }
} }
}; };
@ -173,7 +173,7 @@ struct JSXML {
} u; } u;
}; };
JS_STATIC_ASSERT(sizeof(JSXML) % JSVAL_ALIGN == 0); JS_STATIC_ASSERT(sizeof(JSXML) % JSBOXEDWORD_ALIGN == 0);
/* union member shorthands */ /* union member shorthands */
#define xml_kids u.list.kids #define xml_kids u.list.kids
@ -209,13 +209,13 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
extern JSObject * extern JSObject *
js_GetXMLObject(JSContext *cx, JSXML *xml); js_GetXMLObject(JSContext *cx, JSXML *xml);
extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps; extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
extern JS_FRIEND_DATA(JSClass) js_XMLClass; extern JS_FRIEND_DATA(js::Class) js_XMLClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass; extern JS_FRIEND_DATA(js::ExtendedClass) js_NamespaceClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass; extern JS_FRIEND_DATA(js::ExtendedClass) js_QNameClass;
extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass; extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass;
extern JS_FRIEND_DATA(JSClass) js_AnyNameClass; extern JS_FRIEND_DATA(js::Class) js_AnyNameClass;
extern JSClass js_XMLFilterClass; extern js::Class js_XMLFilterClass;
/* /*
* Methods to test whether an object or a value is of type "xml" (per typeof). * Methods to test whether an object or a value is of type "xml" (per typeof).
@ -231,8 +231,8 @@ JSObject::isXML() const
} }
#define OBJECT_IS_XML(cx,obj) (obj)->isXML() #define OBJECT_IS_XML(cx,obj) (obj)->isXML()
#define VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \ #define VALUE_IS_XML(cx,v) ((v).isObject() && \
JSVAL_TO_OBJECT(v)->isXML()) (v).asObject().isXML())
extern JSObject * extern JSObject *
js_InitNamespaceClass(JSContext *cx, JSObject *obj); js_InitNamespaceClass(JSContext *cx, JSObject *obj);
@ -253,7 +253,7 @@ extern JSObject *
js_InitXMLClasses(JSContext *cx, JSObject *obj); js_InitXMLClasses(JSContext *cx, JSObject *obj);
extern JSBool extern JSBool
js_GetFunctionNamespace(JSContext *cx, jsval *vp); js_GetFunctionNamespace(JSContext *cx, const js::Value *vp);
/* /*
* If obj is QName corresponding to function::name, set *funidp to name's id, * If obj is QName corresponding to function::name, set *funidp to name's id,
@ -266,7 +266,7 @@ extern JSBool
js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp); js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);
extern JSBool extern JSBool
js_SetDefaultXMLNamespace(JSContext *cx, jsval v); js_SetDefaultXMLNamespace(JSContext *cx, const js::Value &v);
/* /*
* Return true if v is a XML QName object, or if it converts to a string that * Return true if v is a XML QName object, or if it converts to a string that
@ -277,7 +277,7 @@ extern JSBool
js_IsXMLName(JSContext *cx, jsval v); js_IsXMLName(JSContext *cx, jsval v);
extern JSBool extern JSBool
js_ToAttributeName(JSContext *cx, jsval *vp); js_ToAttributeName(JSContext *cx, js::Value *vp);
extern JSString * extern JSString *
js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote); js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
@ -290,25 +290,26 @@ extern JSString *
js_EscapeElementValue(JSContext *cx, JSString *str); js_EscapeElementValue(JSContext *cx, JSString *str);
extern JSString * extern JSString *
js_ValueToXMLString(JSContext *cx, jsval v); js_ValueToXMLString(JSContext *cx, const js::Value &v);
extern JSObject * extern JSObject *
js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval); js_ConstructXMLQNameObject(JSContext *cx, const js::Value & nsval,
const js::Value & lnval);
extern JSBool extern JSBool
js_GetAnyName(JSContext *cx, jsval *vp); js_GetAnyName(JSContext *cx, js::Value *vp);
/* /*
* Note: nameval must be either QName, AttributeName, or AnyName. * Note: nameval must be either QName, AttributeName, or AnyName.
*/ */
extern JSBool extern JSBool
js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp); js_FindXMLProperty(JSContext *cx, const js::Value &nameval, JSObject **objp, jsid *idp);
extern JSBool extern JSBool
js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp); js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
extern JSBool extern JSBool
js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp); js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool extern JSBool
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj); js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
@ -317,10 +318,10 @@ extern JSBool
js_StepXMLListFilter(JSContext *cx, JSBool initialized); js_StepXMLListFilter(JSContext *cx, JSBool initialized);
extern JSObject * extern JSObject *
js_ValueToXMLObject(JSContext *cx, jsval v); js_ValueToXMLObject(JSContext *cx, const js::Value &v);
extern JSObject * extern JSObject *
js_ValueToXMLListObject(JSContext *cx, jsval v); js_ValueToXMLListObject(JSContext *cx, const js::Value &v);
extern JSObject * extern JSObject *
js_CloneXMLObject(JSContext *cx, JSObject *obj); js_CloneXMLObject(JSContext *cx, JSObject *obj);
@ -343,11 +344,10 @@ js_EnumerateXMLValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp, jsval *vp); jsval *statep, jsid *idp, jsval *vp);
extern JSBool extern JSBool
js_TestXMLEquality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp); js_TestXMLEquality(JSContext *cx, const js::Value &v1, const js::Value &v2,
JSBool *bp);
extern JSBool extern JSBool
js_ConcatenateXML(JSContext *cx, JSObject *obj, jsval v, jsval *vp); js_ConcatenateXML(JSContext *cx, JSObject *obj1, JSObject *obj2, js::Value *vp);
JS_END_EXTERN_C
#endif /* jsxml_h___ */ #endif /* jsxml_h___ */