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; | |
76 } | 73 } |
77 } | 74 } |
78 return JSRegExp::Flags(flags); | 75 return JSRegExp::Flags(flags); |
79 } | 76 } |
80 | 77 |
81 | 78 |
82 MUST_USE_RESULT | 79 MUST_USE_RESULT |
83 static inline MaybeHandle<Object> ThrowRegExpException( | 80 static inline MaybeHandle<Object> ThrowRegExpException( |
84 Handle<JSRegExp> re, | 81 Handle<JSRegExp> re, |
85 Handle<String> pattern, | 82 Handle<String> pattern, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 return ThrowRegExpException(re, | 178 return ThrowRegExpException(re, |
182 pattern, | 179 pattern, |
183 parse_result.error, | 180 parse_result.error, |
184 "malformed_regexp"); | 181 "malformed_regexp"); |
185 } | 182 } |
186 | 183 |
187 bool has_been_compiled = false; | 184 bool has_been_compiled = false; |
188 | 185 |
189 if (parse_result.simple && | 186 if (parse_result.simple && |
190 !flags.is_ignore_case() && | 187 !flags.is_ignore_case() && |
191 !flags.is_sticky() && | |
192 !HasFewDifferentCharacters(pattern)) { | 188 !HasFewDifferentCharacters(pattern)) { |
193 // Parse-tree is a single atom that is equal to the pattern. | 189 // Parse-tree is a single atom that is equal to the pattern. |
194 AtomCompile(re, pattern, flags, pattern); | 190 AtomCompile(re, pattern, flags, pattern); |
195 has_been_compiled = true; | 191 has_been_compiled = true; |
196 } else if (parse_result.tree->IsAtom() && | 192 } else if (parse_result.tree->IsAtom() && |
197 !flags.is_ignore_case() && | 193 !flags.is_ignore_case() && |
198 !flags.is_sticky() && | |
199 parse_result.capture_count == 0) { | 194 parse_result.capture_count == 0) { |
200 RegExpAtom* atom = parse_result.tree->AsAtom(); | 195 RegExpAtom* atom = parse_result.tree->AsAtom(); |
201 Vector<const uc16> atom_pattern = atom->data(); | 196 Vector<const uc16> atom_pattern = atom->data(); |
202 Handle<String> atom_string; | 197 Handle<String> atom_string; |
203 ASSIGN_RETURN_ON_EXCEPTION( | 198 ASSIGN_RETURN_ON_EXCEPTION( |
204 isolate, atom_string, | 199 isolate, atom_string, |
205 isolate->factory()->NewStringFromTwoByte(atom_pattern), | 200 isolate->factory()->NewStringFromTwoByte(atom_pattern), |
206 Object); | 201 Object); |
207 if (!HasFewDifferentCharacters(atom_string)) { | 202 if (!HasFewDifferentCharacters(atom_string)) { |
208 AtomCompile(re, pattern, flags, atom_string); | 203 AtomCompile(re, pattern, flags, atom_string); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 // Throw an exception if we fail to parse the pattern. | 423 // Throw an exception if we fail to parse the pattern. |
429 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. | 424 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. |
430 USE(ThrowRegExpException(re, | 425 USE(ThrowRegExpException(re, |
431 pattern, | 426 pattern, |
432 compile_data.error, | 427 compile_data.error, |
433 "malformed_regexp")); | 428 "malformed_regexp")); |
434 return false; | 429 return false; |
435 } | 430 } |
436 RegExpEngine::CompilationResult result = RegExpEngine::Compile( | 431 RegExpEngine::CompilationResult result = RegExpEngine::Compile( |
437 &compile_data, flags.is_ignore_case(), flags.is_global(), | 432 &compile_data, flags.is_ignore_case(), flags.is_global(), |
438 flags.is_multiline(), flags.is_sticky(), pattern, sample_subject, | 433 flags.is_multiline(), pattern, sample_subject, is_one_byte, &zone); |
439 is_one_byte, &zone); | |
440 if (result.error_message != NULL) { | 434 if (result.error_message != NULL) { |
441 // Unable to compile regexp. | 435 // Unable to compile regexp. |
442 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( | 436 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( |
443 CStrVector(result.error_message)).ToHandleChecked(); | 437 CStrVector(result.error_message)).ToHandleChecked(); |
444 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); | 438 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); |
445 return false; | 439 return false; |
446 } | 440 } |
447 | 441 |
448 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); | 442 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); |
449 data->set(JSRegExp::code_index(is_one_byte), result.code); | 443 data->set(JSRegExp::code_index(is_one_byte), result.code); |
(...skipping 5576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6026 | 6020 |
6027 | 6021 |
6028 void DispatchTableConstructor::VisitAction(ActionNode* that) { | 6022 void DispatchTableConstructor::VisitAction(ActionNode* that) { |
6029 RegExpNode* target = that->on_success(); | 6023 RegExpNode* target = that->on_success(); |
6030 target->Accept(this); | 6024 target->Accept(this); |
6031 } | 6025 } |
6032 | 6026 |
6033 | 6027 |
6034 RegExpEngine::CompilationResult RegExpEngine::Compile( | 6028 RegExpEngine::CompilationResult RegExpEngine::Compile( |
6035 RegExpCompileData* data, bool ignore_case, bool is_global, | 6029 RegExpCompileData* data, bool ignore_case, bool is_global, |
6036 bool is_multiline, bool is_sticky, Handle<String> pattern, | 6030 bool is_multiline, Handle<String> pattern, Handle<String> sample_subject, |
6037 Handle<String> sample_subject, bool is_one_byte, Zone* zone) { | 6031 bool is_one_byte, Zone* zone) { |
6038 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { | 6032 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { |
6039 return IrregexpRegExpTooBig(zone->isolate()); | 6033 return IrregexpRegExpTooBig(zone->isolate()); |
6040 } | 6034 } |
6041 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); | 6035 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); |
6042 | 6036 |
6043 // Sample some characters from the middle of the string. | 6037 // Sample some characters from the middle of the string. |
6044 static const int kSampleSize = 128; | 6038 static const int kSampleSize = 128; |
6045 | 6039 |
6046 sample_subject = String::Flatten(sample_subject); | 6040 sample_subject = String::Flatten(sample_subject); |
6047 int chars_sampled = 0; | 6041 int chars_sampled = 0; |
6048 int half_way = (sample_subject->length() - kSampleSize) / 2; | 6042 int half_way = (sample_subject->length() - kSampleSize) / 2; |
6049 for (int i = Max(0, half_way); | 6043 for (int i = Max(0, half_way); |
6050 i < sample_subject->length() && chars_sampled < kSampleSize; | 6044 i < sample_subject->length() && chars_sampled < kSampleSize; |
6051 i++, chars_sampled++) { | 6045 i++, chars_sampled++) { |
6052 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); | 6046 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); |
6053 } | 6047 } |
6054 | 6048 |
6055 // Wrap the body of the regexp in capture #0. | 6049 // Wrap the body of the regexp in capture #0. |
6056 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, | 6050 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, |
6057 0, | 6051 0, |
6058 &compiler, | 6052 &compiler, |
6059 compiler.accept()); | 6053 compiler.accept()); |
6060 RegExpNode* node = captured_body; | 6054 RegExpNode* node = captured_body; |
6061 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); | 6055 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
6062 bool is_start_anchored = data->tree->IsAnchoredAtStart(); | 6056 bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
6063 int max_length = data->tree->max_match(); | 6057 int max_length = data->tree->max_match(); |
6064 if (!is_start_anchored && !is_sticky) { | 6058 if (!is_start_anchored) { |
6065 // Add a .*? at the beginning, outside the body capture, unless | 6059 // Add a .*? at the beginning, outside the body capture, unless |
6066 // this expression is anchored at the beginning or sticky. | 6060 // this expression is anchored at the beginning. |
6067 RegExpNode* loop_node = | 6061 RegExpNode* loop_node = |
6068 RegExpQuantifier::ToNode(0, | 6062 RegExpQuantifier::ToNode(0, |
6069 RegExpTree::kInfinity, | 6063 RegExpTree::kInfinity, |
6070 false, | 6064 false, |
6071 new(zone) RegExpCharacterClass('*'), | 6065 new(zone) RegExpCharacterClass('*'), |
6072 &compiler, | 6066 &compiler, |
6073 captured_body, | 6067 captured_body, |
6074 data->contains_anchor); | 6068 data->contains_anchor); |
6075 | 6069 |
6076 if (data->contains_anchor) { | 6070 if (data->contains_anchor) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6159 } | 6153 } |
6160 | 6154 |
6161 return compiler.Assemble(¯o_assembler, | 6155 return compiler.Assemble(¯o_assembler, |
6162 node, | 6156 node, |
6163 data->capture_count, | 6157 data->capture_count, |
6164 pattern); | 6158 pattern); |
6165 } | 6159 } |
6166 | 6160 |
6167 | 6161 |
6168 }} // namespace v8::internal | 6162 }} // namespace v8::internal |
OLD | NEW |