43
43
#ifndef V8_INTERPRETED_REGEXP
45
45
* This assembler uses the following register assignment convention
46
* - t7 : Temporarily stores the index of capture start after a matching pass
47
* for a global regexp.
46
48
* - t1 : Pointer to current code object (Code*) including heap object tag.
47
49
* - t2 : Current position in input, as negative offset from end of string.
48
50
* Please notice that this is the byte offset, not the character offset!
49
51
* - t3 : Currently loaded character. Must be loaded using
50
52
* LoadCurrentCharacter before using any of the dispatch methods.
51
* - t4 : points to tip of backtrack stack
53
* - t4 : Points to tip of backtrack stack
53
55
* - t6 : End of input (points to byte after last character in input).
54
56
* - fp : Frame pointer. Used to access arguments, local variables and
55
57
* RegExp registers.
56
* - sp : points to tip of C stack.
58
* - sp : Points to tip of C stack.
58
60
* The remaining registers are free for computations.
59
61
* Each call to a public method should retain this convention.
61
63
* The stack will have the following structure:
63
* - fp[56] direct_call (if 1, direct call from JavaScript code,
65
* - fp[64] Isolate* isolate (address of the current isolate)
66
* - fp[60] direct_call (if 1, direct call from JavaScript code,
64
67
* if 0, call through the runtime system).
65
* - fp[52] stack_area_base (High end of the memory area to use as
68
* - fp[56] stack_area_base (High end of the memory area to use as
66
69
* backtracking stack).
70
* - fp[52] capture array size (may fit multiple sets of matches)
67
71
* - fp[48] int* capture_array (int[num_saved_registers_], for output).
68
72
* - fp[44] secondary link/return address used by native call.
69
73
* --- sp when called ---
70
* - fp[40] return address (lr).
71
* - fp[36] old frame pointer (r11).
74
* - fp[40] return address (lr).
75
* - fp[36] old frame pointer (r11).
72
76
* - fp[0..32] backup of registers s0..s7.
73
77
* --- frame pointer ----
74
* - fp[-4] end of input (Address of end of string).
75
* - fp[-8] start of input (Address of first character in string).
78
* - fp[-4] end of input (address of end of string).
79
* - fp[-8] start of input (address of first character in string).
76
80
* - fp[-12] start index (character index of start).
77
81
* - fp[-16] void* input_string (location of a handle containing the string).
78
* - fp[-20] Offset of location before start of input (effectively character
82
* - fp[-20] success counter (only for global regexps to count matches).
83
* - fp[-24] Offset of location before start of input (effectively character
79
84
* position -1). Used to initialize capture registers to a
81
* - fp[-24] At start (if 1, we are starting at the start of the
86
* - fp[-28] At start (if 1, we are starting at the start of the
82
87
* string, otherwise 0)
83
* - fp[-28] register 0 (Only positions must be stored in the first
88
* - fp[-32] register 0 (Only positions must be stored in the first
84
89
* - register 1 num_saved_registers_ registers)
86
91
* - register num_registers-1
115
120
RegExpMacroAssemblerMIPS::RegExpMacroAssemblerMIPS(
117
int registers_to_save)
118
: masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
122
int registers_to_save,
124
: NativeRegExpMacroAssembler(zone),
125
masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
120
127
num_registers_(registers_to_save),
121
128
num_saved_registers_(registers_to_save),
201
208
void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) {
202
209
Label not_at_start;
203
210
// Did we start the match at the start of the string at all?
204
__ lw(a0, MemOperand(frame_pointer(), kAtStart));
205
BranchOrBacktrack(¬_at_start, eq, a0, Operand(zero_reg));
211
__ lw(a0, MemOperand(frame_pointer(), kStartIndex));
212
BranchOrBacktrack(¬_at_start, ne, a0, Operand(zero_reg));
207
214
// If we did, are we still at the start of the input?
208
215
__ lw(a1, MemOperand(frame_pointer(), kInputStart));
215
222
void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) {
216
223
// Did we start the match at the start of the string at all?
217
__ lw(a0, MemOperand(frame_pointer(), kAtStart));
218
BranchOrBacktrack(on_not_at_start, eq, a0, Operand(zero_reg));
224
__ lw(a0, MemOperand(frame_pointer(), kStartIndex));
225
BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg));
219
226
// If we did, are we still at the start of the input?
220
227
__ lw(a1, MemOperand(frame_pointer(), kInputStart));
221
228
__ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
378
385
__ li(a3, Operand(ExternalReference::isolate_address()));
380
ExternalReference function =
381
ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
382
__ CallCFunction(function, argument_count);
388
AllowExternalCallThatCantCauseGC scope(masm_);
389
ExternalReference function =
390
ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
391
__ CallCFunction(function, argument_count);
384
394
// Restore regexp engine registers.
385
395
__ MultiPop(regexp_registers_to_retain);
386
__ li(code_pointer(), Operand(masm_->CodeObject()));
396
__ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
387
397
__ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
389
399
// Check if function returned non-zero for success or zero for failure.
444
void RegExpMacroAssemblerMIPS::CheckNotRegistersEqual(int reg1,
446
Label* on_not_equal) {
447
UNIMPLEMENTED_MIPS();
451
454
void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
452
Label* on_not_equal) {
455
Label* on_not_equal) {
453
456
BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c));
457
460
void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c,
460
463
__ And(a0, current_character(), Operand(mask));
461
BranchOrBacktrack(on_equal, eq, a0, Operand(c));
464
Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
465
BranchOrBacktrack(on_equal, eq, a0, rhs);
465
469
void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
467
Label* on_not_equal) {
471
Label* on_not_equal) {
468
472
__ And(a0, current_character(), Operand(mask));
469
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
473
Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
474
BranchOrBacktrack(on_not_equal, ne, a0, rhs);
477
482
Label* on_not_equal) {
478
UNIMPLEMENTED_MIPS();
483
ASSERT(minus < String::kMaxUtf16CodeUnit);
484
__ Subu(a0, current_character(), Operand(minus));
485
__ And(a0, a0, Operand(mask));
486
BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
490
void RegExpMacroAssemblerMIPS::CheckCharacterInRange(
493
Label* on_in_range) {
494
__ Subu(a0, current_character(), Operand(from));
495
// Unsigned lower-or-same condition.
496
BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
500
void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
503
Label* on_not_in_range) {
504
__ Subu(a0, current_character(), Operand(from));
505
// Unsigned higher condition.
506
BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
510
void RegExpMacroAssemblerMIPS::CheckBitInTable(
511
Handle<ByteArray> table,
513
__ li(a0, Operand(table));
514
if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
515
__ And(a1, current_character(), Operand(kTableSize - 1));
518
__ Addu(a0, a0, current_character());
521
__ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize));
522
BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
482
526
bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
483
Label* on_no_match) {
527
Label* on_no_match) {
484
528
// Range checks (c in min..max) are generally implemented by an unsigned
485
529
// (c - min) <= (max - min) check.
639
691
// Exit with OutOfMemory exception. There is not enough space on the stack
640
692
// for our working registers.
641
693
__ li(v0, Operand(EXCEPTION));
642
__ jmp(&exit_label_);
644
696
__ bind(&stack_limit_hit);
645
697
CallCheckStackGuardState(a0);
646
698
// If returned value is non-zero, we exit with the returned value as result.
647
__ Branch(&exit_label_, ne, v0, Operand(zero_reg));
699
__ Branch(&return_v0, ne, v0, Operand(zero_reg));
649
701
__ bind(&stack_ok);
650
702
// Allocate space on stack for registers.
665
717
// position registers.
666
718
__ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
668
// Determine whether the start index is zero, that is at the start of the
669
// string, and store that value in a local variable.
671
__ li(a1, Operand(1));
672
__ movn(a1, zero_reg, t5);
673
__ sw(a1, MemOperand(frame_pointer(), kAtStart));
720
// Initialize code pointer register
721
__ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
723
Label load_char_start_regexp, start_regexp;
724
// Load newline if index is at start, previous character otherwise.
725
__ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg));
726
__ li(current_character(), Operand('\n'));
727
__ jmp(&start_regexp);
729
// Global regexp restarts matching here.
730
__ bind(&load_char_start_regexp);
731
// Load previous char as initial value of current character register.
732
LoadCurrentCharacterUnchecked(-1, 1);
733
__ bind(&start_regexp);
735
// Initialize on-stack registers.
675
736
if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
676
737
// Fill saved registers with initial value = start offset - 1.
678
// Address of register 0.
679
__ Addu(a1, frame_pointer(), Operand(kRegisterZero));
680
__ li(a2, Operand(num_saved_registers_));
683
__ sw(a0, MemOperand(a1));
684
__ Addu(a1, a1, Operand(-kPointerSize));
685
__ Subu(a2, a2, Operand(1));
686
__ Branch(&init_loop, ne, a2, Operand(zero_reg));
738
if (num_saved_registers_ > 8) {
739
// Address of register 0.
740
__ Addu(a1, frame_pointer(), Operand(kRegisterZero));
741
__ li(a2, Operand(num_saved_registers_));
744
__ sw(a0, MemOperand(a1));
745
__ Addu(a1, a1, Operand(-kPointerSize));
746
__ Subu(a2, a2, Operand(1));
747
__ Branch(&init_loop, ne, a2, Operand(zero_reg));
749
for (int i = 0; i < num_saved_registers_; i++) {
750
__ sw(a0, register_location(i));
689
755
// Initialize backtrack stack pointer.
690
756
__ lw(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
691
// Initialize code pointer register
692
__ li(code_pointer(), Operand(masm_->CodeObject()));
693
// Load previous char as initial value of current character register.
695
__ lw(a0, MemOperand(frame_pointer(), kAtStart));
696
__ Branch(&at_start, ne, a0, Operand(zero_reg));
697
LoadCurrentCharacterUnchecked(-1, 1); // Load previous char.
698
__ jmp(&start_label_);
700
__ li(current_character(), Operand('\n'));
701
758
__ jmp(&start_label_);
741
802
__ Addu(a0, a0, kPointerSize);
744
__ li(v0, Operand(SUCCESS));
807
// Restart matching if the regular expression is flagged as global.
808
__ lw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
809
__ lw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
810
__ lw(a2, MemOperand(frame_pointer(), kRegisterOutput));
811
// Increment success counter.
813
__ sw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
814
// Capture results have been stored, so the number of remaining global
815
// output registers is reduced by the number of stored captures.
816
__ Subu(a1, a1, num_saved_registers_);
817
// Check whether we have enough room for another set of capture results.
819
__ Branch(&return_v0, lt, a1, Operand(num_saved_registers_));
821
__ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
822
// Advance the location for output.
823
__ Addu(a2, a2, num_saved_registers_ * kPointerSize);
824
__ sw(a2, MemOperand(frame_pointer(), kRegisterOutput));
826
// Prepare a0 to initialize registers with its value in the next run.
827
__ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
829
if (global_with_zero_length_check()) {
830
// Special case for zero-length matches.
831
// t7: capture start index
832
// Not a zero-length match, restart.
834
&load_char_start_regexp, ne, current_input_offset(), Operand(t7));
835
// Offset from the end is zero if we already reached the end.
836
__ Branch(&exit_label_, eq, current_input_offset(),
838
// Advance current position after a zero-length match.
839
__ Addu(current_input_offset(),
840
current_input_offset(),
841
Operand((mode_ == UC16) ? 2 : 1));
844
__ Branch(&load_char_start_regexp);
846
__ li(v0, Operand(SUCCESS));
746
849
// Exit and return v0.
747
850
__ bind(&exit_label_);
852
__ lw(v0, MemOperand(frame_pointer(), kSuccessfulCaptures));
748
856
// Skip sp past regexp registers and local variables..
749
857
__ mov(sp, frame_pointer());
750
858
// Restore registers s0..s7 and return (restoring ra to pc).
770
878
__ MultiPop(regexp_registers_to_retain);
771
879
// If returning non-zero, we should end execution with the given
772
880
// result as return value.
773
__ Branch(&exit_label_, ne, v0, Operand(zero_reg));
881
__ Branch(&return_v0, ne, v0, Operand(zero_reg));
775
883
// String might have moved: Reload end of string from frame.
776
884
__ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
777
__ li(code_pointer(), Operand(masm_->CodeObject()));
885
__ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
841
949
void RegExpMacroAssemblerMIPS::IfRegisterGE(int reg,
844
952
__ lw(a0, register_location(reg));
845
953
BranchOrBacktrack(if_ge, ge, a0, Operand(comparand));
849
957
void RegExpMacroAssemblerMIPS::IfRegisterLT(int reg,
852
960
__ lw(a0, register_location(reg));
853
961
BranchOrBacktrack(if_lt, lt, a0, Operand(comparand));
857
965
void RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg,
859
967
__ lw(a0, register_location(reg));
860
968
BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset()));
1103
1217
frame_entry<const String*>(re_frame, kInputString) = *subject;
1104
1218
frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1105
1219
frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1220
} else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1221
// Subject string might have been a ConsString that underwent
1222
// short-circuiting during GC. That will not change start_address but
1223
// will change pointer inside the subject handle.
1224
frame_entry<const String*>(re_frame, kInputString) = *subject;
1215
1336
if (OS::ActivationFrameAlignment() != 0) {
1216
1337
__ lw(sp, MemOperand(sp, 16));
1218
__ li(code_pointer(), Operand(masm_->CodeObject()));
1339
__ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
1222
1343
void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
1224
1345
Register offset = current_input_offset();
1225
1346
if (cp_offset != 0) {
1226
__ Addu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1347
// t7 is not being used to store the capture start index at this point.
1348
__ Addu(t7, current_input_offset(), Operand(cp_offset * char_size()));
1229
1351
// We assume that we cannot do unaligned loads on MIPS, so this function
1230
1352
// must only be used to load a single character at a time.
1244
1366
if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
1245
1367
// Stack is already aligned for call, so decrement by alignment
1246
1368
// to make room for storing the return address.
1247
__ Subu(sp, sp, Operand(stack_alignment));
1248
__ sw(ra, MemOperand(sp, 0));
1369
__ Subu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));
1370
const int return_address_offset = kCArgsSlotsSize;
1371
__ Addu(a0, sp, return_address_offset);
1372
__ sw(ra, MemOperand(a0, 0));
1250
1373
__ mov(t9, t1);
1252
__ lw(ra, MemOperand(sp, 0));
1253
__ Addu(sp, sp, Operand(stack_alignment));
1375
__ lw(ra, MemOperand(sp, return_address_offset));
1376
__ Addu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));