Index: third_party/WebKit/Source/platform/text/CompressibleString.cpp |
diff --git a/third_party/WebKit/Source/platform/text/CompressibleString.cpp b/third_party/WebKit/Source/platform/text/CompressibleString.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..956af6fe7eee6bad844f4ed482ef89a728ac5c1e |
--- /dev/null |
+++ b/third_party/WebKit/Source/platform/text/CompressibleString.cpp |
@@ -0,0 +1,189 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "platform/text/CompressibleString.h" |
+ |
+#include "public/platform/Platform.h" |
+#include "wtf/Assertions.h" |
+#include "wtf/LinkedStack.h" |
haraken
2016/01/15 12:46:21
This is not necessary.
hajimehoshi
2016/01/18 09:42:26
Done.
|
+#include "wtf/Partitions.h" |
haraken
2016/01/15 12:46:21
Ditto.
hajimehoshi
2016/01/18 09:42:27
Done.
|
+#include "wtf/PassOwnPtr.h" |
haraken
2016/01/15 12:46:21
Ditto.
hajimehoshi
2016/01/18 09:42:26
Done.
|
+#include "wtf/WTFThreadData.h" |
+#include "wtf/text/WTFString.h" |
+ |
+namespace blink { |
+ |
+class CompressibleStringTable { |
+ WTF_MAKE_NONCOPYABLE(CompressibleStringTable); |
+public: |
+ static CompressibleStringTable* create(WTFThreadData& data) |
+ { |
+ data.m_compressibleStringTable = new CompressibleStringTable; |
+ data.m_compressibleStringTableDestructor = CompressibleStringTable::destroy; |
+ return data.m_compressibleStringTable; |
+ } |
+ |
+ void add(CompressibleStringImpl* string) |
+ { |
+ m_table.add(string); |
haraken
2016/01/15 12:46:21
Can we add:
ASSERT(!m_table.contains(string));
hajimehoshi
2016/01/18 09:42:27
Done.
|
+ } |
+ |
+ bool contains(CompressibleStringImpl* string) const |
+ { |
+ return m_table.contains(string); |
+ } |
+ |
+ void remove(CompressibleStringImpl* string) |
+ { |
+ m_table.remove(string); |
haraken
2016/01/15 12:46:21
Can we add:
ASSERT(m_table.contains(string));
hajimehoshi
2016/01/18 09:42:27
Done.
|
+ } |
+ |
+ void compressAll() |
+ { |
+ HashSet<CompressibleStringImpl*>::iterator end = m_table.end(); |
+ for (HashSet<CompressibleStringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) { |
+ CompressibleStringImpl* string = *iter; |
+ if (!string->isCompressed()) |
+ string->compressString(); |
+ } |
+ } |
+ |
+private: |
+ CompressibleStringTable() { } |
+ |
+ static void destroy(CompressibleStringTable* table) |
+ { |
+ delete table; |
+ } |
+ |
+ HashSet<CompressibleStringImpl*> m_table; |
+}; |
+ |
+static const int CompressibleStringImplSizeThrehold = 100000; |
+ |
+static inline CompressibleStringTable& compressibleStringTable() |
haraken
2016/01/15 12:46:21
How about creating the table in Platform::initiali
hajimehoshi
2016/01/18 09:42:27
Done (I added initializeCompressibleStringTable fu
|
+{ |
+ // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor). |
haraken
2016/01/15 12:46:21
Once possible => remove the word
hajimehoshi
2016/01/18 09:42:27
Done.
|
+ WTFThreadData& data = wtfThreadData(); |
+ CompressibleStringTable* table = data.compressibleStringTable(); |
+ if (UNLIKELY(!table)) |
+ table = CompressibleStringTable::create(data); |
+ return *table; |
+} |
+ |
+bool CompressibleStringImpl::s_isPageBackground = false; |
+ |
+void CompressibleStringImpl::compressAll() |
+{ |
+ compressibleStringTable().compressAll(); |
+} |
+ |
+void CompressibleStringImpl::setPageBackground(bool isPageBackground) |
+{ |
+ s_isPageBackground = isPageBackground; |
+} |
+ |
+CompressibleStringImpl::CompressibleStringImpl(PassRefPtr<StringImpl> impl) |
+ : m_impl(impl) |
+ , m_isCompressed(false) |
+{ |
+ ASSERT(m_impl); |
+ if (originalContentSizeInBytes() > CompressibleStringImplSizeThrehold) |
+ compressibleStringTable().add(this); |
+} |
+ |
+CompressibleStringImpl::~CompressibleStringImpl() |
+{ |
+ if (compressibleStringTable().contains(this)) |
+ compressibleStringTable().remove(this); |
+} |
+ |
+unsigned CompressibleStringImpl::originalContentSizeInBytes() const |
+{ |
+ if (is8Bit()) |
+ return originalLength() * sizeof(LChar); |
+ return originalLength() * sizeof(UChar); |
+} |
+ |
+unsigned CompressibleStringImpl::currentSizeInBytes() const |
+{ |
+ return originalContentSizeInBytes(); |
haraken
2016/01/15 12:46:21
Add a TODO to update this function once we enable
hajimehoshi
2016/01/18 09:42:27
Done.
|
+} |
+ |
+String CompressibleStringImpl::toString() |
+{ |
+ if (UNLIKELY(isCompressed())) |
+ decompressString(); |
+ return m_impl.get(); |
+} |
+ |
+const LChar* CompressibleStringImpl::characters8() |
+{ |
+ return toString().characters8(); |
+} |
+ |
+const UChar* CompressibleStringImpl::characters16() |
+{ |
+ return toString().characters16(); |
+} |
+ |
+enum { |
+ CompressingInBackgroundTab, |
+ DecompressingInBackgroundTab, |
+}; |
+ |
+static const char* histogramName() |
+{ |
+ return "Memory.CompressibleStringCount"; |
+} |
+ |
+// compressString does nothing but collect UMA so far. |
+// TODO(hajimehoshi): Implement this. |
+void CompressibleStringImpl::compressString() |
+{ |
+ if (s_isPageBackground) |
haraken
2016/01/15 12:46:21
Why do we need the 'if (s_isPageBackground)' check
hajimehoshi
2016/01/18 09:42:26
See the below comment.
|
+ Platform::current()->histogramCustomCounts(histogramName(), CompressingInBackgroundTab, 0, 10000, 50); |
+ |
+ ASSERT(m_impl); |
+ ASSERT(!isCompressed()); |
+ m_isCompressed = true; |
+} |
+ |
+// decompressString does nothing but collect UMA so far. |
+// TODO(hajimehoshi): Implement this. |
+void CompressibleStringImpl::decompressString() |
+{ |
+ if (s_isPageBackground) |
haraken
2016/01/15 12:46:21
Ditto.
hajimehoshi
2016/01/18 09:42:27
It's because it would not make sense to count deco
haraken
2016/01/18 09:58:25
Makes sense. Can we also introduce:
else
Pl
hajimehoshi
2016/01/18 10:31:51
Done.
|
+ Platform::current()->histogramCustomCounts(histogramName(), DecompressingInBackgroundTab, 0, 10000, 50); |
+ |
+ ASSERT(isCompressed()); |
+ m_isCompressed = false; |
+} |
+ |
+CompressibleString::CompressibleString() |
+ : m_impl(nullptr) |
+{ |
+} |
+ |
+CompressibleString::CompressibleString(const CompressibleString& rhs) |
+ : m_impl(rhs.m_impl) |
+{ |
+} |
+ |
+CompressibleString::CompressibleString(PassRefPtr<StringImpl> impl) |
+ : m_impl(impl ? adoptRef(new CompressibleStringImpl(impl)) : nullptr) |
+{ |
+} |
+ |
+void CompressibleString::compressString() const |
+{ |
+ m_impl->compressString(); |
+} |
+ |
+void CompressibleString::decompressString() const |
+{ |
+ m_impl->decompressString(); |
+} |
+ |
+} // namespace blink |