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

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

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2008-2009 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 } 127 }
128 128
129 129
130 int RegExpMacroAssemblerIA32::stack_limit_slack() { 130 int RegExpMacroAssemblerIA32::stack_limit_slack() {
131 return RegExpStack::kStackLimitSlack; 131 return RegExpStack::kStackLimitSlack;
132 } 132 }
133 133
134 134
135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 135 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
136 if (by != 0) { 136 if (by != 0) {
137 __ add(Operand(edi), Immediate(by * char_size())); 137 __ add(edi, Immediate(by * char_size()));
138 } 138 }
139 } 139 }
140 140
141 141
142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 142 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
143 ASSERT(reg >= 0); 143 ASSERT(reg >= 0);
144 ASSERT(reg < num_registers_); 144 ASSERT(reg < num_registers_);
145 if (by != 0) { 145 if (by != 0) {
146 __ add(register_location(reg), Immediate(by)); 146 __ add(register_location(reg), Immediate(by));
147 } 147 }
148 } 148 }
149 149
150 150
151 void RegExpMacroAssemblerIA32::Backtrack() { 151 void RegExpMacroAssemblerIA32::Backtrack() {
152 CheckPreemption(); 152 CheckPreemption();
153 // Pop Code* offset from backtrack stack, add Code* and jump to location. 153 // Pop Code* offset from backtrack stack, add Code* and jump to location.
154 Pop(ebx); 154 Pop(ebx);
155 __ add(Operand(ebx), Immediate(masm_->CodeObject())); 155 __ add(ebx, Immediate(masm_->CodeObject()));
156 __ jmp(Operand(ebx)); 156 __ jmp(ebx);
157 } 157 }
158 158
159 159
160 void RegExpMacroAssemblerIA32::Bind(Label* label) { 160 void RegExpMacroAssemblerIA32::Bind(Label* label) {
161 __ bind(label); 161 __ bind(label);
162 } 162 }
163 163
164 164
165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { 165 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
166 __ cmp(current_character(), c); 166 __ cmp(current_character(), c);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 // If input is ASCII, don't even bother calling here if the string to 212 // If input is ASCII, don't even bother calling here if the string to
213 // match contains a non-ascii character. 213 // match contains a non-ascii character.
214 if (mode_ == ASCII) { 214 if (mode_ == ASCII) {
215 ASSERT(String::IsAscii(str.start(), str.length())); 215 ASSERT(String::IsAscii(str.start(), str.length()));
216 } 216 }
217 #endif 217 #endif
218 int byte_length = str.length() * char_size(); 218 int byte_length = str.length() * char_size();
219 int byte_offset = cp_offset * char_size(); 219 int byte_offset = cp_offset * char_size();
220 if (check_end_of_string) { 220 if (check_end_of_string) {
221 // Check that there are at least str.length() characters left in the input. 221 // Check that there are at least str.length() characters left in the input.
222 __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); 222 __ cmp(edi, Immediate(-(byte_offset + byte_length)));
223 BranchOrBacktrack(greater, on_failure); 223 BranchOrBacktrack(greater, on_failure);
224 } 224 }
225 225
226 if (on_failure == NULL) { 226 if (on_failure == NULL) {
227 // Instead of inlining a backtrack, (re)use the global backtrack target. 227 // Instead of inlining a backtrack, (re)use the global backtrack target.
228 on_failure = &backtrack_label_; 228 on_failure = &backtrack_label_;
229 } 229 }
230 230
231 // Do one character test first to minimize loading for the case that 231 // Do one character test first to minimize loading for the case that
232 // we don't match at all (loading more than one character introduces that 232 // we don't match at all (loading more than one character introduces that
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 } 281 }
282 BranchOrBacktrack(not_equal, on_failure); 282 BranchOrBacktrack(not_equal, on_failure);
283 } 283 }
284 } 284 }
285 285
286 286
287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 287 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
288 Label fallthrough; 288 Label fallthrough;
289 __ cmp(edi, Operand(backtrack_stackpointer(), 0)); 289 __ cmp(edi, Operand(backtrack_stackpointer(), 0));
290 __ j(not_equal, &fallthrough); 290 __ j(not_equal, &fallthrough);
291 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); // Pop. 291 __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop.
292 BranchOrBacktrack(no_condition, on_equal); 292 BranchOrBacktrack(no_condition, on_equal);
293 __ bind(&fallthrough); 293 __ bind(&fallthrough);
294 } 294 }
295 295
296 296
297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 297 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
298 int start_reg, 298 int start_reg,
299 Label* on_no_match) { 299 Label* on_no_match) {
300 Label fallthrough; 300 Label fallthrough;
301 __ mov(edx, register_location(start_reg)); // Index of start of capture 301 __ mov(edx, register_location(start_reg)); // Index of start of capture
302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture 302 __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture
303 __ sub(ebx, Operand(edx)); // Length of capture. 303 __ sub(ebx, edx); // Length of capture.
304 304
305 // The length of a capture should not be negative. This can only happen 305 // The length of a capture should not be negative. This can only happen
306 // if the end of the capture is unrecorded, or at a point earlier than 306 // if the end of the capture is unrecorded, or at a point earlier than
307 // the start of the capture. 307 // the start of the capture.
308 BranchOrBacktrack(less, on_no_match); 308 BranchOrBacktrack(less, on_no_match);
309 309
310 // If length is zero, either the capture is empty or it is completely 310 // If length is zero, either the capture is empty or it is completely
311 // uncaptured. In either case succeed immediately. 311 // uncaptured. In either case succeed immediately.
312 __ j(equal, &fallthrough); 312 __ j(equal, &fallthrough);
313 313
314 if (mode_ == ASCII) { 314 if (mode_ == ASCII) {
315 Label success; 315 Label success;
316 Label fail; 316 Label fail;
317 Label loop_increment; 317 Label loop_increment;
318 // Save register contents to make the registers available below. 318 // Save register contents to make the registers available below.
319 __ push(edi); 319 __ push(edi);
320 __ push(backtrack_stackpointer()); 320 __ push(backtrack_stackpointer());
321 // After this, the eax, ecx, and edi registers are available. 321 // After this, the eax, ecx, and edi registers are available.
322 322
323 __ add(edx, Operand(esi)); // Start of capture 323 __ add(edx, esi); // Start of capture
324 __ add(edi, Operand(esi)); // Start of text to match against capture. 324 __ add(edi, esi); // Start of text to match against capture.
325 __ add(ebx, Operand(edi)); // End of text to match against capture. 325 __ add(ebx, edi); // End of text to match against capture.
326 326
327 Label loop; 327 Label loop;
328 __ bind(&loop); 328 __ bind(&loop);
329 __ movzx_b(eax, Operand(edi, 0)); 329 __ movzx_b(eax, Operand(edi, 0));
330 __ cmpb_al(Operand(edx, 0)); 330 __ cmpb_al(Operand(edx, 0));
331 __ j(equal, &loop_increment); 331 __ j(equal, &loop_increment);
332 332
333 // Mismatch, try case-insensitive match (converting letters to lower-case). 333 // Mismatch, try case-insensitive match (converting letters to lower-case).
334 __ or_(eax, 0x20); // Convert match character to lower-case. 334 __ or_(eax, 0x20); // Convert match character to lower-case.
335 __ lea(ecx, Operand(eax, -'a')); 335 __ lea(ecx, Operand(eax, -'a'));
336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? 336 __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter?
337 __ j(above, &fail); 337 __ j(above, &fail);
338 // Also convert capture character. 338 // Also convert capture character.
339 __ movzx_b(ecx, Operand(edx, 0)); 339 __ movzx_b(ecx, Operand(edx, 0));
340 __ or_(ecx, 0x20); 340 __ or_(ecx, 0x20);
341 341
342 __ cmp(eax, Operand(ecx)); 342 __ cmp(eax, ecx);
343 __ j(not_equal, &fail); 343 __ j(not_equal, &fail);
344 344
345 __ bind(&loop_increment); 345 __ bind(&loop_increment);
346 // Increment pointers into match and capture strings. 346 // Increment pointers into match and capture strings.
347 __ add(Operand(edx), Immediate(1)); 347 __ add(edx, Immediate(1));
348 __ add(Operand(edi), Immediate(1)); 348 __ add(edi, Immediate(1));
349 // Compare to end of match, and loop if not done. 349 // Compare to end of match, and loop if not done.
350 __ cmp(edi, Operand(ebx)); 350 __ cmp(edi, ebx);
351 __ j(below, &loop); 351 __ j(below, &loop);
352 __ jmp(&success); 352 __ jmp(&success);
353 353
354 __ bind(&fail); 354 __ bind(&fail);
355 // Restore original values before failing. 355 // Restore original values before failing.
356 __ pop(backtrack_stackpointer()); 356 __ pop(backtrack_stackpointer());
357 __ pop(edi); 357 __ pop(edi);
358 BranchOrBacktrack(no_condition, on_no_match); 358 BranchOrBacktrack(no_condition, on_no_match);
359 359
360 __ bind(&success); 360 __ bind(&success);
361 // Restore original value before continuing. 361 // Restore original value before continuing.
362 __ pop(backtrack_stackpointer()); 362 __ pop(backtrack_stackpointer());
363 // Drop original value of character position. 363 // Drop original value of character position.
364 __ add(Operand(esp), Immediate(kPointerSize)); 364 __ add(esp, Immediate(kPointerSize));
365 // Compute new value of character position after the matched part. 365 // Compute new value of character position after the matched part.
366 __ sub(edi, Operand(esi)); 366 __ sub(edi, esi);
367 } else { 367 } else {
368 ASSERT(mode_ == UC16); 368 ASSERT(mode_ == UC16);
369 // Save registers before calling C function. 369 // Save registers before calling C function.
370 __ push(esi); 370 __ push(esi);
371 __ push(edi); 371 __ push(edi);
372 __ push(backtrack_stackpointer()); 372 __ push(backtrack_stackpointer());
373 __ push(ebx); 373 __ push(ebx);
374 374
375 static const int argument_count = 4; 375 static const int argument_count = 4;
376 __ PrepareCallCFunction(argument_count, ecx); 376 __ PrepareCallCFunction(argument_count, ecx);
377 // Put arguments into allocated stack area, last argument highest on stack. 377 // Put arguments into allocated stack area, last argument highest on stack.
378 // Parameters are 378 // Parameters are
379 // Address byte_offset1 - Address captured substring's start. 379 // Address byte_offset1 - Address captured substring's start.
380 // Address byte_offset2 - Address of current character position. 380 // Address byte_offset2 - Address of current character position.
381 // size_t byte_length - length of capture in bytes(!) 381 // size_t byte_length - length of capture in bytes(!)
382 // Isolate* isolate 382 // Isolate* isolate
383 383
384 // Set isolate. 384 // Set isolate.
385 __ mov(Operand(esp, 3 * kPointerSize), 385 __ mov(Operand(esp, 3 * kPointerSize),
386 Immediate(ExternalReference::isolate_address())); 386 Immediate(ExternalReference::isolate_address()));
387 // Set byte_length. 387 // Set byte_length.
388 __ mov(Operand(esp, 2 * kPointerSize), ebx); 388 __ mov(Operand(esp, 2 * kPointerSize), ebx);
389 // Set byte_offset2. 389 // Set byte_offset2.
390 // Found by adding negative string-end offset of current position (edi) 390 // Found by adding negative string-end offset of current position (edi)
391 // to end of string. 391 // to end of string.
392 __ add(edi, Operand(esi)); 392 __ add(edi, esi);
393 __ mov(Operand(esp, 1 * kPointerSize), edi); 393 __ mov(Operand(esp, 1 * kPointerSize), edi);
394 // Set byte_offset1. 394 // Set byte_offset1.
395 // Start of capture, where edx already holds string-end negative offset. 395 // Start of capture, where edx already holds string-end negative offset.
396 __ add(edx, Operand(esi)); 396 __ add(edx, esi);
397 __ mov(Operand(esp, 0 * kPointerSize), edx); 397 __ mov(Operand(esp, 0 * kPointerSize), edx);
398 398
399 ExternalReference compare = 399 {
400 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 400 AllowExternalCallThatCantCauseGC scope(masm_);
401 __ CallCFunction(compare, argument_count); 401 ExternalReference compare =
402 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
403 __ CallCFunction(compare, argument_count);
404 }
402 // Pop original values before reacting on result value. 405 // Pop original values before reacting on result value.
403 __ pop(ebx); 406 __ pop(ebx);
404 __ pop(backtrack_stackpointer()); 407 __ pop(backtrack_stackpointer());
405 __ pop(edi); 408 __ pop(edi);
406 __ pop(esi); 409 __ pop(esi);
407 410
408 // Check if function returned non-zero for success or zero for failure. 411 // Check if function returned non-zero for success or zero for failure.
409 __ or_(eax, Operand(eax)); 412 __ or_(eax, eax);
410 BranchOrBacktrack(zero, on_no_match); 413 BranchOrBacktrack(zero, on_no_match);
411 // On success, increment position by length of capture. 414 // On success, increment position by length of capture.
412 __ add(edi, Operand(ebx)); 415 __ add(edi, ebx);
413 } 416 }
414 __ bind(&fallthrough); 417 __ bind(&fallthrough);
415 } 418 }
416 419
417 420
418 void RegExpMacroAssemblerIA32::CheckNotBackReference( 421 void RegExpMacroAssemblerIA32::CheckNotBackReference(
419 int start_reg, 422 int start_reg,
420 Label* on_no_match) { 423 Label* on_no_match) {
421 Label fallthrough; 424 Label fallthrough;
422 Label success; 425 Label success;
423 Label fail; 426 Label fail;
424 427
425 // Find length of back-referenced capture. 428 // Find length of back-referenced capture.
426 __ mov(edx, register_location(start_reg)); 429 __ mov(edx, register_location(start_reg));
427 __ mov(eax, register_location(start_reg + 1)); 430 __ mov(eax, register_location(start_reg + 1));
428 __ sub(eax, Operand(edx)); // Length to check. 431 __ sub(eax, edx); // Length to check.
429 // Fail on partial or illegal capture (start of capture after end of capture). 432 // Fail on partial or illegal capture (start of capture after end of capture).
430 BranchOrBacktrack(less, on_no_match); 433 BranchOrBacktrack(less, on_no_match);
431 // Succeed on empty capture (including no capture) 434 // Succeed on empty capture (including no capture)
432 __ j(equal, &fallthrough); 435 __ j(equal, &fallthrough);
433 436
434 // Check that there are sufficient characters left in the input. 437 // Check that there are sufficient characters left in the input.
435 __ mov(ebx, edi); 438 __ mov(ebx, edi);
436 __ add(ebx, Operand(eax)); 439 __ add(ebx, eax);
437 BranchOrBacktrack(greater, on_no_match); 440 BranchOrBacktrack(greater, on_no_match);
438 441
439 // Save register to make it available below. 442 // Save register to make it available below.
440 __ push(backtrack_stackpointer()); 443 __ push(backtrack_stackpointer());
441 444
442 // Compute pointers to match string and capture string 445 // Compute pointers to match string and capture string
443 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. 446 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match.
444 __ add(edx, Operand(esi)); // Start of capture. 447 __ add(edx, esi); // Start of capture.
445 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match 448 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match
446 449
447 Label loop; 450 Label loop;
448 __ bind(&loop); 451 __ bind(&loop);
449 if (mode_ == ASCII) { 452 if (mode_ == ASCII) {
450 __ movzx_b(eax, Operand(edx, 0)); 453 __ movzx_b(eax, Operand(edx, 0));
451 __ cmpb_al(Operand(ebx, 0)); 454 __ cmpb_al(Operand(ebx, 0));
452 } else { 455 } else {
453 ASSERT(mode_ == UC16); 456 ASSERT(mode_ == UC16);
454 __ movzx_w(eax, Operand(edx, 0)); 457 __ movzx_w(eax, Operand(edx, 0));
455 __ cmpw_ax(Operand(ebx, 0)); 458 __ cmpw_ax(Operand(ebx, 0));
456 } 459 }
457 __ j(not_equal, &fail); 460 __ j(not_equal, &fail);
458 // Increment pointers into capture and match string. 461 // Increment pointers into capture and match string.
459 __ add(Operand(edx), Immediate(char_size())); 462 __ add(edx, Immediate(char_size()));
460 __ add(Operand(ebx), Immediate(char_size())); 463 __ add(ebx, Immediate(char_size()));
461 // Check if we have reached end of match area. 464 // Check if we have reached end of match area.
462 __ cmp(ebx, Operand(ecx)); 465 __ cmp(ebx, ecx);
463 __ j(below, &loop); 466 __ j(below, &loop);
464 __ jmp(&success); 467 __ jmp(&success);
465 468
466 __ bind(&fail); 469 __ bind(&fail);
467 // Restore backtrack stackpointer. 470 // Restore backtrack stackpointer.
468 __ pop(backtrack_stackpointer()); 471 __ pop(backtrack_stackpointer());
469 BranchOrBacktrack(no_condition, on_no_match); 472 BranchOrBacktrack(no_condition, on_no_match);
470 473
471 __ bind(&success); 474 __ bind(&success);
472 // Move current character position to position after match. 475 // Move current character position to position after match.
473 __ mov(edi, ecx); 476 __ mov(edi, ecx);
474 __ sub(Operand(edi), esi); 477 __ sub(edi, esi);
475 // Restore backtrack stackpointer. 478 // Restore backtrack stackpointer.
476 __ pop(backtrack_stackpointer()); 479 __ pop(backtrack_stackpointer());
477 480
478 __ bind(&fallthrough); 481 __ bind(&fallthrough);
479 } 482 }
480 483
481 484
482 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, 485 void RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1,
483 int reg2, 486 int reg2,
484 Label* on_not_equal) { 487 Label* on_not_equal) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 BranchOrBacktrack(above, on_no_match); 570 BranchOrBacktrack(above, on_no_match);
568 return true; 571 return true;
569 case 'D': 572 case 'D':
570 // Match non ASCII-digits 573 // Match non ASCII-digits
571 __ lea(eax, Operand(current_character(), -'0')); 574 __ lea(eax, Operand(current_character(), -'0'));
572 __ cmp(eax, '9' - '0'); 575 __ cmp(eax, '9' - '0');
573 BranchOrBacktrack(below_equal, on_no_match); 576 BranchOrBacktrack(below_equal, on_no_match);
574 return true; 577 return true;
575 case '.': { 578 case '.': {
576 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 579 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
577 __ mov(Operand(eax), current_character()); 580 __ mov(eax, current_character());
578 __ xor_(Operand(eax), Immediate(0x01)); 581 __ xor_(eax, Immediate(0x01));
579 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 582 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
580 __ sub(Operand(eax), Immediate(0x0b)); 583 __ sub(eax, Immediate(0x0b));
581 __ cmp(eax, 0x0c - 0x0b); 584 __ cmp(eax, 0x0c - 0x0b);
582 BranchOrBacktrack(below_equal, on_no_match); 585 BranchOrBacktrack(below_equal, on_no_match);
583 if (mode_ == UC16) { 586 if (mode_ == UC16) {
584 // Compare original value to 0x2028 and 0x2029, using the already 587 // Compare original value to 0x2028 and 0x2029, using the already
585 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 588 // computed (current_char ^ 0x01 - 0x0b). I.e., check for
586 // 0x201d (0x2028 - 0x0b) or 0x201e. 589 // 0x201d (0x2028 - 0x0b) or 0x201e.
587 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); 590 __ sub(eax, Immediate(0x2028 - 0x0b));
588 __ cmp(eax, 0x2029 - 0x2028); 591 __ cmp(eax, 0x2029 - 0x2028);
589 BranchOrBacktrack(below_equal, on_no_match); 592 BranchOrBacktrack(below_equal, on_no_match);
590 } 593 }
591 return true; 594 return true;
592 } 595 }
593 case 'w': { 596 case 'w': {
594 if (mode_ != ASCII) { 597 if (mode_ != ASCII) {
595 // Table is 128 entries, so all ASCII characters can be tested. 598 // Table is 128 entries, so all ASCII characters can be tested.
596 __ cmp(Operand(current_character()), Immediate('z')); 599 __ cmp(current_character(), Immediate('z'));
597 BranchOrBacktrack(above, on_no_match); 600 BranchOrBacktrack(above, on_no_match);
598 } 601 }
599 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 602 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
600 ExternalReference word_map = ExternalReference::re_word_character_map(); 603 ExternalReference word_map = ExternalReference::re_word_character_map();
601 __ test_b(current_character(), 604 __ test_b(current_character(),
602 Operand::StaticArray(current_character(), times_1, word_map)); 605 Operand::StaticArray(current_character(), times_1, word_map));
603 BranchOrBacktrack(zero, on_no_match); 606 BranchOrBacktrack(zero, on_no_match);
604 return true; 607 return true;
605 } 608 }
606 case 'W': { 609 case 'W': {
607 Label done; 610 Label done;
608 if (mode_ != ASCII) { 611 if (mode_ != ASCII) {
609 // Table is 128 entries, so all ASCII characters can be tested. 612 // Table is 128 entries, so all ASCII characters can be tested.
610 __ cmp(Operand(current_character()), Immediate('z')); 613 __ cmp(current_character(), Immediate('z'));
611 __ j(above, &done); 614 __ j(above, &done);
612 } 615 }
613 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 616 ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
614 ExternalReference word_map = ExternalReference::re_word_character_map(); 617 ExternalReference word_map = ExternalReference::re_word_character_map();
615 __ test_b(current_character(), 618 __ test_b(current_character(),
616 Operand::StaticArray(current_character(), times_1, word_map)); 619 Operand::StaticArray(current_character(), times_1, word_map));
617 BranchOrBacktrack(not_zero, on_no_match); 620 BranchOrBacktrack(not_zero, on_no_match);
618 if (mode_ != ASCII) { 621 if (mode_ != ASCII) {
619 __ bind(&done); 622 __ bind(&done);
620 } 623 }
621 return true; 624 return true;
622 } 625 }
623 // Non-standard classes (with no syntactic shorthand) used internally. 626 // Non-standard classes (with no syntactic shorthand) used internally.
624 case '*': 627 case '*':
625 // Match any character. 628 // Match any character.
626 return true; 629 return true;
627 case 'n': { 630 case 'n': {
628 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). 631 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029).
629 // The opposite of '.'. 632 // The opposite of '.'.
630 __ mov(Operand(eax), current_character()); 633 __ mov(eax, current_character());
631 __ xor_(Operand(eax), Immediate(0x01)); 634 __ xor_(eax, Immediate(0x01));
632 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 635 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
633 __ sub(Operand(eax), Immediate(0x0b)); 636 __ sub(eax, Immediate(0x0b));
634 __ cmp(eax, 0x0c - 0x0b); 637 __ cmp(eax, 0x0c - 0x0b);
635 if (mode_ == ASCII) { 638 if (mode_ == ASCII) {
636 BranchOrBacktrack(above, on_no_match); 639 BranchOrBacktrack(above, on_no_match);
637 } else { 640 } else {
638 Label done; 641 Label done;
639 BranchOrBacktrack(below_equal, &done); 642 BranchOrBacktrack(below_equal, &done);
640 ASSERT_EQ(UC16, mode_); 643 ASSERT_EQ(UC16, mode_);
641 // Compare original value to 0x2028 and 0x2029, using the already 644 // Compare original value to 0x2028 and 0x2029, using the already
642 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 645 // computed (current_char ^ 0x01 - 0x0b). I.e., check for
643 // 0x201d (0x2028 - 0x0b) or 0x201e. 646 // 0x201d (0x2028 - 0x0b) or 0x201e.
644 __ sub(Operand(eax), Immediate(0x2028 - 0x0b)); 647 __ sub(eax, Immediate(0x2028 - 0x0b));
645 __ cmp(eax, 1); 648 __ cmp(eax, 1);
646 BranchOrBacktrack(above, on_no_match); 649 BranchOrBacktrack(above, on_no_match);
647 __ bind(&done); 650 __ bind(&done);
648 } 651 }
649 return true; 652 return true;
650 } 653 }
651 // No custom implementation (yet): s(UC16), S(UC16). 654 // No custom implementation (yet): s(UC16), S(UC16).
652 default: 655 default:
653 return false; 656 return false;
654 } 657 }
655 } 658 }
656 659
657 660
658 void RegExpMacroAssemblerIA32::Fail() { 661 void RegExpMacroAssemblerIA32::Fail() {
659 ASSERT(FAILURE == 0); // Return value for failure is zero. 662 ASSERT(FAILURE == 0); // Return value for failure is zero.
660 __ Set(eax, Immediate(0)); 663 __ Set(eax, Immediate(0));
661 __ jmp(&exit_label_); 664 __ jmp(&exit_label_);
662 } 665 }
663 666
664 667
665 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { 668 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
666 // Finalize code - write the entry point code now we know how many 669 // Finalize code - write the entry point code now we know how many
667 // registers we need. 670 // registers we need.
668 671
669 // Entry code: 672 // Entry code:
670 __ bind(&entry_label_); 673 __ bind(&entry_label_);
671 // Start new stack frame. 674
675 // Tell the system that we have a stack frame. Because the type is MANUAL, no
676 // code is generated.
677 FrameScope scope(masm_, StackFrame::MANUAL);
678
679 // Actually emit code to start a new stack frame.
672 __ push(ebp); 680 __ push(ebp);
673 __ mov(ebp, esp); 681 __ mov(ebp, esp);
674 // Save callee-save registers. Order here should correspond to order of 682 // Save callee-save registers. Order here should correspond to order of
675 // kBackup_ebx etc. 683 // kBackup_ebx etc.
676 __ push(esi); 684 __ push(esi);
677 __ push(edi); 685 __ push(edi);
678 __ push(ebx); // Callee-save on MacOS. 686 __ push(ebx); // Callee-save on MacOS.
679 __ push(Immediate(0)); // Make room for "input start - 1" constant. 687 __ push(Immediate(0)); // Make room for "input start - 1" constant.
680 688
681 // Check if we have space on the stack for registers. 689 // Check if we have space on the stack for registers.
(...skipping 10 matching lines...) Expand all
692 // the stack limit. 700 // the stack limit.
693 __ cmp(ecx, num_registers_ * kPointerSize); 701 __ cmp(ecx, num_registers_ * kPointerSize);
694 __ j(above_equal, &stack_ok); 702 __ j(above_equal, &stack_ok);
695 // Exit with OutOfMemory exception. There is not enough space on the stack 703 // Exit with OutOfMemory exception. There is not enough space on the stack
696 // for our working registers. 704 // for our working registers.
697 __ mov(eax, EXCEPTION); 705 __ mov(eax, EXCEPTION);
698 __ jmp(&exit_label_); 706 __ jmp(&exit_label_);
699 707
700 __ bind(&stack_limit_hit); 708 __ bind(&stack_limit_hit);
701 CallCheckStackGuardState(ebx); 709 CallCheckStackGuardState(ebx);
702 __ or_(eax, Operand(eax)); 710 __ or_(eax, eax);
703 // If returned value is non-zero, we exit with the returned value as result. 711 // If returned value is non-zero, we exit with the returned value as result.
704 __ j(not_zero, &exit_label_); 712 __ j(not_zero, &exit_label_);
705 713
706 __ bind(&stack_ok); 714 __ bind(&stack_ok);
707 // Load start index for later use. 715 // Load start index for later use.
708 __ mov(ebx, Operand(ebp, kStartIndex)); 716 __ mov(ebx, Operand(ebp, kStartIndex));
709 717
710 // Allocate space on stack for registers. 718 // Allocate space on stack for registers.
711 __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); 719 __ sub(esp, Immediate(num_registers_ * kPointerSize));
712 // Load string length. 720 // Load string length.
713 __ mov(esi, Operand(ebp, kInputEnd)); 721 __ mov(esi, Operand(ebp, kInputEnd));
714 // Load input position. 722 // Load input position.
715 __ mov(edi, Operand(ebp, kInputStart)); 723 __ mov(edi, Operand(ebp, kInputStart));
716 // Set up edi to be negative offset from string end. 724 // Set up edi to be negative offset from string end.
717 __ sub(edi, Operand(esi)); 725 __ sub(edi, esi);
718 726
719 // Set eax to address of char before start of the string. 727 // Set eax to address of char before start of the string.
720 // (effectively string position -1). 728 // (effectively string position -1).
721 __ neg(ebx); 729 __ neg(ebx);
722 if (mode_ == UC16) { 730 if (mode_ == UC16) {
723 __ lea(eax, Operand(edi, ebx, times_2, -char_size())); 731 __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
724 } else { 732 } else {
725 __ lea(eax, Operand(edi, ebx, times_1, -char_size())); 733 __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
726 } 734 }
727 // Store this value in a local variable, for use when clearing 735 // Store this value in a local variable, for use when clearing
728 // position registers. 736 // position registers.
729 __ mov(Operand(ebp, kInputStartMinusOne), eax); 737 __ mov(Operand(ebp, kInputStartMinusOne), eax);
730 738
731 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 739 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
732 // Fill saved registers with initial value = start offset - 1 740 // Fill saved registers with initial value = start offset - 1
733 // Fill in stack push order, to avoid accessing across an unwritten 741 // Fill in stack push order, to avoid accessing across an unwritten
734 // page (a problem on Windows). 742 // page (a problem on Windows).
735 __ mov(ecx, kRegisterZero); 743 __ mov(ecx, kRegisterZero);
736 Label init_loop; 744 Label init_loop;
737 __ bind(&init_loop); 745 __ bind(&init_loop);
738 __ mov(Operand(ebp, ecx, times_1, +0), eax); 746 __ mov(Operand(ebp, ecx, times_1, +0), eax);
739 __ sub(Operand(ecx), Immediate(kPointerSize)); 747 __ sub(ecx, Immediate(kPointerSize));
740 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); 748 __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
741 __ j(greater, &init_loop); 749 __ j(greater, &init_loop);
742 } 750 }
743 // Ensure that we have written to each stack page, in order. Skipping a page 751 // Ensure that we have written to each stack page, in order. Skipping a page
744 // on Windows can cause segmentation faults. Assuming page size is 4k. 752 // on Windows can cause segmentation faults. Assuming page size is 4k.
745 const int kPageSize = 4096; 753 const int kPageSize = 4096;
746 const int kRegistersPerPage = kPageSize / kPointerSize; 754 const int kRegistersPerPage = kPageSize / kPointerSize;
747 for (int i = num_saved_registers_ + kRegistersPerPage - 1; 755 for (int i = num_saved_registers_ + kRegistersPerPage - 1;
748 i < num_registers_; 756 i < num_registers_;
749 i += kRegistersPerPage) { 757 i += kRegistersPerPage) {
(...skipping 20 matching lines...) Expand all
770 __ bind(&success_label_); 778 __ bind(&success_label_);
771 if (num_saved_registers_ > 0) { 779 if (num_saved_registers_ > 0) {
772 // copy captures to output 780 // copy captures to output
773 __ mov(ebx, Operand(ebp, kRegisterOutput)); 781 __ mov(ebx, Operand(ebp, kRegisterOutput));
774 __ mov(ecx, Operand(ebp, kInputEnd)); 782 __ mov(ecx, Operand(ebp, kInputEnd));
775 __ mov(edx, Operand(ebp, kStartIndex)); 783 __ mov(edx, Operand(ebp, kStartIndex));
776 __ sub(ecx, Operand(ebp, kInputStart)); 784 __ sub(ecx, Operand(ebp, kInputStart));
777 if (mode_ == UC16) { 785 if (mode_ == UC16) {
778 __ lea(ecx, Operand(ecx, edx, times_2, 0)); 786 __ lea(ecx, Operand(ecx, edx, times_2, 0));
779 } else { 787 } else {
780 __ add(ecx, Operand(edx)); 788 __ add(ecx, edx);
781 } 789 }
782 for (int i = 0; i < num_saved_registers_; i++) { 790 for (int i = 0; i < num_saved_registers_; i++) {
783 __ mov(eax, register_location(i)); 791 __ mov(eax, register_location(i));
784 // Convert to index from start of string, not end. 792 // Convert to index from start of string, not end.
785 __ add(eax, Operand(ecx)); 793 __ add(eax, ecx);
786 if (mode_ == UC16) { 794 if (mode_ == UC16) {
787 __ sar(eax, 1); // Convert byte index to character index. 795 __ sar(eax, 1); // Convert byte index to character index.
788 } 796 }
789 __ mov(Operand(ebx, i * kPointerSize), eax); 797 __ mov(Operand(ebx, i * kPointerSize), eax);
790 } 798 }
791 } 799 }
792 __ mov(eax, Immediate(SUCCESS)); 800 __ mov(eax, Immediate(SUCCESS));
793 } 801 }
794 // Exit and return eax 802 // Exit and return eax
795 __ bind(&exit_label_); 803 __ bind(&exit_label_);
(...skipping 16 matching lines...) Expand all
812 Label exit_with_exception; 820 Label exit_with_exception;
813 821
814 // Preempt-code 822 // Preempt-code
815 if (check_preempt_label_.is_linked()) { 823 if (check_preempt_label_.is_linked()) {
816 SafeCallTarget(&check_preempt_label_); 824 SafeCallTarget(&check_preempt_label_);
817 825
818 __ push(backtrack_stackpointer()); 826 __ push(backtrack_stackpointer());
819 __ push(edi); 827 __ push(edi);
820 828
821 CallCheckStackGuardState(ebx); 829 CallCheckStackGuardState(ebx);
822 __ or_(eax, Operand(eax)); 830 __ or_(eax, eax);
823 // If returning non-zero, we should end execution with the given 831 // If returning non-zero, we should end execution with the given
824 // result as return value. 832 // result as return value.
825 __ j(not_zero, &exit_label_); 833 __ j(not_zero, &exit_label_);
826 834
827 __ pop(edi); 835 __ pop(edi);
828 __ pop(backtrack_stackpointer()); 836 __ pop(backtrack_stackpointer());
829 // String might have moved: Reload esi from frame. 837 // String might have moved: Reload esi from frame.
830 __ mov(esi, Operand(ebp, kInputEnd)); 838 __ mov(esi, Operand(ebp, kInputEnd));
831 SafeReturn(); 839 SafeReturn();
832 } 840 }
(...skipping 14 matching lines...) Expand all
847 __ mov(Operand(esp, 2 * kPointerSize), 855 __ mov(Operand(esp, 2 * kPointerSize),
848 Immediate(ExternalReference::isolate_address())); 856 Immediate(ExternalReference::isolate_address()));
849 __ lea(eax, Operand(ebp, kStackHighEnd)); 857 __ lea(eax, Operand(ebp, kStackHighEnd));
850 __ mov(Operand(esp, 1 * kPointerSize), eax); 858 __ mov(Operand(esp, 1 * kPointerSize), eax);
851 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); 859 __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
852 ExternalReference grow_stack = 860 ExternalReference grow_stack =
853 ExternalReference::re_grow_stack(masm_->isolate()); 861 ExternalReference::re_grow_stack(masm_->isolate());
854 __ CallCFunction(grow_stack, num_arguments); 862 __ CallCFunction(grow_stack, num_arguments);
855 // If return NULL, we have failed to grow the stack, and 863 // If return NULL, we have failed to grow the stack, and
856 // must exit with a stack-overflow exception. 864 // must exit with a stack-overflow exception.
857 __ or_(eax, Operand(eax)); 865 __ or_(eax, eax);
858 __ j(equal, &exit_with_exception); 866 __ j(equal, &exit_with_exception);
859 // Otherwise use return value as new stack pointer. 867 // Otherwise use return value as new stack pointer.
860 __ mov(backtrack_stackpointer(), eax); 868 __ mov(backtrack_stackpointer(), eax);
861 // Restore saved registers and continue. 869 // Restore saved registers and continue.
862 __ pop(edi); 870 __ pop(edi);
863 __ pop(esi); 871 __ pop(esi);
864 SafeReturn(); 872 SafeReturn();
865 } 873 }
866 874
867 if (exit_with_exception.is_linked()) { 875 if (exit_with_exception.is_linked()) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 void RegExpMacroAssemblerIA32::SafeCall(Label* to) { 1184 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
1177 Label return_to; 1185 Label return_to;
1178 __ push(Immediate::CodeRelativeOffset(&return_to)); 1186 __ push(Immediate::CodeRelativeOffset(&return_to));
1179 __ jmp(to); 1187 __ jmp(to);
1180 __ bind(&return_to); 1188 __ bind(&return_to);
1181 } 1189 }
1182 1190
1183 1191
1184 void RegExpMacroAssemblerIA32::SafeReturn() { 1192 void RegExpMacroAssemblerIA32::SafeReturn() {
1185 __ pop(ebx); 1193 __ pop(ebx);
1186 __ add(Operand(ebx), Immediate(masm_->CodeObject())); 1194 __ add(ebx, Immediate(masm_->CodeObject()));
1187 __ jmp(Operand(ebx)); 1195 __ jmp(ebx);
1188 } 1196 }
1189 1197
1190 1198
1191 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { 1199 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
1192 __ bind(name); 1200 __ bind(name);
1193 } 1201 }
1194 1202
1195 1203
1196 void RegExpMacroAssemblerIA32::Push(Register source) { 1204 void RegExpMacroAssemblerIA32::Push(Register source) {
1197 ASSERT(!source.is(backtrack_stackpointer())); 1205 ASSERT(!source.is(backtrack_stackpointer()));
1198 // Notice: This updates flags, unlike normal Push. 1206 // Notice: This updates flags, unlike normal Push.
1199 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1207 __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
1200 __ mov(Operand(backtrack_stackpointer(), 0), source); 1208 __ mov(Operand(backtrack_stackpointer(), 0), source);
1201 } 1209 }
1202 1210
1203 1211
1204 void RegExpMacroAssemblerIA32::Push(Immediate value) { 1212 void RegExpMacroAssemblerIA32::Push(Immediate value) {
1205 // Notice: This updates flags, unlike normal Push. 1213 // Notice: This updates flags, unlike normal Push.
1206 __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1214 __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
1207 __ mov(Operand(backtrack_stackpointer(), 0), value); 1215 __ mov(Operand(backtrack_stackpointer(), 0), value);
1208 } 1216 }
1209 1217
1210 1218
1211 void RegExpMacroAssemblerIA32::Pop(Register target) { 1219 void RegExpMacroAssemblerIA32::Pop(Register target) {
1212 ASSERT(!target.is(backtrack_stackpointer())); 1220 ASSERT(!target.is(backtrack_stackpointer()));
1213 __ mov(target, Operand(backtrack_stackpointer(), 0)); 1221 __ mov(target, Operand(backtrack_stackpointer(), 0));
1214 // Notice: This updates flags, unlike normal Pop. 1222 // Notice: This updates flags, unlike normal Pop.
1215 __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1223 __ add(backtrack_stackpointer(), Immediate(kPointerSize));
1216 } 1224 }
1217 1225
1218 1226
1219 void RegExpMacroAssemblerIA32::CheckPreemption() { 1227 void RegExpMacroAssemblerIA32::CheckPreemption() {
1220 // Check for preemption. 1228 // Check for preemption.
1221 Label no_preempt; 1229 Label no_preempt;
1222 ExternalReference stack_limit = 1230 ExternalReference stack_limit =
1223 ExternalReference::address_of_stack_limit(masm_->isolate()); 1231 ExternalReference::address_of_stack_limit(masm_->isolate());
1224 __ cmp(esp, Operand::StaticVariable(stack_limit)); 1232 __ cmp(esp, Operand::StaticVariable(stack_limit));
1225 __ j(above, &no_preempt); 1233 __ j(above, &no_preempt);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1268 } 1276 }
1269 1277
1270 1278
1271 #undef __ 1279 #undef __
1272 1280
1273 #endif // V8_INTERPRETED_REGEXP 1281 #endif // V8_INTERPRETED_REGEXP
1274 1282
1275 }} // namespace v8::internal 1283 }} // namespace v8::internal
1276 1284
1277 #endif // V8_TARGET_ARCH_IA32 1285 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698