Fix performance regression in regular expressions after Array.push() optimizations
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 16 May 2014 15:42:00 +0000 (15:42 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 16 May 2014 15:42:00 +0000 (15:42 +0000)
R=yangguo@chromium.org
LOG=N

Review URL: https://codereview.chromium.org/281953002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21348 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/code-stubs-hydrogen.cc
src/regexp.js
src/string.js

index 83b461d..addc83d 100644 (file)
@@ -1483,6 +1483,8 @@ HValue* CodeStubGraphBuilder<RegExpConstructResultStub>::BuildCodeStub() {
   HValue* index = GetParameter(RegExpConstructResultStub::kIndex);
   HValue* input = GetParameter(RegExpConstructResultStub::kInput);
 
+  info()->MarkMustNotHaveEagerFrame();
+
   return BuildRegExpConstructResult(length, index, input);
 }
 
index 76d6a96..8a805b0 100644 (file)
@@ -115,8 +115,12 @@ macro RETURN_NEW_RESULT_FROM_MATCH_INFO(MATCHINFO, STRING)
   var numResults = NUMBER_OF_CAPTURES(MATCHINFO) >> 1;
   var start = MATCHINFO[CAPTURE0];
   var end = MATCHINFO[CAPTURE1];
+  // Calculate the substring of the first match before creating the result array
+  // to avoid an unnecessary write barrier storing the first result.
+  var first = %_SubString(STRING, start, end);
   var result = %_RegExpConstructResult(numResults, start, STRING);
-  result[0] = %_SubString(STRING, start, end);
+  result[0] = first;
+  if (numResults == 1) return result;
   var j = REGEXP_FIRST_CAPTURE + 2;
   for (var i = 1; i < numResults; i++) {
     start = MATCHINFO[j++];
index 1120479..07cdcc0 100644 (file)
@@ -618,8 +618,6 @@ function StringSplitJS(separator, limit) {
 }
 
 
-var ArrayPushBuiltin = $Array.prototype.push;
-
 function StringSplitOnRegExp(subject, separator, limit, length) {
   if (length === 0) {
     if (DoRegExpExec(separator, subject, 0, 0) != null) {
@@ -637,15 +635,13 @@ function StringSplitOnRegExp(subject, separator, limit, length) {
   while (true) {
 
     if (startIndex === length) {
-      %_CallFunction(result, %_SubString(subject, currentIndex, length),
-                     ArrayPushBuiltin);
+      result[result.length] = %_SubString(subject, currentIndex, length);
       break;
     }
 
     var matchInfo = DoRegExpExec(separator, subject, startIndex);
     if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
-      %_CallFunction(result, %_SubString(subject, currentIndex, length),
-                     ArrayPushBuiltin);
+      result[result.length] = %_SubString(subject, currentIndex, length);
       break;
     }
     var endIndex = matchInfo[CAPTURE1];
@@ -656,8 +652,7 @@ function StringSplitOnRegExp(subject, separator, limit, length) {
       continue;
     }
 
-    %_CallFunction(result, %_SubString(subject, currentIndex, startMatch),
-                   ArrayPushBuiltin);
+    result[result.length] = %_SubString(subject, currentIndex, startMatch);
 
     if (result.length === limit) break;
 
@@ -666,10 +661,9 @@ function StringSplitOnRegExp(subject, separator, limit, length) {
       var start = matchInfo[i++];
       var end = matchInfo[i++];
       if (end != -1) {
-        %_CallFunction(result, %_SubString(subject, start, end),
-                       ArrayPushBuiltin);
+        result[result.length] = %_SubString(subject, start, end);
       } else {
-        %_CallFunction(result, UNDEFINED, ArrayPushBuiltin);
+        result[result.length] = UNDEFINED;
       }
       if (result.length === limit) break outer_loop;
     }