Bug 886205 (part 2) - Move some function definitions from vm/ObjectImpl-inl.h to vm/ObjectImpl.h. r=terrence.

--HG--
extra : rebase_source : c12d632b99542002954f02b7004cbbcfdee7f6c5
This commit is contained in:
Nicholas Nethercote 2013-06-24 16:03:02 -07:00
parent 01313ebd4b
commit e85c430408
5 changed files with 191 additions and 280 deletions

View File

@ -16,6 +16,7 @@
#include "ion/AsmJS.h"
#include "vm/ForkJoin.h"
#include "vm/Interpreter.h"
#include "vm/ObjectImpl-inl.h"

View File

@ -393,37 +393,6 @@ class TryNoteIter
/************************************************************************/
/*
* To really poison a set of values, using 'magic' or 'undefined' isn't good
* enough since often these will just be ignored by buggy code (see bug 629974)
* in debug builds and crash in release builds. Instead, we use a safe-for-crash
* pointer.
*/
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(Value *beg, Value *end)
{
#ifdef DEBUG
for (Value *v = beg; v != end; ++v)
v->setObject(*reinterpret_cast<JSObject *>(0x42));
#endif
}
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(Value *vec, size_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
#endif
}
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
#endif
}
bool
Throw(JSContext *cx, HandleValue v);

View File

@ -16,97 +16,22 @@
#include "gc/Heap.h"
#include "gc/Marking.h"
#include "js/TemplateLib.h"
#include "vm/Interpreter.h"
#include "vm/ObjectImpl.h"
#include "gc/Barrier-inl.h"
namespace js {
static MOZ_ALWAYS_INLINE void
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, uint32_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
#endif
}
static MOZ_ALWAYS_INLINE void
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
#endif
}
} // namespace js
inline JSCompartment *
js::ObjectImpl::compartment() const
{
return lastProperty()->base()->compartment();
}
inline js::TaggedProto
js::ObjectImpl::getTaggedProto() const
{
return TaggedProto(getProto());
}
inline js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyId pid)
{
return nativeLookup(cx, pid.asId());
}
inline js::Shape *
js::ObjectImpl::nativeLookup(JSContext *cx, PropertyName *name)
{
return nativeLookup(cx, NameToId(name));
}
inline bool
js::ObjectImpl::nativeContains(JSContext *cx, jsid id)
{
return nativeLookup(cx, id) != NULL;
}
inline bool
js::ObjectImpl::nativeContains(JSContext *cx, PropertyName *name)
{
return nativeLookup(cx, name) != NULL;
}
inline bool
js::ObjectImpl::nativeContains(JSContext *cx, Shape *shape)
{
return nativeLookup(cx, shape->propid()) == shape;
}
inline js::Shape *
js::ObjectImpl::nativeLookupPure(PropertyId pid)
{
return nativeLookupPure(pid.asId());
}
inline js::Shape *
js::ObjectImpl::nativeLookupPure(PropertyName *name)
{
return nativeLookupPure(NameToId(name));
}
inline bool
js::ObjectImpl::nativeContainsPure(jsid id)
{
return nativeLookupPure(id) != NULL;
}
inline bool
js::ObjectImpl::nativeContainsPure(PropertyName *name)
{
return nativeContainsPure(NameToId(name));
}
inline bool
js::ObjectImpl::nativeContainsPure(Shape *shape)
{
@ -123,88 +48,6 @@ js::ObjectImpl::isExtensible() const
return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE);
}
inline uint32_t
js::ObjectImpl::getDenseInitializedLength()
{
MOZ_ASSERT(isNative());
return getElementsHeader()->initializedLength;
}
inline uint32_t
js::ObjectImpl::getDenseCapacity()
{
MOZ_ASSERT(isNative());
return getElementsHeader()->capacity;
}
inline js::HeapSlotArray
js::ObjectImpl::getDenseElements()
{
MOZ_ASSERT(isNative());
return HeapSlotArray(elements);
}
inline const js::Value &
js::ObjectImpl::getDenseElement(uint32_t idx)
{
MOZ_ASSERT(isNative() && idx < getDenseInitializedLength());
return elements[idx];
}
inline bool
js::ObjectImpl::containsDenseElement(uint32_t idx)
{
MOZ_ASSERT(isNative());
return idx < getDenseInitializedLength() && !elements[idx].isMagic(JS_ELEMENTS_HOLE);
}
inline void
js::ObjectImpl::getSlotRangeUnchecked(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd)
{
MOZ_ASSERT(start + length >= start);
uint32_t fixed = numFixedSlots();
if (start < fixed) {
if (start + length < fixed) {
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + length];
*slotsStart = *slotsEnd = NULL;
} else {
uint32_t localCopy = fixed - start;
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + localCopy];
*slotsStart = &slots[0];
*slotsEnd = &slots[length - localCopy];
}
} else {
*fixedStart = *fixedEnd = NULL;
*slotsStart = &slots[start - fixed];
*slotsEnd = &slots[start - fixed + length];
}
}
inline void
js::ObjectImpl::getSlotRange(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd)
{
MOZ_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
}
inline void
js::ObjectImpl::invalidateSlotRange(uint32_t start, uint32_t length)
{
#ifdef DEBUG
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
#endif /* DEBUG */
}
inline bool
js::ObjectImpl::isNative() const
{
@ -217,22 +60,6 @@ js::ObjectImpl::isProxy() const
return js::IsProxy(const_cast<JSObject*>(this->asObjectPtr()));
}
inline js::HeapSlot &
js::ObjectImpl::nativeGetSlotRef(uint32_t slot)
{
MOZ_ASSERT(isNative());
MOZ_ASSERT(slot < slotSpan());
return getSlotRef(slot);
}
inline const js::Value &
js::ObjectImpl::nativeGetSlot(uint32_t slot) const
{
MOZ_ASSERT(isNative());
MOZ_ASSERT(slot < slotSpan());
return getSlot(slot);
}
#ifdef DEBUG
inline bool
IsObjectValueInCompartment(js::Value v, JSCompartment *comp)
@ -309,18 +136,6 @@ js::ObjectImpl::numDynamicSlots() const
return dynamicSlotsCount(numFixedSlots(), slotSpan());
}
inline JSClass *
js::ObjectImpl::getJSClass() const
{
return Jsvalify(getClass());
}
inline const js::ObjectOps *
js::ObjectImpl::getOps() const
{
return &getClass()->ops;
}
inline bool
js::ObjectImpl::isDelegate() const
{
@ -333,26 +148,6 @@ js::ObjectImpl::inDictionaryMode() const
return lastProperty()->inDictionary();
}
/* static */ inline uint32_t
js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span)
{
if (span <= nfixed)
return 0;
span -= nfixed;
if (span <= SLOT_CAPACITY_MIN)
return SLOT_CAPACITY_MIN;
uint32_t slots = RoundUpPow2(span);
MOZ_ASSERT(slots >= span);
return slots;
}
inline size_t
js::ObjectImpl::tenuredSizeOfThis() const
{
return js::gc::Arena::thingSize(tenuredGetAllocKind());
}
JS_ALWAYS_INLINE JS::Zone *
js::ObjectImpl::zone() const
{
@ -442,17 +237,4 @@ js::ObjectImpl::setPrivateGCThing(js::gc::Cell *cell)
privateWriteBarrierPost(pprivate);
}
inline void
js::ObjectImpl::setPrivateUnbarriered(void *data)
{
void **pprivate = &privateRef(numFixedSlots());
*pprivate = data;
}
inline void
js::ObjectImpl::initPrivate(void *data)
{
privateRef(numFixedSlots()) = data;
}
#endif /* vm_ObjectImpl_inl_h */

View File

@ -16,6 +16,18 @@
using namespace js;
void
js::ObjectImpl::assertIsNative() const
{
MOZ_ASSERT(isNative());
}
void
js::ObjectImpl::assertSlotIsWithinSpan(uint32_t slot) const
{
MOZ_ASSERT(slot < slotSpan());
}
PropDesc::PropDesc()
: pd_(UndefinedValue()),
value_(UndefinedValue()),

View File

@ -27,6 +27,53 @@ class ObjectImpl;
class Nursery;
class Shape;
/*
* To really poison a set of values, using 'magic' or 'undefined' isn't good
* enough since often these will just be ignored by buggy code (see bug 629974)
* in debug builds and crash in release builds. Instead, we use a safe-for-crash
* pointer.
*/
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(Value *beg, Value *end)
{
#ifdef DEBUG
for (Value *v = beg; v != end; ++v)
v->setObject(*reinterpret_cast<JSObject *>(0x42));
#endif
}
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(Value *vec, size_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch(vec, vec + len);
#endif
}
static JS_ALWAYS_INLINE void
Debug_SetValueRangeToCrashOnTouch(HeapValue *vec, size_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
#endif
}
static MOZ_ALWAYS_INLINE void
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *vec, uint32_t len)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) vec, len);
#endif
}
static MOZ_ALWAYS_INLINE void
Debug_SetSlotRangeToCrashOnTouch(HeapSlot *begin, HeapSlot *end)
{
#ifdef DEBUG
Debug_SetValueRangeToCrashOnTouch((Value *) begin, end - begin);
#endif
}
static inline PropertyOp
CastAsPropertyOp(JSObject *object)
{
@ -1197,11 +1244,27 @@ class ObjectImpl : public gc::Cell
static bool
preventExtensions(JSContext *cx, Handle<ObjectImpl*> obj);
inline HeapSlotArray getDenseElements();
inline const Value & getDenseElement(uint32_t idx);
inline bool containsDenseElement(uint32_t idx);
inline uint32_t getDenseInitializedLength();
inline uint32_t getDenseCapacity();
HeapSlotArray getDenseElements() {
assertIsNative();
return HeapSlotArray(elements);
}
const Value &getDenseElement(uint32_t idx) {
assertIsNative();
MOZ_ASSERT(idx < getDenseInitializedLength());
return elements[idx];
}
bool containsDenseElement(uint32_t idx) {
assertIsNative();
return idx < getDenseInitializedLength() && !elements[idx].isMagic(JS_ELEMENTS_HOLE);
}
uint32_t getDenseInitializedLength() {
assertIsNative();
return getElementsHeader()->initializedLength;
}
uint32_t getDenseCapacity() {
assertIsNative();
return getElementsHeader()->capacity;
}
bool makeElementsSparse(JSContext *cx) {
NEW_OBJECT_REPRESENTATION_ONLY();
@ -1238,19 +1301,54 @@ class ObjectImpl : public gc::Cell
* Get internal pointers to the range of values starting at start and
* running for length.
*/
inline void getSlotRangeUnchecked(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd);
inline void getSlotRange(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd);
void getSlotRangeUnchecked(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd)
{
MOZ_ASSERT(start + length >= start);
uint32_t fixed = numFixedSlots();
if (start < fixed) {
if (start + length < fixed) {
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + length];
*slotsStart = *slotsEnd = NULL;
} else {
uint32_t localCopy = fixed - start;
*fixedStart = &fixedSlots()[start];
*fixedEnd = &fixedSlots()[start + localCopy];
*slotsStart = &slots[0];
*slotsEnd = &slots[length - localCopy];
}
} else {
*fixedStart = *fixedEnd = NULL;
*slotsStart = &slots[start - fixed];
*slotsEnd = &slots[start - fixed + length];
}
}
void getSlotRange(uint32_t start, uint32_t length,
HeapSlot **fixedStart, HeapSlot **fixedEnd,
HeapSlot **slotsStart, HeapSlot **slotsEnd)
{
MOZ_ASSERT(slotInRange(start + length, SENTINEL_ALLOWED));
getSlotRangeUnchecked(start, length, fixedStart, fixedEnd, slotsStart, slotsEnd);
}
protected:
friend struct GCMarker;
friend class Shape;
friend class NewObjectCache;
inline void invalidateSlotRange(uint32_t start, uint32_t count);
void invalidateSlotRange(uint32_t start, uint32_t length) {
#ifdef DEBUG
HeapSlot *fixedStart, *fixedEnd, *slotsStart, *slotsEnd;
getSlotRange(start, length, &fixedStart, &fixedEnd, &slotsStart, &slotsEnd);
Debug_SetSlotRangeToCrashOnTouch(fixedStart, fixedEnd);
Debug_SetSlotRangeToCrashOnTouch(slotsStart, slotsEnd);
#endif /* DEBUG */
}
void initializeSlotRange(uint32_t start, uint32_t count);
/*
@ -1310,7 +1408,9 @@ class ObjectImpl : public gc::Cell
*/
public:
inline js::TaggedProto getTaggedProto() const;
js::TaggedProto getTaggedProto() const {
return TaggedProto(getProto());
}
Shape * lastProperty() const {
MOZ_ASSERT(shape_);
@ -1324,6 +1424,7 @@ class ObjectImpl : public gc::Cell
inline JSCompartment *compartment() const;
inline bool isNative() const;
void assertIsNative() const;
types::TypeObject *type() const {
MOZ_ASSERT(!hasLazyType());
@ -1347,16 +1448,25 @@ class ObjectImpl : public gc::Cell
bool hasLazyType() const { return type_->lazy(); }
inline uint32_t slotSpan() const;
void assertSlotIsWithinSpan(uint32_t slot) const;
/* 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);
Shape *nativeLookup(JSContext *cx, PropertyId pid) {
return nativeLookup(cx, pid.asId());
}
Shape *nativeLookup(JSContext *cx, PropertyName *name) {
return nativeLookup(cx, NameToId(name));
}
inline bool nativeContains(JSContext *cx, jsid id);
inline bool nativeContains(JSContext *cx, PropertyName* name);
bool nativeContains(JSContext *cx, jsid id) {
return nativeLookup(cx, id) != NULL;
}
bool nativeContains(JSContext *cx, PropertyName* name) {
return nativeLookup(cx, name) != NULL;
}
inline bool nativeContains(JSContext *cx, Shape* shape);
/*
@ -1364,18 +1474,30 @@ class ObjectImpl : public gc::Cell
* operation would have been effectful.
*/
Shape *nativeLookupPure(jsid id);
inline Shape *nativeLookupPure(PropertyId pid);
inline Shape *nativeLookupPure(PropertyName *name);
Shape *nativeLookupPure(PropertyId pid) {
return nativeLookupPure(pid.asId());
}
Shape *nativeLookupPure(PropertyName *name) {
return nativeLookupPure(NameToId(name));
}
inline bool nativeContainsPure(jsid id);
inline bool nativeContainsPure(PropertyName* name);
inline bool nativeContainsPure(Shape* shape);
bool nativeContainsPure(jsid id) {
return nativeLookupPure(id) != NULL;
}
bool nativeContainsPure(PropertyName* name) {
return nativeContainsPure(NameToId(name));
}
bool nativeContainsPure(Shape* shape);
inline JSClass *getJSClass() const;
inline bool hasClass(const Class *c) const {
JSClass *getJSClass() const {
return Jsvalify(getClass());
}
bool hasClass(const Class *c) const {
return getClass() == c;
}
inline const ObjectOps *getOps() const;
const ObjectOps *getOps() const {
return &getClass()->ops;
}
/*
* An object is a delegate if it is on another object's prototype or scope
@ -1425,8 +1547,16 @@ class ObjectImpl : public gc::Cell
return *getSlotAddress(slot);
}
inline HeapSlot &nativeGetSlotRef(uint32_t slot);
inline const Value &nativeGetSlot(uint32_t slot) const;
HeapSlot &nativeGetSlotRef(uint32_t slot) {
assertIsNative();
assertSlotIsWithinSpan(slot);
return getSlotRef(slot);
}
const Value &nativeGetSlot(uint32_t slot) const {
assertIsNative();
assertSlotIsWithinSpan(slot);
return getSlot(slot);
}
inline void setSlot(uint32_t slot, const Value &value);
inline void setCrossCompartmentSlot(uint32_t slot, const Value &value);
@ -1455,10 +1585,22 @@ class ObjectImpl : public gc::Cell
* capacity is not stored explicitly, and the allocated size of the slot
* array is kept in sync with this count.
*/
static inline uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span);
static uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span) {
if (span <= nfixed)
return 0;
span -= nfixed;
if (span <= SLOT_CAPACITY_MIN)
return SLOT_CAPACITY_MIN;
uint32_t slots = RoundUpPow2(span);
MOZ_ASSERT(slots >= span);
return slots;
}
/* Memory usage functions. */
inline size_t tenuredSizeOfThis() const;
size_t tenuredSizeOfThis() const {
return js::gc::Arena::thingSize(tenuredGetAllocKind());
}
/* Elements accessors. */
@ -1531,8 +1673,13 @@ class ObjectImpl : public gc::Cell
}
inline void setPrivate(void *data);
inline void setPrivateGCThing(gc::Cell *cell);
inline void setPrivateUnbarriered(void *data);
inline void initPrivate(void *data);
void setPrivateUnbarriered(void *data) {
void **pprivate = &privateRef(numFixedSlots());
*pprivate = data;
}
void initPrivate(void *data) {
privateRef(numFixedSlots()) = data;
}
/* Access private data for an object with a known number of fixed slots. */
inline void *getPrivate(uint32_t nfixed) const {