2009-02-12 Darin Adler <darin@apple.com>
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Feb 2009 16:16:50 +0000 (16:16 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Feb 2009 16:16:50 +0000 (16:16 +0000)
        Reviewed by Oliver Hunt and Alexey Proskuryakov.

        Speed up a couple string functions.

        * runtime/StringPrototype.cpp:
        (JSC::stringProtoFuncIndexOf): Added a fast path for cases where the second
        argument is either missing or an integer.
        (JSC::stringProtoFuncBig): Use jsNontrivialString since the string is guaranteed
        to be 2 or more characters long.
        (JSC::stringProtoFuncSmall): Ditto.
        (JSC::stringProtoFuncBlink): Ditto.
        (JSC::stringProtoFuncBold): Ditto.
        (JSC::stringProtoFuncItalics): Ditto.
        (JSC::stringProtoFuncStrike): Ditto.
        (JSC::stringProtoFuncSub): Ditto.
        (JSC::stringProtoFuncSup): Ditto.
        (JSC::stringProtoFuncFontcolor): Ditto.
        (JSC::stringProtoFuncFontsize): Make the fast path Sam recently added even faster
        by avoiding all but the minimum memory allocation.
        (JSC::stringProtoFuncAnchor): Use jsNontrivialString.
        (JSC::stringProtoFuncLink): Added a fast path.

        * runtime/UString.cpp:
        (JSC::UString::find): Added a fast path for single-character search strings.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40975 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/Configurations/JavaScriptCore.xcconfig
JavaScriptCore/runtime/StringPrototype.cpp
JavaScriptCore/runtime/UString.cpp

index 4062f5b..f337755 100644 (file)
@@ -1,3 +1,30 @@
+2009-02-12  Darin Adler  <darin@apple.com>
+
+        Reviewed by Oliver Hunt and Alexey Proskuryakov.
+
+        Speed up a couple string functions.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::stringProtoFuncIndexOf): Added a fast path for cases where the second
+        argument is either missing or an integer.
+        (JSC::stringProtoFuncBig): Use jsNontrivialString since the string is guaranteed
+        to be 2 or more characters long.
+        (JSC::stringProtoFuncSmall): Ditto.
+        (JSC::stringProtoFuncBlink): Ditto.
+        (JSC::stringProtoFuncBold): Ditto.
+        (JSC::stringProtoFuncItalics): Ditto.
+        (JSC::stringProtoFuncStrike): Ditto.
+        (JSC::stringProtoFuncSub): Ditto.
+        (JSC::stringProtoFuncSup): Ditto.
+        (JSC::stringProtoFuncFontcolor): Ditto.
+        (JSC::stringProtoFuncFontsize): Make the fast path Sam recently added even faster
+        by avoiding all but the minimum memory allocation.
+        (JSC::stringProtoFuncAnchor): Use jsNontrivialString.
+        (JSC::stringProtoFuncLink): Added a fast path.
+
+        * runtime/UString.cpp:
+        (JSC::UString::find): Added a fast path for single-character search strings.
+
 2009-02-13  David Levin  <levin@chromium.org>
 
         Reviewed by Darin Adler.
index ef199d2..e942e42 100644 (file)
@@ -14,10 +14,3 @@ PRODUCT_NAME = JavaScriptCore;
 
 // This needs to be kept sorted, and in sync with FEATURE_DEFINES in WebCore.xcconfig, WebKit.xcconfig and the default settings of build-webkit.
 FEATURE_DEFINES = ENABLE_DATABASE ENABLE_DOM_STORAGE ENABLE_ICONDATABASE ENABLE_OFFLINE_WEB_APPLICATIONS ENABLE_SVG ENABLE_SVG_ANIMATION ENABLE_SVG_AS_IMAGE ENABLE_SVG_FONTS ENABLE_SVG_FOREIGN_OBJECT ENABLE_SVG_USE ENABLE_VIDEO ENABLE_WORKERS ENABLE_XPATH ENABLE_XSLT;
-
-OTHER_CFLAGS = $(OTHER_CFLAGS_$(CONFIGURATION)_$(CURRENT_VARIANT));
-OTHER_CFLAGS_Release_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL));
-OTHER_CFLAGS_Production_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL));
-OTHER_CFLAGS_normal_0310 = $(OTHER_CFLAGS_normal_GCC_42);
-OTHER_CFLAGS_normal_0320 = $(OTHER_CFLAGS_normal_GCC_42);
-OTHER_CFLAGS_normal_GCC_42 = -fomit-frame-pointer -funwind-tables;
index 2dd49d4..9c58f85 100644 (file)
@@ -374,12 +374,21 @@ JSValuePtr stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValuePtr thisVal
     JSValuePtr a0 = args.at(exec, 0);
     JSValuePtr a1 = args.at(exec, 1);
     UString u2 = a0.toString(exec);
-    double dpos = a1.toInteger(exec);
-    if (dpos < 0)
-        dpos = 0;
-    else if (dpos > len)
-        dpos = len;
-    return jsNumber(exec, s.find(u2, static_cast<int>(dpos)));
+    int pos;
+    if (a1.isUndefined())
+        pos = 0;
+    else if (a1.isUInt32Fast())
+        pos = min<uint32_t>(a1.getUInt32Fast(), len);
+    else {
+        double dpos = a1.toInteger(exec);
+        if (dpos < 0)
+            dpos = 0;
+        else if (dpos > len)
+            dpos = len;
+        pos = static_cast<int>(dpos);
+    }
+
+    return jsNumber(exec, s.find(u2, pos));
 }
 
 JSValuePtr stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
@@ -696,25 +705,25 @@ JSValuePtr stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValuePtr t
 JSValuePtr stringProtoFuncBig(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<big>" + s + "</big>");
+    return jsNontrivialString(exec, "<big>" + s + "</big>");
 }
 
 JSValuePtr stringProtoFuncSmall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<small>" + s + "</small>");
+    return jsNontrivialString(exec, "<small>" + s + "</small>");
 }
 
 JSValuePtr stringProtoFuncBlink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<blink>" + s + "</blink>");
+    return jsNontrivialString(exec, "<blink>" + s + "</blink>");
 }
 
 JSValuePtr stringProtoFuncBold(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<b>" + s + "</b>");
+    return jsNontrivialString(exec, "<b>" + s + "</b>");
 }
 
 JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
@@ -726,32 +735,32 @@ JSValuePtr stringProtoFuncFixed(ExecState* exec, JSObject*, JSValuePtr thisValue
 JSValuePtr stringProtoFuncItalics(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<i>" + s + "</i>");
+    return jsNontrivialString(exec, "<i>" + s + "</i>");
 }
 
 JSValuePtr stringProtoFuncStrike(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<strike>" + s + "</strike>");
+    return jsNontrivialString(exec, "<strike>" + s + "</strike>");
 }
 
 JSValuePtr stringProtoFuncSub(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<sub>" + s + "</sub>");
+    return jsNontrivialString(exec, "<sub>" + s + "</sub>");
 }
 
 JSValuePtr stringProtoFuncSup(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
 {
     UString s = thisValue.toThisString(exec);
-    return jsString(exec, "<sup>" + s + "</sup>");
+    return jsNontrivialString(exec, "<sup>" + s + "</sup>");
 }
 
 JSValuePtr stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValuePtr a0 = args.at(exec, 0);
-    return jsString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
+    return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>");
 }
 
 JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
@@ -760,68 +769,78 @@ JSValuePtr stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValuePtr thisVa
     JSValuePtr a0 = args.at(exec, 0);
 
     uint32_t smallInteger;
-    if (a0.getUInt32(smallInteger)) {
-        switch (smallInteger) {
-            case 1: {
-                UString result = "<font size=\"1\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 2: {
-                UString result = "<font size=\"2\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 3: {
-                UString result = "<font size=\"3\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 4: {
-                UString result = "<font size=\"4\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 5: {
-                UString result = "<font size=\"5\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 6: {
-                UString result = "<font size=\"6\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-            case 7: {
-                UString result = "<font size=\"7\">";
-                result.append(s);
-                result.append("</font>");
-                return jsString(exec, result);
-            }
-        }
+    if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
+        unsigned stringSize = s.size();
+        unsigned bufferSize = 22 + stringSize;
+        UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
+        if (!buffer)
+            return jsUndefined();
+        buffer[0] = '<';
+        buffer[1] = 'f';
+        buffer[2] = 'o';
+        buffer[3] = 'n';
+        buffer[4] = 't';
+        buffer[5] = ' ';
+        buffer[6] = 's';
+        buffer[7] = 'i';
+        buffer[8] = 'z';
+        buffer[9] = 'e';
+        buffer[10] = '=';
+        buffer[11] = '"';
+        buffer[12] = '0' + smallInteger;
+        buffer[13] = '"';
+        buffer[14] = '>';
+        memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar));
+        buffer[15 + stringSize] = '<';
+        buffer[16 + stringSize] = '/';
+        buffer[17 + stringSize] = 'f';
+        buffer[18 + stringSize] = 'o';
+        buffer[19 + stringSize] = 'n';
+        buffer[20 + stringSize] = 't';
+        buffer[21 + stringSize] = '>';
+        return jsNontrivialString(exec, UString(buffer, bufferSize, false));
     }
 
-    return jsString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
+    return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>");
 }
 
 JSValuePtr stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValuePtr a0 = args.at(exec, 0);
-    return jsString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
+    return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>");
 }
 
 JSValuePtr stringProtoFuncLink(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
 {
     UString s = thisValue.toThisString(exec);
     JSValuePtr a0 = args.at(exec, 0);
-    return jsString(exec, "<a href=\"" + a0.toString(exec) + "\">" + s + "</a>");
+    UString linkText = a0.toString(exec);
+
+    unsigned linkTextSize = linkText.size();
+    unsigned stringSize = s.size();
+    unsigned bufferSize = 15 + linkTextSize + stringSize;
+    UChar* buffer = static_cast<UChar*>(tryFastMalloc(bufferSize * sizeof(UChar)));
+    if (!buffer)
+        return jsUndefined();
+    buffer[0] = '<';
+    buffer[1] = 'a';
+    buffer[2] = ' ';
+    buffer[3] = 'h';
+    buffer[4] = 'r';
+    buffer[5] = 'e';
+    buffer[6] = 'f';
+    buffer[7] = '=';
+    buffer[8] = '"';
+    memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar));
+    buffer[9 + linkTextSize] = '"';
+    buffer[10 + linkTextSize] = '>';
+    memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar));
+    buffer[11 + linkTextSize + stringSize] = '<';
+    buffer[12 + linkTextSize + stringSize] = '/';
+    buffer[13 + linkTextSize + stringSize] = 'a';
+    buffer[14 + linkTextSize + stringSize] = '>';
+    return jsNontrivialString(exec, UString(buffer, bufferSize, false));
 }
 
 } // namespace JSC
index 1ef878d..8cb12cf 100644 (file)
@@ -1419,12 +1419,24 @@ uint32_t UString::toStrictUInt32(bool* ok) const
 
 int UString::find(const UString& f, int pos) const
 {
-    int sz = size();
     int fsz = f.size();
-    if (sz < fsz)
-        return -1;
+
     if (pos < 0)
         pos = 0;
+
+    if (fsz == 1) {
+        UChar ch = f[0];
+        const UChar* end = data() + size();
+        for (const UChar* c = data() + pos; c < end; c++) {
+            if (*c == ch)
+                return static_cast<int>(c - data());
+        }
+        return -1;
+    }
+
+    int sz = size();
+    if (sz < fsz)
+        return -1;
     if (fsz == 0)
         return pos;
     const UChar* end = data() + sz - fsz;