5#if V8_TARGET_ARCH_MIPS64
122#define __ ACCESS_MASM(masm_)
126 int registers_to_save)
127 : NativeRegExpMacroAssembler(isolate, zone),
128 masm_(
std::make_unique<MacroAssembler>(
131 no_root_array_scope_(
masm_.get()),
133 num_registers_(registers_to_save),
134 num_saved_registers_(registers_to_save),
140 internal_failure_label_() {
142 __ jmp(&entry_label_);
145 __ bind(&internal_failure_label_);
146 __ li(v0, Operand(FAILURE));
148 __ bind(&start_label_);
151RegExpMacroAssemblerMIPS::~RegExpMacroAssemblerMIPS() {
153 entry_label_.Unuse();
154 start_label_.Unuse();
155 success_label_.Unuse();
156 backtrack_label_.Unuse();
158 check_preempt_label_.Unuse();
159 stack_overflow_label_.Unuse();
160 internal_failure_label_.Unuse();
161 fallback_label_.Unuse();
164int RegExpMacroAssemblerMIPS::stack_limit_slack_slot_count() {
165 return RegExpStack::kStackLimitSlackSlotCount;
168void RegExpMacroAssemblerMIPS::AdvanceCurrentPosition(
int by) {
170 __ Daddu(current_input_offset(),
171 current_input_offset(), Operand(by * char_size()));
176void RegExpMacroAssemblerMIPS::AdvanceRegister(
int reg,
int by) {
180 __ Ld(a0, register_location(
reg));
181 __ Daddu(a0, a0, Operand(by));
182 __ Sd(a0, register_location(
reg));
187void RegExpMacroAssemblerMIPS::Backtrack() {
189 if (has_backtrack_limit()) {
191 __ Ld(a0,
MemOperand(frame_pointer(), kBacktrackCountOffset));
192 __ Daddu(a0, a0, Operand(1));
193 __ Sd(a0,
MemOperand(frame_pointer(), kBacktrackCountOffset));
194 __ Branch(&next, ne, a0, Operand(backtrack_limit()));
197 if (can_fallback()) {
198 __ jmp(&fallback_label_);
208 __ Daddu(a0, a0, code_pointer());
213void RegExpMacroAssemblerMIPS::Bind(Label*
label) {
218void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) {
219 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c));
222void RegExpMacroAssemblerMIPS::CheckCharacterGT(base::uc16 limit,
224 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit));
227void RegExpMacroAssemblerMIPS::CheckAtStart(
int cp_offset, Label* on_at_start) {
228 __ Ld(a1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
229 __ Daddu(a0, current_input_offset(),
230 Operand(-char_size() + cp_offset * char_size()));
231 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1));
235void RegExpMacroAssemblerMIPS::CheckNotAtStart(
int cp_offset,
236 Label* on_not_at_start) {
237 __ Ld(a1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
238 __ Daddu(a0, current_input_offset(),
239 Operand(-char_size() + cp_offset * char_size()));
240 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1));
243void RegExpMacroAssemblerMIPS::CheckCharacterLT(base::uc16 limit,
245 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit));
248void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
249 Label backtrack_non_equal;
251 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0));
252 __ Daddu(backtrack_stackpointer(),
253 backtrack_stackpointer(),
255 __ bind(&backtrack_non_equal);
256 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0));
259void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase(
260 int start_reg,
bool read_backward,
bool unicode, Label* on_no_match) {
262 __ Ld(a0, register_location(start_reg));
263 __ Ld(a1, register_location(start_reg + 1));
264 __ Dsubu(a1, a1, a0);
269 __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
272 __ Ld(t1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
273 __ Daddu(t1, t1, a1);
274 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1));
276 __ Daddu(t1, a1, current_input_offset());
278 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg));
281 if (
mode_ == LATIN1) {
288 __ Daddu(a0, a0, Operand(end_of_input_address()));
289 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset()));
291 __ Dsubu(a2, a2, Operand(a1));
293 __ Daddu(a1, a0, Operand(a1));
302 __ daddiu(a0, a0, char_size());
304 __ daddiu(a2, a2, char_size());
306 __ Branch(&loop_check, eq, a4, Operand(a3));
309 __ Or(a3, a3, Operand(0x20));
310 __ Or(a4, a4, Operand(0x20));
311 __ Branch(&fail, ne, a4, Operand(a3));
312 __ Dsubu(a3, a3, Operand(
'a'));
313 __ Branch(&loop_check, ls, a3, Operand(
'z' -
'a'));
315 __ Dsubu(a3, a3, Operand(224 -
'a'));
317 __ Branch(&fail, hi, a3, Operand(254 - 224));
319 __ Branch(&fail, eq, a3, Operand(247 - 224));
321 __ bind(&loop_check);
322 __ Branch(&loop, lt, a0, Operand(a1));
330 __ Dsubu(current_input_offset(), a2, end_of_input_address());
332 __ Ld(t1, register_location(start_reg));
333 __ Ld(a2, register_location(start_reg + 1));
334 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1));
335 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2));
340 int argument_count = 4;
341 __ PrepareCallCFunction(argument_count, a2);
354 __ Daddu(a0, a0, Operand(end_of_input_address()));
360 __ Daddu(a1, current_input_offset(), Operand(end_of_input_address()));
362 __ Dsubu(a1, a1, Operand(s3));
365 __ li(a3, Operand(ExternalReference::isolate_address(
masm_->isolate())));
368 AllowExternalCallThatCantCauseGC scope(
masm_.get());
369 ExternalReference function =
371 ? ExternalReference::re_case_insensitive_compare_unicode()
372 : ExternalReference::re_case_insensitive_compare_non_unicode();
373 CallCFunctionFromIrregexpCode(function, argument_count);
377 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg));
380 __ Dsubu(current_input_offset(), current_input_offset(), Operand(s3));
382 __ Daddu(current_input_offset(), current_input_offset(), Operand(s3));
386 __ bind(&fallthrough);
389void RegExpMacroAssemblerMIPS::CheckNotBackReference(
int start_reg,
391 Label* on_no_match) {
395 __ Ld(a0, register_location(start_reg));
396 __ Ld(a1, register_location(start_reg + 1));
397 __ Dsubu(a1, a1, a0);
402 __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
405 __ Ld(t1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
406 __ Daddu(t1, t1, a1);
407 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1));
409 __ Daddu(t1, a1, current_input_offset());
411 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg));
415 __ Daddu(a0, a0, Operand(end_of_input_address()));
416 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset()));
418 __ Dsubu(a2, a2, Operand(a1));
420 __ Daddu(a1, a1, Operand(a0));
424 if (
mode_ == LATIN1) {
426 __ daddiu(a0, a0, char_size());
428 __ daddiu(a2, a2, char_size());
432 __ daddiu(a0, a0, char_size());
434 __ daddiu(a2, a2, char_size());
436 BranchOrBacktrack(on_no_match, ne, a3, Operand(a4));
437 __ Branch(&loop, lt, a0, Operand(a1));
440 __ Dsubu(current_input_offset(), a2, end_of_input_address());
442 __ Ld(t1, register_location(start_reg));
443 __ Ld(a2, register_location(start_reg + 1));
444 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1));
445 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2));
447 __ bind(&fallthrough);
451void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
452 Label* on_not_equal) {
453 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c));
457void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c,
460 __ And(a0, current_character(), Operand(
mask));
461 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
462 BranchOrBacktrack(on_equal, eq, a0, rhs);
466void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
468 Label* on_not_equal) {
469 __ And(a0, current_character(), Operand(
mask));
470 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
471 BranchOrBacktrack(on_not_equal, ne, a0, rhs);
474void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
475 base::uc16 c, base::uc16 minus, base::uc16
mask, Label* on_not_equal) {
476 DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
477 __ Dsubu(a0, current_character(), Operand(minus));
479 BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
482void RegExpMacroAssemblerMIPS::CheckCharacterInRange(base::uc16 from,
484 Label* on_in_range) {
485 __ Dsubu(a0, current_character(), Operand(from));
487 BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
490void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
491 base::uc16 from, base::uc16 to, Label* on_not_in_range) {
492 __ Dsubu(a0, current_character(), Operand(from));
494 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
497void RegExpMacroAssemblerMIPS::CallIsCharacterInRangeArray(
498 const ZoneList<CharacterRange>* ranges) {
499 static const int kNumArguments = 3;
500 __ PrepareCallCFunction(kNumArguments, a0);
502 __ mov(a0, current_character());
503 __ li(a1, Operand(GetOrAddRangeArray(ranges)));
504 __ li(a2, Operand(ExternalReference::isolate_address(
isolate())));
508 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
509 CallCFunctionFromIrregexpCode(
510 ExternalReference::re_is_character_in_range_array(), kNumArguments);
513 __ li(code_pointer(), Operand(
masm_->CodeObject()));
516bool RegExpMacroAssemblerMIPS::CheckCharacterInRangeArray(
517 const ZoneList<CharacterRange>* ranges, Label* on_in_range) {
518 CallIsCharacterInRangeArray(ranges);
519 BranchOrBacktrack(on_in_range, ne, v0, Operand(zero_reg));
523bool RegExpMacroAssemblerMIPS::CheckCharacterNotInRangeArray(
524 const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) {
525 CallIsCharacterInRangeArray(ranges);
526 BranchOrBacktrack(on_not_in_range, eq, v0, Operand(zero_reg));
530void RegExpMacroAssemblerMIPS::CheckBitInTable(
531 Handle<ByteArray> table,
533 __ li(a0, Operand(table));
534 if (
mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
535 __ And(a1, current_character(), Operand(kTableSize - 1));
536 __ Daddu(a0, a0, a1);
538 __ Daddu(a0, a0, current_character());
542 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
545void RegExpMacroAssemblerMIPS::SkipUntilBitInTable(
546 int cp_offset, Handle<ByteArray> table, Handle<ByteArray> nibble_table,
551 LoadCurrentCharacter(cp_offset, &cont,
true);
552 CheckBitInTable(table, &cont);
553 AdvanceCurrentPosition(advance_by);
558bool RegExpMacroAssemblerMIPS::CheckSpecialClassRanges(
559 StandardCharacterSet type, Label* on_no_match) {
564 case StandardCharacterSet::kWhitespace:
566 if (
mode_ == LATIN1) {
569 __ Branch(&success, eq, current_character(), Operand(
' '));
571 __ Dsubu(a0, current_character(), Operand(
'\t'));
572 __ Branch(&success, ls, a0, Operand(
'\r' -
'\t'));
574 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00A0 -
'\t'));
579 case StandardCharacterSet::kNotWhitespace:
582 case StandardCharacterSet::kDigit:
584 __ Dsubu(a0, current_character(), Operand(
'0'));
585 BranchOrBacktrack(on_no_match, hi, a0, Operand(
'9' -
'0'));
587 case StandardCharacterSet::kNotDigit:
589 __ Dsubu(a0, current_character(), Operand(
'0'));
590 BranchOrBacktrack(on_no_match, ls, a0, Operand(
'9' -
'0'));
592 case StandardCharacterSet::kNotLineTerminator: {
594 __ Xor(a0, current_character(), Operand(0x01));
596 __ Dsubu(a0, a0, Operand(0x0B));
597 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0C - 0x0B));
602 __ Dsubu(a0, a0, Operand(0x2028 - 0x0B));
603 BranchOrBacktrack(on_no_match, ls, a0, Operand(1));
607 case StandardCharacterSet::kLineTerminator: {
609 __ Xor(a0, current_character(), Operand(0x01));
611 __ Dsubu(a0, a0, Operand(0x0B));
612 if (
mode_ == LATIN1) {
613 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0C - 0x0B));
616 BranchOrBacktrack(&done, ls, a0, Operand(0x0C - 0x0B));
620 __ Dsubu(a0, a0, Operand(0x2028 - 0x0B));
621 BranchOrBacktrack(on_no_match, hi, a0, Operand(1));
626 case StandardCharacterSet::kWord: {
627 if (
mode_ != LATIN1) {
629 BranchOrBacktrack(on_no_match, hi, current_character(), Operand(
'z'));
631 ExternalReference map = ExternalReference::re_word_character_map();
632 __ li(a0, Operand(map));
633 __ Daddu(a0, a0, current_character());
635 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg));
638 case StandardCharacterSet::kNotWord: {
640 if (
mode_ != LATIN1) {
642 __ Branch(&done, hi, current_character(), Operand(
'z'));
644 ExternalReference map = ExternalReference::re_word_character_map();
645 __ li(a0, Operand(map));
646 __ Daddu(a0, a0, current_character());
648 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg));
649 if (
mode_ != LATIN1) {
654 case StandardCharacterSet::kEverything:
660void RegExpMacroAssemblerMIPS::Fail() {
661 __ li(v0, Operand(FAILURE));
662 __ jmp(&exit_label_);
665void RegExpMacroAssemblerMIPS::LoadRegExpStackPointerFromMemory(Register dst) {
666 ExternalReference ref =
667 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
668 __ li(dst, Operand(ref));
672void RegExpMacroAssemblerMIPS::StoreRegExpStackPointerToMemory(
673 Register src, Register scratch) {
674 ExternalReference ref =
675 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
676 __ li(scratch, Operand(ref));
680void RegExpMacroAssemblerMIPS::PushRegExpBasePointer(Register stack_pointer,
682 ExternalReference ref =
683 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
684 __ li(scratch, Operand(ref));
686 __ Dsubu(scratch, stack_pointer, scratch);
687 __ Sd(scratch,
MemOperand(frame_pointer(), kRegExpStackBasePointerOffset));
690void RegExpMacroAssemblerMIPS::PopRegExpBasePointer(Register stack_pointer_out,
692 ExternalReference ref =
693 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
694 __ Ld(stack_pointer_out,
695 MemOperand(frame_pointer(), kRegExpStackBasePointerOffset));
696 __ li(scratch, Operand(ref));
698 __ Daddu(stack_pointer_out, stack_pointer_out, scratch);
699 StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
702DirectHandle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(
703 DirectHandle<String> source, RegExpFlags flags) {
705 if (
masm_->has_exception()) {
709 __ bind_to(&entry_label_, internal_failure_label_.pos());
715 __ bind(&entry_label_);
719 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
726 RegList registers_to_retain = {s0, s1, s2, s3, s4, s5, s6, s7, fp};
728 __ MultiPush(registers_to_retain | ra);
729 __ mov(frame_pointer(), sp);
738 RegList argument_registers = {a0, a1, a2, a3};
739 argument_registers |= {a4, a5, a6, a7};
742 __ li(
kScratchReg, Operand(StackFrame::TypeToMarker(StackFrame::IRREGEXP)));
744 static_assert(kInputEndOffset ==
751 static_assert(kSuccessfulCapturesOffset ==
753 __ mov(a0, zero_reg);
755 static_assert(kStringStartMinusOneOffset ==
758 static_assert(kBacktrackCountOffset ==
761 static_assert(kRegExpStackBasePointerOffset ==
767 static_assert(backtrack_stackpointer() == s7);
768 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
772 PushRegExpBasePointer(backtrack_stackpointer(), a1);
776 Label stack_limit_hit, stack_ok;
778 ExternalReference stack_limit =
779 ExternalReference::address_of_jslimit(
masm_->isolate());
780 Operand extra_space_for_variables(num_registers_ * kPointerSize);
782 __ li(a0, Operand(stack_limit));
784 __ Dsubu(a0, sp, a0);
786 __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg));
789 __ Branch(&stack_ok, hs, a0, extra_space_for_variables);
792 __ li(v0, Operand(EXCEPTION));
795 __ bind(&stack_limit_hit);
796 CallCheckStackGuardState(a0, extra_space_for_variables);
799 __ Branch(&return_v0, ne, v0, Operand(zero_reg));
805 __ Dsubu(sp, sp, Operand(num_registers_ * kPointerSize));
807 __ Ld(end_of_input_address(),
MemOperand(frame_pointer(), kInputEndOffset));
809 __ Ld(a0,
MemOperand(frame_pointer(), kInputStartOffset));
811 __ Dsubu(current_input_offset(), a0, end_of_input_address());
814 __ Ld(a1,
MemOperand(frame_pointer(), kStartIndexOffset));
815 __ Dsubu(a0, current_input_offset(), Operand(char_size()));
816 __ dsll(t1, a1, (
mode_ == UC16) ? 1 : 0);
817 __ Dsubu(a0, a0, t1);
820 __ Sd(a0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
823 __ li(code_pointer(), Operand(
masm_->CodeObject()), CONSTANT_SIZE);
825 Label load_char_start_regexp;
829 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg));
830 __ li(current_character(), Operand(
'\n'));
831 __ jmp(&start_regexp);
834 __ bind(&load_char_start_regexp);
836 LoadCurrentCharacterUnchecked(-1, 1);
837 __ bind(&start_regexp);
841 if (num_saved_registers_ > 0) {
843 if (num_saved_registers_ > 8) {
845 __ Daddu(a1, frame_pointer(), Operand(kRegisterZeroOffset));
846 __ li(a2, Operand(num_saved_registers_));
850 __ Daddu(a1, a1, Operand(-kPointerSize));
851 __ Dsubu(a2, a2, Operand(1));
852 __ Branch(&init_loop, ne, a2, Operand(zero_reg));
854 for (
int i = 0;
i < num_saved_registers_;
i++) {
855 __ Sd(a0, register_location(
i));
860 __ jmp(&start_label_);
863 if (success_label_.is_linked()) {
865 __ bind(&success_label_);
866 if (num_saved_registers_ > 0) {
868 __ Ld(a1,
MemOperand(frame_pointer(), kInputStartOffset));
869 __ Ld(a0,
MemOperand(frame_pointer(), kRegisterOutputOffset));
870 __ Ld(a2,
MemOperand(frame_pointer(), kStartIndexOffset));
871 __ Dsubu(a1, end_of_input_address(), a1);
877 __ Daddu(a1, a1, Operand(a2));
884 for (
int i = 0;
i < num_saved_registers_;
i += 2) {
885 __ Ld(a2, register_location(
i));
886 __ Ld(a3, register_location(
i + 1));
887 if (
i == 0 && global_with_zero_length_check()) {
893 __ Daddu(a2, a2, a1);
895 __ Daddu(a3, a3, a1);
897 __ Daddu(a2, a1, Operand(a2));
898 __ Daddu(a3, a1, Operand(a3));
902 __ Daddu(a0, a0, kIntSize);
904 __ Daddu(a0, a0, kIntSize);
910 __ Ld(a0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
911 __ Ld(a1,
MemOperand(frame_pointer(), kNumOutputRegistersOffset));
912 __ Ld(a2,
MemOperand(frame_pointer(), kRegisterOutputOffset));
915 __ Sd(a0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
918 __ Dsubu(a1, a1, num_saved_registers_);
921 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_));
923 __ Sd(a1,
MemOperand(frame_pointer(), kNumOutputRegistersOffset));
925 __ Daddu(a2, a2, num_saved_registers_ * kIntSize);
926 __ Sd(a2,
MemOperand(frame_pointer(), kRegisterOutputOffset));
930 PopRegExpBasePointer(backtrack_stackpointer(), a2);
932 Label reload_string_start_minus_one;
934 if (global_with_zero_length_check()) {
938 __ Branch(&reload_string_start_minus_one, ne, current_input_offset(),
941 __ Branch(&exit_label_, eq, current_input_offset(),
946 __ Daddu(current_input_offset(), current_input_offset(),
947 Operand((
mode_ == UC16) ? 2 : 1));
948 if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
951 __ bind(&reload_string_start_minus_one);
954 __ Ld(a0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
956 __ Branch(&load_char_start_regexp);
958 __ li(v0, Operand(SUCCESS));
962 __ bind(&exit_label_);
964 __ Ld(v0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
970 PopRegExpBasePointer(backtrack_stackpointer(), a1);
973 __ mov(sp, frame_pointer());
975 __ MultiPop(registers_to_retain | ra);
979 if (backtrack_label_.is_linked()) {
980 __ bind(&backtrack_label_);
984 Label exit_with_exception;
987 if (check_preempt_label_.is_linked()) {
988 SafeCallTarget(&check_preempt_label_);
989 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), a0);
991 CallCheckStackGuardState(a0);
994 __ Branch(&return_v0, ne, v0, Operand(zero_reg));
996 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
999 __ Ld(end_of_input_address(),
1000 MemOperand(frame_pointer(), kInputEndOffset));
1005 if (stack_overflow_label_.is_linked()) {
1006 SafeCallTarget(&stack_overflow_label_);
1007 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), a0);
1011 static constexpr int kNumArguments = 1;
1012 __ PrepareCallCFunction(kNumArguments, a0);
1013 __ li(a0, Operand(ExternalReference::isolate_address(
masm_->isolate())));
1014 ExternalReference
grow_stack = ExternalReference::re_grow_stack();
1015 CallCFunctionFromIrregexpCode(grow_stack, kNumArguments);
1018 __ Branch(&exit_with_exception, eq, v0, Operand(zero_reg));
1020 __ mov(backtrack_stackpointer(), v0);
1024 if (exit_with_exception.is_linked()) {
1026 __ bind(&exit_with_exception);
1028 __ li(v0, Operand(EXCEPTION));
1032 if (fallback_label_.is_linked()) {
1033 __ bind(&fallback_label_);
1034 __ li(v0, Operand(FALLBACK_TO_EXPERIMENTAL));
1043 .set_self_reference(
masm_->CodeObject())
1044 .set_empty_source_position_table()
1047 RegExpCodeCreateEvent(Cast<AbstractCode>(code), source, flags));
1048 return Cast<HeapObject>(code);
1051void RegExpMacroAssemblerMIPS::GoTo(Label* to) {
1052 if (to ==
nullptr) {
1060void RegExpMacroAssemblerMIPS::IfRegisterGE(
int reg,
1063 __ Ld(a0, register_location(
reg));
1064 BranchOrBacktrack(if_ge, ge, a0, Operand(comparand));
1067void RegExpMacroAssemblerMIPS::IfRegisterLT(
int reg,
1070 __ Ld(a0, register_location(
reg));
1071 BranchOrBacktrack(if_lt, lt, a0, Operand(comparand));
1074void RegExpMacroAssemblerMIPS::IfRegisterEqPos(
int reg,
1076 __ Ld(a0, register_location(
reg));
1077 BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset()));
1080RegExpMacroAssembler::IrregexpImplementation
1081 RegExpMacroAssemblerMIPS::Implementation() {
1082 return kMIPSImplementation;
1085void RegExpMacroAssemblerMIPS::PopCurrentPosition() {
1086 Pop(current_input_offset());
1089void RegExpMacroAssemblerMIPS::PopRegister(
int register_index) {
1091 __ Sd(a0, register_location(register_index));
1094void RegExpMacroAssemblerMIPS::PushBacktrack(Label*
label) {
1095 if (
label->is_bound()) {
1096 int target =
label->pos();
1098 Operand(target + InstructionStream::kHeaderSize - kHeapObjectTag));
1100 Assembler::BlockTrampolinePoolScope block_trampoline_pool(
masm_.get());
1101 Label after_constant;
1102 __ Branch(&after_constant);
1107 __ bind(&after_constant);
1108 if (is_int16(cp_offset)) {
1111 __ Daddu(a0, code_pointer(), cp_offset);
1119void RegExpMacroAssemblerMIPS::PushCurrentPosition() {
1120 Push(current_input_offset());
1124void RegExpMacroAssemblerMIPS::PushRegister(
int register_index,
1125 StackCheckFlag check_stack_limit) {
1126 __ Ld(a0, register_location(register_index));
1128 if (check_stack_limit) {
1131 AssertAboveStackLimitMinusSlack();
1135void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(
int reg) {
1136 __ Ld(current_input_offset(), register_location(
reg));
1139void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(
int reg) {
1140 ExternalReference ref =
1141 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1142 __ li(a0, Operand(ref));
1144 __ Dsubu(a0, backtrack_stackpointer(), a0);
1145 __ Sd(a0, register_location(
reg));
1148void RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(
int reg) {
1149 ExternalReference ref =
1150 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1151 __ li(a0, Operand(ref));
1153 __ Ld(backtrack_stackpointer(), register_location(
reg));
1154 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), Operand(a0));
1157void RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(
int by) {
1158 Label after_position;
1159 __ Branch(&after_position,
1161 current_input_offset(),
1162 Operand(-by * char_size()));
1163 __ li(current_input_offset(), -by * char_size());
1167 LoadCurrentCharacterUnchecked(-1, 1);
1168 __ bind(&after_position);
1171void RegExpMacroAssemblerMIPS::SetRegister(
int register_index,
int to) {
1172 DCHECK(register_index >= num_saved_registers_);
1173 __ li(a0, Operand(to));
1174 __ Sd(a0, register_location(register_index));
1177bool RegExpMacroAssemblerMIPS::Succeed() {
1178 __ jmp(&success_label_);
1182void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(
int reg,
1184 if (cp_offset == 0) {
1185 __ Sd(current_input_offset(), register_location(
reg));
1187 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1188 __ Sd(a0, register_location(
reg));
1192void RegExpMacroAssemblerMIPS::ClearRegisters(
int reg_from,
int reg_to) {
1193 DCHECK(reg_from <= reg_to);
1194 __ Ld(a0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
1195 for (
int reg = reg_from;
reg <= reg_to;
reg++) {
1196 __ Sd(a0, register_location(
reg));
1200bool RegExpMacroAssemblerMIPS::CanReadUnaligned()
const {
return false; }
1204void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch,
1205 Operand extra_space) {
1207 DCHECK(!
masm_->options().isolate_independent_code);
1209 int stack_alignment = base::OS::ActivationFrameAlignment();
1212 __ mov(scratch, sp);
1213 __ Dsubu(sp, sp, Operand(kPointerSize));
1214 DCHECK(base::bits::IsPowerOfTwo(stack_alignment));
1215 __ And(sp, sp, Operand(-stack_alignment));
1219 __ li(a3, extra_space);
1221 __ mov(a2, frame_pointer());
1223 __ li(a1, Operand(
masm_->CodeObject()), CONSTANT_SIZE);
1227 __ Dsubu(sp, sp, Operand(stack_alignment));
1232 ExternalReference stack_guard_check =
1233 ExternalReference::re_check_stack_guard_state();
1234 __ li(t9, Operand(stack_guard_check));
1236 EmbeddedData d = EmbeddedData::FromBlob();
1237 CHECK(Builtins::IsIsolateIndependent(Builtin::kDirectCEntry));
1238 Address entry = d.InstructionStartOf(Builtin::kDirectCEntry);
1239 __ li(
kScratchReg, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
1242 __ Ld(sp,
MemOperand(sp, stack_alignment + kCArgsSlotsSize));
1244 __ li(code_pointer(), Operand(
masm_->CodeObject()));
1248template <
typename T>
1249static T& frame_entry(Address re_frame,
int frame_offset) {
1250 return reinterpret_cast<T&
>(Memory<int32_t>(re_frame + frame_offset));
1253template <
typename T>
1254static T* frame_entry_address(Address re_frame,
int frame_offset) {
1255 return reinterpret_cast<T*
>(re_frame + frame_offset);
1258int64_t RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
1261 uintptr_t extra_space) {
1262 Tagged<InstructionStream> re_code =
1263 Cast<InstructionStream>(Tagged<Object>(raw_code));
1264 return NativeRegExpMacroAssembler::CheckStackGuardState(
1265 frame_entry<Isolate*>(re_frame, kIsolateOffset),
1266 static_cast<int>(frame_entry<int64_t>(re_frame, kStartIndexOffset)),
1267 static_cast<RegExp::CallOrigin
>(
1268 frame_entry<int64_t>(re_frame, kDirectCallOffset)),
1269 return_address, re_code,
1270 frame_entry_address<Address>(re_frame, kInputStringOffset),
1271 frame_entry_address<const uint8_t*>(re_frame, kInputStartOffset),
1272 frame_entry_address<const uint8_t*>(re_frame, kInputEndOffset),
1276MemOperand RegExpMacroAssemblerMIPS::register_location(
int register_index) {
1277 DCHECK(register_index < (1<<30));
1278 if (num_registers_ <= register_index) {
1279 num_registers_ = register_index + 1;
1282 kRegisterZeroOffset - register_index * kPointerSize);
1285void RegExpMacroAssemblerMIPS::CheckPosition(
int cp_offset,
1286 Label* on_outside_input) {
1287 if (cp_offset >= 0) {
1288 BranchOrBacktrack(on_outside_input, ge, current_input_offset(),
1289 Operand(-cp_offset * char_size()));
1291 __ Ld(a1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
1292 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1293 BranchOrBacktrack(on_outside_input, le, a0, Operand(a1));
1297void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to,
1300 const Operand& rt) {
1302 if (to ==
nullptr) {
1309 if (to ==
nullptr) {
1316void RegExpMacroAssemblerMIPS::SafeCall(Label* to,
1319 const Operand& rt) {
1320 __ BranchAndLink(to, cond, rs, rt);
1323void RegExpMacroAssemblerMIPS::SafeReturn() {
1325 __ Daddu(t1, ra, Operand(
masm_->CodeObject()));
1329void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) {
1331 __ Dsubu(ra, ra, Operand(
masm_->CodeObject()));
1335void RegExpMacroAssemblerMIPS::Push(Register source) {
1336 DCHECK(source != backtrack_stackpointer());
1337 __ Daddu(backtrack_stackpointer(),
1338 backtrack_stackpointer(),
1339 Operand(-kIntSize));
1343void RegExpMacroAssemblerMIPS::Pop(Register target) {
1344 DCHECK(target != backtrack_stackpointer());
1346 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), kIntSize);
1349void RegExpMacroAssemblerMIPS::CallCFunctionFromIrregexpCode(
1350 ExternalReference function,
int num_arguments) {
1364void RegExpMacroAssemblerMIPS::CheckPreemption() {
1366 ExternalReference stack_limit =
1367 ExternalReference::address_of_jslimit(
masm_->isolate());
1368 __ li(a0, Operand(stack_limit));
1370 SafeCall(&check_preempt_label_, ls, sp, Operand(a0));
1373void RegExpMacroAssemblerMIPS::CheckStackLimit() {
1374 ExternalReference stack_limit =
1375 ExternalReference::address_of_regexp_stack_limit_address(
1378 __ li(a0, Operand(stack_limit));
1380 SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0));
1383void RegExpMacroAssemblerMIPS::AssertAboveStackLimitMinusSlack() {
1384 ExternalReference stack_limit =
1385 ExternalReference::address_of_regexp_stack_limit_address(
1388 __ li(a0, Operand(stack_limit));
1390 SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0));
1393 Label no_stack_overflow;
1395 auto l = ExternalReference::address_of_regexp_stack_limit_address(
isolate());
1398 __ Dsubu(a0, a0, Operand(RegExpStack::kStackLimitSlackSize));
1399 __ Branch(&no_stack_overflow, hi, backtrack_stackpointer(), Operand(a0));
1401 __ bind(&no_stack_overflow);
1404void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(
int cp_offset,
1407 if (cp_offset != 0) {
1409 __ Daddu(t3, current_input_offset(), Operand(cp_offset * char_size()));
1415 __ Daddu(t1, end_of_input_address(), Operand(
offset));
1416 if (
mode_ == LATIN1) {
RegExpMacroAssemblerMIPS(Isolate *isolate, Zone *zone, Mode mode, int registers_to_save)
RecordWriteMode const mode_
const CodeDesc * code_desc
#define ASM_CODE_COMMENT_STRING(asm,...)
#define LOG(isolate, Call)
MaglevAssembler *const masm_
void Or(LiftoffAssembler *lasm, Register dst, Register lhs, Register rhs)
void Xor(LiftoffAssembler *lasm, Register dst, Register lhs, Register rhs)
void And(LiftoffAssembler *lasm, Register dst, Register lhs, Register rhs)
void push(LiftoffAssembler *assm, LiftoffRegister reg, ValueKind kind, int padding=0)
Address grow_stack(Isolate *isolate, void *current_sp, size_t frame_size, size_t gap, Address current_fp)
RegListBase< Register > RegList
MemOperand FieldMemOperand(Register object, int offset)
constexpr int kSystemPointerSize
std::unique_ptr< AssemblerBuffer > NewAssemblerBuffer(int size)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_LE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
constexpr bool IsAligned(T value, U alignment)
#define OFFSET_OF_DATA_START(Type)
#define V8_UNLIKELY(condition)