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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/cpu-profiler.h" | 10 #include "src/cpu-profiler.h" |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 __ sub(r1, r1, r0, SetCC); // Length of capture. | 231 __ sub(r1, r1, r0, SetCC); // Length of capture. |
232 | 232 |
233 // If length is zero, either the capture is empty or it is not participating. | 233 // If length is zero, either the capture is empty or it is not participating. |
234 // In either case succeed immediately. | 234 // In either case succeed immediately. |
235 __ b(eq, &fallthrough); | 235 __ b(eq, &fallthrough); |
236 | 236 |
237 // Check that there are enough characters left in the input. | 237 // Check that there are enough characters left in the input. |
238 __ cmn(r1, Operand(current_input_offset())); | 238 __ cmn(r1, Operand(current_input_offset())); |
239 BranchOrBacktrack(gt, on_no_match); | 239 BranchOrBacktrack(gt, on_no_match); |
240 | 240 |
241 if (mode_ == ASCII) { | 241 if (mode_ == LATIN1) { |
242 Label success; | 242 Label success; |
243 Label fail; | 243 Label fail; |
244 Label loop_check; | 244 Label loop_check; |
245 | 245 |
246 // r0 - offset of start of capture | 246 // r0 - offset of start of capture |
247 // r1 - length of capture | 247 // r1 - length of capture |
248 __ add(r0, r0, Operand(end_of_input_address())); | 248 __ add(r0, r0, Operand(end_of_input_address())); |
249 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 249 __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
250 __ add(r1, r0, Operand(r1)); | 250 __ add(r1, r0, Operand(r1)); |
251 | 251 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 __ cmn(r1, Operand(current_input_offset())); | 347 __ cmn(r1, Operand(current_input_offset())); |
348 BranchOrBacktrack(gt, on_no_match); | 348 BranchOrBacktrack(gt, on_no_match); |
349 | 349 |
350 // Compute pointers to match string and capture string | 350 // Compute pointers to match string and capture string |
351 __ add(r0, r0, Operand(end_of_input_address())); | 351 __ add(r0, r0, Operand(end_of_input_address())); |
352 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 352 __ add(r2, end_of_input_address(), Operand(current_input_offset())); |
353 __ add(r1, r1, Operand(r0)); | 353 __ add(r1, r1, Operand(r0)); |
354 | 354 |
355 Label loop; | 355 Label loop; |
356 __ bind(&loop); | 356 __ bind(&loop); |
357 if (mode_ == ASCII) { | 357 if (mode_ == LATIN1) { |
358 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); | 358 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); |
359 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); | 359 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); |
360 } else { | 360 } else { |
361 DCHECK(mode_ == UC16); | 361 DCHECK(mode_ == UC16); |
362 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); | 362 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); |
363 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); | 363 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); |
364 } | 364 } |
365 __ cmp(r3, r4); | 365 __ cmp(r3, r4); |
366 BranchOrBacktrack(ne, on_no_match); | 366 BranchOrBacktrack(ne, on_no_match); |
367 __ cmp(r0, r1); | 367 __ cmp(r0, r1); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 __ sub(r0, current_character(), Operand(from)); | 436 __ sub(r0, current_character(), Operand(from)); |
437 __ cmp(r0, Operand(to - from)); | 437 __ cmp(r0, Operand(to - from)); |
438 BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition. | 438 BranchOrBacktrack(hi, on_not_in_range); // Unsigned higher condition. |
439 } | 439 } |
440 | 440 |
441 | 441 |
442 void RegExpMacroAssemblerARM::CheckBitInTable( | 442 void RegExpMacroAssemblerARM::CheckBitInTable( |
443 Handle<ByteArray> table, | 443 Handle<ByteArray> table, |
444 Label* on_bit_set) { | 444 Label* on_bit_set) { |
445 __ mov(r0, Operand(table)); | 445 __ mov(r0, Operand(table)); |
446 if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) { | 446 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { |
447 __ and_(r1, current_character(), Operand(kTableSize - 1)); | 447 __ and_(r1, current_character(), Operand(kTableSize - 1)); |
448 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag)); | 448 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag)); |
449 } else { | 449 } else { |
450 __ add(r1, | 450 __ add(r1, |
451 current_character(), | 451 current_character(), |
452 Operand(ByteArray::kHeaderSize - kHeapObjectTag)); | 452 Operand(ByteArray::kHeaderSize - kHeapObjectTag)); |
453 } | 453 } |
454 __ ldrb(r0, MemOperand(r0, r1)); | 454 __ ldrb(r0, MemOperand(r0, r1)); |
455 __ cmp(r0, Operand::Zero()); | 455 __ cmp(r0, Operand::Zero()); |
456 BranchOrBacktrack(ne, on_bit_set); | 456 BranchOrBacktrack(ne, on_bit_set); |
457 } | 457 } |
458 | 458 |
459 | 459 |
460 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, | 460 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, |
461 Label* on_no_match) { | 461 Label* on_no_match) { |
462 // Range checks (c in min..max) are generally implemented by an unsigned | 462 // Range checks (c in min..max) are generally implemented by an unsigned |
463 // (c - min) <= (max - min) check | 463 // (c - min) <= (max - min) check |
464 switch (type) { | 464 switch (type) { |
465 case 's': | 465 case 's': |
466 // Match space-characters | 466 // Match space-characters |
467 if (mode_ == ASCII) { | 467 if (mode_ == LATIN1) { |
468 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 468 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
469 Label success; | 469 Label success; |
470 __ cmp(current_character(), Operand(' ')); | 470 __ cmp(current_character(), Operand(' ')); |
471 __ b(eq, &success); | 471 __ b(eq, &success); |
472 // Check range 0x09..0x0d | 472 // Check range 0x09..0x0d |
473 __ sub(r0, current_character(), Operand('\t')); | 473 __ sub(r0, current_character(), Operand('\t')); |
474 __ cmp(r0, Operand('\r' - '\t')); | 474 __ cmp(r0, Operand('\r' - '\t')); |
475 __ b(ls, &success); | 475 __ b(ls, &success); |
476 // \u00a0 (NBSP). | 476 // \u00a0 (NBSP). |
477 __ cmp(r0, Operand(0x00a0 - '\t')); | 477 __ cmp(r0, Operand(0x00a0 - '\t')); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 BranchOrBacktrack(ls, on_no_match); | 511 BranchOrBacktrack(ls, on_no_match); |
512 } | 512 } |
513 return true; | 513 return true; |
514 } | 514 } |
515 case 'n': { | 515 case 'n': { |
516 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) | 516 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) |
517 __ eor(r0, current_character(), Operand(0x01)); | 517 __ eor(r0, current_character(), Operand(0x01)); |
518 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c | 518 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c |
519 __ sub(r0, r0, Operand(0x0b)); | 519 __ sub(r0, r0, Operand(0x0b)); |
520 __ cmp(r0, Operand(0x0c - 0x0b)); | 520 __ cmp(r0, Operand(0x0c - 0x0b)); |
521 if (mode_ == ASCII) { | 521 if (mode_ == LATIN1) { |
522 BranchOrBacktrack(hi, on_no_match); | 522 BranchOrBacktrack(hi, on_no_match); |
523 } else { | 523 } else { |
524 Label done; | 524 Label done; |
525 __ b(ls, &done); | 525 __ b(ls, &done); |
526 // Compare original value to 0x2028 and 0x2029, using the already | 526 // Compare original value to 0x2028 and 0x2029, using the already |
527 // computed (current_char ^ 0x01 - 0x0b). I.e., check for | 527 // computed (current_char ^ 0x01 - 0x0b). I.e., check for |
528 // 0x201d (0x2028 - 0x0b) or 0x201e. | 528 // 0x201d (0x2028 - 0x0b) or 0x201e. |
529 __ sub(r0, r0, Operand(0x2028 - 0x0b)); | 529 __ sub(r0, r0, Operand(0x2028 - 0x0b)); |
530 __ cmp(r0, Operand(1)); | 530 __ cmp(r0, Operand(1)); |
531 BranchOrBacktrack(hi, on_no_match); | 531 BranchOrBacktrack(hi, on_no_match); |
532 __ bind(&done); | 532 __ bind(&done); |
533 } | 533 } |
534 return true; | 534 return true; |
535 } | 535 } |
536 case 'w': { | 536 case 'w': { |
537 if (mode_ != ASCII) { | 537 if (mode_ != LATIN1) { |
538 // Table is 128 entries, so all ASCII characters can be tested. | 538 // Table is 256 entries, so all Latin1 characters can be tested. |
539 __ cmp(current_character(), Operand('z')); | 539 __ cmp(current_character(), Operand('z')); |
540 BranchOrBacktrack(hi, on_no_match); | 540 BranchOrBacktrack(hi, on_no_match); |
541 } | 541 } |
542 ExternalReference map = ExternalReference::re_word_character_map(); | 542 ExternalReference map = ExternalReference::re_word_character_map(); |
543 __ mov(r0, Operand(map)); | 543 __ mov(r0, Operand(map)); |
544 __ ldrb(r0, MemOperand(r0, current_character())); | 544 __ ldrb(r0, MemOperand(r0, current_character())); |
545 __ cmp(r0, Operand::Zero()); | 545 __ cmp(r0, Operand::Zero()); |
546 BranchOrBacktrack(eq, on_no_match); | 546 BranchOrBacktrack(eq, on_no_match); |
547 return true; | 547 return true; |
548 } | 548 } |
549 case 'W': { | 549 case 'W': { |
550 Label done; | 550 Label done; |
551 if (mode_ != ASCII) { | 551 if (mode_ != LATIN1) { |
552 // Table is 128 entries, so all ASCII characters can be tested. | 552 // Table is 256 entries, so all Latin1 characters can be tested. |
553 __ cmp(current_character(), Operand('z')); | 553 __ cmp(current_character(), Operand('z')); |
554 __ b(hi, &done); | 554 __ b(hi, &done); |
555 } | 555 } |
556 ExternalReference map = ExternalReference::re_word_character_map(); | 556 ExternalReference map = ExternalReference::re_word_character_map(); |
557 __ mov(r0, Operand(map)); | 557 __ mov(r0, Operand(map)); |
558 __ ldrb(r0, MemOperand(r0, current_character())); | 558 __ ldrb(r0, MemOperand(r0, current_character())); |
559 __ cmp(r0, Operand::Zero()); | 559 __ cmp(r0, Operand::Zero()); |
560 BranchOrBacktrack(ne, on_no_match); | 560 BranchOrBacktrack(ne, on_no_match); |
561 if (mode_ != ASCII) { | 561 if (mode_ != LATIN1) { |
562 __ bind(&done); | 562 __ bind(&done); |
563 } | 563 } |
564 return true; | 564 return true; |
565 } | 565 } |
566 case '*': | 566 case '*': |
567 // Match any character. | 567 // Match any character. |
568 return true; | 568 return true; |
569 // No custom implementation (yet): s(UC16), S(UC16). | 569 // No custom implementation (yet): s(UC16), S(UC16). |
570 default: | 570 default: |
571 return false; | 571 return false; |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 return RETRY; | 1060 return RETRY; |
1061 } | 1061 } |
1062 | 1062 |
1063 // Prepare for possible GC. | 1063 // Prepare for possible GC. |
1064 HandleScope handles(isolate); | 1064 HandleScope handles(isolate); |
1065 Handle<Code> code_handle(re_code); | 1065 Handle<Code> code_handle(re_code); |
1066 | 1066 |
1067 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1067 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
1068 | 1068 |
1069 // Current string. | 1069 // Current string. |
1070 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1070 bool is_one_byte = subject->IsOneByteRepresentationUnderneath(); |
1071 | 1071 |
1072 DCHECK(re_code->instruction_start() <= *return_address); | 1072 DCHECK(re_code->instruction_start() <= *return_address); |
1073 DCHECK(*return_address <= | 1073 DCHECK(*return_address <= |
1074 re_code->instruction_start() + re_code->instruction_size()); | 1074 re_code->instruction_start() + re_code->instruction_size()); |
1075 | 1075 |
1076 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1076 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1077 | 1077 |
1078 if (*code_handle != re_code) { // Return address no longer valid | 1078 if (*code_handle != re_code) { // Return address no longer valid |
1079 int delta = code_handle->address() - re_code->address(); | 1079 int delta = code_handle->address() - re_code->address(); |
1080 // Overwrite the return address on the stack. | 1080 // Overwrite the return address on the stack. |
(...skipping 10 matching lines...) Expand all Loading... |
1091 // Extract the underlying string and the slice offset. | 1091 // Extract the underlying string and the slice offset. |
1092 if (StringShape(*subject_tmp).IsCons()) { | 1092 if (StringShape(*subject_tmp).IsCons()) { |
1093 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); | 1093 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); |
1094 } else if (StringShape(*subject_tmp).IsSliced()) { | 1094 } else if (StringShape(*subject_tmp).IsSliced()) { |
1095 SlicedString* slice = SlicedString::cast(*subject_tmp); | 1095 SlicedString* slice = SlicedString::cast(*subject_tmp); |
1096 subject_tmp = Handle<String>(slice->parent()); | 1096 subject_tmp = Handle<String>(slice->parent()); |
1097 slice_offset = slice->offset(); | 1097 slice_offset = slice->offset(); |
1098 } | 1098 } |
1099 | 1099 |
1100 // String might have changed. | 1100 // String might have changed. |
1101 if (subject_tmp->IsOneByteRepresentation() != is_ascii) { | 1101 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) { |
1102 // If we changed between an ASCII and an UC16 string, the specialized | 1102 // If we changed between an Latin1 and an UC16 string, the specialized |
1103 // code cannot be used, and we need to restart regexp matching from | 1103 // code cannot be used, and we need to restart regexp matching from |
1104 // scratch (including, potentially, compiling a new version of the code). | 1104 // scratch (including, potentially, compiling a new version of the code). |
1105 return RETRY; | 1105 return RETRY; |
1106 } | 1106 } |
1107 | 1107 |
1108 // Otherwise, the content of the string might have moved. It must still | 1108 // Otherwise, the content of the string might have moved. It must still |
1109 // be a sequential or external string with the same content. | 1109 // be a sequential or external string with the same content. |
1110 // Update the start and end pointers in the stack frame to the current | 1110 // Update the start and end pointers in the stack frame to the current |
1111 // location (whether it has actually moved or not). | 1111 // location (whether it has actually moved or not). |
1112 DCHECK(StringShape(*subject_tmp).IsSequential() || | 1112 DCHECK(StringShape(*subject_tmp).IsSequential() || |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1242 offset = r4; | 1242 offset = r4; |
1243 } | 1243 } |
1244 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1244 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
1245 // and the operating system running on the target allow it. | 1245 // and the operating system running on the target allow it. |
1246 // If unaligned load/stores are not supported then this function must only | 1246 // If unaligned load/stores are not supported then this function must only |
1247 // be used to load a single character at a time. | 1247 // be used to load a single character at a time. |
1248 if (!CanReadUnaligned()) { | 1248 if (!CanReadUnaligned()) { |
1249 DCHECK(characters == 1); | 1249 DCHECK(characters == 1); |
1250 } | 1250 } |
1251 | 1251 |
1252 if (mode_ == ASCII) { | 1252 if (mode_ == LATIN1) { |
1253 if (characters == 4) { | 1253 if (characters == 4) { |
1254 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); | 1254 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); |
1255 } else if (characters == 2) { | 1255 } else if (characters == 2) { |
1256 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); | 1256 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); |
1257 } else { | 1257 } else { |
1258 DCHECK(characters == 1); | 1258 DCHECK(characters == 1); |
1259 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); | 1259 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); |
1260 } | 1260 } |
1261 } else { | 1261 } else { |
1262 DCHECK(mode_ == UC16); | 1262 DCHECK(mode_ == UC16); |
1263 if (characters == 2) { | 1263 if (characters == 2) { |
1264 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); | 1264 __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); |
1265 } else { | 1265 } else { |
1266 DCHECK(characters == 1); | 1266 DCHECK(characters == 1); |
1267 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); | 1267 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); |
1268 } | 1268 } |
1269 } | 1269 } |
1270 } | 1270 } |
1271 | 1271 |
1272 | 1272 |
1273 #undef __ | 1273 #undef __ |
1274 | 1274 |
1275 #endif // V8_INTERPRETED_REGEXP | 1275 #endif // V8_INTERPRETED_REGEXP |
1276 | 1276 |
1277 }} // namespace v8::internal | 1277 }} // namespace v8::internal |
1278 | 1278 |
1279 #endif // V8_TARGET_ARCH_ARM | 1279 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |