Backout 0d642e4e08cf (bug 707049); requested by evilpie.

This commit is contained in:
Ms2ger 2011-12-31 15:13:01 +01:00
Родитель 89171b6c14
Коммит 06d0c7d4ed
47 изменённых файлов: 594 добавлений и 1507 удалений

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

@ -1373,12 +1373,6 @@ class HashSet
return add(p, t);
}
bool putNew(const Lookup &l, const T &t) {
AddPtr p = lookupForAdd(l);
JS_ASSERT(!p);
return add(p, t);
}
void remove(const Lookup &l) {
if (Ptr p = lookup(l))
remove(p);

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

@ -4360,17 +4360,6 @@ if test -n "$JSGC_INCREMENTAL"; then
AC_DEFINE(JSGC_INCREMENTAL)
fi
dnl ========================================================
dnl = Perform moving GC stack rooting analysis
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(gcrootanalysis,
[ --enable-root-analysis Enable moving GC stack root analysis],
JSGC_ROOT_ANALYSIS=1,
JSGC_ROOT_ANALYSIS= )
if test -n "$JSGC_ROOT_ANALYSIS"; then
AC_DEFINE(JSGC_ROOT_ANALYSIS)
fi
dnl ========================================================
dnl = Use Valgrind
dnl ========================================================

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

@ -52,8 +52,7 @@ TreeContext::TreeContext(Parser *prs)
topStmt(NULL), topScopeStmt(NULL), blockChain(NULL), blockNode(NULL),
decls(prs->context), parser(prs), yieldNode(NULL), argumentsNode(NULL), scopeChain_(NULL),
lexdeps(prs->context), parent(prs->tc), staticLevel(0), funbox(NULL), functionList(NULL),
innermostWith(NULL), bindings(prs->context), bindingsRoot(prs->context, &bindings),
sharpSlotBase(-1)
innermostWith(NULL), bindings(prs->context), sharpSlotBase(-1)
{
prs->tc = this;
}

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

@ -2013,10 +2013,11 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
*/
if ((bce->flags & TCF_FUN_EXTENSIBLE_SCOPE) ||
bce->bindings.extensibleParents()) {
Shape *newShape = Shape::setExtensibleParents(cx, blockObj->lastProperty());
if (!newShape)
HeapPtrShape shape;
shape.init(blockObj->lastProperty());
if (!Shape::setExtensibleParents(cx, &shape))
return false;
blockObj->setLastPropertyInfallible(newShape);
blockObj->setLastPropertyInfallible(shape);
}
return true;
@ -5571,9 +5572,6 @@ EmitWith(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
static bool
SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
{
RootedVarObject parent(cx);
parent = funbox->function()->getParent();
/*
* Replace a boxed function with a new one with a method atom. Methods
* require a function with the extended size finalize kind, which normal
@ -5583,7 +5581,7 @@ SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
JSFunction *fun = js_NewFunction(cx, NULL, NULL,
funbox->function()->nargs,
funbox->function()->flags,
parent,
funbox->function()->getParent(),
funbox->function()->atom,
JSFunction::ExtendedFinalizeKind);
if (!fun)

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

@ -351,7 +351,6 @@ struct TreeContext { /* tree context for semantic checks */
Bindings bindings; /* bindings in this code, including
arguments if we're compiling a function */
Bindings::StackRoot bindingsRoot; /* root for stack allocated bindings. */
void trace(JSTracer *trc);

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

@ -316,6 +316,7 @@ FoldXMLConstants(JSContext *cx, ParseNode *pn, TreeContext *tc)
if (accum) {
{
AutoStringRooter tvr(cx, accum);
str = ((kind == PNK_XMLSTAGO || kind == PNK_XMLPTAGC) && i != 0)
? js_AddAttributePart(cx, i & 1, accum, str)
: js_ConcatStrings(cx, accum, str);

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

@ -953,9 +953,7 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
*/
while (tc->parent)
tc = tc->parent;
RootedVarObject parent(context);
parent = tc->inFunction() ? NULL : tc->scopeChain();
JSObject *parent = tc->inFunction() ? NULL : tc->scopeChain();
JSFunction *fun =
js_NewFunction(context, NULL, NULL, 0,

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

@ -81,7 +81,6 @@ inline
HeapValue::HeapValue(const Value &v)
: value(v)
{
JS_ASSERT(!IsPoisonedValue(v));
post();
}
@ -89,7 +88,6 @@ inline
HeapValue::HeapValue(const HeapValue &v)
: value(v.value)
{
JS_ASSERT(!IsPoisonedValue(v.value));
post();
}
@ -102,7 +100,6 @@ HeapValue::~HeapValue()
inline void
HeapValue::init(const Value &v)
{
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post();
}
@ -170,7 +167,6 @@ inline HeapValue &
HeapValue::operator=(const Value &v)
{
pre();
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post();
return *this;
@ -180,7 +176,6 @@ inline HeapValue &
HeapValue::operator=(const HeapValue &v)
{
pre();
JS_ASSERT(!IsPoisonedValue(v.value));
value = v.value;
post();
return *this;
@ -198,7 +193,6 @@ HeapValue::set(JSCompartment *comp, const Value &v)
#endif
pre(comp);
JS_ASSERT(!IsPoisonedValue(v));
value = v;
post(comp);
}
@ -208,7 +202,6 @@ HeapValue::boxNonDoubleFrom(JSValueType type, uint64_t *out)
{
pre();
value.boxNonDoubleFrom(type, out);
JS_ASSERT(!IsPoisonedValue(value));
post();
}
@ -216,7 +209,6 @@ inline
HeapId::HeapId(jsid id)
: value(id)
{
JS_ASSERT(!IsPoisonedId(id));
post();
}
@ -229,7 +221,6 @@ HeapId::~HeapId()
inline void
HeapId::init(jsid id)
{
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
}
@ -256,7 +247,6 @@ inline HeapId &
HeapId::operator=(jsid id)
{
pre();
JS_ASSERT(!IsPoisonedId(id));
value = id;
post();
return *this;
@ -266,7 +256,6 @@ inline HeapId &
HeapId::operator=(const HeapId &v)
{
pre();
JS_ASSERT(!IsPoisonedId(v.value));
value = v.value;
post();
return *this;

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

@ -186,7 +186,6 @@ class HeapPtr
/* Use this to install a ptr into a newly allocated object. */
void init(T *v) {
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
post();
}
@ -211,7 +210,6 @@ class HeapPtr
HeapPtr<T, Unioned> &operator=(T *v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v));
value = v;
post();
return *this;
@ -219,7 +217,6 @@ class HeapPtr
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
pre();
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
value = v.value;
post();
return *this;

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

@ -1853,8 +1853,6 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, JSBool *resolved)
JSStdName *stdnm;
uintN i;
RootObject objRoot(cx, &obj);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
*resolved = JS_FALSE;
@ -3042,8 +3040,7 @@ JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, parent_proto);
RootObject objRoot(cx, &obj);
return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
nargs, ps, fs, static_ps, static_fs);
}
@ -3591,9 +3588,6 @@ DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &valu
jsid id;
JSAtom *atom;
RootObject objRoot(cx, &obj);
RootValue valueRoot(cx, &value);
if (attrs & JSPROP_INDEX) {
id = INT_TO_JSID(intptr_t(name));
atom = NULL;
@ -3606,8 +3600,6 @@ DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &valu
}
if (attrs & JSPROP_NATIVE_ACCESSORS) {
RootId idRoot(cx, &id);
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
attrs &= ~JSPROP_NATIVE_ACCESSORS;
if (getter) {
@ -3625,7 +3617,6 @@ DefineProperty(JSContext *cx, JSObject *obj, const char *name, const Value &valu
attrs |= JSPROP_SETTER;
}
}
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags, tinyid);
}
@ -3688,10 +3679,7 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *jsclasp
if (!clasp)
clasp = &ObjectClass; /* default class is Object */
RootObject root(cx, &obj);
RootedVarObject nobj(cx);
nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
JSObject *nobj = NewObjectWithClassProto(cx, clasp, proto, obj);
if (!nobj)
return NULL;
@ -3724,7 +3712,6 @@ JS_PUBLIC_API(JSBool)
JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
{
JSBool ok;
RootObject root(cx, &obj);
for (ok = true; ps->name; ps++) {
ok = DefineProperty(cx, obj, ps->name, UndefinedValue(), ps->getter, ps->setter,
@ -4194,6 +4181,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
* Note: we have to make sure that we root obj around the call to
* JS_Enumerate to protect against multiple allocations under it.
*/
AutoObjectRooter tvr(cx, iterobj);
ida = JS_Enumerate(cx, obj);
if (!ida)
return NULL;
@ -4379,9 +4367,7 @@ JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
if (!atom)
return NULL;
}
RootObject parentRoot(cx, &parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom);
return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
}
JS_PUBLIC_API(JSFunction *)
@ -4393,8 +4379,7 @@ JS_NewFunctionById(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSO
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
RootObject parentRoot(cx, &parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id));
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id));
}
JS_PUBLIC_API(JSObject *)
@ -4548,15 +4533,14 @@ js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
JS_PUBLIC_API(JSBool)
JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
uintN flags;
RootedVarObject ctor(cx);
JSObject *ctor;
JSFunction *fun;
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
ctor = NULL;
for (; fs->name; fs++) {
flags = fs->flags;
@ -4569,8 +4553,6 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
* method if flags contains JSFUN_GENERIC_NATIVE.
*/
if (flags & JSFUN_GENERIC_NATIVE) {
RootAtom root(cx, &atom);
if (!ctor) {
ctor = JS_GetConstructor(cx, obj);
if (!ctor)
@ -4593,8 +4575,7 @@ JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
fun->setExtendedSlot(0, PrivateValue(fs));
}
fun = js_DefineFunction(cx, objRoot,
ATOM_TO_JSID(atom), fs->call, fs->nargs, flags);
fun = js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), fs->call, fs->nargs, flags);
if (!fun)
return JS_FALSE;
}
@ -4605,15 +4586,13 @@ JS_PUBLIC_API(JSFunction *)
JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
if (!atom)
return NULL;
return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), call, nargs, attrs);
}
JS_PUBLIC_API(JSFunction *)
@ -4621,27 +4600,23 @@ JS_DefineUCFunction(JSContext *cx, JSObject *obj,
const jschar *name, size_t namelen, JSNative call,
uintN nargs, uintN attrs)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
if (!atom)
return NULL;
return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs);
return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), call, nargs, attrs);
}
extern JS_PUBLIC_API(JSFunction *)
JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
uintN nargs, uintN attrs)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
return js_DefineFunction(cx, objRoot, id, call, nargs, attrs);
return js_DefineFunction(cx, obj, id, call, nargs, attrs);
}
struct AutoLastFrameCheck {
@ -4942,8 +4917,6 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
const jschar *chars, size_t length,
const char *filename, uintN lineno, JSVersion version)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, principals);
@ -4966,7 +4939,7 @@ CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
return NULL;
}
JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, objRoot, funAtom);
JSFunction *fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
if (!fun)
return NULL;

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

@ -204,36 +204,6 @@ inline Anchor<T>::~Anchor()
}
#endif /* defined(__GNUC__) */
/*
* Methods for poisoning GC heap pointer words and checking for poisoned words.
* These are in this file for use in Value methods and so forth.
*
* If the moving GC hazard analysis is in use and detects a non-rooted stack
* pointer to a GC thing, one byte of that pointer is poisoned to refer to an
* invalid location. For both 32 bit and 64 bit systems, the fourth byte of the
* pointer is overwritten, to reduce the likelihood of accidentally changing
* a live integer value.
*/
inline void PoisonPtr(jsuword *v)
{
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG)
uint8_t *ptr = (uint8_t *) v + 3;
*ptr = JS_FREE_PATTERN;
#endif
}
template <typename T>
inline bool IsPoisonedPtr(T *v)
{
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG)
uint32_t mask = jsuword(v) & 0xff000000;
return mask == uint32_t(JS_FREE_PATTERN << 24);
#else
return false;
#endif
}
/*
* JS::Value is the C++ interface for a single JavaScript Engine value.
* A few general notes on JS::Value:
@ -311,7 +281,6 @@ class Value
JS_ALWAYS_INLINE
void setString(JSString *str) {
JS_ASSERT(!IsPoisonedPtr(str));
data = STRING_TO_JSVAL_IMPL(str);
}
@ -322,7 +291,6 @@ class Value
JS_ALWAYS_INLINE
void setObject(JSObject &obj) {
JS_ASSERT(!IsPoisonedPtr(&obj));
data = OBJECT_TO_JSVAL_IMPL(&obj);
}
@ -713,16 +681,6 @@ class Value
friend Value (::IMPL_TO_JSVAL)(jsval_layout l);
} JSVAL_ALIGNMENT;
inline bool
IsPoisonedValue(const Value &v)
{
if (v.isString())
return IsPoisonedPtr(v.toString());
if (v.isObject())
return IsPoisonedPtr(&v.toObject());
return false;
}
/************************************************************************/
static JS_ALWAYS_INLINE Value
@ -2024,16 +1982,6 @@ JS_IsInRequest(JSContext *cx);
#ifdef __cplusplus
JS_END_EXTERN_C
inline bool
IsPoisonedId(jsid iden)
{
if (JSID_IS_STRING(iden))
return JS::IsPoisonedPtr(JSID_TO_STRING(iden));
if (JSID_IS_OBJECT(iden))
return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden));
return false;
}
class JSAutoRequest {
public:
JSAutoRequest(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)

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

@ -660,6 +660,9 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value
if (!iter)
return false;
/* Protect iter against GC under JSObject::deleteProperty. */
AutoObjectRooter tvr(cx, iter);
jsuint gap = oldlen - newlen;
for (;;) {
if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id))
@ -3585,18 +3588,15 @@ js_InitArrayClass(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isNative());
RootedVar<GlobalObject*> global(cx);
global = obj->asGlobal();
GlobalObject *global = obj->asGlobal();
RootedVarObject arrayProto(cx);
arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
JSObject *arrayProto = global->createBlankPrototype(cx, &SlowArrayClass);
if (!arrayProto || !AddLengthProperty(cx, arrayProto))
return NULL;
arrayProto->setArrayLength(cx, 0);
RootedVarFunction ctor(cx);
ctor = global->createConstructor(cx, js_Array, &ArrayClass,
CLASS_ATOM(cx, Array), 1);
JSFunction *ctor = global->createConstructor(cx, js_Array, &ArrayClass,
CLASS_ATOM(cx, Array), 1);
if (!ctor)
return NULL;
@ -3674,15 +3674,10 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
return obj;
}
Root<GlobalObject*> parentRoot(cx, &parent);
if (!proto && !FindProto(cx, &ArrayClass, parentRoot, &proto))
if (!proto && !FindProto(cx, &ArrayClass, parent, &proto))
return NULL;
RootObject protoRoot(cx, &proto);
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
types::TypeObject *type = proto->getNewType(cx);
if (!type)
return NULL;
@ -3690,9 +3685,8 @@ NewArray(JSContext *cx, uint32_t length, JSObject *proto)
* Get a shape with zero fixed slots, regardless of the size class.
* See JSObject::createDenseArray.
*/
RootedVarShape shape(cx);
shape = EmptyShape::getInitialShape(cx, &ArrayClass, proto,
parent, gc::FINALIZE_OBJECT0);
Shape *shape = EmptyShape::getInitialShape(cx, &ArrayClass, proto,
proto->getParent(), gc::FINALIZE_OBJECT0);
if (!shape)
return NULL;

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

@ -1473,12 +1473,6 @@ JSContext::JSContext(JSRuntime *rt)
#ifdef JS_THREADSAFE
PodZero(&threadLinks);
#endif
#ifdef JSGC_ROOT_ANALYSIS
PodArrayZero(thingGCRooters);
#ifdef DEBUG
checkGCRooters = NULL;
#endif
#endif
}
JSContext::~JSContext()

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

@ -796,9 +796,6 @@ extern const JSDebugHooks js_NullDebugHooks; /* defined in jsdbgapi.cpp */
namespace js {
class AutoGCRooter;
template <typename T> class Root;
class CheckRoot;
struct AutoResolving;
static inline bool
@ -1105,28 +1102,6 @@ struct JSContext
/* Stack of thread-stack-allocated GC roots. */
js::AutoGCRooter *autoGCRooters;
#ifdef JSGC_ROOT_ANALYSIS
/*
* Stack allocated GC roots for stack GC heap pointers, which may be
* overwritten if moved during a GC.
*/
js::Root<js::gc::Cell*> *thingGCRooters[js::THING_ROOT_COUNT];
#ifdef DEBUG
/*
* Stack allocated list of stack locations which hold non-relocatable
* GC heap pointers (where the target is rooted somewhere else) or integer
* values which may be confused for GC heap pointers. These are used to
* suppress false positives which occur when a rooting analysis treats the
* location as holding a relocatable pointer, but have no other effect on
* GC behavior.
*/
js::CheckRoot *checkGCRooters;
#endif
#endif /* JSGC_ROOT_ANALYSIS */
/* Debug hooks associated with the current context. */
const JSDebugHooks *debugHooks;
@ -1432,260 +1407,6 @@ class AutoGCRooter {
void operator=(AutoGCRooter &ida) MOZ_DELETE;
};
/*
* Moving GC Stack Rooting
*
* A moving GC may change the physical location of GC allocated things, even
* when they are rooted, updating all pointers to the thing to refer to its new
* location. The GC must therefore know about all live pointers to a thing,
* not just one of them, in order to behave correctly.
*
* The classes below are used to root stack locations whose value may be held
* live across a call that can trigger GC (i.e. a call which might allocate any
* GC things). For a code fragment such as:
*
* Foo();
* ... = obj->lastProperty();
*
* If Foo() can trigger a GC, the stack location of obj must be rooted to
* ensure that the GC does not move the JSObject referred to by obj without
* updating obj's location itself. This rooting must happen regardless of
* whether there are other roots which ensure that the object itself will not
* be collected.
*
* If Foo() cannot trigger a GC, and the same holds for all other calls made
* between obj's definitions and its last uses, then no rooting is required.
*
* Several classes are available for rooting stack locations. All are templated
* on the type T of the value being rooted, for which RootMethods<T> must
* have an instantiation.
*
* - Root<T> roots an existing stack allocated variable or other location of
* type T. This is typically used either when a variable only needs to be
* rooted on certain rare paths, or when a function takes a bare GC thing
* pointer as an argument and needs to root it. In the latter case a
* Handle<T> is generally preferred, see below.
*
* - RootedVar<T> declares a variable of type T, whose value is always rooted.
*
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
* take GC things or values as arguments and need to root those arguments
* should generally replace those arguments with handles and avoid any
* explicit rooting. This has two benefits. First, when several such
* functions call each other then redundant rooting of multiple copies of the
* GC thing can be avoided. Second, if the caller does not pass a rooted
* value a compile error will be generated, which is quicker and easier to
* fix than when relying on a separate rooting analysis.
*/
template <typename T>
struct RootMethods { };
template <> struct RootMethods<const jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
};
template <> struct RootMethods<jsid>
{
static jsid initial() { return JSID_VOID; }
static ThingRootKind kind() { return THING_ROOT_ID; }
static bool poisoned(jsid id) { return IsPoisonedId(id); }
};
template <> struct RootMethods<const Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
template <> struct RootMethods<Value>
{
static Value initial() { return UndefinedValue(); }
static ThingRootKind kind() { return THING_ROOT_VALUE; }
static bool poisoned(const Value &v) { return IsPoisonedValue(v); }
};
template <typename T>
struct RootMethods<T *>
{
static T *initial() { return NULL; }
static ThingRootKind kind() { return T::rootKind(); }
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
};
/*
* Root a stack location holding a GC thing. This takes a stack pointer
* and ensures that throughout its lifetime the referenced variable
* will remain pinned against a moving GC.
*
* It is important to ensure that the location referenced by a Root is
* initialized, as otherwise the GC may try to use the the uninitialized value.
* It is generally preferable to use either RootedVar for local variables, or
* Handle for arguments.
*/
template <typename T>
class Root
{
public:
Root(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
#ifdef JSGC_ROOT_ANALYSIS
ThingRootKind kind = RootMethods<T>::kind();
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
this->prev = *stack;
*stack = this;
#endif
JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
this->ptr = ptr;
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~Root()
{
#ifdef JSGC_ROOT_ANALYSIS
JS_ASSERT(*stack == this);
*stack = prev;
#endif
}
#ifdef JSGC_ROOT_ANALYSIS
Root<T> *previous() { return prev; }
#endif
const T *address() const { return ptr; }
private:
#ifdef JSGC_ROOT_ANALYSIS
Root<T> **stack, *prev;
#endif
const T *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
template<typename T> template <typename S>
inline
Handle<T>::Handle(const Root<S> &root)
{
testAssign<S>();
ptr = reinterpret_cast<const T *>(root.address());
}
typedef Root<JSObject*> RootObject;
typedef Root<JSFunction*> RootFunction;
typedef Root<Shape*> RootShape;
typedef Root<BaseShape*> RootBaseShape;
typedef Root<types::TypeObject*> RootTypeObject;
typedef Root<JSString*> RootString;
typedef Root<JSAtom*> RootAtom;
typedef Root<jsid> RootId;
typedef Root<Value> RootValue;
/* Mark a stack location as a root for a rooting analysis. */
class CheckRoot
{
#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS)
CheckRoot **stack, *prev;
const uint8 *ptr;
public:
template <typename T>
CheckRoot(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
this->stack = &cx->checkGCRooters;
this->prev = *stack;
*stack = this;
this->ptr = (const uint8 *) ptr;
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~CheckRoot()
{
JS_ASSERT(*stack == this);
*stack = prev;
}
CheckRoot *previous() { return prev; }
bool contains(const uint8 *v, size_t len) {
return ptr >= v && ptr < v + len;
}
#else /* DEBUG && JSGC_ROOT_ANALYSIS */
public:
template <typename T>
CheckRoot(JSContext *cx, const T *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
/* Make a local variable which stays rooted throughout its lifetime. */
template <typename T>
class RootedVar
{
public:
RootedVar(JSContext *cx)
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
{}
RootedVar(JSContext *cx, T initial)
: ptr(initial), root(cx, &ptr)
{}
operator T () { return ptr; }
T operator ->() { return ptr; }
T * address() { return &ptr; }
const T * address() const { return &ptr; }
T raw() { return ptr; }
T & operator =(T value)
{
JS_ASSERT(!RootMethods<T>::poisoned(value));
ptr = value;
return ptr;
}
private:
T ptr;
Root<T> root;
};
template <typename T> template <typename S>
inline
Handle<T>::Handle(const RootedVar<S> &root)
{
ptr = reinterpret_cast<const T *>(root.address());
}
typedef RootedVar<JSObject*> RootedVarObject;
typedef RootedVar<JSFunction*> RootedVarFunction;
typedef RootedVar<Shape*> RootedVarShape;
typedef RootedVar<BaseShape*> RootedVarBaseShape;
typedef RootedVar<types::TypeObject*> RootedVarTypeObject;
typedef RootedVar<JSString*> RootedVarString;
typedef RootedVar<JSAtom*> RootedVarAtom;
typedef RootedVar<jsid> RootedVarId;
typedef RootedVar<Value> RootedVarValue;
/* FIXME(bug 332648): Move this into a public header. */
class AutoValueRooter : private AutoGCRooter
{

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

@ -236,15 +236,13 @@ JS_FRIEND_API(JSFunction *)
js::DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
uintN nargs, uintN attrs)
{
RootObject objRoot(cx, &obj);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
JSAtom *atom = js_Atomize(cx, name, strlen(name));
if (!atom)
return NULL;
return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs,
return js_DefineFunction(cx, obj, ATOM_TO_JSID(atom), call, nargs, attrs,
JSFunction::ExtendedFinalizeKind);
}
@ -252,8 +250,6 @@ JS_FRIEND_API(JSFunction *)
js::NewFunctionWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags,
JSObject *parent, const char *name)
{
RootObject parentRoot(cx, &parent);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSAtom *atom;
@ -268,7 +264,7 @@ js::NewFunctionWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN f
return NULL;
}
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom,
return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom,
JSFunction::ExtendedFinalizeKind);
}
@ -276,14 +272,12 @@ JS_FRIEND_API(JSFunction *)
js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, uintN nargs, uintN flags, JSObject *parent,
jsid id)
{
RootObject parentRoot(cx, &parent);
JS_ASSERT(JSID_IS_STRING(id));
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
CHECK_REQUEST(cx);
assertSameCompartment(cx, parent);
return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id),
return js_NewFunction(cx, NULL, native, nargs, flags, parent, JSID_TO_ATOM(id),
JSFunction::ExtendedFinalizeKind);
}
@ -295,8 +289,7 @@ js::InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
{
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, parent_proto);
RootObject objRoot(cx, &obj);
return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
nargs, ps, fs, static_ps, static_fs, NULL,
JSFunction::ExtendedFinalizeKind);
}

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

@ -131,17 +131,13 @@ ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee, StackFra
if (!proto)
return NULL;
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
TypeObject *type = proto->getNewType(cx);
if (!type)
return NULL;
bool strict = callee.toFunction()->inStrictMode();
Class *clasp = strict ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass;
RootedVarShape emptyArgumentsShape(cx);
emptyArgumentsShape =
Shape *emptyArgumentsShape =
EmptyShape::getInitialShape(cx, clasp, proto,
proto->getParent(), FINALIZE_KIND,
BaseShape::INDEXED);
@ -627,15 +623,12 @@ Class js::DeclEnvClass = {
static inline JSObject *
NewDeclEnvObject(JSContext *cx, StackFrame *fp)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
types::TypeObject *type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
JSObject *parent = fp->scopeChain().getGlobal();
RootedVarShape emptyDeclEnvShape(cx);
emptyDeclEnvShape =
Shape *emptyDeclEnvShape =
EmptyShape::getInitialShape(cx, &DeclEnvClass, NULL,
parent, CallObject::DECL_ENV_FINALIZE_KIND);
if (!emptyDeclEnvShape)
@ -1211,8 +1204,6 @@ fun_enumerate(JSContext *cx, JSObject *obj)
{
JS_ASSERT(obj->isFunction());
RootObject root(cx, &obj);
jsid id;
bool found;
@ -1293,8 +1284,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (!JSID_IS_ATOM(id))
return true;
RootedVarFunction fun(cx);
fun = obj->toFunction();
JSFunction *fun = obj->toFunction();
if (JSID_IS_ATOM(id, cx->runtime->atomState.classPrototypeAtom)) {
/*
@ -1312,9 +1302,9 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (fun->isNative() || fun->isFunctionPrototype())
return true;
if (!ResolveInterpretedFunctionPrototype(cx, fun))
if (!ResolveInterpretedFunctionPrototype(cx, obj))
return false;
*objp = fun;
*objp = obj;
return true;
}
@ -1328,11 +1318,11 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
else
v.setString(fun->atom ? fun->atom : cx->runtime->emptyString);
if (!DefineNativeProperty(cx, fun, id, v, JS_PropertyStub, JS_StrictPropertyStub,
if (!DefineNativeProperty(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
return false;
}
*objp = fun;
*objp = obj;
return true;
}
@ -1340,13 +1330,13 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
const uint16_t offset = poisonPillProps[i];
if (JSID_IS_ATOM(id, OFFSET_TO_ATOM(cx->runtime, offset))) {
JS_ASSERT(!IsInternalFunctionObject(fun));
JS_ASSERT(!IsInternalFunctionObject(obj));
PropertyOp getter;
StrictPropertyOp setter;
uintN attrs = JSPROP_PERMANENT;
if (fun->isInterpreted() ? fun->inStrictMode() : fun->isBoundFunction()) {
JSObject *throwTypeError = fun->getThrowTypeError();
if (fun->isInterpreted() ? fun->inStrictMode() : obj->isBoundFunction()) {
JSObject *throwTypeError = obj->getThrowTypeError();
getter = CastAsPropertyOp(throwTypeError);
setter = CastAsStrictPropertyOp(throwTypeError);
@ -1356,11 +1346,11 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
setter = JS_StrictPropertyStub;
}
if (!DefineNativeProperty(cx, fun, id, UndefinedValue(), getter, setter,
if (!DefineNativeProperty(cx, obj, id, UndefinedValue(), getter, setter,
attrs, 0, 0)) {
return false;
}
*objp = fun;
*objp = obj;
return true;
}
}
@ -1397,8 +1387,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
flagsword = (fun->nargs << 16) | fun->flags;
script = fun->script();
} else {
RootedVarObject parent(cx, NULL);
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, parent, NULL);
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
if (!fun)
return false;
if (!fun->clearParent(cx))
@ -1408,6 +1397,8 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp)
script = NULL;
}
AutoObjectRooter tvr(cx, fun);
if (!JS_XDRUint32(xdr, &firstword))
return false;
if ((firstword & 1U) && !js_XDRAtom(xdr, &fun->atom))
@ -1873,8 +1864,7 @@ fun_bind(JSContext *cx, uintN argc, Value *vp)
return false;
}
RootedVarObject target(cx);
target = &thisv.toObject();
JSObject *target = &thisv.toObject();
/* Step 3. */
Value *boundArgs = NULL;
@ -1954,8 +1944,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
CallArgs args = CallArgsFromVp(argc, vp);
/* Block this call if security callbacks forbid it. */
RootedVar<GlobalObject*> global(cx);
global = args.callee().getGlobal();
GlobalObject *global = args.callee().getGlobal();
if (!global->isRuntimeCodeGenEnabled(cx)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
return false;
@ -2155,7 +2144,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, Native native, uintN nargs,
uintN flags, HandleObject parent, JSAtom *atom, js::gc::AllocKind kind)
uintN flags, JSObject *parent, JSAtom *atom, js::gc::AllocKind kind)
{
JS_ASSERT(kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
JS_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
@ -2316,15 +2305,12 @@ js_NewFlatClosure(JSContext *cx, JSFunction *fun)
}
JSFunction *
js_DefineFunction(JSContext *cx, HandleObject obj, jsid id, Native native,
js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, Native native,
uintN nargs, uintN attrs, AllocKind kind)
{
RootId idRoot(cx, &id);
PropertyOp gop;
StrictPropertyOp sop;
RootedVarFunction fun(cx);
JSFunction *fun;
if (attrs & JSFUN_STUB_GSOPS) {
/*

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

@ -310,7 +310,7 @@ fun_toStringHelper(JSContext *cx, JSObject *obj, uintN indent);
extern JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
uintN flags, js::HandleObject parent, JSAtom *atom,
uintN flags, JSObject *parent, JSAtom *atom,
js::gc::AllocKind kind = JSFunction::FinalizeKind);
extern JSFunction * JS_FASTCALL
@ -324,7 +324,7 @@ extern JSFunction *
js_NewFlatClosure(JSContext *cx, JSFunction *fun);
extern JSFunction *
js_DefineFunction(JSContext *cx, js::HandleObject obj, jsid id, JSNative native,
js_DefineFunction(JSContext *cx, JSObject *obj, jsid id, JSNative native,
uintN nargs, uintN flags,
js::gc::AllocKind kind = JSFunction::FinalizeKind);

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

@ -3384,89 +3384,6 @@ RunDebugGC(JSContext *cx)
#endif
}
#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
static void
CheckStackRoot(JSTracer *trc, jsuword *w)
{
/* Mark memory as defined for valgrind, as in MarkWordConservatively. */
#ifdef JS_VALGRIND
VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
#endif
ConservativeGCTest test = MarkIfGCThingWord(trc, *w, DONT_MARK_THING);
if (test == CGCT_VALID) {
JSContext *iter = NULL;
bool matched = false;
JSRuntime *rt = trc->context->runtime;
while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter)) {
for (unsigned i = 0; i < THING_ROOT_COUNT; i++) {
Root<Cell*> *rooter = acx->thingGCRooters[i];
while (rooter) {
if (rooter->address() == (Cell **) w)
matched = true;
rooter = rooter->previous();
}
}
CheckRoot *check = acx->checkGCRooters;
while (check) {
if (check->contains((uint8 *) w, sizeof(w)))
matched = true;
check = check->previous();
}
}
if (!matched) {
/*
* Only poison the last byte in the word. It is easy to get
* accidental collisions when a value that does not occupy a full
* word is used to overwrite a now-dead GC thing pointer. In this
* case we want to avoid damaging the smaller value.
*/
PoisonPtr(w);
}
}
}
static void
CheckStackRootsRange(JSTracer *trc, jsuword *begin, jsuword *end)
{
JS_ASSERT(begin <= end);
for (jsuword *i = begin; i != end; ++i)
CheckStackRoot(trc, i);
}
void
CheckStackRoots(JSContext *cx)
{
AutoCopyFreeListToArenas copy(cx->runtime);
JSTracer checker;
JS_TRACER_INIT(&checker, cx, EmptyMarkCallback);
ThreadData *td = JS_THREAD_DATA(cx);
ConservativeGCThreadData *ctd = &td->conservativeGC;
ctd->recordStackTop();
JS_ASSERT(ctd->hasStackToScan());
jsuword *stackMin, *stackEnd;
#if JS_STACK_GROWTH_DIRECTION > 0
stackMin = td->nativeStackBase;
stackEnd = ctd->nativeStackTop;
#else
stackMin = ctd->nativeStackTop + 1;
stackEnd = td->nativeStackBase;
#endif
JS_ASSERT(stackMin <= stackEnd);
CheckStackRootsRange(&checker, stackMin, stackEnd);
CheckStackRootsRange(&checker, ctd->registerSnapshot.words,
ArrayEnd(ctd->registerSnapshot.words));
}
#endif /* DEBUG && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */
#ifdef JS_GC_ZEAL
/*

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

@ -1837,15 +1837,6 @@ NewCompartment(JSContext *cx, JSPrincipals *principals);
void
RunDebugGC(JSContext *cx);
#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG) && !defined(JS_THREADSAFE)
/* Overwrites stack references to GC things which have not been rooted. */
void CheckStackRoots(JSContext *cx);
inline void MaybeCheckStackRoots(JSContext *cx) { CheckStackRoots(cx); }
#else
inline void MaybeCheckStackRoots(JSContext *cx) {}
#endif
const int ZealPokeThreshold = 1;
const int ZealAllocThreshold = 2;
const int ZealVerifierThreshold = 4;

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

@ -391,8 +391,6 @@ NewGCThing(JSContext *cx, js::gc::AllocKind kind, size_t thingSize)
js::gc::RunDebugGC(cx);
#endif
js::gc::MaybeCheckStackRoots(cx);
JSCompartment *comp = cx->compartment;
void *t = comp->arenas.allocateFromFreeList(kind, thingSize);
if (!t)

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

@ -1969,8 +1969,6 @@ TypeObject *
TypeCompartment::newTypeObject(JSContext *cx, JSScript *script,
JSProtoKey key, JSObject *proto, bool unknown)
{
RootObject root(cx, &proto);
TypeObject *object = gc::NewGCThing<TypeObject>(cx, gc::FINALIZE_TYPE_OBJECT, sizeof(TypeObject));
if (!object)
return NULL;
@ -5178,11 +5176,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
{
JS_ASSERT(script->types && !script->types->hasScope());
Root<JSScript*> scriptRoot(cx, &script);
RootObject scopeRoot(cx, &scope);
JSFunction *fun = script->function();
bool nullClosure = fun && fun->isNullClosure();
JS_ASSERT_IF(!fun, !script->isOuterFunction && !script->isInnerFunction);
JS_ASSERT_IF(!scope, fun && !script->isInnerFunction);
@ -5213,7 +5207,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
if (!cx->typeInferenceEnabled())
return true;
if (!script->isInnerFunction || nullClosure) {
if (!script->isInnerFunction || fun->isNullClosure()) {
/*
* Outermost functions need nesting information if there are inner
* functions directly nested in them.
@ -5817,6 +5811,9 @@ JSObject::setNewTypeUnknown(JSContext *cx)
TypeObject *
JSObject::getNewType(JSContext *cx, JSFunction *fun)
{
if (!setDelegate(cx))
return NULL;
TypeObjectSet &table = cx->compartment->newTypeObjects;
if (!table.initialized() && !table.init())
@ -5843,19 +5840,14 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun)
return type;
}
RootedVarObject self(cx, this);
if (!setDelegate(cx))
return NULL;
bool markUnknown = self->lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN);
bool markUnknown = lastProperty()->hasObjectFlag(BaseShape::NEW_TYPE_UNKNOWN);
TypeObject *type = cx->compartment->types.newTypeObject(cx, NULL,
JSProto_Object, self, markUnknown);
JSProto_Object, this, markUnknown);
if (!type)
return NULL;
if (!table.relookupOrAdd(p, self, type))
if (!table.relookupOrAdd(p, this, type))
return NULL;
if (!cx->typeInferenceEnabled())
@ -5868,7 +5860,7 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun)
* flag set. This is a hack, :XXX: need a real correspondence between
* types and the possible js::Class of objects with that type.
*/
if (self->hasSpecialEquality())
if (hasSpecialEquality())
type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
if (fun)
@ -5876,11 +5868,11 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun)
#if JS_HAS_XML_SUPPORT
/* Special case for XML object equality, see makeLazyType(). */
if (self->isXML() && !type->unknownProperties())
if (isXML() && !type->unknownProperties())
type->flags |= OBJECT_FLAG_UNKNOWN_MASK;
#endif
if (self->getClass()->ext.equality)
if (getClass()->ext.equality)
type->flags |= OBJECT_FLAG_SPECIAL_EQUALITY;
/*
@ -5900,8 +5892,6 @@ JSObject::getNewType(JSContext *cx, JSFunction *fun)
TypeObject *
JSCompartment::getLazyType(JSContext *cx, JSObject *proto)
{
gc::MaybeCheckStackRoots(cx);
TypeObjectSet &table = cx->compartment->lazyTypeObjects;
if (!table.initialized() && !table.init())

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

@ -878,8 +878,6 @@ struct TypeObject : gc::Cell
static inline void writeBarrierPost(TypeObject *type, void *addr);
static inline void readBarrier(TypeObject *type);
static inline ThingRootKind rootKind() { return THING_ROOT_TYPE_OBJECT; }
private:
inline uint32_t basePropertyCount() const;
inline void setBasePropertyCount(uint32_t count);

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

@ -1327,19 +1327,13 @@ JSScript::ensureHasTypes(JSContext *cx)
inline bool
JSScript::ensureRanAnalysis(JSContext *cx, JSObject *scope)
{
JSScript *self = this;
if (!self->ensureHasTypes(cx))
if (!ensureHasTypes(cx))
return false;
if (!self->types->hasScope()) {
js::CheckRoot root(cx, &self);
js::RootObject objRoot(cx, &scope);
if (!js::types::TypeScript::SetScope(cx, self, scope))
return false;
}
if (!self->hasAnalysis() && !self->makeAnalysis(cx))
if (!types->hasScope() && !js::types::TypeScript::SetScope(cx, this, scope))
return false;
JS_ASSERT(self->analysis()->ranBytecode());
if (!hasAnalysis() && !makeAnalysis(cx))
return false;
JS_ASSERT(analysis()->ranBytecode());
return true;
}

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

@ -213,6 +213,7 @@ js::GetScopeChain(JSContext *cx, StackFrame *fp)
JSObject *innermostNewChild = js_CloneBlockObject(cx, sharedBlock, fp);
if (!innermostNewChild)
return NULL;
AutoObjectRooter tvr(cx, innermostNewChild);
/*
* Clone our way towards outer scopes until we reach the innermost
@ -643,8 +644,6 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
{
JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
Root<JSScript*> scriptRoot(cx, &script);
if (script->isEmpty()) {
if (result)
result->setUndefined();
@ -655,9 +654,6 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
return false;
if (!script->ensureRanAnalysis(cx, &scopeChain))
return false;
/* Give strict mode eval its own fresh lexical environment. */
StackFrame *fp = efg.fp();
if (fp->isStrictEvalFrame() && !CreateEvalCallObject(cx, fp))
@ -670,6 +666,9 @@ js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const V
Probes::startExecution(cx, script);
if (!script->ensureRanAnalysis(cx, &scopeChain))
return false;
TypeScript::SetThis(cx, script, fp->thisValue());
AutoPreserveEnumerators preserve(cx);

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

@ -216,15 +216,10 @@ static bool
EnumerateNativeProperties(JSContext *cx, JSObject *obj, JSObject *pobj, uintN flags, IdSet &ht,
AutoIdVector *props)
{
RootObject objRoot(cx, &obj);
RootObject pobjRoot(cx, &pobj);
size_t initialLength = props->length();
/* Collect all unique properties from this object's scope. */
Shape::Range r = pobj->lastProperty()->all();
Shape::Range::Root root(cx, &r);
for (; !r.empty(); r.popFront()) {
for (Shape::Range r = pobj->lastProperty()->all(); !r.empty(); r.popFront()) {
const Shape &shape = r.front();
if (!JSID_IS_DEFAULT_XML_NAMESPACE(shape.propid()) &&
@ -299,10 +294,7 @@ Snapshot(JSContext *cx, JSObject *obj, uintN flags, AutoIdVector *props)
if (!ht.init(32))
return NULL;
RootObject objRoot(cx, &obj);
RootedVarObject pobj(cx);
pobj = obj;
JSObject *pobj = obj;
do {
Class *clasp = pobj->getClass();
if (pobj->isNative() &&
@ -481,14 +473,12 @@ static inline JSObject *
NewIteratorObject(JSContext *cx, uintN flags)
{
if (flags & JSITER_ENUMERATE) {
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
types::TypeObject *type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
RootedVarShape emptyEnumeratorShape(cx);
emptyEnumeratorShape = EmptyShape::getInitialShape(cx, &IteratorClass, NULL, NULL,
ITERATOR_FINALIZE_KIND);
Shape *emptyEnumeratorShape = EmptyShape::getInitialShape(cx, &IteratorClass, NULL, NULL,
ITERATOR_FINALIZE_KIND);
if (!emptyEnumeratorShape)
return NULL;
@ -938,16 +928,16 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
* became visible as a result of this deletion.
*/
if (obj->getProto()) {
JSObject *proto = obj->getProto();
JSObject *obj2;
AutoObjectRooter proto(cx, obj->getProto());
AutoObjectRooter obj2(cx);
JSProperty *prop;
if (!proto->lookupGeneric(cx, *idp, &obj2, &prop))
if (!proto.object()->lookupGeneric(cx, *idp, obj2.addr(), &prop))
return false;
if (prop) {
uintN attrs;
if (obj2->isNative())
if (obj2.object()->isNative())
attrs = ((Shape *) prop)->attributes();
else if (!obj2->getGenericAttributes(cx, *idp, &attrs))
else if (!obj2.object()->getGenericAttributes(cx, *idp, &attrs))
return false;
if (attrs & JSPROP_ENUMERATE)

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

@ -1933,7 +1933,7 @@ obj_keys(JSContext *cx, uintN argc, Value *vp)
}
static bool
HasProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, bool *foundp)
HasProperty(JSContext* cx, JSObject* obj, jsid id, Value* vp, bool *foundp)
{
if (!obj->hasProperty(cx, id, foundp, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING))
return false;
@ -1967,7 +1967,7 @@ PropDesc::PropDesc()
}
bool
PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
PropDesc::initialize(JSContext* cx, const Value &origval, bool checkAccessors)
{
Value v = origval;
@ -1976,7 +1976,7 @@ PropDesc::initialize(JSContext *cx, const Value &origval, bool checkAccessors)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_NONNULL_OBJECT);
return false;
}
JSObject *desc = &v.toObject();
JSObject* desc = &v.toObject();
/* Make a copy of the descriptor. We might need it later. */
pd = v;
@ -2493,7 +2493,7 @@ js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id, const Value &descrip
/* ES5 15.2.3.6: Object.defineProperty(O, P, Attributes) */
static JSBool
obj_defineProperty(JSContext *cx, uintN argc, Value *vp)
obj_defineProperty(JSContext* cx, uintN argc, Value* vp)
{
JSObject *obj;
if (!GetFirstArgumentAsObject(cx, argc, vp, "Object.defineProperty", &obj))
@ -2559,7 +2559,7 @@ js_PopulateObject(JSContext *cx, JSObject *newborn, JSObject *props)
/* ES5 15.2.3.7: Object.defineProperties(O, Properties) */
static JSBool
obj_defineProperties(JSContext *cx, uintN argc, Value *vp)
obj_defineProperties(JSContext* cx, uintN argc, Value* vp)
{
/* Steps 1 and 7. */
JSObject *obj;
@ -2573,7 +2573,7 @@ obj_defineProperties(JSContext *cx, uintN argc, Value *vp)
"Object.defineProperties", "0", "s");
return false;
}
JSObject *props = ToObject(cx, &vp[3]);
JSObject* props = ToObject(cx, &vp[3]);
if (!props)
return false;
@ -2704,8 +2704,6 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
assertSameCompartment(cx, this);
JS_ASSERT(it == SEAL || it == FREEZE);
RootedVarObject self(cx, this);
AutoIdVector props(cx);
if (isExtensible()) {
if (!preventExtensions(cx, &props))
@ -2716,13 +2714,13 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
}
/* preventExtensions must slowify dense arrays, so we can assign to holes without checks. */
JS_ASSERT(!self->isDenseArray());
JS_ASSERT(!isDenseArray());
for (size_t i = 0, len = props.length(); i < len; i++) {
jsid id = props[i];
uintN attrs;
if (!self->getGenericAttributes(cx, id, &attrs))
if (!getGenericAttributes(cx, id, &attrs))
return false;
/* Make all attributes permanent; if freezing, make data attributes read-only. */
@ -2737,7 +2735,7 @@ JSObject::sealOrFreeze(JSContext *cx, ImmutabilityType it)
continue;
attrs |= new_attrs;
if (!self->setGenericAttributes(cx, id, &attrs))
if (!setGenericAttributes(cx, id, &attrs))
return false;
}
@ -2917,10 +2915,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type, JSObject *parent
JS_ASSERT_IF(clasp == &FunctionClass,
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
RootTypeObject typeRoot(cx, &type);
RootedVarShape shape(cx);
shape = EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind);
Shape *shape = EmptyShape::getInitialShape(cx, clasp, type->proto, parent, kind);
if (!shape)
return NULL;
@ -2928,7 +2923,7 @@ NewObject(JSContext *cx, Class *clasp, types::TypeObject *type, JSObject *parent
if (!PreallocateObjectDynamicSlots(cx, shape, &slots))
return NULL;
JSObject *obj = JSObject::create(cx, kind, shape, typeRoot, slots);
JSObject* obj = JSObject::create(cx, kind, shape, type, slots);
if (!obj)
return NULL;
@ -2951,9 +2946,6 @@ js::NewObjectWithGivenProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
return cache.newObjectFromHit(cx, entry);
}
RootObject protoRoot(cx, &proto);
RootObject parentRoot(cx, &parent);
types::TypeObject *type = proto ? proto->getNewType(cx) : cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
@ -3007,9 +2999,7 @@ js::NewObjectWithClassProto(JSContext *cx, js::Class *clasp, JSObject *proto, JS
return cache.newObjectFromHit(cx, entry);
}
RootObject parentRoot(cx, &parent);
if (!FindProto(cx, clasp, parentRoot, &proto))
if (!FindProto(cx, clasp, parent, &proto))
return NULL;
types::TypeObject *type = proto->getNewType(cx);
@ -3519,17 +3509,15 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
{
JSObject *obj;
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
TypeObject *type = proto->getNewType(cx);
if (!type)
return NULL;
StackFrame *priv = js_FloatingFrameIfGenerator(cx, cx->fp());
RootedVarShape emptyWithShape(cx);
emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
parent->getGlobal(),
WITH_FINALIZE_KIND);
Shape *emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
parent->getGlobal(),
WITH_FINALIZE_KIND);
if (!emptyWithShape)
return NULL;
@ -3542,6 +3530,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
return NULL;
obj->setPrivate(priv);
AutoObjectRooter tvr(cx, obj);
JSObject *thisp = proto->thisObject(cx);
if (!thisp)
return NULL;
@ -3558,14 +3547,12 @@ static const gc::AllocKind BLOCK_FINALIZE_KIND = gc::FINALIZE_OBJECT4;
JSObject *
js_NewBlockObject(JSContext *cx)
{
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
types::TypeObject *type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
RootedVarShape emptyBlockShape(cx);
emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL,
BLOCK_FINALIZE_KIND);
Shape *emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL,
BLOCK_FINALIZE_KIND);
if (!emptyBlockShape)
return NULL;
@ -3577,8 +3564,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
{
JS_ASSERT(proto->isStaticBlock());
RootedVarTypeObject type(cx);
type = proto->getNewType(cx);
TypeObject *type = proto->getNewType(cx);
if (!type)
return NULL;
@ -3586,11 +3572,7 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
if (!PreallocateObjectDynamicSlots(cx, proto->lastProperty(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = proto->lastProperty();
JSObject *clone = JSObject::create(cx, BLOCK_FINALIZE_KIND,
shape, type, slots);
JSObject *clone = JSObject::create(cx, BLOCK_FINALIZE_KIND, proto->lastProperty(), type, slots);
if (!clone)
return NULL;
@ -3703,12 +3685,9 @@ JSObject::defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclar
*redeclared = false;
RootedVarObject self(cx, this);
/* Inline JSObject::addProperty in order to trap the redefinition case. */
Shape **spp;
Shape *shape = Shape::search(cx, lastProperty(), id, &spp, true);
if (shape) {
Shape **spp = nativeSearch(cx, id, true);
if (SHAPE_FETCH(spp)) {
*redeclared = true;
return NULL;
}
@ -3718,10 +3697,10 @@ JSObject::defineBlockVariable(JSContext *cx, jsid id, intN index, bool *redeclar
* block's shape later.
*/
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
shape = self->addPropertyInternal(cx, id, block_getProperty, block_setProperty,
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
Shape::HAS_SHORTID, index, spp,
/* allowDictionary = */ false);
const Shape *shape = addPropertyInternal(cx, id, block_getProperty, block_setProperty,
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
Shape::HAS_SHORTID, index, spp,
/* allowDictionary = */ false);
if (!shape)
return NULL;
return shape;
@ -4200,6 +4179,8 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
obj->setStaticBlockScopeChain(parent);
}
AutoObjectRooter tvr(cx, obj);
if (!JS_XDRUint32(xdr, &depthAndCount))
return false;
@ -4333,7 +4314,7 @@ ClearClassObject(JSContext *cx, JSObject *obj, JSProtoKey key)
}
JSObject *
DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
JSObject *protoProto, Class *clasp,
Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
@ -4369,8 +4350,7 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
* [which already needs to happen for bug 638316], figure out nicer
* semantics for null-protoProto, and use createBlankPrototype.)
*/
RootedVarObject proto(cx);
proto = NewObjectWithClassProto(cx, clasp, protoProto, obj);
JSObject *proto = NewObjectWithClassProto(cx, clasp, protoProto, obj);
if (!proto)
return NULL;
@ -4381,7 +4361,7 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
return NULL;
/* After this point, control must exit via label bad or out. */
RootedVarObject ctor(cx);
JSObject *ctor;
bool named = false;
bool cached = false;
if (!constructor) {
@ -4407,9 +4387,9 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
* (FIXME: remove this dependency on the exact identity of the parent,
* perhaps as part of bug 638316.)
*/
RootedVarFunction fun(cx);
fun = js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
ctorKind);
JSFunction *fun =
js_NewFunction(cx, NULL, constructor, nargs, JSFUN_CONSTRUCTOR, obj, atom,
ctorKind);
if (!fun)
goto bad;
fun->setConstructorClass(clasp);
@ -4495,7 +4475,7 @@ IsStandardClassResolved(JSObject *obj, js::Class *clasp)
}
void
MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp)
MarkStandardClassInitializedNoProto(JSObject* obj, js::Class *clasp)
{
JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
@ -4510,16 +4490,13 @@ MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp)
}
JSObject *
js_InitClass(JSContext *cx, HandleObject obj, JSObject *protoProto,
js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
Class *clasp, Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
JSObject **ctorp, AllocKind ctorKind)
{
RootObject rootProto(cx, &protoProto);
RootedVarAtom atom(cx);
atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
JSAtom *atom = js_Atomize(cx, clasp->name, strlen(clasp->name));
if (!atom)
return NULL;
@ -5028,8 +5005,6 @@ JSBool
js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
JSObject **objp)
{
RootObject objRoot(cx, &obj);
obj = obj->getGlobal();
if (!obj->isGlobal()) {
*objp = NULL;
@ -5066,16 +5041,14 @@ JSBool
js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
Value *vp, Class *clasp)
{
JSObject *cobj, *pobj;
JSObject *obj, *cobj, *pobj;
jsid id;
JSProperty *prop;
const Shape *shape;
RootedVarObject obj(cx);
if (start) {
obj = start->getGlobal();
OBJ_TO_INNER_OBJECT(cx, *obj.address());
OBJ_TO_INNER_OBJECT(cx, obj);
} else {
obj = GetGlobalForScopeChain(cx);
}
@ -5247,9 +5220,6 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
{
const Shape *shape;
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
while (obj) {
if (!obj->isNative()) {
obj = obj->getProto();
@ -5273,9 +5243,6 @@ PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
bool
js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
{
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
JS_ASSERT(obj->isDelegate());
PurgeProtoChain(cx, obj->getProto(), id);
@ -5378,23 +5345,13 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, JSObject *obj, const Shape *sha
namespace js {
const Shape *
DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
PropertyOp getter, StrictPropertyOp setter, uintN attrs,
uintN flags, intN shortid, uintN defineHow /* = 0 */)
{
JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE |
DNP_SET_METHOD | DNP_SKIP_TYPE)) == 0);
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
/*
* Make a local copy of value, in case a method barrier needs to update the
* value to define, and just so addProperty can mutate its inout parameter.
*/
RootedVarValue value(cx);
value = value_;
/* Convert string indices to integers if appropriate. */
id = js_CheckForStringIndex(id);
@ -5468,6 +5425,12 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
MarkTypePropertyConfigured(cx, obj, id);
}
/*
* Make a local copy of value, in case a method barrier needs to update the
* value to define, and just so addProperty can mutate its inout parameter.
*/
Value valueCopy = value;
if (!shape) {
/* Add a new property, or replace an existing one of the same id. */
if (defineHow & DNP_SET_METHOD) {
@ -5476,21 +5439,21 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
JS_ASSERT(!getter && !setter);
JSObject *funobj = &value.raw().toObject();
JSObject *funobj = &value.toObject();
if (!funobj->toFunction()->isClonedMethod())
flags |= Shape::METHOD;
}
if (const Shape *existingShape = obj->nativeLookup(cx, id)) {
if (existingShape->isMethod() &&
ObjectValue(*obj->nativeGetMethod(existingShape)) == value)
ObjectValue(*obj->nativeGetMethod(existingShape)) == valueCopy)
{
/*
* Redefining an existing shape-memoized method object without
* changing the property's value, perhaps to change attributes.
* Clone now via the method read barrier.
*/
if (!obj->methodReadBarrier(cx, *existingShape, value.address()))
if (!obj->methodReadBarrier(cx, *existingShape, &valueCopy))
return NULL;
}
}
@ -5503,10 +5466,10 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
/* Store valueCopy before calling addProperty, in case the latter GC's. */
if (shape->hasSlot())
obj->nativeSetSlot(shape->slot(), value);
obj->nativeSetSlot(shape->slot(), valueCopy);
/* XXXbe called with lock held */
if (!CallAddPropertyHook(cx, clasp, obj, shape, value.address())) {
if (!CallAddPropertyHook(cx, clasp, obj, shape, &valueCopy)) {
obj->removeProperty(cx, id);
return NULL;
}
@ -5537,7 +5500,7 @@ DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
* and return true.
*/
static JSBool
CallResolveOp(JSContext *cx, JSObject *start, HandleObject obj, HandleId id, uintN flags,
CallResolveOp(JSContext *cx, JSObject *start, JSObject *obj, jsid id, uintN flags,
JSObject **objp, JSProperty **propp, bool *recursedp)
{
Class *clasp = obj->getClass();
@ -5565,10 +5528,8 @@ CallResolveOp(JSContext *cx, JSObject *start, HandleObject obj, HandleId id, uin
JSNewResolveOp newresolve = reinterpret_cast<JSNewResolveOp>(resolve);
if (flags == RESOLVE_INFER)
flags = js_InferFlags(cx, 0);
RootedVarObject obj2(cx);
obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START) ? start : NULL;
if (!newresolve(cx, obj, id, flags, obj2.address()))
JSObject *obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START) ? start : NULL;
if (!newresolve(cx, obj, id, flags, &obj2))
return false;
/*
@ -5608,9 +5569,6 @@ LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN flags
/* We should not get string indices which aren't already integers here. */
JS_ASSERT(id == js_CheckForStringIndex(id));
RootObject objRoot(cx, &obj);
RootId idRoot(cx, &id);
/* Search scopes starting with obj and following the prototype link. */
JSObject *start = obj;
while (true) {
@ -5624,7 +5582,7 @@ LookupPropertyWithFlagsInline(JSContext *cx, JSObject *obj, jsid id, uintN flags
/* Try obj's class resolve hook if id was not found in obj's scope. */
if (obj->getClass()->resolve != JS_ResolveStub) {
bool recursed;
if (!CallResolveOp(cx, start, objRoot, idRoot, flags, objp, propp, &recursed))
if (!CallResolveOp(cx, start, obj, id, flags, objp, propp, &recursed))
return false;
if (recursed)
break;
@ -6161,7 +6119,7 @@ js::CheckUndeclaredVarAssignment(JSContext *cx, JSString *propname)
}
bool
JSObject::reportReadOnly(JSContext *cx, jsid id, uintN report)
JSObject::reportReadOnly(JSContext* cx, jsid id, uintN report)
{
return js_ReportValueErrorFlags(cx, report, JSMSG_READ_ONLY,
JSDVG_IGNORE_STACK, IdToValue(id), NULL,
@ -6169,7 +6127,7 @@ JSObject::reportReadOnly(JSContext *cx, jsid id, uintN report)
}
bool
JSObject::reportNotConfigurable(JSContext *cx, jsid id, uintN report)
JSObject::reportNotConfigurable(JSContext* cx, jsid id, uintN report)
{
return js_ReportValueErrorFlags(cx, report, JSMSG_CANT_DELETE,
JSDVG_IGNORE_STACK, IdToValue(id), NULL,

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

@ -498,15 +498,15 @@ struct JSObject : js::gc::Cell
/* Make a non-array object with the specified initial state. */
static inline JSObject *create(JSContext *cx,
js::gc::AllocKind kind,
js::HandleShape shape,
js::HandleTypeObject type,
js::Shape *shape,
js::types::TypeObject *type,
js::HeapValue *slots);
/* Make a dense array object with the specified initial state. */
static inline JSObject *createDenseArray(JSContext *cx,
js::gc::AllocKind kind,
js::HandleShape shape,
js::HandleTypeObject type,
js::Shape *shape,
js::types::TypeObject *type,
uint32_t length);
/*
@ -526,6 +526,7 @@ struct JSObject : js::gc::Cell
static inline size_t offsetOfShape() { return offsetof(JSObject, shape_); }
inline js::HeapPtrShape *addressOfShape() { return &shape_; }
inline js::Shape **nativeSearch(JSContext *cx, jsid id, bool adding = false);
const js::Shape *nativeLookup(JSContext *cx, jsid id);
inline bool nativeContains(JSContext *cx, jsid id);
@ -1218,7 +1219,7 @@ struct JSObject : js::gc::Cell
bool callMethod(JSContext *cx, jsid id, uintN argc, js::Value *argv, js::Value *vp);
private:
js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::Shape &child);
/*
* Internal helper that adds a shape not yet mapped by this object.
@ -1230,8 +1231,8 @@ struct JSObject : js::gc::Cell
js::Shape *addPropertyInternal(JSContext *cx, jsid id,
JSPropertyOp getter, JSStrictPropertyOp setter,
uint32_t slot, uintN attrs,
uintN flags, intN shortid, js::Shape **spp,
bool allowDictionary);
uintN flags, intN shortid,
js::Shape **spp, bool allowDictionary);
bool toDictionaryMode(JSContext *cx);
@ -1392,8 +1393,6 @@ struct JSObject : js::gc::Cell
inline void privateWriteBarrierPre(void **oldval);
inline void privateWriteBarrierPost(void **oldval);
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
private:
static void staticAsserts() {
/* Check alignment for any fixed slots allocated after the object. */

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

@ -1032,7 +1032,7 @@ JSObject::initializeSlotRange(size_t start, size_t length)
/* static */ inline JSObject *
JSObject::create(JSContext *cx, js::gc::AllocKind kind,
js::HandleShape shape, js::HandleTypeObject type, js::HeapValue *slots)
js::Shape *shape, js::types::TypeObject *type, js::HeapValue *slots)
{
/*
* Callers must use dynamicSlotsCount to size the initial slot array of the
@ -1063,8 +1063,7 @@ JSObject::create(JSContext *cx, js::gc::AllocKind kind,
/* static */ inline JSObject *
JSObject::createDenseArray(JSContext *cx, js::gc::AllocKind kind,
js::HandleShape shape, js::HandleTypeObject type,
uint32_t length)
js::Shape *shape, js::types::TypeObject *type, uint32_t length)
{
JS_ASSERT(shape && type);
JS_ASSERT(shape->getObjectClass() == &js::ArrayClass);
@ -1193,12 +1192,17 @@ JSObject::isNative() const
return lastProperty()->isNative();
}
inline js::Shape **
JSObject::nativeSearch(JSContext *cx, jsid id, bool adding)
{
return js::Shape::search(cx, &shape_, id, adding);
}
inline const js::Shape *
JSObject::nativeLookup(JSContext *cx, jsid id)
{
JS_ASSERT(isNative());
js::Shape **spp;
return js::Shape::search(cx, lastProperty(), id, &spp);
return SHAPE_FETCH(nativeSearch(cx, id));
}
inline bool
@ -1651,17 +1655,12 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_)
/* Copy the entry to the stack first in case it is purged by a GC. */
size_t nbytes = entry->nbytes;
char stackObject[sizeof(JSObject_Slots16)];
JS_ASSERT(nbytes <= sizeof(stackObject));
JSObject_Slots16 stackObject;
memcpy(&stackObject, &entry->templateObject, nbytes);
JSObject *baseobj = (JSObject *) stackObject;
RootShape shapeRoot(cx, (Shape **) baseobj->addressOfShape());
RootTypeObject typeRoot(cx, (types::TypeObject **) baseobj->addressOfType());
obj = js_NewGCObject(cx, entry->kind);
if (obj) {
memcpy(obj, baseobj, nbytes);
memcpy(obj, &stackObject, nbytes);
Probes::createObject(cx, obj);
return obj;
}
@ -1714,7 +1713,7 @@ GetClassProtoKey(js::Class *clasp)
}
inline bool
FindProto(JSContext *cx, js::Class *clasp, HandleObject parent, JSObject **proto)
FindProto(JSContext *cx, js::Class *clasp, JSObject *parent, JSObject ** proto)
{
JSProtoKey protoKey = GetClassProtoKey(clasp);
if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
@ -1883,16 +1882,15 @@ DefineConstructorAndPrototype(JSContext *cx, GlobalObject *global,
/* Set these first in case AddTypePropertyId looks for this class. */
global->setSlot(key, ObjectValue(*ctor));
global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
global->setSlot(key, UndefinedValue());
global->setSlot(key + JSProto_LIMIT, UndefinedValue());
global->setSlot(key + JSProto_LIMIT * 2, UndefinedValue());
return false;
}
global->setSlot(key + JSProto_LIMIT * 2, ObjectValue(*ctor));
return true;
}
@ -2023,7 +2021,7 @@ ValueIsSpecial(JSObject *obj, Value *propval, SpecialId *sidp, JSContext *cx)
}
JSObject *
DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, HandleAtom atom,
DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
JSObject *protoProto, Class *clasp,
Native constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
@ -2034,7 +2032,7 @@ DefineConstructorAndPrototype(JSContext *cx, HandleObject obj, JSProtoKey key, H
} /* namespace js */
extern JSObject *
js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
js::Class *clasp, JSNative constructor, uintN nargs,
JSPropertySpec *ps, JSFunctionSpec *fs,
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,

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

@ -53,13 +53,13 @@
using namespace js;
inline HashNumber
ShapeHasher::hash(const Lookup &l)
ShapeHasher::hash(const Lookup l)
{
return l.hash();
return l->hash();
}
inline bool
ShapeHasher::match(const Key k, const Lookup &l)
ShapeHasher::match(const Key k, const Lookup l)
{
return k->matches(l);
}
@ -84,8 +84,8 @@ HashChildren(Shape *kid1, Shape *kid2)
return NULL;
}
JS_ALWAYS_TRUE(hash->putNew(kid1, kid1));
JS_ALWAYS_TRUE(hash->putNew(kid2, kid2));
JS_ALWAYS_TRUE(hash->putNew(kid1));
JS_ALWAYS_TRUE(hash->putNew(kid2));
return hash;
}
@ -121,7 +121,7 @@ PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
return true;
}
if (!kidp->toHash()->putNew(child, child)) {
if (!kidp->toHash()->putNew(child)) {
JS_ReportOutOfMemory(cx);
return false;
}
@ -145,9 +145,7 @@ Shape::removeChild(Shape *child)
KidsHash *hash = kidp->toHash();
JS_ASSERT(hash->count() >= 2); /* otherwise kidp->isShape() should be true */
hash->remove(child);
if (hash->count() == 1) {
/* Convert from HASH form back to SHAPE form. */
KidsHash::Range r = hash->all();
@ -173,7 +171,7 @@ ReadBarrier(Shape *shape)
}
Shape *
PropertyTree::getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child)
PropertyTree::getChild(JSContext *cx, Shape *parent, const Shape &child)
{
Shape *shape;
@ -190,24 +188,24 @@ PropertyTree::getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const Stac
KidsPointer *kidp = &parent->kids;
if (kidp->isShape()) {
shape = kidp->toShape();
if (shape->matches(child))
if (shape->matches(&child))
return ReadBarrier(shape);
} else if (kidp->isHash()) {
shape = *kidp->toHash()->lookup(child);
shape = *kidp->toHash()->lookup(&child);
if (shape)
return ReadBarrier(shape);
} else {
/* If kidp->isNull(), we always insert. */
}
RootStackShape childRoot(cx, &child);
RootShape parentRoot(cx, &parent);
shape = newShape(cx);
if (!shape)
return NULL;
new (shape) Shape(child, nfixed);
UnownedBaseShape *base = child.base()->unowned();
new (shape) Shape(&child);
shape->base_.init(base);
if (!insertChild(cx, parent, shape))
return NULL;

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

@ -48,10 +48,10 @@ namespace js {
struct ShapeHasher {
typedef js::Shape *Key;
typedef js::StackShape Lookup;
typedef const js::Shape *Lookup;
static inline HashNumber hash(const Lookup &l);
static inline bool match(Key k, const Lookup &l);
static inline HashNumber hash(const Lookup l);
static inline bool match(Key k, Lookup l);
};
typedef HashSet<js::Shape *, ShapeHasher, SystemAllocPolicy> KidsHash;
@ -116,7 +116,7 @@ class PropertyTree
}
js::Shape *newShape(JSContext *cx);
js::Shape *getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child);
js::Shape *getChild(JSContext *cx, js::Shape *parent, const js::Shape &child);
#ifdef DEBUG
static void dumpShapes(JSContext *cx);

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

@ -1728,6 +1728,7 @@ js::FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
JSObject *newborn = NewObjectWithGivenProto(cx, clasp, proto, parent, kind);
if (!newborn)
return false;
AutoObjectRooter tvr2(cx, newborn);
if (clasp == &CallableObjectClass) {
newborn->setSlot(JSSLOT_CALLABLE_CALL, GetCall(proxy));

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

@ -151,6 +151,7 @@ enum RegExpExecType
RegExpTest
};
class AutoStringRooter;
class ExecuteArgsGuard;
class InvokeFrameGuard;
class InvokeArgsGuard;
@ -224,9 +225,6 @@ struct EmptyShape;
class ShapeKindArray;
class Bindings;
struct StackBaseShape;
struct StackShape;
class MultiDeclRange;
class ParseMapPool;
class DefnOrHeader;
@ -279,69 +277,6 @@ struct TypeCompartment;
} /* namespace types */
enum ThingRootKind
{
THING_ROOT_OBJECT,
THING_ROOT_SHAPE,
THING_ROOT_BASE_SHAPE,
THING_ROOT_TYPE_OBJECT,
THING_ROOT_STRING,
THING_ROOT_SCRIPT,
THING_ROOT_ID,
THING_ROOT_VALUE,
THING_ROOT_LIMIT
};
template <typename T> class Root;
template <typename T> class RootedVar;
/*
* Reference to a stack location rooted for GC. See "Moving GC Stack Rooting"
* comment in jscntxt.h.
*/
template <typename T>
class Handle
{
public:
// Copy handles of different types, with implicit coercion.
template <typename S> Handle(Handle<S> handle) {
testAssign<S>();
ptr = reinterpret_cast<const T *>(handle.address());
}
// Get a handle from a rooted stack location, with implicit coercion.
template <typename S> inline Handle(const Root<S> &root);
template <typename S> inline Handle(const RootedVar<S> &root);
const T *address() { return ptr; }
operator T () { return value(); }
T operator ->() { return value(); }
private:
const T *ptr;
T value() { return *ptr; }
template <typename S>
void testAssign() {
#ifdef DEBUG
T a;
S b;
a = b;
#endif
}
};
typedef Handle<JSObject*> HandleObject;
typedef Handle<JSFunction*> HandleFunction;
typedef Handle<Shape*> HandleShape;
typedef Handle<BaseShape*> HandleBaseShape;
typedef Handle<types::TypeObject*> HandleTypeObject;
typedef Handle<JSString*> HandleString;
typedef Handle<JSAtom*> HandleAtom;
typedef Handle<jsid> HandleId;
typedef Handle<Value> HandleValue;
} /* namespace js */
namespace JSC {

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

@ -3261,10 +3261,7 @@ JS_BEGIN_EXTERN_C
JS_PUBLIC_API(JSObject *)
JS_InitReflect(JSContext *cx, JSObject *obj)
{
RootObject root(cx, &obj);
RootedVarObject Reflect(cx);
Reflect = NewObjectWithClassProto(cx, &ObjectClass, NULL, obj);
JSObject *Reflect = NewObjectWithClassProto(cx, &ObjectClass, NULL, obj);
if (!Reflect || !Reflect->setSingletonType(cx))
return NULL;

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

@ -110,16 +110,14 @@ Shape::makeOwnBaseShape(JSContext *cx)
{
JS_ASSERT(!base()->isOwned());
RootedVarShape self(cx, this);
BaseShape *nbase = js_NewGCBaseShape(cx);
if (!nbase)
return false;
new (nbase) BaseShape(*self->base());
nbase->setOwned(self->base()->toUnowned());
new (nbase) BaseShape(*base());
nbase->setOwned(base()->toUnowned());
self->base_ = nbase;
this->base_ = nbase;
return true;
}
@ -149,22 +147,20 @@ Shape::hashify(JSContext *cx)
{
JS_ASSERT(!hasTable());
RootedVarShape self(cx, this);
if (!ensureOwnBaseShape(cx))
return false;
JSRuntime *rt = cx->runtime;
PropertyTable *table = rt->new_<PropertyTable>(self->entryCount());
PropertyTable *table = rt->new_<PropertyTable>(entryCount());
if (!table)
return false;
if (!table->init(rt, self)) {
if (!table->init(rt, this)) {
rt->free_(table);
return false;
}
self->base()->setTable(table);
base()->setTable(table);
return true;
}
@ -307,13 +303,16 @@ PropertyTable::grow(JSContext *cx)
}
Shape *
Shape::getChildBinding(JSContext *cx, const StackShape &child)
Shape::getChildBinding(JSContext *cx, const js::Shape &child, HeapPtrShape *lastBinding)
{
JS_ASSERT(!inDictionary());
JS_ASSERT(!child.inDictionary());
Shape *shape = JS_PROPERTY_TREE(cx).getChild(cx, this, numFixedSlots(), child);
Shape *shape = JS_PROPERTY_TREE(cx).getChild(cx, this, child);
if (shape) {
JS_ASSERT(shape->parent == this);
JS_ASSERT(this == *lastBinding);
*lastBinding = shape;
/*
* Update the number of fixed slots which bindings of this shape will
@ -342,29 +341,39 @@ Shape::getChildBinding(JSContext *cx, const StackShape &child)
return shape;
}
/* static */ Shape *
Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base, JSObject *proto, Shape *shape)
/* static */ bool
Shape::replaceLastProperty(JSContext *cx, const BaseShape &base, JSObject *proto, HeapPtrShape *lastp)
{
Shape *shape = *lastp;
JS_ASSERT(!shape->inDictionary());
if (!shape->parent) {
/* Treat as resetting the initial property of the shape hierarchy. */
AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
return EmptyShape::getInitialShape(cx, base.clasp, proto,
base.parent, kind,
base.flags & BaseShape::OBJECT_FLAG_MASK);
Shape *newShape =
EmptyShape::getInitialShape(cx, base.clasp, proto,
base.parent, kind,
base.flags & BaseShape::OBJECT_FLAG_MASK);
if (!newShape)
return false;
JS_ASSERT(newShape->numFixedSlots() == shape->numFixedSlots());
*lastp = newShape;
return true;
}
RootShape root(cx, &shape);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
BaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return false;
StackShape child(shape);
child.base = nbase;
Shape child(shape);
child.base_ = nbase;
return JS_PROPERTY_TREE(cx).getChild(cx, shape->parent, shape->numFixedSlots(), child);
Shape *newShape = JS_PROPERTY_TREE(cx).getChild(cx, shape->parent, child);
if (!newShape)
return false;
*lastp = newShape;
return true;
}
/*
@ -373,7 +382,7 @@ Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base, JSObject *
* or lastProp->parent.
*/
Shape *
JSObject::getChildProperty(JSContext *cx, Shape *parent, StackShape &child)
JSObject::getChildProperty(JSContext *cx, Shape *parent, Shape &child)
{
/*
* Shared properties have no slot, but slot_ will reflect that of parent.
@ -398,32 +407,70 @@ JSObject::getChildProperty(JSContext *cx, Shape *parent, StackShape &child)
Shape *shape;
RootedVarObject self(cx, this);
if (inDictionaryMode()) {
JS_ASSERT(parent == lastProperty());
RootStackShape childRoot(cx, &child);
shape = js_NewGCShape(cx);
if (!shape)
return NULL;
if (child.hasSlot() && child.slot() >= self->lastProperty()->base()->slotSpan()) {
if (!self->setSlotSpan(cx, child.slot() + 1))
if (child.hasSlot() && child.slot() >= lastProperty()->base()->slotSpan()) {
if (!setSlotSpan(cx, child.slot() + 1))
return NULL;
}
shape->initDictionaryShape(child, self->numFixedSlots(), &self->shape_);
shape->initDictionaryShape(child, &shape_);
} else {
shape = JS_PROPERTY_TREE(cx).getChild(cx, parent, self->numFixedSlots(), child);
shape = JS_PROPERTY_TREE(cx).getChild(cx, parent, child);
if (!shape)
return NULL;
//JS_ASSERT(shape->parent == parent);
//JS_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
if (!self->setLastProperty(cx, shape))
JS_ASSERT(shape->parent == parent);
JS_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
if (!setLastProperty(cx, shape))
return NULL;
}
return shape;
}
Shape *
Shape::newDictionaryList(JSContext *cx, HeapPtrShape *listp)
{
Shape *shape = *listp;
Shape *list = shape;
/*
* We temporarily create the dictionary shapes using a root located on the
* stack. This way, the GC doesn't see any intermediate state until we
* switch listp at the end.
*/
HeapPtrShape root(NULL);
HeapPtrShape *childp = &root;
while (shape) {
JS_ASSERT(!shape->inDictionary());
Shape *dprop = js_NewGCShape(cx);
if (!dprop) {
*listp = list;
return NULL;
}
dprop->initDictionaryShape(*shape, childp);
JS_ASSERT(!dprop->hasTable());
childp = &dprop->parent;
shape = shape->parent;
}
*listp = root;
root->listp = listp;
JS_ASSERT(root->inDictionary());
if (!root->hashify(cx)) {
*listp = list;
return NULL;
}
return root;
}
bool
JSObject::toDictionaryMode(JSContext *cx)
{
@ -434,48 +481,23 @@ JSObject::toDictionaryMode(JSContext *cx)
uint32_t span = slotSpan();
RootedVarObject self(cx, this);
/*
* Clone the shapes into a new dictionary list. Don't update the
* last property of this object until done, otherwise a GC
* triggered while creating the dictionary will get the wrong
* slot span for this object.
*/
RootedVarShape root(cx);
RootedVarShape dictionaryShape(cx);
RootedVarShape shape(cx);
shape = lastProperty();
while (shape) {
JS_ASSERT(!shape->inDictionary());
Shape *dprop = js_NewGCShape(cx);
if (!dprop)
return false;
HeapPtrShape *listp = dictionaryShape
? &dictionaryShape->parent
: (HeapPtrShape *) root.address();
StackShape child(shape);
dprop->initDictionaryShape(child, self->numFixedSlots(), listp);
JS_ASSERT(!dprop->hasTable());
dictionaryShape = dprop;
shape = shape->previous();
}
if (!root->hashify(cx))
HeapPtrShape last;
last.init(lastProperty());
if (!Shape::newDictionaryList(cx, &last))
return false;
JS_ASSERT((Shape **) root->listp == root.address());
root->listp = &self->shape_;
self->shape_ = root;
JS_ASSERT(last->listp == &last);
last->listp = &shape_;
shape_ = last;
JS_ASSERT(self->inDictionaryMode());
root->base()->setSlotSpan(span);
JS_ASSERT(lastProperty()->hasTable());
lastProperty()->base()->setSlotSpan(span);
return true;
}
@ -594,26 +616,21 @@ JSObject::addProperty(JSContext *cx, jsid id,
NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter);
Shape **spp = NULL;
if (inDictionaryMode())
spp = lastProperty()->table().search(id, true);
return addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid,
spp, allowDictionary);
/* Search for id with adding = true in order to claim its entry. */
Shape **spp = nativeSearch(cx, id, true);
JS_ASSERT(!SHAPE_FETCH(spp));
return addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid, spp, allowDictionary);
}
Shape *
JSObject::addPropertyInternal(JSContext *cx, jsid id,
PropertyOp getter, StrictPropertyOp setter,
uint32_t slot, uintN attrs,
uintN flags, intN shortid, Shape **spp,
bool allowDictionary)
uintN flags, intN shortid,
Shape **spp, bool allowDictionary)
{
JS_ASSERT_IF(!allowDictionary, !inDictionaryMode());
RootId idRoot(cx, &id);
RootedVarObject self(cx, this);
PropertyTable *table = NULL;
if (!inDictionaryMode()) {
bool stableSlot =
@ -625,47 +642,43 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id,
(!stableSlot || lastProperty()->entryCount() >= PropertyTree::MAX_HEIGHT)) {
if (!toDictionaryMode(cx))
return NULL;
spp = nativeSearch(cx, id, true);
table = &lastProperty()->table();
spp = table->search(id, true);
}
} else {
} else if (lastProperty()->hasTable()) {
table = &lastProperty()->table();
if (table->needsToGrow()) {
if (!table->grow(cx))
return NULL;
spp = table->search(id, true);
JS_ASSERT(!SHAPE_FETCH(spp));
}
}
JS_ASSERT(!!table == !!spp);
/* Find or create a property tree node labeled by our arguments. */
Shape *shape;
{
shape = self->lastProperty();
jsuint index;
bool indexed = js_IdIsIndex(id, &index);
UnownedBaseShape *nbase;
if (shape->base()->matchesGetterSetter(getter, setter) && !indexed) {
nbase = shape->base()->unowned();
if (lastProperty()->base()->matchesGetterSetter(getter, setter) && !indexed) {
nbase = lastProperty()->base()->unowned();
} else {
StackBaseShape base(shape->base());
base.updateGetterSetter(attrs, getter, setter);
if (indexed)
base.flags |= BaseShape::INDEXED;
uint32_t flags = lastProperty()->getObjectFlags()
| (indexed ? BaseShape::INDEXED : 0);
BaseShape base(getClass(), getParent(), flags, attrs, getter, setter);
nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return NULL;
}
StackShape child(nbase, id, slot, self->numFixedSlots(), attrs, flags, shortid);
shape = self->getChildProperty(cx, self->lastProperty(), child);
Shape child(nbase, id, slot, numFixedSlots(), attrs, flags, shortid);
shape = getChildProperty(cx, lastProperty(), child);
}
if (shape) {
JS_ASSERT(shape == self->lastProperty());
JS_ASSERT(shape == lastProperty());
if (table) {
/* Store the tree node pointer in the table entry for id. */
@ -677,11 +690,11 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id,
shape->parent->handoffTableTo(shape);
}
CHECK_SHAPE_CONSISTENCY(self);
CHECK_SHAPE_CONSISTENCY(this);
return shape;
}
CHECK_SHAPE_CONSISTENCY(self);
CHECK_SHAPE_CONSISTENCY(this);
return NULL;
}
@ -717,34 +730,28 @@ JSObject::putProperty(JSContext *cx, jsid id,
{
JS_ASSERT(!JSID_IS_VOID(id));
RootId idRoot(cx, &id);
NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter);
RootedVarObject self(cx, this);
/* Search for id in order to claim its entry if table has been allocated. */
Shape **spp;
Shape *shape = Shape::search(cx, lastProperty(), id, &spp, true);
Shape **spp = nativeSearch(cx, id, true);
Shape *shape = SHAPE_FETCH(spp);
if (!shape) {
/*
* You can't add properties to a non-extensible object, but you can change
* attributes of properties in such objects.
*/
if (!self->isExtensible()) {
self->reportNotExtensible(cx);
if (!isExtensible()) {
reportNotExtensible(cx);
return NULL;
}
return self->addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid, spp, true);
return addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid, spp, true);
}
/* Property exists: search must have returned a valid *spp. */
JS_ASSERT_IF(spp, !SHAPE_IS_REMOVED(*spp));
JS_ASSERT(!SHAPE_IS_REMOVED(*spp));
RootShape shapeRoot(cx, &shape);
if (!CheckCanChangeAttrs(cx, self, shape, &attrs))
if (!CheckCanChangeAttrs(cx, this, shape, &attrs))
return NULL;
/*
@ -757,14 +764,13 @@ JSObject::putProperty(JSContext *cx, jsid id,
if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && hadSlot)
slot = oldSlot;
RootedVar<UnownedBaseShape*> nbase(cx);
UnownedBaseShape *nbase;
{
jsuint index;
bool indexed = js_IdIsIndex(id, &index);
StackBaseShape base(self->lastProperty()->base());
base.updateGetterSetter(attrs, getter, setter);
if (indexed)
base.flags |= BaseShape::INDEXED;
uint32_t flags = lastProperty()->getObjectFlags()
| (indexed ? BaseShape::INDEXED : 0);
BaseShape base(getClass(), getParent(), flags, attrs, getter, setter);
nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return NULL;
@ -782,10 +788,10 @@ JSObject::putProperty(JSContext *cx, jsid id,
* The shape tree is shared immutable, and we can't removeProperty and then
* addPropertyInternal because a failure under add would lose data.
*/
if (shape != self->lastProperty() && !self->inDictionaryMode()) {
if (!self->toDictionaryMode(cx))
if (shape != lastProperty() && !inDictionaryMode()) {
if (!toDictionaryMode(cx))
return NULL;
spp = self->lastProperty()->table().search(shape->propid(), false);
spp = nativeSearch(cx, shape->propid());
shape = SHAPE_FETCH(spp);
}
@ -801,20 +807,20 @@ JSObject::putProperty(JSContext *cx, jsid id,
* This is more than an optimization: it is required to preserve for-in
* enumeration order (see bug 601399).
*/
if (self->inDictionaryMode()) {
bool updateLast = (shape == self->lastProperty());
if (!self->generateOwnShape(cx))
if (inDictionaryMode()) {
bool updateLast = (shape == lastProperty());
if (!generateOwnShape(cx))
return NULL;
if (updateLast)
shape = self->lastProperty();
shape = lastProperty();
/* FIXME bug 593129 -- slot allocation and JSObject *this must move out of here! */
if (slot == SHAPE_INVALID_SLOT && !(attrs & JSPROP_SHARED)) {
if (!self->allocSlot(cx, &slot))
if (!allocSlot(cx, &slot))
return NULL;
}
if (shape == self->lastProperty())
if (shape == lastProperty())
shape->base()->adoptUnowned(nbase);
else
shape->base_ = nbase;
@ -833,20 +839,20 @@ JSObject::putProperty(JSContext *cx, jsid id,
* If any shape in the tree has a property hashtable, it is shared and
* immutable too, therefore we must not update *spp.
*/
StackBaseShape base(self->lastProperty()->base());
base.updateGetterSetter(attrs, getter, setter);
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
attrs, getter, setter);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return NULL;
JS_ASSERT(shape == self->lastProperty());
JS_ASSERT(shape == lastProperty());
/* Find or create a property tree node labeled by our arguments. */
StackShape child(nbase, id, slot, self->numFixedSlots(), attrs, flags, shortid);
Shape *newShape = self->getChildProperty(cx, shape->parent, child);
Shape child(nbase, id, slot, numFixedSlots(), attrs, flags, shortid);
Shape *newShape = getChildProperty(cx, shape->parent, child);
if (!newShape) {
CHECK_SHAPE_CONSISTENCY(self);
CHECK_SHAPE_CONSISTENCY(this);
return NULL;
}
@ -860,12 +866,12 @@ JSObject::putProperty(JSContext *cx, jsid id,
* property (shape here) has a slotSpan that does not cover it.
*/
if (hadSlot && !shape->hasSlot()) {
if (oldSlot < self->slotSpan())
self->freeSlot(cx, oldSlot);
if (oldSlot < slotSpan())
freeSlot(cx, oldSlot);
JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
}
CHECK_SHAPE_CONSISTENCY(self);
CHECK_SHAPE_CONSISTENCY(this);
return shape;
}
@ -916,13 +922,8 @@ JSObject::changeProperty(JSContext *cx, Shape *shape, uintN attrs, uintN mask,
bool
JSObject::removeProperty(JSContext *cx, jsid id)
{
RootedVarObject self(cx, this);
RootId idRoot(cx, &id);
RootedVarShape shape(cx);
Shape **spp;
shape = Shape::search(cx, lastProperty(), id, &spp);
Shape **spp = nativeSearch(cx, id);
Shape *shape = SHAPE_FETCH(spp);
if (!shape)
return true;
@ -930,10 +931,10 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* If shape is not the last property added, or the last property cannot
* be removed, switch to dictionary mode.
*/
if (!self->inDictionaryMode() && (shape != self->lastProperty() || !self->canRemoveLastProperty())) {
if (!self->toDictionaryMode(cx))
if (!inDictionaryMode() && (shape != lastProperty() || !canRemoveLastProperty())) {
if (!toDictionaryMode(cx))
return false;
spp = self->lastProperty()->table().search(shape->propid(), false);
spp = nativeSearch(cx, shape->propid());
shape = SHAPE_FETCH(spp);
}
@ -945,7 +946,7 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* the object or table, so the remaining removal is infallible.
*/
Shape *spare = NULL;
if (self->inDictionaryMode()) {
if (inDictionaryMode()) {
spare = js_NewGCShape(cx);
if (!spare)
return false;
@ -958,8 +959,8 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* object's state.
*/
Shape *previous = lastProperty()->parent;
StackBaseShape base(lastProperty()->base());
base.updateGetterSetter(previous->attrs, previous->getter(), previous->setter());
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
previous->attrs, previous->getter(), previous->setter());
BaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return false;
@ -969,7 +970,7 @@ JSObject::removeProperty(JSContext *cx, jsid id)
/* If shape has a slot, free its slot number. */
if (shape->hasSlot()) {
self->freeSlot(cx, shape->slot());
freeSlot(cx, shape->slot());
JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
}
@ -978,8 +979,8 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* doubly linked list, hashed by lastProp->table. So we can edit the list
* and hash in place.
*/
if (self->inDictionaryMode()) {
PropertyTable &table = self->lastProperty()->table();
if (inDictionaryMode()) {
PropertyTable &table = lastProperty()->table();
if (SHAPE_HAD_COLLISION(*spp)) {
*spp = SHAPE_REMOVED;
@ -995,21 +996,21 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* checks not to alter significantly the complexity of the
* delete in debug builds, see bug 534493.
*/
const Shape *aprop = self->lastProperty();
const Shape *aprop = lastProperty();
for (int n = 50; --n >= 0 && aprop->parent; aprop = aprop->parent)
JS_ASSERT_IF(aprop != shape, self->nativeContains(cx, *aprop));
JS_ASSERT_IF(aprop != shape, nativeContains(cx, *aprop));
#endif
}
/* Remove shape from its non-circular doubly linked list. */
Shape *oldLastProp = self->lastProperty();
shape->removeFromDictionary(self);
Shape *oldLastProp = lastProperty();
shape->removeFromDictionary(this);
/* Hand off table from the old to new last property. */
oldLastProp->handoffTableTo(self->lastProperty());
oldLastProp->handoffTableTo(lastProperty());
/* Generate a new shape for the object, infallibly. */
JS_ALWAYS_TRUE(self->generateOwnShape(cx, spare));
JS_ALWAYS_TRUE(generateOwnShape(cx, spare));
/* Consider shrinking table if its load factor is <= .25. */
uint32_t size = table.capacity();
@ -1022,11 +1023,11 @@ JSObject::removeProperty(JSContext *cx, jsid id)
* lazily make via a later hashify the exact table for the new property
* lineage.
*/
JS_ASSERT(shape == self->lastProperty());
self->removeLastProperty(cx);
JS_ASSERT(shape == lastProperty());
removeLastProperty(cx);
}
CHECK_SHAPE_CONSISTENCY(self);
CHECK_SHAPE_CONSISTENCY(this);
return true;
}
@ -1069,8 +1070,6 @@ JSObject::rollbackProperties(JSContext *cx, uint32_t slotSpan)
bool
JSObject::generateOwnShape(JSContext *cx, Shape *newShape)
{
RootedVarObject self(cx, this);
if (!inDictionaryMode() && !toDictionaryMode(cx))
return false;
@ -1078,21 +1077,17 @@ JSObject::generateOwnShape(JSContext *cx, Shape *newShape)
newShape = js_NewGCShape(cx);
if (!newShape)
return false;
new (newShape) Shape(self->lastProperty()->base()->unowned(), 0);
new (newShape) Shape(lastProperty()->base()->unowned(), 0);
}
PropertyTable &table = self->lastProperty()->table();
Shape **spp = self->lastProperty()->isEmptyShape()
? NULL
: table.search(self->lastProperty()->maybePropid(), false);
PropertyTable &table = lastProperty()->table();
Shape **spp = lastProperty()->isEmptyShape() ? NULL : table.search(lastProperty()->maybePropid(), false);
Shape *oldShape = self->lastProperty();
StackShape nshape(self->lastProperty());
newShape->initDictionaryShape(nshape, self->numFixedSlots(), &self->shape_);
Shape *oldShape = lastProperty();
newShape->initDictionaryShape(*oldShape, &shape_);
JS_ASSERT(newShape->parent == oldShape);
oldShape->removeFromDictionary(self);
oldShape->removeFromDictionary(this);
oldShape->handoffTableTo(newShape);
@ -1158,8 +1153,8 @@ JSObject::setParent(JSContext *cx, JSObject *parent)
return false;
if (inDictionaryMode()) {
StackBaseShape base(lastProperty());
base.parent = parent;
BaseShape base(*lastProperty()->base()->unowned());
base.setObjectParent(parent);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return false;
@ -1168,24 +1163,19 @@ JSObject::setParent(JSContext *cx, JSObject *parent)
return true;
}
Shape *newShape = Shape::setObjectParent(cx, parent, getProto(), shape_);
if (!newShape)
return false;
shape_ = newShape;
return true;
return Shape::setObjectParent(cx, parent, getProto(), &shape_);
}
/* static */ Shape *
Shape::setObjectParent(JSContext *cx, JSObject *parent, JSObject *proto, Shape *last)
/* static */ bool
Shape::setObjectParent(JSContext *cx, JSObject *parent, JSObject *proto, HeapPtrShape *listp)
{
if (last->getObjectParent() == parent)
return last;
if ((*listp)->getObjectParent() == parent)
return true;
StackBaseShape base(last);
base.parent = parent;
BaseShape base(*(*listp)->base()->unowned());
base.setObjectParent(parent);
return replaceLastProperty(cx, base, proto, last);
return replaceLastProperty(cx, base, proto, listp);
}
bool
@ -1193,8 +1183,6 @@ JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props)
{
JS_ASSERT(isExtensible());
RootedVarObject self(cx, this);
if (props) {
if (js::FixOp fix = getOps()->fix) {
bool success;
@ -1210,7 +1198,7 @@ JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props)
}
}
return self->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
return setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
}
bool
@ -1221,82 +1209,64 @@ JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateSha
if (lastProperty()->getObjectFlags() & flag)
return true;
RootedVarObject self(cx, this);
if (inDictionaryMode()) {
if (generateShape == GENERATE_SHAPE && !generateOwnShape(cx))
return false;
StackBaseShape base(self->lastProperty());
base.flags |= flag;
BaseShape base(*lastProperty()->base()->unowned());
base.setObjectFlag(flag);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return false;
self->lastProperty()->base()->adoptUnowned(nbase);
lastProperty()->base()->adoptUnowned(nbase);
return true;
}
Shape *newShape = Shape::setObjectFlag(cx, flag, getProto(), lastProperty());
if (!newShape)
return false;
self->shape_ = newShape;
return true;
return Shape::setObjectFlag(cx, flag, getProto(), &shape_);
}
/* static */ Shape *
Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, JSObject *proto, Shape *last)
/* static */ bool
Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, JSObject *proto, HeapPtrShape *listp)
{
if (last->getObjectFlags() & flag)
return last;
if ((*listp)->getObjectFlags() & flag)
return true;
StackBaseShape base(last);
BaseShape base(*(*listp)->base()->unowned());
base.flags |= flag;
return replaceLastProperty(cx, base, proto, last);
return replaceLastProperty(cx, base, proto, listp);
}
/* static */ inline HashNumber
StackBaseShape::hash(const StackBaseShape *base)
BaseShapeEntry::hash(const js::BaseShape *base)
{
JS_ASSERT(!base->isOwned());
JSDHashNumber hash = base->flags;
hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsuword(base->clasp) >> 3);
hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsuword(base->parent) >> 3);
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(base->rawGetter);
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(base->rawSetter);
hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsuword(base->parent.get()) >> 3);
if (base->rawGetter)
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(base->rawGetter);
if (base->rawSetter)
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(base->rawSetter);
return hash;
}
/* static */ inline bool
StackBaseShape::match(UnownedBaseShape *key, const StackBaseShape *lookup)
BaseShapeEntry::match(UnownedBaseShape *key, const BaseShape *lookup)
{
JS_ASSERT(!lookup->isOwned());
return key->flags == lookup->flags
&& key->clasp == lookup->clasp
&& key->parent == lookup->parent
&& (void *) key->rawGetter == lookup->rawGetter
&& (void *) key->rawSetter == lookup->rawSetter;
&& key->getterObj == lookup->getterObj
&& key->setterObj == lookup->setterObj;
}
/* Root for stack allocated base shapes. */
class RootStackBaseShape
{
Root<const JSObject*> parentRoot;
Maybe<RootObject> getterRoot;
Maybe<RootObject> setterRoot;
public:
RootStackBaseShape(JSContext *cx, const StackBaseShape *base)
: parentRoot(cx, &base->parent)
{
if (base->flags & BaseShape::HAS_GETTER_OBJECT)
getterRoot.construct(cx, (JSObject **) &base->rawGetter);
if (base->flags & BaseShape::HAS_SETTER_OBJECT)
setterRoot.construct(cx, (JSObject **) &base->rawSetter);
}
};
/* static */ UnownedBaseShape *
BaseShape::getUnowned(JSContext *cx, const StackBaseShape &base)
BaseShape::getUnowned(JSContext *cx, const BaseShape &base)
{
BaseShapeSet &table = cx->compartment->baseShapes;
@ -1308,8 +1278,6 @@ BaseShape::getUnowned(JSContext *cx, const StackBaseShape &base)
if (p)
return *p;
RootStackBaseShape root(cx, &base);
BaseShape *nbase_ = js_NewGCBaseShape(cx);
if (!nbase_)
return NULL;
@ -1344,16 +1312,17 @@ BaseShape::finalize(JSContext *cx, bool background)
}
}
/* static */ Shape *
Shape::setExtensibleParents(JSContext *cx, Shape *shape)
/* static */ bool
Shape::setExtensibleParents(JSContext *cx, HeapPtrShape *listp)
{
Shape *shape = *listp;
JS_ASSERT(!shape->inDictionary());
StackBaseShape base(shape);
BaseShape base(*shape->base()->unowned());
base.flags |= BaseShape::EXTENSIBLE_PARENTS;
/* This is only used for Block and Call objects, which have a NULL proto. */
return replaceLastProperty(cx, base, NULL, shape);
return replaceLastProperty(cx, base, NULL, listp);
}
bool
@ -1361,36 +1330,17 @@ Bindings::setExtensibleParents(JSContext *cx)
{
if (!ensureShape(cx))
return false;
Shape *newShape = Shape::setExtensibleParents(cx, lastBinding);
if (!newShape)
return false;
lastBinding = newShape;
return true;
return Shape::setExtensibleParents(cx, &lastBinding);
}
bool
Bindings::setParent(JSContext *cx, JSObject *obj)
{
/*
* This may be invoked on GC heap allocated bindings, in which case this
* is pointing to an internal value of a JSScript that can't itself be
* relocated. The script itself will be rooted, and will not be moved, so
* mark the stack value as non-relocatable for the stack root analysis.
*/
Bindings *self = this;
CheckRoot root(cx, &self);
RootObject rootObj(cx, &obj);
if (!ensureShape(cx))
return false;
/* This is only used for Block objects, which have a NULL proto. */
Shape *newShape = Shape::setObjectParent(cx, obj, NULL, self->lastBinding);
if (!newShape)
return false;
self->lastBinding = newShape;
return true;
return Shape::setObjectParent(cx, obj, NULL, &lastBinding);
}
/* static */ inline HashNumber
@ -1429,10 +1379,8 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, JSObject *proto, JSObje
if (p)
return p->shape;
RootedVar<UnownedBaseShape*> nbase(cx);
StackBaseShape base(clasp, parent, objectFlags);
nbase = BaseShape::getUnowned(cx, base);
BaseShape base(clasp, parent, objectFlags);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return NULL;

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

@ -345,8 +345,7 @@ class BaseShape : public js::gc::Cell
{
public:
friend struct Shape;
friend struct StackBaseShape;
friend struct StackShape;
friend struct BaseShapeEntry;
enum Flag {
/* Owned by the referring shape. */
@ -408,10 +407,6 @@ class BaseShape : public js::gc::Cell
inline BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags);
inline BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags,
uint8_t attrs, PropertyOp rawGetter, StrictPropertyOp rawSetter);
inline BaseShape(const StackBaseShape &base);
/* Not defined: BaseShapes must not be stack allocated. */
~BaseShape();
bool isOwned() const { return !!(flags & OWNED_SHAPE); }
@ -421,7 +416,10 @@ class BaseShape : public js::gc::Cell
inline void adoptUnowned(UnownedBaseShape *other);
inline void setOwned(UnownedBaseShape *unowned);
JSObject *getObjectParent() const { return parent; }
inline void setObjectParent(JSObject *obj);
JSObject *getObjectParent() { return parent; }
void setObjectFlag(Flag flag) { JS_ASSERT(!(flag & ~OBJECT_FLAG_MASK)); flags |= flag; }
uint32_t getObjectFlags() const { return flags & OBJECT_FLAG_MASK; }
bool hasGetterObject() const { return !!(flags & HAS_GETTER_OBJECT); }
@ -438,7 +436,7 @@ class BaseShape : public js::gc::Cell
void setSlotSpan(uint32_t slotSpan) { JS_ASSERT(isOwned()); slotSpan_ = slotSpan; }
/* Lookup base shapes from the compartment's baseShapes table. */
static UnownedBaseShape *getUnowned(JSContext *cx, const StackBaseShape &base);
static UnownedBaseShape *getUnowned(JSContext *cx, const BaseShape &base);
/* Get the canonical base shape. */
inline UnownedBaseShape *unowned();
@ -461,8 +459,6 @@ class BaseShape : public js::gc::Cell
static inline void writeBarrierPost(BaseShape *shape, void *addr);
static inline void readBarrier(BaseShape *shape);
static inline ThingRootKind rootKind() { return THING_ROOT_BASE_SHAPE; }
private:
static void staticAsserts() {
JS_STATIC_ASSERT(offsetof(BaseShape, clasp) == offsetof(js::shadow::BaseShape, clasp));
@ -490,45 +486,14 @@ BaseShape::baseUnowned()
}
/* Entries for the per-compartment baseShapes set of unowned base shapes. */
struct StackBaseShape
struct BaseShapeEntry
{
typedef const StackBaseShape *Lookup;
typedef const BaseShape *Lookup;
uint32_t flags;
Class *clasp;
JSObject *parent;
PropertyOp rawGetter;
StrictPropertyOp rawSetter;
StackBaseShape(BaseShape *base)
: flags(base->flags & BaseShape::OBJECT_FLAG_MASK),
clasp(base->clasp),
parent(base->parent),
rawGetter(NULL),
rawSetter(NULL)
{}
StackBaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags)
: flags(objectFlags),
clasp(clasp),
parent(parent),
rawGetter(NULL),
rawSetter(NULL)
{}
inline StackBaseShape(Shape *shape);
inline void updateGetterSetter(uint8_t attrs,
PropertyOp rawGetter,
StrictPropertyOp rawSetter);
static inline HashNumber hash(const StackBaseShape *lookup);
static inline bool match(UnownedBaseShape *key, const StackBaseShape *lookup);
static inline HashNumber hash(const BaseShape *base);
static inline bool match(UnownedBaseShape *key, const BaseShape *lookup);
};
typedef HashSet<ReadBarriered<UnownedBaseShape>,
StackBaseShape,
SystemAllocPolicy> BaseShapeSet;
typedef HashSet<ReadBarriered<UnownedBaseShape>, BaseShapeEntry, SystemAllocPolicy> BaseShapeSet;
struct Shape : public js::gc::Cell
{
@ -536,8 +501,6 @@ struct Shape : public js::gc::Cell
friend struct ::JSFunction;
friend class js::PropertyTree;
friend class js::Bindings;
friend struct js::StackShape;
friend struct js::StackBaseShape;
friend bool IsShapeAboutToBeFinalized(JSContext *cx, const js::Shape *shape);
protected:
@ -586,20 +549,19 @@ struct Shape : public js::gc::Cell
else to obj->lastProp */
};
static inline Shape *search(JSContext *cx, Shape *start, jsid id,
Shape ***pspp, bool adding = false);
static inline Shape **search(JSContext *cx, HeapPtrShape *pstart, jsid id,
bool adding = false);
static js::Shape *newDictionaryList(JSContext *cx, HeapPtrShape *listp);
inline void removeFromDictionary(JSObject *obj);
inline void insertIntoDictionary(HeapPtrShape *dictp);
inline void initDictionaryShape(const StackShape &child, uint32_t nfixed,
HeapPtrShape *dictp);
inline void initDictionaryShape(const Shape &child, HeapPtrShape *dictp);
Shape *getChildBinding(JSContext *cx, const StackShape &child);
Shape *getChildBinding(JSContext *cx, const Shape &child, HeapPtrShape *lastBinding);
/* Replace the base shape of the last shape in a non-dictionary lineage with base. */
static Shape *replaceLastProperty(JSContext *cx, const StackBaseShape &base,
JSObject *proto, Shape *shape);
static bool replaceLastProperty(JSContext *cx, const BaseShape &base, JSObject *proto, HeapPtrShape *lastp);
bool hashify(JSContext *cx);
void handoffTableTo(Shape *newShape);
@ -641,7 +603,9 @@ struct Shape : public js::gc::Cell
class Range {
protected:
friend struct Shape;
const Shape *cursor;
const Shape *end;
public:
Range(const Shape *shape) : cursor(shape) { }
@ -659,14 +623,6 @@ struct Shape : public js::gc::Cell
JS_ASSERT(!empty());
cursor = cursor->parent;
}
class Root {
js::Root<const Shape*> cursorRoot;
public:
Root(JSContext *cx, Range *range)
: cursorRoot(cx, &range->cursor)
{}
};
};
Range all() const {
@ -676,8 +632,8 @@ struct Shape : public js::gc::Cell
Class *getObjectClass() const { return base()->clasp; }
JSObject *getObjectParent() const { return base()->parent; }
static Shape *setObjectParent(JSContext *cx, JSObject *obj, JSObject *proto, Shape *last);
static Shape *setObjectFlag(JSContext *cx, BaseShape::Flag flag, JSObject *proto, Shape *last);
static bool setObjectParent(JSContext *cx, JSObject *obj, JSObject *proto, HeapPtrShape *listp);
static bool setObjectFlag(JSContext *cx, BaseShape::Flag flag, JSObject *proto, HeapPtrShape *listp);
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
bool hasObjectFlag(BaseShape::Flag flag) const {
@ -701,8 +657,11 @@ struct Shape : public js::gc::Cell
UNUSED_BITS = 0x3C
};
Shape(UnownedBaseShape *base, jsid id, uint32_t slot, uint32_t nfixed, uintN attrs,
uintN flags, intN shortid);
/* Get a shape identical to this one, without parent/kids information. */
Shape(const StackShape &other, uint32_t nfixed);
Shape(const Shape *other);
/* Used by EmptyShape (see jsscopeinlines.h). */
Shape(UnownedBaseShape *base, uint32_t nfixed);
@ -710,9 +669,6 @@ struct Shape : public js::gc::Cell
/* Copy constructor disabled, to avoid misuse of the above form. */
Shape(const Shape &other);
/* Not defined: Shapes must not be stack allocated. */
~Shape();
/*
* Whether this shape has a valid slot value. This may be true even if
* !hasSlot() (see SlotInfo comment above), and may be false even if
@ -796,8 +752,8 @@ struct Shape : public js::gc::Cell
void update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8_t attrs);
inline bool matches(const Shape *other) const;
inline bool matches(const StackShape &other) const;
inline JSDHashNumber hash() const;
inline bool matches(const js::Shape *p) const;
inline bool matchesParamsAfterId(BaseShape *base,
uint32_t aslot, uintN aattrs, uintN aflags,
intN ashortid) const;
@ -824,7 +780,7 @@ struct Shape : public js::gc::Cell
void setSlot(uint32_t slot) {
JS_ASSERT(slot <= SHAPE_INVALID_SLOT);
slotInfo = slotInfo & ~Shape::SLOT_MASK;
slotInfo = slotInfo & ~SLOT_MASK;
slotInfo = slotInfo | slot;
}
@ -934,7 +890,7 @@ struct Shape : public js::gc::Cell
* Call or Block objects need unique shapes. If the flag is clear, then we
* can use lastBinding's shape.
*/
static Shape *setExtensibleParents(JSContext *cx, Shape *shape);
static bool setExtensibleParents(JSContext *cx, HeapPtrShape *listp);
bool extensibleParents() const { return !!(base()->flags & BaseShape::EXTENSIBLE_PARENTS); }
uint32_t entryCount() const {
@ -978,8 +934,6 @@ struct Shape : public js::gc::Cell
*/
static inline void readBarrier(const Shape *shape);
static inline ThingRootKind rootKind() { return THING_ROOT_SHAPE; }
/* For JIT usage */
static inline size_t offsetOfBase() { return offsetof(Shape, base_); }
@ -1046,73 +1000,8 @@ struct InitialShapeEntry
static inline HashNumber hash(const Lookup &lookup);
static inline bool match(const InitialShapeEntry &key, const Lookup &lookup);
};
typedef HashSet<InitialShapeEntry, InitialShapeEntry, SystemAllocPolicy> InitialShapeSet;
struct StackShape
{
UnownedBaseShape *base;
jsid propid;
uint32_t slot_;
uint8_t attrs;
uint8_t flags;
int16_t shortid;
StackShape(UnownedBaseShape *base, jsid propid, uint32_t slot,
uint32_t nfixed, uintN attrs, uintN flags, intN shortid)
: base(base),
propid(propid),
slot_(slot),
attrs(uint8_t(attrs)),
flags(uint8_t(flags)),
shortid(int16_t(shortid))
{
JS_ASSERT(base);
JS_ASSERT(!JSID_IS_VOID(propid));
JS_ASSERT(slot <= SHAPE_INVALID_SLOT);
}
StackShape(const Shape *shape)
: base(shape->base()->unowned()),
propid(shape->maybePropid()),
slot_(shape->slotInfo & Shape::SLOT_MASK),
attrs(shape->attrs),
flags(shape->flags),
shortid(shape->shortid_)
{}
bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; }
bool hasMissingSlot() const { return maybeSlot() == SHAPE_INVALID_SLOT; }
uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return slot_; }
uint32_t maybeSlot() const { return slot_; }
uint32_t slotSpan() const {
uint32_t free = JSSLOT_FREE(base->clasp);
return hasMissingSlot() ? free : (maybeSlot() + 1);
}
void setSlot(uint32_t slot) {
JS_ASSERT(slot <= SHAPE_INVALID_SLOT);
slot_ = slot;
}
inline JSDHashNumber hash() const;
};
/* Rooter for stack allocated shapes. */
class RootStackShape
{
Root<const UnownedBaseShape*> baseShapeRoot;
Root<const jsid> propidRoot;
public:
RootStackShape(JSContext *cx, const StackShape *shape)
: baseShapeRoot(cx, &shape->base),
propidRoot(cx, &shape->propid)
{}
};
} /* namespace js */
/* js::Shape pointer tag bit indicating a collision. */
@ -1136,30 +1025,27 @@ class RootStackShape
namespace js {
inline Shape *
Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
/*
* The search succeeds if it finds a Shape with the given id. There are two
* success cases:
* - If the Shape is the last in its shape lineage, we return |startp|, which
* is &obj->lastProp or something similar.
* - Otherwise, we return &shape->parent, where |shape| is the successor to the
* found Shape.
*
* There is one failure case: we return &emptyShape->parent, where
* |emptyShape| is the EmptyShape at the start of the shape lineage.
*/
JS_ALWAYS_INLINE Shape **
Shape::search(JSContext *cx, HeapPtrShape *pstart, jsid id, bool adding)
{
if (start->inDictionary()) {
*pspp = start->table().search(id, adding);
return SHAPE_FETCH(*pspp);
}
*pspp = NULL;
if (start->hasTable()) {
Shape **spp = start->table().search(id, adding);
return SHAPE_FETCH(spp);
}
Shape *start = *pstart;
if (start->hasTable())
return start->table().search(id, adding);
if (start->numLinearSearches() == LINEAR_SEARCHES_MAX) {
if (start->isBigEnoughForAPropertyTable()) {
RootShape startRoot(cx, &start);
RootId idRoot(cx, &id);
if (start->hashify(cx)) {
Shape **spp = start->table().search(id, adding);
return SHAPE_FETCH(spp);
}
}
if (start->isBigEnoughForAPropertyTable() && start->hashify(cx))
return start->table().search(id, adding);
/*
* No table built -- there weren't enough entries, or OOM occurred.
* Don't increment numLinearSearches, to keep hasTable() false.
@ -1169,12 +1055,20 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
start->incrementNumLinearSearches();
}
for (Shape *shape = start; shape; shape = shape->parent) {
/*
* Not enough searches done so far to justify hashing: search linearly
* from start.
*
* We don't use a Range here, or stop at null parent (the empty shape at
* the end). This avoids an extra load per iteration at the cost (if the
* search fails) of an extra load and id test at the end.
*/
HeapPtrShape *spp;
for (spp = pstart; js::Shape *shape = *spp; spp = &shape->parent) {
if (shape->maybePropid() == id)
return shape;
return spp->unsafeGet();
}
return NULL;
return spp->unsafeGet();
}
} // namespace js

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

@ -91,45 +91,16 @@ BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags,
}
}
inline
BaseShape::BaseShape(const StackBaseShape &base)
{
PodZero(this);
this->clasp = base.clasp;
this->parent = base.parent;
this->flags = base.flags;
this->rawGetter = base.rawGetter;
this->rawSetter = base.rawSetter;
}
inline bool
BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter) const
{
return rawGetter == this->rawGetter && rawSetter == this->rawSetter;
}
inline
StackBaseShape::StackBaseShape(Shape *shape)
: flags(shape->getObjectFlags()),
clasp(shape->getObjectClass()),
parent(shape->getObjectParent())
{
updateGetterSetter(shape->attrs, shape->getter(), shape->setter());
}
inline void
StackBaseShape::updateGetterSetter(uint8_t attrs,
PropertyOp rawGetter,
StrictPropertyOp rawSetter)
BaseShape::setObjectParent(JSObject *obj)
{
flags &= ~(BaseShape::HAS_GETTER_OBJECT | BaseShape::HAS_SETTER_OBJECT);
if ((attrs & JSPROP_GETTER) && rawGetter)
flags |= BaseShape::HAS_GETTER_OBJECT;
if ((attrs & JSPROP_SETTER) && rawSetter)
flags |= BaseShape::HAS_SETTER_OBJECT;
this->rawGetter = rawGetter;
this->rawSetter = rawSetter;
parent = obj;
}
inline void
@ -178,13 +149,31 @@ BaseShape::assertConsistency()
}
inline
Shape::Shape(const StackShape &other, uint32_t nfixed)
: base_(other.base),
propid_(other.propid),
slotInfo(other.maybeSlot() | (nfixed << FIXED_SLOTS_SHIFT)),
attrs(other.attrs),
flags(other.flags),
shortid_(other.shortid),
Shape::Shape(UnownedBaseShape *base, jsid propid, uint32_t slot, uint32_t nfixed,
uintN attrs, uintN flags, intN shortid)
: base_(base),
propid_(propid),
slotInfo(slot | (nfixed << FIXED_SLOTS_SHIFT)),
attrs(uint8_t(attrs)),
flags(uint8_t(flags)),
shortid_(int16_t(shortid)),
parent(NULL)
{
JS_ASSERT(base);
JS_ASSERT(!JSID_IS_VOID(propid));
JS_ASSERT_IF(isMethod(), !base->rawGetter);
JS_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
kids.setNull();
}
inline
Shape::Shape(const Shape *other)
: base_(other->base()->unowned()),
propid_(other->maybePropid()),
slotInfo(other->slotInfo & ~LINEAR_SEARCHES_MASK),
attrs(other->attrs),
flags(other->flags),
shortid_(other->maybeShortid()),
parent(NULL)
{
kids.setNull();
@ -205,16 +194,16 @@ Shape::Shape(UnownedBaseShape *base, uint32_t nfixed)
}
inline JSDHashNumber
StackShape::hash() const
Shape::hash() const
{
JSDHashNumber hash = jsuword(base);
JSDHashNumber hash = jsuword(base()->unowned());
/* Accumulate from least to most random so the low bits are most random. */
hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & Shape::PUBLIC_FLAGS);
hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS);
hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
hash = JS_ROTATE_LEFT32(hash, 4) ^ slot_;
hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid);
hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid_;
hash = JS_ROTATE_LEFT32(hash, 4) ^ maybeSlot();
hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid_.get());
return hash;
}
@ -226,13 +215,6 @@ Shape::matches(const js::Shape *other) const
other->flags, other->shortid_);
}
inline bool
Shape::matches(const StackShape &other) const
{
return propid_.get() == other.propid &&
matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, other.shortid);
}
inline bool
Shape::matchesParamsAfterId(BaseShape *base, uint32_t aslot,
uintN aattrs, uintN aflags, intN ashortid) const
@ -315,7 +297,7 @@ Shape::removeFromDictionary(JSObject *obj)
}
inline void
Shape::insertIntoDictionary(HeapPtrShape *dictp)
Shape::insertIntoDictionary(HeapPtr<js::Shape> *dictp)
{
/*
* Don't assert inDictionaryMode() here because we may be called from
@ -331,15 +313,18 @@ Shape::insertIntoDictionary(HeapPtrShape *dictp)
setParent(*dictp);
if (parent)
parent->listp = &parent;
listp = (HeapPtrShape *) dictp;
listp = dictp;
*dictp = this;
}
void
Shape::initDictionaryShape(const StackShape &child, uint32_t nfixed, HeapPtrShape *dictp)
Shape::initDictionaryShape(const Shape &child, HeapPtrShape *dictp)
{
new (this) Shape(child, nfixed);
this->flags |= IN_DICTIONARY;
UnownedBaseShape *base = child.base()->unowned();
new (this) Shape(base, child.maybePropid(),
child.maybeSlot(), child.numFixedSlots(), child.attrs,
child.flags | IN_DICTIONARY, child.maybeShortid());
this->listp = NULL;
insertIntoDictionary(dictp);

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

@ -90,8 +90,9 @@ Bindings::lookup(JSContext *cx, JSAtom *name, uintN *indexp) const
if (!lastBinding)
return NONE;
Shape **spp;
Shape *shape = Shape::search(cx, lastBinding, ATOM_TO_JSID(name), &spp);
Shape *shape =
SHAPE_FETCH(Shape::search(cx, const_cast<HeapPtrShape *>(&lastBinding),
ATOM_TO_JSID(name)));
if (!shape)
return NONE;
@ -165,21 +166,19 @@ Bindings::add(JSContext *cx, JSAtom *name, BindingKind kind)
id = ATOM_TO_JSID(name);
}
StackBaseShape base(&CallClass, NULL, BaseShape::VAROBJ);
base.updateGetterSetter(attrs, getter, setter);
BaseShape base(&CallClass, NULL, BaseShape::VAROBJ, attrs, getter, setter);
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return NULL;
StackShape child(nbase, id, slot, 0, attrs, Shape::HAS_SHORTID, *indexp);
Shape child(nbase, id, slot, 0, attrs, Shape::HAS_SHORTID, *indexp);
/* Shapes in bindings cannot be dictionaries. */
Shape *shape = lastBinding->getChildBinding(cx, child);
Shape *shape = lastBinding->getChildBinding(cx, child, &lastBinding);
if (!shape)
return false;
lastBinding = shape;
JS_ASSERT(lastBinding == shape);
++*indexp;
return true;
}

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

@ -48,7 +48,6 @@
#include "jsdbgapi.h"
#include "jsclist.h"
#include "jsinfer.h"
#include "jsscope.h"
#include "gc/Barrier.h"
@ -208,7 +207,7 @@ class Bindings {
inline bool ensureShape(JSContext *cx);
/* Returns the shape lineage generated for these bindings. */
inline Shape *lastShape() const;
inline js::Shape *lastShape() const;
/* See Scope::extensibleParents */
inline bool extensibleParents();
@ -313,14 +312,6 @@ class Bindings {
const js::Shape *lastUpvar() const;
void trace(JSTracer *trc);
/* Rooter for stack allocated Bindings. */
struct StackRoot {
RootShape root;
StackRoot(JSContext *cx, Bindings *bindings)
: root(cx, (Shape **) &bindings->lastBinding)
{}
};
};
} /* namespace js */
@ -829,8 +820,6 @@ struct JSScript : public js::gc::Cell {
static inline void writeBarrierPre(JSScript *script);
static inline void writeBarrierPost(JSScript *script, void *addr);
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_SCRIPT; }
};
/* If this fails, padding_ can be removed. */

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

@ -1623,15 +1623,15 @@ js::str_match(JSContext *cx, uintN argc, Value *vp)
if (!rep)
return false;
JSObject *array = NULL;
MatchArgType arg = &array;
AutoObjectRooter array(cx);
MatchArgType arg = array.addr();
RegExpStatics *res = cx->regExpStatics();
Value rval;
if (!DoMatch(cx, res, str, *rep, MatchCallback, arg, MATCH_ARGS, &rval))
return false;
if (rep->matcher().global())
vp->setObjectOrNull(array);
vp->setObjectOrNull(array.object());
else
*vp = rval;
return true;

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

@ -5575,6 +5575,7 @@ xml_attributes(JSContext *cx, uintN argc, jsval *vp)
if (!qn)
return JS_FALSE;
AutoObjectRooter tvr(cx, qn);
jsid id = OBJECT_TO_JSID(qn);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)

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

@ -255,15 +255,13 @@ namespace JS {
JSObject*
RegisterPerfMeasurement(JSContext *cx, JSObject *global)
{
js::RootedVarObject prototype(cx);
prototype = JS_InitClass(cx, global, 0 /* parent */,
&pm_class, pm_construct, 1,
pm_props, pm_fns, 0, 0);
JSObject *prototype = JS_InitClass(cx, global, 0 /* parent */,
&pm_class, pm_construct, 1,
pm_props, pm_fns, 0, 0);
if (!prototype)
return 0;
js::RootedVarObject ctor(cx);
ctor = JS_GetConstructor(cx, prototype);
JSObject *ctor = JS_GetConstructor(cx, prototype);
if (!ctor)
return 0;

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

@ -437,8 +437,6 @@ Process(JSContext *cx, JSObject *obj, const char *filename, bool forceTTY)
FILE *file;
uint32_t oldopts;
RootObject root(cx, &obj);
if (forceTTY || !filename || strcmp(filename, "-") == 0) {
file = stdin;
} else {
@ -2950,9 +2948,10 @@ NewSandbox(JSContext *cx, bool lazy)
return NULL;
}
if (!cx->compartment->wrap(cx, &obj))
AutoObjectRooter objroot(cx, obj);
if (!cx->compartment->wrap(cx, objroot.addr()))
return NULL;
return obj;
return objroot.object();
}
static JSBool
@ -4970,11 +4969,9 @@ DestroyContext(JSContext *cx, bool withGC)
static JSObject *
NewGlobalObject(JSContext *cx, CompartmentKind compartment)
{
RootedVarObject glob(cx);
glob = (compartment == NEW_COMPARTMENT)
? JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL)
: JS_NewGlobalObject(cx, &global_class);
JSObject *glob = (compartment == NEW_COMPARTMENT)
? JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL)
: JS_NewGlobalObject(cx, &global_class);
if (!glob)
return NULL;
@ -5017,7 +5014,7 @@ NewGlobalObject(JSContext *cx, CompartmentKind compartment)
return NULL;
}
if (compartment == NEW_COMPARTMENT && !JS_WrapObject(cx, glob.address()))
if (compartment == NEW_COMPARTMENT && !JS_WrapObject(cx, &glob))
return NULL;
return glob;
@ -5026,11 +5023,8 @@ NewGlobalObject(JSContext *cx, CompartmentKind compartment)
static bool
BindScriptArgs(JSContext *cx, JSObject *obj, OptionParser *op)
{
RootObject root(cx, &obj);
MultiStringRange msr = op->getMultiStringArg("scriptArgs");
RootedVarObject scriptArgs(cx);
scriptArgs = JS_NewArrayObject(cx, 0, NULL);
JSObject *scriptArgs = JS_NewArrayObject(cx, 0, NULL);
if (!scriptArgs)
return false;
@ -5059,8 +5053,6 @@ BindScriptArgs(JSContext *cx, JSObject *obj, OptionParser *op)
static int
ProcessArgs(JSContext *cx, JSObject *obj, OptionParser *op)
{
RootObject root(cx, &obj);
if (op->getBoolOption('a'))
JS_ToggleOptions(cx, JSOPTION_METHODJIT_ALWAYS);
@ -5142,8 +5134,7 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
}
RootedVarObject glob(cx);
glob = NewGlobalObject(cx, NEW_COMPARTMENT);
JSObject *glob = NewGlobalObject(cx, NEW_COMPARTMENT);
if (!glob)
return 1;

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

@ -57,9 +57,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
Bindings &bindings = script->bindings;
gc::AllocKind kind = gc::GetGCObjectKind(bindings.lastShape()->numFixedSlots() + 1);
RootedVarTypeObject type(cx);
type = cx->compartment->getEmptyType(cx);
js::types::TypeObject *type = cx->compartment->getEmptyType(cx);
if (!type)
return NULL;
@ -67,10 +65,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
if (!PreallocateObjectDynamicSlots(cx, bindings.lastShape(), &slots))
return NULL;
RootedVarShape shape(cx);
shape = bindings.lastShape();
JSObject *obj = JSObject::create(cx, kind, shape, type, slots);
JSObject *obj = JSObject::create(cx, kind, bindings.lastShape(), type, slots);
if (!obj)
return NULL;

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

@ -2636,8 +2636,7 @@ DebuggerFrame_getArguments(JSContext *cx, uintN argc, Value *vp)
JSObject *argsobj;
if (fp->hasArgs()) {
/* Create an arguments object. */
RootedVar<GlobalObject*> global(cx);
global = args.callee().getGlobal();
GlobalObject *global = args.callee().getGlobal();
JSObject *proto;
if (!js_GetClassPrototype(cx, global, JSProto_Array, &proto))
return false;
@ -3791,45 +3790,35 @@ static JSFunctionSpec DebuggerEnv_methods[] = {
extern JS_PUBLIC_API(JSBool)
JS_DefineDebuggerObject(JSContext *cx, JSObject *obj)
{
RootObject objRoot(cx, &obj);
RootedVarObject
objProto(cx),
debugCtor(cx),
debugProto(cx),
frameProto(cx),
scriptProto(cx),
objectProto(cx);
if (!js_GetClassPrototype(cx, obj, JSProto_Object, objProto.address()))
JSObject *objProto;
if (!js_GetClassPrototype(cx, obj, JSProto_Object, &objProto))
return false;
debugProto = js_InitClass(cx, objRoot,
objProto, &Debugger::jsclass, Debugger::construct,
1, Debugger::properties, Debugger::methods, NULL, NULL,
debugCtor.address());
JSObject *debugCtor;
JSObject *debugProto = js_InitClass(cx, obj, objProto, &Debugger::jsclass, Debugger::construct,
1, Debugger::properties, Debugger::methods, NULL, NULL,
&debugCtor);
if (!debugProto)
return false;
frameProto = js_InitClass(cx, debugCtor, objProto, &DebuggerFrame_class,
DebuggerFrame_construct, 0,
DebuggerFrame_properties, DebuggerFrame_methods,
NULL, NULL);
JSObject *frameProto = js_InitClass(cx, debugCtor, objProto, &DebuggerFrame_class,
DebuggerFrame_construct, 0,
DebuggerFrame_properties, DebuggerFrame_methods,
NULL, NULL);
if (!frameProto)
return false;
scriptProto = js_InitClass(cx, debugCtor, objProto, &DebuggerScript_class,
DebuggerScript_construct, 0,
DebuggerScript_properties, DebuggerScript_methods,
NULL, NULL);
JSObject *scriptProto = js_InitClass(cx, debugCtor, objProto, &DebuggerScript_class,
DebuggerScript_construct, 0,
DebuggerScript_properties, DebuggerScript_methods,
NULL, NULL);
if (!scriptProto)
return false;
objectProto = js_InitClass(cx, debugCtor, objProto, &DebuggerObject_class,
DebuggerObject_construct, 0,
DebuggerObject_properties, DebuggerObject_methods,
NULL, NULL);
JSObject *objectProto = js_InitClass(cx, debugCtor, objProto, &DebuggerObject_class,
DebuggerObject_construct, 0,
DebuggerObject_properties, DebuggerObject_methods,
NULL, NULL);
if (!objectProto)
return false;

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

@ -84,8 +84,6 @@ namespace js {
JSObject *
GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
{
RootedVar<GlobalObject*> self(cx, this);
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JS_ASSERT(isNative());
@ -98,15 +96,13 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
/* If cx has no global object, make this the global object. */
if (!cx->globalObject)
JS_SetGlobalObject(cx, self);
RootedVarObject objectProto(cx);
JS_SetGlobalObject(cx, this);
/*
* Create |Object.prototype| first, mirroring CreateBlankProto but for the
* prototype of the created object.
*/
objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self);
JSObject *objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, this);
if (!objectProto || !objectProto->setSingletonType(cx))
return NULL;
@ -119,20 +115,18 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
return NULL;
/* Create |Function.prototype| next so we can create other functions. */
RootedVarFunction functionProto(cx);
JSFunction *functionProto;
{
JSObject *functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self);
if (!functionProto_)
JSObject *proto = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, this);
if (!proto)
return NULL;
functionProto = functionProto_->toFunction();
/*
* Bizarrely, |Function.prototype| must be an interpreted function, so
* give it the guts to be one.
*/
JSObject *proto = js_NewFunction(cx, functionProto,
NULL, 0, JSFUN_INTERPRETED, self, NULL);
if (!proto)
functionProto = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, this, NULL);
if (!functionProto)
return NULL;
JS_ASSERT(proto == functionProto);
functionProto->flags |= JSFUN_PROTOTYPE;
@ -148,7 +142,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
functionProto->getType(cx)->interpretedFunction = functionProto;
script->setFunction(functionProto);
if (!functionProto->setSingletonType(cx))
if (!proto->setSingletonType(cx))
return NULL;
/*
@ -156,20 +150,22 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
* inference to have unknown properties, to simplify handling of e.g.
* CloneFunctionObject.
*/
if (!functionProto->setNewTypeUnknown(cx))
if (!proto->setNewTypeUnknown(cx))
return NULL;
}
/* Create the Object function now that we have a [[Prototype]] for it. */
RootedVarFunction objectCtor(cx);
jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
JSFunction *objectCtor;
{
JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, this);
if (!ctor)
return NULL;
objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self,
CLASS_ATOM(cx, Object));
objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, this,
JSID_TO_ATOM(objectId));
if (!objectCtor)
return NULL;
JS_ASSERT(ctor == objectCtor);
objectCtor->setConstructorClass(&ObjectClass);
}
@ -178,17 +174,18 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
* Install |Object| and |Object.prototype| for the benefit of subsequent
* code that looks for them.
*/
self->setObjectClassDetails(objectCtor, objectProto);
setObjectClassDetails(objectCtor, objectProto);
/* Create |Function| so it and |Function.prototype| can be installed. */
RootedVarFunction functionCtor(cx);
jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
JSFunction *functionCtor;
{
JSObject *ctor =
NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
NewObjectWithGivenProto(cx, &FunctionClass, functionProto, this);
if (!ctor)
return NULL;
functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
CLASS_ATOM(cx, Function));
functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, this,
JSID_TO_ATOM(functionId));
if (!functionCtor)
return NULL;
JS_ASSERT(ctor == functionCtor);
@ -200,7 +197,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
* Install |Function| and |Function.prototype| so that we can freely create
* functions and objects without special effort.
*/
self->setFunctionClassDetails(functionCtor, functionProto);
setFunctionClassDetails(functionCtor, functionProto);
/*
* The hard part's done: now go back and add all the properties these
@ -217,31 +214,28 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
}
/* Add the global Function and Object properties now. */
jsid objectId = ATOM_TO_JSID(CLASS_ATOM(cx, Object));
if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
if (!addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
return NULL;
jsid functionId = ATOM_TO_JSID(CLASS_ATOM(cx, Function));
if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
if (!addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
return NULL;
/* Heavy lifting done, but lingering tasks remain. */
/* ES5 15.1.2.1. */
jsid id = ATOM_TO_JSID(cx->runtime->atomState.evalAtom);
JSObject *evalobj = js_DefineFunction(cx, self, id, eval, 1, JSFUN_STUB_GSOPS);
JSObject *evalobj = js_DefineFunction(cx, this, id, eval, 1, JSFUN_STUB_GSOPS);
if (!evalobj)
return NULL;
self->setOriginalEval(evalobj);
setOriginalEval(evalobj);
/* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
RootedVarFunction throwTypeError(cx);
throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL);
JSFunction *throwTypeError = js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, this, NULL);
if (!throwTypeError)
return NULL;
AutoIdVector ids(cx);
if (!throwTypeError->preventExtensions(cx, &ids))
return NULL;
self->setThrowTypeError(throwTypeError);
setThrowTypeError(throwTypeError);
/*
* The global object should have |Object.prototype| as its [[Prototype]].
@ -251,7 +245,7 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
* [[Prototype]] before standard classes have been initialized. For now,
* only set the [[Prototype]] if it hasn't already been set.
*/
if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, objectProto))
if (shouldSplicePrototype(cx) && !splicePrototype(cx, objectProto))
return NULL;
/*
@ -267,24 +261,22 @@ GlobalObject::create(JSContext *cx, Class *clasp)
{
JS_ASSERT(clasp->flags & JSCLASS_IS_GLOBAL);
RootedVar<GlobalObject*> obj(cx);
JSObject *obj_ = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
if (!obj_)
JSObject *obj = NewObjectWithGivenProto(cx, clasp, NULL, NULL);
if (!obj || !obj->setSingletonType(cx))
return NULL;
obj = obj_->asGlobal();
if (!obj->setSingletonType(cx) || !obj->setVarObj(cx))
GlobalObject *globalObj = obj->asGlobal();
if (!globalObj->setVarObj(cx))
return NULL;
/* Construct a regexp statics object for this global object. */
JSObject *res = RegExpStatics::create(cx, obj);
JSObject *res = RegExpStatics::create(cx, globalObj);
if (!res)
return NULL;
obj->initSlot(REGEXP_STATICS, ObjectValue(*res));
obj->initFlags(0);
globalObj->initSlot(REGEXP_STATICS, ObjectValue(*res));
globalObj->initFlags(0);
return obj;
return globalObj;
}
bool
@ -379,10 +371,7 @@ JSFunction *
GlobalObject::createConstructor(JSContext *cx, Native ctor, Class *clasp, JSAtom *name,
uintN length, gc::AllocKind kind)
{
RootedVarObject self(cx, this);
JSFunction *fun = js_NewFunction(cx, NULL, ctor, length,
JSFUN_CONSTRUCTOR, self, name, kind);
JSFunction *fun = js_NewFunction(cx, NULL, ctor, length, JSFUN_CONSTRUCTOR, this, name, kind);
if (!fun)
return NULL;
@ -426,9 +415,6 @@ GlobalObject::createBlankPrototypeInheriting(JSContext *cx, Class *clasp, JSObje
bool
LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
{
RootObject ctorRoot(cx, &ctor);
RootObject protoRoot(cx, &proto);
return ctor->defineProperty(cx, cx->runtime->atomState.classPrototypeAtom,
ObjectValue(*proto), JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_PERMANENT | JSPROP_READONLY) &&
@ -439,8 +425,6 @@ LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto)
bool
DefinePropertiesAndBrand(JSContext *cx, JSObject *obj, JSPropertySpec *ps, JSFunctionSpec *fs)
{
RootObject root(cx, &obj);
if ((ps && !JS_DefineProperties(cx, obj, ps)) || (fs && !JS_DefineFunctions(cx, obj, fs)))
return false;
return true;

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

@ -215,94 +215,74 @@ class GlobalObject : public ::JSObject {
JSObject *createBlankPrototypeInheriting(JSContext *cx, js::Class *clasp, JSObject &proto);
JSObject *getOrCreateObjectPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!functionObjectClassesInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!initFunctionAndObjectClasses(cx))
return NULL;
}
return &self->getPrototype(JSProto_Object).toObject();
return &getPrototype(JSProto_Object).toObject();
}
JSObject *getOrCreateFunctionPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!functionObjectClassesInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!initFunctionAndObjectClasses(cx))
return NULL;
}
return &self->getPrototype(JSProto_Function).toObject();
return &getPrototype(JSProto_Function).toObject();
}
JSObject *getOrCreateArrayPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!arrayClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitArrayClass(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_Array).toObject();
return &getPrototype(JSProto_Array).toObject();
}
JSObject *getOrCreateBooleanPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!booleanClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitBooleanClass(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_Boolean).toObject();
return &getPrototype(JSProto_Boolean).toObject();
}
JSObject *getOrCreateNumberPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!numberClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitNumberClass(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_Number).toObject();
return &getPrototype(JSProto_Number).toObject();
}
JSObject *getOrCreateStringPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!stringClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitStringClass(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_String).toObject();
return &getPrototype(JSProto_String).toObject();
}
JSObject *getOrCreateRegExpPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!regexpClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitRegExpClass(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_RegExp).toObject();
return &getPrototype(JSProto_RegExp).toObject();
}
JSObject *getOrCreateArrayBufferPrototype(JSContext *cx) {
GlobalObject *self = this;
if (!arrayBufferClassInitialized()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitTypedArrayClasses(cx, this))
return NULL;
}
return &self->getPrototype(JSProto_ArrayBuffer).toObject();
return &getPrototype(JSProto_ArrayBuffer).toObject();
}
JSObject *getOrCreateGeneratorPrototype(JSContext *cx) {
GlobalObject *self = this;
Value v = getSlotRef(GENERATOR_PROTO);
if (!v.isObject()) {
Root<GlobalObject*> root(cx, &self);
if (!js_InitIteratorClasses(cx, this))
return NULL;
}
return &self->getSlot(GENERATOR_PROTO).toObject();
HeapValue &v = getSlotRef(GENERATOR_PROTO);
if (!v.isObject() && !js_InitIteratorClasses(cx, this))
return NULL;
return &v.toObject();
}
inline RegExpStatics *getRegExpStatics() const;

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

@ -422,8 +422,6 @@ class JSString : public js::gc::Cell
static inline void writeBarrierPre(JSString *str);
static inline void writeBarrierPost(JSString *str, void *addr);
static inline bool needWriteBarrierPre(JSCompartment *comp);
static inline js::ThingRootKind rootKind() { return js::THING_ROOT_STRING; }
};
class JSRope : public JSString