diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 90c43831f4..c4b4db5001 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -865,6 +865,13 @@ class V8EXPORT String : public Primitive { int length = -1, int* nchars = NULL) const; // UTF-8 + /** + * Flatten internal memory. Operations on the string tend to run faster + * after flattening especially if the string is a concatenation of many + * others. + */ + void Flatten(); + /** * A zero length string. */ diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 3ba22d63ea..ed48503e24 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -2731,6 +2731,13 @@ int String::Write(uint16_t* buffer, int start, int length) const { } +void v8::String::Flatten() { + EnsureInitialized("v8::String::Flatten()"); + i::Handle str = Utils::OpenHandle(this); + i::FlattenString(str); +} + + bool v8::String::IsExternal() const { EnsureInitialized("v8::String::IsExternal()"); i::Handle str = Utils::OpenHandle(this); diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index a87398740b..b6eed3c361 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -347,6 +347,31 @@ TEST(Utf8Conversion) { } +TEST(StringConcatFlatten) { + InitializeVM(); + v8::HandleScope handle_scope; + + const char* stringA = "abc"; + const char* stringB = "def"; + + v8::Local a = v8::String::New(stringA); + v8::Local b = v8::String::New(stringB); + + v8::Local cons = v8::String::Concat(a,b); + cons->Flatten(); + + char buffer[7]; + cons->WriteUtf8(buffer); + + int i; + for (i = 0; i < 3; i++) + CHECK_EQ(stringA[i], buffer[i]); + + for (i = 0; i < 3; i++) + CHECK_EQ(stringB[i], buffer[i+3]); +} + + TEST(ExternalShortStringAdd) { ZoneScope zone(DELETE_ON_EXIT); diff --git a/src/node.cc b/src/node.cc index 5dacd68b97..71405018ae 100644 --- a/src/node.cc +++ b/src/node.cc @@ -327,6 +327,7 @@ ssize_t DecodeWrite(char *buf, uint16_t * twobytebuf = new uint16_t[buflen]; + str->Flatten(); str->Write(twobytebuf, 0, buflen); for (size_t i = 0; i < buflen; i++) { diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 7c32d6ec60..f524778f46 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -308,6 +308,7 @@ Handle Buffer::Utf8Write(const Arguments &args) { const char *p = buffer->data() + offset; + s->Flatten(); int written = s->WriteUtf8((char*)p, buffer->length_ - offset); if (written > 0 && p[written-1] == '\0') written--; @@ -340,6 +341,7 @@ Handle Buffer::AsciiWrite(const Arguments &args) { size_t towrite = MIN((unsigned long) s->Length(), buffer->length_ - offset); + s->Flatten(); int written = s->WriteAscii((char*)p, 0, towrite); return scope.Close(Integer::New(written)); }