ReplaceRegExpWithString: Avoid extending handle scope by adding scope inside loop.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1517 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2009-03-16 09:49:14 +00:00
parent 9149e4c8db
commit 014f0fd841

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved. // Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -1135,37 +1135,49 @@ class ReplacementStringBuilder {
ASSERT(estimated_part_count > 0); ASSERT(estimated_part_count > 0);
} }
void EnsureCapacity(int elements) {
int length = parts_->length();
int required_length = part_count_ + elements;
if (length < required_length) {
int new_length = length;
do {
new_length *= 2;
} while (new_length < required_length);
Handle<FixedArray> extended_array =
Factory::NewFixedArray(new_length);
parts_->CopyTo(0, *extended_array, 0, part_count_);
parts_ = extended_array;
}
}
void AddSubjectSlice(int from, int to) { void AddSubjectSlice(int from, int to) {
ASSERT(from >= 0); ASSERT(from >= 0);
int length = to - from; int length = to - from;
ASSERT(length >= 0); ASSERT(length > 0);
if (length > 0) { // Can we encode the slice in 11 bits for length and 19 bits for
// Can we encode the slice in 11 bits for length and 19 bits for // start position - as used by StringBuilderConcatHelper?
// start position - as used by StringBuilderConcatHelper? if (StringBuilderSubstringLength::is_valid(length) &&
if (StringBuilderSubstringLength::is_valid(length) && StringBuilderSubstringPosition::is_valid(from)) {
StringBuilderSubstringPosition::is_valid(from)) { int encoded_slice = StringBuilderSubstringLength::encode(length) |
int encoded_slice = StringBuilderSubstringLength::encode(length) | StringBuilderSubstringPosition::encode(from);
StringBuilderSubstringPosition::encode(from); AddElement(Smi::FromInt(encoded_slice));
AddElement(Handle<Object>(Smi::FromInt(encoded_slice))); } else {
} else { Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
Handle<String> slice = Factory::NewStringSlice(subject_, from, to); AddElement(*slice);
AddElement(slice);
}
IncrementCharacterCount(length);
} }
IncrementCharacterCount(length);
} }
void AddString(Handle<String> string) { void AddString(Handle<String> string) {
StringShape shape(*string); StringShape shape(*string);
int length = string->length(shape); int length = string->length(shape);
if (length > 0) { ASSERT(length > 0);
AddElement(string); AddElement(*string);
if (!shape.IsAsciiRepresentation()) { if (!shape.IsAsciiRepresentation()) {
is_ascii_ = false; is_ascii_ = false;
}
IncrementCharacterCount(length);
} }
IncrementCharacterCount(length);
} }
@ -1220,16 +1232,9 @@ class ReplacementStringBuilder {
} }
void AddElement(Handle<Object> element) { void AddElement(Object* element) {
ASSERT(element->IsSmi() || element->IsString()); ASSERT(element->IsSmi() || element->IsString());
// Extend parts_ array if necessary. parts_->set(part_count_, element);
if (parts_->length() == part_count_) {
Handle<FixedArray> extended_array =
Factory::NewFixedArray(part_count_ * 2);
parts_->CopyTo(0, *extended_array, 0, part_count_);
parts_ = extended_array;
}
parts_->set(part_count_, *element);
part_count_++; part_count_++;
} }
@ -1474,11 +1479,13 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
ReplacementPart part = parts_[i]; ReplacementPart part = parts_[i];
switch (part.tag) { switch (part.tag) {
case SUBJECT_PREFIX: case SUBJECT_PREFIX:
builder->AddSubjectSlice(0, match_from); if (match_from > 0) builder->AddSubjectSlice(0, match_from);
break; break;
case SUBJECT_SUFFIX: { case SUBJECT_SUFFIX: {
int subject_length = part.data; int subject_length = part.data;
builder->AddSubjectSlice(match_to, subject_length); if (match_to < subject_length) {
builder->AddSubjectSlice(match_to, subject_length);
}
break; break;
} }
case SUBJECT_CAPTURE: { case SUBJECT_CAPTURE: {
@ -1549,8 +1556,17 @@ static Object* StringReplaceRegExpWithString(String* subject,
// Index of end of last match. // Index of end of last match.
int prev = 0; int prev = 0;
// Number of parts added by compiled replacement plus preceeding string
// and possibly suffix after last match.
const int parts_added_per_loop = compiled_replacement.parts() + 2;
bool matched;
do { do {
ASSERT(last_match_info_handle->HasFastElements()); ASSERT(last_match_info_handle->HasFastElements());
// Increase the capacity of the builder before entering local handle-scope,
// so its internal buffer can safely allocate a new handle if it grows.
builder.EnsureCapacity(parts_added_per_loop);
HandleScope loop_scope;
int start, end; int start, end;
{ {
AssertNoAllocation match_info_array_is_not_in_a_handle; AssertNoAllocation match_info_array_is_not_in_a_handle;
@ -1588,7 +1604,8 @@ static Object* StringReplaceRegExpWithString(String* subject,
if (match.is_null()) { if (match.is_null()) {
return Failure::Exception(); return Failure::Exception();
} }
} while (!match->IsNull()); matched = !match->IsNull();
} while (matched);
if (prev < length) { if (prev < length) {
builder.AddSubjectSlice(prev, length); builder.AddSubjectSlice(prev, length);