| 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 |