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

Side by Side Diff: src/string.js

Issue 596122: Some string optimizations: (Closed)
Patch Set: Undo unnecessary optimizations. Created 10 years, 10 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
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 16 matching lines...) Expand all
27 27
28 28
29 // This file relies on the fact that the following declaration has been made 29 // This file relies on the fact that the following declaration has been made
30 // in runtime.js: 30 // in runtime.js:
31 // const $String = global.String; 31 // const $String = global.String;
32 // const $NaN = 0/0; 32 // const $NaN = 0/0;
33 33
34 34
35 // Set the String function and constructor. 35 // Set the String function and constructor.
36 %SetCode($String, function(x) { 36 %SetCode($String, function(x) {
37 var value = %_ArgumentsLength() == 0 ? '' : ToString(x); 37 var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
38 if (%_IsConstructCall()) { 38 if (%_IsConstructCall()) {
39 %_SetValueOf(this, value); 39 %_SetValueOf(this, value);
40 } else { 40 } else {
41 return value; 41 return value;
42 } 42 }
43 }); 43 });
44 44
45 %FunctionSetPrototype($String, new $String()); 45 %FunctionSetPrototype($String, new $String());
46 46
47 // ECMA-262 section 15.5.4.2 47 // ECMA-262 section 15.5.4.2
48 function StringToString() { 48 function StringToString() {
49 if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) 49 if (!IS_STRING(this) && !IS_STRING_WRAPPER(this))
50 throw new $TypeError('String.prototype.toString is not generic'); 50 throw new $TypeError('String.prototype.toString is not generic');
51 return %_ValueOf(this); 51 return %_ValueOf(this);
52 } 52 }
53 53
54 54
55 // ECMA-262 section 15.5.4.3 55 // ECMA-262 section 15.5.4.3
56 function StringValueOf() { 56 function StringValueOf() {
57 if (!IS_STRING(this) && !IS_STRING_WRAPPER(this)) 57 if (!IS_STRING(this) && !IS_STRING_WRAPPER(this))
58 throw new $TypeError('String.prototype.valueOf is not generic'); 58 throw new $TypeError('String.prototype.valueOf is not generic');
59 return %_ValueOf(this); 59 return %_ValueOf(this);
60 } 60 }
61 61
62 62
63 // ECMA-262, section 15.5.4.4 63 // ECMA-262, section 15.5.4.4
64 function StringCharAt(pos) { 64 function StringCharAt(pos) {
65 var char_code = %_FastCharCodeAt(this, pos); 65 var char_code = %_FastCharCodeAt(this, pos);
66 if (!%_IsSmi(char_code)) { 66 if (!%_IsSmi(char_code)) {
67 var subject = ToString(this); 67 var subject = TO_STRING_INLINE(this);
68 var index = TO_INTEGER(pos); 68 var index = TO_INTEGER(pos);
69 if (index >= subject.length || index < 0) return ""; 69 if (index >= subject.length || index < 0) return "";
70 char_code = %StringCharCodeAt(subject, index); 70 char_code = %StringCharCodeAt(subject, index);
71 } 71 }
72 return %CharFromCode(char_code); 72 return %CharFromCode(char_code);
73 } 73 }
74 74
75 75
76 // ECMA-262 section 15.5.4.5 76 // ECMA-262 section 15.5.4.5
77 function StringCharCodeAt(pos) { 77 function StringCharCodeAt(pos) {
78 var fast_answer = %_FastCharCodeAt(this, pos); 78 var fast_answer = %_FastCharCodeAt(this, pos);
79 if (%_IsSmi(fast_answer)) { 79 if (%_IsSmi(fast_answer)) {
80 return fast_answer; 80 return fast_answer;
81 } 81 }
82 var subject = ToString(this); 82 var subject = TO_STRING_INLINE(this);
83 var index = TO_INTEGER(pos); 83 var index = TO_INTEGER(pos);
84 return %StringCharCodeAt(subject, index); 84 return %StringCharCodeAt(subject, index);
85 } 85 }
86 86
87 87
88 // ECMA-262, section 15.5.4.6 88 // ECMA-262, section 15.5.4.6
89 function StringConcat() { 89 function StringConcat() {
90 var len = %_ArgumentsLength(); 90 var len = %_ArgumentsLength();
91 var this_as_string = IS_STRING(this) ? this : ToString(this); 91 var this_as_string = TO_STRING_INLINE(this);
92 if (len === 1) { 92 if (len === 1) {
93 return this_as_string + %_Arguments(0); 93 return this_as_string + %_Arguments(0);
94 } 94 }
95 var parts = new $Array(len + 1); 95 var parts = new $Array(len + 1);
96 parts[0] = this_as_string; 96 parts[0] = this_as_string;
97 for (var i = 0; i < len; i++) { 97 for (var i = 0; i < len; i++) {
98 var part = %_Arguments(i); 98 var part = %_Arguments(i);
99 parts[i + 1] = IS_STRING(part) ? part : ToString(part); 99 parts[i + 1] = TO_STRING_INLINE(part);
100 } 100 }
101 return %StringBuilderConcat(parts, len + 1, ""); 101 return %StringBuilderConcat(parts, len + 1, "");
102 } 102 }
103 103
104 // Match ES3 and Safari 104 // Match ES3 and Safari
105 %FunctionSetLength(StringConcat, 1); 105 %FunctionSetLength(StringConcat, 1);
106 106
107 107
108 // ECMA-262 section 15.5.4.7 108 // ECMA-262 section 15.5.4.7
109 function StringIndexOf(searchString /* position */) { // length == 1 109 function StringIndexOf(searchString /* position */) { // length == 1
110 var subject_str = ToString(this); 110 var subject_str = TO_STRING_INLINE(this);
111 var pattern_str = ToString(searchString); 111 var pattern_str = TO_STRING_INLINE(searchString);
112 var subject_str_len = subject_str.length; 112 var subject_str_len = subject_str.length;
113 var pattern_str_len = pattern_str.length; 113 var pattern_str_len = pattern_str.length;
114 var index = 0; 114 var index = 0;
115 if (%_ArgumentsLength() > 1) { 115 if (%_ArgumentsLength() > 1) {
116 var arg1 = %_Arguments(1); // position 116 var arg1 = %_Arguments(1); // position
117 index = TO_INTEGER(arg1); 117 index = TO_INTEGER(arg1);
118 } 118 }
119 if (index < 0) index = 0; 119 if (index < 0) index = 0;
120 if (index > subject_str_len) index = subject_str_len; 120 if (index > subject_str_len) index = subject_str_len;
121 if (pattern_str_len + index > subject_str_len) return -1; 121 if (pattern_str_len + index > subject_str_len) return -1;
122 return %StringIndexOf(subject_str, pattern_str, index); 122 return %StringIndexOf(subject_str, pattern_str, index);
123 } 123 }
124 124
125 125
126 // ECMA-262 section 15.5.4.8 126 // ECMA-262 section 15.5.4.8
127 function StringLastIndexOf(searchString /* position */) { // length == 1 127 function StringLastIndexOf(searchString /* position */) { // length == 1
128 var sub = ToString(this); 128 var sub = TO_STRING_INLINE(this);
129 var subLength = sub.length; 129 var subLength = sub.length;
130 var pat = ToString(searchString); 130 var pat = TO_STRING_INLINE(searchString);
131 var patLength = pat.length; 131 var patLength = pat.length;
132 var index = subLength - patLength; 132 var index = subLength - patLength;
133 if (%_ArgumentsLength() > 1) { 133 if (%_ArgumentsLength() > 1) {
134 var position = ToNumber(%_Arguments(1)); 134 var position = ToNumber(%_Arguments(1));
135 if (!$isNaN(position)) { 135 if (!$isNaN(position)) {
136 position = TO_INTEGER(position); 136 position = TO_INTEGER(position);
137 if (position < 0) { 137 if (position < 0) {
138 position = 0; 138 position = 0;
139 } 139 }
140 if (position + patLength < subLength) { 140 if (position + patLength < subLength) {
141 index = position 141 index = position
142 } 142 }
143 } 143 }
144 } 144 }
145 if (index < 0) { 145 if (index < 0) {
146 return -1; 146 return -1;
147 } 147 }
148 return %StringLastIndexOf(sub, pat, index); 148 return %StringLastIndexOf(sub, pat, index);
149 } 149 }
150 150
151 151
152 // ECMA-262 section 15.5.4.9 152 // ECMA-262 section 15.5.4.9
153 // 153 //
154 // This function is implementation specific. For now, we do not 154 // This function is implementation specific. For now, we do not
155 // do anything locale specific. 155 // do anything locale specific.
156 function StringLocaleCompare(other) { 156 function StringLocaleCompare(other) {
157 if (%_ArgumentsLength() === 0) return 0; 157 if (%_ArgumentsLength() === 0) return 0;
158 158
159 var this_str = ToString(this); 159 var this_str = TO_STRING_INLINE(this);
160 var other_str = ToString(other); 160 var other_str = TO_STRING_INLINE(other);
161 return %StringLocaleCompare(this_str, other_str); 161 return %StringLocaleCompare(this_str, other_str);
162 } 162 }
163 163
164 164
165 // ECMA-262 section 15.5.4.10 165 // ECMA-262 section 15.5.4.10
166 function StringMatch(regexp) { 166 function StringMatch(regexp) {
167 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp); 167 if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp);
168 var subject = ToString(this); 168 var subject = TO_STRING_INLINE(this);
169 169
170 if (!regexp.global) return regexp.exec(subject); 170 if (!regexp.global) return regexp.exec(subject);
171 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); 171 %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
172 // lastMatchInfo is defined in regexp-delay.js. 172 // lastMatchInfo is defined in regexp-delay.js.
173 return %StringMatch(subject, regexp, lastMatchInfo); 173 return %StringMatch(subject, regexp, lastMatchInfo);
174 } 174 }
175 175
176 176
177 // SubString is an internal function that returns the sub string of 'string'. 177 // SubString is an internal function that returns the sub string of 'string'.
178 // If resulting string is of length 1, we use the one character cache 178 // If resulting string is of length 1, we use the one character cache
(...skipping 14 matching lines...) Expand all
193 // This has the same size as the lastMatchInfo array, and can be used for 193 // This has the same size as the lastMatchInfo array, and can be used for
194 // functions that expect that structure to be returned. It is used when the 194 // functions that expect that structure to be returned. It is used when the
195 // needle is a string rather than a regexp. In this case we can't update 195 // needle is a string rather than a regexp. In this case we can't update
196 // lastMatchArray without erroneously affecting the properties on the global 196 // lastMatchArray without erroneously affecting the properties on the global
197 // RegExp object. 197 // RegExp object.
198 var reusableMatchInfo = [2, "", "", -1, -1]; 198 var reusableMatchInfo = [2, "", "", -1, -1];
199 199
200 200
201 // ECMA-262, section 15.5.4.11 201 // ECMA-262, section 15.5.4.11
202 function StringReplace(search, replace) { 202 function StringReplace(search, replace) {
203 var subject = IS_STRING(this) ? this : ToString(this); 203 var subject = TO_STRING_INLINE(this);
204 204
205 // Delegate to one of the regular expression variants if necessary. 205 // Delegate to one of the regular expression variants if necessary.
206 if (IS_REGEXP(search)) { 206 if (IS_REGEXP(search)) {
207 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]); 207 %_Log('regexp', 'regexp-replace,%0r,%1S', [search, subject]);
208 if (IS_FUNCTION(replace)) { 208 if (IS_FUNCTION(replace)) {
209 return StringReplaceRegExpWithFunction(subject, search, replace); 209 return StringReplaceRegExpWithFunction(subject, search, replace);
210 } else { 210 } else {
211 return StringReplaceRegExp(subject, search, replace); 211 return StringReplaceRegExp(subject, search, replace);
212 } 212 }
213 } 213 }
214 214
215 // Convert the search argument to a string and search for it. 215 // Convert the search argument to a string and search for it.
216 search = IS_STRING(search) ? search : ToString(search); 216 search = TO_STRING_INLINE(search);
217 var start = %StringIndexOf(subject, search, 0); 217 var start = %StringIndexOf(subject, search, 0);
218 if (start < 0) return subject; 218 if (start < 0) return subject;
219 var end = start + search.length; 219 var end = start + search.length;
220 220
221 var builder = new ReplaceResultBuilder(subject); 221 var builder = new ReplaceResultBuilder(subject);
222 // prefix 222 // prefix
223 builder.addSpecialSlice(0, start); 223 builder.addSpecialSlice(0, start);
224 224
225 // Compute the string to replace with. 225 // Compute the string to replace with.
226 if (IS_FUNCTION(replace)) { 226 if (IS_FUNCTION(replace)) {
227 builder.add(replace.call(null, search, start, subject)); 227 builder.add(replace.call(null, search, start, subject));
228 } else { 228 } else {
229 reusableMatchInfo[CAPTURE0] = start; 229 reusableMatchInfo[CAPTURE0] = start;
230 reusableMatchInfo[CAPTURE1] = end; 230 reusableMatchInfo[CAPTURE1] = end;
231 if (!IS_STRING(replace)) replace = ToString(replace); 231 replace = TO_STRING_INLINE(replace);
232 ExpandReplacement(replace, subject, reusableMatchInfo, builder); 232 ExpandReplacement(replace, subject, reusableMatchInfo, builder);
233 } 233 }
234 234
235 // suffix 235 // suffix
236 builder.addSpecialSlice(end, subject.length); 236 builder.addSpecialSlice(end, subject.length);
237 237
238 return builder.generate(); 238 return builder.generate();
239 } 239 }
240 240
241 241
242 // Helper function for regular expressions in String.prototype.replace. 242 // Helper function for regular expressions in String.prototype.replace.
243 function StringReplaceRegExp(subject, regexp, replace) { 243 function StringReplaceRegExp(subject, regexp, replace) {
244 replace = ToString(replace); 244 replace = TO_STRING_INLINE(replace);
245 return %StringReplaceRegExpWithString(subject, 245 return %StringReplaceRegExpWithString(subject,
246 regexp, 246 regexp,
247 replace, 247 replace,
248 lastMatchInfo); 248 lastMatchInfo);
249 }; 249 };
250 250
251 251
252 // Expand the $-expressions in the string and return a new string with 252 // Expand the $-expressions in the string and return a new string with
253 // the result. 253 // the result.
254 function ExpandReplacement(string, subject, matchInfo, builder) { 254 function ExpandReplacement(string, subject, matchInfo, builder) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 } 455 }
456 parameters[j] = index; 456 parameters[j] = index;
457 parameters[j + 1] = subject; 457 parameters[j + 1] = subject;
458 return replace.apply(null, parameters); 458 return replace.apply(null, parameters);
459 } 459 }
460 460
461 461
462 // ECMA-262 section 15.5.4.12 462 // ECMA-262 section 15.5.4.12
463 function StringSearch(re) { 463 function StringSearch(re) {
464 var regexp = new ORIGINAL_REGEXP(re); 464 var regexp = new ORIGINAL_REGEXP(re);
465 var s = ToString(this); 465 var s = TO_STRING_INLINE(this);
466 var last_idx = regexp.lastIndex; // keep old lastIndex 466 var last_idx = regexp.lastIndex; // keep old lastIndex
467 regexp.lastIndex = 0; // ignore re.global property 467 regexp.lastIndex = 0; // ignore re.global property
468 var result = regexp.exec(s); 468 var result = regexp.exec(s);
469 regexp.lastIndex = last_idx; // restore lastIndex 469 regexp.lastIndex = last_idx; // restore lastIndex
470 if (result == null) 470 if (result == null)
471 return -1; 471 return -1;
472 else 472 else
473 return result.index; 473 return result.index;
474 } 474 }
475 475
476 476
477 // ECMA-262 section 15.5.4.13 477 // ECMA-262 section 15.5.4.13
478 function StringSlice(start, end) { 478 function StringSlice(start, end) {
479 var s = ToString(this); 479 var s = TO_STRING_INLINE(this);
480 var s_len = s.length; 480 var s_len = s.length;
481 var start_i = TO_INTEGER(start); 481 var start_i = TO_INTEGER(start);
482 var end_i = s_len; 482 var end_i = s_len;
483 if (end !== void 0) 483 if (end !== void 0)
484 end_i = TO_INTEGER(end); 484 end_i = TO_INTEGER(end);
485 485
486 if (start_i < 0) { 486 if (start_i < 0) {
487 start_i += s_len; 487 start_i += s_len;
488 if (start_i < 0) 488 if (start_i < 0)
489 start_i = 0; 489 start_i = 0;
(...skipping 14 matching lines...) Expand all
504 var num_c = end_i - start_i; 504 var num_c = end_i - start_i;
505 if (num_c < 0) 505 if (num_c < 0)
506 num_c = 0; 506 num_c = 0;
507 507
508 return SubString(s, start_i, start_i + num_c); 508 return SubString(s, start_i, start_i + num_c);
509 } 509 }
510 510
511 511
512 // ECMA-262 section 15.5.4.14 512 // ECMA-262 section 15.5.4.14
513 function StringSplit(separator, limit) { 513 function StringSplit(separator, limit) {
514 var subject = ToString(this); 514 var subject = TO_STRING_INLINE(this);
515 limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit); 515 limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit);
516 if (limit === 0) return []; 516 if (limit === 0) return [];
517 517
518 // ECMA-262 says that if separator is undefined, the result should 518 // ECMA-262 says that if separator is undefined, the result should
519 // be an array of size 1 containing the entire string. SpiderMonkey 519 // be an array of size 1 containing the entire string. SpiderMonkey
520 // and KJS have this behaviour only when no separator is given. If 520 // and KJS have this behaviour only when no separator is given. If
521 // undefined is explicitly given, they convert it to a string and 521 // undefined is explicitly given, they convert it to a string and
522 // use that. We do as SpiderMonkey and KJS. 522 // use that. We do as SpiderMonkey and KJS.
523 if (%_ArgumentsLength() === 0) { 523 if (%_ArgumentsLength() === 0) {
524 return [subject]; 524 return [subject];
525 } 525 }
526 526
527 var length = subject.length; 527 var length = subject.length;
528 if (IS_REGEXP(separator)) { 528 if (!IS_REGEXP(separator)) {
529 %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); 529 separator = TO_STRING_INLINE(separator);
530 } else { 530 var separator_length = separator.length;
531 separator = ToString(separator); 531
532 // If the separator string is empty then return the elements in the subject. 532 // If the separator string is empty then return the elements in the subject.
533 if (separator.length == 0) { 533 if (separator_length === 0) {
534 var result = $Array(length); 534 var result = $Array(length);
535 for (var i = 0; i < length; i++) result[i] = subject[i]; 535 for (var i = 0; i < length; i++) result[i] = subject[i];
536 return result; 536 return result;
537 } 537 }
538
539 var result = [];
540 var start_index = 0;
541 var index;
542 while (true) {
543 if (start_index + separator_length > length ||
544 (index = %StringIndexOf(subject, separator, start_index)) === -1) {
545 result.push(SubString(subject, start_index, length));
546 break;
547 }
548 if (result.push(SubString(subject, start_index, index)) === limit) break;
549 start_index = index + separator_length;
550 }
551
552 return result;
538 } 553 }
539 554
555 %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
556
540 if (length === 0) { 557 if (length === 0) {
541 if (splitMatch(separator, subject, 0, 0) != null) return []; 558 if (splitMatch(separator, subject, 0, 0) != null) return [];
542 return [subject]; 559 return [subject];
543 } 560 }
544 561
545 var currentIndex = 0; 562 var currentIndex = 0;
546 var startIndex = 0; 563 var startIndex = 0;
547 var result = []; 564 var result = [];
548 565
549 while (true) { 566 while (true) {
(...skipping 14 matching lines...) Expand all
564 581
565 // We ignore a zero-length match at the currentIndex. 582 // We ignore a zero-length match at the currentIndex.
566 if (startIndex === endIndex && endIndex === currentIndex) { 583 if (startIndex === endIndex && endIndex === currentIndex) {
567 startIndex++; 584 startIndex++;
568 continue; 585 continue;
569 } 586 }
570 587
571 result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0] ); 588 result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0] );
572 if (result.length === limit) return result; 589 if (result.length === limit) return result;
573 590
574 for (var i = 2; i < NUMBER_OF_CAPTURES(matchInfo); i += 2) { 591 var num_captures = NUMBER_OF_CAPTURES(matchInfo);
592 for (var i = 2; i < num_captures; i += 2) {
575 var start = matchInfo[CAPTURE(i)]; 593 var start = matchInfo[CAPTURE(i)];
576 var end = matchInfo[CAPTURE(i + 1)]; 594 var end = matchInfo[CAPTURE(i + 1)];
577 if (start != -1 && end != -1) { 595 if (start != -1 && end != -1) {
578 result[result.length] = SubString(subject, start, end); 596 result[result.length] = SubString(subject, start, end);
579 } else { 597 } else {
580 result[result.length] = void 0; 598 result[result.length] = void 0;
581 } 599 }
582 if (result.length === limit) return result; 600 if (result.length === limit) return result;
583 } 601 }
584 602
585 startIndex = currentIndex = endIndex; 603 startIndex = currentIndex = endIndex;
586 } 604 }
587 } 605 }
588 606
589 607
590 // ECMA-262 section 15.5.4.14 608 // ECMA-262 section 15.5.4.14
591 // Helper function used by split. This version returns the matchInfo 609 // Helper function used by split. This version returns the matchInfo
592 // instead of allocating a new array with basically the same information. 610 // instead of allocating a new array with basically the same information.
593 function splitMatch(separator, subject, current_index, start_index) { 611 function splitMatch(separator, subject, current_index, start_index) {
594 if (IS_REGEXP(separator)) { 612 var matchInfo = DoRegExpExec(separator, subject, start_index);
595 var matchInfo = DoRegExpExec(separator, subject, start_index); 613 if (matchInfo == null) return null;
596 if (matchInfo == null) return null; 614 // Section 15.5.4.14 paragraph two says that we do not allow zero length
597 // Section 15.5.4.14 paragraph two says that we do not allow zero length 615 // matches at the end of the string.
598 // matches at the end of the string. 616 if (matchInfo[CAPTURE0] === subject.length) return null;
599 if (matchInfo[CAPTURE0] === subject.length) return null; 617 return matchInfo;
600 return matchInfo; 618 }
601 }
602
603 var separatorIndex = subject.indexOf(separator, start_index);
604 if (separatorIndex === -1) return null;
605
606 reusableMatchInfo[CAPTURE0] = separatorIndex;
607 reusableMatchInfo[CAPTURE1] = separatorIndex + separator.length;
608 return reusableMatchInfo;
609 };
610 619
611 620
612 // ECMA-262 section 15.5.4.15 621 // ECMA-262 section 15.5.4.15
613 function StringSubstring(start, end) { 622 function StringSubstring(start, end) {
614 var s = this; 623 var s = TO_STRING_INLINE(this);
615 if (!IS_STRING(s)) s = ToString(s);
616 var s_len = s.length; 624 var s_len = s.length;
617 625
618 var start_i = TO_INTEGER(start); 626 var start_i = TO_INTEGER(start);
619 if (start_i < 0) { 627 if (start_i < 0) {
620 start_i = 0; 628 start_i = 0;
621 } else if (start_i > s_len) { 629 } else if (start_i > s_len) {
622 start_i = s_len; 630 start_i = s_len;
623 } 631 }
624 632
625 var end_i = s_len; 633 var end_i = s_len;
(...skipping 10 matching lines...) Expand all
636 } 644 }
637 } 645 }
638 } 646 }
639 647
640 return SubString(s, start_i, end_i); 648 return SubString(s, start_i, end_i);
641 } 649 }
642 650
643 651
644 // This is not a part of ECMA-262. 652 // This is not a part of ECMA-262.
645 function StringSubstr(start, n) { 653 function StringSubstr(start, n) {
646 var s = ToString(this); 654 var s = TO_STRING_INLINE(this);
647 var len; 655 var len;
648 656
649 // Correct n: If not given, set to string length; if explicitly 657 // Correct n: If not given, set to string length; if explicitly
650 // set to undefined, zero, or negative, returns empty string. 658 // set to undefined, zero, or negative, returns empty string.
651 if (n === void 0) { 659 if (n === void 0) {
652 len = s.length; 660 len = s.length;
653 } else { 661 } else {
654 len = TO_INTEGER(n); 662 len = TO_INTEGER(n);
655 if (len <= 0) return ''; 663 if (len <= 0) return '';
656 } 664 }
(...skipping 17 matching lines...) Expand all
674 682
675 var end = start + len; 683 var end = start + len;
676 if (end > s.length) end = s.length; 684 if (end > s.length) end = s.length;
677 685
678 return SubString(s, start, end); 686 return SubString(s, start, end);
679 } 687 }
680 688
681 689
682 // ECMA-262, 15.5.4.16 690 // ECMA-262, 15.5.4.16
683 function StringToLowerCase() { 691 function StringToLowerCase() {
684 return %StringToLowerCase(ToString(this)); 692 return %StringToLowerCase(TO_STRING_INLINE(this));
685 } 693 }
686 694
687 695
688 // ECMA-262, 15.5.4.17 696 // ECMA-262, 15.5.4.17
689 function StringToLocaleLowerCase() { 697 function StringToLocaleLowerCase() {
690 return %StringToLowerCase(ToString(this)); 698 return %StringToLowerCase(TO_STRING_INLINE(this));
691 } 699 }
692 700
693 701
694 // ECMA-262, 15.5.4.18 702 // ECMA-262, 15.5.4.18
695 function StringToUpperCase() { 703 function StringToUpperCase() {
696 return %StringToUpperCase(ToString(this)); 704 return %StringToUpperCase(TO_STRING_INLINE(this));
697 } 705 }
698 706
699 707
700 // ECMA-262, 15.5.4.19 708 // ECMA-262, 15.5.4.19
701 function StringToLocaleUpperCase() { 709 function StringToLocaleUpperCase() {
702 return %StringToUpperCase(ToString(this)); 710 return %StringToUpperCase(TO_STRING_INLINE(this));
703 } 711 }
704 712
705 // ES5, 15.5.4.20 713 // ES5, 15.5.4.20
706 function StringTrim() { 714 function StringTrim() {
707 return %StringTrim(ToString(this), true, true); 715 return %StringTrim(TO_STRING_INLINE(this), true, true);
708 } 716 }
709 717
710 function StringTrimLeft() { 718 function StringTrimLeft() {
711 return %StringTrim(ToString(this), true, false); 719 return %StringTrim(TO_STRING_INLINE(this), true, false);
712 } 720 }
713 721
714 function StringTrimRight() { 722 function StringTrimRight() {
715 return %StringTrim(ToString(this), false, true); 723 return %StringTrim(TO_STRING_INLINE(this), false, true);
716 } 724 }
717 725
718 // ECMA-262, section 15.5.3.2 726 // ECMA-262, section 15.5.3.2
719 function StringFromCharCode(code) { 727 function StringFromCharCode(code) {
720 var n = %_ArgumentsLength(); 728 var n = %_ArgumentsLength();
721 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff) 729 if (n == 1) return %CharFromCode(ToNumber(code) & 0xffff)
722 730
723 // NOTE: This is not super-efficient, but it is necessary because we 731 // NOTE: This is not super-efficient, but it is necessary because we
724 // want to avoid converting to numbers from within the virtual 732 // want to avoid converting to numbers from within the virtual
725 // machine. Maybe we can find another way of doing this? 733 // machine. Maybe we can find another way of doing this?
726 var codes = new $Array(n); 734 var codes = new $Array(n);
727 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i)); 735 for (var i = 0; i < n; i++) codes[i] = ToNumber(%_Arguments(i));
728 return %StringFromCharCodeArray(codes); 736 return %StringFromCharCodeArray(codes);
729 } 737 }
730 738
731 739
732 // Helper function for very basic XSS protection. 740 // Helper function for very basic XSS protection.
733 function HtmlEscape(str) { 741 function HtmlEscape(str) {
734 return ToString(str).replace(/</g, "&lt;") 742 return TO_STRING_INLINE(str).replace(/</g, "&lt;")
735 .replace(/>/g, "&gt;") 743 .replace(/>/g, "&gt;")
736 .replace(/"/g, "&quot;") 744 .replace(/"/g, "&quot;")
737 .replace(/'/g, "&#039;"); 745 .replace(/'/g, "&#039;");
738 }; 746 };
739 747
740 748
741 // Compatibility support for KJS. 749 // Compatibility support for KJS.
742 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js. 750 // Tested by mozilla/js/tests/js1_5/Regress/regress-276103.js.
743 function StringLink(s) { 751 function StringLink(s) {
744 return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>"; 752 return "<a href=\"" + HtmlEscape(s) + "\">" + this + "</a>";
745 } 753 }
746 754
747 755
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 814
807 815
808 // ReplaceResultBuilder support. 816 // ReplaceResultBuilder support.
809 function ReplaceResultBuilder(str) { 817 function ReplaceResultBuilder(str) {
810 this.elements = new $Array(); 818 this.elements = new $Array();
811 this.special_string = str; 819 this.special_string = str;
812 } 820 }
813 821
814 822
815 ReplaceResultBuilder.prototype.add = function(str) { 823 ReplaceResultBuilder.prototype.add = function(str) {
816 if (!IS_STRING(str)) str = ToString(str); 824 str = TO_STRING_INLINE(str);
817 if (str.length > 0) { 825 if (str.length > 0) {
818 var elements = this.elements; 826 var elements = this.elements;
819 elements[elements.length] = str; 827 elements[elements.length] = str;
820 } 828 }
821 } 829 }
822 830
823 831
824 ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) { 832 ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
825 var len = end - start; 833 var len = end - start;
826 if (len == 0) return; 834 if (len == 0) return;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 "small", StringSmall, 904 "small", StringSmall,
897 "strike", StringStrike, 905 "strike", StringStrike,
898 "sub", StringSub, 906 "sub", StringSub,
899 "sup", StringSup, 907 "sup", StringSup,
900 "toJSON", StringToJSON 908 "toJSON", StringToJSON
901 )); 909 ));
902 } 910 }
903 911
904 912
905 SetupString(); 913 SetupString();
OLDNEW
« src/macros.py ('K') | « src/runtime.js ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698