| 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 |