OLD | NEW |
---|---|
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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 cache.lastIndex = lastIndex; | 250 cache.lastIndex = lastIndex; |
251 if (saveAnswer) cache.answer = CloneRegExpResult(result); | 251 if (saveAnswer) cache.answer = CloneRegExpResult(result); |
252 cache.answerSaved = saveAnswer; | 252 cache.answerSaved = saveAnswer; |
253 cache.type = 'exec'; | 253 cache.type = 'exec'; |
254 } | 254 } |
255 return result; | 255 return result; |
256 | 256 |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 // One-element cache for the simplified test regexp. | |
261 var regexp_key; | |
262 var regexp_val; | |
Lasse Reichstein
2010/06/04 11:30:33
How often do you hit this? (And how often will you
sandholm
2010/06/04 11:57:23
Caching negative results in the global regexp cach
| |
263 | |
260 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be | 264 // Section 15.10.6.3 doesn't actually make sense, but the intention seems to be |
261 // that test is defined in terms of String.prototype.exec. However, it probably | 265 // that test is defined in terms of String.prototype.exec. However, it probably |
262 // means the original value of String.prototype.exec, which is what everybody | 266 // means the original value of String.prototype.exec, which is what everybody |
263 // else implements. | 267 // else implements. |
264 function RegExpTest(string) { | 268 function RegExpTest(string) { |
265 if (!IS_REGEXP(this)) { | 269 if (!IS_REGEXP(this)) { |
266 throw MakeTypeError('incompatible_method_receiver', | 270 throw MakeTypeError('incompatible_method_receiver', |
267 ['RegExp.prototype.test', this]); | 271 ['RegExp.prototype.test', this]); |
268 } | 272 } |
269 if (%_ArgumentsLength() == 0) { | 273 if (%_ArgumentsLength() == 0) { |
270 var regExpInput = LAST_INPUT(lastMatchInfo); | 274 var regExpInput = LAST_INPUT(lastMatchInfo); |
271 if (IS_UNDEFINED(regExpInput)) { | 275 if (IS_UNDEFINED(regExpInput)) { |
272 throw MakeError('no_input_to_regexp', [this]); | 276 throw MakeError('no_input_to_regexp', [this]); |
273 } | 277 } |
274 string = regExpInput; | 278 string = regExpInput; |
275 } | 279 } |
276 var s; | 280 var s; |
277 if (IS_STRING(string)) { | 281 if (IS_STRING(string)) { |
278 s = string; | 282 s = string; |
279 } else { | 283 } else { |
280 s = ToString(string); | 284 s = ToString(string); |
281 } | 285 } |
282 | 286 |
283 var lastIndex = this.lastIndex; | 287 var lastIndex = this.lastIndex; |
284 | |
285 var cache = regExpCache; | 288 var cache = regExpCache; |
286 | |
287 if (%_ObjectEquals(cache.type, 'test') && | 289 if (%_ObjectEquals(cache.type, 'test') && |
288 %_ObjectEquals(cache.regExp, this) && | 290 %_ObjectEquals(cache.regExp, this) && |
289 %_ObjectEquals(cache.subject, string) && | 291 %_ObjectEquals(cache.subject, string) && |
290 %_ObjectEquals(cache.lastIndex, lastIndex)) { | 292 %_ObjectEquals(cache.lastIndex, lastIndex)) { |
291 return cache.answer; | 293 return cache.answer; |
292 } | 294 } |
293 | 295 |
296 // Remove irrelevant '.*' around a test regexp. The expression | |
297 // checks whether this.source starts and ends with '.*' and that the third | |
298 // char is not a '?' and that the third to last char is not a '\'. | |
299 if (%_StringCharCodeAt(this.source,0) == 46 && // '.' | |
Lasse Reichstein
2010/06/04 11:30:33
You may want to try moving this.source to a local
sandholm
2010/06/04 11:57:23
Tried this. Causes regressions on some benchmarks
| |
300 %_StringCharCodeAt(this.source,1) == 42 && // '*' | |
301 %_StringCharCodeAt(this.source,2) != 63 && // '?' | |
302 %_StringCharCodeAt(this.source,this.source.length - 3) != 28 && // '\' | |
303 %_StringCharCodeAt(this.source,this.source.length - 2) == 46 && // '.' | |
304 %_StringCharCodeAt(this.source,this.source.length - 1) == 42) { // '*' | |
305 if (!%_ObjectEquals(regexp_key, this)) { | |
306 regexp_key = this; | |
307 regexp_val = new $RegExp(this.source.substring(2, | |
308 this.source.length - 2), | |
309 (this.global ? 'g' : '') | |
310 + (this.ignoreCase ? 'i' : '') | |
311 + (this.multiline ? 'm' : '')); | |
312 } | |
313 if (!regexp_val.test(s)) return false; | |
Lasse Reichstein
2010/06/04 11:30:33
You can cache the negative result in the regexp ca
sandholm
2010/06/04 11:57:23
Often test is called with a new string so that won
| |
314 } | |
315 | |
294 var length = s.length; | 316 var length = s.length; |
295 var i = this.global ? TO_INTEGER(lastIndex) : 0; | 317 var i = this.global ? TO_INTEGER(lastIndex) : 0; |
296 | 318 |
297 cache.type = 'test'; | 319 cache.type = 'test'; |
298 cache.regExp = this; | 320 cache.regExp = this; |
299 cache.subject = s; | 321 cache.subject = s; |
300 cache.lastIndex = i; | 322 cache.lastIndex = i; |
301 | 323 |
302 if (i < 0 || i > s.length) { | 324 if (i < 0 || i > length) { |
303 this.lastIndex = 0; | 325 this.lastIndex = 0; |
304 cache.answer = false; | 326 cache.answer = false; |
305 return false; | 327 return false; |
306 } | 328 } |
307 | 329 |
308 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); | 330 %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); |
309 // matchIndices is either null or the lastMatchInfo array. | 331 // matchIndices is either null or the lastMatchInfo array. |
310 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); | 332 var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); |
311 | 333 |
312 if (matchIndices == null) { | 334 if (matchIndices == null) { |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
519 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); | 541 %DefineAccessor($RegExp, "$'", SETTER, NoOpSetter, DONT_ENUM | DONT_DELETE); |
520 | 542 |
521 for (var i = 1; i < 10; ++i) { | 543 for (var i = 1; i < 10; ++i) { |
522 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); | 544 %DefineAccessor($RegExp, '$' + i, GETTER, RegExpMakeCaptureGetter(i), DONT_D ELETE); |
523 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); | 545 %DefineAccessor($RegExp, '$' + i, SETTER, NoOpSetter, DONT_DELETE); |
524 } | 546 } |
525 } | 547 } |
526 | 548 |
527 | 549 |
528 SetupRegExp(); | 550 SetupRegExp(); |
OLD | NEW |