[prev in list] [next in list] [prev in thread] [next in thread]
List: webkit-changes
Subject: [webkit-changes] [74600] trunk/JavaScriptCore
From: barraclough () apple ! com
Date: 2010-12-24 1:40:58
Message-ID: 20101224014059.2136760AE76C () beta ! macosforge ! org
[Download RAW message or body]
[Attachment #2 (text/html)]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[74600] trunk/JavaScriptCore</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: \
verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: \
bold} #msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: \
bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: \
6px; } #logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em \
0; } #logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg \
h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; } \
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; \
} #logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: \
-1.5em; padding-left: 1.5em; } #logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em \
1em 0 1em; background: white;} #logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid \
#fa0; border-bottom: 1px solid #fa0; background: #fff; } #logmsg table th { \
text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted \
#fa0; } #logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: \
0.2em 0.5em; } #logmsg table thead th { text-align: center; border-bottom: 1px solid \
#fa0; } #logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: \
6px; } #patch { width: 100%; }
#patch h4 {font-family: \
verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, \
#patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins \
{background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del \
{background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, \
.info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a \
href="http://trac.webkit.org/projects/webkit/changeset/74600">74600</a></dd> \
<dt>Author</dt> <dd>barraclough@apple.com</dd> <dt>Date</dt> <dd>2010-12-23 17:40:54 \
-0800 (Thu, 23 Dec 2010)</dd> </dl>
<h3>Log Message</h3>
<pre>Rename RegexCompiler.cpp to RegexPattern.cpp.
Implicitly call compileRegex from RegexPattern's constructor.
Reviewed by Sam Weinig.
* Android.mk:
* CMakeLists.txt:
* GNUmakefile.am:
* JavaScriptCore.gypi:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* runtime/RegExp.cpp:
(JSC::RegExp::compile):
* yarr/RegexCompiler.cpp: Removed.
* yarr/RegexCompiler.h: Removed.
* yarr/RegexInterpreter.cpp:
* yarr/RegexJIT.cpp:
* yarr/RegexPattern.cpp: Copied from JavaScriptCore/yarr/RegexCompiler.cpp.
(JSC::Yarr::compileRegex):
(JSC::Yarr::RegexPattern::RegexPattern):
* yarr/RegexPattern.h:</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreAndroidmk">trunk/JavaScriptCore/Android.mk</a></li>
<li><a href="#trunkJavaScriptCoreCMakeListstxt">trunk/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCoreGNUmakefileam">trunk/JavaScriptCore/GNUmakefile.am</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCoregypi">trunk/JavaScriptCore/JavaScriptCore.gypi</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCorepro">trunk/JavaScriptCore/JavaScriptCore.pro</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCorevcprojJavaScriptCoreJavaScriptCorevcpr \
oj">trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkJavaScriptCoreruntimeRegExpcpp">trunk/JavaScriptCore/runtime/RegExp.cpp</a></li>
<li><a href="#trunkJavaScriptCoreyarrRegexInterpretercpp">trunk/JavaScriptCore/yarr/RegexInterpreter.cpp</a></li>
<li><a href="#trunkJavaScriptCoreyarrRegexJITcpp">trunk/JavaScriptCore/yarr/RegexJIT.cpp</a></li>
<li><a href="#trunkJavaScriptCoreyarrRegexPatternh">trunk/JavaScriptCore/yarr/RegexPattern.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreyarrRegexPatterncpp">trunk/JavaScriptCore/yarr/RegexPattern.cpp</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreyarrRegexCompilercpp">trunk/JavaScriptCore/yarr/RegexCompiler.cpp</a></li>
<li><a href="#trunkJavaScriptCoreyarrRegexCompilerh">trunk/JavaScriptCore/yarr/RegexCompiler.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJavaScriptCoreAndroidmk"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/Android.mk (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/Android.mk 2010-12-24 01:36:39 UTC (rev \
74599)
+++ trunk/JavaScriptCore/Android.mk 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -189,7 +189,7 @@
</span><span class="cx"> \
</span><span class="cx"> wtf/unicode/icu/CollatorICU.cpp \
</span><span class="cx"> \
</span><del>- yarr/RegexCompiler.cpp \
</del><ins>+ yarr/RegexPattern.cpp \
</ins><span class="cx"> yarr/RegexInterpreter.cpp \
</span><span class="cx"> yarr/RegexJIT.cpp
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/CMakeLists.txt (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/CMakeLists.txt 2010-12-24 01:36:39 UTC \
(rev 74599)
+++ trunk/JavaScriptCore/CMakeLists.txt 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -166,7 +166,7 @@
</span><span class="cx"> runtime/TimeoutChecker.cpp
</span><span class="cx"> runtime/UString.cpp
</span><span class="cx">
</span><del>- yarr/RegexCompiler.cpp
</del><ins>+ yarr/RegexPattern.cpp
</ins><span class="cx"> yarr/RegexInterpreter.cpp
</span><span class="cx"> yarr/RegexJIT.cpp
</span><span class="cx">
</span><span class="lines">@@ -219,7 +219,7 @@
</span><span class="cx"> MAIN_DEPENDENCY \
${JAVASCRIPTCORE_DIR}/create_regex_tables </span><span class="cx"> COMMAND \
${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/create_regex_tables > \
${DERIVED_SOURCES_DIR}/RegExpJitTables.h </span><span class="cx"> VERBATIM)
</span><del>-ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/yarr/RegexCompiler.cpp \
${DERIVED_SOURCES_DIR}/RegExpJitTables.h) \
</del><ins>+ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/yarr/RegexPattern.cpp \
${DERIVED_SOURCES_DIR}/RegExpJitTables.h) </ins><span class="cx">
</span><span class="cx">
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/ChangeLog (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog 2010-12-24 01:36:39 UTC (rev \
74599)
+++ trunk/JavaScriptCore/ChangeLog 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2010-12-23 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Rename RegexCompiler.cpp to RegexPattern.cpp.
+ Implicitly call compileRegex from RegexPattern's constructor.
+
+ * Android.mk:
+ * CMakeLists.txt:
+ * GNUmakefile.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.pro:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * runtime/RegExp.cpp:
+ (JSC::RegExp::compile):
+ * yarr/RegexCompiler.cpp: Removed.
+ * yarr/RegexCompiler.h: Removed.
+ * yarr/RegexInterpreter.cpp:
+ * yarr/RegexJIT.cpp:
+ * yarr/RegexPattern.cpp: Copied from JavaScriptCore/yarr/RegexCompiler.cpp.
+ (JSC::Yarr::compileRegex):
+ (JSC::Yarr::RegexPattern::RegexPattern):
+ * yarr/RegexPattern.h:
+
</ins><span class="cx"> 2010-12-23 Patrick Gansterer <paroga@webkit.org>
</span><span class="cx">
</span><span class="cx"> Unreviewed build fix for WinCE after r74360.
</span></span></pre></div>
<a id="trunkJavaScriptCoreGNUmakefileam"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/GNUmakefile.am (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/GNUmakefile.am 2010-12-24 01:36:39 UTC \
(rev 74599)
+++ trunk/JavaScriptCore/GNUmakefile.am 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -548,13 +548,12 @@
</span><span class="cx"> JavaScriptCore/wtf/VMTags.h \
</span><span class="cx"> JavaScriptCore/wtf/WTFThreadData.cpp \
</span><span class="cx"> JavaScriptCore/wtf/WTFThreadData.h \
</span><del>- JavaScriptCore/yarr/RegexCompiler.cpp \
- JavaScriptCore/yarr/RegexCompiler.h \
</del><span class="cx"> JavaScriptCore/yarr/RegexInterpreter.cpp \
</span><span class="cx"> JavaScriptCore/yarr/RegexInterpreter.h \
</span><span class="cx"> JavaScriptCore/yarr/RegexJIT.cpp \
</span><span class="cx"> JavaScriptCore/yarr/RegexJIT.h \
</span><span class="cx"> JavaScriptCore/yarr/RegexParser.h \
</span><ins>+ JavaScriptCore/yarr/RegexPattern.cpp \
</ins><span class="cx"> JavaScriptCore/yarr/RegexPattern.h
</span><span class="cx">
</span><span class="cx"> if TARGET_WIN32
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCoregypi"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.gypi (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.gypi 2010-12-24 01:36:39 \
UTC (rev 74599)
+++ trunk/JavaScriptCore/JavaScriptCore.gypi 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -491,13 +491,12 @@
</span><span class="cx"> 'wtf/win/MainThreadWin.cpp',
</span><span class="cx"> 'wtf/win/OwnPtrWin.cpp',
</span><span class="cx"> 'wtf/wx/MainThreadWx.cpp',
</span><del>- 'yarr/RegexCompiler.cpp',
- 'yarr/RegexCompiler.h',
</del><span class="cx"> 'yarr/RegexInterpreter.cpp',
</span><span class="cx"> 'yarr/RegexInterpreter.h',
</span><span class="cx"> 'yarr/RegexJIT.cpp',
</span><span class="cx"> 'yarr/RegexJIT.h',
</span><span class="cx"> 'yarr/RegexParser.h',
</span><ins>+ 'yarr/RegexPattern.cpp',
</ins><span class="cx"> 'yarr/RegexPattern.h',
</span><span class="cx"> ]
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCorepro"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.pro (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.pro 2010-12-24 01:36:39 \
UTC (rev 74599)
+++ trunk/JavaScriptCore/JavaScriptCore.pro 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -207,7 +207,7 @@
</span><span class="cx"> runtime/Structure.cpp \
</span><span class="cx"> runtime/TimeoutChecker.cpp \
</span><span class="cx"> runtime/UString.cpp \
</span><del>- yarr/RegexCompiler.cpp \
</del><ins>+ yarr/RegexPattern.cpp \
</ins><span class="cx"> yarr/RegexInterpreter.cpp \
</span><span class="cx"> yarr/RegexJIT.cpp
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCorevcprojJavaScriptCoreJavaScriptCorevcproj"></a>
<div class="modfile"><h4>Modified: \
trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj \
(74599 => 74600)</h4> <pre class="diff"><span>
<span class="info">--- \
trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj 2010-12-24 \
01:36:39 UTC (rev 74599)
+++ trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj 2010-12-24 \
01:40:54 UTC (rev 74600) </span><span class="lines">@@ -1652,14 +1652,6 @@
</span><span class="cx"> Name="yarr"
</span><span class="cx"> >
</span><span class="cx"> <File
</span><del>- RelativePath="..\..\yarr\RegexCompiler.cpp"
- >
- </File>
- <File
- RelativePath="..\..\yarr\RegexCompiler.h"
- >
- </File>
- <File
</del><span class="cx"> RelativePath="..\..\yarr\RegexInterpreter.cpp"
</span><span class="cx"> >
</span><span class="cx"> </File>
</span><span class="lines">@@ -1680,6 +1672,10 @@
</span><span class="cx"> >
</span><span class="cx"> </File>
</span><span class="cx"> <File
</span><ins>+ RelativePath="..\..\yarr\RegexPattern.cpp"
+ >
+ </File>
+ <File
</ins><span class="cx"> RelativePath="..\..\yarr\RegexPattern.h"
</span><span class="cx"> >
</span><span class="cx"> </File>
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: \
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (74599 => 74600)</h4> \
<pre class="diff"><span> <span class="info">--- \
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj 2010-12-24 01:36:39 UTC \
(rev 74599)
+++ trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj 2010-12-24 01:40:54 \
UTC (rev 74600) </span><span class="lines">@@ -226,6 +226,7 @@
</span><span class="cx"> 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */ = \
{isa = PBXBuildFile; fileRef = 868BFA15117CF19900B908B1 /* WTFString.cpp */; }; \
</span><span class="cx"> 868BFA18117CF19900B908B1 /* WTFString.h in Headers */ = \
{isa = PBXBuildFile; fileRef = 868BFA16117CF19900B908B1 /* WTFString.h */; settings = \
{ATTRIBUTES = (Private, ); }; }; </span><span class="cx"> 868BFA60117D048200B908B1 \
/* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = \
868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = \
(Private, ); }; }; </span><ins>+ 868D81A212C428CE0093DC84 /* RegexPattern.cpp in \
Sources */ = {isa = PBXBuildFile; fileRef = 868D81A112C428CE0093DC84 /* \
RegexPattern.cpp */; }; </ins><span class="cx"> 8690231512092D5C00630AF9 /* \
PageReservation.h in Headers */ = {isa = PBXBuildFile; fileRef = \
8690231412092D5C00630AF9 /* PageReservation.h */; settings = {ATTRIBUTES = (Private, \
); }; }; </span><span class="cx"> 869D04AF1193B54D00803475 /* \
CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = \
869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES \
= (Private, ); }; }; </span><span class="cx"> 869EBCB70E8C6D4A008722CC /* \
ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC \
/* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; </span><span \
class="lines">@@ -259,8 +260,6 @@ </span><span class="cx"> 86DB64640F95C6FC00D7D921 \
/* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = \
86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; </span><span \
class="cx"> 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = \
PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; \
</span><span class="cx"> 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers \
*/ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; \
}; </span><del>- 86EAC4950F93E8D1008EC948 /* RegexCompiler.cpp in Sources */ = {isa \
= PBXBuildFile; fileRef = 86EAC48D0F93E8D1008EC948 /* \
RegexCompiler.cpp */; };
- 86EAC4960F93E8D1008EC948 /* RegexCompiler.h in Headers */ = {isa = PBXBuildFile; \
fileRef = 86EAC48E0F93E8D1008EC948 /* RegexCompiler.h */; }; </del><span class="cx"> \
86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in Sources */ = {isa = PBXBuildFile; \
fileRef = 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */; }; </span><span \
class="cx"> 86EAC4980F93E8D1008EC948 /* RegexInterpreter.h in Headers */ = {isa = \
PBXBuildFile; fileRef = 86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */; }; \
</span><span class="cx"> 86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in Sources */ = \
{isa = PBXBuildFile; fileRef = 86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */; }; \
</span><span class="lines">@@ -845,6 +844,7 @@ </span><span class="cx"> \
868BFA15117CF19900B908B1 /* WTFString.cpp */ = {isa = PBXFileReference; fileEncoding \
= 4; lastKnownFileType = sourcecode.cpp.cpp; name = WTFString.cpp; path = \
text/WTFString.cpp; sourceTree = "<group>"; }; </span><span \
class="cx"> 868BFA16117CF19900B908B1 /* WTFString.h */ = {isa = PBXFileReference; \
fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WTFString.h; path = \
text/WTFString.h; sourceTree = "<group>"; }; </span><span class="cx"> \
868BFA5F117D048200B908B1 /* StaticConstructors.h */ = {isa = PBXFileReference; \
fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticConstructors.h; \
sourceTree = "<group>"; }; </span><ins>+ 868D81A112C428CE0093DC84 /* \
RegexPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = \
sourcecode.cpp.cpp; name = RegexPattern.cpp; path = yarr/RegexPattern.cpp; sourceTree \
= "<group>"; }; </ins><span class="cx"> 8690231412092D5C00630AF9 /* \
PageReservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = \
sourcecode.c.h; path = PageReservation.h; sourceTree = "<group>"; }; \
</span><span class="cx"> 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h \
*/ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; \
path = CachedTranscendentalFunction.h; sourceTree = "<group>"; }; \
</span><span class="cx"> 869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = \
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \
ResultType.h; sourceTree = "<group>"; }; </span><span \
class="lines">@@ -878,8 +878,6 @@ </span><span class="cx"> 86DB64630F95C6FC00D7D921 \
/* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; \
lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; \
sourceTree = "<group>"; }; </span><span class="cx"> \
86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding \
= 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = \
"<group>"; }; </span><span class="cx"> 86E85538111B9968001AF51E /* \
JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = \
sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; }; \
</span><del>- 86EAC48D0F93E8D1008EC948 /* RegexCompiler.cpp */ = {isa = \
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = \
RegexCompiler.cpp; path = yarr/RegexCompiler.cpp; sourceTree = \
"<group>"; };
- 86EAC48E0F93E8D1008EC948 /* RegexCompiler.h */ = {isa = PBXFileReference; \
fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegexCompiler.h; path = \
yarr/RegexCompiler.h; sourceTree = "<group>"; }; </del><span \
class="cx"> 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */ = {isa = \
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = \
RegexInterpreter.cpp; path = yarr/RegexInterpreter.cpp; sourceTree = \
"<group>"; }; </span><span class="cx"> 86EAC4900F93E8D1008EC948 /* \
RegexInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType \
= sourcecode.c.h; name = RegexInterpreter.h; path = yarr/RegexInterpreter.h; \
sourceTree = "<group>"; }; </span><span class="cx"> \
86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */ = {isa = PBXFileReference; fileEncoding = \
4; lastKnownFileType = sourcecode.cpp.cpp; name = RegexJIT.cpp; path = \
yarr/RegexJIT.cpp; sourceTree = "<group>"; }; </span><span \
class="lines">@@ -1892,14 +1890,13 @@ </span><span class="cx"> \
86EAC48C0F93E8B9008EC948 /* yarr */ = { </span><span class="cx"> isa = PBXGroup;
</span><span class="cx"> children = (
</span><del>- 86EAC48D0F93E8D1008EC948 /* RegexCompiler.cpp */,
- 86EAC48E0F93E8D1008EC948 /* RegexCompiler.h */,
</del><span class="cx"> 86EAC48F0F93E8D1008EC948 /* RegexInterpreter.cpp */,
</span><span class="cx"> 86EAC4900F93E8D1008EC948 /* RegexInterpreter.h */,
</span><span class="cx"> 86EAC4910F93E8D1008EC948 /* RegexJIT.cpp */,
</span><span class="cx"> 86EAC4920F93E8D1008EC948 /* RegexJIT.h */,
</span><span class="cx"> 86EAC4930F93E8D1008EC948 /* RegexParser.h */,
</span><span class="cx"> 86EAC4940F93E8D1008EC948 /* RegexPattern.h */,
</span><ins>+ 868D81A112C428CE0093DC84 /* RegexPattern.cpp */,
</ins><span class="cx"> );
</span><span class="cx"> name = yarr;
</span><span class="cx"> sourceTree = "<group>";
</span><span class="lines">@@ -2275,7 +2272,6 @@
</span><span class="cx"> 90D3469C0E285280009492EE /* RefCountedLeakCounter.h in \
Headers */, </span><span class="cx"> BC18C4580E16F5CD00B34460 /* RefPtr.h in \
Headers */, </span><span class="cx"> BC18C4590E16F5CD00B34460 /* RefPtrHashMap.h \
in Headers */, </span><del>- 86EAC4960F93E8D1008EC948 /* RegexCompiler.h in \
Headers */, </del><span class="cx"> 86EAC4980F93E8D1008EC948 /* \
RegexInterpreter.h in Headers */, </span><span class="cx"> \
86EAC49A0F93E8D1008EC948 /* RegexJIT.h in Headers */, </span><span class="cx"> \
BC18C45A0E16F5CD00B34460 /* RegExp.h in Headers */, </span><span class="lines">@@ \
-2800,13 +2796,13 @@ </span><span class="cx"> 14469DE9107EC7E700650446 /* \
PrototypeFunction.cpp in Sources */, </span><span class="cx"> \
088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */, </span><span class="cx"> \
905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */, \
</span><del>- 86EAC4950F93E8D1008EC948 /* RegexCompiler.cpp in Sources */, \
</del><span class="cx"> 86EAC4970F93E8D1008EC948 /* RegexInterpreter.cpp in \
Sources */, </span><span class="cx"> 86EAC4990F93E8D1008EC948 /* RegexJIT.cpp in \
Sources */, </span><span class="cx"> 14280841107EC0930013E7B2 /* RegExp.cpp in \
Sources */, </span><span class="cx"> A1712B3B11C7B212007A5315 /* RegExpCache.cpp \
in Sources */, </span><span class="cx"> 14280842107EC0930013E7B2 /* \
RegExpConstructor.cpp in Sources */, </span><span class="cx"> \
14280843107EC0930013E7B2 /* RegExpObject.cpp in Sources */, \
</span><ins>+ 868D81A212C428CE0093DC84 /* RegexPattern.cpp in Sources */, \
</ins><span class="cx"> 14280844107EC0930013E7B2 /* RegExpPrototype.cpp in \
Sources */, </span><span class="cx"> 1428083A107EC0750013E7B2 /* RegisterFile.cpp \
in Sources */, </span><span class="cx"> 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp \
in Sources */, </span></span></pre></div>
<a id="trunkJavaScriptCoreruntimeRegExpcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/runtime/RegExp.cpp (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/runtime/RegExp.cpp 2010-12-24 01:36:39 \
UTC (rev 74599)
+++ trunk/JavaScriptCore/runtime/RegExp.cpp 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -29,7 +29,6 @@
</span><span class="cx"> #include <wtf/Assertions.h>
</span><span class="cx"> #include <wtf/OwnArrayPtr.h>
</span><span class="cx">
</span><del>-#include "yarr/RegexCompiler.h"
</del><span class="cx"> #include "yarr/RegexJIT.h"
</span><span class="cx"> #include "yarr/RegexInterpreter.h"
</span><span class="cx"> #include "yarr/RegexPattern.h"
</span><span class="lines">@@ -83,9 +82,8 @@
</span><span class="cx">
</span><span class="cx"> RegExp::RegExpState RegExp::compile(JSGlobalData* \
globalData) </span><span class="cx"> {
</span><del>- Yarr::RegexPattern pattern(ignoreCase(), multiline());
-
- if ((m_constructionError = Yarr::compileRegex(m_patternString, pattern)))
</del><ins>+ Yarr::RegexPattern pattern(m_patternString, ignoreCase(), \
multiline(), &m_constructionError); + if (m_constructionError)
</ins><span class="cx"> return ParseError;
</span><span class="cx">
</span><span class="cx"> m_numSubpatterns = pattern.m_numSubpatterns;
</span></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexCompilercpp"></a>
<div class="delfile"><h4>Deleted: trunk/JavaScriptCore/yarr/RegexCompiler.cpp (74599 \
=> 74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/yarr/RegexCompiler.cpp 2010-12-24 \
01:36:39 UTC (rev 74599)
+++ trunk/JavaScriptCore/yarr/RegexCompiler.cpp 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -1,974 +0,0 @@
</span><del>-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
- *
- * 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 "RegexCompiler.h"
-
-#include "RegexInterpreter.h"
-#include "RegexPattern.h"
-#include <wtf/Vector.h>
-
-using namespace WTF;
-
-namespace JSC { namespace Yarr {
-
-#include "RegExpJitTables.h"
-
-class CharacterClassConstructor {
-public:
- CharacterClassConstructor(bool isCaseInsensitive = false)
- : m_isCaseInsensitive(isCaseInsensitive)
- {
- }
-
- void reset()
- {
- m_matches.clear();
- m_ranges.clear();
- m_matchesUnicode.clear();
- m_rangesUnicode.clear();
- }
-
- void append(const CharacterClass* other)
- {
- for (size_t i = 0; i < other->m_matches.size(); ++i)
- addSorted(m_matches, other->m_matches[i]);
- for (size_t i = 0; i < other->m_ranges.size(); ++i)
- addSortedRange(m_ranges, other->m_ranges[i].begin, \
other->m_ranges[i].end);
- for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
- addSorted(m_matchesUnicode, other->m_matchesUnicode[i]);
- for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
- addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, \
other->m_rangesUnicode[i].end);
- }
-
- void putChar(UChar ch)
- {
- if (ch <= 0x7f) {
- if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
- addSorted(m_matches, toASCIIUpper(ch));
- addSorted(m_matches, toASCIILower(ch));
- } else
- addSorted(m_matches, ch);
- } else {
- UChar upper, lower;
- if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != \
(lower = Unicode::toLower(ch)))) {
- addSorted(m_matchesUnicode, upper);
- addSorted(m_matchesUnicode, lower);
- } else
- addSorted(m_matchesUnicode, ch);
- }
- }
-
- // returns true if this character has another case, and 'ch' is the upper case \
form.
- static inline bool isUnicodeUpper(UChar ch)
- {
- return ch != Unicode::toLower(ch);
- }
-
- // returns true if this character has another case, and 'ch' is the lower case \
form.
- static inline bool isUnicodeLower(UChar ch)
- {
- return ch != Unicode::toUpper(ch);
- }
-
- void putRange(UChar lo, UChar hi)
- {
- if (lo <= 0x7f) {
- char asciiLo = lo;
- char asciiHi = std::min(hi, (UChar)0x7f);
- addSortedRange(m_ranges, lo, asciiHi);
-
- if (m_isCaseInsensitive) {
- if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
- addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), \
std::min(asciiHi, 'Z')+('a'-'A'));
- if ((asciiLo <= 'z') && (asciiHi >= 'a'))
- addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), \
std::min(asciiHi, 'z')+('A'-'a'));
- }
- }
- if (hi >= 0x80) {
- uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
- addSortedRange(m_rangesUnicode, unicodeCurr, hi);
-
- if (m_isCaseInsensitive) {
- while (unicodeCurr <= hi) {
- // If the upper bound of the range (hi) is 0xffff, the \
increments to
- // unicodeCurr in this loop may take it to 0x10000. This is \
fine
- // (if so we won't re-enter the loop, since the loop condition \
above
- // will definitely fail) - but this does mean we cannot use a \
UChar
- // to represent unicodeCurr, we must use a 32-bit value instead.
- ASSERT(unicodeCurr <= 0xffff);
-
- if (isUnicodeUpper(unicodeCurr)) {
- UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
- UChar lowerCaseRangeEnd = lowerCaseRangeBegin;
- while ((++unicodeCurr <= hi) && \
isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == \
(lowerCaseRangeEnd + 1)))
- lowerCaseRangeEnd++;
- addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, \
lowerCaseRangeEnd);
- } else if (isUnicodeLower(unicodeCurr)) {
- UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr);
- UChar upperCaseRangeEnd = upperCaseRangeBegin;
- while ((++unicodeCurr <= hi) && \
isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == \
(upperCaseRangeEnd + 1)))
- upperCaseRangeEnd++;
- addSortedRange(m_rangesUnicode, upperCaseRangeBegin, \
upperCaseRangeEnd);
- } else
- ++unicodeCurr;
- }
- }
- }
- }
-
- CharacterClass* charClass()
- {
- CharacterClass* characterClass = new CharacterClass(0);
-
- characterClass->m_matches.append(m_matches);
- characterClass->m_ranges.append(m_ranges);
- characterClass->m_matchesUnicode.append(m_matchesUnicode);
- characterClass->m_rangesUnicode.append(m_rangesUnicode);
-
- reset();
-
- return characterClass;
- }
-
-private:
- void addSorted(Vector<UChar>& matches, UChar ch)
- {
- unsigned pos = 0;
- unsigned range = matches.size();
-
- // binary chop, find position to insert char.
- while (range) {
- unsigned index = range >> 1;
-
- int val = matches[pos+index] - ch;
- if (!val)
- return;
- else if (val > 0)
- range = index;
- else {
- pos += (index+1);
- range -= (index+1);
- }
- }
-
- if (pos == matches.size())
- matches.append(ch);
- else
- matches.insert(pos, ch);
- }
-
- void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar \
hi)
- {
- unsigned end = ranges.size();
-
- // Simple linear scan - I doubt there are that many ranges anyway...
- // feel free to fix this with something faster (eg binary chop).
- for (unsigned i = 0; i < end; ++i) {
- // does the new range fall before the current position in the array
- if (hi < ranges[i].begin) {
- // optional optimization: concatenate appending ranges? - may not be \
worthwhile.
- if (hi == (ranges[i].begin - 1)) {
- ranges[i].begin = lo;
- return;
- }
- ranges.insert(i, CharacterRange(lo, hi));
- return;
- }
- // Okay, since we didn't hit the last case, the end of the new range is \
definitely at or after the begining
- // If the new range start at or before the end of the last range, then \
the overlap (if it starts one after the
- // end of the last range they concatenate, which is just as good.
- if (lo <= (ranges[i].end + 1)) {
- // found an intersect! we'll replace this entry in the array.
- ranges[i].begin = std::min(ranges[i].begin, lo);
- ranges[i].end = std::max(ranges[i].end, hi);
-
- // now check if the new range can subsume any subsequent ranges.
- unsigned next = i+1;
- // each iteration of the loop we will either remove something from \
the list, or break the loop.
- while (next < ranges.size()) {
- if (ranges[next].begin <= (ranges[i].end + 1)) {
- // the next entry now overlaps / concatenates this one.
- ranges[i].end = std::max(ranges[i].end, ranges[next].end);
- ranges.remove(next);
- } else
- break;
- }
-
- return;
- }
- }
-
- // CharacterRange comes after all existing ranges.
- ranges.append(CharacterRange(lo, hi));
- }
-
- bool m_isCaseInsensitive;
-
- Vector<UChar> m_matches;
- Vector<CharacterRange> m_ranges;
- Vector<UChar> m_matchesUnicode;
- Vector<CharacterRange> m_rangesUnicode;
-};
-
-struct BeginCharHelper {
- BeginCharHelper(Vector<BeginChar>* beginChars, bool isCaseInsensitive = \
false)
- : m_beginChars(beginChars)
- , m_isCaseInsensitive(isCaseInsensitive)
- {}
-
- void addBeginChar(BeginChar beginChar, Vector<TermChain>* hotTerms, \
QuantifierType quantityType, unsigned quantityCount)
- {
- if (quantityType == QuantifierFixedCount && quantityCount > 1) {
- // We duplicate the first found character if the quantity of the term is \
more than one. eg.: /a{3}/
- beginChar.value |= beginChar.value << 16;
- beginChar.mask |= beginChar.mask << 16;
- addCharacter(beginChar);
- } else if (quantityType == QuantifierFixedCount && quantityCount == \
1 && hotTerms->size())
- // In case of characters with fixed quantifier we should check the next \
character as well.
- linkHotTerms(beginChar, hotTerms);
- else
- // In case of greedy matching the next character checking is unnecessary \
therefore we just store
- // the first character.
- addCharacter(beginChar);
- }
-
- // Merge two following BeginChars in the vector to reduce the number of \
character checks.
- void merge(unsigned size)
- {
- for (unsigned i = 0; i < size; i++) {
- BeginChar* curr = &m_beginChars->at(i);
- BeginChar* next = &m_beginChars->at(i + 1);
-
- // If the current and the next size of value is different we should skip \
the merge process
- // because the 16bit and 32bit values are unmergable.
- if (curr->value <= 0xFFFF && next->value > 0xFFFF)
- continue;
-
- unsigned diff = curr->value ^ next->value;
-
- curr->mask |= diff;
- curr->value |= curr->mask;
-
- m_beginChars->remove(i + 1);
- size--;
- }
- }
-
-private:
- void addCharacter(BeginChar beginChar)
- {
- unsigned pos = 0;
- unsigned range = m_beginChars->size();
-
- // binary chop, find position to insert char.
- while (range) {
- unsigned index = range >> 1;
-
- int val = m_beginChars->at(pos+index).value - beginChar.value;
- if (!val)
- return;
- if (val < 0)
- range = index;
- else {
- pos += (index+1);
- range -= (index+1);
- }
- }
-
- if (pos == m_beginChars->size())
- m_beginChars->append(beginChar);
- else
- m_beginChars->insert(pos, beginChar);
- }
-
- // Create BeginChar objects by appending each terms from a hotTerms vector to an \
existing BeginChar object.
- void linkHotTerms(BeginChar beginChar, Vector<TermChain>* hotTerms)
- {
- for (unsigned i = 0; i < hotTerms->size(); i++) {
- PatternTerm hotTerm = hotTerms->at(i).term;
- ASSERT(hotTerm.type == PatternTerm::TypePatternCharacter);
-
- UChar characterNext = hotTerm.patternCharacter;
-
- // Append a character to an existing BeginChar object.
- if (characterNext <= 0x7f) {
- unsigned mask = 0;
-
- if (m_isCaseInsensitive && isASCIIAlpha(characterNext)) {
- mask = 32;
- characterNext = toASCIILower(characterNext);
- }
-
- addCharacter(BeginChar(beginChar.value | (characterNext << \
16), beginChar.mask | (mask << 16)));
- } else {
- UChar upper, lower;
- if (m_isCaseInsensitive && ((upper = \
Unicode::toUpper(characterNext)) != (lower = \
Unicode::toLower(characterNext)))) {
- addCharacter(BeginChar(beginChar.value | (upper << 16), \
beginChar.mask));
- addCharacter(BeginChar(beginChar.value | (lower << 16), \
beginChar.mask));
- } else
- addCharacter(BeginChar(beginChar.value | (characterNext << \
16), beginChar.mask));
- }
- }
- }
-
- Vector<BeginChar>* m_beginChars;
- bool m_isCaseInsensitive;
-};
-
-class RegexPatternConstructor {
-public:
- RegexPatternConstructor(RegexPattern& pattern)
- : m_pattern(pattern)
- , m_characterClassConstructor(pattern.m_ignoreCase)
- , m_beginCharHelper(&pattern.m_beginChars, pattern.m_ignoreCase)
- , m_invertParentheticalAssertion(false)
- {
- }
-
- ~RegexPatternConstructor()
- {
- }
-
- void reset()
- {
- m_pattern.reset();
- m_characterClassConstructor.reset();
- }
-
- void assertionBOL()
- {
- if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) \
{
- m_alternative->m_startsWithBOL = true;
- m_alternative->m_containsBOL = true;
- m_pattern.m_containsBOL = true;
- }
- m_alternative->m_terms.append(PatternTerm::BOL());
- }
- void assertionEOL()
- {
- m_alternative->m_terms.append(PatternTerm::EOL());
- }
- void assertionWordBoundary(bool invert)
- {
- m_alternative->m_terms.append(PatternTerm::WordBoundary(invert));
- }
-
- void atomPatternCharacter(UChar ch)
- {
- // We handle case-insensitive checking of unicode characters which do have \
both
- // cases by handling them as if they were defined using a CharacterClass.
- if (m_pattern.m_ignoreCase && !isASCII(ch) && \
(Unicode::toUpper(ch) != Unicode::toLower(ch))) {
- atomCharacterClassBegin();
- atomCharacterClassAtom(ch);
- atomCharacterClassEnd();
- } else
- m_alternative->m_terms.append(PatternTerm(ch));
- }
-
- void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
- {
- switch (classID) {
- case DigitClassID:
- m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), \
invert));
- break;
- case SpaceClassID:
- m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), \
invert));
- break;
- case WordClassID:
- m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), \
invert));
- break;
- case NewlineClassID:
- m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), \
invert));
- break;
- }
- }
-
- void atomCharacterClassBegin(bool invert = false)
- {
- m_invertCharacterClass = invert;
- }
-
- void atomCharacterClassAtom(UChar ch)
- {
- m_characterClassConstructor.putChar(ch);
- }
-
- void atomCharacterClassRange(UChar begin, UChar end)
- {
- m_characterClassConstructor.putRange(begin, end);
- }
-
- void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
- {
- ASSERT(classID != NewlineClassID);
-
- switch (classID) {
- case DigitClassID:
- m_characterClassConstructor.append(invert ? \
m_pattern.nondigitsCharacterClass() : \
m_pattern.digitsCharacterClass());
- break;
-
- case SpaceClassID:
- m_characterClassConstructor.append(invert ? \
m_pattern.nonspacesCharacterClass() : \
m_pattern.spacesCharacterClass());
- break;
-
- case WordClassID:
- m_characterClassConstructor.append(invert ? \
m_pattern.nonwordcharCharacterClass() : \
m_pattern.wordcharCharacterClass());
- break;
-
- default:
- ASSERT_NOT_REACHED();
- }
- }
-
- void atomCharacterClassEnd()
- {
- CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
- m_pattern.m_userCharacterClasses.append(newCharacterClass);
- m_alternative->m_terms.append(PatternTerm(newCharacterClass, \
m_invertCharacterClass));
- }
-
- void atomParenthesesSubpatternBegin(bool capture = true)
- {
- unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
- if (capture)
- m_pattern.m_numSubpatterns++;
-
- PatternDisjunction* parenthesesDisjunction = new \
PatternDisjunction(m_alternative);
- m_pattern.m_disjunctions.append(parenthesesDisjunction);
- m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, \
subpatternId, parenthesesDisjunction, capture, false));
- m_alternative = parenthesesDisjunction->addNewAlternative();
- }
-
- void atomParentheticalAssertionBegin(bool invert = false)
- {
- PatternDisjunction* parenthesesDisjunction = new \
PatternDisjunction(m_alternative);
- m_pattern.m_disjunctions.append(parenthesesDisjunction);
- m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, \
m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, \
invert));
- m_alternative = parenthesesDisjunction->addNewAlternative();
- m_invertParentheticalAssertion = invert;
- }
-
- void atomParenthesesEnd()
- {
- ASSERT(m_alternative->m_parent);
- ASSERT(m_alternative->m_parent->m_parent);
-
- PatternDisjunction* parenthesesDisjunction = m_alternative->m_parent;
- m_alternative = m_alternative->m_parent->m_parent;
-
- PatternTerm& lastTerm = m_alternative->lastTerm();
-
- unsigned numParenAlternatives = \
parenthesesDisjunction->m_alternatives.size();
- unsigned numBOLAnchoredAlts = 0;
- // Bubble up BOL flags
- for (unsigned i = 0; i < numParenAlternatives; i++) {
- if (parenthesesDisjunction->m_alternatives[i]->m_startsWithBOL)
- numBOLAnchoredAlts++;
- }
-
- if (numBOLAnchoredAlts) {
- m_alternative->m_containsBOL = true;
- // If all the alternatives in parens start with BOL, then so does this \
one
- if (numBOLAnchoredAlts == numParenAlternatives)
- m_alternative->m_startsWithBOL = true;
- }
-
- lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
- m_invertParentheticalAssertion = false;
- }
-
- void atomBackReference(unsigned subpatternId)
- {
- ASSERT(subpatternId);
- m_pattern.m_containsBackreferences = true;
- m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, \
subpatternId);
-
- if (subpatternId > m_pattern.m_numSubpatterns) {
- m_alternative->m_terms.append(PatternTerm::ForwardReference());
- return;
- }
-
- PatternAlternative* currentAlternative = m_alternative;
- ASSERT(currentAlternative);
-
- // Note to self: if we waited until the AST was baked, we could also remove \
forwards refs
- while ((currentAlternative = currentAlternative->m_parent->m_parent)) \
{
- PatternTerm& term = currentAlternative->lastTerm();
- ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || \
(term.type == PatternTerm::TypeParentheticalAssertion));
-
- if ((term.type == PatternTerm::TypeParenthesesSubpattern) && \
term.capture() && (subpatternId == \
term.parentheses.subpatternId)) {
- m_alternative->m_terms.append(PatternTerm::ForwardReference());
- return;
- }
- }
-
- m_alternative->m_terms.append(PatternTerm(subpatternId));
- }
-
- // deep copy the argument disjunction. If filterStartsWithBOL is true,
- // skip alternatives with m_startsWithBOL set true.
- PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool \
filterStartsWithBOL = false)
- {
- PatternDisjunction* newDisjunction = 0;
- for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) {
- PatternAlternative* alternative = disjunction->m_alternatives[alt];
- if (!filterStartsWithBOL || !alternative->m_startsWithBOL) {
- if (!newDisjunction) {
- newDisjunction = new PatternDisjunction();
- newDisjunction->m_parent = disjunction->m_parent;
- }
- PatternAlternative* newAlternative = \
newDisjunction->addNewAlternative();
- for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
- \
newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], \
filterStartsWithBOL));
- }
- }
-
- if (newDisjunction)
- m_pattern.m_disjunctions.append(newDisjunction);
- return newDisjunction;
- }
-
- PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false)
- {
- if ((term.type != PatternTerm::TypeParenthesesSubpattern) && \
(term.type != PatternTerm::TypeParentheticalAssertion))
- return PatternTerm(term);
-
- PatternTerm termCopy = term;
- termCopy.parentheses.disjunction = \
copyDisjunction(termCopy.parentheses.disjunction, \
filterStartsWithBOL);
- return termCopy;
- }
-
- void quantifyAtom(unsigned min, unsigned max, bool greedy)
- {
- ASSERT(min <= max);
- ASSERT(m_alternative->m_terms.size());
-
- if (!max) {
- m_alternative->removeLastTerm();
- return;
- }
-
- PatternTerm& term = m_alternative->lastTerm();
- ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
- ASSERT((term.quantityCount == 1) && (term.quantityType == \
QuantifierFixedCount));
-
- // For any assertion with a zero minimum, not matching is valid and has no \
effect,
- // remove it. Otherwise, we need to match as least once, but there is no \
point
- // matching more than once, so remove the quantifier. It is not entirely \
clear
- // from the spec whether or not this behavior is correct, but I believe this
- // matches Firefox. :-/
- if (term.type == PatternTerm::TypeParentheticalAssertion) {
- if (!min)
- m_alternative->removeLastTerm();
- return;
- }
-
- if (min == 0)
- term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy);
- else if (min == max)
- term.quantify(min, QuantifierFixedCount);
- else {
- term.quantify(min, QuantifierFixedCount);
- m_alternative->m_terms.append(copyTerm(term));
- // NOTE: this term is interesting from an analysis perspective, in that \
it can be ignored.....
- m_alternative->lastTerm().quantify((max == quantifyInfinite) ? max : \
max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
- if (m_alternative->lastTerm().type == \
PatternTerm::TypeParenthesesSubpattern)
- m_alternative->lastTerm().parentheses.isCopy = true;
- }
- }
-
- void disjunction()
- {
- m_alternative = m_alternative->m_parent->addNewAlternative();
- }
-
- void regexBegin()
- {
- m_pattern.m_body = new PatternDisjunction();
- m_alternative = m_pattern.m_body->addNewAlternative();
- m_pattern.m_disjunctions.append(m_pattern.m_body);
- }
- void regexEnd()
- {
- }
- void regexError()
- {
- }
-
- unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned \
currentCallFrameSize, unsigned initialInputPosition)
- {
- alternative->m_hasFixedSize = true;
- unsigned currentInputPosition = initialInputPosition;
-
- for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
- PatternTerm& term = alternative->m_terms[i];
-
- switch (term.type) {
- case PatternTerm::TypeAssertionBOL:
- case PatternTerm::TypeAssertionEOL:
- case PatternTerm::TypeAssertionWordBoundary:
- term.inputPosition = currentInputPosition;
- break;
-
- case PatternTerm::TypeBackReference:
- term.inputPosition = currentInputPosition;
- term.frameLocation = currentCallFrameSize;
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoBackReference;
- alternative->m_hasFixedSize = false;
- break;
-
- case PatternTerm::TypeForwardReference:
- break;
-
- case PatternTerm::TypePatternCharacter:
- term.inputPosition = currentInputPosition;
- if (term.quantityType != QuantifierFixedCount) {
- term.frameLocation = currentCallFrameSize;
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoPatternCharacter;
- alternative->m_hasFixedSize = false;
- } else
- currentInputPosition += term.quantityCount;
- break;
-
- case PatternTerm::TypeCharacterClass:
- term.inputPosition = currentInputPosition;
- if (term.quantityType != QuantifierFixedCount) {
- term.frameLocation = currentCallFrameSize;
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoCharacterClass;
- alternative->m_hasFixedSize = false;
- } else
- currentInputPosition += term.quantityCount;
- break;
-
- case PatternTerm::TypeParenthesesSubpattern:
- // Note: for fixed once parentheses we will ensure at least the \
minimum is available; others are on their own.
- term.frameLocation = currentCallFrameSize;
- if (term.quantityCount == 1 && !term.parentheses.isCopy) {
- if (term.quantityType != QuantifierFixedCount)
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParenthesesOnce;
- currentCallFrameSize = \
setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, \
currentInputPosition);
- // If quantity is fixed, then pre-check its minimum size.
- if (term.quantityType == QuantifierFixedCount)
- currentInputPosition += \
term.parentheses.disjunction->m_minimumSize;
- term.inputPosition = currentInputPosition;
- } else if (term.parentheses.isTerminal) {
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParenthesesTerminal;
- currentCallFrameSize = \
setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, \
currentInputPosition);
- term.inputPosition = currentInputPosition;
- } else {
- term.inputPosition = currentInputPosition;
- setupDisjunctionOffsets(term.parentheses.disjunction, 0, \
currentInputPosition);
- currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParentheses;
- }
- // Fixed count of 1 could be accepted, if they have a fixed size \
*AND* if all alternatives are of the same length.
- alternative->m_hasFixedSize = false;
- break;
-
- case PatternTerm::TypeParentheticalAssertion:
- term.inputPosition = currentInputPosition;
- term.frameLocation = currentCallFrameSize;
- currentCallFrameSize = \
setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + \
RegexStackSpaceForBackTrackInfoParentheticalAssertion, \
currentInputPosition);
- break;
- }
- }
-
- alternative->m_minimumSize = currentInputPosition - initialInputPosition;
- return currentCallFrameSize;
- }
-
- unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned \
initialCallFrameSize, unsigned initialInputPosition)
- {
- if ((disjunction != m_pattern.m_body) && \
(disjunction->m_alternatives.size() > 1))
- initialCallFrameSize += RegexStackSpaceForBackTrackInfoAlternative;
-
- unsigned minimumInputSize = UINT_MAX;
- unsigned maximumCallFrameSize = 0;
- bool hasFixedSize = true;
-
- for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) {
- PatternAlternative* alternative = disjunction->m_alternatives[alt];
- unsigned currentAlternativeCallFrameSize = \
setupAlternativeOffsets(alternative, initialCallFrameSize, \
initialInputPosition);
- minimumInputSize = min(minimumInputSize, alternative->m_minimumSize);
- maximumCallFrameSize = max(maximumCallFrameSize, \
currentAlternativeCallFrameSize);
- hasFixedSize &= alternative->m_hasFixedSize;
- }
-
- ASSERT(minimumInputSize != UINT_MAX);
- ASSERT(maximumCallFrameSize >= initialCallFrameSize);
-
- disjunction->m_hasFixedSize = hasFixedSize;
- disjunction->m_minimumSize = minimumInputSize;
- disjunction->m_callFrameSize = maximumCallFrameSize;
- return maximumCallFrameSize;
- }
-
- void setupOffsets()
- {
- setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
- }
-
- // This optimization identifies sets of parentheses that we will never need to \
backtrack.
- // In these cases we do not need to store state from prior iterations.
- // We can presently avoid backtracking for:
- // * where the parens are at the end of the regular expression (last term in \
any of the
- // alternatives of the main body disjunction).
- // * where the parens are non-capturing, and quantified unbounded greedy (*).
- // * where the parens do not contain any capturing subpatterns.
- void checkForTerminalParentheses()
- {
- // This check is much too crude; should be just checking whether the \
candidate
- // node contains nested capturing subpatterns, not the whole expression!
- if (m_pattern.m_numSubpatterns)
- return;
-
- Vector<PatternAlternative*>& alternatives = \
m_pattern.m_body->m_alternatives;
- for (size_t i = 0; i < alternatives.size(); ++i) {
- Vector<PatternTerm>& terms = alternatives[i]->m_terms;
- if (terms.size()) {
- PatternTerm& term = terms.last();
- if (term.type == PatternTerm::TypeParenthesesSubpattern
- && term.quantityType == QuantifierGreedy
- && term.quantityCount == quantifyInfinite
- && !term.capture())
- term.parentheses.isTerminal = true;
- }
- }
- }
-
- void optimizeBOL()
- {
- // Look for expressions containing beginning of line (^) anchoring and \
unroll them.
- // e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once followed by /c/ \
which loops
- // This code relies on the parsing code tagging alternatives with \
m_containsBOL and
- // m_startsWithBOL and rolling those up to containing alternatives.
- // At this point, this is only valid for non-multiline expressions.
- PatternDisjunction* disjunction = m_pattern.m_body;
-
- if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
- return;
-
- PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true);
-
- // Set alternatives in disjunction to "onceThrough"
- for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt)
- disjunction->m_alternatives[alt]->setOnceThrough();
-
- if (loopDisjunction) {
- // Move alternatives from loopDisjunction to disjunction
- for (unsigned alt = 0; alt < \
loopDisjunction->m_alternatives.size(); ++alt)
- disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt]);
-
- loopDisjunction->m_alternatives.clear();
- }
- }
-
- bool addBeginTerm(PatternTerm term, Vector<TermChain>* beginTerms, \
PatternAlternative* alternative, unsigned numTerms, unsigned termIndex, unsigned \
depth)
- {
- if (term.quantityType == QuantifierFixedCount) {
- beginTerms->append(TermChain(term));
- if (depth < 2 && termIndex < numTerms - 1 && \
term.quantityCount == 1)
- setupAlternativeBeginTerms(alternative, \
&beginTerms->last().hotTerms, termIndex + 1, depth + 1);
- } else if (termIndex != numTerms - 1) {
- beginTerms->append(TermChain(term));
- return true;
- }
-
- return false;
- }
-
- // This function collects the terms which are potentially matching the first \
number of depth characters in the result.
- // If this function returns false then it found at least one term which makes \
the beginning character
- // look-up optimization inefficient.
- bool setupDisjunctionBeginTerms(PatternDisjunction* disjunction, \
Vector<TermChain>* beginTerms, unsigned depth)
- {
- for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) {
- PatternAlternative* alternative = disjunction->m_alternatives[alt];
-
- if (!setupAlternativeBeginTerms(alternative, beginTerms, 0, depth))
- return false;
- }
-
- return true;
- }
-
- bool setupAlternativeBeginTerms(PatternAlternative* alternative, \
Vector<TermChain>* beginTerms, unsigned termIndex, unsigned \
depth)
- {
- bool checkNext = true;
- unsigned numTerms = alternative->m_terms.size();
-
- while (checkNext && termIndex < numTerms) {
- PatternTerm term = alternative->m_terms[termIndex];
- checkNext = false;
-
- switch (term.type) {
- case PatternTerm::TypeAssertionBOL:
- case PatternTerm::TypeAssertionEOL:
- case PatternTerm::TypeAssertionWordBoundary:
- return false;
-
- case PatternTerm::TypeBackReference:
- case PatternTerm::TypeForwardReference:
- return false;
-
- case PatternTerm::TypePatternCharacter:
- if (addBeginTerm(term, beginTerms, alternative, numTerms, termIndex, \
depth)) {
- termIndex++;
- checkNext = true;
- }
- break;
-
- case PatternTerm::TypeCharacterClass:
- return false;
-
- case PatternTerm::TypeParentheticalAssertion:
- if (term.invert())
- return false;
-
- case PatternTerm::TypeParenthesesSubpattern:
- if (term.quantityType != QuantifierFixedCount) {
- if (termIndex == numTerms - 1)
- break;
-
- termIndex++;
- checkNext = true;
-
- }
-
- if (!setupDisjunctionBeginTerms(term.parentheses.disjunction, \
beginTerms, depth))
- return false;
-
- break;
- }
- }
-
- return true;
- }
-
- void setupBeginChars()
- {
- Vector<TermChain> beginTerms;
- bool containsFixedCharacter = false;
-
- if ((!m_pattern.m_body->m_hasFixedSize || \
m_pattern.m_body->m_alternatives.size() > 1)
- && setupDisjunctionBeginTerms(m_pattern.m_body, \
&beginTerms, 0)) {
- unsigned size = beginTerms.size();
-
- // If we haven't collected any terms we should abort the preparation of \
beginning character look-up optimization.
- if (!size)
- return;
-
- m_pattern.m_containsBeginChars = true;
-
- for (unsigned i = 0; i < size; i++) {
- PatternTerm term = beginTerms[i].term;
-
- // We have just collected PatternCharacter terms, other terms are \
not allowed.
- ASSERT(term.type == PatternTerm::TypePatternCharacter);
-
- if (term.quantityType == QuantifierFixedCount)
- containsFixedCharacter = true;
-
- UChar character = term.patternCharacter;
- unsigned mask = 0;
-
- if (character <= 0x7f) {
- if (m_pattern.m_ignoreCase && isASCIIAlpha(character)) {
- mask = 32;
- character = toASCIILower(character);
- }
-
- m_beginCharHelper.addBeginChar(BeginChar(character, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
- } else {
- UChar upper, lower;
- if (m_pattern.m_ignoreCase && ((upper = \
Unicode::toUpper(character)) != (lower = \
Unicode::toLower(character)))) {
- m_beginCharHelper.addBeginChar(BeginChar(upper, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
- m_beginCharHelper.addBeginChar(BeginChar(lower, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
- } else
- m_beginCharHelper.addBeginChar(BeginChar(character, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount);
- }
- }
-
- // If the pattern doesn't contain terms with fixed quantifiers then the \
beginning character look-up optimization is inefficient.
- if (!containsFixedCharacter) {
- m_pattern.m_containsBeginChars = false;
- return;
- }
-
- size = m_pattern.m_beginChars.size();
-
- if (size > 2)
- m_beginCharHelper.merge(size - 1);
- else if (size <= 1)
- m_pattern.m_containsBeginChars = false;
- }
- }
-
-private:
- RegexPattern& m_pattern;
- PatternAlternative* m_alternative;
- CharacterClassConstructor m_characterClassConstructor;
- BeginCharHelper m_beginCharHelper;
- bool m_invertCharacterClass;
- bool m_invertParentheticalAssertion;
-};
-
-
-const char* compileRegex(const UString& patternString, RegexPattern& \
pattern)
-{
- RegexPatternConstructor constructor(pattern);
-
- if (const char* error = parse(constructor, patternString))
- return error;
-
- // If the pattern contains illegal backreferences reset & reparse.
- // Quoting Netscape's "What's new in JavaScript 1.2",
- // "Note: if the number of left parentheses is less than the number \
specified
- // in \#, the \# is taken as an octal escape as described in the next \
row."
- if (pattern.containsIllegalBackReference()) {
- unsigned numSubpatterns = pattern.m_numSubpatterns;
-
- constructor.reset();
-#if !ASSERT_DISABLED
- const char* error =
-#endif
- parse(constructor, patternString, numSubpatterns);
-
- ASSERT(!error);
- ASSERT(numSubpatterns == pattern.m_numSubpatterns);
- }
-
- constructor.checkForTerminalParentheses();
- constructor.optimizeBOL();
-
- constructor.setupOffsets();
- constructor.setupBeginChars();
-
- return 0;
-};
-
-
-} }
</del></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexCompilerh"></a>
<div class="delfile"><h4>Deleted: trunk/JavaScriptCore/yarr/RegexCompiler.h (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/yarr/RegexCompiler.h 2010-12-24 01:36:39 \
UTC (rev 74599)
+++ trunk/JavaScriptCore/yarr/RegexCompiler.h 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -1,39 +0,0 @@
</span><del>-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef RegexCompiler_h
-#define RegexCompiler_h
-
-#include "RegexParser.h"
-#include "RegexPattern.h"
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC { namespace Yarr {
-
-const char* compileRegex(const UString& patternString, RegexPattern& \
pattern);
-
-} } // namespace JSC::Yarr
-
-#endif // RegexCompiler_h
</del></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/yarr/RegexInterpreter.cpp \
(74599 => 74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/yarr/RegexInterpreter.cpp 2010-12-24 \
01:36:39 UTC (rev 74599)
+++ trunk/JavaScriptCore/yarr/RegexInterpreter.cpp 2010-12-24 01:40:54 UTC (rev \
74600) </span><span class="lines">@@ -27,7 +27,6 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "RegexInterpreter.h"
</span><span class="cx">
</span><del>-#include "RegexCompiler.h"
</del><span class="cx"> #include "RegexPattern.h"
</span><span class="cx"> #include <wtf/BumpPointerAllocator.h>
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/yarr/RegexJIT.cpp (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/yarr/RegexJIT.cpp 2010-12-24 01:36:39 UTC \
(rev 74599)
+++ trunk/JavaScriptCore/yarr/RegexJIT.cpp 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> #include "JSGlobalData.h"
</span><span class="cx"> #include "LinkBuffer.h"
</span><span class="cx"> #include "MacroAssembler.h"
</span><del>-#include "RegexCompiler.h"
</del><ins>+#include "RegexParser.h"
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(YARR_JIT)
</span><span class="cx">
</span></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexPatterncppfromrev74496trunkJavaScriptCoreyarrRegexCompilercpp"></a>
<div class="copfile"><h4>Copied: trunk/JavaScriptCore/yarr/RegexPattern.cpp (from \
rev 74496, trunk/JavaScriptCore/yarr/RegexCompiler.cpp) (0 => 74600)</h4> <pre \
class="diff"><span> <span class="info">--- \
trunk/JavaScriptCore/yarr/RegexPattern.cpp \
(rev 0)
+++ trunk/JavaScriptCore/yarr/RegexPattern.cpp 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -0,0 +1,991 @@
</span><ins>+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ *
+ * 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 "RegexInterpreter.h"
+#include "RegexPattern.h"
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+#include "RegExpJitTables.h"
+
+class CharacterClassConstructor {
+public:
+ CharacterClassConstructor(bool isCaseInsensitive = false)
+ : m_isCaseInsensitive(isCaseInsensitive)
+ {
+ }
+
+ void reset()
+ {
+ m_matches.clear();
+ m_ranges.clear();
+ m_matchesUnicode.clear();
+ m_rangesUnicode.clear();
+ }
+
+ void append(const CharacterClass* other)
+ {
+ for (size_t i = 0; i < other->m_matches.size(); ++i)
+ addSorted(m_matches, other->m_matches[i]);
+ for (size_t i = 0; i < other->m_ranges.size(); ++i)
+ addSortedRange(m_ranges, other->m_ranges[i].begin, \
other->m_ranges[i].end); + for (size_t i = 0; i < \
other->m_matchesUnicode.size(); ++i) + addSorted(m_matchesUnicode, \
other->m_matchesUnicode[i]); + for (size_t i = 0; i < \
other->m_rangesUnicode.size(); ++i) + addSortedRange(m_rangesUnicode, \
other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end); + }
+
+ void putChar(UChar ch)
+ {
+ if (ch <= 0x7f) {
+ if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
+ addSorted(m_matches, toASCIIUpper(ch));
+ addSorted(m_matches, toASCIILower(ch));
+ } else
+ addSorted(m_matches, ch);
+ } else {
+ UChar upper, lower;
+ if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != \
(lower = Unicode::toLower(ch)))) { + addSorted(m_matchesUnicode, \
upper); + addSorted(m_matchesUnicode, lower);
+ } else
+ addSorted(m_matchesUnicode, ch);
+ }
+ }
+
+ // returns true if this character has another case, and 'ch' is the upper case \
form. + static inline bool isUnicodeUpper(UChar ch)
+ {
+ return ch != Unicode::toLower(ch);
+ }
+
+ // returns true if this character has another case, and 'ch' is the lower case \
form. + static inline bool isUnicodeLower(UChar ch)
+ {
+ return ch != Unicode::toUpper(ch);
+ }
+
+ void putRange(UChar lo, UChar hi)
+ {
+ if (lo <= 0x7f) {
+ char asciiLo = lo;
+ char asciiHi = std::min(hi, (UChar)0x7f);
+ addSortedRange(m_ranges, lo, asciiHi);
+
+ if (m_isCaseInsensitive) {
+ if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
+ addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), \
std::min(asciiHi, 'Z')+('a'-'A')); + if ((asciiLo <= 'z') \
&& (asciiHi >= 'a')) + addSortedRange(m_ranges, \
std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a')); + }
+ }
+ if (hi >= 0x80) {
+ uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
+ addSortedRange(m_rangesUnicode, unicodeCurr, hi);
+
+ if (m_isCaseInsensitive) {
+ while (unicodeCurr <= hi) {
+ // If the upper bound of the range (hi) is 0xffff, the \
increments to + // unicodeCurr in this loop may take it to \
0x10000. This is fine + // (if so we won't re-enter the loop, \
since the loop condition above + // will definitely fail) - but \
this does mean we cannot use a UChar + // to represent \
unicodeCurr, we must use a 32-bit value instead. + \
ASSERT(unicodeCurr <= 0xffff); +
+ if (isUnicodeUpper(unicodeCurr)) {
+ UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
+ UChar lowerCaseRangeEnd = lowerCaseRangeBegin;
+ while ((++unicodeCurr <= hi) && \
isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == \
(lowerCaseRangeEnd + 1))) + lowerCaseRangeEnd++;
+ addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, \
lowerCaseRangeEnd); + } else if (isUnicodeLower(unicodeCurr)) {
+ UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr);
+ UChar upperCaseRangeEnd = upperCaseRangeBegin;
+ while ((++unicodeCurr <= hi) && \
isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == \
(upperCaseRangeEnd + 1))) + upperCaseRangeEnd++;
+ addSortedRange(m_rangesUnicode, upperCaseRangeBegin, \
upperCaseRangeEnd); + } else
+ ++unicodeCurr;
+ }
+ }
+ }
+ }
+
+ CharacterClass* charClass()
+ {
+ CharacterClass* characterClass = new CharacterClass(0);
+
+ characterClass->m_matches.append(m_matches);
+ characterClass->m_ranges.append(m_ranges);
+ characterClass->m_matchesUnicode.append(m_matchesUnicode);
+ characterClass->m_rangesUnicode.append(m_rangesUnicode);
+
+ reset();
+
+ return characterClass;
+ }
+
+private:
+ void addSorted(Vector<UChar>& matches, UChar ch)
+ {
+ unsigned pos = 0;
+ unsigned range = matches.size();
+
+ // binary chop, find position to insert char.
+ while (range) {
+ unsigned index = range >> 1;
+
+ int val = matches[pos+index] - ch;
+ if (!val)
+ return;
+ else if (val > 0)
+ range = index;
+ else {
+ pos += (index+1);
+ range -= (index+1);
+ }
+ }
+
+ if (pos == matches.size())
+ matches.append(ch);
+ else
+ matches.insert(pos, ch);
+ }
+
+ void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar \
hi) + {
+ unsigned end = ranges.size();
+
+ // Simple linear scan - I doubt there are that many ranges anyway...
+ // feel free to fix this with something faster (eg binary chop).
+ for (unsigned i = 0; i < end; ++i) {
+ // does the new range fall before the current position in the array
+ if (hi < ranges[i].begin) {
+ // optional optimization: concatenate appending ranges? - may not be \
worthwhile. + if (hi == (ranges[i].begin - 1)) {
+ ranges[i].begin = lo;
+ return;
+ }
+ ranges.insert(i, CharacterRange(lo, hi));
+ return;
+ }
+ // Okay, since we didn't hit the last case, the end of the new range is \
definitely at or after the begining + // If the new range start at or \
before the end of the last range, then the overlap (if it starts one after the + \
// end of the last range they concatenate, which is just as good. + if (lo \
<= (ranges[i].end + 1)) { + // found an intersect! we'll replace \
this entry in the array. + ranges[i].begin = std::min(ranges[i].begin, \
lo); + ranges[i].end = std::max(ranges[i].end, hi);
+
+ // now check if the new range can subsume any subsequent ranges.
+ unsigned next = i+1;
+ // each iteration of the loop we will either remove something from \
the list, or break the loop. + while (next < ranges.size()) {
+ if (ranges[next].begin <= (ranges[i].end + 1)) {
+ // the next entry now overlaps / concatenates this one.
+ ranges[i].end = std::max(ranges[i].end, ranges[next].end);
+ ranges.remove(next);
+ } else
+ break;
+ }
+
+ return;
+ }
+ }
+
+ // CharacterRange comes after all existing ranges.
+ ranges.append(CharacterRange(lo, hi));
+ }
+
+ bool m_isCaseInsensitive;
+
+ Vector<UChar> m_matches;
+ Vector<CharacterRange> m_ranges;
+ Vector<UChar> m_matchesUnicode;
+ Vector<CharacterRange> m_rangesUnicode;
+};
+
+struct BeginCharHelper {
+ BeginCharHelper(Vector<BeginChar>* beginChars, bool isCaseInsensitive = \
false) + : m_beginChars(beginChars)
+ , m_isCaseInsensitive(isCaseInsensitive)
+ {}
+
+ void addBeginChar(BeginChar beginChar, Vector<TermChain>* hotTerms, \
QuantifierType quantityType, unsigned quantityCount) + {
+ if (quantityType == QuantifierFixedCount && quantityCount > 1) {
+ // We duplicate the first found character if the quantity of the term is \
more than one. eg.: /a{3}/ + beginChar.value |= beginChar.value << \
16; + beginChar.mask |= beginChar.mask << 16;
+ addCharacter(beginChar);
+ } else if (quantityType == QuantifierFixedCount && quantityCount == \
1 && hotTerms->size()) + // In case of characters with fixed \
quantifier we should check the next character as well. + \
linkHotTerms(beginChar, hotTerms); + else
+ // In case of greedy matching the next character checking is unnecessary \
therefore we just store + // the first character.
+ addCharacter(beginChar);
+ }
+
+ // Merge two following BeginChars in the vector to reduce the number of \
character checks. + void merge(unsigned size)
+ {
+ for (unsigned i = 0; i < size; i++) {
+ BeginChar* curr = &m_beginChars->at(i);
+ BeginChar* next = &m_beginChars->at(i + 1);
+
+ // If the current and the next size of value is different we should skip \
the merge process + // because the 16bit and 32bit values are unmergable.
+ if (curr->value <= 0xFFFF && next->value > 0xFFFF)
+ continue;
+
+ unsigned diff = curr->value ^ next->value;
+
+ curr->mask |= diff;
+ curr->value |= curr->mask;
+
+ m_beginChars->remove(i + 1);
+ size--;
+ }
+ }
+
+private:
+ void addCharacter(BeginChar beginChar)
+ {
+ unsigned pos = 0;
+ unsigned range = m_beginChars->size();
+
+ // binary chop, find position to insert char.
+ while (range) {
+ unsigned index = range >> 1;
+
+ int val = m_beginChars->at(pos+index).value - beginChar.value;
+ if (!val)
+ return;
+ if (val < 0)
+ range = index;
+ else {
+ pos += (index+1);
+ range -= (index+1);
+ }
+ }
+
+ if (pos == m_beginChars->size())
+ m_beginChars->append(beginChar);
+ else
+ m_beginChars->insert(pos, beginChar);
+ }
+
+ // Create BeginChar objects by appending each terms from a hotTerms vector to an \
existing BeginChar object. + void linkHotTerms(BeginChar beginChar, \
Vector<TermChain>* hotTerms) + {
+ for (unsigned i = 0; i < hotTerms->size(); i++) {
+ PatternTerm hotTerm = hotTerms->at(i).term;
+ ASSERT(hotTerm.type == PatternTerm::TypePatternCharacter);
+
+ UChar characterNext = hotTerm.patternCharacter;
+
+ // Append a character to an existing BeginChar object.
+ if (characterNext <= 0x7f) {
+ unsigned mask = 0;
+
+ if (m_isCaseInsensitive && isASCIIAlpha(characterNext)) {
+ mask = 32;
+ characterNext = toASCIILower(characterNext);
+ }
+
+ addCharacter(BeginChar(beginChar.value | (characterNext << \
16), beginChar.mask | (mask << 16))); + } else {
+ UChar upper, lower;
+ if (m_isCaseInsensitive && ((upper = \
Unicode::toUpper(characterNext)) != (lower = Unicode::toLower(characterNext)))) { + \
addCharacter(BeginChar(beginChar.value | (upper << 16), beginChar.mask)); + \
addCharacter(BeginChar(beginChar.value | (lower << 16), beginChar.mask)); + \
} else + addCharacter(BeginChar(beginChar.value | (characterNext \
<< 16), beginChar.mask)); + }
+ }
+ }
+
+ Vector<BeginChar>* m_beginChars;
+ bool m_isCaseInsensitive;
+};
+
+class RegexPatternConstructor {
+public:
+ RegexPatternConstructor(RegexPattern& pattern)
+ : m_pattern(pattern)
+ , m_characterClassConstructor(pattern.m_ignoreCase)
+ , m_beginCharHelper(&pattern.m_beginChars, pattern.m_ignoreCase)
+ , m_invertParentheticalAssertion(false)
+ {
+ }
+
+ ~RegexPatternConstructor()
+ {
+ }
+
+ void reset()
+ {
+ m_pattern.reset();
+ m_characterClassConstructor.reset();
+ }
+
+ void assertionBOL()
+ {
+ if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) \
{ + m_alternative->m_startsWithBOL = true;
+ m_alternative->m_containsBOL = true;
+ m_pattern.m_containsBOL = true;
+ }
+ m_alternative->m_terms.append(PatternTerm::BOL());
+ }
+ void assertionEOL()
+ {
+ m_alternative->m_terms.append(PatternTerm::EOL());
+ }
+ void assertionWordBoundary(bool invert)
+ {
+ m_alternative->m_terms.append(PatternTerm::WordBoundary(invert));
+ }
+
+ void atomPatternCharacter(UChar ch)
+ {
+ // We handle case-insensitive checking of unicode characters which do have \
both + // cases by handling them as if they were defined using a \
CharacterClass. + if (m_pattern.m_ignoreCase && !isASCII(ch) \
&& (Unicode::toUpper(ch) != Unicode::toLower(ch))) { + \
atomCharacterClassBegin(); + atomCharacterClassAtom(ch);
+ atomCharacterClassEnd();
+ } else
+ m_alternative->m_terms.append(PatternTerm(ch));
+ }
+
+ void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
+ {
+ switch (classID) {
+ case DigitClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), \
invert)); + break;
+ case SpaceClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), \
invert)); + break;
+ case WordClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), \
invert)); + break;
+ case NewlineClassID:
+ m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), \
invert)); + break;
+ }
+ }
+
+ void atomCharacterClassBegin(bool invert = false)
+ {
+ m_invertCharacterClass = invert;
+ }
+
+ void atomCharacterClassAtom(UChar ch)
+ {
+ m_characterClassConstructor.putChar(ch);
+ }
+
+ void atomCharacterClassRange(UChar begin, UChar end)
+ {
+ m_characterClassConstructor.putRange(begin, end);
+ }
+
+ void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
+ {
+ ASSERT(classID != NewlineClassID);
+
+ switch (classID) {
+ case DigitClassID:
+ m_characterClassConstructor.append(invert ? \
m_pattern.nondigitsCharacterClass() : m_pattern.digitsCharacterClass()); + \
break; +
+ case SpaceClassID:
+ m_characterClassConstructor.append(invert ? \
m_pattern.nonspacesCharacterClass() : m_pattern.spacesCharacterClass()); + \
break; +
+ case WordClassID:
+ m_characterClassConstructor.append(invert ? \
m_pattern.nonwordcharCharacterClass() : m_pattern.wordcharCharacterClass()); + \
break; +
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ void atomCharacterClassEnd()
+ {
+ CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
+ m_pattern.m_userCharacterClasses.append(newCharacterClass);
+ m_alternative->m_terms.append(PatternTerm(newCharacterClass, \
m_invertCharacterClass)); + }
+
+ void atomParenthesesSubpatternBegin(bool capture = true)
+ {
+ unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
+ if (capture)
+ m_pattern.m_numSubpatterns++;
+
+ PatternDisjunction* parenthesesDisjunction = new \
PatternDisjunction(m_alternative); + \
m_pattern.m_disjunctions.append(parenthesesDisjunction); + \
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, \
subpatternId, parenthesesDisjunction, capture, false)); + m_alternative = \
parenthesesDisjunction->addNewAlternative(); + }
+
+ void atomParentheticalAssertionBegin(bool invert = false)
+ {
+ PatternDisjunction* parenthesesDisjunction = new \
PatternDisjunction(m_alternative); + \
m_pattern.m_disjunctions.append(parenthesesDisjunction); + \
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, \
m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, invert)); + \
m_alternative = parenthesesDisjunction->addNewAlternative(); + \
m_invertParentheticalAssertion = invert; + }
+
+ void atomParenthesesEnd()
+ {
+ ASSERT(m_alternative->m_parent);
+ ASSERT(m_alternative->m_parent->m_parent);
+
+ PatternDisjunction* parenthesesDisjunction = m_alternative->m_parent;
+ m_alternative = m_alternative->m_parent->m_parent;
+
+ PatternTerm& lastTerm = m_alternative->lastTerm();
+
+ unsigned numParenAlternatives = \
parenthesesDisjunction->m_alternatives.size(); + unsigned \
numBOLAnchoredAlts = 0; + // Bubble up BOL flags
+ for (unsigned i = 0; i < numParenAlternatives; i++) {
+ if (parenthesesDisjunction->m_alternatives[i]->m_startsWithBOL)
+ numBOLAnchoredAlts++;
+ }
+
+ if (numBOLAnchoredAlts) {
+ m_alternative->m_containsBOL = true;
+ // If all the alternatives in parens start with BOL, then so does this \
one + if (numBOLAnchoredAlts == numParenAlternatives)
+ m_alternative->m_startsWithBOL = true;
+ }
+
+ lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
+ m_invertParentheticalAssertion = false;
+ }
+
+ void atomBackReference(unsigned subpatternId)
+ {
+ ASSERT(subpatternId);
+ m_pattern.m_containsBackreferences = true;
+ m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, \
subpatternId); +
+ if (subpatternId > m_pattern.m_numSubpatterns) {
+ m_alternative->m_terms.append(PatternTerm::ForwardReference());
+ return;
+ }
+
+ PatternAlternative* currentAlternative = m_alternative;
+ ASSERT(currentAlternative);
+
+ // Note to self: if we waited until the AST was baked, we could also remove \
forwards refs + while ((currentAlternative = \
currentAlternative->m_parent->m_parent)) { + PatternTerm& term = \
currentAlternative->lastTerm(); + ASSERT((term.type == \
PatternTerm::TypeParenthesesSubpattern) || (term.type == \
PatternTerm::TypeParentheticalAssertion)); +
+ if ((term.type == PatternTerm::TypeParenthesesSubpattern) && \
term.capture() && (subpatternId == term.parentheses.subpatternId)) { + \
m_alternative->m_terms.append(PatternTerm::ForwardReference()); + \
return; + }
+ }
+
+ m_alternative->m_terms.append(PatternTerm(subpatternId));
+ }
+
+ // deep copy the argument disjunction. If filterStartsWithBOL is true,
+ // skip alternatives with m_startsWithBOL set true.
+ PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool \
filterStartsWithBOL = false) + {
+ PatternDisjunction* newDisjunction = 0;
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) { + PatternAlternative* alternative = \
disjunction->m_alternatives[alt]; + if (!filterStartsWithBOL || \
!alternative->m_startsWithBOL) { + if (!newDisjunction) {
+ newDisjunction = new PatternDisjunction();
+ newDisjunction->m_parent = disjunction->m_parent;
+ }
+ PatternAlternative* newAlternative = \
newDisjunction->addNewAlternative(); + for (unsigned i = 0; i < \
alternative->m_terms.size(); ++i) + \
newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], \
filterStartsWithBOL)); + }
+ }
+
+ if (newDisjunction)
+ m_pattern.m_disjunctions.append(newDisjunction);
+ return newDisjunction;
+ }
+
+ PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false)
+ {
+ if ((term.type != PatternTerm::TypeParenthesesSubpattern) && \
(term.type != PatternTerm::TypeParentheticalAssertion)) + return \
PatternTerm(term); +
+ PatternTerm termCopy = term;
+ termCopy.parentheses.disjunction = \
copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL); + \
return termCopy; + }
+
+ void quantifyAtom(unsigned min, unsigned max, bool greedy)
+ {
+ ASSERT(min <= max);
+ ASSERT(m_alternative->m_terms.size());
+
+ if (!max) {
+ m_alternative->removeLastTerm();
+ return;
+ }
+
+ PatternTerm& term = m_alternative->lastTerm();
+ ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
+ ASSERT((term.quantityCount == 1) && (term.quantityType == \
QuantifierFixedCount)); +
+ // For any assertion with a zero minimum, not matching is valid and has no \
effect, + // remove it. Otherwise, we need to match as least once, but there \
is no point + // matching more than once, so remove the quantifier. It is not \
entirely clear + // from the spec whether or not this behavior is correct, but \
I believe this + // matches Firefox. :-/
+ if (term.type == PatternTerm::TypeParentheticalAssertion) {
+ if (!min)
+ m_alternative->removeLastTerm();
+ return;
+ }
+
+ if (min == 0)
+ term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy);
+ else if (min == max)
+ term.quantify(min, QuantifierFixedCount);
+ else {
+ term.quantify(min, QuantifierFixedCount);
+ m_alternative->m_terms.append(copyTerm(term));
+ // NOTE: this term is interesting from an analysis perspective, in that \
it can be ignored..... + m_alternative->lastTerm().quantify((max == \
quantifyInfinite) ? max : max - min, greedy ? QuantifierGreedy : \
QuantifierNonGreedy); + if (m_alternative->lastTerm().type == \
PatternTerm::TypeParenthesesSubpattern) + \
m_alternative->lastTerm().parentheses.isCopy = true; + }
+ }
+
+ void disjunction()
+ {
+ m_alternative = m_alternative->m_parent->addNewAlternative();
+ }
+
+ void regexBegin()
+ {
+ m_pattern.m_body = new PatternDisjunction();
+ m_alternative = m_pattern.m_body->addNewAlternative();
+ m_pattern.m_disjunctions.append(m_pattern.m_body);
+ }
+ void regexEnd()
+ {
+ }
+ void regexError()
+ {
+ }
+
+ unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned \
currentCallFrameSize, unsigned initialInputPosition) + {
+ alternative->m_hasFixedSize = true;
+ unsigned currentInputPosition = initialInputPosition;
+
+ for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+ PatternTerm& term = alternative->m_terms[i];
+
+ switch (term.type) {
+ case PatternTerm::TypeAssertionBOL:
+ case PatternTerm::TypeAssertionEOL:
+ case PatternTerm::TypeAssertionWordBoundary:
+ term.inputPosition = currentInputPosition;
+ break;
+
+ case PatternTerm::TypeBackReference:
+ term.inputPosition = currentInputPosition;
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoBackReference; + \
alternative->m_hasFixedSize = false; + break;
+
+ case PatternTerm::TypeForwardReference:
+ break;
+
+ case PatternTerm::TypePatternCharacter:
+ term.inputPosition = currentInputPosition;
+ if (term.quantityType != QuantifierFixedCount) {
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoPatternCharacter; + \
alternative->m_hasFixedSize = false; + } else
+ currentInputPosition += term.quantityCount;
+ break;
+
+ case PatternTerm::TypeCharacterClass:
+ term.inputPosition = currentInputPosition;
+ if (term.quantityType != QuantifierFixedCount) {
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoCharacterClass; + \
alternative->m_hasFixedSize = false; + } else
+ currentInputPosition += term.quantityCount;
+ break;
+
+ case PatternTerm::TypeParenthesesSubpattern:
+ // Note: for fixed once parentheses we will ensure at least the \
minimum is available; others are on their own. + term.frameLocation = \
currentCallFrameSize; + if (term.quantityCount == 1 && \
!term.parentheses.isCopy) { + if (term.quantityType != \
QuantifierFixedCount) + currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParenthesesOnce; + \
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, \
currentCallFrameSize, currentInputPosition); + // If quantity is \
fixed, then pre-check its minimum size. + if (term.quantityType == \
QuantifierFixedCount) + currentInputPosition += \
term.parentheses.disjunction->m_minimumSize; + \
term.inputPosition = currentInputPosition; + } else if \
(term.parentheses.isTerminal) { + currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParenthesesTerminal; + \
currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, \
currentCallFrameSize, currentInputPosition); + term.inputPosition \
= currentInputPosition; + } else {
+ term.inputPosition = currentInputPosition;
+ setupDisjunctionOffsets(term.parentheses.disjunction, 0, \
currentInputPosition); + currentCallFrameSize += \
RegexStackSpaceForBackTrackInfoParentheses; + }
+ // Fixed count of 1 could be accepted, if they have a fixed size \
*AND* if all alternatives are of the same length. + \
alternative->m_hasFixedSize = false; + break;
+
+ case PatternTerm::TypeParentheticalAssertion:
+ term.inputPosition = currentInputPosition;
+ term.frameLocation = currentCallFrameSize;
+ currentCallFrameSize = \
setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + \
RegexStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition); + \
break; + }
+ }
+
+ alternative->m_minimumSize = currentInputPosition - initialInputPosition;
+ return currentCallFrameSize;
+ }
+
+ unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned \
initialCallFrameSize, unsigned initialInputPosition) + {
+ if ((disjunction != m_pattern.m_body) && \
(disjunction->m_alternatives.size() > 1)) + initialCallFrameSize += \
RegexStackSpaceForBackTrackInfoAlternative; +
+ unsigned minimumInputSize = UINT_MAX;
+ unsigned maximumCallFrameSize = 0;
+ bool hasFixedSize = true;
+
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) { + PatternAlternative* alternative = \
disjunction->m_alternatives[alt]; + unsigned \
currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, \
initialCallFrameSize, initialInputPosition); + minimumInputSize = \
min(minimumInputSize, alternative->m_minimumSize); + \
maximumCallFrameSize = max(maximumCallFrameSize, currentAlternativeCallFrameSize); + \
hasFixedSize &= alternative->m_hasFixedSize; + }
+
+ ASSERT(minimumInputSize != UINT_MAX);
+ ASSERT(maximumCallFrameSize >= initialCallFrameSize);
+
+ disjunction->m_hasFixedSize = hasFixedSize;
+ disjunction->m_minimumSize = minimumInputSize;
+ disjunction->m_callFrameSize = maximumCallFrameSize;
+ return maximumCallFrameSize;
+ }
+
+ void setupOffsets()
+ {
+ setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
+ }
+
+ // This optimization identifies sets of parentheses that we will never need to \
backtrack. + // In these cases we do not need to store state from prior \
iterations. + // We can presently avoid backtracking for:
+ // * where the parens are at the end of the regular expression (last term in \
any of the + // alternatives of the main body disjunction).
+ // * where the parens are non-capturing, and quantified unbounded greedy (*).
+ // * where the parens do not contain any capturing subpatterns.
+ void checkForTerminalParentheses()
+ {
+ // This check is much too crude; should be just checking whether the \
candidate + // node contains nested capturing subpatterns, not the whole \
expression! + if (m_pattern.m_numSubpatterns)
+ return;
+
+ Vector<PatternAlternative*>& alternatives = \
m_pattern.m_body->m_alternatives; + for (size_t i = 0; i < \
alternatives.size(); ++i) { + Vector<PatternTerm>& terms = \
alternatives[i]->m_terms; + if (terms.size()) {
+ PatternTerm& term = terms.last();
+ if (term.type == PatternTerm::TypeParenthesesSubpattern
+ && term.quantityType == QuantifierGreedy
+ && term.quantityCount == quantifyInfinite
+ && !term.capture())
+ term.parentheses.isTerminal = true;
+ }
+ }
+ }
+
+ void optimizeBOL()
+ {
+ // Look for expressions containing beginning of line (^) anchoring and \
unroll them. + // e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once \
followed by /c/ which loops + // This code relies on the parsing code tagging \
alternatives with m_containsBOL and + // m_startsWithBOL and rolling those up \
to containing alternatives. + // At this point, this is only valid for \
non-multiline expressions. + PatternDisjunction* disjunction = \
m_pattern.m_body; +
+ if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
+ return;
+
+ PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true);
+
+ // Set alternatives in disjunction to "onceThrough"
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) + disjunction->m_alternatives[alt]->setOnceThrough();
+
+ if (loopDisjunction) {
+ // Move alternatives from loopDisjunction to disjunction
+ for (unsigned alt = 0; alt < \
loopDisjunction->m_alternatives.size(); ++alt) + \
disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt]); + \
+ loopDisjunction->m_alternatives.clear();
+ }
+ }
+
+ bool addBeginTerm(PatternTerm term, Vector<TermChain>* beginTerms, \
PatternAlternative* alternative, unsigned numTerms, unsigned termIndex, unsigned \
depth) + {
+ if (term.quantityType == QuantifierFixedCount) {
+ beginTerms->append(TermChain(term));
+ if (depth < 2 && termIndex < numTerms - 1 && \
term.quantityCount == 1) + setupAlternativeBeginTerms(alternative, \
&beginTerms->last().hotTerms, termIndex + 1, depth + 1); + } else if \
(termIndex != numTerms - 1) { + beginTerms->append(TermChain(term));
+ return true;
+ }
+
+ return false;
+ }
+
+ // This function collects the terms which are potentially matching the first \
number of depth characters in the result. + // If this function returns false then \
it found at least one term which makes the beginning character + // look-up \
optimization inefficient. + bool setupDisjunctionBeginTerms(PatternDisjunction* \
disjunction, Vector<TermChain>* beginTerms, unsigned depth) + {
+ for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); \
++alt) { + PatternAlternative* alternative = \
disjunction->m_alternatives[alt]; +
+ if (!setupAlternativeBeginTerms(alternative, beginTerms, 0, depth))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool setupAlternativeBeginTerms(PatternAlternative* alternative, \
Vector<TermChain>* beginTerms, unsigned termIndex, unsigned depth) + {
+ bool checkNext = true;
+ unsigned numTerms = alternative->m_terms.size();
+
+ while (checkNext && termIndex < numTerms) {
+ PatternTerm term = alternative->m_terms[termIndex];
+ checkNext = false;
+
+ switch (term.type) {
+ case PatternTerm::TypeAssertionBOL:
+ case PatternTerm::TypeAssertionEOL:
+ case PatternTerm::TypeAssertionWordBoundary:
+ return false;
+
+ case PatternTerm::TypeBackReference:
+ case PatternTerm::TypeForwardReference:
+ return false;
+
+ case PatternTerm::TypePatternCharacter:
+ if (addBeginTerm(term, beginTerms, alternative, numTerms, termIndex, \
depth)) { + termIndex++;
+ checkNext = true;
+ }
+ break;
+
+ case PatternTerm::TypeCharacterClass:
+ return false;
+
+ case PatternTerm::TypeParentheticalAssertion:
+ if (term.invert())
+ return false;
+
+ case PatternTerm::TypeParenthesesSubpattern:
+ if (term.quantityType != QuantifierFixedCount) {
+ if (termIndex == numTerms - 1)
+ break;
+
+ termIndex++;
+ checkNext = true;
+
+ }
+
+ if (!setupDisjunctionBeginTerms(term.parentheses.disjunction, \
beginTerms, depth)) + return false;
+
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ void setupBeginChars()
+ {
+ Vector<TermChain> beginTerms;
+ bool containsFixedCharacter = false;
+
+ if ((!m_pattern.m_body->m_hasFixedSize || \
m_pattern.m_body->m_alternatives.size() > 1) + && \
setupDisjunctionBeginTerms(m_pattern.m_body, &beginTerms, 0)) { + \
unsigned size = beginTerms.size(); +
+ // If we haven't collected any terms we should abort the preparation of \
beginning character look-up optimization. + if (!size)
+ return;
+
+ m_pattern.m_containsBeginChars = true;
+
+ for (unsigned i = 0; i < size; i++) {
+ PatternTerm term = beginTerms[i].term;
+
+ // We have just collected PatternCharacter terms, other terms are \
not allowed. + ASSERT(term.type == PatternTerm::TypePatternCharacter);
+
+ if (term.quantityType == QuantifierFixedCount)
+ containsFixedCharacter = true;
+
+ UChar character = term.patternCharacter;
+ unsigned mask = 0;
+
+ if (character <= 0x7f) {
+ if (m_pattern.m_ignoreCase && isASCIIAlpha(character)) {
+ mask = 32;
+ character = toASCIILower(character);
+ }
+
+ m_beginCharHelper.addBeginChar(BeginChar(character, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount); + \
} else { + UChar upper, lower;
+ if (m_pattern.m_ignoreCase && ((upper = \
Unicode::toUpper(character)) != (lower = Unicode::toLower(character)))) { + \
m_beginCharHelper.addBeginChar(BeginChar(upper, mask), &beginTerms[i].hotTerms, \
term.quantityType, term.quantityCount); + \
m_beginCharHelper.addBeginChar(BeginChar(lower, mask), &beginTerms[i].hotTerms, \
term.quantityType, term.quantityCount); + } else
+ m_beginCharHelper.addBeginChar(BeginChar(character, mask), \
&beginTerms[i].hotTerms, term.quantityType, term.quantityCount); + \
} + }
+
+ // If the pattern doesn't contain terms with fixed quantifiers then the \
beginning character look-up optimization is inefficient. + if \
(!containsFixedCharacter) { + m_pattern.m_containsBeginChars = false;
+ return;
+ }
+
+ size = m_pattern.m_beginChars.size();
+
+ if (size > 2)
+ m_beginCharHelper.merge(size - 1);
+ else if (size <= 1)
+ m_pattern.m_containsBeginChars = false;
+ }
+ }
+
+private:
+ RegexPattern& m_pattern;
+ PatternAlternative* m_alternative;
+ CharacterClassConstructor m_characterClassConstructor;
+ BeginCharHelper m_beginCharHelper;
+ bool m_invertCharacterClass;
+ bool m_invertParentheticalAssertion;
+};
+
+
+static const char* compileRegex(const UString& patternString, RegexPattern& \
pattern) +{
+ RegexPatternConstructor constructor(pattern);
+
+ if (const char* error = parse(constructor, patternString))
+ return error;
+
+ // If the pattern contains illegal backreferences reset & reparse.
+ // Quoting Netscape's "What's new in JavaScript 1.2",
+ // "Note: if the number of left parentheses is less than the number \
specified + // in \#, the \# is taken as an octal escape as described in the \
next row." + if (pattern.containsIllegalBackReference()) {
+ unsigned numSubpatterns = pattern.m_numSubpatterns;
+
+ constructor.reset();
+#if !ASSERT_DISABLED
+ const char* error =
+#endif
+ parse(constructor, patternString, numSubpatterns);
+
+ ASSERT(!error);
+ ASSERT(numSubpatterns == pattern.m_numSubpatterns);
+ }
+
+ constructor.checkForTerminalParentheses();
+ constructor.optimizeBOL();
+
+ constructor.setupOffsets();
+ constructor.setupBeginChars();
+
+ return 0;
+};
+
+RegexPattern::RegexPattern(const UString& pattern, bool ignoreCase, bool \
multiline, const char** error) + : m_ignoreCase(ignoreCase)
+ , m_multiline(multiline)
+ , m_containsBackreferences(false)
+ , m_containsBeginChars(false)
+ , m_containsBOL(false)
+ , m_numSubpatterns(0)
+ , m_maxBackReference(0)
+ , newlineCached(0)
+ , digitsCached(0)
+ , spacesCached(0)
+ , wordcharCached(0)
+ , nondigitsCached(0)
+ , nonspacesCached(0)
+ , nonwordcharCached(0)
+{
+ *error = compileRegex(pattern, *this);
+}
+
+} }
</ins></span></pre></div>
<a id="trunkJavaScriptCoreyarrRegexPatternh"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/yarr/RegexPattern.h (74599 => \
74600)</h4> <pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/yarr/RegexPattern.h 2010-12-24 01:36:39 \
UTC (rev 74599)
+++ trunk/JavaScriptCore/yarr/RegexPattern.h 2010-12-24 01:40:54 UTC (rev 74600)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> #include <wtf/Vector.h>
</span><span class="cx"> #include <wtf/unicode/Unicode.h>
</span><span class="cx">
</span><ins>+#include <UString.h>
+
</ins><span class="cx"> namespace JSC { namespace Yarr {
</span><span class="cx">
</span><span class="cx"> #define RegexStackSpaceForBackTrackInfoPatternCharacter 1 // \
Only for !fixed quantifiers. </span><span class="lines">@@ -315,23 +317,7 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> struct RegexPattern {
</span><del>- RegexPattern(bool ignoreCase, bool multiline)
- : m_ignoreCase(ignoreCase)
- , m_multiline(multiline)
- , m_containsBackreferences(false)
- , m_containsBeginChars(false)
- , m_containsBOL(false)
- , m_numSubpatterns(0)
- , m_maxBackReference(0)
- , newlineCached(0)
- , digitsCached(0)
- , spacesCached(0)
- , wordcharCached(0)
- , nondigitsCached(0)
- , nonspacesCached(0)
- , nonwordcharCached(0)
- {
- }
</del><ins>+ RegexPattern(const UString& pattern, bool ignoreCase, bool \
multiline, const char** error); </ins><span class="cx">
</span><span class="cx"> ~RegexPattern()
</span><span class="cx"> {
</span></span></pre>
</div>
</div>
</body>
</html>
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic