mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 511425 - removal of JSObjectOps.(get|set)RequiredSlot. r=brendan
This commit is contained in:
parent
3c773f1b39
commit
b919139e8d
@ -2727,13 +2727,13 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
JS_PUBLIC_API(JSClass *)
|
||||
JS_GetClass(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return OBJ_GET_CLASS(cx, obj);
|
||||
return obj->getClass();
|
||||
}
|
||||
#else
|
||||
JS_PUBLIC_API(JSClass *)
|
||||
JS_GetClass(JSObject *obj)
|
||||
{
|
||||
return LOCKED_OBJ_GET_CLASS(obj);
|
||||
return obj->getClass();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4140,50 +4140,18 @@ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
return obj->checkAccess(cx, id, mode, vp, attrsp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
|
||||
uint32 index, uint32 limit)
|
||||
{
|
||||
/* Check the computed, possibly per-instance, upper bound. */
|
||||
if (clasp->reserveSlots)
|
||||
JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
|
||||
if (index >= limit) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_RESERVED_SLOT_RANGE);
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
|
||||
{
|
||||
JSClass *clasp;
|
||||
uint32 limit, slot;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
clasp = OBJ_GET_CLASS(cx, obj);
|
||||
limit = JSCLASS_RESERVED_SLOTS(clasp);
|
||||
if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
|
||||
return JS_FALSE;
|
||||
slot = JSSLOT_START(clasp) + index;
|
||||
*vp = obj->getRequiredSlot(cx, slot);
|
||||
return JS_TRUE;
|
||||
return js_GetReservedSlot(cx, obj, index, vp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
|
||||
{
|
||||
JSClass *clasp;
|
||||
uint32 limit, slot;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
clasp = OBJ_GET_CLASS(cx, obj);
|
||||
limit = JSCLASS_RESERVED_SLOTS(clasp);
|
||||
if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
|
||||
return JS_FALSE;
|
||||
slot = JSSLOT_START(clasp) + index;
|
||||
return obj->setRequiredSlot(cx, slot, v);
|
||||
return js_SetReservedSlot(cx, obj, index, v);
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
@ -764,7 +764,7 @@ array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
||||
return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
|
||||
|
||||
if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) {
|
||||
*vp = STOBJ_GET_SLOT(obj, JSSLOT_PROTO);
|
||||
*vp = OBJECT_TO_JSVAL(obj->getProto());
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -876,7 +876,7 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj)
|
||||
* exists. If we hit the end of the prototype chain, it's safe to set the
|
||||
* element on the original object.
|
||||
*/
|
||||
while ((obj = JSVAL_TO_OBJECT(obj->fslots[JSSLOT_PROTO])) != NULL) {
|
||||
while ((obj = obj->getProto()) != NULL) {
|
||||
/*
|
||||
* If the prototype is a non-native object (possibly a dense array), or
|
||||
* a native object (possibly a slow array) that has indexed properties,
|
||||
@ -1217,6 +1217,7 @@ array_trace(JSTracer *trc, JSObject *obj)
|
||||
jsval v;
|
||||
|
||||
JS_ASSERT(js_IsDenseArray(obj));
|
||||
obj->traceProtoAndParent(trc);
|
||||
|
||||
capacity = js_DenseArrayCapacity(obj);
|
||||
for (i = 0; i < capacity; i++) {
|
||||
@ -1226,14 +1227,6 @@ array_trace(JSTracer *trc, JSObject *obj)
|
||||
JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = JSSLOT_PROTO; i <= JSSLOT_PARENT; ++i) {
|
||||
v = STOBJ_GET_SLOT(obj, i);
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
|
||||
JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern JSObjectOps js_ArrayObjectOps;
|
||||
@ -1250,7 +1243,6 @@ JSObjectOps js_ArrayObjectOps = {
|
||||
NULL, array_dropProperty,
|
||||
NULL, NULL,
|
||||
js_HasInstance, array_trace,
|
||||
NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -3425,8 +3417,8 @@ js_NewEmptyArray(JSContext* cx, JSObject* proto)
|
||||
/* Initialize all fields of JSObject. */
|
||||
obj->map = const_cast<JSObjectMap *>(&SharedArrayMap);
|
||||
obj->classword = jsuword(&js_ArrayClass);
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
obj->setProto(proto);
|
||||
obj->setParent(proto->getParent());
|
||||
|
||||
obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
|
||||
obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
|
||||
|
@ -394,9 +394,9 @@ js_NewNullClosure(JSContext* cx, JSObject* funobj, JSObject* proto, JSObject* pa
|
||||
|
||||
closure->map = &scope->map;
|
||||
closure->classword = jsuword(&js_FunctionClass);
|
||||
closure->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
closure->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent);
|
||||
closure->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
|
||||
closure->setProto(proto);
|
||||
closure->setParent(parent);
|
||||
closure->setPrivate(fun);
|
||||
for (unsigned i = JSSLOT_PRIVATE + 1; i != JS_INITIAL_NSLOTS; ++i)
|
||||
closure->fslots[i] = JSVAL_VOID;
|
||||
closure->dslots = NULL;
|
||||
|
@ -1714,7 +1714,7 @@ JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags)
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_IsSystemObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
return STOBJ_IS_SYSTEM(obj);
|
||||
return obj->isSystem();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
@ -1725,7 +1725,7 @@ JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
|
||||
obj = js_NewObject(cx, clasp, proto, parent);
|
||||
if (obj && system)
|
||||
STOBJ_SET_SYSTEM(obj);
|
||||
obj->setSystem();
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ jsdtrace_object_finalize(JSObject *obj)
|
||||
{
|
||||
JSClass *clasp;
|
||||
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
clasp = obj->getClass();
|
||||
|
||||
/* the first arg is NULL - reserved for future use (filename?) */
|
||||
JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
|
||||
|
@ -1525,7 +1525,7 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
||||
continue;
|
||||
|
||||
obj = stmt->blockObj;
|
||||
JS_ASSERT(LOCKED_OBJ_GET_CLASS(obj) == &js_BlockClass);
|
||||
JS_ASSERT(obj->getClass() == &js_BlockClass);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
sprop = scope->lookup(ATOM_TO_JSID(atom));
|
||||
if (sprop) {
|
||||
|
@ -2406,37 +2406,22 @@ js_UnlockGCThingRT(JSRuntime *rt, void *thing)
|
||||
JS_PUBLIC_API(void)
|
||||
JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
|
||||
{
|
||||
JSObject *obj;
|
||||
size_t nslots, i;
|
||||
jsval v;
|
||||
JSString *str;
|
||||
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT:
|
||||
case JSTRACE_OBJECT: {
|
||||
/* If obj has no map, it must be a newborn. */
|
||||
obj = (JSObject *) thing;
|
||||
JSObject *obj = (JSObject *) thing;
|
||||
if (!obj->map)
|
||||
break;
|
||||
if (obj->map->ops->trace) {
|
||||
obj->map->ops->trace(trc, obj);
|
||||
} else {
|
||||
nslots = STOBJ_NSLOTS(obj);
|
||||
for (i = 0; i != nslots; ++i) {
|
||||
v = STOBJ_GET_SLOT(obj, i);
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
JS_SET_TRACING_INDEX(trc, "slot", i);
|
||||
JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v),
|
||||
JSVAL_TRACE_KIND(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
obj->map->ops->trace(trc, obj);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSTRACE_STRING:
|
||||
str = (JSString *)thing;
|
||||
case JSTRACE_STRING: {
|
||||
JSString *str = (JSString *) thing;
|
||||
if (str->isDependent())
|
||||
JS_CALL_STRING_TRACER(trc, str->dependentBase(), "base");
|
||||
break;
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case JSTRACE_XML:
|
||||
@ -3168,10 +3153,10 @@ ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
|
||||
|
||||
pobj = ssr->pobj;
|
||||
if (slot == JSSLOT_PROTO) {
|
||||
STOBJ_SET_PROTO(obj, pobj);
|
||||
obj->setProto(pobj);
|
||||
} else {
|
||||
JS_ASSERT(slot == JSSLOT_PARENT);
|
||||
STOBJ_SET_PARENT(obj, pobj);
|
||||
obj->setParent(pobj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj,
|
||||
#ifdef DEBUG_notme
|
||||
fprintf(stderr,
|
||||
"branding %p (%s) for funobj %p (%s), shape %lu\n",
|
||||
pobj, LOCKED_OBJ_GET_CLASS(pobj)->name,
|
||||
pobj, pobj->getClass()->name,
|
||||
JSVAL_TO_OBJECT(v),
|
||||
JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))),
|
||||
OBJ_SHAPE(obj));
|
||||
@ -332,7 +332,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj,
|
||||
* platforms where another CPU can fail to see this write, it's OK
|
||||
* because the property cache and JIT cache are thread-local.
|
||||
*/
|
||||
OBJ_SET_DELEGATE(cx, obj);
|
||||
obj->setDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,18 +723,7 @@ js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
jsword me;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We handle non-native objects via JSObjectOps.getRequiredSlot, treating
|
||||
* all slots starting from 0 as required slots. A property definition or
|
||||
* some prior arrangement must have allocated slot.
|
||||
*
|
||||
* Note once again (see jspubtd.h, before JSGetRequiredSlotOp's typedef)
|
||||
* the crucial distinction between a |required slot number| that's passed
|
||||
* to the get/setRequiredSlot JSObjectOps, and a |reserved slot index|
|
||||
* passed to the JS_Get/SetReservedSlot APIs.
|
||||
*/
|
||||
if (!OBJ_IS_NATIVE(obj))
|
||||
return obj->getRequiredSlot(cx, slot);
|
||||
OBJ_CHECK_SLOT(obj, slot);
|
||||
|
||||
/*
|
||||
* Native object locking is inlined here to optimize the single-threaded
|
||||
@ -815,6 +804,8 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
jsword me;
|
||||
#endif
|
||||
|
||||
OBJ_CHECK_SLOT(obj, slot);
|
||||
|
||||
/* Any string stored in a thread-safe object must be immutable. */
|
||||
if (JSVAL_IS_STRING(v) &&
|
||||
!js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
|
||||
@ -822,15 +813,6 @@ js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
v = JSVAL_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle non-native objects via JSObjectOps.setRequiredSlot, as above
|
||||
* for the Get case.
|
||||
*/
|
||||
if (!OBJ_IS_NATIVE(obj)) {
|
||||
obj->setRequiredSlot(cx, slot, v);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Native object locking is inlined here to optimize the single-threaded
|
||||
* and contention-free multi-threaded cases.
|
||||
|
@ -236,19 +236,6 @@ extern void js_SetScopeInfo(JSScope *scope, const char *file, int line);
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define JS_LOCK_OBJ_VOID(cx, obj, e) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_LOCK_OBJ(cx, obj); \
|
||||
e; \
|
||||
JS_UNLOCK_OBJ(cx, obj); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_LOCK_VOID(cx, e) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSRuntime *_rt = (cx)->runtime; \
|
||||
JS_LOCK_RUNTIME_VOID(_rt, e); \
|
||||
JS_END_MACRO
|
||||
|
||||
#else /* !JS_THREADSAFE */
|
||||
|
||||
#define JS_ATOMIC_INCREMENT(p) (++*(p))
|
||||
@ -284,7 +271,6 @@ extern void js_SetScopeInfo(JSScope *scope, const char *file, int line);
|
||||
#define JS_IS_RUNTIME_LOCKED(rt) 1
|
||||
#define JS_IS_OBJ_LOCKED(cx,obj) 1
|
||||
#define JS_IS_TITLE_LOCKED(cx,title) 1
|
||||
#define JS_LOCK_VOID(cx, e) JS_LOCK_RUNTIME_VOID((cx)->runtime, e)
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
|
165
js/src/jsobj.cpp
165
js/src/jsobj.cpp
@ -113,8 +113,7 @@ JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
|
||||
NULL, NATIVE_DROP_PROPERTY,
|
||||
js_Call, js_Construct,
|
||||
js_HasInstance, js_TraceObject,
|
||||
js_Clear, js_GetRequiredSlot,
|
||||
js_SetRequiredSlot
|
||||
js_Clear
|
||||
};
|
||||
|
||||
JSClass js_ObjectClass = {
|
||||
@ -311,9 +310,9 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj,
|
||||
|
||||
if (!pobj || !checkForCycles) {
|
||||
if (slot == JSSLOT_PROTO)
|
||||
STOBJ_SET_PROTO(obj, pobj);
|
||||
obj->setProto(pobj);
|
||||
else
|
||||
STOBJ_SET_PARENT(obj, pobj);
|
||||
obj->setParent(pobj);
|
||||
} else {
|
||||
/*
|
||||
* Use the GC machinery to serialize access to all objects on the
|
||||
@ -2090,18 +2089,16 @@ js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
|
||||
*/
|
||||
JS_ASSERT(((jsuword) clasp & 3) == 0);
|
||||
obj->classword = jsuword(clasp);
|
||||
JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
|
||||
JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
|
||||
JS_ASSERT(!obj->isDelegate());
|
||||
JS_ASSERT(!obj->isSystem());
|
||||
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->setProto(proto);
|
||||
|
||||
/*
|
||||
* Default parent to the parent of the prototype, which was set from
|
||||
* the parent of the prototype's constructor.
|
||||
*/
|
||||
obj->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL((!parent && proto)
|
||||
? OBJ_GET_PARENT(cx, proto)
|
||||
: parent);
|
||||
obj->setParent((!parent && proto) ? proto->getParent() : parent);
|
||||
|
||||
/* Initialize the remaining fixed slots. */
|
||||
for (uint32 i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
|
||||
@ -2201,8 +2198,8 @@ NewNativeObject(JSContext* cx, JSClass* clasp, JSObject* proto, JSObject *parent
|
||||
return NULL;
|
||||
|
||||
obj->classword = jsuword(clasp);
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent);
|
||||
obj->setProto(proto);
|
||||
obj->setParent(parent);
|
||||
for (unsigned i = JSSLOT_PRIVATE; i < JS_INITIAL_NSLOTS; ++i)
|
||||
obj->fslots[i] = JSVAL_VOID;
|
||||
|
||||
@ -2489,8 +2486,7 @@ JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
|
||||
with_ThisObject, NATIVE_DROP_PROPERTY,
|
||||
NULL, NULL,
|
||||
NULL, js_TraceObject,
|
||||
js_Clear, NULL,
|
||||
NULL
|
||||
js_Clear
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
@ -2548,8 +2544,8 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, JSStackFrame *fp)
|
||||
clone->map = &scope->map;
|
||||
|
||||
clone->classword = jsuword(&js_BlockClass);
|
||||
clone->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
clone->fslots[JSSLOT_PARENT] = JSVAL_NULL; // caller's responsibility
|
||||
clone->setProto(proto);
|
||||
clone->setParent(NULL); // caller's responsibility
|
||||
clone->setPrivate(fp);
|
||||
clone->fslots[JSSLOT_BLOCK_DEPTH] = proto->fslots[JSSLOT_BLOCK_DEPTH];
|
||||
JS_ASSERT(scope->freeslot == JSSLOT_BLOCK_DEPTH + 1);
|
||||
@ -3135,10 +3131,10 @@ js_NewNativeObject(JSContext *cx, JSClass *clasp, JSObject *proto, uint32 slot)
|
||||
}
|
||||
obj->map = &scope->map;
|
||||
obj->classword = jsuword(clasp);
|
||||
obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
|
||||
obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
|
||||
obj->setProto(proto);
|
||||
obj->setParent(proto->getParent());
|
||||
|
||||
JS_ASSERT(slot > JSSLOT_PARENT);
|
||||
JS_ASSERT(slot >= JSSLOT_PRIVATE);
|
||||
while (slot < JS_INITIAL_NSLOTS)
|
||||
obj->fslots[slot++] = JSVAL_VOID;
|
||||
|
||||
@ -3395,7 +3391,7 @@ js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
JSClass *clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
JSClass *clasp = obj->getClass();
|
||||
if (scope->freeslot == JSSLOT_FREE(clasp) && clasp->reserveSlots) {
|
||||
/* Adjust scope->freeslot to include computed reserved slots, if any. */
|
||||
scope->freeslot += clasp->reserveSlots(cx, obj);
|
||||
@ -3517,7 +3513,7 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
obj = LOCKED_OBJ_GET_PROTO(obj);
|
||||
obj = obj->getProto();
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
}
|
||||
return JS_FALSE;
|
||||
@ -3526,8 +3522,8 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
void
|
||||
js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
|
||||
{
|
||||
JS_ASSERT(OBJ_IS_DELEGATE(cx, obj));
|
||||
PurgeProtoChain(cx, OBJ_GET_PROTO(cx, obj), id);
|
||||
JS_ASSERT(obj->isDelegate());
|
||||
PurgeProtoChain(cx, obj->getProto(), id);
|
||||
|
||||
/*
|
||||
* We must purge the scope chain only for Call objects as they are the only
|
||||
@ -3695,14 +3691,14 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||
* prototype object. See the comment in jscntxt.h before protoHazardShape's
|
||||
* member declaration.
|
||||
*/
|
||||
if (OBJ_IS_DELEGATE(cx, obj) && (attrs & (JSPROP_READONLY | JSPROP_SETTER)))
|
||||
if (obj->isDelegate() && (attrs & (JSPROP_READONLY | JSPROP_SETTER)))
|
||||
cx->runtime->protoHazardShape = js_GenerateShape(cx, false);
|
||||
|
||||
/* Lock if object locking is required by this implementation. */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
|
||||
/* Use the object's class getter and setter by default. */
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
clasp = obj->getClass();
|
||||
if (!getter)
|
||||
getter = clasp->getProperty;
|
||||
if (!setter)
|
||||
@ -3790,7 +3786,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
|
||||
/* Try obj's class resolve hook if id was not found in obj's scope. */
|
||||
if (!sprop) {
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
clasp = obj->getClass();
|
||||
resolve = clasp->resolve;
|
||||
if (resolve != JS_ResolveStub) {
|
||||
/* Avoid recursion on (obj, id) already being resolved on cx. */
|
||||
@ -3910,7 +3906,7 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
return protoIndex;
|
||||
}
|
||||
|
||||
proto = LOCKED_OBJ_GET_PROTO(obj);
|
||||
proto = obj->getProto();
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
if (!proto)
|
||||
break;
|
||||
@ -4686,8 +4682,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
||||
}
|
||||
|
||||
/* XXXbe called with obj locked */
|
||||
if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop),
|
||||
rval)) {
|
||||
if (!obj->getClass()->delProperty(cx, obj, SPROP_USERID(sprop), rval)) {
|
||||
obj->dropProperty(cx, prop);
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -4724,7 +4719,7 @@ js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
|
||||
JSObject *pobj = obj;
|
||||
|
||||
if (!sprop) {
|
||||
pobj = LOCKED_OBJ_GET_PROTO(obj);
|
||||
pobj = obj->getProto();
|
||||
|
||||
if (pobj && OBJ_GET_CLASS(cx, pobj) == &js_StringClass) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
@ -5645,6 +5640,7 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
||||
JS_ASSERT(trc->debugPrinter == js_PrintObjectSlotName);
|
||||
obj = (JSObject *)trc->debugPrintArg;
|
||||
slot = (uint32)trc->debugPrintIndex;
|
||||
JS_ASSERT(slot >= JSSLOT_PRIVATE);
|
||||
|
||||
if (OBJ_IS_NATIVE(obj)) {
|
||||
scope = OBJ_SCOPE(obj);
|
||||
@ -5656,30 +5652,20 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
||||
}
|
||||
|
||||
if (!sprop) {
|
||||
switch (slot) {
|
||||
case JSSLOT_PROTO:
|
||||
JS_snprintf(buf, bufsize, "__proto__");
|
||||
break;
|
||||
case JSSLOT_PARENT:
|
||||
JS_snprintf(buf, bufsize, "__parent__");
|
||||
break;
|
||||
default:
|
||||
slotname = NULL;
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
if (clasp->flags & JSCLASS_IS_GLOBAL) {
|
||||
key = slot - JSSLOT_START(clasp);
|
||||
#define JS_PROTO(name,code,init) \
|
||||
slotname = NULL;
|
||||
clasp = obj->getClass();
|
||||
if (clasp->flags & JSCLASS_IS_GLOBAL) {
|
||||
key = slot - JSSLOT_START(clasp);
|
||||
#define JS_PROTO(name,code,init) \
|
||||
if ((code) == key) { slotname = js_##name##_str; goto found; }
|
||||
#include "jsproto.tbl"
|
||||
#undef JS_PROTO
|
||||
}
|
||||
found:
|
||||
if (slotname)
|
||||
JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
|
||||
else
|
||||
JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
|
||||
break;
|
||||
}
|
||||
found:
|
||||
if (slotname)
|
||||
JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
|
||||
else
|
||||
JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
|
||||
} else {
|
||||
nval = ID_TO_VALUE(sprop->id);
|
||||
if (JSVAL_IS_INT(nval)) {
|
||||
@ -5727,7 +5713,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
js_TraceWatchPoints(trc, obj);
|
||||
|
||||
/* No one runs while the GC is running, so we can use LOCKED_... here. */
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
clasp = obj->getClass();
|
||||
if (clasp->mark) {
|
||||
if (clasp->flags & JSCLASS_MARK_IS_TRACE)
|
||||
((JSTraceOp) clasp->mark)(trc, obj);
|
||||
@ -5735,6 +5721,8 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
(void) clasp->mark(cx, obj, trc);
|
||||
}
|
||||
|
||||
obj->traceProtoAndParent(trc);
|
||||
|
||||
/*
|
||||
* An unmutated object that shares a prototype object's scope. We can't
|
||||
* tell how many slots are in use in obj by looking at its scope, so we
|
||||
@ -5748,7 +5736,7 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
||||
if (scope->owned() && scope->freeslot < nslots)
|
||||
nslots = scope->freeslot;
|
||||
|
||||
for (i = 0; i != nslots; ++i) {
|
||||
for (i = JSSLOT_PRIVATE; i != nslots; ++i) {
|
||||
v = STOBJ_GET_SLOT(obj, i);
|
||||
if (JSVAL_IS_TRACEABLE(v)) {
|
||||
JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
|
||||
@ -5776,7 +5764,7 @@ js_Clear(JSContext *cx, JSObject *obj)
|
||||
|
||||
/* Clear slot values and reset freeslot so we're consistent. */
|
||||
i = STOBJ_NSLOTS(obj);
|
||||
n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
|
||||
n = JSSLOT_FREE(obj->getClass());
|
||||
while (--i >= n)
|
||||
STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
|
||||
scope->freeslot = n;
|
||||
@ -5784,40 +5772,73 @@ js_Clear(JSContext *cx, JSObject *obj)
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
}
|
||||
|
||||
jsval
|
||||
js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot)
|
||||
/* On failure the function unlocks the object. */
|
||||
static bool
|
||||
ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
|
||||
uint32 index, uint32 limit)
|
||||
{
|
||||
jsval v;
|
||||
JS_IS_OBJ_LOCKED(cx, obj);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
v = (slot < STOBJ_NSLOTS(obj)) ? STOBJ_GET_SLOT(obj, slot) : JSVAL_VOID;
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return v;
|
||||
/* Check the computed, possibly per-instance, upper bound. */
|
||||
if (clasp->reserveSlots)
|
||||
limit += clasp->reserveSlots(cx, obj);
|
||||
if (index >= limit) {
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_RESERVED_SLOT_RANGE);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
bool
|
||||
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
|
||||
{
|
||||
JSScope *scope;
|
||||
uint32 nslots;
|
||||
JSClass *clasp;
|
||||
if (!OBJ_IS_NATIVE(obj)) {
|
||||
*vp = JSVAL_VOID;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSClass *clasp = obj->getClass();
|
||||
uint32 limit = JSCLASS_RESERVED_SLOTS(clasp);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
|
||||
return false;
|
||||
|
||||
uint32 slot = JSSLOT_START(clasp) + index;
|
||||
*vp = (slot < STOBJ_NSLOTS(obj)) ? STOBJ_GET_SLOT(obj, slot) : JSVAL_VOID;
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
|
||||
{
|
||||
if (!OBJ_IS_NATIVE(obj))
|
||||
return true;
|
||||
|
||||
JSClass *clasp = OBJ_GET_CLASS(cx, obj);
|
||||
uint32 limit = JSCLASS_RESERVED_SLOTS(clasp);
|
||||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
|
||||
return false;
|
||||
|
||||
uint32 slot = JSSLOT_START(clasp) + index;
|
||||
if (slot >= JS_INITIAL_NSLOTS && !obj->dslots) {
|
||||
/*
|
||||
* At this point, obj may or may not own scope, and we may or may not
|
||||
* need to allocate dslots. If scope is shared, scope->freeslot may not
|
||||
* be accurate for obj (see comment below).
|
||||
*/
|
||||
clasp = LOCKED_OBJ_GET_CLASS(obj);
|
||||
nslots = JSSLOT_FREE(clasp);
|
||||
uint32 nslots = JSSLOT_FREE(clasp);
|
||||
if (clasp->reserveSlots)
|
||||
nslots += clasp->reserveSlots(cx, obj);
|
||||
JS_ASSERT(slot < nslots);
|
||||
if (!AllocSlots(cx, obj, nslots)) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return JS_FALSE;
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5829,13 +5850,14 @@ js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
|
||||
* their own scopes before mutating, and elsewhere (e.g. js_TraceObject) we
|
||||
* use STOBJ_NSLOTS(obj) rather than rely on freeslot.
|
||||
*/
|
||||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
if (scope->owned() && slot >= scope->freeslot)
|
||||
scope->freeslot = slot + 1;
|
||||
|
||||
STOBJ_SET_SLOT(obj, slot, v);
|
||||
GC_POKE(cx, JS_NULL);
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return JS_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
@ -5876,7 +5898,6 @@ js_ReportGetterOnlyAssignment(JSContext *cx)
|
||||
JSMSG_GETTER_ONLY, NULL);
|
||||
}
|
||||
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
|
201
js/src/jsobj.h
201
js/src/jsobj.h
@ -83,8 +83,6 @@ struct JSObjectOps {
|
||||
JSHasInstanceOp hasInstance;
|
||||
JSTraceOp trace;
|
||||
JSFinalizeOp clear;
|
||||
JSGetRequiredSlotOp getRequiredSlot;
|
||||
JSSetRequiredSlotOp setRequiredSlot;
|
||||
};
|
||||
|
||||
struct JSObjectMap {
|
||||
@ -106,7 +104,8 @@ const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
|
||||
*
|
||||
* 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.
|
||||
* 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
|
||||
@ -124,7 +123,7 @@ const uintptr_t JSSLOT_CLASS_MASK_BITS = 3;
|
||||
* any such association.
|
||||
*
|
||||
* Both these classword tag bits are initially zero; they may be set or queried
|
||||
* using the STOBJ_(IS|SET)_(DELEGATE|SYSTEM) macros.
|
||||
* 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]
|
||||
@ -140,6 +139,63 @@ struct JSObject {
|
||||
return (JSClass *) (classword & ~JSSLOT_CLASS_MASK_BITS);
|
||||
}
|
||||
|
||||
bool isDelegate() const {
|
||||
return (classword & jsuword(1)) != jsuword(0);
|
||||
}
|
||||
|
||||
void setDelegate() {
|
||||
classword |= jsuword(1);
|
||||
}
|
||||
|
||||
static void setDelegateNullSafe(JSObject *obj) {
|
||||
if (obj)
|
||||
obj->setDelegate();
|
||||
}
|
||||
|
||||
bool isSystem() const {
|
||||
return (classword & jsuword(2)) != jsuword(0);
|
||||
}
|
||||
|
||||
void setSystem() {
|
||||
classword |= jsuword(2);
|
||||
}
|
||||
|
||||
JSObject *getProto() const {
|
||||
return JSVAL_TO_OBJECT(fslots[JSSLOT_PROTO]);
|
||||
}
|
||||
|
||||
void clearProto() {
|
||||
fslots[JSSLOT_PROTO] = JSVAL_NULL;
|
||||
}
|
||||
|
||||
void setProto(JSObject *newProto) {
|
||||
setDelegateNullSafe(newProto);
|
||||
fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(newProto);
|
||||
}
|
||||
|
||||
JSObject *getParent() const {
|
||||
return JSVAL_TO_OBJECT(fslots[JSSLOT_PARENT]);
|
||||
}
|
||||
|
||||
void clearParent() {
|
||||
fslots[JSSLOT_PARENT] = JSVAL_NULL;
|
||||
}
|
||||
|
||||
void setParent(JSObject *newParent) {
|
||||
setDelegateNullSafe(newParent);
|
||||
fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(newParent);
|
||||
}
|
||||
|
||||
void traceProtoAndParent(JSTracer *trc) const {
|
||||
JSObject *proto = getProto();
|
||||
if (proto)
|
||||
JS_CALL_OBJECT_TRACER(trc, proto, "__proto__");
|
||||
|
||||
JSObject *parent = getParent();
|
||||
if (parent)
|
||||
JS_CALL_OBJECT_TRACER(trc, parent, "__parent__");
|
||||
}
|
||||
|
||||
/*
|
||||
* Get private value previously assigned with setPrivate.
|
||||
*/
|
||||
@ -169,71 +225,81 @@ struct JSObject {
|
||||
fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool lookupProperty(JSContext *cx, jsid id,
|
||||
JSObject **objp, JSProperty **propp) {
|
||||
JSBool lookupProperty(JSContext *cx, jsid id,
|
||||
JSObject **objp, JSProperty **propp) {
|
||||
return map->ops->lookupProperty(cx, this, id, objp, propp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool defineProperty(JSContext *cx, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter, uintN attrs) {
|
||||
JSBool defineProperty(JSContext *cx, jsid id, jsval value,
|
||||
JSPropertyOp getter, JSPropertyOp setter,
|
||||
uintN attrs) {
|
||||
return map->ops->defineProperty(cx, this, id, value, getter, setter, attrs);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool getProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
JSBool getProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
return map->ops->getProperty(cx, this, id, vp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool setProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
JSBool setProperty(JSContext *cx, jsid id, jsval *vp) {
|
||||
return map->ops->setProperty(cx, this, id, vp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool getAttributes(JSContext *cx, jsid id, JSProperty *prop,
|
||||
uintN *attrsp) {
|
||||
JSBool getAttributes(JSContext *cx, jsid id, JSProperty *prop,
|
||||
uintN *attrsp) {
|
||||
return map->ops->getAttributes(cx, this, id, prop, attrsp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool setAttributes(JSContext *cx, jsid id, JSProperty *prop,
|
||||
uintN *attrsp) {
|
||||
JSBool setAttributes(JSContext *cx, jsid id, JSProperty *prop,
|
||||
uintN *attrsp) {
|
||||
return map->ops->setAttributes(cx, this, id, prop, attrsp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool deleteProperty(JSContext *cx, jsid id, jsval *rval) {
|
||||
JSBool deleteProperty(JSContext *cx, jsid id, jsval *rval) {
|
||||
return map->ops->deleteProperty(cx, this, id, rval);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool defaultValue(JSContext *cx, JSType hint, jsval *vp) {
|
||||
JSBool defaultValue(JSContext *cx, JSType hint, jsval *vp) {
|
||||
return map->ops->defaultValue(cx, this, hint, vp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool enumerate(JSContext *cx, JSIterateOp op, jsval *statep,
|
||||
jsid *idp) {
|
||||
JSBool enumerate(JSContext *cx, JSIterateOp op, jsval *statep,
|
||||
jsid *idp) {
|
||||
return map->ops->enumerate(cx, this, op, statep, idp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, jsval *vp,
|
||||
uintN *attrsp) {
|
||||
JSBool checkAccess(JSContext *cx, jsid id, JSAccessMode mode, jsval *vp,
|
||||
uintN *attrsp) {
|
||||
return map->ops->checkAccess(cx, this, id, mode, vp, attrsp);
|
||||
}
|
||||
|
||||
/* These four are time-optimized to avoid stub calls. */
|
||||
JS_ALWAYS_INLINE JSObject *thisObject(JSContext *cx) {
|
||||
JSObject *thisObject(JSContext *cx) {
|
||||
return map->ops->thisObject ? map->ops->thisObject(cx, this) : this;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE void dropProperty(JSContext *cx, JSProperty *prop) {
|
||||
void dropProperty(JSContext *cx, JSProperty *prop) {
|
||||
if (map->ops->dropProperty)
|
||||
map->ops->dropProperty(cx, this, prop);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE jsval getRequiredSlot(JSContext *cx, uint32 slot) {
|
||||
return map->ops->getRequiredSlot ? map->ops->getRequiredSlot(cx, this, slot) : JSVAL_VOID;
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE JSBool setRequiredSlot(JSContext *cx, uint32 slot, jsval v) {
|
||||
return map->ops->setRequiredSlot ? map->ops->setRequiredSlot(cx, this, slot, v) : JS_TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
/* Compatibility macros. */
|
||||
#define STOBJ_GET_PROTO(obj) ((obj)->getProto())
|
||||
#define STOBJ_SET_PROTO(obj,proto) ((obj)->setProto(proto))
|
||||
#define STOBJ_CLEAR_PROTO(obj) ((obj)->clearProto())
|
||||
|
||||
#define STOBJ_GET_PARENT(obj) ((obj)->getParent())
|
||||
#define STOBJ_SET_PARENT(obj,parent) ((obj)->setParent(parent))
|
||||
#define STOBJ_CLEAR_PARENT(obj) ((obj)->clearParent())
|
||||
|
||||
#define OBJ_GET_PROTO(cx,obj) STOBJ_GET_PROTO(obj)
|
||||
#define OBJ_SET_PROTO(cx,obj,proto) STOBJ_SET_PROTO(obj, proto)
|
||||
#define OBJ_CLEAR_PROTO(cx,obj) STOBJ_CLEAR_PROTO(obj)
|
||||
|
||||
#define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj)
|
||||
#define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent)
|
||||
#define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj)
|
||||
|
||||
#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
|
||||
? JSSLOT_PRIVATE + 1 \
|
||||
: JSSLOT_PARENT + 1)
|
||||
@ -268,42 +334,14 @@ struct JSObject {
|
||||
: (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
|
||||
(obj)->dslots[(slot) - JS_INITIAL_NSLOTS] = (value)))
|
||||
|
||||
#define STOBJ_GET_PROTO(obj) \
|
||||
JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PROTO])
|
||||
#define STOBJ_SET_PROTO(obj,proto) \
|
||||
(void)(STOBJ_NULLSAFE_SET_DELEGATE(proto), \
|
||||
(obj)->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto))
|
||||
#define STOBJ_CLEAR_PROTO(obj) \
|
||||
((obj)->fslots[JSSLOT_PROTO] = JSVAL_NULL)
|
||||
|
||||
#define STOBJ_GET_PARENT(obj) \
|
||||
JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PARENT])
|
||||
#define STOBJ_SET_PARENT(obj,parent) \
|
||||
(void)(STOBJ_NULLSAFE_SET_DELEGATE(parent), \
|
||||
(obj)->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent))
|
||||
#define STOBJ_CLEAR_PARENT(obj) \
|
||||
((obj)->fslots[JSSLOT_PARENT] = JSVAL_NULL)
|
||||
|
||||
/*
|
||||
* We use JSObject.classword to store both JSClass* and the delegate and system
|
||||
* flags in the two least significant bits. We do *not* synchronize updates of
|
||||
* obj->classword -- API clients must take care.
|
||||
*/
|
||||
JS_ALWAYS_INLINE JSClass*
|
||||
inline JSClass*
|
||||
STOBJ_GET_CLASS(const JSObject* obj)
|
||||
{
|
||||
return obj->getClass();
|
||||
}
|
||||
|
||||
#define STOBJ_IS_DELEGATE(obj) (((obj)->classword & 1) != 0)
|
||||
#define STOBJ_SET_DELEGATE(obj) ((obj)->classword |= 1)
|
||||
#define STOBJ_NULLSAFE_SET_DELEGATE(obj) \
|
||||
(!(obj) || STOBJ_SET_DELEGATE((JSObject*)obj))
|
||||
#define STOBJ_IS_SYSTEM(obj) (((obj)->classword & 2) != 0)
|
||||
#define STOBJ_SET_SYSTEM(obj) ((obj)->classword |= 2)
|
||||
|
||||
#define OBJ_CHECK_SLOT(obj,slot) \
|
||||
JS_ASSERT_IF(OBJ_IS_NATIVE(obj), slot < OBJ_SCOPE(obj)->freeslot)
|
||||
(JS_ASSERT(OBJ_IS_NATIVE(obj)), JS_ASSERT(slot < OBJ_SCOPE(obj)->freeslot))
|
||||
|
||||
#define LOCKED_OBJ_GET_SLOT(obj,slot) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), STOBJ_GET_SLOT(obj, slot))
|
||||
@ -345,32 +383,19 @@ STOBJ_GET_CLASS(const JSObject* obj)
|
||||
GC_POKE(cx, oldval); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define LOCKED_OBJ_GET_PROTO(obj) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_GET_PROTO(obj))
|
||||
#define LOCKED_OBJ_SET_PROTO(obj,proto) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_SET_PROTO(obj, proto))
|
||||
|
||||
#define LOCKED_OBJ_GET_PARENT(obj) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_GET_PARENT(obj))
|
||||
#define LOCKED_OBJ_SET_PARENT(obj,parent) \
|
||||
(OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_SET_PARENT(obj, parent))
|
||||
|
||||
#define LOCKED_OBJ_GET_CLASS(obj) \
|
||||
STOBJ_GET_CLASS(obj)
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
/* Thread-safe functions and wrapper macros for accessing slots in obj. */
|
||||
#define OBJ_GET_SLOT(cx,obj,slot) \
|
||||
(OBJ_CHECK_SLOT(obj, slot), \
|
||||
(OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
|
||||
(OBJ_SCOPE(obj)->title.ownercx == cx) \
|
||||
? LOCKED_OBJ_GET_SLOT(obj, slot) \
|
||||
: js_GetSlotThreadSafe(cx, obj, slot))
|
||||
|
||||
#define OBJ_SET_SLOT(cx,obj,slot,value) \
|
||||
JS_BEGIN_MACRO \
|
||||
OBJ_CHECK_SLOT(obj, slot); \
|
||||
if (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
|
||||
if (OBJ_SCOPE(obj)->title.ownercx == cx) \
|
||||
LOCKED_OBJ_WRITE_SLOT(cx, obj, slot, value); \
|
||||
else \
|
||||
js_SetSlotThreadSafe(cx, obj, slot, value); \
|
||||
@ -401,18 +426,6 @@ STOBJ_GET_CLASS(const JSObject* obj)
|
||||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
/* Thread-safe delegate, proto, parent, and class access macros. */
|
||||
#define OBJ_IS_DELEGATE(cx,obj) STOBJ_IS_DELEGATE(obj)
|
||||
#define OBJ_SET_DELEGATE(cx,obj) STOBJ_SET_DELEGATE(obj)
|
||||
|
||||
#define OBJ_GET_PROTO(cx,obj) STOBJ_GET_PROTO(obj)
|
||||
#define OBJ_SET_PROTO(cx,obj,proto) STOBJ_SET_PROTO(obj, proto)
|
||||
#define OBJ_CLEAR_PROTO(cx,obj) STOBJ_CLEAR_PROTO(obj)
|
||||
|
||||
#define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj)
|
||||
#define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent)
|
||||
#define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj)
|
||||
|
||||
/*
|
||||
* Class is invariant and comes from the fixed clasp member. Thus no locking
|
||||
* is necessary to read it. Same for the private slot.
|
||||
@ -429,7 +442,7 @@ STOBJ_GET_CLASS(const JSObject* obj)
|
||||
#define OBJ_IS_NATIVE(obj) OPS_IS_NATIVE((obj)->map->ops)
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_ALWAYS_INLINE void
|
||||
inline void
|
||||
OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
|
||||
{
|
||||
JSClass *clasp = OBJ_GET_CLASS(cx, obj);
|
||||
@ -444,7 +457,7 @@ OBJ_TO_INNER_OBJECT(JSContext *cx, JSObject *&obj)
|
||||
* 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.
|
||||
*/
|
||||
JS_ALWAYS_INLINE void
|
||||
inline void
|
||||
OBJ_TO_OUTER_OBJECT(JSContext *cx, JSObject *&obj)
|
||||
{
|
||||
JSClass *clasp = OBJ_GET_CLASS(cx, obj);
|
||||
@ -676,7 +689,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id);
|
||||
static JS_INLINE void
|
||||
js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
{
|
||||
if (OBJ_IS_DELEGATE(cx, obj))
|
||||
if (obj->isDelegate())
|
||||
js_PurgeScopeChainHelper(cx, obj, id);
|
||||
}
|
||||
#endif
|
||||
@ -906,11 +919,11 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
|
||||
extern void
|
||||
js_Clear(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern jsval
|
||||
js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot);
|
||||
extern bool
|
||||
js_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
|
||||
|
||||
extern JSBool
|
||||
js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
|
||||
bool
|
||||
js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
|
||||
|
||||
/*
|
||||
* Precondition: obj must be locked.
|
||||
|
@ -1751,7 +1751,7 @@
|
||||
* above and inline compensation code here,
|
||||
* depending on real-world workloads.
|
||||
*/
|
||||
JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
|
||||
JS_ASSERT(!(obj->getClass()->flags &
|
||||
JSCLASS_SHARE_ALL_PROPERTIES));
|
||||
|
||||
PCMETER(cache->pchits++);
|
||||
@ -3378,8 +3378,7 @@
|
||||
obj = JSVAL_TO_OBJECT(lval);
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
JS_ASSERT(!OBJ_GET_CLASS(cx, obj)->reserveSlots);
|
||||
JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
|
||||
JSCLASS_SHARE_ALL_PROPERTIES));
|
||||
JS_ASSERT(!(obj->getClass()->flags & JSCLASS_SHARE_ALL_PROPERTIES));
|
||||
|
||||
do {
|
||||
JSScope *scope;
|
||||
|
@ -342,25 +342,6 @@ typedef JSBool
|
||||
typedef void
|
||||
(* JSPropertyRefOp)(JSContext *cx, JSObject *obj, JSProperty *prop);
|
||||
|
||||
/*
|
||||
* Get and set a required slot, one that should already have been allocated.
|
||||
* These operations are infallible, so required slots must be pre-allocated,
|
||||
* or implementations must suppress out-of-memory errors. The native ops
|
||||
* (js_ObjectOps, see jsobj.c) access slots reserved by including a call to
|
||||
* the JSCLASS_HAS_RESERVED_SLOTS(n) macro in the JSClass.flags initializer.
|
||||
*
|
||||
* NB: the slot parameter is a zero-based index into obj slots, unlike the
|
||||
* index parameter to the JS_GetReservedSlot and JS_SetReservedSlot API entry
|
||||
* points, which is a zero-based index into the JSCLASS_RESERVED_SLOTS(clasp)
|
||||
* reserved slots that come after the initial well-known slots: proto, parent,
|
||||
* class, and optionally, the private data slot.
|
||||
*/
|
||||
typedef jsval
|
||||
(* JSGetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot);
|
||||
|
||||
typedef JSBool
|
||||
(* JSSetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
|
||||
|
||||
/*
|
||||
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
|
||||
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
|
||||
|
@ -99,7 +99,7 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
|
||||
* birth, and runtime clone of a block objects are never mutated.
|
||||
*/
|
||||
JS_ASSERT(STOBJ_GET_CLASS(obj) != &js_BlockClass);
|
||||
newscope = JSScope::create(cx, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj), obj);
|
||||
newscope = JSScope::create(cx, scope->map.ops, obj->getClass(), obj);
|
||||
if (!newscope)
|
||||
return NULL;
|
||||
JS_LOCK_SCOPE(cx, newscope);
|
||||
|
@ -8096,7 +8096,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2
|
||||
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
|
||||
guardDenseArray(obj, obj_ins, BRANCH_EXIT);
|
||||
aobj = OBJ_GET_PROTO(cx, obj);
|
||||
obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||
obj_ins = stobj_get_proto(obj_ins);
|
||||
}
|
||||
|
||||
LIns* map_ins = map(obj_ins);
|
||||
@ -8235,7 +8235,7 @@ TraceRecorder::guardPropertyCacheHit(LIns* obj_ins,
|
||||
LIns* obj2_ins;
|
||||
if (PCVCAP_TAG(entry->vcap) == 1) {
|
||||
// Duplicate the special case in PROPERTY_CACHE_TEST.
|
||||
obj2_ins = addName(stobj_get_fslot(obj_ins, JSSLOT_PROTO), "proto");
|
||||
obj2_ins = addName(stobj_get_proto(obj_ins), "proto");
|
||||
guard(false, lir->ins_eq0(obj2_ins), BRANCH_EXIT);
|
||||
} else {
|
||||
obj2_ins = INS_CONSTOBJ(obj2);
|
||||
@ -8532,8 +8532,8 @@ TraceRecorder::guardHasPrototype(JSObject* obj, LIns* obj_ins,
|
||||
JSObject** pobj, LIns** pobj_ins,
|
||||
VMSideExit* exit)
|
||||
{
|
||||
*pobj = JSVAL_TO_OBJECT(obj->fslots[JSSLOT_PROTO]);
|
||||
*pobj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||
*pobj = obj->getProto();
|
||||
*pobj_ins = stobj_get_proto(obj_ins);
|
||||
|
||||
bool cond = *pobj == NULL;
|
||||
guard(cond, addName(lir->ins_eq0(*pobj_ins), "guard(proto-not-null)"), exit);
|
||||
@ -10812,7 +10812,7 @@ TraceRecorder::guardCallee(jsval& callee)
|
||||
branchExit);
|
||||
guard(true,
|
||||
lir->ins2(LIR_eq,
|
||||
stobj_get_fslot(callee_ins, JSSLOT_PARENT),
|
||||
stobj_get_parent(callee_ins),
|
||||
INS_CONSTOBJ(OBJ_GET_PARENT(cx, callee_obj))),
|
||||
branchExit);
|
||||
return JSRS_CONTINUE;
|
||||
@ -11270,7 +11270,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp,
|
||||
* obj_ins the last proto-load.
|
||||
*/
|
||||
while (obj != obj2) {
|
||||
obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||
obj_ins = stobj_get_proto(obj_ins);
|
||||
obj = STOBJ_GET_PROTO(obj);
|
||||
}
|
||||
}
|
||||
|
@ -850,6 +850,10 @@ class TraceRecorder : public avmplus::GCObject {
|
||||
lir->insImmPtr((void*) ~mask));
|
||||
}
|
||||
|
||||
nanojit::LIns* stobj_get_proto(nanojit::LIns* obj_ins) {
|
||||
return stobj_get_fslot(obj_ins, JSSLOT_PROTO);
|
||||
}
|
||||
|
||||
nanojit::LIns* stobj_get_parent(nanojit::LIns* obj_ins) {
|
||||
return stobj_get_fslot(obj_ins, JSSLOT_PARENT);
|
||||
}
|
||||
|
@ -5329,8 +5329,7 @@ JS_FRIEND_DATA(JSObjectOps) js_XMLObjectOps = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
xml_hasInstance, js_TraceObject,
|
||||
xml_clear, NULL,
|
||||
NULL
|
||||
xml_clear
|
||||
};
|
||||
|
||||
static JSObjectOps *
|
||||
|
@ -2452,7 +2452,7 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
|
||||
// - We're not about to force a XOW (e.g. for "window") OR
|
||||
// - We're not actually going to create a XOW (we're wrapping for
|
||||
// chrome).
|
||||
if(STOBJ_IS_SYSTEM(aObject) ||
|
||||
if(aObject->isSystem() ||
|
||||
(sameScope &&
|
||||
(!forceXOW || (aFilenameFlags & JSFILENAME_SYSTEM))))
|
||||
return NS_OK;
|
||||
|
@ -253,7 +253,7 @@ nsXPCWrappedJSClass::CallQueryInterfaceOnJSObject(XPCCallContext& ccx,
|
||||
// interface (i.e. whether the interface is scriptable) and most content
|
||||
// objects don't have QI implementations anyway. Also see bug 503926.
|
||||
if(XPCPerThreadData::IsMainThread(ccx) &&
|
||||
!STOBJ_IS_SYSTEM(JS_GetGlobalForObject(ccx, jsobj)))
|
||||
!JS_GetGlobalForObject(ccx, jsobj)->isSystem())
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> objprin;
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
|
@ -509,9 +509,9 @@ XPCWrappedNative::GetNewOrUsed(XPCCallContext& ccx,
|
||||
nsCOMPtr<nsIXPConnectWrappedJS> wrappedjs(do_QueryInterface(Object));
|
||||
JSObject *obj;
|
||||
wrappedjs->GetJSObject(&obj);
|
||||
if((STOBJ_IS_SYSTEM(obj) ||
|
||||
STOBJ_IS_SYSTEM(JS_GetGlobalForObject(ccx, obj))) &&
|
||||
!STOBJ_IS_SYSTEM(Scope->GetGlobalJSObject()))
|
||||
if((obj->isSystem() ||
|
||||
JS_GetGlobalForObject(ccx, obj)->isSystem()) &&
|
||||
!Scope->GetGlobalJSObject()->isSystem())
|
||||
{
|
||||
crossDoubleWrapped = JS_TRUE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user