7 #if V8_TARGET_ARCH_ARM64
22 #ifndef V8_INTERPRETED_REGEXP
112 #define __ ACCESS_MASM(masm_)
116 int registers_to_save,
118 : NativeRegExpMacroAssembler(zone),
119 masm_(new MacroAssembler(zone->isolate(),
NULL, kRegExpCodeSize)),
121 num_registers_(registers_to_save),
122 num_saved_registers_(registers_to_save),
128 __ SetStackPointer(csp);
134 __ Bind(&start_label_);
138 RegExpMacroAssemblerARM64::~RegExpMacroAssemblerARM64() {
141 entry_label_.Unuse();
142 start_label_.Unuse();
143 success_label_.Unuse();
144 backtrack_label_.Unuse();
146 check_preempt_label_.Unuse();
147 stack_overflow_label_.Unuse();
150 int RegExpMacroAssemblerARM64::stack_limit_slack() {
151 return RegExpStack::kStackLimitSlack;
155 void RegExpMacroAssemblerARM64::AdvanceCurrentPosition(
int by) {
157 __ Add(current_input_offset(),
158 current_input_offset(), by * char_size());
163 void RegExpMacroAssemblerARM64::AdvanceRegister(
int reg,
int by) {
164 DCHECK((reg >= 0) && (reg < num_registers_));
167 RegisterState register_state = GetRegisterState(reg);
168 switch (register_state) {
170 __ Ldr(w10, register_location(reg));
171 __ Add(w10, w10, by);
172 __ Str(w10, register_location(reg));
175 to_advance = GetCachedRegister(reg);
176 __ Add(to_advance, to_advance, by);
179 to_advance = GetCachedRegister(reg);
180 __ Add(to_advance, to_advance,
191 void RegExpMacroAssemblerARM64::Backtrack() {
194 __ Add(x10, code_pointer(), Operand(w10,
UXTW));
199 void RegExpMacroAssemblerARM64::Bind(Label* label) {
204 void RegExpMacroAssemblerARM64::CheckCharacter(
uint32_t c, Label* on_equal) {
205 CompareAndBranchOrBacktrack(current_character(), c,
eq, on_equal);
209 void RegExpMacroAssemblerARM64::CheckCharacterGT(
uc16 limit,
211 CompareAndBranchOrBacktrack(current_character(), limit,
hi, on_greater);
215 void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) {
218 CompareAndBranchOrBacktrack(start_offset(), 0,
ne, ¬_at_start);
220 __ Add(x10, input_end(), Operand(current_input_offset(),
SXTW));
221 __ Cmp(x10, input_start());
222 BranchOrBacktrack(
eq, on_at_start);
223 __ Bind(¬_at_start);
227 void RegExpMacroAssemblerARM64::CheckNotAtStart(Label* on_not_at_start) {
229 CompareAndBranchOrBacktrack(start_offset(), 0,
ne, on_not_at_start);
231 __ Add(x10, input_end(), Operand(current_input_offset(),
SXTW));
232 __ Cmp(x10, input_start());
233 BranchOrBacktrack(
ne, on_not_at_start);
237 void RegExpMacroAssemblerARM64::CheckCharacterLT(
uc16 limit, Label* on_less) {
238 CompareAndBranchOrBacktrack(current_character(), limit,
lo, on_less);
242 void RegExpMacroAssemblerARM64::CheckCharacters(Vector<const uc16> str,
245 bool check_end_of_string) {
248 if (check_end_of_string) {
250 CheckPosition(cp_offset + str.length() - 1, on_failure);
253 Register characters_address = x11;
255 __ Add(characters_address,
257 Operand(current_input_offset(),
SXTW));
258 if (cp_offset != 0) {
259 __ Add(characters_address, characters_address, cp_offset * char_size());
262 for (
int i = 0;
i < str.length();
i++) {
263 if (mode_ == LATIN1) {
265 DCHECK(str[
i] <= String::kMaxOneByteCharCode);
269 CompareAndBranchOrBacktrack(w10, str[
i],
ne, on_failure);
274 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) {
276 __ Cmp(current_input_offset(), w10);
278 __ Add(backtrack_stackpointer(),
280 BranchOrBacktrack(
eq, on_equal);
283 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
285 Label* on_no_match) {
288 Register capture_start_offset = w10;
291 Register capture_length = w19;
295 DCHECK((start_reg % 2) == 0);
296 if (start_reg < kNumCachedRegisters) {
297 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg));
300 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10));
302 __ Sub(capture_length, w11, capture_start_offset);
304 __ Cbz(capture_length, &fallthrough);
307 __ Cmn(capture_length, current_input_offset());
308 BranchOrBacktrack(
gt, on_no_match);
310 if (mode_ == LATIN1) {
315 Register capture_start_address = x12;
316 Register capture_end_addresss = x13;
317 Register current_position_address = x14;
319 __ Add(capture_start_address,
321 Operand(capture_start_offset,
SXTW));
322 __ Add(capture_end_addresss,
323 capture_start_address,
324 Operand(capture_length,
SXTW));
325 __ Add(current_position_address,
327 Operand(current_input_offset(),
SXTW));
334 __ B(
eq, &loop_check);
337 __ Orr(w10, w10, 0x20);
338 __ Orr(w11, w11, 0x20);
341 __ Sub(w10, w10,
'a');
342 __ Cmp(w10,
'z' -
'a');
343 __ B(
ls, &loop_check);
345 __ Sub(w10, w10, 224 -
'a');
346 __ Cmp(w10, 254 - 224);
350 __ Bind(&loop_check);
351 __ Cmp(capture_start_address, capture_end_addresss);
356 BranchOrBacktrack(
al, on_no_match);
360 __ Sub(current_input_offset().
X(), current_position_address, input_end());
361 if (masm_->emit_debug_code()) {
362 __ Cmp(current_input_offset().
X(), Operand(current_input_offset(),
SXTW));
363 __ Ccmp(current_input_offset(), 0,
NoFlag,
eq);
365 __ Check(
le, kOffsetOutOfRange);
369 int argument_count = 4;
373 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters);
374 __ PushCPURegList(cached_registers);
384 __ Add(x0, input_end(), Operand(capture_start_offset,
SXTW));
386 __ Mov(w2, capture_length);
388 __ Add(x1, input_end(), Operand(current_input_offset(),
SXTW));
390 __ Mov(x3, ExternalReference::isolate_address(isolate()));
393 AllowExternalCallThatCantCauseGC scope(masm_);
394 ExternalReference
function =
395 ExternalReference::re_case_insensitive_compare_uc16(isolate());
396 __ CallCFunction(
function, argument_count);
403 __ PopCPURegList(cached_registers);
404 BranchOrBacktrack(
eq, on_no_match);
407 __ Add(current_input_offset(), current_input_offset(), capture_length);
410 __ Bind(&fallthrough);
413 void RegExpMacroAssemblerARM64::CheckNotBackReference(
415 Label* on_no_match) {
418 Register capture_start_address = x12;
419 Register capture_end_address = x13;
420 Register current_position_address = x14;
421 Register capture_length = w15;
424 DCHECK((start_reg % 2) == 0);
425 if (start_reg < kNumCachedRegisters) {
426 __ Mov(x10, GetCachedRegister(start_reg));
429 __ Ldp(w11, w10, capture_location(start_reg, x10));
431 __ Sub(capture_length, w11, w10);
433 __ Cbz(capture_length, &fallthrough);
436 __ Cmn(capture_length, current_input_offset());
437 BranchOrBacktrack(
gt, on_no_match);
440 __ Add(capture_start_address, input_end(), Operand(w10,
SXTW));
441 __ Add(capture_end_address,
442 capture_start_address,
443 Operand(capture_length,
SXTW));
444 __ Add(current_position_address,
446 Operand(current_input_offset(),
SXTW));
450 if (mode_ == LATIN1) {
459 BranchOrBacktrack(
ne, on_no_match);
460 __ Cmp(capture_start_address, capture_end_address);
464 __ Sub(current_input_offset().
X(), current_position_address, input_end());
465 if (masm_->emit_debug_code()) {
466 __ Cmp(current_input_offset().
X(), Operand(current_input_offset(),
SXTW));
467 __ Ccmp(current_input_offset(), 0,
NoFlag,
eq);
469 __ Check(
le, kOffsetOutOfRange);
471 __ Bind(&fallthrough);
475 void RegExpMacroAssemblerARM64::CheckNotCharacter(
unsigned c,
476 Label* on_not_equal) {
477 CompareAndBranchOrBacktrack(current_character(), c,
ne, on_not_equal);
481 void RegExpMacroAssemblerARM64::CheckCharacterAfterAnd(
uint32_t c,
484 __ And(w10, current_character(), mask);
485 CompareAndBranchOrBacktrack(w10, c,
eq, on_equal);
489 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterAnd(
unsigned c,
491 Label* on_not_equal) {
492 __ And(w10, current_character(), mask);
493 CompareAndBranchOrBacktrack(w10, c,
ne, on_not_equal);
497 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd(
501 Label* on_not_equal) {
502 DCHECK(minus < String::kMaxUtf16CodeUnit);
503 __ Sub(w10, current_character(), minus);
504 __ And(w10, w10, mask);
505 CompareAndBranchOrBacktrack(w10, c,
ne, on_not_equal);
509 void RegExpMacroAssemblerARM64::CheckCharacterInRange(
512 Label* on_in_range) {
513 __ Sub(w10, current_character(), from);
515 CompareAndBranchOrBacktrack(w10,
to - from,
ls, on_in_range);
519 void RegExpMacroAssemblerARM64::CheckCharacterNotInRange(
522 Label* on_not_in_range) {
523 __ Sub(w10, current_character(), from);
525 CompareAndBranchOrBacktrack(w10,
to - from,
hi, on_not_in_range);
529 void RegExpMacroAssemblerARM64::CheckBitInTable(
530 Handle<ByteArray> table,
532 __ Mov(x11, Operand(table));
533 if ((mode_ != LATIN1) || (kTableMask != String::kMaxOneByteCharCode)) {
534 __ And(w10, current_character(), kTableMask);
540 CompareAndBranchOrBacktrack(w11, 0,
ne, on_bit_set);
544 bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(
uc16 type,
545 Label* on_no_match) {
551 if (mode_ == LATIN1) {
555 __ Cmp(current_character(),
' ');
556 __ Ccmp(current_character(), 0x00a0,
ZFlag,
ne);
559 __ Sub(w10, current_character(),
'\t');
560 CompareAndBranchOrBacktrack(w10,
'\r' -
'\t',
hi, on_no_match);
570 __ Sub(w10, current_character(),
'0');
571 CompareAndBranchOrBacktrack(w10,
'9' -
'0',
hi, on_no_match);
575 __ Sub(w10, current_character(),
'0');
576 CompareAndBranchOrBacktrack(w10,
'9' -
'0',
ls, on_no_match);
583 __ Cmp(current_character(), 0x0a);
584 __ Ccmp(current_character(), 0x0d,
ZFlag,
ne);
586 __ Sub(w10, current_character(), 0x2028);
590 BranchOrBacktrack(
ls, on_no_match);
592 BranchOrBacktrack(
eq, on_no_match);
600 __ Cmp(current_character(), 0x0a);
601 __ Ccmp(current_character(), 0x0d,
ZFlag,
ne);
603 __ Sub(w10, current_character(), 0x2028);
607 BranchOrBacktrack(
hi, on_no_match);
609 BranchOrBacktrack(
ne, on_no_match);
614 if (mode_ != LATIN1) {
616 CompareAndBranchOrBacktrack(current_character(),
'z',
hi, on_no_match);
618 ExternalReference
map = ExternalReference::re_word_character_map();
621 CompareAndBranchOrBacktrack(w10, 0,
eq, on_no_match);
626 if (mode_ != LATIN1) {
628 __ Cmp(current_character(),
'z');
631 ExternalReference
map = ExternalReference::re_word_character_map();
634 CompareAndBranchOrBacktrack(w10, 0,
ne, on_no_match);
648 void RegExpMacroAssemblerARM64::Fail() {
654 Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
660 __ Bind(&entry_label_);
678 FrameScope scope(masm_, StackFrame::MANUAL);
681 CPURegList argument_registers(x0, x5, x6, x7);
685 registers_to_retain.Combine(
lr);
688 __ PushCPURegList(registers_to_retain);
689 __ PushCPURegList(argument_registers);
692 __ Add(frame_pointer(), csp, argument_registers.Count() *
kPointerSize);
695 __ Mov(start_offset(), w1);
696 __ Mov(input_start(), x2);
697 __ Mov(input_end(), x3);
698 __ Mov(output_array(), x4);
703 int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters;
705 if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; }
707 num_wreg_to_allocate += 2;
710 int alignment = masm_->ActivationFrameAlignment();
712 int align_mask = (alignment /
kWRegSize) - 1;
713 num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask;
716 Label stack_limit_hit;
719 ExternalReference stack_limit =
720 ExternalReference::address_of_stack_limit(isolate());
721 __ Mov(x10, stack_limit);
723 __ Subs(x10, csp, x10);
726 __ B(
ls, &stack_limit_hit);
735 __ Mov(w0, EXCEPTION);
738 __ Bind(&stack_limit_hit);
739 CallCheckStackGuardState(x10);
741 __ Cbnz(w0, &return_w0);
749 __ Str(wzr,
MemOperand(frame_pointer(), kSuccessCounter));
752 __ Sub(x10, input_start(), input_end());
753 if (masm_->emit_debug_code()) {
756 __ Cmp(x11, (1<<30) - 1);
757 __ Check(
ls, kInputStringTooLong);
759 __ Mov(current_input_offset(), w10);
764 __ Sub(non_position_value(), current_input_offset(), char_size());
765 __ Sub(non_position_value(), non_position_value(),
766 Operand(start_offset(),
LSL, (mode_ == UC16) ? 1 : 0));
769 __ Orr(twice_non_position_value(),
770 non_position_value().
X(),
774 __ Mov(code_pointer(), Operand(masm_->CodeObject()));
776 Label load_char_start_regexp, start_regexp;
778 __ Cbnz(start_offset(), &load_char_start_regexp);
779 __ Mov(current_character(),
'\n');
783 __ Bind(&load_char_start_regexp);
785 LoadCurrentCharacterUnchecked(-1, 1);
786 __ Bind(&start_regexp);
788 if (num_saved_registers_ > 0) {
789 ClearRegisters(0, num_saved_registers_ - 1);
793 __ Ldr(backtrack_stackpointer(),
MemOperand(frame_pointer(), kStackBase));
798 if (backtrack_label_.is_linked()) {
799 __ Bind(&backtrack_label_);
803 if (success_label_.is_linked()) {
804 Register first_capture_start = w15;
807 __ Bind(&success_label_);
809 if (num_saved_registers_ > 0) {
811 Register capture_start = w12;
812 Register capture_end = w13;
813 Register input_length = w14;
818 __ Sub(x10, input_end(), input_start());
819 if (masm_->emit_debug_code()) {
821 __ Cmp(x10, (1<<30) - 1);
822 __ Check(
ls, kInputStringTooLong);
827 __ Add(input_length, start_offset(), Operand(w10,
LSR, 1));
829 __ Add(input_length, start_offset(), w10);
834 (
i < num_saved_registers_) && (
i < kNumCachedRegisters);
836 __ Mov(capture_start.X(), GetCachedRegister(
i));
838 if ((
i == 0) && global_with_zero_length_check()) {
840 __ Mov(first_capture_start, capture_start);
844 __ Add(capture_start, input_length, Operand(capture_start,
ASR, 1));
845 __ Add(capture_end, input_length, Operand(capture_end,
ASR, 1));
847 __ Add(capture_start, input_length, capture_start);
848 __ Add(capture_end, input_length, capture_end);
851 __ Stp(capture_start,
858 int num_registers_left_on_stack =
859 num_saved_registers_ - kNumCachedRegisters;
860 if (num_registers_left_on_stack > 0) {
864 DCHECK_EQ(0, num_registers_left_on_stack % 2);
865 __ Add(base, frame_pointer(), kFirstCaptureOnStack);
870 if (num_registers_left_on_stack <= kNumRegistersToUnroll) {
871 for (
int i = 0;
i < num_registers_left_on_stack / 2;
i++) {
875 if ((
i == 0) && global_with_zero_length_check()) {
877 __ Mov(first_capture_start, capture_start);
881 __ Add(capture_start,
883 Operand(capture_start,
ASR, 1));
884 __ Add(capture_end, input_length, Operand(capture_end,
ASR, 1));
886 __ Add(capture_start, input_length, capture_start);
887 __ Add(capture_end, input_length, capture_end);
890 __ Stp(capture_start,
896 __ Mov(x11, num_registers_left_on_stack);
901 if (global_with_zero_length_check()) {
902 __ Mov(first_capture_start, capture_start);
912 __ Add(capture_start, input_length, Operand(capture_start,
ASR, 1));
913 __ Add(capture_end, input_length, Operand(capture_end,
ASR, 1));
915 __ Add(capture_start, input_length, capture_start);
916 __ Add(capture_end, input_length, capture_end);
919 __ Stp(capture_start,
929 Register success_counter = w0;
930 Register output_size = x10;
934 __ Ldr(success_counter,
MemOperand(frame_pointer(), kSuccessCounter));
935 __ Add(success_counter, success_counter, 1);
936 __ Str(success_counter,
MemOperand(frame_pointer(), kSuccessCounter));
940 __ Ldr(output_size,
MemOperand(frame_pointer(), kOutputSize));
941 __ Sub(output_size, output_size, num_saved_registers_);
943 __ Cmp(output_size, num_saved_registers_);
944 __ B(
lt, &return_w0);
949 __ Str(output_size,
MemOperand(frame_pointer(), kOutputSize));
951 if (global_with_zero_length_check()) {
953 __ Cmp(current_input_offset(), first_capture_start);
955 __ B(
ne, &load_char_start_regexp);
957 __ Cbz(current_input_offset(), &return_w0);
959 __ Add(current_input_offset(),
960 current_input_offset(),
961 Operand((mode_ == UC16) ? 2 : 1));
964 __ B(&load_char_start_regexp);
970 if (exit_label_.is_linked()) {
972 __ Bind(&exit_label_);
974 __ Ldr(w0,
MemOperand(frame_pointer(), kSuccessCounter));
983 __ AssertStackConsistency();
986 __ PopCPURegList(registers_to_retain);
990 Label exit_with_exception;
994 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters);
996 if (check_preempt_label_.is_linked()) {
997 __ Bind(&check_preempt_label_);
1000 __ PushCPURegList(cached_registers);
1001 CallCheckStackGuardState(x10);
1004 __ Cbnz(w0, &return_w0);
1006 __ PopCPURegList(cached_registers);
1007 RestoreLinkRegister();
1011 if (stack_overflow_label_.is_linked()) {
1012 __ Bind(&stack_overflow_label_);
1015 __ PushCPURegList(cached_registers);
1017 __ Mov(x2, ExternalReference::isolate_address(isolate()));
1018 __ Add(x1, frame_pointer(), kStackBase);
1019 __ Mov(x0, backtrack_stackpointer());
1020 ExternalReference grow_stack =
1021 ExternalReference::re_grow_stack(isolate());
1022 __ CallCFunction(grow_stack, 3);
1027 __ Cbz(w0, &exit_with_exception);
1029 __ Mov(backtrack_stackpointer(), x0);
1031 __ PopCPURegList(cached_registers);
1032 RestoreLinkRegister();
1036 if (exit_with_exception.is_linked()) {
1037 __ Bind(&exit_with_exception);
1038 __ Mov(w0, EXCEPTION);
1043 masm_->GetCode(&code_desc);
1044 Handle<Code> code = isolate()->factory()->NewCode(
1045 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject());
1046 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
1047 return Handle<HeapObject>::cast(code);
1051 void RegExpMacroAssemblerARM64::GoTo(Label*
to) {
1052 BranchOrBacktrack(
al,
to);
1055 void RegExpMacroAssemblerARM64::IfRegisterGE(
int reg,
int comparand,
1057 Register to_compare = GetRegister(reg, w10);
1058 CompareAndBranchOrBacktrack(to_compare, comparand,
ge, if_ge);
1062 void RegExpMacroAssemblerARM64::IfRegisterLT(
int reg,
int comparand,
1064 Register to_compare = GetRegister(reg, w10);
1065 CompareAndBranchOrBacktrack(to_compare, comparand,
lt, if_lt);
1069 void RegExpMacroAssemblerARM64::IfRegisterEqPos(
int reg, Label* if_eq) {
1070 Register to_compare = GetRegister(reg, w10);
1071 __ Cmp(to_compare, current_input_offset());
1072 BranchOrBacktrack(
eq, if_eq);
1075 RegExpMacroAssembler::IrregexpImplementation
1076 RegExpMacroAssemblerARM64::Implementation() {
1077 return kARM64Implementation;
1081 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(
int cp_offset,
1082 Label* on_end_of_input,
1089 DCHECK(cp_offset < (1<<30));
1091 CheckPosition(cp_offset + characters - 1, on_end_of_input);
1093 LoadCurrentCharacterUnchecked(cp_offset, characters);
1097 void RegExpMacroAssemblerARM64::PopCurrentPosition() {
1098 Pop(current_input_offset());
1102 void RegExpMacroAssemblerARM64::PopRegister(
int register_index) {
1104 StoreRegister(register_index, w10);
1108 void RegExpMacroAssemblerARM64::PushBacktrack(Label* label) {
1109 if (label->is_bound()) {
1110 int target = label->pos();
1113 __ Adr(x10, label, MacroAssembler::kAdrFar);
1114 __ Sub(x10, x10, code_pointer());
1115 if (masm_->emit_debug_code()) {
1118 __ Check(
ls, kOffsetOutOfRange);
1126 void RegExpMacroAssemblerARM64::PushCurrentPosition() {
1127 Push(current_input_offset());
1131 void RegExpMacroAssemblerARM64::PushRegister(
int register_index,
1132 StackCheckFlag check_stack_limit) {
1133 Register to_push = GetRegister(register_index, w10);
1135 if (check_stack_limit) CheckStackLimit();
1139 void RegExpMacroAssemblerARM64::ReadCurrentPositionFromRegister(
int reg) {
1140 Register cached_register;
1141 RegisterState register_state = GetRegisterState(reg);
1142 switch (register_state) {
1144 __ Ldr(current_input_offset(), register_location(reg));
1147 cached_register = GetCachedRegister(reg);
1148 __ Mov(current_input_offset(), cached_register.W());
1151 cached_register = GetCachedRegister(reg);
1161 void RegExpMacroAssemblerARM64::ReadStackPointerFromRegister(
int reg) {
1162 Register read_from = GetRegister(reg, w10);
1164 __ Add(backtrack_stackpointer(), x11, Operand(read_from,
SXTW));
1168 void RegExpMacroAssemblerARM64::SetCurrentPositionFromEnd(
int by) {
1169 Label after_position;
1170 __ Cmp(current_input_offset(), -by * char_size());
1171 __ B(
ge, &after_position);
1172 __ Mov(current_input_offset(), -by * char_size());
1176 LoadCurrentCharacterUnchecked(-1, 1);
1177 __ Bind(&after_position);
1181 void RegExpMacroAssemblerARM64::SetRegister(
int register_index,
int to) {
1182 DCHECK(register_index >= num_saved_registers_);
1183 Register set_to = wzr;
1188 StoreRegister(register_index, set_to);
1192 bool RegExpMacroAssemblerARM64::Succeed() {
1193 __ B(&success_label_);
1198 void RegExpMacroAssemblerARM64::WriteCurrentPositionToRegister(
int reg,
1200 Register position = current_input_offset();
1201 if (cp_offset != 0) {
1203 __ Add(position, current_input_offset(), cp_offset * char_size());
1205 StoreRegister(reg, position);
1209 void RegExpMacroAssemblerARM64::ClearRegisters(
int reg_from,
int reg_to) {
1210 DCHECK(reg_from <= reg_to);
1211 int num_registers = reg_to - reg_from + 1;
1215 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) {
1216 StoreRegister(reg_from, non_position_value());
1222 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) {
1223 DCHECK(GetRegisterState(reg_from) == CACHED_LSW);
1224 __ Mov(GetCachedRegister(reg_from), twice_non_position_value());
1229 if ((num_registers % 2) == 1) {
1230 StoreRegister(reg_from, non_position_value());
1235 if (num_registers > 0) {
1237 DCHECK(reg_from >= kNumCachedRegisters);
1241 reg_from -= kNumCachedRegisters;
1242 reg_to -= kNumCachedRegisters;
1246 int base_offset = kFirstRegisterOnStack -
1248 if (num_registers > kNumRegistersToUnroll) {
1249 Register base = x10;
1250 __ Add(base, frame_pointer(), base_offset);
1253 __ Mov(x11, num_registers);
1255 __ Str(twice_non_position_value(),
1257 __ Sub(x11, x11, 2);
1258 __ Cbnz(x11, &loop);
1260 for (
int i = reg_from;
i <= reg_to;
i += 2) {
1261 __ Str(twice_non_position_value(),
1270 void RegExpMacroAssemblerARM64::WriteStackPointerToRegister(
int reg) {
1272 __ Sub(x10, backtrack_stackpointer(), x10);
1273 if (masm_->emit_debug_code()) {
1274 __ Cmp(x10, Operand(w10,
SXTW));
1276 __ Check(
eq, kOffsetOutOfRange);
1278 StoreRegister(reg, w10);
1283 template <
typename T>
1284 static T& frame_entry(
Address re_frame,
int frame_offset) {
1285 return *
reinterpret_cast<T*
>(re_frame + frame_offset);
1289 int RegExpMacroAssemblerARM64::CheckStackGuardState(
Address* return_address,
1293 const byte** input_start,
1294 const byte** input_end) {
1295 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1296 StackLimitCheck check(isolate);
1297 if (check.JsHasOverflowed()) {
1298 isolate->StackOverflow();
1307 if (frame_entry<int>(re_frame, kDirectCall) == 1) {
1312 HandleScope handles(isolate);
1313 Handle<Code> code_handle(re_code);
1315 Handle<String> subject(frame_entry<String*>(re_frame, kInput));
1318 bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
1320 DCHECK(re_code->instruction_start() <= *return_address);
1321 DCHECK(*return_address <=
1322 re_code->instruction_start() + re_code->instruction_size());
1324 Object* result = isolate->stack_guard()->HandleInterrupts();
1326 if (*code_handle != re_code) {
1327 int delta = code_handle->address() - re_code->address();
1329 *return_address += delta;
1332 if (result->IsException()) {
1336 Handle<String> subject_tmp = subject;
1337 int slice_offset = 0;
1340 if (StringShape(*subject_tmp).IsCons()) {
1341 subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
1342 }
else if (StringShape(*subject_tmp).IsSliced()) {
1343 SlicedString* slice = SlicedString::cast(*subject_tmp);
1344 subject_tmp = Handle<String>(slice->parent());
1345 slice_offset = slice->offset();
1349 if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
1360 DCHECK(StringShape(*subject_tmp).IsSequential() ||
1361 StringShape(*subject_tmp).IsExternal());
1364 const byte* start_address = *input_start;
1368 const byte* new_address = StringCharacterPosition(*subject_tmp,
1369 start_offset + slice_offset);
1371 if (start_address != new_address) {
1374 const byte* end_address = *input_end;
1375 int byte_length =
static_cast<int>(end_address - start_address);
1376 frame_entry<const String*>(re_frame, kInput) = *subject;
1377 *input_start = new_address;
1378 *input_end = new_address + byte_length;
1379 }
else if (frame_entry<const String*>(re_frame, kInput) != *subject) {
1383 frame_entry<const String*>(re_frame, kInput) = *subject;
1390 void RegExpMacroAssemblerARM64::CheckPosition(
int cp_offset,
1391 Label* on_outside_input) {
1392 CompareAndBranchOrBacktrack(current_input_offset(),
1393 -cp_offset * char_size(),
1399 bool RegExpMacroAssemblerARM64::CanReadUnaligned() {
1401 return !slow_safe();
1407 void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) {
1412 int alignment = masm_->ActivationFrameAlignment();
1414 int align_mask = (alignment /
kXRegSize) - 1;
1415 int xreg_to_claim = (3 + align_mask) & ~align_mask;
1418 __ Claim(xreg_to_claim);
1426 __ Mov(w3, start_offset());
1428 __ Mov(x2, frame_pointer());
1430 __ Mov(x1, Operand(masm_->CodeObject()));
1437 ExternalReference check_stack_guard_state =
1438 ExternalReference::re_check_stack_guard_state(isolate());
1439 __ Mov(scratch, check_stack_guard_state);
1440 DirectCEntryStub stub(isolate());
1441 stub.GenerateCall(masm_, scratch);
1448 __ Drop(xreg_to_claim);
1451 __ Mov(code_pointer(), Operand(masm_->CodeObject()));
1454 void RegExpMacroAssemblerARM64::BranchOrBacktrack(
Condition condition,
1456 if (condition ==
al) {
1465 to = &backtrack_label_;
1467 __ B(condition,
to);
1470 void RegExpMacroAssemblerARM64::CompareAndBranchOrBacktrack(Register reg,
1474 if ((immediate == 0) && ((condition ==
eq) || (condition ==
ne))) {
1476 to = &backtrack_label_;
1478 if (condition ==
eq) {
1484 __ Cmp(reg, immediate);
1485 BranchOrBacktrack(condition,
to);
1490 void RegExpMacroAssemblerARM64::CheckPreemption() {
1492 ExternalReference stack_limit =
1493 ExternalReference::address_of_stack_limit(isolate());
1494 __ Mov(x10, stack_limit);
1498 CallIf(&check_preempt_label_,
ls);
1502 void RegExpMacroAssemblerARM64::CheckStackLimit() {
1503 ExternalReference stack_limit =
1504 ExternalReference::address_of_regexp_stack_limit(isolate());
1505 __ Mov(x10, stack_limit);
1507 __ Cmp(backtrack_stackpointer(), x10);
1508 CallIf(&stack_overflow_label_,
ls);
1513 DCHECK(source.Is32Bits());
1514 DCHECK(!source.is(backtrack_stackpointer()));
1522 void RegExpMacroAssemblerARM64::Pop(Register target) {
1523 DCHECK(target.Is32Bits());
1524 DCHECK(!target.is(backtrack_stackpointer()));
1530 Register RegExpMacroAssemblerARM64::GetCachedRegister(
int register_index) {
1531 DCHECK(register_index < kNumCachedRegisters);
1536 Register RegExpMacroAssemblerARM64::GetRegister(
int register_index,
1537 Register maybe_result) {
1538 DCHECK(maybe_result.Is32Bits());
1539 DCHECK(register_index >= 0);
1540 if (num_registers_ <= register_index) {
1541 num_registers_ = register_index + 1;
1544 RegisterState register_state = GetRegisterState(register_index);
1545 switch (register_state) {
1547 __ Ldr(maybe_result, register_location(register_index));
1548 result = maybe_result;
1551 result = GetCachedRegister(register_index).W();
1554 __ Lsr(maybe_result.X(), GetCachedRegister(register_index),
1556 result = maybe_result;
1562 DCHECK(result.Is32Bits());
1567 void RegExpMacroAssemblerARM64::StoreRegister(
int register_index,
1569 DCHECK(source.Is32Bits());
1570 DCHECK(register_index >= 0);
1571 if (num_registers_ <= register_index) {
1572 num_registers_ = register_index + 1;
1575 Register cached_register;
1576 RegisterState register_state = GetRegisterState(register_index);
1577 switch (register_state) {
1579 __ Str(source, register_location(register_index));
1582 cached_register = GetCachedRegister(register_index);
1583 if (!source.Is(cached_register.W())) {
1588 cached_register = GetCachedRegister(register_index);
1598 void RegExpMacroAssemblerARM64::CallIf(Label*
to,
Condition condition) {
1602 __ Bind(&skip_call);
1606 void RegExpMacroAssemblerARM64::RestoreLinkRegister() {
1609 __ Add(
lr,
lr, Operand(masm_->CodeObject()));
1613 void RegExpMacroAssemblerARM64::SaveLinkRegister() {
1615 __ Sub(
lr,
lr, Operand(masm_->CodeObject()));
1620 MemOperand RegExpMacroAssemblerARM64::register_location(
int register_index) {
1621 DCHECK(register_index < (1<<30));
1622 DCHECK(register_index >= kNumCachedRegisters);
1623 if (num_registers_ <= register_index) {
1624 num_registers_ = register_index + 1;
1626 register_index -= kNumCachedRegisters;
1627 int offset = kFirstRegisterOnStack - register_index *
kWRegSize;
1631 MemOperand RegExpMacroAssemblerARM64::capture_location(
int register_index,
1633 DCHECK(register_index < (1<<30));
1634 DCHECK(register_index < num_saved_registers_);
1635 DCHECK(register_index >= kNumCachedRegisters);
1637 register_index -= kNumCachedRegisters;
1638 int offset = kFirstCaptureOnStack - register_index *
kWRegSize;
1641 if (is_int7(offset)) {
1644 __ Add(scratch, frame_pointer(), offset);
1649 void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(
int cp_offset,
1651 Register offset = current_input_offset();
1661 if (!CanReadUnaligned()) {
1665 if (cp_offset != 0) {
1666 if (masm_->emit_debug_code()) {
1667 __ Mov(x10, cp_offset * char_size());
1668 __ Add(x10, x10, Operand(current_input_offset(),
SXTW));
1669 __ Cmp(x10, Operand(w10,
SXTW));
1671 __ Check(
eq, kOffsetOutOfRange);
1673 __ Add(w10, current_input_offset(), cp_offset * char_size());
1678 if (mode_ == LATIN1) {
1679 if (characters == 4) {
1681 }
else if (characters == 2) {
1689 if (characters == 2) {
RegExpMacroAssemblerARM64(Mode mode, int registers_to_save, Zone *zone)
#define PROFILE(IsolateGetter, Call)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define STATIC_ASSERT(test)
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
const unsigned kWRegSizeLog2
const unsigned kXRegSizeInBits
const unsigned kWRegSizeInBits
kSerializedDataOffset Object
Condition NegateCondition(Condition cond)
Debugger support for the V8 JavaScript engine.
#define T(name, string, precedence)
Definitions and convenience functions for working with unicode.