bug 511425 - removal of JSObjectOps.(get|set)RequiredSlot. r=brendan

This commit is contained in:
Igor Bukanov 2009-08-28 09:53:26 +04:00
parent 3c773f1b39
commit b919139e8d
21 changed files with 249 additions and 319 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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