Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: src/regexp/ia32/regexp-macro-assembler-ia32.cc

Issue 1418963009: Experimental support for RegExp lookbehind. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressed comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_IA32 5 #if V8_TARGET_ARCH_IA32
6 6
7 #include "src/regexp/ia32/regexp-macro-assembler-ia32.h" 7 #include "src/regexp/ia32/regexp-macro-assembler-ia32.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
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
149 } 150 }
150 151
151 152
152 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { 153 void RegExpMacroAssemblerIA32::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 RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { 159 void RegExpMacroAssemblerIA32::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, &not_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(&not_at_start);
168 } 163 }
169 164
170 165
171 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { 166 void RegExpMacroAssemblerIA32::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 RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { 174 void RegExpMacroAssemblerIA32::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 RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 180 void RegExpMacroAssemblerIA32::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 RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 190 void RegExpMacroAssemblerIA32::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 // The length of the capture can only be negative if the end of the
207 // if the end of the capture is unrecorded, or at a point earlier than 198 // capture is not yet recorded. If the length is zero, the capture is
208 // the start of the capture. 199 // either empty or uncaptured. In either of those cases, succeed.
209 BranchOrBacktrack(less, on_no_match); 200 __ j(less_equal, &fallthrough);
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);
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, edi);
218 BranchOrBacktrack(greater, on_no_match); 205 __ sub(eax, ebx);
206 __ cmp(eax, Operand(ebp, kStringStartMinusOne));
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
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 RegExpMacroAssemblerIA32::CheckNotBackReference( 344 void RegExpMacroAssemblerIA32::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 // The length of the capture can only be negative if the end of the
347 BranchOrBacktrack(less, on_no_match); 356 // capture is not yet recorded. If the length is zero, the capture is
348 // Succeed on empty capture (including no capture) 357 // either empty or uncaptured. In either of those cases, succeed.
349 __ j(equal, &fallthrough); 358 __ j(less_equal, &fallthrough);
350 359
351 // Check that there are sufficient characters left in the input. 360 // Check that there are sufficient characters left in the input.
352 __ mov(ebx, edi); 361 if (read_backward) {
353 __ add(ebx, eax); 362 __ mov(ebx, edi);
354 BranchOrBacktrack(greater, on_no_match); 363 __ sub(ebx, eax);
364 __ cmp(ebx, Operand(ebp, kStringStartMinusOne));
365 BranchOrBacktrack(less_equal, on_no_match);
366 } else {
367 __ mov(ebx, edi);
368 __ add(ebx, eax);
369 BranchOrBacktrack(greater, on_no_match);
370 }
355 371
356 // Save register to make it available below. 372 // Save register to make it available below.
357 __ push(backtrack_stackpointer()); 373 __ push(backtrack_stackpointer());
358 374
359 // Compute pointers to match string and capture string 375 // Compute pointers to match string and capture string
376 __ add(edx, esi); // Start of capture.
360 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. 377 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match.
361 __ add(edx, esi); // Start of capture. 378 if (read_backward) {
379 __ sub(ebx, eax); // Offset by length when matching backwards.
380 }
362 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match 381 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match
363 382
364 Label loop; 383 Label loop;
365 __ bind(&loop); 384 __ bind(&loop);
366 if (mode_ == LATIN1) { 385 if (mode_ == LATIN1) {
367 __ movzx_b(eax, Operand(edx, 0)); 386 __ movzx_b(eax, Operand(edx, 0));
368 __ cmpb_al(Operand(ebx, 0)); 387 __ cmpb_al(Operand(ebx, 0));
369 } else { 388 } else {
370 DCHECK(mode_ == UC16); 389 DCHECK(mode_ == UC16);
371 __ movzx_w(eax, Operand(edx, 0)); 390 __ movzx_w(eax, Operand(edx, 0));
(...skipping 10 matching lines...) Expand all
382 401
383 __ bind(&fail); 402 __ bind(&fail);
384 // Restore backtrack stackpointer. 403 // Restore backtrack stackpointer.
385 __ pop(backtrack_stackpointer()); 404 __ pop(backtrack_stackpointer());
386 BranchOrBacktrack(no_condition, on_no_match); 405 BranchOrBacktrack(no_condition, on_no_match);
387 406
388 __ bind(&success); 407 __ bind(&success);
389 // Move current character position to position after match. 408 // Move current character position to position after match.
390 __ mov(edi, ecx); 409 __ mov(edi, ecx);
391 __ sub(edi, esi); 410 __ sub(edi, esi);
411 if (read_backward) {
412 // Subtract match length if we matched backward.
413 __ add(edi, register_location(start_reg));
414 __ sub(edi, register_location(start_reg + 1));
415 }
392 // Restore backtrack stackpointer. 416 // Restore backtrack stackpointer.
393 __ pop(backtrack_stackpointer()); 417 __ pop(backtrack_stackpointer());
394 418
395 __ bind(&fallthrough); 419 __ bind(&fallthrough);
396 } 420 }
397 421
398 422
399 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, 423 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
400 Label* on_not_equal) { 424 Label* on_not_equal) {
401 __ cmp(current_character(), c); 425 __ cmp(current_character(), c);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 651
628 // Actually emit code to start a new stack frame. 652 // Actually emit code to start a new stack frame.
629 __ push(ebp); 653 __ push(ebp);
630 __ mov(ebp, esp); 654 __ mov(ebp, esp);
631 // Save callee-save registers. Order here should correspond to order of 655 // Save callee-save registers. Order here should correspond to order of
632 // kBackup_ebx etc. 656 // kBackup_ebx etc.
633 __ push(esi); 657 __ push(esi);
634 __ push(edi); 658 __ push(edi);
635 __ push(ebx); // Callee-save on MacOS. 659 __ push(ebx); // Callee-save on MacOS.
636 __ push(Immediate(0)); // Number of successful matches in a global regexp. 660 __ push(Immediate(0)); // Number of successful matches in a global regexp.
637 __ push(Immediate(0)); // Make room for "input start - 1" constant. 661 __ push(Immediate(0)); // Make room for "string start - 1" constant.
638 662
639 // Check if we have space on the stack for registers. 663 // Check if we have space on the stack for registers.
640 Label stack_limit_hit; 664 Label stack_limit_hit;
641 Label stack_ok; 665 Label stack_ok;
642 666
643 ExternalReference stack_limit = 667 ExternalReference stack_limit =
644 ExternalReference::address_of_stack_limit(isolate()); 668 ExternalReference::address_of_stack_limit(isolate());
645 __ mov(ecx, esp); 669 __ mov(ecx, esp);
646 __ sub(ecx, Operand::StaticVariable(stack_limit)); 670 __ sub(ecx, Operand::StaticVariable(stack_limit));
647 // Handle it if the stack pointer is already below the stack limit. 671 // Handle it if the stack pointer is already below the stack limit.
(...skipping 29 matching lines...) Expand all
677 // Set eax to address of char before start of the string. 701 // Set eax to address of char before start of the string.
678 // (effectively string position -1). 702 // (effectively string position -1).
679 __ neg(ebx); 703 __ neg(ebx);
680 if (mode_ == UC16) { 704 if (mode_ == UC16) {
681 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); 705 __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
682 } else { 706 } else {
683 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); 707 __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
684 } 708 }
685 // Store this value in a local variable, for use when clearing 709 // Store this value in a local variable, for use when clearing
686 // position registers. 710 // position registers.
687 __ mov(Operand(ebp, kInputStartMinusOne), eax); 711 __ mov(Operand(ebp, kStringStartMinusOne), eax);
688 712
689 #if V8_OS_WIN 713 #if V8_OS_WIN
690 // Ensure that we write to each stack page, in order. Skipping a page 714 // 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. 715 // on Windows can cause segmentation faults. Assuming page size is 4k.
692 const int kPageSize = 4096; 716 const int kPageSize = 4096;
693 const int kRegistersPerPage = kPageSize / kPointerSize; 717 const int kRegistersPerPage = kPageSize / kPointerSize;
694 for (int i = num_saved_registers_ + kRegistersPerPage - 1; 718 for (int i = num_saved_registers_ + kRegistersPerPage - 1;
695 i < num_registers_; 719 i < num_registers_;
696 i += kRegistersPerPage) { 720 i += kRegistersPerPage) {
697 __ mov(register_location(i), eax); // One write every page. 721 __ mov(register_location(i), eax); // One write every page.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 // Convert to index from start of string, not end. 784 // Convert to index from start of string, not end.
761 __ add(eax, ecx); 785 __ add(eax, ecx);
762 if (mode_ == UC16) { 786 if (mode_ == UC16) {
763 __ sar(eax, 1); // Convert byte index to character index. 787 __ sar(eax, 1); // Convert byte index to character index.
764 } 788 }
765 __ mov(Operand(ebx, i * kPointerSize), eax); 789 __ mov(Operand(ebx, i * kPointerSize), eax);
766 } 790 }
767 } 791 }
768 792
769 if (global()) { 793 if (global()) {
770 // Restart matching if the regular expression is flagged as global. 794 // Restart matching if the regular expression is flagged as global.
771 // Increment success counter. 795 // Increment success counter.
772 __ inc(Operand(ebp, kSuccessfulCaptures)); 796 __ inc(Operand(ebp, kSuccessfulCaptures));
773 // Capture results have been stored, so the number of remaining global 797 // Capture results have been stored, so the number of remaining global
774 // output registers is reduced by the number of stored captures. 798 // output registers is reduced by the number of stored captures.
775 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); 799 __ mov(ecx, Operand(ebp, kNumOutputRegisters));
776 __ sub(ecx, Immediate(num_saved_registers_)); 800 __ sub(ecx, Immediate(num_saved_registers_));
777 // Check whether we have enough room for another set of capture results. 801 // Check whether we have enough room for another set of capture results.
778 __ cmp(ecx, Immediate(num_saved_registers_)); 802 __ cmp(ecx, Immediate(num_saved_registers_));
779 __ j(less, &exit_label_); 803 __ j(less, &exit_label_);
780 804
781 __ mov(Operand(ebp, kNumOutputRegisters), ecx); 805 __ mov(Operand(ebp, kNumOutputRegisters), ecx);
782 // Advance the location for output. 806 // Advance the location for output.
783 __ add(Operand(ebp, kRegisterOutput), 807 __ add(Operand(ebp, kRegisterOutput),
784 Immediate(num_saved_registers_ * kPointerSize)); 808 Immediate(num_saved_registers_ * kPointerSize));
785 809
786 // Prepare eax to initialize registers with its value in the next run. 810 // Prepare eax to initialize registers with its value in the next run.
787 __ mov(eax, Operand(ebp, kInputStartMinusOne)); 811 __ mov(eax, Operand(ebp, kStringStartMinusOne));
788 812
789 if (global_with_zero_length_check()) { 813 if (global_with_zero_length_check()) {
790 // Special case for zero-length matches. 814 // Special case for zero-length matches.
791 // edx: capture start index 815 // edx: capture start index
792 __ cmp(edi, edx); 816 __ cmp(edi, edx);
793 // Not a zero-length match, restart. 817 // Not a zero-length match, restart.
794 __ j(not_equal, &load_char_start_regexp); 818 __ j(not_equal, &load_char_start_regexp);
795 // edi (offset from the end) is zero if we already reached the end. 819 // edi (offset from the end) is zero if we already reached the end.
796 __ test(edi, edi); 820 __ test(edi, edi);
797 __ j(zero, &exit_label_, Label::kNear); 821 __ j(zero, &exit_label_, Label::kNear);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 RegExpMacroAssembler::IrregexpImplementation 961 RegExpMacroAssembler::IrregexpImplementation
938 RegExpMacroAssemblerIA32::Implementation() { 962 RegExpMacroAssemblerIA32::Implementation() {
939 return kIA32Implementation; 963 return kIA32Implementation;
940 } 964 }
941 965
942 966
943 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, 967 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
944 Label* on_end_of_input, 968 Label* on_end_of_input,
945 bool check_bounds, 969 bool check_bounds,
946 int characters) { 970 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) 971 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
949 if (check_bounds) { 972 if (check_bounds) {
950 CheckPosition(cp_offset + characters - 1, on_end_of_input); 973 if (cp_offset >= 0) {
974 CheckPosition(cp_offset + characters - 1, on_end_of_input);
975 } else {
976 CheckPosition(cp_offset, on_end_of_input);
977 }
951 } 978 }
952 LoadCurrentCharacterUnchecked(cp_offset, characters); 979 LoadCurrentCharacterUnchecked(cp_offset, characters);
953 } 980 }
954 981
955 982
956 void RegExpMacroAssemblerIA32::PopCurrentPosition() { 983 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
957 Pop(edi); 984 Pop(edi);
958 } 985 }
959 986
960 987
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 __ mov(register_location(reg), edi); 1051 __ mov(register_location(reg), edi);
1025 } else { 1052 } else {
1026 __ lea(eax, Operand(edi, cp_offset * char_size())); 1053 __ lea(eax, Operand(edi, cp_offset * char_size()));
1027 __ mov(register_location(reg), eax); 1054 __ mov(register_location(reg), eax);
1028 } 1055 }
1029 } 1056 }
1030 1057
1031 1058
1032 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { 1059 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
1033 DCHECK(reg_from <= reg_to); 1060 DCHECK(reg_from <= reg_to);
1034 __ mov(eax, Operand(ebp, kInputStartMinusOne)); 1061 __ mov(eax, Operand(ebp, kStringStartMinusOne));
1035 for (int reg = reg_from; reg <= reg_to; reg++) { 1062 for (int reg = reg_from; reg <= reg_to; reg++) {
1036 __ mov(register_location(reg), eax); 1063 __ mov(register_location(reg), eax);
1037 } 1064 }
1038 } 1065 }
1039 1066
1040 1067
1041 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 1068 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
1042 __ mov(eax, backtrack_stackpointer()); 1069 __ mov(eax, backtrack_stackpointer());
1043 __ sub(eax, Operand(ebp, kStackHighEnd)); 1070 __ sub(eax, Operand(ebp, kStackHighEnd));
1044 __ mov(register_location(reg), eax); 1071 __ mov(register_location(reg), eax);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1093 DCHECK(register_index < (1<<30)); 1120 DCHECK(register_index < (1<<30));
1094 if (num_registers_ <= register_index) { 1121 if (num_registers_ <= register_index) {
1095 num_registers_ = register_index + 1; 1122 num_registers_ = register_index + 1;
1096 } 1123 }
1097 return Operand(ebp, kRegisterZero - register_index * kPointerSize); 1124 return Operand(ebp, kRegisterZero - register_index * kPointerSize);
1098 } 1125 }
1099 1126
1100 1127
1101 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1128 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
1102 Label* on_outside_input) { 1129 Label* on_outside_input) {
1103 __ cmp(edi, -cp_offset * char_size()); 1130 if (cp_offset >= 0) {
1104 BranchOrBacktrack(greater_equal, on_outside_input); 1131 __ cmp(edi, -cp_offset * char_size());
1132 BranchOrBacktrack(greater_equal, on_outside_input);
1133 } else {
1134 __ lea(eax, Operand(edi, cp_offset * char_size()));
1135 __ cmp(eax, Operand(ebp, kStringStartMinusOne));
1136 BranchOrBacktrack(less_equal, on_outside_input);
1137 }
1105 } 1138 }
1106 1139
1107 1140
1108 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1141 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
1109 Label* to) { 1142 Label* to) {
1110 if (condition < 0) { // No condition 1143 if (condition < 0) { // No condition
1111 if (to == NULL) { 1144 if (to == NULL) {
1112 Backtrack(); 1145 Backtrack();
1113 return; 1146 return;
1114 } 1147 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 1252
1220 1253
1221 #undef __ 1254 #undef __
1222 1255
1223 #endif // V8_INTERPRETED_REGEXP 1256 #endif // V8_INTERPRETED_REGEXP
1224 1257
1225 } // namespace internal 1258 } // namespace internal
1226 } // namespace v8 1259 } // namespace v8
1227 1260
1228 #endif // V8_TARGET_ARCH_IA32 1261 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698