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 |