91#define __ ACCESS_MASM(masm_)
97 int registers_to_save)
98 : NativeRegExpMacroAssembler(isolate, zone),
99 masm_(
std::make_unique<MacroAssembler>(
102 no_root_array_scope_(
masm_.get()),
104 num_registers_(registers_to_save),
105 num_saved_registers_(registers_to_save),
112 __ jmp(&entry_label_);
113 __ bind(&start_label_);
116RegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() =
default;
118void RegExpMacroAssemblerARM::AbortedCodeGeneration() {
119 masm_->AbortedCodeGeneration();
121 entry_label_.Unuse();
122 start_label_.Unuse();
123 success_label_.Unuse();
124 backtrack_label_.Unuse();
126 check_preempt_label_.Unuse();
127 stack_overflow_label_.Unuse();
128 fallback_label_.Unuse();
131int RegExpMacroAssemblerARM::stack_limit_slack_slot_count() {
132 return RegExpStack::kStackLimitSlackSlotCount;
135void RegExpMacroAssemblerARM::AdvanceCurrentPosition(
int by) {
137 __ add(current_input_offset(),
138 current_input_offset(), Operand(by * char_size()));
143void RegExpMacroAssemblerARM::AdvanceRegister(
int reg,
int by) {
147 __ ldr(r0, register_location(
reg));
148 __ add(r0, r0, Operand(by));
149 __ str(r0, register_location(
reg));
154void RegExpMacroAssemblerARM::Backtrack() {
156 if (has_backtrack_limit()) {
158 __ ldr(r0,
MemOperand(frame_pointer(), kBacktrackCountOffset));
159 __ add(r0, r0, Operand(1));
160 __ str(r0,
MemOperand(frame_pointer(), kBacktrackCountOffset));
161 __ cmp(r0, Operand(backtrack_limit()));
165 if (can_fallback()) {
166 __ jmp(&fallback_label_);
177 __ add(
pc, r0, Operand(code_pointer()));
181void RegExpMacroAssemblerARM::Bind(Label*
label) {
186void RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) {
187 __ cmp(current_character(), Operand(c));
188 BranchOrBacktrack(eq, on_equal);
191void RegExpMacroAssemblerARM::CheckCharacterGT(base::uc16 limit,
193 __ cmp(current_character(), Operand(limit));
194 BranchOrBacktrack(gt, on_greater);
197void RegExpMacroAssemblerARM::CheckAtStart(
int cp_offset, Label* on_at_start) {
198 __ ldr(r1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
199 __ add(r0, current_input_offset(),
200 Operand(-char_size() + cp_offset * char_size()));
202 BranchOrBacktrack(eq, on_at_start);
205void RegExpMacroAssemblerARM::CheckNotAtStart(
int cp_offset,
206 Label* on_not_at_start) {
207 __ ldr(r1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
208 __ add(r0, current_input_offset(),
209 Operand(-char_size() + cp_offset * char_size()));
211 BranchOrBacktrack(ne, on_not_at_start);
214void RegExpMacroAssemblerARM::CheckCharacterLT(base::uc16 limit,
216 __ cmp(current_character(), Operand(limit));
217 BranchOrBacktrack(lt, on_less);
220void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
222 __ cmp(current_input_offset(), r0);
223 __ add(backtrack_stackpointer(), backtrack_stackpointer(),
224 Operand(kSystemPointerSize), LeaveCC, eq);
225 BranchOrBacktrack(eq, on_equal);
228void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase(
229 int start_reg,
bool read_backward,
bool unicode, Label* on_no_match) {
231 __ ldr(r0, register_location(start_reg));
232 __ ldr(r1, register_location(start_reg + 1));
233 __ sub(r1, r1, r0, SetCC);
238 __ b(eq, &fallthrough);
242 __ ldr(r3,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
244 __ cmp(current_input_offset(), r3);
245 BranchOrBacktrack(le, on_no_match);
247 __ cmn(r1, Operand(current_input_offset()));
248 BranchOrBacktrack(gt, on_no_match);
251 if (
mode_ == LATIN1) {
258 __ add(r0, r0, end_of_input_address());
259 __ add(r2, end_of_input_address(), current_input_offset());
274 __ b(eq, &loop_check);
277 __ orr(r3, r3, Operand(0x20));
278 __ orr(r4, r4, Operand(0x20));
281 __ sub(r3, r3, Operand(
'a'));
282 __ cmp(r3, Operand(
'z' -
'a'));
283 __ b(ls, &loop_check);
285 __ sub(r3, r3, Operand(224 -
'a'));
286 __ cmp(r3, Operand(254 - 224));
288 __ cmp(r3, Operand(247 - 224));
291 __ bind(&loop_check);
297 BranchOrBacktrack(al, on_no_match);
301 __ sub(current_input_offset(), r2, end_of_input_address());
303 __ ldr(r0, register_location(start_reg));
304 __ ldr(r1, register_location(start_reg + 1));
305 __ add(current_input_offset(), current_input_offset(), r0);
306 __ sub(current_input_offset(), current_input_offset(), r1);
310 int argument_count = 4;
311 __ PrepareCallCFunction(argument_count);
324 __ add(r0, r0, Operand(end_of_input_address()));
326 __ mov(r2, Operand(r1));
328 __ mov(r4, Operand(r1));
330 __ add(r1, current_input_offset(), end_of_input_address());
335 __ mov(r3, Operand(ExternalReference::isolate_address(
isolate())));
338 AllowExternalCallThatCantCauseGC scope(
masm_.get());
339 ExternalReference function =
341 ? ExternalReference::re_case_insensitive_compare_unicode()
342 : ExternalReference::re_case_insensitive_compare_non_unicode();
343 CallCFunctionFromIrregexpCode(function, argument_count);
347 __ cmp(r0, Operand::Zero());
348 BranchOrBacktrack(eq, on_no_match);
352 __ sub(current_input_offset(), current_input_offset(), r4);
354 __ add(current_input_offset(), current_input_offset(), r4);
358 __ bind(&fallthrough);
361void RegExpMacroAssemblerARM::CheckNotBackReference(
int start_reg,
363 Label* on_no_match) {
367 __ ldr(r0, register_location(start_reg));
368 __ ldr(r1, register_location(start_reg + 1));
369 __ sub(r1, r1, r0, SetCC);
374 __ b(eq, &fallthrough);
378 __ ldr(r3,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
380 __ cmp(current_input_offset(), r3);
381 BranchOrBacktrack(le, on_no_match);
383 __ cmn(r1, Operand(current_input_offset()));
384 BranchOrBacktrack(gt, on_no_match);
389 __ add(r0, r0, end_of_input_address());
390 __ add(r2, end_of_input_address(), current_input_offset());
398 if (
mode_ == LATIN1) {
407 BranchOrBacktrack(ne, on_no_match);
412 __ sub(current_input_offset(), r2, end_of_input_address());
414 __ ldr(r0, register_location(start_reg));
415 __ ldr(r1, register_location(start_reg + 1));
416 __ add(current_input_offset(), current_input_offset(), r0);
417 __ sub(current_input_offset(), current_input_offset(), r1);
420 __ bind(&fallthrough);
424void RegExpMacroAssemblerARM::CheckNotCharacter(
unsigned c,
425 Label* on_not_equal) {
426 __ cmp(current_character(), Operand(c));
427 BranchOrBacktrack(ne, on_not_equal);
431void RegExpMacroAssemblerARM::CheckCharacterAfterAnd(uint32_t c,
435 __ tst(current_character(), Operand(
mask));
437 __ and_(r0, current_character(), Operand(
mask));
438 __ cmp(r0, Operand(c));
440 BranchOrBacktrack(eq, on_equal);
444void RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(
unsigned c,
446 Label* on_not_equal) {
448 __ tst(current_character(), Operand(
mask));
450 __ and_(r0, current_character(), Operand(
mask));
451 __ cmp(r0, Operand(c));
453 BranchOrBacktrack(ne, on_not_equal);
456void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
457 base::uc16 c, base::uc16 minus, base::uc16
mask, Label* on_not_equal) {
458 DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
459 __ sub(r0, current_character(), Operand(minus));
460 __ and_(r0, r0, Operand(
mask));
461 __ cmp(r0, Operand(c));
462 BranchOrBacktrack(ne, on_not_equal);
465void RegExpMacroAssemblerARM::CheckCharacterInRange(base::uc16 from,
467 Label* on_in_range) {
468 __ sub(r0, current_character(), Operand(from));
469 __ cmp(r0, Operand(to - from));
470 BranchOrBacktrack(ls, on_in_range);
473void RegExpMacroAssemblerARM::CheckCharacterNotInRange(base::uc16 from,
475 Label* on_not_in_range) {
476 __ sub(r0, current_character(), Operand(from));
477 __ cmp(r0, Operand(to - from));
478 BranchOrBacktrack(hi, on_not_in_range);
481void RegExpMacroAssemblerARM::CallIsCharacterInRangeArray(
482 const ZoneList<CharacterRange>* ranges) {
483 static const int kNumArguments = 2;
484 __ PrepareCallCFunction(kNumArguments);
486 __ mov(r0, current_character());
487 __ mov(r1, Operand(GetOrAddRangeArray(ranges)));
491 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
492 CallCFunctionFromIrregexpCode(
493 ExternalReference::re_is_character_in_range_array(), kNumArguments);
496 __ mov(code_pointer(), Operand(
masm_->CodeObject()));
499bool RegExpMacroAssemblerARM::CheckCharacterInRangeArray(
500 const ZoneList<CharacterRange>* ranges, Label* on_in_range) {
501 CallIsCharacterInRangeArray(ranges);
502 __ cmp(r0, Operand::Zero());
503 BranchOrBacktrack(ne, on_in_range);
507bool RegExpMacroAssemblerARM::CheckCharacterNotInRangeArray(
508 const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) {
509 CallIsCharacterInRangeArray(ranges);
510 __ cmp(r0, Operand::Zero());
511 BranchOrBacktrack(eq, on_not_in_range);
515void RegExpMacroAssemblerARM::CheckBitInTable(
516 Handle<ByteArray> table,
518 __ mov(r0, Operand(table));
519 if (
mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
520 __ and_(r1, current_character(), Operand(kTableSize - 1));
523 __ add(r1, current_character(),
527 __ cmp(r0, Operand::Zero());
528 BranchOrBacktrack(ne, on_bit_set);
531void RegExpMacroAssemblerARM::SkipUntilBitInTable(
532 int cp_offset, Handle<ByteArray> table, Handle<ByteArray> nibble_table,
537 LoadCurrentCharacter(cp_offset, &cont,
true);
538 CheckBitInTable(table, &cont);
539 AdvanceCurrentPosition(advance_by);
544bool RegExpMacroAssemblerARM::CheckSpecialClassRanges(StandardCharacterSet type,
545 Label* on_no_match) {
550 case StandardCharacterSet::kWhitespace:
552 if (
mode_ == LATIN1) {
555 __ cmp(current_character(), Operand(
' '));
558 __ sub(r0, current_character(), Operand(
'\t'));
559 __ cmp(r0, Operand(
'\r' -
'\t'));
562 __ cmp(r0, Operand(0x00A0 -
'\t'));
563 BranchOrBacktrack(ne, on_no_match);
568 case StandardCharacterSet::kNotWhitespace:
571 case StandardCharacterSet::kDigit:
573 __ sub(r0, current_character(), Operand(
'0'));
574 __ cmp(r0, Operand(
'9' -
'0'));
575 BranchOrBacktrack(hi, on_no_match);
577 case StandardCharacterSet::kNotDigit:
579 __ sub(r0, current_character(), Operand(
'0'));
580 __ cmp(r0, Operand(
'9' -
'0'));
581 BranchOrBacktrack(ls, on_no_match);
583 case StandardCharacterSet::kNotLineTerminator: {
585 __ eor(r0, current_character(), Operand(0x01));
587 __ sub(r0, r0, Operand(0x0B));
588 __ cmp(r0, Operand(0x0C - 0x0B));
589 BranchOrBacktrack(ls, on_no_match);
594 __ sub(r0, r0, Operand(0x2028 - 0x0B));
595 __ cmp(r0, Operand(1));
596 BranchOrBacktrack(ls, on_no_match);
600 case StandardCharacterSet::kLineTerminator: {
602 __ eor(r0, current_character(), Operand(0x01));
604 __ sub(r0, r0, Operand(0x0B));
605 __ cmp(r0, Operand(0x0C - 0x0B));
606 if (
mode_ == LATIN1) {
607 BranchOrBacktrack(hi, on_no_match);
614 __ sub(r0, r0, Operand(0x2028 - 0x0B));
615 __ cmp(r0, Operand(1));
616 BranchOrBacktrack(hi, on_no_match);
621 case StandardCharacterSet::kWord: {
622 if (
mode_ != LATIN1) {
624 __ cmp(current_character(), Operand(
'z'));
625 BranchOrBacktrack(hi, on_no_match);
627 ExternalReference map = ExternalReference::re_word_character_map();
628 __ mov(r0, Operand(map));
630 __ cmp(r0, Operand::Zero());
631 BranchOrBacktrack(eq, on_no_match);
634 case StandardCharacterSet::kNotWord: {
636 if (
mode_ != LATIN1) {
638 __ cmp(current_character(), Operand(
'z'));
641 ExternalReference map = ExternalReference::re_word_character_map();
642 __ mov(r0, Operand(map));
644 __ cmp(r0, Operand::Zero());
645 BranchOrBacktrack(ne, on_no_match);
646 if (
mode_ != LATIN1) {
651 case StandardCharacterSet::kEverything:
657void RegExpMacroAssemblerARM::Fail() {
658 __ mov(r0, Operand(FAILURE));
659 __ jmp(&exit_label_);
662void RegExpMacroAssemblerARM::LoadRegExpStackPointerFromMemory(Register dst) {
663 ExternalReference ref =
664 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
665 __ mov(dst, Operand(ref));
669void RegExpMacroAssemblerARM::StoreRegExpStackPointerToMemory(
670 Register src, Register scratch) {
671 ExternalReference ref =
672 ExternalReference::address_of_regexp_stack_stack_pointer(
isolate());
673 __ mov(scratch, Operand(ref));
677void RegExpMacroAssemblerARM::PushRegExpBasePointer(Register stack_pointer,
679 ExternalReference ref =
680 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
681 __ mov(scratch, Operand(ref));
683 __ sub(scratch, stack_pointer, scratch);
684 __ str(scratch,
MemOperand(frame_pointer(), kRegExpStackBasePointerOffset));
687void RegExpMacroAssemblerARM::PopRegExpBasePointer(Register stack_pointer_out,
689 ExternalReference ref =
690 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
691 __ ldr(stack_pointer_out,
692 MemOperand(frame_pointer(), kRegExpStackBasePointerOffset));
693 __ mov(scratch, Operand(ref));
695 __ add(stack_pointer_out, stack_pointer_out, scratch);
696 StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
699DirectHandle<HeapObject> RegExpMacroAssemblerARM::GetCode(
700 DirectHandle<String> source, RegExpFlags flags) {
706 __ bind(&entry_label_);
710 FrameScope scope(
masm_.get(), StackFrame::MANUAL);
715 RegList registers_to_retain = {r4, r5, r6, r7, r8, r9, r10, fp};
716 __ stm(db_w, sp, registers_to_retain | lr);
717 __ mov(frame_pointer(), sp);
726 RegList argument_registers = {
r0, r1, r2, r3};
728 __ mov(r4, Operand(StackFrame::TypeToMarker(StackFrame::IRREGEXP)));
734 __ stm(db_w, sp, argument_registers | r4);
736 static_assert(kSuccessfulCapturesOffset ==
738 __ mov(r0, Operand::Zero());
740 static_assert(kStringStartMinusOneOffset ==
743 static_assert(kBacktrackCountOffset ==
746 static_assert(kRegExpStackBasePointerOffset ==
752 static_assert(backtrack_stackpointer() == r8);
753 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
757 PushRegExpBasePointer(backtrack_stackpointer(), r1);
761 Label stack_limit_hit, stack_ok;
763 ExternalReference stack_limit =
764 ExternalReference::address_of_jslimit(
isolate());
765 __ mov(r0, Operand(stack_limit));
767 __ sub(r0, sp, r0, SetCC);
768 Operand extra_space_for_variables(num_registers_ * kSystemPointerSize);
771 __ b(ls, &stack_limit_hit);
774 __ cmp(r0, extra_space_for_variables);
778 __ mov(r0, Operand(EXCEPTION));
781 __ bind(&stack_limit_hit);
782 CallCheckStackGuardState(extra_space_for_variables);
783 __ cmp(r0, Operand::Zero());
785 __ b(ne, &return_r0);
791 __ AllocateStackSpace(num_registers_ * kSystemPointerSize);
793 __ ldr(end_of_input_address(),
MemOperand(frame_pointer(), kInputEndOffset));
795 __ ldr(r0,
MemOperand(frame_pointer(), kInputStartOffset));
797 __ sub(current_input_offset(), r0, end_of_input_address());
800 __ ldr(r1,
MemOperand(frame_pointer(), kStartIndexOffset));
801 __ sub(r0, current_input_offset(), Operand(char_size()));
802 __ sub(r0, r0, Operand(r1, LSL, (
mode_ == UC16) ? 1 : 0));
805 __ str(r0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
808 __ mov(code_pointer(), Operand(
masm_->CodeObject()));
810 Label load_char_start_regexp;
814 __ cmp(r1, Operand::Zero());
815 __ b(ne, &load_char_start_regexp);
816 __ mov(current_character(), Operand(
'\n'), LeaveCC, eq);
817 __ jmp(&start_regexp);
820 __ bind(&load_char_start_regexp);
822 LoadCurrentCharacterUnchecked(-1, 1);
823 __ bind(&start_regexp);
827 if (num_saved_registers_ > 0) {
829 if (num_saved_registers_ > 8) {
831 __ add(r1, frame_pointer(), Operand(kRegisterZeroOffset));
832 __ mov(r2, Operand(num_saved_registers_));
835 __ str(r0,
MemOperand(r1, kSystemPointerSize, NegPostIndex));
836 __ sub(r2, r2, Operand(1), SetCC);
837 __ b(ne, &init_loop);
839 for (
int i = 0;
i < num_saved_registers_;
i++) {
840 __ str(r0, register_location(
i));
845 __ jmp(&start_label_);
848 if (success_label_.is_linked()) {
850 __ bind(&success_label_);
851 if (num_saved_registers_ > 0) {
853 __ ldr(r1,
MemOperand(frame_pointer(), kInputStartOffset));
854 __ ldr(r0,
MemOperand(frame_pointer(), kRegisterOutputOffset));
855 __ ldr(r2,
MemOperand(frame_pointer(), kStartIndexOffset));
856 __ sub(r1, end_of_input_address(), r1);
859 __ mov(r1, Operand(r1, LSR, 1));
862 __ add(r1, r1, Operand(r2));
869 for (
int i = 0;
i < num_saved_registers_;
i += 2) {
870 __ ldr(r2, register_location(
i));
871 __ ldr(r3, register_location(
i + 1));
872 if (
i == 0 && global_with_zero_length_check()) {
877 __ add(r2, r1, Operand(r2, ASR, 1));
878 __ add(r3, r1, Operand(r3, ASR, 1));
880 __ add(r2, r1, Operand(r2));
881 __ add(r3, r1, Operand(r3));
883 __ str(r2,
MemOperand(r0, kSystemPointerSize, PostIndex));
884 __ str(r3,
MemOperand(r0, kSystemPointerSize, PostIndex));
890 __ ldr(r0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
891 __ ldr(r1,
MemOperand(frame_pointer(), kNumOutputRegistersOffset));
892 __ ldr(r2,
MemOperand(frame_pointer(), kRegisterOutputOffset));
894 __ add(r0, r0, Operand(1));
895 __ str(r0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
898 __ sub(r1, r1, Operand(num_saved_registers_));
900 __ cmp(r1, Operand(num_saved_registers_));
901 __ b(lt, &return_r0);
903 __ str(r1,
MemOperand(frame_pointer(), kNumOutputRegistersOffset));
905 __ add(r2, r2, Operand(num_saved_registers_ * kSystemPointerSize));
906 __ str(r2,
MemOperand(frame_pointer(), kRegisterOutputOffset));
910 PopRegExpBasePointer(backtrack_stackpointer(), r2);
912 Label reload_string_start_minus_one;
914 if (global_with_zero_length_check()) {
917 __ cmp(current_input_offset(), r4);
919 __ b(ne, &reload_string_start_minus_one);
921 __ cmp(current_input_offset(), Operand::Zero());
922 __ b(eq, &exit_label_);
926 __ add(current_input_offset(), current_input_offset(),
927 Operand((
mode_ == UC16) ? 2 : 1));
928 if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
931 __ bind(&reload_string_start_minus_one);
934 __ ldr(r0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
936 __ b(&load_char_start_regexp);
938 __ mov(r0, Operand(SUCCESS));
943 __ bind(&exit_label_);
945 __ ldr(r0,
MemOperand(frame_pointer(), kSuccessfulCapturesOffset));
951 PopRegExpBasePointer(backtrack_stackpointer(), r2);
954 __ mov(sp, frame_pointer());
956 __ ldm(ia_w, sp, registers_to_retain |
pc);
959 if (backtrack_label_.is_linked()) {
960 __ bind(&backtrack_label_);
964 Label exit_with_exception;
967 if (check_preempt_label_.is_linked()) {
968 SafeCallTarget(&check_preempt_label_);
970 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r1);
972 CallCheckStackGuardState();
973 __ cmp(r0, Operand::Zero());
976 __ b(ne, &return_r0);
978 LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
981 __ ldr(end_of_input_address(),
982 MemOperand(frame_pointer(), kInputEndOffset));
987 if (stack_overflow_label_.is_linked()) {
988 SafeCallTarget(&stack_overflow_label_);
993 StoreRegExpStackPointerToMemory(backtrack_stackpointer(), r1);
995 static constexpr int kNumArguments = 1;
996 __ PrepareCallCFunction(kNumArguments);
997 __ mov(r0, Operand(ExternalReference::isolate_address(
isolate())));
998 ExternalReference
grow_stack = ExternalReference::re_grow_stack();
999 CallCFunctionFromIrregexpCode(grow_stack, kNumArguments);
1002 __ cmp(r0, Operand::Zero());
1003 __ b(eq, &exit_with_exception);
1005 __ mov(backtrack_stackpointer(), r0);
1010 if (exit_with_exception.is_linked()) {
1012 __ bind(&exit_with_exception);
1014 __ mov(r0, Operand(EXCEPTION));
1018 if (fallback_label_.is_linked()) {
1019 __ bind(&fallback_label_);
1020 __ mov(r0, Operand(FALLBACK_TO_EXPERIMENTAL));
1028 .set_self_reference(
masm_->CodeObject())
1029 .set_empty_source_position_table()
1032 RegExpCodeCreateEvent(Cast<AbstractCode>(code), source, flags));
1033 return Cast<HeapObject>(code);
1036void RegExpMacroAssemblerARM::GoTo(Label* to) {
1037 BranchOrBacktrack(al, to);
1041void RegExpMacroAssemblerARM::IfRegisterGE(
int reg,
1044 __ ldr(r0, register_location(
reg));
1045 __ cmp(r0, Operand(comparand));
1046 BranchOrBacktrack(ge, if_ge);
1050void RegExpMacroAssemblerARM::IfRegisterLT(
int reg,
1053 __ ldr(r0, register_location(
reg));
1054 __ cmp(r0, Operand(comparand));
1055 BranchOrBacktrack(lt, if_lt);
1059void RegExpMacroAssemblerARM::IfRegisterEqPos(
int reg,
1061 __ ldr(r0, register_location(
reg));
1062 __ cmp(r0, Operand(current_input_offset()));
1063 BranchOrBacktrack(eq, if_eq);
1067RegExpMacroAssembler::IrregexpImplementation
1068 RegExpMacroAssemblerARM::Implementation() {
1069 return kARMImplementation;
1073void RegExpMacroAssemblerARM::PopCurrentPosition() {
1074 Pop(current_input_offset());
1078void RegExpMacroAssemblerARM::PopRegister(
int register_index) {
1080 __ str(r0, register_location(register_index));
1084void RegExpMacroAssemblerARM::PushBacktrack(Label*
label) {
1085 __ mov_label_offset(r0,
label);
1091void RegExpMacroAssemblerARM::PushCurrentPosition() {
1092 Push(current_input_offset());
1097void RegExpMacroAssemblerARM::PushRegister(
int register_index,
1098 StackCheckFlag check_stack_limit) {
1099 __ ldr(r0, register_location(register_index));
1101 if (check_stack_limit) {
1104 AssertAboveStackLimitMinusSlack();
1109void RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(
int reg) {
1110 __ ldr(current_input_offset(), register_location(
reg));
1113void RegExpMacroAssemblerARM::WriteStackPointerToRegister(
int reg) {
1114 ExternalReference ref =
1115 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1116 __ mov(r1, Operand(ref));
1118 __ sub(r0, backtrack_stackpointer(), r1);
1119 __ str(r0, register_location(
reg));
1122void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(
int reg) {
1123 ExternalReference ref =
1124 ExternalReference::address_of_regexp_stack_memory_top_address(
isolate());
1125 __ mov(r0, Operand(ref));
1127 __ ldr(backtrack_stackpointer(), register_location(
reg));
1128 __ add(backtrack_stackpointer(), backtrack_stackpointer(), r0);
1131void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(
int by) {
1132 Label after_position;
1133 __ cmp(current_input_offset(), Operand(-by * char_size()));
1134 __ b(ge, &after_position);
1135 __ mov(current_input_offset(), Operand(-by * char_size()));
1139 LoadCurrentCharacterUnchecked(-1, 1);
1140 __ bind(&after_position);
1144void RegExpMacroAssemblerARM::SetRegister(
int register_index,
int to) {
1145 DCHECK(register_index >= num_saved_registers_);
1146 __ mov(r0, Operand(to));
1147 __ str(r0, register_location(register_index));
1151bool RegExpMacroAssemblerARM::Succeed() {
1152 __ jmp(&success_label_);
1157void RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(
int reg,
1159 if (cp_offset == 0) {
1160 __ str(current_input_offset(), register_location(
reg));
1162 __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1163 __ str(r0, register_location(
reg));
1168void RegExpMacroAssemblerARM::ClearRegisters(
int reg_from,
int reg_to) {
1169 DCHECK(reg_from <= reg_to);
1170 __ ldr(r0,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
1171 for (
int reg = reg_from;
reg <= reg_to;
reg++) {
1172 __ str(r0, register_location(
reg));
1178void RegExpMacroAssemblerARM::CallCheckStackGuardState(Operand extra_space) {
1180 DCHECK(!
masm_->options().isolate_independent_code);
1182 __ PrepareCallCFunction(4);
1185 __ mov(kCArgRegs[3], extra_space);
1187 __ mov(kCArgRegs[2], frame_pointer());
1189 __ mov(kCArgRegs[1], Operand(
masm_->CodeObject()));
1192 int stack_alignment = base::OS::ActivationFrameAlignment();
1194 __ AllocateStackSpace(stack_alignment);
1199 ExternalReference stack_guard_check =
1200 ExternalReference::re_check_stack_guard_state();
1201 __ mov(ip, Operand(stack_guard_check));
1203 EmbeddedData d = EmbeddedData::FromBlob();
1204 Address entry = d.InstructionStartOf(Builtin::kDirectCEntry);
1205 __ mov(lr, Operand(entry, RelocInfo::OFF_HEAP_TARGET));
1209 __ add(sp, sp, Operand(stack_alignment));
1214 __ mov(code_pointer(), Operand(
masm_->CodeObject()));
1218template <
typename T>
1219static T& frame_entry(Address re_frame,
int frame_offset) {
1220 return reinterpret_cast<T&
>(Memory<int32_t>(re_frame + frame_offset));
1224template <
typename T>
1225static T* frame_entry_address(Address re_frame,
int frame_offset) {
1226 return reinterpret_cast<T*
>(re_frame + frame_offset);
1229int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
1232 uintptr_t extra_space) {
1233 Tagged<InstructionStream> re_code =
1234 Cast<InstructionStream>(Tagged<Object>(raw_code));
1235 return NativeRegExpMacroAssembler::CheckStackGuardState(
1236 frame_entry<Isolate*>(re_frame, kIsolateOffset),
1237 frame_entry<int>(re_frame, kStartIndexOffset),
1238 static_cast<RegExp::CallOrigin
>(
1239 frame_entry<int>(re_frame, kDirectCallOffset)),
1240 return_address, re_code,
1241 frame_entry_address<Address>(re_frame, kInputStringOffset),
1242 frame_entry_address<const uint8_t*>(re_frame, kInputStartOffset),
1243 frame_entry_address<const uint8_t*>(re_frame, kInputEndOffset),
1247MemOperand RegExpMacroAssemblerARM::register_location(
int register_index) {
1248 DCHECK(register_index < (1<<30));
1249 if (num_registers_ <= register_index) {
1250 num_registers_ = register_index + 1;
1253 kRegisterZeroOffset - register_index * kSystemPointerSize);
1257void RegExpMacroAssemblerARM::CheckPosition(
int cp_offset,
1258 Label* on_outside_input) {
1259 if (cp_offset >= 0) {
1260 __ cmp(current_input_offset(), Operand(-cp_offset * char_size()));
1261 BranchOrBacktrack(ge, on_outside_input);
1263 __ ldr(r1,
MemOperand(frame_pointer(), kStringStartMinusOneOffset));
1264 __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1266 BranchOrBacktrack(le, on_outside_input);
1271void RegExpMacroAssemblerARM::BranchOrBacktrack(Condition
condition,
1274 if (to ==
nullptr) {
1281 if (to ==
nullptr) {
1289void RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) {
1294void RegExpMacroAssemblerARM::SafeReturn() {
1296 __ add(
pc, lr, Operand(
masm_->CodeObject()));
1300void RegExpMacroAssemblerARM::SafeCallTarget(Label* name) {
1302 __ sub(lr, lr, Operand(
masm_->CodeObject()));
1307void RegExpMacroAssemblerARM::Push(Register source) {
1308 DCHECK(source != backtrack_stackpointer());
1310 MemOperand(backtrack_stackpointer(), kSystemPointerSize, NegPreIndex));
1314void RegExpMacroAssemblerARM::Pop(Register target) {
1315 DCHECK(target != backtrack_stackpointer());
1317 MemOperand(backtrack_stackpointer(), kSystemPointerSize, PostIndex));
1320void RegExpMacroAssemblerARM::CallCFunctionFromIrregexpCode(
1321 ExternalReference function,
int num_arguments) {
1335void RegExpMacroAssemblerARM::CheckPreemption() {
1337 ExternalReference stack_limit =
1338 ExternalReference::address_of_jslimit(
isolate());
1339 __ mov(r0, Operand(stack_limit));
1342 SafeCall(&check_preempt_label_, ls);
1346void RegExpMacroAssemblerARM::CheckStackLimit() {
1347 ExternalReference stack_limit =
1348 ExternalReference::address_of_regexp_stack_limit_address(
isolate());
1349 __ mov(r0, Operand(stack_limit));
1351 __ cmp(backtrack_stackpointer(), Operand(r0));
1352 SafeCall(&stack_overflow_label_, ls);
1355void RegExpMacroAssemblerARM::AssertAboveStackLimitMinusSlack() {
1357 Label no_stack_overflow;
1359 auto l = ExternalReference::address_of_regexp_stack_limit_address(
isolate());
1360 __ mov(r0, Operand(l));
1362 __ sub(r0, r0, Operand(RegExpStack::kStackLimitSlackSize));
1363 __ cmp(backtrack_stackpointer(), Operand(r0));
1364 __ b(hi, &no_stack_overflow);
1366 __ bind(&no_stack_overflow);
1369void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(
int cp_offset,
1372 if (cp_offset != 0) {
1374 __ add(r4, current_input_offset(), Operand(cp_offset * char_size()));
1381 if (!CanReadUnaligned()) {
1385 if (
mode_ == LATIN1) {
1386 if (characters == 4) {
1388 }
else if (characters == 2) {
1396 if (characters == 2) {
RegExpMacroAssemblerARM(Isolate *isolate, Zone *zone, Mode mode, int registers_to_save)
static constexpr int kRegExpCodeSize
#define PROFILE(the_isolate, Call)
RecordWriteMode const mode_
const CodeDesc * code_desc
#define ASM_CODE_COMMENT_STRING(asm,...)
MaglevAssembler *const masm_
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)
uint32_t WasmInterpreterRuntime int64_t r0
RegListBase< Register > RegList
constexpr int kSystemPointerSize
std::unique_ptr< AssemblerBuffer > NewAssemblerBuffer(int size)
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_LE(v1, v2)
#define DCHECK_NE(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)