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
3 // found in the LICENSE file.
7 #include "src/assembler.h"
9 #include "src/regexp-macro-assembler.h"
10 #include "src/regexp-stack.h"
11 #include "src/simulator.h"
16 RegExpMacroAssembler::RegExpMacroAssembler(Zone* zone)
17 : slow_safe_compiler_(false),
18 global_mode_(NOT_GLOBAL),
23 RegExpMacroAssembler::~RegExpMacroAssembler() {
27 #ifndef V8_INTERPRETED_REGEXP // Avoid unused code, e.g., on ARM.
29 NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(Zone* zone)
30 : RegExpMacroAssembler(zone) {
34 NativeRegExpMacroAssembler::~NativeRegExpMacroAssembler() {
38 bool NativeRegExpMacroAssembler::CanReadUnaligned() {
39 return FLAG_enable_unaligned_accesses && !slow_safe();
42 const byte* NativeRegExpMacroAssembler::StringCharacterPosition(
45 // Not just flat, but ultra flat.
46 DCHECK(subject->IsExternalString() || subject->IsSeqString());
47 DCHECK(start_index >= 0);
48 DCHECK(start_index <= subject->length());
49 if (subject->IsOneByteRepresentation()) {
51 if (StringShape(subject).IsExternal()) {
52 const uint8_t* data = ExternalOneByteString::cast(subject)->GetChars();
53 address = reinterpret_cast<const byte*>(data);
55 DCHECK(subject->IsSeqOneByteString());
56 const uint8_t* data = SeqOneByteString::cast(subject)->GetChars();
57 address = reinterpret_cast<const byte*>(data);
59 return address + start_index;
62 if (StringShape(subject).IsExternal()) {
63 data = ExternalTwoByteString::cast(subject)->GetChars();
65 DCHECK(subject->IsSeqTwoByteString());
66 data = SeqTwoByteString::cast(subject)->GetChars();
68 return reinterpret_cast<const byte*>(data + start_index);
72 NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match(
73 Handle<Code> regexp_code,
74 Handle<String> subject,
76 int offsets_vector_length,
80 DCHECK(subject->IsFlat());
81 DCHECK(previous_index >= 0);
82 DCHECK(previous_index <= subject->length());
84 // No allocations before calling the regexp, but we can't use
85 // DisallowHeapAllocation, since regexps might be preempted, and another
86 // thread might do allocation anyway.
88 String* subject_ptr = *subject;
89 // Character offsets into string.
90 int start_offset = previous_index;
91 int char_length = subject_ptr->length() - start_offset;
94 // The string has been flattened, so if it is a cons string it contains the
95 // full string in the first part.
96 if (StringShape(subject_ptr).IsCons()) {
97 DCHECK_EQ(0, ConsString::cast(subject_ptr)->second()->length());
98 subject_ptr = ConsString::cast(subject_ptr)->first();
99 } else if (StringShape(subject_ptr).IsSliced()) {
100 SlicedString* slice = SlicedString::cast(subject_ptr);
101 subject_ptr = slice->parent();
102 slice_offset = slice->offset();
104 // Ensure that an underlying string has the same representation.
105 bool is_one_byte = subject_ptr->IsOneByteRepresentation();
106 DCHECK(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
107 // String is now either Sequential or External
108 int char_size_shift = is_one_byte ? 0 : 1;
110 const byte* input_start =
111 StringCharacterPosition(subject_ptr, start_offset + slice_offset);
112 int byte_length = char_length << char_size_shift;
113 const byte* input_end = input_start + byte_length;
114 Result res = Execute(*regexp_code,
120 offsets_vector_length,
126 NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Execute(
128 String* input, // This needs to be the unpacked (sliced, cons) string.
130 const byte* input_start,
131 const byte* input_end,
135 // Ensure that the minimum stack has been allocated.
136 RegExpStackScope stack_scope(isolate);
137 Address stack_base = stack_scope.stack()->stack_base();
140 int result = CALL_GENERATED_REGEXP_CODE(code->entry(),
150 DCHECK(result >= RETRY);
152 if (result == EXCEPTION && !isolate->has_pending_exception()) {
153 // We detected a stack overflow (on the backtrack stack) in RegExp code,
154 // but haven't created the exception yet.
155 isolate->StackOverflow();
157 return static_cast<Result>(result);
161 const byte NativeRegExpMacroAssembler::word_character_map[] = {
162 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
163 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
164 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
165 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
167 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
168 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
169 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // '0' - '7'
170 0xffu, 0xffu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, // '8' - '9'
172 0x00u, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'A' - 'G'
173 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'H' - 'O'
174 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'P' - 'W'
175 0xffu, 0xffu, 0xffu, 0x00u, 0x00u, 0x00u, 0x00u, 0xffu, // 'X' - 'Z', '_'
177 0x00u, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'a' - 'g'
178 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'h' - 'o'
179 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, 0xffu, // 'p' - 'w'
180 0xffu, 0xffu, 0xffu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, // 'x' - 'z'
182 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
183 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
184 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
185 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
187 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
188 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
189 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
190 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
192 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
193 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
194 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
195 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
197 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
198 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
199 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
200 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
204 int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16(
205 Address byte_offset1,
206 Address byte_offset2,
209 unibrow::Mapping<unibrow::Ecma262Canonicalize>* canonicalize =
210 isolate->regexp_macro_assembler_canonicalize();
211 // This function is not allowed to cause a garbage collection.
212 // A GC might move the calling generated code and invalidate the
213 // return address on the stack.
214 DCHECK(byte_length % 2 == 0);
215 uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1);
216 uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2);
217 size_t length = byte_length >> 1;
219 for (size_t i = 0; i < length; i++) {
220 unibrow::uchar c1 = substring1[i];
221 unibrow::uchar c2 = substring2[i];
223 unibrow::uchar s1[1] = { c1 };
224 canonicalize->get(c1, '\0', s1);
226 unibrow::uchar s2[1] = { c2 };
227 canonicalize->get(c2, '\0', s2);
228 if (s1[0] != s2[0]) {
238 Address NativeRegExpMacroAssembler::GrowStack(Address stack_pointer,
241 RegExpStack* regexp_stack = isolate->regexp_stack();
242 size_t size = regexp_stack->stack_capacity();
243 Address old_stack_base = regexp_stack->stack_base();
244 DCHECK(old_stack_base == *stack_base);
245 DCHECK(stack_pointer <= old_stack_base);
246 DCHECK(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
247 Address new_stack_base = regexp_stack->EnsureCapacity(size * 2);
248 if (new_stack_base == NULL) {
251 *stack_base = new_stack_base;
252 intptr_t stack_content_size = old_stack_base - stack_pointer;
253 return new_stack_base - stack_content_size;
256 #endif // V8_INTERPRETED_REGEXP
258 } } // namespace v8::internal