Chromium Code Reviews| 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 |