RexExp constructor last match properties should not rely on previous ovector
https://bugs.webkit.org/show_bug.cgi?id=82077

Reviewed by Oliver Hunt.

This change simplifies matching, and will enable subpattern results to be fully lazily generated in the future.

This patch changes the scheme used to lazily generate the last match properties of the RegExp object.
Instead of relying on the results in the ovector, we can instead lazily generate the subpatters using
a RegExpMatchesArray. To do so we just need to store the input, the regexp matched, and the match
location (the MatchResult). When the match is accessed or the input is set, we reify results. We use
a special value of setting the saved result to MatchResult::failed() to indicated that we're in a
reified state. This means that next time a match is performed, the store of the result will
automatically blow away the reified value.

* JavaScriptCore.xcodeproj/project.pbxproj:
    - Added new files.
* runtime/RegExp.cpp:
(JSC::RegExpFunctionalTestCollector::outputOneTest):
    - changed 'subPattern' -> 'subpattern' (there was a mix in JSC, 'subpattern' was more common).
* runtime/RegExpCachedResult.cpp: Added.
(JSC::RegExpCachedResult::visitChildren):
(JSC::RegExpCachedResult::lastResult):
(JSC::RegExpCachedResult::setInput):
    - New methods, mark GC objects, lazily create the matches array, and record a user provided input (via assignment to RegExp.inupt).
* runtime/RegExpCachedResult.h: Added.
(RegExpCachedResult):
    - Added new class.
(JSC::RegExpCachedResult::RegExpCachedResult):
(JSC::RegExpCachedResult::record):
(JSC::RegExpCachedResult::input):
    - Initialize the object, record the result of a RegExp match, access the stored input property.
* runtime/RegExpConstructor.cpp:
(JSC::RegExpConstructor::RegExpConstructor):
    - Initialize m_result/m_multiline properties.
(JSC::RegExpConstructor::visitChildren):
    - Make sure the cached results (or lazy source for them) are marked.
(JSC::RegExpConstructor::getBackref):
(JSC::RegExpConstructor::getLastParen):
(JSC::RegExpConstructor::getLeftContext):
(JSC::RegExpConstructor::getRightContext):
    - Moved from RegExpConstructor, moved to RegExpCachedResult, and using new caching scheme.
(JSC::regExpConstructorInput):
(JSC::setRegExpConstructorInput):
    - Changed to use RegExpCachedResult.
* runtime/RegExpConstructor.h:
(JSC::RegExpConstructor::create):
(RegExpConstructor):
(JSC::RegExpConstructor::setMultiline):
(JSC::RegExpConstructor::multiline):
    - Move multiline property onto the constructor object; it is not affected by the last match.
(JSC::RegExpConstructor::setInput):
(JSC::RegExpConstructor::input):
    - These defer to RegExpCachedResult.
(JSC::RegExpConstructor::performMatch):
* runtime/RegExpMatchesArray.cpp: Added.
(JSC::RegExpMatchesArray::visitChildren):
    - Eeeep! added missing visitChildren!
(JSC::RegExpMatchesArray::finishCreation):
(JSC::RegExpMatchesArray::reifyAllProperties):
(JSC::RegExpMatchesArray::reifyMatchProperty):
    - Moved from RegExpConstructor.cpp.
(JSC::RegExpMatchesArray::leftContext):
(JSC::RegExpMatchesArray::rightContext):
    - Since the match start/
* runtime/RegExpMatchesArray.h:
(RegExpMatchesArray):
    - Declare new methods & structure flags.
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::match):
    - performMatch now requires the JSString input, to cache.
* runtime/StringPrototype.cpp:
(JSC::removeUsingRegExpSearch):
(JSC::replaceUsingRegExpSearch):
(JSC::stringProtoFuncMatch):
(JSC::stringProtoFuncSearch):
    - performMatch now requires the JSString input, to cache.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@111889 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
new file mode 100644
index 0000000..0788145
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RegExpCachedResult.h"
+
+#include "RegExpMatchesArray.h"
+
+namespace JSC {
+
+void RegExpCachedResult::visitChildren(SlotVisitor& visitor)
+{
+    if (m_result) {
+        visitor.append(&m_lastInput);
+        visitor.append(&m_lastRegExp);
+    } else {
+        visitor.append(&m_reifiedInput);
+        visitor.append(&m_reifiedResult);
+    }
+}
+
+RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner)
+{
+    if (m_result) {
+        m_reifiedInput.set(exec->globalData(), owner, m_lastInput.get());
+        m_reifiedResult.set(exec->globalData(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result));
+        m_result = MatchResult::failed();
+    }
+    return m_reifiedResult.get();
+}
+
+void RegExpCachedResult::setInput(ExecState* exec, JSObject* owner, JSString* input)
+{
+    // Make sure we're reified, otherwise m_reifiedInput will be ignored.
+    lastResult(exec, owner);
+    ASSERT(!m_result);
+    m_reifiedInput.set(exec->globalData(), owner, input);
+}
+
+} // namespace JSC