Bug 713944 -Convert PropertyCacheEntry::vindex into two separate, private fields, and add some accessors for them. r=jorendorff

--HG--
extra : rebase_source : f7efae003a443e5381900b95273370ff3baa8a62
This commit is contained in:
Jeff Walden 2011-12-29 05:43:57 -06:00
parent d075492ab2
commit e0aea303a9
5 changed files with 61 additions and 37 deletions

View File

@ -3162,16 +3162,16 @@ BEGIN_CASE(JSOP_SETMETHOD)
*/
const Shape *shape = entry->prop;
JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
JS_ASSERT_IF(shape->hasSlot(), !entry->vindex);
JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
if (entry->vindex == 0 ||
if (entry->isOwnPropertyHit() ||
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
#ifdef DEBUG
if (entry->directHit()) {
if (entry->isOwnPropertyHit()) {
JS_ASSERT(obj->nativeContains(cx, *shape));
} else {
JS_ASSERT(obj2->nativeContains(cx, *shape));
JS_ASSERT(entry->vindex == 1);
JS_ASSERT(entry->isPrototypePropertyHit());
JS_ASSERT(entry->kshape != entry->pshape);
JS_ASSERT(!shape->hasSlot());
}
@ -4466,7 +4466,8 @@ BEGIN_CASE(JSOP_INITMETHOD)
JSAtom *atom;
if (JS_PROPERTY_CACHE(cx).testForSet(cx, regs.pc, obj, &entry, &obj2, &atom) &&
entry->prop->hasDefaultSetter() &&
entry->vindex == 0) {
entry->isOwnPropertyHit())
{
JS_ASSERT(obj == obj2);
/* Fast path. Property cache hit. */
obj->nativeSetSlotWithType(cx, entry->prop, rval);

View File

@ -80,7 +80,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
JS_ASSERT_IF(obj == pobj, scopeIndex == 0);
JSObject *tmp = obj;
for (uintN i = 0; i != scopeIndex; i++)
for (uintN i = 0; i < scopeIndex; i++)
tmp = tmp->internalScopeChain();
uintN protoIndex = 0;
@ -109,7 +109,8 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
++protoIndex;
}
if (scopeIndex > PCINDEX_SCOPEMASK || protoIndex > PCINDEX_PROTOMASK) {
typedef PropertyCacheEntry Entry;
if (scopeIndex > Entry::MaxScopeIndex || protoIndex > Entry::MaxProtoIndex) {
PCMETER(longchains++);
return JS_NO_PROP_CACHE_FILL;
}
@ -196,7 +197,6 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
const JSCodeSpec &cs = js_CodeSpec[op];
obj = *objp;
uint32_t vindex = entry->vindex;
if (entry->kpc != pc) {
PCMETER(kpcmisses++);
@ -234,23 +234,25 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
pobj = obj;
if (JOF_MODE(cs.format) == JOF_NAME) {
while (vindex & (PCINDEX_SCOPEMASK << PCINDEX_PROTOBITS)) {
uint8_t scopeIndex = entry->scopeIndex;
while (scopeIndex > 0) {
tmp = pobj->scopeChain();
if (!tmp || !tmp->isNative())
break;
pobj = tmp;
vindex -= PCINDEX_PROTOSIZE;
scopeIndex--;
}
*objp = pobj;
}
while (vindex & PCINDEX_PROTOMASK) {
uint8_t protoIndex = entry->protoIndex;
while (protoIndex > 0) {
tmp = pobj->getProto();
if (!tmp || !tmp->isNative())
break;
pobj = tmp;
--vindex;
protoIndex--;
}
if (pobj->lastProperty() == entry->pshape) {
@ -279,7 +281,8 @@ PropertyCache::assertEmpty()
JS_ASSERT(!table[i].kshape);
JS_ASSERT(!table[i].pshape);
JS_ASSERT(!table[i].prop);
JS_ASSERT(!table[i].vindex);
JS_ASSERT(!table[i].scopeIndex);
JS_ASSERT(!table[i].protoIndex);
}
}
#endif

View File

@ -52,17 +52,7 @@ namespace js {
* polymorphic callsite method/get/set speedups. For details, see
* <https://developer.mozilla.org/en/SpiderMonkey/Internals/Property_cache>.
*/
/* Indexing for property cache entry scope and prototype chain walking. */
enum {
PCINDEX_PROTOBITS = 4,
PCINDEX_PROTOSIZE = JS_BIT(PCINDEX_PROTOBITS),
PCINDEX_PROTOMASK = JS_BITMASK(PCINDEX_PROTOBITS),
PCINDEX_SCOPEBITS = 4,
PCINDEX_SCOPESIZE = JS_BIT(PCINDEX_SCOPEBITS),
PCINDEX_SCOPEMASK = JS_BITMASK(PCINDEX_SCOPEBITS)
};
class PropertyCache;
struct PropertyCacheEntry
{
@ -70,21 +60,50 @@ struct PropertyCacheEntry
const Shape *kshape; /* shape of direct (key) object */
const Shape *pshape; /* shape of owning object */
const Shape *prop; /* shape of accessed property */
uint16_t vindex; /* scope/proto chain indexing,
* see PCINDEX above */
bool directHit() const { return vindex == 0; }
friend class PropertyCache;
private:
/* Index into scope chain; inapplicable to property lookup entries. */
uint8_t scopeIndex;
/* Index into the prototype chain from the object for this entry. */
uint8_t protoIndex;
public:
static const size_t MaxScopeIndex = 15;
static const size_t MaxProtoIndex = 15;
/*
* True iff the property lookup will find an own property on the object if
* the entry matches.
*
* This test is applicable only to property lookups, not to identifier
* lookups. It is meaningless to ask this question of an entry for an
* identifier lookup.
*/
bool isOwnPropertyHit() const { return scopeIndex == 0 && protoIndex == 0; }
/*
* True iff the property lookup will find the property on the prototype of
* the object if the entry matches.
*
* This test is applicable only to property lookups, not to identifier
* lookups. It is meaningless to ask this question of an entry for an
* identifier lookup.
*/
bool isPrototypePropertyHit() const { return scopeIndex == 0 && protoIndex == 1; }
void assign(jsbytecode *kpc, const Shape *kshape, const Shape *pshape,
const Shape *prop, uintN scopeIndex, uintN protoIndex) {
JS_ASSERT(scopeIndex <= PCINDEX_SCOPEMASK);
JS_ASSERT(protoIndex <= PCINDEX_PROTOMASK);
JS_ASSERT(scopeIndex <= MaxScopeIndex);
JS_ASSERT(protoIndex <= MaxProtoIndex);
this->kpc = kpc;
this->kshape = kshape;
this->pshape = pshape;
this->prop = prop;
this->vindex = (scopeIndex << PCINDEX_PROTOBITS) | protoIndex;
this->scopeIndex = uint8_t(scopeIndex);
this->protoIndex = uint8_t(protoIndex);
}
};

View File

@ -77,14 +77,14 @@ PropertyCache::test(JSContext *cx, jsbytecode *pc, JSObject *&obj,
if (entry->kpc == pc && entry->kshape == kshape) {
JSObject *tmp;
pobj = obj;
if (entry->vindex == 1 &&
if (entry->isPrototypePropertyHit() &&
(tmp = pobj->getProto()) != NULL) {
pobj = tmp;
}
if (pobj->lastProperty() == entry->pshape) {
PCMETER(pchits++);
PCMETER(!entry->vindex || protopchits++);
PCMETER(entry->isOwnPropertyHit() || protopchits++);
atom = NULL;
return;
}

View File

@ -169,16 +169,16 @@ stubs::SetName(VMFrame &f, JSAtom *origAtom)
*/
const Shape *shape = entry->prop;
JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable());
JS_ASSERT_IF(shape->hasSlot(), !entry->vindex);
JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit());
if (entry->vindex == 0 ||
if (entry->isOwnPropertyHit() ||
((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) {
#ifdef DEBUG
if (entry->directHit()) {
if (entry->isOwnPropertyHit()) {
JS_ASSERT(obj->nativeContains(cx, *shape));
} else {
JS_ASSERT(obj2->nativeContains(cx, *shape));
JS_ASSERT(entry->vindex == 1);
JS_ASSERT(entry->isPrototypePropertyHit());
JS_ASSERT(entry->kshape != entry->pshape);
JS_ASSERT(!shape->hasSlot());
}
@ -1646,7 +1646,8 @@ InitPropOrMethod(VMFrame &f, JSAtom *atom, JSOp op)
JSAtom *atom2;
if (JS_PROPERTY_CACHE(cx).testForSet(cx, f.pc(), obj, &entry, &obj2, &atom2) &&
entry->prop->hasDefaultSetter() &&
entry->vindex == 0) {
entry->isOwnPropertyHit())
{
JS_ASSERT(obj == obj2);
/* Fast path. Property cache hit. */
obj->nativeSetSlotWithType(cx, entry->prop, rval);