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..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 |