Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(877)

Unified Diff: src/runtime.cc

Issue 9038: Create an abstraction for the string type flags so that they can be cached.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/runtime.cc
===================================================================
--- src/runtime.cc (revision 654)
+++ src/runtime.cc (working copy)
@@ -952,9 +952,12 @@
// 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
// accessed.
- subject->TryFlatten();
- if (i >= static_cast<uint32_t>(subject->length())) return Heap::nan_value();
- return Smi::FromInt(subject->Get(i));
+ StringShape shape(subject);
+ subject->TryFlatten(shape); // shape no longer valid!
+ if (i >= static_cast<uint32_t>(subject->length(StringShape(subject)))) {
+ return Heap::nan_value();
+ }
+ return Smi::FromInt(subject->Get(StringShape(subject), i));
}
@@ -1334,39 +1337,47 @@
Handle<String> pat,
int start_index) {
ASSERT(0 <= start_index);
- ASSERT(start_index <= sub->length());
+ StringShape sub_shape(*sub);
+ StringShape pat_shape(*pat);
+ ASSERT(start_index <= sub->length(sub_shape));
- int pattern_length = pat->length();
+ int pattern_length = pat->length(pat_shape);
if (pattern_length == 0) return start_index;
- int subject_length = sub->length();
+ int subject_length = sub->length(sub_shape);
if (start_index + pattern_length > subject_length) return -1;
- FlattenString(sub);
+ if (!sub->IsFlat(sub_shape)) {
+ FlattenString(sub);
+ sub_shape = StringShape(*sub);
+ }
// Searching for one specific character is common. For one
// character patterns linear search is necessary, so any smart
// algorithm is unnecessary overhead.
if (pattern_length == 1) {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
- if (sub->is_ascii_representation()) {
- return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(0), start_index);
+ if (sub_shape.IsAsciiRepresentation()) {
+ return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(pat_shape, 0), start_index);
}
- return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
+ return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(pat_shape, 0), start_index);
}
- FlattenString(pat);
+ if (!pat->IsFlat(pat_shape)) {
+ FlattenString(pat);
+ pat_shape = StringShape(*pat);
+ }
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
// dispatch on type of strings
- if (pat->is_ascii_representation()) {
+ if (pat_shape.IsAsciiRepresentation()) {
Vector<const char> pat_vector = pat->ToAsciiVector();
- if (sub->is_ascii_representation()) {
+ if (sub_shape.IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
}
Vector<const uc16> pat_vector = pat->ToUC16Vector();
- if (sub->is_ascii_representation()) {
+ if (sub_shape.IsAsciiRepresentation()) {
return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
}
return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
@@ -1397,14 +1408,17 @@
CONVERT_CHECKED(String, pat, args[1]);
Object* index = args[2];
- sub->TryFlatten();
- pat->TryFlatten();
+ sub->TryFlatten(StringShape(sub));
+ pat->TryFlatten(StringShape(pat));
+ StringShape sub_shape(sub);
+ StringShape pat_shape(pat);
+
uint32_t start_index;
if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
- uint32_t pattern_length = pat->length();
- uint32_t sub_length = sub->length();
+ uint32_t pattern_length = pat->length(pat_shape);
+ uint32_t sub_length = sub->length(sub_shape);
if (start_index + pattern_length > sub_length) {
start_index = sub_length - pattern_length;
@@ -1413,7 +1427,7 @@
for (int i = start_index; i >= 0; i--) {
bool found = true;
for (uint32_t j = 0; j < pattern_length; j++) {
- if (sub->Get(i + j) != pat->Get(j)) {
+ if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) {
found = false;
break;
}
@@ -1433,8 +1447,10 @@
CONVERT_CHECKED(String, str2, args[1]);
if (str1 == str2) return Smi::FromInt(0); // Equal.
- int str1_length = str1->length();
- int str2_length = str2->length();
+ StringShape shape1(str1);
+ StringShape shape2(str2);
+ int str1_length = str1->length(shape1);
+ int str2_length = str2->length(shape2);
// Decide trivial cases without flattening.
if (str1_length == 0) {
@@ -1449,11 +1465,11 @@
// No need to flatten if we are going to find the answer on the first
// character. At this point we know there is at least one character
// in each string, due to the trivial case handling above.
- int d = str1->Get(0) - str2->Get(0);
+ int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
if (d != 0) return Smi::FromInt(d);
- str1->TryFlatten();
- str2->TryFlatten();
+ str1->TryFlatten(shape1); // Shapes are no longer valid now!
+ str2->TryFlatten(shape2);
static StringInputBuffer buf1;
static StringInputBuffer buf2;
@@ -1482,10 +1498,12 @@
int start = FastD2I(from_number);
int end = FastD2I(to_number);
+ StringShape shape(value);
+
RUNTIME_ASSERT(end >= start);
RUNTIME_ASSERT(start >= 0);
- RUNTIME_ASSERT(end <= value->length());
- return value->Slice(start, end);
+ RUNTIME_ASSERT(end <= value->length(shape));
+ return value->Slice(shape, start, end);
}
@@ -1588,9 +1606,11 @@
// Returns a single character string where first character equals
// string->Get(index).
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
- if (index < static_cast<uint32_t>(string->length())) {
- string->TryFlatten();
- return LookupSingleCharacterStringFromCode(string->Get(index));
+ StringShape shape(*string);
+ if (index < static_cast<uint32_t>(string->length(shape))) {
+ string->TryFlatten(shape); // Invalidates shape!
+ return LookupSingleCharacterStringFromCode(
+ string->Get(StringShape(*string), index));
}
return Execution::CharAt(string, index);
}
@@ -1775,7 +1795,7 @@
result = SetElement(js_object, index, value);
} else {
Handle<String> key_string = Handle<String>::cast(key);
- key_string->TryFlatten();
+ key_string->TryFlatten(StringShape(*key_string));
result = SetProperty(js_object, key_string, value, attr);
}
if (result.is_null()) return Failure::Exception();
@@ -1866,7 +1886,8 @@
uint32_t index;
if (key->AsArrayIndex(&index)) {
String* string = String::cast(args[0]);
- if (index < static_cast<uint32_t>(string->length()))
+ StringShape shape(string);
+ if (index < static_cast<uint32_t>(string->length(shape)))
return Heap::true_value();
}
}
@@ -2049,7 +2070,7 @@
NoHandleAllocation ha;
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, subject, args[0]);
- subject->TryFlatten();
+ subject->TryFlatten(StringShape(subject));
return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
}
@@ -2079,10 +2100,11 @@
if (object->IsFailure()) return object;
String* result = String::cast(object);
+ StringShape result_shape(result);
for (int i = 0; i < length; i++) {
Object* element = codes->GetElement(i);
CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
- result->Set(i, chr & 0xffff);
+ result->Set(result_shape, i, chr & 0xffff);
}
return result;
}
@@ -2131,10 +2153,11 @@
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]);
- source->TryFlatten();
+ source->TryFlatten(StringShape(source));
+ StringShape sshape(source);
Mads Ager (chromium) 2008/11/03 08:45:49 How about source_shape?
int escaped_length = 0;
- int length = source->length();
+ int length = source->length(sshape);
{
Access<StringInputBuffer> buffer(&string_input_buffer);
buffer->Reset(source);
@@ -2161,27 +2184,28 @@
Object* o = Heap::AllocateRawAsciiString(escaped_length);
if (o->IsFailure()) return o;
String* destination = String::cast(o);
+ StringShape dshape(destination);
Mads Ager (chromium) 2008/11/03 08:45:49 dest_shape or even destination_shape?
Erik Corry 2008/11/03 09:33:54 I changed the other one, but I left this in, becau
int dest_position = 0;
Access<StringInputBuffer> buffer(&string_input_buffer);
buffer->Rewind();
while (buffer->has_more()) {
- uint16_t character = buffer->GetNext();
- if (character >= 256) {
- destination->Set(dest_position, '%');
- destination->Set(dest_position+1, 'u');
- destination->Set(dest_position+2, hex_chars[character >> 12]);
- destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]);
- destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]);
- destination->Set(dest_position+5, hex_chars[character & 0xf]);
+ uint16_t chr = buffer->GetNext();
+ if (chr >= 256) {
+ destination->Set(dshape, dest_position, '%');
+ destination->Set(dshape, dest_position+1, 'u');
+ destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]);
+ destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]);
+ destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]);
+ destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]);
dest_position += 6;
- } else if (IsNotEscaped(character)) {
- destination->Set(dest_position, character);
+ } else if (IsNotEscaped(chr)) {
+ destination->Set(dshape, dest_position, chr);
dest_position++;
} else {
- destination->Set(dest_position, '%');
- destination->Set(dest_position+1, hex_chars[character >> 4]);
- destination->Set(dest_position+2, hex_chars[character & 0xf]);
+ destination->Set(dshape, dest_position, '%');
+ destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]);
+ destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]);
dest_position += 3;
}
}
@@ -2209,19 +2233,26 @@
}
-static inline int Unescape(String* source, int i, int length, int* step) {
- uint16_t character = source->Get(i);
+static inline int Unescape(String* source,
+ StringShape shape,
+ int i,
+ int length,
+ int* step) {
+ uint16_t character = source->Get(shape, i);
int32_t hi, lo;
if (character == '%' &&
i <= length - 6 &&
- source->Get(i + 1) == 'u' &&
- (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 &&
- (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) {
+ source->Get(shape, i + 1) == 'u' &&
+ (hi = TwoDigitHex(source->Get(shape, i + 2),
+ source->Get(shape, i + 3))) != -1 &&
+ (lo = TwoDigitHex(source->Get(shape, i + 4),
+ source->Get(shape, i + 5))) != -1) {
*step = 6;
return (hi << 8) + lo;
} else if (character == '%' &&
i <= length - 3 &&
- (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) {
+ (lo = TwoDigitHex(source->Get(shape, i + 1),
+ source->Get(shape, i + 2))) != -1) {
*step = 3;
return lo;
} else {
@@ -2236,15 +2267,16 @@
ASSERT(args.length() == 1);
CONVERT_CHECKED(String, source, args[0]);
- source->TryFlatten();
+ source->TryFlatten(StringShape(source));
+ StringShape sshape(source);
Mads Ager (chromium) 2008/11/03 08:45:49 source_shape?
bool ascii = true;
- int length = source->length();
+ int length = source->length(sshape);
int unescaped_length = 0;
for (int i = 0; i < length; unescaped_length++) {
int step;
- if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode)
+ if (Unescape(source, sshape, i, length, &step) > String::kMaxAsciiCharCode)
ascii = false;
i += step;
}
@@ -2258,11 +2290,14 @@
Heap::AllocateRawTwoByteString(unescaped_length);
if (o->IsFailure()) return o;
String* destination = String::cast(o);
+ StringShape dshape(destination);
Mads Ager (chromium) 2008/11/03 08:45:49 destination_shape?
int dest_position = 0;
for (int i = 0; i < length; dest_position++) {
int step;
- destination->Set(dest_position, Unescape(source, i, length, &step));
+ destination->Set(dshape,
+ dest_position,
+ Unescape(source, sshape, i, length, &step));
i += step;
}
return destination;
@@ -2276,31 +2311,33 @@
CONVERT_DOUBLE_CHECKED(n, args[1]);
int radix = FastD2I(n);
- s->TryFlatten();
+ s->TryFlatten(StringShape(s));
- int len = s->length();
+ StringShape shape(s);
+
+ int len = s->length(shape);
int i;
// Skip leading white space.
- for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
+ for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ;
if (i == len) return Heap::nan_value();
// Compute the sign (default to +).
int sign = 1;
- if (s->Get(i) == '-') {
+ if (s->Get(shape, i) == '-') {
sign = -1;
i++;
- } else if (s->Get(i) == '+') {
+ } else if (s->Get(shape, i) == '+') {
i++;
}
// Compute the radix if 0.
if (radix == 0) {
radix = 10;
- if (i < len && s->Get(i) == '0') {
+ if (i < len && s->Get(shape, i) == '0') {
radix = 8;
if (i + 1 < len) {
- int c = s->Get(i + 1);
+ int c = s->Get(shape, i + 1);
if (c == 'x' || c == 'X') {
radix = 16;
i += 2;
@@ -2309,8 +2346,8 @@
}
} else if (radix == 16) {
// Allow 0x or 0X prefix if radix is 16.
- if (i + 1 < len && s->Get(i) == '0') {
- int c = s->Get(i + 1);
+ if (i + 1 < len && s->Get(shape, i) == '0') {
+ int c = s->Get(shape, i + 1);
if (c == 'x' || c == 'X') i += 2;
}
}
@@ -2347,12 +2384,14 @@
NoHandleAllocation ha;
CONVERT_CHECKED(String, s, args[0]);
- int raw_string_length = s->length();
+ s->TryFlatten(StringShape(s));
+ StringShape shape(s);
+
+ int raw_string_length = s->length(shape);
// Assume that the string is not empty; we need this assumption later
if (raw_string_length == 0) return s;
int length = raw_string_length;
- s->TryFlatten();
// We try this twice, once with the assumption that the result is
// no longer than the input and, if that assumption breaks, again
@@ -2368,11 +2407,12 @@
// character is also ascii. This is currently the case, but it
// might break in the future if we implement more context and locale
// dependent upper/lower conversions.
- Object* o = s->IsAsciiRepresentation()
+ Object* o = shape.IsAsciiRepresentation()
? Heap::AllocateRawAsciiString(length)
: Heap::AllocateRawTwoByteString(length);
if (o->IsFailure()) return o;
String* result = String::cast(o);
+ StringShape result_shape(result);
bool has_changed_character = false;
// Convert all characters to upper case, assuming that they will fit
@@ -2389,12 +2429,12 @@
int char_length = mapping->get(current, next, chars);
if (char_length == 0) {
// The case conversion of this character is the character itself.
- result->Set(i, current);
+ result->Set(result_shape, i, current);
i++;
} else if (char_length == 1) {
// Common case: converting the letter resulted in one character.
ASSERT(static_cast<uc32>(chars[0]) != current);
- result->Set(i, chars[0]);
+ result->Set(result_shape, i, chars[0]);
has_changed_character = true;
i++;
} else if (length == raw_string_length) {
@@ -2429,7 +2469,7 @@
goto try_convert;
} else {
for (int j = 0; j < char_length; j++) {
- result->Set(i, chars[j]);
+ result->Set(result_shape, i, chars[j]);
i++;
}
has_changed_character = true;
@@ -2613,8 +2653,10 @@
CONVERT_CHECKED(String, str1, args[0]);
CONVERT_CHECKED(String, str2, args[1]);
- int len1 = str1->length();
- int len2 = str2->length();
+ StringShape shape1(str1);
+ StringShape shape2(str2);
+ int len1 = str1->length(shape1);
+ int len2 = str2->length(shape2);
if (len1 == 0) return str2;
if (len2 == 0) return str1;
int length_sum = len1 + len2;
@@ -2624,12 +2666,13 @@
Top::context()->mark_out_of_memory();
return Failure::OutOfMemoryException();
}
- return Heap::AllocateConsString(str1, str2);
+ return Heap::AllocateConsString(str1, shape1, str2, shape2);
}
template<typename sinkchar>
static inline void StringBuilderConcatHelper(String* special,
+ StringShape special_shape,
sinkchar* sink,
FixedArray* fixed_array,
int array_length) {
@@ -2640,12 +2683,17 @@
int len = Smi::cast(element)->value();
int pos = len >> 11;
len &= 0x7ff;
- String::WriteToFlat(special, sink + position, pos, pos + len);
+ String::WriteToFlat(special,
+ special_shape,
+ sink + position,
+ pos,
+ pos + len);
position += len;
} else {
String* string = String::cast(element);
- int element_length = string->length();
- String::WriteToFlat(string, sink + position, 0, element_length);
+ StringShape shape(string);
+ int element_length = string->length(shape);
+ String::WriteToFlat(string, shape, sink + position, 0, element_length);
position += element_length;
}
}
@@ -2657,7 +2705,8 @@
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSArray, array, args[0]);
CONVERT_CHECKED(String, special, args[1]);
- int special_length = special->length();
+ StringShape special_shape(special);
+ int special_length = special->length(special_shape);
Object* smi_array_length = array->length();
if (!smi_array_length->IsSmi()) {
Top::context()->mark_out_of_memory();
@@ -2679,7 +2728,7 @@
if (first->IsString()) return first;
}
- bool ascii = special->IsAsciiRepresentation();
+ bool ascii = special_shape.IsAsciiRepresentation();
int position = 0;
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
@@ -2693,13 +2742,14 @@
position += len;
} else if (elt->IsString()) {
String* element = String::cast(elt);
- int element_length = element->length();
+ StringShape element_shape(element);
+ int element_length = element->length(element_shape);
if (!Smi::IsValid(element_length + position)) {
Top::context()->mark_out_of_memory();
return Failure::OutOfMemoryException();
}
position += element_length;
- if (ascii && !element->IsAsciiRepresentation()) {
+ if (ascii && !element_shape.IsAsciiRepresentation()) {
ascii = false;
}
} else {
@@ -2715,6 +2765,7 @@
if (object->IsFailure()) return object;
SeqAsciiString* answer = SeqAsciiString::cast(object);
StringBuilderConcatHelper(special,
+ special_shape,
answer->GetChars(),
fixed_array,
array_length);
@@ -2724,6 +2775,7 @@
if (object->IsFailure()) return object;
SeqTwoByteString* answer = SeqTwoByteString::cast(object);
StringBuilderConcatHelper(special,
+ special_shape,
answer->GetChars(),
fixed_array,
array_length);
@@ -2918,21 +2970,24 @@
CONVERT_CHECKED(String, x, args[0]);
CONVERT_CHECKED(String, y, args[1]);
+ StringShape x_shape(x);
+ StringShape y_shape(y);
+
// A few fast case tests before we flatten.
if (x == y) return Smi::FromInt(EQUAL);
- if (y->length() == 0) {
- if (x->length() == 0) return Smi::FromInt(EQUAL);
+ if (y->length(y_shape) == 0) {
+ if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL);
return Smi::FromInt(GREATER);
- } else if (x->length() == 0) {
+ } else if (x->length(x_shape) == 0) {
return Smi::FromInt(LESS);
}
- int d = x->Get(0) - y->Get(0);
+ int d = x->Get(x_shape, 0) - y->Get(y_shape, 0);
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
- x->TryFlatten();
- y->TryFlatten();
+ x->TryFlatten(x_shape); // Shapes are no longer valid!
+ y->TryFlatten(y_shape);
static StringInputBuffer bufx;
static StringInputBuffer bufy;
« src/objects-inl.h ('K') | « src/property.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698