Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: src/regexp.js

Issue 5708006: Optimizing BuildResultFromMatchInfo, StringReplace and StringSplit. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/string.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 113
114 function DoRegExpExec(regexp, string, index) { 114 function DoRegExpExec(regexp, string, index) {
115 var result = %_RegExpExec(regexp, string, index, lastMatchInfo); 115 var result = %_RegExpExec(regexp, string, index, lastMatchInfo);
116 if (result !== null) lastMatchInfoOverride = null; 116 if (result !== null) lastMatchInfoOverride = null;
117 return result; 117 return result;
118 } 118 }
119 119
120 120
121 function BuildResultFromMatchInfo(lastMatchInfo, s) { 121 function BuildResultFromMatchInfo(lastMatchInfo, s) {
122 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; 122 var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
123 var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s); 123 var start = lastMatchInfo[CAPTURE0];
124 if (numResults === 1) { 124 var end = lastMatchInfo[CAPTURE1];
125 var matchStart = lastMatchInfo[CAPTURE(0)]; 125 var result = %_RegExpConstructResult(numResults, start, s);
126 var matchEnd = lastMatchInfo[CAPTURE(1)]; 126 if (start + 1 == end) {
127 result[0] = SubString(s, matchStart, matchEnd); 127 result[0] = %_StringCharAt(s, start);
128 } else { 128 } else {
129 for (var i = 0; i < numResults; i++) { 129 result[0] = %_SubString(s, start, end);
130 var matchStart = lastMatchInfo[CAPTURE(i << 1)]; 130 }
131 var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; 131 var j = REGEXP_FIRST_CAPTURE + 2;
132 if (matchStart != -1 && matchEnd != -1) { 132 for (var i = 1; i < numResults; i++) {
133 result[i] = SubString(s, matchStart, matchEnd); 133 start = lastMatchInfo[j++];
134 end = lastMatchInfo[j++];
135 if (end != -1) {
136 if (start + 1 == end) {
137 result[i] = %_StringCharAt(s, start);
134 } else { 138 } else {
135 // Make sure the element is present. Avoid reading the undefined 139 result[i] = %_SubString(s, start, end);
136 // property from the global object since this may change.
137 result[i] = void 0;
138 } 140 }
141 } else {
142 // Make sure the element is present. Avoid reading the undefined
143 // property from the global object since this may change.
144 result[i] = void 0;
139 } 145 }
140 } 146 }
141 return result; 147 return result;
142 } 148 }
143 149
144 150
145 function RegExpExecNoTests(regexp, string, start) { 151 function RegExpExecNoTests(regexp, string, start) {
146 // Must be called with RegExp, string and positive integer as arguments. 152 // Must be called with RegExp, string and positive integer as arguments.
147 var matchInfo = DoRegExpExec(regexp, string, start); 153 var matchInfo = DoRegExpExec(regexp, string, start);
148 var result = null; 154 var result = null;
(...skipping 10 matching lines...) Expand all
159 ['RegExp.prototype.exec', this]); 165 ['RegExp.prototype.exec', this]);
160 } 166 }
161 167
162 if (%_ArgumentsLength() === 0) { 168 if (%_ArgumentsLength() === 0) {
163 var regExpInput = LAST_INPUT(lastMatchInfo); 169 var regExpInput = LAST_INPUT(lastMatchInfo);
164 if (IS_UNDEFINED(regExpInput)) { 170 if (IS_UNDEFINED(regExpInput)) {
165 throw MakeError('no_input_to_regexp', [this]); 171 throw MakeError('no_input_to_regexp', [this]);
166 } 172 }
167 string = regExpInput; 173 string = regExpInput;
168 } 174 }
169 var s; 175 string = TO_STRING_INLINE(string);
170 if (IS_STRING(string)) {
171 s = string;
172 } else {
173 s = ToString(string);
174 }
175 var lastIndex = this.lastIndex; 176 var lastIndex = this.lastIndex;
176 177
177 // Conversion is required by the ES5 specification (RegExp.prototype.exec 178 // Conversion is required by the ES5 specification (RegExp.prototype.exec
178 // algorithm, step 5) even if the value is discarded for non-global RegExps. 179 // algorithm, step 5) even if the value is discarded for non-global RegExps.
179 var i = TO_INTEGER(lastIndex); 180 var i = TO_INTEGER(lastIndex);
180 181
181 var global = this.global; 182 var global = this.global;
182 if (global) { 183 if (global) {
183 if (i < 0 || i > s.length) { 184 if (i < 0 || i > string.length) {
184 this.lastIndex = 0; 185 this.lastIndex = 0;
185 return null; 186 return null;
186 } 187 }
187 } else { 188 } else {
188 i = 0; 189 i = 0;
189 } 190 }
190 191
191 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 192 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
192 // matchIndices is either null or the lastMatchInfo array. 193 // matchIndices is either null or the lastMatchInfo array.
193 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 194 var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
194 195
195 if (matchIndices === null) { 196 if (matchIndices === null) {
196 if (global) this.lastIndex = 0; 197 if (global) this.lastIndex = 0;
197 return null; 198 return null;
198 } 199 }
199 200
200 // Successful match. 201 // Successful match.
201 lastMatchInfoOverride = null; 202 lastMatchInfoOverride = null;
202 if (global) { 203 if (global) {
203 this.lastIndex = lastMatchInfo[CAPTURE1]; 204 this.lastIndex = lastMatchInfo[CAPTURE1];
204 } 205 }
205 return BuildResultFromMatchInfo(matchIndices, s); 206 return BuildResultFromMatchInfo(matchIndices, string);
206 } 207 }
207 208
208 209
209 // One-element cache for the simplified test regexp. 210 // One-element cache for the simplified test regexp.
210 var regexp_key; 211 var regexp_key;
211 var regexp_val; 212 var regexp_val;
212 213
213 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be 214 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be
214 // that test is defined in terms of String.prototype.exec. However, it probably 215 // that test is defined in terms of String.prototype.exec. However, it probably
215 // means the original value of String.prototype.exec, which is what everybody 216 // means the original value of String.prototype.exec, which is what everybody
216 // else implements. 217 // else implements.
217 function RegExpTest(string) { 218 function RegExpTest(string) {
218 if (!IS_REGEXP(this)) { 219 if (!IS_REGEXP(this)) {
219 throw MakeTypeError('incompatible_method_receiver', 220 throw MakeTypeError('incompatible_method_receiver',
220 ['RegExp.prototype.test', this]); 221 ['RegExp.prototype.test', this]);
221 } 222 }
222 if (%_ArgumentsLength() == 0) { 223 if (%_ArgumentsLength() == 0) {
223 var regExpInput = LAST_INPUT(lastMatchInfo); 224 var regExpInput = LAST_INPUT(lastMatchInfo);
224 if (IS_UNDEFINED(regExpInput)) { 225 if (IS_UNDEFINED(regExpInput)) {
225 throw MakeError('no_input_to_regexp', [this]); 226 throw MakeError('no_input_to_regexp', [this]);
226 } 227 }
227 string = regExpInput; 228 string = regExpInput;
228 } 229 }
229 230
230 var s; 231 string = TO_STRING_INLINE(string);
231 if (IS_STRING(string)) {
232 s = string;
233 } else {
234 s = ToString(string);
235 }
236 232
237 var lastIndex = this.lastIndex; 233 var lastIndex = this.lastIndex;
238 234
239 // Conversion is required by the ES5 specification (RegExp.prototype.exec 235 // Conversion is required by the ES5 specification (RegExp.prototype.exec
240 // algorithm, step 5) even if the value is discarded for non-global RegExps. 236 // algorithm, step 5) even if the value is discarded for non-global RegExps.
241 var i = TO_INTEGER(lastIndex); 237 var i = TO_INTEGER(lastIndex);
242 238
243 if (this.global) { 239 if (this.global) {
244 if (i < 0 || i > s.length) { 240 if (i < 0 || i > string.length) {
245 this.lastIndex = 0; 241 this.lastIndex = 0;
246 return false; 242 return false;
247 } 243 }
248 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 244 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
249 // matchIndices is either null or the lastMatchInfo array. 245 // matchIndices is either null or the lastMatchInfo array.
250 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); 246 var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
251 if (matchIndices === null) { 247 if (matchIndices === null) {
252 this.lastIndex = 0; 248 this.lastIndex = 0;
253 return false; 249 return false;
254 } 250 }
255 lastMatchInfoOverride = null; 251 lastMatchInfoOverride = null;
256 this.lastIndex = lastMatchInfo[CAPTURE1]; 252 this.lastIndex = lastMatchInfo[CAPTURE1];
257 return true; 253 return true;
258 } else { 254 } else {
259 // Non-global regexp. 255 // Non-global regexp.
260 // Remove irrelevant preceeding '.*' in a non-global test regexp. 256 // Remove irrelevant preceeding '.*' in a non-global test regexp.
261 // The expression checks whether this.source starts with '.*' and 257 // The expression checks whether this.source starts with '.*' and
262 // that the third char is not a '?'. 258 // that the third char is not a '?'.
263 if (%_StringCharCodeAt(this.source, 0) == 46 && // '.' 259 if (%_StringCharCodeAt(this.source, 0) == 46 && // '.'
264 %_StringCharCodeAt(this.source, 1) == 42 && // '*' 260 %_StringCharCodeAt(this.source, 1) == 42 && // '*'
265 %_StringCharCodeAt(this.source, 2) != 63) { // '?' 261 %_StringCharCodeAt(this.source, 2) != 63) { // '?'
266 if (!%_ObjectEquals(regexp_key, this)) { 262 if (!%_ObjectEquals(regexp_key, this)) {
267 regexp_key = this; 263 regexp_key = this;
268 regexp_val = new $RegExp(this.source.substring(2, this.source.length), 264 regexp_val = new $RegExp(this.source.substring(2, this.source.length),
269 (this.ignoreCase ? 'i' : '') 265 (this.ignoreCase ? 'i' : '')
270 + (this.multiline ? 'm' : '')); 266 + (this.multiline ? 'm' : ''));
271 } 267 }
272 if (!regexp_val.test(s)) return false; 268 if (!regexp_val.test(string)) return false;
273 } 269 }
274 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); 270 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
275 // matchIndices is either null or the lastMatchInfo array. 271 // matchIndices is either null or the lastMatchInfo array.
276 var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo); 272 var matchIndices = %_RegExpExec(this, string, 0, lastMatchInfo);
277 if (matchIndices === null) return false; 273 if (matchIndices === null) return false;
278 lastMatchInfoOverride = null; 274 lastMatchInfoOverride = null;
279 return true; 275 return true;
280 } 276 }
281 } 277 }
282 278
283 279
284 function RegExpToString() { 280 function RegExpToString() {
285 // If this.source is an empty string, output /(?:)/. 281 // If this.source is an empty string, output /(?:)/.
286 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550 282 // http://bugzilla.mozilla.org/show_bug.cgi?id=225550
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); 471 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE);
476 472
477 for (var i = 1; i < 10; ++i) { 473 for (var i = 1; i < 10; ++i) {
478 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); 474 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE);
479 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); 475 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE);
480 } 476 }
481 } 477 }
482 478
483 479
484 SetupRegExp(); 480 SetupRegExp();
OLDNEW
« no previous file with comments | « no previous file | src/string.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698