- Changed fast case for computing object size based on usage histogram.
authorbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Jun 2009 13:31:31 +0000 (13:31 +0000)
committerbak@chromium.org <bak@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Jun 2009 13:31:31 +0000 (13:31 +0000)
- Added fast case to String.prototype.split (Mads's idea).
- Made minor other optimizations in String.prototype.split.

Review URL: http://codereview.chromium.org/126201

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

src/objects-inl.h
src/string.js

index d34e46539e7139da0d61ebb7fc487c8f50e3f0eb..bac0d559db1ce742838955287acadfaedd029a4b 100644 (file)
@@ -1786,11 +1786,17 @@ int Map::inobject_properties() {
 
 int HeapObject::SizeFromMap(Map* map) {
   InstanceType instance_type = map->instance_type();
-  // Only inline the two most frequent cases.
-  if (instance_type == JS_OBJECT_TYPE) return  map->instance_size();
+  // Only inline the most frequent cases.
+  if (instance_type == JS_OBJECT_TYPE ||
+      (instance_type & (kIsNotStringMask | kStringRepresentationMask)) ==
+      (kStringTag | kConsStringTag) ||
+      instance_type == JS_ARRAY_TYPE) return map->instance_size();
   if (instance_type == FIXED_ARRAY_TYPE) {
     return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
   }
+  if (instance_type == BYTE_ARRAY_TYPE) {
+    return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
+  }
   // Otherwise do the general size computation.
   return SlowSizeFromMap(map);
 }
index df1f393e0187821ea0acd361b2cfcf338cac08a3..3d8a11b2255093e5e1933251269b4c3d65f19f35 100644 (file)
@@ -370,10 +370,10 @@ function addCaptureString(builder, matchInfo, index) {
 //     'abcd'.replace(/(.)/g, function() { return RegExp.$1; }
 // should be 'abcd' and not 'dddd' (or anything else).
 function StringReplaceRegExpWithFunction(subject, regexp, replace) {
-  var result = new ReplaceResultBuilder(subject);
   var lastMatchInfo = DoRegExpExec(regexp, subject, 0);
   if (IS_NULL(lastMatchInfo)) return subject;
 
+  var result = new ReplaceResultBuilder(subject);
   // There's at least one match.  If the regexp is global, we have to loop
   // over all matches.  The loop is not in C++ code here like the one in
   // RegExp.prototype.exec, because of the interleaved function application.
@@ -498,10 +498,8 @@ function StringSlice(start, end) {
 // ECMA-262 section 15.5.4.14
 function StringSplit(separator, limit) {
   var subject = ToString(this);
-  var result = [];
-  var lim = (limit === void 0) ? 0xffffffff : ToUint32(limit);
-
-  if (lim === 0) return result;
+  limit = (limit === void 0) ? 0xffffffff : ToUint32(limit);
+  if (limit === 0) return [];
 
   // ECMA-262 says that if separator is undefined, the result should
   // be an array of size 1 containing the entire string.  SpiderMonkey
@@ -509,28 +507,31 @@ function StringSplit(separator, limit) {
   // undefined is explicitly given, they convert it to a string and
   // use that.  We do as SpiderMonkey and KJS.
   if (%_ArgumentsLength() === 0) {
-    result[result.length] = subject;
-    return result;
+    return [subject];
   }
 
   var length = subject.length;
-  var currentIndex = 0;
-  var startIndex = 0;
-
-  var sep;
   if (IS_REGEXP(separator)) {
-    sep = separator;
-    %_Log('regexp', 'regexp-split,%0S,%1r', [subject, sep]);
+    %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
   } else {
-    sep = ToString(separator);
+    separator = ToString(separator);
+    // If the separator string is empty then return the elements in the subject.
+    if (separator.length == 0) {
+      var result = $Array(length);
+      for (var i = 0; i < length; i++) result[i] = subject[i];
+      return result;
+    }
   }
 
   if (length === 0) {
-    if (splitMatch(sep, subject, 0, 0) != null) return result;
-    result[result.length] = subject;
-    return result;
+    if (splitMatch(separator, subject, 0, 0) != null) return [];
+    return [subject];
   }
 
+  var currentIndex = 0;
+  var startIndex = 0;
+  var result = [];
+
   while (true) {
 
     if (startIndex === length) {
@@ -538,7 +539,7 @@ function StringSplit(separator, limit) {
       return result;
     }
 
-    var lastMatchInfo = splitMatch(sep, subject, currentIndex, startIndex);
+    var lastMatchInfo = splitMatch(separator, subject, currentIndex, startIndex);
 
     if (IS_NULL(lastMatchInfo)) {
       result[result.length] = subject.slice(currentIndex, length);
@@ -553,21 +554,18 @@ function StringSplit(separator, limit) {
       continue;
     }
 
-    result[result.length] =
-        SubString(subject, currentIndex, lastMatchInfo[CAPTURE0]);
-    if (result.length === lim) return result;
+    result[result.length] = SubString(subject, currentIndex, lastMatchInfo[CAPTURE0]);
+    if (result.length === limit) return result;
 
     for (var i = 2; i < NUMBER_OF_CAPTURES(lastMatchInfo); i += 2) {
       var start = lastMatchInfo[CAPTURE(i)];
       var end = lastMatchInfo[CAPTURE(i + 1)];
       if (start != -1 && end != -1) {
-        result[result.length] = SubString(subject,
-                                          lastMatchInfo[CAPTURE(i)],
-                                          lastMatchInfo[CAPTURE(i + 1)]);
+        result[result.length] = SubString(subject, start, end);
       } else {
         result[result.length] = void 0;
       }
-      if (result.length === lim) return result;
+      if (result.length === limit) return result;
     }
 
     startIndex = currentIndex = endIndex;