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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 __ Dsubu(a1, a1, a0); // Length of capture. | 270 __ Dsubu(a1, a1, a0); // Length of capture. |
271 | 271 |
272 // If length is zero, either the capture is empty or it is not participating. | 272 // If length is zero, either the capture is empty or it is not participating. |
273 // In either case succeed immediately. | 273 // In either case succeed immediately. |
274 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | 274 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); |
275 | 275 |
276 __ Daddu(t1, a1, current_input_offset()); | 276 __ Daddu(t1, a1, current_input_offset()); |
277 // Check that there are enough characters left in the input. | 277 // Check that there are enough characters left in the input. |
278 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); | 278 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); |
279 | 279 |
280 if (mode_ == ASCII) { | 280 if (mode_ == LATIN1) { |
281 Label success; | 281 Label success; |
282 Label fail; | 282 Label fail; |
283 Label loop_check; | 283 Label loop_check; |
284 | 284 |
285 // a0 - offset of start of capture. | 285 // a0 - offset of start of capture. |
286 // a1 - length of capture. | 286 // a1 - length of capture. |
287 __ Daddu(a0, a0, Operand(end_of_input_address())); | 287 __ Daddu(a0, a0, Operand(end_of_input_address())); |
288 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); | 288 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); |
289 __ Daddu(a1, a0, Operand(a1)); | 289 __ Daddu(a1, a0, Operand(a1)); |
290 | 290 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 // Check that there are enough characters left in the input. | 394 // Check that there are enough characters left in the input. |
395 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); | 395 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); |
396 | 396 |
397 // Compute pointers to match string and capture string. | 397 // Compute pointers to match string and capture string. |
398 __ Daddu(a0, a0, Operand(end_of_input_address())); | 398 __ Daddu(a0, a0, Operand(end_of_input_address())); |
399 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); | 399 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); |
400 __ Daddu(a1, a1, Operand(a0)); | 400 __ Daddu(a1, a1, Operand(a0)); |
401 | 401 |
402 Label loop; | 402 Label loop; |
403 __ bind(&loop); | 403 __ bind(&loop); |
404 if (mode_ == ASCII) { | 404 if (mode_ == LATIN1) { |
405 __ lbu(a3, MemOperand(a0, 0)); | 405 __ lbu(a3, MemOperand(a0, 0)); |
406 __ daddiu(a0, a0, char_size()); | 406 __ daddiu(a0, a0, char_size()); |
407 __ lbu(a4, MemOperand(a2, 0)); | 407 __ lbu(a4, MemOperand(a2, 0)); |
408 __ daddiu(a2, a2, char_size()); | 408 __ daddiu(a2, a2, char_size()); |
409 } else { | 409 } else { |
410 DCHECK(mode_ == UC16); | 410 DCHECK(mode_ == UC16); |
411 __ lhu(a3, MemOperand(a0, 0)); | 411 __ lhu(a3, MemOperand(a0, 0)); |
412 __ daddiu(a0, a0, char_size()); | 412 __ daddiu(a0, a0, char_size()); |
413 __ lhu(a4, MemOperand(a2, 0)); | 413 __ lhu(a4, MemOperand(a2, 0)); |
414 __ daddiu(a2, a2, char_size()); | 414 __ daddiu(a2, a2, char_size()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 __ Dsubu(a0, current_character(), Operand(from)); | 475 __ Dsubu(a0, current_character(), Operand(from)); |
476 // Unsigned higher condition. | 476 // Unsigned higher condition. |
477 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); | 477 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); |
478 } | 478 } |
479 | 479 |
480 | 480 |
481 void RegExpMacroAssemblerMIPS::CheckBitInTable( | 481 void RegExpMacroAssemblerMIPS::CheckBitInTable( |
482 Handle<ByteArray> table, | 482 Handle<ByteArray> table, |
483 Label* on_bit_set) { | 483 Label* on_bit_set) { |
484 __ li(a0, Operand(table)); | 484 __ li(a0, Operand(table)); |
485 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 485 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
486 __ And(a1, current_character(), Operand(kTableSize - 1)); | 486 __ And(a1, current_character(), Operand(kTableSize - 1)); |
487 __ Daddu(a0, a0, a1); | 487 __ Daddu(a0, a0, a1); |
488 } else { | 488 } else { |
489 __ Daddu(a0, a0, current_character()); | 489 __ Daddu(a0, a0, current_character()); |
490 } | 490 } |
491 | 491 |
492 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); | 492 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); |
493 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); | 493 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); |
494 } | 494 } |
495 | 495 |
496 | 496 |
497 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, | 497 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, |
498 Label* on_no_match) { | 498 Label* on_no_match) { |
499 // Range checks (c in min..max) are generally implemented by an unsigned | 499 // Range checks (c in min..max) are generally implemented by an unsigned |
500 // (c - min) <= (max - min) check. | 500 // (c - min) <= (max - min) check. |
501 switch (type) { | 501 switch (type) { |
502 case 's': | 502 case 's': |
503 // Match space-characters. | 503 // Match space-characters. |
504 if (mode_ == ASCII) { | 504 if (mode_ == LATIN1) { |
505 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 505 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
506 Label success; | 506 Label success; |
507 __ Branch(&success, eq, current_character(), Operand(' ')); | 507 __ Branch(&success, eq, current_character(), Operand(' ')); |
508 // Check range 0x09..0x0d. | 508 // Check range 0x09..0x0d. |
509 __ Dsubu(a0, current_character(), Operand('\t')); | 509 __ Dsubu(a0, current_character(), Operand('\t')); |
510 __ Branch(&success, ls, a0, Operand('\r' - '\t')); | 510 __ Branch(&success, ls, a0, Operand('\r' - '\t')); |
511 // \u00a0 (NBSP). | 511 // \u00a0 (NBSP). |
512 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); | 512 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); |
513 __ bind(&success); | 513 __ bind(&success); |
514 return true; | 514 return true; |
515 } | 515 } |
516 return false; | 516 return false; |
517 case 'S': | 517 case 'S': |
518 // The emitted code for generic character classes is good enough. | 518 // The emitted code for generic character classes is good enough. |
519 return false; | 519 return false; |
520 case 'd': | 520 case 'd': |
521 // Match ASCII digits ('0'..'9'). | 521 // Match Latin1 digits ('0'..'9'). |
522 __ Dsubu(a0, current_character(), Operand('0')); | 522 __ Dsubu(a0, current_character(), Operand('0')); |
523 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); | 523 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); |
524 return true; | 524 return true; |
525 case 'D': | 525 case 'D': |
526 // Match non ASCII-digits. | 526 // Match non Latin1-digits. |
527 __ Dsubu(a0, current_character(), Operand('0')); | 527 __ Dsubu(a0, current_character(), Operand('0')); |
528 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); | 528 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); |
529 return true; | 529 return true; |
530 case '.': { | 530 case '.': { |
531 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). | 531 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). |
532 __ Xor(a0, current_character(), Operand(0x01)); | 532 __ Xor(a0, current_character(), Operand(0x01)); |
533 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. | 533 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. |
534 __ Dsubu(a0, a0, Operand(0x0b)); | 534 __ Dsubu(a0, a0, Operand(0x0b)); |
535 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); | 535 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); |
536 if (mode_ == UC16) { | 536 if (mode_ == UC16) { |
537 // Compare original value to 0x2028 and 0x2029, using the already | 537 // Compare original value to 0x2028 and 0x2029, using the already |
538 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 538 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
539 // 0x201d (0x2028 - 0x0b) or 0x201e. | 539 // 0x201d (0x2028 - 0x0b) or 0x201e. |
540 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); | 540 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); |
541 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); | 541 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); |
542 } | 542 } |
543 return true; | 543 return true; |
544 } | 544 } |
545 case 'n': { | 545 case 'n': { |
546 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). | 546 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). |
547 __ Xor(a0, current_character(), Operand(0x01)); | 547 __ Xor(a0, current_character(), Operand(0x01)); |
548 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. | 548 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. |
549 __ Dsubu(a0, a0, Operand(0x0b)); | 549 __ Dsubu(a0, a0, Operand(0x0b)); |
550 if (mode_ == ASCII) { | 550 if (mode_ == LATIN1) { |
551 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); | 551 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); |
552 } else { | 552 } else { |
553 Label done; | 553 Label done; |
554 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); | 554 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); |
555 // Compare original value to 0x2028 and 0x2029, using the already | 555 // Compare original value to 0x2028 and 0x2029, using the already |
556 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 556 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
557 // 0x201d (0x2028 - 0x0b) or 0x201e. | 557 // 0x201d (0x2028 - 0x0b) or 0x201e. |
558 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); | 558 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); |
559 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); | 559 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); |
560 __ bind(&done); | 560 __ bind(&done); |
561 } | 561 } |
562 return true; | 562 return true; |
563 } | 563 } |
564 case 'w': { | 564 case 'w': { |
565 if (mode_ != ASCII) { | 565 if (mode_ != LATIN1) { |
566 // Table is 128 entries, so all ASCII characters can be tested. | 566 // Table is 256 entries, so all Latin1 characters can be tested. |
567 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); | 567 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); |
568 } | 568 } |
569 ExternalReference map = ExternalReference::re_word_character_map(); | 569 ExternalReference map = ExternalReference::re_word_character_map(); |
570 __ li(a0, Operand(map)); | 570 __ li(a0, Operand(map)); |
571 __ Daddu(a0, a0, current_character()); | 571 __ Daddu(a0, a0, current_character()); |
572 __ lbu(a0, MemOperand(a0, 0)); | 572 __ lbu(a0, MemOperand(a0, 0)); |
573 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); | 573 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); |
574 return true; | 574 return true; |
575 } | 575 } |
576 case 'W': { | 576 case 'W': { |
577 Label done; | 577 Label done; |
578 if (mode_ != ASCII) { | 578 if (mode_ != LATIN1) { |
579 // Table is 128 entries, so all ASCII characters can be tested. | 579 // Table is 256 entries, so all Latin1 characters can be tested. |
580 __ Branch(&done, hi, current_character(), Operand('z')); | 580 __ Branch(&done, hi, current_character(), Operand('z')); |
581 } | 581 } |
582 ExternalReference map = ExternalReference::re_word_character_map(); | 582 ExternalReference map = ExternalReference::re_word_character_map(); |
583 __ li(a0, Operand(map)); | 583 __ li(a0, Operand(map)); |
584 __ Daddu(a0, a0, current_character()); | 584 __ Daddu(a0, a0, current_character()); |
585 __ lbu(a0, MemOperand(a0, 0)); | 585 __ lbu(a0, MemOperand(a0, 0)); |
586 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); | 586 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); |
587 if (mode_ != ASCII) { | 587 if (mode_ != LATIN1) { |
588 __ bind(&done); | 588 __ bind(&done); |
589 } | 589 } |
590 return true; | 590 return true; |
591 } | 591 } |
592 case '*': | 592 case '*': |
593 // Match any character. | 593 // Match any character. |
594 return true; | 594 return true; |
595 // No custom implementation (yet): s(UC16), S(UC16). | 595 // No custom implementation (yet): s(UC16), S(UC16). |
596 default: | 596 default: |
597 return false; | 597 return false; |
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 if (frame_entry<int>(re_frame, kDirectCall) == 1) { | 1165 if (frame_entry<int>(re_frame, kDirectCall) == 1) { |
1166 return RETRY; | 1166 return RETRY; |
1167 } | 1167 } |
1168 | 1168 |
1169 // Prepare for possible GC. | 1169 // Prepare for possible GC. |
1170 HandleScope handles(isolate); | 1170 HandleScope handles(isolate); |
1171 Handle<Code> code_handle(re_code); | 1171 Handle<Code> code_handle(re_code); |
1172 | 1172 |
1173 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1173 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
1174 // Current string. | 1174 // Current string. |
1175 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1175 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
1176 | 1176 |
1177 DCHECK(re_code->instruction_start() <= *return_address); | 1177 DCHECK(re_code->instruction_start() <= *return_address); |
1178 DCHECK(*return_address <= | 1178 DCHECK(*return_address <= |
1179 re_code->instruction_start() + re_code->instruction_size()); | 1179 re_code->instruction_start() + re_code->instruction_size()); |
1180 | 1180 |
1181 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1181 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1182 | 1182 |
1183 if (*code_handle != re_code) { // Return address no longer valid. | 1183 if (*code_handle != re_code) { // Return address no longer valid. |
1184 int delta = code_handle->address() - re_code->address(); | 1184 int delta = code_handle->address() - re_code->address(); |
1185 // Overwrite the return address on the stack. | 1185 // Overwrite the return address on the stack. |
(...skipping 10 matching lines...) Expand all Loading... |
1196 // Extract the underlying string and the slice offset. | 1196 // Extract the underlying string and the slice offset. |
1197 if (StringShape(*subject_tmp).IsCons()) { | 1197 if (StringShape(*subject_tmp).IsCons()) { |
1198 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1198 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
1199 } else if (StringShape(*subject_tmp).IsSliced()) { | 1199 } else if (StringShape(*subject_tmp).IsSliced()) { |
1200 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1200 SlicedString* slice = SlicedString::cast(*subject_tmp); |
1201 subject_tmp = Handle<String>(slice->parent()); | 1201 subject_tmp = Handle<String>(slice->parent()); |
1202 slice_offset = slice->offset(); | 1202 slice_offset = slice->offset(); |
1203 } | 1203 } |
1204 | 1204 |
1205 // String might have changed. | 1205 // String might have changed. |
1206 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1206 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
1207 // If we changed between an ASCII and an UC16 string, the specialized | 1207 // If we changed between an Latin1 and an UC16 string, the specialized |
1208 // code cannot be used, and we need to restart regexp matching from | 1208 // code cannot be used, and we need to restart regexp matching from |
1209 // scratch (including, potentially, compiling a new version of the code). | 1209 // scratch (including, potentially, compiling a new version of the code). |
1210 return RETRY; | 1210 return RETRY; |
1211 } | 1211 } |
1212 | 1212 |
1213 // Otherwise, the content of the string might have moved. It must still | 1213 // Otherwise, the content of the string might have moved. It must still |
1214 // be a sequential or external string with the same content. | 1214 // be a sequential or external string with the same content. |
1215 // Update the start and end pointers in the stack frame to the current | 1215 // Update the start and end pointers in the stack frame to the current |
1216 // location (whether it has actually moved or not). | 1216 // location (whether it has actually moved or not). |
1217 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1217 DCHECK(StringShape(*subject_tmp).IsSequential() || |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 Register offset = current_input_offset(); | 1347 Register offset = current_input_offset(); |
1348 if (cp_offset != 0) { | 1348 if (cp_offset != 0) { |
1349 // t3 is not being used to store the capture start index at this point. | 1349 // t3 is not being used to store the capture start index at this point. |
1350 __ Daddu(t3, current_input_offset(), Operand(cp_offset * char_size())); | 1350 __ Daddu(t3, current_input_offset(), Operand(cp_offset * char_size())); |
1351 offset = t3; | 1351 offset = t3; |
1352 } | 1352 } |
1353 // We assume that we cannot do unaligned loads on MIPS, so this function | 1353 // We assume that we cannot do unaligned loads on MIPS, so this function |
1354 // must only be used to load a single character at a time. | 1354 // must only be used to load a single character at a time. |
1355 DCHECK(characters == 1); | 1355 DCHECK(characters == 1); |
1356 __ Daddu(t1, end_of_input_address(), Operand(offset)); | 1356 __ Daddu(t1, end_of_input_address(), Operand(offset)); |
1357 if (mode_ == ASCII) { | 1357 if (mode_ == LATIN1) { |
1358 __ lbu(current_character(), MemOperand(t1, 0)); | 1358 __ lbu(current_character(), MemOperand(t1, 0)); |
1359 } else { | 1359 } else { |
1360 DCHECK(mode_ == UC16); | 1360 DCHECK(mode_ == UC16); |
1361 __ lhu(current_character(), MemOperand(t1, 0)); | 1361 __ lhu(current_character(), MemOperand(t1, 0)); |
1362 } | 1362 } |
1363 } | 1363 } |
1364 | 1364 |
1365 #undef __ | 1365 #undef __ |
1366 | 1366 |
1367 #endif // V8_INTERPRETED_REGEXP | 1367 #endif // V8_INTERPRETED_REGEXP |
1368 | 1368 |
1369 }} // namespace v8::internal | 1369 }} // namespace v8::internal |
1370 | 1370 |
1371 #endif // V8_TARGET_ARCH_MIPS64 | 1371 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |