1. 03 Sep, 2013 1 commit
    • darin@apple.com's avatar
      Cut down on double hashing and code needlessly using hash table iterators · 78bf2d4c
      darin@apple.com authored
      https://bugs.webkit.org/show_bug.cgi?id=120611
      
      Reviewed by Andreas Kling.
      
      Source/WebCore:
      
      Some of these changes are primarily code cleanup, but others could provide
      a small code size and speed improvement by avoiding extra hashing.
      
      * Modules/geolocation/Geolocation.cpp:
      (WebCore::Geolocation::Watchers::find): Use get instead of find.
      (WebCore::Geolocation::Watchers::remove): Use take instead of find.
      (WebCore::Geolocation::makeCachedPositionCallbacks): Use the return
      value from remove to avoid hashing twice.
      
      * Modules/webaudio/AudioContext.cpp:
      (WebCore::AudioContext::addAutomaticPullNode): Use the return value from
      add to avoid hashing twice.
      (WebCore::AudioContext::removeAutomaticPullNode): Use the return value
      from remove to avoid hashing twice.
      
      * Modules/webaudio/AudioNodeInput.cpp:
      (WebCore::AudioNodeInput::connect): Use the return value from add to avoid
      hashing twice.
      (WebCore::AudioNodeInput::disconnect): Use the return value from remove
      to avoid hashing twice.
      
      * Modules/webaudio/AudioParam.cpp:
      (WebCore::AudioParam::connect): Use the return value from add to avoid
      hashing twice.
      (WebCore::AudioParam::disconnect): Use the return value from remove to
      avoid hashing twice.
      
      * bridge/NP_jsobject.cpp:
      (ObjectMap::remove): Use remove instead of find/remove.
      
      * dom/Node.cpp:
      (WebCore::Node::~Node): Use the return value from remove instead of
      find/remove.
      
      * inspector/InspectorProfilerAgent.cpp:
      (WebCore::InspectorProfilerAgent::removeProfile): Remove needless
      calls to contains.
      
      * loader/DocumentLoader.cpp:
      (WebCore::DocumentLoader::removeSubresourceLoader): Use the return
      value from remove instead of find/remove.
      
      * loader/ResourceLoadScheduler.cpp:
      (WebCore::ResourceLoadScheduler::HostInformation::remove): Use the
      return value from remove to avoid hashing twice.
      
      * loader/appcache/ApplicationCacheGroup.cpp:
      (WebCore::ApplicationCacheGroup::disassociateDocumentLoader): Use
      remove instead of find/remove.
      (WebCore::ApplicationCacheGroup::cacheDestroyed): Removed a needless
      call to contains to avoid hashing twice. It's fine to do the check
      for an empty hash table unconditionally.
      
      * page/DOMWindow.cpp:
      (WebCore::addUnloadEventListener): Eliminated a local variable for clarity.
      (WebCore::removeUnloadEventListener): Ditto. Also use remove instead
      of find/remove.
      (WebCore::removeAllUnloadEventListeners): Ditto. Also use removeAll instead
      of find/removeAll.
      (WebCore::addBeforeUnloadEventListener): Ditto.
      (WebCore::removeBeforeUnloadEventListener): Ditto.
      (WebCore::removeAllBeforeUnloadEventListeners): Ditto.
      
      * page/FrameView.cpp:
      (WebCore::FrameView::removeViewportConstrainedObject): Use the return
      value from remove to avoid hashing twice.
      (WebCore::FrameView::removeScrollableArea): Use the return value from
      remove instead of find/remove.
      (WebCore::FrameView::containsScrollableArea): Use && instead of an if
      statement in a way that is idiomatic for this kind of function.
      
      * page/Page.cpp:
      (WebCore::Page::addRelevantRepaintedObject): Use the return value from
      remove instead of find/remove.
      
      * page/PageGroup.cpp:
      (WebCore::PageGroup::removeUserScriptsFromWorld): Use remove instead
      of find/remove.
      (WebCore::PageGroup::removeUserStyleSheetsFromWorld): Use the return
      value from remove instead of find/remove.
      
      * page/PerformanceUserTiming.cpp:
      (WebCore::clearPeformanceEntries): Removed a needless call to contains.
      
      * platform/graphics/DisplayRefreshMonitor.cpp:
      (WebCore::DisplayRefreshMonitor::removeClient): Use the return value
      from remove instead of find/remove.
      (WebCore::DisplayRefreshMonitorManager::displayDidRefresh): Use remove
      instead of find/remove.
      
      * platform/graphics/blackberry/LayerRenderer.cpp:
      (WebCore::LayerRenderer::removeLayer): Use the return value from remove
      instead of find/remove.
      
      * platform/win/WindowMessageBroadcaster.cpp:
      (WebCore::WindowMessageBroadcaster::removeListener): Use remove instead
      of find/remove. It's fine to do the check for an empty hash table unconditionally.
      
      * plugins/PluginDatabase.cpp:
      (WebCore::PluginDatabase::removeDisabledPluginFile): Use the return value
      from remove instead of find/remove.
      
      * rendering/style/StyleCustomFilterProgramCache.cpp:
      (WebCore::StyleCustomFilterProgramCache::lookup): Use get instead of find.
      (WebCore::StyleCustomFilterProgramCache::add): Use contains instead of find
      in an assertion.
      (WebCore::StyleCustomFilterProgramCache::remove): Use remove instead of
      find/remove.
      
      * svg/SVGCursorElement.cpp:
      (WebCore::SVGCursorElement::removeClient): Use the return value from remove
      instead of find/remove.
      
      * svg/SVGDocumentExtensions.cpp:
      (WebCore::SVGDocumentExtensions::removeResource): Removed an unneeded call
      to contains.
      (WebCore::SVGDocumentExtensions::removeAllTargetReferencesForElement): Use
      remove instead of find/remove. It's fine to do the check for an empty hash
      table unconditionally.
      (WebCore::SVGDocumentExtensions::removeAllElementReferencesForTarget): Use
      remove instead of find/remove. Also removed unhelpful assertions. One is
      already done by HashMap, and the other is just checking a basic invariant
      of every HashMap that doesn't need to be checked.
      
      * svg/graphics/SVGImageCache.cpp:
      (WebCore::SVGImageCache::removeClientFromCache): Removed an unneeded call
      to contains.
      
      * svg/properties/SVGAnimatedProperty.cpp:
      (WebCore::SVGAnimatedProperty::~SVGAnimatedProperty): Use the version of
      remove that takes an iterator rather than the one that takes a key, so
      we don't need to redo the hashing.
      
      Source/WebKit2:
      
      * Platform/CoreIPC/Connection.cpp:
      (CoreIPC::Connection::waitForMessage): Use take instead of find/remove.
      
      * UIProcess/WebPreferences.cpp:
      (WebKit::WebPreferences::removePageGroup): Use the return value from remove
      instead of find/remove.
      
      * WebProcess/Geolocation/GeolocationPermissionRequestManager.cpp:
      (WebKit::GeolocationPermissionRequestManager::cancelRequestForGeolocation):
      (WebKit::GeolocationPermissionRequestManager::didReceiveGeolocationPermissionDecision):
      Use take instead of find/remove.
      
      * WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
      (WebKit::NetscapePlugin::frameDidFinishLoading): Use take instead of find/remove.
      (WebKit::NetscapePlugin::frameDidFail): Use take instead of find/remove.
      
      * WebProcess/WebPage/WebBackForwardListProxy.cpp:
      (WebKit::WebBackForwardListProxy::removeItem): Use take instead of find/remove.
      
      * WebProcess/WebPage/WebPage.cpp:
      (WebKit::WebPage::didFinishCheckingText): Use take instead of get/remove so we
      hash only once.
      (WebKit::WebPage::didCancelCheckingText): Ditto.
      (WebKit::WebPage::stopExtendingIncrementalRenderingSuppression): Use the return
      value from remove instead of contains/remove so we hash only once.
      
      Source/WTF:
      
      Double hashing is common in code that needs to combine a remove with some
      action to only be done if the code is removed. The only way to avoid it is
      to write code using find and a hash table iterator. To help with this, add
      a boolean return value to remove functions to indicate if anything was removed.
      
      Double hashing also happens in code that does a get followed by a remove.
      The take function is helpful in this case. To help with this, add a takeFirst
      funciton to ListHashSet.
      
      * wtf/HashCountedSet.h:
      (WTF::HashCountedSet::removeAll): Added a boolean return value, analogous to the one
      that the HashCountedSet::remove function already has.
      
      * wtf/HashMap.h:
      (WTF::HashMap::remove): Added a boolean return value, true if something was removed.
      * wtf/HashSet.h:
      (WTF::HashSet::remove): Ditto.
      * wtf/RefPtrHashMap.h:
      (WTF::RefPtrHashMap::remove): Ditto.
      
      * wtf/ListHashSet.h:
      (WTF::ListHashSet::takeFirst): Added.
      (WTF::ListHashSet::takeLast): Added.
      (WTF::ListHashSet::remove): Added a boolean return value, true if something was removed.
      
      * wtf/WTFThreadData.h:
      (JSC::IdentifierTable::remove): Use the new remove return value to get rid of most of
      the code in this function.
      
      git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154967 268f45cc-cd09-0410-ab3c-d52691b4dbfc
      78bf2d4c
  2. 05 May, 2013 1 commit
    • andersca@apple.com's avatar
      Remove the Vector::append overload that takes a Vector · 9201299b
      andersca@apple.com authored
      https://bugs.webkit.org/show_bug.cgi?id=115535
      
      Reviewed by Andreas Kling.
      
      Source/WebCore:
      
      Use Vector::appendVector instead.
      
      * Modules/indexeddb/IDBBackingStore.cpp:
      (WebCore::IDBBackingStore::putRecord):
      (WebCore::IDBBackingStore::putIndexDataForRecord):
      * Modules/indexeddb/IDBLevelDBCoding.cpp:
      (WebCore::IDBLevelDBCoding::encodeStringWithLength):
      (WebCore::IDBLevelDBCoding::encodeIDBKey):
      (WebCore::IDBLevelDBCoding::encodeIDBKeyPath):
      (WebCore::IDBLevelDBCoding::SchemaVersionKey::encode):
      (WebCore::IDBLevelDBCoding::MaxDatabaseIdKey::encode):
      (WebCore::IDBLevelDBCoding::DataVersionKey::encode):
      (WebCore::IDBLevelDBCoding::DatabaseFreeListKey::encode):
      (WebCore::IDBLevelDBCoding::DatabaseNameKey::encode):
      (WebCore::IDBLevelDBCoding::DatabaseMetaDataKey::encode):
      (WebCore::IDBLevelDBCoding::ObjectStoreMetaDataKey::encode):
      (WebCore::IDBLevelDBCoding::IndexMetaDataKey::encode):
      (WebCore::IDBLevelDBCoding::ObjectStoreFreeListKey::encode):
      (WebCore::IDBLevelDBCoding::IndexFreeListKey::encode):
      (WebCore::IDBLevelDBCoding::ObjectStoreNamesKey::encode):
      (WebCore::IDBLevelDBCoding::IndexNamesKey::encode):
      (WebCore::IDBLevelDBCoding::ObjectStoreDataKey::encode):
      (WebCore::IDBLevelDBCoding::ExistsEntryKey::encode):
      (WebCore::IDBLevelDBCoding::IndexDataKey::encode):
      * Modules/webaudio/AudioContext.cpp:
      (WebCore::AudioContext::clear):
      (WebCore::AudioContext::scheduleNodeDeletion):
      * accessibility/AccessibilityARIAGrid.cpp:
      (WebCore::AccessibilityARIAGrid::addTableCellChild):
      * accessibility/AccessibilityTable.cpp:
      (WebCore::AccessibilityTable::cells):
      * css/RuleFeature.cpp:
      (WebCore::RuleFeatureSet::add):
      * css/StyleResolver.cpp:
      (WebCore::StyleResolver::addToMatchedPropertiesCache):
      * dom/DocumentStyleSheetCollection.cpp:
      (WebCore::collectActiveCSSStyleSheetsFromSeamlessParents):
      (WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets):
      * dom/Range.cpp:
      (WebCore::Range::getBorderAndTextQuads):
      * html/FormController.cpp:
      (WebCore::FormController::getReferencedFilePaths):
      * html/canvas/CanvasRenderingContext2D.cpp:
      (WebCore::CanvasRenderingContext2D::setLineDash):
      * html/parser/HTMLFormattingElementList.cpp:
      (WebCore::HTMLFormattingElementList::tryToEnsureNoahsArkConditionQuickly):
      * html/track/WebVTTToken.h:
      (WebCore::WebVTTToken::addNewClass):
      (WebCore::WebVTTToken::addNewAnnotation):
      * page/CaptionUserPreferencesMac.mm:
      (WebCore::CaptionUserPreferencesMac::preferredLanguages):
      * platform/FileChooser.cpp:
      (WebCore::FileChooserSettings::acceptTypes):
      * platform/SharedBufferChunkReader.cpp:
      (WebCore::SharedBufferChunkReader::nextChunk):
      * platform/graphics/MediaPlayer.cpp:
      (WebCore::MediaPlayer::getSitesInMediaCache):
      * platform/graphics/ca/GraphicsLayerCA.cpp:
      (WebCore::GraphicsLayerCA::updateSublayerList):
      * platform/mac/PasteboardMac.mm:
      (WebCore::createWritableTypesForImage):
      (WebCore::writableTypesForImage):
      (WebCore::Pasteboard::writeSelectionForTypes):
      * platform/network/FormDataBuilder.cpp:
      (WebCore::FormDataBuilder::generateUniqueBoundaryString):
      * plugins/PluginDatabase.cpp:
      (WebCore::PluginDatabase::defaultPluginDirectories):
      * rendering/RenderBlockLineLayout.cpp:
      (WebCore::constructBidiRunsForSegment):
      * rendering/RenderLayerCompositor.cpp:
      (WebCore::RenderLayerCompositor::OverlapMap::popCompositingContainer):
      * rendering/RenderTableSection.cpp:
      (WebCore::RenderTableSection::splitColumn):
      * svg/SVGGlyphMap.h:
      (WebCore::SVGGlyphMap::collectGlyphsForString):
      * xml/XPathNodeSet.h:
      (WebCore::XPath::NodeSet::append):
      
      Source/WebKit2:
      
      Use Vector::appendVector instead.
      
      * NetworkProcess/FileAPI/NetworkBlobRegistry.cpp:
      (WebKit::NetworkBlobRegistry::registerBlobURL):
      * NetworkProcess/SchedulableLoader.cpp:
      (WebKit::SchedulableLoader::SchedulableLoader):
      * Platform/CoreIPC/Connection.cpp:
      (CoreIPC::Connection::SyncMessageState::dispatchMessages):
      * UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp:
      (WebKit::PluginInfoStore::pluginsDirectories):
      
      Source/WTF:
      
      The Vector::append overload that takes a Vector conflicts with rvalues in C++11, so remove it and
      replace calls to it with calls to appendVector.
      
      * wtf/Vector.h:
      (Vector):
      
      Tools:
      
      Use Vector::appendVector instead.
      
      * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
      (concatenateAttributeAndValue):
      * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
      (WTR::concatenateAttributeAndValue):
      
      git-svn-id: http://svn.webkit.org/repository/webkit/trunk@149579 268f45cc-cd09-0410-ab3c-d52691b4dbfc
      9201299b
  3. 15 Jan, 2013 1 commit
  4. 04 Dec, 2012 2 commits
  5. 22 Oct, 2012 2 commits
    • commit-queue@webkit.org's avatar
      [User Timing]Integrate with Perforamnce Timeline. · 7e09c33a
      commit-queue@webkit.org authored
      https://bugs.webkit.org/show_bug.cgi?id=91072.
      
      Patch by Pan Deng <pan.deng@intel.com> on 2012-10-22
      Reviewed by Tony Gentilcore.
      
      This patch expose user timing entries via performance timeline interface. JavaScriptCore custom binding will be another patch
      
      No new tests, user timing test cases have been landed.
      
      * page/Performance.cpp:
      (WebCore::Performance::Performance):
      (WebCore::Performance::webkitGetEntries):
      (WebCore::Performance::webkitGetEntriesByType):
      (WebCore::Performance::webkitGetEntriesByName):
      * page/PerformanceEntry.h:
      (WebCore::PerformanceEntry::startTimeCompareLessThan):
      (PerformanceEntry):
      * page/PerformanceEntryList.cpp:
      (WebCore::PerformanceEntryList::sort):
      (WebCore):
      * page/PerformanceEntryList.h:
      (PerformanceEntryList):
      * page/PerformanceUserTiming.cpp:
      (WebCore::convertToEntrySequence):
      (WebCore):
      (WebCore::getEntrySequenceByName):
      (WebCore::UserTiming::getMarks):
      (WebCore::UserTiming::getMeasures):
      * page/PerformanceUserTiming.h:
      (UserTiming):
      
      git-svn-id: http://svn.webkit.org/repository/webkit/trunk@132147 268f45cc-cd09-0410-ab3c-d52691b4dbfc
      7e09c33a
    • commit-queue@webkit.org's avatar
      Modify obsolete code in User Timing · 83c500d0
      commit-queue@webkit.org authored
      https://bugs.webkit.org/show_bug.cgi?id=99851
      
      Patch by Pan Deng <pan.deng@intel.com> on 2012-10-22
      Reviewed by Tony Gentilcore.
      
      Modify user timing implementation as PlatformString.h, prefix of webkitNow is removed, etc.
      
      No new tests.
      
      * page/PerformanceUserTiming.cpp:
      (WebCore::insertPerformanceEntry):
      (WebCore::UserTiming::mark):
      (WebCore::UserTiming::measure):
      * page/PerformanceUserTiming.h:
      
      git-svn-id: http://svn.webkit.org/repository/webkit/trunk@132146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
      83c500d0
  6. 18 Oct, 2012 1 commit
    • commit-queue@webkit.org's avatar
      Source/WebCore: [User Timing] implement main interface in of User Timing,... · e1e35a27
      commit-queue@webkit.org authored
      Source/WebCore: [User Timing] implement main interface in of User Timing, according to http://www.w3.org/TR/2012/CR-user-timing-20120726/
      https://bugs.webkit.org/show_bug.cgi?id=90963
      
      Patch by Pan Deng <pan.deng@intel.com> on 2012-10-17
      Reviewed by Tony Gentilcore.
      
      This patch implemented mark(), measure(), clearMarks() and clearMeasures() interface of User Timing. Getters are not exposed by Performance Timeline yet, it will be future patch.
      
      Tests: http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMarks.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMeasures.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark_exception.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_associate_with_navigation_timing.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_exception.html
             http/tests/w3c/webperf/submission/user-timing/test_user_timing_method_exist.html
      
      * GNUmakefile.list.am:
      * WebCore.gypi:
      * page/Performance.cpp:
      (WebCore::Performance::webkitGetEntries):
      (WebCore::Performance::webkitGetEntriesByType):
      (WebCore::Performance::webkitGetEntriesByName):
      (WebCore):
      (WebCore::Performance::webkitMark):
      (WebCore::Performance::webkitClearMarks):
      (WebCore::Performance::webkitMeasure):
      (WebCore::Performance::webkitClearMeasures):
      * page/Performance.h:
      (WebCore):
      (Performance):
      * page/Performance.idl:
      * page/PerformanceMark.h: Added.
      (WebCore):
      (PerformanceMark):
      (WebCore::PerformanceMark::create):
      (WebCore::PerformanceMark::PerformanceMark):
      (WebCore::PerformanceMark::~PerformanceMark):
      * page/PerformanceMark.idl: Added.
      * page/PerformanceMeasure.h: Added.
      (WebCore):
      (PerformanceMeasure):
      (WebCore::PerformanceMeasure::create):
      (WebCore::PerformanceMeasure::PerformanceMeasure):
      (WebCore::PerformanceMeasure::~PerformanceMeasure):
      * page/PerformanceMeasure.idl: Added.
      * page/PerformanceUserTiming.cpp: Added.
      (WebCore):
      (WebCore::UserTiming::UserTiming):
      (WebCore::insertPerformanceEntry):
      (WebCore::clearPeformanceEntries):
      (WebCore::UserTiming::mark):
      (WebCore::UserTiming::clearMarks):
      (WebCore::UserTiming::findExistingMarkStartTime):
      (WebCore::UserTiming::measure):
      (WebCore::UserTiming::clearMeasures):
      * page/PerformanceUserTiming.h: Added.
      (WebCore):
      (UserTiming):
      (WebCore::UserTiming::create):
      
      LayoutTests: [User Timing] Test Cases of User Timing. According to http://www.w3.org/TR/2012/CR-user-timing-20120726/
      https://bugs.webkit.org/show_bug.cgi?id=90963
      
      Patch by Pan Deng <pan.deng@intel.com> on 2012-10-17
      Reviewed by Tony Gentilcore.
      
      Test cases in this patch validate functionality of W3C User Timing interface. These test cases use W3C testharness. Since User Timing feature is not enabled in any platform yet, all skipped currenttly.
      
      * http/tests/w3c/webperf/resources/webperftestharnessextension.js: Added.
      (test_method_exists):
      (test_noless_than):
      (performance_entrylist_checker.entry_check.test_equals):
      (performance_entrylist_checker.entry_check):
      (performance_entrylist_checker.entrylist_order_check):
      (performance_entrylist_checker.entrylist_check):
      (PerformanceContext):
      (PerformanceContext.prototype.initialMeasures):
      (PerformanceContext.prototype.mark):
      (PerformanceContext.prototype.measure):
      (PerformanceContext.prototype.clearMarks):
      (PerformanceContext.prototype.clearMeasures):
      (PerformanceContext.prototype.getEntries):
      (PerformanceContext.prototype.getEntriesByType):
      (PerformanceContext.prototype.getEntriesByName):
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMarks-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMarks.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMeasures-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_clearMeasures.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark_exception-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_mark_exception.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_associate_with_navigation_timing-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_associate_with_navigation_timing.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_exception-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_measure_exception.html: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_method_exist-expected.txt: Added.
      * http/tests/w3c/webperf/submission/user-timing/test_user_timing_method_exist.html: Added.
      * platform/chromium/TestExpectations:
      * platform/efl/TestExpectations:
      * platform/gtk/TestExpectations:
      * platform/mac/TestExpectations:
      * platform/qt-5.0-wk2/TestExpectations:
      * platform/qt/TestExpectations:
      * platform/win/TestExpectations:
      
      git-svn-id: http://svn.webkit.org/repository/webkit/trunk@131693 268f45cc-cd09-0410-ab3c-d52691b4dbfc
      e1e35a27