WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-80444-20120627211122.patch (text/plain), 20.36 KB, created by
Adam Barth
on 2012-06-27 21:11:24 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Adam Barth
Created:
2012-06-27 21:11:24 PDT
Size:
20.36 KB
patch
obsolete
>Subversion Revision: 121359 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index f492f3a193423c380c71be0aefa0721aad6f4e87..ac2131dbe345589753ea9f6d2604120492c1b91e 100755 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,57 @@ >+2012-06-27 Adam Barth <abarth@webkit.org> >+ >+ Add a Setting to expose quantized, rate-limited MemoryInfo values >+ https://bugs.webkit.org/show_bug.cgi?id=80444 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We do not currently expose real MemoryInfo objects to the web unless >+ the user opts in because we're worried that this memory information >+ could be used in side-channel attacks. >+ >+ We've gotten feedback from a number of web app developers that this >+ information is very useful in tracking the performance of their >+ applications. These developers use the setting in their testing labs >+ and regression harnesses to catch memory leaks and regressiosn early in >+ their development cycle. >+ >+ Some of these developers have experimented with enabling this feature >+ within their enterprise and have found the memory data from the field >+ extremely useful in tracking down memory issues that slip through their >+ testing. >+ >+ Based on this experience, they've asked whether we can enable this >+ functionality on a wider scale so they catch even more problems >+ including problems that don't manifest within their enterprise. >+ Because we're still worried about side-channel attacks, we don't want >+ to expose the raw data, so we've talked with these folks in more detail >+ to understand what information they find most valuable. >+ >+ This patch is the result of those discussions. In particular, this >+ patch adds an option to expose quantized and rate-limited memory >+ information to web pages. Web pages can only learn new data every 20 >+ minutes, which helps mitigate attacks where the attacker compares two >+ or readings to extract side-channel information. The patch also only >+ reports 100 distinct memory values, which (combined with the rate >+ limts) makes it difficult for attackers to learn about small changes in >+ memory use. >+ >+ * page/MemoryInfo.cpp: >+ (WebCore): >+ (HeapSizeCache): >+ (WebCore::HeapSizeCache::HeapSizeCache): >+ (WebCore::HeapSizeCache::getCachedHeapSize): >+ (WebCore::HeapSizeCache::maybeUpdate): >+ (WebCore::HeapSizeCache::update): >+ (WebCore::HeapSizeCache::quantize): >+ (WebCore::MemoryInfo::MemoryInfo): >+ * page/Settings.cpp: >+ (WebCore::Settings::Settings): >+ * page/Settings.h: >+ (WebCore::Settings::setQuantizedMemoryInfoEnabled): >+ (WebCore::Settings::quantizedMemoryInfoEnabled): >+ (Settings): >+ > 2012-06-27 Anthony Scian <ascian@rim.com> > > Web Inspector [JSC]: Implement ScriptCallStack::stackTrace >diff --git a/Source/WebCore/bindings/js/ScriptGCEvent.cpp b/Source/WebCore/bindings/js/ScriptGCEvent.cpp >index 9fe0c2e0896a831b1f7c2cec1fa2a980fcba8b25..65c626a4dd90877e5a7eff2ae25e5e5482703998 100644 >--- a/Source/WebCore/bindings/js/ScriptGCEvent.cpp >+++ b/Source/WebCore/bindings/js/ScriptGCEvent.cpp >@@ -43,12 +43,12 @@ namespace WebCore { > > using namespace JSC; > >-void ScriptGCEvent::getHeapSize(size_t& usedHeapSize, size_t& totalHeapSize, size_t& heapSizeLimit) >+void ScriptGCEvent::getHeapSize(HeapInfo& info) > { > JSGlobalData* globalData = JSDOMWindow::commonJSGlobalData(); >- totalHeapSize = globalData->heap.capacity(); >- usedHeapSize = globalData->heap.size(); >- heapSizeLimit = 0; >+ info.totalJSHeapSize = globalData->heap.capacity(); >+ info.usedJSHeapSize = globalData->heap.size(); >+ info.jsHeapSizeLimit = 0; > } > > } // namespace WebCore >diff --git a/Source/WebCore/bindings/js/ScriptGCEvent.h b/Source/WebCore/bindings/js/ScriptGCEvent.h >index 6614b8e002a4d1d62e51bed558f6b117b680b77c..1bd9071bddfcafeca50df6d02060588ae5f30ebd 100644 >--- a/Source/WebCore/bindings/js/ScriptGCEvent.h >+++ b/Source/WebCore/bindings/js/ScriptGCEvent.h >@@ -37,12 +37,25 @@ namespace WebCore { > > class ScriptGCEventListener; > >+struct HeapInfo { >+ HeapInfo() >+ : usedJSHeapSize(0) >+ , totalJSHeapSize(0) >+ , jsHeapSizeLimit(0) >+ { >+ } >+ >+ size_t usedJSHeapSize; >+ size_t totalJSHeapSize; >+ size_t jsHeapSizeLimit; >+}; >+ > class ScriptGCEvent > { > public: > static void addEventListener(ScriptGCEventListener*) { } > static void removeEventListener(ScriptGCEventListener*) { } >- static void getHeapSize(size_t& usedHeapSize, size_t& totalHeapSize, size_t& heapSizeLimit); >+ static void getHeapSize(HeapInfo&); > }; > > } // namespace WebCore >diff --git a/Source/WebCore/bindings/v8/ScriptGCEvent.cpp b/Source/WebCore/bindings/v8/ScriptGCEvent.cpp >index 622f22bcdae7716e33bab5a68fc671815e5389ef..37dd85e5534f66233e0735e228a09dc892dc8851 100644 >--- a/Source/WebCore/bindings/v8/ScriptGCEvent.cpp >+++ b/Source/WebCore/bindings/v8/ScriptGCEvent.cpp >@@ -71,13 +71,13 @@ void ScriptGCEvent::removeEventListener(ScriptGCEventListener* eventListener) > } > } > >-void ScriptGCEvent::getHeapSize(size_t& usedHeapSize, size_t& totalHeapSize, size_t& heapSizeLimit) >+void ScriptGCEvent::getHeapSize(HeapInfo& info) > { > v8::HeapStatistics heapStatistics; > v8::V8::GetHeapStatistics(&heapStatistics); >- usedHeapSize = heapStatistics.used_heap_size(); >- totalHeapSize = heapStatistics.total_heap_size(); >- heapSizeLimit = heapStatistics.heap_size_limit(); >+ info.usedJSHeapSize = heapStatistics.used_heap_size(); >+ info.totalJSHeapSize = heapStatistics.total_heap_size(); >+ info.jsHeapSizeLimit = heapStatistics.heap_size_limit(); > } > > size_t ScriptGCEvent::getUsedHeapSize() >diff --git a/Source/WebCore/bindings/v8/ScriptGCEvent.h b/Source/WebCore/bindings/v8/ScriptGCEvent.h >index f2ba49525f6e898cc3d655f1339c15df3d4a436a..d6d5e57a5323cd6c8e2607432201f0a00325c53d 100644 >--- a/Source/WebCore/bindings/v8/ScriptGCEvent.h >+++ b/Source/WebCore/bindings/v8/ScriptGCEvent.h >@@ -40,12 +40,26 @@ namespace WebCore { > > class ScriptGCEventListener; > >+struct HeapInfo { >+ HeapInfo() >+ : usedJSHeapSize(0) >+ , totalJSHeapSize(0) >+ , jsHeapSizeLimit(0) >+ { >+ } >+ >+ size_t usedJSHeapSize; >+ size_t totalJSHeapSize; >+ size_t jsHeapSizeLimit; >+}; >+ > class ScriptGCEvent > { > public: > static void addEventListener(ScriptGCEventListener*); > static void removeEventListener(ScriptGCEventListener*); >- static void getHeapSize(size_t&, size_t&, size_t&); >+ static void getHeapSize(HeapInfo&); >+ > private: > static void gcEpilogueCallback(v8::GCType type, v8::GCCallbackFlags flags); > static void gcPrologueCallback(v8::GCType type, v8::GCCallbackFlags flags); >diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp >index b05f622d00acf562e4f94802ae72f5419efc6426..130bda6b75dbd5ab7e10d83ffde7f6c01d66e2a5 100644 >--- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp >+++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp >@@ -366,17 +366,15 @@ void InspectorMemoryAgent::getDOMNodeCount(ErrorString*, RefPtr<TypeBuilder::Arr > > static PassRefPtr<InspectorMemoryBlock> jsHeapInfo() > { >- size_t usedJSHeapSize; >- size_t totalJSHeapSize; >- size_t jsHeapSizeLimit; >- ScriptGCEvent::getHeapSize(usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit); >+ HeapInfo info; >+ ScriptGCEvent::getHeapSize(info); > > RefPtr<InspectorMemoryBlock> jsHeapAllocated = InspectorMemoryBlock::create().setName(MemoryBlockName::jsHeapAllocated); >- jsHeapAllocated->setSize(totalJSHeapSize); >+ jsHeapAllocated->setSize(static_cast<int>(info.totalJSHeapSize)); > > RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create(); > RefPtr<InspectorMemoryBlock> jsHeapUsed = InspectorMemoryBlock::create().setName(MemoryBlockName::jsHeapUsed); >- jsHeapUsed->setSize(usedJSHeapSize); >+ jsHeapUsed->setSize(static_cast<int>(info.usedJSHeapSize)); > children->addItem(jsHeapUsed); > > jsHeapAllocated->setChildren(children); >diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.cpp b/Source/WebCore/inspector/InspectorTimelineAgent.cpp >index 47282e9573716f3329b40fd5a3671b16c8187304..f72c3132b8b55fb4712e22f6ac5d3e205e0e10d2 100644 >--- a/Source/WebCore/inspector/InspectorTimelineAgent.cpp >+++ b/Source/WebCore/inspector/InspectorTimelineAgent.cpp >@@ -448,12 +448,10 @@ void InspectorTimelineAgent::innerAddRecordToTimeline(PassRefPtr<InspectorObject > > void InspectorTimelineAgent::setHeapSizeStatistic(InspectorObject* record) > { >- size_t usedHeapSize = 0; >- size_t totalHeapSize = 0; >- size_t heapSizeLimit = 0; >- ScriptGCEvent::getHeapSize(usedHeapSize, totalHeapSize, heapSizeLimit); >- record->setNumber("usedHeapSize", usedHeapSize); >- record->setNumber("totalHeapSize", totalHeapSize); >+ HeapInfo info; >+ ScriptGCEvent::getHeapSize(info); >+ record->setNumber("usedHeapSize", info.usedJSHeapSize); >+ record->setNumber("totalHeapSize", info.totalJSHeapSize); > > if (m_state->getBoolean(TimelineAgentState::includeMemoryDetails)) { > RefPtr<InspectorObject> counters = InspectorObject::create(); >diff --git a/Source/WebCore/page/MemoryInfo.cpp b/Source/WebCore/page/MemoryInfo.cpp >index 57dae2b4074ec305ca4610526460e3e32aaf98e3..398c216c37f2126b9b7dc7fae4157f4dd4f47d07 100644 >--- a/Source/WebCore/page/MemoryInfo.cpp >+++ b/Source/WebCore/page/MemoryInfo.cpp >@@ -34,19 +34,119 @@ > #include "Frame.h" > #include "ScriptGCEvent.h" > #include "Settings.h" >+#include <limits> >+#include <wtf/CurrentTime.h> >+#include <wtf/MainThread.h> > > namespace WebCore { > >+#if ENABLE(INSPECTOR) >+ >+class HeapSizeCache { >+ WTF_MAKE_NONCOPYABLE(HeapSizeCache); >+public: >+ HeapSizeCache() >+ : m_lastUpdateTime(0) >+ { >+ } >+ >+ void getCachedHeapSize(HeapInfo& info) >+ { >+ maybeUpdate(); >+ info = m_info; >+ } >+ >+private: >+ void maybeUpdate() >+ { >+ // We rate-limit queries to once every twenty minutes to make it more difficult >+ // for attackers to compare memory usage before and after some event. >+ const double TwentyMinutesInSeconds = 20 * 60; >+ >+ double now = monotonicallyIncreasingTime(); >+ if (now - m_lastUpdateTime >= TwentyMinutesInSeconds) { >+ update(); >+ m_lastUpdateTime = now; >+ } >+ } >+ >+ void update() >+ { >+ ScriptGCEvent::getHeapSize(m_info); >+ m_info.usedJSHeapSize = quantizeMemorySize(m_info.usedJSHeapSize); >+ m_info.totalJSHeapSize = quantizeMemorySize(m_info.totalJSHeapSize); >+ m_info.jsHeapSizeLimit = quantizeMemorySize(m_info.jsHeapSizeLimit); >+ } >+ >+ double m_lastUpdateTime; >+ >+ HeapInfo m_info; >+}; >+ >+// We quantize the sizes to make it more difficult for an attacker to see precise >+// impact of operations on memory. The values are used for performance tuning, >+// and hence don't need to be as refined when the value is large, so we threshold >+// at a list of exponentially separated buckets. >+size_t quantizeMemorySize(size_t size) >+{ >+ const int numberOfBuckets = 100; >+ DEFINE_STATIC_LOCAL(Vector<size_t>, bucketSizeList, ()); >+ >+ ASSERT(isMainThread()); >+ if (bucketSizeList.isEmpty()) { >+ bucketSizeList.resize(numberOfBuckets); >+ >+ float sizeOfNextBucket = 10000000.0; // First bucket size is roughly 10M. >+ const float largestBucketSize = 4000000000.0; // Roughly 4GB. >+ // We scale with the Nth root of the ratio, so that we use all the bucktes. >+ const float scalingFactor = exp(log(largestBucketSize / sizeOfNextBucket) / numberOfBuckets); >+ >+ size_t nextPowerOfTen = static_cast<size_t>(pow(10, floor(log10(sizeOfNextBucket)) + 1) + 0.5); >+ size_t granularity = nextPowerOfTen / 1000; // We want 3 signficant digits. >+ >+ for (int i = 0; i < numberOfBuckets; ++i) { >+ size_t currentBucketSize = static_cast<size_t>(sizeOfNextBucket); >+ bucketSizeList[i] = currentBucketSize - (currentBucketSize % granularity); >+ >+ sizeOfNextBucket *= scalingFactor; >+ if (sizeOfNextBucket >= nextPowerOfTen) { >+ if (std::numeric_limits<size_t>::max() / 10 <= nextPowerOfTen) >+ nextPowerOfTen = std::numeric_limits<size_t>::max(); >+ else { >+ nextPowerOfTen *= 10; >+ granularity *= 10; >+ } >+ } >+ >+ // Watch out for overflow, if the range is too large for size_t. >+ if (i > 0 && bucketSizeList[i] < bucketSizeList[i - 1]) >+ bucketSizeList[i] = std::numeric_limits<size_t>::max(); >+ } >+ } >+ >+ for (int i = 0; i < numberOfBuckets; ++i) { >+ if (size <= bucketSizeList[i]) >+ return bucketSizeList[i]; >+ } >+ >+ return bucketSizeList[numberOfBuckets - 1]; >+} >+ >+#endif >+ > MemoryInfo::MemoryInfo(Frame* frame) >- : m_totalJSHeapSize(0), >- m_usedJSHeapSize(0), >- m_jsHeapSizeLimit(0) > { >- if (frame && frame->settings() && frame->settings()->memoryInfoEnabled()) { >+ if (!frame || !frame->settings()) >+ return; >+ > #if ENABLE(INSPECTOR) >- ScriptGCEvent::getHeapSize(m_usedJSHeapSize, m_totalJSHeapSize, m_jsHeapSizeLimit); >-#endif >+ if (frame->settings()->memoryInfoEnabled()) >+ ScriptGCEvent::getHeapSize(m_info); >+ else if (true || frame->settings()->quantizedMemoryInfoEnabled()) { >+ DEFINE_STATIC_LOCAL(HeapSizeCache, heapSizeCache, ()); >+ heapSizeCache.getCachedHeapSize(m_info); > } >+#endif > } > > } // namespace WebCore >diff --git a/Source/WebCore/page/MemoryInfo.h b/Source/WebCore/page/MemoryInfo.h >index 27a7344b8ff33939465ae8516382c5a9305a2292..55578fdedffce5c1cf631367596b5a9f198aaaab 100644 >--- a/Source/WebCore/page/MemoryInfo.h >+++ b/Source/WebCore/page/MemoryInfo.h >@@ -31,6 +31,7 @@ > #ifndef MemoryInfo_h > #define MemoryInfo_h > >+#include "ScriptGCEvent.h" > #include <wtf/PassRefPtr.h> > #include <wtf/RefCounted.h> > >@@ -42,18 +43,18 @@ class MemoryInfo : public RefCounted<MemoryInfo> { > public: > static PassRefPtr<MemoryInfo> create(Frame* frame) { return adoptRef(new MemoryInfo(frame)); } > >- size_t totalJSHeapSize() const { return m_totalJSHeapSize; } >- size_t usedJSHeapSize() const { return m_usedJSHeapSize; } >- size_t jsHeapSizeLimit() const { return m_jsHeapSizeLimit; } >+ size_t totalJSHeapSize() const { return m_info.totalJSHeapSize; } >+ size_t usedJSHeapSize() const { return m_info.usedJSHeapSize; } >+ size_t jsHeapSizeLimit() const { return m_info.jsHeapSizeLimit; } > > private: > MemoryInfo(Frame*); > >- size_t m_totalJSHeapSize; >- size_t m_usedJSHeapSize; >- size_t m_jsHeapSizeLimit; >+ HeapInfo m_info; > }; > >+size_t quantizeMemorySize(size_t); >+ > } // namespace WebCore > > #endif // MemoryInfo_h >diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp >index edd3d7931d448b4e63d80ebafabdf435bb97ab63..9fa35b3c8277a1ce807cb98a9529aaaba13c7610 100644 >--- a/Source/WebCore/page/Settings.cpp >+++ b/Source/WebCore/page/Settings.cpp >@@ -230,6 +230,7 @@ Settings::Settings(Page* page) > , m_unifiedTextCheckerEnabled(false) > #endif > , m_memoryInfoEnabled(false) >+ , m_quantizedMemoryInfoEnabled(false) > , m_interactiveFormValidation(false) > , m_usePreHTML5ParserQuirks(false) > , m_hyperlinkAuditingEnabled(false) >diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h >index a464cc86e34611db3c8ac59a05a897dda5d38246..396c7bfac0c863f0b7b916b04733a1e68b7dbe51 100644 >--- a/Source/WebCore/page/Settings.h >+++ b/Source/WebCore/page/Settings.h >@@ -443,6 +443,9 @@ namespace WebCore { > void setMemoryInfoEnabled(bool flag) { m_memoryInfoEnabled = flag; } > bool memoryInfoEnabled() const { return m_memoryInfoEnabled; } > >+ void setQuantizedMemoryInfoEnabled(bool flag) { m_quantizedMemoryInfoEnabled = flag; } >+ bool quantizedMemoryInfoEnabled() const { return m_quantizedMemoryInfoEnabled; } >+ > // This setting will be removed when an HTML5 compatibility issue is > // resolved and WebKit implementation of interactive validation is > // completed. See http://webkit.org/b/40520, http://webkit.org/b/40747, >@@ -717,11 +720,12 @@ namespace WebCore { > #if ENABLE(FULLSCREEN_API) > bool m_fullScreenAPIEnabled : 1; > #endif >- bool m_asynchronousSpellCheckingEnabled: 1; >- bool m_unifiedTextCheckerEnabled: 1; >- bool m_memoryInfoEnabled: 1; >- bool m_interactiveFormValidation: 1; >- bool m_usePreHTML5ParserQuirks: 1; >+ bool m_asynchronousSpellCheckingEnabled : 1; >+ bool m_unifiedTextCheckerEnabled : 1; >+ bool m_memoryInfoEnabled : 1; >+ bool m_quantizedMemoryInfoEnabled : 1; >+ bool m_interactiveFormValidation : 1; >+ bool m_usePreHTML5ParserQuirks : 1; > bool m_hyperlinkAuditingEnabled : 1; > bool m_crossOriginCheckInGetMatchedCSSRulesDisabled : 1; > bool m_forceCompositingMode : 1; >diff --git a/Source/WebKit/chromium/WebKit.gypi b/Source/WebKit/chromium/WebKit.gypi >index c410e6f4f7584fd20e8883a00f1ec06078e27267..23f98da7ca1c5444fb7d97152a1cc9b7cb51f870 100644 >--- a/Source/WebKit/chromium/WebKit.gypi >+++ b/Source/WebKit/chromium/WebKit.gypi >@@ -124,6 +124,7 @@ > 'tests/LinkHighlightTest.cpp', > 'tests/ListenerLeakTest.cpp', > 'tests/LocalizedNumberICUTest.cpp', >+ 'tests/MemoryInfo.cpp', > 'tests/MockCCQuadCuller.h', > 'tests/OpaqueRectTrackingContentLayerDelegateTest.cpp', > 'tests/PaintAggregatorTest.cpp', >diff --git a/Source/WebKit/chromium/tests/MemoryInfo.cpp b/Source/WebKit/chromium/tests/MemoryInfo.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..07ce2e518eb9711eb5d8163e073aebfb0af0ec40 >--- /dev/null >+++ b/Source/WebKit/chromium/tests/MemoryInfo.cpp >@@ -0,0 +1,60 @@ >+/* >+ * Copyright (C) 2012 Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions are >+ * met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * Redistributions in binary form must reproduce the above >+ * copyright notice, this list of conditions and the following disclaimer >+ * in the documentation and/or other materials provided with the >+ * distribution. >+ * * Neither the name of Google Inc. nor the names of its >+ * contributors may be used to endorse or promote products derived from >+ * this software without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS >+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT >+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR >+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT >+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, >+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT >+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, >+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY >+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+ >+#include "MemoryInfo.h" >+ >+#include <gtest/gtest.h> >+ >+using namespace WebCore; >+ >+namespace { >+ >+TEST(MemoryInfo, quantizeMemorySize) >+{ >+ EXPECT_EQ(10000000u, quantizeMemorySize(1024)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(1024 * 1024)); >+ EXPECT_EQ(1136000000u, quantizeMemorySize(1024 * 1024 * 1024)); >+ EXPECT_EQ(3767000000u, quantizeMemorySize(3894729835)); >+ EXPECT_EQ(410000000u, quantizeMemorySize(389472983)); >+ EXPECT_EQ(39600000u, quantizeMemorySize(38947298)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(3894729)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(389472)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(38947)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(3894)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(389)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(38)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(3)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(1)); >+ EXPECT_EQ(10000000u, quantizeMemorySize(0)); >+} >+ >+} // namespace
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 80444
:
130449
|
130482
|
130487
|
148287
|
149845
|
149860
|
149890
|
149891
|
154876