mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 500431 part 2 - Replace macros with inline functions in jspropertycache. r=brendan.
--HG-- extra : rebase_source : efb0e75798145ff1bb64607262345aea67a51290
This commit is contained in:
parent
25153c3c13
commit
dbf25821e4
@ -49,42 +49,63 @@ JS_BEGIN_EXTERN_C
|
||||
* polymorphic callsite method/get/set speedups. For details, see
|
||||
* <https://developer.mozilla.org/en/SpiderMonkey/Internals/Property_cache>.
|
||||
*/
|
||||
#define PROPERTY_CACHE_LOG2 12
|
||||
#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2)
|
||||
#define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2)
|
||||
|
||||
enum {
|
||||
PROPERTY_CACHE_LOG2 = 12,
|
||||
PROPERTY_CACHE_SIZE = JS_BIT(PROPERTY_CACHE_LOG2),
|
||||
PROPERTY_CACHE_MASK = JS_BITMASK(PROPERTY_CACHE_LOG2)
|
||||
};
|
||||
|
||||
/*
|
||||
* Add kshape rather than xor it to avoid collisions between nearby bytecode
|
||||
* that are evolving an object by setting successive properties, incrementing
|
||||
* the object's scope->shape on each set.
|
||||
*/
|
||||
#define PROPERTY_CACHE_HASH(pc,kshape) \
|
||||
(((((jsuword)(pc) >> PROPERTY_CACHE_LOG2) ^ (jsuword)(pc)) + (kshape)) & \
|
||||
PROPERTY_CACHE_MASK)
|
||||
inline jsuword
|
||||
PROPERTY_CACHE_HASH(jsbytecode *pc, jsuword kshape)
|
||||
{
|
||||
return ((((jsuword(pc) >> PROPERTY_CACHE_LOG2) ^ jsuword(pc)) + kshape) & PROPERTY_CACHE_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Property cache value capability macros.
|
||||
*/
|
||||
#define PCVCAP_PROTOBITS 4
|
||||
#define PCVCAP_PROTOSIZE JS_BIT(PCVCAP_PROTOBITS)
|
||||
#define PCVCAP_PROTOMASK JS_BITMASK(PCVCAP_PROTOBITS)
|
||||
/* Property cache value capabilities. */
|
||||
enum {
|
||||
PCVCAP_PROTOBITS = 4,
|
||||
PCVCAP_PROTOSIZE = JS_BIT(PCVCAP_PROTOBITS),
|
||||
PCVCAP_PROTOMASK = JS_BITMASK(PCVCAP_PROTOBITS),
|
||||
|
||||
#define PCVCAP_SCOPEBITS 4
|
||||
#define PCVCAP_SCOPESIZE JS_BIT(PCVCAP_SCOPEBITS)
|
||||
#define PCVCAP_SCOPEMASK JS_BITMASK(PCVCAP_SCOPEBITS)
|
||||
PCVCAP_SCOPEBITS = 4,
|
||||
PCVCAP_SCOPESIZE = JS_BIT(PCVCAP_SCOPEBITS),
|
||||
PCVCAP_SCOPEMASK = JS_BITMASK(PCVCAP_SCOPEBITS),
|
||||
|
||||
#define PCVCAP_TAGBITS (PCVCAP_PROTOBITS + PCVCAP_SCOPEBITS)
|
||||
#define PCVCAP_TAGMASK JS_BITMASK(PCVCAP_TAGBITS)
|
||||
#define PCVCAP_TAG(t) ((t) & PCVCAP_TAGMASK)
|
||||
PCVCAP_TAGBITS = PCVCAP_PROTOBITS + PCVCAP_SCOPEBITS,
|
||||
PCVCAP_TAGMASK = JS_BITMASK(PCVCAP_TAGBITS)
|
||||
};
|
||||
|
||||
#define PCVCAP_MAKE(t,s,p) ((uint32(t) << PCVCAP_TAGBITS) | \
|
||||
((s) << PCVCAP_PROTOBITS) | \
|
||||
(p))
|
||||
#define PCVCAP_SHAPE(t) ((t) >> PCVCAP_TAGBITS)
|
||||
const uint32 SHAPE_OVERFLOW_BIT = JS_BIT(32 - PCVCAP_TAGBITS);
|
||||
|
||||
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS)
|
||||
inline jsuword
|
||||
PCVCAP_TAG(jsuword t)
|
||||
{
|
||||
return t & PCVCAP_TAGMASK;
|
||||
}
|
||||
|
||||
struct JSPropCacheEntry {
|
||||
inline jsuword
|
||||
PCVCAP_MAKE(uint32 t, unsigned int s, unsigned int p)
|
||||
{
|
||||
JS_ASSERT(t < SHAPE_OVERFLOW_BIT);
|
||||
JS_ASSERT(s <= PCVCAP_SCOPEMASK);
|
||||
JS_ASSERT(p <= PCVCAP_PROTOMASK);
|
||||
return (t << PCVCAP_TAGBITS) | (s << PCVCAP_PROTOBITS) | p;
|
||||
}
|
||||
|
||||
inline uint32
|
||||
PCVCAP_SHAPE(jsuword t)
|
||||
{
|
||||
return t >> PCVCAP_TAGBITS;
|
||||
}
|
||||
|
||||
struct JSPropCacheEntry
|
||||
{
|
||||
jsbytecode *kpc; /* pc of cache-testing bytecode */
|
||||
jsuword kshape; /* shape of direct (key) object */
|
||||
jsuword vcap; /* value capability, see above */
|
||||
@ -153,33 +174,37 @@ typedef struct JSPropertyCache {
|
||||
/*
|
||||
* Property cache value tagging/untagging macros.
|
||||
*/
|
||||
#define PCVAL_OBJECT 0
|
||||
#define PCVAL_SLOT 1
|
||||
#define PCVAL_SPROP 2
|
||||
enum {
|
||||
PCVAL_OBJECT = 0,
|
||||
PCVAL_SLOT = 1,
|
||||
PCVAL_SPROP = 2,
|
||||
|
||||
#define PCVAL_TAGBITS 2
|
||||
#define PCVAL_TAGMASK JS_BITMASK(PCVAL_TAGBITS)
|
||||
#define PCVAL_TAG(v) ((v) & PCVAL_TAGMASK)
|
||||
#define PCVAL_CLRTAG(v) ((v) & ~(jsuword)PCVAL_TAGMASK)
|
||||
#define PCVAL_SETTAG(v,t) ((jsuword)(v) | (t))
|
||||
PCVAL_TAGBITS = 2,
|
||||
PCVAL_TAGMASK = JS_BITMASK(PCVAL_TAGBITS),
|
||||
|
||||
#define PCVAL_NULL 0
|
||||
#define PCVAL_IS_NULL(v) ((v) == PCVAL_NULL)
|
||||
PCVAL_NULL = 0
|
||||
};
|
||||
|
||||
#define PCVAL_IS_OBJECT(v) (PCVAL_TAG(v) == PCVAL_OBJECT)
|
||||
#define PCVAL_TO_OBJECT(v) ((JSObject *) (v))
|
||||
#define OBJECT_TO_PCVAL(obj) ((jsuword) (obj))
|
||||
inline jsuword PCVAL_TAG(jsuword v) { return v & PCVAL_TAGMASK; }
|
||||
inline jsuword PCVAL_CLRTAG(jsuword v) { return v & ~jsuword(PCVAL_TAGMASK); }
|
||||
inline jsuword PCVAL_SETTAG(jsuword v, jsuword t) { return v | t; }
|
||||
|
||||
#define PCVAL_OBJECT_TO_JSVAL(v) OBJECT_TO_JSVAL(PCVAL_TO_OBJECT(v))
|
||||
#define JSVAL_OBJECT_TO_PCVAL(v) OBJECT_TO_PCVAL(JSVAL_TO_OBJECT(v))
|
||||
inline bool PCVAL_IS_NULL(jsuword v) { return v == PCVAL_NULL; }
|
||||
|
||||
#define PCVAL_IS_SLOT(v) ((v) & PCVAL_SLOT)
|
||||
#define PCVAL_TO_SLOT(v) ((jsuint)(v) >> 1)
|
||||
#define SLOT_TO_PCVAL(i) (((jsuword)(i) << 1) | PCVAL_SLOT)
|
||||
inline bool PCVAL_IS_OBJECT(jsuword v) { return PCVAL_TAG(v) == PCVAL_OBJECT; }
|
||||
inline JSObject *PCVAL_TO_OBJECT(jsuword v) { JS_ASSERT(PCVAL_IS_OBJECT(v)); return (JSObject *) v; }
|
||||
inline jsuword OBJECT_TO_PCVAL(JSObject *obj) { return jsuword(obj); }
|
||||
|
||||
#define PCVAL_IS_SPROP(v) (PCVAL_TAG(v) == PCVAL_SPROP)
|
||||
#define PCVAL_TO_SPROP(v) ((JSScopeProperty *) PCVAL_CLRTAG(v))
|
||||
#define SPROP_TO_PCVAL(sprop) PCVAL_SETTAG(sprop, PCVAL_SPROP)
|
||||
inline jsval PCVAL_OBJECT_TO_JSVAL(jsuword v) { return OBJECT_TO_JSVAL(PCVAL_TO_OBJECT(v)); }
|
||||
inline jsuword JSVAL_OBJECT_TO_PCVAL(jsval v) { return OBJECT_TO_PCVAL(JSVAL_TO_OBJECT(v)); }
|
||||
|
||||
inline bool PCVAL_IS_SLOT(jsuword v) { return v & PCVAL_SLOT; }
|
||||
inline jsuint PCVAL_TO_SLOT(jsuword v) { JS_ASSERT(PCVAL_IS_SLOT(v)); return jsuint(v) >> 1; }
|
||||
inline jsuword SLOT_TO_PCVAL(jsuint i) { return (jsuword(i) << 1) | PCVAL_SLOT; }
|
||||
|
||||
inline bool PCVAL_IS_SPROP(jsuword v) { return PCVAL_TAG(v) == PCVAL_SPROP; }
|
||||
inline JSScopeProperty *PCVAL_TO_SPROP(jsuword v) { JS_ASSERT(PCVAL_IS_SPROP(v)); return (JSScopeProperty *) PCVAL_CLRTAG(v); }
|
||||
inline jsuword SPROP_TO_PCVAL(JSScopeProperty *sprop) { return PCVAL_SETTAG(jsuword(sprop), PCVAL_SPROP); }
|
||||
|
||||
/*
|
||||
* Fill property cache entry for key cx->fp->pc, optimized value word computed
|
||||
|
@ -42,8 +42,7 @@
|
||||
#ifndef jspropertycacheinlines_h___
|
||||
#define jspropertycacheinlines_h___
|
||||
|
||||
#include "jsinterp.h"
|
||||
#include "jslock.h"
|
||||
#include "jspropertycache.h"
|
||||
#include "jsscope.h"
|
||||
|
||||
/* static */ inline bool
|
||||
@ -53,10 +52,10 @@ JSPropCacheEntry::matchShape(JSContext *cx, JSObject *obj, uint32 shape)
|
||||
}
|
||||
|
||||
/*
|
||||
* Property cache lookup macros. PROPERTY_CACHE_TEST is designed to inline the
|
||||
* fast path in js_Interpret, so it makes "just-so" restrictions on parameters,
|
||||
* e.g. pobj and obj should not be the same variable, since for JOF_PROP-mode
|
||||
* opcodes, obj must not be changed because of a cache miss.
|
||||
* PROPERTY_CACHE_TEST is designed to inline the fast path in js_Interpret, so
|
||||
* it makes "just-so" restrictions on parameters, e.g. pobj and obj should not
|
||||
* be the same variable, since for JOF_PROP-mode opcodes, obj must not be
|
||||
* changed because of a cache miss.
|
||||
*
|
||||
* On return from PROPERTY_CACHE_TEST, if atom is null then obj points to the
|
||||
* scope chain element in which the property was found, pobj is locked, and
|
||||
@ -68,33 +67,35 @@ JSPropCacheEntry::matchShape(JSContext *cx, JSObject *obj, uint32 shape)
|
||||
* be deleting a property from its scope, or otherwise invalidating property
|
||||
* caches (on all threads) by re-generating scope->shape.
|
||||
*/
|
||||
#define PROPERTY_CACHE_TEST(cx, pc, obj, pobj, entry, atom) \
|
||||
do { \
|
||||
JSPropertyCache *cache_ = &JS_PROPERTY_CACHE(cx); \
|
||||
uint32 kshape_ = (JS_ASSERT(OBJ_IS_NATIVE(obj)), OBJ_SHAPE(obj)); \
|
||||
entry = &cache_->table[PROPERTY_CACHE_HASH(pc, kshape_)]; \
|
||||
PCMETER(cache_->pctestentry = entry); \
|
||||
PCMETER(cache_->tests++); \
|
||||
JS_ASSERT(&obj != &pobj); \
|
||||
if (entry->kpc == pc && entry->kshape == kshape_) { \
|
||||
JSObject *tmp_; \
|
||||
pobj = obj; \
|
||||
if (PCVCAP_TAG(entry->vcap) == 1 && \
|
||||
(tmp_ = pobj->getProto()) != NULL) { \
|
||||
pobj = tmp_; \
|
||||
} \
|
||||
\
|
||||
if (JSPropCacheEntry::matchShape(cx, pobj, \
|
||||
PCVCAP_SHAPE(entry->vcap))) { \
|
||||
PCMETER(cache_->pchits++); \
|
||||
PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \
|
||||
atom = NULL; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, entry); \
|
||||
if (atom) \
|
||||
PCMETER(cache_->misses++); \
|
||||
} while (0)
|
||||
JS_ALWAYS_INLINE void
|
||||
PROPERTY_CACHE_TEST(JSContext *cx, jsbytecode *pc, JSObject *&obj,
|
||||
JSObject *&pobj, JSPropCacheEntry *&entry, JSAtom *&atom)
|
||||
{
|
||||
JSPropertyCache *cache = &JS_PROPERTY_CACHE(cx);
|
||||
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||
uint32 kshape = OBJ_SHAPE(obj);
|
||||
entry = &cache->table[PROPERTY_CACHE_HASH(pc, kshape)];
|
||||
PCMETER(cache->pctestentry = entry);
|
||||
PCMETER(cache->tests++);
|
||||
JS_ASSERT(&obj != &pobj);
|
||||
if (entry->kpc == pc && entry->kshape == kshape) {
|
||||
JSObject *tmp;
|
||||
pobj = obj;
|
||||
if (PCVCAP_TAG(entry->vcap) == 1 &&
|
||||
(tmp = pobj->getProto()) != NULL) {
|
||||
pobj = tmp;
|
||||
}
|
||||
|
||||
if (JSPropCacheEntry::matchShape(cx, pobj, PCVCAP_SHAPE(entry->vcap))) {
|
||||
PCMETER(cache->pchits++);
|
||||
PCMETER(!PCVCAP_TAG(entry->vcap) || cache->protopchits++);
|
||||
atom = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, entry);
|
||||
if (atom)
|
||||
PCMETER(cache->misses++);
|
||||
}
|
||||
|
||||
#endif /* jspropertycacheinlines_h___ */
|
||||
|
Loading…
Reference in New Issue
Block a user