7 #include "src/regexp/arm/regexp-macro-assembler-arm.h" 9 #include "src/assembler-inl.h" 10 #include "src/code-stubs.h" 11 #include "src/heap/factory.h" 13 #include "src/macro-assembler.h" 14 #include "src/objects-inl.h" 15 #include "src/regexp/regexp-macro-assembler.h" 16 #include "src/regexp/regexp-stack.h" 22 #ifndef V8_INTERPRETED_REGEXP 92 #define __ ACCESS_MASM(masm_) 94 RegExpMacroAssemblerARM::RegExpMacroAssemblerARM(Isolate* isolate, Zone* zone,
96 int registers_to_save)
97 : NativeRegExpMacroAssembler(isolate, zone),
98 masm_(new MacroAssembler(isolate, nullptr, kRegExpCodeSize,
99 CodeObjectRequired::kYes)),
101 num_registers_(registers_to_save),
102 num_saved_registers_(registers_to_save),
108 DCHECK_EQ(0, registers_to_save % 2);
109 __ jmp(&entry_label_);
110 __ bind(&start_label_);
114 RegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() {
117 entry_label_.Unuse();
118 start_label_.Unuse();
119 success_label_.Unuse();
120 backtrack_label_.Unuse();
122 check_preempt_label_.Unuse();
123 stack_overflow_label_.Unuse();
127 int RegExpMacroAssemblerARM::stack_limit_slack() {
128 return RegExpStack::kStackLimitSlack;
132 void RegExpMacroAssemblerARM::AdvanceCurrentPosition(
int by) {
134 __ add(current_input_offset(),
135 current_input_offset(), Operand(by * char_size()));
140 void RegExpMacroAssemblerARM::AdvanceRegister(
int reg,
int by) {
142 DCHECK_GT(num_registers_, reg);
144 __ ldr(r0, register_location(reg));
145 __ add(r0, r0, Operand(by));
146 __ str(r0, register_location(reg));
151 void RegExpMacroAssemblerARM::Backtrack() {
155 __ add(pc, r0, Operand(code_pointer()));
159 void RegExpMacroAssemblerARM::Bind(Label* label) {
164 void RegExpMacroAssemblerARM::CheckCharacter(
uint32_t c, Label* on_equal) {
165 __ cmp(current_character(), Operand(c));
166 BranchOrBacktrack(eq, on_equal);
170 void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) {
171 __ cmp(current_character(), Operand(limit));
172 BranchOrBacktrack(gt, on_greater);
176 void RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) {
177 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne));
178 __ add(r0, current_input_offset(), Operand(-char_size()));
180 BranchOrBacktrack(eq, on_at_start);
184 void RegExpMacroAssemblerARM::CheckNotAtStart(
int cp_offset,
185 Label* on_not_at_start) {
186 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne));
187 __ add(r0, current_input_offset(),
188 Operand(-char_size() + cp_offset * char_size()));
190 BranchOrBacktrack(ne, on_not_at_start);
194 void RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) {
195 __ cmp(current_character(), Operand(limit));
196 BranchOrBacktrack(lt, on_less);
200 void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) {
201 __ ldr(r0, MemOperand(backtrack_stackpointer(), 0));
202 __ cmp(current_input_offset(), r0);
203 __ add(backtrack_stackpointer(),
204 backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq);
205 BranchOrBacktrack(eq, on_equal);
209 void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase(
210 int start_reg,
bool read_backward,
bool unicode, Label* on_no_match) {
212 __ ldr(r0, register_location(start_reg));
213 __ ldr(r1, register_location(start_reg + 1));
214 __ sub(r1, r1, r0, SetCC);
219 __ b(eq, &fallthrough);
223 __ ldr(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
225 __ cmp(current_input_offset(), r3);
226 BranchOrBacktrack(le, on_no_match);
228 __ cmn(r1, Operand(current_input_offset()));
229 BranchOrBacktrack(gt, on_no_match);
232 if (mode_ == LATIN1) {
239 __ add(r0, r0, end_of_input_address());
240 __ add(r2, end_of_input_address(), current_input_offset());
252 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
253 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
255 __ b(eq, &loop_check);
258 __ orr(r3, r3, Operand(0x20));
259 __ orr(r4, r4, Operand(0x20));
262 __ sub(r3, r3, Operand(
'a'));
263 __ cmp(r3, Operand(
'z' -
'a'));
264 __ b(ls, &loop_check);
266 __ sub(r3, r3, Operand(224 -
'a'));
267 __ cmp(r3, Operand(254 - 224));
269 __ cmp(r3, Operand(247 - 224));
272 __ bind(&loop_check);
278 BranchOrBacktrack(al, on_no_match);
282 __ sub(current_input_offset(), r2, end_of_input_address());
284 __ ldr(r0, register_location(start_reg));
285 __ ldr(r1, register_location(start_reg + 1));
286 __ add(current_input_offset(), current_input_offset(), r0);
287 __ sub(current_input_offset(), current_input_offset(), r1);
290 DCHECK(mode_ == UC16);
291 int argument_count = 4;
292 __ PrepareCallCFunction(argument_count);
305 __ add(r0, r0, Operand(end_of_input_address()));
307 __ mov(r2, Operand(r1));
309 __ mov(r4, Operand(r1));
311 __ add(r1, current_input_offset(), end_of_input_address());
316 #ifdef V8_INTL_SUPPORT 318 __ mov(r3, Operand(0));
320 #endif // V8_INTL_SUPPORT 322 __ mov(r3, Operand(ExternalReference::isolate_address(isolate())));
326 AllowExternalCallThatCantCauseGC scope(masm_);
327 ExternalReference
function =
328 ExternalReference::re_case_insensitive_compare_uc16(isolate());
329 __ CallCFunction(
function, argument_count);
333 __ cmp(r0, Operand::Zero());
334 BranchOrBacktrack(eq, on_no_match);
338 __ sub(current_input_offset(), current_input_offset(), r4);
340 __ add(current_input_offset(), current_input_offset(), r4);
344 __ bind(&fallthrough);
348 void RegExpMacroAssemblerARM::CheckNotBackReference(
int start_reg,
350 Label* on_no_match) {
355 __ ldr(r0, register_location(start_reg));
356 __ ldr(r1, register_location(start_reg + 1));
357 __ sub(r1, r1, r0, SetCC);
362 __ b(eq, &fallthrough);
366 __ ldr(r3, MemOperand(frame_pointer(), kStringStartMinusOne));
368 __ cmp(current_input_offset(), r3);
369 BranchOrBacktrack(le, on_no_match);
371 __ cmn(r1, Operand(current_input_offset()));
372 BranchOrBacktrack(gt, on_no_match);
377 __ add(r0, r0, end_of_input_address());
378 __ add(r2, end_of_input_address(), current_input_offset());
386 if (mode_ == LATIN1) {
387 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex));
388 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex));
390 DCHECK(mode_ == UC16);
391 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex));
392 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex));
395 BranchOrBacktrack(ne, on_no_match);
400 __ sub(current_input_offset(), r2, end_of_input_address());
402 __ ldr(r0, register_location(start_reg));
403 __ ldr(r1, register_location(start_reg + 1));
404 __ add(current_input_offset(), current_input_offset(), r0);
405 __ sub(current_input_offset(), current_input_offset(), r1);
408 __ bind(&fallthrough);
412 void RegExpMacroAssemblerARM::CheckNotCharacter(
unsigned c,
413 Label* on_not_equal) {
414 __ cmp(current_character(), Operand(c));
415 BranchOrBacktrack(ne, on_not_equal);
419 void RegExpMacroAssemblerARM::CheckCharacterAfterAnd(
uint32_t c,
423 __ tst(current_character(), Operand(mask));
425 __ and_(r0, current_character(), Operand(mask));
426 __ cmp(r0, Operand(c));
428 BranchOrBacktrack(eq, on_equal);
432 void RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(
unsigned c,
434 Label* on_not_equal) {
436 __ tst(current_character(), Operand(mask));
438 __ and_(r0, current_character(), Operand(mask));
439 __ cmp(r0, Operand(c));
441 BranchOrBacktrack(ne, on_not_equal);
445 void RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd(
449 Label* on_not_equal) {
450 DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
451 __ sub(r0, current_character(), Operand(minus));
452 __ and_(r0, r0, Operand(mask));
453 __ cmp(r0, Operand(c));
454 BranchOrBacktrack(ne, on_not_equal);
458 void RegExpMacroAssemblerARM::CheckCharacterInRange(
461 Label* on_in_range) {
462 __ sub(r0, current_character(), Operand(from));
463 __ cmp(r0, Operand(to - from));
464 BranchOrBacktrack(ls, on_in_range);
468 void RegExpMacroAssemblerARM::CheckCharacterNotInRange(
471 Label* on_not_in_range) {
472 __ sub(r0, current_character(), Operand(from));
473 __ cmp(r0, Operand(to - from));
474 BranchOrBacktrack(hi, on_not_in_range);
478 void RegExpMacroAssemblerARM::CheckBitInTable(
479 Handle<ByteArray> table,
481 __ mov(r0, Operand(table));
482 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
483 __ and_(r1, current_character(), Operand(kTableSize - 1));
484 __ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
488 Operand(ByteArray::kHeaderSize - kHeapObjectTag));
490 __ ldrb(r0, MemOperand(r0, r1));
491 __ cmp(r0, Operand::Zero());
492 BranchOrBacktrack(ne, on_bit_set);
496 bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type,
497 Label* on_no_match) {
503 if (mode_ == LATIN1) {
506 __ cmp(current_character(), Operand(
' '));
509 __ sub(r0, current_character(), Operand(
'\t'));
510 __ cmp(r0, Operand(
'\r' -
'\t'));
513 __ cmp(r0, Operand(0x00A0 -
'\t'));
514 BranchOrBacktrack(ne, on_no_match);
524 __ sub(r0, current_character(), Operand(
'0'));
525 __ cmp(r0, Operand(
'9' -
'0'));
526 BranchOrBacktrack(hi, on_no_match);
530 __ sub(r0, current_character(), Operand(
'0'));
531 __ cmp(r0, Operand(
'9' -
'0'));
532 BranchOrBacktrack(ls, on_no_match);
536 __ eor(r0, current_character(), Operand(0x01));
538 __ sub(r0, r0, Operand(0x0B));
539 __ cmp(r0, Operand(0x0C - 0x0B));
540 BranchOrBacktrack(ls, on_no_match);
545 __ sub(r0, r0, Operand(0x2028 - 0x0B));
546 __ cmp(r0, Operand(1));
547 BranchOrBacktrack(ls, on_no_match);
553 __ eor(r0, current_character(), Operand(0x01));
555 __ sub(r0, r0, Operand(0x0B));
556 __ cmp(r0, Operand(0x0C - 0x0B));
557 if (mode_ == LATIN1) {
558 BranchOrBacktrack(hi, on_no_match);
565 __ sub(r0, r0, Operand(0x2028 - 0x0B));
566 __ cmp(r0, Operand(1));
567 BranchOrBacktrack(hi, on_no_match);
573 if (mode_ != LATIN1) {
575 __ cmp(current_character(), Operand(
'z'));
576 BranchOrBacktrack(hi, on_no_match);
578 ExternalReference map = ExternalReference::re_word_character_map(isolate());
579 __ mov(r0, Operand(map));
580 __ ldrb(r0, MemOperand(r0, current_character()));
581 __ cmp(r0, Operand::Zero());
582 BranchOrBacktrack(eq, on_no_match);
587 if (mode_ != LATIN1) {
589 __ cmp(current_character(), Operand(
'z'));
592 ExternalReference map = ExternalReference::re_word_character_map(isolate());
593 __ mov(r0, Operand(map));
594 __ ldrb(r0, MemOperand(r0, current_character()));
595 __ cmp(r0, Operand::Zero());
596 BranchOrBacktrack(ne, on_no_match);
597 if (mode_ != LATIN1) {
612 void RegExpMacroAssemblerARM::Fail() {
613 __ mov(r0, Operand(FAILURE));
614 __ jmp(&exit_label_);
618 Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
624 __ bind(&entry_label_);
628 FrameScope scope(masm_, StackFrame::MANUAL);
636 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() |
637 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit();
638 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit();
639 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit());
642 __ add(frame_pointer(), sp, Operand(4 * kPointerSize));
643 __ mov(r0, Operand::Zero());
647 Label stack_limit_hit;
650 ExternalReference stack_limit =
651 ExternalReference::address_of_stack_limit(isolate());
652 __ mov(r0, Operand(stack_limit));
653 __ ldr(r0, MemOperand(r0));
654 __ sub(r0, sp, r0, SetCC);
656 __ b(ls, &stack_limit_hit);
659 __ cmp(r0, Operand(num_registers_ * kPointerSize));
663 __ mov(r0, Operand(EXCEPTION));
666 __ bind(&stack_limit_hit);
667 CallCheckStackGuardState();
668 __ cmp(r0, Operand::Zero());
670 __ b(ne, &return_r0);
675 __ sub(sp, sp, Operand(num_registers_ * kPointerSize));
677 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
679 __ ldr(r0, MemOperand(frame_pointer(), kInputStart));
681 __ sub(current_input_offset(), r0, end_of_input_address());
684 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex));
685 __ sub(r0, current_input_offset(), Operand(char_size()));
686 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0));
689 __ str(r0, MemOperand(frame_pointer(), kStringStartMinusOne));
692 __ mov(code_pointer(), Operand(masm_->CodeObject()));
694 Label load_char_start_regexp, start_regexp;
696 __ cmp(r1, Operand::Zero());
697 __ b(ne, &load_char_start_regexp);
698 __ mov(current_character(), Operand(
'\n'), LeaveCC, eq);
699 __ jmp(&start_regexp);
702 __ bind(&load_char_start_regexp);
704 LoadCurrentCharacterUnchecked(-1, 1);
705 __ bind(&start_regexp);
708 if (num_saved_registers_ > 0) {
710 if (num_saved_registers_ > 8) {
712 __ add(r1, frame_pointer(), Operand(kRegisterZero));
713 __ mov(r2, Operand(num_saved_registers_));
716 __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex));
717 __ sub(r2, r2, Operand(1), SetCC);
718 __ b(ne, &init_loop);
720 for (
int i = 0;
i < num_saved_registers_;
i++) {
721 __ str(r0, register_location(
i));
727 __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
729 __ jmp(&start_label_);
732 if (success_label_.is_linked()) {
734 __ bind(&success_label_);
735 if (num_saved_registers_ > 0) {
737 __ ldr(r1, MemOperand(frame_pointer(), kInputStart));
738 __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput));
739 __ ldr(r2, MemOperand(frame_pointer(), kStartIndex));
740 __ sub(r1, end_of_input_address(), r1);
743 __ mov(r1, Operand(r1, LSR, 1));
746 __ add(r1, r1, Operand(r2));
749 DCHECK_EQ(0, num_saved_registers_ % 2);
753 for (
int i = 0;
i < num_saved_registers_;
i += 2) {
754 __ ldr(r2, register_location(
i));
755 __ ldr(r3, register_location(
i + 1));
756 if (
i == 0 && global_with_zero_length_check()) {
761 __ add(r2, r1, Operand(r2, ASR, 1));
762 __ add(r3, r1, Operand(r3, ASR, 1));
764 __ add(r2, r1, Operand(r2));
765 __ add(r3, r1, Operand(r3));
767 __ str(r2, MemOperand(r0, kPointerSize, PostIndex));
768 __ str(r3, MemOperand(r0, kPointerSize, PostIndex));
774 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
775 __ ldr(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
776 __ ldr(r2, MemOperand(frame_pointer(), kRegisterOutput));
778 __ add(r0, r0, Operand(1));
779 __ str(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
782 __ sub(r1, r1, Operand(num_saved_registers_));
784 __ cmp(r1, Operand(num_saved_registers_));
785 __ b(lt, &return_r0);
787 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters));
789 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize));
790 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput));
793 __ ldr(r0, MemOperand(frame_pointer(), kStringStartMinusOne));
795 if (global_with_zero_length_check()) {
798 __ cmp(current_input_offset(), r4);
800 __ b(ne, &load_char_start_regexp);
802 __ cmp(current_input_offset(), Operand::Zero());
803 __ b(eq, &exit_label_);
807 __ add(current_input_offset(),
808 current_input_offset(),
809 Operand((mode_ == UC16) ? 2 : 1));
810 if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
813 __ b(&load_char_start_regexp);
815 __ mov(r0, Operand(SUCCESS));
820 __ bind(&exit_label_);
822 __ ldr(r0, MemOperand(frame_pointer(), kSuccessfulCaptures));
827 __ mov(sp, frame_pointer());
829 __ ldm(ia_w, sp, registers_to_retain | pc.bit());
832 if (backtrack_label_.is_linked()) {
833 __ bind(&backtrack_label_);
837 Label exit_with_exception;
840 if (check_preempt_label_.is_linked()) {
841 SafeCallTarget(&check_preempt_label_);
843 CallCheckStackGuardState();
844 __ cmp(r0, Operand::Zero());
847 __ b(ne, &return_r0);
850 __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
855 if (stack_overflow_label_.is_linked()) {
856 SafeCallTarget(&stack_overflow_label_);
861 static const int num_arguments = 3;
862 __ PrepareCallCFunction(num_arguments);
863 __ mov(r0, backtrack_stackpointer());
864 __ add(r1, frame_pointer(), Operand(kStackHighEnd));
865 __ mov(r2, Operand(ExternalReference::isolate_address(isolate())));
866 ExternalReference grow_stack =
867 ExternalReference::re_grow_stack(isolate());
868 __ CallCFunction(grow_stack, num_arguments);
871 __ cmp(r0, Operand::Zero());
872 __ b(eq, &exit_with_exception);
874 __ mov(backtrack_stackpointer(), r0);
879 if (exit_with_exception.is_linked()) {
881 __ bind(&exit_with_exception);
883 __ mov(r0, Operand(EXCEPTION));
888 masm_->GetCode(isolate(), &code_desc);
889 Handle<Code> code = isolate()->factory()->NewCode(code_desc, Code::REGEXP,
890 masm_->CodeObject());
891 PROFILE(masm_->isolate(),
892 RegExpCodeCreateEvent(AbstractCode::cast(*code), *source));
893 return Handle<HeapObject>::cast(code);
897 void RegExpMacroAssemblerARM::GoTo(Label* to) {
898 BranchOrBacktrack(al, to);
902 void RegExpMacroAssemblerARM::IfRegisterGE(
int reg,
905 __ ldr(r0, register_location(reg));
906 __ cmp(r0, Operand(comparand));
907 BranchOrBacktrack(ge, if_ge);
911 void RegExpMacroAssemblerARM::IfRegisterLT(
int reg,
914 __ ldr(r0, register_location(reg));
915 __ cmp(r0, Operand(comparand));
916 BranchOrBacktrack(lt, if_lt);
920 void RegExpMacroAssemblerARM::IfRegisterEqPos(
int reg,
922 __ ldr(r0, register_location(reg));
923 __ cmp(r0, Operand(current_input_offset()));
924 BranchOrBacktrack(eq, if_eq);
928 RegExpMacroAssembler::IrregexpImplementation
929 RegExpMacroAssemblerARM::Implementation() {
930 return kARMImplementation;
934 void RegExpMacroAssemblerARM::LoadCurrentCharacter(
int cp_offset,
935 Label* on_end_of_input,
938 DCHECK(cp_offset < (1<<30));
940 if (cp_offset >= 0) {
941 CheckPosition(cp_offset + characters - 1, on_end_of_input);
943 CheckPosition(cp_offset, on_end_of_input);
946 LoadCurrentCharacterUnchecked(cp_offset, characters);
950 void RegExpMacroAssemblerARM::PopCurrentPosition() {
951 Pop(current_input_offset());
955 void RegExpMacroAssemblerARM::PopRegister(
int register_index) {
957 __ str(r0, register_location(register_index));
961 void RegExpMacroAssemblerARM::PushBacktrack(Label* label) {
962 __ mov_label_offset(r0, label);
968 void RegExpMacroAssemblerARM::PushCurrentPosition() {
969 Push(current_input_offset());
973 void RegExpMacroAssemblerARM::PushRegister(
int register_index,
974 StackCheckFlag check_stack_limit) {
975 __ ldr(r0, register_location(register_index));
977 if (check_stack_limit) CheckStackLimit();
981 void RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(
int reg) {
982 __ ldr(current_input_offset(), register_location(reg));
986 void RegExpMacroAssemblerARM::ReadStackPointerFromRegister(
int reg) {
987 __ ldr(backtrack_stackpointer(), register_location(reg));
988 __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd));
989 __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0));
993 void RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(
int by) {
994 Label after_position;
995 __ cmp(current_input_offset(), Operand(-by * char_size()));
996 __ b(ge, &after_position);
997 __ mov(current_input_offset(), Operand(-by * char_size()));
1001 LoadCurrentCharacterUnchecked(-1, 1);
1002 __ bind(&after_position);
1006 void RegExpMacroAssemblerARM::SetRegister(
int register_index,
int to) {
1007 DCHECK(register_index >= num_saved_registers_);
1008 __ mov(r0, Operand(to));
1009 __ str(r0, register_location(register_index));
1013 bool RegExpMacroAssemblerARM::Succeed() {
1014 __ jmp(&success_label_);
1019 void RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(
int reg,
1021 if (cp_offset == 0) {
1022 __ str(current_input_offset(), register_location(reg));
1024 __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1025 __ str(r0, register_location(reg));
1030 void RegExpMacroAssemblerARM::ClearRegisters(
int reg_from,
int reg_to) {
1031 DCHECK(reg_from <= reg_to);
1032 __ ldr(r0, MemOperand(frame_pointer(), kStringStartMinusOne));
1033 for (
int reg = reg_from; reg <= reg_to; reg++) {
1034 __ str(r0, register_location(reg));
1039 void RegExpMacroAssemblerARM::WriteStackPointerToRegister(
int reg) {
1040 __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd));
1041 __ sub(r0, backtrack_stackpointer(), r1);
1042 __ str(r0, register_location(reg));
1048 void RegExpMacroAssemblerARM::CallCheckStackGuardState() {
1049 __ PrepareCallCFunction(3);
1052 __ mov(r2, frame_pointer());
1054 __ mov(r1, Operand(masm_->CodeObject()));
1057 int stack_alignment = base::OS::ActivationFrameAlignment();
1058 DCHECK(IsAligned(stack_alignment, kPointerSize));
1059 __ sub(sp, sp, Operand(stack_alignment));
1064 ExternalReference stack_guard_check =
1065 ExternalReference::re_check_stack_guard_state(isolate());
1066 __ mov(ip, Operand(stack_guard_check));
1067 DirectCEntryStub stub(isolate());
1068 stub.GenerateCall(masm_, ip);
1071 __ add(sp, sp, Operand(stack_alignment));
1073 DCHECK_NE(0, stack_alignment);
1074 __ ldr(sp, MemOperand(sp, 0));
1076 __ mov(code_pointer(), Operand(masm_->CodeObject()));
1081 template <
typename T>
1082 static T& frame_entry(Address re_frame,
int frame_offset) {
1083 return reinterpret_cast<T&
>(Memory<int32_t>(re_frame + frame_offset));
1087 template <
typename T>
1088 static T* frame_entry_address(Address re_frame,
int frame_offset) {
1089 return reinterpret_cast<T*
>(re_frame + frame_offset);
1092 int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
1095 Code re_code = Code::cast(ObjectPtr(raw_code));
1096 return NativeRegExpMacroAssembler::CheckStackGuardState(
1097 frame_entry<Isolate*>(re_frame, kIsolate),
1098 frame_entry<int>(re_frame, kStartIndex),
1099 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
1100 frame_entry_address<Address>(re_frame, kInputString),
1101 frame_entry_address<const byte*>(re_frame, kInputStart),
1102 frame_entry_address<const byte*>(re_frame, kInputEnd));
1106 MemOperand RegExpMacroAssemblerARM::register_location(
int register_index) {
1107 DCHECK(register_index < (1<<30));
1108 if (num_registers_ <= register_index) {
1109 num_registers_ = register_index + 1;
1111 return MemOperand(frame_pointer(),
1112 kRegisterZero - register_index * kPointerSize);
1116 void RegExpMacroAssemblerARM::CheckPosition(
int cp_offset,
1117 Label* on_outside_input) {
1118 if (cp_offset >= 0) {
1119 __ cmp(current_input_offset(), Operand(-cp_offset * char_size()));
1120 BranchOrBacktrack(ge, on_outside_input);
1122 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne));
1123 __ add(r0, current_input_offset(), Operand(cp_offset * char_size()));
1125 BranchOrBacktrack(le, on_outside_input);
1130 void RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition,
1132 if (condition == al) {
1133 if (to ==
nullptr) {
1140 if (to ==
nullptr) {
1141 __ b(condition, &backtrack_label_);
1144 __ b(condition, to);
1148 void RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) {
1153 void RegExpMacroAssemblerARM::SafeReturn() {
1155 __ add(pc, lr, Operand(masm_->CodeObject()));
1159 void RegExpMacroAssemblerARM::SafeCallTarget(Label* name) {
1161 __ sub(lr, lr, Operand(masm_->CodeObject()));
1166 void RegExpMacroAssemblerARM::Push(Register source) {
1167 DCHECK(source != backtrack_stackpointer());
1169 MemOperand(backtrack_stackpointer(), kPointerSize, NegPreIndex));
1173 void RegExpMacroAssemblerARM::Pop(Register target) {
1174 DCHECK(target != backtrack_stackpointer());
1176 MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex));
1180 void RegExpMacroAssemblerARM::CheckPreemption() {
1182 ExternalReference stack_limit =
1183 ExternalReference::address_of_stack_limit(isolate());
1184 __ mov(r0, Operand(stack_limit));
1185 __ ldr(r0, MemOperand(r0));
1187 SafeCall(&check_preempt_label_, ls);
1191 void RegExpMacroAssemblerARM::CheckStackLimit() {
1192 ExternalReference stack_limit =
1193 ExternalReference::address_of_regexp_stack_limit(isolate());
1194 __ mov(r0, Operand(stack_limit));
1195 __ ldr(r0, MemOperand(r0));
1196 __ cmp(backtrack_stackpointer(), Operand(r0));
1197 SafeCall(&stack_overflow_label_, ls);
1201 void RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(
int cp_offset,
1203 Register offset = current_input_offset();
1204 if (cp_offset != 0) {
1206 __ add(r4, current_input_offset(), Operand(cp_offset * char_size()));
1213 if (!CanReadUnaligned()) {
1214 DCHECK_EQ(1, characters);
1217 if (mode_ == LATIN1) {
1218 if (characters == 4) {
1219 __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1220 }
else if (characters == 2) {
1221 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1223 DCHECK_EQ(1, characters);
1224 __ ldrb(current_character(), MemOperand(end_of_input_address(), offset));
1227 DCHECK(mode_ == UC16);
1228 if (characters == 2) {
1229 __ ldr(current_character(), MemOperand(end_of_input_address(), offset));
1231 DCHECK_EQ(1, characters);
1232 __ ldrh(current_character(), MemOperand(end_of_input_address(), offset));
1240 #endif // V8_INTERPRETED_REGEXP 1245 #endif // V8_TARGET_ARCH_ARM