Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 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 #include "log.h" | |
| 30 #include "ast.h" | |
| 31 #include "macro-assembler.h" | |
| 29 #include "regexp-macro-assembler-ia32.h" | 32 #include "regexp-macro-assembler-ia32.h" |
| 30 | 33 |
| 31 namespace v8 { namespace internal { | 34 namespace v8 { namespace internal { |
| 32 | 35 |
| 33 /* | 36 /* |
| 34 * This assembler uses the following register assignment convention | 37 * This assembler uses the following register assignment convention |
| 35 * - edx : current character, or kEndOfInput if current position is not | 38 * - edx : current character, or kEndOfInput if current position is not |
| 36 * inside string. The kEndOfInput value is greater than 0xffff, | 39 * inside string. The kEndOfInput value is greater than 0xffff, |
| 37 * so any tests that don't check whether the current position | 40 * so any tests that don't check whether the current position |
| 38 * is inside the correct range should retain bits above the | 41 * is inside the correct range should retain bits above the |
| 39 * 15th in their computations, and fail if the value is too | 42 * 15th in their computations, and fail if the value is too |
| 40 * great. | 43 * great. |
| 41 * - edi : current position in input. | 44 * - edi : current position in input, as negative offset from end of string. |
| 42 * - esi : end of input (points to byte after last character in input). | 45 * - esi : end of input (points to byte after last character in input). |
| 43 * - ebp : points to the location above the registers on the stack, | 46 * - ebp : points to the location above the registers on the stack, |
| 44 * as if by the "enter <register_count>" opcode. | 47 * as if by the "enter <register_count>" opcode. |
| 45 * - esp : points to tip of backtracking stack. | 48 * - esp : points to tip of backtracking stack. |
| 46 * | 49 * |
| 47 * The registers eax, ebx and eax are free to use for computations. | 50 * The registers eax, ebx and ecx are free to use for computations. |
| 48 * | 51 * |
| 49 * Each call to a public method should retain this convention. | 52 * Each call to a public method should retain this convention. |
| 50 * The stack is expected to have the following structure (tentative): | 53 * The stack is expected to have the following structure (tentative): |
|
Erik Corry
2008/11/21 13:03:04
Be bold, not tentative! :-)
Lasse Reichstein
2008/11/24 08:32:33
Done!
| |
| 51 * | 54 * - int* capture_array (int[num_saved_registers_], for output). |
| 52 * - pointer to array where captures can be stored | 55 * - end of input (index of end of string, relative to *string_base) |
| 53 * - end of input | 56 * - start of input (index of first character in string, relative |
| 54 * - start of input | 57 * to *string_base) |
| 58 * - void** string_base (location of a handle containing the string) | |
| 55 * - return address | 59 * - return address |
| 60 * - backup of esi | |
| 61 * - backup of edi | |
| 56 * ebp-> - old ebp | 62 * ebp-> - old ebp |
| 57 * - register 0 ebp[-4] | 63 * - register 0 ebp[-4] |
| 58 * - register 1 ebp[-8] | 64 * - register 1 ebp[-8] |
| 59 * - ... | 65 * - ... |
| 60 * | 66 * |
| 61 * The data before ebp must be placed there by the calling code. | 67 * The data before ebp must be placed there by the calling code, e.g., |
| 68 * by calling the code as cast to: | |
| 69 * bool (*match)(void** string_base, | |
| 70 * int start_offset, | |
| 71 * int end_offset, | |
| 72 * int* capture_array) | |
| 62 */ | 73 */ |
| 63 | 74 |
| 64 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32() | 75 #define __ masm_-> |
| 76 | |
| 77 | |
| 78 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( | |
| 79 Mode mode, | |
| 80 int registers_to_save, | |
| 81 bool ignore_case) | |
| 65 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), | 82 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), |
| 66 constants_(kRegExpConstantsSize), | 83 constants_(kRegExpConstantsSize), |
| 67 num_registers_(0), | 84 mode_(mode), |
| 68 ignore_case(false) {} | 85 num_registers_(registers_to_save), |
| 86 num_saved_registers_(registers_to_save), | |
| 87 ignore_case_(ignore_case), | |
| 88 entry_label_(), | |
| 89 start_label_(), | |
| 90 success_label_(), | |
| 91 exit_label_(), | |
| 92 self_() { | |
| 93 __ jmp(&entry_label_); // We'll write the entry code later. | |
| 94 __ bind(&start_label_); // And then continue from here. | |
| 95 } | |
| 96 | |
| 69 | 97 |
| 70 | 98 |
| 71 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { | 99 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { |
| 72 delete masm_; | 100 delete masm_; |
| 73 } | 101 } |
| 74 | 102 |
| 75 | 103 |
| 76 #define __ masm_-> | |
| 77 | 104 |
| 78 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { | 105 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { |
| 79 __ add(edi, by * sizeof(SubjectChar)); | 106 ASSERT(by > 0); |
| 80 __ cmp(edi, esi); | |
| 81 Label inside_string; | 107 Label inside_string; |
| 108 __ add(Operand(edi), Immediate(by * char_size())); | |
| 109 __ j(below, &inside_string); | |
| 82 Backtrack(); | 110 Backtrack(); |
| 83 | 111 |
| 84 __ bind(&inside_string); | 112 __ bind(&inside_string); |
| 85 ReadChar(edx, 0); | |
| 86 } | 113 } |
| 87 | 114 |
| 88 | 115 |
| 116 | |
| 89 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { | 117 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { |
| 90 ASSERT(reg >= 0); | 118 ASSERT(reg >= 0); |
| 91 ASSERT(reg < num_registers); | 119 ASSERT(reg < num_registers_); |
| 92 __ add(register_location(reg), by); | 120 __ add(register_location(reg), Immediate(by)); |
| 93 } | 121 } |
| 94 | 122 |
| 95 | 123 |
| 124 | |
| 96 void RegExpMacroAssemblerIA32::Backtrack() { | 125 void RegExpMacroAssemblerIA32::Backtrack() { |
| 97 __ ret(); | 126 __ pop(ecx); |
| 127 __ add(Operand(ecx), Immediate(self_)); | |
| 128 __ jmp(Operand(ecx)); | |
| 98 } | 129 } |
| 99 | 130 |
| 100 | 131 |
| 132 | |
| 101 void RegExpMacroAssemblerIA32::Bind(Label* label) { | 133 void RegExpMacroAssemblerIA32::Bind(Label* label) { |
| 102 __ bind(label); | 134 __ bind(label); |
| 103 } | 135 } |
| 104 | 136 |
| 105 | 137 |
| 138 | |
| 106 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, | 139 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, |
| 107 Label* bitmap, | 140 Label* bitmap, |
| 108 Label* on_zero) { | 141 Label* on_zero) { |
| 109 ReadCurrentChar(eax); | 142 ReadCurrentChar(eax); |
| 110 __ sub(eax, start); | 143 __ sub(Operand(eax), Immediate(start)); |
| 111 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. | 144 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. |
| 112 BranchOrBacktrack(greater_equal, on_zero); | 145 BranchOrBacktrack(greater_equal, on_zero); |
| 113 __ mov(ebx, eax); | 146 __ mov(ebx, eax); |
| 114 __ shr(ebx, 3); | 147 __ shr(ebx, 3); |
| 115 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead. | 148 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead. |
| 116 // __ mov(ecx, position_of_bitmap); | 149 // __ mov(ecx, position_of_bitmap); |
| 117 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0)); | 150 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0)); |
| 118 __ and_(eax, (1<<3)-1); | 151 __ and_(eax, (1<<3)-1); |
| 119 __ bt(ebx, eax); | 152 __ bt(Operand(ebx), eax); |
| 120 __ j(greater_equal, on_zero); // Aka. jump on carry set. | 153 __ j(carry, on_zero); |
| 121 } | 154 } |
| 122 | 155 |
| 123 | 156 |
| 124 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, | 157 void RegExpMacroAssemblerIA32::CheckCharacter(uc16 c, Label* on_equal) { |
| 125 Label* on_end_of_input) { | 158 __ cmp(edx, c); |
| 126 UNREACHABLE(); // Not implemented. | 159 BranchOrBacktrack(equal, on_equal); |
| 160 } | |
| 161 | |
| 162 | |
| 163 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { | |
| 164 __ cmp(edx, limit); | |
| 165 BranchOrBacktrack(greater, on_greater); | |
| 127 } | 166 } |
| 128 | 167 |
| 129 | 168 |
| 130 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { | 169 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { |
| 131 UNREACHABLE(); // Not implemented. | 170 __ cmp(edx, limit); |
| 171 BranchOrBacktrack(less, on_less); | |
| 132 } | 172 } |
| 133 | 173 |
| 134 | 174 |
| 135 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { | 175 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, |
| 136 UNREACHABLE(); // Not implemented. | 176 int cp_offset, |
| 137 } | 177 Label* on_failure) { |
| 178 int byte_length = str.length() * char_size(); | |
| 179 int start_offset = cp_offset * char_size(); | |
| 180 __ mov(ebx, edi); | |
| 181 __ add(Operand(ebx), Immediate(start_offset + byte_length)); | |
| 182 BranchOrBacktrack(greater_equal, on_failure); | |
| 138 | 183 |
| 139 | 184 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); |
| 140 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<uc16> str, | 185 for (int i = 0; i < str.length(); i++) { |
| 141 Label* on_failure) { | 186 if (mode_ == ASCII) { |
| 142 if (sizeof(SubjectChar) == 1) { | 187 constant_buffer.at<char>(i) = static_cast<char>(str[i]); |
| 143 for (int i = 0; i < str.length(); i++) { | 188 } else { |
| 144 if (str[i] > String::kMaxAsciiCharCode) { | 189 constant_buffer.at<uc16>(i) = str[i]; |
| 145 __ jmp(on_failure); | |
| 146 return; | |
| 147 } | |
| 148 } | 190 } |
| 149 } | 191 } |
| 150 int byte_length = str.length() * sizeof(SubjectChar); | |
| 151 __ mov(ebx, edi); | |
| 152 __ add(ebx, byte_length); | |
| 153 __ cmp(ebx, esi); | |
| 154 BranchOrBacktrack(greater_equal, on_failure); | |
| 155 | 192 |
| 156 if (str.length() <= kMaxInlineStringTests || ignore_case()) { | 193 __ mov(eax, edi); |
| 157 // TODO(lrn): make loop if str.length is large but ignore_case is true; | 194 __ mov(ebx, esi); |
| 158 for (int i = 0; i < str.length(); i++) { | 195 __ lea(edi, Operand(esi, edi, times_1, start_offset)); |
| 159 ReadChar(eax, i); | 196 LoadConstantBufferAddress(esi, &constant_buffer); |
| 160 if (ignore_case()) { | 197 __ mov(ecx, str.length()); |
| 161 Canonicalize(eax); | 198 if (mode_ == ASCII) { |
| 162 } | 199 __ rep_cmpsb(); |
| 163 __ cmp(eax, str[i]); | |
| 164 BranchOrBacktrack(not_equal, on_failure); | |
| 165 } | |
| 166 add(edi, byte_length); | |
| 167 } else { | 200 } else { |
| 168 int offset; | 201 ASSERT(mode_ == UC16); |
| 169 ArraySlice<SubjectChar> constant_buffer = | 202 __ rep_cmpsw(); |
| 170 constants_.GetBuffer<SubjectChar>(str.length()); | |
| 171 for (int i = 0; i < str.length(); i++) { | |
| 172 constant_buffer[i] = str[i]; | |
| 173 } | |
| 174 __ mov(ebx, esi); | |
| 175 LoadConstantBufferAddress(esi, constant_buffer); | |
| 176 __ mov(ecx, str.length()); | |
| 177 if (sizeof(SubjectChar) == 1) { | |
| 178 __ rep_cmpsb(); | |
| 179 } else { | |
| 180 ASSERT(sizeof(SubjectChar) == 2); | |
| 181 __ rep_cmpsw(); | |
| 182 } | |
| 183 __ mov(esi, ebx); | |
| 184 BranchOrBacktrack(not_equal, on_failure); | |
| 185 } | 203 } |
| 186 }; | 204 __ mov(esi, ebx); |
| 205 __ mov(edi, eax); | |
| 206 BranchOrBacktrack(not_equal, on_failure); | |
| 207 } | |
| 187 | 208 |
| 188 | 209 |
| 189 void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index, | 210 void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index, |
| 190 Label* on_equal) { | 211 Label* on_equal) { |
| 191 __ cmp(register_location(register_index), edi); | 212 __ cmp(edi, register_location(register_index)); |
| 192 BranchOrBacktrack(equal, on_equal); | 213 BranchOrBacktrack(equal, on_equal); |
| 193 } | 214 } |
| 194 | 215 |
| 195 | 216 |
| 217 void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) { | |
| 218 __ cmp(edx, c); | |
| 219 BranchOrBacktrack(not_equal, on_not_equal); | |
| 220 } | |
| 221 | |
| 222 | |
| 196 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( | 223 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( |
| 197 uc16 start, | 224 uc16 start, |
| 198 Label* half_nibble_map, | 225 Label* half_nibble_map, |
| 199 const Vector<Label*>& destinations) { | 226 const Vector<Label*>& destinations) { |
| 227 ReadCurrentChar(eax); | |
| 228 __ sub(Operand(eax), Immediate(start)); | |
| 200 | 229 |
| 201 if (sizeof(SubjectChar) == 1 && start > String::kMaxAsciiCharCode) { | 230 __ mov(ecx, eax); |
| 202 return; | |
| 203 } | |
| 204 | |
| 205 Label fallthrough; | |
| 206 | |
| 207 ReadCurrentChar(eax); | |
| 208 __ sub(eax, start); | |
| 209 __ cmp(eax, 64); // FIXME: 64 = size of map in bytes. Found somehow?? | |
| 210 __ j(greater_equal, &fallthrough); | |
| 211 | |
| 212 __ mov(ebx, eax); | |
| 213 __ shr(eax, 2); | 231 __ shr(eax, 2); |
| 214 __ movzx_b(eax, Operand(ecx, eax)); // FIXME: ecx holds address of map | 232 // FIXME: ecx must hold address of map |
| 233 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | |
| 215 Label got_nybble; | 234 Label got_nybble; |
| 216 Label high_bits; | 235 Label high_bits; |
| 217 __ and_(ebx, 0x03); | 236 __ and_(ecx, 0x03); |
| 218 __ shr(eax, ebx); | 237 __ add(ecx, Operand(ecx)); |
| 238 __ shr(eax); // Shift right cl times | |
| 219 | 239 |
| 220 Label second_bit_set, case_3, case_1; | 240 Label second_bit_set, case_3, case_1; |
| 221 __ test(eax, 2); | 241 __ test(eax, Immediate(0x02)); |
| 222 __ j(not_equal, &second_bit_set); | 242 __ j(not_zero, &second_bit_set); |
| 223 __ test(eax, 1); | 243 __ test(eax, Immediate(0x01)); |
| 224 __ j(not_equal, &case_1); | 244 __ j(not_zero, &case_1); |
| 225 // Case 0: | 245 // Case 0: |
| 226 __ jmp(&destinations[0]); | 246 __ jmp(destinations[0]); |
| 227 __ bind(&case_1); | 247 __ bind(&case_1); |
| 228 // Case 1: | 248 // Case 1: |
| 229 __ jmp(&destinations[1]); | 249 __ jmp(destinations[1]); |
| 230 __ bind(&second_bit_set); | 250 __ bind(&second_bit_set); |
| 231 __ test(eax, 1); | 251 __ test(eax, Immediate(0x01)); |
| 232 __ j(not_equal, &case_3); | 252 __ j(not_zero, &case_3); |
| 233 // Case 2 | 253 // Case 2 |
| 234 __ jmp(&destinations[2]); | 254 __ jmp(destinations[2]); |
| 235 __ bind(&case_3); | 255 __ bind(&case_3); |
| 236 // Case 3: | 256 // Case 3: |
| 237 __ jmp(&destinations[3]); | 257 __ jmp(destinations[3]); |
| 238 | |
| 239 __ bind(&fallthrough); | |
| 240 } | 258 } |
| 241 | 259 |
| 242 | 260 |
| 243 void RegExpMacroAssemblerIA32::DispatchByteMap( | 261 void RegExpMacroAssemblerIA32::DispatchByteMap( |
| 244 uc16 start, | 262 uc16 start, |
| 245 Label* byte_map, | 263 Label* byte_map, |
| 246 const Vector<Label*>& destinations) { | 264 const Vector<Label*>& destinations) { |
| 247 | 265 |
| 248 if (sizeof(SubjectChar) == 1 && start > String::kMaxAsciiCharCode) { | |
| 249 return; | |
| 250 } | |
| 251 | |
| 252 Label fallthrough; | 266 Label fallthrough; |
| 253 | 267 |
| 254 ReadCurrentChar(eax); | 268 ReadCurrentChar(eax); |
| 255 __ sub(eax, start); | 269 __ sub(Operand(eax), Immediate(start)); |
| 256 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? | 270 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? |
| 257 __ j(greater_equal, &fallthrough); | 271 __ j(greater_equal, &fallthrough); |
| 258 | 272 // FIXME: ecx must hold address of map |
| 259 __ movzx_b(eax, Operand(ecx, eax)); // FIXME: ecx must hold address of map | 273 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); |
| 260 // jump table: jump to destinations[eax]; | 274 // jump table: jump to destinations[eax]; |
| 261 | 275 |
| 262 __ bind(&fallthrough); | 276 __ bind(&fallthrough); |
| 263 } | 277 } |
| 264 | 278 |
| 279 | |
| 280 | |
| 265 void RegExpMacroAssemblerIA32::DispatchHighByteMap( | 281 void RegExpMacroAssemblerIA32::DispatchHighByteMap( |
| 266 byte start, | 282 byte start, |
| 267 Label* byte_map, | 283 Label* byte_map, |
| 268 const Vector<Label*>& destinations) { | 284 const Vector<Label*>& destinations) { |
| 269 Label fallthrough; | 285 Label fallthrough; |
| 270 ReadCurrentChar(eax); | 286 ReadCurrentChar(eax); |
| 271 __ shr(eax, 8); | 287 __ shr(eax, 8); |
| 272 __ sub(eax, start); | 288 __ sub(Operand(eax), Immediate(start)); |
| 273 __ cmp(eax, destinations.length() - start); | 289 __ cmp(eax, destinations.length() - start); |
| 274 __ j(greater_equal, &fallthrough); | 290 __ j(greater_equal, &fallthrough); |
| 275 | 291 |
| 276 // TODO(lrn) jumptable: jump to destinations[eax] | 292 // TODO(lrn) jumptable: jump to destinations[eax] |
| 277 __ bind(&fallthrough); | 293 __ bind(&fallthrough); |
| 278 } | 294 } |
| 279 | 295 |
| 280 | 296 |
| 281 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { | 297 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { |
| 282 UNREACHABLE(); // Has no use. | 298 UNREACHABLE(); // Has no use. |
| 283 } | 299 } |
| 284 | 300 |
| 285 | 301 |
| 286 void RegExpMacroAssemblerIA32::Fail() { | 302 void RegExpMacroAssemblerIA32::Fail() { |
| 287 Exit(false); | 303 __ mov(eax, 0); |
| 288 } | 304 __ jmp(&exit_label_); |
| 289 | |
| 290 Handle<Object> RegExpMacroAssemblerIA32::GetCode() { | |
| 291 // something | |
| 292 return Handle(); | |
| 293 } | 305 } |
| 294 | 306 |
| 295 | 307 |
| 308 Handle<Object> RegExpMacroAssemblerIA32::GetCode() { | |
| 309 // Finalize code - write the entry point code now we know how many | |
| 310 // registers we need. | |
| 311 | |
| 312 // Entry code: | |
| 313 __ bind(&entry_label_); | |
| 314 __ push(esi); | |
| 315 __ push(edi); | |
| 316 __ enter(Immediate(num_registers_ * sizeof(uint32_t))); | |
| 317 __ mov(esi, Operand(ebp, kInputEndOffset)); | |
| 318 __ mov(edi, Operand(ebp, kInputStartOffset)); | |
| 319 __ sub(edi, Operand(esi)); | |
| 320 __ mov(edx, Operand(ebp, kInputBuffer)); | |
| 321 __ mov(edx, Operand(edx, 0)); | |
| 322 __ add(esi, Operand(edx)); | |
| 323 __ jmp(&start_label_); | |
| 324 | |
| 325 // Exit code: | |
| 326 __ bind(&success_label_); | |
| 327 __ mov(ebx, Operand(ebp, kRegisterOutput)); | |
| 328 __ mov(ecx, Operand(ebp, kInputEndOffset)); | |
| 329 __ sub(ecx, Operand(ebp, kInputStartOffset)); | |
| 330 for (int i = 0; i < num_saved_registers_; i++) { | |
| 331 __ mov(eax, register_location(i)); | |
| 332 __ sub(eax, Operand(ecx)); // Convert to index from start, not end. | |
| 333 __ mov(Operand(ebx, i * sizeof(int32_t)), eax); | |
| 334 } | |
| 335 // copy captures to output | |
| 336 __ mov(eax, Immediate(1)); | |
| 337 | |
| 338 __ bind(&exit_label_); | |
| 339 __ leave(); | |
| 340 __ pop(edi); | |
| 341 __ pop(esi); | |
| 342 __ ret(0); | |
| 343 | |
| 344 CodeDesc code_desc; | |
| 345 masm_->GetCode(&code_desc); | |
| 346 Handle<Code> code = Factory::NewCode(code_desc, | |
| 347 NULL, | |
|
Erik Corry
2008/11/21 13:03:04
Indentation!
Lasse Reichstein
2008/11/24 08:32:33
Done.
| |
| 348 Code::ComputeFlags(Code::REGEXP)); | |
| 349 LOG(CodeCreateEvent("RegExp", *code, "(Compiled RegExp)")); | |
| 350 return Handle<Object>::cast(code); | |
| 351 } | |
| 352 | |
| 353 | |
| 296 void RegExpMacroAssemblerIA32::GoTo(Label* to) { | 354 void RegExpMacroAssemblerIA32::GoTo(Label* to) { |
| 297 __ jmp(to); | 355 __ jmp(to); |
| 298 } | 356 } |
| 299 | 357 |
| 300 | 358 |
| 359 | |
| 301 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, | 360 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, |
| 302 int comparand, | 361 int comparand, |
| 303 Label* if_ge) { | 362 Label* if_ge) { |
| 304 __ cmp(register_location(reg), comparand); | 363 __ cmp(register_location(reg), Immediate(comparand)); |
| 305 BranchOrBacktrack(greater_equal, if_ge); | 364 BranchOrBacktrack(greater_equal, if_ge); |
| 306 } | 365 } |
| 307 | 366 |
| 308 | 367 |
| 368 | |
| 309 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, | 369 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, |
| 310 int comparand, | 370 int comparand, |
| 311 Label* if_lt) { | 371 Label* if_lt) { |
| 312 __ cmp(register_location(reg), comparand); | 372 __ cmp(register_location(reg), Immediate(comparand)); |
| 313 BranchOrBacktrack(less, if_lt); | 373 BranchOrBacktrack(less, if_lt); |
| 314 } | 374 } |
| 315 | 375 |
| 316 | 376 |
| 317 Re2kImplementation RegExpMacroAssemblerIA32::Implementation() { | 377 |
| 378 RegExpMacroAssembler::Re2kImplementation | |
| 379 RegExpMacroAssemblerIA32::Implementation() { | |
| 318 return kIA32Implementation; | 380 return kIA32Implementation; |
| 319 } | 381 } |
| 320 | 382 |
| 321 | 383 |
| 384 | |
| 385 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, | |
| 386 Label* on_end_of_input) { | |
| 387 ASSERT(cp_offset >= 0); | |
| 388 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | |
| 389 __ cmp(edi, -cp_offset); | |
| 390 BranchOrBacktrack(less_equal, on_end_of_input); | |
| 391 ReadChar(edx, cp_offset); | |
| 392 } | |
| 393 | |
| 394 | |
| 322 void RegExpMacroAssemblerIA32::PopCurrentPosition() { | 395 void RegExpMacroAssemblerIA32::PopCurrentPosition() { |
| 323 __ pop(edi); | 396 __ pop(edi); |
| 324 ReadChar(edx, 0); | |
| 325 } | 397 } |
| 326 | 398 |
| 327 | 399 |
| 328 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { | 400 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { |
| 401 RecordRegister(register_index); | |
| 329 __ pop(register_location(register_index)); | 402 __ pop(register_location(register_index)); |
| 330 } | 403 } |
| 331 | 404 |
| 332 | 405 |
| 333 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { | 406 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { |
| 407 // Check for preemption first. | |
| 408 Label no_preempt; | |
| 409 Label retry_preempt; | |
| 410 // Check for preemption. | |
| 411 ExternalReference stack_limit = | |
| 412 ExternalReference::address_of_stack_guard_limit(); | |
| 413 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 414 __ j(above, &no_preempt); | |
|
Erik Corry
2008/11/21 13:03:04
We don't have to fix this now, but this needs movi
| |
| 415 | |
| 416 __ push(edi); // Current position. | |
| 417 __ push(edx); // Current character. | |
| 418 // Restore original edi, esi. | |
| 419 __ mov(edi, Operand(ebp, kBackup_edi)); | |
| 420 __ mov(esi, Operand(ebp, kBackup_esi)); | |
| 421 | |
| 422 __ bind(&retry_preempt); | |
| 423 // simulate stack for Runtime call. | |
| 424 __ push(0); // Dummy receiver | |
| 425 __ CallRuntime(Runtime::kStackGuard, 0); | |
| 426 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 427 __ j(below_equal, &retry_preempt); | |
| 428 | |
| 429 __ pop(edx); | |
| 430 __ pop(edi); | |
| 431 __ mov(esi, Operand(ebp, kInputBuffer)); | |
| 432 __ mov(esi, Operand(esi, 0)); | |
| 433 __ add(esi, Operand(ebp, kInputEndOffset)); | |
| 434 | |
| 435 __ bind(&no_preempt); | |
| 436 | |
| 334 Label cont; | 437 Label cont; |
| 335 __ call(&cont); | 438 __ push(label); |
| 336 __ jmp(label); | |
| 337 __ bind(&cont); | |
| 338 } | 439 } |
| 339 | 440 |
| 340 | 441 |
| 341 void RegExpMacroAssemblerIA32::PushCurrentPosition() { | 442 void RegExpMacroAssemblerIA32::PushCurrentPosition() { |
| 342 __ push(edi); | 443 __ push(edi); |
| 343 } | 444 } |
| 344 | 445 |
| 345 | 446 |
| 346 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { | 447 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { |
| 347 __ push(register_location(register_index)); | 448 __ push(register_location(register_index)); |
| 348 } | 449 } |
| 349 | 450 |
| 350 | 451 |
| 452 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { | |
| 453 __ mov(edi, register_location(reg)); | |
| 454 } | |
| 455 | |
| 456 | |
| 457 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { | |
| 458 __ mov(esp, register_location(reg)); | |
| 459 } | |
| 460 | |
| 461 | |
| 351 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { | 462 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { |
| 352 __ mov(register_location(register_index), to); | 463 RecordRegister(register_index); |
| 464 __ mov(register_location(register_index), Immediate(to)); | |
| 353 } | 465 } |
| 354 | 466 |
| 355 | 467 |
| 356 void RegExpMacroAssemblerIA32::Succeed() { | 468 void RegExpMacroAssemblerIA32::Succeed() { |
| 357 Exit(true); | 469 __ jmp(&success_label_); |
|
Erik Corry
2008/11/21 13:03:04
Do we need to set eax here?
Lasse Reichstein
2008/11/24 08:32:33
No.
The code at success_lable_ sets eax and runs i
| |
| 358 } | 470 } |
| 359 | 471 |
| 360 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister() { | 472 |
| 473 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( | |
| 474 int register_index) { | |
| 361 __ mov(register_location(register_index), edi); | 475 __ mov(register_location(register_index), edi); |
| 362 } | 476 } |
| 363 | 477 |
| 364 // Custom : | 478 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { |
| 365 | 479 __ mov(register_location(reg), esp); |
| 366 void RegExpMacroAssemblerIA32::Initialize(int num_registers, bool ignore_case) { | |
| 367 num_registers_ = num_registers; | |
| 368 ignore_case_ = ignore_case; | |
| 369 __ enter(num_registers * sizeof(uint32_t)); | |
| 370 } | 480 } |
| 371 | 481 |
| 372 | 482 |
| 373 Operand RegExpMacroAssemblerIA32::register_location(int register_index) { | 483 // Private methods: |
| 484 | |
| 485 Operand RegExpMacroAssemblerIA32::register_location( | |
| 486 int register_index) { | |
| 374 ASSERT(register_index < (1<<30)); | 487 ASSERT(register_index < (1<<30)); |
| 375 return Operand(ebp, -((register_index + 1) * sizeof(uint32_t))); | 488 return Operand(ebp, -((register_index + 1) * sizeof(uint32_t))); |
| 376 } | 489 } |
| 377 | 490 |
| 378 | 491 |
| 492 size_t RegExpMacroAssemblerIA32::char_size() { | |
| 493 return static_cast<size_t>(mode_); | |
| 494 } | |
| 495 | |
| 496 | |
| 379 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, | 497 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, |
| 380 Label* to) { | 498 Label* to) { |
| 381 if (condition < 0) { // No condition | 499 if (condition < 0) { // No condition |
| 382 if (to == NULL) { | 500 if (to == NULL) { |
| 383 Backtrack(); | 501 Backtrack(); |
| 384 return; | 502 return; |
| 385 } | 503 } |
| 386 __ jmp(to); | 504 __ jmp(to); |
| 387 return; | 505 return; |
| 388 } else if (to == NULL) { | 506 } else if (to == NULL) { |
| 389 Label skip; | 507 Label skip; |
| 390 __ j(NegateCondition(condition), &skip); | 508 __ j(NegateCondition(condition), &skip); |
| 391 Backtrack(); | 509 Backtrack(); |
| 392 __ bind(&skip); | 510 __ bind(&skip); |
| 393 return; | 511 return; |
| 394 } | 512 } |
| 395 __ j(condition, to); | 513 __ j(condition, to); |
| 396 } | 514 } |
| 397 | 515 |
| 398 | 516 |
| 399 void RegExpMacroAssemblerIA32::Canonicalize(Register reg) { | 517 void RegExpMacroAssemblerIA32::Canonicalize(Register reg) { |
| 400 if (sizeof(SubjectChar) == 1) { | 518 if (mode_ == ASCII) { |
| 401 Label end; | 519 Label end; |
| 402 __ cmp(reg, 'a'); | 520 __ cmp(Operand(reg), Immediate('a')); |
| 403 __ j(below, &end); | 521 __ j(below, &end); |
| 404 __ cmp(reg, 'z'); | 522 __ cmp(Operand(reg), Immediate('z')); |
| 405 __ j(above, &end); | 523 __ j(above, &end); |
| 406 __ sub(reg, 'a' - 'A'); | 524 __ sub(Operand(reg), Immediate('a' - 'A')); |
| 407 __ bind(&end); | 525 __ bind(&end); |
| 408 return; | 526 return; |
| 409 } | 527 } |
| 410 ASSERT(sizeof(SubjectChar) == 2); | 528 ASSERT(mode_ == UC16); |
| 411 // TODO(lrn): Use some tables. | 529 // TODO(lrn): Use some tables. |
| 412 } | 530 } |
| 413 | 531 |
| 414 | 532 |
| 415 void RegExpMacroAssemblerIA32::Exit(bool success) { | 533 void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { |
| 416 if (success) { | 534 if (register_index >= num_registers_) { |
| 417 // Copy captures to output capture array. | 535 num_registers_ = register_index + 1; |
| 418 } | 536 } |
| 419 __ leave(); | |
| 420 __ mov(eax, success ? 1 : 0); | |
| 421 __ ret(); | |
| 422 } | 537 } |
| 423 | 538 |
| 424 | 539 |
| 425 void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { | 540 void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { |
| 426 if (sizeof(SubjectChar) == 1) { | 541 if (mode_ == ASCII) { |
| 427 __ movzx_b(destination, Operand(edi, offset)); | 542 __ movzx_b(destination, Operand(esi, edi, times_1, offset)); |
| 428 return; | 543 return; |
| 429 } | 544 } |
| 430 ASSERT(sizeof(SubjectChar) == 2); | 545 ASSERT(mode_ == UC16); |
| 431 __ movzx_w(destination, Operand(edi, offset * 2)); | 546 __ movzx_w(destination, Operand(esi, edi, times_1, offset * 2)); |
| 432 } | 547 } |
| 433 | 548 |
| 434 | 549 |
| 435 void RegExpMacroAssemblerIA32::ReadCurrentChar(Register destination) { | 550 void RegExpMacroAssemblerIA32::ReadCurrentChar(Register destination) { |
| 436 mov(destination, edx); | 551 __ mov(destination, edx); |
| 437 } | 552 } |
| 438 | 553 |
| 439 | 554 |
| 440 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress( | 555 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, |
| 441 Register reg, ArraySlice<T>* buffer) { | 556 ArraySlice* buffer) { |
| 442 __ mov(reg, buffer->array()); | 557 __ mov(reg, buffer->array()); |
| 443 __ add(reg, buffer->base_offset()); | 558 __ add(Operand(reg), Immediate(buffer->base_offset())); |
| 444 } | 559 } |
| 445 | 560 |
| 446 #undef __ | 561 #undef __ |
| 447 }} | 562 }} |
| OLD | NEW |