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

Side by Side Diff: src/runtime.cc

Issue 45010: Remove all uses of StringShape variables, since that has proven... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 9 months 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/regexp-macro-assembler-ia32.cc ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 return *target; 1070 return *target;
1071 } 1071 }
1072 1072
1073 1073
1074 static Object* CharCodeAt(String* subject, Object* index) { 1074 static Object* CharCodeAt(String* subject, Object* index) {
1075 uint32_t i = 0; 1075 uint32_t i = 0;
1076 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value(); 1076 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
1077 // Flatten the string. If someone wants to get a char at an index 1077 // Flatten the string. If someone wants to get a char at an index
1078 // in a cons string, it is likely that more indices will be 1078 // in a cons string, it is likely that more indices will be
1079 // accessed. 1079 // accessed.
1080 subject->TryFlattenIfNotFlat(StringShape(subject)); 1080 subject->TryFlattenIfNotFlat();
1081 StringShape shape(subject); 1081 if (i >= static_cast<uint32_t>(subject->length())) {
1082 if (i >= static_cast<uint32_t>(subject->length(shape))) {
1083 return Heap::nan_value(); 1082 return Heap::nan_value();
1084 } 1083 }
1085 return Smi::FromInt(subject->Get(shape, i)); 1084 return Smi::FromInt(subject->Get(i));
1086 } 1085 }
1087 1086
1088 1087
1089 static Object* Runtime_StringCharCodeAt(Arguments args) { 1088 static Object* Runtime_StringCharCodeAt(Arguments args) {
1090 NoHandleAllocation ha; 1089 NoHandleAllocation ha;
1091 ASSERT(args.length() == 2); 1090 ASSERT(args.length() == 2);
1092 1091
1093 CONVERT_CHECKED(String, subject, args[0]); 1092 CONVERT_CHECKED(String, subject, args[0]);
1094 Object* index = args[1]; 1093 Object* index = args[1];
1095 return CharCodeAt(subject, index); 1094 return CharCodeAt(subject, index);
(...skipping 11 matching lines...) Expand all
1107 } 1106 }
1108 return Heap::empty_string(); 1107 return Heap::empty_string();
1109 } 1108 }
1110 1109
1111 // Forward declarations. 1110 // Forward declarations.
1112 static const int kStringBuilderConcatHelperLengthBits = 11; 1111 static const int kStringBuilderConcatHelperLengthBits = 11;
1113 static const int kStringBuilderConcatHelperPositionBits = 19; 1112 static const int kStringBuilderConcatHelperPositionBits = 19;
1114 1113
1115 template <typename schar> 1114 template <typename schar>
1116 static inline void StringBuilderConcatHelper(String*, 1115 static inline void StringBuilderConcatHelper(String*,
1117 StringShape,
1118 schar*, 1116 schar*,
1119 FixedArray*, 1117 FixedArray*,
1120 int); 1118 int);
1121 1119
1122 typedef BitField<int, 0, 11> StringBuilderSubstringLength; 1120 typedef BitField<int, 0, 11> StringBuilderSubstringLength;
1123 typedef BitField<int, 11, 19> StringBuilderSubstringPosition; 1121 typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
1124 1122
1125 class ReplacementStringBuilder { 1123 class ReplacementStringBuilder {
1126 public: 1124 public:
1127 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count) 1125 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 AddElement(Smi::FromInt(encoded_slice)); 1161 AddElement(Smi::FromInt(encoded_slice));
1164 } else { 1162 } else {
1165 Handle<String> slice = Factory::NewStringSlice(subject_, from, to); 1163 Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
1166 AddElement(*slice); 1164 AddElement(*slice);
1167 } 1165 }
1168 IncrementCharacterCount(length); 1166 IncrementCharacterCount(length);
1169 } 1167 }
1170 1168
1171 1169
1172 void AddString(Handle<String> string) { 1170 void AddString(Handle<String> string) {
1173 StringShape shape(*string); 1171 int length = string->length();
1174 int length = string->length(shape);
1175 ASSERT(length > 0); 1172 ASSERT(length > 0);
1176 AddElement(*string); 1173 AddElement(*string);
1177 if (!shape.IsAsciiRepresentation()) { 1174 if (!StringShape(*string).IsAsciiRepresentation()) {
1178 is_ascii_ = false; 1175 is_ascii_ = false;
1179 } 1176 }
1180 IncrementCharacterCount(length); 1177 IncrementCharacterCount(length);
1181 } 1178 }
1182 1179
1183 1180
1184 Handle<String> ToString() { 1181 Handle<String> ToString() {
1185 if (part_count_ == 0) { 1182 if (part_count_ == 0) {
1186 return Factory::empty_string(); 1183 return Factory::empty_string();
1187 } 1184 }
1188 1185
1189 Handle<String> joined_string; 1186 Handle<String> joined_string;
1190 if (is_ascii_) { 1187 if (is_ascii_) {
1191 joined_string = NewRawAsciiString(character_count_); 1188 joined_string = NewRawAsciiString(character_count_);
1192 AssertNoAllocation no_alloc; 1189 AssertNoAllocation no_alloc;
1193 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); 1190 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1194 char* char_buffer = seq->GetChars(); 1191 char* char_buffer = seq->GetChars();
1195 StringBuilderConcatHelper(*subject_, 1192 StringBuilderConcatHelper(*subject_,
1196 StringShape(*subject_),
1197 char_buffer, 1193 char_buffer,
1198 *parts_, 1194 *parts_,
1199 part_count_); 1195 part_count_);
1200 } else { 1196 } else {
1201 // Non-ASCII. 1197 // Non-ASCII.
1202 joined_string = NewRawTwoByteString(character_count_); 1198 joined_string = NewRawTwoByteString(character_count_);
1203 AssertNoAllocation no_alloc; 1199 AssertNoAllocation no_alloc;
1204 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); 1200 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1205 uc16* char_buffer = seq->GetChars(); 1201 uc16* char_buffer = seq->GetChars();
1206 StringBuilderConcatHelper(*subject_, 1202 StringBuilderConcatHelper(*subject_,
1207 StringShape(*subject_),
1208 char_buffer, 1203 char_buffer,
1209 *parts_, 1204 *parts_,
1210 part_count_); 1205 part_count_);
1211 } 1206 }
1212 return joined_string; 1207 return joined_string;
1213 } 1208 }
1214 1209
1215 1210
1216 void IncrementCharacterCount(int by) { 1211 void IncrementCharacterCount(int by) {
1217 if (character_count_ > Smi::kMaxValue - by) { 1212 if (character_count_ > Smi::kMaxValue - by) {
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 } 1420 }
1426 1421
1427 ZoneList<ReplacementPart> parts_; 1422 ZoneList<ReplacementPart> parts_;
1428 ZoneList<Handle<String> > replacement_substrings_; 1423 ZoneList<Handle<String> > replacement_substrings_;
1429 }; 1424 };
1430 1425
1431 1426
1432 void CompiledReplacement::Compile(Handle<String> replacement, 1427 void CompiledReplacement::Compile(Handle<String> replacement,
1433 int capture_count, 1428 int capture_count,
1434 int subject_length) { 1429 int subject_length) {
1435 StringShape shape(*replacement); 1430 ASSERT(replacement->IsFlat());
1436 ASSERT(replacement->IsFlat(shape)); 1431 if (StringShape(*replacement).IsAsciiRepresentation()) {
1437 if (shape.IsAsciiRepresentation()) {
1438 AssertNoAllocation no_alloc; 1432 AssertNoAllocation no_alloc;
1439 ParseReplacementPattern(&parts_, 1433 ParseReplacementPattern(&parts_,
1440 replacement->ToAsciiVector(), 1434 replacement->ToAsciiVector(),
1441 capture_count, 1435 capture_count,
1442 subject_length); 1436 subject_length);
1443 } else { 1437 } else {
1444 ASSERT(shape.IsTwoByteRepresentation()); 1438 ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
1445 AssertNoAllocation no_alloc; 1439 AssertNoAllocation no_alloc;
1446 1440
1447 ParseReplacementPattern(&parts_, 1441 ParseReplacementPattern(&parts_,
1448 replacement->ToUC16Vector(), 1442 replacement->ToUC16Vector(),
1449 capture_count, 1443 capture_count,
1450 subject_length); 1444 subject_length);
1451 } 1445 }
1452 // Find substrings of replacement string and create them as String objects.. 1446 // Find substrings of replacement string and create them as String objects..
1453 int substring_index = 0; 1447 int substring_index = 0;
1454 for (int i = 0, n = parts_.length(); i < n; i++) { 1448 for (int i = 0, n = parts_.length(); i < n; i++) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1507 } 1501 }
1508 } 1502 }
1509 } 1503 }
1510 1504
1511 1505
1512 1506
1513 static Object* StringReplaceRegExpWithString(String* subject, 1507 static Object* StringReplaceRegExpWithString(String* subject,
1514 JSRegExp* regexp, 1508 JSRegExp* regexp,
1515 String* replacement, 1509 String* replacement,
1516 JSArray* last_match_info) { 1510 JSArray* last_match_info) {
1517 ASSERT(subject->IsFlat(StringShape(subject))); 1511 ASSERT(subject->IsFlat());
1518 ASSERT(replacement->IsFlat(StringShape(replacement))); 1512 ASSERT(replacement->IsFlat());
1519 1513
1520 HandleScope handles; 1514 HandleScope handles;
1521 1515
1522 int length = subject->length(); 1516 int length = subject->length();
1523 Handle<String> subject_handle(subject); 1517 Handle<String> subject_handle(subject);
1524 Handle<JSRegExp> regexp_handle(regexp); 1518 Handle<JSRegExp> regexp_handle(regexp);
1525 Handle<String> replacement_handle(replacement); 1519 Handle<String> replacement_handle(replacement);
1526 Handle<JSArray> last_match_info_handle(last_match_info); 1520 Handle<JSArray> last_match_info_handle(last_match_info);
1527 Handle<Object> match = RegExpImpl::Exec(regexp_handle, 1521 Handle<Object> match = RegExpImpl::Exec(regexp_handle,
1528 subject_handle, 1522 subject_handle,
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1612 } 1606 }
1613 1607
1614 return *(builder.ToString()); 1608 return *(builder.ToString());
1615 } 1609 }
1616 1610
1617 1611
1618 static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { 1612 static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
1619 ASSERT(args.length() == 4); 1613 ASSERT(args.length() == 4);
1620 1614
1621 CONVERT_CHECKED(String, subject, args[0]); 1615 CONVERT_CHECKED(String, subject, args[0]);
1622 StringShape subject_shape(subject); 1616 if (!subject->IsFlat()) {
1623 if (!subject->IsFlat(subject_shape)) { 1617 Object* flat_subject = subject->TryFlatten();
1624 Object* flat_subject = subject->TryFlatten(subject_shape);
1625 if (flat_subject->IsFailure()) { 1618 if (flat_subject->IsFailure()) {
1626 return flat_subject; 1619 return flat_subject;
1627 } 1620 }
1628 subject = String::cast(flat_subject); 1621 subject = String::cast(flat_subject);
1629 } 1622 }
1630 1623
1631 CONVERT_CHECKED(String, replacement, args[2]); 1624 CONVERT_CHECKED(String, replacement, args[2]);
1632 StringShape replacement_shape(replacement); 1625 if (!replacement->IsFlat()) {
1633 if (!replacement->IsFlat(replacement_shape)) { 1626 Object* flat_replacement = replacement->TryFlatten();
1634 Object* flat_replacement = replacement->TryFlatten(replacement_shape);
1635 if (flat_replacement->IsFailure()) { 1627 if (flat_replacement->IsFailure()) {
1636 return flat_replacement; 1628 return flat_replacement;
1637 } 1629 }
1638 replacement = String::cast(flat_replacement); 1630 replacement = String::cast(flat_replacement);
1639 } 1631 }
1640 1632
1641 CONVERT_CHECKED(JSRegExp, regexp, args[1]); 1633 CONVERT_CHECKED(JSRegExp, regexp, args[1]);
1642 CONVERT_CHECKED(JSArray, last_match_info, args[3]); 1634 CONVERT_CHECKED(JSArray, last_match_info, args[3]);
1643 1635
1644 ASSERT(last_match_info->HasFastElements()); 1636 ASSERT(last_match_info->HasFastElements());
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1995 return BoyerMooreIndexOf(sub, pat, idx); 1987 return BoyerMooreIndexOf(sub, pat, idx);
1996 } 1988 }
1997 1989
1998 // Perform string match of pattern on subject, starting at start index. 1990 // Perform string match of pattern on subject, starting at start index.
1999 // Caller must ensure that 0 <= start_index <= sub->length(), 1991 // Caller must ensure that 0 <= start_index <= sub->length(),
2000 // and should check that pat->length() + start_index <= sub->length() 1992 // and should check that pat->length() + start_index <= sub->length()
2001 int Runtime::StringMatch(Handle<String> sub, 1993 int Runtime::StringMatch(Handle<String> sub,
2002 Handle<String> pat, 1994 Handle<String> pat,
2003 int start_index) { 1995 int start_index) {
2004 ASSERT(0 <= start_index); 1996 ASSERT(0 <= start_index);
2005 StringShape sub_shape(*sub); 1997 ASSERT(start_index <= sub->length());
2006 ASSERT(start_index <= sub->length(sub_shape));
2007 1998
2008 int pattern_length = pat->length(); 1999 int pattern_length = pat->length();
2009 if (pattern_length == 0) return start_index; 2000 if (pattern_length == 0) return start_index;
2010 2001
2011 int subject_length = sub->length(sub_shape); 2002 int subject_length = sub->length();
2012 if (start_index + pattern_length > subject_length) return -1; 2003 if (start_index + pattern_length > subject_length) return -1;
2013 2004
2014 if (!sub->IsFlat(sub_shape)) { 2005 if (!sub->IsFlat()) {
2015 FlattenString(sub); 2006 FlattenString(sub);
2016 sub_shape = StringShape(*sub);
2017 } 2007 }
2018 StringShape pat_shape(*pat);
2019 // Searching for one specific character is common. For one 2008 // Searching for one specific character is common. For one
2020 // character patterns linear search is necessary, so any smart 2009 // character patterns linear search is necessary, so any smart
2021 // algorithm is unnecessary overhead. 2010 // algorithm is unnecessary overhead.
2022 if (pattern_length == 1) { 2011 if (pattern_length == 1) {
2023 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 2012 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
2024 if (sub_shape.IsAsciiRepresentation()) { 2013 if (StringShape(*sub).IsAsciiRepresentation()) {
2025 uc16 pchar = pat->Get(pat_shape, 0); 2014 uc16 pchar = pat->Get(0);
2026 if (pchar > String::kMaxAsciiCharCode) { 2015 if (pchar > String::kMaxAsciiCharCode) {
2027 return -1; 2016 return -1;
2028 } 2017 }
2029 Vector<const char> ascii_vector = 2018 Vector<const char> ascii_vector =
2030 sub->ToAsciiVector().SubVector(start_index, subject_length); 2019 sub->ToAsciiVector().SubVector(start_index, subject_length);
2031 const void* pos = memchr(ascii_vector.start(), 2020 const void* pos = memchr(ascii_vector.start(),
2032 static_cast<const char>(pchar), 2021 static_cast<const char>(pchar),
2033 static_cast<size_t>(ascii_vector.length())); 2022 static_cast<size_t>(ascii_vector.length()));
2034 if (pos == NULL) { 2023 if (pos == NULL) {
2035 return -1; 2024 return -1;
2036 } 2025 }
2037 return reinterpret_cast<const char*>(pos) - ascii_vector.start() 2026 return reinterpret_cast<const char*>(pos) - ascii_vector.start()
2038 + start_index; 2027 + start_index;
2039 } 2028 }
2040 return SingleCharIndexOf(sub->ToUC16Vector(), 2029 return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
2041 pat->Get(pat_shape, 0),
2042 start_index);
2043 } 2030 }
2044 2031
2045 if (!pat->IsFlat(pat_shape)) { 2032 if (!pat->IsFlat()) {
2046 FlattenString(pat); 2033 FlattenString(pat);
2047 pat_shape = StringShape(*pat);
2048 sub_shape = StringShape(*sub);
2049 } 2034 }
2050 2035
2051 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 2036 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
2052 // dispatch on type of strings 2037 // dispatch on type of strings
2053 if (pat_shape.IsAsciiRepresentation()) { 2038 if (StringShape(*pat).IsAsciiRepresentation()) {
2054 Vector<const char> pat_vector = pat->ToAsciiVector(); 2039 Vector<const char> pat_vector = pat->ToAsciiVector();
2055 if (sub_shape.IsAsciiRepresentation()) { 2040 if (StringShape(*sub).IsAsciiRepresentation()) {
2056 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 2041 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
2057 } 2042 }
2058 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 2043 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
2059 } 2044 }
2060 Vector<const uc16> pat_vector = pat->ToUC16Vector(); 2045 Vector<const uc16> pat_vector = pat->ToUC16Vector();
2061 if (sub_shape.IsAsciiRepresentation()) { 2046 if (StringShape(*sub).IsAsciiRepresentation()) {
2062 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 2047 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
2063 } 2048 }
2064 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 2049 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
2065 } 2050 }
2066 2051
2067 2052
2068 static Object* Runtime_StringIndexOf(Arguments args) { 2053 static Object* Runtime_StringIndexOf(Arguments args) {
2069 HandleScope scope; // create a new handle scope 2054 HandleScope scope; // create a new handle scope
2070 ASSERT(args.length() == 3); 2055 ASSERT(args.length() == 3);
2071 2056
(...skipping 11 matching lines...) Expand all
2083 2068
2084 2069
2085 static Object* Runtime_StringLastIndexOf(Arguments args) { 2070 static Object* Runtime_StringLastIndexOf(Arguments args) {
2086 NoHandleAllocation ha; 2071 NoHandleAllocation ha;
2087 ASSERT(args.length() == 3); 2072 ASSERT(args.length() == 3);
2088 2073
2089 CONVERT_CHECKED(String, sub, args[0]); 2074 CONVERT_CHECKED(String, sub, args[0]);
2090 CONVERT_CHECKED(String, pat, args[1]); 2075 CONVERT_CHECKED(String, pat, args[1]);
2091 Object* index = args[2]; 2076 Object* index = args[2];
2092 2077
2093 sub->TryFlattenIfNotFlat(StringShape(sub)); 2078 sub->TryFlattenIfNotFlat();
2094 pat->TryFlattenIfNotFlat(StringShape(pat)); 2079 pat->TryFlattenIfNotFlat();
2095
2096 StringShape sub_shape(sub);
2097 StringShape pat_shape(pat);
2098 2080
2099 uint32_t start_index; 2081 uint32_t start_index;
2100 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); 2082 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
2101 2083
2102 uint32_t pattern_length = pat->length(pat_shape); 2084 uint32_t pattern_length = pat->length();
2103 uint32_t sub_length = sub->length(sub_shape); 2085 uint32_t sub_length = sub->length();
2104 2086
2105 if (start_index + pattern_length > sub_length) { 2087 if (start_index + pattern_length > sub_length) {
2106 start_index = sub_length - pattern_length; 2088 start_index = sub_length - pattern_length;
2107 } 2089 }
2108 2090
2109 for (int i = start_index; i >= 0; i--) { 2091 for (int i = start_index; i >= 0; i--) {
2110 bool found = true; 2092 bool found = true;
2111 for (uint32_t j = 0; j < pattern_length; j++) { 2093 for (uint32_t j = 0; j < pattern_length; j++) {
2112 if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) { 2094 if (sub->Get(i + j) != pat->Get(j)) {
2113 found = false; 2095 found = false;
2114 break; 2096 break;
2115 } 2097 }
2116 } 2098 }
2117 if (found) return Smi::FromInt(i); 2099 if (found) return Smi::FromInt(i);
2118 } 2100 }
2119 2101
2120 return Smi::FromInt(-1); 2102 return Smi::FromInt(-1);
2121 } 2103 }
2122 2104
2123 2105
2124 static Object* Runtime_StringLocaleCompare(Arguments args) { 2106 static Object* Runtime_StringLocaleCompare(Arguments args) {
2125 NoHandleAllocation ha; 2107 NoHandleAllocation ha;
2126 ASSERT(args.length() == 2); 2108 ASSERT(args.length() == 2);
2127 2109
2128 CONVERT_CHECKED(String, str1, args[0]); 2110 CONVERT_CHECKED(String, str1, args[0]);
2129 CONVERT_CHECKED(String, str2, args[1]); 2111 CONVERT_CHECKED(String, str2, args[1]);
2130 2112
2131 if (str1 == str2) return Smi::FromInt(0); // Equal. 2113 if (str1 == str2) return Smi::FromInt(0); // Equal.
2132 StringShape shape1(str1); 2114 int str1_length = str1->length();
2133 StringShape shape2(str2); 2115 int str2_length = str2->length();
2134 int str1_length = str1->length(shape1);
2135 int str2_length = str2->length(shape2);
2136 2116
2137 // Decide trivial cases without flattening. 2117 // Decide trivial cases without flattening.
2138 if (str1_length == 0) { 2118 if (str1_length == 0) {
2139 if (str2_length == 0) return Smi::FromInt(0); // Equal. 2119 if (str2_length == 0) return Smi::FromInt(0); // Equal.
2140 return Smi::FromInt(-str2_length); 2120 return Smi::FromInt(-str2_length);
2141 } else { 2121 } else {
2142 if (str2_length == 0) return Smi::FromInt(str1_length); 2122 if (str2_length == 0) return Smi::FromInt(str1_length);
2143 } 2123 }
2144 2124
2145 int end = str1_length < str2_length ? str1_length : str2_length; 2125 int end = str1_length < str2_length ? str1_length : str2_length;
2146 2126
2147 // No need to flatten if we are going to find the answer on the first 2127 // No need to flatten if we are going to find the answer on the first
2148 // character. At this point we know there is at least one character 2128 // character. At this point we know there is at least one character
2149 // in each string, due to the trivial case handling above. 2129 // in each string, due to the trivial case handling above.
2150 int d = str1->Get(shape1, 0) - str2->Get(shape2, 0); 2130 int d = str1->Get(0) - str2->Get(0);
2151 if (d != 0) return Smi::FromInt(d); 2131 if (d != 0) return Smi::FromInt(d);
2152 2132
2153 str1->TryFlattenIfNotFlat(shape1); // Shapes are no longer valid now! 2133 str1->TryFlattenIfNotFlat();
2154 str2->TryFlattenIfNotFlat(shape2); 2134 str2->TryFlattenIfNotFlat();
2155 2135
2156 static StringInputBuffer buf1; 2136 static StringInputBuffer buf1;
2157 static StringInputBuffer buf2; 2137 static StringInputBuffer buf2;
2158 2138
2159 buf1.Reset(str1); 2139 buf1.Reset(str1);
2160 buf2.Reset(str2); 2140 buf2.Reset(str2);
2161 2141
2162 for (int i = 0; i < end; i++) { 2142 for (int i = 0; i < end; i++) {
2163 uint16_t char1 = buf1.GetNext(); 2143 uint16_t char1 = buf1.GetNext();
2164 uint16_t char2 = buf2.GetNext(); 2144 uint16_t char2 = buf2.GetNext();
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2279 char* str = DoubleToPrecisionCString(value, f); 2259 char* str = DoubleToPrecisionCString(value, f);
2280 Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); 2260 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
2281 DeleteArray(str); 2261 DeleteArray(str);
2282 return res; 2262 return res;
2283 } 2263 }
2284 2264
2285 2265
2286 // Returns a single character string where first character equals 2266 // Returns a single character string where first character equals
2287 // string->Get(index). 2267 // string->Get(index).
2288 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 2268 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
2289 StringShape shape(*string); 2269 if (index < static_cast<uint32_t>(string->length())) {
2290 if (index < static_cast<uint32_t>(string->length(shape))) { 2270 string->TryFlattenIfNotFlat();
2291 string->TryFlattenIfNotFlat(shape); // Invalidates shape!
2292 return LookupSingleCharacterStringFromCode( 2271 return LookupSingleCharacterStringFromCode(
2293 string->Get(StringShape(*string), index)); 2272 string->Get(index));
2294 } 2273 }
2295 return Execution::CharAt(string, index); 2274 return Execution::CharAt(string, index);
2296 } 2275 }
2297 2276
2298 2277
2299 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { 2278 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
2300 // Handle [] indexing on Strings 2279 // Handle [] indexing on Strings
2301 if (object->IsString()) { 2280 if (object->IsString()) {
2302 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 2281 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
2303 if (!result->IsUndefined()) return *result; 2282 if (!result->IsUndefined()) return *result;
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2474 return *value; 2453 return *value;
2475 } 2454 }
2476 2455
2477 if (key->IsString()) { 2456 if (key->IsString()) {
2478 Handle<Object> result; 2457 Handle<Object> result;
2479 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 2458 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
2480 ASSERT(attr == NONE); 2459 ASSERT(attr == NONE);
2481 result = SetElement(js_object, index, value); 2460 result = SetElement(js_object, index, value);
2482 } else { 2461 } else {
2483 Handle<String> key_string = Handle<String>::cast(key); 2462 Handle<String> key_string = Handle<String>::cast(key);
2484 key_string->TryFlattenIfNotFlat(StringShape(*key_string)); 2463 key_string->TryFlattenIfNotFlat();
2485 result = SetProperty(js_object, key_string, value, attr); 2464 result = SetProperty(js_object, key_string, value, attr);
2486 } 2465 }
2487 if (result.is_null()) return Failure::Exception(); 2466 if (result.is_null()) return Failure::Exception();
2488 return *value; 2467 return *value;
2489 } 2468 }
2490 2469
2491 // Call-back into JavaScript to convert the key to a string. 2470 // Call-back into JavaScript to convert the key to a string.
2492 bool has_pending_exception = false; 2471 bool has_pending_exception = false;
2493 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 2472 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
2494 if (has_pending_exception) return Failure::Exception(); 2473 if (has_pending_exception) return Failure::Exception();
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
2768 // host objects gives that it is okay to return "object" 2747 // host objects gives that it is okay to return "object"
2769 return Heap::object_symbol(); 2748 return Heap::object_symbol();
2770 } 2749 }
2771 } 2750 }
2772 2751
2773 2752
2774 static Object* Runtime_StringToNumber(Arguments args) { 2753 static Object* Runtime_StringToNumber(Arguments args) {
2775 NoHandleAllocation ha; 2754 NoHandleAllocation ha;
2776 ASSERT(args.length() == 1); 2755 ASSERT(args.length() == 1);
2777 CONVERT_CHECKED(String, subject, args[0]); 2756 CONVERT_CHECKED(String, subject, args[0]);
2778 subject->TryFlattenIfNotFlat(StringShape(subject)); 2757 subject->TryFlattenIfNotFlat();
2779 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); 2758 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
2780 } 2759 }
2781 2760
2782 2761
2783 static Object* Runtime_StringFromCharCodeArray(Arguments args) { 2762 static Object* Runtime_StringFromCharCodeArray(Arguments args) {
2784 NoHandleAllocation ha; 2763 NoHandleAllocation ha;
2785 ASSERT(args.length() == 1); 2764 ASSERT(args.length() == 1);
2786 2765
2787 CONVERT_CHECKED(JSArray, codes, args[0]); 2766 CONVERT_CHECKED(JSArray, codes, args[0]);
2788 int length = Smi::cast(codes->length())->value(); 2767 int length = Smi::cast(codes->length())->value();
2789 2768
2790 // Check if the string can be ASCII. 2769 // Check if the string can be ASCII.
2791 int i; 2770 int i;
2792 for (i = 0; i < length; i++) { 2771 for (i = 0; i < length; i++) {
2793 Object* element = codes->GetElement(i); 2772 Object* element = codes->GetElement(i);
2794 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2773 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2795 if ((chr & 0xffff) > String::kMaxAsciiCharCode) 2774 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
2796 break; 2775 break;
2797 } 2776 }
2798 2777
2799 Object* object = NULL; 2778 Object* object = NULL;
2800 if (i == length) { // The string is ASCII. 2779 if (i == length) { // The string is ASCII.
2801 object = Heap::AllocateRawAsciiString(length); 2780 object = Heap::AllocateRawAsciiString(length);
2802 } else { // The string is not ASCII. 2781 } else { // The string is not ASCII.
2803 object = Heap::AllocateRawTwoByteString(length); 2782 object = Heap::AllocateRawTwoByteString(length);
2804 } 2783 }
2805 2784
2806 if (object->IsFailure()) return object; 2785 if (object->IsFailure()) return object;
2807 String* result = String::cast(object); 2786 String* result = String::cast(object);
2808 StringShape result_shape(result);
2809 for (int i = 0; i < length; i++) { 2787 for (int i = 0; i < length; i++) {
2810 Object* element = codes->GetElement(i); 2788 Object* element = codes->GetElement(i);
2811 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2789 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2812 result->Set(result_shape, i, chr & 0xffff); 2790 result->Set(i, chr & 0xffff);
2813 } 2791 }
2814 return result; 2792 return result;
2815 } 2793 }
2816 2794
2817 2795
2818 // kNotEscaped is generated by the following: 2796 // kNotEscaped is generated by the following:
2819 // 2797 //
2820 // #!/bin/perl 2798 // #!/bin/perl
2821 // for (my $i = 0; $i < 256; $i++) { 2799 // for (my $i = 0; $i < 256; $i++) {
2822 // print "\n" if $i % 16 == 0; 2800 // print "\n" if $i % 16 == 0;
(...skipping 28 matching lines...) Expand all
2851 return kNotEscaped[character] != 0; 2829 return kNotEscaped[character] != 0;
2852 } 2830 }
2853 2831
2854 2832
2855 static Object* Runtime_URIEscape(Arguments args) { 2833 static Object* Runtime_URIEscape(Arguments args) {
2856 const char hex_chars[] = "0123456789ABCDEF"; 2834 const char hex_chars[] = "0123456789ABCDEF";
2857 NoHandleAllocation ha; 2835 NoHandleAllocation ha;
2858 ASSERT(args.length() == 1); 2836 ASSERT(args.length() == 1);
2859 CONVERT_CHECKED(String, source, args[0]); 2837 CONVERT_CHECKED(String, source, args[0]);
2860 2838
2861 source->TryFlattenIfNotFlat(StringShape(source)); 2839 source->TryFlattenIfNotFlat();
2862 2840
2863 int escaped_length = 0; 2841 int escaped_length = 0;
2864 int length = source->length(); 2842 int length = source->length();
2865 { 2843 {
2866 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); 2844 Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
2867 buffer->Reset(source); 2845 buffer->Reset(source);
2868 while (buffer->has_more()) { 2846 while (buffer->has_more()) {
2869 uint16_t character = buffer->GetNext(); 2847 uint16_t character = buffer->GetNext();
2870 if (character >= 256) { 2848 if (character >= 256) {
2871 escaped_length += 6; 2849 escaped_length += 6;
2872 } else if (IsNotEscaped(character)) { 2850 } else if (IsNotEscaped(character)) {
2873 escaped_length++; 2851 escaped_length++;
2874 } else { 2852 } else {
2875 escaped_length += 3; 2853 escaped_length += 3;
2876 } 2854 }
2877 // We don't allow strings that are longer than Smi range. 2855 // We don't allow strings that are longer than Smi range.
2878 if (!Smi::IsValid(escaped_length)) { 2856 if (!Smi::IsValid(escaped_length)) {
2879 Top::context()->mark_out_of_memory(); 2857 Top::context()->mark_out_of_memory();
2880 return Failure::OutOfMemoryException(); 2858 return Failure::OutOfMemoryException();
2881 } 2859 }
2882 } 2860 }
2883 } 2861 }
2884 // No length change implies no change. Return original string if no change. 2862 // No length change implies no change. Return original string if no change.
2885 if (escaped_length == length) { 2863 if (escaped_length == length) {
2886 return source; 2864 return source;
2887 } 2865 }
2888 Object* o = Heap::AllocateRawAsciiString(escaped_length); 2866 Object* o = Heap::AllocateRawAsciiString(escaped_length);
2889 if (o->IsFailure()) return o; 2867 if (o->IsFailure()) return o;
2890 String* destination = String::cast(o); 2868 String* destination = String::cast(o);
2891 StringShape dshape(destination);
2892 int dest_position = 0; 2869 int dest_position = 0;
2893 2870
2894 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); 2871 Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
2895 buffer->Rewind(); 2872 buffer->Rewind();
2896 while (buffer->has_more()) { 2873 while (buffer->has_more()) {
2897 uint16_t chr = buffer->GetNext(); 2874 uint16_t chr = buffer->GetNext();
2898 if (chr >= 256) { 2875 if (chr >= 256) {
2899 destination->Set(dshape, dest_position, '%'); 2876 destination->Set(dest_position, '%');
2900 destination->Set(dshape, dest_position+1, 'u'); 2877 destination->Set(dest_position+1, 'u');
2901 destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]); 2878 destination->Set(dest_position+2, hex_chars[chr >> 12]);
2902 destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]); 2879 destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
2903 destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]); 2880 destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
2904 destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]); 2881 destination->Set(dest_position+5, hex_chars[chr & 0xf]);
2905 dest_position += 6; 2882 dest_position += 6;
2906 } else if (IsNotEscaped(chr)) { 2883 } else if (IsNotEscaped(chr)) {
2907 destination->Set(dshape, dest_position, chr); 2884 destination->Set(dest_position, chr);
2908 dest_position++; 2885 dest_position++;
2909 } else { 2886 } else {
2910 destination->Set(dshape, dest_position, '%'); 2887 destination->Set(dest_position, '%');
2911 destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]); 2888 destination->Set(dest_position+1, hex_chars[chr >> 4]);
2912 destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]); 2889 destination->Set(dest_position+2, hex_chars[chr & 0xf]);
2913 dest_position += 3; 2890 dest_position += 3;
2914 } 2891 }
2915 } 2892 }
2916 return destination; 2893 return destination;
2917 } 2894 }
2918 2895
2919 2896
2920 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) { 2897 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
2921 static const signed char kHexValue['g'] = { 2898 static const signed char kHexValue['g'] = {
2922 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2899 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2923 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2900 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2924 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2901 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2925 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 2902 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
2926 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2903 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2927 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2904 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2928 -1, 10, 11, 12, 13, 14, 15 }; 2905 -1, 10, 11, 12, 13, 14, 15 };
2929 2906
2930 if (character1 > 'f') return -1; 2907 if (character1 > 'f') return -1;
2931 int hi = kHexValue[character1]; 2908 int hi = kHexValue[character1];
2932 if (hi == -1) return -1; 2909 if (hi == -1) return -1;
2933 if (character2 > 'f') return -1; 2910 if (character2 > 'f') return -1;
2934 int lo = kHexValue[character2]; 2911 int lo = kHexValue[character2];
2935 if (lo == -1) return -1; 2912 if (lo == -1) return -1;
2936 return (hi << 4) + lo; 2913 return (hi << 4) + lo;
2937 } 2914 }
2938 2915
2939 2916
2940 static inline int Unescape(String* source, 2917 static inline int Unescape(String* source,
2941 StringShape shape,
2942 int i, 2918 int i,
2943 int length, 2919 int length,
2944 int* step) { 2920 int* step) {
2945 uint16_t character = source->Get(shape, i); 2921 uint16_t character = source->Get(i);
2946 int32_t hi = 0; 2922 int32_t hi = 0;
2947 int32_t lo = 0; 2923 int32_t lo = 0;
2948 if (character == '%' && 2924 if (character == '%' &&
2949 i <= length - 6 && 2925 i <= length - 6 &&
2950 source->Get(shape, i + 1) == 'u' && 2926 source->Get(i + 1) == 'u' &&
2951 (hi = TwoDigitHex(source->Get(shape, i + 2), 2927 (hi = TwoDigitHex(source->Get(i + 2),
2952 source->Get(shape, i + 3))) != -1 && 2928 source->Get(i + 3))) != -1 &&
2953 (lo = TwoDigitHex(source->Get(shape, i + 4), 2929 (lo = TwoDigitHex(source->Get(i + 4),
2954 source->Get(shape, i + 5))) != -1) { 2930 source->Get(i + 5))) != -1) {
2955 *step = 6; 2931 *step = 6;
2956 return (hi << 8) + lo; 2932 return (hi << 8) + lo;
2957 } else if (character == '%' && 2933 } else if (character == '%' &&
2958 i <= length - 3 && 2934 i <= length - 3 &&
2959 (lo = TwoDigitHex(source->Get(shape, i + 1), 2935 (lo = TwoDigitHex(source->Get(i + 1),
2960 source->Get(shape, i + 2))) != -1) { 2936 source->Get(i + 2))) != -1) {
2961 *step = 3; 2937 *step = 3;
2962 return lo; 2938 return lo;
2963 } else { 2939 } else {
2964 *step = 1; 2940 *step = 1;
2965 return character; 2941 return character;
2966 } 2942 }
2967 } 2943 }
2968 2944
2969 2945
2970 static Object* Runtime_URIUnescape(Arguments args) { 2946 static Object* Runtime_URIUnescape(Arguments args) {
2971 NoHandleAllocation ha; 2947 NoHandleAllocation ha;
2972 ASSERT(args.length() == 1); 2948 ASSERT(args.length() == 1);
2973 CONVERT_CHECKED(String, source, args[0]); 2949 CONVERT_CHECKED(String, source, args[0]);
2974 2950
2975 source->TryFlattenIfNotFlat(StringShape(source)); 2951 source->TryFlattenIfNotFlat();
2976 StringShape source_shape(source);
2977 2952
2978 bool ascii = true; 2953 bool ascii = true;
2979 int length = source->length(source_shape); 2954 int length = source->length();
2980 2955
2981 int unescaped_length = 0; 2956 int unescaped_length = 0;
2982 for (int i = 0; i < length; unescaped_length++) { 2957 for (int i = 0; i < length; unescaped_length++) {
2983 int step; 2958 int step;
2984 if (Unescape(source, 2959 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
2985 source_shape,
2986 i,
2987 length,
2988 &step) >
2989 String::kMaxAsciiCharCode)
2990 ascii = false; 2960 ascii = false;
2961 }
2991 i += step; 2962 i += step;
2992 } 2963 }
2993 2964
2994 // No length change implies no change. Return original string if no change. 2965 // No length change implies no change. Return original string if no change.
2995 if (unescaped_length == length) 2966 if (unescaped_length == length)
2996 return source; 2967 return source;
2997 2968
2998 Object* o = ascii ? 2969 Object* o = ascii ?
2999 Heap::AllocateRawAsciiString(unescaped_length) : 2970 Heap::AllocateRawAsciiString(unescaped_length) :
3000 Heap::AllocateRawTwoByteString(unescaped_length); 2971 Heap::AllocateRawTwoByteString(unescaped_length);
3001 if (o->IsFailure()) return o; 2972 if (o->IsFailure()) return o;
3002 String* destination = String::cast(o); 2973 String* destination = String::cast(o);
3003 StringShape destination_shape(destination);
3004 2974
3005 int dest_position = 0; 2975 int dest_position = 0;
3006 for (int i = 0; i < length; dest_position++) { 2976 for (int i = 0; i < length; dest_position++) {
3007 int step; 2977 int step;
3008 destination->Set(destination_shape, 2978 destination->Set(dest_position, Unescape(source, i, length, &step));
3009 dest_position,
3010 Unescape(source, source_shape, i, length, &step));
3011 i += step; 2979 i += step;
3012 } 2980 }
3013 return destination; 2981 return destination;
3014 } 2982 }
3015 2983
3016 2984
3017 static Object* Runtime_StringParseInt(Arguments args) { 2985 static Object* Runtime_StringParseInt(Arguments args) {
3018 NoHandleAllocation ha; 2986 NoHandleAllocation ha;
3019 2987
3020 CONVERT_CHECKED(String, s, args[0]); 2988 CONVERT_CHECKED(String, s, args[0]);
3021 CONVERT_DOUBLE_CHECKED(n, args[1]); 2989 CONVERT_DOUBLE_CHECKED(n, args[1]);
3022 int radix = FastD2I(n); 2990 int radix = FastD2I(n);
3023 2991
3024 s->TryFlattenIfNotFlat(StringShape(s)); 2992 s->TryFlattenIfNotFlat();
3025 2993
3026 StringShape shape(s); 2994 int len = s->length();
3027
3028 int len = s->length(shape);
3029 int i; 2995 int i;
3030 2996
3031 // Skip leading white space. 2997 // Skip leading white space.
3032 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ; 2998 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
3033 if (i == len) return Heap::nan_value(); 2999 if (i == len) return Heap::nan_value();
3034 3000
3035 // Compute the sign (default to +). 3001 // Compute the sign (default to +).
3036 int sign = 1; 3002 int sign = 1;
3037 if (s->Get(shape, i) == '-') { 3003 if (s->Get(i) == '-') {
3038 sign = -1; 3004 sign = -1;
3039 i++; 3005 i++;
3040 } else if (s->Get(shape, i) == '+') { 3006 } else if (s->Get(i) == '+') {
3041 i++; 3007 i++;
3042 } 3008 }
3043 3009
3044 // Compute the radix if 0. 3010 // Compute the radix if 0.
3045 if (radix == 0) { 3011 if (radix == 0) {
3046 radix = 10; 3012 radix = 10;
3047 if (i < len && s->Get(shape, i) == '0') { 3013 if (i < len && s->Get(i) == '0') {
3048 radix = 8; 3014 radix = 8;
3049 if (i + 1 < len) { 3015 if (i + 1 < len) {
3050 int c = s->Get(shape, i + 1); 3016 int c = s->Get(i + 1);
3051 if (c == 'x' || c == 'X') { 3017 if (c == 'x' || c == 'X') {
3052 radix = 16; 3018 radix = 16;
3053 i += 2; 3019 i += 2;
3054 } 3020 }
3055 } 3021 }
3056 } 3022 }
3057 } else if (radix == 16) { 3023 } else if (radix == 16) {
3058 // Allow 0x or 0X prefix if radix is 16. 3024 // Allow 0x or 0X prefix if radix is 16.
3059 if (i + 1 < len && s->Get(shape, i) == '0') { 3025 if (i + 1 < len && s->Get(i) == '0') {
3060 int c = s->Get(shape, i + 1); 3026 int c = s->Get(i + 1);
3061 if (c == 'x' || c == 'X') i += 2; 3027 if (c == 'x' || c == 'X') i += 2;
3062 } 3028 }
3063 } 3029 }
3064 3030
3065 RUNTIME_ASSERT(2 <= radix && radix <= 36); 3031 RUNTIME_ASSERT(2 <= radix && radix <= 36);
3066 double value; 3032 double value;
3067 int end_index = StringToInt(s, i, radix, &value); 3033 int end_index = StringToInt(s, i, radix, &value);
3068 if (end_index != i) { 3034 if (end_index != i) {
3069 return Heap::NumberFromDouble(sign * value); 3035 return Heap::NumberFromDouble(sign * value);
3070 } 3036 }
(...skipping 11 matching lines...) Expand all
3082 // Create a number object from the value. 3048 // Create a number object from the value.
3083 return Heap::NumberFromDouble(value); 3049 return Heap::NumberFromDouble(value);
3084 } 3050 }
3085 3051
3086 3052
3087 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping; 3053 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
3088 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping; 3054 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
3089 3055
3090 3056
3091 template <class Converter> 3057 template <class Converter>
3092 static Object* ConvertCase(Arguments args, 3058 static Object* ConvertCaseHelper(String* s,
3093 unibrow::Mapping<Converter, 128>* mapping) { 3059 int length,
3094 NoHandleAllocation ha; 3060 int input_string_length,
3095 3061 unibrow::Mapping<Converter, 128>* mapping) {
3096 CONVERT_CHECKED(String, s, args[0]); 3062 // We try this twice, once with the assumption that the result is no longer
3097 s->TryFlattenIfNotFlat(StringShape(s)); 3063 // than the input and, if that assumption breaks, again with the exact
3098 StringShape shape(s); 3064 // length. This may not be pretty, but it is nicer than what was here before
3099 3065 // and I hereby claim my vaffel-is.
3100 int raw_string_length = s->length(shape); 3066 //
3101 // Assume that the string is not empty; we need this assumption later
3102 if (raw_string_length == 0) return s;
3103 int length = raw_string_length;
3104
3105
3106 // We try this twice, once with the assumption that the result is
3107 // no longer than the input and, if that assumption breaks, again
3108 // with the exact length. This is implemented using a goto back
3109 // to this label if we discover that the assumption doesn't hold.
3110 // I apologize sincerely for this and will give a vaffel-is to
3111 // the first person who can implement it in a nicer way.
3112 try_convert:
3113
3114 // Allocate the resulting string. 3067 // Allocate the resulting string.
3115 // 3068 //
3116 // NOTE: This assumes that the upper/lower case of an ascii 3069 // NOTE: This assumes that the upper/lower case of an ascii
3117 // character is also ascii. This is currently the case, but it 3070 // character is also ascii. This is currently the case, but it
3118 // might break in the future if we implement more context and locale 3071 // might break in the future if we implement more context and locale
3119 // dependent upper/lower conversions. 3072 // dependent upper/lower conversions.
3120 Object* o = shape.IsAsciiRepresentation() 3073 Object* o = StringShape(s).IsAsciiRepresentation()
3121 ? Heap::AllocateRawAsciiString(length) 3074 ? Heap::AllocateRawAsciiString(length)
3122 : Heap::AllocateRawTwoByteString(length); 3075 : Heap::AllocateRawTwoByteString(length);
3123 if (o->IsFailure()) return o; 3076 if (o->IsFailure()) return o;
3124 String* result = String::cast(o); 3077 String* result = String::cast(o);
3125 StringShape result_shape(result);
3126 bool has_changed_character = false; 3078 bool has_changed_character = false;
3127 3079
3128 // Convert all characters to upper case, assuming that they will fit 3080 // Convert all characters to upper case, assuming that they will fit
3129 // in the buffer 3081 // in the buffer
3130 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); 3082 Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
3131 buffer->Reset(s); 3083 buffer->Reset(s);
3132 unibrow::uchar chars[Converter::kMaxWidth]; 3084 unibrow::uchar chars[Converter::kMaxWidth];
3133 int i = 0;
3134 // We can assume that the string is not empty 3085 // We can assume that the string is not empty
3135 uc32 current = buffer->GetNext(); 3086 uc32 current = buffer->GetNext();
3136 while (i < length) { 3087 for (int i = 0; i < length; ) {
3137 bool has_next = buffer->has_more(); 3088 bool has_next = buffer->has_more();
3138 uc32 next = has_next ? buffer->GetNext() : 0; 3089 uc32 next = has_next ? buffer->GetNext() : 0;
3139 int char_length = mapping->get(current, next, chars); 3090 int char_length = mapping->get(current, next, chars);
3140 if (char_length == 0) { 3091 if (char_length == 0) {
3141 // The case conversion of this character is the character itself. 3092 // The case conversion of this character is the character itself.
3142 result->Set(result_shape, i, current); 3093 result->Set(i, current);
3143 i++; 3094 i++;
3144 } else if (char_length == 1) { 3095 } else if (char_length == 1) {
3145 // Common case: converting the letter resulted in one character. 3096 // Common case: converting the letter resulted in one character.
3146 ASSERT(static_cast<uc32>(chars[0]) != current); 3097 ASSERT(static_cast<uc32>(chars[0]) != current);
3147 result->Set(result_shape, i, chars[0]); 3098 result->Set(i, chars[0]);
3148 has_changed_character = true; 3099 has_changed_character = true;
3149 i++; 3100 i++;
3150 } else if (length == raw_string_length) { 3101 } else if (length == input_string_length) {
3151 // We've assumed that the result would be as long as the 3102 // We've assumed that the result would be as long as the
3152 // input but here is a character that converts to several 3103 // input but here is a character that converts to several
3153 // characters. No matter, we calculate the exact length 3104 // characters. No matter, we calculate the exact length
3154 // of the result and try the whole thing again. 3105 // of the result and try the whole thing again.
3155 // 3106 //
3156 // Note that this leaves room for optimization. We could just 3107 // Note that this leaves room for optimization. We could just
3157 // memcpy what we already have to the result string. Also, 3108 // memcpy what we already have to the result string. Also,
3158 // the result string is the last object allocated we could 3109 // the result string is the last object allocated we could
3159 // "realloc" it and probably, in the vast majority of cases, 3110 // "realloc" it and probably, in the vast majority of cases,
3160 // extend the existing string to be able to hold the full 3111 // extend the existing string to be able to hold the full
3161 // result. 3112 // result.
3162 int next_length = 0; 3113 int next_length = 0;
3163 if (has_next) { 3114 if (has_next) {
3164 next_length = mapping->get(next, 0, chars); 3115 next_length = mapping->get(next, 0, chars);
3165 if (next_length == 0) next_length = 1; 3116 if (next_length == 0) next_length = 1;
3166 } 3117 }
3167 int current_length = i + char_length + next_length; 3118 int current_length = i + char_length + next_length;
3168 while (buffer->has_more()) { 3119 while (buffer->has_more()) {
3169 current = buffer->GetNext(); 3120 current = buffer->GetNext();
3170 // NOTE: we use 0 as the next character here because, while 3121 // NOTE: we use 0 as the next character here because, while
3171 // the next character may affect what a character converts to, 3122 // the next character may affect what a character converts to,
3172 // it does not in any case affect the length of what it convert 3123 // it does not in any case affect the length of what it convert
3173 // to. 3124 // to.
3174 int char_length = mapping->get(current, 0, chars); 3125 int char_length = mapping->get(current, 0, chars);
3175 if (char_length == 0) char_length = 1; 3126 if (char_length == 0) char_length = 1;
3176 current_length += char_length; 3127 current_length += char_length;
3128 if (current_length > Smi::kMaxValue) {
3129 Top::context()->mark_out_of_memory();
3130 return Failure::OutOfMemoryException();
3131 }
3177 } 3132 }
3178 length = current_length; 3133 // Try again with the real length.
3179 goto try_convert; 3134 return Smi::FromInt(current_length);
3180 } else { 3135 } else {
3181 for (int j = 0; j < char_length; j++) { 3136 for (int j = 0; j < char_length; j++) {
3182 result->Set(result_shape, i, chars[j]); 3137 result->Set(i, chars[j]);
3183 i++; 3138 i++;
3184 } 3139 }
3185 has_changed_character = true; 3140 has_changed_character = true;
3186 } 3141 }
3187 current = next; 3142 current = next;
3188 } 3143 }
3189 if (has_changed_character) { 3144 if (has_changed_character) {
3190 return result; 3145 return result;
3191 } else { 3146 } else {
3192 // If we didn't actually change anything in doing the conversion 3147 // If we didn't actually change anything in doing the conversion
3193 // we simple return the result and let the converted string 3148 // we simple return the result and let the converted string
3194 // become garbage; there is no reason to keep two identical strings 3149 // become garbage; there is no reason to keep two identical strings
3195 // alive. 3150 // alive.
3196 return s; 3151 return s;
3197 } 3152 }
3198 } 3153 }
3199 3154
3200 3155
3156 template <class Converter>
3157 static Object* ConvertCase(Arguments args,
3158 unibrow::Mapping<Converter, 128>* mapping) {
3159 NoHandleAllocation ha;
3160
3161 CONVERT_CHECKED(String, s, args[0]);
3162 s->TryFlattenIfNotFlat();
3163
3164 int input_string_length = s->length();
3165 // Assume that the string is not empty; we need this assumption later
3166 if (input_string_length == 0) return s;
3167 int length = input_string_length;
3168
3169 Object* answer = ConvertCaseHelper(s, length, length, mapping);
3170 if (answer->IsSmi()) {
3171 // Retry with correct length.
3172 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
3173 }
3174 return answer; // This may be a failure.
3175 }
3176
3177
3201 static Object* Runtime_StringToLowerCase(Arguments args) { 3178 static Object* Runtime_StringToLowerCase(Arguments args) {
3202 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping); 3179 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
3203 } 3180 }
3204 3181
3205 3182
3206 static Object* Runtime_StringToUpperCase(Arguments args) { 3183 static Object* Runtime_StringToUpperCase(Arguments args) {
3207 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping); 3184 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
3208 } 3185 }
3209 3186
3210 3187
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3377 if (length_sum > Smi::kMaxValue || length_sum < 0) { 3354 if (length_sum > Smi::kMaxValue || length_sum < 0) {
3378 Top::context()->mark_out_of_memory(); 3355 Top::context()->mark_out_of_memory();
3379 return Failure::OutOfMemoryException(); 3356 return Failure::OutOfMemoryException();
3380 } 3357 }
3381 return Heap::AllocateConsString(str1, str2); 3358 return Heap::AllocateConsString(str1, str2);
3382 } 3359 }
3383 3360
3384 3361
3385 template<typename sinkchar> 3362 template<typename sinkchar>
3386 static inline void StringBuilderConcatHelper(String* special, 3363 static inline void StringBuilderConcatHelper(String* special,
3387 StringShape special_shape,
3388 sinkchar* sink, 3364 sinkchar* sink,
3389 FixedArray* fixed_array, 3365 FixedArray* fixed_array,
3390 int array_length) { 3366 int array_length) {
3391 int position = 0; 3367 int position = 0;
3392 for (int i = 0; i < array_length; i++) { 3368 for (int i = 0; i < array_length; i++) {
3393 Object* element = fixed_array->get(i); 3369 Object* element = fixed_array->get(i);
3394 if (element->IsSmi()) { 3370 if (element->IsSmi()) {
3395 int encoded_slice = Smi::cast(element)->value(); 3371 int encoded_slice = Smi::cast(element)->value();
3396 int pos = StringBuilderSubstringPosition::decode(encoded_slice); 3372 int pos = StringBuilderSubstringPosition::decode(encoded_slice);
3397 int len = StringBuilderSubstringLength::decode(encoded_slice); 3373 int len = StringBuilderSubstringLength::decode(encoded_slice);
3398 String::WriteToFlat(special, 3374 String::WriteToFlat(special,
3399 special_shape,
3400 sink + position, 3375 sink + position,
3401 pos, 3376 pos,
3402 pos + len); 3377 pos + len);
3403 position += len; 3378 position += len;
3404 } else { 3379 } else {
3405 String* string = String::cast(element); 3380 String* string = String::cast(element);
3406 StringShape shape(string); 3381 int element_length = string->length();
3407 int element_length = string->length(shape); 3382 String::WriteToFlat(string, sink + position, 0, element_length);
3408 String::WriteToFlat(string, shape, sink + position, 0, element_length);
3409 position += element_length; 3383 position += element_length;
3410 } 3384 }
3411 } 3385 }
3412 } 3386 }
3413 3387
3414 3388
3415 static Object* Runtime_StringBuilderConcat(Arguments args) { 3389 static Object* Runtime_StringBuilderConcat(Arguments args) {
3416 NoHandleAllocation ha; 3390 NoHandleAllocation ha;
3417 ASSERT(args.length() == 2); 3391 ASSERT(args.length() == 2);
3418 CONVERT_CHECKED(JSArray, array, args[0]); 3392 CONVERT_CHECKED(JSArray, array, args[0]);
3419 CONVERT_CHECKED(String, special, args[1]); 3393 CONVERT_CHECKED(String, special, args[1]);
3420 StringShape special_shape(special); 3394 int special_length = special->length();
3421 int special_length = special->length(special_shape);
3422 Object* smi_array_length = array->length(); 3395 Object* smi_array_length = array->length();
3423 if (!smi_array_length->IsSmi()) { 3396 if (!smi_array_length->IsSmi()) {
3424 Top::context()->mark_out_of_memory(); 3397 Top::context()->mark_out_of_memory();
3425 return Failure::OutOfMemoryException(); 3398 return Failure::OutOfMemoryException();
3426 } 3399 }
3427 int array_length = Smi::cast(smi_array_length)->value(); 3400 int array_length = Smi::cast(smi_array_length)->value();
3428 if (!array->HasFastElements()) { 3401 if (!array->HasFastElements()) {
3429 return Top::Throw(Heap::illegal_argument_symbol()); 3402 return Top::Throw(Heap::illegal_argument_symbol());
3430 } 3403 }
3431 FixedArray* fixed_array = FixedArray::cast(array->elements()); 3404 FixedArray* fixed_array = FixedArray::cast(array->elements());
3432 if (fixed_array->length() < array_length) { 3405 if (fixed_array->length() < array_length) {
3433 array_length = fixed_array->length(); 3406 array_length = fixed_array->length();
3434 } 3407 }
3435 3408
3436 if (array_length == 0) { 3409 if (array_length == 0) {
3437 return Heap::empty_string(); 3410 return Heap::empty_string();
3438 } else if (array_length == 1) { 3411 } else if (array_length == 1) {
3439 Object* first = fixed_array->get(0); 3412 Object* first = fixed_array->get(0);
3440 if (first->IsString()) return first; 3413 if (first->IsString()) return first;
3441 } 3414 }
3442 3415
3443 bool ascii = special_shape.IsAsciiRepresentation(); 3416 bool ascii = StringShape(special).IsAsciiRepresentation();
3444 int position = 0; 3417 int position = 0;
3445 for (int i = 0; i < array_length; i++) { 3418 for (int i = 0; i < array_length; i++) {
3446 Object* elt = fixed_array->get(i); 3419 Object* elt = fixed_array->get(i);
3447 if (elt->IsSmi()) { 3420 if (elt->IsSmi()) {
3448 int len = Smi::cast(elt)->value(); 3421 int len = Smi::cast(elt)->value();
3449 int pos = len >> 11; 3422 int pos = len >> 11;
3450 len &= 0x7ff; 3423 len &= 0x7ff;
3451 if (pos + len > special_length) { 3424 if (pos + len > special_length) {
3452 return Top::Throw(Heap::illegal_argument_symbol()); 3425 return Top::Throw(Heap::illegal_argument_symbol());
3453 } 3426 }
3454 position += len; 3427 position += len;
3455 } else if (elt->IsString()) { 3428 } else if (elt->IsString()) {
3456 String* element = String::cast(elt); 3429 String* element = String::cast(elt);
3457 StringShape element_shape(element); 3430 int element_length = element->length();
3458 int element_length = element->length(element_shape);
3459 if (!Smi::IsValid(element_length + position)) { 3431 if (!Smi::IsValid(element_length + position)) {
3460 Top::context()->mark_out_of_memory(); 3432 Top::context()->mark_out_of_memory();
3461 return Failure::OutOfMemoryException(); 3433 return Failure::OutOfMemoryException();
3462 } 3434 }
3463 position += element_length; 3435 position += element_length;
3464 if (ascii && !element_shape.IsAsciiRepresentation()) { 3436 if (ascii && !StringShape(element).IsAsciiRepresentation()) {
3465 ascii = false; 3437 ascii = false;
3466 } 3438 }
3467 } else { 3439 } else {
3468 return Top::Throw(Heap::illegal_argument_symbol()); 3440 return Top::Throw(Heap::illegal_argument_symbol());
3469 } 3441 }
3470 } 3442 }
3471 3443
3472 int length = position; 3444 int length = position;
3473 Object* object; 3445 Object* object;
3474 3446
3475 if (ascii) { 3447 if (ascii) {
3476 object = Heap::AllocateRawAsciiString(length); 3448 object = Heap::AllocateRawAsciiString(length);
3477 if (object->IsFailure()) return object; 3449 if (object->IsFailure()) return object;
3478 SeqAsciiString* answer = SeqAsciiString::cast(object); 3450 SeqAsciiString* answer = SeqAsciiString::cast(object);
3479 StringBuilderConcatHelper(special, 3451 StringBuilderConcatHelper(special,
3480 special_shape,
3481 answer->GetChars(), 3452 answer->GetChars(),
3482 fixed_array, 3453 fixed_array,
3483 array_length); 3454 array_length);
3484 return answer; 3455 return answer;
3485 } else { 3456 } else {
3486 object = Heap::AllocateRawTwoByteString(length); 3457 object = Heap::AllocateRawTwoByteString(length);
3487 if (object->IsFailure()) return object; 3458 if (object->IsFailure()) return object;
3488 SeqTwoByteString* answer = SeqTwoByteString::cast(object); 3459 SeqTwoByteString* answer = SeqTwoByteString::cast(object);
3489 StringBuilderConcatHelper(special, 3460 StringBuilderConcatHelper(special,
3490 special_shape,
3491 answer->GetChars(), 3461 answer->GetChars(),
3492 fixed_array, 3462 fixed_array,
3493 array_length); 3463 array_length);
3494 return answer; 3464 return answer;
3495 } 3465 }
3496 } 3466 }
3497 3467
3498 3468
3499 static Object* Runtime_NumberOr(Arguments args) { 3469 static Object* Runtime_NumberOr(Arguments args) {
3500 NoHandleAllocation ha; 3470 NoHandleAllocation ha;
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
3675 } 3645 }
3676 3646
3677 3647
3678 static Object* Runtime_StringCompare(Arguments args) { 3648 static Object* Runtime_StringCompare(Arguments args) {
3679 NoHandleAllocation ha; 3649 NoHandleAllocation ha;
3680 ASSERT(args.length() == 2); 3650 ASSERT(args.length() == 2);
3681 3651
3682 CONVERT_CHECKED(String, x, args[0]); 3652 CONVERT_CHECKED(String, x, args[0]);
3683 CONVERT_CHECKED(String, y, args[1]); 3653 CONVERT_CHECKED(String, y, args[1]);
3684 3654
3685 StringShape x_shape(x);
3686 StringShape y_shape(y);
3687
3688 // A few fast case tests before we flatten. 3655 // A few fast case tests before we flatten.
3689 if (x == y) return Smi::FromInt(EQUAL); 3656 if (x == y) return Smi::FromInt(EQUAL);
3690 if (y->length(y_shape) == 0) { 3657 if (y->length() == 0) {
3691 if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL); 3658 if (x->length() == 0) return Smi::FromInt(EQUAL);
3692 return Smi::FromInt(GREATER); 3659 return Smi::FromInt(GREATER);
3693 } else if (x->length(x_shape) == 0) { 3660 } else if (x->length() == 0) {
3694 return Smi::FromInt(LESS); 3661 return Smi::FromInt(LESS);
3695 } 3662 }
3696 3663
3697 int d = x->Get(x_shape, 0) - y->Get(y_shape, 0); 3664 int d = x->Get(0) - y->Get(0);
3698 if (d < 0) return Smi::FromInt(LESS); 3665 if (d < 0) return Smi::FromInt(LESS);
3699 else if (d > 0) return Smi::FromInt(GREATER); 3666 else if (d > 0) return Smi::FromInt(GREATER);
3700 3667
3701 x->TryFlattenIfNotFlat(x_shape); // Shapes are no longer valid! 3668 x->TryFlattenIfNotFlat();
3702 y->TryFlattenIfNotFlat(y_shape); 3669 y->TryFlattenIfNotFlat();
3703 3670
3704 static StringInputBuffer bufx; 3671 static StringInputBuffer bufx;
3705 static StringInputBuffer bufy; 3672 static StringInputBuffer bufy;
3706 bufx.Reset(x); 3673 bufx.Reset(x);
3707 bufy.Reset(y); 3674 bufy.Reset(y);
3708 while (bufx.has_more() && bufy.has_more()) { 3675 while (bufx.has_more() && bufy.has_more()) {
3709 int d = bufx.GetNext() - bufy.GetNext(); 3676 int d = bufx.GetNext() - bufy.GetNext();
3710 if (d < 0) return Smi::FromInt(LESS); 3677 if (d < 0) return Smi::FromInt(LESS);
3711 else if (d > 0) return Smi::FromInt(GREATER); 3678 else if (d > 0) return Smi::FromInt(GREATER);
3712 } 3679 }
(...skipping 2960 matching lines...) Expand 10 before | Expand all | Expand 10 after
6673 } else { 6640 } else {
6674 // Handle last resort GC and make sure to allow future allocations 6641 // Handle last resort GC and make sure to allow future allocations
6675 // to grow the heap without causing GCs (if possible). 6642 // to grow the heap without causing GCs (if possible).
6676 Counters::gc_last_resort_from_js.Increment(); 6643 Counters::gc_last_resort_from_js.Increment();
6677 Heap::CollectAllGarbage(); 6644 Heap::CollectAllGarbage();
6678 } 6645 }
6679 } 6646 }
6680 6647
6681 6648
6682 } } // namespace v8::internal 6649 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/regexp-macro-assembler-ia32.cc ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698