Fixed getter/setters, pave way for brutal sharing (15146, r=shaver@mozilla.org,rogerl@netscape.com)

This commit is contained in:
brendan%mozilla.org 1999-11-02 02:23:50 +00:00
Родитель 7ffe77c49e
Коммит f6243a48b1
13 изменённых файлов: 312 добавлений и 285 удалений

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

@ -976,7 +976,7 @@ DumpScope(JSContext *cx, JSObject *obj, JSHashEnumerator dump, FILE *fp)
int i;
fprintf(fp, "\n%s scope contents:\n", OBJ_GET_CLASS(cx, obj)->name);
scope = (JSScope *)obj->map;
scope = OBJ_SCOPE(obj);
if (!MAP_IS_NATIVE(&scope->map))
return;
if (scope->ops == &js_list_scope_ops) {

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

@ -1661,7 +1661,7 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
if (!atom) {
ok = JS_FALSE;
} else {
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
ok = (scope->ops->add(cx, scope, (jsid)atom, (JSScopeProperty *)prop)
!= NULL);
}
@ -2006,7 +2006,7 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
return JS_FALSE;
}
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
ok = (scope->ops->add(cx, scope, INT_TO_JSVAL(alias),
(JSScopeProperty *)prop)
!= NULL);
@ -2506,11 +2506,16 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
funAtom = NULL;
goto out;
}
funAtom = js_Atomize(cx, name, strlen(name), 0);
if (!funAtom) {
fun = NULL;
goto out;
if (!name) {
funAtom = NULL;
} else {
funAtom = js_Atomize(cx, name, strlen(name), 0);
if (!funAtom) {
fun = NULL;
goto out;
}
}
/* XXXbe new-function, bind name only on success */
fun = js_DefineFunction(cx, obj, funAtom, NULL, nargs, 0);
if (!fun)
goto out;

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

@ -251,9 +251,9 @@ DropWatchPoint(JSContext *cx, JSWatchPoint *wp)
{
if (--wp->nrefs != 0)
return;
wp->sprop->setter = wp->setter;
SPROP_SETTER(wp->sprop, wp->object) = wp->setter;
JS_LOCK_OBJ_VOID(cx, wp->object,
js_DropScopeProperty(cx, (JSScope *)wp->object->map,
js_DropScopeProperty(cx, OBJ_SCOPE(wp->object),
wp->sprop));
JS_REMOVE_LINK(&wp->links);
js_RemoveRoot(cx->runtime, &wp->closure);
@ -319,7 +319,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
}
symid = (jsid)atom;
}
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
JS_ASSERT(scope->props);
ok = LOCKED_OBJ_GET_CLASS(obj)->addProperty(cx, obj, sprop->id,
&value);
@ -409,8 +409,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
return JS_FALSE;
}
}
getter = sprop->getter;
setter = sprop->setter;
getter = SPROP_GETTER(sprop, pobj);
setter = SPROP_SETTER(sprop, pobj);
attrs = sprop->attrs;
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
@ -434,9 +434,9 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
JS_APPEND_LINK(&wp->links, &rt->watchPointList);
wp->object = obj;
wp->userid = id;
wp->sprop = js_HoldScopeProperty(cx, (JSScope *)obj->map, sprop);
wp->setter = sprop->setter;
sprop->setter = js_watch_set;
wp->sprop = js_HoldScopeProperty(cx, OBJ_SCOPE(obj), sprop);
wp->setter = SPROP_SETTER(sprop, obj);
SPROP_SETTER(sprop, obj) = js_watch_set;
wp->nrefs = 1;
}
wp->handler = handler;
@ -732,7 +732,7 @@ JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
JSScope *scope;
sprop = *iteratorp;
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
sprop = (sprop == NULL) ? scope->props : sprop->next;
*iteratorp = sprop;
return sprop;
@ -743,23 +743,25 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
JSPropertyDesc *pd)
{
JSSymbol *sym;
JSPropertyOp getter;
sym = sprop->symbols;
pd->id = sym ? js_IdToValue(sym_id(sym)) : JSVAL_VOID;
if (!sym || !js_GetProperty(cx, obj, sym_id(sym), &pd->value))
pd->value = OBJ_GET_SLOT(cx, obj, sprop->slot);
getter = SPROP_GETTER(sprop, obj);
pd->flags = ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
| ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
| ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0)
#if JS_HAS_CALL_OBJECT
| ((sprop->getter == js_GetCallVariable) ? JSPD_VARIABLE : 0)
| ((getter == js_GetCallVariable) ? JSPD_VARIABLE : 0)
#endif /* JS_HAS_CALL_OBJECT */
| ((sprop->getter == js_GetArgument) ? JSPD_ARGUMENT : 0)
| ((sprop->getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0);
| ((getter == js_GetArgument) ? JSPD_ARGUMENT : 0)
| ((getter == js_GetLocalVariable) ? JSPD_VARIABLE : 0);
#if JS_HAS_CALL_OBJECT
/* for Call Object 'real' getter isn't passed in to us */
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass &&
sprop->getter == js_CallClass.getProperty) {
getter == js_CallClass.getProperty) {
pd->flags |= JSPD_ARGUMENT;
}
#endif /* JS_HAS_CALL_OBJECT */
@ -795,10 +797,9 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
return JS_FALSE;
/* have no props, or object's scope has not mutated from that of proto */
scope = (JSScope *)obj->map;
scope = OBJ_SCOPE(obj);
if (!scope->props ||
(OBJ_GET_PROTO(cx,obj) &&
scope == (JSScope *)(OBJ_GET_PROTO(cx,obj)->map))) {
(OBJ_GET_PROTO(cx,obj) && scope == OBJ_SCOPE(OBJ_GET_PROTO(cx,obj)))) {
pda->length = 0;
pda->array = NULL;
return JS_TRUE;

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

@ -469,9 +469,9 @@ call_enumerate(JSContext *cx, JSObject *obj)
return JS_TRUE;
/* Reflect actual args for formal parameters, and all local variables. */
scope = (JSScope *)fun->object->map;
scope = OBJ_SCOPE(fun->object);
for (sprop = scope->props; sprop; sprop = sprop->next) {
getter = sprop->getter;
getter = SPROP_GETTER_SCOPE(sprop, scope);
if (getter != js_GetArgument && getter != js_GetLocalVariable)
continue;
@ -518,7 +518,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
}
if (sprop) {
getter = sprop->getter;
getter = SPROP_GETTER(sprop, obj2);
propid = sprop->id;
symid = (jsid) sym_atom(sprop->symbols);
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
@ -804,7 +804,7 @@ fun_enumProperty(JSContext *cx, JSObject *obj)
*/
JS_LOCK_OBJ(cx, obj);
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
for (sprop = scope->props; sprop; sprop = sprop->next) {
jsval id = sprop->id;
if (!JSVAL_IS_INT(id)) {
@ -1023,13 +1023,15 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
/* do arguments and local vars */
if (fun->object) {
if (xdr->mode == JSXDR_ENCODE) {
JSScope *scope = (JSScope *) fun->object->map;
JSScope *scope = OBJ_SCOPE(fun->object);
for (sprop = scope->props; sprop; sprop = sprop->next) {
if (sprop->getter == js_GetArgument) {
JSPropertyOp getter = SPROP_GETTER_SCOPE(sprop, scope);
if (getter == js_GetArgument) {
type = JSXDR_FUNARG;
JS_ASSERT(nargs++ <= fun->nargs);
} else if (sprop->getter == js_GetLocalVariable) {
} else if (getter == js_GetLocalVariable) {
type = JSXDR_FUNVAR;
JS_ASSERT(nvars++ <= fun->nvars);
} else {
@ -1535,7 +1537,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
if (sprop && obj2 == obj) {
#ifdef CHECK_ARGUMENT_HIDING
JS_ASSERT(sprop->getter == js_GetArgument);
JS_ASSERT(SPROP_GETTER(sprop, obj) == js_GetArgument);
OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *)sprop);
JS_ReportErrorNumber(cx, JSREPORT_WARNING,
JSMSG_SAME_FORMAL, ATOM_BYTES(atom));

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

@ -502,7 +502,7 @@ gc_mark(JSRuntime *rt, void *thing)
obj = thing;
vp = obj->slots;
if (vp) {
scope = OBJ_IS_NATIVE(obj) ? (JSScope *) obj->map : NULL;
scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL;
if (scope) {
clasp = JSVAL_TO_PRIVATE(obj->slots[JSSLOT_CLASS]);
@ -550,7 +550,8 @@ gc_mark(JSRuntime *rt, void *thing)
id, js_getter_str);
#endif
GC_MARK(rt,
JSVAL_TO_GCTHING((jsval)sprop->getter),
JSVAL_TO_GCTHING((jsval)
SPROP_GETTER_SCOPE(sprop, scope)),
buf,
prev);
}
@ -560,7 +561,8 @@ gc_mark(JSRuntime *rt, void *thing)
id, js_setter_str);
#endif
GC_MARK(rt,
JSVAL_TO_GCTHING((jsval)sprop->setter),
JSVAL_TO_GCTHING((jsval)
SPROP_SETTER_SCOPE(sprop, scope)),
buf,
prev);
}

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

@ -70,11 +70,11 @@ js_UnlockGlobal(void *id)
}
#define ReadWord(W) (W)
#define AtomicAddBody(P,I)\
jsword n;\
do {\
n = ReadWord(*(P));\
} while (!js_CompareAndSwap(P, n, n + I));
#define AtomicAddBody(P,I) \
jsword n; \
do { \
n = ReadWord(*(P)); \
} while (!js_CompareAndSwap(P, n, n + I))
/* Exclude Alpha NT. */
#if defined(_WIN32) && defined(_M_IX86) && !defined(NSPR_LOCK)
@ -112,10 +112,10 @@ static PRLock *_counter_lock;
#define UsingCounterLock 1
#undef AtomicAddBody
#define AtomicAddBody(P,I) \
PR_Lock(_counter_lock);\
*(P) += I;\
PR_Unlock(_counter_lock);
#define AtomicAddBody(P,I) \
PR_Lock(_counter_lock); \
*(P) += I; \
PR_Unlock(_counter_lock)
#endif /* !ULTRA_SPARC */
@ -182,10 +182,10 @@ static PRLock *_counter_lock;
#define UsingCounterLock 1
#undef AtomicAddBody
#define AtomicAddBody(P,I) \
PR_Lock(_counter_lock);\
*(P) += I;\
PR_Unlock(_counter_lock);
#define AtomicAddBody(P,I) \
PR_Lock(_counter_lock); \
*(P) += I; \
PR_Unlock(_counter_lock)
static PRLock *_compare_and_swap_lock;
#define UsingCompareAndSwapLock 1
@ -219,25 +219,25 @@ js_CurrentThreadId()
}
void
js_NewLock(JSThinLock *p)
js_NewLock(JSThinLock *tl)
{
#ifdef NSPR_LOCK
p->owner = 0;
p->fat = (JSFatLock*)JS_NEW_LOCK();
tl->owner = 0;
tl->fat = (JSFatLock*)JS_NEW_LOCK();
#else
memset(p, 0, sizeof(JSThinLock));
memset(tl, 0, sizeof(JSThinLock));
#endif
}
void
js_DestroyLock(JSThinLock *p)
js_DestroyLock(JSThinLock *tl)
{
#ifdef NSPR_LOCK
p->owner = 0xdeadbeef;
JS_DESTROY_LOCK(((JSLock*)p->fat));
tl->owner = 0xdeadbeef;
JS_DESTROY_LOCK(((JSLock*)tl->fat));
#else
JS_ASSERT(p->owner == 0);
JS_ASSERT(p->fat == NULL);
JS_ASSERT(tl->owner == 0);
JS_ASSERT(tl->fat == NULL);
#endif
}
@ -248,27 +248,27 @@ js_GetSlotWhileLocked(JSContext *cx, JSObject *obj, uint32 slot)
{
jsval v;
#ifndef NSPR_LOCK
JSScope *scp = (JSScope *)obj->map;
JSThinLock *p = &scp->lock;
JSScope *scope = OBJ_SCOPE(obj);
JSThinLock *tl = &scope->lock;
jsword me = cx->thread;
#endif
JS_ASSERT(obj->slots && slot < obj->map->freeslot);
#ifndef NSPR_LOCK
JS_ASSERT(me == CurrentThreadId());
if (js_CompareAndSwap(&p->owner, 0, me)) {
if (scp == (JSScope *)obj->map) {
if (js_CompareAndSwap(&tl->owner, 0, me)) {
if (scope == OBJ_SCOPE(obj)) {
v = obj->slots[slot];
if (!js_CompareAndSwap(&p->owner, me, 0)) {
scp->count = 1;
if (!js_CompareAndSwap(&tl->owner, me, 0)) {
scope->count = 1;
js_UnlockObj(cx,obj);
}
return v;
}
if (!js_CompareAndSwap(&p->owner, me, 0))
js_Dequeue(p);
if (!js_CompareAndSwap(&tl->owner, me, 0))
js_Dequeue(tl);
}
else if (Thin_RemoveWait(ReadWord(p->owner)) == me) {
else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
return obj->slots[slot];
}
#endif
@ -282,27 +282,27 @@ JS_INLINE void
js_SetSlotWhileLocked(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
{
#ifndef NSPR_LOCK
JSScope *scp = (JSScope *)obj->map;
JSThinLock *p = &scp->lock;
JSScope *scope = OBJ_SCOPE(obj);
JSThinLock *tl = &scope->lock;
jsword me = cx->thread;
#endif
JS_ASSERT(obj->slots && slot < obj->map->freeslot);
#ifndef NSPR_LOCK
JS_ASSERT(me == CurrentThreadId());
if (js_CompareAndSwap(&p->owner, 0, me)) {
if (scp == (JSScope *)obj->map) {
if (js_CompareAndSwap(&tl->owner, 0, me)) {
if (scope == OBJ_SCOPE(obj)) {
obj->slots[slot] = v;
if (!js_CompareAndSwap(&p->owner, me, 0)) {
scp->count = 1;
if (!js_CompareAndSwap(&tl->owner, me, 0)) {
scope->count = 1;
js_UnlockObj(cx,obj);
}
return;
}
if (!js_CompareAndSwap(&p->owner, me, 0))
js_Dequeue(p);
if (!js_CompareAndSwap(&tl->owner, me, 0))
js_Dequeue(tl);
}
else if (Thin_RemoveWait(ReadWord(p->owner)) == me) {
else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
obj->slots[slot] = v;
return;
}
@ -316,7 +316,7 @@ static JSFatLock *
mallocFatlock()
{
JSFatLock *fl = (JSFatLock *)malloc(sizeof(JSFatLock)); /* for now */
JS_ASSERT(fl);
if (!fl) return NULL;
fl->susp = 0;
fl->next = NULL;
fl->prev = NULL;
@ -338,13 +338,13 @@ listOfFatlocks(int l)
{
JSFatLock *m;
JSFatLock *m0;
int i;
int i;
JS_ASSERT(l>0);
m0 = m = mallocFatlock();
for (i=1; i<l; i++) {
m->next = mallocFatlock();
m = m->next;
m->next = mallocFatlock();
m = m->next;
}
return m0;
}
@ -364,25 +364,25 @@ static JSFatLockTable* _fl_tables;
static JSFatLock *
allocateFatlock(void *id)
{
JSFatLock *m;
JSFatLock *m;
int i = ((int)id/4)%_nr_of_globals;
if (_fl_tables[i].free == NULL) {
#ifdef DEBUG
printf("Ran out of fat locks!\n");
#endif
_fl_tables[i].free = listOfFatlocks(10);
}
m = _fl_tables[i].free;
_fl_tables[i].free = m->next;
_fl_tables[i].free->prev = NULL;
m->susp = 0;
m->next = _fl_tables[i].taken;
m->prev = NULL;
if (_fl_tables[i].taken != NULL)
_fl_tables[i].taken->prev = m;
_fl_tables[i].taken = m;
return m;
int i = ((int)id/4)%_nr_of_globals;
if (_fl_tables[i].free == NULL) {
#ifdef DEBUG
printf("Ran out of fat locks!\n");
#endif
_fl_tables[i].free = listOfFatlocks(10);
}
m = _fl_tables[i].free;
_fl_tables[i].free = m->next;
_fl_tables[i].free->prev = NULL;
m->susp = 0;
m->next = _fl_tables[i].taken;
m->prev = NULL;
if (_fl_tables[i].taken != NULL)
_fl_tables[i].taken->prev = m;
_fl_tables[i].taken = m;
return m;
}
static void
@ -508,93 +508,93 @@ js_InitContextForLocking(JSContext *cx)
(ii) fl->susp >= 0
*/
static int
js_SuspendThread(JSThinLock *p)
js_SuspendThread(JSThinLock *tl)
{
JSFatLock *fl;
JSStatus stat;
if (p->fat == NULL)
fl = p->fat = allocateFatlock(p);
if (tl->fat == NULL)
fl = tl->fat = allocateFatlock(tl);
else
fl = p->fat;
fl = tl->fat;
JS_ASSERT(fl->susp >= 0);
fl->susp++;
PR_Lock(fl->slock);
js_UnlockGlobal(p);
js_UnlockGlobal(tl);
stat = (JSStatus)PR_WaitCondVar(fl->svar,PR_INTERVAL_NO_TIMEOUT);
JS_ASSERT(stat != JS_FAILURE);
PR_Unlock(fl->slock);
js_LockGlobal(p);
js_LockGlobal(tl);
fl->susp--;
if (fl->susp == 0) {
deallocateFatlock(fl,p);
p->fat = NULL;
deallocateFatlock(fl,tl);
tl->fat = NULL;
}
return p->fat == NULL;
return tl->fat == NULL;
}
/* (i) global lock is held
/* (i) global lock is held
(ii) fl->susp > 0
*/
static void
js_ResumeThread(JSThinLock *p)
js_ResumeThread(JSThinLock *tl)
{
JSFatLock *fl = p->fat;
JSFatLock *fl = tl->fat;
JSStatus stat;
JS_ASSERT(fl != NULL);
JS_ASSERT(fl->susp > 0);
PR_Lock(fl->slock);
js_UnlockGlobal(p);
js_UnlockGlobal(tl);
stat = (JSStatus)PR_NotifyCondVar(fl->svar);
JS_ASSERT(stat != JS_FAILURE);
PR_Unlock(fl->slock);
}
static void
js_Enqueue(JSThinLock *p, jsword me)
js_Enqueue(JSThinLock *tl, jsword me)
{
jsword o, n;
js_LockGlobal(p);
js_LockGlobal(tl);
while (1) {
o = ReadWord(p->owner);
o = ReadWord(tl->owner);
n = Thin_SetWait(o);
if (o != 0 && js_CompareAndSwap(&p->owner,o,n)) {
if (js_SuspendThread(p))
if (o != 0 && js_CompareAndSwap(&tl->owner,o,n)) {
if (js_SuspendThread(tl))
me = Thin_RemoveWait(me);
else
me = Thin_SetWait(me);
}
else if (js_CompareAndSwap(&p->owner,0,me)) {
js_UnlockGlobal(p);
else if (js_CompareAndSwap(&tl->owner,0,me)) {
js_UnlockGlobal(tl);
return;
}
}
}
static void
js_Dequeue(JSThinLock *p)
js_Dequeue(JSThinLock *tl)
{
int o;
js_LockGlobal(p);
o = ReadWord(p->owner);
js_LockGlobal(tl);
o = ReadWord(tl->owner);
JS_ASSERT(Thin_GetWait(o) != 0);
JS_ASSERT(p->fat != NULL);
if (!js_CompareAndSwap(&p->owner,o,0)) /* release it */
JS_ASSERT(tl->fat != NULL);
if (!js_CompareAndSwap(&tl->owner,o,0)) /* release it */
JS_ASSERT(0);
js_ResumeThread(p);
js_ResumeThread(tl);
}
JS_INLINE void
js_Lock(JSThinLock *p, jsword me)
js_Lock(JSThinLock *tl, jsword me)
{
JS_ASSERT(me == CurrentThreadId());
if (js_CompareAndSwap(&p->owner, 0, me))
if (js_CompareAndSwap(&tl->owner, 0, me))
return;
if (Thin_RemoveWait(ReadWord(p->owner)) != me)
js_Enqueue(p, me);
if (Thin_RemoveWait(ReadWord(tl->owner)) != me)
js_Enqueue(tl, me);
#ifdef DEBUG
else
JS_ASSERT(0);
@ -602,13 +602,13 @@ js_Lock(JSThinLock *p, jsword me)
}
JS_INLINE void
js_Unlock(JSThinLock *p, jsword me)
js_Unlock(JSThinLock *tl, jsword me)
{
JS_ASSERT(me == CurrentThreadId());
if (js_CompareAndSwap(&p->owner, me, 0))
if (js_CompareAndSwap(&tl->owner, me, 0))
return;
if (Thin_RemoveWait(ReadWord(p->owner)) == me)
js_Dequeue(p);
if (Thin_RemoveWait(ReadWord(tl->owner)) == me)
js_Dequeue(tl);
#ifdef DEBUG
else
JS_ASSERT(0);
@ -619,35 +619,35 @@ void
js_LockRuntime(JSRuntime *rt)
{
jsword me = CurrentThreadId();
JSThinLock *p;
JSThinLock *tl;
JS_ASSERT(Thin_RemoveWait(ReadWord(rt->rtLock.owner)) != me);
p = &rt->rtLock;
JS_LOCK0(p,me);
tl = &rt->rtLock;
JS_LOCK0(tl,me);
}
void
js_UnlockRuntime(JSRuntime *rt)
{
jsword me = CurrentThreadId();
JSThinLock *p;
JSThinLock *tl;
JS_ASSERT(Thin_RemoveWait(ReadWord(rt->rtLock.owner)) == me);
p = &rt->rtLock;
JS_UNLOCK0(p,me);
tl = &rt->rtLock;
JS_UNLOCK0(tl,me);
}
static JS_INLINE void
js_LockScope1(JSContext *cx, JSScope *scope, jsword me)
{
JSThinLock *p;
JSThinLock *tl;
if (Thin_RemoveWait(ReadWord(scope->lock.owner)) == me) {
JS_ASSERT(scope->count > 0);
scope->count++;
} else {
p = &scope->lock;
JS_LOCK0(p,me);
tl = &scope->lock;
JS_LOCK0(tl,me);
JS_ASSERT(scope->count == 0);
scope->count = 1;
}
@ -664,7 +664,7 @@ void
js_UnlockScope(JSContext *cx, JSScope *scope)
{
jsword me = cx->thread;
JSThinLock *p;
JSThinLock *tl;
JS_ASSERT(scope->count > 0);
if (Thin_RemoveWait(ReadWord(scope->lock.owner)) != me) {
@ -672,8 +672,8 @@ js_UnlockScope(JSContext *cx, JSScope *scope)
return;
}
if (--scope->count == 0) {
p = &scope->lock;
JS_UNLOCK0(p,me);
tl = &scope->lock;
JS_UNLOCK0(tl,me);
}
}
@ -681,30 +681,32 @@ void
js_TransferScopeLock(JSContext *cx, JSScope *oldscope, JSScope *newscope)
{
jsword me;
JSThinLock *p;
JSThinLock *tl;
JS_ASSERT(JS_IS_SCOPE_LOCKED(newscope));
/*
* If the last reference to oldscope went away, newscope needs no lock
* state update.
*/
if (!oldscope) {
if (!oldscope)
return;
}
JS_ASSERT(JS_IS_SCOPE_LOCKED(oldscope));
/*
* Transfer oldscope's entry count to newscope, as it will be unlocked
* now via JS_UNLOCK_OBJ(cx,obj) calls made while we unwind the C stack
* from the current point (under js_GetMutableScope).
*/
newscope->count = oldscope->count;
/*
* Reset oldscope's lock state so that it is completely unlocked.
*/
oldscope->count = 0;
p = &oldscope->lock;
tl = &oldscope->lock;
me = cx->thread;
JS_UNLOCK0(p,me);
JS_UNLOCK0(tl,me);
}
void
@ -714,22 +716,22 @@ js_LockObj(JSContext *cx, JSObject *obj)
jsword me = cx->thread;
JS_ASSERT(me == CurrentThreadId());
for (;;) {
scope = (JSScope *) obj->map;
js_LockScope1(cx, scope, me);
scope = OBJ_SCOPE(obj);
js_LockScope1(cx, scope, me);
/* If obj still has this scope, we're done. */
if (scope == (JSScope *) obj->map)
return;
/* If obj still has this scope, we're done. */
if (scope == OBJ_SCOPE(obj))
return;
/* Lost a race with a mutator; retry with obj's new scope. */
js_UnlockScope(cx, scope);
/* Lost a race with a mutator; retry with obj's new scope. */
js_UnlockScope(cx, scope);
}
}
void
js_UnlockObj(JSContext *cx, JSObject *obj)
{
js_UnlockScope(cx, (JSScope *) obj->map);
js_UnlockScope(cx, OBJ_SCOPE(obj));
}
#ifdef DEBUG
@ -742,9 +744,10 @@ js_IsRuntimeLocked(JSRuntime *rt)
JSBool
js_IsObjLocked(JSObject *obj)
{
JSObjectMap *map = obj->map;
JSScope *scope = OBJ_SCOPE(obj);
return MAP_IS_NATIVE(map) && CurrentThreadId() == Thin_RemoveWait(ReadWord(((JSScope *)map)->lock.owner));
return MAP_IS_NATIVE(&scope->map) &&
CurrentThreadId() == Thin_RemoveWait(ReadWord(scope->lock.owner));
}
JSBool

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

@ -87,7 +87,7 @@ typedef struct JSFatLockTable {
#include "jsscope.h"
#define _SET_OBJ_INFO(obj,f,l) \
_SET_SCOPE_INFO(((JSScope*)obj->map),f,l)
_SET_SCOPE_INFO(OBJ_SCOPE(obj),f,l)
#define _SET_SCOPE_INFO(scope,f,l) \
(JS_ASSERT(scope->count > 0 && scope->count <= 4), \

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

@ -249,7 +249,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
val = JSVAL_NULL;
if (attrs & JSPROP_GETTER)
val = (jsval) ((JSScopeProperty *)prop)->getter;
val = (jsval)SPROP_GETTER((JSScopeProperty*)prop, obj2);
if (attrs & JSPROP_SETTER) {
if (val != JSVAL_NULL) {
/* Mark the getter here, then set val to setter. */
@ -257,7 +257,7 @@ MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
NULL)
!= NULL);
}
val = (jsval) ((JSScopeProperty *)prop)->setter;
val = (jsval)SPROP_SETTER((JSScopeProperty*)prop, obj2);
}
} else {
ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
@ -486,13 +486,15 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
valcnt = 0;
if (attrs & JSPROP_GETTER) {
val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
val[valcnt] = (jsval)
SPROP_GETTER((JSScopeProperty *)prop, obj2);
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
valcnt++;
}
if (attrs & JSPROP_SETTER) {
val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter;
val[valcnt] = (jsval)
SPROP_SETTER((JSScopeProperty *)prop, obj2);
gsop[valcnt] =
ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
valcnt++;
@ -1516,9 +1518,9 @@ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
(sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
sprop->attrs |= attrs;
if (attrs & JSPROP_GETTER)
sprop->getter = getter;
SPROP_GETTER(sprop, pobj) = getter;
else
sprop->setter = setter;
SPROP_SETTER(sprop, pobj) = setter;
if (propp)
*propp = (JSProperty *) sprop;
#ifdef JS_THREADSAFE
@ -1610,7 +1612,7 @@ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
for (;;) {
JS_LOCK_OBJ(cx, obj);
_SET_OBJ_INFO(obj, file, line);
scope = (JSScope *)obj->map;
scope = OBJ_SCOPE(obj);
if (scope == prevscope)
goto skip;
sym = scope->ops->lookup(cx, scope, id, hash);
@ -1635,7 +1637,7 @@ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
JS_LOCK_OBJ(cx, obj);
_SET_OBJ_INFO(obj, file, line);
if (obj2) {
scope = (JSScope *)obj2->map;
scope = OBJ_SCOPE(obj2);
if (MAP_IS_NATIVE(&scope->map))
sym = scope->ops->lookup(cx, scope, id, hash);
}
@ -1645,14 +1647,14 @@ js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
return JS_FALSE;
JS_LOCK_OBJ(cx, obj);
_SET_OBJ_INFO(obj, file, line);
scope = (JSScope *)obj->map;
scope = OBJ_SCOPE(obj);
if (MAP_IS_NATIVE(&scope->map))
sym = scope->ops->lookup(cx, scope, id, hash);
}
}
}
if (sym && (sprop = sym_property(sym)) != NULL) {
JS_ASSERT((JSScope *)obj->map == scope);
JS_ASSERT(OBJ_SCOPE(obj) == scope);
*objp = scope->object; /* XXXbe hide in jsscope.[ch] */
#ifdef JS_THREADSAFE
js_HoldScopeProperty(cx, scope, sprop);
@ -1924,7 +1926,7 @@ js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
JS_UNLOCK_OBJ(cx, obj);
while (proto) {
JS_LOCK_OBJ(cx, proto);
protoscope = (JSScope *)proto->map;
protoscope = OBJ_SCOPE(proto);
if (MAP_IS_NATIVE(&protoscope->map)) {
protosym = protoscope->ops->lookup(cx, protoscope, id, hash);
if (protosym) {
@ -1952,8 +1954,8 @@ js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
#endif /* JS_HAS_GETTER_SETTER */
protoid = protosprop->id;
protogetter = protosprop->getter;
protosetter = protosprop->setter;
protogetter = SPROP_GETTER_SCOPE(protosprop,protoscope);
protosetter = SPROP_SETTER_SCOPE(protosprop,protoscope);
JS_UNLOCK_OBJ(cx, proto);
break;
}
@ -2191,7 +2193,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
}
GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
scope = (JSScope *)obj->map;
scope = OBJ_SCOPE(obj);
/*
* Purge cache only if prop is not about to be destroyed (since
@ -2203,7 +2205,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
}
#if JS_HAS_OBJ_WATCHPOINT
if (sprop->setter == js_watch_set) {
if (SPROP_SETTER_SCOPE(sprop, scope) == js_watch_set) {
/*
* Keep the symbol around with null value in case of re-set.
* The watchpoint will hold the "deleted" property until it
@ -2381,7 +2383,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
* deleted during the iteration.
*/
JS_LOCK_OBJ(cx, obj);
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
/*
* If this object shares a scope with its prototype, don't enumerate
@ -2389,7 +2391,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
* when the prototype object is enumerated.
*/
proto_obj = OBJ_GET_PROTO(cx, obj);
if (proto_obj && (scope == (JSScope *)proto_obj->map)) {
if (proto_obj && scope == OBJ_SCOPE(proto_obj)) {
ida = js_NewIdArray(cx, 0);
if (!ida) {
JS_UNLOCK_OBJ(cx, obj);
@ -2553,7 +2555,7 @@ js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
void
js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
{
js_DropScopeProperty(cx, (JSScope *)obj->map, (JSScopeProperty *)prop);
js_DropScopeProperty(cx, OBJ_SCOPE(obj), (JSScopeProperty *)prop);
JS_UNLOCK_OBJ(cx, obj);
}
#endif

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

@ -165,8 +165,8 @@ struct JSObject {
extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps;
extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps;
extern JSClass js_ObjectClass;
extern JSClass js_WithClass;
extern JSClass js_ObjectClass;
extern JSClass js_WithClass;
struct JSSharpObjectMap {
jsrefcount depth;

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

@ -451,7 +451,7 @@ js_NewPrinter(JSContext *cx, const char *name, uintN indent, JSBool pretty)
if (fp && fp->scopeChain) {
obj = fp->scopeChain;
map = obj->map;
if (map->ops == &js_ObjectOps) {
if (MAP_IS_NATIVE(map)) {
if (OBJ_GET_CLASS(cx, obj) == &js_CallClass) {
obj = fp->fun ? fp->fun->object : NULL;
if (obj)
@ -747,7 +747,7 @@ GetSlotAtom(JSScope *scope, JSPropertyOp getter, uintN slot)
if (!scope)
return NULL;
for (sprop = scope->props; sprop; sprop = sprop->next) {
if (sprop->getter != getter)
if (SPROP_GETTER_SCOPE(sprop, scope) != getter)
continue;
if ((uintN)JSVAL_TO_INT(sprop->id) == slot)
return sym_atom(sprop->symbols);
@ -2128,7 +2128,7 @@ js_DecompileFunctionBody(JSPrinter *jp, JSFunction *fun)
js_printf(jp, native_code_str);
return JS_TRUE;
}
scope = fun->object ? (JSScope *)fun->object->map : NULL;
scope = fun->object ? OBJ_SCOPE(fun->object) : NULL;
save = jp->scope;
jp->scope = scope;
ok = js_DecompileCode(jp, script, script->code, (uintN)script->length);
@ -2171,10 +2171,10 @@ js_DecompileFunction(JSPrinter *jp, JSFunction *fun)
for (i = 0; ; i++) {
jsid id;
atom = NULL;
scope = (JSScope *)fun->object->map;
scope = OBJ_SCOPE(fun->object);
for (sprop = scope->props; sprop; sprop = snext) {
snext = sprop->next;
if (sprop->getter != js_GetArgument)
if (SPROP_GETTER_SCOPE(sprop, scope) != js_GetArgument)
continue;
if (JSVAL_IS_INT(sprop->id) && JSVAL_TO_INT(sprop->id) == i) {
atom = sym_atom(sprop->symbols);

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

@ -110,21 +110,18 @@ static JSMemberParser MemberExpr;
static JSParser PrimaryExpr;
/*
* Insist that the next token be of type tt, or report err and throw or fail.
* Insist that the next token be of type tt, or report errno and return null.
* NB: this macro uses cx and ts from its lexical environment.
*/
#define MUST_MATCH_TOKEN_THROW(tt, errno, throw) \
#define MUST_MATCH_TOKEN(tt, errno) \
JS_BEGIN_MACRO \
if (js_GetToken(cx, ts) != tt) { \
js_ReportCompileErrorNumber(cx, ts, JSREPORT_ERROR, errno); \
throw; \
return NULL; \
} \
JS_END_MACRO
#define MUST_MATCH_TOKEN(tt, errno) \
MUST_MATCH_TOKEN_THROW(tt, errno, return NULL)
/*
* Allocate a JSParseNode from cx's temporary arena.
@ -447,9 +444,12 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
JSParseNode *pn, *pn2;
JSOp op;
JSAtom *funAtom, *argAtom;
JSObject *parent;
JSFunction *fun, *outerFun;
JSBool ok, named;
JSObject *parent;
JSPropertyOp getter, setter;
uintN attrs;
JSBool named;
jsval fval;
JSObject *pobj;
JSScopeProperty *sprop;
JSTreeContext funtc;
@ -471,74 +471,55 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (!parent)
return NULL;
/* Set up for ultimate OBJ_DEFINE_PROPERTY call, if not anonymous. */
named = !lambda && funAtom && !InWithStatement(tc);
getter = setter = NULL;
attrs = JSPROP_ENUMERATE;
fun = js_NewFunction(cx, NULL, NULL, 0, 0, parent, funAtom);
if (!fun)
return NULL;
#if JS_HAS_GETTER_SETTER
if (op != JSOP_NOP) {
JSPropertyOp getter, setter;
uintN attr;
uintN gsattr;
fun = js_NewFunction(cx, NULL, NULL, 0, 0, parent, funAtom);
if (!fun)
return NULL;
if (op == JSOP_GETTER) {
getter = (JSPropertyOp) fun->object;
setter = NULL;
attr = JSPROP_GETTER;
gsattr = JSPROP_GETTER;
} else {
getter = NULL;
setter = (JSPropertyOp) fun->object;
attr = JSPROP_SETTER;
gsattr = JSPROP_SETTER;
}
fun->flags |= attr;
fun->flags |= gsattr;
attrs |= gsattr;
if (!lambda && funAtom && !InWithStatement(tc)) {
if (!OBJ_DEFINE_PROPERTY(cx, parent, (jsid)funAtom, JSVAL_VOID,
getter, setter, attr | JSPROP_ENUMERATE,
NULL)) {
return NULL;
}
}
} else
#endif
#if JS_HAS_LEXICAL_CLOSURE
if (lambda || !funAtom || InWithStatement(tc)) {
/* Don't name the function if enclosed by a with statement or equiv. */
fun = js_NewFunction(cx, NULL, NULL, 0, 0, cx->fp->scopeChain,
funAtom);
named = JS_FALSE;
fval = JSVAL_VOID;
} else
#endif
{
/* Don't add the function to it's parent until the parse succeeds. */
fun = js_NewFunction(cx, NULL, NULL, 0, 0, parent, funAtom);
named = (fun != NULL);
}
if (!fun) {
ok = JS_FALSE;
goto out;
fval = OBJECT_TO_JSVAL(fun->object);
}
/* Now parse formal argument list and compute fun->nargs. */
MUST_MATCH_TOKEN_THROW(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL,
ok = JS_FALSE; goto out);
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL);
if (!js_MatchToken(cx, ts, TOK_RP)) {
do {
MUST_MATCH_TOKEN_THROW(TOK_NAME, JSMSG_MISSING_FORMAL,
ok = JS_FALSE; goto out);
MUST_MATCH_TOKEN(TOK_NAME, JSMSG_MISSING_FORMAL);
argAtom = CURRENT_TOKEN(ts).t_atom;
pobj = NULL;
ok = js_LookupProperty(cx, fun->object, (jsid)argAtom, &pobj,
(JSProperty **)&sprop);
if (!ok)
goto out;
if (!js_LookupProperty(cx, fun->object, (jsid)argAtom, &pobj,
(JSProperty **)&sprop)) {
return NULL;
}
if (sprop && pobj == fun->object) {
if (sprop->getter == js_GetArgument) {
if (SPROP_GETTER(sprop, pobj) == js_GetArgument) {
#ifdef CHECK_ARGUMENT_HIDING
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
js_ReportCompileErrorNumber(cx, ts, JSREPORT_WARNING,
JSMSG_DUPLICATE_FORMAL,
ATOM_BYTES(argAtom));
ok = JS_FALSE;
goto out;
return NULL;
#else
/*
* A duplicate parameter name. We create a dummy symbol
@ -549,13 +530,13 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
jsid oldArgId = (jsid) sprop->id;
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
sprop = NULL;
ok = js_DefineProperty(cx, fun->object,
if (!js_DefineProperty(cx, fun->object,
oldArgId, JSVAL_VOID,
js_GetArgument, js_SetArgument,
JSPROP_ENUMERATE | JSPROP_PERMANENT,
(JSProperty **)&sprop);
if (!ok)
goto out;
(JSProperty **)&sprop)) {
return NULL;
}
sprop->id = (jsid) argAtom;
#endif
}
@ -564,35 +545,30 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
OBJ_DROP_PROPERTY(cx, pobj, (JSProperty *)sprop);
sprop = NULL;
}
ok = js_DefineProperty(cx, fun->object,
if (!js_DefineProperty(cx, fun->object,
(jsid)argAtom, JSVAL_VOID,
js_GetArgument, js_SetArgument,
JSPROP_ENUMERATE | JSPROP_PERMANENT,
(JSProperty **)&sprop);
if (!ok)
goto out;
(JSProperty **)&sprop)) {
return NULL;
}
JS_ASSERT(sprop);
sprop->id = INT_TO_JSVAL(fun->nargs++);
OBJ_DROP_PROPERTY(cx, fun->object, (JSProperty *)sprop);
} while (js_MatchToken(cx, ts, TOK_COMMA));
MUST_MATCH_TOKEN_THROW(TOK_RP, JSMSG_PAREN_AFTER_FORMAL,
ok = JS_FALSE; goto out);
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL);
}
MUST_MATCH_TOKEN_THROW(TOK_LC, JSMSG_CURLY_BEFORE_BODY,
ok = JS_FALSE; goto out);
MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;
TREE_CONTEXT_INIT(&funtc);
pn2 = FunctionBody(cx, ts, fun, &funtc);
if (!pn2) {
ok = JS_FALSE;
goto out;
}
if (!pn2)
return NULL;
MUST_MATCH_TOKEN_THROW(TOK_RC, JSMSG_CURLY_AFTER_BODY,
ok = JS_FALSE; goto out);
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
pn->pn_fun = fun;
@ -608,15 +584,10 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
#endif
pn->pn_op = JSOP_NOP;
ok = JS_TRUE;
if (named)
if (!OBJ_DEFINE_PROPERTY(cx, parent, (jsid)funAtom, OBJECT_TO_JSVAL(fun->object),
NULL, NULL, JSPROP_ENUMERATE, NULL)) {
return NULL;
}
out:
if (!ok) {
return NULL;
if (named &&
!OBJ_DEFINE_PROPERTY(cx, parent, (jsid)funAtom, fval, getter, setter,
attrs, NULL)) {
return NULL;
}
return pn;
}
@ -1085,8 +1056,8 @@ Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
/*
* We can be sure that if it's a for/in loop, there's still an 'in'
* keyword here, even if Javascript recognizes it as an operator,
* because we've excluded it from parsing by setting the
* TCF_IN_FOR_INIT flag on the JSTreeContext argument.
* because we've excluded it from being parsed in RelExpr by setting
* the TCF_IN_FOR_INIT flag in our JSTreeContext.
*/
if (pn1 && js_MatchToken(cx, ts, TOK_IN)) {
stmtInfo.type = STMT_FOR_IN_LOOP;
@ -1589,8 +1560,9 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (pobj == obj &&
OBJ_IS_NATIVE(pobj) &&
(sprop = (JSScopeProperty *)prop) != NULL) {
if (sprop->getter == js_GetArgument) {
currentGetter = sprop->getter;
if (SPROP_GETTER(sprop, pobj) == js_GetArgument) {
currentGetter = js_GetArgument;
currentSetter = js_SetArgument;
#ifdef CHECK_ARGUMENT_HIDING
js_ReportCompileErrorNumber(cx, ts, JSREPORT_WARNING,
JSMSG_VAR_HIDES_ARG,
@ -1604,11 +1576,11 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
if (fun) {
/* Not an argument, must be a redeclared local var. */
if (clasp == &js_FunctionClass) {
JS_ASSERT(sprop->getter == js_GetLocalVariable);
JS_ASSERT(SPROP_GETTER(sprop,pobj) == js_GetLocalVariable);
JS_ASSERT(JSVAL_IS_INT(sprop->id) &&
JSVAL_TO_INT(sprop->id) < fun->nvars);
} else if (clasp == &js_CallClass) {
if (sprop->getter == js_GetCallVariable) {
if (SPROP_GETTER(sprop, pobj) == js_GetCallVariable) {
/*
* Referencing a variable introduced by a var
* statement in the enclosing function. Check
@ -1622,16 +1594,16 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
* don't use the special getters and setters
* since we can't allocate a slot in the frame.
*/
currentGetter = sprop->getter;
currentSetter = sprop->setter;
currentGetter = SPROP_GETTER(sprop, pobj);
currentSetter = SPROP_SETTER(sprop, pobj);
}
}
} else {
/* Global var: (re-)set id a la js_DefineProperty. */
sprop->id = ATOM_KEY(atom);
}
sprop->getter = currentGetter;
sprop->setter = currentSetter;
SPROP_GETTER(sprop, pobj) = currentGetter;
SPROP_SETTER(sprop, pobj) = currentSetter;
sprop->attrs |= JSPROP_ENUMERATE | JSPROP_PERMANENT;
sprop->attrs &= ~JSPROP_READONLY;
}
@ -1684,8 +1656,9 @@ Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
}
}
if (ok && fun && (clasp == &js_FunctionClass ||
clasp == &js_CallClass) &&
if (ok &&
fun &&
(clasp == &js_FunctionClass || clasp == &js_CallClass) &&
!InWithStatement(tc))
{
/* Depending on the value of the getter, change the
@ -1764,11 +1737,13 @@ LookupArgOrVar(JSContext *cx, JSAtom *atom, JSTreeContext *tc,
return JS_FALSE;
*slotp = -1;
if (sprop) {
if (sprop->getter == js_GetArgument) {
JSPropertyOp getter = SPROP_GETTER(sprop, pobj);
if (getter == js_GetArgument) {
*opp = JSOP_GETARG;
*slotp = JSVAL_TO_INT(sprop->id);
} else if (sprop->getter == js_GetLocalVariable ||
sprop->getter == js_GetCallVariable)
} else if (getter == js_GetLocalVariable ||
getter == js_GetCallVariable)
{
*opp = JSOP_GETVAR;
*slotp = JSVAL_TO_INT(sprop->id);
@ -1966,7 +1941,7 @@ RelExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
(js_MatchToken(cx, ts, TOK_RELOP)
#if JS_HAS_IN_OPERATOR
/*
* Only recognize the 'in' token as an operator if we're not
* Recognize the 'in' token as an operator only if we're not
* currently in the init expr of a for loop.
*/
|| (inForInitFlag == 0 && js_MatchToken(cx, ts, TOK_IN))

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

@ -367,7 +367,7 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
{
JSScope *scope, *newscope;
scope = (JSScope *) obj->map;
scope = OBJ_SCOPE(obj);
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
if (scope->object == obj)
return scope;

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

@ -43,6 +43,7 @@
#include "jsprvtd.h"
#include "jspubtd.h"
#ifndef JS_DOUBLE_HASHING
struct JSScopeOps {
JSSymbol * (*lookup)(JSContext *cx, JSScope *scope, jsid id,
JSHashNumber hash);
@ -51,16 +52,24 @@ struct JSScopeOps {
JSBool (*remove)(JSContext *cx, JSScope *scope, jsid id);
void (*clear)(JSContext *cx, JSScope *scope);
};
#endif
struct JSScope {
JSObjectMap map; /* base class state */
JSObject *object; /* object that owns this scope */
JSScopeProperty *props; /* property list in definition order */
JSScopeProperty **proptail; /* pointer to pointer to last prop */
#ifdef JS_DOUBLE_HASHING
uint32 tableLength;
JSScopeProperty *table;
uint32 gsTableLength; /* number of entries in gsTable */
JSPropertyOp gsTable[1]; /* actually, gsTableLength ops */
#else
JSScopeOps *ops; /* virtual operations */
void *data; /* private data specific to ops */
#endif
#ifdef JS_THREADSAFE
JSThinLock lock; /* binary semaphore protecting scope */
JSThinLock lock; /* binary semaphore protecting scope */
int32 count; /* entry count for reentrancy */
#ifdef DEBUG
const char *file[4]; /* file where lock was (re-)taken */
@ -69,6 +78,27 @@ struct JSScope {
#endif
};
#define OBJ_SCOPE(obj) ((JSScope *)(obj)->map)
#define SPROP_GETTER(sprop,obj) SPROP_GETTER_SCOPE(sprop, OBJ_SCOPE(obj))
#define SPROP_SETTER(sprop,obj) SPROP_SETTER_SCOPE(sprop, OBJ_SCOPE(obj))
#ifdef JS_DOUBLE_HASHING
struct JSScopeProperty {
jsid id;
uint32 slot; /* index in obj->slots vector */
uint8 attrs; /* attributes, see jsapi.h JSPROP_ */
uint8 getterIndex; /* getter and setter method indexes */
uint8 setterIndex; /* in JSScope.gsTable[] */
uint8 reserved;
JSScopeProperty *next; /* singly-linked list linkage */
};
#define SPROP_GETTER_SCOPE(sprop,scope) ((scope)->gsTable[(sprop)->getterIndex])
#define SPROP_SETTER_SCOPE(sprop,scope) ((scope)->gsTable[(sprop)->setterIndex])
#else /* !JS_DOUBLE_HASHING */
struct JSSymbol {
JSHashEntry entry; /* base class state */
JSScope *scope; /* pointer to owning scope */
@ -92,21 +122,28 @@ struct JSScopeProperty {
JSScopeProperty **prevp;
};
#define SPROP_GETTER_SCOPE(sprop,scope) ((sprop)->getter)
#define SPROP_SETTER_SCOPE(sprop,scope) ((sprop)->setter)
#endif /* !JS_DOUBLE_HASHING */
/*
* These macros are designed to decouple getter and setter from sprop, by
* passing obj2 (in whose scope sprop lives, and in whose scope getter and
* setter might be stored apart from sprop -- say in scope->opTable[i] for
* setter might be stored apart from sprop -- say in scope->gsTable[i] for
* a compressed getter or setter index i that is stored in sprop).
*/
#define SPROP_GET(cx,sprop,obj,obj2,vp) \
(((sprop)->attrs & JSPROP_GETTER) \
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(sprop->getter), 0, 0, vp) \
: (sprop)->getter(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(SPROP_GETTER(sprop,obj2)), \
0, 0, vp) \
: SPROP_GETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
#define SPROP_SET(cx,sprop,obj,obj2,vp) \
(((sprop)->attrs & JSPROP_SETTER) \
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(sprop->setter), 1, vp, vp) \
: (sprop)->setter(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(SPROP_SETTER(sprop,obj2)), \
1, vp, vp) \
: SPROP_SETTER(sprop,obj2)(cx, OBJ_THIS_OBJECT(cx,obj), sprop->id, vp))
extern JSScope *
js_GetMutableScope(JSContext *cx, JSObject *obj);