Commit 327eb48c authored by yangguo@chromium.org's avatar yangguo@chromium.org

Enable slices of external strings (in the tentative implementation).

TEST=cctest test-strings/SliceFromExternal, mjsunit/string-slices.js

Review URL: http://codereview.chromium.org/7832002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9295 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9e4663a8
......@@ -2737,25 +2737,23 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
// Make an attempt to flatten the buffer to reduce access time.
buffer = buffer->TryFlattenGetString();
// TODO(1626): For now slicing external strings is not supported. However,
// a flat cons string can have an external string as first part in some cases.
// Therefore we have to single out this case as well.
if (!FLAG_string_slices ||
(buffer->IsConsString() &&
(!buffer->IsFlat() ||
!ConsString::cast(buffer)->first()->IsSeqString())) ||
buffer->IsExternalString() ||
!buffer->IsFlat() ||
length < SlicedString::kMinLength ||
pretenure == TENURED) {
Object* result;
{ MaybeObject* maybe_result = buffer->IsAsciiRepresentation()
? AllocateRawAsciiString(length, pretenure)
: AllocateRawTwoByteString(length, pretenure);
// WriteToFlat takes care of the case when an indirect string has a
// different encoding from its underlying string. These encodings may
// differ because of externalization.
bool is_ascii = buffer->IsAsciiRepresentation();
{ MaybeObject* maybe_result = is_ascii
? AllocateRawAsciiString(length, pretenure)
: AllocateRawTwoByteString(length, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
String* string_result = String::cast(result);
// Copy the characters into the new object.
if (buffer->IsAsciiRepresentation()) {
if (is_ascii) {
ASSERT(string_result->IsAsciiRepresentation());
char* dest = SeqAsciiString::cast(string_result)->GetChars();
String::WriteToFlat(buffer, dest, start, end);
......@@ -2768,12 +2766,17 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
}
ASSERT(buffer->IsFlat());
ASSERT(!buffer->IsExternalString());
#if DEBUG
buffer->StringVerify();
#endif
Object* result;
// When slicing an indirect string we use its encoding for a newly created
// slice and don't check the encoding of the underlying string. This is safe
// even if the encodings are different because of externalization. If an
// indirect ASCII string is pointing to a two-byte string, the two-byte char
// codes of the underlying string must still fit into ASCII (because
// externalization must not change char codes).
{ Map* map = buffer->IsAsciiRepresentation()
? sliced_ascii_string_map()
: sliced_string_map();
......@@ -2799,7 +2802,8 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
sliced_string->set_parent(buffer);
sliced_string->set_offset(start);
}
ASSERT(sliced_string->parent()->IsSeqString());
ASSERT(sliced_string->parent()->IsSeqString() ||
sliced_string->parent()->IsExternalString());
return result;
}
......
......@@ -2893,7 +2893,7 @@ void FindStringIndicesDispatch(Isolate* isolate,
}
} else {
Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
if (pattern->IsAsciiRepresentation()) {
if (pattern_content.IsAscii()) {
FindStringIndices(isolate,
subject_vector,
pattern_content.ToAsciiVector(),
......
......@@ -502,6 +502,35 @@ TEST(SliceFromCons) {
}
class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
public:
explicit AsciiVectorResource(i::Vector<const char> vector)
: data_(vector) {}
virtual ~AsciiVectorResource() {}
virtual size_t length() const { return data_.length(); }
virtual const char* data() const { return data_.start(); }
private:
i::Vector<const char> data_;
};
TEST(SliceFromExternal) {
FLAG_string_slices = true;
InitializeVM();
v8::HandleScope scope;
AsciiVectorResource resource(
i::Vector<const char>("abcdefghijklmnopqrstuvwxyz", 26));
Handle<String> string = FACTORY->NewExternalStringFromAscii(&resource);
CHECK(string->IsExternalString());
Handle<String> slice = FACTORY->NewSubString(string, 1, 25);
CHECK(slice->IsSlicedString());
CHECK(string->IsExternalString());
CHECK_EQ(SlicedString::cast(*slice)->parent(), *string);
CHECK(SlicedString::cast(*slice)->parent()->IsExternalString());
CHECK(slice->IsFlat());
}
TEST(TrivialSlice) {
// This tests whether a slice that contains the entire parent string
// actually creates a new string (it should not).
......
......@@ -189,11 +189,16 @@ assertEquals("\u03B4\u03B5\u03B6\u03B7\u03B8\u03B9abcdefghijklmnop",
assertEquals("\u03B2\u03B3\u03B4\u03B5\u03B4\u03B5\u03B6\u03B7",
utf.substring(5,1) + utf.substring(3,7));
/*
// Externalizing strings.
var a = "123456789qwertyuiopasdfghjklzxcvbnm";
var b = a.slice(1,-1);
var a = "123456789" + "qwertyuiopasdfghjklzxcvbnm";
var b = "23456789qwertyuiopasdfghjklzxcvbn"
assertEquals(a.slice(1,-1), b);
externalizeString(a);
assertTrue(isAsciiString(a));
externalizeString(a, true);
assertFalse(isAsciiString(a));
assertEquals(a.slice(1,-1), b);
*/
assertTrue(/3456789qwe/.test(a));
assertEquals(5, a.indexOf("678"));
assertEquals("12345", a.split("6")[0]);
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