OLD | NEW |
1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "utils.h" | 33 #include "utils.h" |
34 #include "ast.h" | 34 #include "ast.h" |
35 #include "bytecodes-irregexp.h" | 35 #include "bytecodes-irregexp.h" |
36 #include "interpreter-irregexp.h" | 36 #include "interpreter-irregexp.h" |
37 | 37 |
38 | 38 |
39 namespace v8 { | 39 namespace v8 { |
40 namespace internal { | 40 namespace internal { |
41 | 41 |
42 | 42 |
43 static unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize; | 43 typedef unibrow::Mapping<unibrow::Ecma262Canonicalize> Canonicalize; |
44 | 44 |
45 | 45 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize, |
46 static bool BackRefMatchesNoCase(int from, | 46 int from, |
47 int current, | 47 int current, |
48 int len, | 48 int len, |
49 Vector<const uc16> subject) { | 49 Vector<const uc16> subject) { |
50 for (int i = 0; i < len; i++) { | 50 for (int i = 0; i < len; i++) { |
51 unibrow::uchar old_char = subject[from++]; | 51 unibrow::uchar old_char = subject[from++]; |
52 unibrow::uchar new_char = subject[current++]; | 52 unibrow::uchar new_char = subject[current++]; |
53 if (old_char == new_char) continue; | 53 if (old_char == new_char) continue; |
54 unibrow::uchar old_string[1] = { old_char }; | 54 unibrow::uchar old_string[1] = { old_char }; |
55 unibrow::uchar new_string[1] = { new_char }; | 55 unibrow::uchar new_string[1] = { new_char }; |
56 interp_canonicalize.get(old_char, '\0', old_string); | 56 interp_canonicalize->get(old_char, '\0', old_string); |
57 interp_canonicalize.get(new_char, '\0', new_string); | 57 interp_canonicalize->get(new_char, '\0', new_string); |
58 if (old_string[0] != new_string[0]) { | 58 if (old_string[0] != new_string[0]) { |
59 return false; | 59 return false; |
60 } | 60 } |
61 } | 61 } |
62 return true; | 62 return true; |
63 } | 63 } |
64 | 64 |
65 | 65 |
66 static bool BackRefMatchesNoCase(int from, | 66 static bool BackRefMatchesNoCase(Canonicalize* interp_canonicalize, |
| 67 int from, |
67 int current, | 68 int current, |
68 int len, | 69 int len, |
69 Vector<const char> subject) { | 70 Vector<const char> subject) { |
70 for (int i = 0; i < len; i++) { | 71 for (int i = 0; i < len; i++) { |
71 unsigned int old_char = subject[from++]; | 72 unsigned int old_char = subject[from++]; |
72 unsigned int new_char = subject[current++]; | 73 unsigned int new_char = subject[current++]; |
73 if (old_char == new_char) continue; | 74 if (old_char == new_char) continue; |
74 if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20; | 75 if (old_char - 'A' <= 'Z' - 'A') old_char |= 0x20; |
75 if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20; | 76 if (new_char - 'A' <= 'Z' - 'A') new_char |= 0x20; |
76 if (old_char != new_char) return false; | 77 if (old_char != new_char) return false; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 return *reinterpret_cast<const uint16_t *>(pc); | 144 return *reinterpret_cast<const uint16_t *>(pc); |
144 } | 145 } |
145 | 146 |
146 | 147 |
147 // A simple abstraction over the backtracking stack used by the interpreter. | 148 // A simple abstraction over the backtracking stack used by the interpreter. |
148 // This backtracking stack does not grow automatically, but it ensures that the | 149 // This backtracking stack does not grow automatically, but it ensures that the |
149 // the memory held by the stack is released or remembered in a cache if the | 150 // the memory held by the stack is released or remembered in a cache if the |
150 // matching terminates. | 151 // matching terminates. |
151 class BacktrackStack { | 152 class BacktrackStack { |
152 public: | 153 public: |
153 explicit BacktrackStack() { | 154 explicit BacktrackStack(Isolate* isolate) : isolate_(isolate) { |
154 if (cache_ != NULL) { | 155 if (isolate->irregexp_interpreter_backtrack_stack_cache() != NULL) { |
155 // If the cache is not empty reuse the previously allocated stack. | 156 // If the cache is not empty reuse the previously allocated stack. |
156 data_ = cache_; | 157 data_ = isolate->irregexp_interpreter_backtrack_stack_cache(); |
157 cache_ = NULL; | 158 isolate->set_irregexp_interpreter_backtrack_stack_cache(NULL); |
158 } else { | 159 } else { |
159 // Cache was empty. Allocate a new backtrack stack. | 160 // Cache was empty. Allocate a new backtrack stack. |
160 data_ = NewArray<int>(kBacktrackStackSize); | 161 data_ = NewArray<int>(kBacktrackStackSize); |
161 } | 162 } |
162 } | 163 } |
163 | 164 |
164 ~BacktrackStack() { | 165 ~BacktrackStack() { |
165 if (cache_ == NULL) { | 166 if (isolate_->irregexp_interpreter_backtrack_stack_cache() == NULL) { |
166 // The cache is empty. Keep this backtrack stack around. | 167 // The cache is empty. Keep this backtrack stack around. |
167 cache_ = data_; | 168 isolate_->set_irregexp_interpreter_backtrack_stack_cache(data_); |
168 } else { | 169 } else { |
169 // A backtrack stack was already cached, just release this one. | 170 // A backtrack stack was already cached, just release this one. |
170 DeleteArray(data_); | 171 DeleteArray(data_); |
171 } | 172 } |
172 } | 173 } |
173 | 174 |
174 int* data() const { return data_; } | 175 int* data() const { return data_; } |
175 | 176 |
176 int max_size() const { return kBacktrackStackSize; } | 177 int max_size() const { return kBacktrackStackSize; } |
177 | 178 |
178 private: | 179 private: |
179 static const int kBacktrackStackSize = 10000; | 180 static const int kBacktrackStackSize = 10000; |
180 | 181 |
181 int* data_; | 182 int* data_; |
182 static int* cache_; | 183 Isolate* isolate_; |
183 | 184 |
184 DISALLOW_COPY_AND_ASSIGN(BacktrackStack); | 185 DISALLOW_COPY_AND_ASSIGN(BacktrackStack); |
185 }; | 186 }; |
186 | 187 |
187 int* BacktrackStack::cache_ = NULL; | |
188 | |
189 | 188 |
190 template <typename Char> | 189 template <typename Char> |
191 static bool RawMatch(const byte* code_base, | 190 static bool RawMatch(Isolate* isolate, |
| 191 const byte* code_base, |
192 Vector<const Char> subject, | 192 Vector<const Char> subject, |
193 int* registers, | 193 int* registers, |
194 int current, | 194 int current, |
195 uint32_t current_char) { | 195 uint32_t current_char) { |
196 const byte* pc = code_base; | 196 const byte* pc = code_base; |
197 // BacktrackStack ensures that the memory allocated for the backtracking stack | 197 // BacktrackStack ensures that the memory allocated for the backtracking stack |
198 // is returned to the system or cached if there is no stack being cached at | 198 // is returned to the system or cached if there is no stack being cached at |
199 // the moment. | 199 // the moment. |
200 BacktrackStack backtrack_stack; | 200 BacktrackStack backtrack_stack(isolate); |
201 int* backtrack_stack_base = backtrack_stack.data(); | 201 int* backtrack_stack_base = backtrack_stack.data(); |
202 int* backtrack_sp = backtrack_stack_base; | 202 int* backtrack_sp = backtrack_stack_base; |
203 int backtrack_stack_space = backtrack_stack.max_size(); | 203 int backtrack_stack_space = backtrack_stack.max_size(); |
204 #ifdef DEBUG | 204 #ifdef DEBUG |
205 if (FLAG_trace_regexp_bytecodes) { | 205 if (FLAG_trace_regexp_bytecodes) { |
206 PrintF("\n\nStart bytecode interpreter\n\n"); | 206 PrintF("\n\nStart bytecode interpreter\n\n"); |
207 } | 207 } |
208 #endif | 208 #endif |
209 while (true) { | 209 while (true) { |
210 int32_t insn = Load32Aligned(pc); | 210 int32_t insn = Load32Aligned(pc); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 int from = registers[insn >> BYTECODE_SHIFT]; | 577 int from = registers[insn >> BYTECODE_SHIFT]; |
578 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; | 578 int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from; |
579 if (from < 0 || len <= 0) { | 579 if (from < 0 || len <= 0) { |
580 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH; | 580 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH; |
581 break; | 581 break; |
582 } | 582 } |
583 if (current + len > subject.length()) { | 583 if (current + len > subject.length()) { |
584 pc = code_base + Load32Aligned(pc + 4); | 584 pc = code_base + Load32Aligned(pc + 4); |
585 break; | 585 break; |
586 } else { | 586 } else { |
587 if (BackRefMatchesNoCase(from, current, len, subject)) { | 587 if (BackRefMatchesNoCase(isolate->interp_canonicalize_mapping(), |
| 588 from, current, len, subject)) { |
588 current += len; | 589 current += len; |
589 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH; | 590 pc += BC_CHECK_NOT_BACK_REF_NO_CASE_LENGTH; |
590 } else { | 591 } else { |
591 pc = code_base + Load32Aligned(pc + 4); | 592 pc = code_base + Load32Aligned(pc + 4); |
592 } | 593 } |
593 } | 594 } |
594 break; | 595 break; |
595 } | 596 } |
596 BYTECODE(CHECK_AT_START) | 597 BYTECODE(CHECK_AT_START) |
597 if (current == 0) { | 598 if (current == 0) { |
(...skipping 19 matching lines...) Expand all Loading... |
617 break; | 618 break; |
618 } | 619 } |
619 default: | 620 default: |
620 UNREACHABLE(); | 621 UNREACHABLE(); |
621 break; | 622 break; |
622 } | 623 } |
623 } | 624 } |
624 } | 625 } |
625 | 626 |
626 | 627 |
627 bool IrregexpInterpreter::Match(Handle<ByteArray> code_array, | 628 bool IrregexpInterpreter::Match(Isolate* isolate, |
| 629 Handle<ByteArray> code_array, |
628 Handle<String> subject, | 630 Handle<String> subject, |
629 int* registers, | 631 int* registers, |
630 int start_position) { | 632 int start_position) { |
631 ASSERT(subject->IsFlat()); | 633 ASSERT(subject->IsFlat()); |
632 | 634 |
633 AssertNoAllocation a; | 635 AssertNoAllocation a; |
634 const byte* code_base = code_array->GetDataStartAddress(); | 636 const byte* code_base = code_array->GetDataStartAddress(); |
635 uc16 previous_char = '\n'; | 637 uc16 previous_char = '\n'; |
636 if (subject->IsAsciiRepresentation()) { | 638 if (subject->IsAsciiRepresentation()) { |
637 Vector<const char> subject_vector = subject->ToAsciiVector(); | 639 Vector<const char> subject_vector = subject->ToAsciiVector(); |
638 if (start_position != 0) previous_char = subject_vector[start_position - 1]; | 640 if (start_position != 0) previous_char = subject_vector[start_position - 1]; |
639 return RawMatch(code_base, | 641 return RawMatch(isolate, |
| 642 code_base, |
640 subject_vector, | 643 subject_vector, |
641 registers, | 644 registers, |
642 start_position, | 645 start_position, |
643 previous_char); | 646 previous_char); |
644 } else { | 647 } else { |
645 Vector<const uc16> subject_vector = subject->ToUC16Vector(); | 648 Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
646 if (start_position != 0) previous_char = subject_vector[start_position - 1]; | 649 if (start_position != 0) previous_char = subject_vector[start_position - 1]; |
647 return RawMatch(code_base, | 650 return RawMatch(isolate, |
| 651 code_base, |
648 subject_vector, | 652 subject_vector, |
649 registers, | 653 registers, |
650 start_position, | 654 start_position, |
651 previous_char); | 655 previous_char); |
652 } | 656 } |
653 } | 657 } |
654 | 658 |
655 } } // namespace v8::internal | 659 } } // namespace v8::internal |
OLD | NEW |