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