(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,
void *closure)
{
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure));
JSDExecHook* jsdhook = (JSDExecHook*)closure;
JSD_ExecutionHookProc hook;
void* hookData;
JSDContext* jsdc;
@ -800,7 +800,7 @@ jsd_SetExecutionHook(JSDContext* jsdc,
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
(jsbytecode*)pc, jsd_TrapHandler,
(void*) PRIVATE_TO_JSVAL(jsdhook)) )
PRIVATE_TO_JSVAL(jsdhook)) )
{
free(jsdhook);
JSD_UNLOCK();

View File

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

View File

@ -38,8 +38,6 @@
* ***** END LICENSE BLOCK ***** */
#include "jsdbgapi.h"
#include "jscntxt.h"
#include "jsfun.h"
#include "jsd_xpc.h"
#include "nsIXPConnect.h"
@ -1014,7 +1012,8 @@ jsdScript::CreatePPLineMap()
PRBool scriptOwner = PR_FALSE;
if (fun) {
if (fun->nargs > 12)
uintN nargs = JS_GetFunctionArgumentCount(cx, fun);
if (nargs > 12)
return nsnull;
JSString *jsstr = JS_DecompileFunctionBody (cx, fun, 4);
if (!jsstr)
@ -1023,7 +1022,7 @@ jsdScript::CreatePPLineMap()
const char *argnames[] = {"arg1", "arg2", "arg3", "arg4",
"arg5", "arg6", "arg7", "arg8",
"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_GetStringLength(jsstr),
"x-jsd:ppbuffer?type=function", 3);
@ -1232,37 +1231,32 @@ jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
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;
*paramNames = nsnull;
return NS_OK;
}
PRUnichar **ret =
static_cast<PRUnichar**>(NS_Alloc(fun->nargs * sizeof(PRUnichar*)));
static_cast<PRUnichar**>(NS_Alloc(nargs * sizeof(PRUnichar*)));
if (!ret)
return NS_ERROR_OUT_OF_MEMORY;
void *mark = JS_ARENA_MARK(&cx->tempPool);
jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
void *mark;
jsuword *names = JS_GetFunctionLocalNameArray(cx, fun, &mark);
if (!names) {
NS_Free(ret);
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = NS_OK;
for (uintN i = 0; i < fun->nargs; ++i) {
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]);
for (uintN i = 0; i < nargs; ++i) {
JSAtom *atom = JS_LocalNameToAtom(names[i]);
if (!atom) {
ret[i] = 0;
} else {
jsval atomVal = ATOM_KEY(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);
JSString *str = JS_AtomKey(atom);
ret[i] = NS_strndup(reinterpret_cast<PRUnichar*>(JS_GetStringChars(str)),
JS_GetStringLength(str));
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))
return rv;
*count = fun->nargs;
*count = nargs;
*paramNames = ret;
return NS_OK;
}
@ -1484,8 +1478,7 @@ jsdScript::SetBreakpoint(PRUint32 aPC)
{
ASSERT_VALID_EPHEMERAL;
jsuword pc = mFirstPC + aPC;
JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc,
reinterpret_cast<void *>(PRIVATE_TO_JSVAL(NULL)));
JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc, NULL);
return NS_OK;
}
@ -1989,7 +1982,7 @@ jsdStackFrame::Eval (const nsAString &bytes, const nsACString &fileName,
if (JS_IsExceptionPending(cx))
JS_GetPendingException (cx, &jv);
else
jv = 0;
jv = JSVAL_NULL;
}
JS_RestoreExceptionState (cx, estate);
@ -2436,8 +2429,8 @@ jsdService::SetInitAtStartup (PRBool state)
return rv;
}
if (state && mInitAtStartup == triYes ||
!state && mInitAtStartup == triNo) {
if ((state && mInitAtStartup == triYes) ||
(!state && mInitAtStartup == triNo)) {
/* already in the requested state */
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 "jsobj.h"
JS_BEGIN_EXTERN_C
#define ARRAY_CAPACITY_MIN 7
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
JSObject::isDenseArray() const
@ -112,7 +110,7 @@ extern JSObject * JS_FASTCALL
js_NewArrayWithSlots(JSContext* cx, JSObject* proto, uint32 len);
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. */
extern JSObject *
@ -125,7 +123,7 @@ static JS_INLINE uint32
js_DenseArrayCapacity(JSObject *obj)
{
JS_ASSERT(obj->isDenseArray());
return obj->dslots ? (uint32) obj->dslots[-1] : 0;
return obj->dslots ? obj->dslotLength() : 0;
}
static JS_INLINE void
@ -133,7 +131,7 @@ js_SetDenseArrayCapacity(JSObject *obj, uint32 capacity)
{
JS_ASSERT(obj->isDenseArray());
JS_ASSERT(obj->dslots);
obj->dslots[-1] = (jsval) capacity;
obj->dslots[-1].setPrivateUint32(capacity);
}
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
* 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
* comparator function cmp returns an error inside a comparison, so remember
* to check the return value of this function.
*/
extern JSBool
extern bool
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
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
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.
@ -211,11 +211,11 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj);
*/
JSBool
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. */
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
@ -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|.
*/
JS_FRIEND_API(JSObject *)
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, jsval **vector);
JS_END_EXTERN_C
js_NewArrayObjectWithCapacity(JSContext *cx, jsuint capacity, js::Value **vector);
#endif /* jsarray_h___ */

View File

@ -37,6 +37,8 @@
*
* ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/*
* JS atom table.
*/
@ -58,7 +60,13 @@
#include "jsscan.h"
#include "jsstr.h"
#include "jsversion.h"
#include "jsxml.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.
@ -85,7 +93,7 @@ JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
const char *
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;
@ -269,12 +277,12 @@ const char js_current_str[] = "current";
*/
typedef struct JSAtomHashEntry {
JSDHashEntryHdr hdr;
jsuword keyAndFlags;
jsboxedword keyAndFlags;
} JSAtomHashEntry;
#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.
@ -536,8 +544,8 @@ js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT;
}
JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry),
IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
CallGCMarker(trc, ATOM_ENTRY_KEY(entry),
IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
return JS_DHASH_NEXT;
}
@ -556,7 +564,7 @@ js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
? "pinned_atom"
: "interned_atom",
(size_t)number);
js_CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
CallGCMarker(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
}
return JS_DHASH_NEXT;
}
@ -619,7 +627,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
JSAtomHashEntry *entry;
uint32 gen;
jsdouble *key;
jsval v;
jsboxedword w;
state = &cx->runtime->atomState;
table = &state->doubleAtoms;
@ -632,7 +640,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
gen = ++table->generation;
JS_UNLOCK(cx, &state->lock);
key = js_NewWeaklyRootedDouble(cx, d);
key = js_NewWeaklyRootedDoubleAtom(cx, d);
if (!key)
return NULL;
@ -652,11 +660,11 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
}
finish:
v = DOUBLE_TO_JSVAL((jsdouble *)ATOM_ENTRY_KEY(entry));
cx->weakRoots.lastAtom = v;
w = DOUBLE_TO_JSBOXEDWORD((jsdouble *)ATOM_ENTRY_KEY(entry));
cx->weakRoots.lastAtom = (JSAtom *)w;
JS_UNLOCK(cx, &state->lock);
return (JSAtom *)v;
return (JSAtom *)w;
failed_hash_add:
JS_UNLOCK(cx, &state->lock);
@ -667,7 +675,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
jsval v;
JSAtom *atom;
JSAtomState *state;
JSDHashTable *table;
JSAtomHashEntry *entry;
@ -678,13 +686,13 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
if (str->isAtomized())
return (JSAtom *) STRING_TO_JSVAL(str);
return STRING_TO_ATOM(str);
size_t length = str->length();
if (length == 1) {
jschar c = str->chars()[0];
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)
i = i * 10 + chars[2] - '0';
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:
ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED));
JS_ASSERT(key->isAtomized());
v = STRING_TO_JSVAL(key);
cx->weakRoots.lastAtom = v;
atom = STRING_TO_ATOM(key);
cx->weakRoots.lastAtom = atom;
JS_UNLOCK(cx, &state->lock);
return (JSAtom *)v;
return atom;
failed_hash_add:
JS_UNLOCK(cx, &state->lock);
@ -842,7 +850,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
if (length == 1) {
jschar c = *chars;
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);
@ -855,26 +863,26 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
: NULL;
JS_UNLOCK(cx, &state->lock);
return str2 ? (JSAtom *)STRING_TO_JSVAL(str2) : NULL;
return str2 ? STRING_TO_ATOM(str2) : NULL;
}
JSBool
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp)
js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp)
{
JSAtom *atom;
if (JSVAL_IS_STRING(v)) {
atom = js_AtomizeString(cx, JSVAL_TO_STRING(v), 0);
if (JSBOXEDWORD_IS_STRING(w)) {
atom = js_AtomizeString(cx, JSBOXEDWORD_TO_STRING(w), 0);
if (!atom)
return JS_FALSE;
} else if (JSVAL_IS_DOUBLE(v)) {
atom = js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v));
} else if (JSBOXEDWORD_IS_DOUBLE(w)) {
atom = js_AtomizeDouble(cx, *JSBOXEDWORD_TO_DOUBLE(w));
if (!atom)
return JS_FALSE;
} else {
JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_BOOLEAN(v) ||
JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v));
atom = (JSAtom *)v;
JS_ASSERT(JSBOXEDWORD_IS_INT(w) || JSBOXEDWORD_IS_BOOLEAN(w) ||
JSBOXEDWORD_IS_NULL(w) || JSBOXEDWORD_IS_VOID(w));
atom = (JSAtom *)w;
}
*atomp = atom;
return JS_TRUE;
@ -1265,3 +1273,96 @@ js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
}
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 "jslock.h"
JS_BEGIN_EXTERN_C
#define ATOM_PINNED 0x1 /* atom is pinned against GC */
#define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */
#define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */
#define ATOM_KEY(atom) ((jsval)(atom))
#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
#define ATOM_KEY(atom) ((jsboxedword)(atom))
#define ATOM_IS_DOUBLE(atom) JSBOXEDWORD_IS_DOUBLE(ATOM_KEY(atom))
#define ATOM_TO_DOUBLE(atom) JSBOXEDWORD_TO_DOUBLE(ATOM_KEY(atom))
#define ATOM_IS_STRING(atom) JSBOXEDWORD_IS_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
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
@ -88,7 +88,7 @@ struct JSAtomListElement {
#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key)
#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)
/*
@ -119,8 +119,6 @@ struct JSAtomSet {
jsuint count; /* count of indexed literals */
};
#ifdef __cplusplus
struct JSAtomList : public JSAtomSet
{
#ifdef DEBUG
@ -198,8 +196,6 @@ class JSAtomListIterator {
JSAtomListElement* operator ()();
};
#endif /* __cplusplus */
struct JSAtomMap {
JSAtom **vector; /* array of ptrs to 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.
*/
JSBool
js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp);
js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp);
#ifdef DEBUG
@ -494,6 +490,18 @@ js_DumpAtoms(JSContext *cx, FILE *fp);
#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
* 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
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___ */

View File

@ -46,8 +46,8 @@
/*
* Convert v to an atomized string and wrap it as an id.
*/
inline JSBool
js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
inline bool
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp)
{
JSString *str;
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
* is least weakly rooted.
*/
if (JSVAL_IS_STRING(v)) {
str = JSVAL_TO_STRING(v);
if (v.isString()) {
str = v.asString();
if (str->isAtomized()) {
cx->weakRoots.lastAtom = v;
*idp = ATOM_TO_JSID((JSAtom *) v);
return JS_TRUE;
cx->weakRoots.lastAtom = *atomp = STRING_TO_ATOM(str);
return true;
}
} else {
str = js_ValueToString(cx, v);
if (!str)
return JS_FALSE;
return false;
}
atom = js_AtomizeString(cx, str, 0);
if (!atom)
return JS_FALSE;
*idp = ATOM_TO_JSID(atom);
return JS_TRUE;
return false;
*atomp = atom;
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)
{
if (INT_FITS_IN_JSVAL(index)) {
if (INT32_FITS_IN_JSID(index)) {
*id = INT_TO_JSID(index);
JS_ASSERT(INT_JSID_TO_JSVAL(*id) == INT_TO_JSVAL(index));
return JS_TRUE;
return true;
}
JSString* str = js_NumberToString(cx, index);
if (!str)
return JS_FALSE;
return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
return false;
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___ */

View File

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

View File

@ -45,27 +45,7 @@
#include "jsapi.h"
JS_BEGIN_EXTERN_C
/*
* 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 js::Class js_BooleanClass;
extern JSObject *
js_InitBooleanClass(JSContext *cx, JSObject *obj);
@ -77,8 +57,6 @@ extern JSBool
js_BooleanToCharBuffer(JSContext *cx, JSBool b, JSCharBuffer &cb);
extern JSBool
js_ValueToBoolean(jsval v);
JS_END_EXTERN_C
js_ValueToBoolean(const js::Value &v);
#endif /* jsbool_h___ */

View File

@ -222,7 +222,7 @@ struct ClosureVarInfo;
#define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _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_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_CHARPTR _JS_CTYPE(char *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_APNPTR _JS_CTYPE(ArgsPrivateNative *, _JS_PTR, --, --, INFALLIBLE)

View File

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

View File

@ -285,62 +285,71 @@ class CallStack
/* The first frame executed in this callstack. null iff cx is null */
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. */
JSFrameRegs *suspendedRegs;
/* This callstack was suspended by JS_SaveFrameChain. */
bool saved;
/* End of arguments before the first frame. See StackSpace comment. */
jsval *initialArgEnd;
js::Value *initialArgEnd;
/* The varobj on entry to initialFrame. */
JSObject *initialVarObj;
JSStackFrame *suspendedFrame() const {
return suspendedFrameAndSaved.ptr();
}
bool saved() const {
return suspendedFrameAndSaved.flag();
}
public:
CallStack()
: cx(NULL), previousInContext(NULL), previousInThread(NULL),
initialFrame(NULL), suspendedFrame(NULL), saved(false),
initialFrame(NULL), suspendedFrameAndSaved(NULL, false),
initialArgEnd(NULL), initialVarObj(NULL)
{}
/* Safe casts guaranteed by the contiguous-stack layout. */
jsval *previousCallStackEnd() const {
return (jsval *)this;
Value *previousCallStackEnd() const {
return (Value *)this;
}
jsval *getInitialArgBegin() const {
return (jsval *)(this + 1);
Value *getInitialArgBegin() const {
return (Value *)(this + 1);
}
/* The three mutually exclusive states of a callstack */
bool inContext() const {
JS_ASSERT(!!cx == !!initialFrame);
JS_ASSERT_IF(!initialFrame, !suspendedFrame && !saved);
JS_ASSERT_IF(!initialFrame, !suspendedFrame() && !saved());
return cx;
}
bool isActive() const {
JS_ASSERT_IF(suspendedFrame, inContext());
return initialFrame && !suspendedFrame;
JS_ASSERT_IF(suspendedFrame(), inContext());
return initialFrame && !suspendedFrame();
}
bool isSuspended() const {
JS_ASSERT_IF(!suspendedFrame, !saved);
JS_ASSERT_IF(suspendedFrame, inContext());
return suspendedFrame;
JS_ASSERT_IF(!suspendedFrame(), !saved());
JS_ASSERT_IF(suspendedFrame(), inContext());
return !!suspendedFrame();
}
/* Substate of suspended, queryable in any state. */
bool isSaved() const {
JS_ASSERT_IF(saved, isSuspended());
return saved;
JS_ASSERT_IF(saved(), isSuspended());
return saved();
}
/* Transitioning between inContext <--> isActive */
@ -365,37 +374,37 @@ class CallStack
void suspend(JSStackFrame *fp, JSFrameRegs *regs) {
JS_ASSERT(fp && isActive() && contains(fp));
suspendedFrame = fp;
suspendedFrameAndSaved.set(fp, false);
suspendedRegs = regs;
}
void resume() {
JS_ASSERT(suspendedFrame);
suspendedFrame = NULL;
JS_ASSERT(suspendedFrame());
suspendedFrameAndSaved.set(NULL, false);
}
/* When isSuspended, transitioning isSaved <--> !isSaved */
void save(JSStackFrame *fp, JSFrameRegs *regs) {
JS_ASSERT(!saved);
JS_ASSERT(!saved());
suspend(fp, regs);
saved = true;
suspendedFrameAndSaved.setFlag();
}
void restore() {
JS_ASSERT(saved);
saved = false;
JS_ASSERT(saved());
suspendedFrameAndSaved.unsetFlag();
resume();
}
/* Data available when !inContext */
void setInitialArgEnd(jsval *v) {
void setInitialArgEnd(Value *v) {
JS_ASSERT(!inContext() && !initialArgEnd);
initialArgEnd = v;
}
jsval *getInitialArgEnd() const {
Value *getInitialArgEnd() const {
JS_ASSERT(!inContext() && initialArgEnd);
return initialArgEnd;
}
@ -413,7 +422,7 @@ class CallStack
JSStackFrame *getSuspendedFrame() const {
JS_ASSERT(isSuspended());
return suspendedFrame;
return suspendedFrame();
}
JSFrameRegs *getSuspendedRegs() const {
@ -421,7 +430,7 @@ class CallStack
return suspendedRegs;
}
jsval *getSuspendedSP() const {
js::Value *getSuspendedSP() const {
JS_ASSERT(isSuspended());
return suspendedRegs->sp;
}
@ -460,8 +469,8 @@ class CallStack
};
JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(jsval) == 0);
static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(jsval);
JS_STATIC_ASSERT(sizeof(CallStack) % sizeof(Value) == 0);
static const size_t ValuesPerCallStack = sizeof(CallStack) / sizeof(Value);
/*
* The ternary constructor is used when arguments are already pushed on the
@ -473,13 +482,13 @@ class InvokeArgsGuard
friend class StackSpace;
JSContext *cx;
CallStack *cs; /* null implies nothing pushed */
jsval *vp;
Value *vp;
uintN argc;
public:
inline InvokeArgsGuard();
inline InvokeArgsGuard(jsval *vp, uintN argc);
inline InvokeArgsGuard(Value *vp, uintN argc);
inline ~InvokeArgsGuard();
jsval *getvp() const { return vp; }
Value *getvp() const { return vp; }
uintN getArgc() const { JS_ASSERT(vp != NULL); return argc; }
};
@ -502,13 +511,13 @@ class ExecuteFrameGuard
friend class StackSpace;
JSContext *cx; /* null implies nothing pushed */
CallStack *cs;
jsval *vp;
Value *vp;
JSStackFrame *fp;
JSStackFrame *down;
public:
ExecuteFrameGuard();
JS_REQUIRES_STACK ~ExecuteFrameGuard();
jsval *getvp() const { return vp; }
Value *getvp() const { return vp; }
JSStackFrame *getFrame() const { return fp; }
};
@ -537,7 +546,7 @@ class ExecuteFrameGuard
* ? <----' `----------' `----------'
*
* 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.
*
* An empty callstack roots the initial slots before the initial frame is
@ -570,16 +579,16 @@ class ExecuteFrameGuard
*/
class StackSpace
{
jsval *base;
Value *base;
#ifdef XP_WIN
mutable jsval *commitEnd;
mutable Value *commitEnd;
#endif
jsval *end;
Value *end;
CallStack *currentCallStack;
/* Although guards are friends, XGuard should only call popX(). */
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;
JS_REQUIRES_STACK void popInvokeFrame(JSContext *cx, CallStack *maybecs);
friend class ExecuteFrameGuard;
@ -587,7 +596,7 @@ class StackSpace
/* Return a pointer to the first unused slot. */
JS_REQUIRES_STACK
inline jsval *firstUnused() const;
inline Value *firstUnused() const;
#ifdef DEBUG
inline bool isCurrent(JSContext *cx) const;
@ -598,18 +607,18 @@ class StackSpace
* Return whether nvals can be allocated from the top of the stack.
* 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
/* 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
public:
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 sCommitBytes = sCommitVals * sizeof(jsval);
static const size_t sCommitBytes = sCommitVals * sizeof(Value);
JS_STATIC_ASSERT(sCapacityVals % sCommitVals == 0);
@ -694,7 +703,7 @@ class StackSpace
* call pushInlineFrame/popInlineFrame.
*/
JS_REQUIRES_STACK
inline JSStackFrame *getInlineFrame(JSContext *cx, jsval *sp,
inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp,
uintN nmissing, uintN nslots) const;
JS_REQUIRES_STACK
@ -737,7 +746,7 @@ class FrameRegsIter
{
CallStack *curcs;
JSStackFrame *curfp;
jsval *cursp;
Value *cursp;
jsbytecode *curpc;
public:
@ -747,7 +756,7 @@ class FrameRegsIter
FrameRegsIter &operator++();
JSStackFrame *fp() const { return curfp; }
jsval *sp() const { return cursp; }
Value *sp() const { return cursp; }
jsbytecode *pc() const { return curpc; }
};
@ -923,7 +932,7 @@ struct JSLocalRootChunk;
#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT)
struct JSLocalRootChunk {
jsval roots[JSLRS_CHUNK_SIZE];
void *roots[JSLRS_CHUNK_SIZE];
JSLocalRootChunk *down;
};
@ -1141,12 +1150,24 @@ struct JSClassProtoCache {
#endif
friend JSBool js_GetClassPrototype(JSContext *cx, JSObject *scope,
JSProtoKey protoKey, JSObject **protop,
JSClass *clasp);
js::Class *clasp);
#ifdef __GNUC__
# pragma GCC visibility pop
#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 {
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
JSRuntimeState state;
@ -1172,7 +1193,7 @@ struct JSRuntime {
JSGCChunkInfo *gcChunkList;
JSGCArenaList gcArenaList[FINALIZE_LIMIT];
JSGCDoubleArenaList gcDoubleArenaList;
JSDHashTable gcRootsHash;
JSRootedValueMap gcRootsHash;
JSDHashTable gcLocksHash;
jsrefcount gcKeepAtoms;
size_t gcBytes;
@ -1249,9 +1270,9 @@ struct JSRuntime {
JSSetSlotRequest *setSlotRequests;
/* Well-known numbers held for use by this runtime's contexts. */
jsval NaNValue;
jsval negativeInfinityValue;
jsval positiveInfinityValue;
js::Value NaNValue;
js::Value negativeInfinityValue;
js::Value positiveInfinityValue;
js::DeflatedStringCache *deflatedStringCache;
@ -1640,7 +1661,7 @@ struct JSContext
/*
* cx->resolvingTable is non-null and non-empty if we are initializing
* 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).
*/
JSDHashTable *resolvingTable;
@ -1656,7 +1677,7 @@ struct JSContext
/* Exception state -- the exception member is a GC root by definition. */
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. */
jsuword stackLimit;
@ -1680,7 +1701,7 @@ struct JSContext
private:
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. */
void setCurrentFrame(JSStackFrame *fp) {
@ -2034,8 +2055,8 @@ struct JSContext
#ifdef DEBUG
void assertValidStackDepth(uintN depth) {
JS_ASSERT(0 <= regs->sp - StackBase(fp));
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(fp)));
JS_ASSERT(0 <= regs->sp - fp->base());
JS_ASSERT(depth <= uintptr_t(regs->sp - fp->base()));
}
#else
void assertValidStackDepth(uintN /*depth*/) {}
@ -2124,7 +2145,7 @@ class AutoGCRooter {
/*
* 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
* below. Any other negative value indicates some deeper problem such as
* memory corruption.
@ -2171,48 +2192,49 @@ class AutoSaveWeakRoots : private AutoGCRooter
class AutoValueRooter : private AutoGCRooter
{
public:
explicit AutoValueRooter(JSContext *cx, jsval v = JSVAL_NULL
explicit AutoValueRooter(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(v)
: AutoGCRooter(cx, JSVAL), val(js::NullValue())
{
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
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(STRING_TO_JSVAL(str))
: AutoGCRooter(cx, JSVAL), val(str)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
AutoValueRooter(JSContext *cx, JSObject *obj
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, JSVAL), val(OBJECT_TO_JSVAL(obj))
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
void setObject(JSObject *obj) {
JS_ASSERT(tag == JSVAL);
val = OBJECT_TO_JSVAL(obj);
}
/*
* If you are looking for Object* overloads, use AutoObjectRooter instead;
* rooting Object*s as a js::Value requires discerning whether or not it is
* a function object. Also, AutoObjectRooter is smaller.
*/
void setString(JSString *str) {
JS_ASSERT(tag == JSVAL);
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(dp);
val = DOUBLE_TO_JSVAL(dp);
JS_ASSERT(d);
val.setDouble(d);
}
jsval value() const {
const Value &value() const {
JS_ASSERT(tag == JSVAL);
return val;
}
jsval *addr() {
Value *addr() {
JS_ASSERT(tag == JSVAL);
return &val;
}
@ -2220,7 +2242,7 @@ class AutoValueRooter : private AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc);
private:
jsval val;
Value val;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
@ -2254,7 +2276,7 @@ class AutoObjectRooter : private AutoGCRooter {
class AutoArrayRooter : private AutoGCRooter {
public:
AutoArrayRooter(JSContext *cx, size_t len, jsval *vec
AutoArrayRooter(JSContext *cx, size_t len, Value *vec
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, len), array(vec)
{
@ -2267,12 +2289,12 @@ class AutoArrayRooter : private AutoGCRooter {
JS_ASSERT(tag >= 0);
}
void changeArray(jsval *newArray, size_t newLength) {
void changeArray(Value *newArray, size_t newLength) {
changeLength(newLength);
array = newArray;
}
jsval *array;
Value *array;
friend void AutoGCRooter::trace(JSTracer *trc);
@ -2385,14 +2407,14 @@ class AutoEnumStateRooter : private AutoGCRooter
public:
AutoEnumStateRooter(JSContext *cx, JSObject *obj
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_ASSERT(obj);
}
~AutoEnumStateRooter() {
if (!JSVAL_IS_NULL(stateValue)) {
if (!stateValue.isNull()) {
#ifdef DEBUG
JSBool ok =
#endif
@ -2403,8 +2425,8 @@ class AutoEnumStateRooter : private AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc);
jsval state() const { return stateValue; }
jsval * addr() { return &stateValue; }
const Value &state() const { return stateValue; }
Value *addr() { return &stateValue; }
protected:
void trace(JSTracer *trc) {
@ -2415,7 +2437,7 @@ class AutoEnumStateRooter : private AutoGCRooter
JSObject * const obj;
private:
jsval stateValue;
Value stateValue;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
@ -2624,7 +2646,7 @@ js_WaitForGC(JSRuntime *rt);
#endif
/*
* JSClass.resolve and watchpoint recursion damping machinery.
* Class.resolve and watchpoint recursion damping machinery.
*/
extern JSBool
js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
@ -2636,26 +2658,21 @@ js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
/*
* 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
js_EnterLocalRootScope(JSContext *cx);
#define js_LeaveLocalRootScope(cx) \
js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL)
js_LeaveLocalRootScopeWithResult(cx, sNullValue)
extern void
js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
js_LeaveLocalRootScopeWithResult(JSContext *cx, const js::Value &rval);
extern void
js_ForgetLocalRoot(JSContext *cx, jsval v);
js_ForgetLocalRoot(JSContext *cx, void *thing);
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
@ -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).
*/
extern JSBool
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, const js::Value &v,
JSString *fallback);
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
@ -2740,7 +2757,7 @@ js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
*/
extern JSBool
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);
#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
@ -2825,7 +2842,7 @@ LeaveTrace(JSContext *cx)
static JS_INLINE void
LeaveTraceIfGlobalObject(JSContext *cx, JSObject *obj)
{
if (!obj->fslots[JSSLOT_PARENT])
if (obj->fslots[JSSLOT_PARENT].isNull())
LeaveTrace(cx);
}
@ -2916,10 +2933,10 @@ class AutoValueVector : private AutoGCRooter
size_t length() const { return vector.length(); }
bool push(jsval v) { return vector.append(v); }
bool push(JSString *str) { return push(STRING_TO_JSVAL(str)); }
bool push(JSObject *obj) { return push(OBJECT_TO_JSVAL(obj)); }
bool push(jsdouble *dp) { return push(DOUBLE_TO_JSVAL(dp)); }
bool push(const js::Value &v) { return vector.append(v); }
bool push(JSString *str) { return push(str); }
bool push(JSObject *obj) { return push(obj); }
bool push(jsdouble d) { return push(d); }
void pop() { vector.popBack(); }
@ -2933,16 +2950,16 @@ class AutoValueVector : private AutoGCRooter
return vector.reserve(newLength);
}
jsval &operator[](size_t i) { return vector[i]; }
jsval operator[](size_t i) const { return vector[i]; }
const js::Value &operator[](size_t i) { return vector[i]; }
const js::Value &operator[](size_t i) const { return vector[i]; }
const jsval *buffer() const { return vector.begin(); }
jsval *buffer() { return vector.begin(); }
const js::Value *buffer() const { return vector.begin(); }
const js::Value *buffer() { return vector.begin(); }
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<jsval, 8> vector;
Vector<js::Value, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};

View File

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

View File

@ -38,6 +38,9 @@
*
* ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/*
* JS date methods.
*/
@ -71,6 +74,8 @@
#include "jsobj.h"
#include "jsstr.h"
#include "jsobjinlines.h"
using namespace js;
/*
@ -499,12 +504,12 @@ const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
const uint32 DATE_RESERVED_SLOTS = 2;
JSClass js_DateClass = {
Class js_DateClass = {
js_Date_str,
JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL,
PropertyStub, PropertyStub, PropertyStub, PropertyStub,
EnumerateStub, ResolveStub, ConvertStub, NULL,
JSCLASS_NO_OPTIONAL_MEMBERS
};
@ -583,7 +588,7 @@ date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
#define MAXARGS 7
static JSBool
date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
date_msecFromArgs(JSContext *cx, uintN argc, Value *argv, jsdouble *rval)
{
uintN loop;
jsdouble array[MAXARGS];
@ -592,7 +597,7 @@ date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
for (loop = 0; loop < MAXARGS; loop++) {
if (loop < argc) {
jsdouble d;
if (!ValueToNumber(cx, argv[loop], &d))
if (!ValueToNumber(cx, &argv[loop], &d))
return JS_FALSE;
/* return NaN if any arg is not finite */
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];
*/
static JSBool
date_UTC(JSContext *cx, uintN argc, jsval *vp)
date_UTC(JSContext *cx, uintN argc, Value *vp)
{
jsdouble msec_time;
@ -632,7 +637,8 @@ date_UTC(JSContext *cx, uintN argc, jsval *vp)
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
date_parse(JSContext *cx, uintN argc, jsval *vp)
date_parse(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
jsdouble result;
if (argc == 0) {
*vp = cx->runtime->NaNValue;
vp->setDouble(js_NaN);
return true;
}
str = js_ValueToString(cx, vp[2]);
if (!str)
return JS_FALSE;
vp[2] = STRING_TO_JSVAL(str);
vp[2].setString(str);
if (!date_parseString(str, &result)) {
*vp = cx->runtime->NaNValue;
vp->setDouble(js_NaN);
return true;
}
result = TIMECLIP(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return true;
}
static inline jsdouble
@ -1188,9 +1195,10 @@ NowAsMillis()
}
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
@ -1206,38 +1214,37 @@ date_now_tn(JSContext*)
* Date type.
*/
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;
*dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
*dp = obj->fslots[JSSLOT_UTC_TIME].asDouble();
return JS_TRUE;
}
static void
SetDateToNaN(JSContext *cx, JSObject *obj, jsval *vp = NULL)
SetDateToNaN(JSContext *cx, JSObject *obj, Value *vp = NULL)
{
JS_ASSERT(obj->getClass() == &js_DateClass);
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue;
obj->fslots[JSSLOT_UTC_TIME] = cx->runtime->NaNValue;
obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
obj->fslots[JSSLOT_UTC_TIME].setDouble(js_NaN);
if (vp)
*vp = cx->runtime->NaNValue;
vp->setDouble(js_NaN);
}
/*
* Set UTC time to a given time and invalidate cached local time.
*/
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);
obj->fslots[JSSLOT_LOCAL_TIME] = cx->runtime->NaNValue;
if (!js_NewDoubleInRootedValue(cx, t, &obj->fslots[JSSLOT_UTC_TIME]))
return false;
obj->fslots[JSSLOT_LOCAL_TIME].setDouble(js_NaN);
obj->fslots[JSSLOT_UTC_TIME].setDouble(t);
if (vp)
*vp = obj->fslots[JSSLOT_UTC_TIME];
vp->setDouble(t);
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.
*/
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;
jsval *slotp = &obj->fslots[JSSLOT_LOCAL_TIME];
jsdouble result = *JSVAL_TO_DOUBLE(*slotp);
Value &slot = obj->fslots[JSSLOT_LOCAL_TIME];
jsdouble result = slot.asDouble();
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 (JSDOUBLE_IS_FINITE(result))
result = LocalTime(result);
if (!js_NewDoubleInRootedValue(cx, result, slotp))
return false;
slot.setDouble(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
*/
static JSBool
date_getTime(JSContext *cx, uintN argc, jsval *vp)
date_getTime(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) &&
js_NewNumberInRootedValue(cx, result, vp);
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
GetYear(JSContext *cx, JSBool fullyear, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result)) {
@ -1296,214 +1304,228 @@ GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
result -= 1900;
}
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getYear(JSContext *cx, uintN argc, jsval *vp)
date_getYear(JSContext *cx, uintN argc, Value *vp)
{
return GetYear(cx, JS_FALSE, vp);
}
static JSBool
date_getFullYear(JSContext *cx, uintN argc, jsval *vp)
date_getFullYear(JSContext *cx, uintN argc, Value *vp)
{
return GetYear(cx, JS_TRUE, vp);
}
static JSBool
date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = YearFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getMonth(JSContext *cx, uintN argc, jsval *vp)
date_getMonth(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp)
date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getDate(JSContext *cx, uintN argc, jsval *vp)
date_getDate(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getUTCDate(JSContext *cx, uintN argc, jsval *vp)
date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getDay(JSContext *cx, uintN argc, jsval *vp)
date_getDay(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getUTCDay(JSContext *cx, uintN argc, jsval *vp)
date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getHours(JSContext *cx, uintN argc, jsval *vp)
date_getHours(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getUTCHours(JSContext *cx, uintN argc, jsval *vp)
date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getMinutes(JSContext *cx, uintN argc, jsval *vp)
date_getMinutes(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetAndCacheLocalTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
/* Date.getSeconds is mapped to getUTCSeconds */
static JSBool
date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
date_getUTCSeconds(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = SecFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
/* Date.getMilliseconds is mapped to getUTCMilliseconds */
static JSBool
date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (JSDOUBLE_IS_FINITE(result))
result = msFromTime(result);
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
static JSBool
date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
jsdouble utctime, localtime, result;
obj = JS_THIS_OBJECT(cx, vp);
obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
@ -1515,14 +1537,15 @@ date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
* daylight savings time.
*/
result = (utctime - localtime) / msPerMinute;
return js_NewNumberInRootedValue(cx, result, vp);
vp->setDouble(result);
return JS_TRUE;
}
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);
if (!JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
JSObject *obj = ComputeThisObjectFromVp(cx, vp);
if (!InstanceOf(cx, obj, &js_DateClass, vp + 2))
return false;
if (argc == 0) {
@ -1531,17 +1554,17 @@ date_setTime(JSContext *cx, uintN argc, jsval *vp)
}
jsdouble result;
if (!ValueToNumber(cx, vp[2], &result))
if (!ValueToNumber(cx, &vp[2], &result))
return false;
return SetUTCTime(cx, obj, TIMECLIP(result), vp);
}
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;
jsval *argv;
Value *argv;
uintN i;
jsdouble args[4], *argp, *stop;
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 result;
obj = JS_THIS_OBJECT(cx, vp);
obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &result))
return false;
/* just return NaN if the date is already NaN */
if (!JSDOUBLE_IS_FINITE(result))
return js_NewNumberInRootedValue(cx, result, vp);
if (!JSDOUBLE_IS_FINITE(result)) {
vp->setDouble(result);
return true;
}
/*
* 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;
for (i = 0; i < argc; i++) {
if (!ValueToNumber(cx, argv[i], &args[i]))
if (!ValueToNumber(cx, &argv[i], &args[i]))
return false;
if (!JSDOUBLE_IS_FINITE(args[i])) {
SetDateToNaN(cx, obj, vp);
@ -1627,65 +1652,65 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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;
jsval *argv;
Value *argv;
uintN i;
jsdouble lorutime; /* local or UTC version of *date */
jsdouble args[3], *argp, *stop;
jsdouble year, month, day;
jsdouble result;
obj = JS_THIS_OBJECT(cx, vp);
obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &result))
return false;
@ -1700,7 +1725,7 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
argv = vp + 2;
for (i = 0; i < argc; i++) {
if (!ValueToNumber(cx, argv[i], &args[i]))
if (!ValueToNumber(cx, &argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
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,
* If we are, use 0 as the time. */
if (!(JSDOUBLE_IS_FINITE(result))) {
if (maxargs < 3)
return js_NewNumberInRootedValue(cx, result, vp);
if (maxargs < 3) {
vp->setDouble(result);
return true;
}
lorutime = +0.;
} else {
lorutime = local ? LocalTime(result) : result;
@ -1746,45 +1773,45 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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;
if (!GetUTCTime(cx, obj, vp, &result))
@ -1797,7 +1824,7 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
}
jsdouble year;
if (!ValueToNumber(cx, vp[2], &year))
if (!ValueToNumber(cx, &vp[2], &year))
return false;
if (!JSDOUBLE_IS_FINITE(year)) {
SetDateToNaN(cx, obj, vp);
@ -1856,14 +1883,14 @@ print_iso_string(char* buf, size_t size, jsdouble utctime)
}
static JSBool
date_utc_format(JSContext *cx, jsval *vp,
date_utc_format(JSContext *cx, Value *vp,
void (*printFunc)(char*, size_t, jsdouble))
{
char buf[100];
JSString *str;
jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(utctime)) {
@ -1874,18 +1901,18 @@ date_utc_format(JSContext *cx, jsval *vp,
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
vp->setString(str);
return JS_TRUE;
}
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);
}
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);
}
@ -1918,7 +1945,7 @@ typedef enum formatspec {
/* helper function */
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];
JSString *str;
@ -2026,12 +2053,12 @@ date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
*rval = STRING_TO_JSVAL(str);
rval->setString(str);
return JS_TRUE;
}
static JSBool
date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
{
JSObject *obj;
char buf[100];
@ -2039,7 +2066,7 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
PRMJTime split;
jsdouble utctime;
obj = JS_THIS_OBJECT(cx, vp);
obj = ComputeThisObjectFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
@ -2073,17 +2100,17 @@ date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
}
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);
if (!str)
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
vp->setString(str);
return JS_TRUE;
}
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
* 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
date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
{
/* Use '%#x' for windows, because '%x' is
* 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
date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp)
date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
{
return date_toLocaleHelper(cx, "%X", vp);
}
static JSBool
date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
{
JSString *fmt;
const char *fmtbytes;
@ -2132,7 +2159,7 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
fmt = js_ValueToString(cx, vp[2]);
if (!fmt)
return JS_FALSE;
vp[2] = STRING_TO_JSVAL(fmt);
vp[2].setString(fmt);
fmtbytes = js_GetStringBytes(cx, fmt);
if (!fmtbytes)
return JS_FALSE;
@ -2141,21 +2168,21 @@ date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
}
static JSBool
date_toTimeString(JSContext *cx, uintN argc, jsval *vp)
date_toTimeString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_TIME, vp);
}
static JSBool
date_toDateString(JSContext *cx, uintN argc, jsval *vp)
date_toDateString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_DATE, vp);
}
@ -2165,13 +2192,13 @@ date_toDateString(JSContext *cx, uintN argc, jsval *vp)
#include "jsdtoa.h"
static JSBool
date_toSource(JSContext *cx, uintN argc, jsval *vp)
date_toSource(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
JSString *str;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
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);
return JS_FALSE;
}
*vp = STRING_TO_JSVAL(str);
vp->setString(str);
return JS_TRUE;
}
#endif
static JSBool
date_toString(JSContext *cx, uintN argc, jsval *vp)
date_toString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
if (!GetUTCTime(cx, ComputeThisObjectFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_FULL, vp);
}
@ -2210,7 +2237,7 @@ date_toString(JSContext *cx, uintN argc, jsval *vp)
static jsval FASTCALL
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]);
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
static JSBool
date_valueOf(JSContext *cx, uintN argc, jsval *vp)
date_valueOf(JSContext *cx, uintN argc, Value *vp)
{
JSString *str, *number_str;
@ -2319,7 +2346,7 @@ static JSFunctionSpec date_methods[] = {
};
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. */
if (!JS_IsConstructing(cx))
@ -2330,9 +2357,9 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (argc == 0) {
d = NowAsMillis();
} else if (argc == 1) {
if (!JSVAL_IS_STRING(argv[0])) {
if (!argv[0].isString()) {
/* the argument is a millisecond number */
if (!ValueToNumber(cx, argv[0], &d))
if (!ValueToNumber(cx, &argv[0], &d))
return JS_FALSE;
d = TIMECLIP(d);
} else {
@ -2340,7 +2367,7 @@ js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSString *str = js_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
argv[0] = STRING_TO_JSVAL(str);
argv[0].setString(str);
if (!date_parseString(str, &d))
d = js_NaN;
@ -2368,8 +2395,9 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
/* set static LocalTZA */
LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
NULL, date_methods, NULL, date_static_methods);
proto = js_InitClass(cx, obj, NULL, &js_DateClass, js_Date,
MAXARGS, NULL, date_methods, NULL,
date_static_methods);
if (!proto)
return NULL;

View File

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

View File

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

View File

@ -45,7 +45,6 @@
*/
#include "jsapi.h"
#include "jsopcode.h"
#include "jsprvtd.h"
JS_BEGIN_EXTERN_C
@ -59,14 +58,14 @@ js_UntrapScriptCode(JSContext *cx, JSScript *script);
extern JS_PUBLIC_API(JSBool)
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler handler, void *closure);
JSTrapHandler handler, jsval closure);
extern JS_PUBLIC_API(JSOp)
JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
extern JS_PUBLIC_API(void)
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
JSTrapHandler *handlerp, void **closurep);
JSTrapHandler *handlerp, jsval *closurep);
extern JS_PUBLIC_API(void)
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);
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)
JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
/************************************************************************/
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);
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);
extern JS_PUBLIC_API(JSBool)
@ -113,19 +112,23 @@ js_SweepWatchPoints(JSContext *cx);
extern JSScopeProperty *
js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id);
#ifdef __cplusplus
/*
* NB: callers outside of jsdbgapi.c must pass non-null scope.
*/
extern JSPropertyOp
extern js::PropertyOp
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
const JSScopeProperty *sprop);
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
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
js::Value *rval);
#endif
extern JSPropertyOp
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 *)
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 *)
JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
extern JS_PUBLIC_API(JSNative)
JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
#ifdef __cpluscplus
extern JS_PUBLIC_API(JSFastNative)
JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
#endif
extern JS_PUBLIC_API(JSPrincipals *)
JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
@ -297,7 +325,7 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
/************************************************************************/
typedef struct JSPropertyDesc {
jsval id; /* primary id, a string or int */
jsval id; /* primary id, atomized string, or int */
jsval value; /* property value */
uint8 flags; /* flags, see below */
uint8 spare; /* unused */
@ -337,7 +365,7 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
/************************************************************************/
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)
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);

View File

@ -37,6 +37,8 @@
*
* ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/*
* 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);
extern void
jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp);
jsdtrace_object_create_start(JSStackFrame *fp, js::Class *clasp);
extern void
jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp);
jsdtrace_object_create_done(JSStackFrame *fp, js::Class *clasp);
extern void
jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj);
jsdtrace_object_create(JSContext *cx, js::Class *clasp, JSObject *obj);
extern void
jsdtrace_object_finalize(JSObject *obj);

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,6 @@
#include "jspubtd.h"
#include "jsobj.h"
JS_BEGIN_EXTERN_C
typedef struct JSLocalNameMap JSLocalNameMap;
/*
@ -137,8 +135,8 @@ struct JSFunction : public JSObject
struct {
uint16 extra; /* number of arg slots for local GC roots */
uint16 spare; /* reserved for future use */
JSNative native; /* native method pointer or null */
JSClass *clasp; /* class of objects constructed
js::Native native; /* native method pointer or null */
js::Class *clasp; /* class of objects constructed
by this function */
JSNativeTraceInfo *trcinfo;
} n;
@ -231,7 +229,7 @@ struct JSFunction : public JSObject
* Yes, this is an incompatible change, which prefigures the impending move to
* single-threaded objects and GC heaps.
*/
extern JSClass js_ArgumentsClass;
extern js::Class js_ArgumentsClass;
inline bool
JSObject::isArguments() const
@ -239,12 +237,12 @@ JSObject::isArguments() const
return getClass() == &js_ArgumentsClass;
}
extern JS_FRIEND_DATA(JSClass) js_CallClass;
extern JSClass js_DeclEnvClass;
extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern js::Class js_DeclEnvClass;
extern const uint32 CALL_CLASS_FIXED_RESERVED_SLOTS;
/* 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
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.
*/
#define VALUE_IS_FUNCTION(cx, v) \
@ -300,7 +299,7 @@ extern JSObject *
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
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);
extern void
@ -309,9 +308,9 @@ js_TraceFunction(JSTracer *trc, JSFunction *fun);
extern void
js_FinalizeFunction(JSContext *cx, JSFunction *fun);
extern JSObject * JS_FASTCALL
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent,
JSObject *proto);
extern JSObject *
js_CloneFunctionObject(JSContext *cx, JSFunction *fun, const js::Value &parent,
const js::Value &proto);
inline JSObject *
CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
@ -320,8 +319,8 @@ CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
JSObject *proto;
if (!js_GetClassPrototype(cx, parent, JSProto_Function, &proto))
return NULL;
JS_ASSERT(proto);
return js_CloneFunctionObject(cx, fun, parent, proto);
return js_CloneFunctionObject(cx, fun, js::NonFunObjValue(*parent),
js::FunObjValue(*proto));
}
extern JS_REQUIRES_STACK JSObject *
@ -331,7 +330,7 @@ extern JS_REQUIRES_STACK JSObject *
js_NewDebuggableFlatClosure(JSContext *cx, JSFunction *fun);
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);
/*
@ -344,16 +343,16 @@ js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
#define JSV2F_SEARCH_STACK 0x10000
extern JSFunction *
js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags);
js_ValueToFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject *
js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags);
js_ValueToFunctionObject(JSContext *cx, js::Value *vp, uintN flags);
extern JSObject *
js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags);
js_ValueToCallableObject(JSContext *cx, js::Value *vp, uintN flags);
extern void
js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags);
js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, uintN flags);
extern JSObject *
js_GetCallObject(JSContext *cx, JSStackFrame *fp);
@ -365,23 +364,23 @@ extern void
js_PutCallObject(JSContext *cx, JSStackFrame *fp);
extern JSBool JS_FASTCALL
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs, jsval *argv,
uint32 nvars, jsval *slots);
js_PutCallObjectOnTrace(JSContext *cx, JSObject *scopeChain, uint32 nargs,
js::Value *argv, uint32 nvars, js::Value *slots);
extern JSFunction *
js_GetCallObjectFunction(JSObject *obj);
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
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
extern JSBool
SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
SetCallArg(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
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
@ -390,23 +389,23 @@ SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
* property ops map.
*/
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
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
* leak an optimized closure via indirect or debugger eval.
*/
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
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp);
js_GetArgsValue(JSContext *cx, JSStackFrame *fp, js::Value *vp);
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 *
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;
/*
* JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int jsval.
* Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must fit JSVAL_INT_MAX. To assert that
* we check first that the shift does not overflow uint32.
* JSSLOT_ARGS_LENGTH stores ((argc << 1) | overwritten_flag) as int value.
* Thus (JS_ARGS_LENGTH_MAX << 1) | 1 must into an int32.
*/
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 {
inline jsval
inline const Value &
GetArgsSlot(JSObject *argsobj, uint32 arg)
{
return argsobj->dslots[arg];
}
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
IsOverriddenArgsLength(JSObject *obj)
{
JS_ASSERT(obj->isArguments());
jsval v = obj->fslots[JSSLOT_ARGS_LENGTH];
return (JSVAL_TO_INT(v) & 1) != 0;
return (obj->fslots[JSSLOT_ARGS_LENGTH].asInt32() & 1) != 0;
}
inline uint32
@ -490,7 +485,7 @@ GetArgsLength(JSObject *obj)
{
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);
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
* check if nameWord corresponds to the const declaration.
*/
extern JS_FRIEND_API(jsuword *)
extern jsuword *
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
@ -551,12 +546,9 @@ extern void
js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
extern JSBool
js_fun_apply(JSContext *cx, uintN argc, jsval *vp);
js_fun_apply(JSContext *cx, uintN argc, js::Value *vp);
extern JSBool
js_fun_call(JSContext *cx, uintN argc, jsval *vp);
JS_END_EXTERN_C
js_fun_call(JSContext *cx, uintN argc, js::Value *vp);
#endif /* jsfun_h___ */

View File

@ -38,6 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
#define __STDC_LIMIT_MACROS
/*
* JS Mark-and-Sweep Garbage Collector.
*
@ -115,20 +117,15 @@ using namespace js;
* JSTRACE_STRING.
*/
JS_STATIC_ASSERT(JSTRACE_OBJECT == 0);
JS_STATIC_ASSERT(JSTRACE_DOUBLE == 1);
JS_STATIC_ASSERT(JSTRACE_STRING == 2);
JS_STATIC_ASSERT(JSTRACE_STRING == 1);
JS_STATIC_ASSERT(JSTRACE_DOUBLE == 2);
JS_STATIC_ASSERT(JSTRACE_XML == 3);
/*
* JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
* trace kind when JS_HAS_XML_SUPPORT is false.
*/
JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML);
/*
* Check that we can use memset(p, 0, ...) to implement JS_CLEAR_WEAK_ROOTS.
*/
JS_STATIC_ASSERT(JSVAL_NULL == 0);
JS_STATIC_ASSERT(JSTRACE_DOUBLE + 1 == JSTRACE_XML);
/*
* Check consistency of external string constants from JSFinalizeGCThingKind.
@ -900,13 +897,6 @@ js_IsAboutToBeFinalized(void *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
* to amortize).
@ -923,11 +913,8 @@ JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes)
{
InitGCArenaLists(rt);
if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL,
sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
rt->gcRootsHash.ops = NULL;
if (!rt->gcRootsHash.init(GC_ROOTS_SIZE))
return false;
}
if (!JS_DHashTableInit(&rt->gcLocksHash, JS_DHashGetStubOps(), NULL,
sizeof(JSGCLockHashEntry), GC_ROOTS_SIZE)) {
rt->gcLocksHash.ops = NULL;
@ -1150,12 +1137,10 @@ js_FinishGC(JSRuntime *rt)
rt->gcIteratorTable.clear();
FinishGCArenaLists(rt);
if (rt->gcRootsHash.ops) {
if (rt->gcRootsHash.initialized()) {
#ifdef DEBUG
CheckLeakedRoots(rt);
#endif
JS_DHashTableFinish(&rt->gcRootsHash);
rt->gcRootsHash.ops = NULL;
}
if (rt->gcLocksHash.ops) {
JS_DHashTableFinish(&rt->gcLocksHash);
@ -1164,20 +1149,26 @@ js_FinishGC(JSRuntime *rt)
}
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)
JS_ReportOutOfMemory(cx);
return ok;
}
JSBool
js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
js_AddGCThingRoot(JSContext *cx, void **rp, const char *name)
{
JSBool ok;
JSGCRootHashEntry *rhe;
JSBool ok = js_AddGCThingRootRT(cx->runtime, rp, name);
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
* 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);
js_WaitForGC(rt);
rhe = (JSGCRootHashEntry *)
JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_ADD);
if (rhe) {
rhe->root = rp;
rhe->name = name;
ok = JS_TRUE;
} else {
ok = JS_FALSE;
}
return ok;
void *key = vp;
return !!rt->gcRootsHash.put(key, JSRootInfo(name, JS_GC_ROOT_VALUE_PTR));
}
JSBool
js_AddRootRT(JSRuntime *rt, void **rp, const char *name)
{
/*
* 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
@ -1208,35 +1209,31 @@ js_RemoveRoot(JSRuntime *rt, void *rp)
*/
AutoLockGC lock(rt);
js_WaitForGC(rt);
(void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE);
rt->gcRootsHash.remove(rp);
rt->gcPoke = JS_TRUE;
return JS_TRUE;
}
typedef JSRootedValueMap::Range RootRange;
typedef JSRootedValueMap::Entry RootEntry;
typedef JSRootedValueMap::Enum RootEnum;
#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
CheckLeakedRoots(JSRuntime *rt)
{
uint32 leakedroots = 0;
/* Warn (but don't assert) debug builds of any remaining roots. */
JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,
&leakedroots);
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
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 == 1) {
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
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)
{
NamedRootDumpArgs args;
args.dump = dump;
args.data = data;
JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
RootEntry &entry = r.front();
if (const char *name = entry.value.name)
dump(name, entry.key, entry.value.type, data);
}
}
#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
js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
{
GCRootMapArgs args = {map, data};
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
@ -1582,7 +1543,7 @@ js_NewFinalizableGCThing(JSContext *cx, unsigned thingKind)
* this reference, allowing thing to be GC'd if it has no other refs.
* 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);
*freeListp = thing;
return NULL;
@ -1728,8 +1689,8 @@ RefillDoubleFreeList(JSContext *cx)
return MakeNewArenaFreeList(a, sizeof(jsdouble));
}
JSBool
js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
jsdouble *
js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d)
{
/* Updates of metering counters here are not thread-safe. */
METER(cx->runtime->gcStats.doubleArenaStats.alloc++);
@ -1744,8 +1705,8 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
*dp = d;
*vp = DOUBLE_TO_JSVAL(dp);
return true;
cx->weakRoots.newbornDouble = dp;
return dp;
}
JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack;
@ -1769,7 +1730,7 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
js_ReportOutOfMemory(cx);
METER(cx->runtime->gcStats.doubleArenaStats.fail++);
}
return false;
return NULL;
}
CheckGCFreeListLink(thing);
@ -1777,19 +1738,11 @@ js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
jsdouble *dp = reinterpret_cast<jsdouble *>(thing);
*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;
/*
* N.B. We any active local root scope, since this function is called only
* from the compiler to create double atoms.
*/
return dp;
}
@ -2049,8 +2002,10 @@ MarkDelayedChildren(JSTracer *trc)
JS_ASSERT(rt->gcMarkLaterCount == 0);
}
namespace js {
void
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
{
JSContext *cx;
JSRuntime *rt;
@ -2152,40 +2107,42 @@ js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind)
}
void
js_CallValueTracerIfGCThing(JSTracer *trc, jsval v)
CallGCMarkerForGCThing(JSTracer *trc, void *thing)
{
void *thing;
uint32 kind;
if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) {
thing = JSVAL_TO_TRACEABLE(v);
kind = JSVAL_TRACE_KIND(v);
JS_ASSERT(kind == js_GetGCThingTraceKind(thing));
} else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) {
/* v can be an arbitrary GC thing reinterpreted as an object. */
thing = JSVAL_TO_OBJECT(v);
kind = js_GetGCThingTraceKind(thing);
} else {
#ifdef DEBUG
/*
* The incoming thing should be a real gc-thing, not a boxed, word-sized
* primitive value.
*/
jsboxedword w = (jsboxedword)thing;
JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
#endif
if (!thing)
return;
}
js_CallGCMarker(trc, thing, kind);
uint32 kind = js_GetGCThingTraceKind(thing);
CallGCMarker(trc, thing, kind);
}
static JSDHashOperator
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;
} /* namespace js */
/* Ignore null reference, scalar values, and static strings. */
if (JSVAL_IS_TRACEABLE(v)) {
static void
gc_root_traversal(JSTracer *trc, const RootEntry &entry)
{
#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;
jsuword thing = (jsuword) JSVAL_TO_GCTHING(v);
jsuword thing = (jsuword) ptr;
JSRuntime *rt = trc->context->runtime;
for (unsigned i = 0; i != FINALIZE_LIMIT; 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,
"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",
rhe->name);
entry.value.name);
}
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
@ -2249,7 +2208,7 @@ TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len)
for (uint32 i = 0; i < len; i++) {
if (JSObject *obj = vec[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)
JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
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)
js_TraceScript(trc, fp->script);
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
JS_CALL_VALUE_TRACER(trc, fp->thisv, "this");
JS_CALL_VALUE_TRACER(trc, fp->rval, "rval");
CallGCMarkerIfGCThing(trc, fp->thisv, "this");
CallGCMarkerIfGCThing(trc, fp->rval, "rval");
if (fp->scopeChain)
JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
}
@ -2305,9 +2263,8 @@ JSWeakRoots::mark(JSTracer *trc)
}
if (newbornDouble)
JS_CALL_DOUBLE_TRACER(trc, newbornDouble, "newborn_double");
JS_CALL_VALUE_TRACER(trc, lastAtom, "lastAtom");
JS_SET_TRACING_NAME(trc, "lastInternalResult");
js_CallValueTracerIfGCThing(trc, lastInternalResult);
CallGCMarkerIfGCThing(trc, ATOM_TO_JSID(lastAtom), "lastAtom");
CallGCMarkerForGCThing(trc, lastInternalResult, "lastInternalResult");
}
void
@ -2320,10 +2277,10 @@ js_TraceContext(JSTracer *trc, JSContext *acx)
JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object");
acx->weakRoots.mark(trc);
if (acx->throwing) {
JS_CALL_VALUE_TRACER(trc, acx->exception, "exception");
CallGCMarkerIfGCThing(trc, acx->exception, "exception");
} else {
/* 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)
@ -2350,7 +2307,9 @@ js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
JSRuntime *rt = trc->context->runtime;
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_TraceAtomState(trc, allAtoms);
js_TraceRuntimeNumberState(trc);
@ -2406,12 +2365,12 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
ssr->cycle = true;
return;
}
pobj = JSVAL_TO_OBJECT(pobj->getSlot(slot));
pobj = pobj->getSlot(slot).asObjectOrNull();
}
pobj = ssr->pobj;
if (slot == JSSLOT_PROTO) {
obj->setProto(pobj);
obj->setProto(ToObjPtr(pobj));
} else {
JS_ASSERT(slot == JSSLOT_PARENT);
obj->setParent(pobj);
@ -2443,7 +2402,7 @@ FinalizeObject(JSContext *cx, JSObject *obj, unsigned thingKind)
return;
/* Finalize obj first, in case it needs map and slots. */
JSClass *clasp = obj->getClass();
Class *clasp = obj->getClass();
if (clasp->finalize)
clasp->finalize(cx, obj);

View File

@ -50,6 +50,7 @@
#include "jstask.h"
#include "jsversion.h"
#define JSTRACE_DOUBLE 2
#define JSTRACE_XML 3
/*
@ -98,10 +99,16 @@ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop);
extern JSBool
js_AddRoot(JSContext *cx, void *rp, const char *name);
js_AddRoot(JSContext *cx, js::Value *vp, const char *name);
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
js_RemoveRoot(JSRuntime *rt, void *rp);
@ -109,7 +116,7 @@ js_RemoveRoot(JSRuntime *rt, void *rp);
#ifdef DEBUG
extern void
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);
#endif
@ -125,19 +132,12 @@ typedef struct JSPtrTable {
extern JSBool
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,
* or null when the allocation fails.
*/
extern jsdouble *
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d);
#ifdef JS_TRACER
extern JSBool
@ -162,17 +162,9 @@ js_IsAboutToBeFinalized(void *thing);
#if JS_HAS_XML_SUPPORT
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
#else
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_DOUBLE)
#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
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
@ -229,9 +221,6 @@ typedef enum JSGCInvocationKind {
extern void
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
* ordinary string to simplify js_GetExternalStringGCType.
@ -346,14 +335,14 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data);
struct JSWeakRoots {
/* Most recently created things by type, members of the GC's root set. */
void *finalizableNewborns[FINALIZE_LIMIT];
jsdouble *newbornDouble;
void *finalizableNewborns[FINALIZE_LIMIT];
jsdouble *newbornDouble;
/* 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. */
jsval lastInternalResult;
void *lastInternalResult;
void mark(JSTracer *trc);
};
@ -453,29 +442,87 @@ js_MarkTraps(JSTracer *trc);
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
TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len);
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) {
jsval v = *vp;
if (JSVAL_IS_TRACEABLE(v)) {
for (Value *vp = beg; vp < end; ++vp) {
if (vp->isGCThing()) {
JS_SET_TRACING_INDEX(trc, name, vp - beg);
js_CallGCMarker(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
CallGCMarkerForGCThing(trc, *vp);
}
}
}
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++) {
jsval v = *vp;
if (JSVAL_IS_TRACEABLE(v)) {
for (Value *vp = vec, *end = vp + len; vp < end; vp++) {
if (vp->isGCThing()) {
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;
}
const T &front() const {
T &front() const {
JS_ASSERT(!empty());
return cur->t;
}
@ -313,6 +313,8 @@ class HashTable : AllocPolicy
return true;
}
bool initialized() const { return table; }
~HashTable()
{
if (table)
@ -721,6 +723,7 @@ class HashMap
*/
HashMap(AllocPolicy a = AllocPolicy()) : impl(a) {}
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.:
@ -868,6 +871,7 @@ class HashSet
*/
HashSet(AllocPolicy a = AllocPolicy()) : impl(a) {}
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.:

File diff suppressed because it is too large Load Diff

View File

@ -49,11 +49,9 @@
#include "jsopcode.h"
#include "jsscript.h"
JS_BEGIN_EXTERN_C
typedef struct JSFrameRegs {
jsbytecode *pc; /* program counter */
jsval *sp; /* stack pointer */
js::Value *sp; /* stack pointer */
} JSFrameRegs;
/* JS stack frame flags. */
@ -82,16 +80,17 @@ typedef struct JSFrameRegs {
*/
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 */
JSObject *callobj; /* lazily created Call object */
jsval argsobj; /* lazily created arguments object, must be
JSVAL_OBJECT */
JSObject *argsobj; /* lazily created arguments object */
JSScript *script; /* script being interpreted */
JSFunction *fun; /* function being called or null */
jsval thisv; /* "this" pointer if in method */
uintN argc; /* actual argument count */
jsval *argv; /* base of argument stack slots */
jsval rval; /* function return value */
js::Value *argv; /* base of argument stack slots */
void *annotation; /* used by Java security */
/* Maintained by StackSpace operations */
@ -138,10 +137,7 @@ struct JSStackFrame
* also used in some other cases --- entering 'with' blocks, for
* example.
*/
union {
JSObject *scopeChain;
jsval scopeChainVal;
};
JSObject *scopeChain;
JSObject *blockChain;
uint32 flags; /* frame flags -- see below */
@ -168,26 +164,25 @@ struct JSStackFrame
/* Get the frame's current bytecode, assuming |this| is in |cx|. */
jsbytecode *pc(JSContext *cx) const;
jsval *argEnd() const {
return (jsval *)this;
js::Value *argEnd() const {
return (js::Value *)this;
}
jsval *slots() const {
return (jsval *)(this + 1);
js::Value *slots() const {
return (js::Value *)(this + 1);
}
jsval calleeValue() {
js::Value *base() const {
return slots() + script->nfixed;
}
const js::Value &calleeValue() {
JS_ASSERT(argv);
return argv[-2];
}
JSObject *calleeObject() {
JS_ASSERT(argv);
return JSVAL_TO_OBJECT(argv[-2]);
}
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()). */
JSObject *varobj(JSContext *cx) const;
inline JSObject *getThisObject(JSContext *cx);
inline js::ObjPtr getThisObject(JSContext *cx);
bool isGenerator() const { return flags & JSFRAME_GENERATOR; }
bool isFloatingGenerator() const {
@ -211,16 +206,10 @@ struct JSStackFrame
namespace js {
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(jsval) == 0);
static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(jsval);
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(Value) == 0);
static const size_t ValuesPerStackFrame = sizeof(JSStackFrame) / sizeof(Value);
}
static JS_INLINE jsval *
StackBase(JSStackFrame *fp)
{
return fp->slots() + fp->script->nfixed;
}
} /* namespace js */
static JS_INLINE uintN
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.
*
* NB: this function loads and uses *vp before storing *thisvp, so the two may
* alias the same jsval.
* alias the same Value.
*/
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
@ -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]
* must not be a JSVAL_VOID.
*/
extern JSObject *
js_ComputeThis(JSContext *cx, jsval *argv);
extern bool
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_ASSERT(!JSVAL_IS_VOID(thisv)), \
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
JS_ALWAYS_INLINE bool
ComputeThisValueFromVp(JSContext *cx, js::Value *vp, js::Value **thisvpp)
{
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
@ -276,8 +295,11 @@ extern const uint16 js_PrimitiveTestFlags[];
* and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
* be initialized actual arguments.
*/
extern JS_REQUIRES_STACK JS_FRIEND_API(JSBool)
js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags);
extern JS_REQUIRES_STACK bool
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
@ -300,56 +322,79 @@ js_Invoke(JSContext *cx, const js::InvokeArgsGuard &args, uintN flags);
*/
#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
/*
* "Internal" calls may come from C or C++ code using a JSContext on which no
* JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
*/
#define js_InternalCall(cx,obj,fval,argc,argv,rval) \
js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval)
extern bool
InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
uintN argc, const Value *argv, Value *rval);
#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \
js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval)
static JS_ALWAYS_INLINE bool
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
js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
uintN argc, jsval *argv, jsval *rval);
static JS_ALWAYS_INLINE bool
InternalConstruct(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
const Value *argv, Value *rval)
{
return InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval);
}
extern JSBool
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval);
extern bool
InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
JSAccessMode mode, uintN argc, const Value *argv, Value *rval);
extern JS_FORCES_STACK JSBool
js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSStackFrame *down, uintN flags, jsval *result);
extern JS_FORCES_STACK bool
Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSStackFrame *down, uintN flags, Value *result);
extern JS_REQUIRES_STACK JSBool
js_InvokeConstructor(JSContext *cx, const js::InvokeArgsGuard &args,
JSBool clampReturn);
extern JS_REQUIRES_STACK bool
InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args,
JSBool clampReturn);
extern JS_REQUIRES_STACK JSBool
js_Interpret(JSContext *cx);
extern JS_REQUIRES_STACK bool
Interpret(JSContext *cx);
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
extern JSBool
js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
JSObject **objp, JSProperty **propp);
extern bool
CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
JSObject **objp, JSProperty **propp);
extern JSBool
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval);
extern bool
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. */
extern JSBool
js_SameValue(jsval v1, jsval v2, JSContext *cx);
extern bool
SameValue(JSContext *cx, const Value &v1, const Value &v2);
extern JSBool
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
JSType
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
* the value of the upvar.
*/
extern jsval&
extern const js::Value &
js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
/*
@ -378,31 +423,13 @@ js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
#else
# 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
js_EnterWith(JSContext *cx, jsint stackIndex);
extern JS_REQUIRES_STACK void
js_LeaveWith(JSContext *cx);
extern JS_REQUIRES_STACK JSClass *
extern JS_REQUIRES_STACK js::Class *
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);
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,
@ -422,7 +449,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp);
* the result. Both vp and vp2 must be roots.
*/
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
@ -442,19 +469,16 @@ js_MeterSlotOpcode(JSOp op, uint32 slot);
#endif /* JS_LONE_INTERPRET */
JS_END_EXTERN_C
inline JSObject *
inline js::ObjPtr
JSStackFrame::getThisObject(JSContext *cx)
{
if (flags & JSFRAME_COMPUTED_THIS)
return JSVAL_TO_OBJECT(thisv); /* JSVAL_COMPUTED_THIS invariant */
JSObject* obj = js_ComputeThis(cx, argv);
if (!obj)
return NULL;
thisv = OBJECT_TO_JSVAL(obj);
return thisv.asObjPtr(); /* JSVAL_COMPUTED_THIS invariant */
if (!js::ComputeThisFromArgv(cx, argv))
return js::NullObjPtr();
thisv.copy(argv[-1]);
flags |= JSFRAME_COMPUTED_THIS;
return obj;
return thisv.asObjPtr();
}
#endif /* jsinterp_h___ */

View File

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

View File

@ -71,17 +71,17 @@ const uint32 JSSLOT_ITER_FLAGS = JSSLOT_PRIVATE + 1;
* iterator will never be exposed to scripts.
*/
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
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
* JSVAL_HOLE. Otherwise set it to the result of the next call.
*/
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.
@ -160,15 +160,14 @@ js_LiveFrameIfGenerator(JSStackFrame *fp)
}
#endif
extern JS_FRIEND_API(JSClass) js_GeneratorClass;
extern JSClass js_IteratorClass;
extern JSClass js_StopIterationClass;
extern JS_FRIEND_API(js::Class) js_GeneratorClass;
extern js::Class js_IteratorClass;
extern js::Class js_StopIterationClass;
static inline bool
js_ValueIsStopIteration(jsval v)
js_ValueIsStopIteration(const js::Value &v)
{
return !JSVAL_IS_PRIMITIVE(v) &&
JSVAL_TO_OBJECT(v)->getClass() == &js_StopIterationClass;
return v.isObject() && v.asObject().getClass() == &js_StopIterationClass;
}
extern JSObject *

View File

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

View File

@ -800,29 +800,6 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
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
* 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 {
jsval
ValueToNumberSlow(JSContext *cx, jsval v, double *out)
bool
ValueToNumberSlow(JSContext *cx, Value *vp, double *out)
{
JS_ASSERT(!JSVAL_IS_INT(v) && !JSVAL_IS_DOUBLE(v));
goto skip_int_double;
@ -999,24 +976,7 @@ ValueToNumberSlow(JSContext *cx, jsval v, double *out)
}
bool
ValueToNumberValueSlow(JSContext *cx, jsval *vp, double *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)
ValueToECMAInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
@ -1031,7 +991,7 @@ ValueToECMAInt32Slow(JSContext *cx, jsval v, int32_t *out)
}
bool
ValueToECMAUint32Slow(JSContext *cx, jsval v, uint32_t *out)
ValueToECMAUint32Slow(JSContext *cx, js::Value *vp, uint32_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
@ -1079,7 +1039,7 @@ js_DoubleToECMAUint32(jsdouble d)
namespace js {
bool
ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
ValueToInt32Slow(JSContext *cx, js::Value *vp, int32_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;
@ -1105,7 +1065,7 @@ ValueToInt32Slow(JSContext *cx, jsval v, int32_t *out)
}
bool
ValueToUint16Slow(JSContext *cx, jsval v, uint16_t *out)
ValueToUint16Slow(JSContext *cx, js::Value *vp, uint16_t *out)
{
JS_ASSERT(!JSVAL_IS_INT(v));
jsdouble d;

View File

@ -132,15 +132,15 @@ JSDOUBLE_IS_NEGZERO(jsdouble d)
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
static inline int
JSDOUBLE_IS_INT(jsdouble d, jsint& i)
static inline bool
JSDOUBLE_IS_INT32(jsdouble d, int32_t& i)
{
if (JSDOUBLE_IS_NEGZERO(d))
return false;
return d == (i = jsint(d));
return d == (i = int32_t(d));
}
static inline int
static inline bool
JSDOUBLE_IS_NEG(jsdouble d)
{
#ifdef WIN32
@ -184,9 +184,9 @@ extern void
js_FinishRuntimeNumberState(JSContext *cx);
/* 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);
/*
@ -199,19 +199,6 @@ extern const char js_isFinite_str[];
extern const char js_parseFloat_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. */
extern JSString * JS_FASTCALL
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
* 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
ValueToNumber(JSContext *cx, jsval v, double *out)
ValueToNumber(JSContext *cx, js::Value *vp, double *out)
{
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
if (vp->isInt32()) {
*out = vp->asInt32();
return true;
}
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
if (vp->isDouble()) {
*out = vp->asDouble();
return true;
}
extern jsval ValueToNumberSlow(JSContext *, jsval, double *);
return !JSVAL_IS_NULL(ValueToNumberSlow(cx, v, out));
extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
return ValueToNumberSlow(cx, vp, out);
}
/*
* 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.
*/
/* Convert a value to a number, replacing 'vp' with the converted value. */
JS_ALWAYS_INLINE bool
ValueToNumberValue(JSContext *cx, jsval *vp, double *out)
ValueToNumber(JSContext *cx, js::Value *vp)
{
jsval v = *vp;
if (JSVAL_IS_INT(v)) {
*out = JSVAL_TO_INT(v);
if (vp->isInt32())
return true;
}
if (JSVAL_IS_DOUBLE(v)) {
*out = *JSVAL_TO_DOUBLE(v);
if (vp->isDouble())
return true;
}
extern bool ValueToNumberValueSlow(JSContext *, jsval *, double *);
return ValueToNumberValueSlow(cx, vp, out);
}
/*
* 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);
double _;
extern bool ValueToNumberSlow(JSContext *, js::Value *, double *);
return ValueToNumberSlow(cx, vp, &_);
}
/*
* 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
* must be a copy of a rooted jsval.
* ToInt32 and ToUint32. Return converted value in *out on success, !ok on
* failure. As a side effect, *vp will be mutated to match *out.
*/
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)) {
*out = JSVAL_TO_INT(v);
if (vp->isInt32()) {
*out = vp->asInt32();
return true;
}
extern bool ValueToECMAInt32Slow(JSContext *, jsval, int32_t *);
return ValueToECMAInt32Slow(cx, v, out);
extern bool ValueToECMAInt32Slow(JSContext *, js::Value *, int32_t *);
return ValueToECMAInt32Slow(cx, vp, out);
}
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)) {
*out = (uint32_t)JSVAL_TO_INT(v);
if (vp->isInt32()) {
*out = (uint32_t)vp->asInt32();
return true;
}
extern bool ValueToECMAUint32Slow(JSContext *, jsval, uint32_t *);
return ValueToECMAUint32Slow(cx, v, out);
extern bool ValueToECMAUint32Slow(JSContext *, js::Value *, uint32_t *);
return ValueToECMAUint32Slow(cx, vp, out);
}
/*
* 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
* of a rooted jsval.
* nearest. Return converted value in *out on success, !ok on failure. As a
* side effect, *vp will be mutated to match *out.
*/
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)) {
*out = JSVAL_TO_INT(v);
if (vp->isInt32()) {
*out = vp->asInt32();
return true;
}
extern bool ValueToInt32Slow(JSContext *, jsval, int32_t *);
return ValueToInt32Slow(cx, v, out);
extern bool ValueToInt32Slow(JSContext *, js::Value *, int32_t *);
return ValueToInt32Slow(cx, vp, out);
}
/*
@ -335,14 +293,14 @@ ValueToInt32(JSContext *cx, jsval v, int32_t *out)
* copy of a rooted jsval.
*/
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)) {
*out = (uint16_t)JSVAL_TO_INT(v);
if (vp->isInt32()) {
*out = (uint16_t)vp->asInt32();
return true;
}
extern bool ValueToUint16Slow(JSContext *, jsval, uint16_t *);
return ValueToUint16Slow(cx, v, out);
extern bool ValueToUint16Slow(JSContext *, js::Value *, uint16_t *);
return ValueToUint16Slow(cx, vp, out);
}
} /* namespace js */
@ -508,6 +466,25 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
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<> struct NumberTraits<int32> {
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 "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
@ -66,7 +97,7 @@ struct PropertyDescriptor {
public:
/* 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) */
bool isAccessorDescriptor() const {
@ -96,31 +127,31 @@ struct PropertyDescriptor {
}
JSObject* getterObject() const {
return get != JSVAL_VOID ? JSVAL_TO_OBJECT(get) : NULL;
return get.isUndefined() ? NULL : &get.asObject();
}
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;
}
jsval setterValue() const {
const js::Value &setterValue() const {
return set;
}
JSPropertyOp getter() const {
return js_CastAsPropertyOp(getterObject());
js::PropertyOp getter() const {
return js::CastAsPropertyOp(getterObject());
}
JSPropertyOp setter() const {
return js_CastAsPropertyOp(setterObject());
js::PropertyOp setter() const {
return js::CastAsPropertyOp(setterObject());
}
static void traceDescriptorArray(JSTracer* trc, JSObject* obj);
static void finalizeDescriptorArray(JSContext* cx, JSObject* obj);
jsid id;
jsval value, get, set;
js::Value value, get, set;
/* Property descriptor boolean fields. */
uint8 attrs;
@ -134,8 +165,6 @@ struct PropertyDescriptor {
bool hasConfigurable : 1;
};
JS_BEGIN_EXTERN_C
/* For detailed comments on these function pointer types, see jsprvtd.h. */
struct JSObjectOps {
/*
@ -147,24 +176,24 @@ struct JSObjectOps {
/* Mandatory non-null function pointer members. */
JSLookupPropOp lookupProperty;
JSDefinePropOp defineProperty;
JSPropertyIdOp getProperty;
JSPropertyIdOp setProperty;
js::DefinePropOp defineProperty;
js::PropertyIdOp getProperty;
js::PropertyIdOp setProperty;
JSAttributesOp getAttributes;
JSAttributesOp setAttributes;
JSPropertyIdOp deleteProperty;
JSConvertOp defaultValue;
JSNewEnumerateOp enumerate;
JSCheckAccessIdOp checkAccess;
js::PropertyIdOp deleteProperty;
js::ConvertOp defaultValue;
js::NewEnumerateOp enumerate;
js::CheckAccessIdOp checkAccess;
JSTypeOfOp typeOf;
JSTraceOp trace;
/* Optionally non-null members start here. */
JSObjectOp thisObject;
JSPropertyRefOp dropProperty;
JSNative call;
JSNative construct;
JSHasInstanceOp hasInstance;
js::Native call;
js::Native construct;
js::HasInstanceOp hasInstance;
JSFinalizeOp clear;
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
* 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
* tagging and should be accessed using the (get|set)Private methods of
* JSObject.
@ -213,18 +242,11 @@ const uint32 JSSLOT_PRIVATE = 2;
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,
* 64 bytes on 64-bit systems. The JSFunction struct is an extension of this
* 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
* 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
@ -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
* any such association.
*
* Both these classword tag bits are initially zero; they may be set or queried
* using the (is|set)(Delegate|System) inline methods.
* Both these flags are initially zero; they may be set or queried using the
* (is|set)(Delegate|System) inline methods.
*
* 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.
*/
struct JSObject {
@ -255,29 +277,32 @@ struct JSObject {
friend class js::TraceRecorder;
JSObjectMap *map; /* property map, see jsscope.h */
jsuword classword; /* JSClass ptr | bits, see above */
jsval fslots[JS_INITIAL_NSLOTS]; /* small number of fixed slots */
jsval *dslots; /* dynamically allocated slots */
private:
js::Class *clasp; /* class pointer */
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(); }
JSClass *getClass() const {
return (JSClass *) (classword & ~JSSLOT_CLASS_MASK_BITS);
js::Class *getClass() const {
return clasp;
}
bool hasClass(const JSClass *clasp) const {
return clasp == getClass();
bool hasClass(const js::Class *c) const {
return c == clasp;
}
inline JSScope *scope() const;
inline uint32 shape() const;
bool isDelegate() const {
return (classword & jsuword(1)) != jsuword(0);
return (flags & jsuword(1)) != jsuword(0);
}
void setDelegate() {
classword |= jsuword(1);
flags |= jsuword(1);
}
static void setDelegateNullSafe(JSObject *obj) {
@ -286,42 +311,46 @@ struct JSObject {
}
bool isSystem() const {
return (classword & jsuword(2)) != jsuword(0);
return (flags & jsuword(2)) != jsuword(0);
}
void setSystem() {
classword |= jsuword(2);
flags |= jsuword(2);
}
uint32 dslotLength() const {
return dslots[-1].asPrivateUint32();
}
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)
? fslots[slot]
: (JS_ASSERT(slot < (uint32)dslots[-1]),
: (JS_ASSERT(slot < dslotLength()),
dslots[slot - JS_INITIAL_NSLOTS]);
}
jsval getSlot(uintN slot) const {
const js::Value &getSlot(uintN slot) const {
return (slot < JS_INITIAL_NSLOTS)
? fslots[slot]
: (JS_ASSERT(slot < (uint32)dslots[-1]),
: (JS_ASSERT(slot < dslotLength()),
dslots[slot - JS_INITIAL_NSLOTS]);
}
void setSlot(uintN slot, jsval value) {
void setSlot(uintN slot, const js::Value &value) {
if (slot < JS_INITIAL_NSLOTS) {
fslots[slot] = value;
fslots[slot].copy(value);
} else {
JS_ASSERT(slot < (uint32)dslots[-1]);
dslots[slot - JS_INITIAL_NSLOTS] = value;
JS_ASSERT(slot < dslotLength());
dslots[slot - JS_INITIAL_NSLOTS].copy(value);
}
}
inline jsval lockedGetSlot(uintN slot) const;
inline void lockedSetSlot(uintN slot, jsval value);
inline const js::Value &lockedGetSlot(uintN slot) const;
inline void lockedSetSlot(uintN slot, const js::Value &value);
/*
* 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
* JS_INITIAL_NSLOTS.
*/
inline jsval getSlotMT(JSContext *cx, uintN slot);
inline void setSlotMT(JSContext *cx, uintN slot, jsval value);
inline const js::Value &getSlotMT(JSContext *cx, uintN slot);
inline void setSlotMT(JSContext *cx, uintN slot, const js::Value &value);
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() {
fslots[JSSLOT_PROTO] = JSVAL_NULL;
fslots[JSSLOT_PROTO].setNull();
}
void setProto(JSObject *newProto) {
void setProto(js::ObjPtr newProto) {
setDelegateNullSafe(newProto);
fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(newProto);
fslots[JSSLOT_PROTO].copy(newProto);
}
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() {
fslots[JSSLOT_PARENT] = JSVAL_NULL;
fslots[JSSLOT_PARENT].setNull();
}
void setParent(JSObject *newParent) {
setDelegateNullSafe(newParent);
fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(newParent);
fslots[JSSLOT_PARENT].setNonFunObjOrNull(newParent);
}
void traceProtoAndParent(JSTracer *trc) const {
@ -372,22 +409,21 @@ struct JSObject {
void *getPrivate() const {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
jsval v = fslots[JSSLOT_PRIVATE];
JS_ASSERT((v & jsval(1)) == jsval(0));
return reinterpret_cast<void *>(v);
void *priv = fslots[JSSLOT_PRIVATE].asPrivateVoidPtr();
JS_ASSERT((size_t(priv) & 1) == 0);
return priv;
}
void setPrivate(void *data) {
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
jsval v = reinterpret_cast<jsval>(data);
JS_ASSERT((v & jsval(1)) == jsval(0));
fslots[JSSLOT_PRIVATE] = v;
JS_ASSERT((size_t(data) & 1) == 0);
fslots[JSSLOT_PRIVATE].setPrivateVoidPtr(data);
}
static jsval defaultPrivate(JSClass *clasp) {
static const js::Value &defaultPrivate(js::Class *clasp) {
return (clasp->flags & JSCLASS_HAS_PRIVATE)
? JSVAL_NULL
: JSVAL_VOID;
? js::sNullValue
: js::sUndefinedValue;
}
/*
@ -413,7 +449,6 @@ struct JSObject {
inline void voidDenseArrayCount();
inline void incArrayCountBy(uint32 posDelta);
inline void decArrayCountBy(uint32 negDelta);
inline void voidArrayUnused();
/*
* Back to generic stuff.
@ -422,22 +457,22 @@ struct JSObject {
bool isCallable();
/* The map field is not initialized here and should be set separately. */
void init(JSClass *clasp, JSObject *proto, JSObject *parent,
jsval privateSlotValue) {
void init(js::Class *c, js::ObjPtr proto, JSObject *parent,
const js::Value &privateSlotValue) {
JS_ASSERT(((jsuword) clasp & 3) == 0);
JS_STATIC_ASSERT(JSSLOT_PRIVATE + 3 == JS_INITIAL_NSLOTS);
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(!isSystem());
setProto(proto);
setParent(parent);
fslots[JSSLOT_PRIVATE] = privateSlotValue;
fslots[JSSLOT_PRIVATE + 1] = JSVAL_VOID;
fslots[JSSLOT_PRIVATE + 2] = JSVAL_VOID;
fslots[JSSLOT_PRIVATE].copy(privateSlotValue);
fslots[JSSLOT_PRIVATE + 1].setUndefined();
fslots[JSSLOT_PRIVATE + 2].setUndefined();
dslots = NULL;
}
@ -445,8 +480,9 @@ struct JSObject {
* Like init, but also initializes map. The catch: proto must be the result
* of a call to js_InitClass(...clasp, ...).
*/
inline void initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
jsval privateSlotValue);
inline void initSharingEmptyScope(js::Class *clasp,
js::ObjPtr proto, JSObject *parent,
const js::Value &privateSlotValue);
inline bool hasSlotsArray() const { return !!dslots; }
@ -458,18 +494,18 @@ struct JSObject {
return map->ops->lookupProperty(cx, this, id, objp, propp);
}
JSBool defineProperty(JSContext *cx, jsid id, jsval value,
JSPropertyOp getter = JS_PropertyStub,
JSPropertyOp setter = JS_PropertyStub,
JSBool defineProperty(JSContext *cx, jsid id, const js::Value &value,
js::PropertyOp getter = js::PropertyStub,
js::PropertyOp setter = js::PropertyStub,
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);
}
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);
}
@ -483,20 +519,20 @@ struct JSObject {
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);
}
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);
}
JSBool enumerate(JSContext *cx, JSIterateOp op, jsval *statep,
JSBool enumerate(JSContext *cx, JSIterateOp op, js::Value *statep,
jsid *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) {
return map->ops->checkAccess(cx, this, id, mode, vp, attrsp);
}
@ -505,10 +541,8 @@ struct JSObject {
return map->ops->typeOf(cx, this);
}
/* These four are time-optimized to avoid stub calls. */
JSObject *thisObject(JSContext *cx) {
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
}
inline JSObject *thisObject(JSContext *cx);
static inline js::ObjPtr thisObject(JSContext *cx, js::ObjPtr obj);
void dropProperty(JSContext *cx, JSProperty *prop) {
if (map->ops->dropProperty)
@ -524,6 +558,10 @@ struct JSObject {
inline bool isXML() const;
inline bool unbrand(JSContext *cx);
inline void initArrayClass();
inline void changeClassToSlowArray();
inline void changeClassToFastArray();
};
#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
* 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_LENGTH32 (~uint32(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(js::Value) - 1)
#define OBJ_CHECK_SLOT(obj,slot) \
(JS_ASSERT((obj)->isNative()), JS_ASSERT(slot < (obj)->scope()->freeslot))
@ -559,37 +597,22 @@ struct JSObject {
#endif /* JS_THREADSAFE */
#ifdef __cplusplus
/* N.B. There is a corresponding OBJ_TO_OUTER_OBJ in jsd/jsd_val.c. */
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) {
JSExtendedClass *xclasp = (JSExtendedClass *) clasp;
if (xclasp->innerObject)
obj = xclasp->innerObject(cx, obj);
*ppobj = xclasp->innerObject(cx, pobj);
}
}
/*
* The following function has been copied to jsd/jsd_val.c. If making changes to
* OBJ_TO_OUTER_OBJECT, please update jsd/jsd_val.c as well.
*/
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;
extern js::Class js_ObjectClass;
extern js::Class js_WithClass;
extern js::Class js_BlockClass;
/*
* 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) \
((OBJ_IS_CLONED_BLOCK(obj) ? obj->getProto() : obj)->scope()->entryCount)
#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) \
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
@ -684,14 +707,14 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
extern JSBool
js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
jsval *vp);
js::Value *vp);
extern JSBool
js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
JSObject **objp, JSProperty **propp);
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 *
js_InitEval(JSContext *cx, JSObject *obj);
@ -701,7 +724,7 @@ js_InitObjectClass(JSContext *cx, JSObject *obj);
extern JSObject *
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 *static_ps, JSFunctionSpec *static_fs);
@ -719,14 +742,14 @@ extern const char js_lookupGetter_str[];
extern const char js_lookupSetter_str[];
extern JSObject *
js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, size_t objectSize = 0);
js_NewObject(JSContext *cx, js::Class *clasp, JSObject *proto, JSObject *parent,
size_t objectSize = 0);
/*
* See jsapi.h, JS_NewObjectWithGivenProto.
*/
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);
/*
@ -742,8 +765,8 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
* object, not by the parent of its .prototype object value.
*/
extern JSObject*
js_NewObjectWithClassProto(JSContext *cx, JSClass *clasp, JSObject *proto,
jsval privateSlotValue);
js_NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto,
const js::Value &privateSlotValue);
/*
* Fast access to immutable standard objects (constructors and prototypes).
@ -753,19 +776,20 @@ js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **objp);
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
* JSProto_Null, clasp must non-null.
*/
extern JSBool
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key, jsval *vp,
JSClass *clasp = NULL);
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
js::Value *vp, js::Class *clasp = NULL);
extern JSObject *
js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
JSObject *parent, uintN argc, jsval *argv);
js_ConstructObject(JSContext *cx, js::Class *clasp, JSObject *proto,
JSObject *parent, uintN argc, js::Value *argv);
extern JSBool
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
* 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
* 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.
*/
bool
@ -817,7 +841,7 @@ js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
*/
extern JSScopeProperty *
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);
/*
@ -828,14 +852,15 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
extern JSScopeProperty *
js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
JSScopeProperty *sprop, uintN attrs, uintN mask,
JSPropertyOp getter, JSPropertyOp setter);
js::PropertyOp getter, js::PropertyOp setter);
extern JSBool
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
js::PropertyOp getter, js::PropertyOp setter, uintN attrs);
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.
@ -854,8 +879,8 @@ const uintN JSDNP_SET_METHOD = 4; /* js_{DefineNativeProperty,SetPropertyHelpe
* the held property, and to release the lock on obj.
*/
extern JSBool
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value &value,
js::PropertyOp getter, js::PropertyOp setter, uintN attrs,
uintN flags, intN shortid, JSProperty **propp,
uintN defineHow = 0);
@ -888,11 +913,11 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
static inline bool
js_IsCacheableNonGlobalScope(JSObject *obj)
{
extern JS_FRIEND_DATA(JSClass) js_CallClass;
extern JS_FRIEND_DATA(JSClass) js_DeclEnvClass;
extern JS_FRIEND_DATA(js::Class) js_CallClass;
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
JS_ASSERT(obj->getParent());
JSClass *clasp = obj->getClass();
js::Class *clasp = obj->getClass();
bool cacheable = (clasp == &js_CallClass ||
clasp == &js_BlockClass ||
clasp == &js_DeclEnvClass);
@ -947,24 +972,24 @@ const uintN JSGET_NO_METHOD_BARRIER = 2; // call to joined function can't leak
*/
extern JSBool
js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
JSScopeProperty *sprop, uintN getHow, jsval *vp);
JSScopeProperty *sprop, uintN getHow, js::Value *vp);
extern JSBool
js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
jsval *vp);
js::Value *vp);
extern JSBool
js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow,
jsval *vp);
js::Value *vp);
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
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
js_GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
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
@ -975,10 +1000,10 @@ js_CheckUndeclaredVarAssignment(JSContext *cx);
extern JSBool
js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
jsval *vp);
js::Value *vp);
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
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);
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
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, js::Value *vp);
extern JSBool
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
jsval *statep, jsid *idp);
js::Value *statep, jsid *idp);
extern void
js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, jsval state);
js_MarkEnumeratorState(JSTracer *trc, JSObject *obj, const js::Value &v);
extern void
js_PurgeCachedNativeEnumerators(JSContext *cx, JSThreadData *data);
extern JSBool
js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp, uintN *attrsp);
js::Value *vp, uintN *attrsp);
extern JSType
js_TypeOf(JSContext *cx, JSObject *obj);
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
js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
js_Construct(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
js::Value *rval);
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
js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
JSBool checkForCycles);
extern JSBool
js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
extern bool
js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
/*
* 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)
js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
JSObject **protop, JSClass *clasp = NULL);
JSObject **protop, js::Class *clasp = NULL);
extern JSBool
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.
*/
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
js_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
extern JSObject *
js_ValueToNonNullObject(JSContext *cx, jsval v);
extern JSBool
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, js::Value *rval);
extern JSBool
js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
uintN argc, jsval *argv, jsval *rval);
uintN argc, js::Value *argv, js::Value *rval);
extern JSBool
js_XDRObject(JSXDRState *xdr, JSObject **objp);
@ -1082,10 +1116,10 @@ js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
#endif
extern bool
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, js::Value *vp);
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.
@ -1115,24 +1149,26 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
JSPrincipals *principals, uintN *linenop);
static inline bool
js_IsCallable(jsval v) {
return !JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isCallable();
js_IsCallable(const js::Value &v) {
return v.isObject() && v.asObject().isCallable();
}
extern JSBool
js_ReportGetterOnlyAssignment(JSContext *cx);
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
JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n);
JS_FRIEND_API(void) js_DumpString(JSString *str);
JS_FRIEND_API(void) js_DumpAtom(JSAtom *atom);
JS_FRIEND_API(void) js_DumpValue(jsval val);
JS_FRIEND_API(void) js_DumpId(jsid id);
JS_FRIEND_API(void) js_DumpObject(JSObject *obj);
JS_FRIEND_API(void) js_DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL);
namespace js {
JS_FRIEND_API(void) DumpChars(const jschar *s, size_t n);
JS_FRIEND_API(void) DumpString(JSString *str);
JS_FRIEND_API(void) DumpAtom(JSAtom *atom);
JS_FRIEND_API(void) DumpValue(const js::Value &val);
JS_FRIEND_API(void) DumpId(jsid id);
JS_FRIEND_API(void) DumpObject(JSObject *obj);
JS_FRIEND_API(void) DumpStackFrameChain(JSContext *cx, JSStackFrame *start = NULL);
}
#endif
extern uintN
@ -1140,8 +1176,23 @@ js_InferFlags(JSContext *cx, uintN defaultFlags);
/* Object constructor native. Exposed only so the JIT can know its address. */
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___ */

View File

@ -44,7 +44,7 @@
#include "jsobj.h"
#include "jsscope.h"
inline jsval
inline const js::Value &
JSObject::getSlotMT(JSContext *cx, uintN slot)
{
#ifdef JS_THREADSAFE
@ -54,7 +54,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
* (obj->scope()->ownercx == cx), to avoid needlessly switching from
* 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
* 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.
*/
OBJ_CHECK_SLOT(this, slot);
@ -67,7 +67,7 @@ JSObject::getSlotMT(JSContext *cx, uintN slot)
}
inline void
JSObject::setSlotMT(JSContext *cx, uintN slot, jsval value)
JSObject::setSlotMT(JSContext *cx, uintN slot, const js::Value &value)
{
#ifdef JS_THREADSAFE
/* Thread-safe way to set a slot. */
@ -90,61 +90,55 @@ inline uint32
JSObject::getArrayLength() const
{
JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_LENGTH]);
return fslots[JSSLOT_ARRAY_LENGTH].asPrivateUint32();
}
inline uint32
JSObject::getArrayCount() const
{
JS_ASSERT(isArray());
return uint32(fslots[JSSLOT_ARRAY_COUNT]);
return fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32();
}
inline void
JSObject::setArrayLength(uint32 length)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_LENGTH] = length;
fslots[JSSLOT_ARRAY_LENGTH].setPrivateUint32(length);
}
inline void
JSObject::setArrayCount(uint32 count)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] = count;
fslots[JSSLOT_ARRAY_COUNT].setPrivateUint32(count);
}
inline void
JSObject::voidDenseArrayCount()
{
JS_ASSERT(isDenseArray());
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
fslots[JSSLOT_ARRAY_COUNT].setUndefined();
}
inline void
JSObject::incArrayCountBy(uint32 posDelta)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] += posDelta;
fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() += posDelta;
}
inline void
JSObject::decArrayCountBy(uint32 negDelta)
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] -= negDelta;
fslots[JSSLOT_ARRAY_COUNT].asPrivateUint32Ref() -= negDelta;
}
inline void
JSObject::voidArrayUnused()
{
JS_ASSERT(isArray());
fslots[JSSLOT_ARRAY_COUNT] = JSVAL_VOID;
}
inline void
JSObject::initSharingEmptyScope(JSClass *clasp, JSObject *proto, JSObject *parent,
jsval privateSlotValue)
JSObject::initSharingEmptyScope(js::Class *clasp,
js::ObjPtr proto, JSObject *parent,
const js::Value &privateSlotValue)
{
init(clasp, proto, parent, privateSlotValue);
@ -158,7 +152,7 @@ inline void
JSObject::freeSlotsArray(JSContext *cx)
{
JS_ASSERT(hasSlotsArray());
JS_ASSERT(size_t(dslots[-1]) > JS_INITIAL_NSLOTS);
JS_ASSERT(dslotLength() > JS_INITIAL_NSLOTS);
cx->free(dslots - 1);
}
@ -181,6 +175,46 @@ JSObject::unbrand(JSContext *cx)
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 {
typedef Vector<PropertyDescriptor, 1> PropertyDescriptorArray;
@ -209,6 +243,82 @@ class AutoDescriptorArray : private AutoGCRooter
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___ */

View File

@ -47,7 +47,7 @@
JS_BEGIN_EXTERN_C
extern JSClass js_JSONClass;
extern js::Class js_JSONClass;
extern JSObject *
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_POST (1U<<12) /* postorder increment or decrement */
#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 */
#define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */
#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.
*/
extern char *
js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
js_DecompileValueGenerator(JSContext *cx, intN spindex, const jsval *v,
JSString *fallback);
#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 */,
unsigned staticLevel /* = 0 */)
{
JSCompiler jsc(cx, principals, callerFrame);
JSArenaPool codePool, notePool;
TokenKind tt;
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(staticLevel != 0, callerFrame);
JSCompiler jsc(cx, principals, callerFrame);
if (!jsc.init(chars, length, file, filename, lineno))
return NULL;
@ -789,6 +789,8 @@ JSCompiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *cal
&cx->scriptStackQuota);
JSCodeGenerator cg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno());
if (!cg.init())
return NULL;
MUST_FLOW_THROUGH("out");
@ -1561,6 +1563,9 @@ JSCompiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *pr
&cx->scriptStackQuota);
JSCodeGenerator funcg(&jsc, &codePool, &notePool, jsc.tokenStream.getLineno());
if (!funcg.init())
return NULL;
funcg.flags |= TCF_IN_FUNCTION;
funcg.fun = fun;
if (!GenerateBlockId(&funcg, funcg.bodyid))

View File

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

View File

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

View File

@ -57,26 +57,6 @@
#include "jspubtd.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.
*/
@ -179,17 +159,12 @@ class DeflatedStringCache;
class PropertyCache;
struct PropertyCacheEntry;
} /* namespace js */
/* Common instantiations. */
typedef js::Vector<jschar, 32> JSCharBuffer;
static inline JSPropertyOp
js_CastAsPropertyOp(JSObject *object)
{
return JS_DATA_TO_FUNC_PTR(JSPropertyOp, object);
}
} /* export "C++" */
#endif /* __cplusplus */
@ -204,10 +179,21 @@ typedef enum JSTrapStatus {
typedef JSTrapStatus
(* 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
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old,
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsid id, jsval old,
jsval *newp, void *closure);
/* called just after script creation */
@ -266,13 +252,13 @@ typedef JSBool
void *closure);
typedef struct JSDebugHooks {
JSTrapHandler interruptHandler;
void *interruptHandlerData;
JSInterruptHook interruptHook;
void *interruptHookData;
JSNewScriptHook newScriptHook;
void *newScriptHookData;
JSDestroyScriptHook destroyScriptHook;
void *destroyScriptHookData;
JSTrapHandler debuggerHandler;
JSDebuggerHandler debuggerHandler;
void *debuggerHandlerData;
JSSourceHandler sourceHandler;
void *sourceHandlerData;
@ -282,7 +268,7 @@ typedef struct JSDebugHooks {
void *callHookData;
JSObjectHook objectHook;
void *objectHookData;
JSTrapHandler throwHook;
JSThrowHook throwHook;
void *throwHookData;
JSDebugErrorHook debugErrorHook;
void *debugErrorHookData;
@ -316,7 +302,7 @@ typedef JSBool
* value, with the specified getter, setter, and attributes.
*/
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);
/*
@ -368,4 +354,57 @@ typedef void
extern JSBool js_CStringsAreUTF8;
#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___ */

View File

@ -42,8 +42,8 @@
/*
* JS public API typedefs.
*/
#include "jstypes.h"
#include "jscompat.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C
@ -52,8 +52,6 @@ typedef uint16 jschar;
typedef int32 jsint;
typedef uint32 jsuint;
typedef float64 jsdouble;
typedef jsword jsval;
typedef jsword jsid;
typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
/*
@ -155,6 +153,340 @@ typedef struct JSLocaleCallbacks JSLocaleCallbacks;
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
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. */
/*
@ -165,7 +497,7 @@ typedef struct JSONParser JSONParser;
* obj[id] can't be deleted (because it's permanent).
*/
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
@ -218,7 +550,7 @@ typedef JSBool
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
*/
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:
@ -250,7 +582,7 @@ typedef JSBool
* *objp without a new JSClass flag.
*/
typedef JSBool
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
JSObject **objp);
/*
@ -317,7 +649,7 @@ typedef JSObjectOps *
* specialize access checks.
*/
typedef JSBool
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
jsval *vp);
/*
@ -333,7 +665,7 @@ typedef JSBool
* *bp otherwise.
*/
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
@ -420,7 +752,7 @@ typedef uint32
/* JSExtendedClass function pointer typedefs. */
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
@ -443,7 +775,6 @@ typedef JSBool
(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
typedef JSBool
(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
@ -593,4 +924,60 @@ typedef JSBool
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___ */

View File

@ -50,8 +50,6 @@
#include "jsdhash.h"
#endif
JS_BEGIN_EXTERN_C
struct JSRegExpStatics {
JSString *input; /* input string to match (perl $_, GC root) */
JSBool multiline; /* whether input contains newlines (perl $*) */
@ -153,7 +151,7 @@ js_FreeRegExpStatics(JSContext *cx);
#define VALUE_IS_REGEXP(cx, v) \
(!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isRegExp())
extern JSClass js_RegExpClass;
extern js::Class js_RegExpClass;
inline bool
JSObject::isRegExp() const
@ -202,13 +200,11 @@ static inline void
js_ClearRegExpLastIndex(JSObject *obj)
{
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. */
extern bool
js_ContainsRegExpMetaChars(const jschar *chars, size_t length);
JS_END_EXTERN_C
#endif /* jsregexp_h___ */

View File

@ -63,8 +63,6 @@
#pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
#endif
JS_BEGIN_EXTERN_C
/*
* 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
@ -281,10 +279,10 @@ struct JSScope : public JSObjectMap
void generateOwnShape(JSContext *cx);
JSScopeProperty **searchTable(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,
JSPropertyOp getter, JSPropertyOp setter,
js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs,
uintN flags, intN shortid,
JSScopeProperty **spp);
@ -295,7 +293,7 @@ struct JSScope : public JSObjectMap
/* Create a mutable, owned, empty scope. */
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);
@ -306,11 +304,11 @@ struct JSScope : public JSObjectMap
* 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|.
*/
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);
@ -319,7 +317,7 @@ struct JSScope : public JSObjectMap
/* Add a property whose id is not yet in this scope. */
JSScopeProperty *addProperty(JSContext *cx, jsid id,
JSPropertyOp getter, JSPropertyOp setter,
js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs,
uintN flags, intN shortid);
@ -331,14 +329,14 @@ struct JSScope : public JSObjectMap
/* Add or overwrite a property for id in this scope. */
JSScopeProperty *putProperty(JSContext *cx, jsid id,
JSPropertyOp getter, JSPropertyOp setter,
js::PropertyOp getter, js::PropertyOp setter,
uint32 slot, uintN attrs,
uintN flags, intN shortid);
/* Change the given property into a sibling with the same id in this scope. */
JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop,
uintN attrs, uintN mask,
JSPropertyOp getter, JSPropertyOp setter);
js::PropertyOp getter, js::PropertyOp setter);
/* Remove id from this scope. */
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
* 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
@ -363,14 +361,14 @@ struct JSScope : public JSObjectMap
* flags show this is necessary. The methodShapeChange overload (directly
* below) parallels this.
*/
bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v);
bool methodWriteBarrier(JSContext *cx, uint32 slot, jsval v);
bool methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, const js::Value &v);
bool methodWriteBarrier(JSContext *cx, uint32 slot, const js::Value &v);
void trace(JSTracer *trc);
void deletingShapeChange(JSContext *cx, JSScopeProperty *sprop);
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval);
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, const js::Value &toval);
bool methodShapeChange(JSContext *cx, uint32 slot, const js::Value &toval);
void protoShapeChange(JSContext *cx);
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
@ -420,7 +418,7 @@ struct JSScope : public JSObjectMap
*/
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());
generateOwnShape(cx);
if (js_IsPropertyCacheDisabled(cx)) // check for rt->shapeGen overflow
@ -501,10 +499,10 @@ struct JSScope : public JSObjectMap
struct JSEmptyScope : public JSScope
{
JSClass * const clasp;
jsrefcount nrefs; /* count of all referencing objects */
js::Class * const clasp;
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() {
/* The method is only called for already held objects. */
@ -554,7 +552,7 @@ JSObject::shape() const
return map->shape;
}
inline jsval
inline const js::Value &
JSObject::lockedGetSlot(uintN slot) const
{
OBJ_CHECK_SLOT(this, slot);
@ -562,28 +560,12 @@ JSObject::lockedGetSlot(uintN slot) const
}
inline void
JSObject::lockedSetSlot(uintN slot, jsval value)
JSObject::lockedSetSlot(uintN slot, const js::Value &value)
{
OBJ_CHECK_SLOT(this, slot);
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 {
class PropertyTree;
}
@ -595,23 +577,23 @@ struct JSScopeProperty {
uint32 number, void *arg);
friend void js::SweepScopeProperties(JSContext *cx);
jsid id; /* int-tagged jsval/untagged JSAtom* */
jsid id;
private:
union {
JSPropertyOp rawGetter; /* getter and setter hooks or objects */
js::PropertyOp rawGetter; /* getter and setter hooks or objects */
JSScopeProperty *next; /* next node in freelist */
};
union {
JSPropertyOp rawSetter; /* getter is JSObject* and setter is 0
js::PropertyOp rawSetter; /* getter is JSObject* and setter is 0
if sprop->isMethod() */
JSScopeProperty **prevp; /* pointer to previous node's next, or
pointer to head of freelist */
};
void insertFree(JSScopeProperty *&list) {
id = JSVAL_NULL;
id = JSID_NULL;
next = list;
prevp = &list;
if (list)
@ -620,7 +602,7 @@ struct JSScopeProperty {
}
void removeFree() {
JS_ASSERT(JSVAL_IS_NULL(id));
JS_ASSERT(JSID_IS_NULL(id));
*prevp = next;
if (next)
next->prevp = prevp;
@ -665,15 +647,15 @@ struct JSScopeProperty {
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)
: id(id), rawGetter(getter), rawSetter(setter), slot(slot), attrs(uint8(attrs)),
flags(uint8(flags)), shortid(int16(shortid))
{
JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER),
JSVAL_TO_OBJECT(getterValue())->isCallable());
getterObject()->isCallable());
JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER),
JSVAL_TO_OBJECT(setterValue())->isCallable());
setterObject()->isCallable());
}
bool marked() const { return (flags & MARK) != 0; }
@ -702,50 +684,55 @@ struct JSScopeProperty {
JSObject *methodObject() const {
JS_ASSERT(isMethod());
return js_CastAsObject(rawGetter);
return CastAsObject(rawGetter);
}
jsval methodValue() const {
js::Value methodValue() const {
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; }
JSPropertyOp getterOp() const {
js::PropertyOp getterOp() const {
JS_ASSERT(!hasGetterValue());
return rawGetter;
}
JSObject *getterObject() const {
JS_ASSERT(hasGetterValue());
return js_CastAsObject(rawGetter);
return CastAsObject(rawGetter);
}
jsval getterValue() const {
js::Value getterValue() const {
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; }
JSPropertyOp setterOp() const {
js::PropertyOp setterOp() const {
JS_ASSERT(!hasSetterValue());
return rawSetter;
}
JSObject *setterObject() const {
JS_ASSERT(hasSetterValue() && rawSetter);
return js_CastAsObject(rawSetter);
return CastAsObject(rawSetter);
}
jsval setterValue() const {
js::Value setterValue() const {
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 bool matches(const JSScopeProperty *p) const;
inline bool matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot,
uintN aattrs, uintN aflags, intN ashortid) const;
inline bool matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter,
uint32 aslot, uintN aattrs, uintN aflags,
intN ashortid) const;
bool get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp);
bool set(JSContext* cx, JSObject* obj, jsval* vp);
bool get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp);
bool set(JSContext* cx, JSObject *obj, js::Value* vp);
inline bool isSharedPermanent() const;
@ -815,7 +802,7 @@ JSScope::hasProperty(JSScopeProperty *sprop)
inline JSScopeProperty *
JSScope::lastProperty() const
{
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
return lastProp;
}
@ -826,8 +813,8 @@ JSScope::lastProperty() const
inline void
JSScope::setLastProperty(JSScopeProperty *sprop)
{
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
JS_ASSERT(!JSID_IS_NULL(sprop->id));
JS_ASSERT_IF(lastProp, !JSID_IS_NULL(lastProp->id));
lastProp = sprop;
}
@ -836,7 +823,7 @@ inline void
JSScope::removeLastProperty()
{
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;
--entryCount;
@ -848,12 +835,12 @@ JSScope::removeDictionaryProperty(JSScopeProperty *sprop)
JS_ASSERT(inDictionaryMode());
JS_ASSERT(sprop->inDictionary());
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->childp == &lastProp);
JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id));
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id));
JS_ASSERT_IF(lastProp != sprop, !JSID_IS_NULL(lastProp->id));
JS_ASSERT_IF(lastProp->parent, !JSID_IS_NULL(lastProp->parent->id));
if (sprop->parent)
sprop->parent->childp = sprop->childp;
@ -871,12 +858,12 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
*/
JS_ASSERT(sprop->inDictionary());
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(lastProp, lastProp->inDictionary());
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;
*childp = sprop;
@ -891,8 +878,8 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
* than id when calling sprop's getter or setter.
*/
#define SPROP_USERID(sprop) \
((sprop)->hasShortID() ? INT_TO_JSVAL((sprop)->shortid) \
: ID_TO_VALUE((sprop)->id))
((sprop)->hasShortID() ? INT_TO_JSID((sprop)->shortid) \
: (sprop)->id)
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
#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
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
@ -973,19 +960,18 @@ JSScope::canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp)
}
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());
if (hasGetterValue()) {
JS_ASSERT(!isMethod());
jsval fval = getterValue();
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_READ, 0, 0, vp);
return js::InternalGetOrSet(cx, obj, id, getterValue(), JSACC_READ, 0, 0, vp);
}
if (isMethod()) {
*vp = methodValue();
vp->copy(methodValue());
JSScope *scope = pobj->scope();
JS_ASSERT(scope->object == pobj);
@ -999,19 +985,17 @@ JSScopeProperty::get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp)
* but with objects do.
*/
if (obj->getClass() == &js_WithClass)
obj = obj->map->ops->thisObject(cx, obj);
obj = obj->thisObject(cx);
return getterOp()(cx, obj, SPROP_USERID(this), vp);
}
inline bool
JSScopeProperty::set(JSContext* cx, JSObject* obj, jsval* vp)
JSScopeProperty::set(JSContext* cx, JSObject *obj, js::Value* vp)
{
JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
if (attrs & JSPROP_SETTER) {
jsval fval = setterValue();
return js_InternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
}
if (attrs & JSPROP_SETTER)
return js::InternalGetOrSet(cx, obj, id, setterValue(), JSACC_WRITE, 1, vp, vp);
if (attrs & JSPROP_GETTER)
return !!js_ReportGetterOnlyAssignment(cx);
@ -1034,8 +1018,6 @@ js_GetMutableScope(JSContext *cx, JSObject *obj);
extern void
js_TraceId(JSTracer *trc, jsid id);
JS_END_EXTERN_C
#ifdef _MSC_VER
#pragma warning(pop)
#pragma warning(pop)

View File

@ -47,7 +47,7 @@
#include "jsscope.h"
inline JSEmptyScope *
JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
{
JS_ASSERT(!emptyScope);
emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
@ -55,7 +55,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
}
inline JSEmptyScope *
JSScope::getEmptyScope(JSContext *cx, JSClass *clasp)
JSScope::getEmptyScope(JSContext *cx, js::Class *clasp)
{
if (emptyScope) {
JS_ASSERT(clasp == emptyScope->clasp);
@ -66,7 +66,7 @@ JSScope::getEmptyScope(JSContext *cx, JSClass *clasp)
}
inline bool
JSScope::ensureEmptyScope(JSContext *cx, JSClass *clasp)
JSScope::ensureEmptyScope(JSContext *cx, js::Class *clasp)
{
if (emptyScope) {
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.
*/
inline bool
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp)
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, js::Value *vp)
{
JS_ASSERT(hasMethodBarrier());
JS_ASSERT(hasProperty(sprop));
JS_ASSERT(sprop->isMethod());
JS_ASSERT(sprop->methodValue() == *vp);
JS_ASSERT(sprop->methodValue().isSame(*vp));
JS_ASSERT(object->getClass() == &js_ObjectClass);
JSObject *funobj = JSVAL_TO_OBJECT(*vp);
JSObject *funobj = &vp->asFunObj();
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
JS_ASSERT(FUN_OBJECT(fun) == funobj && FUN_NULL_CLOSURE(fun));
funobj = CloneFunctionObject(cx, fun, funobj->getParent());
if (!funobj)
return false;
*vp = OBJECT_TO_JSVAL(funobj);
vp->setFunObj(*funobj);
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
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop, jsval v)
JSScope::methodWriteBarrier(JSContext *cx, JSScopeProperty *sprop,
const js::Value &v)
{
if (flags & (BRANDED | METHOD_BARRIER)) {
jsval prev = object->lockedGetSlot(sprop->slot);
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
const js::Value &prev = object->lockedGetSlot(sprop->slot);
if (ChangesMethodValue(prev, v))
return methodShapeChange(cx, sprop, v);
}
return true;
}
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)) {
jsval prev = object->lockedGetSlot(slot);
if (prev != v && VALUE_IS_FUNCTION(cx, prev))
const js::Value &prev = object->lockedGetSlot(slot);
if (ChangesMethodValue(prev, v))
return methodShapeChange(cx, slot, v);
}
return true;
@ -231,18 +237,18 @@ JSScopeProperty::hash() const
inline bool
JSScopeProperty::matches(const JSScopeProperty *p) const
{
JS_ASSERT(!JSVAL_IS_NULL(id));
JS_ASSERT(!JSVAL_IS_NULL(p->id));
JS_ASSERT(!JSID_IS_NULL(id));
JS_ASSERT(!JSID_IS_NULL(p->id));
return id == p->id &&
matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags,
p->shortid);
}
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
{
JS_ASSERT(!JSVAL_IS_NULL(id));
JS_ASSERT(!JSID_IS_NULL(id));
return rawGetter == agetter &&
rawSetter == asetter &&
slot == aslot &&

View File

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

View File

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

View File

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

View File

@ -54,8 +54,6 @@
#include "jshashtable.h"
#include "jslock.h"
JS_BEGIN_EXTERN_C
#define JSSTRING_BIT(n) ((size_t)1 << (n))
#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
@ -471,7 +469,7 @@ JS_ISSPACE(jschar c)
#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
/* Initialize the String class, returning its prototype object. */
extern JSClass js_StringClass;
extern js::Class js_StringClass;
extern JSObject *
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.
*/
typedef JSString *(*JSValueToStringFun)(JSContext *cx, jsval v);
typedef JSString *(*JSValueToStringFun)(JSContext *cx, const js::Value &v);
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) \
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,
* otherwise returning a new string reference.
*/
extern JS_FRIEND_API(JSString *)
js_ValueToString(JSContext *cx, jsval v);
extern JSString *
js_ValueToString(JSContext *cx, const js::Value &v);
/*
* 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
* passed buffer may have partial results appended.
*/
extern JS_FRIEND_API(JSBool)
js_ValueToCharBuffer(JSContext *cx, jsval v, JSCharBuffer &cb);
extern JSBool
js_ValueToCharBuffer(JSContext *cx, const js::Value &v, JSCharBuffer &cb);
/*
* Convert a value to its source expression, returning null after reporting
* an error, otherwise returning a new string reference.
*/
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
@ -713,8 +711,6 @@ js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
extern JSBool
js_String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
JS_END_EXTERN_C
namespace js {
class DeflatedStringCache {

View File

@ -343,6 +343,44 @@ PodArrayZero(T (&t)[N])
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 */
#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* 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");
if (!JSVAL_IS_INT(idx)) {
@ -14564,7 +14564,7 @@ TraceRecorder::record_JSOP_CALLPROP()
if (JSVAL_IS_PRIMITIVE(l)) {
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|");
}

View File

@ -55,7 +55,7 @@ namespace js {
* TypedArray with a size.
*/
struct JS_FRIEND_API(ArrayBuffer) {
static JSClass jsclass;
static js::Class jsclass;
static JSPropertySpec jsprops[];
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.
static JSClass fastClasses[TYPE_MAX];
static js::Class fastClasses[TYPE_MAX];
// These are the slow/original classes, used
// fo constructing new objects
static JSClass slowClasses[TYPE_MAX];
static js::Class slowClasses[TYPE_MAX];
static JSPropertySpec jsprops[];

View File

@ -103,6 +103,18 @@
# ifdef HAVE_VISIBILITY_ATTRIBUTE
# 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)
# define JS_EXTERNAL_VIS __global
# else

View File

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

View File

@ -41,8 +41,6 @@
#include "jspubtd.h"
JS_BEGIN_EXTERN_C
extern const char js_AnyName_str[];
extern const char js_AttributeName_str[];
extern const char js_isXMLName_str[];
@ -59,7 +57,7 @@ typedef JSBool
struct JSXMLArray {
uint32 length;
uint32 capacity;
void **vector;
js::Value *vector;
JSXMLArrayCursor *cursors;
};
@ -69,11 +67,12 @@ struct JSXMLArrayCursor
uint32 index;
JSXMLArrayCursor *next;
JSXMLArrayCursor **prevp;
void *root;
js::Value root;
js::Value null;
JSXMLArrayCursor(JSXMLArray *array)
: array(array), index(0), next(array->cursors), prevp(&array->cursors),
root(NULL)
root(), null()
{
if (next)
next->prevp = &next;
@ -91,16 +90,18 @@ struct JSXMLArrayCursor
array = NULL;
}
void *getNext() {
const js::Value &getNext() {
if (!array || index >= array->length)
return NULL;
return root = array->vector[index++];
return null;
root.copy(array->vector[index++]);
return root;
}
void *getCurrent() {
const js::Value &getCurrent() {
if (!array || index >= array->length)
return NULL;
return root = array->vector[index];
return null;
root.copy(array->vector[index]);
return root;
}
void trace(JSTracer *trc) {
@ -108,9 +109,8 @@ struct JSXMLArrayCursor
size_t index = 0;
#endif
for (JSXMLArrayCursor *cursor = this; cursor; cursor = cursor->next) {
void *root = cursor->root;
JS_SET_TRACING_INDEX(trc, "cursor_root", index++);
js_CallValueTracerIfGCThing(trc, jsval(root));
CallGCMarkerIfGCThing(trc, cursor->root);
}
}
};
@ -173,7 +173,7 @@ struct JSXML {
} u;
};
JS_STATIC_ASSERT(sizeof(JSXML) % JSVAL_ALIGN == 0);
JS_STATIC_ASSERT(sizeof(JSXML) % JSBOXEDWORD_ALIGN == 0);
/* union member shorthands */
#define xml_kids u.list.kids
@ -209,13 +209,13 @@ js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
extern JSObject *
js_GetXMLObject(JSContext *cx, JSXML *xml);
extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
extern JS_FRIEND_DATA(JSClass) js_XMLClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass;
extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass;
extern JS_FRIEND_DATA(JSClass) js_AnyNameClass;
extern JSClass js_XMLFilterClass;
extern JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps;
extern JS_FRIEND_DATA(js::Class) js_XMLClass;
extern JS_FRIEND_DATA(js::ExtendedClass) js_NamespaceClass;
extern JS_FRIEND_DATA(js::ExtendedClass) js_QNameClass;
extern JS_FRIEND_DATA(js::Class) js_AttributeNameClass;
extern JS_FRIEND_DATA(js::Class) js_AnyNameClass;
extern js::Class js_XMLFilterClass;
/*
* 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 VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \
JSVAL_TO_OBJECT(v)->isXML())
#define VALUE_IS_XML(cx,v) ((v).isObject() && \
(v).asObject().isXML())
extern JSObject *
js_InitNamespaceClass(JSContext *cx, JSObject *obj);
@ -253,7 +253,7 @@ extern JSObject *
js_InitXMLClasses(JSContext *cx, JSObject *obj);
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,
@ -266,7 +266,7 @@ extern JSBool
js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);
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
@ -277,7 +277,7 @@ extern JSBool
js_IsXMLName(JSContext *cx, jsval v);
extern JSBool
js_ToAttributeName(JSContext *cx, jsval *vp);
js_ToAttributeName(JSContext *cx, js::Value *vp);
extern JSString *
js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
@ -290,25 +290,26 @@ extern JSString *
js_EscapeElementValue(JSContext *cx, JSString *str);
extern JSString *
js_ValueToXMLString(JSContext *cx, jsval v);
js_ValueToXMLString(JSContext *cx, const js::Value &v);
extern JSObject *
js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval);
js_ConstructXMLQNameObject(JSContext *cx, const js::Value & nsval,
const js::Value & lnval);
extern JSBool
js_GetAnyName(JSContext *cx, jsval *vp);
js_GetAnyName(JSContext *cx, js::Value *vp);
/*
* Note: nameval must be either QName, AttributeName, or AnyName.
*/
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
js_GetXMLMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
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
js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
@ -317,10 +318,10 @@ extern JSBool
js_StepXMLListFilter(JSContext *cx, JSBool initialized);
extern JSObject *
js_ValueToXMLObject(JSContext *cx, jsval v);
js_ValueToXMLObject(JSContext *cx, const js::Value &v);
extern JSObject *
js_ValueToXMLListObject(JSContext *cx, jsval v);
js_ValueToXMLListObject(JSContext *cx, const js::Value &v);
extern JSObject *
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);
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
js_ConcatenateXML(JSContext *cx, JSObject *obj, jsval v, jsval *vp);
JS_END_EXTERN_C
js_ConcatenateXML(JSContext *cx, JSObject *obj1, JSObject *obj2, js::Value *vp);
#endif /* jsxml_h___ */