7 #include "src/regexp/x64/regexp-macro-assembler-x64.h" 9 #include "src/heap/factory.h" 11 #include "src/macro-assembler.h" 12 #include "src/objects-inl.h" 13 #include "src/regexp/regexp-macro-assembler.h" 14 #include "src/regexp/regexp-stack.h" 20 #ifndef V8_INTERPRETED_REGEXP 94 #define __ ACCESS_MASM((&masm_)) 96 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64(Isolate* isolate, Zone* zone,
98 int registers_to_save)
99 : NativeRegExpMacroAssembler(isolate, zone),
100 masm_(isolate, nullptr, kRegExpCodeSize, CodeObjectRequired::kYes),
101 no_root_array_scope_(&masm_),
102 code_relative_fixup_positions_(zone),
104 num_registers_(registers_to_save),
105 num_saved_registers_(registers_to_save),
111 DCHECK_EQ(0, registers_to_save % 2);
112 __ jmp(&entry_label_);
113 __ bind(&start_label_);
117 RegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() {
119 entry_label_.Unuse();
120 start_label_.Unuse();
121 success_label_.Unuse();
122 backtrack_label_.Unuse();
124 check_preempt_label_.Unuse();
125 stack_overflow_label_.Unuse();
129 int RegExpMacroAssemblerX64::stack_limit_slack() {
130 return RegExpStack::kStackLimitSlack;
134 void RegExpMacroAssemblerX64::AdvanceCurrentPosition(
int by) {
136 __ addq(rdi, Immediate(by * char_size()));
141 void RegExpMacroAssemblerX64::AdvanceRegister(
int reg,
int by) {
143 DCHECK_GT(num_registers_, reg);
145 __ addp(register_location(reg), Immediate(by));
150 void RegExpMacroAssemblerX64::Backtrack() {
154 __ addp(rbx, code_object_pointer());
159 void RegExpMacroAssemblerX64::Bind(Label* label) {
164 void RegExpMacroAssemblerX64::CheckCharacter(
uint32_t c, Label* on_equal) {
165 __ cmpl(current_character(), Immediate(c));
166 BranchOrBacktrack(equal, on_equal);
170 void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) {
171 __ cmpl(current_character(), Immediate(limit));
172 BranchOrBacktrack(greater, on_greater);
176 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) {
177 __ leap(rax, Operand(rdi, -char_size()));
178 __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
179 BranchOrBacktrack(equal, on_at_start);
183 void RegExpMacroAssemblerX64::CheckNotAtStart(
int cp_offset,
184 Label* on_not_at_start) {
185 __ leap(rax, Operand(rdi, -char_size() + cp_offset * char_size()));
186 __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
187 BranchOrBacktrack(not_equal, on_not_at_start);
191 void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) {
192 __ cmpl(current_character(), Immediate(limit));
193 BranchOrBacktrack(less, on_less);
197 void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) {
199 __ cmpl(rdi, Operand(backtrack_stackpointer(), 0));
200 __ j(not_equal, &fallthrough);
202 BranchOrBacktrack(no_condition, on_equal);
203 __ bind(&fallthrough);
207 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
208 int start_reg,
bool read_backward,
bool unicode, Label* on_no_match) {
210 ReadPositionFromRegister(rdx, start_reg);
211 ReadPositionFromRegister(rbx, start_reg + 1);
221 __ j(equal, &fallthrough);
228 __ movl(rax, Operand(rbp, kStringStartMinusOne));
231 BranchOrBacktrack(less_equal, on_no_match);
235 BranchOrBacktrack(greater, on_no_match);
238 if (mode_ == LATIN1) {
239 Label loop_increment;
240 if (on_no_match ==
nullptr) {
241 on_no_match = &backtrack_label_;
244 __ leap(r9, Operand(rsi, rdx, times_1, 0));
245 __ leap(r11, Operand(rsi, rdi, times_1, 0));
257 __ movzxbl(rdx, Operand(r9, 0));
258 __ movzxbl(rax, Operand(r11, 0));
262 __ j(equal, &loop_increment);
267 __ orp(rax, Immediate(0x20));
268 __ orp(rdx, Immediate(0x20));
270 __ j(not_equal, on_no_match);
271 __ subb(rax, Immediate(
'a'));
272 __ cmpb(rax, Immediate(
'z' -
'a'));
273 __ j(below_equal, &loop_increment);
275 __ subb(rax, Immediate(224 -
'a'));
276 __ cmpb(rax, Immediate(254 - 224));
277 __ j(above, on_no_match);
278 __ cmpb(rax, Immediate(247 - 224));
279 __ j(equal, on_no_match);
280 __ bind(&loop_increment);
282 __ addp(r11, Immediate(1));
283 __ addp(r9, Immediate(1));
293 __ addq(rdi, register_location(start_reg));
294 __ subq(rdi, register_location(start_reg + 1));
297 DCHECK(mode_ == UC16);
304 __ pushq(backtrack_stackpointer());
306 static const int num_arguments = 4;
307 __ PrepareCallCFunction(num_arguments);
315 DCHECK(rcx == arg_reg_1);
316 DCHECK(rdx == arg_reg_2);
318 __ leap(rcx, Operand(rsi, rdx, times_1, 0));
320 __ leap(rdx, Operand(rsi, rdi, times_1, 0));
324 #else // AMD64 calling convention 325 DCHECK(rdi == arg_reg_1);
326 DCHECK(rsi == arg_reg_2);
328 __ leap(rax, Operand(rsi, rdi, times_1, 0));
330 __ leap(rdi, Operand(rsi, rdx, times_1, 0));
339 __ movp(arg_reg_3, rbx);
341 #ifdef V8_INTL_SUPPORT 343 __ movp(arg_reg_4, Immediate(0));
345 #endif // V8_INTL_SUPPORT 347 __ LoadAddress(arg_reg_4, ExternalReference::isolate_address(isolate()));
352 AllowExternalCallThatCantCauseGC scope(&masm_);
353 ExternalReference compare =
354 ExternalReference::re_case_insensitive_compare_uc16(isolate());
355 __ CallCFunction(compare, num_arguments);
359 __ Move(code_object_pointer(), masm_.CodeObject());
360 __ popq(backtrack_stackpointer());
368 BranchOrBacktrack(zero, on_no_match);
377 __ bind(&fallthrough);
381 void RegExpMacroAssemblerX64::CheckNotBackReference(
int start_reg,
383 Label* on_no_match) {
387 ReadPositionFromRegister(rdx, start_reg);
388 ReadPositionFromRegister(rax, start_reg + 1);
394 __ j(equal, &fallthrough);
401 __ movl(rbx, Operand(rbp, kStringStartMinusOne));
404 BranchOrBacktrack(less_equal, on_no_match);
408 BranchOrBacktrack(greater, on_no_match);
412 __ leap(rbx, Operand(rsi, rdi, times_1, 0));
417 __ leap(r9, Operand(rdx, rax, times_1, 0));
426 if (mode_ == LATIN1) {
427 __ movzxbl(rax, Operand(rdx, 0));
428 __ cmpb(rax, Operand(rbx, 0));
430 DCHECK(mode_ == UC16);
431 __ movzxwl(rax, Operand(rdx, 0));
432 __ cmpw(rax, Operand(rbx, 0));
434 BranchOrBacktrack(not_equal, on_no_match);
436 __ addp(rbx, Immediate(char_size()));
437 __ addp(rdx, Immediate(char_size()));
448 __ addq(rdi, register_location(start_reg));
449 __ subq(rdi, register_location(start_reg + 1));
452 __ bind(&fallthrough);
456 void RegExpMacroAssemblerX64::CheckNotCharacter(
uint32_t c,
457 Label* on_not_equal) {
458 __ cmpl(current_character(), Immediate(c));
459 BranchOrBacktrack(not_equal, on_not_equal);
463 void RegExpMacroAssemblerX64::CheckCharacterAfterAnd(
uint32_t c,
467 __ testl(current_character(), Immediate(mask));
469 __ movl(rax, Immediate(mask));
470 __ andp(rax, current_character());
471 __ cmpl(rax, Immediate(c));
473 BranchOrBacktrack(equal, on_equal);
477 void RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(
uint32_t c,
479 Label* on_not_equal) {
481 __ testl(current_character(), Immediate(mask));
483 __ movl(rax, Immediate(mask));
484 __ andp(rax, current_character());
485 __ cmpl(rax, Immediate(c));
487 BranchOrBacktrack(not_equal, on_not_equal);
491 void RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd(
495 Label* on_not_equal) {
496 DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
497 __ leap(rax, Operand(current_character(), -minus));
498 __ andp(rax, Immediate(mask));
499 __ cmpl(rax, Immediate(c));
500 BranchOrBacktrack(not_equal, on_not_equal);
504 void RegExpMacroAssemblerX64::CheckCharacterInRange(
507 Label* on_in_range) {
508 __ leal(rax, Operand(current_character(), -from));
509 __ cmpl(rax, Immediate(to - from));
510 BranchOrBacktrack(below_equal, on_in_range);
514 void RegExpMacroAssemblerX64::CheckCharacterNotInRange(
517 Label* on_not_in_range) {
518 __ leal(rax, Operand(current_character(), -from));
519 __ cmpl(rax, Immediate(to - from));
520 BranchOrBacktrack(above, on_not_in_range);
524 void RegExpMacroAssemblerX64::CheckBitInTable(
525 Handle<ByteArray> table,
528 Register index = current_character();
529 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
530 __ movp(rbx, current_character());
531 __ andp(rbx, Immediate(kTableMask));
534 __ cmpb(FieldOperand(rax, index, times_1, ByteArray::kHeaderSize),
536 BranchOrBacktrack(not_equal, on_bit_set);
540 bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
541 Label* on_no_match) {
549 if (mode_ == LATIN1) {
552 __ cmpl(current_character(), Immediate(
' '));
553 __ j(equal, &success, Label::kNear);
555 __ leap(rax, Operand(current_character(), -
'\t'));
556 __ cmpl(rax, Immediate(
'\r' -
'\t'));
557 __ j(below_equal, &success, Label::kNear);
559 __ cmpl(rax, Immediate(0x00A0 -
'\t'));
560 BranchOrBacktrack(not_equal, on_no_match);
570 __ leap(rax, Operand(current_character(), -
'0'));
571 __ cmpl(rax, Immediate(
'9' -
'0'));
572 BranchOrBacktrack(above, on_no_match);
576 __ leap(rax, Operand(current_character(), -
'0'));
577 __ cmpl(rax, Immediate(
'9' -
'0'));
578 BranchOrBacktrack(below_equal, on_no_match);
582 __ movl(rax, current_character());
583 __ xorp(rax, Immediate(0x01));
585 __ subl(rax, Immediate(0x0B));
586 __ cmpl(rax, Immediate(0x0C - 0x0B));
587 BranchOrBacktrack(below_equal, on_no_match);
592 __ subl(rax, Immediate(0x2028 - 0x0B));
593 __ cmpl(rax, Immediate(0x2029 - 0x2028));
594 BranchOrBacktrack(below_equal, on_no_match);
600 __ movl(rax, current_character());
601 __ xorp(rax, Immediate(0x01));
603 __ subl(rax, Immediate(0x0B));
604 __ cmpl(rax, Immediate(0x0C - 0x0B));
605 if (mode_ == LATIN1) {
606 BranchOrBacktrack(above, on_no_match);
609 BranchOrBacktrack(below_equal, &done);
613 __ subl(rax, Immediate(0x2028 - 0x0B));
614 __ cmpl(rax, Immediate(0x2029 - 0x2028));
615 BranchOrBacktrack(above, on_no_match);
621 if (mode_ != LATIN1) {
623 __ cmpl(current_character(), Immediate(
'z'));
624 BranchOrBacktrack(above, on_no_match);
626 __ Move(rbx, ExternalReference::re_word_character_map(isolate()));
627 DCHECK_EQ(0, word_character_map[0]);
628 __ testb(Operand(rbx, current_character(), times_1, 0),
629 current_character());
630 BranchOrBacktrack(zero, on_no_match);
635 if (mode_ != LATIN1) {
637 __ cmpl(current_character(), Immediate(
'z'));
640 __ Move(rbx, ExternalReference::re_word_character_map(isolate()));
641 DCHECK_EQ(0, word_character_map[0]);
642 __ testb(Operand(rbx, current_character(), times_1, 0),
643 current_character());
644 BranchOrBacktrack(not_zero, on_no_match);
645 if (mode_ != LATIN1) {
661 void RegExpMacroAssemblerX64::Fail() {
662 STATIC_ASSERT(FAILURE == 0);
664 __ Set(rax, FAILURE);
666 __ jmp(&exit_label_);
670 Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
675 __ bind(&entry_label_);
679 FrameScope scope(&masm_, StackFrame::MANUAL);
689 __ movq(Operand(rbp, kInputString), rcx);
690 __ movq(Operand(rbp, kStartIndex), rdx);
691 __ movq(Operand(rbp, kInputStart), r8);
692 __ movq(Operand(rbp, kInputEnd), r9);
700 DCHECK_EQ(kInputString, -1 * kRegisterSize);
701 DCHECK_EQ(kStartIndex, -2 * kRegisterSize);
702 DCHECK_EQ(kInputStart, -3 * kRegisterSize);
703 DCHECK_EQ(kInputEnd, -4 * kRegisterSize);
704 DCHECK_EQ(kRegisterOutput, -5 * kRegisterSize);
705 DCHECK_EQ(kNumOutputRegisters, -6 * kRegisterSize);
716 __ Push(Immediate(0));
717 __ Push(Immediate(0));
720 Label stack_limit_hit;
723 ExternalReference stack_limit =
724 ExternalReference::address_of_stack_limit(isolate());
726 __ Move(kScratchRegister, stack_limit);
727 __ subp(rcx, Operand(kScratchRegister, 0));
729 __ j(below_equal, &stack_limit_hit);
732 __ cmpp(rcx, Immediate(num_registers_ * kPointerSize));
733 __ j(above_equal, &stack_ok);
736 __ Set(rax, EXCEPTION);
739 __ bind(&stack_limit_hit);
740 __ Move(code_object_pointer(), masm_.CodeObject());
741 CallCheckStackGuardState();
744 __ j(not_zero, &return_rax);
749 __ subp(rsp, Immediate(num_registers_ * kPointerSize));
751 __ movp(rsi, Operand(rbp, kInputEnd));
753 __ movp(rdi, Operand(rbp, kInputStart));
758 __ movp(rbx, Operand(rbp, kStartIndex));
761 __ leap(rax, Operand(rdi, rbx, times_2, -char_size()));
763 __ leap(rax, Operand(rdi, rbx, times_1, -char_size()));
767 __ movp(Operand(rbp, kStringStartMinusOne), rax);
772 const int kPageSize = 4096;
773 const int kRegistersPerPage = kPageSize / kPointerSize;
774 for (
int i = num_saved_registers_ + kRegistersPerPage - 1;
776 i += kRegistersPerPage) {
777 __ movp(register_location(
i), rax);
782 __ Move(code_object_pointer(), masm_.CodeObject());
784 Label load_char_start_regexp, start_regexp;
786 __ cmpl(Operand(rbp, kStartIndex), Immediate(0));
787 __ j(not_equal, &load_char_start_regexp, Label::kNear);
788 __ Set(current_character(),
'\n');
789 __ jmp(&start_regexp, Label::kNear);
792 __ bind(&load_char_start_regexp);
794 LoadCurrentCharacterUnchecked(-1, 1);
795 __ bind(&start_regexp);
798 if (num_saved_registers_ > 0) {
802 if (num_saved_registers_ > 8) {
803 __ Set(rcx, kRegisterZero);
806 __ movp(Operand(rbp, rcx, times_1, 0), rax);
807 __ subq(rcx, Immediate(kPointerSize));
809 Immediate(kRegisterZero - num_saved_registers_ * kPointerSize));
810 __ j(greater, &init_loop);
812 for (
int i = 0;
i < num_saved_registers_;
i++) {
813 __ movp(register_location(
i), rax);
819 __ movp(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
821 __ jmp(&start_label_);
824 if (success_label_.is_linked()) {
826 __ bind(&success_label_);
827 if (num_saved_registers_ > 0) {
829 __ movp(rdx, Operand(rbp, kStartIndex));
830 __ movp(rbx, Operand(rbp, kRegisterOutput));
831 __ movp(rcx, Operand(rbp, kInputEnd));
832 __ subp(rcx, Operand(rbp, kInputStart));
834 __ leap(rcx, Operand(rcx, rdx, times_2, 0));
838 for (
int i = 0;
i < num_saved_registers_;
i++) {
839 __ movp(rax, register_location(
i));
840 if (
i == 0 && global_with_zero_length_check()) {
846 __ sarp(rax, Immediate(1));
848 __ movl(Operand(rbx,
i * kIntSize), rax);
855 __ incp(Operand(rbp, kSuccessfulCaptures));
858 __ movsxlq(rcx, Operand(rbp, kNumOutputRegisters));
859 __ subp(rcx, Immediate(num_saved_registers_));
861 __ cmpp(rcx, Immediate(num_saved_registers_));
862 __ j(less, &exit_label_);
864 __ movp(Operand(rbp, kNumOutputRegisters), rcx);
866 __ addp(Operand(rbp, kRegisterOutput),
867 Immediate(num_saved_registers_ * kIntSize));
870 __ movp(rax, Operand(rbp, kStringStartMinusOne));
872 if (global_with_zero_length_check()) {
877 __ j(not_equal, &load_char_start_regexp);
880 __ j(zero, &exit_label_, Label::kNear);
885 __ addq(rdi, Immediate(2));
889 if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
892 __ jmp(&load_char_start_regexp);
894 __ movp(rax, Immediate(SUCCESS));
898 __ bind(&exit_label_);
901 __ movp(rax, Operand(rbp, kSuccessfulCaptures));
904 __ bind(&return_rax);
907 __ leap(rsp, Operand(rbp, kLastCalleeSaveRegister));
914 __ movp(rbx, Operand(rbp, kBackup_rbx));
923 if (backtrack_label_.is_linked()) {
924 __ bind(&backtrack_label_);
928 Label exit_with_exception;
931 if (check_preempt_label_.is_linked()) {
932 SafeCallTarget(&check_preempt_label_);
934 __ pushq(backtrack_stackpointer());
937 CallCheckStackGuardState();
941 __ j(not_zero, &return_rax);
944 __ Move(code_object_pointer(), masm_.CodeObject());
946 __ popq(backtrack_stackpointer());
948 __ movp(rsi, Operand(rbp, kInputEnd));
953 if (stack_overflow_label_.is_linked()) {
954 SafeCallTarget(&stack_overflow_label_);
966 static const int num_arguments = 3;
967 __ PrepareCallCFunction(num_arguments);
971 __ leap(rdx, Operand(rbp, kStackHighEnd));
972 __ LoadAddress(r8, ExternalReference::isolate_address(isolate()));
975 __ movp(rdi, backtrack_stackpointer());
976 __ leap(rsi, Operand(rbp, kStackHighEnd));
977 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate()));
979 ExternalReference grow_stack =
980 ExternalReference::re_grow_stack(isolate());
981 __ CallCFunction(grow_stack, num_arguments);
985 __ j(equal, &exit_with_exception);
987 __ movp(backtrack_stackpointer(), rax);
989 __ Move(code_object_pointer(), masm_.CodeObject());
997 if (exit_with_exception.is_linked()) {
999 __ bind(&exit_with_exception);
1001 __ Set(rax, EXCEPTION);
1002 __ jmp(&return_rax);
1005 FixupCodeRelativePositions();
1008 Isolate* isolate = this->isolate();
1009 masm_.GetCode(isolate, &code_desc);
1011 isolate->factory()->NewCode(code_desc, Code::REGEXP, masm_.CodeObject());
1012 PROFILE(isolate, RegExpCodeCreateEvent(AbstractCode::cast(*code), *source));
1013 return Handle<HeapObject>::cast(code);
1017 void RegExpMacroAssemblerX64::GoTo(Label* to) {
1018 BranchOrBacktrack(no_condition, to);
1022 void RegExpMacroAssemblerX64::IfRegisterGE(
int reg,
1025 __ cmpp(register_location(reg), Immediate(comparand));
1026 BranchOrBacktrack(greater_equal, if_ge);
1030 void RegExpMacroAssemblerX64::IfRegisterLT(
int reg,
1033 __ cmpp(register_location(reg), Immediate(comparand));
1034 BranchOrBacktrack(less, if_lt);
1038 void RegExpMacroAssemblerX64::IfRegisterEqPos(
int reg,
1040 __ cmpp(rdi, register_location(reg));
1041 BranchOrBacktrack(equal, if_eq);
1045 RegExpMacroAssembler::IrregexpImplementation
1046 RegExpMacroAssemblerX64::Implementation() {
1047 return kX64Implementation;
1051 void RegExpMacroAssemblerX64::LoadCurrentCharacter(
int cp_offset,
1052 Label* on_end_of_input,
1055 DCHECK(cp_offset < (1<<30));
1057 if (cp_offset >= 0) {
1058 CheckPosition(cp_offset + characters - 1, on_end_of_input);
1060 CheckPosition(cp_offset, on_end_of_input);
1063 LoadCurrentCharacterUnchecked(cp_offset, characters);
1067 void RegExpMacroAssemblerX64::PopCurrentPosition() {
1072 void RegExpMacroAssemblerX64::PopRegister(
int register_index) {
1074 __ movp(register_location(register_index), rax);
1078 void RegExpMacroAssemblerX64::PushBacktrack(Label* label) {
1084 void RegExpMacroAssemblerX64::PushCurrentPosition() {
1089 void RegExpMacroAssemblerX64::PushRegister(
int register_index,
1090 StackCheckFlag check_stack_limit) {
1091 __ movp(rax, register_location(register_index));
1093 if (check_stack_limit) CheckStackLimit();
1097 STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
1100 void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(
int reg) {
1101 if (kPointerSize == kInt64Size) {
1102 __ movq(rdi, register_location(reg));
1105 __ movsxlq(rdi, register_location(reg));
1110 void RegExpMacroAssemblerX64::ReadPositionFromRegister(Register dst,
int reg) {
1111 if (kPointerSize == kInt64Size) {
1112 __ movq(dst, register_location(reg));
1115 __ movsxlq(dst, register_location(reg));
1120 void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(
int reg) {
1121 __ movp(backtrack_stackpointer(), register_location(reg));
1122 __ addp(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
1126 void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(
int by) {
1127 Label after_position;
1128 __ cmpp(rdi, Immediate(-by * char_size()));
1129 __ j(greater_equal, &after_position, Label::kNear);
1130 __ movq(rdi, Immediate(-by * char_size()));
1134 LoadCurrentCharacterUnchecked(-1, 1);
1135 __ bind(&after_position);
1139 void RegExpMacroAssemblerX64::SetRegister(
int register_index,
int to) {
1140 DCHECK(register_index >= num_saved_registers_);
1141 __ movp(register_location(register_index), Immediate(to));
1145 bool RegExpMacroAssemblerX64::Succeed() {
1146 __ jmp(&success_label_);
1151 void RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(
int reg,
1153 if (cp_offset == 0) {
1154 __ movp(register_location(reg), rdi);
1156 __ leap(rax, Operand(rdi, cp_offset * char_size()));
1157 __ movp(register_location(reg), rax);
1162 void RegExpMacroAssemblerX64::ClearRegisters(
int reg_from,
int reg_to) {
1163 DCHECK(reg_from <= reg_to);
1164 __ movp(rax, Operand(rbp, kStringStartMinusOne));
1165 for (
int reg = reg_from; reg <= reg_to; reg++) {
1166 __ movp(register_location(reg), rax);
1171 void RegExpMacroAssemblerX64::WriteStackPointerToRegister(
int reg) {
1172 __ movp(rax, backtrack_stackpointer());
1173 __ subp(rax, Operand(rbp, kStackHighEnd));
1174 __ movp(register_location(reg), rax);
1180 void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
1183 static const int num_arguments = 3;
1184 __ PrepareCallCFunction(num_arguments);
1187 __ movp(rdx, code_object_pointer());
1192 __ leap(rcx, Operand(rsp, -kPointerSize));
1197 __ movp(rsi, code_object_pointer());
1200 __ leap(rdi, Operand(rsp, -kRegisterSize));
1202 ExternalReference stack_check =
1203 ExternalReference::re_check_stack_guard_state(isolate());
1204 __ CallCFunction(stack_check, num_arguments);
1209 template <
typename T>
1210 static T& frame_entry(Address re_frame,
int frame_offset) {
1211 return reinterpret_cast<T&
>(Memory<int32_t>(re_frame + frame_offset));
1215 template <
typename T>
1216 static T* frame_entry_address(Address re_frame,
int frame_offset) {
1217 return reinterpret_cast<T*
>(re_frame + frame_offset);
1220 int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
1223 Code re_code = Code::cast(ObjectPtr(raw_code));
1224 return NativeRegExpMacroAssembler::CheckStackGuardState(
1225 frame_entry<Isolate*>(re_frame, kIsolate),
1226 frame_entry<int>(re_frame, kStartIndex),
1227 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
1228 frame_entry_address<Address>(re_frame, kInputString),
1229 frame_entry_address<const byte*>(re_frame, kInputStart),
1230 frame_entry_address<const byte*>(re_frame, kInputEnd));
1234 Operand RegExpMacroAssemblerX64::register_location(
int register_index) {
1235 DCHECK(register_index < (1<<30));
1236 if (num_registers_ <= register_index) {
1237 num_registers_ = register_index + 1;
1239 return Operand(rbp, kRegisterZero - register_index * kPointerSize);
1243 void RegExpMacroAssemblerX64::CheckPosition(
int cp_offset,
1244 Label* on_outside_input) {
1245 if (cp_offset >= 0) {
1246 __ cmpl(rdi, Immediate(-cp_offset * char_size()));
1247 BranchOrBacktrack(greater_equal, on_outside_input);
1249 __ leap(rax, Operand(rdi, cp_offset * char_size()));
1250 __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
1251 BranchOrBacktrack(less_equal, on_outside_input);
1256 void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition,
1258 if (condition < 0) {
1259 if (to ==
nullptr) {
1266 if (to ==
nullptr) {
1267 __ j(condition, &backtrack_label_);
1270 __ j(condition, to);
1274 void RegExpMacroAssemblerX64::SafeCall(Label* to) {
1279 void RegExpMacroAssemblerX64::SafeCallTarget(Label* label) {
1281 __ subp(Operand(rsp, 0), code_object_pointer());
1285 void RegExpMacroAssemblerX64::SafeReturn() {
1286 __ addp(Operand(rsp, 0), code_object_pointer());
1291 void RegExpMacroAssemblerX64::Push(Register source) {
1292 DCHECK(source != backtrack_stackpointer());
1294 __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1295 __ movl(Operand(backtrack_stackpointer(), 0), source);
1299 void RegExpMacroAssemblerX64::Push(Immediate value) {
1301 __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1302 __ movl(Operand(backtrack_stackpointer(), 0), value);
1306 void RegExpMacroAssemblerX64::FixupCodeRelativePositions() {
1307 for (
int position : code_relative_fixup_positions_) {
1311 int patch_position = position - kIntSize;
1312 int offset = masm_.long_at(patch_position);
1313 masm_.long_at_put(patch_position,
1319 code_relative_fixup_positions_.Rewind(0);
1323 void RegExpMacroAssemblerX64::Push(Label* backtrack_target) {
1324 __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1325 __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target);
1326 MarkPositionForCodeRelativeFixup();
1330 void RegExpMacroAssemblerX64::Pop(Register target) {
1331 DCHECK(target != backtrack_stackpointer());
1332 __ movsxlq(target, Operand(backtrack_stackpointer(), 0));
1334 __ addp(backtrack_stackpointer(), Immediate(kIntSize));
1338 void RegExpMacroAssemblerX64::Drop() {
1339 __ addp(backtrack_stackpointer(), Immediate(kIntSize));
1343 void RegExpMacroAssemblerX64::CheckPreemption() {
1346 ExternalReference stack_limit =
1347 ExternalReference::address_of_stack_limit(isolate());
1348 __ load_rax(stack_limit);
1350 __ j(above, &no_preempt);
1352 SafeCall(&check_preempt_label_);
1354 __ bind(&no_preempt);
1358 void RegExpMacroAssemblerX64::CheckStackLimit() {
1359 Label no_stack_overflow;
1360 ExternalReference stack_limit =
1361 ExternalReference::address_of_regexp_stack_limit(isolate());
1362 __ load_rax(stack_limit);
1363 __ cmpp(backtrack_stackpointer(), rax);
1364 __ j(above, &no_stack_overflow);
1366 SafeCall(&stack_overflow_label_);
1368 __ bind(&no_stack_overflow);
1372 void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(
int cp_offset,
1374 if (mode_ == LATIN1) {
1375 if (characters == 4) {
1376 __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1377 }
else if (characters == 2) {
1378 __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1380 DCHECK_EQ(1, characters);
1381 __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1384 DCHECK(mode_ == UC16);
1385 if (characters == 2) {
1386 __ movl(current_character(),
1387 Operand(rsi, rdi, times_1, cp_offset *
sizeof(uc16)));
1389 DCHECK_EQ(1, characters);
1390 __ movzxwl(current_character(),
1391 Operand(rsi, rdi, times_1, cp_offset *
sizeof(uc16)));
1398 #endif // V8_INTERPRETED_REGEXP 1403 #endif // V8_TARGET_ARCH_X64