From b5255ffab4aa412d1229d61a08d40415c1dc3aa1 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Thu, 18 Jun 2009 14:26:16 +0200 Subject: [PATCH] bug 498899 - avoiding excessive JS_(LOCK|UNLOCK)_OBJ while quering property cache. r=brendan --- js/src/jsinterp.cpp | 22 +++++++--------------- js/src/jsinterp.h | 9 +++------ js/src/jslock.cpp | 11 +++++++++++ js/src/jslock.h | 13 +++++++++++++ 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 7f5d49acf45b..561a711cd41c 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -433,16 +433,13 @@ js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, } pobj = obj; - JS_LOCK_OBJ(cx, pobj); if (JOF_MODE(cs->format) == JOF_NAME) { while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) { - tmp = LOCKED_OBJ_GET_PARENT(pobj); + tmp = OBJ_GET_PARENT(cx, pobj); if (!tmp || !OBJ_IS_NATIVE(tmp)) break; - JS_UNLOCK_OBJ(cx, pobj); pobj = tmp; - JS_LOCK_OBJ(cx, pobj); vcap -= PCVCAP_PROTOSIZE; } @@ -450,16 +447,14 @@ js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, } while (vcap & PCVCAP_PROTOMASK) { - tmp = LOCKED_OBJ_GET_PROTO(pobj); + tmp = OBJ_GET_PROTO(cx, pobj); if (!tmp || !OBJ_IS_NATIVE(tmp)) break; - JS_UNLOCK_OBJ(cx, pobj); pobj = tmp; - JS_LOCK_OBJ(cx, pobj); --vcap; } - if (PCVCAP_SHAPE(vcap) == OBJ_SHAPE(pobj)) { + if (JS_LOCK_OBJ_IF_SHAPE(cx, pobj, PCVCAP_SHAPE(vcap))) { #ifdef DEBUG jsid id = ATOM_TO_JSID(atom); @@ -472,7 +467,6 @@ js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, } PCMETER(JS_PROPERTY_CACHE(cx).vcmisses++); - JS_UNLOCK_OBJ(cx, pobj); return atom; } @@ -4641,13 +4635,13 @@ js_Interpret(JSContext *cx) PCVCAP_SHAPE(entry->vcap) == rt->protoHazardShape) { JS_ASSERT(PCVCAP_TAG(entry->vcap) == 0); - JS_LOCK_OBJ(cx, obj); - JSScope *scope = OBJ_SCOPE(obj); - if (scope->shape == kshape) { + if (JS_LOCK_OBJ_IF_SHAPE(cx, obj, kshape)) { JS_ASSERT(PCVAL_IS_SPROP(entry->vword)); sprop = PCVAL_TO_SPROP(entry->vword); JS_ASSERT(!(sprop->attrs & JSPROP_READONLY)); - JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj))); + + JSScope *scope = OBJ_SCOPE(obj); + JS_ASSERT(!SCOPE_IS_SEALED(scope)); /* * Fastest path: check whether the cached sprop is @@ -4776,8 +4770,6 @@ js_Interpret(JSContext *cx) PCMETER(cache->setpcmisses++); atom = NULL; } - - JS_UNLOCK_OBJ(cx, obj); } atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2, diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 7cbcdcb87880..1f4be263a616 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -380,23 +380,20 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj, if (entry->kpc == pc && entry->kshape == kshape_) { \ JSObject *tmp_; \ pobj = obj; \ - JS_LOCK_OBJ(cx, pobj); \ JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \ if (PCVCAP_TAG(entry->vcap) == 1 && \ - (tmp_ = LOCKED_OBJ_GET_PROTO(pobj)) != NULL && \ + (tmp_ = OBJ_GET_PROTO(cx, pobj)) != NULL && \ OBJ_IS_NATIVE(tmp_)) { \ - JS_UNLOCK_OBJ(cx, pobj); \ pobj = tmp_; \ - JS_LOCK_OBJ(cx, pobj); \ } \ - if (PCVCAP_SHAPE(entry->vcap) == OBJ_SHAPE(pobj)) { \ + \ + if (JS_LOCK_OBJ_IF_SHAPE(cx, pobj, PCVCAP_SHAPE(entry->vcap))) { \ PCMETER(cache_->pchits++); \ PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \ pobj = OBJ_SCOPE(pobj)->object; \ atom = NULL; \ break; \ } \ - JS_UNLOCK_OBJ(cx, pobj); \ } \ atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, &entry); \ if (atom) \ diff --git a/js/src/jslock.cpp b/js/src/jslock.cpp index eab89d473131..98ae26940e4c 100644 --- a/js/src/jslock.cpp +++ b/js/src/jslock.cpp @@ -1422,6 +1422,17 @@ js_UnlockObj(JSContext *cx, JSObject *obj) js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title); } +bool +js_LockObjIfShape(JSContext *cx, JSObject *obj, uint32 shape) +{ + JS_ASSERT(OBJ_SCOPE(obj)->title.ownercx != cx); + js_LockObj(cx, obj); + if (OBJ_SHAPE(obj) == shape) + return true; + js_UnlockObj(cx, obj); + return false; +} + void js_InitTitle(JSContext *cx, JSTitle *title) { diff --git a/js/src/jslock.h b/js/src/jslock.h index bfa0c637d7be..e466131861e7 100644 --- a/js/src/jslock.h +++ b/js/src/jslock.h @@ -160,6 +160,16 @@ struct JSTitle { #define JS_UNLOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->title.ownercx == (cx)) \ ? (void)0 : js_UnlockObj(cx, obj)) +/* + * Lock object only if its scope has the given shape. + */ +#define JS_LOCK_OBJ_IF_SHAPE(cx,obj,shape) \ + (OBJ_SHAPE(obj) == (shape) \ + ? (OBJ_SCOPE(obj)->title.ownercx == (cx) \ + ? true \ + : js_LockObjIfShape(cx, obj, shape)) \ + : false) + #define JS_LOCK_TITLE(cx,title) \ ((title)->ownercx == (cx) ? (void)0 \ : (js_LockTitle(cx, (title)), \ @@ -181,6 +191,7 @@ extern void js_LockRuntime(JSRuntime *rt); extern void js_UnlockRuntime(JSRuntime *rt); extern void js_LockObj(JSContext *cx, JSObject *obj); extern void js_UnlockObj(JSContext *cx, JSObject *obj); +extern bool js_LockObjIfShape(JSContext *cx, JSObject *obj, uint32 shape); extern void js_InitTitle(JSContext *cx, JSTitle *title); extern void js_FinishTitle(JSContext *cx, JSTitle *title); extern void js_LockTitle(JSContext *cx, JSTitle *title); @@ -262,6 +273,8 @@ extern void js_SetScopeInfo(JSScope *scope, const char *file, int line); #define JS_UNLOCK_RUNTIME(rt) ((void)0) #define JS_LOCK_OBJ(cx,obj) ((void)0) #define JS_UNLOCK_OBJ(cx,obj) ((void)0) +#define JS_LOCK_OBJ_IF_SHAPE(cx,obj,shape) (OBJ_SHAPE(obj) == (shape)) + #define JS_LOCK_OBJ_VOID(cx,obj,e) (e) #define JS_LOCK_SCOPE(cx,scope) ((void)0) #define JS_UNLOCK_SCOPE(cx,scope) ((void)0)