Commit 8db56e8e authored by bratell@opera.com's avatar bratell@opera.com

Shrink the binary by not super inlining all string concatenations.

String concatenation is used a lot to build error and exception
messages and it was larger than intended because of over eager
inlining.

Outlining template code saves 90 KB with clang and 65 KB with
gcc (lin64 content_shell). After this there is roughly 60 KB of
concatenation code left (clang).

clang:
Total change: -91866 bytes
==========================
  47 added, totalling +6264 bytes across 3 sources
  38 removed, totalling -18354 bytes across 2 sources
  79 grown, for a net change of +4604 bytes (98534 bytes before, 103138 bytes after) across 50 sources
  405 shrunk, for a net change of -84380 bytes (370130 bytes before, 285750 bytes after) across 134 sources

gcc:
Total change: -66849 bytes
==========================
  333 added, totalling +81561 bytes across 69 sources
  203 removed, totalling -65785 bytes across 76 sources
  211 grown, for a net change of +18666 bytes (228381 bytes before, 247047 bytes after) across 85 sources
  406 shrunk, for a net change of -101291 bytes (568083 bytes before, 466792 bytes after) across 160 sources

BUG=

Review URL: https://codereview.chromium.org/559133002

git-svn-id: svn://svn.chromium.org/blink/trunk@181896 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 3bf27e1b
/*
* Copyright 2014 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 "config.h"
#include "StringConcatenate.h"
// This macro is helpful for testing how many intermediate Strings are created while evaluating an
// expression containing operator+.
#ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
#define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
#endif
void WTF::StringTypeAdapter<char*>::writeTo(LChar* destination)
{
for (unsigned i = 0; i < m_length; ++i)
destination[i] = static_cast<LChar>(m_buffer[i]);
}
void WTF::StringTypeAdapter<char*>::writeTo(UChar* destination)
{
for (unsigned i = 0; i < m_length; ++i) {
unsigned char c = m_buffer[i];
destination[i] = c;
}
}
WTF::StringTypeAdapter<LChar*>::StringTypeAdapter(LChar* buffer)
: m_buffer(buffer)
, m_length(strlen(reinterpret_cast<char*>(buffer)))
{
}
void WTF::StringTypeAdapter<LChar*>::writeTo(LChar* destination)
{
memcpy(destination, m_buffer, m_length * sizeof(LChar));
}
void WTF::StringTypeAdapter<LChar*>::writeTo(UChar* destination)
{
StringImpl::copyChars(destination, m_buffer, m_length);
}
WTF::StringTypeAdapter<const UChar*>::StringTypeAdapter(const UChar* buffer)
: m_buffer(buffer)
{
size_t len = 0;
while (m_buffer[len] != UChar(0))
++len;
RELEASE_ASSERT(len <= std::numeric_limits<unsigned>::max());
m_length = len;
}
void WTF::StringTypeAdapter<const UChar*>::writeTo(UChar* destination)
{
memcpy(destination, m_buffer, m_length * sizeof(UChar));
}
WTF::StringTypeAdapter<const char*>::StringTypeAdapter(const char* buffer)
: m_buffer(buffer)
, m_length(strlen(buffer))
{
}
void WTF::StringTypeAdapter<const char*>::writeTo(LChar* destination)
{
memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
}
void WTF::StringTypeAdapter<const char*>::writeTo(UChar* destination)
{
for (unsigned i = 0; i < m_length; ++i) {
unsigned char c = m_buffer[i];
destination[i] = c;
}
}
WTF::StringTypeAdapter<const LChar*>::StringTypeAdapter(const LChar* buffer)
: m_buffer(buffer)
, m_length(strlen(reinterpret_cast<const char*>(buffer)))
{
}
void WTF::StringTypeAdapter<const LChar*>::writeTo(LChar* destination)
{
memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
}
void WTF::StringTypeAdapter<const LChar*>::writeTo(UChar* destination)
{
StringImpl::copyChars(destination, m_buffer, m_length);
}
void WTF::StringTypeAdapter<Vector<char> >::writeTo(LChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = static_cast<unsigned char>(m_buffer[i]);
}
void WTF::StringTypeAdapter<Vector<char> >::writeTo(UChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = static_cast<unsigned char>(m_buffer[i]);
}
void WTF::StringTypeAdapter<Vector<LChar> >::writeTo(LChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = m_buffer[i];
}
void WTF::StringTypeAdapter<Vector<LChar> >::writeTo(UChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = m_buffer[i];
}
void WTF::StringTypeAdapter<String>::writeTo(LChar* destination)
{
unsigned length = m_buffer.length();
ASSERT(is8Bit());
const LChar* data = m_buffer.characters8();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
}
void WTF::StringTypeAdapter<String>::writeTo(UChar* destination)
{
unsigned length = m_buffer.length();
if (is8Bit()) {
const LChar* data = m_buffer.characters8();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
} else {
const UChar* data = m_buffer.characters16();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
}
WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
}
......@@ -115,7 +115,7 @@ private:
};
template<>
class StringTypeAdapter<char*> {
class WTF_EXPORT StringTypeAdapter<char*> {
public:
StringTypeAdapter<char*>(char* buffer)
: m_buffer(buffer)
......@@ -127,19 +127,9 @@ public:
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
for (unsigned i = 0; i < m_length; ++i)
destination[i] = static_cast<LChar>(m_buffer[i]);
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
for (unsigned i = 0; i < m_length; ++i) {
unsigned char c = m_buffer[i];
destination[i] = c;
}
}
void writeTo(UChar* destination);
private:
const char* m_buffer;
......@@ -147,27 +137,17 @@ private:
};
template<>
class StringTypeAdapter<LChar*> {
class WTF_EXPORT StringTypeAdapter<LChar*> {
public:
StringTypeAdapter<LChar*>(LChar* buffer)
: m_buffer(buffer)
, m_length(strlen(reinterpret_cast<char*>(buffer)))
{
}
StringTypeAdapter<LChar*>(LChar* buffer);
unsigned length() { return m_length; }
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
memcpy(destination, m_buffer, m_length * sizeof(LChar));
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
StringImpl::copyChars(destination, m_buffer, m_length);
}
void writeTo(UChar* destination);
private:
const LChar* m_buffer;
......@@ -175,19 +155,9 @@ private:
};
template<>
class StringTypeAdapter<const UChar*> {
class WTF_EXPORT StringTypeAdapter<const UChar*> {
public:
StringTypeAdapter<const UChar*>(const UChar* buffer)
: m_buffer(buffer)
{
size_t len = 0;
while (m_buffer[len] != UChar(0))
++len;
RELEASE_ASSERT(len <= std::numeric_limits<unsigned>::max());
m_length = len;
}
StringTypeAdapter(const UChar* buffer);
unsigned length() { return m_length; }
......@@ -198,10 +168,7 @@ public:
RELEASE_ASSERT(false);
}
void writeTo(UChar* destination)
{
memcpy(destination, m_buffer, m_length * sizeof(UChar));
}
void writeTo(UChar* destination);
private:
const UChar* m_buffer;
......@@ -209,30 +176,17 @@ private:
};
template<>
class StringTypeAdapter<const char*> {
class WTF_EXPORT StringTypeAdapter<const char*> {
public:
StringTypeAdapter<const char*>(const char* buffer)
: m_buffer(buffer)
, m_length(strlen(buffer))
{
}
StringTypeAdapter<const char*>(const char* buffer);
unsigned length() { return m_length; }
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
for (unsigned i = 0; i < m_length; ++i) {
unsigned char c = m_buffer[i];
destination[i] = c;
}
}
void writeTo(UChar* destination);
private:
const char* m_buffer;
......@@ -240,27 +194,17 @@ private:
};
template<>
class StringTypeAdapter<const LChar*> {
class WTF_EXPORT StringTypeAdapter<const LChar*> {
public:
StringTypeAdapter<const LChar*>(const LChar* buffer)
: m_buffer(buffer)
, m_length(strlen(reinterpret_cast<const char*>(buffer)))
{
}
StringTypeAdapter<const LChar*>(const LChar* buffer);
unsigned length() { return m_length; }
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar));
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
StringImpl::copyChars(destination, m_buffer, m_length);
}
void writeTo(UChar* destination);
private:
const LChar* m_buffer;
......@@ -268,7 +212,7 @@ private:
};
template<>
class StringTypeAdapter<Vector<char> > {
class WTF_EXPORT StringTypeAdapter<Vector<char> > {
public:
StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
: m_buffer(buffer)
......@@ -279,17 +223,9 @@ public:
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = static_cast<unsigned char>(m_buffer[i]);
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = static_cast<unsigned char>(m_buffer[i]);
}
void writeTo(UChar* destination);
private:
const Vector<char>& m_buffer;
......@@ -307,24 +243,16 @@ public:
bool is8Bit() { return true; }
void writeTo(LChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = m_buffer[i];
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
for (size_t i = 0; i < m_buffer.size(); ++i)
destination[i] = m_buffer[i];
}
void writeTo(UChar* destination);
private:
const Vector<LChar>& m_buffer;
};
template<>
class StringTypeAdapter<String> {
class WTF_EXPORT StringTypeAdapter<String> {
public:
StringTypeAdapter<String>(const String& string)
: m_buffer(string)
......@@ -335,34 +263,9 @@ public:
bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); }
void writeTo(LChar* destination)
{
unsigned length = m_buffer.length();
void writeTo(LChar* destination);
ASSERT(is8Bit());
const LChar* data = m_buffer.characters8();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
}
void writeTo(UChar* destination)
{
unsigned length = m_buffer.length();
if (is8Bit()) {
const LChar* data = m_buffer.characters8();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
} else {
const UChar* data = m_buffer.characters16();
for (unsigned i = 0; i < length; ++i)
destination[i] = data[i];
}
WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
}
void writeTo(UChar* destination);
private:
const String& m_buffer;
......
......@@ -22,63 +22,86 @@
#ifndef StringOperators_h
#define StringOperators_h
#include "StringConcatenate.h"
namespace WTF {
template<typename StringType1, typename StringType2>
class StringAppend {
public:
StringAppend(StringType1 string1, StringType2 string2)
: m_string1(string1)
, m_string2(string2)
{
}
StringAppend(StringType1 string1, StringType2 string2);
operator String() const
{
return String(makeString(m_string1, m_string2));
}
operator String() const;
operator AtomicString() const
{
return AtomicString(makeString(m_string1, m_string2));
}
operator AtomicString() const;
bool is8Bit()
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
return adapter1.is8Bit() && adapter2.is8Bit();
}
bool is8Bit();
void writeTo(LChar* destination)
{
ASSERT(is8Bit());
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
adapter1.writeTo(destination);
adapter2.writeTo(destination + adapter1.length());
}
void writeTo(LChar* destination);
void writeTo(UChar* destination)
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
adapter1.writeTo(destination);
adapter2.writeTo(destination + adapter1.length());
}
void writeTo(UChar* destination);
unsigned length()
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
return adapter1.length() + adapter2.length();
}
unsigned length();
private:
StringType1 m_string1;
StringType2 m_string2;
};
template<typename StringType1, typename StringType2>
StringAppend<StringType1, StringType2>::StringAppend(StringType1 string1, StringType2 string2)
: m_string1(string1)
, m_string2(string2)
{
}
template<typename StringType1, typename StringType2>
StringAppend<StringType1, StringType2>::operator String() const
{
return String(makeString(m_string1, m_string2));
}
template<typename StringType1, typename StringType2>
StringAppend<StringType1, StringType2>::operator AtomicString() const
{
return AtomicString(makeString(m_string1, m_string2));
}
template<typename StringType1, typename StringType2>
bool StringAppend<StringType1, StringType2>::is8Bit()
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
return adapter1.is8Bit() && adapter2.is8Bit();
}
template<typename StringType1, typename StringType2>
void StringAppend<StringType1, StringType2>::writeTo(LChar* destination)
{
ASSERT(is8Bit());
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
adapter1.writeTo(destination);
adapter2.writeTo(destination + adapter1.length());
}
template<typename StringType1, typename StringType2>
void StringAppend<StringType1, StringType2>::writeTo(UChar* destination)
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
adapter1.writeTo(destination);
adapter2.writeTo(destination + adapter1.length());
}
template<typename StringType1, typename StringType2>
unsigned StringAppend<StringType1, StringType2>::length()
{
StringTypeAdapter<StringType1> adapter1(m_string1);
StringTypeAdapter<StringType2> adapter2(m_string2);
return adapter1.length() + adapter2.length();
}
template<typename StringType1, typename StringType2>
class StringTypeAdapter<StringAppend<StringType1, StringType2> > {
public:
......
......@@ -173,6 +173,7 @@
'text/StringBuilder.cpp',
'text/StringBuilder.h',
'text/StringCF.cpp',
'text/StringConcatenate.cpp',
'text/StringConcatenate.h',
'text/StringHash.h',
'text/StringImpl.cpp',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment