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
// modification, are permitted provided that the following conditions are
// met:
@ -1135,37 +1135,49 @@ class ReplacementStringBuilder {
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) {
ASSERT(from >= 0);
int length = to - from;
ASSERT(length >= 0);
if (length > 0) {
// Can we encode the slice in 11 bits for length and 19 bits for
// start position - as used by StringBuilderConcatHelper?
if (StringBuilderSubstringLength::is_valid(length) &&
StringBuilderSubstringPosition::is_valid(from)) {
int encoded_slice = StringBuilderSubstringLength::encode(length) |
StringBuilderSubstringPosition::encode(from);
AddElement(Handle<Object>(Smi::FromInt(encoded_slice)));
} else {
Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
AddElement(slice);
}
IncrementCharacterCount(length);
ASSERT(length > 0);
// Can we encode the slice in 11 bits for length and 19 bits for
// start position - as used by StringBuilderConcatHelper?
if (StringBuilderSubstringLength::is_valid(length) &&
StringBuilderSubstringPosition::is_valid(from)) {
int encoded_slice = StringBuilderSubstringLength::encode(length) |
StringBuilderSubstringPosition::encode(from);
AddElement(Smi::FromInt(encoded_slice));
} else {
Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
AddElement(*slice);
}
IncrementCharacterCount(length);
}
void AddString(Handle<String> string) {
StringShape shape(*string);
int length = string->length(shape);
if (length > 0) {
AddElement(string);
if (!shape.IsAsciiRepresentation()) {
is_ascii_ = false;
}
IncrementCharacterCount(length);
ASSERT(length > 0);
AddElement(*string);
if (!shape.IsAsciiRepresentation()) {
is_ascii_ = false;
}
IncrementCharacterCount(length);
}
@ -1220,16 +1232,9 @@ class ReplacementStringBuilder {
}
void AddElement(Handle<Object> element) {
void AddElement(Object* element) {
ASSERT(element->IsSmi() || element->IsString());
// Extend parts_ array if necessary.
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);
parts_->set(part_count_, element);
part_count_++;
}
@ -1474,11 +1479,13 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
ReplacementPart part = parts_[i];
switch (part.tag) {
case SUBJECT_PREFIX:
builder->AddSubjectSlice(0, match_from);
if (match_from > 0) builder->AddSubjectSlice(0, match_from);
break;
case SUBJECT_SUFFIX: {
int subject_length = part.data;
builder->AddSubjectSlice(match_to, subject_length);
if (match_to < subject_length) {
builder->AddSubjectSlice(match_to, subject_length);
}
break;
}
case SUBJECT_CAPTURE: {
@ -1549,8 +1556,17 @@ static Object* StringReplaceRegExpWithString(String* subject,
// Index of end of last match.
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 {
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;
{
AssertNoAllocation match_info_array_is_not_in_a_handle;
@ -1588,7 +1604,8 @@ static Object* StringReplaceRegExpWithString(String* subject,
if (match.is_null()) {
return Failure::Exception();
}
} while (!match->IsNull());
matched = !match->IsNull();
} while (matched);
if (prev < length) {
builder.AddSubjectSlice(prev, length);