Ignore:
Timestamp:
Dec 6, 2011, 9:21:11 AM (14 years ago)
Author:
[email protected]
Message:

Add 8 bit paths to global object functions
https://bugs.webkit.org/show_bug.cgi?id=73875

Added 8 bit paths for converions methods.

This is worth 1.5% on kraken audio-oscillator,
1.6% on stanford-crypto-ccm and 2.5% on
stanford-crypto-sha256-iterative. See bug for
a full report.

Reviewed by Oliver Hunt.

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::decode): Split into a templated helper.
(JSC::parseInt): Split into a templated helper.
(JSC::parseFloat): Added an 8 bit path
(JSC::globalFuncEscape): Added 8 bit path
(JSC::globalFuncUnescape): Added 8 bit path

  • runtime/JSStringBuilder.h:

(JSC::JSStringBuilder::append): New append for LChar

  • wtf/text/StringBuilder.h:

(WTF::StringBuilder::append): New append for LChar

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp

    r101151 r102146  
    7272}
    7373
    74 static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
     74template <typename CharType>
     75ALWAYS_INLINE
     76static JSValue decode(ExecState* exec, const CharType* characters, int length, const char* doNotUnescape, bool strict)
    7577{
    7678    JSStringBuilder builder;
    77     UString str = exec->argument(0).toString(exec);
    7879    int k = 0;
    79     int len = str.length();
    80     const UChar* d = str.characters();
    8180    UChar u = 0;
    82     while (k < len) {
    83         const UChar* p = d + k;
    84         UChar c = *p;
     81    while (k < length) {
     82        const CharType* p = characters + k;
     83        CharType c = *p;
    8584        if (c == '%') {
    8685            int charLen = 0;
    87             if (k <= len - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
    88                 const char b0 = Lexer<UChar>::convertHex(p[1], p[2]);
     86            if (k <= length - 3 && isASCIIHexDigit(p[1]) && isASCIIHexDigit(p[2])) {
     87                const char b0 = Lexer<CharType>::convertHex(p[1], p[2]);
    8988                const int sequenceLen = UTF8SequenceLength(b0);
    90                 if (sequenceLen != 0 && k <= len - sequenceLen * 3) {
     89                if (sequenceLen && k <= length - sequenceLen * 3) {
    9190                    charLen = sequenceLen * 3;
    9291                    char sequence[5];
    9392                    sequence[0] = b0;
    9493                    for (int i = 1; i < sequenceLen; ++i) {
    95                         const UChar* q = p + i * 3;
     94                        const CharType* q = p + i * 3;
    9695                        if (q[0] == '%' && isASCIIHexDigit(q[1]) && isASCIIHexDigit(q[2]))
    97                             sequence[i] = Lexer<UChar>::convertHex(q[1], q[2]);
     96                            sequence[i] = Lexer<CharType>::convertHex(q[1], q[2]);
    9897                        else {
    9998                            charLen = 0;
     
    120119                // The only case where we don't use "strict" mode is the "unescape" function.
    121120                // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
    122                 if (k <= len - 6 && p[1] == 'u'
     121                if (k <= length - 6 && p[1] == 'u'
    123122                        && isASCIIHexDigit(p[2]) && isASCIIHexDigit(p[3])
    124123                        && isASCIIHexDigit(p[4]) && isASCIIHexDigit(p[5])) {
     
    128127            }
    129128            if (charLen && (u == 0 || u >= 128 || !strchr(doNotUnescape, u))) {
    130                 c = u;
    131                 k += charLen - 1;
     129                if (u < 256)
     130                    builder.append(static_cast<LChar>(u));
     131                else
     132                    builder.append(u);
     133                k += charLen;
     134                continue;
    132135            }
    133136        }
     
    136139    }
    137140    return builder.build(exec);
     141}
     142
     143static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
     144{
     145    JSStringBuilder builder;
     146    UString str = exec->argument(0).toString(exec);
     147   
     148    if (str.is8Bit())
     149        return decode(exec, str.characters8(), str.length(), doNotUnescape, strict);
     150    return decode(exec, str.characters16(), str.length(), doNotUnescape, strict);
    138151}
    139152
     
    218231}
    219232
    220 static double parseInt(const UString& s, int radix)
     233template <typename CharType>
     234ALWAYS_INLINE
     235static double parseInt(const UString& s, const CharType* data, int radix)
    221236{
    222237    int length = s.length();
    223     const UChar* data = s.characters();
    224238    int p = 0;
    225239
     
    274288
    275289    return sign * number;
     290}
     291
     292static double parseInt(const UString& s, int radix)
     293{
     294    if (s.is8Bit())
     295        return parseInt(s, s.characters8(), radix);
     296    return parseInt(s, s.characters16(), radix);
    276297}
    277298
     
    427448    }
    428449
    429     const UChar* data = s.characters();
     450    if (s.is8Bit()) {
     451        const LChar* data = s.characters8();
     452        const LChar* end = data + size;
     453
     454        // Skip leading white space.
     455        for (; data < end; ++data) {
     456            if (!isStrWhiteSpace(*data))
     457                break;
     458        }
     459
     460        // Empty string.
     461        if (data == end)
     462            return std::numeric_limits<double>::quiet_NaN();
     463
     464        return jsStrDecimalLiteral(data, end);
     465    }
     466
     467    const UChar* data = s.characters16();
    430468    const UChar* end = data + size;
    431469
     
    565603    JSStringBuilder builder;
    566604    UString str = exec->argument(0).toString(exec);
    567     const UChar* c = str.characters();
     605    if (str.is8Bit()) {
     606        const LChar* c = str.characters8();
     607        for (unsigned k = 0; k < str.length(); k++, c++) {
     608            int u = c[0];
     609            if (u && strchr(do_not_escape, static_cast<char>(u)))
     610                builder.append(c, 1);
     611            else {
     612                char tmp[4];
     613                snprintf(tmp, sizeof(tmp), "%%%02X", u);
     614                builder.append(tmp);
     615            }
     616        }
     617
     618        return JSValue::encode(builder.build(exec));       
     619    }
     620
     621    const UChar* c = str.characters16();
    568622    for (unsigned k = 0; k < str.length(); k++, c++) {
    569623        int u = c[0];
     
    590644    int k = 0;
    591645    int len = str.length();
    592     while (k < len) {
    593         const UChar* c = str.characters() + k;
    594         UChar u;
    595         if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
    596             if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
    597                 u = Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]);
     646   
     647    if (str.is8Bit()) {
     648        const LChar* characters = str.characters8();
     649
     650        while (k < len) {
     651            const LChar* c = characters + k;
     652            if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
     653                if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
     654                    builder.append(Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]));
     655                    k += 5;
     656                }
     657            } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
     658                builder.append(Lexer<LChar>::convertHex(c[1], c[2]));
     659                k += 2;
     660            } else
     661                builder.append(*c);
     662            k++;
     663        }       
     664    } else {
     665        const UChar* characters = str.characters16();
     666
     667        while (k < len) {
     668            const UChar* c = characters + k;
     669            UChar u;
     670            if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
     671                if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
     672                    u = Lexer<UChar>::convertUnicode(c[2], c[3], c[4], c[5]);
     673                    c = &u;
     674                    k += 5;
     675                }
     676            } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
     677                u = UChar(Lexer<UChar>::convertHex(c[1], c[2]));
    598678                c = &u;
    599                 k += 5;
     679                k += 2;
    600680            }
    601         } else if (c[0] == '%' && k <= len - 3 && isASCIIHexDigit(c[1]) && isASCIIHexDigit(c[2])) {
    602             u = UChar(Lexer<UChar>::convertHex(c[1], c[2]));
    603             c = &u;
    604             k += 2;
    605         }
    606         k++;
    607         builder.append(*c);
     681            k++;
     682            builder.append(*c);
     683        }
    608684    }
    609685
Note: See TracChangeset for help on using the changeset viewer.