mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 816776 - Add debug-mode exact rooting assertions for Shape; r=sfink
--HG-- extra : rebase_source : fbd47f598964cbb03dcc782198c10164e09a26f2
This commit is contained in:
parent
cdfe65034b
commit
ea1ffaab45
@ -2075,7 +2075,7 @@ BindLet(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser)
|
||||
*/
|
||||
bool redeclared;
|
||||
RootedId id(cx, NameToId(name));
|
||||
Shape *shape = StaticBlockObject::addVar(cx, blockObj, id, blockCount, &redeclared);
|
||||
RootedShape shape(cx, StaticBlockObject::addVar(cx, blockObj, id, blockCount, &redeclared));
|
||||
if (!shape) {
|
||||
if (redeclared)
|
||||
ReportRedeclaration(cx, parser, pn, false, name);
|
||||
|
@ -123,7 +123,7 @@ frontend::LexicalLookup(ContextT *ct, HandleAtom atom, int *slotp, typename Cont
|
||||
continue;
|
||||
|
||||
StaticBlockObject &blockObj = *stmt->blockObj;
|
||||
Shape *shape = blockObj.nativeLookup(ct->sc->context, AtomToId(atom));
|
||||
UnrootedShape shape = blockObj.nativeLookup(ct->sc->context, AtomToId(atom));
|
||||
if (shape) {
|
||||
JS_ASSERT(shape->hasShortID());
|
||||
|
||||
|
@ -71,7 +71,7 @@ static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSScript *thing);
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, Shape *thing);
|
||||
PushMarkStack(GCMarker *gcmarker, UnrootedShape thing);
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker *gcmarker, JSString *thing);
|
||||
@ -84,7 +84,7 @@ namespace gc {
|
||||
|
||||
static void MarkChildren(JSTracer *trc, JSString *str);
|
||||
static void MarkChildren(JSTracer *trc, JSScript *script);
|
||||
static void MarkChildren(JSTracer *trc, Shape *shape);
|
||||
static void MarkChildren(JSTracer *trc, UnrootedShape shape);
|
||||
static void MarkChildren(JSTracer *trc, UnrootedBaseShape base);
|
||||
static void MarkChildren(JSTracer *trc, types::TypeObject *type);
|
||||
static void MarkChildren(JSTracer *trc, ion::IonCode *code);
|
||||
@ -292,12 +292,14 @@ Is##base##Marked(EncapsulatedPtr<type> *thingp)
|
||||
return IsMarked<type>(thingp->unsafeGet()); \
|
||||
} \
|
||||
\
|
||||
bool Is##base##AboutToBeFinalized(type **thingp) \
|
||||
bool \
|
||||
Is##base##AboutToBeFinalized(type **thingp) \
|
||||
{ \
|
||||
return IsAboutToBeFinalized<type>(thingp); \
|
||||
} \
|
||||
\
|
||||
bool Is##base##AboutToBeFinalized(EncapsulatedPtr<type> *thingp) \
|
||||
bool \
|
||||
Is##base##AboutToBeFinalized(EncapsulatedPtr<type> *thingp) \
|
||||
{ \
|
||||
return IsAboutToBeFinalized<type>(thingp->unsafeGet()); \
|
||||
}
|
||||
@ -731,10 +733,10 @@ PushMarkStack(GCMarker *gcmarker, JSScript *thing)
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker *gcmarker, Shape *shape);
|
||||
ScanShape(GCMarker *gcmarker, UnrootedShape shape);
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker *gcmarker, Shape *thing)
|
||||
PushMarkStack(GCMarker *gcmarker, UnrootedShape thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
|
||||
|
||||
@ -766,7 +768,7 @@ PushMarkStack(GCMarker *gcmarker, UnrootedBaseShape thing)
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker *gcmarker, Shape *shape)
|
||||
ScanShape(GCMarker *gcmarker, UnrootedShape shape)
|
||||
{
|
||||
restart:
|
||||
PushMarkStack(gcmarker, shape->base());
|
||||
@ -930,7 +932,7 @@ gc::MarkChildren(JSTracer *trc, JSScript *script)
|
||||
}
|
||||
|
||||
static void
|
||||
gc::MarkChildren(JSTracer *trc, Shape *shape)
|
||||
gc::MarkChildren(JSTracer *trc, UnrootedShape shape)
|
||||
{
|
||||
shape->markChildren(trc);
|
||||
}
|
||||
@ -990,7 +992,7 @@ MarkCycleCollectorChildren(JSTracer *trc, UnrootedBaseShape base, JSObject **pre
|
||||
* parent pointer will only be marked once.
|
||||
*/
|
||||
void
|
||||
gc::MarkCycleCollectorChildren(JSTracer *trc, Shape *shape)
|
||||
gc::MarkCycleCollectorChildren(JSTracer *trc, UnrootedShape shape)
|
||||
{
|
||||
JSObject *prevParent = NULL;
|
||||
do {
|
||||
@ -1021,7 +1023,7 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
|
||||
|
||||
if (type->newScript) {
|
||||
PushMarkStack(gcmarker, type->newScript->fun);
|
||||
PushMarkStack(gcmarker, type->newScript->shape);
|
||||
PushMarkStack(gcmarker, type->newScript->shape.get());
|
||||
}
|
||||
|
||||
if (type->interpretedFunction)
|
||||
@ -1356,7 +1358,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
||||
types::TypeObject *type = obj->typeFromGC();
|
||||
PushMarkStack(this, type);
|
||||
|
||||
Shape *shape = obj->lastProperty();
|
||||
UnrootedShape shape = obj->lastProperty();
|
||||
PushMarkStack(this, shape);
|
||||
|
||||
/* Call the trace hook if necessary. */
|
||||
|
@ -236,7 +236,7 @@ MarkChildren(JSTracer *trc, JSObject *obj);
|
||||
* JS_TraceShapeCycleCollectorChildren.
|
||||
*/
|
||||
void
|
||||
MarkCycleCollectorChildren(JSTracer *trc, Shape *shape);
|
||||
MarkCycleCollectorChildren(JSTracer *trc, UnrootedShape shape);
|
||||
|
||||
void
|
||||
PushArena(GCMarker *gcmarker, ArenaHeader *aheader);
|
||||
|
@ -279,8 +279,7 @@ class MutableHandle : public js::MutableHandleBase<T>
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline
|
||||
MutableHandle(js::Rooted<S> *root,
|
||||
inline MutableHandle(js::Rooted<S> *root,
|
||||
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
|
||||
|
||||
void set(T v) {
|
||||
@ -288,6 +287,9 @@ class MutableHandle : public js::MutableHandleBase<T>
|
||||
*ptr = v;
|
||||
}
|
||||
|
||||
template <typename S>
|
||||
inline void set(const js::Unrooted<S> &v);
|
||||
|
||||
/*
|
||||
* This may be called only if the location of the T is guaranteed
|
||||
* to be marked (for some reason other than being a Rooted),
|
||||
@ -478,6 +480,13 @@ class Unrooted
|
||||
ptr_ = other;
|
||||
return *this;
|
||||
}
|
||||
Unrooted &operator=(Unrooted other) {
|
||||
JS_ASSERT(other.ptr_ != UninitializedTag());
|
||||
if (ptr_ == UninitializedTag())
|
||||
EnterAssertNoGCScope();
|
||||
ptr_ = other.ptr_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator T() const { return (ptr_ == UninitializedTag()) ? NULL : ptr_; }
|
||||
T *operator&() { return &ptr_; }
|
||||
@ -859,6 +868,13 @@ MutableHandle<T>::MutableHandle(js::Rooted<S> *root,
|
||||
ptr = root->address();
|
||||
}
|
||||
|
||||
template <typename T> template <typename S>
|
||||
inline void MutableHandle<T>::set(const js::Unrooted<S> &v)
|
||||
{
|
||||
JS_ASSERT(!js::RootMethods<T>::poisoned(v));
|
||||
*ptr = static_cast<S>(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* The scoped guard object AutoAssertNoGC forces the GC to assert if a GC is
|
||||
* attempted while the guard object is live. If you have a GC-unsafe operation
|
||||
|
@ -41,6 +41,7 @@ class CompilerRoot : public CompilerRootNode
|
||||
|
||||
public:
|
||||
operator T () const { return static_cast<T>(ptr); }
|
||||
operator Unrooted<T> () const { return static_cast<T>(ptr); }
|
||||
T operator ->() const { return static_cast<T>(ptr); }
|
||||
|
||||
private:
|
||||
@ -51,7 +52,9 @@ class CompilerRoot : public CompilerRootNode
|
||||
|
||||
typedef CompilerRoot<JSObject*> CompilerRootObject;
|
||||
typedef CompilerRoot<JSFunction*> CompilerRootFunction;
|
||||
typedef CompilerRoot<JSScript*> CompilerRootScript;
|
||||
typedef CompilerRoot<PropertyName*> CompilerRootPropertyName;
|
||||
typedef CompilerRoot<Shape*> CompilerRootShape;
|
||||
typedef CompilerRoot<Value> CompilerRootValue;
|
||||
|
||||
} // namespace ion
|
||||
|
@ -4854,6 +4854,8 @@ bool
|
||||
IonBuilder::pushTypeBarrier(MInstruction *ins, types::StackTypeSet *actual,
|
||||
types::StackTypeSet *observed)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
// If the instruction has no side effects, we'll resume the entire operation.
|
||||
// The actual type barrier will occur in the interpreter. If the
|
||||
// instruction is effectful, even if it has a singleton type, there
|
||||
@ -4971,7 +4973,7 @@ IonBuilder::jsop_getgname(HandlePropertyName name)
|
||||
|
||||
// For the fastest path, the property must be found, and it must be found
|
||||
// as a normal data property on exactly the global object.
|
||||
const js::Shape *shape = globalObj->nativeLookup(cx, id);
|
||||
RootedShape shape(cx, globalObj->nativeLookup(cx, id));
|
||||
if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
|
||||
return jsop_getname(name);
|
||||
|
||||
@ -5048,7 +5050,7 @@ IonBuilder::jsop_setgname(HandlePropertyName name)
|
||||
|
||||
// For the fastest path, the property must be found, and it must be found
|
||||
// as a normal data property on exactly the global object.
|
||||
const js::Shape *shape = globalObj->nativeLookup(cx, id);
|
||||
RootedShape shape(cx, globalObj->nativeLookup(cx, id));
|
||||
if (!shape || !shape->hasDefaultSetter() || !shape->writable() || !shape->hasSlot())
|
||||
return jsop_setprop(name);
|
||||
|
||||
@ -6145,7 +6147,7 @@ IonBuilder::invalidatedIdempotentCache()
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType)
|
||||
IonBuilder::loadSlot(MDefinition *obj, HandleShape shape, MIRType rvalType)
|
||||
{
|
||||
JS_ASSERT(shape->hasDefaultGetter());
|
||||
JS_ASSERT(shape->hasSlot());
|
||||
@ -6175,7 +6177,7 @@ IonBuilder::loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType)
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier)
|
||||
IonBuilder::storeSlot(MDefinition *obj, UnrootedShape shape, MDefinition *value, bool needsBarrier)
|
||||
{
|
||||
JS_ASSERT(shape->hasDefaultSetter());
|
||||
JS_ASSERT(shape->writable());
|
||||
@ -6400,13 +6402,14 @@ bool
|
||||
IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSet *barrier,
|
||||
TypeOracle::Unary unary, TypeOracle::UnaryTypes unaryTypes)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(*emitted == false);
|
||||
bool accessGetter = oracle->propertyReadAccessGetter(script(), pc);
|
||||
|
||||
if (unary.ival != MIRType_Object)
|
||||
return true;
|
||||
|
||||
Shape *objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing());
|
||||
RootedShape objShape(cx, mjit::GetPICSingleShape(cx, script(), pc, info().constructing()));
|
||||
if (!objShape || objShape->inDictionary()) {
|
||||
spew("GETPROP not monomorphic");
|
||||
return true;
|
||||
@ -6421,7 +6424,7 @@ IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSe
|
||||
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
|
||||
|
||||
spew("Inlining monomorphic GETPROP");
|
||||
Shape *shape = objShape->search(cx, id);
|
||||
RootedShape shape(cx, objShape->search(cx, id));
|
||||
JS_ASSERT(shape);
|
||||
|
||||
MIRType rvalType = unary.rval;
|
||||
@ -6561,7 +6564,7 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||
if (monitored) {
|
||||
ins = MCallSetProperty::New(obj, value, name, script()->strict);
|
||||
} else {
|
||||
Shape *objShape;
|
||||
UnrootedShape objShape;
|
||||
if ((objShape = mjit::GetPICSingleShape(cx, script(), pc, info().constructing())) &&
|
||||
!objShape->inDictionary())
|
||||
{
|
||||
@ -6571,7 +6574,7 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||
// on dictionary mode shapes that aren't lastProperty is invalid.
|
||||
obj = addShapeGuard(obj, objShape, Bailout_CachedShapeGuard);
|
||||
|
||||
Shape *shape = objShape->search(cx, NameToId(name));
|
||||
UnrootedShape shape = DropUnrooted(objShape)->search(cx, NameToId(name));
|
||||
JS_ASSERT(shape);
|
||||
|
||||
spew("Inlining monomorphic SETPROP");
|
||||
@ -6579,7 +6582,7 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||
jsid typeId = types::MakeTypeId(cx, id);
|
||||
bool needsBarrier = oracle->propertyWriteNeedsBarrier(script(), pc, typeId);
|
||||
|
||||
return storeSlot(obj, shape, value, needsBarrier);
|
||||
return storeSlot(obj, DropUnrooted(shape), value, needsBarrier);
|
||||
}
|
||||
|
||||
spew("SETPROP not monomorphic");
|
||||
@ -6962,7 +6965,7 @@ IonBuilder::addBoundsCheck(MDefinition *index, MDefinition *length)
|
||||
}
|
||||
|
||||
MInstruction *
|
||||
IonBuilder::addShapeGuard(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind)
|
||||
IonBuilder::addShapeGuard(MDefinition *obj, const UnrootedShape shape, BailoutKind bailoutKind)
|
||||
{
|
||||
MGuardShape *guard = MGuardShape::New(obj, shape, bailoutKind);
|
||||
current->add(guard);
|
||||
|
@ -304,14 +304,14 @@ class IonBuilder : public MIRGenerator
|
||||
MDefinition *walkScopeChain(unsigned hops);
|
||||
|
||||
MInstruction *addBoundsCheck(MDefinition *index, MDefinition *length);
|
||||
MInstruction *addShapeGuard(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind);
|
||||
MInstruction *addShapeGuard(MDefinition *obj, const UnrootedShape shape, BailoutKind bailoutKind);
|
||||
|
||||
JSObject *getNewArrayTemplateObject(uint32_t count);
|
||||
|
||||
bool invalidatedIdempotentCache();
|
||||
|
||||
bool loadSlot(MDefinition *obj, Shape *shape, MIRType rvalType);
|
||||
bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier);
|
||||
bool loadSlot(MDefinition *obj, HandleShape shape, MIRType rvalType);
|
||||
bool storeSlot(MDefinition *obj, UnrootedShape shape, MDefinition *value, bool needsBarrier);
|
||||
|
||||
// jsop_getprop() helpers.
|
||||
bool getPropTryArgumentsLength(bool *emitted);
|
||||
|
@ -149,7 +149,7 @@ IsCacheableProtoChain(JSObject *obj, JSObject *holder)
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableGetPropReadSlot(JSObject *obj, JSObject *holder, const Shape *shape)
|
||||
IsCacheableGetPropReadSlot(JSObject *obj, JSObject *holder, UnrootedShape shape)
|
||||
{
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||
return false;
|
||||
@ -161,7 +161,7 @@ IsCacheableGetPropReadSlot(JSObject *obj, JSObject *holder, const Shape *shape)
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableNoProperty(JSObject *obj, JSObject *holder, const Shape *shape, jsbytecode *pc,
|
||||
IsCacheableNoProperty(JSObject *obj, JSObject *holder, UnrootedShape shape, jsbytecode *pc,
|
||||
const TypedOrValueRegister &output)
|
||||
{
|
||||
if (shape)
|
||||
@ -212,7 +212,7 @@ IsCacheableNoProperty(JSObject *obj, JSObject *holder, const Shape *shape, jsbyt
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableGetPropCallNative(JSObject *obj, JSObject *holder, const Shape *shape)
|
||||
IsCacheableGetPropCallNative(JSObject *obj, JSObject *holder, UnrootedShape shape)
|
||||
{
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||
return false;
|
||||
@ -225,7 +225,7 @@ IsCacheableGetPropCallNative(JSObject *obj, JSObject *holder, const Shape *shape
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableGetPropCallPropertyOp(JSObject *obj, JSObject *holder, const Shape *shape)
|
||||
IsCacheableGetPropCallPropertyOp(JSObject *obj, JSObject *holder, UnrootedShape shape)
|
||||
{
|
||||
if (!shape || !IsCacheableProtoChain(obj, holder))
|
||||
return false;
|
||||
@ -243,7 +243,7 @@ struct GetNativePropertyStub
|
||||
CodeOffsetLabel stubCodePatchOffset;
|
||||
|
||||
void generateReadSlot(JSContext *cx, MacroAssembler &masm, JSObject *obj, PropertyName *propName,
|
||||
JSObject *holder, const Shape *shape, Register object, TypedOrValueRegister output,
|
||||
JSObject *holder, HandleShape shape, Register object, TypedOrValueRegister output,
|
||||
RepatchLabel *failures, Label *nonRepatchFailures = NULL)
|
||||
{
|
||||
// If there's a single jump to |failures|, we can patch the shape guard
|
||||
@ -354,7 +354,7 @@ struct GetNativePropertyStub
|
||||
}
|
||||
|
||||
bool generateCallGetter(JSContext *cx, MacroAssembler &masm, JSObject *obj,
|
||||
PropertyName *propName, JSObject *holder, const Shape *shape,
|
||||
PropertyName *propName, JSObject *holder, HandleShape shape,
|
||||
RegisterSet &liveRegs, Register object, TypedOrValueRegister output,
|
||||
void *returnAddr, jsbytecode *pc,
|
||||
RepatchLabel *failures, Label *nonRepatchFailures = NULL)
|
||||
@ -619,7 +619,7 @@ struct GetNativePropertyStub
|
||||
|
||||
bool
|
||||
IonCacheGetProperty::attachReadSlot(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
const Shape *shape)
|
||||
HandleShape shape)
|
||||
{
|
||||
MacroAssembler masm;
|
||||
RepatchLabel failures;
|
||||
@ -654,9 +654,10 @@ IonCacheGetProperty::attachReadSlot(JSContext *cx, IonScript *ion, JSObject *obj
|
||||
|
||||
bool
|
||||
IonCacheGetProperty::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj,
|
||||
JSObject *holder, const Shape *shape,
|
||||
JSObject *holder, HandleShape shape,
|
||||
const SafepointIndex *safepointIndex, void *returnAddr)
|
||||
{
|
||||
AssertCanGC();
|
||||
MacroAssembler masm;
|
||||
RepatchLabel failures;
|
||||
|
||||
@ -1136,8 +1137,8 @@ IonCacheSetProperty::attachSetterCall(JSContext *cx, IonScript *ion,
|
||||
|
||||
bool
|
||||
IonCacheSetProperty::attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj,
|
||||
const Shape *oldShape, const Shape *newShape,
|
||||
const Shape *propShape)
|
||||
HandleShape oldShape, HandleShape newShape,
|
||||
HandleShape propShape)
|
||||
{
|
||||
MacroAssembler masm;
|
||||
|
||||
@ -1156,7 +1157,7 @@ IonCacheSetProperty::attachNativeAdding(JSContext *cx, IonScript *ion, JSObject
|
||||
JSObject *proto = obj->getProto();
|
||||
Register protoReg = object();
|
||||
while (proto) {
|
||||
Shape *protoShape = proto->lastProperty();
|
||||
UnrootedShape protoShape = proto->lastProperty();
|
||||
|
||||
// load next prototype
|
||||
masm.loadPtr(Address(protoReg, JSObject::offsetOfType()), protoReg);
|
||||
@ -1248,7 +1249,7 @@ IsPropertyInlineable(JSObject *obj, IonCacheSetProperty &cache)
|
||||
static bool
|
||||
IsPropertySetInlineable(JSContext *cx, HandleObject obj, HandleId id, MutableHandleShape pshape)
|
||||
{
|
||||
Shape *shape = obj->nativeLookup(cx, id);
|
||||
UnrootedShape shape = obj->nativeLookup(cx, id);
|
||||
|
||||
if (!shape)
|
||||
return false;
|
||||
@ -1299,7 +1300,7 @@ IsPropertyAddInlineable(JSContext *cx, HandleObject obj, jsid id, uint32_t oldSl
|
||||
if (pShape.get())
|
||||
return false;
|
||||
|
||||
Shape *shape = obj->nativeLookup(cx, id);
|
||||
RootedShape shape(cx, obj->nativeLookup(cx, id));
|
||||
if (!shape || shape->inDictionary() || !shape->hasSlot() || !shape->hasDefaultSetter())
|
||||
return false;
|
||||
|
||||
@ -1319,7 +1320,7 @@ IsPropertyAddInlineable(JSContext *cx, HandleObject obj, jsid id, uint32_t oldSl
|
||||
return false;
|
||||
|
||||
// if prototype defines this property in a non-plain way, don't optimize
|
||||
const Shape *protoShape = proto->nativeLookup(cx, id);
|
||||
UnrootedShape protoShape = proto->nativeLookup(cx, id);
|
||||
if (protoShape && !protoShape->hasDefaultSetter())
|
||||
return false;
|
||||
|
||||
@ -1376,7 +1377,7 @@ js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Ha
|
||||
}
|
||||
|
||||
uint32_t oldSlots = obj->numDynamicSlots();
|
||||
const Shape *oldShape = obj->lastProperty();
|
||||
RootedShape oldShape(cx, obj->lastProperty());
|
||||
|
||||
// Set/Add the property on the object, the inlined cache are setup for the next execution.
|
||||
if (!SetProperty(cx, obj, name, value, cache.strict(), isSetName))
|
||||
@ -1385,7 +1386,7 @@ js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Ha
|
||||
// The property did not exists before, now we can try again to inline the
|
||||
// procedure which is adding the property.
|
||||
if (inlinable && IsPropertyAddInlineable(cx, obj, id, oldSlots, &shape)) {
|
||||
const Shape *newShape = obj->lastProperty();
|
||||
RootedShape newShape(cx, obj->lastProperty());
|
||||
cache.incrementStubCount();
|
||||
if (!cache.attachNativeAdding(cx, ion, obj, oldShape, newShape, shape))
|
||||
return false;
|
||||
@ -1619,7 +1620,7 @@ IonCacheBindName::attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeCha
|
||||
|
||||
static inline void
|
||||
GenerateScopeChainGuard(MacroAssembler &masm, JSObject *scopeObj,
|
||||
Register scopeObjReg, Shape *shape, Label *failures)
|
||||
Register scopeObjReg, UnrootedShape shape, Label *failures)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
if (scopeObj->isCall()) {
|
||||
@ -1789,8 +1790,10 @@ js::ion::BindNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheName::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder, Shape *shape)
|
||||
IonCacheName::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder,
|
||||
HandleShape shape)
|
||||
{
|
||||
AssertCanGC();
|
||||
MacroAssembler masm;
|
||||
Label failures;
|
||||
|
||||
|
@ -273,9 +273,9 @@ class IonCacheGetProperty : public IonCache
|
||||
bool allowGetters() const { return u.getprop.allowGetters; }
|
||||
|
||||
bool attachReadSlot(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
const Shape *shape);
|
||||
HandleShape shape);
|
||||
bool attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
const Shape *shape,
|
||||
HandleShape shape,
|
||||
const SafepointIndex *safepointIndex, void *returnAddr);
|
||||
};
|
||||
|
||||
@ -305,8 +305,8 @@ class IonCacheSetProperty : public IonCache
|
||||
bool attachNativeExisting(JSContext *cx, IonScript *ion, HandleObject obj, HandleShape shape);
|
||||
bool attachSetterCall(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape, void *returnAddr);
|
||||
bool attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj, const Shape *oldshape,
|
||||
const Shape *newshape, const Shape *propshape);
|
||||
bool attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj, HandleShape oldshape,
|
||||
HandleShape newshape, HandleShape propshape);
|
||||
};
|
||||
|
||||
class IonCacheGetElement : public IonCache
|
||||
@ -412,7 +412,7 @@ class IonCacheName : public IonCache
|
||||
}
|
||||
|
||||
bool attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
|
||||
Shape *shape);
|
||||
HandleShape shape);
|
||||
};
|
||||
|
||||
bool
|
||||
|
@ -4455,8 +4455,8 @@ class MBindNameCache
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy
|
||||
{
|
||||
PropertyName *name_;
|
||||
JSScript *script_;
|
||||
CompilerRootPropertyName name_;
|
||||
CompilerRootScript script_;
|
||||
jsbytecode *pc_;
|
||||
|
||||
MBindNameCache(MDefinition *scopeChain, PropertyName *name, JSScript *script, jsbytecode *pc)
|
||||
@ -4495,10 +4495,10 @@ class MGuardShape
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy
|
||||
{
|
||||
const Shape *shape_;
|
||||
CompilerRootShape shape_;
|
||||
BailoutKind bailoutKind_;
|
||||
|
||||
MGuardShape(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind)
|
||||
MGuardShape(MDefinition *obj, UnrootedShape shape, BailoutKind bailoutKind)
|
||||
: MUnaryInstruction(obj),
|
||||
shape_(shape),
|
||||
bailoutKind_(bailoutKind)
|
||||
@ -4511,7 +4511,7 @@ class MGuardShape
|
||||
public:
|
||||
INSTRUCTION_HEADER(GuardShape)
|
||||
|
||||
static MGuardShape *New(MDefinition *obj, const Shape *shape, BailoutKind bailoutKind) {
|
||||
static MGuardShape *New(MDefinition *obj, UnrootedShape shape, BailoutKind bailoutKind) {
|
||||
return new MGuardShape(obj, shape, bailoutKind);
|
||||
}
|
||||
|
||||
@ -4521,7 +4521,7 @@ class MGuardShape
|
||||
MDefinition *obj() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
const Shape *shape() const {
|
||||
const UnrootedShape shape() const {
|
||||
return shape_;
|
||||
}
|
||||
BailoutKind bailoutKind() const {
|
||||
|
@ -142,7 +142,7 @@ InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue v
|
||||
|
||||
if (name == cx->names().proto)
|
||||
return baseops::SetPropertyHelper(cx, obj, obj, id, 0, &rval, false);
|
||||
return !!DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, 0);
|
||||
return DefineNativeProperty(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, 0, 0, 0);
|
||||
}
|
||||
|
||||
template<bool Equal>
|
||||
|
@ -98,6 +98,12 @@ struct ImmGCPtr
|
||||
|
||||
explicit ImmGCPtr(const gc::Cell *ptr) : value(reinterpret_cast<uintptr_t>(ptr))
|
||||
{ }
|
||||
|
||||
// ImmGCPtr is rooted so we can convert safely directly from Unrooted<T>.
|
||||
template <typename T>
|
||||
explicit ImmGCPtr(Unrooted<T> ptr)
|
||||
: value(reinterpret_cast<uintptr_t>(static_cast<T>(ptr)))
|
||||
{ }
|
||||
};
|
||||
|
||||
// Specifies a hardcoded, absolute address.
|
||||
|
@ -3829,7 +3829,7 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
|
||||
|
||||
JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
|
||||
if (flags != 0 && obj->isNative()) {
|
||||
return !!DefineNativeProperty(cx, obj, id, value, getter, setter,
|
||||
return DefineNativeProperty(cx, obj, id, value, getter, setter,
|
||||
attrs, flags, tinyid);
|
||||
}
|
||||
return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
|
||||
@ -4477,15 +4477,15 @@ JS_DeleteProperty(JSContext *cx, JSObject *objArg, const char *name)
|
||||
return JS_DeleteProperty2(cx, objArg, name, &junk);
|
||||
}
|
||||
|
||||
static Shape *
|
||||
static UnrootedShape
|
||||
LastConfigurableShape(JSObject *obj)
|
||||
{
|
||||
for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
|
||||
Shape *shape = &r.front();
|
||||
UnrootedShape shape = &r.front();
|
||||
if (shape->configurable())
|
||||
return shape;
|
||||
}
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
@ -4502,18 +4502,20 @@ JS_ClearNonGlobalObject(JSContext *cx, JSObject *objArg)
|
||||
return;
|
||||
|
||||
/* Remove all configurable properties from obj. */
|
||||
while (Shape *shape = LastConfigurableShape(obj)) {
|
||||
RootedShape shape(cx);
|
||||
while ((shape = LastConfigurableShape(obj))) {
|
||||
if (!obj->removeProperty(cx, shape->propid()))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set all remaining writable plain data properties to undefined. */
|
||||
for (Shape::Range r(obj->lastProperty()->all()); !r.empty(); r.popFront()) {
|
||||
Shape *shape = &r.front();
|
||||
UnrootedShape shape = &r.front();
|
||||
if (shape->isDataDescriptor() &&
|
||||
shape->writable() &&
|
||||
shape->hasDefaultSetter() &&
|
||||
shape->hasSlot()) {
|
||||
shape->hasSlot())
|
||||
{
|
||||
obj->nativeSetSlot(shape->slot(), UndefinedValue());
|
||||
}
|
||||
}
|
||||
@ -4556,7 +4558,7 @@ JS_Enumerate(JSContext *cx, JSObject *objArg)
|
||||
* XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
|
||||
* prop_iterator_class somehow...
|
||||
* + preserve the obj->enumerate API while optimizing the native object case
|
||||
* + native case here uses a Shape *, but that iterates in reverse!
|
||||
* + native case here uses a JSShape *, but that iterates in reverse!
|
||||
* + so we make non-native match, by reverse-iterating after JS_Enumerating
|
||||
*/
|
||||
const uint32_t JSSLOT_ITER_INDEX = 0;
|
||||
@ -4588,7 +4590,7 @@ prop_iter_trace(JSTracer *trc, RawObject obj)
|
||||
* barrier here because the pointer is updated via setPrivate, which
|
||||
* always takes a barrier.
|
||||
*/
|
||||
Shape *tmp = (Shape *)pdata;
|
||||
UnrootedShape tmp = static_cast<RawShape>(pdata);
|
||||
MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
|
||||
obj->setPrivateUnbarriered(tmp);
|
||||
} else {
|
||||
@ -4653,18 +4655,15 @@ JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
|
||||
{
|
||||
RootedObject iterobj(cx, iterobjArg);
|
||||
AutoAssertNoGC nogc;
|
||||
int32_t i;
|
||||
Shape *shape;
|
||||
JSIdArray *ida;
|
||||
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, iterobj);
|
||||
i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
|
||||
int32_t i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
|
||||
if (i < 0) {
|
||||
/* Native case: private data is a property tree node pointer. */
|
||||
JS_ASSERT(iterobj->getParent()->isNative());
|
||||
shape = (Shape *) iterobj->getPrivate();
|
||||
UnrootedShape shape = static_cast<RawShape>(iterobj->getPrivate());
|
||||
|
||||
while (shape->previous() && !shape->enumerable())
|
||||
shape = shape->previous();
|
||||
@ -4673,12 +4672,12 @@ JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
|
||||
JS_ASSERT(shape->isEmptyShape());
|
||||
*idp = JSID_VOID;
|
||||
} else {
|
||||
iterobj->setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
|
||||
iterobj->setPrivateGCThing(const_cast<RawShape>(shape->previous().get()));
|
||||
*idp = shape->propid();
|
||||
}
|
||||
} else {
|
||||
/* Non-native case: use the ida enumerated when iterobj was created. */
|
||||
ida = (JSIdArray *) iterobj->getPrivate();
|
||||
JSIdArray *ida = (JSIdArray *) iterobj->getPrivate();
|
||||
JS_ASSERT(i <= ida->length);
|
||||
STATIC_ASSUME(i <= ida->length);
|
||||
if (i == 0) {
|
||||
|
@ -206,14 +206,14 @@ js::StringIsArrayIndex(JSLinearString *str, uint32_t *indexp)
|
||||
return false;
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
js::GetDenseArrayShape(JSContext *cx, HandleObject globalObj)
|
||||
{
|
||||
JS_ASSERT(globalObj);
|
||||
|
||||
JSObject *proto = globalObj->global().getOrCreateArrayPrototype(cx);
|
||||
if (!proto)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
return EmptyShape::getInitialShape(cx, &ArrayClass, proto, proto->getParent(),
|
||||
gc::FINALIZE_OBJECT0);
|
||||
@ -265,7 +265,7 @@ JSObject::arrayGetOwnDataElement(JSContext *cx, size_t i, Value *vp)
|
||||
if (!IndexToId(cx, i, &id))
|
||||
return false;
|
||||
|
||||
Shape *shape = nativeLookup(cx, id);
|
||||
UnrootedShape shape = nativeLookup(cx, id);
|
||||
if (!shape || !shape->isDataDescriptor())
|
||||
vp->setMagic(JS_ARRAY_HOLE);
|
||||
else
|
||||
@ -1254,7 +1254,7 @@ AddLengthProperty(JSContext *cx, HandleObject obj)
|
||||
if (!obj->allocateSlowArrayElements(cx))
|
||||
return false;
|
||||
|
||||
return obj->addProperty(cx, lengthId, array_length_getter, array_length_setter,
|
||||
return JSObject::addProperty(cx, obj, lengthId, array_length_getter, array_length_setter,
|
||||
SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0);
|
||||
}
|
||||
|
||||
@ -1294,11 +1294,12 @@ JSObject::makeDenseArraySlow(JSContext *cx, HandleObject obj)
|
||||
* on error. This is gross, but a better way is not obvious. Note: the
|
||||
* exact contents of the array are not preserved on error.
|
||||
*/
|
||||
js::Shape *oldShape = obj->lastProperty();
|
||||
RootedShape oldShape(cx, obj->lastProperty());
|
||||
|
||||
/* Create a native scope. */
|
||||
{
|
||||
gc::AllocKind kind = obj->getAllocKind();
|
||||
Shape *shape = EmptyShape::getInitialShape(cx, &SlowArrayClass, obj->getProto(),
|
||||
UnrootedShape shape = EmptyShape::getInitialShape(cx, &SlowArrayClass, obj->getProto(),
|
||||
oldShape->getObjectParent(), kind);
|
||||
if (!shape)
|
||||
return false;
|
||||
@ -1315,6 +1316,7 @@ JSObject::makeDenseArraySlow(JSContext *cx, HandleObject obj)
|
||||
obj->prepareElementRangeForOverwrite(0, arrayInitialized);
|
||||
|
||||
obj->shape_ = shape;
|
||||
}
|
||||
|
||||
/* Reset to an empty dense array. */
|
||||
obj->elements = emptyObjectElements;
|
||||
|
@ -76,7 +76,7 @@ extern JSObject *
|
||||
NewSlowEmptyArray(JSContext *cx);
|
||||
|
||||
/* Get the common shape used by all dense arrays with a prototype at globalObj. */
|
||||
extern Shape *
|
||||
extern UnrootedShape
|
||||
GetDenseArrayShape(JSContext *cx, HandleObject globalObj);
|
||||
|
||||
extern JSBool
|
||||
|
@ -428,6 +428,7 @@ template<XDRMode mode>
|
||||
bool
|
||||
js::XDRAtom(XDRState<mode> *xdr, MutableHandleAtom atomp)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (mode == XDR_ENCODE) {
|
||||
uint32_t nchars = atomp->length();
|
||||
if (!xdr->codeUint32(&nchars))
|
||||
|
@ -573,7 +573,7 @@ js::ReportUsageError(JSContext *cx, HandleObject callee, const char *msg)
|
||||
{
|
||||
const char *usageStr = "usage";
|
||||
PropertyName *usageAtom = Atomize(cx, usageStr, strlen(usageStr))->asPropertyName();
|
||||
DebugOnly<Shape *> shape = callee->nativeLookup(cx, NameToId(usageAtom));
|
||||
DebugOnly<RawShape> shape = static_cast<RawShape>(callee->nativeLookup(cx, NameToId(usageAtom)));
|
||||
JS_ASSERT(!shape->configurable());
|
||||
JS_ASSERT(!shape->writable());
|
||||
JS_ASSERT(shape->hasDefaultGetter());
|
||||
|
@ -317,7 +317,7 @@ class NewObjectCache
|
||||
inline void fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj);
|
||||
|
||||
/* Invalidate any entries which might produce an object with shape/proto. */
|
||||
void invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto);
|
||||
void invalidateEntriesForShape(JSContext *cx, HandleShape shape, HandleObject proto);
|
||||
|
||||
private:
|
||||
inline bool lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry);
|
||||
|
@ -798,7 +798,7 @@ JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
/* This all should be reworked to avoid requiring JSScopeProperty types. */
|
||||
|
||||
static JSBool
|
||||
GetPropertyDesc(JSContext *cx, JSObject *obj_, Shape *shape, JSPropertyDesc *pd)
|
||||
GetPropertyDesc(JSContext *cx, JSObject *obj_, HandleShape shape, JSPropertyDesc *pd)
|
||||
{
|
||||
assertSameCompartment(cx, obj_);
|
||||
pd->id = IdToJsval(shape->propid());
|
||||
@ -901,7 +901,7 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj_, JSPropertyDescArray *pda)
|
||||
goto bad;
|
||||
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
||||
goto bad;
|
||||
Shape *shape = const_cast<Shape *>(&r.front());
|
||||
RootedShape shape(cx, const_cast<Shape *>(&r.front()));
|
||||
if (!GetPropertyDesc(cx, obj, shape, &pd[i]))
|
||||
goto bad;
|
||||
if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
|
||||
|
@ -256,7 +256,7 @@ JS_WrapAutoIdVector(JSContext *cx, js::AutoIdVector &props)
|
||||
JS_FRIEND_API(void)
|
||||
JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
|
||||
{
|
||||
MarkCycleCollectorChildren(trc, (Shape *)shape);
|
||||
MarkCycleCollectorChildren(trc, static_cast<RawShape>(shape));
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -905,7 +905,7 @@ js::IncrementalReferenceBarrier(void *ptr)
|
||||
else if (kind == JSTRACE_SCRIPT)
|
||||
JSScript::writeBarrierPre(reinterpret_cast<RawScript>(ptr));
|
||||
else if (kind == JSTRACE_SHAPE)
|
||||
Shape::writeBarrierPre((Shape *) ptr);
|
||||
Shape::writeBarrierPre(reinterpret_cast<RawShape>(ptr));
|
||||
else if (kind == JSTRACE_BASE_SHAPE)
|
||||
BaseShape::writeBarrierPre(reinterpret_cast<RawBaseShape>(ptr));
|
||||
else if (kind == JSTRACE_TYPE_OBJECT)
|
||||
|
@ -595,7 +595,7 @@ js_NewGCScript(JSContext *cx)
|
||||
return js::gc::NewGCThing<JSScript>(cx, js::gc::FINALIZE_SCRIPT, sizeof(JSScript));
|
||||
}
|
||||
|
||||
inline js::Shape *
|
||||
inline js::UnrootedShape
|
||||
js_NewGCShape(JSContext *cx)
|
||||
{
|
||||
return js::gc::NewGCThing<js::Shape>(cx, js::gc::FINALIZE_SHAPE, sizeof(js::Shape));
|
||||
|
@ -807,20 +807,22 @@ HeapTypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target)
|
||||
}
|
||||
|
||||
/* If id is a normal slotful 'own' property of an object, get its shape. */
|
||||
static inline Shape *
|
||||
GetSingletonShape(JSContext *cx, HandleObject obj, jsid id)
|
||||
static inline UnrootedShape
|
||||
GetSingletonShape(JSContext *cx, RawObject obj, RawId id)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (!obj->isNative())
|
||||
return NULL;
|
||||
Shape *shape = obj->nativeLookup(cx, id);
|
||||
return UnrootedShape(NULL);
|
||||
UnrootedShape shape = DropUnrooted(obj)->nativeLookup(cx, DropUnrooted(id));
|
||||
if (shape && shape->hasDefaultGetter() && shape->hasSlot())
|
||||
return shape;
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32_t offset)
|
||||
{
|
||||
AssertCanGC();
|
||||
TypeBarrier **pbarrier = &getCode(offset).typeBarriers;
|
||||
while (*pbarrier) {
|
||||
TypeBarrier *barrier = *pbarrier;
|
||||
@ -831,8 +833,7 @@ ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32_t offset)
|
||||
}
|
||||
if (barrier->singleton) {
|
||||
JS_ASSERT(barrier->type.isPrimitive(JSVAL_TYPE_UNDEFINED));
|
||||
RootedObject barrierSingleton(cx, barrier->singleton);
|
||||
Shape *shape = GetSingletonShape(cx, barrierSingleton, barrier->singletonId);
|
||||
UnrootedShape shape = GetSingletonShape(cx, barrier->singleton, barrier->singletonId);
|
||||
if (shape && !barrier->singleton->nativeGetSlot(shape->slot()).isUndefined()) {
|
||||
/*
|
||||
* When we analyzed the script the singleton had an 'own'
|
||||
@ -1674,6 +1675,7 @@ class TypeConstraintFreezeObjectFlags : public TypeConstraint
|
||||
|
||||
void newObjectState(JSContext *cx, TypeObject *object, bool force)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
if (!marked && (object->hasAnyFlags(flags) || (!flags && force))) {
|
||||
marked = true;
|
||||
cx->compartment->types.addPendingRecompile(cx, info);
|
||||
@ -2548,6 +2550,7 @@ TypeCompartment::nukeTypes(FreeOp *fop)
|
||||
void
|
||||
TypeCompartment::addPendingRecompile(JSContext *cx, const RecompileInfo &info)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
CompilerOutput *co = info.compilerOutput(cx);
|
||||
|
||||
if (co->pendingRecompilation)
|
||||
@ -3027,13 +3030,14 @@ struct types::ObjectTableKey
|
||||
((uint32_t)obj->getTaggedProto().toWord() >> 2));
|
||||
}
|
||||
|
||||
static inline bool match(const ObjectTableKey &v, JSObject *obj) {
|
||||
static inline bool match(const ObjectTableKey &v, RawObject obj) {
|
||||
if (obj->slotSpan() != v.nslots ||
|
||||
obj->numFixedSlots() != v.nfixed ||
|
||||
obj->getTaggedProto() != v.proto) {
|
||||
return false;
|
||||
}
|
||||
Shape *shape = obj->lastProperty();
|
||||
UnrootedShape shape = obj->lastProperty();
|
||||
obj = NULL;
|
||||
while (!shape->isEmptyShape()) {
|
||||
if (shape->propid() != v.ids[shape->slot()])
|
||||
return false;
|
||||
@ -3075,7 +3079,7 @@ TypeCompartment::fixObjectType(JSContext *cx, HandleObject obj)
|
||||
return;
|
||||
|
||||
ObjectTypeTable::AddPtr p = objectTypeTable->lookupForAdd(obj.get());
|
||||
Shape *baseShape = obj->lastProperty();
|
||||
RootedShape baseShape(cx, obj->lastProperty());
|
||||
|
||||
if (p) {
|
||||
/* The lookup ensures the shape matches, now check that the types match. */
|
||||
@ -3086,7 +3090,7 @@ TypeCompartment::fixObjectType(JSContext *cx, HandleObject obj)
|
||||
if (NumberTypes(ntype, types[i])) {
|
||||
if (types[i].isPrimitive(JSVAL_TYPE_INT32)) {
|
||||
types[i] = Type::DoubleType();
|
||||
Shape *shape = baseShape;
|
||||
RootedShape shape(cx, baseShape);
|
||||
while (!shape->isEmptyShape()) {
|
||||
if (shape->slot() == i) {
|
||||
Type type = Type::DoubleType();
|
||||
@ -3127,7 +3131,7 @@ TypeCompartment::fixObjectType(JSContext *cx, HandleObject obj)
|
||||
return;
|
||||
}
|
||||
|
||||
Shape *shape = baseShape;
|
||||
RootedShape shape(cx, baseShape);
|
||||
while (!shape->isEmptyShape()) {
|
||||
ids[shape->slot()] = shape->propid();
|
||||
types[shape->slot()] = GetValueTypeForTable(cx, obj->getSlot(shape->slot()));
|
||||
@ -3194,7 +3198,7 @@ TypeObject::getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force
|
||||
}
|
||||
|
||||
static inline void
|
||||
UpdatePropertyType(JSContext *cx, TypeSet *types, HandleObject obj, Shape *shape, bool force)
|
||||
UpdatePropertyType(JSContext *cx, TypeSet *types, RawObject obj, UnrootedShape shape, bool force)
|
||||
{
|
||||
types->setOwnProperty(cx, false);
|
||||
if (!shape->writable())
|
||||
@ -3239,14 +3243,14 @@ TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
|
||||
RootedObject rSingleton(cx, singleton);
|
||||
if (JSID_IS_VOID(id)) {
|
||||
/* Go through all shapes on the object to get integer-valued properties. */
|
||||
Shape *shape = singleton->lastProperty();
|
||||
UnrootedShape shape = singleton->lastProperty();
|
||||
while (!shape->isEmptyShape()) {
|
||||
if (JSID_IS_VOID(MakeTypeId(cx, shape->propid())))
|
||||
UpdatePropertyType(cx, &base->types, rSingleton, shape, true);
|
||||
shape = shape->previous();
|
||||
}
|
||||
} else if (!JSID_IS_EMPTY(id) && singleton->isNative()) {
|
||||
Shape *shape = singleton->nativeLookup(cx, id);
|
||||
UnrootedShape shape = singleton->nativeLookup(cx, id);
|
||||
if (shape)
|
||||
UpdatePropertyType(cx, &base->types, rSingleton, shape, false);
|
||||
}
|
||||
@ -3278,7 +3282,7 @@ TypeObject::addDefiniteProperties(JSContext *cx, HandleObject obj)
|
||||
/* Mark all properties of obj as definite properties of this type. */
|
||||
AutoEnterTypeInference enter(cx);
|
||||
|
||||
Shape *shape = obj->lastProperty();
|
||||
RootedShape shape(cx, obj->lastProperty());
|
||||
while (!shape->isEmptyShape()) {
|
||||
jsid id = MakeTypeId(cx, shape->propid());
|
||||
if (!JSID_IS_VOID(id) && obj->isFixedSlot(shape->slot()) &&
|
||||
@ -3306,7 +3310,7 @@ TypeObject::matchDefiniteProperties(HandleObject obj)
|
||||
unsigned slot = prop->types.definiteSlot();
|
||||
|
||||
bool found = false;
|
||||
Shape *shape = obj->lastProperty();
|
||||
UnrootedShape shape = obj->lastProperty();
|
||||
while (!shape->isEmptyShape()) {
|
||||
if (shape->slot() == slot && shape->propid() == prop->id) {
|
||||
found = true;
|
||||
@ -3325,6 +3329,7 @@ TypeObject::matchDefiniteProperties(HandleObject obj)
|
||||
inline void
|
||||
InlineAddTypeProperty(JSContext *cx, TypeObject *obj, jsid id, Type type)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(id == MakeTypeId(cx, id));
|
||||
|
||||
AutoEnterTypeInference enter(cx);
|
||||
@ -3353,6 +3358,7 @@ TypeObject::addPropertyType(JSContext *cx, jsid id, const Value &value)
|
||||
void
|
||||
TypeObject::addPropertyType(JSContext *cx, const char *name, Type type)
|
||||
{
|
||||
AssertCanGC();
|
||||
jsid id = JSID_VOID;
|
||||
if (name) {
|
||||
JSAtom *atom = Atomize(cx, name, strlen(name));
|
||||
@ -3387,6 +3393,8 @@ TypeObject::markPropertyConfigured(JSContext *cx, jsid id)
|
||||
void
|
||||
TypeObject::markStateChange(JSContext *cx)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
if (unknownProperties())
|
||||
return;
|
||||
|
||||
@ -5020,6 +5028,8 @@ CheckNewScriptProperties(JSContext *cx, HandleTypeObject type, JSFunction *fun)
|
||||
return;
|
||||
}
|
||||
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
type->newScript->fun = fun;
|
||||
type->newScript->allocKind = kind;
|
||||
type->newScript->shape = baseobj->lastProperty();
|
||||
@ -5828,6 +5838,7 @@ JSObject::setNewTypeUnknown(JSContext *cx)
|
||||
TypeObject *
|
||||
JSCompartment::getNewType(JSContext *cx, TaggedProto proto_, JSFunction *fun_, bool isDOM)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT_IF(fun_, proto_.isObject());
|
||||
JS_ASSERT_IF(proto_.isObject(), cx->compartment == proto_.toObject()->compartment());
|
||||
|
||||
|
@ -275,6 +275,7 @@ TypeFlagPrimitive(TypeFlags flags)
|
||||
inline jsid
|
||||
MakeTypeId(JSContext *cx, jsid id)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(!JSID_IS_EMPTY(id));
|
||||
|
||||
/*
|
||||
@ -546,6 +547,8 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
|
||||
inline bool
|
||||
TrackPropertyTypes(JSContext *cx, HandleObject obj, jsid id)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
if (!cx->typeInferenceEnabled() || obj->hasLazyType() || obj->type()->unknownProperties())
|
||||
return false;
|
||||
|
||||
@ -559,6 +562,7 @@ TrackPropertyTypes(JSContext *cx, HandleObject obj, jsid id)
|
||||
inline void
|
||||
AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, Type type)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled())
|
||||
id = MakeTypeId(cx, id);
|
||||
if (TrackPropertyTypes(cx, obj, id))
|
||||
@ -568,6 +572,7 @@ AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, Type type)
|
||||
inline void
|
||||
AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, const Value &value)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled())
|
||||
id = MakeTypeId(cx, id);
|
||||
if (TrackPropertyTypes(cx, obj, id))
|
||||
@ -577,6 +582,7 @@ AddTypePropertyId(JSContext *cx, HandleObject obj, jsid id, const Value &value)
|
||||
inline void
|
||||
AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, Type type)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled() && !obj->unknownProperties())
|
||||
obj->addPropertyType(cx, name, type);
|
||||
}
|
||||
@ -584,6 +590,7 @@ AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, Type type)
|
||||
inline void
|
||||
AddTypeProperty(JSContext *cx, TypeObject *obj, const char *name, const Value &value)
|
||||
{
|
||||
AssertCanGC();
|
||||
if (cx->typeInferenceEnabled() && !obj->unknownProperties())
|
||||
obj->addPropertyType(cx, name, value);
|
||||
}
|
||||
@ -629,8 +636,9 @@ MarkTypePropertyConfigured(JSContext *cx, HandleObject obj, jsid id)
|
||||
|
||||
/* Mark a state change on a particular object. */
|
||||
inline void
|
||||
MarkObjectStateChange(JSContext *cx, HandleObject obj)
|
||||
MarkObjectStateChange(JSContext *cx, RawObject obj)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties())
|
||||
obj->type()->markStateChange(cx);
|
||||
}
|
||||
@ -1565,6 +1573,7 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool own)
|
||||
inline HeapTypeSet *
|
||||
TypeObject::maybeGetProperty(JSContext *cx, jsid id)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
|
||||
JS_ASSERT_IF(!JSID_IS_EMPTY(id), id == MakeTypeId(cx, id));
|
||||
JS_ASSERT(!unknownProperties());
|
||||
|
@ -174,15 +174,16 @@ ValuePropertyBearer(JSContext *cx, StackFrame *fp, HandleValue v, int spindex)
|
||||
}
|
||||
|
||||
inline bool
|
||||
NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shape,
|
||||
NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shapeArg,
|
||||
unsigned getHow, MutableHandleValue vp)
|
||||
{
|
||||
if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {
|
||||
if (shapeArg->isDataDescriptor() && shapeArg->hasDefaultGetter()) {
|
||||
/* Fast path for Object instance properties. */
|
||||
JS_ASSERT(shape->hasSlot());
|
||||
vp.set(pobj->nativeGetSlot(shape->slot()));
|
||||
JS_ASSERT(shapeArg->hasSlot());
|
||||
vp.set(pobj->nativeGetSlot(shapeArg->slot()));
|
||||
} else {
|
||||
if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp.address()))
|
||||
RootedShape shape(cx, shapeArg);
|
||||
if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -431,8 +431,8 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
|
||||
size_t plength = props.length();
|
||||
NativeIterator *ni = (NativeIterator *)
|
||||
cx->malloc_(sizeof(NativeIterator)
|
||||
+ plength * sizeof(JSString *)
|
||||
+ slength * sizeof(Shape *));
|
||||
+ plength * sizeof(RawString)
|
||||
+ slength * sizeof(RawShape));
|
||||
if (!ni)
|
||||
return NULL;
|
||||
AutoValueVector strings(cx);
|
||||
@ -602,7 +602,7 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector<Shape *, 8> shapes(cx);
|
||||
Vector<RawShape, 8> shapes(cx);
|
||||
uint32_t key = 0;
|
||||
|
||||
bool keysOnly = (flags == JSITER_ENUMERATE);
|
||||
@ -651,6 +651,7 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
|
||||
* currently active.
|
||||
*/
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
RawObject pobj = obj;
|
||||
do {
|
||||
if (!pobj->isNative() ||
|
||||
@ -660,9 +661,9 @@ js::GetIterator(JSContext *cx, HandleObject obj, unsigned flags, MutableHandleVa
|
||||
shapes.clear();
|
||||
goto miss;
|
||||
}
|
||||
Shape *shape = pobj->lastProperty();
|
||||
RawShape shape = pobj->lastProperty();
|
||||
key = (key + (key << 16)) ^ (uintptr_t(shape) >> 3);
|
||||
if (!shapes.append((Shape *) shape))
|
||||
if (!shapes.append(shape))
|
||||
return false;
|
||||
pobj = pobj->getProto();
|
||||
} while (pobj);
|
||||
|
@ -197,7 +197,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
}
|
||||
case JSTRACE_SHAPE:
|
||||
{
|
||||
Shape *shape = static_cast<Shape*>(thing);
|
||||
UnrootedShape shape = static_cast<RawShape>(thing);
|
||||
size_t propTableSize, kidsSize;
|
||||
shape->sizeOfExcludingThis(rtStats->mallocSizeOf, &propTableSize, &kidsSize);
|
||||
if (shape->inDictionary()) {
|
||||
|
155
js/src/jsobj.cpp
155
js/src/jsobj.cpp
@ -1348,7 +1348,7 @@ DefinePropertyOnObject(JSContext *cx, HandleObject obj, HandleId id, const PropD
|
||||
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
|
||||
}
|
||||
|
||||
if (!js_NativeGet(cx, obj, obj2, shape, 0, v.address()))
|
||||
if (!js_NativeGet(cx, obj, obj2, shape, 0, &v))
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
@ -1880,11 +1880,11 @@ JSObject::sealOrFreeze(JSContext *cx, HandleObject obj, ImmutabilityType it)
|
||||
* generic path below then any non-empty object will be converted to
|
||||
* dictionary mode.
|
||||
*/
|
||||
Shape *last = EmptyShape::getInitialShape(cx, obj->getClass(),
|
||||
RootedShape last(cx, EmptyShape::getInitialShape(cx, obj->getClass(),
|
||||
obj->getTaggedProto(),
|
||||
obj->getParent(),
|
||||
obj->getAllocKind(),
|
||||
obj->lastProperty()->getObjectFlags());
|
||||
obj->lastProperty()->getObjectFlags()));
|
||||
if (!last)
|
||||
return false;
|
||||
|
||||
@ -2113,6 +2113,7 @@ static inline JSObject *
|
||||
NewObject(JSContext *cx, Class *clasp, types::TypeObject *type_, JSObject *parent,
|
||||
gc::AllocKind kind)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(clasp != &ArrayClass);
|
||||
JS_ASSERT_IF(clasp == &FunctionClass,
|
||||
kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
|
||||
@ -2291,15 +2292,17 @@ js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
|
||||
|
||||
/* Get all the ids in the object, in order. */
|
||||
js::AutoIdVector ids(cx);
|
||||
{
|
||||
for (unsigned i = 0; i <= shape->slot(); i++) {
|
||||
if (!ids.append(JSID_VOID))
|
||||
return NULL;
|
||||
}
|
||||
js::Shape *nshape = shape;
|
||||
UnrootedShape nshape = shape;
|
||||
while (!nshape->isEmptyShape()) {
|
||||
ids[nshape->slot()] = nshape->propid();
|
||||
nshape = nshape->previous();
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct the new shape. */
|
||||
RootedId id(cx);
|
||||
@ -2340,9 +2343,10 @@ CreateThisForFunctionWithType(JSContext *cx, HandleTypeObject type, JSObject *pa
|
||||
*/
|
||||
gc::AllocKind kind = type->newScript->allocKind;
|
||||
RootedObject res(cx, NewObjectWithType(cx, type, parent, kind));
|
||||
if (res)
|
||||
JS_ALWAYS_TRUE(JSObject::setLastProperty(cx, res,
|
||||
(Shape *) type->newScript->shape.get()));
|
||||
if (res) {
|
||||
RootedShape shape(cx, type->newScript->shape);
|
||||
JS_ALWAYS_TRUE(JSObject::setLastProperty(cx, res, shape));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2550,9 +2554,12 @@ JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedValue v(cx);
|
||||
RootedId id(cx);
|
||||
size_t n = shapes.length();
|
||||
while (n > 0) {
|
||||
Shape *shape = shapes[--n];
|
||||
shape = shapes[--n];
|
||||
unsigned attrs = shape->attributes();
|
||||
PropertyOp getter = shape->getter();
|
||||
StrictPropertyOp setter = shape->setter();
|
||||
@ -2561,10 +2568,10 @@ JS_CopyPropertiesFrom(JSContext *cx, JSObject *targetArg, JSObject *obj)
|
||||
return false;
|
||||
if ((attrs & JSPROP_SETTER) && !cx->compartment->wrap(cx, &setter))
|
||||
return false;
|
||||
RootedValue v(cx, shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue());
|
||||
v = shape->hasSlot() ? obj->getSlot(shape->slot()) : UndefinedValue();
|
||||
if (!cx->compartment->wrap(cx, v.address()))
|
||||
return false;
|
||||
Rooted<jsid> id(cx, shape->propid());
|
||||
id = shape->propid();
|
||||
if (!JSObject::defineGeneric(cx, target, id, v, getter, setter, attrs))
|
||||
return false;
|
||||
}
|
||||
@ -2648,15 +2655,15 @@ struct JSObject::TradeGutsReserved {
|
||||
Vector<Value> bvals;
|
||||
int newafixed;
|
||||
int newbfixed;
|
||||
Shape *newashape;
|
||||
Shape *newbshape;
|
||||
RootedShape newashape;
|
||||
RootedShape newbshape;
|
||||
HeapSlot *newaslots;
|
||||
HeapSlot *newbslots;
|
||||
|
||||
TradeGutsReserved(JSContext *cx)
|
||||
: avals(cx), bvals(cx),
|
||||
newafixed(0), newbfixed(0),
|
||||
newashape(NULL), newbshape(NULL),
|
||||
newashape(cx), newbshape(cx),
|
||||
newaslots(NULL), newbslots(NULL)
|
||||
{}
|
||||
|
||||
@ -2673,6 +2680,7 @@ bool
|
||||
JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
|
||||
TradeGutsReserved &reserved)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(a->compartment() == b->compartment());
|
||||
AutoCompartment ac(cx, a);
|
||||
|
||||
@ -2782,6 +2790,7 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
|
||||
void
|
||||
JSObject::TradeGuts(JSContext *cx, JSObject *a, JSObject *b, TradeGutsReserved &reserved)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(a->compartment() == b->compartment());
|
||||
JS_ASSERT(a->isFunction() == b->isFunction());
|
||||
|
||||
@ -2956,11 +2965,10 @@ DefineStandardSlot(JSContext *cx, HandleObject obj, JSProtoKey key, JSAtom *atom
|
||||
JS_ASSERT(obj->isGlobal());
|
||||
JS_ASSERT(obj->isNative());
|
||||
|
||||
Shape *shape = obj->nativeLookup(cx, id);
|
||||
if (!shape) {
|
||||
if (!obj->nativeLookup(cx, id)) {
|
||||
uint32_t slot = 2 * JSProto_LIMIT + key;
|
||||
obj->setReservedSlot(slot, v);
|
||||
if (!obj->addProperty(cx, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
|
||||
if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
|
||||
return false;
|
||||
AddTypePropertyId(cx, obj, id, v);
|
||||
|
||||
@ -3234,7 +3242,7 @@ JSObject::updateSlotsForSpan(JSContext *cx, HandleObject obj, size_t oldSpan, si
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
JSObject::setLastProperty(JSContext *cx, HandleObject obj, js::Shape *shape)
|
||||
JSObject::setLastProperty(JSContext *cx, HandleObject obj, HandleShape shape)
|
||||
{
|
||||
JS_ASSERT(!obj->inDictionaryMode());
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
@ -3689,31 +3697,32 @@ js_FindClassObject(JSContext *cx, JSProtoKey protoKey, MutableHandleValue vp, Cl
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSObject::allocSlot(JSContext *cx, uint32_t *slotp)
|
||||
/* static */ bool
|
||||
JSObject::allocSlot(JSContext *cx, HandleObject obj, uint32_t *slotp)
|
||||
{
|
||||
uint32_t slot = slotSpan();
|
||||
JS_ASSERT(slot >= JSSLOT_FREE(getClass()));
|
||||
AssertCanGC();
|
||||
uint32_t slot = obj->slotSpan();
|
||||
JS_ASSERT(slot >= JSSLOT_FREE(obj->getClass()));
|
||||
|
||||
/*
|
||||
* If this object is in dictionary mode, try to pull a free slot from the
|
||||
* shape table's slot-number freelist.
|
||||
*/
|
||||
if (inDictionaryMode()) {
|
||||
ShapeTable &table = lastProperty()->table();
|
||||
if (obj->inDictionaryMode()) {
|
||||
ShapeTable &table = obj->lastProperty()->table();
|
||||
uint32_t last = table.freelist;
|
||||
if (last != SHAPE_INVALID_SLOT) {
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(last < slot);
|
||||
uint32_t next = getSlot(last).toPrivateUint32();
|
||||
uint32_t next = obj->getSlot(last).toPrivateUint32();
|
||||
JS_ASSERT_IF(next != SHAPE_INVALID_SLOT, next < slot);
|
||||
#endif
|
||||
|
||||
*slotp = last;
|
||||
|
||||
const Value &vref = getSlot(last);
|
||||
const Value &vref = obj->getSlot(last);
|
||||
table.freelist = vref.toPrivateUint32();
|
||||
setSlot(last, UndefinedValue());
|
||||
obj->setSlot(last, UndefinedValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3725,8 +3734,7 @@ JSObject::allocSlot(JSContext *cx, uint32_t *slotp)
|
||||
|
||||
*slotp = slot;
|
||||
|
||||
RootedObject self(cx, this);
|
||||
if (inDictionaryMode() && !setSlotSpan(cx, self, slot + 1))
|
||||
if (obj->inDictionaryMode() && !setSlotSpan(cx, obj, slot + 1))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -3758,13 +3766,12 @@ JSObject::freeSlot(uint32_t slot)
|
||||
}
|
||||
|
||||
static bool
|
||||
PurgeProtoChain(JSContext *cx, JSObject *obj_, jsid id_)
|
||||
PurgeProtoChain(JSContext *cx, RawObject objArg, HandleId id)
|
||||
{
|
||||
Shape *shape;
|
||||
|
||||
RootedObject obj(cx, obj_);
|
||||
RootedId id(cx, id_);
|
||||
/* Root locally so we can re-assign. */
|
||||
RootedObject obj(cx, objArg);
|
||||
|
||||
RootedShape shape(cx);
|
||||
while (obj) {
|
||||
/* Lookups will not be cached through non-native protos. */
|
||||
if (!obj->isNative())
|
||||
@ -3785,10 +3792,10 @@ PurgeProtoChain(JSContext *cx, JSObject *obj_, jsid id_)
|
||||
}
|
||||
|
||||
bool
|
||||
js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj_, jsid id_)
|
||||
js_PurgeScopeChainHelper(JSContext *cx, HandleObject objArg, HandleId id)
|
||||
{
|
||||
RootedObject obj(cx, obj_);
|
||||
RootedId id(cx, id_);
|
||||
/* Re-root locally so we can re-assign. */
|
||||
RootedObject obj(cx, objArg);
|
||||
|
||||
JS_ASSERT(obj->isNative());
|
||||
JS_ASSERT(obj->isDelegate());
|
||||
@ -3810,29 +3817,27 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj_, jsid id_)
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
js_AddNativeProperty(JSContext *cx, HandleObject obj, jsid id_,
|
||||
UnrootedShape
|
||||
js_AddNativeProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
PropertyOp getter, StrictPropertyOp setter, uint32_t slot,
|
||||
unsigned attrs, unsigned flags, int shortid)
|
||||
{
|
||||
RootedId id(cx, id_);
|
||||
|
||||
/*
|
||||
* Purge the property cache of now-shadowed id in obj's scope chain. Do
|
||||
* this optimistically (assuming no failure below) before locking obj, so
|
||||
* we can lock the shadowed scope.
|
||||
*/
|
||||
if (!js_PurgeScopeChain(cx, obj, id))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid);
|
||||
return JSObject::putProperty(cx, obj, id, getter, setter, slot, attrs, flags, shortid);
|
||||
}
|
||||
|
||||
JSBool
|
||||
baseops::DefineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
|
||||
{
|
||||
return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -3842,7 +3847,7 @@ baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleVa
|
||||
Rooted<jsid> id(cx);
|
||||
if (index <= JSID_INT_MAX) {
|
||||
id = INT_TO_JSID(index);
|
||||
return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
}
|
||||
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
@ -3850,7 +3855,7 @@ baseops::DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleVa
|
||||
if (!IndexToId(cx, index, id.address()))
|
||||
return false;
|
||||
|
||||
return !!DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
return DefineNativeProperty(cx, obj, id, value, getter, setter, attrs, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3878,7 +3883,7 @@ CallAddPropertyHook(JSContext *cx, Class *clasp, HandleObject obj, HandleShape s
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
bool
|
||||
js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
|
||||
@ -3908,7 +3913,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
RootedObject pobj(cx);
|
||||
RootedShape prop(cx);
|
||||
if (!baseops::LookupProperty(cx, obj, id, &pobj, &prop))
|
||||
return NULL;
|
||||
return false;
|
||||
if (prop && pobj == obj) {
|
||||
shape = prop;
|
||||
if (shape->isAccessorDescriptor()) {
|
||||
@ -3921,7 +3926,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
? setter
|
||||
: shape->setter());
|
||||
if (!shape)
|
||||
return NULL;
|
||||
return false;
|
||||
} else {
|
||||
shape = NULL;
|
||||
}
|
||||
@ -3935,7 +3940,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
*/
|
||||
if (!(defineHow & DNP_DONT_PURGE)) {
|
||||
if (!js_PurgeScopeChain(cx, obj, id))
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Use the object's class getter and setter by default. */
|
||||
@ -3956,10 +3961,10 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
}
|
||||
|
||||
if (!shape) {
|
||||
shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
|
||||
shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT,
|
||||
attrs, flags, shortid);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Store valueCopy before calling addProperty, in case the latter GC's. */
|
||||
@ -3968,7 +3973,7 @@ js::DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
|
||||
|
||||
if (!CallAddPropertyHook(cx, clasp, obj, shape, value)) {
|
||||
obj->removeProperty(cx, id);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return shape;
|
||||
@ -4051,7 +4056,7 @@ CallResolveOp(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
objp.set(obj);
|
||||
}
|
||||
|
||||
Shape *shape;
|
||||
UnrootedShape shape;
|
||||
if (!objp->nativeEmpty() && (shape = objp->nativeLookup(cx, id)))
|
||||
propp.set(shape);
|
||||
else
|
||||
@ -4067,12 +4072,14 @@ LookupPropertyWithFlagsInline(JSContext *cx, HandleObject obj, HandleId id, unsi
|
||||
/* Search scopes starting with obj and following the prototype link. */
|
||||
RootedObject current(cx, obj);
|
||||
while (true) {
|
||||
Shape *shape = current->nativeLookup(cx, id);
|
||||
{
|
||||
UnrootedShape shape = current->nativeLookup(cx, id);
|
||||
if (shape) {
|
||||
objp.set(current);
|
||||
propp.set(shape);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try obj's class resolve hook if id was not found in obj's scope. */
|
||||
if (current->getClass()->resolve != JS_ResolveStub) {
|
||||
@ -4177,18 +4184,19 @@ js::LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleOb
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, JSObject *obj, JSObject *pobj,
|
||||
Shape *shape, unsigned getHow, Value *vp)
|
||||
js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, Handle<JSObject*> obj,
|
||||
Handle<JSObject*> pobj, Handle<Shape*> shape, unsigned getHow,
|
||||
MutableHandle<Value> vp)
|
||||
{
|
||||
JS_ASSERT(pobj->isNative());
|
||||
|
||||
if (shape->hasSlot()) {
|
||||
*vp = pobj->nativeGetSlot(shape->slot());
|
||||
JS_ASSERT(!vp->isMagic());
|
||||
vp.set(pobj->nativeGetSlot(shape->slot()));
|
||||
JS_ASSERT(!vp.isMagic());
|
||||
JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetter(),
|
||||
js::types::TypeHasProperty(cx, pobj->type(), shape->propid(), *vp));
|
||||
js::types::TypeHasProperty(cx, pobj->type(), shape->propid(), vp));
|
||||
} else {
|
||||
vp->setUndefined();
|
||||
vp.setUndefined();
|
||||
}
|
||||
if (shape->hasDefaultGetter())
|
||||
return true;
|
||||
@ -4201,24 +4209,19 @@ js_NativeGetInline(JSContext *cx, Handle<JSObject*> receiver, JSObject *obj, JSO
|
||||
code->accessGetter = true;
|
||||
}
|
||||
|
||||
Rooted<Shape*> shapeRoot(cx, shape);
|
||||
RootedObject pobjRoot(cx, pobj);
|
||||
RootedValue nvp(cx, *vp);
|
||||
|
||||
if (!shape->get(cx, receiver, obj, pobj, &nvp))
|
||||
if (!shape->get(cx, receiver, obj, pobj, vp))
|
||||
return false;
|
||||
|
||||
/* Update slotful shapes according to the value produced by the getter. */
|
||||
if (shapeRoot->hasSlot() && pobjRoot->nativeContains(cx, shapeRoot))
|
||||
pobjRoot->nativeSetSlot(shapeRoot->slot(), nvp);
|
||||
if (shape->hasSlot() && pobj->nativeContains(cx, shape))
|
||||
pobj->nativeSetSlot(shape->slot(), vp);
|
||||
|
||||
*vp = nvp;
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Shape *shape,
|
||||
unsigned getHow, Value *vp)
|
||||
js_NativeGet(JSContext *cx, Handle<JSObject*> obj, Handle<JSObject*> pobj, Handle<Shape*> shape,
|
||||
unsigned getHow, MutableHandle<Value> vp)
|
||||
{
|
||||
return js_NativeGetInline(cx, obj, obj, pobj, shape, getHow, vp);
|
||||
}
|
||||
@ -4358,7 +4361,7 @@ js_GetPropertyHelperInline(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
cx->propertyCache().fill(cx, obj, obj2, shape);
|
||||
|
||||
/* This call site is hot -- use the always-inlined variant of js_NativeGet(). */
|
||||
if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp.address()))
|
||||
if (!js_NativeGetInline(cx, receiver, obj, obj2, shape, getHow, vp))
|
||||
return JS_FALSE;
|
||||
|
||||
return JS_TRUE;
|
||||
@ -4638,7 +4641,7 @@ baseops::SetPropertyHelper(JSContext *cx, HandleObject obj, HandleObject receive
|
||||
if (!js_PurgeScopeChain(cx, obj, id))
|
||||
return JS_FALSE;
|
||||
|
||||
shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
|
||||
shape = JSObject::putProperty(cx, obj, id, getter, setter, SHAPE_INVALID_SLOT,
|
||||
attrs, flags, shortid);
|
||||
if (!shape)
|
||||
return JS_FALSE;
|
||||
@ -4809,7 +4812,7 @@ baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
|
||||
bool
|
||||
js::HasDataProperty(JSContext *cx, HandleObject obj, jsid id, Value *vp)
|
||||
{
|
||||
if (Shape *shape = obj->nativeLookup(cx, id)) {
|
||||
if (UnrootedShape shape = obj->nativeLookup(cx, id)) {
|
||||
if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
*vp = obj->nativeGetSlot(shape->slot());
|
||||
return true;
|
||||
@ -5158,7 +5161,7 @@ js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
||||
JSObject *obj = (JSObject *)trc->debugPrintArg;
|
||||
uint32_t slot = uint32_t(trc->debugPrintIndex);
|
||||
|
||||
Shape *shape;
|
||||
UnrootedShape shape;
|
||||
if (obj->isNative()) {
|
||||
shape = obj->lastProperty();
|
||||
while (shape && (!shape->hasSlot() || shape->slot() != slot))
|
||||
@ -5295,7 +5298,7 @@ DumpProperty(JSObject *obj, Shape &shape)
|
||||
jsid id = shape.propid();
|
||||
uint8_t attrs = shape.attributes();
|
||||
|
||||
fprintf(stderr, " ((Shape *) %p) ", (void *) &shape);
|
||||
fprintf(stderr, " ((JSShape *) %p) ", (void *) &shape);
|
||||
if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
|
||||
if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
|
||||
if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
|
||||
@ -5396,7 +5399,7 @@ JSObject::dump()
|
||||
|
||||
if (obj->isNative()) {
|
||||
fprintf(stderr, "properties:\n");
|
||||
Vector<Shape *, 8, SystemAllocPolicy> props;
|
||||
Vector<RawShape, 8, SystemAllocPolicy> props;
|
||||
for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront())
|
||||
props.append(&r.front());
|
||||
for (size_t i = props.length(); i-- != 0;)
|
||||
|
@ -21,9 +21,6 @@
|
||||
#include "jsclass.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsinfer.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jslock.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "gc/Heap.h"
|
||||
@ -38,6 +35,8 @@ class BaseProxyHandler;
|
||||
class CallObject;
|
||||
struct GCMarker;
|
||||
struct NativeIterator;
|
||||
ForwardDeclare(Shape);
|
||||
struct StackShape;
|
||||
|
||||
namespace mjit { class Compiler; }
|
||||
|
||||
@ -280,10 +279,10 @@ struct JSObject : public js::ObjectImpl
|
||||
* Update the last property, keeping the number of allocated slots in sync
|
||||
* with the object's new slot span.
|
||||
*/
|
||||
static bool setLastProperty(JSContext *cx, js::HandleObject obj, js::Shape *shape);
|
||||
static bool setLastProperty(JSContext *cx, JS::HandleObject obj, js::HandleShape shape);
|
||||
|
||||
/* As above, but does not change the slot span. */
|
||||
inline void setLastPropertyInfallible(js::Shape *shape);
|
||||
inline void setLastPropertyInfallible(js::UnrootedShape shape);
|
||||
|
||||
/* Make a non-array object with the specified initial state. */
|
||||
static inline JSObject *create(JSContext *cx,
|
||||
@ -726,7 +725,7 @@ struct JSObject : public js::ObjectImpl
|
||||
* after calling object-parameter-free shape methods, avoiding coupling
|
||||
* logic across the object vs. shape module wall.
|
||||
*/
|
||||
bool allocSlot(JSContext *cx, uint32_t *slotp);
|
||||
static bool allocSlot(JSContext *cx, JS::HandleObject obj, uint32_t *slotp);
|
||||
void freeSlot(uint32_t slot);
|
||||
|
||||
public:
|
||||
@ -744,7 +743,8 @@ struct JSObject : public js::ObjectImpl
|
||||
js::MutableHandleValue vp);
|
||||
|
||||
private:
|
||||
js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
|
||||
static js::UnrootedShape getChildProperty(JSContext *cx, JS::HandleObject obj,
|
||||
js::HandleShape parent, js::StackShape &child);
|
||||
|
||||
protected:
|
||||
/*
|
||||
@ -754,7 +754,8 @@ struct JSObject : public js::ObjectImpl
|
||||
* 1. getter and setter must be normalized based on flags (see jsscope.cpp).
|
||||
* 2. !isExtensible() checking must be done by callers.
|
||||
*/
|
||||
js::Shape *addPropertyInternal(JSContext *cx, jsid id,
|
||||
static js::UnrootedShape addPropertyInternal(JSContext *cx,
|
||||
JS::HandleObject obj, JS::HandleId id,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid, js::Shape **spp,
|
||||
@ -772,32 +773,37 @@ struct JSObject : public js::ObjectImpl
|
||||
|
||||
public:
|
||||
/* Add a property whose id is not yet in this scope. */
|
||||
js::Shape *addProperty(JSContext *cx, jsid id,
|
||||
static js::UnrootedShape addProperty(JSContext *cx, JS::HandleObject, JS::HandleId id,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid, bool allowDictionary = true);
|
||||
uint32_t slot, unsigned attrs, unsigned flags,
|
||||
int shortid, bool allowDictionary = true);
|
||||
|
||||
/* Add a data property whose id is not yet in this scope. */
|
||||
js::Shape *addDataProperty(JSContext *cx, jsid id, uint32_t slot, unsigned attrs) {
|
||||
js::UnrootedShape addDataProperty(JSContext *cx, jsid id_, uint32_t slot, unsigned attrs) {
|
||||
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||
return addProperty(cx, id, NULL, NULL, slot, attrs, 0, 0);
|
||||
js::RootedObject self(cx, this);
|
||||
js::RootedId id(cx, id_);
|
||||
return addProperty(cx, self, id, NULL, NULL, slot, attrs, 0, 0);
|
||||
}
|
||||
|
||||
/* Add or overwrite a property for id in this scope. */
|
||||
js::Shape *putProperty(JSContext *cx, jsid id,
|
||||
static js::UnrootedShape putProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid);
|
||||
inline js::Shape *
|
||||
putProperty(JSContext *cx, js::PropertyName *name,
|
||||
static js::UnrootedShape putProperty(JSContext *cx, JS::HandleObject obj,
|
||||
js::PropertyName *name,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs, unsigned flags, int shortid) {
|
||||
return putProperty(cx, js::NameToId(name), getter, setter, slot, attrs, flags, shortid);
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid)
|
||||
{
|
||||
js::RootedId id(cx, js::NameToId(name));
|
||||
return putProperty(cx, obj, id, getter, setter, slot, attrs, flags, shortid);
|
||||
}
|
||||
|
||||
/* Change the given property into a sibling with the same id in this scope. */
|
||||
static js::Shape *changeProperty(JSContext *cx, js::HandleObject obj,
|
||||
js::Shape *shape, unsigned attrs, unsigned mask,
|
||||
static js::UnrootedShape changeProperty(JSContext *cx, js::HandleObject obj,
|
||||
js::RawShape shape, unsigned attrs, unsigned mask,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter);
|
||||
|
||||
static inline bool changePropertyAttributes(JSContext *cx, js::HandleObject obj,
|
||||
@ -1176,14 +1182,14 @@ js_CreateThis(JSContext *cx, js::Class *clasp, js::HandleObject callee);
|
||||
* Find or create a property named by id in obj's scope, with the given getter
|
||||
* and setter, slot, attributes, and other members.
|
||||
*/
|
||||
extern js::Shape *
|
||||
js_AddNativeProperty(JSContext *cx, js::HandleObject obj, jsid id,
|
||||
extern js::UnrootedShape
|
||||
js_AddNativeProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JSPropertyOp getter, JSStrictPropertyOp setter, uint32_t slot,
|
||||
unsigned attrs, unsigned flags, int shortid);
|
||||
|
||||
extern JSBool
|
||||
js_DefineOwnProperty(JSContext *cx, js::HandleObject obj, js::HandleId id,
|
||||
const js::Value &descriptor, JSBool *bp);
|
||||
js_DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
const JS::Value &descriptor, JSBool *bp);
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -1203,12 +1209,12 @@ const unsigned DNP_SKIP_TYPE = 8; /* Don't update type information */
|
||||
/*
|
||||
* Return successfully added or changed shape or NULL on error.
|
||||
*/
|
||||
extern Shape *
|
||||
extern bool
|
||||
DefineNativeProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
unsigned flags, int shortid, unsigned defineHow = 0);
|
||||
|
||||
inline Shape *
|
||||
inline bool
|
||||
DefineNativeProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
|
||||
unsigned flags, int shortid, unsigned defineHow = 0)
|
||||
@ -1292,7 +1298,7 @@ const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode
|
||||
*/
|
||||
extern JSBool
|
||||
js_NativeGet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> pobj,
|
||||
js::Shape *shape, unsigned getHow, js::Value *vp);
|
||||
js::Handle<js::Shape*> shape, unsigned getHow, js::MutableHandle<js::Value> vp);
|
||||
|
||||
extern JSBool
|
||||
js_NativeSet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> receiver,
|
||||
|
@ -272,7 +272,7 @@ JSObject::dynamicSlotIndex(size_t slot)
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setLastPropertyInfallible(js::Shape *shape)
|
||||
JSObject::setLastPropertyInfallible(js::UnrootedShape shape)
|
||||
{
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
JS_ASSERT(shape->compartment() == compartment());
|
||||
@ -288,7 +288,8 @@ JSObject::removeLastProperty(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(canRemoveLastProperty());
|
||||
js::RootedObject self(cx, this);
|
||||
JS_ALWAYS_TRUE(setLastProperty(cx, self, lastProperty()->previous()));
|
||||
js::RootedShape prev(cx, lastProperty()->previous());
|
||||
JS_ALWAYS_TRUE(setLastProperty(cx, self, prev));
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -302,7 +303,7 @@ JSObject::canRemoveLastProperty()
|
||||
* converted to dictionary mode instead. See BaseShape comment in jsscope.h
|
||||
*/
|
||||
JS_ASSERT(!inDictionaryMode());
|
||||
js::Shape *previous = lastProperty()->previous();
|
||||
js::UnrootedShape previous = lastProperty()->previous().get();
|
||||
return previous->getObjectParent() == lastProperty()->getObjectParent()
|
||||
&& previous->getObjectFlags() == lastProperty()->getObjectFlags();
|
||||
}
|
||||
@ -1522,7 +1523,8 @@ CopyInitializerObject(JSContext *cx, HandleObject baseobj)
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (!JSObject::setLastProperty(cx, obj, baseobj->lastProperty()))
|
||||
RootedShape lastProp(cx, baseobj->lastProperty());
|
||||
if (!JSObject::setLastProperty(cx, obj, lastProp))
|
||||
return NULL;
|
||||
|
||||
return obj;
|
||||
@ -1558,7 +1560,7 @@ GuessArrayGCKind(size_t numSlots)
|
||||
* may or may not need dynamic slots.
|
||||
*/
|
||||
inline bool
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, Shape *shape, HeapSlot **slots)
|
||||
PreallocateObjectDynamicSlots(JSContext *cx, UnrootedShape shape, HeapSlot **slots)
|
||||
{
|
||||
if (size_t count = JSObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
|
||||
*slots = cx->pod_malloc<HeapSlot>(count);
|
||||
@ -1673,10 +1675,10 @@ js_InitClass(JSContext *cx, js::HandleObject obj, JSObject *parent_proto,
|
||||
* (i.e., obj has ever been on a prototype or parent chain).
|
||||
*/
|
||||
extern bool
|
||||
js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id);
|
||||
js_PurgeScopeChainHelper(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
|
||||
|
||||
inline bool
|
||||
js_PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
|
||||
js_PurgeScopeChain(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
||||
{
|
||||
if (obj->isDelegate())
|
||||
return js_PurgeScopeChainHelper(cx, obj, id);
|
||||
|
@ -35,7 +35,7 @@ js::PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
|
||||
|
||||
JS_ASSERT(this == &cx->propertyCache());
|
||||
|
||||
Shape *kshape = obj->lastProperty();
|
||||
UnrootedShape kshape = obj->lastProperty();
|
||||
entry = &table[hash(pc, kshape)];
|
||||
PCMETER(pctestentry = entry);
|
||||
PCMETER(tests++);
|
||||
@ -64,9 +64,11 @@ JS_ALWAYS_INLINE bool
|
||||
js::PropertyCache::testForSet(JSContext *cx, jsbytecode *pc, JSObject *obj,
|
||||
PropertyCacheEntry **entryp, JSObject **obj2p, PropertyName **namep)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
|
||||
JS_ASSERT(this == &cx->propertyCache());
|
||||
|
||||
Shape *kshape = obj->lastProperty();
|
||||
UnrootedShape kshape = obj->lastProperty();
|
||||
PropertyCacheEntry *entry = &table[hash(pc, kshape)];
|
||||
*entryp = entry;
|
||||
PCMETER(pctestentry = entry);
|
||||
|
@ -30,19 +30,17 @@ ShapeHasher::match(const Key k, const Lookup &l)
|
||||
return k->matches(l);
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
PropertyTree::newShape(JSContext *cx)
|
||||
{
|
||||
Shape *shape = js_NewGCShape(cx);
|
||||
if (!shape) {
|
||||
UnrootedShape shape = js_NewGCShape(cx);
|
||||
if (!shape)
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return shape;
|
||||
}
|
||||
|
||||
static KidsHash *
|
||||
HashChildren(Shape *kid1, Shape *kid2)
|
||||
HashChildren(UnrootedShape kid1, UnrootedShape kid2)
|
||||
{
|
||||
KidsHash *hash = js_new<KidsHash>();
|
||||
if (!hash || !hash->init(2)) {
|
||||
@ -56,7 +54,7 @@ HashChildren(Shape *kid1, Shape *kid2)
|
||||
}
|
||||
|
||||
bool
|
||||
PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
|
||||
PropertyTree::insertChild(JSContext *cx, UnrootedShape parent, UnrootedShape child)
|
||||
{
|
||||
JS_ASSERT(!parent->inDictionary());
|
||||
JS_ASSERT(!child->parent);
|
||||
@ -73,7 +71,7 @@ PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
|
||||
}
|
||||
|
||||
if (kidp->isShape()) {
|
||||
Shape *shape = kidp->toShape();
|
||||
UnrootedShape shape = kidp->toShape();
|
||||
JS_ASSERT(shape != child);
|
||||
JS_ASSERT(!shape->matches(child));
|
||||
|
||||
@ -97,7 +95,7 @@ PropertyTree::insertChild(JSContext *cx, Shape *parent, Shape *child)
|
||||
}
|
||||
|
||||
void
|
||||
Shape::removeChild(Shape *child)
|
||||
Shape::removeChild(UnrootedShape child)
|
||||
{
|
||||
JS_ASSERT(!child->inDictionary());
|
||||
JS_ASSERT(child->parent == this);
|
||||
@ -127,12 +125,13 @@ Shape::removeChild(Shape *child)
|
||||
}
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const StackShape &child)
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
Shape *shape = NULL;
|
||||
{
|
||||
UnrootedShape shape = NULL;
|
||||
|
||||
JS_ASSERT(parent_);
|
||||
|
||||
@ -146,7 +145,7 @@ PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const Sta
|
||||
*/
|
||||
KidsPointer *kidp = &parent_->kids;
|
||||
if (kidp->isShape()) {
|
||||
Shape *kid = kidp->toShape();
|
||||
UnrootedShape kid = kidp->toShape();
|
||||
if (kid->matches(child))
|
||||
shape = kid;
|
||||
} else if (kidp->isHash()) {
|
||||
@ -183,18 +182,19 @@ PropertyTree::getChild(JSContext *cx, Shape *parent_, uint32_t nfixed, const Sta
|
||||
|
||||
if (shape)
|
||||
return shape;
|
||||
}
|
||||
|
||||
StackShape::AutoRooter childRoot(cx, &child);
|
||||
RootedShape parent(cx, parent_);
|
||||
|
||||
shape = newShape(cx);
|
||||
UnrootedShape shape = newShape(cx);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
new (shape) Shape(child, nfixed);
|
||||
|
||||
if (!insertChild(cx, parent, shape))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
return shape;
|
||||
}
|
||||
@ -236,7 +236,7 @@ Shape::finalize(FreeOp *fop)
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
KidsPointer::checkConsistency(Shape *aKid) const
|
||||
KidsPointer::checkConsistency(UnrootedShape aKid) const
|
||||
{
|
||||
if (isShape()) {
|
||||
JS_ASSERT(toShape() == aKid);
|
||||
@ -323,13 +323,13 @@ Shape::dumpSubtree(JSContext *cx, int level, FILE *fp) const
|
||||
if (!kids.isNull()) {
|
||||
++level;
|
||||
if (kids.isShape()) {
|
||||
Shape *kid = kids.toShape();
|
||||
UnrootedShape kid = kids.toShape();
|
||||
JS_ASSERT(kid->parent == this);
|
||||
kid->dumpSubtree(cx, level, fp);
|
||||
} else {
|
||||
const KidsHash &hash = *kids.toHash();
|
||||
for (KidsHash::Range range = hash.all(); !range.empty(); range.popFront()) {
|
||||
Shape *kid = range.front();
|
||||
RawShape kid = range.front();
|
||||
|
||||
JS_ASSERT(kid->parent == this);
|
||||
kid->dumpSubtree(cx, level, fp);
|
||||
@ -363,7 +363,7 @@ js::PropertyTree::dumpShapes(JSRuntime *rt)
|
||||
typedef JSCompartment::EmptyShapeSet HS;
|
||||
HS &h = c->emptyShapes;
|
||||
for (HS::Range r = h.all(); !r.empty(); r.popFront()) {
|
||||
Shape *empty = r.front();
|
||||
RawShape empty = r.front();
|
||||
empty->dumpSubtree(rt, 0, dumpfp);
|
||||
putc('\n', dumpfp);
|
||||
}
|
||||
|
@ -7,21 +7,22 @@
|
||||
#ifndef jspropertytree_h___
|
||||
#define jspropertytree_h___
|
||||
|
||||
#include "jsprvtd.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
ForwardDeclare(Shape);
|
||||
struct StackShape;
|
||||
|
||||
struct ShapeHasher {
|
||||
typedef js::Shape *Key;
|
||||
typedef js::StackShape Lookup;
|
||||
typedef RawShape Key;
|
||||
typedef StackShape Lookup;
|
||||
|
||||
static inline HashNumber hash(const Lookup &l);
|
||||
static inline bool match(Key k, const Lookup &l);
|
||||
};
|
||||
|
||||
typedef HashSet<js::Shape *, ShapeHasher, SystemAllocPolicy> KidsHash;
|
||||
typedef HashSet<RawShape, ShapeHasher, SystemAllocPolicy> KidsHash;
|
||||
|
||||
class KidsPointer {
|
||||
private:
|
||||
@ -38,14 +39,14 @@ class KidsPointer {
|
||||
void setNull() { w = 0; }
|
||||
|
||||
bool isShape() const { return (w & TAG) == SHAPE && !isNull(); }
|
||||
js::Shape *toShape() const {
|
||||
UnrootedShape toShape() const {
|
||||
JS_ASSERT(isShape());
|
||||
return reinterpret_cast<js::Shape *>(w & ~uintptr_t(TAG));
|
||||
return reinterpret_cast<RawShape>(w & ~uintptr_t(TAG));
|
||||
}
|
||||
void setShape(js::Shape *shape) {
|
||||
void setShape(UnrootedShape shape) {
|
||||
JS_ASSERT(shape);
|
||||
JS_ASSERT((reinterpret_cast<uintptr_t>(shape) & TAG) == 0);
|
||||
w = reinterpret_cast<uintptr_t>(shape) | SHAPE;
|
||||
JS_ASSERT((reinterpret_cast<uintptr_t>(static_cast<RawShape>(shape)) & TAG) == 0);
|
||||
w = reinterpret_cast<uintptr_t>(static_cast<RawShape>(shape)) | SHAPE;
|
||||
}
|
||||
|
||||
bool isHash() const { return (w & TAG) == HASH; }
|
||||
@ -60,7 +61,7 @@ class KidsPointer {
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void checkConsistency(js::Shape *aKid) const;
|
||||
void checkConsistency(UnrootedShape aKid) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -70,7 +71,7 @@ class PropertyTree
|
||||
|
||||
JSCompartment *compartment;
|
||||
|
||||
bool insertChild(JSContext *cx, js::Shape *parent, js::Shape *child);
|
||||
bool insertChild(JSContext *cx, UnrootedShape parent, UnrootedShape child);
|
||||
|
||||
PropertyTree();
|
||||
|
||||
@ -82,12 +83,11 @@ class PropertyTree
|
||||
{
|
||||
}
|
||||
|
||||
js::Shape *newShape(JSContext *cx);
|
||||
js::Shape *getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child);
|
||||
UnrootedShape newShape(JSContext *cx);
|
||||
UnrootedShape getChild(JSContext *cx, Shape *parent, uint32_t nfixed, const StackShape &child);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void dumpShapes(JSRuntime *rt);
|
||||
static void meter(JSBasicStats *bs, js::Shape *node);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -142,15 +142,7 @@ class InlineMap;
|
||||
|
||||
class LifoAlloc;
|
||||
|
||||
class BaseShape;
|
||||
class UnownedBaseShape;
|
||||
struct Shape;
|
||||
struct EmptyShape;
|
||||
class ShapeKindArray;
|
||||
class Bindings;
|
||||
|
||||
struct StackBaseShape;
|
||||
struct StackShape;
|
||||
|
||||
class Breakpoint;
|
||||
class BreakpointSite;
|
||||
@ -207,7 +199,6 @@ struct TypeCompartment;
|
||||
} /* namespace types */
|
||||
|
||||
typedef JS::Handle<Shape*> HandleShape;
|
||||
typedef JS::Handle<BaseShape*> HandleBaseShape;
|
||||
typedef JS::Handle<types::TypeObject*> HandleTypeObject;
|
||||
typedef JS::Handle<JSAtom*> HandleAtom;
|
||||
typedef JS::Handle<PropertyName*> HandlePropertyName;
|
||||
@ -218,7 +209,6 @@ typedef JS::MutableHandle<JSAtom*> MutableHandleAtom;
|
||||
typedef JSAtom * RawAtom;
|
||||
|
||||
typedef js::Rooted<Shape*> RootedShape;
|
||||
typedef js::Rooted<BaseShape*> RootedBaseShape;
|
||||
typedef js::Rooted<types::TypeObject*> RootedTypeObject;
|
||||
typedef js::Rooted<JSAtom*> RootedAtom;
|
||||
typedef js::Rooted<PropertyName*> RootedPropertyName;
|
||||
|
@ -37,7 +37,7 @@ using namespace js::gc;
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
bool
|
||||
ShapeTable::init(JSRuntime *rt, Shape *lastProp)
|
||||
ShapeTable::init(JSRuntime *rt, UnrootedShape lastProp)
|
||||
{
|
||||
/*
|
||||
* Either we're creating a table for a large scope that was populated
|
||||
@ -92,7 +92,7 @@ Shape::makeOwnBaseShape(JSContext *cx, HandleShape shape)
|
||||
}
|
||||
|
||||
void
|
||||
Shape::handoffTableTo(Shape *shape)
|
||||
Shape::handoffTableTo(UnrootedShape shape)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(inDictionary() && shape->inDictionary());
|
||||
@ -273,7 +273,7 @@ ShapeTable::grow(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
Shape::getChildBinding(JSContext *cx, const StackShape &child)
|
||||
{
|
||||
AssertCanGC();
|
||||
@ -287,12 +287,10 @@ Shape::getChildBinding(JSContext *cx, const StackShape &child)
|
||||
return cx->propertyTree().getChild(cx, this, nfixed, child);
|
||||
}
|
||||
|
||||
/* static */ Shape *
|
||||
/* static */ UnrootedShape
|
||||
Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
TaggedProto proto, Shape *shape_)
|
||||
TaggedProto proto, HandleShape shape)
|
||||
{
|
||||
RootedShape shape(cx, shape_);
|
||||
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
|
||||
if (!shape->parent) {
|
||||
@ -307,7 +305,7 @@ Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
{
|
||||
UnrootedUnownedBaseShape nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
child.base = nbase;
|
||||
}
|
||||
@ -320,8 +318,8 @@ Shape::replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
* which must be lastProperty() if inDictionaryMode(), else parent must be
|
||||
* one of lastProperty() or lastProperty()->parent.
|
||||
*/
|
||||
Shape *
|
||||
JSObject::getChildProperty(JSContext *cx, Shape *parent, StackShape &child)
|
||||
/* static */ UnrootedShape
|
||||
JSObject::getChildProperty(JSContext *cx, HandleObject obj, HandleShape parent, StackShape &child)
|
||||
{
|
||||
/*
|
||||
* Shared properties have no slot, but slot_ will reflect that of parent.
|
||||
@ -333,40 +331,38 @@ JSObject::getChildProperty(JSContext *cx, Shape *parent, StackShape &child)
|
||||
} else {
|
||||
if (child.hasMissingSlot()) {
|
||||
uint32_t slot;
|
||||
if (!allocSlot(cx, &slot))
|
||||
return NULL;
|
||||
if (!allocSlot(cx, obj, &slot))
|
||||
return UnrootedShape(NULL);
|
||||
child.setSlot(slot);
|
||||
} else {
|
||||
/* Slots can only be allocated out of order on objects in dictionary mode. */
|
||||
JS_ASSERT(inDictionaryMode() ||
|
||||
JS_ASSERT(obj->inDictionaryMode() ||
|
||||
parent->hasMissingSlot() ||
|
||||
child.slot() == parent->maybeSlot() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Shape *shape;
|
||||
RootedShape shape(cx);
|
||||
|
||||
RootedObject self(cx, this);
|
||||
|
||||
if (inDictionaryMode()) {
|
||||
JS_ASSERT(parent == lastProperty());
|
||||
if (obj->inDictionaryMode()) {
|
||||
JS_ASSERT(parent == obj->lastProperty());
|
||||
StackShape::AutoRooter childRoot(cx, &child);
|
||||
shape = js_NewGCShape(cx);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
if (child.hasSlot() && child.slot() >= self->lastProperty()->base()->slotSpan()) {
|
||||
if (!JSObject::setSlotSpan(cx, self, child.slot() + 1))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
if (child.hasSlot() && child.slot() >= obj->lastProperty()->base()->slotSpan()) {
|
||||
if (!JSObject::setSlotSpan(cx, obj, child.slot() + 1))
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
shape->initDictionaryShape(child, self->numFixedSlots(), &self->shape_);
|
||||
shape->initDictionaryShape(child, obj->numFixedSlots(), &obj->shape_);
|
||||
} else {
|
||||
shape = cx->propertyTree().getChild(cx, parent, self->numFixedSlots(), child);
|
||||
shape = cx->propertyTree().getChild(cx, parent, obj->numFixedSlots(), child);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
//JS_ASSERT(shape->parent == parent);
|
||||
//JS_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
|
||||
if (!JSObject::setLastProperty(cx, self, shape))
|
||||
return NULL;
|
||||
if (!JSObject::setLastProperty(cx, obj, shape))
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
return shape;
|
||||
@ -397,7 +393,7 @@ JSObject::toDictionaryMode(JSContext *cx)
|
||||
while (shape) {
|
||||
JS_ASSERT(!shape->inDictionary());
|
||||
|
||||
Shape *dprop = js_NewGCShape(cx);
|
||||
UnrootedShape dprop = js_NewGCShape(cx);
|
||||
if (!dprop) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
@ -452,65 +448,60 @@ NormalizeGetterAndSetter(JSObject *obj,
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
JSObject::addProperty(JSContext *cx, jsid id,
|
||||
/* static */ UnrootedShape
|
||||
JSObject::addProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
PropertyOp getter, StrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid, bool allowDictionary)
|
||||
{
|
||||
JS_ASSERT(!JSID_IS_VOID(id));
|
||||
|
||||
if (!isExtensible()) {
|
||||
reportNotExtensible(cx);
|
||||
return NULL;
|
||||
if (!obj->isExtensible()) {
|
||||
obj->reportNotExtensible(cx);
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
NormalizeGetterAndSetter(this, id, attrs, flags, getter, setter);
|
||||
|
||||
RootedObject self(cx, this);
|
||||
NormalizeGetterAndSetter(obj, id, attrs, flags, getter, setter);
|
||||
|
||||
Shape **spp = NULL;
|
||||
if (inDictionaryMode())
|
||||
spp = lastProperty()->table().search(id, true);
|
||||
if (obj->inDictionaryMode())
|
||||
spp = obj->lastProperty()->table().search(id, true);
|
||||
|
||||
return self->addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid,
|
||||
return addPropertyInternal(cx, obj, id, getter, setter, slot, attrs, flags, shortid,
|
||||
spp, allowDictionary);
|
||||
}
|
||||
|
||||
Shape *
|
||||
JSObject::addPropertyInternal(JSContext *cx, jsid id_,
|
||||
/* static */ UnrootedShape
|
||||
JSObject::addPropertyInternal(JSContext *cx, HandleObject obj, HandleId id,
|
||||
PropertyOp getter, StrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid, Shape **spp,
|
||||
bool allowDictionary)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT_IF(!allowDictionary, !inDictionaryMode());
|
||||
|
||||
RootedId id(cx, id_);
|
||||
RootedObject self(cx, this);
|
||||
JS_ASSERT_IF(!allowDictionary, !obj->inDictionaryMode());
|
||||
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
|
||||
ShapeTable *table = NULL;
|
||||
if (!inDictionaryMode()) {
|
||||
if (!obj->inDictionaryMode()) {
|
||||
bool stableSlot =
|
||||
(slot == SHAPE_INVALID_SLOT) ||
|
||||
lastProperty()->hasMissingSlot() ||
|
||||
(slot == lastProperty()->maybeSlot() + 1);
|
||||
obj->lastProperty()->hasMissingSlot() ||
|
||||
(slot == obj->lastProperty()->maybeSlot() + 1);
|
||||
JS_ASSERT_IF(!allowDictionary, stableSlot);
|
||||
if (allowDictionary &&
|
||||
(!stableSlot || lastProperty()->entryCount() >= PropertyTree::MAX_HEIGHT)) {
|
||||
if (!toDictionaryMode(cx))
|
||||
return NULL;
|
||||
table = &self->lastProperty()->table();
|
||||
(!stableSlot || obj->lastProperty()->entryCount() >= PropertyTree::MAX_HEIGHT)) {
|
||||
if (!obj->toDictionaryMode(cx))
|
||||
return UnrootedShape(NULL);
|
||||
table = &obj->lastProperty()->table();
|
||||
spp = table->search(id, true);
|
||||
}
|
||||
} else {
|
||||
table = &lastProperty()->table();
|
||||
table = &obj->lastProperty()->table();
|
||||
if (table->needsToGrow()) {
|
||||
if (!table->grow(cx))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
spp = table->search(id, true);
|
||||
JS_ASSERT(!SHAPE_FETCH(spp));
|
||||
}
|
||||
@ -519,37 +510,36 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id_,
|
||||
JS_ASSERT(!!table == !!spp);
|
||||
|
||||
/* Find or create a property tree node labeled by our arguments. */
|
||||
Shape *shape;
|
||||
UnrootedShape shape;
|
||||
{
|
||||
shape = self->lastProperty();
|
||||
RootedShape last(cx, obj->lastProperty());
|
||||
|
||||
uint32_t index;
|
||||
bool indexed = js_IdIsIndex(id, &index);
|
||||
|
||||
UnrootedUnownedBaseShape nbase;
|
||||
if (shape->base()->matchesGetterSetter(getter, setter) && !indexed) {
|
||||
nbase = shape->base()->unowned();
|
||||
if (last->base()->matchesGetterSetter(getter, setter) && !indexed) {
|
||||
nbase = last->base()->unowned();
|
||||
} else {
|
||||
StackBaseShape base(shape->base());
|
||||
StackBaseShape base(last->base());
|
||||
base.updateGetterSetter(attrs, getter, setter);
|
||||
if (indexed)
|
||||
base.flags |= BaseShape::INDEXED;
|
||||
nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
StackShape child(nbase, id, slot, self->numFixedSlots(), attrs, flags, shortid);
|
||||
DropUnrooted(nbase);
|
||||
shape = self->getChildProperty(cx, self->lastProperty(), child);
|
||||
StackShape child(DropUnrooted(nbase), id, slot, obj->numFixedSlots(), attrs, flags, shortid);
|
||||
shape = getChildProperty(cx, obj, last, child);
|
||||
}
|
||||
|
||||
if (shape) {
|
||||
JS_ASSERT(shape == self->lastProperty());
|
||||
JS_ASSERT(shape == obj->lastProperty());
|
||||
|
||||
if (table) {
|
||||
/* Store the tree node pointer in the table entry for id. */
|
||||
SHAPE_STORE_PRESERVING_COLLISION(spp, shape);
|
||||
SHAPE_STORE_PRESERVING_COLLISION(spp, static_cast<RawShape>(shape));
|
||||
++table->entryCount;
|
||||
|
||||
/* Pass the table along to the new last property, namely shape. */
|
||||
@ -557,12 +547,12 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id_,
|
||||
shape->parent->handoffTableTo(shape);
|
||||
}
|
||||
|
||||
self->checkShapeConsistency();
|
||||
obj->checkShapeConsistency();
|
||||
return shape;
|
||||
}
|
||||
|
||||
self->checkShapeConsistency();
|
||||
return NULL;
|
||||
obj->checkShapeConsistency();
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -589,41 +579,39 @@ CheckCanChangeAttrs(JSContext *cx, JSObject *obj, Shape *shape, unsigned *attrsp
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
JSObject::putProperty(JSContext *cx, jsid id_,
|
||||
/* static */ UnrootedShape
|
||||
JSObject::putProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
PropertyOp getter, StrictPropertyOp setter,
|
||||
uint32_t slot, unsigned attrs,
|
||||
unsigned flags, int shortid)
|
||||
{
|
||||
RootedId id(cx, id_);
|
||||
JS_ASSERT(!JSID_IS_VOID(id));
|
||||
|
||||
NormalizeGetterAndSetter(this, id, attrs, flags, getter, setter);
|
||||
NormalizeGetterAndSetter(obj, id, attrs, flags, getter, setter);
|
||||
|
||||
RootedObject self(cx, this);
|
||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||
|
||||
/* Search for id in order to claim its entry if table has been allocated. */
|
||||
Shape **spp;
|
||||
RootedShape shape(cx, Shape::search(cx, lastProperty(), id, &spp, true));
|
||||
RootedShape shape(cx, Shape::search(cx, obj->lastProperty(), id, &spp, true));
|
||||
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);
|
||||
return NULL;
|
||||
if (!obj->isExtensible()) {
|
||||
obj->reportNotExtensible(cx);
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
return self->addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid, spp, true);
|
||||
return addPropertyInternal(cx, obj, 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));
|
||||
|
||||
if (!CheckCanChangeAttrs(cx, self, shape, &attrs))
|
||||
return NULL;
|
||||
if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
/*
|
||||
* If the caller wants to allocate a slot, but doesn't care which slot,
|
||||
@ -639,13 +627,13 @@ JSObject::putProperty(JSContext *cx, jsid id_,
|
||||
{
|
||||
uint32_t index;
|
||||
bool indexed = js_IdIsIndex(id, &index);
|
||||
StackBaseShape base(self->lastProperty()->base());
|
||||
StackBaseShape base(obj->lastProperty()->base());
|
||||
base.updateGetterSetter(attrs, getter, setter);
|
||||
if (indexed)
|
||||
base.flags |= BaseShape::INDEXED;
|
||||
nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -660,33 +648,33 @@ 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))
|
||||
return NULL;
|
||||
spp = self->lastProperty()->table().search(shape->propid(), false);
|
||||
if (shape != obj->lastProperty() && !obj->inDictionaryMode()) {
|
||||
if (!obj->toDictionaryMode(cx))
|
||||
return UnrootedShape(NULL);
|
||||
spp = obj->lastProperty()->table().search(shape->propid(), false);
|
||||
shape = SHAPE_FETCH(spp);
|
||||
}
|
||||
|
||||
JS_ASSERT_IF(shape->hasSlot() && !(attrs & JSPROP_SHARED), shape->slot() == slot);
|
||||
|
||||
if (self->inDictionaryMode()) {
|
||||
if (obj->inDictionaryMode()) {
|
||||
/*
|
||||
* Updating some property in a dictionary-mode object. Create a new
|
||||
* shape for the existing property, and also generate a new shape for
|
||||
* the last property of the dictionary (unless the modified property
|
||||
* is also the last property).
|
||||
*/
|
||||
bool updateLast = (shape == self->lastProperty());
|
||||
shape = self->replaceWithNewEquivalentShape(cx, shape);
|
||||
bool updateLast = (shape == obj->lastProperty());
|
||||
shape = obj->replaceWithNewEquivalentShape(cx, shape);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
if (!updateLast && !self->generateOwnShape(cx))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
if (!updateLast && !obj->generateOwnShape(cx))
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
/* 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))
|
||||
return NULL;
|
||||
if (!allocSlot(cx, obj, &slot))
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
if (updateLast)
|
||||
@ -703,23 +691,24 @@ JSObject::putProperty(JSContext *cx, jsid id_,
|
||||
* Updating the last property in a non-dictionary-mode object. Find an
|
||||
* alternate shared child of the last property's previous shape.
|
||||
*/
|
||||
StackBaseShape base(self->lastProperty()->base());
|
||||
StackBaseShape base(obj->lastProperty()->base());
|
||||
base.updateGetterSetter(attrs, getter, setter);
|
||||
|
||||
UnrootedUnownedBaseShape nbase = BaseShape::getUnowned(cx, base);
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
JS_ASSERT(shape == self->lastProperty());
|
||||
JS_ASSERT(shape == obj->lastProperty());
|
||||
|
||||
/* Find or create a property tree node labeled by our arguments. */
|
||||
StackShape child(nbase, id, slot, self->numFixedSlots(), attrs, flags, shortid);
|
||||
StackShape child(nbase, id, slot, obj->numFixedSlots(), attrs, flags, shortid);
|
||||
DropUnrooted(nbase);
|
||||
Shape *newShape = self->getChildProperty(cx, shape->parent, child);
|
||||
RootedShape parent(cx, shape->parent);
|
||||
UnrootedShape newShape = JSObject::getChildProperty(cx, obj, parent, child);
|
||||
|
||||
if (!newShape) {
|
||||
self->checkShapeConsistency();
|
||||
return NULL;
|
||||
obj->checkShapeConsistency();
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
shape = newShape;
|
||||
@ -732,18 +721,18 @@ 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(oldSlot);
|
||||
if (oldSlot < obj->slotSpan())
|
||||
obj->freeSlot(oldSlot);
|
||||
++cx->runtime->propertyRemovals;
|
||||
}
|
||||
|
||||
self->checkShapeConsistency();
|
||||
obj->checkShapeConsistency();
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
/* static */ Shape *
|
||||
JSObject::changeProperty(JSContext *cx, HandleObject obj, Shape *shape, unsigned attrs, unsigned mask,
|
||||
/* static */ UnrootedShape
|
||||
JSObject::changeProperty(JSContext *cx, HandleObject obj, RawShape shape, unsigned attrs, unsigned mask,
|
||||
PropertyOp getter, StrictPropertyOp setter)
|
||||
{
|
||||
JS_ASSERT(obj->nativeContainsNoAllocation(*shape));
|
||||
@ -764,7 +753,7 @@ JSObject::changeProperty(JSContext *cx, HandleObject obj, Shape *shape, unsigned
|
||||
setter = NULL;
|
||||
|
||||
if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
if (shape->attrs == attrs && shape->getter() == getter && shape->setter() == setter)
|
||||
return shape;
|
||||
@ -775,7 +764,8 @@ JSObject::changeProperty(JSContext *cx, HandleObject obj, Shape *shape, unsigned
|
||||
* removeProperty because it will free an allocated shape->slot, and
|
||||
* putProperty won't re-allocate it.
|
||||
*/
|
||||
Shape *newShape = obj->putProperty(cx, shape->propid(), getter, setter, shape->maybeSlot(),
|
||||
RootedId propid(cx, shape->propid());
|
||||
UnrootedShape newShape = putProperty(cx, obj, propid, getter, setter, shape->maybeSlot(),
|
||||
attrs, shape->flags, shape->maybeShortid());
|
||||
|
||||
obj->checkShapeConsistency();
|
||||
@ -862,18 +852,20 @@ JSObject::removeProperty(JSContext *cx, jsid id_)
|
||||
* checks not to alter significantly the complexity of the
|
||||
* delete in debug builds, see bug 534493.
|
||||
*/
|
||||
Shape *aprop = self->lastProperty();
|
||||
UnrootedShape aprop = self->lastProperty();
|
||||
for (int n = 50; --n >= 0 && aprop->parent; aprop = aprop->parent)
|
||||
JS_ASSERT_IF(aprop != shape, self->nativeContainsNoAllocation(*aprop));
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
/* Remove shape from its non-circular doubly linked list. */
|
||||
Shape *oldLastProp = self->lastProperty();
|
||||
UnrootedShape oldLastProp = self->lastProperty();
|
||||
shape->removeFromDictionary(self);
|
||||
|
||||
/* Hand off table from the old to new last property. */
|
||||
oldLastProp->handoffTableTo(self->lastProperty());
|
||||
}
|
||||
|
||||
/* Generate a new shape for the object, infallibly. */
|
||||
JS_ALWAYS_TRUE(self->generateOwnShape(cx, spare));
|
||||
@ -900,7 +892,7 @@ JSObject::removeProperty(JSContext *cx, jsid id_)
|
||||
/* static */ void
|
||||
JSObject::clear(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
Shape *shape = obj->lastProperty();
|
||||
RootedShape shape(cx, obj->lastProperty());
|
||||
JS_ASSERT(obj->inDictionaryMode() == shape->inDictionary());
|
||||
|
||||
while (shape->parent) {
|
||||
@ -936,6 +928,7 @@ JSObject::rollbackProperties(JSContext *cx, uint32_t slotSpan)
|
||||
Shape *
|
||||
JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *newShape)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(cx->compartment == oldShape->compartment());
|
||||
JS_ASSERT_IF(oldShape != lastProperty(),
|
||||
inDictionaryMode() &&
|
||||
@ -1016,7 +1009,7 @@ JSObject::setParent(JSContext *cx, HandleObject obj, HandleObject parent)
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *newShape = Shape::setObjectParent(cx, parent, obj->getTaggedProto(), obj->shape_);
|
||||
UnrootedShape newShape = Shape::setObjectParent(cx, parent, obj->getTaggedProto(), obj->shape_);
|
||||
if (!newShape)
|
||||
return false;
|
||||
|
||||
@ -1024,7 +1017,7 @@ JSObject::setParent(JSContext *cx, HandleObject obj, HandleObject parent)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ Shape *
|
||||
/* static */ UnrootedShape
|
||||
Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape *last)
|
||||
{
|
||||
if (last->getObjectParent() == parent)
|
||||
@ -1033,7 +1026,8 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape
|
||||
StackBaseShape base(last);
|
||||
base.parent = parent;
|
||||
|
||||
return replaceLastProperty(cx, base, proto, last);
|
||||
RootedShape lastRoot(cx, last);
|
||||
return replaceLastProperty(cx, base, proto, lastRoot);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1080,7 +1074,7 @@ JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateSha
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *newShape = Shape::setObjectFlag(cx, flag, getTaggedProto(), lastProperty());
|
||||
UnrootedShape newShape = Shape::setObjectFlag(cx, flag, getTaggedProto(), lastProperty());
|
||||
if (!newShape)
|
||||
return false;
|
||||
|
||||
@ -1088,7 +1082,7 @@ JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateSha
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ Shape *
|
||||
/* static */ UnrootedShape
|
||||
Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last)
|
||||
{
|
||||
if (last->getObjectFlags() & flag)
|
||||
@ -1097,7 +1091,8 @@ Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Sha
|
||||
StackBaseShape base(last);
|
||||
base.flags |= flag;
|
||||
|
||||
return replaceLastProperty(cx, base, proto, last);
|
||||
RootedShape lastRoot(cx, last);
|
||||
return replaceLastProperty(cx, base, proto, lastRoot);
|
||||
}
|
||||
|
||||
/* static */ inline HashNumber
|
||||
@ -1238,7 +1233,7 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto, JSOb
|
||||
if (!nbase)
|
||||
return NULL;
|
||||
|
||||
Shape *shape = cx->propertyTree().newShape(cx);
|
||||
UnrootedShape shape = cx->propertyTree().newShape(cx);
|
||||
if (!shape)
|
||||
return NULL;
|
||||
new (shape) EmptyShape(nbase, nfixed);
|
||||
@ -1253,8 +1248,9 @@ EmptyShape::getInitialShape(JSContext *cx, Class *clasp, TaggedProto proto, JSOb
|
||||
}
|
||||
|
||||
void
|
||||
NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto_)
|
||||
NewObjectCache::invalidateEntriesForShape(JSContext *cx, HandleShape shape, HandleObject proto)
|
||||
{
|
||||
AssertCanGC();
|
||||
Class *clasp = shape->getObjectClass();
|
||||
|
||||
gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
|
||||
@ -1262,8 +1258,7 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject
|
||||
kind = GetBackgroundAllocKind(kind);
|
||||
|
||||
Rooted<GlobalObject *> global(cx, &shape->getObjectParent()->global());
|
||||
RootedObject proto(cx, proto_);
|
||||
types::TypeObject *type = proto->getNewType(cx);
|
||||
Rooted<types::TypeObject *> type(cx, proto->getNewType(cx));
|
||||
|
||||
EntryIndex entry;
|
||||
if (lookupGlobal(clasp, global, kind, &entry))
|
||||
@ -1275,10 +1270,11 @@ NewObjectCache::invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
EmptyShape::insertInitialShape(JSContext *cx, Shape *shape, JSObject *proto)
|
||||
EmptyShape::insertInitialShape(JSContext *cx, HandleShape shape, HandleObject proto)
|
||||
{
|
||||
InitialShapeEntry::Lookup lookup(shape->getObjectClass(), proto, shape->getObjectParent(),
|
||||
shape->numFixedSlots(), shape->getObjectFlags());
|
||||
InitialShapeEntry::Lookup lookup(shape->getObjectClass(), TaggedProto(proto),
|
||||
shape->getObjectParent(), shape->numFixedSlots(),
|
||||
shape->getObjectFlags());
|
||||
|
||||
InitialShapeSet::Ptr p = cx->compartment->initialShapes.lookup(lookup);
|
||||
JS_ASSERT(p);
|
||||
@ -1288,13 +1284,13 @@ EmptyShape::insertInitialShape(JSContext *cx, Shape *shape, JSObject *proto)
|
||||
|
||||
/* The new shape had better be rooted at the old one. */
|
||||
#ifdef DEBUG
|
||||
Shape *nshape = shape;
|
||||
RawShape nshape = shape;
|
||||
while (!nshape->isEmptyShape())
|
||||
nshape = nshape->previous();
|
||||
JS_ASSERT(nshape == entry.shape);
|
||||
#endif
|
||||
|
||||
entry.shape = shape;
|
||||
entry.shape = shape.get();
|
||||
|
||||
/*
|
||||
* This affects the shape that will be produced by the various NewObject
|
||||
@ -1315,7 +1311,7 @@ JSCompartment::sweepInitialShapeTable()
|
||||
if (initialShapes.initialized()) {
|
||||
for (InitialShapeSet::Enum e(initialShapes); !e.empty(); e.popFront()) {
|
||||
const InitialShapeEntry &entry = e.front();
|
||||
Shape *shape = entry.shape;
|
||||
RawShape shape = entry.shape;
|
||||
JSObject *proto = entry.proto.raw();
|
||||
if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) {
|
||||
e.removeFront();
|
||||
|
111
js/src/jsscope.h
111
js/src/jsscope.h
@ -90,8 +90,12 @@
|
||||
* a single BaseShape.
|
||||
*/
|
||||
|
||||
struct JSObject;
|
||||
|
||||
namespace js {
|
||||
|
||||
class Bindings;
|
||||
|
||||
/* Limit on the number of slotful properties in an object. */
|
||||
static const uint32_t SHAPE_INVALID_SLOT = JS_BIT(24) - 1;
|
||||
static const uint32_t SHAPE_MAXIMUM_SLOT = JS_BIT(24) - 2;
|
||||
@ -132,7 +136,7 @@ struct ShapeTable {
|
||||
uint32_t capacity() const { return JS_BIT(HASH_BITS - hashShift); }
|
||||
|
||||
/* Computes the size of the entries array for a given capacity. */
|
||||
static size_t sizeOfEntries(size_t cap) { return cap * sizeof(Shape *); }
|
||||
static size_t sizeOfEntries(size_t cap) { return cap * sizeof(RawShape); }
|
||||
|
||||
/*
|
||||
* This counts the ShapeTable object itself (which must be
|
||||
@ -160,19 +164,11 @@ struct ShapeTable {
|
||||
* cope or ignore. They do however use JSRuntime's calloc_ method in order
|
||||
* to update the malloc counter on success.
|
||||
*/
|
||||
bool init(JSRuntime *rt, js::Shape *lastProp);
|
||||
bool init(JSRuntime *rt, UnrootedShape lastProp);
|
||||
bool change(int log2Delta, JSContext *cx);
|
||||
js::Shape **search(jsid id, bool adding);
|
||||
Shape **search(jsid id, bool adding);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
struct JSObject;
|
||||
|
||||
namespace js {
|
||||
|
||||
class PropertyTree;
|
||||
|
||||
/*
|
||||
* Reuse the API-only JSPROP_INDEX attribute to mean shadowability.
|
||||
*/
|
||||
@ -229,6 +225,7 @@ class PropertyTree;
|
||||
ForwardDeclare(UnownedBaseShape);
|
||||
ForwardDeclare(BaseShape);
|
||||
ForwardDeclare(Shape);
|
||||
struct StackBaseShape;
|
||||
|
||||
class BaseShape : public js::gc::Cell
|
||||
{
|
||||
@ -272,13 +269,13 @@ class BaseShape : public js::gc::Cell
|
||||
* dictionary last properties. */
|
||||
|
||||
union {
|
||||
js::PropertyOp rawGetter; /* getter hook for shape */
|
||||
PropertyOp rawGetter; /* getter hook for shape */
|
||||
JSObject *getterObj; /* user-defined callable "get" object or
|
||||
null if shape->hasGetterValue() */
|
||||
};
|
||||
|
||||
union {
|
||||
js::StrictPropertyOp rawSetter; /* setter hook for shape */
|
||||
StrictPropertyOp rawSetter; /* setter hook for shape */
|
||||
JSObject *setterObj; /* user-defined callable "set" object or
|
||||
null if shape->hasSetterValue() */
|
||||
};
|
||||
@ -393,7 +390,7 @@ struct StackBaseShape
|
||||
PropertyOp rawGetter;
|
||||
StrictPropertyOp rawSetter;
|
||||
|
||||
StackBaseShape(UnrootedBaseShape base)
|
||||
explicit StackBaseShape(UnrootedBaseShape base)
|
||||
: flags(base->flags & BaseShape::OBJECT_FLAG_MASK),
|
||||
clasp(base->clasp),
|
||||
parent(base->parent),
|
||||
@ -409,7 +406,7 @@ struct StackBaseShape
|
||||
rawSetter(NULL)
|
||||
{}
|
||||
|
||||
inline StackBaseShape(Shape *shape);
|
||||
inline StackBaseShape(UnrootedShape shape);
|
||||
|
||||
inline void updateGetterSetter(uint8_t attrs,
|
||||
PropertyOp rawGetter,
|
||||
@ -498,10 +495,10 @@ struct Shape : public js::gc::Cell
|
||||
last, else to obj->shape_ */
|
||||
};
|
||||
|
||||
static inline Shape *search(JSContext *cx, Shape *start, jsid id,
|
||||
static inline UnrootedShape search(JSContext *cx, Shape *start, jsid id,
|
||||
Shape ***pspp, bool adding = false);
|
||||
|
||||
static inline Shape *searchNoAllocation(Shape *start, jsid id);
|
||||
static inline UnrootedShape searchNoAllocation(UnrootedShape start, jsid id);
|
||||
|
||||
inline void removeFromDictionary(JSObject *obj);
|
||||
inline void insertIntoDictionary(HeapPtrShape *dictp);
|
||||
@ -509,16 +506,16 @@ struct Shape : public js::gc::Cell
|
||||
inline void initDictionaryShape(const StackShape &child, uint32_t nfixed,
|
||||
HeapPtrShape *dictp);
|
||||
|
||||
Shape *getChildBinding(JSContext *cx, const StackShape &child);
|
||||
UnrootedShape getChildBinding(JSContext *cx, const StackShape &child);
|
||||
|
||||
/* Replace the base shape of the last shape in a non-dictionary lineage with base. */
|
||||
static Shape *replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
TaggedProto proto, Shape *shape);
|
||||
static UnrootedShape replaceLastProperty(JSContext *cx, const StackBaseShape &base,
|
||||
TaggedProto proto, HandleShape shape);
|
||||
|
||||
static bool hashify(JSContext *cx, HandleShape shape);
|
||||
void handoffTableTo(Shape *newShape);
|
||||
void handoffTableTo(UnrootedShape newShape);
|
||||
|
||||
inline void setParent(js::Shape *p);
|
||||
inline void setParent(UnrootedShape p);
|
||||
|
||||
bool ensureOwnBaseShape(JSContext *cx) {
|
||||
if (base()->isOwned())
|
||||
@ -531,7 +528,7 @@ struct Shape : public js::gc::Cell
|
||||
|
||||
public:
|
||||
bool hasTable() const { return base()->hasTable(); }
|
||||
js::ShapeTable &table() const { return base()->table(); }
|
||||
ShapeTable &table() const { return base()->table(); }
|
||||
|
||||
void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
|
||||
size_t *propTableSize, size_t *kidsSize) const {
|
||||
@ -553,10 +550,12 @@ struct Shape : public js::gc::Cell
|
||||
class Range {
|
||||
protected:
|
||||
friend struct Shape;
|
||||
Shape *cursor;
|
||||
|
||||
/* |cursor| is rooted manually when necessary using Range::AutoRooter. */
|
||||
RawShape cursor;
|
||||
|
||||
public:
|
||||
Range(Shape *shape) : cursor(shape) { }
|
||||
Range(UnrootedShape shape) : cursor(shape) { }
|
||||
|
||||
bool empty() const {
|
||||
return !cursor || cursor->isEmptyShape();
|
||||
@ -599,8 +598,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, TaggedProto proto, Shape *last);
|
||||
static Shape *setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last);
|
||||
static UnrootedShape setObjectParent(JSContext *cx, JSObject *obj, TaggedProto proto, Shape *last);
|
||||
static UnrootedShape setObjectFlag(JSContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last);
|
||||
|
||||
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
|
||||
bool hasObjectFlag(BaseShape::Flag flag) const {
|
||||
@ -660,7 +659,7 @@ struct Shape : public js::gc::Cell
|
||||
// Per ES5, decode null getterObj as the undefined value, which encodes as null.
|
||||
Value getterValue() const {
|
||||
JS_ASSERT(hasGetterValue());
|
||||
return base()->getterObj ? js::ObjectValue(*base()->getterObj) : js::UndefinedValue();
|
||||
return base()->getterObj ? ObjectValue(*base()->getterObj) : UndefinedValue();
|
||||
}
|
||||
|
||||
Value getterOrUndefined() const {
|
||||
@ -677,7 +676,7 @@ struct Shape : public js::gc::Cell
|
||||
// Per ES5, decode null setterObj as the undefined value, which encodes as null.
|
||||
Value setterValue() const {
|
||||
JS_ASSERT(hasSetterValue());
|
||||
return base()->setterObj ? js::ObjectValue(*base()->setterObj) : js::UndefinedValue();
|
||||
return base()->setterObj ? ObjectValue(*base()->setterObj) : UndefinedValue();
|
||||
}
|
||||
|
||||
Value setterOrUndefined() const {
|
||||
@ -686,9 +685,9 @@ struct Shape : public js::gc::Cell
|
||||
: UndefinedValue();
|
||||
}
|
||||
|
||||
void update(js::PropertyOp getter, js::StrictPropertyOp setter, uint8_t attrs);
|
||||
void update(PropertyOp getter, StrictPropertyOp setter, uint8_t attrs);
|
||||
|
||||
inline bool matches(const Shape *other) const;
|
||||
inline bool matches(const UnrootedShape other) const;
|
||||
inline bool matches(const StackShape &other) const;
|
||||
inline bool matchesParamsAfterId(UnrootedBaseShape base,
|
||||
uint32_t aslot, unsigned aattrs, unsigned aflags,
|
||||
@ -697,7 +696,7 @@ struct Shape : public js::gc::Cell
|
||||
bool get(JSContext* cx, HandleObject receiver, JSObject *obj, JSObject *pobj, MutableHandleValue vp);
|
||||
bool set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict, MutableHandleValue vp);
|
||||
|
||||
BaseShape* base() const { return base_; }
|
||||
RawBaseShape base() const { return base_.get(); }
|
||||
|
||||
bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; }
|
||||
uint32_t slot() const { JS_ASSERT(hasSlot() && !hasMissingSlot()); return maybeSlot(); }
|
||||
@ -799,18 +798,18 @@ struct Shape : public js::gc::Cell
|
||||
if (hasTable())
|
||||
return table().entryCount;
|
||||
|
||||
js::Shape *shape = this;
|
||||
UnrootedShape shape = this;
|
||||
uint32_t count = 0;
|
||||
for (js::Shape::Range r = shape->all(); !r.empty(); r.popFront())
|
||||
for (Shape::Range r = shape->all(); !r.empty(); r.popFront())
|
||||
++count;
|
||||
return count;
|
||||
}
|
||||
|
||||
bool isBigEnoughForAShapeTable() {
|
||||
JS_ASSERT(!hasTable());
|
||||
js::Shape *shape = this;
|
||||
UnrootedShape shape = this;
|
||||
uint32_t count = 0;
|
||||
for (js::Shape::Range r = shape->all(); !r.empty(); r.popFront()) {
|
||||
for (Shape::Range r = shape->all(); !r.empty(); r.popFront()) {
|
||||
++count;
|
||||
if (count >= ShapeTable::MIN_ENTRIES)
|
||||
return true;
|
||||
@ -824,23 +823,23 @@ struct Shape : public js::gc::Cell
|
||||
#endif
|
||||
|
||||
void finalize(FreeOp *fop);
|
||||
void removeChild(js::Shape *child);
|
||||
void removeChild(UnrootedShape child);
|
||||
|
||||
static inline void writeBarrierPre(Shape *shape);
|
||||
static inline void writeBarrierPost(Shape *shape, void *addr);
|
||||
static inline void writeBarrierPre(UnrootedShape shape);
|
||||
static inline void writeBarrierPost(UnrootedShape shape, void *addr);
|
||||
|
||||
/*
|
||||
* All weak references need a read barrier for incremental GC. This getter
|
||||
* method implements the read barrier. It's used to obtain initial shapes
|
||||
* from the compartment.
|
||||
*/
|
||||
static inline void readBarrier(Shape *shape);
|
||||
static inline void readBarrier(UnrootedShape shape);
|
||||
|
||||
static inline ThingRootKind rootKind() { return THING_ROOT_SHAPE; }
|
||||
|
||||
inline void markChildren(JSTracer *trc);
|
||||
|
||||
inline Shape *search(JSContext *cx, jsid id) {
|
||||
inline UnrootedShape search(JSContext *cx, jsid id) {
|
||||
Shape **_;
|
||||
return search(cx, this, id, &_);
|
||||
}
|
||||
@ -913,7 +912,7 @@ struct EmptyShape : public js::Shape
|
||||
* getInitialShape calls, until the new shape becomes unreachable in a GC
|
||||
* and the table entry is purged.
|
||||
*/
|
||||
static void insertInitialShape(JSContext *cx, Shape *shape, JSObject *proto);
|
||||
static void insertInitialShape(JSContext *cx, HandleShape shape, HandleObject proto);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -970,7 +969,7 @@ struct StackShape
|
||||
uint8_t flags;
|
||||
int16_t shortid;
|
||||
|
||||
StackShape(UnrootedUnownedBaseShape base, jsid propid, uint32_t slot,
|
||||
explicit StackShape(UnrootedUnownedBaseShape base, jsid propid, uint32_t slot,
|
||||
uint32_t nfixed, unsigned attrs, unsigned flags, int shortid)
|
||||
: base(base),
|
||||
propid(propid),
|
||||
@ -984,9 +983,9 @@ struct StackShape
|
||||
JS_ASSERT(slot <= SHAPE_INVALID_SLOT);
|
||||
}
|
||||
|
||||
StackShape(const Shape *shape)
|
||||
StackShape(const UnrootedShape &shape)
|
||||
: base(shape->base()->unowned()),
|
||||
propid(const_cast<Shape *>(shape)->propidRef()),
|
||||
propid(shape->propidRef()),
|
||||
slot_(shape->slotInfo & Shape::SLOT_MASK),
|
||||
attrs(shape->attrs),
|
||||
flags(shape->flags),
|
||||
@ -1034,26 +1033,26 @@ struct StackShape
|
||||
|
||||
/* js::Shape pointer tag bit indicating a collision. */
|
||||
#define SHAPE_COLLISION (uintptr_t(1))
|
||||
#define SHAPE_REMOVED ((js::Shape *) SHAPE_COLLISION)
|
||||
#define SHAPE_REMOVED ((RawShape) SHAPE_COLLISION)
|
||||
|
||||
/* Macros to get and set shape pointer values and collision flags. */
|
||||
#define SHAPE_IS_FREE(shape) ((shape) == NULL)
|
||||
#define SHAPE_IS_REMOVED(shape) ((shape) == SHAPE_REMOVED)
|
||||
#define SHAPE_IS_LIVE(shape) ((shape) > SHAPE_REMOVED)
|
||||
#define SHAPE_FLAG_COLLISION(spp,shape) (*(spp) = (js::Shape *) \
|
||||
#define SHAPE_FLAG_COLLISION(spp,shape) (*(spp) = (RawShape) \
|
||||
(uintptr_t(shape) | SHAPE_COLLISION))
|
||||
#define SHAPE_HAD_COLLISION(shape) (uintptr_t(shape) & SHAPE_COLLISION)
|
||||
#define SHAPE_FETCH(spp) SHAPE_CLEAR_COLLISION(*(spp))
|
||||
|
||||
#define SHAPE_CLEAR_COLLISION(shape) \
|
||||
((js::Shape *) (uintptr_t(shape) & ~SHAPE_COLLISION))
|
||||
((RawShape) (uintptr_t(shape) & ~SHAPE_COLLISION))
|
||||
|
||||
#define SHAPE_STORE_PRESERVING_COLLISION(spp, shape) \
|
||||
(*(spp) = (js::Shape *) (uintptr_t(shape) | SHAPE_HAD_COLLISION(*(spp))))
|
||||
(*(spp) = (RawShape) (uintptr_t(shape) | SHAPE_HAD_COLLISION(*(spp))))
|
||||
|
||||
namespace js {
|
||||
|
||||
inline Shape *
|
||||
inline UnrootedShape
|
||||
Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
|
||||
{
|
||||
AssertCanGC();
|
||||
@ -1097,28 +1096,28 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
|
||||
start->incrementNumLinearSearches();
|
||||
}
|
||||
|
||||
for (Shape *shape = start; shape; shape = shape->parent) {
|
||||
for (UnrootedShape shape = start; shape; shape = shape->parent) {
|
||||
if (shape->propidRef() == id)
|
||||
return shape;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
/* static */ inline Shape *
|
||||
Shape::searchNoAllocation(Shape *start, jsid id)
|
||||
/* static */ inline UnrootedShape
|
||||
Shape::searchNoAllocation(UnrootedShape start, jsid id)
|
||||
{
|
||||
if (start->hasTable()) {
|
||||
Shape **spp = start->table().search(id, false);
|
||||
return SHAPE_FETCH(spp);
|
||||
}
|
||||
|
||||
for (Shape *shape = start; shape; shape = shape->parent) {
|
||||
for (UnrootedShape shape = start; shape; shape = shape->parent) {
|
||||
if (shape->propidRef() == id)
|
||||
return shape;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -124,7 +124,7 @@ BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter)
|
||||
}
|
||||
|
||||
inline
|
||||
StackBaseShape::StackBaseShape(Shape *shape)
|
||||
StackBaseShape::StackBaseShape(UnrootedShape shape)
|
||||
: flags(shape->getObjectFlags()),
|
||||
clasp(shape->getObjectClass()),
|
||||
parent(shape->getObjectParent())
|
||||
@ -238,7 +238,7 @@ StackShape::hash() const
|
||||
}
|
||||
|
||||
inline bool
|
||||
Shape::matches(const js::Shape *other) const
|
||||
Shape::matches(const UnrootedShape other) const
|
||||
{
|
||||
return propid_.get() == other->propid_.get() &&
|
||||
matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
|
||||
@ -334,7 +334,7 @@ Shape::set(JSContext* cx, HandleObject obj, HandleObject receiver, bool strict,
|
||||
}
|
||||
|
||||
inline void
|
||||
Shape::setParent(js::Shape *p)
|
||||
Shape::setParent(UnrootedShape p)
|
||||
{
|
||||
JS_ASSERT_IF(p && !p->hasMissingSlot() && !inDictionary(),
|
||||
p->maybeSlot() <= maybeSlot());
|
||||
@ -373,7 +373,7 @@ Shape::insertIntoDictionary(HeapPtrShape *dictp)
|
||||
JS_ASSERT_IF(*dictp, (*dictp)->listp == dictp);
|
||||
JS_ASSERT_IF(*dictp, compartment() == (*dictp)->compartment());
|
||||
|
||||
setParent(*dictp);
|
||||
setParent(dictp->get());
|
||||
if (parent)
|
||||
parent->listp = &parent;
|
||||
listp = (HeapPtrShape *) dictp;
|
||||
@ -400,7 +400,7 @@ EmptyShape::EmptyShape(UnrootedUnownedBaseShape base, uint32_t nfixed)
|
||||
}
|
||||
|
||||
inline void
|
||||
Shape::writeBarrierPre(Shape *shape)
|
||||
Shape::writeBarrierPre(UnrootedShape shape)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
if (!shape)
|
||||
@ -408,7 +408,7 @@ Shape::writeBarrierPre(Shape *shape)
|
||||
|
||||
JSCompartment *comp = shape->compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
Shape *tmp = const_cast<Shape *>(shape);
|
||||
UnrootedShape tmp = shape;
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "write barrier");
|
||||
JS_ASSERT(tmp == shape);
|
||||
}
|
||||
@ -416,17 +416,17 @@ Shape::writeBarrierPre(Shape *shape)
|
||||
}
|
||||
|
||||
inline void
|
||||
Shape::writeBarrierPost(Shape *shape, void *addr)
|
||||
Shape::writeBarrierPost(UnrootedShape shape, void *addr)
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
Shape::readBarrier(Shape *shape)
|
||||
Shape::readBarrier(UnrootedShape shape)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
JSCompartment *comp = shape->compartment();
|
||||
if (comp->needsBarrier()) {
|
||||
Shape *tmp = const_cast<Shape *>(shape);
|
||||
UnrootedShape tmp = shape;
|
||||
MarkShapeUnbarriered(comp->barrierTracer(), &tmp, "read barrier");
|
||||
JS_ASSERT(tmp == shape);
|
||||
}
|
||||
|
@ -132,9 +132,11 @@ Bindings::initWithTemporaryStorage(JSContext *cx, InternalBindingsHandle self,
|
||||
StackShape child(nbase, id, slot++, 0, attrs, Shape::HAS_SHORTID, frameIndex);
|
||||
DropUnrooted(nbase);
|
||||
|
||||
self->callObjShape_ = self->callObjShape_->getChildBinding(cx, child);
|
||||
if (!self->callObjShape_)
|
||||
UnrootedShape shape = self->callObjShape_->getChildBinding(cx, child);
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
self->callObjShape_ = shape;
|
||||
}
|
||||
JS_ASSERT(!bi);
|
||||
|
||||
|
@ -191,7 +191,7 @@ class Bindings
|
||||
unsigned count() const { return numArgs() + numVars(); }
|
||||
|
||||
/* Return the initial shape of call objects created for this scope. */
|
||||
Shape *callObjShape() const { return callObjShape_; }
|
||||
UnrootedShape callObjShape() const { return callObjShape_.get(); }
|
||||
|
||||
/* Convenience method to get the var index of 'arguments'. */
|
||||
static unsigned argumentsVarIndex(JSContext *cx, InternalBindingsHandle);
|
||||
@ -210,7 +210,7 @@ struct RootMethods<Bindings> {
|
||||
static Bindings initial();
|
||||
static ThingRootKind kind() { return THING_ROOT_BINDINGS; }
|
||||
static bool poisoned(const Bindings &bindings) {
|
||||
return IsPoisonedPtr(bindings.callObjShape());
|
||||
return IsPoisonedPtr(static_cast<RawShape>(bindings.callObjShape()));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3241,13 +3241,13 @@ static JSFunctionSpec string_static_methods[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
StringObject::assignInitialShape(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(nativeEmpty());
|
||||
|
||||
return addDataProperty(cx, NameToId(cx->names().length),
|
||||
LENGTH_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
RootedId lengthid(cx, NameToId(cx->names().length));
|
||||
return addDataProperty(cx, lengthid, LENGTH_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
@ -132,7 +132,7 @@ WatchpointMap::triggerWatchpoint(JSContext *cx, HandleObject obj, HandleId id, M
|
||||
Value old;
|
||||
old.setUndefined();
|
||||
if (obj->isNative()) {
|
||||
if (Shape *shape = obj->nativeLookup(cx, id)) {
|
||||
if (UnrootedShape shape = obj->nativeLookup(cx, id)) {
|
||||
if (shape->hasSlot())
|
||||
old = obj->nativeGetSlot(shape->slot());
|
||||
}
|
||||
|
@ -4724,10 +4724,9 @@ xml_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||
objp.set(NULL);
|
||||
propp.set(NULL);
|
||||
} else {
|
||||
Shape *shape =
|
||||
js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
|
||||
RootedShape shape(cx, js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
|
||||
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE,
|
||||
0, 0);
|
||||
0, 0));
|
||||
if (!shape)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -4756,13 +4755,12 @@ xml_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandle
|
||||
return true;
|
||||
}
|
||||
|
||||
jsid id;
|
||||
if (!IndexToId(cx, index, &id))
|
||||
RootedId id(cx);
|
||||
if (!IndexToId(cx, index, id.address()))
|
||||
return false;
|
||||
|
||||
Shape *shape =
|
||||
js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty, SHAPE_INVALID_SLOT,
|
||||
JSPROP_ENUMERATE, 0, 0);
|
||||
RootedShape shape(cx, js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
|
||||
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, 0, 0));
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
|
@ -197,7 +197,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
|
||||
loadPtr(Address(obj, JSObject::offsetOfShape()), shape);
|
||||
}
|
||||
|
||||
Jump guardShape(RegisterID objReg, Shape *shape) {
|
||||
Jump guardShape(RegisterID objReg, UnrootedShape shape) {
|
||||
return branchPtr(NotEqual, Address(objReg, JSObject::offsetOfShape()), ImmPtr(shape));
|
||||
}
|
||||
|
||||
@ -981,7 +981,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
|
||||
}
|
||||
|
||||
void loadObjProp(JSObject *obj, RegisterID objReg,
|
||||
js::Shape *shape,
|
||||
js::UnrootedShape shape,
|
||||
RegisterID typeReg, RegisterID dataReg)
|
||||
{
|
||||
if (obj->isFixedSlot(shape->slot()))
|
||||
@ -1342,6 +1342,7 @@ static const JSC::MacroAssembler::RegisterID JSParamReg_Argc = JSC::MIPSRegiste
|
||||
*/
|
||||
Jump getNewObject(JSContext *cx, RegisterID result, JSObject *templateObject)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
gc::AllocKind allocKind = templateObject->getAllocKind();
|
||||
|
||||
JS_ASSERT(allocKind >= gc::FINALIZE_OBJECT0 && allocKind <= gc::FINALIZE_OBJECT_LAST);
|
||||
|
@ -6079,7 +6079,7 @@ mjit::Compiler::jsop_aliasedVar(ScopeCoordinate sc, bool get, bool poppedAfter)
|
||||
for (unsigned i = 0; i < sc.hops; i++)
|
||||
masm.loadPayload(Address(reg, ScopeObject::offsetOfEnclosingScope()), reg);
|
||||
|
||||
Shape *shape = ScopeCoordinateToStaticScope(script_, PC).scopeShape();
|
||||
UnrootedShape shape = ScopeCoordinateToStaticScope(script_, PC).scopeShape();
|
||||
Address addr;
|
||||
if (shape->numFixedSlots() <= sc.slot) {
|
||||
masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg);
|
||||
@ -6227,7 +6227,7 @@ mjit::Compiler::iter(unsigned flags)
|
||||
masm.loadPtr(Address(T1, offsetof(types::TypeObject, proto)), T1);
|
||||
masm.loadShape(T1, T1);
|
||||
masm.loadPtr(Address(nireg, offsetof(NativeIterator, shapes_array)), T2);
|
||||
masm.loadPtr(Address(T2, sizeof(Shape *)), T2);
|
||||
masm.loadPtr(Address(T2, sizeof(RawShape)), T2);
|
||||
Jump mismatchedProto = masm.branchPtr(Assembler::NotEqual, T1, T2);
|
||||
stubcc.linkExit(mismatchedProto, Uses(1));
|
||||
|
||||
@ -6462,6 +6462,8 @@ mjit::Compiler::jsop_bindgname()
|
||||
bool
|
||||
mjit::Compiler::jsop_getgname(uint32_t index)
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
/* Optimize undefined, NaN and Infinity. */
|
||||
PropertyName *name = script_->getName(index);
|
||||
if (name == cx->names().undefined) {
|
||||
@ -6500,9 +6502,9 @@ mjit::Compiler::jsop_getgname(uint32_t index)
|
||||
* then bake its address into the jitcode and guard against future
|
||||
* reallocation of the global object's slots.
|
||||
*/
|
||||
js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
|
||||
UnrootedShape shape = globalObj->nativeLookup(cx, NameToId(name));
|
||||
if (shape && shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
HeapSlot *value = &globalObj->getSlotRef(shape->slot());
|
||||
HeapSlot *value = &globalObj->getSlotRef(DropUnrooted(shape)->slot());
|
||||
if (!value->isUndefined() &&
|
||||
!propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
|
||||
watchGlobalReallocation();
|
||||
@ -6626,7 +6628,7 @@ mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
|
||||
types::HeapTypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
|
||||
if (!types)
|
||||
return false;
|
||||
js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
|
||||
UnrootedShape shape = globalObj->nativeLookup(cx, NameToId(name));
|
||||
if (shape && shape->hasDefaultSetter() &&
|
||||
shape->writable() && shape->hasSlot() &&
|
||||
!types->isOwnProperty(cx, globalObj->getType(cx), true)) {
|
||||
@ -7911,6 +7913,8 @@ mjit::Compiler::BarrierState
|
||||
mjit::Compiler::pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
|
||||
bool testUndefined)
|
||||
{
|
||||
AssertCanGC();
|
||||
|
||||
if (!hasTypeBarriers(PC) && !testUndefined) {
|
||||
frame.push(address, type, reuseBase);
|
||||
return BarrierState();
|
||||
|
@ -1515,7 +1515,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
|
||||
ic.slowPathStart = stubcc.syncExit(Uses(3));
|
||||
|
||||
// Guard obj is a dense array.
|
||||
Shape *shape = GetDenseArrayShape(cx, globalObj);
|
||||
UnrootedShape shape = GetDenseArrayShape(cx, globalObj);
|
||||
if (!shape)
|
||||
return false;
|
||||
ic.shapeGuard = masm.guardShape(ic.objReg, shape);
|
||||
@ -2093,7 +2093,7 @@ mjit::Compiler::jsop_getelem()
|
||||
}
|
||||
|
||||
// Guard obj is a dense array.
|
||||
Shape *shape = GetDenseArrayShape(cx, globalObj);
|
||||
UnrootedShape shape = GetDenseArrayShape(cx, globalObj);
|
||||
if (!shape)
|
||||
return false;
|
||||
ic.shapeGuard = masm.guardShape(ic.objReg, shape);
|
||||
|
@ -1400,12 +1400,12 @@ GetPIC(JSContext *cx, JSScript *script, jsbytecode *pc, bool constructing)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
mjit::GetPICSingleShape(JSContext *cx, JSScript *script, jsbytecode *pc, bool constructing)
|
||||
{
|
||||
ic::PICInfo *pic = GetPIC(cx, script, pc, constructing);
|
||||
if (!pic)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
return pic->getSingleShape();
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1035,7 @@ IsLowerableFunCallOrApply(jsbytecode *pc)
|
||||
#endif
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
GetPICSingleShape(JSContext *cx, JSScript *script, jsbytecode *pc, bool constructing);
|
||||
|
||||
static inline void
|
||||
|
@ -68,7 +68,9 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
|
||||
RecompilationMonitor monitor(f.cx);
|
||||
|
||||
Shape *shape = obj->nativeLookup(f.cx, NameToId(name));
|
||||
uint32_t slot;
|
||||
{
|
||||
RootedShape shape(f.cx, obj->nativeLookup(f.cx, NameToId(name)));
|
||||
|
||||
if (monitor.recompiled()) {
|
||||
stubs::Name(f);
|
||||
@ -84,7 +86,7 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
stubs::Name(f);
|
||||
return;
|
||||
}
|
||||
uint32_t slot = shape->slot();
|
||||
slot = shape->slot();
|
||||
|
||||
/* Patch shape guard. */
|
||||
Repatcher repatcher(f.chunk());
|
||||
@ -94,6 +96,7 @@ ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
|
||||
uint32_t index = obj->dynamicSlotIndex(slot);
|
||||
JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
|
||||
repatcher.patchAddressOffsetForValueLoad(label, index * sizeof(Value));
|
||||
}
|
||||
|
||||
/* Do load anyway... this time. */
|
||||
stubs::Name(f);
|
||||
@ -117,14 +120,14 @@ PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic)
|
||||
}
|
||||
|
||||
void
|
||||
SetGlobalNameIC::patchInlineShapeGuard(Repatcher &repatcher, Shape *shape)
|
||||
SetGlobalNameIC::patchInlineShapeGuard(Repatcher &repatcher, UnrootedShape shape)
|
||||
{
|
||||
JSC::CodeLocationDataLabelPtr label = fastPathStart.dataLabelPtrAtOffset(shapeOffset);
|
||||
repatcher.repatch(label, shape);
|
||||
}
|
||||
|
||||
static LookupStatus
|
||||
UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, Shape *shape)
|
||||
UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, UnrootedShape shape)
|
||||
{
|
||||
/* Give globals a chance to appear. */
|
||||
if (!shape)
|
||||
@ -162,13 +165,15 @@ ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
|
||||
|
||||
RecompilationMonitor monitor(f.cx);
|
||||
|
||||
Shape *shape = obj->nativeLookup(f.cx, NameToId(name));
|
||||
{
|
||||
UnrootedShape shape = obj->nativeLookup(f.cx, NameToId(name));
|
||||
|
||||
if (!monitor.recompiled()) {
|
||||
LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
|
||||
if (status == Lookup_Error)
|
||||
THROW();
|
||||
}
|
||||
}
|
||||
|
||||
stubs::SetName(f, name);
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ struct SetGlobalNameIC : public GlobalNameIC
|
||||
/* SET only. */
|
||||
ValueRemat vr; /* RHS value. */
|
||||
|
||||
void patchInlineShapeGuard(Repatcher &repatcher, Shape *shape);
|
||||
void patchInlineShapeGuard(Repatcher &repatcher, UnrootedShape shape);
|
||||
};
|
||||
|
||||
void JS_FASTCALL GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic);
|
||||
|
@ -189,7 +189,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
repatcher.relink(pic.slowPathCall, target);
|
||||
}
|
||||
|
||||
LookupStatus patchInline(Shape *shape)
|
||||
LookupStatus patchInline(UnrootedShape shape)
|
||||
{
|
||||
JS_ASSERT(!pic.inlinePathPatched);
|
||||
JaegerSpew(JSpew_PICs, "patch setprop inline at %p\n", pic.fastPathStart.executableAddress());
|
||||
@ -249,7 +249,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
repatcher.relink(label.jumpAtOffset(secondGuardOffset), cs);
|
||||
}
|
||||
|
||||
LookupStatus generateStub(Shape *initialShape, Shape *shape, bool adding)
|
||||
LookupStatus generateStub(UnrootedShape initialShape, UnrootedShape shape, bool adding)
|
||||
{
|
||||
if (hadGC())
|
||||
return Lookup_Uncacheable;
|
||||
@ -510,7 +510,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
proto = proto->getProto();
|
||||
}
|
||||
|
||||
Shape *initialShape = obj->lastProperty();
|
||||
RootedShape initialShape(cx, obj->lastProperty());
|
||||
uint32_t slots = obj->numDynamicSlots();
|
||||
|
||||
unsigned flags = 0;
|
||||
@ -521,8 +521,7 @@ class SetPropCompiler : public PICStubCompiler
|
||||
* populate the slot to satisfy the method invariant (in case we
|
||||
* hit an early return below).
|
||||
*/
|
||||
shape =
|
||||
obj->putProperty(cx, name, getter, clasp->setProperty,
|
||||
shape = JSObject::putProperty(cx, obj, name, getter, clasp->setProperty,
|
||||
SHAPE_INVALID_SLOT, JSPROP_ENUMERATE, flags, 0);
|
||||
if (!shape)
|
||||
return error();
|
||||
@ -1016,7 +1015,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
return Lookup_Cacheable;
|
||||
}
|
||||
|
||||
LookupStatus patchInline(JSObject *holder, Shape *shape)
|
||||
LookupStatus patchInline(JSObject *holder, UnrootedShape shape)
|
||||
{
|
||||
spew("patch", "inline");
|
||||
Repatcher repatcher(f.chunk());
|
||||
@ -1051,7 +1050,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
}
|
||||
|
||||
/* For JSPropertyOp getters. */
|
||||
void generateGetterStub(Assembler &masm, Shape *shape, jsid userid,
|
||||
void generateGetterStub(Assembler &masm, UnrootedShape shape, jsid userid,
|
||||
Label start, Vector<Jump, 8> &shapeMismatches)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
@ -1163,7 +1162,7 @@ class GetPropCompiler : public PICStubCompiler
|
||||
}
|
||||
|
||||
/* For getters backed by a JSNative. */
|
||||
void generateNativeGetterStub(Assembler &masm, Shape *shape,
|
||||
void generateNativeGetterStub(Assembler &masm, UnrootedShape shape,
|
||||
Label start, Vector<Jump, 8> &shapeMismatches)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
@ -1704,7 +1703,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
JS_ASSERT(obj == getprop.holder);
|
||||
JS_ASSERT(getprop.holder != &scopeChain->global());
|
||||
|
||||
Shape *shape = getprop.shape;
|
||||
UnrootedShape shape = getprop.shape;
|
||||
if (!shape->hasDefaultGetter())
|
||||
return disable("unhandled callobj sprop getter");
|
||||
|
||||
@ -1833,7 +1832,17 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
Rooted<JSObject*> normalized(cx, obj);
|
||||
if (obj->isWith() && !shape->hasDefaultGetter())
|
||||
normalized = &obj->asWith().object();
|
||||
NATIVE_GET(cx, normalized, holder, shape, 0, vp.address(), return false);
|
||||
if (shape->isDataDescriptor() && shape->hasDefaultGetter()) {
|
||||
/* Fast path for Object instance properties. */
|
||||
JS_ASSERT(shape->slot() != SHAPE_INVALID_SLOT || !shape->hasDefaultSetter());
|
||||
if (shape->slot() != SHAPE_INVALID_SLOT)
|
||||
vp.set(holder->nativeGetSlot(shape->slot()));
|
||||
else
|
||||
vp.setUndefined();
|
||||
} else {
|
||||
if (!js_NativeGet(cx, normalized, holder, shape, 0, vp))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@ -2402,7 +2411,7 @@ GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandleP
|
||||
}
|
||||
|
||||
// Load the value.
|
||||
Shape *shape = getprop.shape;
|
||||
RootedShape shape(cx, getprop.shape);
|
||||
masm.loadObjProp(holder, holderReg, shape, typeReg, objReg);
|
||||
|
||||
Jump done = masm.jump();
|
||||
|
@ -489,14 +489,14 @@ struct PICInfo : public BasePolyIC {
|
||||
public:
|
||||
void purge(Repatcher &repatcher);
|
||||
|
||||
void setInlinePathShape(Shape *shape) {
|
||||
void setInlinePathShape(UnrootedShape shape) {
|
||||
JS_ASSERT(!inlinePathShape_);
|
||||
inlinePathShape_ = shape;
|
||||
}
|
||||
|
||||
Shape *getSingleShape() {
|
||||
UnrootedShape getSingleShape() {
|
||||
if (disabled || hadUncacheable || stubsGenerated > 0)
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
return inlinePathShape_;
|
||||
}
|
||||
|
||||
|
@ -29,23 +29,8 @@ ReportAtomNotDefined(JSContext *cx, JSAtom *atom)
|
||||
js_ReportIsNotDefined(cx, printable.ptr());
|
||||
}
|
||||
|
||||
#define NATIVE_GET(cx,obj,pobj,shape,getHow,vp,onerr) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (shape->isDataDescriptor() && shape->hasDefaultGetter()) { \
|
||||
/* Fast path for Object instance properties. */ \
|
||||
JS_ASSERT((shape)->slot() != SHAPE_INVALID_SLOT || \
|
||||
!shape->hasDefaultSetter()); \
|
||||
if (((shape)->slot() != SHAPE_INVALID_SLOT)) \
|
||||
*(vp) = (pobj)->nativeGetSlot((shape)->slot()); \
|
||||
else \
|
||||
(vp)->setUndefined(); \
|
||||
} else { \
|
||||
if (!js_NativeGet(cx, obj, pobj, shape, getHow, vp)) \
|
||||
onerr; \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
}}
|
||||
} /* namespace mjit */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jslogic_h__ */
|
||||
|
||||
|
@ -2776,7 +2776,7 @@ CopyProperty(JSContext *cx, HandleObject obj, HandleObject referent, HandleId id
|
||||
|
||||
RootedValue value(cx, desc.value);
|
||||
objp.set(obj);
|
||||
return !!DefineNativeProperty(cx, obj, id, value, desc.getter, desc.setter,
|
||||
return DefineNativeProperty(cx, obj, id, value, desc.getter, desc.setter,
|
||||
desc.attrs, propFlags, desc.shortid);
|
||||
}
|
||||
|
||||
|
@ -849,7 +849,7 @@ Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value
|
||||
/* Check that rv is {return: val} or {throw: val}. */
|
||||
JSContext *cx = ac.ref().context();
|
||||
Rooted<JSObject*> obj(cx);
|
||||
Shape *shape;
|
||||
RootedShape shape(cx);
|
||||
jsid returnId = NameToId(cx->names().return_);
|
||||
jsid throwId = NameToId(cx->names().throw_);
|
||||
bool okResumption = rv.isObject();
|
||||
@ -869,8 +869,10 @@ Debugger::parseResumptionValue(Maybe<AutoCompartment> &ac, bool ok, const Value
|
||||
return handleUncaughtException(ac, vp, callHook);
|
||||
}
|
||||
|
||||
if (!js_NativeGet(cx, obj, obj, shape, 0, vp) || !unwrapDebuggeeValue(cx, vp))
|
||||
return handleUncaughtException(ac, vp, callHook);
|
||||
RootedValue v(cx, *vp);
|
||||
if (!js_NativeGet(cx, obj, obj, shape, 0, &v) || !unwrapDebuggeeValue(cx, v.address()))
|
||||
return handleUncaughtException(ac, v.address(), callHook);
|
||||
*vp = v;
|
||||
|
||||
ac.destroy();
|
||||
if (!cx->compartment->wrap(cx, vp)) {
|
||||
|
@ -40,25 +40,25 @@ Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
|
||||
|
||||
} // namespace js
|
||||
|
||||
inline js::Shape *
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
|
||||
{
|
||||
return nativeLookup(cx, pid.asId());
|
||||
}
|
||||
|
||||
inline js::Shape *
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
|
||||
{
|
||||
return nativeLookup(cx, PropertyId(name));
|
||||
}
|
||||
|
||||
inline js::Shape *
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(PropertyId pid)
|
||||
{
|
||||
return nativeLookupNoAllocation(pid.asId());
|
||||
}
|
||||
|
||||
inline js::Shape *
|
||||
inline js::UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(PropertyName *name)
|
||||
{
|
||||
return nativeLookupNoAllocation(PropertyId(name));
|
||||
|
@ -164,8 +164,8 @@ js::ObjectImpl::checkShapeConsistency()
|
||||
|
||||
MOZ_ASSERT(isNative());
|
||||
|
||||
Shape *shape = lastProperty();
|
||||
Shape *prev = NULL;
|
||||
UnrootedShape shape = lastProperty();
|
||||
UnrootedShape prev = NULL;
|
||||
|
||||
if (inDictionaryMode()) {
|
||||
MOZ_ASSERT(shape->hasTable());
|
||||
@ -177,7 +177,7 @@ js::ObjectImpl::checkShapeConsistency()
|
||||
}
|
||||
|
||||
for (int n = throttle; --n >= 0 && shape->parent; shape = shape->parent) {
|
||||
MOZ_ASSERT_IF(shape != lastProperty(), !shape->hasTable());
|
||||
MOZ_ASSERT_IF(lastProperty() != shape, !shape->hasTable());
|
||||
|
||||
Shape **spp = table.search(shape->propid(), false);
|
||||
MOZ_ASSERT(SHAPE_FETCH(spp) == shape);
|
||||
@ -187,7 +187,7 @@ js::ObjectImpl::checkShapeConsistency()
|
||||
for (int n = throttle; --n >= 0 && shape; shape = shape->parent) {
|
||||
MOZ_ASSERT_IF(shape->slot() != SHAPE_INVALID_SLOT, shape->slot() < slotSpan());
|
||||
if (!prev) {
|
||||
MOZ_ASSERT(shape == lastProperty());
|
||||
MOZ_ASSERT(lastProperty() == shape);
|
||||
MOZ_ASSERT(shape->listp == &shape_);
|
||||
} else {
|
||||
MOZ_ASSERT(shape->listp == &prev->parent);
|
||||
@ -257,15 +257,16 @@ js::ObjectImpl::slotInRange(uint32_t slot, SentinelAllowed sentinel) const
|
||||
*/
|
||||
MOZ_NEVER_INLINE
|
||||
#endif
|
||||
Shape *
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, jsid id)
|
||||
UnrootedShape
|
||||
js::ObjectImpl::nativeLookup(JSContext *cx, jsid idArg)
|
||||
{
|
||||
MOZ_ASSERT(isNative());
|
||||
Shape **spp;
|
||||
RootedId id(cx, idArg);
|
||||
return Shape::search(cx, lastProperty(), id, &spp);
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
js::ObjectImpl::nativeLookupNoAllocation(jsid id)
|
||||
{
|
||||
MOZ_ASSERT(isNative());
|
||||
@ -503,8 +504,11 @@ js::GetOwnProperty(JSContext *cx, Handle<ObjectImpl*> obj, PropertyId pid_, unsi
|
||||
return false;
|
||||
}
|
||||
|
||||
Shape *shape = obj->nativeLookup(cx, pid);
|
||||
/* |shape| is always set /after/ a GC. */
|
||||
UnrootedShape shape = obj->nativeLookup(cx, pid);
|
||||
if (!shape) {
|
||||
DropUnrooted(shape);
|
||||
|
||||
/* Not found: attempt to resolve it. */
|
||||
Class *clasp = obj->getClass();
|
||||
JSResolveOp resolve = clasp->resolve;
|
||||
|
@ -24,6 +24,7 @@ namespace js {
|
||||
|
||||
class Debugger;
|
||||
class ObjectImpl;
|
||||
ForwardDeclare(Shape);
|
||||
|
||||
class AutoPropDescArrayRooter;
|
||||
|
||||
@ -358,7 +359,7 @@ class ElementsHeader
|
||||
} dense;
|
||||
class {
|
||||
friend class SparseElementsHeader;
|
||||
Shape * shape;
|
||||
RawShape shape;
|
||||
} sparse;
|
||||
class {
|
||||
friend class ArrayBufferElementsHeader;
|
||||
@ -449,7 +450,7 @@ class DenseElementsHeader : public ElementsHeader
|
||||
class SparseElementsHeader : public ElementsHeader
|
||||
{
|
||||
public:
|
||||
Shape * shape() {
|
||||
UnrootedShape shape() {
|
||||
MOZ_ASSERT(ElementsHeader::isSparseElements());
|
||||
return sparse.shape;
|
||||
}
|
||||
@ -1155,13 +1156,13 @@ class ObjectImpl : public gc::Cell
|
||||
/* Compute dynamicSlotsCount() for this object. */
|
||||
inline uint32_t numDynamicSlots() const;
|
||||
|
||||
Shape * nativeLookup(JSContext *cx, jsid id);
|
||||
inline Shape * nativeLookup(JSContext *cx, PropertyId pid);
|
||||
inline Shape * nativeLookup(JSContext *cx, PropertyName *name);
|
||||
UnrootedShape nativeLookup(JSContext *cx, jsid id);
|
||||
inline UnrootedShape nativeLookup(JSContext *cx, PropertyId pid);
|
||||
inline UnrootedShape nativeLookup(JSContext *cx, PropertyName *name);
|
||||
|
||||
Shape * nativeLookupNoAllocation(jsid id);
|
||||
inline Shape * nativeLookupNoAllocation(PropertyId pid);
|
||||
inline Shape * nativeLookupNoAllocation(PropertyName *name);
|
||||
UnrootedShape nativeLookupNoAllocation(jsid id);
|
||||
inline UnrootedShape nativeLookupNoAllocation(PropertyId pid);
|
||||
inline UnrootedShape nativeLookupNoAllocation(PropertyName *name);
|
||||
|
||||
inline bool nativeContains(JSContext *cx, Handle<jsid> id);
|
||||
inline bool nativeContains(JSContext *cx, Handle<PropertyName*> name);
|
||||
|
@ -322,7 +322,7 @@ RegExpObject::createShared(JSContext *cx, RegExpGuard *g)
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
RegExpObject::assignInitialShape(JSContext *cx)
|
||||
{
|
||||
JS_ASSERT(isRegExp());
|
||||
@ -338,27 +338,20 @@ RegExpObject::assignInitialShape(JSContext *cx)
|
||||
RootedObject self(cx, this);
|
||||
|
||||
/* The lastIndex property alone is writable but non-configurable. */
|
||||
if (!addDataProperty(cx, NameToId(cx->names().lastIndex),
|
||||
LAST_INDEX_SLOT, JSPROP_PERMANENT))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (!addDataProperty(cx, NameToId(cx->names().lastIndex), LAST_INDEX_SLOT, JSPROP_PERMANENT))
|
||||
return UnrootedShape(NULL);
|
||||
|
||||
/* Remaining instance properties are non-writable and non-configurable. */
|
||||
if (!self->addDataProperty(cx, NameToId(cx->names().source),
|
||||
SOURCE_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
|
||||
!self->addDataProperty(cx, NameToId(cx->names().global),
|
||||
GLOBAL_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
|
||||
!self->addDataProperty(cx, NameToId(cx->names().ignoreCase),
|
||||
IGNORE_CASE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY) ||
|
||||
!self->addDataProperty(cx, NameToId(cx->names().multiline),
|
||||
MULTILINE_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self->addDataProperty(cx, NameToId(cx->names().sticky),
|
||||
STICKY_FLAG_SLOT, JSPROP_PERMANENT | JSPROP_READONLY);
|
||||
unsigned attrs = JSPROP_PERMANENT | JSPROP_READONLY;
|
||||
if (!self->addDataProperty(cx, NameToId(cx->names().source), SOURCE_SLOT, attrs))
|
||||
return UnrootedShape(NULL);
|
||||
if (!self->addDataProperty(cx, NameToId(cx->names().global), GLOBAL_FLAG_SLOT, attrs))
|
||||
return UnrootedShape(NULL);
|
||||
if (!self->addDataProperty(cx, NameToId(cx->names().ignoreCase), IGNORE_CASE_FLAG_SLOT, attrs))
|
||||
return UnrootedShape(NULL);
|
||||
if (!self->addDataProperty(cx, NameToId(cx->names().multiline), MULTILINE_FLAG_SLOT, attrs))
|
||||
return UnrootedShape(NULL);
|
||||
return self->addDataProperty(cx, NameToId(cx->names().sticky), STICKY_FLAG_SLOT, attrs);
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -371,10 +364,11 @@ RegExpObject::init(JSContext *cx, HandleAtom source, RegExpFlag flags)
|
||||
if (!assignInitialShape(cx))
|
||||
return false;
|
||||
} else {
|
||||
Shape *shape = assignInitialShape(cx);
|
||||
RootedShape shape(cx, assignInitialShape(cx));
|
||||
if (!shape)
|
||||
return false;
|
||||
EmptyShape::insertInitialShape(cx, shape, self->getProto());
|
||||
RootedObject proto(cx, self->getProto());
|
||||
EmptyShape::insertInitialShape(cx, shape, proto);
|
||||
}
|
||||
JS_ASSERT(!self->nativeEmpty());
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ class RegExpObject : public JSObject
|
||||
* encoding their initial properties. Return the shape after
|
||||
* changing this regular expression object's last property to it.
|
||||
*/
|
||||
Shape *assignInitialShape(JSContext *cx);
|
||||
UnrootedShape assignInitialShape(JSContext *cx);
|
||||
|
||||
inline bool init(JSContext *cx, HandleAtom source, RegExpFlag flags);
|
||||
|
||||
|
@ -58,12 +58,14 @@ StaticScopeIter::hasDynamicScopeObject() const
|
||||
: obj->toFunction()->isHeavyweight();
|
||||
}
|
||||
|
||||
Shape *
|
||||
UnrootedShape
|
||||
StaticScopeIter::scopeShape() const
|
||||
{
|
||||
JS_ASSERT(hasDynamicScopeObject());
|
||||
JS_ASSERT(type() != NAMED_LAMBDA);
|
||||
return type() == BLOCK ? block().lastProperty() : funScript()->bindings.callObjShape();
|
||||
return type() == BLOCK
|
||||
? UnrootedShape(block().lastProperty())
|
||||
: funScript()->bindings.callObjShape();
|
||||
}
|
||||
|
||||
StaticScopeIter::Type
|
||||
@ -303,7 +305,7 @@ DeclEnvObject::createTemplateObject(JSContext *cx, HandleFunction fun)
|
||||
Rooted<jsid> id(cx, AtomToId(fun->atom()));
|
||||
Class *clasp = obj->getClass();
|
||||
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY;
|
||||
if (!obj->putProperty(cx, id, clasp->getProperty, clasp->setProperty,
|
||||
if (!JSObject::putProperty(cx, obj, id, clasp->getProperty, clasp->setProperty,
|
||||
lambdaSlot(), attrs, 0, 0))
|
||||
{
|
||||
return NULL;
|
||||
@ -689,7 +691,7 @@ StaticBlockObject::create(JSContext *cx)
|
||||
return &obj->asStaticBlock();
|
||||
}
|
||||
|
||||
/* static */ Shape *
|
||||
/* static */ UnrootedShape
|
||||
StaticBlockObject::addVar(JSContext *cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
int index, bool *redeclared)
|
||||
{
|
||||
@ -701,7 +703,7 @@ StaticBlockObject::addVar(JSContext *cx, Handle<StaticBlockObject*> block, Handl
|
||||
Shape **spp;
|
||||
if (Shape::search(cx, block->lastProperty(), id, &spp, true)) {
|
||||
*redeclared = true;
|
||||
return NULL;
|
||||
return UnrootedShape(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -709,7 +711,7 @@ StaticBlockObject::addVar(JSContext *cx, Handle<StaticBlockObject*> block, Handl
|
||||
* block's shape later.
|
||||
*/
|
||||
uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
|
||||
return block->addPropertyInternal(cx, id, /* getter = */ NULL, /* setter = */ NULL,
|
||||
return JSObject::addPropertyInternal(cx, block, id, /* getter = */ NULL, /* setter = */ NULL,
|
||||
slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
|
||||
Shape::HAS_SHORTID, index, spp,
|
||||
/* allowDictionary = */ false);
|
||||
@ -800,7 +802,7 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope, Handl
|
||||
return false;
|
||||
|
||||
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
|
||||
Shape *shape = &r.front();
|
||||
UnrootedShape shape = &r.front();
|
||||
shapes[shape->shortid()] = shape;
|
||||
}
|
||||
|
||||
@ -808,18 +810,21 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope, Handl
|
||||
* XDR the block object's properties. We know that there are 'count'
|
||||
* properties to XDR, stored as id/shortid pairs.
|
||||
*/
|
||||
RootedShape shape(cx);
|
||||
RootedId propid(cx);
|
||||
RootedAtom atom(cx);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
Shape *shape = shapes[i];
|
||||
shape = shapes[i];
|
||||
JS_ASSERT(shape->hasDefaultGetter());
|
||||
JS_ASSERT(unsigned(shape->shortid()) == i);
|
||||
|
||||
jsid propid = shape->propid();
|
||||
propid = shape->propid();
|
||||
JS_ASSERT(JSID_IS_ATOM(propid) || JSID_IS_INT(propid));
|
||||
|
||||
/* The empty string indicates an int id. */
|
||||
RootedAtom atom(cx, JSID_IS_ATOM(propid)
|
||||
atom = JSID_IS_ATOM(propid)
|
||||
? JSID_TO_ATOM(propid)
|
||||
: cx->runtime->emptyString);
|
||||
: cx->runtime->emptyString;
|
||||
if (!XDRAtom(xdr, &atom))
|
||||
return false;
|
||||
|
||||
@ -1222,7 +1227,7 @@ class DebugScopeProxy : public BaseProxyHandler
|
||||
/* Handle unaliased let and catch bindings at block scope. */
|
||||
if (scope->isClonedBlock()) {
|
||||
ClonedBlockObject &block = scope->asClonedBlock();
|
||||
Shape *shape = block.lastProperty()->search(cx, id);
|
||||
UnrootedShape shape = block.lastProperty()->search(cx, id);
|
||||
if (!shape)
|
||||
return false;
|
||||
|
||||
|
@ -65,7 +65,7 @@ class StaticScopeIter
|
||||
|
||||
/* Return whether this static scope will be on the dynamic scope chain. */
|
||||
bool hasDynamicScopeObject() const;
|
||||
Shape *scopeShape() const;
|
||||
UnrootedShape scopeShape() const;
|
||||
|
||||
enum Type { BLOCK, FUNCTION, NAMED_LAMBDA };
|
||||
Type type() const;
|
||||
@ -346,7 +346,7 @@ class StaticBlockObject : public BlockObject
|
||||
void initPrevBlockChainFromParser(StaticBlockObject *prev);
|
||||
void resetPrevBlockChainFromParser();
|
||||
|
||||
static Shape *addVar(JSContext *cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
static UnrootedShape addVar(JSContext *cx, Handle<StaticBlockObject*> block, HandleId id,
|
||||
int index, bool *redeclared);
|
||||
};
|
||||
|
||||
|
@ -855,6 +855,7 @@ class AutoNameVector : public AutoVectorRooter<PropertyName *>
|
||||
JS_ALWAYS_INLINE const jschar *
|
||||
JSString::getChars(JSContext *cx)
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
if (JSLinearString *str = ensureLinear(cx))
|
||||
return str->chars();
|
||||
return NULL;
|
||||
@ -863,6 +864,7 @@ JSString::getChars(JSContext *cx)
|
||||
JS_ALWAYS_INLINE const jschar *
|
||||
JSString::getCharsZ(JSContext *cx)
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
if (JSFlatString *str = ensureFlat(cx))
|
||||
return str->chars();
|
||||
return NULL;
|
||||
@ -871,6 +873,7 @@ JSString::getCharsZ(JSContext *cx)
|
||||
JS_ALWAYS_INLINE JSLinearString *
|
||||
JSString::ensureLinear(JSContext *cx)
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
return isLinear()
|
||||
? &asLinear()
|
||||
: asRope().flatten(cx);
|
||||
@ -879,6 +882,7 @@ JSString::ensureLinear(JSContext *cx)
|
||||
JS_ALWAYS_INLINE JSFlatString *
|
||||
JSString::ensureFlat(JSContext *cx)
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
return isFlat()
|
||||
? &asFlat()
|
||||
: isDependent()
|
||||
@ -889,6 +893,7 @@ JSString::ensureFlat(JSContext *cx)
|
||||
JS_ALWAYS_INLINE JSStableString *
|
||||
JSString::ensureStable(JSContext *maybecx)
|
||||
{
|
||||
JS::AutoAssertNoGC nogc;
|
||||
if (isRope()) {
|
||||
JSFlatString *flat = asRope().flatten(maybecx);
|
||||
if (!flat)
|
||||
|
@ -22,6 +22,7 @@ namespace js {
|
||||
inline bool
|
||||
StringObject::init(JSContext *cx, HandleString str)
|
||||
{
|
||||
AssertCanGC();
|
||||
JS_ASSERT(gc::GetGCKindSlots(getAllocKind()) == 2);
|
||||
|
||||
Rooted<StringObject *> self(cx, this);
|
||||
@ -31,10 +32,11 @@ StringObject::init(JSContext *cx, HandleString str)
|
||||
if (!assignInitialShape(cx))
|
||||
return false;
|
||||
} else {
|
||||
Shape *shape = assignInitialShape(cx);
|
||||
RootedShape shape(cx, assignInitialShape(cx));
|
||||
if (!shape)
|
||||
return false;
|
||||
EmptyShape::insertInitialShape(cx, shape, self->getProto());
|
||||
RootedObject proto(cx, self->getProto());
|
||||
EmptyShape::insertInitialShape(cx, shape, proto);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ class StringObject : public JSObject
|
||||
* encodes the initial length property. Return the shape after changing
|
||||
* this String object's last property to it.
|
||||
*/
|
||||
Shape *assignInitialShape(JSContext *cx);
|
||||
UnrootedShape assignInitialShape(JSContext *cx);
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
Loading…
Reference in New Issue
Block a user