2009-07-03 Yong Li <yong.li@torchmobile.com>
authormjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 4 Jul 2009 14:21:30 +0000 (14:21 +0000)
committermjs@apple.com <mjs@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 4 Jul 2009 14:21:30 +0000 (14:21 +0000)
        Reviewed by Maciej Stachowiak (and revised slightly)

        RegExp::match to be optimized
        https://bugs.webkit.org/show_bug.cgi?id=26957

        Allow regexp matching to use Vectors with inline capacity instead of
        allocating a new ovector buffer every time.

        ~5% speedup on SunSpider string-unpack-code test, 0.3% on SunSpider overall.

        * runtime/RegExp.cpp:
        (JSC::RegExp::match):
        * runtime/RegExp.h:
        * runtime/RegExpConstructor.cpp:
        (JSC::RegExpConstructorPrivate::RegExpConstructorPrivate):
        (JSC::RegExpConstructorPrivate::lastOvector):
        (JSC::RegExpConstructorPrivate::tempOvector):
        (JSC::RegExpConstructorPrivate::changeLastOvector):
        (JSC::RegExpConstructor::performMatch):
        (JSC::RegExpMatchesArray::RegExpMatchesArray):
        (JSC::RegExpMatchesArray::fillArrayInstance):
        (JSC::RegExpConstructor::getBackref):
        (JSC::RegExpConstructor::getLastParen):
        (JSC::RegExpConstructor::getLeftContext):
        (JSC::RegExpConstructor::getRightContext):
        * runtime/StringPrototype.cpp:
        (JSC::stringProtoFuncSplit):

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

JavaScriptCore/ChangeLog
JavaScriptCore/runtime/RegExp.cpp
JavaScriptCore/runtime/RegExp.h
JavaScriptCore/runtime/RegExpConstructor.cpp
JavaScriptCore/runtime/StringPrototype.cpp

index 037b84c44b7f368bd8a27e90d6a3c680748e9bc1..c035840c39a7b2cec353efa81d3fea317196769a 100644 (file)
@@ -1,3 +1,33 @@
+2009-07-03  Yong Li  <yong.li@torchmobile.com>
+
+        Reviewed by Maciej Stachowiak (and revised slightly)
+
+        RegExp::match to be optimized
+        https://bugs.webkit.org/show_bug.cgi?id=26957
+
+        Allow regexp matching to use Vectors with inline capacity instead of
+        allocating a new ovector buffer every time.
+        
+        ~5% speedup on SunSpider string-unpack-code test, 0.3% on SunSpider overall.
+
+        * runtime/RegExp.cpp:
+        (JSC::RegExp::match):
+        * runtime/RegExp.h:
+        * runtime/RegExpConstructor.cpp:
+        (JSC::RegExpConstructorPrivate::RegExpConstructorPrivate):
+        (JSC::RegExpConstructorPrivate::lastOvector):
+        (JSC::RegExpConstructorPrivate::tempOvector):
+        (JSC::RegExpConstructorPrivate::changeLastOvector):
+        (JSC::RegExpConstructor::performMatch):
+        (JSC::RegExpMatchesArray::RegExpMatchesArray):
+        (JSC::RegExpMatchesArray::fillArrayInstance):
+        (JSC::RegExpConstructor::getBackref):
+        (JSC::RegExpConstructor::getLastParen):
+        (JSC::RegExpConstructor::getLeftContext):
+        (JSC::RegExpConstructor::getRightContext):
+        * runtime/StringPrototype.cpp:
+        (JSC::stringProtoFuncSplit):
+
 2009-06-30  Kwang Yul Seo  <skyul@company100.net>
 
         Reviewed by Eric Seidel.
index 857a316906c4bcb8859819a3bb9ef9cb1de795b0..7dd4a8ffdede0b04eead102d02bffca35b2eb10f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
  *  Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -110,7 +111,7 @@ void RegExp::compile(JSGlobalData* globalData)
 #endif
 }
 
-int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
+int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
 {
     if (startOffset < 0)
         startOffset = 0;
@@ -126,16 +127,20 @@ int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
     if (m_regExpBytecode) {
 #endif
         int offsetVectorSize = (m_numSubpatterns + 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
-        int* offsetVector = new int [offsetVectorSize];
+        int* offsetVector;
+        Vector<int, 32> nonReturnedOvector;
+        if (ovector) {
+            ovector->resize(offsetVectorSize);
+            offsetVector = ovector->data();
+        } else {
+            nonReturnedOvector.resize(offsetVectorSize);
+            offsetVector = nonReturnedOvector.data();
+        }
+
         ASSERT(offsetVector);
         for (int j = 0; j < offsetVectorSize; ++j)
             offsetVector[j] = -1;
 
-        OwnArrayPtr<int> nonReturnedOvector;
-        if (!ovector)
-            nonReturnedOvector.set(offsetVector);
-        else
-            ovector->set(offsetVector);
 
 #if ENABLE(YARR_JIT)
         int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize);
@@ -177,7 +182,7 @@ void RegExp::compile(JSGlobalData* globalData)
     m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
 }
 
-int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
+int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
 {
     if (startOffset < 0)
         startOffset = 0;
@@ -190,17 +195,19 @@ int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
 #if ENABLE(WREC)
     if (m_wrecFunction) {
         int offsetVectorSize = (m_numSubpatterns + 1) * 2;
-        int* offsetVector = new int [offsetVectorSize];
+        int* offsetVector;
+        Vector<int, 32> nonReturnedOvector;
+        if (ovector) {
+            ovector->resize(offsetVectorSize);
+            offsetVector = ovector->data();
+        } else {
+            nonReturnedOvector.resize(offsetVectorSize);
+            offsetVector = nonReturnedOvector.data();
+        }
         ASSERT(offsetVector);
         for (int j = 0; j < offsetVectorSize; ++j)
             offsetVector[j] = -1;
 
-        OwnArrayPtr<int> nonReturnedOvector;
-        if (!ovector)
-            nonReturnedOvector.set(offsetVector);
-        else
-            ovector->set(offsetVector);
-
         int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector);
 
         if (result < 0) {
@@ -226,8 +233,8 @@ int RegExp::match(const UString& s, int startOffset, OwnArrayPtr<int>* ovector)
             offsetVector = fixedSizeOffsetVector;
         } else {
             offsetVectorSize = (m_numSubpatterns + 1) * 3;
-            offsetVector = new int [offsetVectorSize];
-            ovector->set(offsetVector);
+            ovector->resize(offsetVectorSize);
+            offsetVector = ovector->data();
         }
 
         int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
index f3be656d76e475be32ce06de41edf362d4e4c40b..24d4199f4c7478985cd7d3780736982708714d01 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -53,7 +54,7 @@ namespace JSC {
         bool isValid() const { return !m_constructionError; }
         const char* errorMessage() const { return m_constructionError; }
 
-        int match(const UString&, int startOffset, OwnArrayPtr<int>* ovector = 0);
+        int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0);
         unsigned numSubpatterns() const { return m_numSubpatterns; }
 
     private:
index bcd0d07906759f0cdfc9b51caacc3d72884f16ab..d1d59bdbcd9f2ab9c8ec8d09f7f20a06cbf9827b 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -93,14 +94,21 @@ struct RegExpConstructorPrivate {
     RegExpConstructorPrivate()
         : lastNumSubPatterns(0)
         , multiline(false)
+        , lastOvectorIndex(0)
     {
     }
 
+    const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; }
+    Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; }
+    Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; }
+    void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; }
+
     UString input;
     UString lastInput;
-    OwnArrayPtr<int> lastOvector;
-    unsigned lastNumSubPatterns : 31;
+    Vector<int, 32> ovector[2];
+    unsigned lastNumSubPatterns : 30;
     bool multiline : 1;
+    unsigned lastOvectorIndex : 1;
 };
 
 RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
@@ -121,20 +129,19 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> stru
 */
 void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
 {
-    OwnArrayPtr<int> tmpOvector;
-    position = r->match(s, startOffset, &tmpOvector);
+    position = r->match(s, startOffset, &d->tempOvector());
 
     if (ovector)
-        *ovector = tmpOvector.get();
+        *ovector = d->tempOvector().data();
 
     if (position != -1) {
-        ASSERT(tmpOvector);
+        ASSERT(!d->tempOvector().isEmpty());
 
-        length = tmpOvector[1] - tmpOvector[0];
+        length = d->tempOvector()[1] - d->tempOvector()[0];
 
         d->input = s;
         d->lastInput = s;
-        d->lastOvector.set(tmpOvector.release());
+        d->changeLastOvector();
         d->lastNumSubPatterns = r->numSubpatterns();
     }
 }
@@ -147,8 +154,8 @@ RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate
     d->lastInput = data->lastInput;
     d->lastNumSubPatterns = data->lastNumSubPatterns;
     unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
-    d->lastOvector.set(new int[offsetVectorSize]);
-    memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int));
+    d->lastOvector().resize(offsetVectorSize);
+    memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int));
     // d->multiline is not needed, and remains uninitialized
 
     setLazyCreationData(d);
@@ -167,13 +174,13 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
     unsigned lastNumSubpatterns = d->lastNumSubPatterns;
 
     for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
-        int start = d->lastOvector[2 * i];
+        int start = d->lastOvector()[2 * i];
         if (start >= 0)
-            JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start));
+            JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start));
     }
 
     PutPropertySlot slot;
-    JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0]), slot);
+    JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector()[0]), slot);
     JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot);
 
     delete d;
@@ -187,10 +194,10 @@ JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
 
 JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
 {
-    if (d->lastOvector && i <= d->lastNumSubPatterns) {
-        int start = d->lastOvector[2 * i];
+    if (!d->lastOvector().isEmpty() && i <= d->lastNumSubPatterns) {
+        int start = d->lastOvector()[2 * i];
         if (start >= 0)
-            return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+            return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
     }
     return jsEmptyString(exec);
 }
@@ -200,24 +207,24 @@ JSValue RegExpConstructor::getLastParen(ExecState* exec) const
     unsigned i = d->lastNumSubPatterns;
     if (i > 0) {
         ASSERT(d->lastOvector);
-        int start = d->lastOvector[2 * i];
+        int start = d->lastOvector()[2 * i];
         if (start >= 0)
-            return jsSubstring(exec, d->lastInput, start, d->lastOvector[2 * i + 1] - start);
+            return jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start);
     }
     return jsEmptyString(exec);
 }
 
 JSValue RegExpConstructor::getLeftContext(ExecState* exec) const
 {
-    if (d->lastOvector)
-        return jsSubstring(exec, d->lastInput, 0, d->lastOvector[0]);
+    if (!d->lastOvector().isEmpty())
+        return jsSubstring(exec, d->lastInput, 0, d->lastOvector()[0]);
     return jsEmptyString(exec);
 }
 
 JSValue RegExpConstructor::getRightContext(ExecState* exec) const
 {
-    if (d->lastOvector)
-        return jsSubstring(exec, d->lastInput, d->lastOvector[1], d->lastInput.size() - d->lastOvector[1]);
+    if (!d->lastOvector().isEmpty())
+        return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.size() - d->lastOvector()[1]);
     return jsEmptyString(exec);
 }
     
index d6939cb5b41b45f3018a70fab03909ca2c9e294e..ceb6b1ea2bffa8408a8394a295c648341e2f4604 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2009 Torch Mobile, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -575,7 +576,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue t
         }
         int pos = 0;
         while (i != limit && pos < s.size()) {
-            OwnArrayPtr<int> ovector;
+            Vector<int, 32> ovector;
             int mpos = reg->match(s, pos, &ovector);
             if (mpos < 0)
                 break;