OSDN Git Service

Merge WebKit at r73109: Initial merge by git.
[android-x86/external-webkit.git] / JavaScriptCore / runtime / RegExp.cpp
1 /*
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.
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "config.h"
23 #include "RegExp.h"
24 #include "Lexer.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <wtf/Assertions.h>
29 #include <wtf/OwnArrayPtr.h>
30
31 #include "yarr/RegexCompiler.h"
32 #if ENABLE(YARR_JIT)
33 #include "yarr/RegexJIT.h"
34 #else
35 #include "yarr/RegexInterpreter.h"
36 #endif
37
38 namespace JSC {
39
40 struct RegExpRepresentation {
41 #if ENABLE(YARR_JIT)
42     Yarr::RegexCodeBlock m_regExpJITCode;
43 #else
44     OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
45 #endif
46 };
47
48 inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
49     : m_pattern(pattern)
50     , m_flagBits(0)
51     , m_constructionError(0)
52     , m_numSubpatterns(0)
53 #if ENABLE(REGEXP_TRACING)
54     , m_rtMatchCallCount(0)
55     , m_rtMatchFoundCount(0)
56 #endif
57     , m_representation(adoptPtr(new RegExpRepresentation))
58 {
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)
63             m_flagBits |= Global;
64         if (flags.find('i') != notFound)
65             m_flagBits |= IgnoreCase;
66         if (flags.find('m') != notFound)
67             m_flagBits |= Multiline;
68     }
69     compile(globalData);
70 }
71
72 RegExp::~RegExp()
73 {
74 }
75
76 PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
77 {
78     RefPtr<RegExp> res = adoptRef(new RegExp(globalData, pattern, flags));
79 #if ENABLE(REGEXP_TRACING)
80     globalData->addRegExpToTrace(res);
81 #endif
82     return res.release();
83 }
84
85 void RegExp::compile(JSGlobalData* globalData)
86 {
87 #if ENABLE(YARR_JIT)
88     Yarr::jitCompileRegex(globalData, m_representation->m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, &globalData->m_regexAllocator, ignoreCase(), multiline());
89 #else
90     m_representation->m_regExpBytecode = Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, &globalData->m_regexAllocator, ignoreCase(), multiline());
91 #endif
92 }
93
94 int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
95 {
96     if (startOffset < 0)
97         startOffset = 0;
98     
99 #if ENABLE(REGEXP_TRACING)
100     m_rtMatchCallCount++;
101 #endif
102
103     if (static_cast<unsigned>(startOffset) > s.length() || s.isNull())
104         return -1;
105
106 #if ENABLE(YARR_JIT)
107     if (!!m_representation->m_regExpJITCode) {
108 #else
109     if (m_representation->m_regExpBytecode) {
110 #endif
111         int offsetVectorSize = (m_numSubpatterns + 1) * 2;
112         int* offsetVector;
113         Vector<int, 32> nonReturnedOvector;
114         if (ovector) {
115             ovector->resize(offsetVectorSize);
116             offsetVector = ovector->data();
117         } else {
118             nonReturnedOvector.resize(offsetVectorSize);
119             offsetVector = nonReturnedOvector.data();
120         }
121
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;
128
129 #if ENABLE(YARR_JIT)
130         int result = Yarr::executeRegex(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector);
131 #else
132         int result = Yarr::interpretRegex(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector);
133 #endif
134
135         ASSERT(result >= -1);;
136         
137 #if ENABLE(REGEXP_TRACING)
138         if (result != -1)
139             m_rtMatchFoundCount++;
140 #endif
141
142         return result;
143     }
144
145     return -1;
146 }
147
148 #if ENABLE(REGEXP_TRACING)
149     void RegExp::printTraceData()
150     {
151         char formattedPattern[41];
152         char rawPattern[41];
153         
154         strncpy(rawPattern, m_pattern.utf8().data(), 40);
155         rawPattern[40]= '\0';
156         
157         int pattLen = strlen(rawPattern);
158         
159         snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
160
161 #if ENABLE(YARR_JIT)
162         Yarr::RegexCodeBlock& codeBlock = m_representation->m_regExpJITCode;
163
164         char jitAddr[20];
165         if (codeBlock.getFallback())
166             sprintf(jitAddr, "fallback");
167         else
168             sprintf(jitAddr, "0x%014lx", reinterpret_cast<unsigned long int>(codeBlock.getAddr()));
169 #else
170         const char* jitAddr = "JIT Off";
171 #endif
172         
173         printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);
174     }
175 #endif
176     
177 } // namespace JSC