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 |