| 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 defined(V8_TARGET_ARCH_A64) | 30 #if V8_TARGET_ARCH_A64 |
| 31 | 31 |
| 32 #include "cpu-profiler.h" |
| 32 #include "unicode.h" | 33 #include "unicode.h" |
| 33 #include "log.h" | 34 #include "log.h" |
| 34 #include "code-stubs.h" | 35 #include "code-stubs.h" |
| 35 #include "regexp-stack.h" | 36 #include "regexp-stack.h" |
| 36 #include "macro-assembler.h" | 37 #include "macro-assembler.h" |
| 37 #include "regexp-macro-assembler.h" | 38 #include "regexp-macro-assembler.h" |
| 38 #include "a64/regexp-macro-assembler-a64.h" | 39 #include "a64/regexp-macro-assembler-a64.h" |
| 39 | 40 |
| 40 namespace v8 { | 41 namespace v8 { |
| 41 namespace internal { | 42 namespace internal { |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 exit_label_() { | 149 exit_label_() { |
| 149 __ SetStackPointer(csp); | 150 __ SetStackPointer(csp); |
| 150 ASSERT_EQ(0, registers_to_save % 2); | 151 ASSERT_EQ(0, registers_to_save % 2); |
| 151 // We can cache at most 16 W registers in x0-x7. | 152 // We can cache at most 16 W registers in x0-x7. |
| 152 STATIC_ASSERT(kNumCachedRegisters <= 16); | 153 STATIC_ASSERT(kNumCachedRegisters <= 16); |
| 153 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); | 154 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); |
| 154 __ B(&entry_label_); // We'll write the entry code later. | 155 __ B(&entry_label_); // We'll write the entry code later. |
| 155 __ Bind(&start_label_); // And then continue from here. | 156 __ Bind(&start_label_); // And then continue from here. |
| 156 } | 157 } |
| 157 | 158 |
| 159 |
| 158 RegExpMacroAssemblerA64::~RegExpMacroAssemblerA64() { | 160 RegExpMacroAssemblerA64::~RegExpMacroAssemblerA64() { |
| 159 delete masm_; | 161 delete masm_; |
| 160 // 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. |
| 161 entry_label_.Unuse(); | 163 entry_label_.Unuse(); |
| 162 start_label_.Unuse(); | 164 start_label_.Unuse(); |
| 163 success_label_.Unuse(); | 165 success_label_.Unuse(); |
| 164 backtrack_label_.Unuse(); | 166 backtrack_label_.Unuse(); |
| 165 exit_label_.Unuse(); | 167 exit_label_.Unuse(); |
| 166 check_preempt_label_.Unuse(); | 168 check_preempt_label_.Unuse(); |
| 167 stack_overflow_label_.Unuse(); | 169 stack_overflow_label_.Unuse(); |
| 168 } | 170 } |
| 169 | 171 |
| 170 int RegExpMacroAssemblerA64::stack_limit_slack() { | 172 int RegExpMacroAssemblerA64::stack_limit_slack() { |
| 171 return RegExpStack::kStackLimitSlack; | 173 return RegExpStack::kStackLimitSlack; |
| 172 } | 174 } |
| 173 | 175 |
| 176 |
| 174 void RegExpMacroAssemblerA64::AdvanceCurrentPosition(int by) { | 177 void RegExpMacroAssemblerA64::AdvanceCurrentPosition(int by) { |
| 175 if (by != 0) { | 178 if (by != 0) { |
| 176 __ Add(current_input_offset(), | 179 __ Add(current_input_offset(), |
| 177 current_input_offset(), by * char_size()); | 180 current_input_offset(), by * char_size()); |
| 178 } | 181 } |
| 179 } | 182 } |
| 180 | 183 |
| 184 |
| 181 void RegExpMacroAssemblerA64::AdvanceRegister(int reg, int by) { | 185 void RegExpMacroAssemblerA64::AdvanceRegister(int reg, int by) { |
| 182 ASSERT((reg >= 0) && (reg < num_registers_)); | 186 ASSERT((reg >= 0) && (reg < num_registers_)); |
| 183 if (by != 0) { | 187 if (by != 0) { |
| 184 Register to_advance; | 188 Register to_advance; |
| 185 RegisterState register_state = GetRegisterState(reg); | 189 RegisterState register_state = GetRegisterState(reg); |
| 186 switch (register_state) { | 190 switch (register_state) { |
| 187 case STACKED: | 191 case STACKED: |
| 188 __ Ldr(w10, register_location(reg)); | 192 __ Ldr(w10, register_location(reg)); |
| 189 __ Add(w10, w10, by); | 193 __ Add(w10, w10, by); |
| 190 __ Str(w10, register_location(reg)); | 194 __ Str(w10, register_location(reg)); |
| 191 break; | 195 break; |
| 192 case CACHED_LSW: | 196 case CACHED_LSW: |
| 193 to_advance = GetCachedRegister(reg); | 197 to_advance = GetCachedRegister(reg); |
| 194 __ Add(to_advance, to_advance, by); | 198 __ Add(to_advance, to_advance, by); |
| 195 break; | 199 break; |
| 196 case CACHED_MSW: | 200 case CACHED_MSW: |
| 197 to_advance = GetCachedRegister(reg); | 201 to_advance = GetCachedRegister(reg); |
| 198 __ Add(to_advance, to_advance, static_cast<int64_t>(by) << kWRegSize); | 202 __ Add(to_advance, to_advance, static_cast<int64_t>(by) << kWRegSize); |
| 199 break; | 203 break; |
| 200 default: | 204 default: |
| 201 UNREACHABLE(); | 205 UNREACHABLE(); |
| 202 break; | 206 break; |
| 203 } | 207 } |
| 204 } | 208 } |
| 205 } | 209 } |
| 206 | 210 |
| 211 |
| 207 void RegExpMacroAssemblerA64::Backtrack() { | 212 void RegExpMacroAssemblerA64::Backtrack() { |
| 208 CheckPreemption(); | 213 CheckPreemption(); |
| 209 Pop(w10); | 214 Pop(w10); |
| 210 __ Add(x10, code_pointer(), Operand(w10, UXTW)); | 215 __ Add(x10, code_pointer(), Operand(w10, UXTW)); |
| 211 __ Br(x10); | 216 __ Br(x10); |
| 212 } | 217 } |
| 213 | 218 |
| 219 |
| 214 void RegExpMacroAssemblerA64::Bind(Label* label) { | 220 void RegExpMacroAssemblerA64::Bind(Label* label) { |
| 215 __ Bind(label); | 221 __ Bind(label); |
| 216 } | 222 } |
| 217 | 223 |
| 218 | 224 |
| 219 void RegExpMacroAssemblerA64::CheckCharacter(uint32_t c, Label* on_equal) { | 225 void RegExpMacroAssemblerA64::CheckCharacter(uint32_t c, Label* on_equal) { |
| 220 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); | 226 CompareAndBranchOrBacktrack(current_character(), c, eq, on_equal); |
| 221 } | 227 } |
| 222 | 228 |
| 223 | 229 |
| (...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 void RegExpMacroAssemblerA64::PopCurrentPosition() { | 1118 void RegExpMacroAssemblerA64::PopCurrentPosition() { |
| 1113 Pop(current_input_offset()); | 1119 Pop(current_input_offset()); |
| 1114 } | 1120 } |
| 1115 | 1121 |
| 1116 | 1122 |
| 1117 void RegExpMacroAssemblerA64::PopRegister(int register_index) { | 1123 void RegExpMacroAssemblerA64::PopRegister(int register_index) { |
| 1118 Pop(w10); | 1124 Pop(w10); |
| 1119 StoreRegister(register_index, w10); | 1125 StoreRegister(register_index, w10); |
| 1120 } | 1126 } |
| 1121 | 1127 |
| 1128 |
| 1122 void RegExpMacroAssemblerA64::PushBacktrack(Label* label) { | 1129 void RegExpMacroAssemblerA64::PushBacktrack(Label* label) { |
| 1123 if (label->is_bound()) { | 1130 if (label->is_bound()) { |
| 1124 int target = label->pos(); | 1131 int target = label->pos(); |
| 1125 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); | 1132 __ Mov(w10, target + Code::kHeaderSize - kHeapObjectTag); |
| 1126 } else { | 1133 } else { |
| 1127 __ Adr(x10, label); | 1134 __ Adr(x10, label); |
| 1128 __ Sub(x10, x10, code_pointer()); | 1135 __ Sub(x10, x10, code_pointer()); |
| 1129 if (masm_->emit_debug_code()) { | 1136 if (masm_->emit_debug_code()) { |
| 1130 __ Cmp(x10, kWRegMask); | 1137 __ Cmp(x10, kWRegMask); |
| 1131 __ Check(ls, "The code offset needs to fit in a W register."); | 1138 __ Check(ls, "The code offset needs to fit in a W register."); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { | 1290 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { |
| 1284 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); | 1291 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); |
| 1285 __ Sub(x10, backtrack_stackpointer(), x10); | 1292 __ Sub(x10, backtrack_stackpointer(), x10); |
| 1286 if (masm_->emit_debug_code()) { | 1293 if (masm_->emit_debug_code()) { |
| 1287 __ Cmp(x10, Operand(w10, SXTW)); | 1294 __ Cmp(x10, Operand(w10, SXTW)); |
| 1288 __ Check(eq, "Offset from the stack base needs to fit in a W register."); | 1295 __ Check(eq, "Offset from the stack base needs to fit in a W register."); |
| 1289 } | 1296 } |
| 1290 StoreRegister(reg, w10); | 1297 StoreRegister(reg, w10); |
| 1291 } | 1298 } |
| 1292 | 1299 |
| 1300 |
| 1293 // Helper function for reading a value out of a stack frame. | 1301 // Helper function for reading a value out of a stack frame. |
| 1294 template <typename T> | 1302 template <typename T> |
| 1295 static T& frame_entry(Address re_frame, int frame_offset) { | 1303 static T& frame_entry(Address re_frame, int frame_offset) { |
| 1296 return *reinterpret_cast<T*>(re_frame + frame_offset); | 1304 return *reinterpret_cast<T*>(re_frame + frame_offset); |
| 1297 } | 1305 } |
| 1298 | 1306 |
| 1307 |
| 1299 int RegExpMacroAssemblerA64::CheckStackGuardState(Address* return_address, | 1308 int RegExpMacroAssemblerA64::CheckStackGuardState(Address* return_address, |
| 1300 Code* re_code, | 1309 Code* re_code, |
| 1301 Address re_frame, | 1310 Address re_frame, |
| 1302 int start_offset, | 1311 int start_offset, |
| 1303 const byte** input_start, | 1312 const byte** input_start, |
| 1304 const byte** input_end) { | 1313 const byte** input_end) { |
| 1305 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); | 1314 Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); |
| 1306 ASSERT(isolate == Isolate::Current()); | 1315 ASSERT(isolate == Isolate::Current()); |
| 1307 if (isolate->stack_guard()->IsStackOverflow()) { | 1316 if (isolate->stack_guard()->IsStackOverflow()) { |
| 1308 isolate->StackOverflow(); | 1317 isolate->StackOverflow(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 } else if (frame_entry<const String*>(re_frame, kInput) != *subject) { | 1398 } else if (frame_entry<const String*>(re_frame, kInput) != *subject) { |
| 1390 // Subject string might have been a ConsString that underwent | 1399 // Subject string might have been a ConsString that underwent |
| 1391 // short-circuiting during GC. That will not change start_address but | 1400 // short-circuiting during GC. That will not change start_address but |
| 1392 // will change pointer inside the subject handle. | 1401 // will change pointer inside the subject handle. |
| 1393 frame_entry<const String*>(re_frame, kInput) = *subject; | 1402 frame_entry<const String*>(re_frame, kInput) = *subject; |
| 1394 } | 1403 } |
| 1395 | 1404 |
| 1396 return 0; | 1405 return 0; |
| 1397 } | 1406 } |
| 1398 | 1407 |
| 1408 |
| 1399 void RegExpMacroAssemblerA64::CheckPosition(int cp_offset, | 1409 void RegExpMacroAssemblerA64::CheckPosition(int cp_offset, |
| 1400 Label* on_outside_input) { | 1410 Label* on_outside_input) { |
| 1401 CompareAndBranchOrBacktrack(current_input_offset(), | 1411 CompareAndBranchOrBacktrack(current_input_offset(), |
| 1402 -cp_offset * char_size(), | 1412 -cp_offset * char_size(), |
| 1403 ge, | 1413 ge, |
| 1404 on_outside_input); | 1414 on_outside_input); |
| 1405 } | 1415 } |
| 1406 | 1416 |
| 1417 |
| 1407 bool RegExpMacroAssemblerA64::CanReadUnaligned() { | 1418 bool RegExpMacroAssemblerA64::CanReadUnaligned() { |
| 1408 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1419 // TODO(pielan): See whether or not we should disable unaligned accesses. |
| 1409 return !slow_safe(); | 1420 return !slow_safe(); |
| 1410 } | 1421 } |
| 1411 | 1422 |
| 1423 |
| 1412 // Private methods: | 1424 // Private methods: |
| 1413 | 1425 |
| 1414 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { | 1426 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { |
| 1415 // Allocate space on the stack to store the return address. The | 1427 // Allocate space on the stack to store the return address. The |
| 1416 // CheckStackGuardState C++ function will override it if the code | 1428 // CheckStackGuardState C++ function will override it if the code |
| 1417 // moved. Allocate extra space for 2 arguments passed by pointers. | 1429 // moved. Allocate extra space for 2 arguments passed by pointers. |
| 1418 // AAPCS64 requires the stack to be 16 byte aligned. | 1430 // AAPCS64 requires the stack to be 16 byte aligned. |
| 1419 int alignment = masm_->ActivationFrameAlignment(); | 1431 int alignment = masm_->ActivationFrameAlignment(); |
| 1420 ASSERT_EQ(alignment % 16, 0); | 1432 ASSERT_EQ(alignment % 16, 0); |
| 1421 int align_mask = (alignment / kXRegSizeInBytes) - 1; | 1433 int align_mask = (alignment / kXRegSizeInBytes) - 1; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1507 // Check for preemption. | 1519 // Check for preemption. |
| 1508 ExternalReference stack_limit = | 1520 ExternalReference stack_limit = |
| 1509 ExternalReference::address_of_stack_limit(isolate()); | 1521 ExternalReference::address_of_stack_limit(isolate()); |
| 1510 __ Mov(x10, Operand(stack_limit)); | 1522 __ Mov(x10, Operand(stack_limit)); |
| 1511 __ Ldr(x10, MemOperand(x10)); | 1523 __ Ldr(x10, MemOperand(x10)); |
| 1512 ASSERT(csp.Is(__ StackPointer())); | 1524 ASSERT(csp.Is(__ StackPointer())); |
| 1513 __ Cmp(csp, x10); | 1525 __ Cmp(csp, x10); |
| 1514 CallIf(&check_preempt_label_, ls); | 1526 CallIf(&check_preempt_label_, ls); |
| 1515 } | 1527 } |
| 1516 | 1528 |
| 1529 |
| 1517 void RegExpMacroAssemblerA64::CheckStackLimit() { | 1530 void RegExpMacroAssemblerA64::CheckStackLimit() { |
| 1518 ExternalReference stack_limit = | 1531 ExternalReference stack_limit = |
| 1519 ExternalReference::address_of_regexp_stack_limit(isolate()); | 1532 ExternalReference::address_of_regexp_stack_limit(isolate()); |
| 1520 __ Mov(x10, Operand(stack_limit)); | 1533 __ Mov(x10, Operand(stack_limit)); |
| 1521 __ Ldr(x10, MemOperand(x10)); | 1534 __ Ldr(x10, MemOperand(x10)); |
| 1522 __ Cmp(backtrack_stackpointer(), x10); | 1535 __ Cmp(backtrack_stackpointer(), x10); |
| 1523 CallIf(&stack_overflow_label_, ls); | 1536 CallIf(&stack_overflow_label_, ls); |
| 1524 } | 1537 } |
| 1525 | 1538 |
| 1526 | 1539 |
| 1527 void RegExpMacroAssemblerA64::Push(Register source) { | 1540 void RegExpMacroAssemblerA64::Push(Register source) { |
| 1528 ASSERT(source.Is32Bits()); | 1541 ASSERT(source.Is32Bits()); |
| 1529 ASSERT(!source.is(backtrack_stackpointer())); | 1542 ASSERT(!source.is(backtrack_stackpointer())); |
| 1530 __ Str(source, | 1543 __ Str(source, |
| 1531 MemOperand(backtrack_stackpointer(), | 1544 MemOperand(backtrack_stackpointer(), |
| 1532 -static_cast<int>(kWRegSizeInBytes), | 1545 -static_cast<int>(kWRegSizeInBytes), |
| 1533 PreIndex)); | 1546 PreIndex)); |
| 1534 } | 1547 } |
| 1535 | 1548 |
| 1549 |
| 1536 void RegExpMacroAssemblerA64::Pop(Register target) { | 1550 void RegExpMacroAssemblerA64::Pop(Register target) { |
| 1537 ASSERT(target.Is32Bits()); | 1551 ASSERT(target.Is32Bits()); |
| 1538 ASSERT(!target.is(backtrack_stackpointer())); | 1552 ASSERT(!target.is(backtrack_stackpointer())); |
| 1539 __ Ldr(target, | 1553 __ Ldr(target, |
| 1540 MemOperand(backtrack_stackpointer(), kWRegSizeInBytes, PostIndex)); | 1554 MemOperand(backtrack_stackpointer(), kWRegSizeInBytes, PostIndex)); |
| 1541 } | 1555 } |
| 1542 | 1556 |
| 1543 | 1557 |
| 1544 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { | 1558 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { |
| 1545 ASSERT(register_index < kNumCachedRegisters); | 1559 ASSERT(register_index < kNumCachedRegisters); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1705 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1719 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
| 1706 } | 1720 } |
| 1707 } | 1721 } |
| 1708 } | 1722 } |
| 1709 | 1723 |
| 1710 #endif // V8_INTERPRETED_REGEXP | 1724 #endif // V8_INTERPRETED_REGEXP |
| 1711 | 1725 |
| 1712 }} // namespace v8::internal | 1726 }} // namespace v8::internal |
| 1713 | 1727 |
| 1714 #endif // V8_TARGET_ARCH_A64 | 1728 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |