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

Side by Side Diff: src/jsregexp.cc

Issue 580383003: Reland sticky regexps https://codereview.chromium.org/567313003/ (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months 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 | « src/jsregexp.h ('k') | src/objects.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/ast.h" 7 #include "src/ast.h"
8 #include "src/base/platform/platform.h" 8 #include "src/base/platform/platform.h"
9 #include "src/compilation-cache.h" 9 #include "src/compilation-cache.h"
10 #include "src/compiler.h" 10 #include "src/compiler.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 switch (str->Get(i)) { 63 switch (str->Get(i)) {
64 case 'i': 64 case 'i':
65 flags |= JSRegExp::IGNORE_CASE; 65 flags |= JSRegExp::IGNORE_CASE;
66 break; 66 break;
67 case 'g': 67 case 'g':
68 flags |= JSRegExp::GLOBAL; 68 flags |= JSRegExp::GLOBAL;
69 break; 69 break;
70 case 'm': 70 case 'm':
71 flags |= JSRegExp::MULTILINE; 71 flags |= JSRegExp::MULTILINE;
72 break; 72 break;
73 case 'y':
74 if (FLAG_harmony_regexps) flags |= JSRegExp::STICKY;
75 break;
73 } 76 }
74 } 77 }
75 return JSRegExp::Flags(flags); 78 return JSRegExp::Flags(flags);
76 } 79 }
77 80
78 81
79 MUST_USE_RESULT 82 MUST_USE_RESULT
80 static inline MaybeHandle<Object> ThrowRegExpException( 83 static inline MaybeHandle<Object> ThrowRegExpException(
81 Handle<JSRegExp> re, 84 Handle<JSRegExp> re,
82 Handle<String> pattern, 85 Handle<String> pattern,
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 return ThrowRegExpException(re, 181 return ThrowRegExpException(re,
179 pattern, 182 pattern,
180 parse_result.error, 183 parse_result.error,
181 "malformed_regexp"); 184 "malformed_regexp");
182 } 185 }
183 186
184 bool has_been_compiled = false; 187 bool has_been_compiled = false;
185 188
186 if (parse_result.simple && 189 if (parse_result.simple &&
187 !flags.is_ignore_case() && 190 !flags.is_ignore_case() &&
191 !flags.is_sticky() &&
188 !HasFewDifferentCharacters(pattern)) { 192 !HasFewDifferentCharacters(pattern)) {
189 // Parse-tree is a single atom that is equal to the pattern. 193 // Parse-tree is a single atom that is equal to the pattern.
190 AtomCompile(re, pattern, flags, pattern); 194 AtomCompile(re, pattern, flags, pattern);
191 has_been_compiled = true; 195 has_been_compiled = true;
192 } else if (parse_result.tree->IsAtom() && 196 } else if (parse_result.tree->IsAtom() &&
193 !flags.is_ignore_case() && 197 !flags.is_ignore_case() &&
198 !flags.is_sticky() &&
194 parse_result.capture_count == 0) { 199 parse_result.capture_count == 0) {
195 RegExpAtom* atom = parse_result.tree->AsAtom(); 200 RegExpAtom* atom = parse_result.tree->AsAtom();
196 Vector<const uc16> atom_pattern = atom->data(); 201 Vector<const uc16> atom_pattern = atom->data();
197 Handle<String> atom_string; 202 Handle<String> atom_string;
198 ASSIGN_RETURN_ON_EXCEPTION( 203 ASSIGN_RETURN_ON_EXCEPTION(
199 isolate, atom_string, 204 isolate, atom_string,
200 isolate->factory()->NewStringFromTwoByte(atom_pattern), 205 isolate->factory()->NewStringFromTwoByte(atom_pattern),
201 Object); 206 Object);
202 if (!HasFewDifferentCharacters(atom_string)) { 207 if (!HasFewDifferentCharacters(atom_string)) {
203 AtomCompile(re, pattern, flags, atom_string); 208 AtomCompile(re, pattern, flags, atom_string);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 // Throw an exception if we fail to parse the pattern. 428 // Throw an exception if we fail to parse the pattern.
424 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. 429 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
425 USE(ThrowRegExpException(re, 430 USE(ThrowRegExpException(re,
426 pattern, 431 pattern,
427 compile_data.error, 432 compile_data.error,
428 "malformed_regexp")); 433 "malformed_regexp"));
429 return false; 434 return false;
430 } 435 }
431 RegExpEngine::CompilationResult result = RegExpEngine::Compile( 436 RegExpEngine::CompilationResult result = RegExpEngine::Compile(
432 &compile_data, flags.is_ignore_case(), flags.is_global(), 437 &compile_data, flags.is_ignore_case(), flags.is_global(),
433 flags.is_multiline(), pattern, sample_subject, is_one_byte, &zone); 438 flags.is_multiline(), flags.is_sticky(), pattern, sample_subject,
439 is_one_byte, &zone);
434 if (result.error_message != NULL) { 440 if (result.error_message != NULL) {
435 // Unable to compile regexp. 441 // Unable to compile regexp.
436 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( 442 Handle<String> error_message = isolate->factory()->NewStringFromUtf8(
437 CStrVector(result.error_message)).ToHandleChecked(); 443 CStrVector(result.error_message)).ToHandleChecked();
438 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); 444 CreateRegExpErrorObjectAndThrow(re, error_message, isolate);
439 return false; 445 return false;
440 } 446 }
441 447
442 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); 448 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data()));
443 data->set(JSRegExp::code_index(is_one_byte), result.code); 449 data->set(JSRegExp::code_index(is_one_byte), result.code);
(...skipping 5576 matching lines...) Expand 10 before | Expand all | Expand 10 after
6020 6026
6021 6027
6022 void DispatchTableConstructor::VisitAction(ActionNode* that) { 6028 void DispatchTableConstructor::VisitAction(ActionNode* that) {
6023 RegExpNode* target = that->on_success(); 6029 RegExpNode* target = that->on_success();
6024 target->Accept(this); 6030 target->Accept(this);
6025 } 6031 }
6026 6032
6027 6033
6028 RegExpEngine::CompilationResult RegExpEngine::Compile( 6034 RegExpEngine::CompilationResult RegExpEngine::Compile(
6029 RegExpCompileData* data, bool ignore_case, bool is_global, 6035 RegExpCompileData* data, bool ignore_case, bool is_global,
6030 bool is_multiline, Handle<String> pattern, Handle<String> sample_subject, 6036 bool is_multiline, bool is_sticky, Handle<String> pattern,
6031 bool is_one_byte, Zone* zone) { 6037 Handle<String> sample_subject, bool is_one_byte, Zone* zone) {
6032 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { 6038 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
6033 return IrregexpRegExpTooBig(zone->isolate()); 6039 return IrregexpRegExpTooBig(zone->isolate());
6034 } 6040 }
6035 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); 6041 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone);
6036 6042
6037 // Sample some characters from the middle of the string. 6043 // Sample some characters from the middle of the string.
6038 static const int kSampleSize = 128; 6044 static const int kSampleSize = 128;
6039 6045
6040 sample_subject = String::Flatten(sample_subject); 6046 sample_subject = String::Flatten(sample_subject);
6041 int chars_sampled = 0; 6047 int chars_sampled = 0;
6042 int half_way = (sample_subject->length() - kSampleSize) / 2; 6048 int half_way = (sample_subject->length() - kSampleSize) / 2;
6043 for (int i = Max(0, half_way); 6049 for (int i = Max(0, half_way);
6044 i < sample_subject->length() && chars_sampled < kSampleSize; 6050 i < sample_subject->length() && chars_sampled < kSampleSize;
6045 i++, chars_sampled++) { 6051 i++, chars_sampled++) {
6046 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); 6052 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i));
6047 } 6053 }
6048 6054
6049 // Wrap the body of the regexp in capture #0. 6055 // Wrap the body of the regexp in capture #0.
6050 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, 6056 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
6051 0, 6057 0,
6052 &compiler, 6058 &compiler,
6053 compiler.accept()); 6059 compiler.accept());
6054 RegExpNode* node = captured_body; 6060 RegExpNode* node = captured_body;
6055 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); 6061 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
6056 bool is_start_anchored = data->tree->IsAnchoredAtStart(); 6062 bool is_start_anchored = data->tree->IsAnchoredAtStart();
6057 int max_length = data->tree->max_match(); 6063 int max_length = data->tree->max_match();
6058 if (!is_start_anchored) { 6064 if (!is_start_anchored && !is_sticky) {
6059 // Add a .*? at the beginning, outside the body capture, unless 6065 // Add a .*? at the beginning, outside the body capture, unless
6060 // this expression is anchored at the beginning. 6066 // this expression is anchored at the beginning or sticky.
6061 RegExpNode* loop_node = 6067 RegExpNode* loop_node =
6062 RegExpQuantifier::ToNode(0, 6068 RegExpQuantifier::ToNode(0,
6063 RegExpTree::kInfinity, 6069 RegExpTree::kInfinity,
6064 false, 6070 false,
6065 new(zone) RegExpCharacterClass('*'), 6071 new(zone) RegExpCharacterClass('*'),
6066 &compiler, 6072 &compiler,
6067 captured_body, 6073 captured_body,
6068 data->contains_anchor); 6074 data->contains_anchor);
6069 6075
6070 if (data->contains_anchor) { 6076 if (data->contains_anchor) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
6153 } 6159 }
6154 6160
6155 return compiler.Assemble(&macro_assembler, 6161 return compiler.Assemble(&macro_assembler,
6156 node, 6162 node,
6157 data->capture_count, 6163 data->capture_count,
6158 pattern); 6164 pattern);
6159 } 6165 }
6160 6166
6161 6167
6162 }} // namespace v8::internal 6168 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698