Commit 50e5ad72 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Fix bug where strings were not flattened before regexp.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1142 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e33a8ee1
...@@ -2017,7 +2017,7 @@ int String::WriteAscii(char* buffer, int start, int length) const { ...@@ -2017,7 +2017,7 @@ int String::WriteAscii(char* buffer, int start, int length) const {
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
// Flatten the string for efficiency. This applies whether we are // Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters. // using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten(i::StringShape(*str)); str->TryFlattenIfNotFlat(i::StringShape(*str));
int end = length; int end = length;
if ( (length == -1) || (length > str->length() - start) ) if ( (length == -1) || (length > str->length() - start) )
end = str->length() - start; end = str->length() - start;
...@@ -2042,7 +2042,7 @@ int String::Write(uint16_t* buffer, int start, int length) const { ...@@ -2042,7 +2042,7 @@ int String::Write(uint16_t* buffer, int start, int length) const {
i::Handle<i::String> str = Utils::OpenHandle(this); i::Handle<i::String> str = Utils::OpenHandle(this);
// Flatten the string for efficiency. This applies whether we are // Flatten the string for efficiency. This applies whether we are
// using StringInputBuffer or Get(i) to access the characters. // using StringInputBuffer or Get(i) to access the characters.
str->TryFlatten(i::StringShape(*str)); str->TryFlattenIfNotFlat(i::StringShape(*str));
int end = length; int end = length;
if ( (length == -1) || (length > str->length() - start) ) if ( (length == -1) || (length > str->length() - start) )
end = str->length() - start; end = str->length() - start;
......
...@@ -188,7 +188,7 @@ void TransformToFastProperties(Handle<JSObject> object, ...@@ -188,7 +188,7 @@ void TransformToFastProperties(Handle<JSObject> object,
void FlattenString(Handle<String> string) { void FlattenString(Handle<String> string) {
StringShape shape(*string); StringShape shape(*string);
if (string->IsFlat(shape)) return; if (string->IsFlat(shape)) return;
CALL_HEAP_FUNCTION_VOID(string->Flatten(shape)); CALL_HEAP_FUNCTION_VOID(string->TryFlatten(shape));
ASSERT(string->IsFlat(StringShape(*string))); ASSERT(string->IsFlat(StringShape(*string)));
} }
......
...@@ -697,7 +697,7 @@ static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re, ...@@ -697,7 +697,7 @@ static Handle<FixedArray> GetCompiledIrregexp(Handle<JSRegExp> re,
Handle<String> pattern(re->Pattern()); Handle<String> pattern(re->Pattern());
StringShape shape(*pattern); StringShape shape(*pattern);
if (!pattern->IsFlat(shape)) { if (!pattern->IsFlat(shape)) {
pattern->Flatten(shape); FlattenString(pattern);
} }
RegExpCompileData compile_data; RegExpCompileData compile_data;
...@@ -824,7 +824,7 @@ Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp, ...@@ -824,7 +824,7 @@ Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
Handle<Object> matches; Handle<Object> matches;
if (!subject->IsFlat(shape)) { if (!subject->IsFlat(shape)) {
subject->Flatten(shape); FlattenString(subject);
} }
while (true) { while (true) {
...@@ -920,6 +920,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp, ...@@ -920,6 +920,7 @@ Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
offsets_vector, offsets_vector,
previous_index == 0); previous_index == 0);
} else { // Sequential string } else { // Sequential string
ASSERT(StringShape(*subject).IsSequential());
Address char_address = Address char_address =
is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress() is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress()
: SeqTwoByteString::cast(*subject)->GetCharsAddress(); : SeqTwoByteString::cast(*subject)->GetCharsAddress();
......
...@@ -1431,13 +1431,14 @@ void String::set_length_field(uint32_t value) { ...@@ -1431,13 +1431,14 @@ void String::set_length_field(uint32_t value) {
} }
void String::TryFlatten(StringShape shape) { Object* String::TryFlattenIfNotFlat(StringShape shape) {
ASSERT(shape.type() == StringShape(this).type()); ASSERT(shape.type() == StringShape(this).type());
// We don't need to flatten strings that are already flat. Since this code // We don't need to flatten strings that are already flat. Since this code
// is inlined, it can be helpful in the flat case to not call out to Flatten. // is inlined, it can be helpful in the flat case to not call out to Flatten.
if (!IsFlat(shape)) { if (!IsFlat(shape)) {
Flatten(shape); return TryFlatten(shape);
} }
return this;
} }
......
...@@ -587,7 +587,7 @@ static bool AnWord(String* str) { ...@@ -587,7 +587,7 @@ static bool AnWord(String* str) {
} }
Object* String::Flatten(StringShape shape) { Object* String::TryFlatten(StringShape shape) {
#ifdef DEBUG #ifdef DEBUG
// Do not attempt to flatten in debug mode when allocation is not // Do not attempt to flatten in debug mode when allocation is not
// allowed. This is to avoid an assertion failure when allocating. // allowed. This is to avoid an assertion failure when allocating.
...@@ -604,11 +604,11 @@ Object* String::Flatten(StringShape shape) { ...@@ -604,11 +604,11 @@ Object* String::Flatten(StringShape shape) {
// SlicedStrings. // SlicedStrings.
String* buf = ss->buffer(); String* buf = ss->buffer();
ASSERT(!buf->IsSlicedString()); ASSERT(!buf->IsSlicedString());
Object* ok = buf->Flatten(StringShape(buf)); Object* ok = buf->TryFlatten(StringShape(buf));
if (ok->IsFailure()) return ok; if (ok->IsFailure()) return ok;
// Under certain circumstances (TryFlatten fails in String::Slice) // Under certain circumstances (TryFlattenIfNotFlat fails in
// we can have a cons string under a slice. In this case we need // String::Slice) we can have a cons string under a slice.
// to get the flat string out of the cons! // In this case we need to get the flat string out of the cons!
if (StringShape(String::cast(ok)).IsCons()) { if (StringShape(String::cast(ok)).IsCons()) {
ss->set_buffer(ConsString::cast(ok)->first()); ss->set_buffer(ConsString::cast(ok)->first());
} }
...@@ -2413,8 +2413,8 @@ Object* JSObject::DefineGetterSetter(String* name, ...@@ -2413,8 +2413,8 @@ Object* JSObject::DefineGetterSetter(String* name,
return Heap::undefined_value(); return Heap::undefined_value();
} }
// TryFlatten before operating on the string. // Try to flatten before operating on the string.
name->TryFlatten(StringShape(name)); name->TryFlattenIfNotFlat(StringShape(name));
// Make sure name is not an index. // Make sure name is not an index.
uint32_t index; uint32_t index;
...@@ -3065,9 +3065,7 @@ int String::Utf8Length() { ...@@ -3065,9 +3065,7 @@ int String::Utf8Length() {
// doesn't make Utf8Length faster, but it is very likely that // doesn't make Utf8Length faster, but it is very likely that
// the string will be accessed later (for example by WriteUtf8) // the string will be accessed later (for example by WriteUtf8)
// so it's still a good idea. // so it's still a good idea.
if (!IsFlat(shape)) { TryFlattenIfNotFlat(shape); // shape is now no longer valid.
TryFlatten(shape); // shape is now no longer valid.
}
Access<StringInputBuffer> buffer(&string_input_buffer); Access<StringInputBuffer> buffer(&string_input_buffer);
buffer->Reset(0, this); buffer->Reset(0, this);
int result = 0; int result = 0;
......
...@@ -3131,15 +3131,17 @@ class String: public HeapObject { ...@@ -3131,15 +3131,17 @@ class String: public HeapObject {
// to this method are not efficient unless the string is flat. // to this method are not efficient unless the string is flat.
inline uint16_t Get(StringShape shape, int index); inline uint16_t Get(StringShape shape, int index);
// Flatten the top level ConsString that is hiding behind this // Try to flatten the top level ConsString that is hiding behind this
// string. This is a no-op unless the string is a ConsString or a // string. This is a no-op unless the string is a ConsString or a
// SlicedString. Flatten mutates the ConsString and might return a // SlicedString. Flatten mutates the ConsString and might return a
// failure. // failure.
Object* Flatten(StringShape shape); Object* TryFlatten(StringShape shape);
// Try to flatten the string. Do not allow handling of allocation
// failures. After calling TryFlatten, the string could still be a // Try to flatten the string. Checks first inline to see if it is necessary.
// ConsString. // Do not handle allocation failures. After calling TryFlattenIfNotFlat, the
inline void TryFlatten(StringShape shape); // string could still be a ConsString, in which case a failure is returned.
// Use FlattenString from Handles.cc to be sure to flatten.
inline Object* TryFlattenIfNotFlat(StringShape shape);
Vector<const char> ToAsciiVector(); Vector<const char> ToAsciiVector();
Vector<const uc16> ToUC16Vector(); Vector<const uc16> ToUC16Vector();
......
...@@ -1092,7 +1092,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, ...@@ -1092,7 +1092,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
Counters::total_parse_size.Increment(source->length(shape)); Counters::total_parse_size.Increment(source->length(shape));
// Initialize parser state. // Initialize parser state.
source->TryFlatten(shape); source->TryFlattenIfNotFlat(shape);
scanner_.Init(source, stream, 0); scanner_.Init(source, stream, 0);
ASSERT(target_stack_ == NULL); ASSERT(target_stack_ == NULL);
...@@ -1141,7 +1141,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source, ...@@ -1141,7 +1141,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
bool is_expression) { bool is_expression) {
ZoneScope zone_scope(DONT_DELETE_ON_EXIT); ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
StatsRateScope timer(&Counters::parse_lazy); StatsRateScope timer(&Counters::parse_lazy);
source->TryFlatten(StringShape(*source)); source->TryFlattenIfNotFlat(StringShape(*source));
StringShape shape(*source); StringShape shape(*source);
Counters::total_parse_size.Increment(source->length(shape)); Counters::total_parse_size.Increment(source->length(shape));
SafeStringInputBuffer buffer(source.location()); SafeStringInputBuffer buffer(source.location());
......
...@@ -1060,7 +1060,7 @@ static Object* CharCodeAt(String* subject, Object* index) { ...@@ -1060,7 +1060,7 @@ static Object* CharCodeAt(String* subject, Object* index) {
// Flatten the string. If someone wants to get a char at an index // Flatten the string. If someone wants to get a char at an index
// in a cons string, it is likely that more indices will be // in a cons string, it is likely that more indices will be
// accessed. // accessed.
subject->TryFlatten(StringShape(subject)); subject->TryFlattenIfNotFlat(StringShape(subject));
StringShape shape(subject); StringShape shape(subject);
if (i >= static_cast<uint32_t>(subject->length(shape))) { if (i >= static_cast<uint32_t>(subject->length(shape))) {
return Heap::nan_value(); return Heap::nan_value();
...@@ -1531,8 +1531,8 @@ static Object* Runtime_StringLastIndexOf(Arguments args) { ...@@ -1531,8 +1531,8 @@ static Object* Runtime_StringLastIndexOf(Arguments args) {
CONVERT_CHECKED(String, pat, args[1]); CONVERT_CHECKED(String, pat, args[1]);
Object* index = args[2]; Object* index = args[2];
sub->TryFlatten(StringShape(sub)); sub->TryFlattenIfNotFlat(StringShape(sub));
pat->TryFlatten(StringShape(pat)); pat->TryFlattenIfNotFlat(StringShape(pat));
StringShape sub_shape(sub); StringShape sub_shape(sub);
StringShape pat_shape(pat); StringShape pat_shape(pat);
...@@ -1591,8 +1591,8 @@ static Object* Runtime_StringLocaleCompare(Arguments args) { ...@@ -1591,8 +1591,8 @@ static Object* Runtime_StringLocaleCompare(Arguments args) {
int d = str1->Get(shape1, 0) - str2->Get(shape2, 0); int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
if (d != 0) return Smi::FromInt(d); if (d != 0) return Smi::FromInt(d);
str1->TryFlatten(shape1); // Shapes are no longer valid now! str1->TryFlattenIfNotFlat(shape1); // Shapes are no longer valid now!
str2->TryFlatten(shape2); str2->TryFlattenIfNotFlat(shape2);
static StringInputBuffer buf1; static StringInputBuffer buf1;
static StringInputBuffer buf2; static StringInputBuffer buf2;
...@@ -1729,7 +1729,7 @@ static Object* Runtime_NumberToPrecision(Arguments args) { ...@@ -1729,7 +1729,7 @@ static Object* Runtime_NumberToPrecision(Arguments args) {
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
StringShape shape(*string); StringShape shape(*string);
if (index < static_cast<uint32_t>(string->length(shape))) { if (index < static_cast<uint32_t>(string->length(shape))) {
string->TryFlatten(shape); // Invalidates shape! string->TryFlattenIfNotFlat(shape); // Invalidates shape!
return LookupSingleCharacterStringFromCode( return LookupSingleCharacterStringFromCode(
string->Get(StringShape(*string), index)); string->Get(StringShape(*string), index));
} }
...@@ -1922,7 +1922,7 @@ Object* Runtime::SetObjectProperty(Handle<Object> object, ...@@ -1922,7 +1922,7 @@ Object* Runtime::SetObjectProperty(Handle<Object> object,
result = SetElement(js_object, index, value); result = SetElement(js_object, index, value);
} else { } else {
Handle<String> key_string = Handle<String>::cast(key); Handle<String> key_string = Handle<String>::cast(key);
key_string->TryFlatten(StringShape(*key_string)); key_string->TryFlattenIfNotFlat(StringShape(*key_string));
result = SetProperty(js_object, key_string, value, attr); result = SetProperty(js_object, key_string, value, attr);
} }
if (result.is_null()) return Failure::Exception(); if (result.is_null()) return Failure::Exception();
...@@ -2194,7 +2194,7 @@ static Object* Runtime_StringToNumber(Arguments args) { ...@@ -2194,7 +2194,7 @@ static Object* Runtime_StringToNumber(Arguments args) {
NoHandleAllocation ha; NoHandleAllocation ha;
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
CONVERT_CHECKED(String, subject, args[0]); CONVERT_CHECKED(String, subject, args[0]);
subject->TryFlatten(StringShape(subject)); subject->TryFlattenIfNotFlat(StringShape(subject));
return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
} }
...@@ -2277,7 +2277,7 @@ static Object* Runtime_URIEscape(Arguments args) { ...@@ -2277,7 +2277,7 @@ static Object* Runtime_URIEscape(Arguments args) {
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]); CONVERT_CHECKED(String, source, args[0]);
source->TryFlatten(StringShape(source)); source->TryFlattenIfNotFlat(StringShape(source));
int escaped_length = 0; int escaped_length = 0;
int length = source->length(); int length = source->length();
...@@ -2391,7 +2391,7 @@ static Object* Runtime_URIUnescape(Arguments args) { ...@@ -2391,7 +2391,7 @@ static Object* Runtime_URIUnescape(Arguments args) {
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]); CONVERT_CHECKED(String, source, args[0]);
source->TryFlatten(StringShape(source)); source->TryFlattenIfNotFlat(StringShape(source));
StringShape source_shape(source); StringShape source_shape(source);
bool ascii = true; bool ascii = true;
...@@ -2440,7 +2440,7 @@ static Object* Runtime_StringParseInt(Arguments args) { ...@@ -2440,7 +2440,7 @@ static Object* Runtime_StringParseInt(Arguments args) {
CONVERT_DOUBLE_CHECKED(n, args[1]); CONVERT_DOUBLE_CHECKED(n, args[1]);
int radix = FastD2I(n); int radix = FastD2I(n);
s->TryFlatten(StringShape(s)); s->TryFlattenIfNotFlat(StringShape(s));
StringShape shape(s); StringShape shape(s);
...@@ -2513,7 +2513,7 @@ static Object* ConvertCase(Arguments args, ...@@ -2513,7 +2513,7 @@ static Object* ConvertCase(Arguments args,
NoHandleAllocation ha; NoHandleAllocation ha;
CONVERT_CHECKED(String, s, args[0]); CONVERT_CHECKED(String, s, args[0]);
s->TryFlatten(StringShape(s)); s->TryFlattenIfNotFlat(StringShape(s));
StringShape shape(s); StringShape shape(s);
int raw_string_length = s->length(shape); int raw_string_length = s->length(shape);
...@@ -3117,8 +3117,8 @@ static Object* Runtime_StringCompare(Arguments args) { ...@@ -3117,8 +3117,8 @@ static Object* Runtime_StringCompare(Arguments args) {
if (d < 0) return Smi::FromInt(LESS); if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER); else if (d > 0) return Smi::FromInt(GREATER);
x->TryFlatten(x_shape); // Shapes are no longer valid! x->TryFlattenIfNotFlat(x_shape); // Shapes are no longer valid!
y->TryFlatten(y_shape); y->TryFlattenIfNotFlat(y_shape);
static StringInputBuffer bufx; static StringInputBuffer bufx;
static StringInputBuffer bufy; static StringInputBuffer bufy;
......
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