OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 5574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6018 | 6024 |
6019 | 6025 |
6020 void DispatchTableConstructor::VisitAction(ActionNode* that) { | 6026 void DispatchTableConstructor::VisitAction(ActionNode* that) { |
6021 RegExpNode* target = that->on_success(); | 6027 RegExpNode* target = that->on_success(); |
6022 target->Accept(this); | 6028 target->Accept(this); |
6023 } | 6029 } |
6024 | 6030 |
6025 | 6031 |
6026 RegExpEngine::CompilationResult RegExpEngine::Compile( | 6032 RegExpEngine::CompilationResult RegExpEngine::Compile( |
6027 RegExpCompileData* data, bool ignore_case, bool is_global, | 6033 RegExpCompileData* data, bool ignore_case, bool is_global, |
6028 bool is_multiline, Handle<String> pattern, Handle<String> sample_subject, | 6034 bool is_multiline, bool is_sticky, Handle<String> pattern, |
6029 bool is_one_byte, Zone* zone) { | 6035 Handle<String> sample_subject, bool is_one_byte, Zone* zone) { |
6030 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { | 6036 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { |
6031 return IrregexpRegExpTooBig(zone->isolate()); | 6037 return IrregexpRegExpTooBig(zone->isolate()); |
6032 } | 6038 } |
6033 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); | 6039 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); |
6034 | 6040 |
6035 // Sample some characters from the middle of the string. | 6041 // Sample some characters from the middle of the string. |
6036 static const int kSampleSize = 128; | 6042 static const int kSampleSize = 128; |
6037 | 6043 |
6038 sample_subject = String::Flatten(sample_subject); | 6044 sample_subject = String::Flatten(sample_subject); |
6039 int chars_sampled = 0; | 6045 int chars_sampled = 0; |
6040 int half_way = (sample_subject->length() - kSampleSize) / 2; | 6046 int half_way = (sample_subject->length() - kSampleSize) / 2; |
6041 for (int i = Max(0, half_way); | 6047 for (int i = Max(0, half_way); |
6042 i < sample_subject->length() && chars_sampled < kSampleSize; | 6048 i < sample_subject->length() && chars_sampled < kSampleSize; |
6043 i++, chars_sampled++) { | 6049 i++, chars_sampled++) { |
6044 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); | 6050 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); |
6045 } | 6051 } |
6046 | 6052 |
6047 // Wrap the body of the regexp in capture #0. | 6053 // Wrap the body of the regexp in capture #0. |
6048 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, | 6054 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, |
6049 0, | 6055 0, |
6050 &compiler, | 6056 &compiler, |
6051 compiler.accept()); | 6057 compiler.accept()); |
6052 RegExpNode* node = captured_body; | 6058 RegExpNode* node = captured_body; |
6053 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); | 6059 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
6054 bool is_start_anchored = data->tree->IsAnchoredAtStart(); | 6060 bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
6055 int max_length = data->tree->max_match(); | 6061 int max_length = data->tree->max_match(); |
6056 if (!is_start_anchored) { | 6062 if (!is_start_anchored && !is_sticky) { |
6057 // Add a .*? at the beginning, outside the body capture, unless | 6063 // Add a .*? at the beginning, outside the body capture, unless |
6058 // this expression is anchored at the beginning. | 6064 // this expression is anchored at the beginning. |
Yang
2014/09/15 09:23:16
... or sticky.
Erik Corry
2014/09/16 17:49:40
Done.
| |
6059 RegExpNode* loop_node = | 6065 RegExpNode* loop_node = |
6060 RegExpQuantifier::ToNode(0, | 6066 RegExpQuantifier::ToNode(0, |
6061 RegExpTree::kInfinity, | 6067 RegExpTree::kInfinity, |
6062 false, | 6068 false, |
6063 new(zone) RegExpCharacterClass('*'), | 6069 new(zone) RegExpCharacterClass('*'), |
6064 &compiler, | 6070 &compiler, |
6065 captured_body, | 6071 captured_body, |
6066 data->contains_anchor); | 6072 data->contains_anchor); |
6067 | 6073 |
6068 if (data->contains_anchor) { | 6074 if (data->contains_anchor) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6151 } | 6157 } |
6152 | 6158 |
6153 return compiler.Assemble(¯o_assembler, | 6159 return compiler.Assemble(¯o_assembler, |
6154 node, | 6160 node, |
6155 data->capture_count, | 6161 data->capture_count, |
6156 pattern); | 6162 pattern); |
6157 } | 6163 } |
6158 | 6164 |
6159 | 6165 |
6160 }} // namespace v8::internal | 6166 }} // namespace v8::internal |
OLD | NEW |