void js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al) { JSAtom **vector; JSAtomListElement *ale; uint32 count; /* Map length must already be initialized. */ JS_ASSERT(al->count == map->length); #ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_count); #endif ale = (JSAtomListElement *)al->list; if (!ale && !al->table) { JS_ASSERT(!map->vector); return; } count = al->count; vector = map->vector; if (al->table) { #ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count); #endif JS_HashTableEnumerateEntries(al->table, js_map_atom, vector); } else { do { vector[ALE_INDEX(ale)] = ALE_ATOM(ale); } while ((ale = ALE_NEXT(ale)) != NULL); } al->clear(); }
js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al) { JSAtom **vector; JSAtomListElement *ale; uint32 count; #ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_count); #endif ale = al->list; if (!ale && !al->table) { map->vector = NULL; map->length = 0; return JS_TRUE; } count = al->count; if (count >= ATOM_INDEX_LIMIT) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_LITERALS); return JS_FALSE; } vector = (JSAtom **) JS_malloc(cx, (size_t) count * sizeof *vector); if (!vector) return JS_FALSE; if (al->table) { #ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count); #endif JS_HashTableEnumerateEntries(al->table, js_map_atom, vector); } else { do { vector[ALE_INDEX(ale)] = ALE_ATOM(ale); } while ((ale = ALE_NEXT(ale)) != NULL); } ATOM_LIST_INIT(al); map->vector = vector; map->length = (jsatomid)count; return JS_TRUE; }
void ThreadData::triggerOperationCallback(JSRuntime *rt) { /* * Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures * the write will become immediately visible to other processors polling * the flag. Note that we only care about visibility here, not read/write * ordering: this field can only be written with the GC lock held. */ if (interruptFlags) return; JS_ATOMIC_SET(&interruptFlags, 1); #ifdef JS_THREADSAFE /* rt->interruptCounter does not reflect suspended threads. */ if (requestDepth != 0) JS_ATOMIC_INCREMENT(&rt->interruptCounter); #endif }
int64_t PRMJ_Now(void) { static int nCalls = 0; long double lowresTime, highresTimerValue; FILETIME ft; LARGE_INTEGER now; JSBool calibrated = JS_FALSE; JSBool needsCalibration = JS_FALSE; 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); #endif do { if (!calibration.calibrated || needsCalibration) { MUTEX_LOCK(&calibration.calibration_lock); MUTEX_LOCK(&calibration.data_lock); /* Recalibrate only if no one else did before us */ if(calibration.offset == cachedOffset) { /* Since calibration can take a while, make any other threads immediately wait */ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0); NowCalibrate(); calibrated = JS_TRUE; /* Restore spin count */ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT); } MUTEX_UNLOCK(&calibration.data_lock); MUTEX_UNLOCK(&calibration.calibration_lock); } /* Calculate a low resolution time */ LowResTime(&ft); lowresTime = 0.1*(long double)(FILETIME2INT64(ft) - win2un); if (calibration.freq > 0.0) { long double highresTime, diff; DWORD timeAdjustment, timeIncrement; BOOL timeAdjustmentDisabled; /* Default to 15.625 ms if the syscall fails */ long double skewThreshold = 15625.25; /* Grab high resolution time */ QueryPerformanceCounter(&now); highresTimerValue = (long double)now.QuadPart; MUTEX_LOCK(&calibration.data_lock); highresTime = calibration.offset + PRMJ_USEC_PER_SEC* (highresTimerValue-calibration.timer_offset)/calibration.freq; cachedOffset = calibration.offset; /* On some dual processor/core systems, we might get an earlier time so we cache the last time that we returned */ calibration.last = JS_MAX(calibration.last, int64_t(highresTime)); returnedTime = calibration.last; MUTEX_UNLOCK(&calibration.data_lock); /* Rather than assume the NT kernel ticks every 15.6ms, ask it */ if (GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled)) { if (timeAdjustmentDisabled) { /* timeAdjustment is in units of 100ns */ skewThreshold = timeAdjustment/10.0; } else { /* timeIncrement is in units of 100ns */ skewThreshold = timeIncrement/10.0; } } /* Check for clock skew */ diff = lowresTime - highresTime; /* For some reason that I have not determined, the skew can be up to twice a kernel tick. This does not seem to happen by itself, but I have only seen it triggered by another program doing some kind of file I/O. The symptoms are a negative diff followed by an equally large positive diff. */ if (fabs(diff) > 2*skewThreshold) { /*fprintf(stderr,"Clock skew detected (diff = %f)!\n", diff);*/ if (calibrated) { /* If we already calibrated once this instance, and the clock is still skewed, then either the processor(s) are wildly changing clockspeed or the system is so busy that we get switched out for long periods of time. In either case, it would be infeasible to make use of high resolution results for anything, so let's resort to old behavior for this call. It's possible that in the future, the user will want the high resolution timer, so we don't disable it entirely. */ returnedTime = int64_t(lowresTime); needsCalibration = JS_FALSE; } else { /* It is possible that when we recalibrate, we will return a value less than what we have returned before; this is unavoidable. We cannot tell the different between a faulty QueryPerformanceCounter implementation and user changes to the operating system time. Since we must respect user changes to the operating system time, we cannot maintain the invariant that Date.now() never decreases; the old implementation has this behavior as well. */ needsCalibration = JS_TRUE; } } else { /* No detectable clock skew */ returnedTime = int64_t(highresTime); needsCalibration = JS_FALSE; } } else { /* No high resolution timer is available, so fall back */ returnedTime = int64_t(lowresTime); } } while (needsCalibration); return returnedTime; }