diff options
Diffstat (limited to 'Source/WebCore/page/PerformanceUserTiming.cpp')
-rw-r--r-- | Source/WebCore/page/PerformanceUserTiming.cpp | 194 |
1 files changed, 96 insertions, 98 deletions
diff --git a/Source/WebCore/page/PerformanceUserTiming.cpp b/Source/WebCore/page/PerformanceUserTiming.cpp index e2af43ed8..6c933d82b 100644 --- a/Source/WebCore/page/PerformanceUserTiming.cpp +++ b/Source/WebCore/page/PerformanceUserTiming.cpp @@ -26,69 +26,69 @@ #include "config.h" #include "PerformanceUserTiming.h" -#if ENABLE(USER_TIMING) +#if ENABLE(WEB_TIMING) +#include "Document.h" +#include "ExceptionCode.h" #include "Performance.h" -#include "PerformanceMark.h" -#include "PerformanceMeasure.h" +#include "PerformanceTiming.h" +#include <array> +#include <wtf/MainThread.h> +#include <wtf/NeverDestroyed.h> #include <wtf/dtoa/utils.h> -#include <wtf/text/WTFString.h> namespace WebCore { namespace { -typedef HashMap<String, NavigationTimingFunction> RestrictedKeyMap; -static RestrictedKeyMap restrictedKeyMap() +typedef unsigned long long (PerformanceTiming::*NavigationTimingFunction)() const; + +static NavigationTimingFunction restrictedMarkFunction(const String& markName) { - DEFINE_STATIC_LOCAL(RestrictedKeyMap, map, ()); - if (map.isEmpty()) { - map.add("navigationStart", &PerformanceTiming::navigationStart); - map.add("unloadEventStart", &PerformanceTiming::unloadEventStart); - map.add("unloadEventEnd", &PerformanceTiming::unloadEventEnd); - map.add("redirectStart", &PerformanceTiming::redirectStart); - map.add("redirectEnd", &PerformanceTiming::redirectEnd); - map.add("fetchStart", &PerformanceTiming::fetchStart); - map.add("domainLookupStart", &PerformanceTiming::domainLookupStart); - map.add("domainLookupEnd", &PerformanceTiming::domainLookupEnd); - map.add("connectStart", &PerformanceTiming::connectStart); - map.add("connectEnd", &PerformanceTiming::connectEnd); - map.add("secureConnectionStart", &PerformanceTiming::secureConnectionStart); - map.add("requestStart", &PerformanceTiming::requestStart); - map.add("responseStart", &PerformanceTiming::responseStart); - map.add("responseEnd", &PerformanceTiming::responseEnd); - map.add("domLoading", &PerformanceTiming::domLoading); - map.add("domInteractive", &PerformanceTiming::domInteractive); - map.add("domContentLoadedEventStart", &PerformanceTiming::domContentLoadedEventStart); - map.add("domContentLoadedEventEnd", &PerformanceTiming::domContentLoadedEventEnd); - map.add("domComplete", &PerformanceTiming::domComplete); - map.add("loadEventStart", &PerformanceTiming::loadEventStart); - map.add("loadEventEnd", &PerformanceTiming::loadEventEnd); + ASSERT(isMainThread()); + + using MapPair = std::pair<ASCIILiteral, NavigationTimingFunction>; + static const std::array<MapPair, 21> pairs = { { + MapPair { ASCIILiteral("navigationStart"), &PerformanceTiming::navigationStart }, + MapPair { ASCIILiteral("unloadEventStart"), &PerformanceTiming::unloadEventStart }, + MapPair { ASCIILiteral("unloadEventEnd"), &PerformanceTiming::unloadEventEnd }, + MapPair { ASCIILiteral("redirectStart"), &PerformanceTiming::redirectStart }, + MapPair { ASCIILiteral("redirectEnd"), &PerformanceTiming::redirectEnd }, + MapPair { ASCIILiteral("fetchStart"), &PerformanceTiming::fetchStart }, + MapPair { ASCIILiteral("domainLookupStart"), &PerformanceTiming::domainLookupStart }, + MapPair { ASCIILiteral("domainLookupEnd"), &PerformanceTiming::domainLookupEnd }, + MapPair { ASCIILiteral("connectStart"), &PerformanceTiming::connectStart }, + MapPair { ASCIILiteral("connectEnd"), &PerformanceTiming::connectEnd }, + MapPair { ASCIILiteral("secureConnectionStart"), &PerformanceTiming::secureConnectionStart }, + MapPair { ASCIILiteral("requestStart"), &PerformanceTiming::requestStart }, + MapPair { ASCIILiteral("responseStart"), &PerformanceTiming::responseStart }, + MapPair { ASCIILiteral("responseEnd"), &PerformanceTiming::responseEnd }, + MapPair { ASCIILiteral("domLoading"), &PerformanceTiming::domLoading }, + MapPair { ASCIILiteral("domInteractive"), &PerformanceTiming::domInteractive }, + MapPair { ASCIILiteral("domContentLoadedEventStart"), &PerformanceTiming::domContentLoadedEventStart }, + MapPair { ASCIILiteral("domContentLoadedEventEnd"), &PerformanceTiming::domContentLoadedEventEnd }, + MapPair { ASCIILiteral("domComplete"), &PerformanceTiming::domComplete }, + MapPair { ASCIILiteral("loadEventStart"), &PerformanceTiming::loadEventStart }, + MapPair { ASCIILiteral("loadEventEnd"), &PerformanceTiming::loadEventEnd }, + } }; + + static NeverDestroyed<HashMap<String, NavigationTimingFunction>> map; + if (map.get().isEmpty()) { + for (auto& pair : pairs) + map.get().add(pair.first, pair.second); } - return map; + + return map.get().get(markName); } } // namespace anonymous -UserTiming::UserTiming(Performance* performance) +UserTiming::UserTiming(Performance& performance) : m_performance(performance) { } -static void insertPerformanceEntry(PerformanceEntryMap& performanceEntryMap, PassRefPtr<PerformanceEntry> performanceEntry) -{ - RefPtr<PerformanceEntry> entry = performanceEntry; - PerformanceEntryMap::iterator it = performanceEntryMap.find(entry->name()); - if (it != performanceEntryMap.end()) - it->value.append(entry); - else { - Vector<RefPtr<PerformanceEntry> > v(1); - v[0] = entry; - performanceEntryMap.set(entry->name(), v); - } -} - -static void clearPeformanceEntries(PerformanceEntryMap& performanceEntryMap, const String& name) +static void clearPerformanceEntries(PerformanceEntryMap& performanceEntryMap, const String& name) { if (name.isNull()) { performanceEntryMap.clear(); @@ -98,113 +98,111 @@ static void clearPeformanceEntries(PerformanceEntryMap& performanceEntryMap, con performanceEntryMap.remove(name); } -void UserTiming::mark(const String& markName, ExceptionCode& ec) +ExceptionOr<Ref<PerformanceMark>> UserTiming::mark(const String& markName) { - ec = 0; - if (restrictedKeyMap().contains(markName)) { - ec = SYNTAX_ERR; - return; + if (is<Document>(m_performance.scriptExecutionContext())) { + if (restrictedMarkFunction(markName)) + return Exception { SYNTAX_ERR }; } - double startTime = m_performance->now(); - insertPerformanceEntry(m_marksMap, PerformanceMark::create(markName, startTime)); + auto& performanceEntryList = m_marksMap.ensure(markName, [] { return Vector<RefPtr<PerformanceEntry>>(); }).iterator->value; + auto entry = PerformanceMark::create(markName, m_performance.now()); + performanceEntryList.append(entry.copyRef()); + return WTFMove(entry); } void UserTiming::clearMarks(const String& markName) { - clearPeformanceEntries(m_marksMap, markName); + clearPerformanceEntries(m_marksMap, markName); } -double UserTiming::findExistingMarkStartTime(const String& markName, ExceptionCode& ec) +ExceptionOr<double> UserTiming::findExistingMarkStartTime(const String& markName) { - ec = 0; - if (m_marksMap.contains(markName)) return m_marksMap.get(markName).last()->startTime(); - if (restrictedKeyMap().contains(markName)) { - double value = static_cast<double>((m_performance->timing()->*(restrictedKeyMap().get(markName)))()); - if (!value) { - ec = INVALID_ACCESS_ERR; - return 0.0; - } - return value - m_performance->timing()->navigationStart(); + PerformanceTiming* timing = m_performance.timing(); + if (!timing) + return 0.0; + + if (auto function = restrictedMarkFunction(markName)) { + double value = static_cast<double>(((*timing).*(function))()); + if (!value) + return Exception { INVALID_ACCESS_ERR }; + return value - timing->navigationStart(); } - ec = SYNTAX_ERR; - return 0.0; + return Exception { SYNTAX_ERR }; } -void UserTiming::measure(const String& measureName, const String& startMark, const String& endMark, ExceptionCode& ec) +ExceptionOr<Ref<PerformanceMeasure>> UserTiming::measure(const String& measureName, const String& startMark, const String& endMark) { double startTime = 0.0; double endTime = 0.0; if (startMark.isNull()) - endTime = m_performance->now(); + endTime = m_performance.now(); else if (endMark.isNull()) { - endTime = m_performance->now(); - startTime = findExistingMarkStartTime(startMark, ec); - if (ec) - return; + endTime = m_performance.now(); + auto startMarkResult = findExistingMarkStartTime(startMark); + if (startMarkResult.hasException()) + return startMarkResult.releaseException(); + startTime = startMarkResult.releaseReturnValue(); } else { - endTime = findExistingMarkStartTime(endMark, ec); - if (ec) - return; - startTime = findExistingMarkStartTime(startMark, ec); - if (ec) - return; + auto endMarkResult = findExistingMarkStartTime(endMark); + if (endMarkResult.hasException()) + return endMarkResult.releaseException(); + auto startMarkResult = findExistingMarkStartTime(startMark); + if (startMarkResult.hasException()) + return startMarkResult.releaseException(); + startTime = startMarkResult.releaseReturnValue(); + endTime = endMarkResult.releaseReturnValue(); } - insertPerformanceEntry(m_measuresMap, PerformanceMeasure::create(measureName, startTime, endTime)); + auto& performanceEntryList = m_measuresMap.ensure(measureName, [] { return Vector<RefPtr<PerformanceEntry>>(); }).iterator->value; + auto entry = PerformanceMeasure::create(measureName, startTime, endTime); + performanceEntryList.append(entry.copyRef()); + return WTFMove(entry); } void UserTiming::clearMeasures(const String& measureName) { - clearPeformanceEntries(m_measuresMap, measureName); + clearPerformanceEntries(m_measuresMap, measureName); } -static Vector<RefPtr<PerformanceEntry> > convertToEntrySequence(const PerformanceEntryMap& performanceEntryMap) +static Vector<RefPtr<PerformanceEntry>> convertToEntrySequence(const PerformanceEntryMap& performanceEntryMap) { - Vector<RefPtr<PerformanceEntry> > entries; - - for (PerformanceEntryMap::const_iterator it = performanceEntryMap.begin(); it != performanceEntryMap.end(); ++it) - entries.appendVector(it->value); - + Vector<RefPtr<PerformanceEntry>> entries; + for (auto& entry : performanceEntryMap.values()) + entries.appendVector(entry); return entries; } -static Vector<RefPtr<PerformanceEntry> > getEntrySequenceByName(const PerformanceEntryMap& performanceEntryMap, const String& name) +static Vector<RefPtr<PerformanceEntry>> getEntrySequenceByName(const PerformanceEntryMap& performanceEntryMap, const String& name) { - Vector<RefPtr<PerformanceEntry> > entries; - - PerformanceEntryMap::const_iterator it = performanceEntryMap.find(name); - if (it != performanceEntryMap.end()) - entries.appendVector(it->value); - - return entries; + return performanceEntryMap.get(name); } -Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks() const +Vector<RefPtr<PerformanceEntry>> UserTiming::getMarks() const { return convertToEntrySequence(m_marksMap); } -Vector<RefPtr<PerformanceEntry> > UserTiming::getMarks(const String& name) const +Vector<RefPtr<PerformanceEntry>> UserTiming::getMarks(const String& name) const { return getEntrySequenceByName(m_marksMap, name); } -Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures() const +Vector<RefPtr<PerformanceEntry>> UserTiming::getMeasures() const { return convertToEntrySequence(m_measuresMap); } -Vector<RefPtr<PerformanceEntry> > UserTiming::getMeasures(const String& name) const +Vector<RefPtr<PerformanceEntry>> UserTiming::getMeasures(const String& name) const { return getEntrySequenceByName(m_measuresMap, name); } } // namespace WebCore -#endif // ENABLE(USER_TIMING) +#endif // ENABLE(WEB_TIMING) |