| 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/assembler.h" | 7 #include "src/assembler.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/regexp-macro-assembler.h" | 9 #include "src/regexp-macro-assembler.h" |
| 10 #include "src/regexp-stack.h" | 10 #include "src/regexp-stack.h" |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 | 45 |
| 46 | 46 |
| 47 bool NativeRegExpMacroAssembler::CanReadUnaligned() { | 47 bool NativeRegExpMacroAssembler::CanReadUnaligned() { |
| 48 return FLAG_enable_unaligned_accesses && !slow_safe(); | 48 return FLAG_enable_unaligned_accesses && !slow_safe(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 const byte* NativeRegExpMacroAssembler::StringCharacterPosition( | 51 const byte* NativeRegExpMacroAssembler::StringCharacterPosition( |
| 52 String* subject, | 52 String* subject, |
| 53 int start_index) { | 53 int start_index) { |
| 54 // Not just flat, but ultra flat. | 54 // Not just flat, but ultra flat. |
| 55 ASSERT(subject->IsExternalString() || subject->IsSeqString()); | 55 DCHECK(subject->IsExternalString() || subject->IsSeqString()); |
| 56 ASSERT(start_index >= 0); | 56 DCHECK(start_index >= 0); |
| 57 ASSERT(start_index <= subject->length()); | 57 DCHECK(start_index <= subject->length()); |
| 58 if (subject->IsOneByteRepresentation()) { | 58 if (subject->IsOneByteRepresentation()) { |
| 59 const byte* address; | 59 const byte* address; |
| 60 if (StringShape(subject).IsExternal()) { | 60 if (StringShape(subject).IsExternal()) { |
| 61 const uint8_t* data = ExternalAsciiString::cast(subject)->GetChars(); | 61 const uint8_t* data = ExternalAsciiString::cast(subject)->GetChars(); |
| 62 address = reinterpret_cast<const byte*>(data); | 62 address = reinterpret_cast<const byte*>(data); |
| 63 } else { | 63 } else { |
| 64 ASSERT(subject->IsSeqOneByteString()); | 64 DCHECK(subject->IsSeqOneByteString()); |
| 65 const uint8_t* data = SeqOneByteString::cast(subject)->GetChars(); | 65 const uint8_t* data = SeqOneByteString::cast(subject)->GetChars(); |
| 66 address = reinterpret_cast<const byte*>(data); | 66 address = reinterpret_cast<const byte*>(data); |
| 67 } | 67 } |
| 68 return address + start_index; | 68 return address + start_index; |
| 69 } | 69 } |
| 70 const uc16* data; | 70 const uc16* data; |
| 71 if (StringShape(subject).IsExternal()) { | 71 if (StringShape(subject).IsExternal()) { |
| 72 data = ExternalTwoByteString::cast(subject)->GetChars(); | 72 data = ExternalTwoByteString::cast(subject)->GetChars(); |
| 73 } else { | 73 } else { |
| 74 ASSERT(subject->IsSeqTwoByteString()); | 74 DCHECK(subject->IsSeqTwoByteString()); |
| 75 data = SeqTwoByteString::cast(subject)->GetChars(); | 75 data = SeqTwoByteString::cast(subject)->GetChars(); |
| 76 } | 76 } |
| 77 return reinterpret_cast<const byte*>(data + start_index); | 77 return reinterpret_cast<const byte*>(data + start_index); |
| 78 } | 78 } |
| 79 | 79 |
| 80 | 80 |
| 81 NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match( | 81 NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match( |
| 82 Handle<Code> regexp_code, | 82 Handle<Code> regexp_code, |
| 83 Handle<String> subject, | 83 Handle<String> subject, |
| 84 int* offsets_vector, | 84 int* offsets_vector, |
| 85 int offsets_vector_length, | 85 int offsets_vector_length, |
| 86 int previous_index, | 86 int previous_index, |
| 87 Isolate* isolate) { | 87 Isolate* isolate) { |
| 88 | 88 |
| 89 ASSERT(subject->IsFlat()); | 89 DCHECK(subject->IsFlat()); |
| 90 ASSERT(previous_index >= 0); | 90 DCHECK(previous_index >= 0); |
| 91 ASSERT(previous_index <= subject->length()); | 91 DCHECK(previous_index <= subject->length()); |
| 92 | 92 |
| 93 // No allocations before calling the regexp, but we can't use | 93 // No allocations before calling the regexp, but we can't use |
| 94 // DisallowHeapAllocation, since regexps might be preempted, and another | 94 // DisallowHeapAllocation, since regexps might be preempted, and another |
| 95 // thread might do allocation anyway. | 95 // thread might do allocation anyway. |
| 96 | 96 |
| 97 String* subject_ptr = *subject; | 97 String* subject_ptr = *subject; |
| 98 // Character offsets into string. | 98 // Character offsets into string. |
| 99 int start_offset = previous_index; | 99 int start_offset = previous_index; |
| 100 int char_length = subject_ptr->length() - start_offset; | 100 int char_length = subject_ptr->length() - start_offset; |
| 101 int slice_offset = 0; | 101 int slice_offset = 0; |
| 102 | 102 |
| 103 // The string has been flattened, so if it is a cons string it contains the | 103 // The string has been flattened, so if it is a cons string it contains the |
| 104 // full string in the first part. | 104 // full string in the first part. |
| 105 if (StringShape(subject_ptr).IsCons()) { | 105 if (StringShape(subject_ptr).IsCons()) { |
| 106 ASSERT_EQ(0, ConsString::cast(subject_ptr)->second()->length()); | 106 DCHECK_EQ(0, ConsString::cast(subject_ptr)->second()->length()); |
| 107 subject_ptr = ConsString::cast(subject_ptr)->first(); | 107 subject_ptr = ConsString::cast(subject_ptr)->first(); |
| 108 } else if (StringShape(subject_ptr).IsSliced()) { | 108 } else if (StringShape(subject_ptr).IsSliced()) { |
| 109 SlicedString* slice = SlicedString::cast(subject_ptr); | 109 SlicedString* slice = SlicedString::cast(subject_ptr); |
| 110 subject_ptr = slice->parent(); | 110 subject_ptr = slice->parent(); |
| 111 slice_offset = slice->offset(); | 111 slice_offset = slice->offset(); |
| 112 } | 112 } |
| 113 // Ensure that an underlying string has the same ASCII-ness. | 113 // Ensure that an underlying string has the same ASCII-ness. |
| 114 bool is_ascii = subject_ptr->IsOneByteRepresentation(); | 114 bool is_ascii = subject_ptr->IsOneByteRepresentation(); |
| 115 ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString()); | 115 DCHECK(subject_ptr->IsExternalString() || subject_ptr->IsSeqString()); |
| 116 // String is now either Sequential or External | 116 // String is now either Sequential or External |
| 117 int char_size_shift = is_ascii ? 0 : 1; | 117 int char_size_shift = is_ascii ? 0 : 1; |
| 118 | 118 |
| 119 const byte* input_start = | 119 const byte* input_start = |
| 120 StringCharacterPosition(subject_ptr, start_offset + slice_offset); | 120 StringCharacterPosition(subject_ptr, start_offset + slice_offset); |
| 121 int byte_length = char_length << char_size_shift; | 121 int byte_length = char_length << char_size_shift; |
| 122 const byte* input_end = input_start + byte_length; | 122 const byte* input_end = input_start + byte_length; |
| 123 Result res = Execute(*regexp_code, | 123 Result res = Execute(*regexp_code, |
| 124 *subject, | 124 *subject, |
| 125 start_offset, | 125 start_offset, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 149 int result = CALL_GENERATED_REGEXP_CODE(code->entry(), | 149 int result = CALL_GENERATED_REGEXP_CODE(code->entry(), |
| 150 input, | 150 input, |
| 151 start_offset, | 151 start_offset, |
| 152 input_start, | 152 input_start, |
| 153 input_end, | 153 input_end, |
| 154 output, | 154 output, |
| 155 output_size, | 155 output_size, |
| 156 stack_base, | 156 stack_base, |
| 157 direct_call, | 157 direct_call, |
| 158 isolate); | 158 isolate); |
| 159 ASSERT(result >= RETRY); | 159 DCHECK(result >= RETRY); |
| 160 | 160 |
| 161 if (result == EXCEPTION && !isolate->has_pending_exception()) { | 161 if (result == EXCEPTION && !isolate->has_pending_exception()) { |
| 162 // We detected a stack overflow (on the backtrack stack) in RegExp code, | 162 // We detected a stack overflow (on the backtrack stack) in RegExp code, |
| 163 // but haven't created the exception yet. | 163 // but haven't created the exception yet. |
| 164 isolate->StackOverflow(); | 164 isolate->StackOverflow(); |
| 165 } | 165 } |
| 166 return static_cast<Result>(result); | 166 return static_cast<Result>(result); |
| 167 } | 167 } |
| 168 | 168 |
| 169 | 169 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16( | 213 int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16( |
| 214 Address byte_offset1, | 214 Address byte_offset1, |
| 215 Address byte_offset2, | 215 Address byte_offset2, |
| 216 size_t byte_length, | 216 size_t byte_length, |
| 217 Isolate* isolate) { | 217 Isolate* isolate) { |
| 218 unibrow::Mapping<unibrow::Ecma262Canonicalize>* canonicalize = | 218 unibrow::Mapping<unibrow::Ecma262Canonicalize>* canonicalize = |
| 219 isolate->regexp_macro_assembler_canonicalize(); | 219 isolate->regexp_macro_assembler_canonicalize(); |
| 220 // This function is not allowed to cause a garbage collection. | 220 // This function is not allowed to cause a garbage collection. |
| 221 // A GC might move the calling generated code and invalidate the | 221 // A GC might move the calling generated code and invalidate the |
| 222 // return address on the stack. | 222 // return address on the stack. |
| 223 ASSERT(byte_length % 2 == 0); | 223 DCHECK(byte_length % 2 == 0); |
| 224 uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1); | 224 uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1); |
| 225 uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2); | 225 uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2); |
| 226 size_t length = byte_length >> 1; | 226 size_t length = byte_length >> 1; |
| 227 | 227 |
| 228 for (size_t i = 0; i < length; i++) { | 228 for (size_t i = 0; i < length; i++) { |
| 229 unibrow::uchar c1 = substring1[i]; | 229 unibrow::uchar c1 = substring1[i]; |
| 230 unibrow::uchar c2 = substring2[i]; | 230 unibrow::uchar c2 = substring2[i]; |
| 231 if (c1 != c2) { | 231 if (c1 != c2) { |
| 232 unibrow::uchar s1[1] = { c1 }; | 232 unibrow::uchar s1[1] = { c1 }; |
| 233 canonicalize->get(c1, '\0', s1); | 233 canonicalize->get(c1, '\0', s1); |
| 234 if (s1[0] != c2) { | 234 if (s1[0] != c2) { |
| 235 unibrow::uchar s2[1] = { c2 }; | 235 unibrow::uchar s2[1] = { c2 }; |
| 236 canonicalize->get(c2, '\0', s2); | 236 canonicalize->get(c2, '\0', s2); |
| 237 if (s1[0] != s2[0]) { | 237 if (s1[0] != s2[0]) { |
| 238 return 0; | 238 return 0; |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 } | 242 } |
| 243 return 1; | 243 return 1; |
| 244 } | 244 } |
| 245 | 245 |
| 246 | 246 |
| 247 Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer, | 247 Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer, |
| 248 Address* stack_base, | 248 Address* stack_base, |
| 249 Isolate* isolate) { | 249 Isolate* isolate) { |
| 250 RegExpStack* regexp_stack = isolate->regexp_stack(); | 250 RegExpStack* regexp_stack = isolate->regexp_stack(); |
| 251 size_t size = regexp_stack->stack_capacity(); | 251 size_t size = regexp_stack->stack_capacity(); |
| 252 Address old_stack_base = regexp_stack->stack_base(); | 252 Address old_stack_base = regexp_stack->stack_base(); |
| 253 ASSERT(old_stack_base == *stack_base); | 253 DCHECK(old_stack_base == *stack_base); |
| 254 ASSERT(stack_pointer <= old_stack_base); | 254 DCHECK(stack_pointer <= old_stack_base); |
| 255 ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size); | 255 DCHECK(static_cast<size_t>(old_stack_base - stack_pointer) <= size); |
| 256 Address new_stack_base = regexp_stack->EnsureCapacity(size * 2); | 256 Address new_stack_base = regexp_stack->EnsureCapacity(size * 2); |
| 257 if (new_stack_base == NULL) { | 257 if (new_stack_base == NULL) { |
| 258 return NULL; | 258 return NULL; |
| 259 } | 259 } |
| 260 *stack_base = new_stack_base; | 260 *stack_base = new_stack_base; |
| 261 intptr_t stack_content_size = old_stack_base - stack_pointer; | 261 intptr_t stack_content_size = old_stack_base - stack_pointer; |
| 262 return new_stack_base - stack_content_size; | 262 return new_stack_base - stack_content_size; |
| 263 } | 263 } |
| 264 | 264 |
| 265 #endif // V8_INTERPRETED_REGEXP | 265 #endif // V8_INTERPRETED_REGEXP |
| 266 | 266 |
| 267 } } // namespace v8::internal | 267 } } // namespace v8::internal |
| OLD | NEW |