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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 // Generic RegExp methods. Dispatches to implementation specific methods. | 134 // Generic RegExp methods. Dispatches to implementation specific methods. |
135 | 135 |
136 | 136 |
137 MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re, | 137 MaybeHandle<Object> RegExpImpl::Compile(Handle<JSRegExp> re, |
138 Handle<String> pattern, | 138 Handle<String> pattern, |
139 JSRegExp::Flags flags) { | 139 JSRegExp::Flags flags) { |
140 Isolate* isolate = re->GetIsolate(); | 140 Isolate* isolate = re->GetIsolate(); |
141 Zone zone(isolate); | 141 Zone zone; |
142 CompilationCache* compilation_cache = isolate->compilation_cache(); | 142 CompilationCache* compilation_cache = isolate->compilation_cache(); |
143 MaybeHandle<FixedArray> maybe_cached = | 143 MaybeHandle<FixedArray> maybe_cached = |
144 compilation_cache->LookupRegExp(pattern, flags); | 144 compilation_cache->LookupRegExp(pattern, flags); |
145 Handle<FixedArray> cached; | 145 Handle<FixedArray> cached; |
146 bool in_cache = maybe_cached.ToHandle(&cached); | 146 bool in_cache = maybe_cached.ToHandle(&cached); |
147 LOG(isolate, RegExpCompileEvent(re, in_cache)); | 147 LOG(isolate, RegExpCompileEvent(re, in_cache)); |
148 | 148 |
149 Handle<Object> result; | 149 Handle<Object> result; |
150 if (in_cache) { | 150 if (in_cache) { |
151 re->set_data(*cached); | 151 re->set_data(*cached); |
152 return re; | 152 return re; |
153 } | 153 } |
154 pattern = String::Flatten(pattern); | 154 pattern = String::Flatten(pattern); |
155 PostponeInterruptsScope postpone(isolate); | 155 PostponeInterruptsScope postpone(isolate); |
156 RegExpCompileData parse_result; | 156 RegExpCompileData parse_result; |
157 FlatStringReader reader(isolate, pattern); | 157 FlatStringReader reader(isolate, pattern); |
158 if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(), | 158 if (!RegExpParser::ParseRegExp(re->GetIsolate(), &zone, &reader, |
159 flags.is_unicode(), &parse_result, &zone)) { | 159 flags.is_multiline(), flags.is_unicode(), |
| 160 &parse_result)) { |
160 // Throw an exception if we fail to parse the pattern. | 161 // Throw an exception if we fail to parse the pattern. |
161 return ThrowRegExpException(re, | 162 return ThrowRegExpException(re, |
162 pattern, | 163 pattern, |
163 parse_result.error, | 164 parse_result.error, |
164 "malformed_regexp"); | 165 "malformed_regexp"); |
165 } | 166 } |
166 | 167 |
167 bool has_been_compiled = false; | 168 bool has_been_compiled = false; |
168 | 169 |
169 if (parse_result.simple && | 170 if (parse_result.simple && |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 factory->NewSyntaxError("malformed_regexp", array); | 365 factory->NewSyntaxError("malformed_regexp", array); |
365 if (maybe_error.ToHandle(&error)) isolate->Throw(*error); | 366 if (maybe_error.ToHandle(&error)) isolate->Throw(*error); |
366 } | 367 } |
367 | 368 |
368 | 369 |
369 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, | 370 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re, |
370 Handle<String> sample_subject, | 371 Handle<String> sample_subject, |
371 bool is_one_byte) { | 372 bool is_one_byte) { |
372 // Compile the RegExp. | 373 // Compile the RegExp. |
373 Isolate* isolate = re->GetIsolate(); | 374 Isolate* isolate = re->GetIsolate(); |
374 Zone zone(isolate); | 375 Zone zone; |
375 PostponeInterruptsScope postpone(isolate); | 376 PostponeInterruptsScope postpone(isolate); |
376 // If we had a compilation error the last time this is saved at the | 377 // If we had a compilation error the last time this is saved at the |
377 // saved code index. | 378 // saved code index. |
378 Object* entry = re->DataAt(JSRegExp::code_index(is_one_byte)); | 379 Object* entry = re->DataAt(JSRegExp::code_index(is_one_byte)); |
379 // When arriving here entry can only be a smi, either representing an | 380 // When arriving here entry can only be a smi, either representing an |
380 // uncompiled regexp, a previous compilation error, or code that has | 381 // uncompiled regexp, a previous compilation error, or code that has |
381 // been flushed. | 382 // been flushed. |
382 DCHECK(entry->IsSmi()); | 383 DCHECK(entry->IsSmi()); |
383 int entry_value = Smi::cast(entry)->value(); | 384 int entry_value = Smi::cast(entry)->value(); |
384 DCHECK(entry_value == JSRegExp::kUninitializedValue || | 385 DCHECK(entry_value == JSRegExp::kUninitializedValue || |
(...skipping 10 matching lines...) Expand all Loading... |
395 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); | 396 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); |
396 return false; | 397 return false; |
397 } | 398 } |
398 | 399 |
399 JSRegExp::Flags flags = re->GetFlags(); | 400 JSRegExp::Flags flags = re->GetFlags(); |
400 | 401 |
401 Handle<String> pattern(re->Pattern()); | 402 Handle<String> pattern(re->Pattern()); |
402 pattern = String::Flatten(pattern); | 403 pattern = String::Flatten(pattern); |
403 RegExpCompileData compile_data; | 404 RegExpCompileData compile_data; |
404 FlatStringReader reader(isolate, pattern); | 405 FlatStringReader reader(isolate, pattern); |
405 if (!RegExpParser::ParseRegExp(&reader, flags.is_multiline(), | 406 if (!RegExpParser::ParseRegExp(isolate, &zone, &reader, flags.is_multiline(), |
406 flags.is_unicode(), &compile_data, &zone)) { | 407 flags.is_unicode(), &compile_data)) { |
407 // Throw an exception if we fail to parse the pattern. | 408 // Throw an exception if we fail to parse the pattern. |
408 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. | 409 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. |
409 USE(ThrowRegExpException(re, | 410 USE(ThrowRegExpException(re, |
410 pattern, | 411 pattern, |
411 compile_data.error, | 412 compile_data.error, |
412 "malformed_regexp")); | 413 "malformed_regexp")); |
413 return false; | 414 return false; |
414 } | 415 } |
415 RegExpEngine::CompilationResult result = RegExpEngine::Compile( | 416 RegExpEngine::CompilationResult result = RegExpEngine::Compile( |
416 &compile_data, flags.is_ignore_case(), flags.is_global(), | 417 isolate, &zone, &compile_data, flags.is_ignore_case(), flags.is_global(), |
417 flags.is_multiline(), flags.is_sticky(), pattern, sample_subject, | 418 flags.is_multiline(), flags.is_sticky(), pattern, sample_subject, |
418 is_one_byte, &zone); | 419 is_one_byte); |
419 if (result.error_message != NULL) { | 420 if (result.error_message != NULL) { |
420 // Unable to compile regexp. | 421 // Unable to compile regexp. |
421 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( | 422 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( |
422 CStrVector(result.error_message)).ToHandleChecked(); | 423 CStrVector(result.error_message)).ToHandleChecked(); |
423 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); | 424 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); |
424 return false; | 425 return false; |
425 } | 426 } |
426 | 427 |
427 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); | 428 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); |
428 data->set(JSRegExp::code_index(is_one_byte), result.code); | 429 data->set(JSRegExp::code_index(is_one_byte), result.code); |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 | 965 |
965 | 966 |
966 private: | 967 private: |
967 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; | 968 CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize]; |
968 int total_samples_; | 969 int total_samples_; |
969 }; | 970 }; |
970 | 971 |
971 | 972 |
972 class RegExpCompiler { | 973 class RegExpCompiler { |
973 public: | 974 public: |
974 RegExpCompiler(int capture_count, bool ignore_case, bool is_one_byte, | 975 RegExpCompiler(Isolate* isolate, Zone* zone, int capture_count, |
975 Zone* zone); | 976 bool ignore_case, bool is_one_byte); |
976 | 977 |
977 int AllocateRegister() { | 978 int AllocateRegister() { |
978 if (next_register_ >= RegExpMacroAssembler::kMaxRegister) { | 979 if (next_register_ >= RegExpMacroAssembler::kMaxRegister) { |
979 reg_exp_too_big_ = true; | 980 reg_exp_too_big_ = true; |
980 return next_register_; | 981 return next_register_; |
981 } | 982 } |
982 return next_register_++; | 983 return next_register_++; |
983 } | 984 } |
984 | 985 |
985 RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler, | 986 RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler, |
(...skipping 21 matching lines...) Expand all Loading... |
1007 inline bool one_byte() { return one_byte_; } | 1008 inline bool one_byte() { return one_byte_; } |
1008 inline bool optimize() { return optimize_; } | 1009 inline bool optimize() { return optimize_; } |
1009 inline void set_optimize(bool value) { optimize_ = value; } | 1010 inline void set_optimize(bool value) { optimize_ = value; } |
1010 FrequencyCollator* frequency_collator() { return &frequency_collator_; } | 1011 FrequencyCollator* frequency_collator() { return &frequency_collator_; } |
1011 | 1012 |
1012 int current_expansion_factor() { return current_expansion_factor_; } | 1013 int current_expansion_factor() { return current_expansion_factor_; } |
1013 void set_current_expansion_factor(int value) { | 1014 void set_current_expansion_factor(int value) { |
1014 current_expansion_factor_ = value; | 1015 current_expansion_factor_ = value; |
1015 } | 1016 } |
1016 | 1017 |
| 1018 Isolate* isolate() const { return isolate_; } |
1017 Zone* zone() const { return zone_; } | 1019 Zone* zone() const { return zone_; } |
1018 | 1020 |
1019 static const int kNoRegister = -1; | 1021 static const int kNoRegister = -1; |
1020 | 1022 |
1021 private: | 1023 private: |
1022 EndNode* accept_; | 1024 EndNode* accept_; |
1023 int next_register_; | 1025 int next_register_; |
1024 List<RegExpNode*>* work_list_; | 1026 List<RegExpNode*>* work_list_; |
1025 int recursion_depth_; | 1027 int recursion_depth_; |
1026 RegExpMacroAssembler* macro_assembler_; | 1028 RegExpMacroAssembler* macro_assembler_; |
1027 bool ignore_case_; | 1029 bool ignore_case_; |
1028 bool one_byte_; | 1030 bool one_byte_; |
1029 bool reg_exp_too_big_; | 1031 bool reg_exp_too_big_; |
1030 bool optimize_; | 1032 bool optimize_; |
1031 int current_expansion_factor_; | 1033 int current_expansion_factor_; |
1032 FrequencyCollator frequency_collator_; | 1034 FrequencyCollator frequency_collator_; |
| 1035 Isolate* isolate_; |
1033 Zone* zone_; | 1036 Zone* zone_; |
1034 }; | 1037 }; |
1035 | 1038 |
1036 | 1039 |
1037 class RecursionCheck { | 1040 class RecursionCheck { |
1038 public: | 1041 public: |
1039 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { | 1042 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { |
1040 compiler->IncrementRecursionDepth(); | 1043 compiler->IncrementRecursionDepth(); |
1041 } | 1044 } |
1042 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } | 1045 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } |
1043 private: | 1046 private: |
1044 RegExpCompiler* compiler_; | 1047 RegExpCompiler* compiler_; |
1045 }; | 1048 }; |
1046 | 1049 |
1047 | 1050 |
1048 static RegExpEngine::CompilationResult IrregexpRegExpTooBig(Isolate* isolate) { | 1051 static RegExpEngine::CompilationResult IrregexpRegExpTooBig(Isolate* isolate) { |
1049 return RegExpEngine::CompilationResult(isolate, "RegExp too big"); | 1052 return RegExpEngine::CompilationResult(isolate, "RegExp too big"); |
1050 } | 1053 } |
1051 | 1054 |
1052 | 1055 |
1053 // Attempts to compile the regexp using an Irregexp code generator. Returns | 1056 // Attempts to compile the regexp using an Irregexp code generator. Returns |
1054 // a fixed array or a null handle depending on whether it succeeded. | 1057 // a fixed array or a null handle depending on whether it succeeded. |
1055 RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, | 1058 RegExpCompiler::RegExpCompiler(Isolate* isolate, Zone* zone, int capture_count, |
1056 bool one_byte, Zone* zone) | 1059 bool ignore_case, bool one_byte) |
1057 : next_register_(2 * (capture_count + 1)), | 1060 : next_register_(2 * (capture_count + 1)), |
1058 work_list_(NULL), | 1061 work_list_(NULL), |
1059 recursion_depth_(0), | 1062 recursion_depth_(0), |
1060 ignore_case_(ignore_case), | 1063 ignore_case_(ignore_case), |
1061 one_byte_(one_byte), | 1064 one_byte_(one_byte), |
1062 reg_exp_too_big_(false), | 1065 reg_exp_too_big_(false), |
1063 optimize_(FLAG_regexp_optimization), | 1066 optimize_(FLAG_regexp_optimization), |
1064 current_expansion_factor_(1), | 1067 current_expansion_factor_(1), |
1065 frequency_collator_(), | 1068 frequency_collator_(), |
| 1069 isolate_(isolate), |
1066 zone_(zone) { | 1070 zone_(zone) { |
1067 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone); | 1071 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone); |
1068 DCHECK(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); | 1072 DCHECK(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); |
1069 } | 1073 } |
1070 | 1074 |
1071 | 1075 |
1072 RegExpEngine::CompilationResult RegExpCompiler::Assemble( | 1076 RegExpEngine::CompilationResult RegExpCompiler::Assemble( |
1073 RegExpMacroAssembler* macro_assembler, | 1077 RegExpMacroAssembler* macro_assembler, |
1074 RegExpNode* start, | 1078 RegExpNode* start, |
1075 int capture_count, | 1079 int capture_count, |
1076 Handle<String> pattern) { | 1080 Handle<String> pattern) { |
1077 Heap* heap = pattern->GetHeap(); | 1081 Heap* heap = pattern->GetHeap(); |
1078 | 1082 |
1079 #ifdef DEBUG | 1083 #ifdef DEBUG |
1080 if (FLAG_trace_regexp_assembler) | 1084 if (FLAG_trace_regexp_assembler) |
1081 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler); | 1085 macro_assembler_ = |
| 1086 new RegExpMacroAssemblerTracer(isolate(), macro_assembler); |
1082 else | 1087 else |
1083 #endif | 1088 #endif |
1084 macro_assembler_ = macro_assembler; | 1089 macro_assembler_ = macro_assembler; |
1085 | 1090 |
1086 List <RegExpNode*> work_list(0); | 1091 List <RegExpNode*> work_list(0); |
1087 work_list_ = &work_list; | 1092 work_list_ = &work_list; |
1088 Label fail; | 1093 Label fail; |
1089 macro_assembler_->PushBacktrack(&fail); | 1094 macro_assembler_->PushBacktrack(&fail); |
1090 Trace new_trace; | 1095 Trace new_trace; |
1091 start->Emit(this, &new_trace); | 1096 start->Emit(this, &new_trace); |
1092 macro_assembler_->Bind(&fail); | 1097 macro_assembler_->Bind(&fail); |
1093 macro_assembler_->Fail(); | 1098 macro_assembler_->Fail(); |
1094 while (!work_list.is_empty()) { | 1099 while (!work_list.is_empty()) { |
1095 work_list.RemoveLast()->Emit(this, &new_trace); | 1100 work_list.RemoveLast()->Emit(this, &new_trace); |
1096 } | 1101 } |
1097 if (reg_exp_too_big_) return IrregexpRegExpTooBig(zone_->isolate()); | 1102 if (reg_exp_too_big_) return IrregexpRegExpTooBig(isolate_); |
1098 | 1103 |
1099 Handle<HeapObject> code = macro_assembler_->GetCode(pattern); | 1104 Handle<HeapObject> code = macro_assembler_->GetCode(pattern); |
1100 heap->IncreaseTotalRegexpCodeGenerated(code->Size()); | 1105 heap->IncreaseTotalRegexpCodeGenerated(code->Size()); |
1101 work_list_ = NULL; | 1106 work_list_ = NULL; |
1102 #ifdef ENABLE_DISASSEMBLER | 1107 #ifdef ENABLE_DISASSEMBLER |
1103 if (FLAG_print_code) { | 1108 if (FLAG_print_code) { |
1104 CodeTracer::Scope trace_scope(heap->isolate()->GetCodeTracer()); | 1109 CodeTracer::Scope trace_scope(heap->isolate()->GetCodeTracer()); |
1105 OFStream os(trace_scope.file()); | 1110 OFStream os(trace_scope.file()); |
1106 Handle<Code>::cast(code)->Disassemble(pattern->ToCString().get(), os); | 1111 Handle<Code>::cast(code)->Disassemble(pattern->ToCString().get(), os); |
1107 } | 1112 } |
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 bit ^= 1; | 1821 bit ^= 1; |
1817 for (int i = start_index; i < end_index; i++) { | 1822 for (int i = start_index; i < end_index; i++) { |
1818 for (j = (ranges->at(i) & kMask); j < (ranges->at(i + 1) & kMask); j++) { | 1823 for (j = (ranges->at(i) & kMask); j < (ranges->at(i + 1) & kMask); j++) { |
1819 templ[j] = bit; | 1824 templ[j] = bit; |
1820 } | 1825 } |
1821 bit ^= 1; | 1826 bit ^= 1; |
1822 } | 1827 } |
1823 for (int i = j; i < kSize; i++) { | 1828 for (int i = j; i < kSize; i++) { |
1824 templ[i] = bit; | 1829 templ[i] = bit; |
1825 } | 1830 } |
1826 Factory* factory = masm->zone()->isolate()->factory(); | 1831 Factory* factory = masm->isolate()->factory(); |
1827 // TODO(erikcorry): Cache these. | 1832 // TODO(erikcorry): Cache these. |
1828 Handle<ByteArray> ba = factory->NewByteArray(kSize, TENURED); | 1833 Handle<ByteArray> ba = factory->NewByteArray(kSize, TENURED); |
1829 for (int i = 0; i < kSize; i++) { | 1834 for (int i = 0; i < kSize; i++) { |
1830 ba->set(i, templ[i]); | 1835 ba->set(i, templ[i]); |
1831 } | 1836 } |
1832 masm->CheckBitInTable(ba, on_bit_set); | 1837 masm->CheckBitInTable(ba, on_bit_set); |
1833 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear); | 1838 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear); |
1834 } | 1839 } |
1835 | 1840 |
1836 | 1841 |
(...skipping 658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2495 // | 2500 // |
2496 // We iterate along the text object, building up for each character a | 2501 // We iterate along the text object, building up for each character a |
2497 // mask and value that can be used to test for a quick failure to match. | 2502 // mask and value that can be used to test for a quick failure to match. |
2498 // The masks and values for the positions will be combined into a single | 2503 // The masks and values for the positions will be combined into a single |
2499 // machine word for the current character width in order to be used in | 2504 // machine word for the current character width in order to be used in |
2500 // generating a quick check. | 2505 // generating a quick check. |
2501 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, | 2506 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, |
2502 RegExpCompiler* compiler, | 2507 RegExpCompiler* compiler, |
2503 int characters_filled_in, | 2508 int characters_filled_in, |
2504 bool not_at_start) { | 2509 bool not_at_start) { |
2505 Isolate* isolate = compiler->macro_assembler()->zone()->isolate(); | 2510 Isolate* isolate = compiler->macro_assembler()->isolate(); |
2506 DCHECK(characters_filled_in < details->characters()); | 2511 DCHECK(characters_filled_in < details->characters()); |
2507 int characters = details->characters(); | 2512 int characters = details->characters(); |
2508 int char_mask; | 2513 int char_mask; |
2509 if (compiler->one_byte()) { | 2514 if (compiler->one_byte()) { |
2510 char_mask = String::kMaxOneByteCharCode; | 2515 char_mask = String::kMaxOneByteCharCode; |
2511 } else { | 2516 } else { |
2512 char_mask = String::kMaxUtf16CodeUnit; | 2517 char_mask = String::kMaxUtf16CodeUnit; |
2513 } | 2518 } |
2514 for (int k = 0; k < elms_->length(); k++) { | 2519 for (int k = 0; k < elms_->length(); k++) { |
2515 TextElement elm = elms_->at(k); | 2520 TextElement elm = elms_->at(k); |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3196 // up to the limit the quick check already checked. In addition the quick | 3201 // up to the limit the quick check already checked. In addition the quick |
3197 // check can have involved a mask and compare operation which may simplify | 3202 // check can have involved a mask and compare operation which may simplify |
3198 // or obviate the need for further checks at some character positions. | 3203 // or obviate the need for further checks at some character positions. |
3199 void TextNode::TextEmitPass(RegExpCompiler* compiler, | 3204 void TextNode::TextEmitPass(RegExpCompiler* compiler, |
3200 TextEmitPassType pass, | 3205 TextEmitPassType pass, |
3201 bool preloaded, | 3206 bool preloaded, |
3202 Trace* trace, | 3207 Trace* trace, |
3203 bool first_element_checked, | 3208 bool first_element_checked, |
3204 int* checked_up_to) { | 3209 int* checked_up_to) { |
3205 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 3210 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
3206 Isolate* isolate = assembler->zone()->isolate(); | 3211 Isolate* isolate = assembler->isolate(); |
3207 bool one_byte = compiler->one_byte(); | 3212 bool one_byte = compiler->one_byte(); |
3208 Label* backtrack = trace->backtrack(); | 3213 Label* backtrack = trace->backtrack(); |
3209 QuickCheckDetails* quick_check = trace->quick_check_performed(); | 3214 QuickCheckDetails* quick_check = trace->quick_check_performed(); |
3210 int element_count = elms_->length(); | 3215 int element_count = elms_->length(); |
3211 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { | 3216 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { |
3212 TextElement elm = elms_->at(i); | 3217 TextElement elm = elms_->at(i); |
3213 int cp_offset = trace->cp_offset() + elm.cp_offset(); | 3218 int cp_offset = trace->cp_offset() + elm.cp_offset(); |
3214 if (elm.text_type() == TextElement::ATOM) { | 3219 if (elm.text_type() == TextElement::ATOM) { |
3215 Vector<const uc16> quarks = elm.atom()->data(); | 3220 Vector<const uc16> quarks = elm.atom()->data(); |
3216 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { | 3221 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3357 quick_check_performed_.Advance(by, compiler->one_byte()); | 3362 quick_check_performed_.Advance(by, compiler->one_byte()); |
3358 cp_offset_ += by; | 3363 cp_offset_ += by; |
3359 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { | 3364 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { |
3360 compiler->SetRegExpTooBig(); | 3365 compiler->SetRegExpTooBig(); |
3361 cp_offset_ = 0; | 3366 cp_offset_ = 0; |
3362 } | 3367 } |
3363 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); | 3368 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); |
3364 } | 3369 } |
3365 | 3370 |
3366 | 3371 |
3367 void TextNode::MakeCaseIndependent(bool is_one_byte) { | 3372 void TextNode::MakeCaseIndependent(Isolate* isolate, bool is_one_byte) { |
3368 int element_count = elms_->length(); | 3373 int element_count = elms_->length(); |
3369 for (int i = 0; i < element_count; i++) { | 3374 for (int i = 0; i < element_count; i++) { |
3370 TextElement elm = elms_->at(i); | 3375 TextElement elm = elms_->at(i); |
3371 if (elm.text_type() == TextElement::CHAR_CLASS) { | 3376 if (elm.text_type() == TextElement::CHAR_CLASS) { |
3372 RegExpCharacterClass* cc = elm.char_class(); | 3377 RegExpCharacterClass* cc = elm.char_class(); |
3373 // None of the standard character classes is different in the case | 3378 // None of the standard character classes is different in the case |
3374 // independent case and it slows us down if we don't know that. | 3379 // independent case and it slows us down if we don't know that. |
3375 if (cc->is_standard(zone())) continue; | 3380 if (cc->is_standard(zone())) continue; |
3376 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); | 3381 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
3377 int range_count = ranges->length(); | 3382 int range_count = ranges->length(); |
3378 for (int j = 0; j < range_count; j++) { | 3383 for (int j = 0; j < range_count; j++) { |
3379 ranges->at(j).AddCaseEquivalents(ranges, is_one_byte, zone()); | 3384 ranges->at(j).AddCaseEquivalents(isolate, zone(), ranges, is_one_byte); |
3380 } | 3385 } |
3381 } | 3386 } |
3382 } | 3387 } |
3383 } | 3388 } |
3384 | 3389 |
3385 | 3390 |
3386 int TextNode::GreedyLoopTextLength() { | 3391 int TextNode::GreedyLoopTextLength() { |
3387 TextElement elm = elms_->at(elms_->length() - 1); | 3392 TextElement elm = elms_->at(elms_->length() - 1); |
3388 return elm.cp_offset() + elm.length(); | 3393 return elm.cp_offset() + elm.length(); |
3389 } | 3394 } |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3768 &cont); | 3773 &cont); |
3769 } else { | 3774 } else { |
3770 masm->CheckCharacter(single_character, &cont); | 3775 masm->CheckCharacter(single_character, &cont); |
3771 } | 3776 } |
3772 masm->AdvanceCurrentPosition(lookahead_width); | 3777 masm->AdvanceCurrentPosition(lookahead_width); |
3773 masm->GoTo(&again); | 3778 masm->GoTo(&again); |
3774 masm->Bind(&cont); | 3779 masm->Bind(&cont); |
3775 return; | 3780 return; |
3776 } | 3781 } |
3777 | 3782 |
3778 Factory* factory = masm->zone()->isolate()->factory(); | 3783 Factory* factory = masm->isolate()->factory(); |
3779 Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED); | 3784 Handle<ByteArray> boolean_skip_table = factory->NewByteArray(kSize, TENURED); |
3780 int skip_distance = GetSkipTable( | 3785 int skip_distance = GetSkipTable( |
3781 min_lookahead, max_lookahead, boolean_skip_table); | 3786 min_lookahead, max_lookahead, boolean_skip_table); |
3782 DCHECK(skip_distance != 0); | 3787 DCHECK(skip_distance != 0); |
3783 | 3788 |
3784 Label cont, again; | 3789 Label cont, again; |
3785 masm->Bind(&again); | 3790 masm->Bind(&again); |
3786 masm->LoadCurrentCharacter(max_lookahead, &cont, true); | 3791 masm->LoadCurrentCharacter(max_lookahead, &cont, true); |
3787 masm->CheckBitInTable(boolean_skip_table, &cont); | 3792 masm->CheckBitInTable(boolean_skip_table, &cont); |
3788 masm->AdvanceCurrentPosition(skip_distance); | 3793 masm->AdvanceCurrentPosition(skip_distance); |
(...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5296 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); | 5301 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); |
5297 for (int i = 0; i < overlay.length(); i += 2) { | 5302 for (int i = 0; i < overlay.length(); i += 2) { |
5298 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), | 5303 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), |
5299 CharacterRangeSplitter::kInOverlay, zone); | 5304 CharacterRangeSplitter::kInOverlay, zone); |
5300 } | 5305 } |
5301 CharacterRangeSplitter callback(included, excluded, zone); | 5306 CharacterRangeSplitter callback(included, excluded, zone); |
5302 table.ForEach(&callback); | 5307 table.ForEach(&callback); |
5303 } | 5308 } |
5304 | 5309 |
5305 | 5310 |
5306 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, | 5311 void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone, |
5307 bool is_one_byte, Zone* zone) { | 5312 ZoneList<CharacterRange>* ranges, |
5308 Isolate* isolate = zone->isolate(); | 5313 bool is_one_byte) { |
5309 uc16 bottom = from(); | 5314 uc16 bottom = from(); |
5310 uc16 top = to(); | 5315 uc16 top = to(); |
5311 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) { | 5316 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) { |
5312 if (bottom > String::kMaxOneByteCharCode) return; | 5317 if (bottom > String::kMaxOneByteCharCode) return; |
5313 if (top > String::kMaxOneByteCharCode) top = String::kMaxOneByteCharCode; | 5318 if (top > String::kMaxOneByteCharCode) top = String::kMaxOneByteCharCode; |
5314 } | 5319 } |
5315 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 5320 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
5316 if (top == bottom) { | 5321 if (top == bottom) { |
5317 // If this is a singleton we just expand the one character. | 5322 // If this is a singleton we just expand the one character. |
5318 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); | 5323 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5686 else | 5691 else |
5687 return empty(); | 5692 return empty(); |
5688 } | 5693 } |
5689 | 5694 |
5690 | 5695 |
5691 // ------------------------------------------------------------------- | 5696 // ------------------------------------------------------------------- |
5692 // Analysis | 5697 // Analysis |
5693 | 5698 |
5694 | 5699 |
5695 void Analysis::EnsureAnalyzed(RegExpNode* that) { | 5700 void Analysis::EnsureAnalyzed(RegExpNode* that) { |
5696 StackLimitCheck check(that->zone()->isolate()); | 5701 StackLimitCheck check(isolate()); |
5697 if (check.HasOverflowed()) { | 5702 if (check.HasOverflowed()) { |
5698 fail("Stack overflow"); | 5703 fail("Stack overflow"); |
5699 return; | 5704 return; |
5700 } | 5705 } |
5701 if (that->info()->been_analyzed || that->info()->being_analyzed) | 5706 if (that->info()->been_analyzed || that->info()->being_analyzed) |
5702 return; | 5707 return; |
5703 that->info()->being_analyzed = true; | 5708 that->info()->being_analyzed = true; |
5704 that->Accept(this); | 5709 that->Accept(this); |
5705 that->info()->being_analyzed = false; | 5710 that->info()->being_analyzed = false; |
5706 that->info()->been_analyzed = true; | 5711 that->info()->been_analyzed = true; |
(...skipping 13 matching lines...) Expand all Loading... |
5720 for (int i = 0; i < element_count; i++) { | 5725 for (int i = 0; i < element_count; i++) { |
5721 TextElement& elm = elements()->at(i); | 5726 TextElement& elm = elements()->at(i); |
5722 elm.set_cp_offset(cp_offset); | 5727 elm.set_cp_offset(cp_offset); |
5723 cp_offset += elm.length(); | 5728 cp_offset += elm.length(); |
5724 } | 5729 } |
5725 } | 5730 } |
5726 | 5731 |
5727 | 5732 |
5728 void Analysis::VisitText(TextNode* that) { | 5733 void Analysis::VisitText(TextNode* that) { |
5729 if (ignore_case_) { | 5734 if (ignore_case_) { |
5730 that->MakeCaseIndependent(is_one_byte_); | 5735 that->MakeCaseIndependent(isolate(), is_one_byte_); |
5731 } | 5736 } |
5732 EnsureAnalyzed(that->on_success()); | 5737 EnsureAnalyzed(that->on_success()); |
5733 if (!has_failed()) { | 5738 if (!has_failed()) { |
5734 that->CalculateOffsets(); | 5739 that->CalculateOffsets(); |
5735 } | 5740 } |
5736 } | 5741 } |
5737 | 5742 |
5738 | 5743 |
5739 void Analysis::VisitAction(ActionNode* that) { | 5744 void Analysis::VisitAction(ActionNode* that) { |
5740 RegExpNode* target = that->on_success(); | 5745 RegExpNode* target = that->on_success(); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5996 } | 6001 } |
5997 | 6002 |
5998 | 6003 |
5999 void DispatchTableConstructor::VisitAction(ActionNode* that) { | 6004 void DispatchTableConstructor::VisitAction(ActionNode* that) { |
6000 RegExpNode* target = that->on_success(); | 6005 RegExpNode* target = that->on_success(); |
6001 target->Accept(this); | 6006 target->Accept(this); |
6002 } | 6007 } |
6003 | 6008 |
6004 | 6009 |
6005 RegExpEngine::CompilationResult RegExpEngine::Compile( | 6010 RegExpEngine::CompilationResult RegExpEngine::Compile( |
6006 RegExpCompileData* data, bool ignore_case, bool is_global, | 6011 Isolate* isolate, Zone* zone, RegExpCompileData* data, bool ignore_case, |
6007 bool is_multiline, bool is_sticky, Handle<String> pattern, | 6012 bool is_global, bool is_multiline, bool is_sticky, Handle<String> pattern, |
6008 Handle<String> sample_subject, bool is_one_byte, Zone* zone) { | 6013 Handle<String> sample_subject, bool is_one_byte) { |
6009 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { | 6014 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { |
6010 return IrregexpRegExpTooBig(zone->isolate()); | 6015 return IrregexpRegExpTooBig(isolate); |
6011 } | 6016 } |
6012 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); | 6017 RegExpCompiler compiler(isolate, zone, data->capture_count, ignore_case, |
| 6018 is_one_byte); |
6013 | 6019 |
6014 compiler.set_optimize(!TooMuchRegExpCode(pattern)); | 6020 compiler.set_optimize(!TooMuchRegExpCode(pattern)); |
6015 | 6021 |
6016 // Sample some characters from the middle of the string. | 6022 // Sample some characters from the middle of the string. |
6017 static const int kSampleSize = 128; | 6023 static const int kSampleSize = 128; |
6018 | 6024 |
6019 sample_subject = String::Flatten(sample_subject); | 6025 sample_subject = String::Flatten(sample_subject); |
6020 int chars_sampled = 0; | 6026 int chars_sampled = 0; |
6021 int half_way = (sample_subject->length() - kSampleSize) / 2; | 6027 int half_way = (sample_subject->length() - kSampleSize) / 2; |
6022 for (int i = Max(0, half_way); | 6028 for (int i = Max(0, half_way); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6062 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); | 6068 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); |
6063 // Do it again to propagate the new nodes to places where they were not | 6069 // Do it again to propagate the new nodes to places where they were not |
6064 // put because they had not been calculated yet. | 6070 // put because they had not been calculated yet. |
6065 if (node != NULL) { | 6071 if (node != NULL) { |
6066 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); | 6072 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); |
6067 } | 6073 } |
6068 } | 6074 } |
6069 | 6075 |
6070 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); | 6076 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); |
6071 data->node = node; | 6077 data->node = node; |
6072 Analysis analysis(ignore_case, is_one_byte); | 6078 Analysis analysis(isolate, ignore_case, is_one_byte); |
6073 analysis.EnsureAnalyzed(node); | 6079 analysis.EnsureAnalyzed(node); |
6074 if (analysis.has_failed()) { | 6080 if (analysis.has_failed()) { |
6075 const char* error_message = analysis.error_message(); | 6081 const char* error_message = analysis.error_message(); |
6076 return CompilationResult(zone->isolate(), error_message); | 6082 return CompilationResult(isolate, error_message); |
6077 } | 6083 } |
6078 | 6084 |
6079 // Create the correct assembler for the architecture. | 6085 // Create the correct assembler for the architecture. |
6080 #ifndef V8_INTERPRETED_REGEXP | 6086 #ifndef V8_INTERPRETED_REGEXP |
6081 // Native regexp implementation. | 6087 // Native regexp implementation. |
6082 | 6088 |
6083 NativeRegExpMacroAssembler::Mode mode = | 6089 NativeRegExpMacroAssembler::Mode mode = |
6084 is_one_byte ? NativeRegExpMacroAssembler::LATIN1 | 6090 is_one_byte ? NativeRegExpMacroAssembler::LATIN1 |
6085 : NativeRegExpMacroAssembler::UC16; | 6091 : NativeRegExpMacroAssembler::UC16; |
6086 | 6092 |
6087 #if V8_TARGET_ARCH_IA32 | 6093 #if V8_TARGET_ARCH_IA32 |
6088 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2, | 6094 RegExpMacroAssemblerIA32 macro_assembler(isolate, zone, mode, |
6089 zone); | 6095 (data->capture_count + 1) * 2); |
6090 #elif V8_TARGET_ARCH_X64 | 6096 #elif V8_TARGET_ARCH_X64 |
6091 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2, | 6097 RegExpMacroAssemblerX64 macro_assembler(isolate, zone, mode, |
6092 zone); | 6098 (data->capture_count + 1) * 2); |
6093 #elif V8_TARGET_ARCH_ARM | 6099 #elif V8_TARGET_ARCH_ARM |
6094 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2, | 6100 RegExpMacroAssemblerARM macro_assembler(isolate, zone, mode, |
6095 zone); | 6101 (data->capture_count + 1) * 2); |
6096 #elif V8_TARGET_ARCH_ARM64 | 6102 #elif V8_TARGET_ARCH_ARM64 |
6097 RegExpMacroAssemblerARM64 macro_assembler(mode, (data->capture_count + 1) * 2, | 6103 RegExpMacroAssemblerARM64 macro_assembler(isolate, zone, mode, |
6098 zone); | 6104 (data->capture_count + 1) * 2); |
6099 #elif V8_TARGET_ARCH_PPC | 6105 #elif V8_TARGET_ARCH_PPC |
6100 RegExpMacroAssemblerPPC macro_assembler(mode, (data->capture_count + 1) * 2, | 6106 RegExpMacroAssemblerPPC macro_assembler(isolate, zone, mode, |
6101 zone); | 6107 (data->capture_count + 1) * 2); |
6102 #elif V8_TARGET_ARCH_MIPS | 6108 #elif V8_TARGET_ARCH_MIPS |
6103 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2, | 6109 RegExpMacroAssemblerMIPS macro_assembler(isolate, zone, mode, |
6104 zone); | 6110 (data->capture_count + 1) * 2); |
6105 #elif V8_TARGET_ARCH_MIPS64 | 6111 #elif V8_TARGET_ARCH_MIPS64 |
6106 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2, | 6112 RegExpMacroAssemblerMIPS macro_assembler(isolate, zone, mode, |
6107 zone); | 6113 (data->capture_count + 1) * 2); |
6108 #elif V8_TARGET_ARCH_X87 | 6114 #elif V8_TARGET_ARCH_X87 |
6109 RegExpMacroAssemblerX87 macro_assembler(mode, (data->capture_count + 1) * 2, | 6115 RegExpMacroAssemblerX87 macro_assembler(isolate, zone, mode, |
6110 zone); | 6116 (data->capture_count + 1) * 2); |
6111 #else | 6117 #else |
6112 #error "Unsupported architecture" | 6118 #error "Unsupported architecture" |
6113 #endif | 6119 #endif |
6114 | 6120 |
6115 #else // V8_INTERPRETED_REGEXP | 6121 #else // V8_INTERPRETED_REGEXP |
6116 // Interpreted regexp implementation. | 6122 // Interpreted regexp implementation. |
6117 EmbeddedVector<byte, 1024> codes; | 6123 EmbeddedVector<byte, 1024> codes; |
6118 RegExpMacroAssemblerIrregexp macro_assembler(codes, zone); | 6124 RegExpMacroAssemblerIrregexp macro_assembler(codes, zone); |
6119 #endif // V8_INTERPRETED_REGEXP | 6125 #endif // V8_INTERPRETED_REGEXP |
6120 | 6126 |
(...skipping 26 matching lines...) Expand all Loading... |
6147 Heap* heap = pattern->GetHeap(); | 6153 Heap* heap = pattern->GetHeap(); |
6148 bool too_much = pattern->length() > RegExpImpl::kRegExpTooLargeToOptimize; | 6154 bool too_much = pattern->length() > RegExpImpl::kRegExpTooLargeToOptimize; |
6149 if (heap->total_regexp_code_generated() > RegExpImpl::kRegExpCompiledLimit && | 6155 if (heap->total_regexp_code_generated() > RegExpImpl::kRegExpCompiledLimit && |
6150 heap->isolate()->memory_allocator()->SizeExecutable() > | 6156 heap->isolate()->memory_allocator()->SizeExecutable() > |
6151 RegExpImpl::kRegExpExecutableMemoryLimit) { | 6157 RegExpImpl::kRegExpExecutableMemoryLimit) { |
6152 too_much = true; | 6158 too_much = true; |
6153 } | 6159 } |
6154 return too_much; | 6160 return too_much; |
6155 } | 6161 } |
6156 }} // namespace v8::internal | 6162 }} // namespace v8::internal |
OLD | NEW |