Changeset 62148 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Jun 29, 2010, 3:01:29 PM (15 years ago)
Author:
[email protected]
Message:

2010-06-29 Michael Saboff <[email protected]>

Reviewed by Darin Adler.

Bug 41238 - RegExp performance slow on Dromaeo benchmark

Other javascript engines appear to cache prior results of regular
expression operations.

Suggest adding some sort of caching mechanism to regular expression
processing.

Added a single entry cache of match() results to RegExp class.

Also added performance improvements to UString == operator.
First check the impls for equality. Then get the length of
each of the non-null impls. Next check the sizes for equality.
Then check the data for the case of different impls that point
to the same data (most likely due to substrings from the beginning of
another string). Lastly we check the underlying data for equality.

  • runtime/RegExp.cpp: (JSC::RegExp::RegExp): (JSC::RegExp::match):
  • runtime/RegExp.h:
  • runtime/UString.h: (JSC::operator==):
Location:
trunk/JavaScriptCore/runtime
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/RegExp.cpp

    r61927 r62148  
    5252    , m_constructionError(0)
    5353    , m_numSubpatterns(0)
     54    , m_lastMatchStart(-1)
    5455{
    5556    compile(globalData);
     
    6162    , m_constructionError(0)
    6263    , m_numSubpatterns(0)
     64    , m_lastMatchStart(-1)
    6365{
    6466    // NOTE: The global flag is handled on a case-by-case basis by functions like
     
    110112        ovector->resize(0);
    111113
    112     if (static_cast<unsigned>(startOffset) > s.size() || s.isNull())
     114    if (static_cast<unsigned>(startOffset) > s.size() || s.isNull()) {
     115        m_lastMatchString = UString();
     116        m_lastMatchStart = -1;
     117        m_lastOVector.shrink(0);
    113118        return -1;
     119    }
     120   
     121    // Perform check to see if this match call is the same as the last match invocation
     122    // and if it is return the prior result.
     123    if ((startOffset == m_lastMatchStart) && (s.rep() == m_lastMatchString.rep())) {
     124        if (ovector)
     125            *ovector = m_lastOVector;
     126       
     127        if (m_lastOVector.isEmpty())
     128            return -1;
     129
     130        return m_lastOVector.at(0);
     131    }
    114132
    115133#if ENABLE(YARR_JIT)
     
    148166                ovector->clear();
    149167        }
     168       
     169        m_lastMatchString = s;
     170        m_lastMatchStart = startOffset;
     171
     172        if (ovector)
     173            m_lastOVector = *ovector;
     174        else
     175            m_lastOVector = nonReturnedOvector;
     176
    150177        return result;
    151178    }
     179
     180    m_lastMatchString = UString();
     181    m_lastMatchStart = -1;
     182    m_lastOVector.shrink(0);
    152183
    153184    return -1;
  • trunk/JavaScriptCore/runtime/RegExp.h

    r61927 r62148  
    6868        const char* m_constructionError;
    6969        unsigned m_numSubpatterns;
     70        UString m_lastMatchString;
     71        int m_lastMatchStart;
     72        Vector<int, 32> m_lastOVector;
    7073
    7174#if ENABLE(YARR_JIT)
  • trunk/JavaScriptCore/runtime/UString.h

    r60332 r62148  
    159159    ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
    160160    {
    161         unsigned size = s1.size();
    162         switch (size) {
    163         case 0:
    164             return !s2.size();
     161        UString::Rep* rep1 = s1.rep();
     162        UString::Rep* rep2 = s2.rep();
     163        unsigned size1 = 0;
     164        unsigned size2 = 0;
     165
     166        if (rep1 == rep2) // If they're the same rep, they're equal.
     167            return true;
     168       
     169        if (rep1)
     170            size1 = rep1->length();
     171           
     172        if (rep2)
     173            size2 = rep2->length();
     174           
     175        if (size1 != size2) // If the lengths are not the same, we're done.
     176            return false;
     177       
     178        if (!size1)
     179            return true;
     180       
     181        // At this point we know
     182        //   (a) that the strings are the same length and
     183        //   (b) that they are greater than zero length.
     184        const UChar* d1 = rep1->characters();
     185        const UChar* d2 = rep2->characters();
     186       
     187        if (d1 == d2) // Check to see if the data pointers are the same.
     188            return true;
     189       
     190        // Do quick checks for sizes 1 and 2.
     191        switch (size1) {
    165192        case 1:
    166             return s2.size() == 1 && s1.data()[0] == s2.data()[0];
    167         case 2: {
    168             if (s2.size() != 2)
    169                 return false;
    170             const UChar* d1 = s1.data();
    171             const UChar* d2 = s2.data();
     193            return d1[0] == d2[0];
     194        case 2:
    172195            return (d1[0] == d2[0]) & (d1[1] == d2[1]);
    173         }
    174196        default:
    175             return s2.size() == size && memcmp(s1.data(), s2.data(), size * sizeof(UChar)) == 0;
     197            return memcmp(d1, d2, size1 * sizeof(UChar)) == 0;
    176198        }
    177199    }
Note: See TracChangeset for help on using the changeset viewer.