// Lazily load a concatenated HRTF database for given subject and store it in a // local hash table to ensure quick efficient future retrievals. static PassRefPtr<AudioBus> getConcatenatedImpulseResponsesForSubject(const String& subjectName) { typedef HashMap<String, RefPtr<AudioBus>> AudioBusMap; DEFINE_THREAD_SAFE_STATIC_LOCAL(AudioBusMap, audioBusMap, new AudioBusMap()); DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex()); MutexLocker locker(mutex); RefPtr<AudioBus> bus; AudioBusMap::iterator iterator = audioBusMap.find(subjectName); if (iterator == audioBusMap.end()) { RefPtr<AudioBus> concatenatedImpulseResponses(AudioBus::loadPlatformResource(subjectName.utf8().data(), ResponseSampleRate)); ASSERT(concatenatedImpulseResponses); if (!concatenatedImpulseResponses) return nullptr; bus = concatenatedImpulseResponses; audioBusMap.set(subjectName, bus); } else bus = iterator->value; size_t responseLength = bus->length(); size_t expectedLength = static_cast<size_t>(TotalNumberOfResponses * ResponseFrameSize); // Check number of channels and length. For now these are fixed and known. bool isBusGood = responseLength == expectedLength && bus->numberOfChannels() == 2; ASSERT(isBusGood); if (!isBusGood) return nullptr; return bus; }
void NotificationImageLoader::didFinishLoading(unsigned long resourceIdentifier, double finishTime) { // If this has been stopped it is not desirable to trigger further work, // there is a shutdown of some sort in progress. if (m_stopped) return; DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, finishedTimeHistogram, new CustomCountHistogram("Notifications.Icon.LoadFinishTime", 1, 1000 * 60 * 60 /* 1 hour max */, 50 /* buckets */)); finishedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); if (m_data) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, fileSizeHistogram, new CustomCountHistogram("Notifications.Icon.FileSize", 1, 10000000 /* ~10mb max */, 50 /* buckets */)); fileSizeHistogram.count(m_data->size()); std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( m_data, true /* dataComplete */, ImageDecoder::AlphaPremultiplied, ImageDecoder::ColorSpaceApplied); if (decoder) { // The |ImageFrame*| is owned by the decoder. ImageFrame* imageFrame = decoder->frameBufferAtIndex(0); if (imageFrame) { (*m_imageCallback)(imageFrame->bitmap()); return; } } } runCallbackWithEmptyBitmap(); }
static ThreadSpecific<BlobURLOriginMap>& originMap() { // We want to create the BlobOriginCache exactly once because it is shared by all the threads. DEFINE_THREAD_SAFE_STATIC_LOCAL(BlobOriginCache, cache, new BlobOriginCache); (void)cache; // BlobOriginCache's constructor does the interesting work. DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<BlobURLOriginMap>, map, new ThreadSpecific<BlobURLOriginMap>); return map; }
String ImageEncoderUtils::toEncodingMimeType(const String& mimeType, const EncodeReason encodeReason) { String lowercaseMimeType = mimeType.lower(); if (mimeType.isNull()) lowercaseMimeType = DefaultMimeType; RequestedImageMimeType imageFormat; if (lowercaseMimeType == "image/png") { imageFormat = RequestedImageMimeTypePng; } else if (lowercaseMimeType == "image/jpeg") { imageFormat = RequestedImageMimeTypeJpeg; } else if (lowercaseMimeType == "image/webp") { imageFormat = RequestedImageMimeTypeWebp; } else if (lowercaseMimeType == "image/gif") { imageFormat = RequestedImageMimeTypeGif; } else if (lowercaseMimeType == "image/bmp" || lowercaseMimeType == "image/x-windows-bmp") { imageFormat = RequestedImageMimeTypeBmp; } else if (lowercaseMimeType == "image/x-icon") { imageFormat = RequestedImageMimeTypeIco; } else if (lowercaseMimeType == "image/tiff" || lowercaseMimeType == "image/x-tiff") { imageFormat = RequestedImageMimeTypeTiff; } else { imageFormat = RequestedImageMimeTypeUnknown; } if (encodeReason == EncodeReasonToDataURL) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, toDataURLImageFormatHistogram, new EnumerationHistogram("Canvas.RequestedImageMimeTypes_toDataURL", NumberOfRequestedImageMimeTypes)); toDataURLImageFormatHistogram.count(imageFormat); } else if (encodeReason == EncodeReasonToBlobCallback) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, toBlobCallbackImageFormatHistogram, new EnumerationHistogram( "Canvas.RequestedImageMimeTypes_toBlobCallback", NumberOfRequestedImageMimeTypes)); toBlobCallbackImageFormatHistogram.count(imageFormat); } else if (encodeReason == EncodeReasonConvertToBlobPromise) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, convertToBlobPromiseImageFormatHistogram, new EnumerationHistogram( "Canvas.RequestedImageMimeTypes_convertToBlobPromise", NumberOfRequestedImageMimeTypes)); convertToBlobPromiseImageFormatHistogram.count(imageFormat); } // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this // method to be used on a worker thread). if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType)) lowercaseMimeType = DefaultMimeType; return lowercaseMimeType; }
void ServiceWorkerGlobalScope::didEvaluateWorkerScript() { DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scriptCountHistogram, new CustomCountHistogram("ServiceWorker.ScriptCount", 1, 1000, 50)); scriptCountHistogram.count(m_scriptCount); DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scriptTotalSizeHistogram, new CustomCountHistogram("ServiceWorker.ScriptTotalSize", 1000, 5000000, 50)); scriptTotalSizeHistogram.count(m_scriptTotalSize); if (m_scriptCachedMetadataTotalSize) { DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, cachedMetadataHistogram, new CustomCountHistogram("ServiceWorker.ScriptCachedMetadataTotalSize", 1000, 50000000, 50)); cachedMetadataHistogram.count(m_scriptCachedMetadataTotalSize); } m_didEvaluateScript = true; }
static void adjustAmountOfExternalAllocatedMemory(int64_t diff) { #if ENABLE(ASSERT) DEFINE_THREAD_SAFE_STATIC_LOCAL(int64_t, processTotal, new int64_t(0)); DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex); { MutexLocker locker(mutex); processTotal += diff; DCHECK_GE(processTotal, 0) << "total amount = " << processTotal << ", diff = " << diff; } #endif v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(diff); }
void IDBDatabase::recordApiCallsHistogram(IndexedDatabaseMethods method) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, apiCallsHistogram, new EnumerationHistogram("WebCore.IndexedDB.FrontEndAPICalls", IDBMethodsMax)); apiCallsHistogram.count(method); }
ScriptPromise ServiceWorkerRegistrationNotifications::showNotification(ScriptState* scriptState, ServiceWorkerRegistration& serviceWorkerRegistration, const String& title, const NotificationOptions& options, ExceptionState& exceptionState) { ExecutionContext* executionContext = scriptState->executionContext(); // If context object's active worker is null, reject promise with a TypeError exception. if (!serviceWorkerRegistration.active()) return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "No active registration available on the ServiceWorkerRegistration.")); // If permission for notification's origin is not "granted", reject promise with a TypeError exception, and terminate these substeps. if (Notification::checkPermission(executionContext) != WebNotificationPermissionAllowed) return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "No notification permission has been granted for this origin.")); // Validate the developer-provided values to get a WebNotificationData object. WebNotificationData data = createWebNotificationData(executionContext, title, options, exceptionState); if (exceptionState.hadException()) return exceptionState.reject(scriptState); // Log number of actions developer provided in linear histogram: 0 -> underflow bucket, 1-16 -> distinct buckets, 17+ -> overflow bucket. DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, notificationCountHistogram, new EnumerationHistogram("Notifications.PersistentNotificationActionCount", 17)); notificationCountHistogram.count(options.actions().size()); ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); WebNotificationShowCallbacks* callbacks = new CallbackPromiseAdapter<void, void>(resolver); SecurityOrigin* origin = executionContext->securityOrigin(); WebNotificationManager* notificationManager = Platform::current()->notificationManager(); ASSERT(notificationManager); notificationManager->showPersistent(WebSecurityOrigin(origin), data, serviceWorkerRegistration.webRegistration(), callbacks); return promise; }
void NotificationImageLoader::didFail(const ResourceError& error) { DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, failedTimeHistogram, new CustomCountHistogram("Notifications.Icon.LoadFailTime", 1, 1000 * 60 * 60 /* 1 hour max */, 50 /* buckets */)); failedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); runCallbackWithEmptyBitmap(); }
void BitmapImageMetrics::countImageOrientation( const ImageOrientationEnum orientation) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, orientationHistogram, new EnumerationHistogram("Blink.DecodedImage.Orientation", ImageOrientationEnumEnd)); orientationHistogram.count(orientation); }
ScriptPromise ServiceWorkerRegistrationNotifications::showNotification( ScriptState* scriptState, ServiceWorkerRegistration& registration, const String& title, const NotificationOptions& options, ExceptionState& exceptionState) { ExecutionContext* executionContext = scriptState->getExecutionContext(); // If context object's active worker is null, reject the promise with a // TypeError exception. if (!registration.active()) return ScriptPromise::reject( scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "No active registration available on " "the ServiceWorkerRegistration.")); // If permission for notification's origin is not "granted", reject the // promise with a TypeError exception, and terminate these substeps. if (NotificationManager::from(executionContext) ->permissionStatus(executionContext) != mojom::blink::PermissionStatus::GRANTED) return ScriptPromise::reject( scriptState, V8ThrowException::createTypeError( scriptState->isolate(), "No notification permission has been granted for this origin.")); // Validate the developer-provided options to get the WebNotificationData. WebNotificationData data = createWebNotificationData(executionContext, title, options, exceptionState); if (exceptionState.hadException()) return exceptionState.reject(scriptState); // Log number of actions developer provided in linear histogram: // 0 -> underflow bucket, // 1-16 -> distinct buckets, // 17+ -> overflow bucket. DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, notificationCountHistogram, new EnumerationHistogram( "Notifications.PersistentNotificationActionCount", 17)); notificationCountHistogram.count(options.actions().size()); ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); std::unique_ptr<WebNotificationShowCallbacks> callbacks = WTF::wrapUnique(new CallbackPromiseAdapter<void, void>(resolver)); ServiceWorkerRegistrationNotifications::from(executionContext, registration) .prepareShow(data, std::move(callbacks)); return promise; }
bool V8GCController::hasPendingActivity(ExecutionContext* executionContext) { // V8GCController::hasPendingActivity is used only when a worker checks if // the worker contains any wrapper that has pending activities. ASSERT(!isMainThread()); DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scanPendingActivityHistogram, new CustomCountHistogram("Blink.ScanPendingActivityDuration", 1, 1000, 50)); double startTime = WTF::currentTimeMS(); PendingActivityVisitor visitor(executionContext); toIsolate(executionContext)->VisitHandlesWithClassIds(&visitor); scanPendingActivityHistogram.count(static_cast<int>(WTF::currentTimeMS() - startTime)); return visitor.pendingActivityFound(); }
bool BMPImageReader::processInfoHeader() { // Read info header. ASSERT(m_decodedOffset == m_headerOffset); if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_infoHeader.biSize) || !readInfoHeader()) return false; m_decodedOffset += m_infoHeader.biSize; DEFINE_THREAD_SAFE_STATIC_LOCAL( blink::CustomCountHistogram, dimensionsLocationHistogram, new blink::CustomCountHistogram( "Blink.DecodedImage.EffectiveDimensionsLocation.BMP", 0, 50000, 50)); dimensionsLocationHistogram.count(m_decodedOffset - 1); // Sanity-check header values. if (!isInfoHeaderValid()) return m_parent->setFailed(); // Set our size. if (!m_parent->setSize(m_infoHeader.biWidth, m_infoHeader.biHeight)) return false; // For paletted images, bitmaps can set biClrUsed to 0 to mean "all // colors", so set it to the maximum number of colors for this bit depth. // Also do this for bitmaps that put too large a value here. if (m_infoHeader.biBitCount < 16) { const uint32_t maxColors = static_cast<uint32_t>(1) << m_infoHeader.biBitCount; if (!m_infoHeader.biClrUsed || (m_infoHeader.biClrUsed > maxColors)) m_infoHeader.biClrUsed = maxColors; } // For any bitmaps that set their BitCount to the wrong value, reset the // counts now that we've calculated the number of necessary colors, since // other code relies on this value being correct. if (m_infoHeader.biCompression == RLE8) m_infoHeader.biBitCount = 8; else if (m_infoHeader.biCompression == RLE4) m_infoHeader.biBitCount = 4; // Tell caller what still needs to be processed. if (m_infoHeader.biBitCount >= 16) m_needToProcessBitmasks = true; else if (m_infoHeader.biBitCount) m_needToProcessColorTable = true; return true; }
void BitmapImageMetrics::countGamma(SkColorSpace* colorSpace) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, gammaNamedHistogram, new EnumerationHistogram("Blink.ColorSpace.Destination", GammaEnd)); if (colorSpace) { Gamma gamma; if (colorSpace->gammaCloseToSRGB()) { gamma = GammaSRGB; } else if (colorSpace->gammaIsLinear()) { gamma = GammaLinear; } else { gamma = GammaNonStandard; } gammaNamedHistogram.count(gamma); } else { gammaNamedHistogram.count(GammaNull); } }
bool ICOImageDecoder::processDirectoryEntries() { // Read directory entries. ASSERT(m_decodedOffset == sizeOfDirectory); if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < (m_dirEntriesCount * sizeOfDirEntry))) return false; // Enlarge member vectors to hold all the entries. m_dirEntries.resize(m_dirEntriesCount); m_bmpReaders.resize(m_dirEntriesCount); m_pngDecoders.resize(m_dirEntriesCount); for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) *i = readDirectoryEntry(); // Updates m_decodedOffset. // Make sure the specified image offsets are past the end of the directory // entries. for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) { if (i->m_imageOffset < m_decodedOffset) return setFailed(); } DEFINE_THREAD_SAFE_STATIC_LOCAL( blink::CustomCountHistogram, dimensionsLocationHistogram, new blink::CustomCountHistogram( "Blink.DecodedImage.EffectiveDimensionsLocation.ICO", 0, 50000, 50)); dimensionsLocationHistogram.count(m_decodedOffset - 1); // Arrange frames in decreasing quality order. std::sort(m_dirEntries.begin(), m_dirEntries.end(), compareEntries); // The image size is the size of the largest entry. const IconDirectoryEntry& dirEntry = m_dirEntries.first(); // Technically, this next call shouldn't be able to fail, since the width // and height here are each <= 256, and |m_frameSize| is empty. return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); }
void BitmapImageMetrics::countDecodedImageType(const String& type) { DecodedImageType decodedImageType = type == "jpg" ? ImageJPEG : type == "png" ? ImagePNG : type == "gif" ? ImageGIF : type == "webp" ? ImageWebP : type == "ico" ? ImageICO : type == "bmp" ? ImageBMP : DecodedImageType::ImageUnknown; DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, decodedImageTypeHistogram, new EnumerationHistogram("Blink.DecodedImageType", DecodedImageTypeEnumEnd)); decodedImageTypeHistogram.count(decodedImageType); }
void GCInfoTable::ensureGCInfoIndex(const GCInfo* gcInfo, size_t* gcInfoIndexSlot) { ASSERT(gcInfo); ASSERT(gcInfoIndexSlot); // Keep a global GCInfoTable lock while allocating a new slot. DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex); MutexLocker locker(mutex); // If more than one thread ends up allocating a slot for // the same GCInfo, have later threads reuse the slot // allocated by the first. if (*gcInfoIndexSlot) return; int index = ++s_gcInfoIndex; size_t gcInfoIndex = static_cast<size_t>(index); RELEASE_ASSERT(gcInfoIndex < GCInfoTable::maxIndex); if (gcInfoIndex >= s_gcInfoTableSize) resize(); s_gcInfoTable[gcInfoIndex] = gcInfo; releaseStore(reinterpret_cast<int*>(gcInfoIndexSlot), index); }
QuotaTracker& QuotaTracker::instance() { DEFINE_THREAD_SAFE_STATIC_LOCAL(QuotaTracker, tracker, new QuotaTracker); return tracker; }
RecursiveMutex& ThreadHeap::allHeapsMutex() { DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, (new RecursiveMutex)); return mutex; }
CrossThreadPersistentRegion& ProcessHeap::crossThreadPersistentRegion() { DEFINE_THREAD_SAFE_STATIC_LOCAL(CrossThreadPersistentRegion, persistentRegion, new CrossThreadPersistentRegion()); return persistentRegion; }
static Mutex& activeIteratorCountMutex() { DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, new Mutex()); return mutex; }
Mutex& MainThreadDebugger::creationMutex() { DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, (new Mutex)); return mutex; }
static HeapSizeCache& forCurrentThread() { DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<HeapSizeCache>, heapSizeCache, new ThreadSpecific<HeapSizeCache>); return *heapSizeCache; }
// FIXME: move all guid-related functions to a DatabaseVersionTracker class. static RecursiveMutex& guidMutex() { DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, new RecursiveMutex); return mutex; }
DatabaseTracker& DatabaseTracker::tracker() { DEFINE_THREAD_SAFE_STATIC_LOCAL(DatabaseTracker, tracker, new DatabaseTracker); return tracker; }
static void recordPackageFormatHistogram(FontPackageFormat format) { DEFINE_THREAD_SAFE_STATIC_LOCAL( EnumerationHistogram, packageFormatHistogram, new EnumerationHistogram("WebFont.PackageFormat", PackageFormatEnumMax)); packageFormatHistogram.count(format); }
ImageDecodingStore& ImageDecodingStore::instance() { DEFINE_THREAD_SAFE_STATIC_LOCAL(ImageDecodingStore, store, ImageDecodingStore::create().release()); return store; }