2 * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
3 * Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2009 Torch Mobile, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <wtf/Assertions.h>
29 #include <wtf/OwnArrayPtr.h>
31 #include "yarr/RegexCompiler.h"
33 #include "yarr/RegexJIT.h"
35 #include "yarr/RegexInterpreter.h"
40 struct RegExpRepresentation {
42 Yarr::RegexCodeBlock m_regExpJITCode;
44 OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
48 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
51 , m_constructionError(0)
53 #if ENABLE(REGEXP_TRACING)
54 , m_rtMatchCallCount(0)
55 , m_rtMatchFoundCount(0)
57 , m_representation(adoptPtr(new RegExpRepresentation))
59 // NOTE: The global flag is handled on a case-by-case basis by functions like
60 // String::match and RegExpObject::match.
61 if (!flags.isNull()) {
62 if (flags.find('g') != notFound)
64 if (flags.find('i') != notFound)
65 m_flagBits |= IgnoreCase;
66 if (flags.find('m') != notFound)
67 m_flagBits |= Multiline;
76 PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
78 RefPtr<RegExp> res = adoptRef(new RegExp(globalData, pattern, flags));
79 #if ENABLE(REGEXP_TRACING)
80 globalData->addRegExpToTrace(res);
85 void RegExp::compile(JSGlobalData* globalData)
88 Yarr::jitCompileRegex(globalData, m_representation->m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, &globalData->m_regexAllocator, ignoreCase(), multiline());
90 m_representation->m_regExpBytecode = Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, &globalData->m_regexAllocator, ignoreCase(), multiline());
94 int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
99 #if ENABLE(REGEXP_TRACING)
100 m_rtMatchCallCount++;
103 if (static_cast<unsigned>(startOffset) > s.length() || s.isNull())
107 if (!!m_representation->m_regExpJITCode) {
109 if (m_representation->m_regExpBytecode) {
111 int offsetVectorSize = (m_numSubpatterns + 1) * 2;
113 Vector<int, 32> nonReturnedOvector;
115 ovector->resize(offsetVectorSize);
116 offsetVector = ovector->data();
118 nonReturnedOvector.resize(offsetVectorSize);
119 offsetVector = nonReturnedOvector.data();
122 ASSERT(offsetVector);
123 // Initialize offsetVector with the return value (index 0) and the
124 // first subpattern start indicies (even index values) set to -1.
125 // No need to init the subpattern end indicies.
126 for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)
127 offsetVector[j] = -1;
130 int result = Yarr::executeRegex(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector);
132 int result = Yarr::interpretRegex(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector);
135 ASSERT(result >= -1);;
137 #if ENABLE(REGEXP_TRACING)
139 m_rtMatchFoundCount++;
148 #if ENABLE(REGEXP_TRACING)
149 void RegExp::printTraceData()
151 char formattedPattern[41];
154 strncpy(rawPattern, m_pattern.utf8().data(), 40);
155 rawPattern[40]= '\0';
157 int pattLen = strlen(rawPattern);
159 snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
162 Yarr::RegexCodeBlock& codeBlock = m_representation->m_regExpJITCode;
165 if (codeBlock.getFallback())
166 sprintf(jitAddr, "fallback");
168 sprintf(jitAddr, "0x%014lx", reinterpret_cast<unsigned long int>(codeBlock.getAddr()));
170 const char* jitAddr = "JIT Off";
173 printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);