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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/regexp/x87/regexp-macro-assembler-x87.h" | 7 #include "src/regexp/x87/regexp-macro-assembler-x87.h" |
8 | 8 |
9 #include "src/log.h" | 9 #include "src/log.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 * - start index (character index of start) | 46 * - start index (character index of start) |
47 * - String* input_string (location of a handle containing the string) | 47 * - String* input_string (location of a handle containing the string) |
48 * --- frame alignment (if applicable) --- | 48 * --- frame alignment (if applicable) --- |
49 * - return address | 49 * - return address |
50 * ebp-> - old ebp | 50 * ebp-> - old ebp |
51 * - backup of caller esi | 51 * - backup of caller esi |
52 * - backup of caller edi | 52 * - backup of caller edi |
53 * - backup of caller ebx | 53 * - backup of caller ebx |
54 * - success counter (only for global regexps to count matches). | 54 * - success counter (only for global regexps to count matches). |
55 * - Offset of location before start of input (effectively character | 55 * - Offset of location before start of input (effectively character |
56 * position -1). Used to initialize capture registers to a non-position. | 56 * string start - 1). Used to initialize capture registers to a |
| 57 * non-position. |
57 * - register 0 ebp[-4] (only positions must be stored in the first | 58 * - register 0 ebp[-4] (only positions must be stored in the first |
58 * - register 1 ebp[-8] num_saved_registers_ registers) | 59 * - register 1 ebp[-8] num_saved_registers_ registers) |
59 * - ... | 60 * - ... |
60 * | 61 * |
61 * The first num_saved_registers_ registers are initialized to point to | 62 * The first num_saved_registers_ registers are initialized to point to |
62 * "character -1" in the string (i.e., char_size() bytes before the first | 63 * "character -1" in the string (i.e., char_size() bytes before the first |
63 * character of the string). The remaining registers starts out as garbage. | 64 * character of the string). The remaining registers starts out as garbage. |
64 * | 65 * |
65 * The data up to the return address must be placed there by the calling | 66 * The data up to the return address must be placed there by the calling |
66 * code, by calling the code entry as cast to a function with the signature: | 67 * code, by calling the code entry as cast to a function with the signature: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 } | 150 } |
150 | 151 |
151 | 152 |
152 void RegExpMacroAssemblerX87::CheckCharacterGT(uc16 limit, Label* on_greater) { | 153 void RegExpMacroAssemblerX87::CheckCharacterGT(uc16 limit, Label* on_greater) { |
153 __ cmp(current_character(), limit); | 154 __ cmp(current_character(), limit); |
154 BranchOrBacktrack(greater, on_greater); | 155 BranchOrBacktrack(greater, on_greater); |
155 } | 156 } |
156 | 157 |
157 | 158 |
158 void RegExpMacroAssemblerX87::CheckAtStart(Label* on_at_start) { | 159 void RegExpMacroAssemblerX87::CheckAtStart(Label* on_at_start) { |
159 Label not_at_start; | 160 __ lea(eax, Operand(edi, -char_size())); |
160 // Did we start the match at the start of the string at all? | 161 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); |
161 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); | |
162 BranchOrBacktrack(not_equal, ¬_at_start); | |
163 // If we did, are we still at the start of the input? | |
164 __ lea(eax, Operand(esi, edi, times_1, 0)); | |
165 __ cmp(eax, Operand(ebp, kInputStart)); | |
166 BranchOrBacktrack(equal, on_at_start); | 162 BranchOrBacktrack(equal, on_at_start); |
167 __ bind(¬_at_start); | |
168 } | 163 } |
169 | 164 |
170 | 165 |
171 void RegExpMacroAssemblerX87::CheckNotAtStart(Label* on_not_at_start) { | 166 void RegExpMacroAssemblerX87::CheckNotAtStart(int cp_offset, |
172 // Did we start the match at the start of the string at all? | 167 Label* on_not_at_start) { |
173 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); | 168 __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size())); |
174 BranchOrBacktrack(not_equal, on_not_at_start); | 169 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); |
175 // If we did, are we still at the start of the input? | |
176 __ lea(eax, Operand(esi, edi, times_1, 0)); | |
177 __ cmp(eax, Operand(ebp, kInputStart)); | |
178 BranchOrBacktrack(not_equal, on_not_at_start); | 170 BranchOrBacktrack(not_equal, on_not_at_start); |
179 } | 171 } |
180 | 172 |
181 | 173 |
182 void RegExpMacroAssemblerX87::CheckCharacterLT(uc16 limit, Label* on_less) { | 174 void RegExpMacroAssemblerX87::CheckCharacterLT(uc16 limit, Label* on_less) { |
183 __ cmp(current_character(), limit); | 175 __ cmp(current_character(), limit); |
184 BranchOrBacktrack(less, on_less); | 176 BranchOrBacktrack(less, on_less); |
185 } | 177 } |
186 | 178 |
187 | 179 |
188 void RegExpMacroAssemblerX87::CheckGreedyLoop(Label* on_equal) { | 180 void RegExpMacroAssemblerX87::CheckGreedyLoop(Label* on_equal) { |
189 Label fallthrough; | 181 Label fallthrough; |
190 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); | 182 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); |
191 __ j(not_equal, &fallthrough); | 183 __ j(not_equal, &fallthrough); |
192 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. | 184 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. |
193 BranchOrBacktrack(no_condition, on_equal); | 185 BranchOrBacktrack(no_condition, on_equal); |
194 __ bind(&fallthrough); | 186 __ bind(&fallthrough); |
195 } | 187 } |
196 | 188 |
197 | 189 |
198 void RegExpMacroAssemblerX87::CheckNotBackReferenceIgnoreCase( | 190 void RegExpMacroAssemblerX87::CheckNotBackReferenceIgnoreCase( |
199 int start_reg, | 191 int start_reg, bool read_backward, Label* on_no_match) { |
200 Label* on_no_match) { | |
201 Label fallthrough; | 192 Label fallthrough; |
202 __ mov(edx, register_location(start_reg)); // Index of start of capture | 193 __ mov(edx, register_location(start_reg)); // Index of start of capture |
203 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture | 194 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture |
204 __ sub(ebx, edx); // Length of capture. | 195 __ sub(ebx, edx); // Length of capture. |
205 | 196 |
206 // The length of a capture should not be negative. This can only happen | 197 // At this point, the capture registers are either both set or both cleared. |
207 // if the end of the capture is unrecorded, or at a point earlier than | 198 // If the capture length is zero, then the capture is either empty or cleared. |
208 // the start of the capture. | 199 // Fall through in both cases. |
209 BranchOrBacktrack(less, on_no_match); | |
210 | |
211 // If length is zero, either the capture is empty or it is completely | |
212 // uncaptured. In either case succeed immediately. | |
213 __ j(equal, &fallthrough); | 200 __ j(equal, &fallthrough); |
214 | 201 |
215 // Check that there are sufficient characters left in the input. | 202 // Check that there are sufficient characters left in the input. |
216 __ mov(eax, edi); | 203 if (read_backward) { |
217 __ add(eax, ebx); | 204 __ mov(eax, Operand(ebp, kStringStartMinusOne)); |
218 BranchOrBacktrack(greater, on_no_match); | 205 __ add(eax, ebx); |
| 206 __ cmp(edi, eax); |
| 207 BranchOrBacktrack(less_equal, on_no_match); |
| 208 } else { |
| 209 __ mov(eax, edi); |
| 210 __ add(eax, ebx); |
| 211 BranchOrBacktrack(greater, on_no_match); |
| 212 } |
219 | 213 |
220 if (mode_ == LATIN1) { | 214 if (mode_ == LATIN1) { |
221 Label success; | 215 Label success; |
222 Label fail; | 216 Label fail; |
223 Label loop_increment; | 217 Label loop_increment; |
224 // Save register contents to make the registers available below. | 218 // Save register contents to make the registers available below. |
225 __ push(edi); | 219 __ push(edi); |
226 __ push(backtrack_stackpointer()); | 220 __ push(backtrack_stackpointer()); |
227 // After this, the eax, ecx, and edi registers are available. | 221 // After this, the eax, ecx, and edi registers are available. |
228 | 222 |
229 __ add(edx, esi); // Start of capture | 223 __ add(edx, esi); // Start of capture |
230 __ add(edi, esi); // Start of text to match against capture. | 224 __ add(edi, esi); // Start of text to match against capture. |
| 225 if (read_backward) { |
| 226 __ sub(edi, ebx); // Offset by length when matching backwards. |
| 227 } |
231 __ add(ebx, edi); // End of text to match against capture. | 228 __ add(ebx, edi); // End of text to match against capture. |
232 | 229 |
233 Label loop; | 230 Label loop; |
234 __ bind(&loop); | 231 __ bind(&loop); |
235 __ movzx_b(eax, Operand(edi, 0)); | 232 __ movzx_b(eax, Operand(edi, 0)); |
236 __ cmpb_al(Operand(edx, 0)); | 233 __ cmpb_al(Operand(edx, 0)); |
237 __ j(equal, &loop_increment); | 234 __ j(equal, &loop_increment); |
238 | 235 |
239 // Mismatch, try case-insensitive match (converting letters to lower-case). | 236 // Mismatch, try case-insensitive match (converting letters to lower-case). |
240 __ or_(eax, 0x20); // Convert match character to lower-case. | 237 __ or_(eax, 0x20); // Convert match character to lower-case. |
(...skipping 30 matching lines...) Expand all Loading... |
271 __ pop(edi); | 268 __ pop(edi); |
272 BranchOrBacktrack(no_condition, on_no_match); | 269 BranchOrBacktrack(no_condition, on_no_match); |
273 | 270 |
274 __ bind(&success); | 271 __ bind(&success); |
275 // Restore original value before continuing. | 272 // Restore original value before continuing. |
276 __ pop(backtrack_stackpointer()); | 273 __ pop(backtrack_stackpointer()); |
277 // Drop original value of character position. | 274 // Drop original value of character position. |
278 __ add(esp, Immediate(kPointerSize)); | 275 __ add(esp, Immediate(kPointerSize)); |
279 // Compute new value of character position after the matched part. | 276 // Compute new value of character position after the matched part. |
280 __ sub(edi, esi); | 277 __ sub(edi, esi); |
| 278 if (read_backward) { |
| 279 // Subtract match length if we matched backward. |
| 280 __ add(edi, register_location(start_reg)); |
| 281 __ sub(edi, register_location(start_reg + 1)); |
| 282 } |
281 } else { | 283 } else { |
282 DCHECK(mode_ == UC16); | 284 DCHECK(mode_ == UC16); |
283 // Save registers before calling C function. | 285 // Save registers before calling C function. |
284 __ push(esi); | 286 __ push(esi); |
285 __ push(edi); | 287 __ push(edi); |
286 __ push(backtrack_stackpointer()); | 288 __ push(backtrack_stackpointer()); |
287 __ push(ebx); | 289 __ push(ebx); |
288 | 290 |
289 static const int argument_count = 4; | 291 static const int argument_count = 4; |
290 __ PrepareCallCFunction(argument_count, ecx); | 292 __ PrepareCallCFunction(argument_count, ecx); |
291 // Put arguments into allocated stack area, last argument highest on stack. | 293 // Put arguments into allocated stack area, last argument highest on stack. |
292 // Parameters are | 294 // Parameters are |
293 // Address byte_offset1 - Address captured substring's start. | 295 // Address byte_offset1 - Address captured substring's start. |
294 // Address byte_offset2 - Address of current character position. | 296 // Address byte_offset2 - Address of current character position. |
295 // size_t byte_length - length of capture in bytes(!) | 297 // size_t byte_length - length of capture in bytes(!) |
296 // Isolate* isolate | 298 // Isolate* isolate |
297 | 299 |
298 // Set isolate. | 300 // Set isolate. |
299 __ mov(Operand(esp, 3 * kPointerSize), | 301 __ mov(Operand(esp, 3 * kPointerSize), |
300 Immediate(ExternalReference::isolate_address(isolate()))); | 302 Immediate(ExternalReference::isolate_address(isolate()))); |
301 // Set byte_length. | 303 // Set byte_length. |
302 __ mov(Operand(esp, 2 * kPointerSize), ebx); | 304 __ mov(Operand(esp, 2 * kPointerSize), ebx); |
303 // Set byte_offset2. | 305 // Set byte_offset2. |
304 // Found by adding negative string-end offset of current position (edi) | 306 // Found by adding negative string-end offset of current position (edi) |
305 // to end of string. | 307 // to end of string. |
306 __ add(edi, esi); | 308 __ add(edi, esi); |
| 309 if (read_backward) { |
| 310 __ sub(edi, ebx); // Offset by length when matching backwards. |
| 311 } |
307 __ mov(Operand(esp, 1 * kPointerSize), edi); | 312 __ mov(Operand(esp, 1 * kPointerSize), edi); |
308 // Set byte_offset1. | 313 // Set byte_offset1. |
309 // Start of capture, where edx already holds string-end negative offset. | 314 // Start of capture, where edx already holds string-end negative offset. |
310 __ add(edx, esi); | 315 __ add(edx, esi); |
311 __ mov(Operand(esp, 0 * kPointerSize), edx); | 316 __ mov(Operand(esp, 0 * kPointerSize), edx); |
312 | 317 |
313 { | 318 { |
314 AllowExternalCallThatCantCauseGC scope(masm_); | 319 AllowExternalCallThatCantCauseGC scope(masm_); |
315 ExternalReference compare = | 320 ExternalReference compare = |
316 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 321 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
317 __ CallCFunction(compare, argument_count); | 322 __ CallCFunction(compare, argument_count); |
318 } | 323 } |
319 // Pop original values before reacting on result value. | 324 // Pop original values before reacting on result value. |
320 __ pop(ebx); | 325 __ pop(ebx); |
321 __ pop(backtrack_stackpointer()); | 326 __ pop(backtrack_stackpointer()); |
322 __ pop(edi); | 327 __ pop(edi); |
323 __ pop(esi); | 328 __ pop(esi); |
324 | 329 |
325 // Check if function returned non-zero for success or zero for failure. | 330 // Check if function returned non-zero for success or zero for failure. |
326 __ or_(eax, eax); | 331 __ or_(eax, eax); |
327 BranchOrBacktrack(zero, on_no_match); | 332 BranchOrBacktrack(zero, on_no_match); |
328 // On success, increment position by length of capture. | 333 // On success, advance position by length of capture. |
329 __ add(edi, ebx); | 334 if (read_backward) { |
| 335 __ sub(edi, ebx); |
| 336 } else { |
| 337 __ add(edi, ebx); |
| 338 } |
330 } | 339 } |
331 __ bind(&fallthrough); | 340 __ bind(&fallthrough); |
332 } | 341 } |
333 | 342 |
334 | 343 |
335 void RegExpMacroAssemblerX87::CheckNotBackReference( | 344 void RegExpMacroAssemblerX87::CheckNotBackReference(int start_reg, |
336 int start_reg, | 345 bool read_backward, |
337 Label* on_no_match) { | 346 Label* on_no_match) { |
338 Label fallthrough; | 347 Label fallthrough; |
339 Label success; | 348 Label success; |
340 Label fail; | 349 Label fail; |
341 | 350 |
342 // Find length of back-referenced capture. | 351 // Find length of back-referenced capture. |
343 __ mov(edx, register_location(start_reg)); | 352 __ mov(edx, register_location(start_reg)); |
344 __ mov(eax, register_location(start_reg + 1)); | 353 __ mov(eax, register_location(start_reg + 1)); |
345 __ sub(eax, edx); // Length to check. | 354 __ sub(eax, edx); // Length to check. |
346 // Fail on partial or illegal capture (start of capture after end of capture). | 355 |
347 BranchOrBacktrack(less, on_no_match); | 356 // At this point, the capture registers are either both set or both cleared. |
348 // Succeed on empty capture (including no capture) | 357 // If the capture length is zero, then the capture is either empty or cleared. |
| 358 // Fall through in both cases. |
349 __ j(equal, &fallthrough); | 359 __ j(equal, &fallthrough); |
350 | 360 |
351 // Check that there are sufficient characters left in the input. | 361 // Check that there are sufficient characters left in the input. |
352 __ mov(ebx, edi); | 362 if (read_backward) { |
353 __ add(ebx, eax); | 363 __ mov(ebx, Operand(ebp, kStringStartMinusOne)); |
354 BranchOrBacktrack(greater, on_no_match); | 364 __ add(ebx, eax); |
| 365 __ cmp(edi, ebx); |
| 366 BranchOrBacktrack(less_equal, on_no_match); |
| 367 } else { |
| 368 __ mov(ebx, edi); |
| 369 __ add(ebx, eax); |
| 370 BranchOrBacktrack(greater, on_no_match); |
| 371 } |
355 | 372 |
356 // Save register to make it available below. | 373 // Save register to make it available below. |
357 __ push(backtrack_stackpointer()); | 374 __ push(backtrack_stackpointer()); |
358 | 375 |
359 // Compute pointers to match string and capture string | 376 // Compute pointers to match string and capture string |
| 377 __ add(edx, esi); // Start of capture. |
360 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | 378 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
361 __ add(edx, esi); // Start of capture. | 379 if (read_backward) { |
| 380 __ sub(ebx, eax); // Offset by length when matching backwards. |
| 381 } |
362 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 382 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
363 | 383 |
364 Label loop; | 384 Label loop; |
365 __ bind(&loop); | 385 __ bind(&loop); |
366 if (mode_ == LATIN1) { | 386 if (mode_ == LATIN1) { |
367 __ movzx_b(eax, Operand(edx, 0)); | 387 __ movzx_b(eax, Operand(edx, 0)); |
368 __ cmpb_al(Operand(ebx, 0)); | 388 __ cmpb_al(Operand(ebx, 0)); |
369 } else { | 389 } else { |
370 DCHECK(mode_ == UC16); | 390 DCHECK(mode_ == UC16); |
371 __ movzx_w(eax, Operand(edx, 0)); | 391 __ movzx_w(eax, Operand(edx, 0)); |
(...skipping 10 matching lines...) Expand all Loading... |
382 | 402 |
383 __ bind(&fail); | 403 __ bind(&fail); |
384 // Restore backtrack stackpointer. | 404 // Restore backtrack stackpointer. |
385 __ pop(backtrack_stackpointer()); | 405 __ pop(backtrack_stackpointer()); |
386 BranchOrBacktrack(no_condition, on_no_match); | 406 BranchOrBacktrack(no_condition, on_no_match); |
387 | 407 |
388 __ bind(&success); | 408 __ bind(&success); |
389 // Move current character position to position after match. | 409 // Move current character position to position after match. |
390 __ mov(edi, ecx); | 410 __ mov(edi, ecx); |
391 __ sub(edi, esi); | 411 __ sub(edi, esi); |
| 412 if (read_backward) { |
| 413 // Subtract match length if we matched backward. |
| 414 __ add(edi, register_location(start_reg)); |
| 415 __ sub(edi, register_location(start_reg + 1)); |
| 416 } |
392 // Restore backtrack stackpointer. | 417 // Restore backtrack stackpointer. |
393 __ pop(backtrack_stackpointer()); | 418 __ pop(backtrack_stackpointer()); |
394 | 419 |
395 __ bind(&fallthrough); | 420 __ bind(&fallthrough); |
396 } | 421 } |
397 | 422 |
398 | 423 |
399 void RegExpMacroAssemblerX87::CheckNotCharacter(uint32_t c, | 424 void RegExpMacroAssemblerX87::CheckNotCharacter(uint32_t c, |
400 Label* on_not_equal) { | 425 Label* on_not_equal) { |
401 __ cmp(current_character(), c); | 426 __ cmp(current_character(), c); |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 | 652 |
628 // Actually emit code to start a new stack frame. | 653 // Actually emit code to start a new stack frame. |
629 __ push(ebp); | 654 __ push(ebp); |
630 __ mov(ebp, esp); | 655 __ mov(ebp, esp); |
631 // Save callee-save registers. Order here should correspond to order of | 656 // Save callee-save registers. Order here should correspond to order of |
632 // kBackup_ebx etc. | 657 // kBackup_ebx etc. |
633 __ push(esi); | 658 __ push(esi); |
634 __ push(edi); | 659 __ push(edi); |
635 __ push(ebx); // Callee-save on MacOS. | 660 __ push(ebx); // Callee-save on MacOS. |
636 __ push(Immediate(0)); // Number of successful matches in a global regexp. | 661 __ push(Immediate(0)); // Number of successful matches in a global regexp. |
637 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 662 __ push(Immediate(0)); // Make room for "string start - 1" constant. |
638 | 663 |
639 // Check if we have space on the stack for registers. | 664 // Check if we have space on the stack for registers. |
640 Label stack_limit_hit; | 665 Label stack_limit_hit; |
641 Label stack_ok; | 666 Label stack_ok; |
642 | 667 |
643 ExternalReference stack_limit = | 668 ExternalReference stack_limit = |
644 ExternalReference::address_of_stack_limit(isolate()); | 669 ExternalReference::address_of_stack_limit(isolate()); |
645 __ mov(ecx, esp); | 670 __ mov(ecx, esp); |
646 __ sub(ecx, Operand::StaticVariable(stack_limit)); | 671 __ sub(ecx, Operand::StaticVariable(stack_limit)); |
647 // Handle it if the stack pointer is already below the stack limit. | 672 // Handle it if the stack pointer is already below the stack limit. |
(...skipping 29 matching lines...) Expand all Loading... |
677 // Set eax to address of char before start of the string. | 702 // Set eax to address of char before start of the string. |
678 // (effectively string position -1). | 703 // (effectively string position -1). |
679 __ neg(ebx); | 704 __ neg(ebx); |
680 if (mode_ == UC16) { | 705 if (mode_ == UC16) { |
681 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); | 706 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); |
682 } else { | 707 } else { |
683 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); | 708 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); |
684 } | 709 } |
685 // Store this value in a local variable, for use when clearing | 710 // Store this value in a local variable, for use when clearing |
686 // position registers. | 711 // position registers. |
687 __ mov(Operand(ebp, kInputStartMinusOne), eax); | 712 __ mov(Operand(ebp, kStringStartMinusOne), eax); |
688 | 713 |
689 #if V8_OS_WIN | 714 #if V8_OS_WIN |
690 // Ensure that we write to each stack page, in order. Skipping a page | 715 // Ensure that we write to each stack page, in order. Skipping a page |
691 // on Windows can cause segmentation faults. Assuming page size is 4k. | 716 // on Windows can cause segmentation faults. Assuming page size is 4k. |
692 const int kPageSize = 4096; | 717 const int kPageSize = 4096; |
693 const int kRegistersPerPage = kPageSize / kPointerSize; | 718 const int kRegistersPerPage = kPageSize / kPointerSize; |
694 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 719 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
695 i < num_registers_; | 720 i < num_registers_; |
696 i += kRegistersPerPage) { | 721 i += kRegistersPerPage) { |
697 __ mov(register_location(i), eax); // One write every page. | 722 __ mov(register_location(i), eax); // One write every page. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 // Convert to index from start of string, not end. | 785 // Convert to index from start of string, not end. |
761 __ add(eax, ecx); | 786 __ add(eax, ecx); |
762 if (mode_ == UC16) { | 787 if (mode_ == UC16) { |
763 __ sar(eax, 1); // Convert byte index to character index. | 788 __ sar(eax, 1); // Convert byte index to character index. |
764 } | 789 } |
765 __ mov(Operand(ebx, i * kPointerSize), eax); | 790 __ mov(Operand(ebx, i * kPointerSize), eax); |
766 } | 791 } |
767 } | 792 } |
768 | 793 |
769 if (global()) { | 794 if (global()) { |
770 // Restart matching if the regular expression is flagged as global. | 795 // Restart matching if the regular expression is flagged as global. |
771 // Increment success counter. | 796 // Increment success counter. |
772 __ inc(Operand(ebp, kSuccessfulCaptures)); | 797 __ inc(Operand(ebp, kSuccessfulCaptures)); |
773 // Capture results have been stored, so the number of remaining global | 798 // Capture results have been stored, so the number of remaining global |
774 // output registers is reduced by the number of stored captures. | 799 // output registers is reduced by the number of stored captures. |
775 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); | 800 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); |
776 __ sub(ecx, Immediate(num_saved_registers_)); | 801 __ sub(ecx, Immediate(num_saved_registers_)); |
777 // Check whether we have enough room for another set of capture results. | 802 // Check whether we have enough room for another set of capture results. |
778 __ cmp(ecx, Immediate(num_saved_registers_)); | 803 __ cmp(ecx, Immediate(num_saved_registers_)); |
779 __ j(less, &exit_label_); | 804 __ j(less, &exit_label_); |
780 | 805 |
781 __ mov(Operand(ebp, kNumOutputRegisters), ecx); | 806 __ mov(Operand(ebp, kNumOutputRegisters), ecx); |
782 // Advance the location for output. | 807 // Advance the location for output. |
783 __ add(Operand(ebp, kRegisterOutput), | 808 __ add(Operand(ebp, kRegisterOutput), |
784 Immediate(num_saved_registers_ * kPointerSize)); | 809 Immediate(num_saved_registers_ * kPointerSize)); |
785 | 810 |
786 // Prepare eax to initialize registers with its value in the next run. | 811 // Prepare eax to initialize registers with its value in the next run. |
787 __ mov(eax, Operand(ebp, kInputStartMinusOne)); | 812 __ mov(eax, Operand(ebp, kStringStartMinusOne)); |
788 | 813 |
789 if (global_with_zero_length_check()) { | 814 if (global_with_zero_length_check()) { |
790 // Special case for zero-length matches. | 815 // Special case for zero-length matches. |
791 // edx: capture start index | 816 // edx: capture start index |
792 __ cmp(edi, edx); | 817 __ cmp(edi, edx); |
793 // Not a zero-length match, restart. | 818 // Not a zero-length match, restart. |
794 __ j(not_equal, &load_char_start_regexp); | 819 __ j(not_equal, &load_char_start_regexp); |
795 // edi (offset from the end) is zero if we already reached the end. | 820 // edi (offset from the end) is zero if we already reached the end. |
796 __ test(edi, edi); | 821 __ test(edi, edi); |
797 __ j(zero, &exit_label_, Label::kNear); | 822 __ j(zero, &exit_label_, Label::kNear); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 RegExpMacroAssembler::IrregexpImplementation | 962 RegExpMacroAssembler::IrregexpImplementation |
938 RegExpMacroAssemblerX87::Implementation() { | 963 RegExpMacroAssemblerX87::Implementation() { |
939 return kX87Implementation; | 964 return kX87Implementation; |
940 } | 965 } |
941 | 966 |
942 | 967 |
943 void RegExpMacroAssemblerX87::LoadCurrentCharacter(int cp_offset, | 968 void RegExpMacroAssemblerX87::LoadCurrentCharacter(int cp_offset, |
944 Label* on_end_of_input, | 969 Label* on_end_of_input, |
945 bool check_bounds, | 970 bool check_bounds, |
946 int characters) { | 971 int characters) { |
947 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. | |
948 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 972 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
949 if (check_bounds) { | 973 if (check_bounds) { |
950 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 974 if (cp_offset >= 0) { |
| 975 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 976 } else { |
| 977 CheckPosition(cp_offset, on_end_of_input); |
| 978 } |
951 } | 979 } |
952 LoadCurrentCharacterUnchecked(cp_offset, characters); | 980 LoadCurrentCharacterUnchecked(cp_offset, characters); |
953 } | 981 } |
954 | 982 |
955 | 983 |
956 void RegExpMacroAssemblerX87::PopCurrentPosition() { | 984 void RegExpMacroAssemblerX87::PopCurrentPosition() { |
957 Pop(edi); | 985 Pop(edi); |
958 } | 986 } |
959 | 987 |
960 | 988 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 __ mov(register_location(reg), edi); | 1052 __ mov(register_location(reg), edi); |
1025 } else { | 1053 } else { |
1026 __ lea(eax, Operand(edi, cp_offset * char_size())); | 1054 __ lea(eax, Operand(edi, cp_offset * char_size())); |
1027 __ mov(register_location(reg), eax); | 1055 __ mov(register_location(reg), eax); |
1028 } | 1056 } |
1029 } | 1057 } |
1030 | 1058 |
1031 | 1059 |
1032 void RegExpMacroAssemblerX87::ClearRegisters(int reg_from, int reg_to) { | 1060 void RegExpMacroAssemblerX87::ClearRegisters(int reg_from, int reg_to) { |
1033 DCHECK(reg_from <= reg_to); | 1061 DCHECK(reg_from <= reg_to); |
1034 __ mov(eax, Operand(ebp, kInputStartMinusOne)); | 1062 __ mov(eax, Operand(ebp, kStringStartMinusOne)); |
1035 for (int reg = reg_from; reg <= reg_to; reg++) { | 1063 for (int reg = reg_from; reg <= reg_to; reg++) { |
1036 __ mov(register_location(reg), eax); | 1064 __ mov(register_location(reg), eax); |
1037 } | 1065 } |
1038 } | 1066 } |
1039 | 1067 |
1040 | 1068 |
1041 void RegExpMacroAssemblerX87::WriteStackPointerToRegister(int reg) { | 1069 void RegExpMacroAssemblerX87::WriteStackPointerToRegister(int reg) { |
1042 __ mov(eax, backtrack_stackpointer()); | 1070 __ mov(eax, backtrack_stackpointer()); |
1043 __ sub(eax, Operand(ebp, kStackHighEnd)); | 1071 __ sub(eax, Operand(ebp, kStackHighEnd)); |
1044 __ mov(register_location(reg), eax); | 1072 __ mov(register_location(reg), eax); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 DCHECK(register_index < (1<<30)); | 1121 DCHECK(register_index < (1<<30)); |
1094 if (num_registers_ <= register_index) { | 1122 if (num_registers_ <= register_index) { |
1095 num_registers_ = register_index + 1; | 1123 num_registers_ = register_index + 1; |
1096 } | 1124 } |
1097 return Operand(ebp, kRegisterZero - register_index * kPointerSize); | 1125 return Operand(ebp, kRegisterZero - register_index * kPointerSize); |
1098 } | 1126 } |
1099 | 1127 |
1100 | 1128 |
1101 void RegExpMacroAssemblerX87::CheckPosition(int cp_offset, | 1129 void RegExpMacroAssemblerX87::CheckPosition(int cp_offset, |
1102 Label* on_outside_input) { | 1130 Label* on_outside_input) { |
1103 __ cmp(edi, -cp_offset * char_size()); | 1131 if (cp_offset >= 0) { |
1104 BranchOrBacktrack(greater_equal, on_outside_input); | 1132 __ cmp(edi, -cp_offset * char_size()); |
| 1133 BranchOrBacktrack(greater_equal, on_outside_input); |
| 1134 } else { |
| 1135 __ lea(eax, Operand(edi, cp_offset * char_size())); |
| 1136 __ cmp(eax, Operand(ebp, kStringStartMinusOne)); |
| 1137 BranchOrBacktrack(less_equal, on_outside_input); |
| 1138 } |
1105 } | 1139 } |
1106 | 1140 |
1107 | 1141 |
1108 void RegExpMacroAssemblerX87::BranchOrBacktrack(Condition condition, | 1142 void RegExpMacroAssemblerX87::BranchOrBacktrack(Condition condition, |
1109 Label* to) { | 1143 Label* to) { |
1110 if (condition < 0) { // No condition | 1144 if (condition < 0) { // No condition |
1111 if (to == NULL) { | 1145 if (to == NULL) { |
1112 Backtrack(); | 1146 Backtrack(); |
1113 return; | 1147 return; |
1114 } | 1148 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1219 | 1253 |
1220 | 1254 |
1221 #undef __ | 1255 #undef __ |
1222 | 1256 |
1223 #endif // V8_INTERPRETED_REGEXP | 1257 #endif // V8_INTERPRETED_REGEXP |
1224 | 1258 |
1225 } // namespace internal | 1259 } // namespace internal |
1226 } // namespace v8 | 1260 } // namespace v8 |
1227 | 1261 |
1228 #endif // V8_TARGET_ARCH_X87 | 1262 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |