This commit is contained in:
Luke Wagner 2010-05-10 22:01:31 -07:00
Родитель 2ea3056f2b
Коммит 55e7f5e2d3
62 изменённых файлов: 7364 добавлений и 5518 удалений

Просмотреть файл

@ -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();

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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();
}

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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)

Просмотреть файл

@ -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;

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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;

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);

Просмотреть файл

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

Просмотреть файл

@ -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);

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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);

Просмотреть файл

@ -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));
}
}
}

Просмотреть файл

@ -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.:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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___ */

Просмотреть файл

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

Просмотреть файл

@ -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 *

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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;

Просмотреть файл

@ -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; }

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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))

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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; }

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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___ */

Просмотреть файл

@ -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)

Просмотреть файл

@ -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 &&

Просмотреть файл

@ -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),

Просмотреть файл

@ -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);

Просмотреть файл

@ -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))

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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_ */

Просмотреть файл

@ -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|");
}

Просмотреть файл

@ -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[];

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
/*

Просмотреть файл

@ -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___ */