| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if V8_TARGET_ARCH_A64 | 30 #if V8_TARGET_ARCH_ARM64 |
| 31 | 31 |
| 32 #include "cpu-profiler.h" | 32 #include "cpu-profiler.h" |
| 33 #include "unicode.h" | 33 #include "unicode.h" |
| 34 #include "log.h" | 34 #include "log.h" |
| 35 #include "code-stubs.h" | 35 #include "code-stubs.h" |
| 36 #include "regexp-stack.h" | 36 #include "regexp-stack.h" |
| 37 #include "macro-assembler.h" | 37 #include "macro-assembler.h" |
| 38 #include "regexp-macro-assembler.h" | 38 #include "regexp-macro-assembler.h" |
| 39 #include "a64/regexp-macro-assembler-a64.h" | 39 #include "arm64/regexp-macro-assembler-arm64.h" |
| 40 | 40 |
| 41 namespace v8 { | 41 namespace v8 { |
| 42 namespace internal { | 42 namespace internal { |
| 43 | 43 |
| 44 #ifndef V8_INTERPRETED_REGEXP | 44 #ifndef V8_INTERPRETED_REGEXP |
| 45 /* | 45 /* |
| 46 * This assembler uses the following register assignment convention: | 46 * This assembler uses the following register assignment convention: |
| 47 * - w19 : Used to temporarely store a value before a call to C code. | 47 * - w19 : Used to temporarely store a value before a call to C code. |
| 48 * See CheckNotBackReferenceIgnoreCase. | 48 * See CheckNotBackReferenceIgnoreCase. |
| 49 * - x20 : Pointer to the current code object (Code*), | 49 * - x20 : Pointer to the current code object (Code*), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 * Address input_start, | 117 * Address input_start, |
| 118 * Address input_end, | 118 * Address input_end, |
| 119 * int* output, | 119 * int* output, |
| 120 * int output_size, | 120 * int output_size, |
| 121 * Address stack_base, | 121 * Address stack_base, |
| 122 * bool direct_call = false, | 122 * bool direct_call = false, |
| 123 * Address secondary_return_address, // Only used by native call. | 123 * Address secondary_return_address, // Only used by native call. |
| 124 * Isolate* isolate) | 124 * Isolate* isolate) |
| 125 * The call is performed by NativeRegExpMacroAssembler::Execute() | 125 * The call is performed by NativeRegExpMacroAssembler::Execute() |
| 126 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro | 126 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro |
| 127 * in a64/simulator-a64.h. | 127 * in arm64/simulator-arm64.h. |
| 128 * When calling as a non-direct call (i.e., from C++ code), the return address | 128 * When calling as a non-direct call (i.e., from C++ code), the return address |
| 129 * area is overwritten with the LR register by the RegExp code. When doing a | 129 * area is overwritten with the LR register by the RegExp code. When doing a |
| 130 * direct call from generated code, the return address is placed there by | 130 * direct call from generated code, the return address is placed there by |
| 131 * the calling code, as in a normal exit frame. | 131 * the calling code, as in a normal exit frame. |
| 132 */ | 132 */ |
| 133 | 133 |
| 134 #define __ ACCESS_MASM(masm_) | 134 #define __ ACCESS_MASM(masm_) |
| 135 | 135 |
| 136 RegExpMacroAssemblerA64::RegExpMacroAssemblerA64( | 136 RegExpMacroAssemblerARM64::RegExpMacroAssemblerARM64( |
| 137 Mode mode, | 137 Mode mode, |
| 138 int registers_to_save, | 138 int registers_to_save, |
| 139 Zone* zone) | 139 Zone* zone) |
| 140 : NativeRegExpMacroAssembler(zone), | 140 : NativeRegExpMacroAssembler(zone), |
| 141 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), | 141 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), |
| 142 mode_(mode), | 142 mode_(mode), |
| 143 num_registers_(registers_to_save), | 143 num_registers_(registers_to_save), |
| 144 num_saved_registers_(registers_to_save), | 144 num_saved_registers_(registers_to_save), |
| 145 entry_label_(), | 145 entry_label_(), |
| 146 start_label_(), | 146 start_label_(), |
| 147 success_label_(), | 147 success_label_(), |
| 148 backtrack_label_(), | 148 backtrack_label_(), |
| 149 exit_label_() { | 149 exit_label_() { |
| 150 __ SetStackPointer(csp); | 150 __ SetStackPointer(csp); |
| 151 ASSERT_EQ(0, registers_to_save % 2); | 151 ASSERT_EQ(0, registers_to_save % 2); |
| 152 // We can cache at most 16 W registers in x0-x7. | 152 // We can cache at most 16 W registers in x0-x7. |
| 153 STATIC_ASSERT(kNumCachedRegisters <= 16); | 153 STATIC_ASSERT(kNumCachedRegisters <= 16); |
| 154 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); | 154 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); |
| 155 __ B(&entry_label_); // We'll write the entry code later. | 155 __ B(&entry_label_); // We'll write the entry code later. |
| 156 __ Bind(&start_label_); // And then continue from here. | 156 __ Bind(&start_label_); // And then continue from here. |
| 157 } | 157 } |
| 158 | 158 |
| 159 | 159 |
| 160 RegExpMacroAssemblerA64::~RegExpMacroAssemblerA64() { | 160 RegExpMacroAssemblerARM64::~RegExpMacroAssemblerARM64() { |
| 161 delete masm_; | 161 delete masm_; |
| 162 // Unuse labels in case we throw away the assembler without calling GetCode. | 162 // Unuse labels in case we throw away the assembler without calling GetCode. |
| 163 entry_label_.Unuse(); | 163 entry_label_.Unuse(); |
| 164 start_label_.Unuse(); | 164 start_label_.Unuse(); |
| 165 success_label_.Unuse(); | 165 success_label_.Unuse(); |
| 166 backtrack_label_.Unuse(); | 166 backtrack_label_.Unuse(); |
| 167 exit_label_.Unuse(); | 167 exit_label_.Unuse(); |
| 168 check_preempt_label_.Unuse(); | 168 check_preempt_label_.Unuse(); |
| 169 stack_overflow_label_.Unuse(); | 169 stack_overflow_label_.Unuse(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 int RegExpMacroAssemblerA64::stack_limit_slack() { | 172 int RegExpMacroAssemblerARM64::stack_limit_slack() { |
| 173 return RegExpStack::kStackLimitSlack; | 173 return RegExpStack::kStackLimitSlack; |
| 174 } | 174 } |
| 175 | 175 |
| 176 | 176 |
| 177 void RegExpMacroAssemblerA64::AdvanceCurrentPosition(int by) { | 177 void RegExpMacroAssemblerARM64::AdvanceCurrentPosition(int by) { |
| 178 if (by != 0) { | 178 if (by != 0) { |
| 179 __ Add(current_input_offset(), | 179 __ Add(current_input_offset(), |
| 180 current_input_offset(), by * char_size()); | 180 current_input_offset(), by * char_size()); |
| 181 } | 181 } |
| 182 } | 182 } |
| 183 | 183 |
| 184 | 184 |
| 185 void RegExpMacroAssemblerA64::AdvanceRegister(int reg, int by) { | 185 void RegExpMacroAssemblerARM64::AdvanceRegister(int reg, int by) { |
| 186 ASSERT((reg >= 0) && (reg < num_registers_)); | 186 ASSERT((reg >= 0) && (reg < num_registers_)); |
| 187 if (by != 0) { | 187 if (by != 0) { |
| 188 Register to_advance; | 188 Register to_advance; |
| 189 RegisterState register_state = GetRegisterState(reg); | 189 RegisterState register_state = GetRegisterState(reg); |
| 190 switch (register_state) { | 190 switch (register_state) { |
| 191 case STACKED: | 191 case STACKED: |
| 192 __ Ldr(w10, register_location(reg)); | 192 __ Ldr(w10, register_location(reg)); |
| 193 __ Add(w10, w10, by); | 193 __ Add(w10, w10, by); |
| 194 __ Str(w10, register_location(reg)); | 194 __ Str(w10, register_location(reg)); |
| 195 break; | 195 break; |
| 196 case CACHED_LSW: | 196 case CACHED_LSW: |
| 197 to_advance = GetCachedRegister(reg); | 197 to_advance = GetCachedRegister(reg); |
| 198 __ Add(to_advance, to_advance, by); | 198 __ Add(to_advance, to_advance, by); |
| 199 break; | 199 break; |
| 200 case CACHED_MSW: | 200 case CACHED_MSW: |
| 201 to_advance = GetCachedRegister(reg); | 201 to_advance = GetCachedRegister(reg); |
| 202 __ Add(to_advance, to_advance, | 202 __ Add(to_advance, to_advance, |
| 203 static_cast<int64_t>(by) << kWRegSizeInBits); | 203 static_cast<int64_t>(by) << kWRegSizeInBits); |
| 204 break; | 204 break; |
| 205 default: | 205 default: |
| 206 UNREACHABLE(); | 206 UNREACHABLE(); |
| 207 break; | 207 break; |
| 208 } | 208 } |
| 209 } | 209 } |
| 210 } | 210 } |
| 211 | 211 |
| 212 | 212 |
| 213 void RegExpMacroAssemblerA64::Backtrack() { | 213 void RegExpMacroAssemblerARM64::Backtrack() { |
| 214 CheckPreemption(); | 214 CheckPreemption(); |
| 215 Pop(w10); | 215 Pop(w10); |
| 216 __ Add(x10, code_pointer(), Operand(w10, UXTW)); | 216 __ Add(x10, code_pointer(), Operand(w10, UXTW)); |
| 217 __ Br(x10); | 217 __ Br(x10); |
| 218 } | 218 } |
| 219 | 219 |
| 220 | 220 |
| 221 void RegExpMacroAssemblerA64::Bind(Label* label) { | 221 void RegExpMacroAssemblerARM64::Bind(Label* label) { |
| 222 __ Bind(label); | 222 __ Bind(label); |
| 223 } | 223 } |
| 224 | 224 |
| 225 | 225 |
| 226 void RegExpMacroAssemblerA64::CheckCharacter(uint32_t c, Label* on_equal) { | 226 void RegExpMacroAssemblerARM64::CheckCharacter(uint32_t c, Label* on_equal) { |
| 227 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); | 227 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); |
| 228 } | 228 } |
| 229 | 229 |
| 230 | 230 |
| 231 void RegExpMacroAssemblerA64::CheckCharacterGT(uc16 limit, Label* on_greater) { | 231 void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit, |
| 232 Label* on_greater) { |
| 232 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); | 233 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); |
| 233 } | 234 } |
| 234 | 235 |
| 235 | 236 |
| 236 void RegExpMacroAssemblerA64::CheckAtStart(Label* on_at_start) { | 237 void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) { |
| 237 Label not_at_start; | 238 Label not_at_start; |
| 238 // Did we start the match at the start of the input string? | 239 // Did we start the match at the start of the input string? |
| 239 CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start); | 240 CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start); |
| 240 // If we did, are we still at the start of the input string? | 241 // If we did, are we still at the start of the input string? |
| 241 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); | 242 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
| 242 __ Cmp(x10, input_start()); | 243 __ Cmp(x10, input_start()); |
| 243 BranchOrBacktrack(eq, on_at_start); | 244 BranchOrBacktrack(eq, on_at_start); |
| 244 __ Bind(¬_at_start); | 245 __ Bind(¬_at_start); |
| 245 } | 246 } |
| 246 | 247 |
| 247 | 248 |
| 248 void RegExpMacroAssemblerA64::CheckNotAtStart(Label* on_not_at_start) { | 249 void RegExpMacroAssemblerARM64::CheckNotAtStart(Label* on_not_at_start) { |
| 249 // Did we start the match at the start of the input string? | 250 // Did we start the match at the start of the input string? |
| 250 CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start); | 251 CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start); |
| 251 // If we did, are we still at the start of the input string? | 252 // If we did, are we still at the start of the input string? |
| 252 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); | 253 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
| 253 __ Cmp(x10, input_start()); | 254 __ Cmp(x10, input_start()); |
| 254 BranchOrBacktrack(ne, on_not_at_start); | 255 BranchOrBacktrack(ne, on_not_at_start); |
| 255 } | 256 } |
| 256 | 257 |
| 257 | 258 |
| 258 void RegExpMacroAssemblerA64::CheckCharacterLT(uc16 limit, Label* on_less) { | 259 void RegExpMacroAssemblerARM64::CheckCharacterLT(uc16 limit, Label* on_less) { |
| 259 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); | 260 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); |
| 260 } | 261 } |
| 261 | 262 |
| 262 | 263 |
| 263 void RegExpMacroAssemblerA64::CheckCharacters(Vector<const uc16> str, | 264 void RegExpMacroAssemblerARM64::CheckCharacters(Vector<const uc16> str, |
| 264 int cp_offset, | 265 int cp_offset, |
| 265 Label* on_failure, | 266 Label* on_failure, |
| 266 bool check_end_of_string) { | 267 bool check_end_of_string) { |
| 267 // This method is only ever called from the cctests. | 268 // This method is only ever called from the cctests. |
| 268 | 269 |
| 269 if (check_end_of_string) { | 270 if (check_end_of_string) { |
| 270 // Is last character of required match inside string. | 271 // Is last character of required match inside string. |
| 271 CheckPosition(cp_offset + str.length() - 1, on_failure); | 272 CheckPosition(cp_offset + str.length() - 1, on_failure); |
| 272 } | 273 } |
| 273 | 274 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 285 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); | 286 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); |
| 286 ASSERT(str[i] <= String::kMaxOneByteCharCode); | 287 ASSERT(str[i] <= String::kMaxOneByteCharCode); |
| 287 } else { | 288 } else { |
| 288 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); | 289 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); |
| 289 } | 290 } |
| 290 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); | 291 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); |
| 291 } | 292 } |
| 292 } | 293 } |
| 293 | 294 |
| 294 | 295 |
| 295 void RegExpMacroAssemblerA64::CheckGreedyLoop(Label* on_equal) { | 296 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { |
| 296 __ Ldr(w10, MemOperand(backtrack_stackpointer())); | 297 __ Ldr(w10, MemOperand(backtrack_stackpointer())); |
| 297 __ Cmp(current_input_offset(), w10); | 298 __ Cmp(current_input_offset(), w10); |
| 298 __ Cset(x11, eq); | 299 __ Cset(x11, eq); |
| 299 __ Add(backtrack_stackpointer(), | 300 __ Add(backtrack_stackpointer(), |
| 300 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); | 301 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); |
| 301 BranchOrBacktrack(eq, on_equal); | 302 BranchOrBacktrack(eq, on_equal); |
| 302 } | 303 } |
| 303 | 304 |
| 304 void RegExpMacroAssemblerA64::CheckNotBackReferenceIgnoreCase( | 305 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( |
| 305 int start_reg, | 306 int start_reg, |
| 306 Label* on_no_match) { | 307 Label* on_no_match) { |
| 307 Label fallthrough; | 308 Label fallthrough; |
| 308 | 309 |
| 309 Register capture_start_offset = w10; | 310 Register capture_start_offset = w10; |
| 310 // Save the capture length in a callee-saved register so it will | 311 // Save the capture length in a callee-saved register so it will |
| 311 // be preserved if we call a C helper. | 312 // be preserved if we call a C helper. |
| 312 Register capture_length = w19; | 313 Register capture_length = w19; |
| 313 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); | 314 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); |
| 314 | 315 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 CompareAndBranchOrBacktrack(x0, 0, eq, on_no_match); | 422 CompareAndBranchOrBacktrack(x0, 0, eq, on_no_match); |
| 422 // On success, increment position by length of capture. | 423 // On success, increment position by length of capture. |
| 423 __ Add(current_input_offset(), current_input_offset(), capture_length); | 424 __ Add(current_input_offset(), current_input_offset(), capture_length); |
| 424 // Reset the cached registers. | 425 // Reset the cached registers. |
| 425 __ PopCPURegList(cached_registers); | 426 __ PopCPURegList(cached_registers); |
| 426 } | 427 } |
| 427 | 428 |
| 428 __ Bind(&fallthrough); | 429 __ Bind(&fallthrough); |
| 429 } | 430 } |
| 430 | 431 |
| 431 void RegExpMacroAssemblerA64::CheckNotBackReference( | 432 void RegExpMacroAssemblerARM64::CheckNotBackReference( |
| 432 int start_reg, | 433 int start_reg, |
| 433 Label* on_no_match) { | 434 Label* on_no_match) { |
| 434 Label fallthrough; | 435 Label fallthrough; |
| 435 | 436 |
| 436 Register capture_start_address = x12; | 437 Register capture_start_address = x12; |
| 437 Register capture_end_address = x13; | 438 Register capture_end_address = x13; |
| 438 Register current_position_address = x14; | 439 Register current_position_address = x14; |
| 439 Register capture_length = w15; | 440 Register capture_length = w15; |
| 440 | 441 |
| 441 // Find length of back-referenced capture. | 442 // Find length of back-referenced capture. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 if (masm_->emit_debug_code()) { | 484 if (masm_->emit_debug_code()) { |
| 484 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 485 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
| 485 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 486 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
| 486 // The current input offset should be <= 0, and fit in a W register. | 487 // The current input offset should be <= 0, and fit in a W register. |
| 487 __ Check(le, kOffsetOutOfRange); | 488 __ Check(le, kOffsetOutOfRange); |
| 488 } | 489 } |
| 489 __ Bind(&fallthrough); | 490 __ Bind(&fallthrough); |
| 490 } | 491 } |
| 491 | 492 |
| 492 | 493 |
| 493 void RegExpMacroAssemblerA64::CheckNotCharacter(unsigned c, | 494 void RegExpMacroAssemblerARM64::CheckNotCharacter(unsigned c, |
| 494 Label* on_not_equal) { | 495 Label* on_not_equal) { |
| 495 CompareAndBranchOrBacktrack(current_character(), c, ne, on_not_equal); | 496 CompareAndBranchOrBacktrack(current_character(), c, ne, on_not_equal); |
| 496 } | 497 } |
| 497 | 498 |
| 498 | 499 |
| 499 void RegExpMacroAssemblerA64::CheckCharacterAfterAnd(uint32_t c, | 500 void RegExpMacroAssemblerARM64::CheckCharacterAfterAnd(uint32_t c, |
| 500 uint32_t mask, | 501 uint32_t mask, |
| 501 Label* on_equal) { | 502 Label* on_equal) { |
| 502 __ And(w10, current_character(), mask); | 503 __ And(w10, current_character(), mask); |
| 503 CompareAndBranchOrBacktrack(w10, c, eq, on_equal); | 504 CompareAndBranchOrBacktrack(w10, c, eq, on_equal); |
| 504 } | 505 } |
| 505 | 506 |
| 506 | 507 |
| 507 void RegExpMacroAssemblerA64::CheckNotCharacterAfterAnd(unsigned c, | 508 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterAnd(unsigned c, |
| 508 unsigned mask, | 509 unsigned mask, |
| 509 Label* on_not_equal) { | 510 Label* on_not_equal) { |
| 510 __ And(w10, current_character(), mask); | 511 __ And(w10, current_character(), mask); |
| 511 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 512 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
| 512 } | 513 } |
| 513 | 514 |
| 514 | 515 |
| 515 void RegExpMacroAssemblerA64::CheckNotCharacterAfterMinusAnd( | 516 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd( |
| 516 uc16 c, | 517 uc16 c, |
| 517 uc16 minus, | 518 uc16 minus, |
| 518 uc16 mask, | 519 uc16 mask, |
| 519 Label* on_not_equal) { | 520 Label* on_not_equal) { |
| 520 ASSERT(minus < String::kMaxUtf16CodeUnit); | 521 ASSERT(minus < String::kMaxUtf16CodeUnit); |
| 521 __ Sub(w10, current_character(), minus); | 522 __ Sub(w10, current_character(), minus); |
| 522 __ And(w10, w10, mask); | 523 __ And(w10, w10, mask); |
| 523 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 524 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
| 524 } | 525 } |
| 525 | 526 |
| 526 | 527 |
| 527 void RegExpMacroAssemblerA64::CheckCharacterInRange( | 528 void RegExpMacroAssemblerARM64::CheckCharacterInRange( |
| 528 uc16 from, | 529 uc16 from, |
| 529 uc16 to, | 530 uc16 to, |
| 530 Label* on_in_range) { | 531 Label* on_in_range) { |
| 531 __ Sub(w10, current_character(), from); | 532 __ Sub(w10, current_character(), from); |
| 532 // Unsigned lower-or-same condition. | 533 // Unsigned lower-or-same condition. |
| 533 CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range); | 534 CompareAndBranchOrBacktrack(w10, to - from, ls, on_in_range); |
| 534 } | 535 } |
| 535 | 536 |
| 536 | 537 |
| 537 void RegExpMacroAssemblerA64::CheckCharacterNotInRange( | 538 void RegExpMacroAssemblerARM64::CheckCharacterNotInRange( |
| 538 uc16 from, | 539 uc16 from, |
| 539 uc16 to, | 540 uc16 to, |
| 540 Label* on_not_in_range) { | 541 Label* on_not_in_range) { |
| 541 __ Sub(w10, current_character(), from); | 542 __ Sub(w10, current_character(), from); |
| 542 // Unsigned higher condition. | 543 // Unsigned higher condition. |
| 543 CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range); | 544 CompareAndBranchOrBacktrack(w10, to - from, hi, on_not_in_range); |
| 544 } | 545 } |
| 545 | 546 |
| 546 | 547 |
| 547 void RegExpMacroAssemblerA64::CheckBitInTable( | 548 void RegExpMacroAssemblerARM64::CheckBitInTable( |
| 548 Handle<ByteArray> table, | 549 Handle<ByteArray> table, |
| 549 Label* on_bit_set) { | 550 Label* on_bit_set) { |
| 550 __ Mov(x11, Operand(table)); | 551 __ Mov(x11, Operand(table)); |
| 551 if ((mode_ != ASCII) || (kTableMask != String::kMaxOneByteCharCode)) { | 552 if ((mode_ != ASCII) || (kTableMask != String::kMaxOneByteCharCode)) { |
| 552 __ And(w10, current_character(), kTableMask); | 553 __ And(w10, current_character(), kTableMask); |
| 553 __ Add(w10, w10, ByteArray::kHeaderSize - kHeapObjectTag); | 554 __ Add(w10, w10, ByteArray::kHeaderSize - kHeapObjectTag); |
| 554 } else { | 555 } else { |
| 555 __ Add(w10, current_character(), ByteArray::kHeaderSize - kHeapObjectTag); | 556 __ Add(w10, current_character(), ByteArray::kHeaderSize - kHeapObjectTag); |
| 556 } | 557 } |
| 557 __ Ldrb(w11, MemOperand(x11, w10, UXTW)); | 558 __ Ldrb(w11, MemOperand(x11, w10, UXTW)); |
| 558 CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set); | 559 CompareAndBranchOrBacktrack(w11, 0, ne, on_bit_set); |
| 559 } | 560 } |
| 560 | 561 |
| 561 | 562 |
| 562 bool RegExpMacroAssemblerA64::CheckSpecialCharacterClass(uc16 type, | 563 bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(uc16 type, |
| 563 Label* on_no_match) { | 564 Label* on_no_match) { |
| 564 // Range checks (c in min..max) are generally implemented by an unsigned | 565 // Range checks (c in min..max) are generally implemented by an unsigned |
| 565 // (c - min) <= (max - min) check | 566 // (c - min) <= (max - min) check |
| 566 switch (type) { | 567 switch (type) { |
| 567 case 's': | 568 case 's': |
| 568 // Match space-characters | 569 // Match space-characters |
| 569 if (mode_ == ASCII) { | 570 if (mode_ == ASCII) { |
| 570 // One byte space characters are '\t'..'\r', ' ' and \u00a0. | 571 // One byte space characters are '\t'..'\r', ' ' and \u00a0. |
| 571 Label success; | 572 Label success; |
| 572 // Check for ' ' or 0x00a0. | 573 // Check for ' ' or 0x00a0. |
| 573 __ Cmp(current_character(), ' '); | 574 __ Cmp(current_character(), ' '); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 case '*': | 657 case '*': |
| 657 // Match any character. | 658 // Match any character. |
| 658 return true; | 659 return true; |
| 659 // No custom implementation (yet): s(UC16), S(UC16). | 660 // No custom implementation (yet): s(UC16), S(UC16). |
| 660 default: | 661 default: |
| 661 return false; | 662 return false; |
| 662 } | 663 } |
| 663 } | 664 } |
| 664 | 665 |
| 665 | 666 |
| 666 void RegExpMacroAssemblerA64::Fail() { | 667 void RegExpMacroAssemblerARM64::Fail() { |
| 667 __ Mov(w0, FAILURE); | 668 __ Mov(w0, FAILURE); |
| 668 __ B(&exit_label_); | 669 __ B(&exit_label_); |
| 669 } | 670 } |
| 670 | 671 |
| 671 | 672 |
| 672 Handle<HeapObject> RegExpMacroAssemblerA64::GetCode(Handle<String> source) { | 673 Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) { |
| 673 Label return_w0; | 674 Label return_w0; |
| 674 // Finalize code - write the entry point code now we know how many | 675 // Finalize code - write the entry point code now we know how many |
| 675 // registers we need. | 676 // registers we need. |
| 676 | 677 |
| 677 // Entry code: | 678 // Entry code: |
| 678 __ Bind(&entry_label_); | 679 __ Bind(&entry_label_); |
| 679 | 680 |
| 680 // Arguments on entry: | 681 // Arguments on entry: |
| 681 // x0: String* input | 682 // x0: String* input |
| 682 // x1: int start_offset | 683 // x1: int start_offset |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 | 1059 |
| 1059 CodeDesc code_desc; | 1060 CodeDesc code_desc; |
| 1060 masm_->GetCode(&code_desc); | 1061 masm_->GetCode(&code_desc); |
| 1061 Handle<Code> code = isolate()->factory()->NewCode( | 1062 Handle<Code> code = isolate()->factory()->NewCode( |
| 1062 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); | 1063 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); |
| 1063 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); | 1064 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); |
| 1064 return Handle<HeapObject>::cast(code); | 1065 return Handle<HeapObject>::cast(code); |
| 1065 } | 1066 } |
| 1066 | 1067 |
| 1067 | 1068 |
| 1068 void RegExpMacroAssemblerA64::GoTo(Label* to) { | 1069 void RegExpMacroAssemblerARM64::GoTo(Label* to) { |
| 1069 BranchOrBacktrack(al, to); | 1070 BranchOrBacktrack(al, to); |
| 1070 } | 1071 } |
| 1071 | 1072 |
| 1072 void RegExpMacroAssemblerA64::IfRegisterGE(int reg, | 1073 void RegExpMacroAssemblerARM64::IfRegisterGE(int reg, int comparand, |
| 1073 int comparand, | 1074 Label* if_ge) { |
| 1074 Label* if_ge) { | |
| 1075 Register to_compare = GetRegister(reg, w10); | 1075 Register to_compare = GetRegister(reg, w10); |
| 1076 CompareAndBranchOrBacktrack(to_compare, comparand, ge, if_ge); | 1076 CompareAndBranchOrBacktrack(to_compare, comparand, ge, if_ge); |
| 1077 } | 1077 } |
| 1078 | 1078 |
| 1079 | 1079 |
| 1080 void RegExpMacroAssemblerA64::IfRegisterLT(int reg, | 1080 void RegExpMacroAssemblerARM64::IfRegisterLT(int reg, int comparand, |
| 1081 int comparand, | 1081 Label* if_lt) { |
| 1082 Label* if_lt) { | |
| 1083 Register to_compare = GetRegister(reg, w10); | 1082 Register to_compare = GetRegister(reg, w10); |
| 1084 CompareAndBranchOrBacktrack(to_compare, comparand, lt, if_lt); | 1083 CompareAndBranchOrBacktrack(to_compare, comparand, lt, if_lt); |
| 1085 } | 1084 } |
| 1086 | 1085 |
| 1087 | 1086 |
| 1088 void RegExpMacroAssemblerA64::IfRegisterEqPos(int reg, | 1087 void RegExpMacroAssemblerARM64::IfRegisterEqPos(int reg, Label* if_eq) { |
| 1089 Label* if_eq) { | |
| 1090 Register to_compare = GetRegister(reg, w10); | 1088 Register to_compare = GetRegister(reg, w10); |
| 1091 __ Cmp(to_compare, current_input_offset()); | 1089 __ Cmp(to_compare, current_input_offset()); |
| 1092 BranchOrBacktrack(eq, if_eq); | 1090 BranchOrBacktrack(eq, if_eq); |
| 1093 } | 1091 } |
| 1094 | 1092 |
| 1095 RegExpMacroAssembler::IrregexpImplementation | 1093 RegExpMacroAssembler::IrregexpImplementation |
| 1096 RegExpMacroAssemblerA64::Implementation() { | 1094 RegExpMacroAssemblerARM64::Implementation() { |
| 1097 return kA64Implementation; | 1095 return kARM64Implementation; |
| 1098 } | 1096 } |
| 1099 | 1097 |
| 1100 | 1098 |
| 1101 void RegExpMacroAssemblerA64::LoadCurrentCharacter(int cp_offset, | 1099 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, |
| 1102 Label* on_end_of_input, | 1100 Label* on_end_of_input, |
| 1103 bool check_bounds, | 1101 bool check_bounds, |
| 1104 int characters) { | 1102 int characters) { |
| 1105 // TODO(pielan): Make sure long strings are caught before this, and not | 1103 // TODO(pielan): Make sure long strings are caught before this, and not |
| 1106 // just asserted in debug mode. | 1104 // just asserted in debug mode. |
| 1107 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. | 1105 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. |
| 1108 // Be sane! (And ensure that an int32_t can be used to index the string) | 1106 // Be sane! (And ensure that an int32_t can be used to index the string) |
| 1109 ASSERT(cp_offset < (1<<30)); | 1107 ASSERT(cp_offset < (1<<30)); |
| 1110 if (check_bounds) { | 1108 if (check_bounds) { |
| 1111 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1109 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 1112 } | 1110 } |
| 1113 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1111 LoadCurrentCharacterUnchecked(cp_offset, characters); |
| 1114 } | 1112 } |
| 1115 | 1113 |
| 1116 | 1114 |
| 1117 void RegExpMacroAssemblerA64::PopCurrentPosition() { | 1115 void RegExpMacroAssemblerARM64::PopCurrentPosition() { |
| 1118 Pop(current_input_offset()); | 1116 Pop(current_input_offset()); |
| 1119 } | 1117 } |
| 1120 | 1118 |
| 1121 | 1119 |
| 1122 void RegExpMacroAssemblerA64::PopRegister(int register_index) { | 1120 void RegExpMacroAssemblerARM64::PopRegister(int register_index) { |
| 1123 Pop(w10); | 1121 Pop(w10); |
| 1124 StoreRegister(register_index, w10); | 1122 StoreRegister(register_index, w10); |
| 1125 } | 1123 } |
| 1126 | 1124 |
| 1127 | 1125 |
| 1128 void RegExpMacroAssemblerA64::PushBacktrack(Label* label) { | 1126 void RegExpMacroAssemblerARM64::PushBacktrack(Label* label) { |
| 1129 if (label->is_bound()) { | 1127 if (label->is_bound()) { |
| 1130 int target = label->pos(); | 1128 int target = label->pos(); |
| 1131 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); | 1129 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); |
| 1132 } else { | 1130 } else { |
| 1133 __ Adr(x10, label); | 1131 __ Adr(x10, label); |
| 1134 __ Sub(x10, x10, code_pointer()); | 1132 __ Sub(x10, x10, code_pointer()); |
| 1135 if (masm_->emit_debug_code()) { | 1133 if (masm_->emit_debug_code()) { |
| 1136 __ Cmp(x10, kWRegMask); | 1134 __ Cmp(x10, kWRegMask); |
| 1137 // The code offset has to fit in a W register. | 1135 // The code offset has to fit in a W register. |
| 1138 __ Check(ls, kOffsetOutOfRange); | 1136 __ Check(ls, kOffsetOutOfRange); |
| 1139 } | 1137 } |
| 1140 } | 1138 } |
| 1141 Push(w10); | 1139 Push(w10); |
| 1142 CheckStackLimit(); | 1140 CheckStackLimit(); |
| 1143 } | 1141 } |
| 1144 | 1142 |
| 1145 | 1143 |
| 1146 void RegExpMacroAssemblerA64::PushCurrentPosition() { | 1144 void RegExpMacroAssemblerARM64::PushCurrentPosition() { |
| 1147 Push(current_input_offset()); | 1145 Push(current_input_offset()); |
| 1148 } | 1146 } |
| 1149 | 1147 |
| 1150 | 1148 |
| 1151 void RegExpMacroAssemblerA64::PushRegister(int register_index, | 1149 void RegExpMacroAssemblerARM64::PushRegister(int register_index, |
| 1152 StackCheckFlag check_stack_limit) { | 1150 StackCheckFlag check_stack_limit) { |
| 1153 Register to_push = GetRegister(register_index, w10); | 1151 Register to_push = GetRegister(register_index, w10); |
| 1154 Push(to_push); | 1152 Push(to_push); |
| 1155 if (check_stack_limit) CheckStackLimit(); | 1153 if (check_stack_limit) CheckStackLimit(); |
| 1156 } | 1154 } |
| 1157 | 1155 |
| 1158 | 1156 |
| 1159 void RegExpMacroAssemblerA64::ReadCurrentPositionFromRegister(int reg) { | 1157 void RegExpMacroAssemblerARM64::ReadCurrentPositionFromRegister(int reg) { |
| 1160 Register cached_register; | 1158 Register cached_register; |
| 1161 RegisterState register_state = GetRegisterState(reg); | 1159 RegisterState register_state = GetRegisterState(reg); |
| 1162 switch (register_state) { | 1160 switch (register_state) { |
| 1163 case STACKED: | 1161 case STACKED: |
| 1164 __ Ldr(current_input_offset(), register_location(reg)); | 1162 __ Ldr(current_input_offset(), register_location(reg)); |
| 1165 break; | 1163 break; |
| 1166 case CACHED_LSW: | 1164 case CACHED_LSW: |
| 1167 cached_register = GetCachedRegister(reg); | 1165 cached_register = GetCachedRegister(reg); |
| 1168 __ Mov(current_input_offset(), cached_register.W()); | 1166 __ Mov(current_input_offset(), cached_register.W()); |
| 1169 break; | 1167 break; |
| 1170 case CACHED_MSW: | 1168 case CACHED_MSW: |
| 1171 cached_register = GetCachedRegister(reg); | 1169 cached_register = GetCachedRegister(reg); |
| 1172 __ Lsr(current_input_offset().X(), cached_register, kWRegSizeInBits); | 1170 __ Lsr(current_input_offset().X(), cached_register, kWRegSizeInBits); |
| 1173 break; | 1171 break; |
| 1174 default: | 1172 default: |
| 1175 UNREACHABLE(); | 1173 UNREACHABLE(); |
| 1176 break; | 1174 break; |
| 1177 } | 1175 } |
| 1178 } | 1176 } |
| 1179 | 1177 |
| 1180 | 1178 |
| 1181 void RegExpMacroAssemblerA64::ReadStackPointerFromRegister(int reg) { | 1179 void RegExpMacroAssemblerARM64::ReadStackPointerFromRegister(int reg) { |
| 1182 Register read_from = GetRegister(reg, w10); | 1180 Register read_from = GetRegister(reg, w10); |
| 1183 __ Ldr(x11, MemOperand(frame_pointer(), kStackBase)); | 1181 __ Ldr(x11, MemOperand(frame_pointer(), kStackBase)); |
| 1184 __ Add(backtrack_stackpointer(), x11, Operand(read_from, SXTW)); | 1182 __ Add(backtrack_stackpointer(), x11, Operand(read_from, SXTW)); |
| 1185 } | 1183 } |
| 1186 | 1184 |
| 1187 | 1185 |
| 1188 void RegExpMacroAssemblerA64::SetCurrentPositionFromEnd(int by) { | 1186 void RegExpMacroAssemblerARM64::SetCurrentPositionFromEnd(int by) { |
| 1189 Label after_position; | 1187 Label after_position; |
| 1190 __ Cmp(current_input_offset(), -by * char_size()); | 1188 __ Cmp(current_input_offset(), -by * char_size()); |
| 1191 __ B(ge, &after_position); | 1189 __ B(ge, &after_position); |
| 1192 __ Mov(current_input_offset(), -by * char_size()); | 1190 __ Mov(current_input_offset(), -by * char_size()); |
| 1193 // On RegExp code entry (where this operation is used), the character before | 1191 // On RegExp code entry (where this operation is used), the character before |
| 1194 // the current position is expected to be already loaded. | 1192 // the current position is expected to be already loaded. |
| 1195 // We have advanced the position, so it's safe to read backwards. | 1193 // We have advanced the position, so it's safe to read backwards. |
| 1196 LoadCurrentCharacterUnchecked(-1, 1); | 1194 LoadCurrentCharacterUnchecked(-1, 1); |
| 1197 __ Bind(&after_position); | 1195 __ Bind(&after_position); |
| 1198 } | 1196 } |
| 1199 | 1197 |
| 1200 | 1198 |
| 1201 void RegExpMacroAssemblerA64::SetRegister(int register_index, int to) { | 1199 void RegExpMacroAssemblerARM64::SetRegister(int register_index, int to) { |
| 1202 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | 1200 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! |
| 1203 Register set_to = wzr; | 1201 Register set_to = wzr; |
| 1204 if (to != 0) { | 1202 if (to != 0) { |
| 1205 set_to = w10; | 1203 set_to = w10; |
| 1206 __ Mov(set_to, to); | 1204 __ Mov(set_to, to); |
| 1207 } | 1205 } |
| 1208 StoreRegister(register_index, set_to); | 1206 StoreRegister(register_index, set_to); |
| 1209 } | 1207 } |
| 1210 | 1208 |
| 1211 | 1209 |
| 1212 bool RegExpMacroAssemblerA64::Succeed() { | 1210 bool RegExpMacroAssemblerARM64::Succeed() { |
| 1213 __ B(&success_label_); | 1211 __ B(&success_label_); |
| 1214 return global(); | 1212 return global(); |
| 1215 } | 1213 } |
| 1216 | 1214 |
| 1217 | 1215 |
| 1218 void RegExpMacroAssemblerA64::WriteCurrentPositionToRegister(int reg, | 1216 void RegExpMacroAssemblerARM64::WriteCurrentPositionToRegister(int reg, |
| 1219 int cp_offset) { | 1217 int cp_offset) { |
| 1220 Register position = current_input_offset(); | 1218 Register position = current_input_offset(); |
| 1221 if (cp_offset != 0) { | 1219 if (cp_offset != 0) { |
| 1222 position = w10; | 1220 position = w10; |
| 1223 __ Add(position, current_input_offset(), cp_offset * char_size()); | 1221 __ Add(position, current_input_offset(), cp_offset * char_size()); |
| 1224 } | 1222 } |
| 1225 StoreRegister(reg, position); | 1223 StoreRegister(reg, position); |
| 1226 } | 1224 } |
| 1227 | 1225 |
| 1228 | 1226 |
| 1229 void RegExpMacroAssemblerA64::ClearRegisters(int reg_from, int reg_to) { | 1227 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { |
| 1230 ASSERT(reg_from <= reg_to); | 1228 ASSERT(reg_from <= reg_to); |
| 1231 int num_registers = reg_to - reg_from + 1; | 1229 int num_registers = reg_to - reg_from + 1; |
| 1232 | 1230 |
| 1233 // If the first capture register is cached in a hardware register but not | 1231 // If the first capture register is cached in a hardware register but not |
| 1234 // aligned on a 64-bit one, we need to clear the first one specifically. | 1232 // aligned on a 64-bit one, we need to clear the first one specifically. |
| 1235 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { | 1233 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { |
| 1236 StoreRegister(reg_from, non_position_value()); | 1234 StoreRegister(reg_from, non_position_value()); |
| 1237 num_registers--; | 1235 num_registers--; |
| 1238 reg_from++; | 1236 reg_from++; |
| 1239 } | 1237 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1280 for (int i = reg_from; i <= reg_to; i += 2) { | 1278 for (int i = reg_from; i <= reg_to; i += 2) { |
| 1281 __ Str(twice_non_position_value(), | 1279 __ Str(twice_non_position_value(), |
| 1282 MemOperand(frame_pointer(), base_offset)); | 1280 MemOperand(frame_pointer(), base_offset)); |
| 1283 base_offset -= kWRegSize * 2; | 1281 base_offset -= kWRegSize * 2; |
| 1284 } | 1282 } |
| 1285 } | 1283 } |
| 1286 } | 1284 } |
| 1287 } | 1285 } |
| 1288 | 1286 |
| 1289 | 1287 |
| 1290 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { | 1288 void RegExpMacroAssemblerARM64::WriteStackPointerToRegister(int reg) { |
| 1291 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); | 1289 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); |
| 1292 __ Sub(x10, backtrack_stackpointer(), x10); | 1290 __ Sub(x10, backtrack_stackpointer(), x10); |
| 1293 if (masm_->emit_debug_code()) { | 1291 if (masm_->emit_debug_code()) { |
| 1294 __ Cmp(x10, Operand(w10, SXTW)); | 1292 __ Cmp(x10, Operand(w10, SXTW)); |
| 1295 // The stack offset needs to fit in a W register. | 1293 // The stack offset needs to fit in a W register. |
| 1296 __ Check(eq, kOffsetOutOfRange); | 1294 __ Check(eq, kOffsetOutOfRange); |
| 1297 } | 1295 } |
| 1298 StoreRegister(reg, w10); | 1296 StoreRegister(reg, w10); |
| 1299 } | 1297 } |
| 1300 | 1298 |
| 1301 | 1299 |
| 1302 // Helper function for reading a value out of a stack frame. | 1300 // Helper function for reading a value out of a stack frame. |
| 1303 template <typename T> | 1301 template <typename T> |
| 1304 static T& frame_entry(Address re_frame, int frame_offset) { | 1302 static T& frame_entry(Address re_frame, int frame_offset) { |
| 1305 return *reinterpret_cast<T*>(re_frame + frame_offset); | 1303 return *reinterpret_cast<T*>(re_frame + frame_offset); |
| 1306 } | 1304 } |
| 1307 | 1305 |
| 1308 | 1306 |
| 1309 int RegExpMacroAssemblerA64::CheckStackGuardState(Address* return_address, | 1307 int RegExpMacroAssemblerARM64::CheckStackGuardState(Address* return_address, |
| 1310 Code* re_code, | 1308 Code* re_code, |
| 1311 Address re_frame, | 1309 Address re_frame, |
| 1312 int start_offset, | 1310 int start_offset, |
| 1313 const byte** input_start, | 1311 const byte** input_start, |
| 1314 const byte** input_end) { | 1312 const byte** input_end) { |
| 1315 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); | 1313 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); |
| 1316 if (isolate->stack_guard()->IsStackOverflow()) { | 1314 if (isolate->stack_guard()->IsStackOverflow()) { |
| 1317 isolate->StackOverflow(); | 1315 isolate->StackOverflow(); |
| 1318 return EXCEPTION; | 1316 return EXCEPTION; |
| 1319 } | 1317 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1399 // Subject string might have been a ConsString that underwent | 1397 // Subject string might have been a ConsString that underwent |
| 1400 // short-circuiting during GC. That will not change start_address but | 1398 // short-circuiting during GC. That will not change start_address but |
| 1401 // will change pointer inside the subject handle. | 1399 // will change pointer inside the subject handle. |
| 1402 frame_entry<const String*>(re_frame, kInput) = *subject; | 1400 frame_entry<const String*>(re_frame, kInput) = *subject; |
| 1403 } | 1401 } |
| 1404 | 1402 |
| 1405 return 0; | 1403 return 0; |
| 1406 } | 1404 } |
| 1407 | 1405 |
| 1408 | 1406 |
| 1409 void RegExpMacroAssemblerA64::CheckPosition(int cp_offset, | 1407 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, |
| 1410 Label* on_outside_input) { | 1408 Label* on_outside_input) { |
| 1411 CompareAndBranchOrBacktrack(current_input_offset(), | 1409 CompareAndBranchOrBacktrack(current_input_offset(), |
| 1412 -cp_offset * char_size(), | 1410 -cp_offset * char_size(), |
| 1413 ge, | 1411 ge, |
| 1414 on_outside_input); | 1412 on_outside_input); |
| 1415 } | 1413 } |
| 1416 | 1414 |
| 1417 | 1415 |
| 1418 bool RegExpMacroAssemblerA64::CanReadUnaligned() { | 1416 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { |
| 1419 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1417 // TODO(pielan): See whether or not we should disable unaligned accesses. |
| 1420 return !slow_safe(); | 1418 return !slow_safe(); |
| 1421 } | 1419 } |
| 1422 | 1420 |
| 1423 | 1421 |
| 1424 // Private methods: | 1422 // Private methods: |
| 1425 | 1423 |
| 1426 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { | 1424 void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) { |
| 1427 // Allocate space on the stack to store the return address. The | 1425 // Allocate space on the stack to store the return address. The |
| 1428 // CheckStackGuardState C++ function will override it if the code | 1426 // CheckStackGuardState C++ function will override it if the code |
| 1429 // moved. Allocate extra space for 2 arguments passed by pointers. | 1427 // moved. Allocate extra space for 2 arguments passed by pointers. |
| 1430 // AAPCS64 requires the stack to be 16 byte aligned. | 1428 // AAPCS64 requires the stack to be 16 byte aligned. |
| 1431 int alignment = masm_->ActivationFrameAlignment(); | 1429 int alignment = masm_->ActivationFrameAlignment(); |
| 1432 ASSERT_EQ(alignment % 16, 0); | 1430 ASSERT_EQ(alignment % 16, 0); |
| 1433 int align_mask = (alignment / kXRegSize) - 1; | 1431 int align_mask = (alignment / kXRegSize) - 1; |
| 1434 int xreg_to_claim = (3 + align_mask) & ~align_mask; | 1432 int xreg_to_claim = (3 + align_mask) & ~align_mask; |
| 1435 | 1433 |
| 1436 ASSERT(csp.Is(__ StackPointer())); | 1434 ASSERT(csp.Is(__ StackPointer())); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1463 __ Peek(input_start(), kPointerSize); | 1461 __ Peek(input_start(), kPointerSize); |
| 1464 __ Peek(input_end(), 2 * kPointerSize); | 1462 __ Peek(input_end(), 2 * kPointerSize); |
| 1465 | 1463 |
| 1466 ASSERT(csp.Is(__ StackPointer())); | 1464 ASSERT(csp.Is(__ StackPointer())); |
| 1467 __ Drop(xreg_to_claim); | 1465 __ Drop(xreg_to_claim); |
| 1468 | 1466 |
| 1469 // Reload the Code pointer. | 1467 // Reload the Code pointer. |
| 1470 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 1468 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
| 1471 } | 1469 } |
| 1472 | 1470 |
| 1473 void RegExpMacroAssemblerA64::BranchOrBacktrack(Condition condition, | 1471 void RegExpMacroAssemblerARM64::BranchOrBacktrack(Condition condition, |
| 1474 Label* to) { | 1472 Label* to) { |
| 1475 if (condition == al) { // Unconditional. | 1473 if (condition == al) { // Unconditional. |
| 1476 if (to == NULL) { | 1474 if (to == NULL) { |
| 1477 Backtrack(); | 1475 Backtrack(); |
| 1478 return; | 1476 return; |
| 1479 } | 1477 } |
| 1480 __ B(to); | 1478 __ B(to); |
| 1481 return; | 1479 return; |
| 1482 } | 1480 } |
| 1483 if (to == NULL) { | 1481 if (to == NULL) { |
| 1484 to = &backtrack_label_; | 1482 to = &backtrack_label_; |
| 1485 } | 1483 } |
| 1486 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. | 1484 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. |
| 1487 Condition inverted_condition = InvertCondition(condition); | 1485 Condition inverted_condition = InvertCondition(condition); |
| 1488 Label no_branch; | 1486 Label no_branch; |
| 1489 __ B(inverted_condition, &no_branch); | 1487 __ B(inverted_condition, &no_branch); |
| 1490 __ B(to); | 1488 __ B(to); |
| 1491 __ Bind(&no_branch); | 1489 __ Bind(&no_branch); |
| 1492 } | 1490 } |
| 1493 | 1491 |
| 1494 void RegExpMacroAssemblerA64::CompareAndBranchOrBacktrack(Register reg, | 1492 void RegExpMacroAssemblerARM64::CompareAndBranchOrBacktrack(Register reg, |
| 1495 int immediate, | 1493 int immediate, |
| 1496 Condition condition, | 1494 Condition condition, |
| 1497 Label* to) { | 1495 Label* to) { |
| 1498 if ((immediate == 0) && ((condition == eq) || (condition == ne))) { | 1496 if ((immediate == 0) && ((condition == eq) || (condition == ne))) { |
| 1499 if (to == NULL) { | 1497 if (to == NULL) { |
| 1500 to = &backtrack_label_; | 1498 to = &backtrack_label_; |
| 1501 } | 1499 } |
| 1502 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. | 1500 // TODO(ulan): do direct jump when jump distance is known and fits in imm19. |
| 1503 Label no_branch; | 1501 Label no_branch; |
| 1504 if (condition == eq) { | 1502 if (condition == eq) { |
| 1505 __ Cbnz(reg, &no_branch); | 1503 __ Cbnz(reg, &no_branch); |
| 1506 } else { | 1504 } else { |
| 1507 __ Cbz(reg, &no_branch); | 1505 __ Cbz(reg, &no_branch); |
| 1508 } | 1506 } |
| 1509 __ B(to); | 1507 __ B(to); |
| 1510 __ Bind(&no_branch); | 1508 __ Bind(&no_branch); |
| 1511 } else { | 1509 } else { |
| 1512 __ Cmp(reg, immediate); | 1510 __ Cmp(reg, immediate); |
| 1513 BranchOrBacktrack(condition, to); | 1511 BranchOrBacktrack(condition, to); |
| 1514 } | 1512 } |
| 1515 } | 1513 } |
| 1516 | 1514 |
| 1517 | 1515 |
| 1518 void RegExpMacroAssemblerA64::CheckPreemption() { | 1516 void RegExpMacroAssemblerARM64::CheckPreemption() { |
| 1519 // Check for preemption. | 1517 // Check for preemption. |
| 1520 ExternalReference stack_limit = | 1518 ExternalReference stack_limit = |
| 1521 ExternalReference::address_of_stack_limit(isolate()); | 1519 ExternalReference::address_of_stack_limit(isolate()); |
| 1522 __ Mov(x10, stack_limit); | 1520 __ Mov(x10, stack_limit); |
| 1523 __ Ldr(x10, MemOperand(x10)); | 1521 __ Ldr(x10, MemOperand(x10)); |
| 1524 ASSERT(csp.Is(__ StackPointer())); | 1522 ASSERT(csp.Is(__ StackPointer())); |
| 1525 __ Cmp(csp, x10); | 1523 __ Cmp(csp, x10); |
| 1526 CallIf(&check_preempt_label_, ls); | 1524 CallIf(&check_preempt_label_, ls); |
| 1527 } | 1525 } |
| 1528 | 1526 |
| 1529 | 1527 |
| 1530 void RegExpMacroAssemblerA64::CheckStackLimit() { | 1528 void RegExpMacroAssemblerARM64::CheckStackLimit() { |
| 1531 ExternalReference stack_limit = | 1529 ExternalReference stack_limit = |
| 1532 ExternalReference::address_of_regexp_stack_limit(isolate()); | 1530 ExternalReference::address_of_regexp_stack_limit(isolate()); |
| 1533 __ Mov(x10, stack_limit); | 1531 __ Mov(x10, stack_limit); |
| 1534 __ Ldr(x10, MemOperand(x10)); | 1532 __ Ldr(x10, MemOperand(x10)); |
| 1535 __ Cmp(backtrack_stackpointer(), x10); | 1533 __ Cmp(backtrack_stackpointer(), x10); |
| 1536 CallIf(&stack_overflow_label_, ls); | 1534 CallIf(&stack_overflow_label_, ls); |
| 1537 } | 1535 } |
| 1538 | 1536 |
| 1539 | 1537 |
| 1540 void RegExpMacroAssemblerA64::Push(Register source) { | 1538 void RegExpMacroAssemblerARM64::Push(Register source) { |
| 1541 ASSERT(source.Is32Bits()); | 1539 ASSERT(source.Is32Bits()); |
| 1542 ASSERT(!source.is(backtrack_stackpointer())); | 1540 ASSERT(!source.is(backtrack_stackpointer())); |
| 1543 __ Str(source, | 1541 __ Str(source, |
| 1544 MemOperand(backtrack_stackpointer(), | 1542 MemOperand(backtrack_stackpointer(), |
| 1545 -static_cast<int>(kWRegSize), | 1543 -static_cast<int>(kWRegSize), |
| 1546 PreIndex)); | 1544 PreIndex)); |
| 1547 } | 1545 } |
| 1548 | 1546 |
| 1549 | 1547 |
| 1550 void RegExpMacroAssemblerA64::Pop(Register target) { | 1548 void RegExpMacroAssemblerARM64::Pop(Register target) { |
| 1551 ASSERT(target.Is32Bits()); | 1549 ASSERT(target.Is32Bits()); |
| 1552 ASSERT(!target.is(backtrack_stackpointer())); | 1550 ASSERT(!target.is(backtrack_stackpointer())); |
| 1553 __ Ldr(target, | 1551 __ Ldr(target, |
| 1554 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); | 1552 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); |
| 1555 } | 1553 } |
| 1556 | 1554 |
| 1557 | 1555 |
| 1558 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { | 1556 Register RegExpMacroAssemblerARM64::GetCachedRegister(int register_index) { |
| 1559 ASSERT(register_index < kNumCachedRegisters); | 1557 ASSERT(register_index < kNumCachedRegisters); |
| 1560 return Register::Create(register_index / 2, kXRegSizeInBits); | 1558 return Register::Create(register_index / 2, kXRegSizeInBits); |
| 1561 } | 1559 } |
| 1562 | 1560 |
| 1563 | 1561 |
| 1564 Register RegExpMacroAssemblerA64::GetRegister(int register_index, | 1562 Register RegExpMacroAssemblerARM64::GetRegister(int register_index, |
| 1565 Register maybe_result) { | 1563 Register maybe_result) { |
| 1566 ASSERT(maybe_result.Is32Bits()); | 1564 ASSERT(maybe_result.Is32Bits()); |
| 1567 ASSERT(register_index >= 0); | 1565 ASSERT(register_index >= 0); |
| 1568 if (num_registers_ <= register_index) { | 1566 if (num_registers_ <= register_index) { |
| 1569 num_registers_ = register_index + 1; | 1567 num_registers_ = register_index + 1; |
| 1570 } | 1568 } |
| 1571 Register result; | 1569 Register result; |
| 1572 RegisterState register_state = GetRegisterState(register_index); | 1570 RegisterState register_state = GetRegisterState(register_index); |
| 1573 switch (register_state) { | 1571 switch (register_state) { |
| 1574 case STACKED: | 1572 case STACKED: |
| 1575 __ Ldr(maybe_result, register_location(register_index)); | 1573 __ Ldr(maybe_result, register_location(register_index)); |
| 1576 result = maybe_result; | 1574 result = maybe_result; |
| 1577 break; | 1575 break; |
| 1578 case CACHED_LSW: | 1576 case CACHED_LSW: |
| 1579 result = GetCachedRegister(register_index).W(); | 1577 result = GetCachedRegister(register_index).W(); |
| 1580 break; | 1578 break; |
| 1581 case CACHED_MSW: | 1579 case CACHED_MSW: |
| 1582 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), | 1580 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), |
| 1583 kWRegSizeInBits); | 1581 kWRegSizeInBits); |
| 1584 result = maybe_result; | 1582 result = maybe_result; |
| 1585 break; | 1583 break; |
| 1586 default: | 1584 default: |
| 1587 UNREACHABLE(); | 1585 UNREACHABLE(); |
| 1588 break; | 1586 break; |
| 1589 } | 1587 } |
| 1590 ASSERT(result.Is32Bits()); | 1588 ASSERT(result.Is32Bits()); |
| 1591 return result; | 1589 return result; |
| 1592 } | 1590 } |
| 1593 | 1591 |
| 1594 | 1592 |
| 1595 void RegExpMacroAssemblerA64::StoreRegister(int register_index, | 1593 void RegExpMacroAssemblerARM64::StoreRegister(int register_index, |
| 1596 Register source) { | 1594 Register source) { |
| 1597 ASSERT(source.Is32Bits()); | 1595 ASSERT(source.Is32Bits()); |
| 1598 ASSERT(register_index >= 0); | 1596 ASSERT(register_index >= 0); |
| 1599 if (num_registers_ <= register_index) { | 1597 if (num_registers_ <= register_index) { |
| 1600 num_registers_ = register_index + 1; | 1598 num_registers_ = register_index + 1; |
| 1601 } | 1599 } |
| 1602 | 1600 |
| 1603 Register cached_register; | 1601 Register cached_register; |
| 1604 RegisterState register_state = GetRegisterState(register_index); | 1602 RegisterState register_state = GetRegisterState(register_index); |
| 1605 switch (register_state) { | 1603 switch (register_state) { |
| 1606 case STACKED: | 1604 case STACKED: |
| 1607 __ Str(source, register_location(register_index)); | 1605 __ Str(source, register_location(register_index)); |
| 1608 break; | 1606 break; |
| 1609 case CACHED_LSW: | 1607 case CACHED_LSW: |
| 1610 cached_register = GetCachedRegister(register_index); | 1608 cached_register = GetCachedRegister(register_index); |
| 1611 if (!source.Is(cached_register.W())) { | 1609 if (!source.Is(cached_register.W())) { |
| 1612 __ Bfi(cached_register, source.X(), 0, kWRegSizeInBits); | 1610 __ Bfi(cached_register, source.X(), 0, kWRegSizeInBits); |
| 1613 } | 1611 } |
| 1614 break; | 1612 break; |
| 1615 case CACHED_MSW: | 1613 case CACHED_MSW: |
| 1616 cached_register = GetCachedRegister(register_index); | 1614 cached_register = GetCachedRegister(register_index); |
| 1617 __ Bfi(cached_register, source.X(), kWRegSizeInBits, kWRegSizeInBits); | 1615 __ Bfi(cached_register, source.X(), kWRegSizeInBits, kWRegSizeInBits); |
| 1618 break; | 1616 break; |
| 1619 default: | 1617 default: |
| 1620 UNREACHABLE(); | 1618 UNREACHABLE(); |
| 1621 break; | 1619 break; |
| 1622 } | 1620 } |
| 1623 } | 1621 } |
| 1624 | 1622 |
| 1625 | 1623 |
| 1626 void RegExpMacroAssemblerA64::CallIf(Label* to, Condition condition) { | 1624 void RegExpMacroAssemblerARM64::CallIf(Label* to, Condition condition) { |
| 1627 Label skip_call; | 1625 Label skip_call; |
| 1628 if (condition != al) __ B(&skip_call, InvertCondition(condition)); | 1626 if (condition != al) __ B(&skip_call, InvertCondition(condition)); |
| 1629 __ Bl(to); | 1627 __ Bl(to); |
| 1630 __ Bind(&skip_call); | 1628 __ Bind(&skip_call); |
| 1631 } | 1629 } |
| 1632 | 1630 |
| 1633 | 1631 |
| 1634 void RegExpMacroAssemblerA64::RestoreLinkRegister() { | 1632 void RegExpMacroAssemblerARM64::RestoreLinkRegister() { |
| 1635 ASSERT(csp.Is(__ StackPointer())); | 1633 ASSERT(csp.Is(__ StackPointer())); |
| 1636 __ Pop(lr, xzr); | 1634 __ Pop(lr, xzr); |
| 1637 __ Add(lr, lr, Operand(masm_->CodeObject())); | 1635 __ Add(lr, lr, Operand(masm_->CodeObject())); |
| 1638 } | 1636 } |
| 1639 | 1637 |
| 1640 | 1638 |
| 1641 void RegExpMacroAssemblerA64::SaveLinkRegister() { | 1639 void RegExpMacroAssemblerARM64::SaveLinkRegister() { |
| 1642 ASSERT(csp.Is(__ StackPointer())); | 1640 ASSERT(csp.Is(__ StackPointer())); |
| 1643 __ Sub(lr, lr, Operand(masm_->CodeObject())); | 1641 __ Sub(lr, lr, Operand(masm_->CodeObject())); |
| 1644 __ Push(xzr, lr); | 1642 __ Push(xzr, lr); |
| 1645 } | 1643 } |
| 1646 | 1644 |
| 1647 | 1645 |
| 1648 MemOperand RegExpMacroAssemblerA64::register_location(int register_index) { | 1646 MemOperand RegExpMacroAssemblerARM64::register_location(int register_index) { |
| 1649 ASSERT(register_index < (1<<30)); | 1647 ASSERT(register_index < (1<<30)); |
| 1650 ASSERT(register_index >= kNumCachedRegisters); | 1648 ASSERT(register_index >= kNumCachedRegisters); |
| 1651 if (num_registers_ <= register_index) { | 1649 if (num_registers_ <= register_index) { |
| 1652 num_registers_ = register_index + 1; | 1650 num_registers_ = register_index + 1; |
| 1653 } | 1651 } |
| 1654 register_index -= kNumCachedRegisters; | 1652 register_index -= kNumCachedRegisters; |
| 1655 int offset = kFirstRegisterOnStack - register_index * kWRegSize; | 1653 int offset = kFirstRegisterOnStack - register_index * kWRegSize; |
| 1656 return MemOperand(frame_pointer(), offset); | 1654 return MemOperand(frame_pointer(), offset); |
| 1657 } | 1655 } |
| 1658 | 1656 |
| 1659 MemOperand RegExpMacroAssemblerA64::capture_location(int register_index, | 1657 MemOperand RegExpMacroAssemblerARM64::capture_location(int register_index, |
| 1660 Register scratch) { | 1658 Register scratch) { |
| 1661 ASSERT(register_index < (1<<30)); | 1659 ASSERT(register_index < (1<<30)); |
| 1662 ASSERT(register_index < num_saved_registers_); | 1660 ASSERT(register_index < num_saved_registers_); |
| 1663 ASSERT(register_index >= kNumCachedRegisters); | 1661 ASSERT(register_index >= kNumCachedRegisters); |
| 1664 ASSERT_EQ(register_index % 2, 0); | 1662 ASSERT_EQ(register_index % 2, 0); |
| 1665 register_index -= kNumCachedRegisters; | 1663 register_index -= kNumCachedRegisters; |
| 1666 int offset = kFirstCaptureOnStack - register_index * kWRegSize; | 1664 int offset = kFirstCaptureOnStack - register_index * kWRegSize; |
| 1667 // capture_location is used with Stp instructions to load/store 2 registers. | 1665 // capture_location is used with Stp instructions to load/store 2 registers. |
| 1668 // The immediate field in the encoding is limited to 7 bits (signed). | 1666 // The immediate field in the encoding is limited to 7 bits (signed). |
| 1669 if (is_int7(offset)) { | 1667 if (is_int7(offset)) { |
| 1670 return MemOperand(frame_pointer(), offset); | 1668 return MemOperand(frame_pointer(), offset); |
| 1671 } else { | 1669 } else { |
| 1672 __ Add(scratch, frame_pointer(), offset); | 1670 __ Add(scratch, frame_pointer(), offset); |
| 1673 return MemOperand(scratch); | 1671 return MemOperand(scratch); |
| 1674 } | 1672 } |
| 1675 } | 1673 } |
| 1676 | 1674 |
| 1677 void RegExpMacroAssemblerA64::LoadCurrentCharacterUnchecked(int cp_offset, | 1675 void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(int cp_offset, |
| 1678 int characters) { | 1676 int characters) { |
| 1679 Register offset = current_input_offset(); | 1677 Register offset = current_input_offset(); |
| 1680 | 1678 |
| 1681 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1679 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
| 1682 // and the operating system running on the target allow it. | 1680 // and the operating system running on the target allow it. |
| 1683 // If unaligned load/stores are not supported then this function must only | 1681 // If unaligned load/stores are not supported then this function must only |
| 1684 // be used to load a single character at a time. | 1682 // be used to load a single character at a time. |
| 1685 | 1683 |
| 1686 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to | 1684 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to |
| 1687 // disable it. | 1685 // disable it. |
| 1688 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1686 // TODO(pielan): See whether or not we should disable unaligned accesses. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1720 ASSERT(characters == 1); | 1718 ASSERT(characters == 1); |
| 1721 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1719 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
| 1722 } | 1720 } |
| 1723 } | 1721 } |
| 1724 } | 1722 } |
| 1725 | 1723 |
| 1726 #endif // V8_INTERPRETED_REGEXP | 1724 #endif // V8_INTERPRETED_REGEXP |
| 1727 | 1725 |
| 1728 }} // namespace v8::internal | 1726 }} // namespace v8::internal |
| 1729 | 1727 |
| 1730 #endif // V8_TARGET_ARCH_A64 | 1728 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |