diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 5ccce3197722..3ebfe1c1986b 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -464,7 +464,7 @@ static unsigned finalizeCount = 0; static void finalize_counter_finalize(JSFreeOp *fop, JSObject *obj) { - ++finalizeCount; + JS_ATOMIC_INCREMENT(&finalizeCount); } static JSClass FinalizeCounterClass = { diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 0be5cb6bdaf3..7a8e6b0ff5f6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4560,14 +4560,14 @@ JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id_, JSAccessMode mode, JS_PUBLIC_API(void) JS_HoldPrincipals(JSPrincipals *principals) { - ++principals->refcount; + JS_ATOMIC_INCREMENT(&principals->refcount); } JS_PUBLIC_API(void) JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals) { - JS_AbortIfWrongThread(rt); - if (--principals->refcount == 0) + int rc = JS_ATOMIC_DECREMENT(&principals->refcount); + if (rc == 0) rt->destroyPrincipals(principals); } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index c62ea986762b..2f4c73e8de3c 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -125,7 +125,11 @@ JSRuntime::sizeOfExplicitNonHeap() void JSRuntime::triggerOperationCallback() { - interrupt = 1; + /* + * Use JS_ATOMIC_SET in the hope that it ensures the write will become + * immediately visible to other processors polling the flag. + */ + JS_ATOMIC_SET(&interrupt, 1); } void @@ -434,9 +438,8 @@ js_ReportOutOfMemory(JSContext *cx) } if (onError) { - ++cx->runtime->inOOMReport; + AutoAtomicIncrement incr(&cx->runtime->inOOMReport); onError(cx, msg, &report); - --cx->runtime->inOOMReport; } } @@ -908,7 +911,7 @@ js_InvokeOperationCallback(JSContext *cx) * thread is racing us here we will accumulate another callback request * which will be serviced at the next opportunity. */ - rt->interrupt = 0; + JS_ATOMIC_SET(&rt->interrupt, 0); if (rt->gcIsNeeded) GCSlice(rt, GC_NORMAL, rt->gcTriggerReason); diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 6c2c48714264..f69397c8f7d3 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -758,7 +758,7 @@ struct JSRuntime : js::RuntimeFriendFields * and for each JSObject::remove method call that frees a slot in the given * object. See js_NativeGet and js_NativeSet in jsobj.cpp. */ - uint32_t propertyRemovals; + int32_t propertyRemovals; /* Number localization, used by jsnum.c */ const char *thousandsSeparator; diff --git a/js/src/jslock.h b/js/src/jslock.h index 4db943a5918d..15a0e7380685 100644 --- a/js/src/jslock.h +++ b/js/src/jslock.h @@ -10,17 +10,49 @@ #ifdef JS_THREADSAFE +# include "pratom.h" # include "prlock.h" # include "prcvar.h" # include "prthread.h" # include "prinit.h" +# define JS_ATOMIC_INCREMENT(p) PR_ATOMIC_INCREMENT((PRInt32 *)(p)) +# define JS_ATOMIC_DECREMENT(p) PR_ATOMIC_DECREMENT((PRInt32 *)(p)) +# define JS_ATOMIC_ADD(p,v) PR_ATOMIC_ADD((PRInt32 *)(p), (PRInt32)(v)) +# define JS_ATOMIC_SET(p,v) PR_ATOMIC_SET((PRInt32 *)(p), (PRInt32)(v)) + #else /* JS_THREADSAFE */ typedef struct PRThread PRThread; typedef struct PRCondVar PRCondVar; typedef struct PRLock PRLock; +# define JS_ATOMIC_INCREMENT(p) (++*(p)) +# define JS_ATOMIC_DECREMENT(p) (--*(p)) +# define JS_ATOMIC_ADD(p,v) (*(p) += (v)) +# define JS_ATOMIC_SET(p,v) (*(p) = (v)) + #endif /* JS_THREADSAFE */ +namespace js { + +class AutoAtomicIncrement +{ + int32_t *p; + JS_DECL_USE_GUARD_OBJECT_NOTIFIER + + public: + AutoAtomicIncrement(int32_t *p JS_GUARD_OBJECT_NOTIFIER_PARAM) + : p(p) { + JS_GUARD_OBJECT_NOTIFIER_INIT; + JS_ATOMIC_INCREMENT(p); + } + + ~AutoAtomicIncrement() { + JS_ATOMIC_DECREMENT(p); + } +}; + +} /* namespace js */ + #endif /* jslock_h___ */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index dc9f87490761..aea9707812ac 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -4618,7 +4618,7 @@ js_NativeSet(JSContext *cx, Handle obj, Handle receiver, Rooted shapeRoot(cx, shape); - uint32_t sample = cx->runtime->propertyRemovals; + int32_t sample = cx->runtime->propertyRemovals; if (!shapeRoot->set(cx, obj, receiver, strict, vp)) return false; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index cbf8718908c0..961c0bfbbfc5 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -748,7 +748,7 @@ JSObject::putProperty(JSContext *cx, jsid id_, if (hadSlot && !shape->hasSlot()) { if (oldSlot < self->slotSpan()) self->freeSlot(cx, oldSlot); - ++cx->runtime->propertyRemovals; + JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); } self->checkShapeConsistency(); @@ -851,7 +851,7 @@ JSObject::removeProperty(JSContext *cx, jsid id_) /* If shape has a slot, free its slot number. */ if (shape->hasSlot()) { self->freeSlot(cx, shape->slot()); - ++cx->runtime->propertyRemovals; + JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); } /* @@ -928,7 +928,7 @@ JSObject::clear(JSContext *cx) JS_ALWAYS_TRUE(setLastProperty(cx, shape)); - ++cx->runtime->propertyRemovals; + JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); checkShapeConsistency(); } diff --git a/js/src/prmjtime.cpp b/js/src/prmjtime.cpp index a64fa98a1911..e4731894ddd2 100644 --- a/js/src/prmjtime.cpp +++ b/js/src/prmjtime.cpp @@ -346,9 +346,15 @@ def PRMJ_Now(): */ +// We parameterize the delay count just so that shell builds can +// set it to 0 in order to get high-resolution benchmarking. +// 10 seems to be the number of calls to load with a blank homepage. +int CALIBRATION_DELAY_COUNT = 10; + int64_t PRMJ_Now(void) { + static int nCalls = 0; long double lowresTime, highresTimerValue; FILETIME ft; LARGE_INTEGER now; @@ -357,6 +363,16 @@ PRMJ_Now(void) int64_t returnedTime; long double cachedOffset = 0.0; + /* To avoid regressing startup time (where high resolution is likely + not needed), give the old behavior for the first few calls. + This does not appear to be needed on Vista as the timeBegin/timeEndPeriod + calls seem to immediately take effect. */ + int thiscall = JS_ATOMIC_INCREMENT(&nCalls); + if (thiscall <= CALIBRATION_DELAY_COUNT) { + LowResTime(&ft); + return (FILETIME2INT64(ft)-win2un)/10L; + } + /* For non threadsafe platforms, NowInit is not necessary */ #ifdef JS_THREADSAFE PR_CallOnce(&calibrationOnce, NowInit); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 3130575aacca..fbf56f039b73 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -4853,6 +4853,13 @@ main(int argc, char **argv, char **envp) if (op.getBoolOption('U')) JS_SetCStringsAreUTF8(); +#ifdef XP_WIN + // Set the timer calibration delay count to 0 so we get high + // resolution right away, which we need for precise benchmarking. + extern int CALIBRATION_DELAY_COUNT; + CALIBRATION_DELAY_COUNT = 0; +#endif + /* Use the same parameters as the browser in xpcjsruntime.cpp. */ rt = JS_NewRuntime(32L * 1024L * 1024L); if (!rt)