OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X87 | 7 #if V8_TARGET_ARCH_X87 |
8 | 8 |
9 #include "src/cpu-profiler.h" | 9 #include "src/cpu-profiler.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 212 |
213 // If length is zero, either the capture is empty or it is completely | 213 // If length is zero, either the capture is empty or it is completely |
214 // uncaptured. In either case succeed immediately. | 214 // uncaptured. In either case succeed immediately. |
215 __ j(equal, &fallthrough); | 215 __ j(equal, &fallthrough); |
216 | 216 |
217 // Check that there are sufficient characters left in the input. | 217 // Check that there are sufficient characters left in the input. |
218 __ mov(eax, edi); | 218 __ mov(eax, edi); |
219 __ add(eax, ebx); | 219 __ add(eax, ebx); |
220 BranchOrBacktrack(greater, on_no_match); | 220 BranchOrBacktrack(greater, on_no_match); |
221 | 221 |
222 if (mode_ == ASCII) { | 222 if (mode_ == LATIN1) { |
223 Label success; | 223 Label success; |
224 Label fail; | 224 Label fail; |
225 Label loop_increment; | 225 Label loop_increment; |
226 // Save register contents to make the registers available below. | 226 // Save register contents to make the registers available below. |
227 __ push(edi); | 227 __ push(edi); |
228 __ push(backtrack_stackpointer()); | 228 __ push(backtrack_stackpointer()); |
229 // After this, the eax, ecx, and edi registers are available. | 229 // After this, the eax, ecx, and edi registers are available. |
230 | 230 |
231 __ add(edx, esi); // Start of capture | 231 __ add(edx, esi); // Start of capture |
232 __ add(edi, esi); // Start of text to match against capture. | 232 __ add(edi, esi); // Start of text to match against capture. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 // Save register to make it available below. | 358 // Save register to make it available below. |
359 __ push(backtrack_stackpointer()); | 359 __ push(backtrack_stackpointer()); |
360 | 360 |
361 // Compute pointers to match string and capture string | 361 // Compute pointers to match string and capture string |
362 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. | 362 __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. |
363 __ add(edx, esi); // Start of capture. | 363 __ add(edx, esi); // Start of capture. |
364 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match | 364 __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match |
365 | 365 |
366 Label loop; | 366 Label loop; |
367 __ bind(&loop); | 367 __ bind(&loop); |
368 if (mode_ == ASCII) { | 368 if (mode_ == LATIN1) { |
369 __ movzx_b(eax, Operand(edx, 0)); | 369 __ movzx_b(eax, Operand(edx, 0)); |
370 __ cmpb_al(Operand(ebx, 0)); | 370 __ cmpb_al(Operand(ebx, 0)); |
371 } else { | 371 } else { |
372 DCHECK(mode_ == UC16); | 372 DCHECK(mode_ == UC16); |
373 __ movzx_w(eax, Operand(edx, 0)); | 373 __ movzx_w(eax, Operand(edx, 0)); |
374 __ cmpw_ax(Operand(ebx, 0)); | 374 __ cmpw_ax(Operand(ebx, 0)); |
375 } | 375 } |
376 __ j(not_equal, &fail); | 376 __ j(not_equal, &fail); |
377 // Increment pointers into capture and match string. | 377 // Increment pointers into capture and match string. |
378 __ add(edx, Immediate(char_size())); | 378 __ add(edx, Immediate(char_size())); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 __ cmp(eax, to - from); | 468 __ cmp(eax, to - from); |
469 BranchOrBacktrack(above, on_not_in_range); | 469 BranchOrBacktrack(above, on_not_in_range); |
470 } | 470 } |
471 | 471 |
472 | 472 |
473 void RegExpMacroAssemblerX87::CheckBitInTable( | 473 void RegExpMacroAssemblerX87::CheckBitInTable( |
474 Handle<ByteArray> table, | 474 Handle<ByteArray> table, |
475 Label* on_bit_set) { | 475 Label* on_bit_set) { |
476 __ mov(eax, Immediate(table)); | 476 __ mov(eax, Immediate(table)); |
477 Register index = current_character(); | 477 Register index = current_character(); |
478 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 478 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
479 __ mov(ebx, kTableSize - 1); | 479 __ mov(ebx, kTableSize - 1); |
480 __ and_(ebx, current_character()); | 480 __ and_(ebx, current_character()); |
481 index = ebx; | 481 index = ebx; |
482 } | 482 } |
483 __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0); | 483 __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0); |
484 BranchOrBacktrack(not_equal, on_bit_set); | 484 BranchOrBacktrack(not_equal, on_bit_set); |
485 } | 485 } |
486 | 486 |
487 | 487 |
488 bool RegExpMacroAssemblerX87::CheckSpecialCharacterClass(uc16 type, | 488 bool RegExpMacroAssemblerX87::CheckSpecialCharacterClass(uc16 type, |
489 Label* on_no_match) { | 489 Label* on_no_match) { |
490 // Range checks (c in min..max) are generally implemented by an unsigned | 490 // Range checks (c in min..max) are generally implemented by an unsigned |
491 // (c - min) <= (max - min) check | 491 // (c - min) <= (max - min) check |
492 switch (type) { | 492 switch (type) { |
493 case 's': | 493 case 's': |
494 // Match space-characters | 494 // Match space-characters |
495 if (mode_ == ASCII) { | 495 if (mode_ == LATIN1) { |
496 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 496 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
497 Label success; | 497 Label success; |
498 __ cmp(current_character(), ' '); | 498 __ cmp(current_character(), ' '); |
499 __ j(equal, &success, Label::kNear); | 499 __ j(equal, &success, Label::kNear); |
500 // Check range 0x09..0x0d | 500 // Check range 0x09..0x0d |
501 __ lea(eax, Operand(current_character(), -'\t')); | 501 __ lea(eax, Operand(current_character(), -'\t')); |
502 __ cmp(eax, '\r' - '\t'); | 502 __ cmp(eax, '\r' - '\t'); |
503 __ j(below_equal, &success, Label::kNear); | 503 __ j(below_equal, &success, Label::kNear); |
504 // \u00a0 (NBSP). | 504 // \u00a0 (NBSP). |
505 __ cmp(eax, 0x00a0 - '\t'); | 505 __ cmp(eax, 0x00a0 - '\t'); |
(...skipping 29 matching lines...) Expand all Loading... |
535 // Compare original value to 0x2028 and 0x2029, using the already | 535 // Compare original value to 0x2028 and 0x2029, using the already |
536 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 536 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
537 // 0x201d (0x2028 - 0x0b) or 0x201e. | 537 // 0x201d (0x2028 - 0x0b) or 0x201e. |
538 __ sub(eax, Immediate(0x2028 - 0x0b)); | 538 __ sub(eax, Immediate(0x2028 - 0x0b)); |
539 __ cmp(eax, 0x2029 - 0x2028); | 539 __ cmp(eax, 0x2029 - 0x2028); |
540 BranchOrBacktrack(below_equal, on_no_match); | 540 BranchOrBacktrack(below_equal, on_no_match); |
541 } | 541 } |
542 return true; | 542 return true; |
543 } | 543 } |
544 case 'w': { | 544 case 'w': { |
545 if (mode_ != ASCII) { | 545 if (mode_ != LATIN1) { |
546 // Table is 128 entries, so all ASCII characters can be tested. | 546 // Table is 256 entries, so all Latin1 characters can be tested. |
547 __ cmp(current_character(), Immediate('z')); | 547 __ cmp(current_character(), Immediate('z')); |
548 BranchOrBacktrack(above, on_no_match); | 548 BranchOrBacktrack(above, on_no_match); |
549 } | 549 } |
550 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 550 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
551 ExternalReference word_map = ExternalReference::re_word_character_map(); | 551 ExternalReference word_map = ExternalReference::re_word_character_map(); |
552 __ test_b(current_character(), | 552 __ test_b(current_character(), |
553 Operand::StaticArray(current_character(), times_1, word_map)); | 553 Operand::StaticArray(current_character(), times_1, word_map)); |
554 BranchOrBacktrack(zero, on_no_match); | 554 BranchOrBacktrack(zero, on_no_match); |
555 return true; | 555 return true; |
556 } | 556 } |
557 case 'W': { | 557 case 'W': { |
558 Label done; | 558 Label done; |
559 if (mode_ != ASCII) { | 559 if (mode_ != LATIN1) { |
560 // Table is 128 entries, so all ASCII characters can be tested. | 560 // Table is 256 entries, so all Latin1 characters can be tested. |
561 __ cmp(current_character(), Immediate('z')); | 561 __ cmp(current_character(), Immediate('z')); |
562 __ j(above, &done); | 562 __ j(above, &done); |
563 } | 563 } |
564 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. | 564 DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. |
565 ExternalReference word_map = ExternalReference::re_word_character_map(); | 565 ExternalReference word_map = ExternalReference::re_word_character_map(); |
566 __ test_b(current_character(), | 566 __ test_b(current_character(), |
567 Operand::StaticArray(current_character(), times_1, word_map)); | 567 Operand::StaticArray(current_character(), times_1, word_map)); |
568 BranchOrBacktrack(not_zero, on_no_match); | 568 BranchOrBacktrack(not_zero, on_no_match); |
569 if (mode_ != ASCII) { | 569 if (mode_ != LATIN1) { |
570 __ bind(&done); | 570 __ bind(&done); |
571 } | 571 } |
572 return true; | 572 return true; |
573 } | 573 } |
574 // Non-standard classes (with no syntactic shorthand) used internally. | 574 // Non-standard classes (with no syntactic shorthand) used internally. |
575 case '*': | 575 case '*': |
576 // Match any character. | 576 // Match any character. |
577 return true; | 577 return true; |
578 case 'n': { | 578 case 'n': { |
579 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). | 579 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). |
580 // The opposite of '.'. | 580 // The opposite of '.'. |
581 __ mov(eax, current_character()); | 581 __ mov(eax, current_character()); |
582 __ xor_(eax, Immediate(0x01)); | 582 __ xor_(eax, Immediate(0x01)); |
583 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 583 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
584 __ sub(eax, Immediate(0x0b)); | 584 __ sub(eax, Immediate(0x0b)); |
585 __ cmp(eax, 0x0c - 0x0b); | 585 __ cmp(eax, 0x0c - 0x0b); |
586 if (mode_ == ASCII) { | 586 if (mode_ == LATIN1) { |
587 BranchOrBacktrack(above, on_no_match); | 587 BranchOrBacktrack(above, on_no_match); |
588 } else { | 588 } else { |
589 Label done; | 589 Label done; |
590 BranchOrBacktrack(below_equal, &done); | 590 BranchOrBacktrack(below_equal, &done); |
591 DCHECK_EQ(UC16, mode_); | 591 DCHECK_EQ(UC16, mode_); |
592 // Compare original value to 0x2028 and 0x2029, using the already | 592 // Compare original value to 0x2028 and 0x2029, using the already |
593 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 593 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
594 // 0x201d (0x2028 - 0x0b) or 0x201e. | 594 // 0x201d (0x2028 - 0x0b) or 0x201e. |
595 __ sub(eax, Immediate(0x2028 - 0x0b)); | 595 __ sub(eax, Immediate(0x2028 - 0x0b)); |
596 __ cmp(eax, 1); | 596 __ cmp(eax, 1); |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 return RETRY; | 1091 return RETRY; |
1092 } | 1092 } |
1093 | 1093 |
1094 // Prepare for possible GC. | 1094 // Prepare for possible GC. |
1095 HandleScope handles(isolate); | 1095 HandleScope handles(isolate); |
1096 Handle<Code> code_handle(re_code); | 1096 Handle<Code> code_handle(re_code); |
1097 | 1097 |
1098 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1098 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
1099 | 1099 |
1100 // Current string. | 1100 // Current string. |
1101 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1101 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
1102 | 1102 |
1103 DCHECK(re_code->instruction_start() <= *return_address); | 1103 DCHECK(re_code->instruction_start() <= *return_address); |
1104 DCHECK(*return_address <= | 1104 DCHECK(*return_address <= |
1105 re_code->instruction_start() + re_code->instruction_size()); | 1105 re_code->instruction_start() + re_code->instruction_size()); |
1106 | 1106 |
1107 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1107 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1108 | 1108 |
1109 if (*code_handle != re_code) { // Return address no longer valid | 1109 if (*code_handle != re_code) { // Return address no longer valid |
1110 int delta = code_handle->address() - re_code->address(); | 1110 int delta = code_handle->address() - re_code->address(); |
1111 // Overwrite the return address on the stack. | 1111 // Overwrite the return address on the stack. |
(...skipping 10 matching lines...) Expand all Loading... |
1122 // Extract the underlying string and the slice offset. | 1122 // Extract the underlying string and the slice offset. |
1123 if (StringShape(*subject_tmp).IsCons()) { | 1123 if (StringShape(*subject_tmp).IsCons()) { |
1124 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1124 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
1125 } else if (StringShape(*subject_tmp).IsSliced()) { | 1125 } else if (StringShape(*subject_tmp).IsSliced()) { |
1126 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1126 SlicedString* slice = SlicedString::cast(*subject_tmp); |
1127 subject_tmp = Handle<String>(slice->parent()); | 1127 subject_tmp = Handle<String>(slice->parent()); |
1128 slice_offset = slice->offset(); | 1128 slice_offset = slice->offset(); |
1129 } | 1129 } |
1130 | 1130 |
1131 // String might have changed. | 1131 // String might have changed. |
1132 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1132 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
1133 // If we changed between an ASCII and an UC16 string, the specialized | 1133 // If we changed between an LATIN1 and an UC16 string, the specialized |
1134 // code cannot be used, and we need to restart regexp matching from | 1134 // code cannot be used, and we need to restart regexp matching from |
1135 // scratch (including, potentially, compiling a new version of the code). | 1135 // scratch (including, potentially, compiling a new version of the code). |
1136 return RETRY; | 1136 return RETRY; |
1137 } | 1137 } |
1138 | 1138 |
1139 // Otherwise, the content of the string might have moved. It must still | 1139 // Otherwise, the content of the string might have moved. It must still |
1140 // be a sequential or external string with the same content. | 1140 // be a sequential or external string with the same content. |
1141 // Update the start and end pointers in the stack frame to the current | 1141 // Update the start and end pointers in the stack frame to the current |
1142 // location (whether it has actually moved or not). | 1142 // location (whether it has actually moved or not). |
1143 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1143 DCHECK(StringShape(*subject_tmp).IsSequential() || |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 __ j(above, &no_stack_overflow); | 1270 __ j(above, &no_stack_overflow); |
1271 | 1271 |
1272 SafeCall(&stack_overflow_label_); | 1272 SafeCall(&stack_overflow_label_); |
1273 | 1273 |
1274 __ bind(&no_stack_overflow); | 1274 __ bind(&no_stack_overflow); |
1275 } | 1275 } |
1276 | 1276 |
1277 | 1277 |
1278 void RegExpMacroAssemblerX87::LoadCurrentCharacterUnchecked(int cp_offset, | 1278 void RegExpMacroAssemblerX87::LoadCurrentCharacterUnchecked(int cp_offset, |
1279 int characters) { | 1279 int characters) { |
1280 if (mode_ == ASCII) { | 1280 if (mode_ == LATIN1) { |
1281 if (characters == 4) { | 1281 if (characters == 4) { |
1282 __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1282 __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1283 } else if (characters == 2) { | 1283 } else if (characters == 2) { |
1284 __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1284 __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1285 } else { | 1285 } else { |
1286 DCHECK(characters == 1); | 1286 DCHECK(characters == 1); |
1287 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); | 1287 __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); |
1288 } | 1288 } |
1289 } else { | 1289 } else { |
1290 DCHECK(mode_ == UC16); | 1290 DCHECK(mode_ == UC16); |
1291 if (characters == 2) { | 1291 if (characters == 2) { |
1292 __ mov(current_character(), | 1292 __ mov(current_character(), |
1293 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1293 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
1294 } else { | 1294 } else { |
1295 DCHECK(characters == 1); | 1295 DCHECK(characters == 1); |
1296 __ movzx_w(current_character(), | 1296 __ movzx_w(current_character(), |
1297 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); | 1297 Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); |
1298 } | 1298 } |
1299 } | 1299 } |
1300 } | 1300 } |
1301 | 1301 |
1302 | 1302 |
1303 #undef __ | 1303 #undef __ |
1304 | 1304 |
1305 #endif // V8_INTERPRETED_REGEXP | 1305 #endif // V8_INTERPRETED_REGEXP |
1306 | 1306 |
1307 }} // namespace v8::internal | 1307 }} // namespace v8::internal |
1308 | 1308 |
1309 #endif // V8_TARGET_ARCH_X87 | 1309 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |