Chromium Code Reviews| 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..63f597f61e968437a416dfe68032dae1db5b3f86 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/platform/text/CompressibleString.cpp |
| @@ -0,0 +1,201 @@ |
| +// 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/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) |
| + { |
| + ASSERT(!m_table.contains(string)); |
| + m_table.add(string); |
| + } |
| + |
| + bool contains(CompressibleStringImpl* string) const |
| + { |
| + return m_table.contains(string); |
| + } |
| + |
| + void remove(CompressibleStringImpl* string) |
| + { |
| + ASSERT(m_table.contains(string)); |
| + m_table.remove(string); |
| + } |
| + |
| + 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; |
| + |
| +void initializeCompressibleStringTable() |
| +{ |
| + WTFThreadData& data = wtfThreadData(); |
| + ASSERT(!data.compressibleStringTable()); |
| + CompressibleStringTable::create(data); |
| +} |
| + |
| +static inline CompressibleStringTable& compressibleStringTable() |
| +{ |
| + WTFThreadData& data = wtfThreadData(); |
| + ASSERT(data.compressibleStringTable()); |
| + return *data.compressibleStringTable(); |
| +} |
| + |
| +bool CompressibleStringImpl::s_isPageBackground = false; |
| + |
| +void CompressibleStringImpl::compressAll() |
| +{ |
| + compressibleStringTable().compressAll(); |
| +} |
| + |
| +void CompressibleStringImpl::setPageBackground(bool isPageBackground) |
| +{ |
| + s_isPageBackground = isPageBackground; |
| +} |
| + |
| +CompressibleStringImpl::CompressibleStringImpl() |
|
haraken
2016/01/19 07:43:35
For performance reasons, I'd suggest inlining most
hajimehoshi
2016/01/19 10:19:20
Done.
|
| + : m_string() |
| + , m_isCompressed(false) |
| +{ |
| +} |
| + |
| +CompressibleStringImpl::CompressibleStringImpl(PassRefPtr<StringImpl> impl) |
|
haraken
2016/01/19 07:43:35
Inline.
hajimehoshi
2016/01/19 10:19:21
Hmm, I don't want to expose compressibleStringTabl
|
| + : m_string(impl) |
| + , m_isCompressed(false) |
| +{ |
| + ASSERT(impl); |
| + if (originalContentSizeInBytes() > CompressibleStringImplSizeThrehold) |
| + compressibleStringTable().add(this); |
| +} |
| + |
| +CompressibleStringImpl::~CompressibleStringImpl() |
| +{ |
| + if (compressibleStringTable().contains(this)) |
|
haraken
2016/01/19 07:43:35
A better condition would be:
if (originalConten
hajimehoshi
2016/01/19 10:19:20
Done.
|
| + compressibleStringTable().remove(this); |
| +} |
| + |
| +unsigned CompressibleStringImpl::originalContentSizeInBytes() const |
|
haraken
2016/01/19 07:43:35
Inline.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| +{ |
| + if (is8Bit()) |
| + return originalLength() * sizeof(LChar); |
| + return originalLength() * sizeof(UChar); |
| +} |
| + |
| +// TODO(hajimehoshi): Update this once we implement compression. |
| +unsigned CompressibleStringImpl::currentSizeInBytes() const |
|
haraken
2016/01/19 07:43:35
Inline.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| +{ |
| + return originalContentSizeInBytes(); |
| +} |
| + |
| +const String& CompressibleStringImpl::toString() |
|
haraken
2016/01/19 07:43:35
It would be better to inline this.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| +{ |
| + if (UNLIKELY(isCompressed())) |
| + decompressString(); |
| + return m_string; |
| +} |
| + |
| +const LChar* CompressibleStringImpl::characters8() |
|
haraken
2016/01/19 07:43:35
Inline.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| +{ |
| + return toString().characters8(); |
| +} |
| + |
| +const UChar* CompressibleStringImpl::characters16() |
|
haraken
2016/01/19 07:43:35
Inline.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| +{ |
| + return toString().characters16(); |
| +} |
| + |
| +enum { |
| + CompressingInBackgroundTab, |
|
haraken
2016/01/19 07:43:35
StringWasCompressedInBackgroundTab
StringWasDecomp
hajimehoshi
2016/01/19 10:19:21
Done.
|
| + DecompressingInBackgroundTab, |
| + DecompressingInForegroundTab, |
| +}; |
| + |
| +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/19 07:43:35
Shouldn't this be:
ASSERT(s_isPageBackground);
hajimehoshi
2016/01/19 10:19:21
Done.
|
| + Platform::current()->histogramCustomCounts(histogramName(), CompressingInBackgroundTab, 0, 10000, 50); |
| + |
| + ASSERT(!isCompressed()); |
| + m_isCompressed = true; |
| +} |
| + |
| +// decompressString does nothing but collect UMA so far. |
| +// TODO(hajimehoshi): Implement this. |
| +void CompressibleStringImpl::decompressString() |
| +{ |
| + if (s_isPageBackground) |
| + Platform::current()->histogramCustomCounts(histogramName(), DecompressingInBackgroundTab, 0, 10000, 50); |
| + else |
| + Platform::current()->histogramCustomCounts(histogramName(), DecompressingInForegroundTab, 0, 10000, 50); |
| + |
| + ASSERT(isCompressed()); |
| + m_isCompressed = false; |
| +} |
| + |
| +CompressibleString::CompressibleString() |
|
haraken
2016/01/19 07:43:35
Inline these methods.
hajimehoshi
2016/01/19 10:19:21
Done.
|
| + : 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 |