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

Side by Side Diff: src/string.js

Issue 12217071: Combine %_SubString and %_StringCharAt. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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 | Annotate | Revision Log
« no previous file with comments | « src/runtime.cc ('k') | src/x64/code-stubs-x64.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 if (result !== null) lastMatchInfoOverride = null; 196 if (result !== null) lastMatchInfoOverride = null;
197 regexp.lastIndex = 0; 197 regexp.lastIndex = 0;
198 return result; 198 return result;
199 } 199 }
200 // Non-regexp argument. 200 // Non-regexp argument.
201 regexp = new $RegExp(regexp); 201 regexp = new $RegExp(regexp);
202 return RegExpExecNoTests(regexp, subject, 0); 202 return RegExpExecNoTests(regexp, subject, 0);
203 } 203 }
204 204
205 205
206 // SubString is an internal function that returns the sub string of 'string'.
207 // If resulting string is of length 1, we use the one character cache
208 // otherwise we call the runtime system.
209 function SubString(string, start, end) {
210 // Use the one character string cache.
211 if (start + 1 == end) return %_StringCharAt(string, start);
212 return %_SubString(string, start, end);
213 }
214
215
216 // This has the same size as the lastMatchInfo array, and can be used for 206 // This has the same size as the lastMatchInfo array, and can be used for
217 // functions that expect that structure to be returned. It is used when the 207 // functions that expect that structure to be returned. It is used when the
218 // needle is a string rather than a regexp. In this case we can't update 208 // needle is a string rather than a regexp. In this case we can't update
219 // lastMatchArray without erroneously affecting the properties on the global 209 // lastMatchArray without erroneously affecting the properties on the global
220 // RegExp object. 210 // RegExp object.
221 var reusableMatchInfo = [2, "", "", -1, -1]; 211 var reusableMatchInfo = [2, "", "", -1, -1];
222 212
223 213
224 // ECMA-262, section 15.5.4.11 214 // ECMA-262, section 15.5.4.11
225 function StringReplace(search, replace) { 215 function StringReplace(search, replace) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 %StringIndexOf(replace, '$', 0) < 0) { 279 %StringIndexOf(replace, '$', 0) < 0) {
290 // Searching by traversing a cons string tree and replace with cons of 280 // Searching by traversing a cons string tree and replace with cons of
291 // slices works only when the replaced string is a single character, being 281 // slices works only when the replaced string is a single character, being
292 // replaced by a simple string and only pays off for long strings. 282 // replaced by a simple string and only pays off for long strings.
293 return %StringReplaceOneCharWithString(subject, search, replace); 283 return %StringReplaceOneCharWithString(subject, search, replace);
294 } 284 }
295 var start = %StringIndexOf(subject, search, 0); 285 var start = %StringIndexOf(subject, search, 0);
296 if (start < 0) return subject; 286 if (start < 0) return subject;
297 var end = start + search.length; 287 var end = start + search.length;
298 288
299 var result = SubString(subject, 0, start); 289 var result = %_SubString(subject, 0, start);
300 290
301 // Compute the string to replace with. 291 // Compute the string to replace with.
302 if (IS_SPEC_FUNCTION(replace)) { 292 if (IS_SPEC_FUNCTION(replace)) {
303 var receiver = %GetDefaultReceiver(replace); 293 var receiver = %GetDefaultReceiver(replace);
304 result += %_CallFunction(receiver, search, start, subject, replace); 294 result += %_CallFunction(receiver, search, start, subject, replace);
305 } else { 295 } else {
306 reusableMatchInfo[CAPTURE0] = start; 296 reusableMatchInfo[CAPTURE0] = start;
307 reusableMatchInfo[CAPTURE1] = end; 297 reusableMatchInfo[CAPTURE1] = end;
308 replace = TO_STRING_INLINE(replace); 298 replace = TO_STRING_INLINE(replace);
309 result = ExpandReplacement(replace, subject, reusableMatchInfo, result); 299 result = ExpandReplacement(replace, subject, reusableMatchInfo, result);
310 } 300 }
311 301
312 return result + SubString(subject, end, subject.length); 302 return result + %_SubString(subject, end, subject.length);
313 } 303 }
314 304
315 305
316 // Expand the $-expressions in the string and return a new string with 306 // Expand the $-expressions in the string and return a new string with
317 // the result. 307 // the result.
318 function ExpandReplacement(string, subject, matchInfo, result) { 308 function ExpandReplacement(string, subject, matchInfo, result) {
319 var length = string.length; 309 var length = string.length;
320 var next = %StringIndexOf(string, '$', 0); 310 var next = %StringIndexOf(string, '$', 0);
321 if (next < 0) { 311 if (next < 0) {
322 if (length > 0) result += string; 312 if (length > 0) result += string;
323 return result; 313 return result;
324 } 314 }
325 315
326 if (next > 0) result += SubString(string, 0, next); 316 if (next > 0) result += %_SubString(string, 0, next);
327 317
328 while (true) { 318 while (true) {
329 var expansion = '$'; 319 var expansion = '$';
330 var position = next + 1; 320 var position = next + 1;
331 if (position < length) { 321 if (position < length) {
332 var peek = %_StringCharCodeAt(string, position); 322 var peek = %_StringCharCodeAt(string, position);
333 if (peek == 36) { // $$ 323 if (peek == 36) { // $$
334 ++position; 324 ++position;
335 result += '$'; 325 result += '$';
336 } else if (peek == 38) { // $& - match 326 } else if (peek == 38) { // $& - match
337 ++position; 327 ++position;
338 result += SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]); 328 result +=
329 %_SubString(subject, matchInfo[CAPTURE0], matchInfo[CAPTURE1]);
339 } else if (peek == 96) { // $` - prefix 330 } else if (peek == 96) { // $` - prefix
340 ++position; 331 ++position;
341 result += SubString(subject, 0, matchInfo[CAPTURE0]); 332 result += %_SubString(subject, 0, matchInfo[CAPTURE0]);
342 } else if (peek == 39) { // $' - suffix 333 } else if (peek == 39) { // $' - suffix
343 ++position; 334 ++position;
344 result += SubString(subject, matchInfo[CAPTURE1], subject.length); 335 result += %_SubString(subject, matchInfo[CAPTURE1], subject.length);
345 } else { 336 } else {
346 result += '$'; 337 result += '$';
347 } 338 }
348 } else { 339 } else {
349 result += '$'; 340 result += '$';
350 } 341 }
351 342
352 // Go the the next $ in the string. 343 // Go the the next $ in the string.
353 next = %StringIndexOf(string, '$', position); 344 next = %StringIndexOf(string, '$', position);
354 345
355 // Return if there are no more $ characters in the string. If we 346 // Return if there are no more $ characters in the string. If we
356 // haven't reached the end, we need to append the suffix. 347 // haven't reached the end, we need to append the suffix.
357 if (next < 0) { 348 if (next < 0) {
358 if (position < length) { 349 if (position < length) {
359 result += SubString(string, position, length); 350 result += %_SubString(string, position, length);
360 } 351 }
361 return result; 352 return result;
362 } 353 }
363 354
364 // Append substring between the previous and the next $ character. 355 // Append substring between the previous and the next $ character.
365 if (next > position) { 356 if (next > position) {
366 result += SubString(string, position, next); 357 result += %_SubString(string, position, next);
367 } 358 }
368 } 359 }
369 return result; 360 return result;
370 } 361 }
371 362
372 363
373 // Compute the string of a given regular expression capture. 364 // Compute the string of a given regular expression capture.
374 function CaptureString(string, lastCaptureInfo, index) { 365 function CaptureString(string, lastCaptureInfo, index) {
375 // Scale the index. 366 // Scale the index.
376 var scaled = index << 1; 367 var scaled = index << 1;
377 // Compute start and end. 368 // Compute start and end.
378 var start = lastCaptureInfo[CAPTURE(scaled)]; 369 var start = lastCaptureInfo[CAPTURE(scaled)];
379 // If start isn't valid, return undefined. 370 // If start isn't valid, return undefined.
380 if (start < 0) return; 371 if (start < 0) return;
381 var end = lastCaptureInfo[CAPTURE(scaled + 1)]; 372 var end = lastCaptureInfo[CAPTURE(scaled + 1)];
382 return SubString(string, start, end); 373 return %_SubString(string, start, end);
383 } 374 }
384 375
385 376
386 // TODO(lrn): This array will survive indefinitely if replace is never 377 // TODO(lrn): This array will survive indefinitely if replace is never
387 // called again. However, it will be empty, since the contents are cleared 378 // called again. However, it will be empty, since the contents are cleared
388 // in the finally block. 379 // in the finally block.
389 var reusableReplaceArray = new InternalArray(16); 380 var reusableReplaceArray = new InternalArray(16);
390 381
391 // Helper function for replacing regular expressions with the result of a 382 // Helper function for replacing regular expressions with the result of a
392 // function application in String.prototype.replace. 383 // function application in String.prototype.replace.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 } 459 }
469 460
470 461
471 function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) { 462 function StringReplaceNonGlobalRegExpWithFunction(subject, regexp, replace) {
472 var matchInfo = DoRegExpExec(regexp, subject, 0); 463 var matchInfo = DoRegExpExec(regexp, subject, 0);
473 if (IS_NULL(matchInfo)) { 464 if (IS_NULL(matchInfo)) {
474 regexp.lastIndex = 0; 465 regexp.lastIndex = 0;
475 return subject; 466 return subject;
476 } 467 }
477 var index = matchInfo[CAPTURE0]; 468 var index = matchInfo[CAPTURE0];
478 var result = SubString(subject, 0, index); 469 var result = %_SubString(subject, 0, index);
479 var endOfMatch = matchInfo[CAPTURE1]; 470 var endOfMatch = matchInfo[CAPTURE1];
480 // Compute the parameter list consisting of the match, captures, index, 471 // Compute the parameter list consisting of the match, captures, index,
481 // and subject for the replace function invocation. 472 // and subject for the replace function invocation.
482 // The number of captures plus one for the match. 473 // The number of captures plus one for the match.
483 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; 474 var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;
484 var replacement; 475 var replacement;
485 var receiver = %GetDefaultReceiver(replace); 476 var receiver = %GetDefaultReceiver(replace);
486 if (m == 1) { 477 if (m == 1) {
487 // No captures, only the match, which is always valid. 478 // No captures, only the match, which is always valid.
488 var s = SubString(subject, index, endOfMatch); 479 var s = %_SubString(subject, index, endOfMatch);
489 // Don't call directly to avoid exposing the built-in global object. 480 // Don't call directly to avoid exposing the built-in global object.
490 replacement = %_CallFunction(receiver, s, index, subject, replace); 481 replacement = %_CallFunction(receiver, s, index, subject, replace);
491 } else { 482 } else {
492 var parameters = new InternalArray(m + 2); 483 var parameters = new InternalArray(m + 2);
493 for (var j = 0; j < m; j++) { 484 for (var j = 0; j < m; j++) {
494 parameters[j] = CaptureString(subject, matchInfo, j); 485 parameters[j] = CaptureString(subject, matchInfo, j);
495 } 486 }
496 parameters[j] = index; 487 parameters[j] = index;
497 parameters[j + 1] = subject; 488 parameters[j + 1] = subject;
498 489
499 replacement = %Apply(replace, receiver, parameters, 0, j + 2); 490 replacement = %Apply(replace, receiver, parameters, 0, j + 2);
500 } 491 }
501 492
502 result += replacement; // The add method converts to string if necessary. 493 result += replacement; // The add method converts to string if necessary.
503 // Can't use matchInfo any more from here, since the function could 494 // Can't use matchInfo any more from here, since the function could
504 // overwrite it. 495 // overwrite it.
505 return result + SubString(subject, endOfMatch, subject.length); 496 return result + %_SubString(subject, endOfMatch, subject.length);
506 } 497 }
507 498
508 499
509 // ECMA-262 section 15.5.4.12 500 // ECMA-262 section 15.5.4.12
510 function StringSearch(re) { 501 function StringSearch(re) {
511 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 502 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
512 throw MakeTypeError("called_on_null_or_undefined", 503 throw MakeTypeError("called_on_null_or_undefined",
513 ["String.prototype.search"]); 504 ["String.prototype.search"]);
514 } 505 }
515 var regexp; 506 var regexp;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 } else { 552 } else {
562 if (end_i > s_len) { 553 if (end_i > s_len) {
563 end_i = s_len; 554 end_i = s_len;
564 } 555 }
565 } 556 }
566 557
567 if (end_i <= start_i) { 558 if (end_i <= start_i) {
568 return ''; 559 return '';
569 } 560 }
570 561
571 return SubString(s, start_i, end_i); 562 return %_SubString(s, start_i, end_i);
572 } 563 }
573 564
574 565
575 // ECMA-262 section 15.5.4.14 566 // ECMA-262 section 15.5.4.14
576 function StringSplit(separator, limit) { 567 function StringSplit(separator, limit) {
577 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 568 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
578 throw MakeTypeError("called_on_null_or_undefined", 569 throw MakeTypeError("called_on_null_or_undefined",
579 ["String.prototype.split"]); 570 ["String.prototype.split"]);
580 } 571 }
581 var subject = TO_STRING_INLINE(this); 572 var subject = TO_STRING_INLINE(this);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 613
623 var currentIndex = 0; 614 var currentIndex = 0;
624 var startIndex = 0; 615 var startIndex = 0;
625 var startMatch = 0; 616 var startMatch = 0;
626 var result = []; 617 var result = [];
627 618
628 outer_loop: 619 outer_loop:
629 while (true) { 620 while (true) {
630 621
631 if (startIndex === length) { 622 if (startIndex === length) {
632 result.push(SubString(subject, currentIndex, length)); 623 result.push(%_SubString(subject, currentIndex, length));
633 break; 624 break;
634 } 625 }
635 626
636 var matchInfo = DoRegExpExec(separator, subject, startIndex); 627 var matchInfo = DoRegExpExec(separator, subject, startIndex);
637 if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) { 628 if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
638 result.push(SubString(subject, currentIndex, length)); 629 result.push(%_SubString(subject, currentIndex, length));
639 break; 630 break;
640 } 631 }
641 var endIndex = matchInfo[CAPTURE1]; 632 var endIndex = matchInfo[CAPTURE1];
642 633
643 // We ignore a zero-length match at the currentIndex. 634 // We ignore a zero-length match at the currentIndex.
644 if (startIndex === endIndex && endIndex === currentIndex) { 635 if (startIndex === endIndex && endIndex === currentIndex) {
645 startIndex++; 636 startIndex++;
646 continue; 637 continue;
647 } 638 }
648 639
649 if (currentIndex + 1 == startMatch) { 640 result.push(%_SubString(subject, currentIndex, startMatch));
650 result.push(%_StringCharAt(subject, currentIndex));
651 } else {
652 result.push(%_SubString(subject, currentIndex, startMatch));
653 }
654 641
655 if (result.length === limit) break; 642 if (result.length === limit) break;
656 643
657 var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; 644 var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
658 for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) { 645 for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
659 var start = matchInfo[i++]; 646 var start = matchInfo[i++];
660 var end = matchInfo[i++]; 647 var end = matchInfo[i++];
661 if (end != -1) { 648 if (end != -1) {
662 if (start + 1 == end) { 649 result.push(%_SubString(subject, start, end));
663 result.push(%_StringCharAt(subject, start));
664 } else {
665 result.push(%_SubString(subject, start, end));
666 }
667 } else { 650 } else {
668 result.push(void 0); 651 result.push(void 0);
669 } 652 }
670 if (result.length === limit) break outer_loop; 653 if (result.length === limit) break outer_loop;
671 } 654 }
672 655
673 startIndex = currentIndex = endIndex; 656 startIndex = currentIndex = endIndex;
674 } 657 }
675 return result; 658 return result;
676 } 659 }
(...skipping 23 matching lines...) Expand all
700 } else { 683 } else {
701 if (end_i < 0) end_i = 0; 684 if (end_i < 0) end_i = 0;
702 if (start_i > end_i) { 685 if (start_i > end_i) {
703 var tmp = end_i; 686 var tmp = end_i;
704 end_i = start_i; 687 end_i = start_i;
705 start_i = tmp; 688 start_i = tmp;
706 } 689 }
707 } 690 }
708 } 691 }
709 692
710 return ((start_i + 1 == end_i) 693 return %_SubString(s, start_i, end_i);
711 ? %_StringCharAt(s, start_i)
712 : %_SubString(s, start_i, end_i));
713 } 694 }
714 695
715 696
716 // This is not a part of ECMA-262. 697 // This is not a part of ECMA-262.
717 function StringSubstr(start, n) { 698 function StringSubstr(start, n) {
718 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 699 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
719 throw MakeTypeError("called_on_null_or_undefined", 700 throw MakeTypeError("called_on_null_or_undefined",
720 ["String.prototype.substr"]); 701 ["String.prototype.substr"]);
721 } 702 }
722 var s = TO_STRING_INLINE(this); 703 var s = TO_STRING_INLINE(this);
(...skipping 21 matching lines...) Expand all
744 // use zero. 725 // use zero.
745 if (start < 0) { 726 if (start < 0) {
746 start += s.length; 727 start += s.length;
747 if (start < 0) start = 0; 728 if (start < 0) start = 0;
748 } 729 }
749 } 730 }
750 731
751 var end = start + len; 732 var end = start + len;
752 if (end > s.length) end = s.length; 733 if (end > s.length) end = s.length;
753 734
754 return ((start + 1 == end) 735 return %_SubString(s, start, end);
755 ? %_StringCharAt(s, start)
756 : %_SubString(s, start, end));
757 } 736 }
758 737
759 738
760 // ECMA-262, 15.5.4.16 739 // ECMA-262, 15.5.4.16
761 function StringToLowerCase() { 740 function StringToLowerCase() {
762 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) { 741 if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
763 throw MakeTypeError("called_on_null_or_undefined", 742 throw MakeTypeError("called_on_null_or_undefined",
764 ["String.prototype.toLowerCase"]); 743 ["String.prototype.toLowerCase"]);
765 } 744 }
766 return %StringToLowerCase(TO_STRING_INLINE(this)); 745 return %StringToLowerCase(TO_STRING_INLINE(this));
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 "fixed", StringFixed, 994 "fixed", StringFixed,
1016 "italics", StringItalics, 995 "italics", StringItalics,
1017 "small", StringSmall, 996 "small", StringSmall,
1018 "strike", StringStrike, 997 "strike", StringStrike,
1019 "sub", StringSub, 998 "sub", StringSub,
1020 "sup", StringSup 999 "sup", StringSup
1021 )); 1000 ));
1022 } 1001 }
1023 1002
1024 SetUpString(); 1003 SetUpString();
OLDNEW
« no previous file with comments | « src/runtime.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698