Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | |
| 2 // Redistribution and use in source and binary forms, with or without | |
| 3 // modification, are permitted provided that the following conditions are | |
| 4 // met: | |
| 5 // | |
| 6 // * Redistributions of source code must retain the above copyright | |
| 7 // notice, this list of conditions and the following disclaimer. | |
| 8 // * Redistributions in binary form must reproduce the above | |
| 9 // copyright notice, this list of conditions and the following | |
| 10 // disclaimer in the documentation and/or other materials provided | |
| 11 // with the distribution. | |
| 12 // * Neither the name of Google Inc. nor the names of its | |
| 13 // contributors may be used to endorse or promote products derived | |
| 14 // from this software without specific prior written permission. | |
| 15 // | |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 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. | |
| 27 | |
| 28 #include <string.h> | |
| 29 #include "v8.h" | |
| 30 #include "log.h" | |
| 31 #include "ast.h" | |
| 32 #include "macro-assembler.h" | |
| 33 #include "regexp-macro-assembler-ia32.h" | |
| 34 | |
| 35 namespace v8 { namespace internal { | |
| 36 /* | |
| 37 * This assembler uses the following register assignment convention | |
| 38 * - edx : current character, or kEndOfInput if current position is not | |
| 39 * inside string. The kEndOfInput value is greater than 0xffff, | |
| 40 * so any tests that don't check whether the current position | |
| 41 * is inside the correct range should retain bits above the | |
| 42 * 15th in their computations, and fail if the value is too | |
| 43 * great. | |
| 44 * - edi : current position in input, as negative offset from end of string. | |
| 45 * - esi : end of input (points to byte after last character in input). | |
| 46 * - ebp : points to the location above the registers on the stack, | |
| 47 * as if by the "enter <register_count>" opcode. | |
| 48 * - esp : points to tip of backtracking stack. | |
| 49 * | |
| 50 * The registers eax, ebx and ecx are free to use for computations. | |
| 51 * | |
| 52 * Each call to a public method should retain this convention. | |
| 53 * The stack will have the following structure: | |
| 54 * - int* capture_array (int[num_saved_registers_], for output). | |
| 55 * - end of input (index of end of string, relative to *string_base) | |
| 56 * - start of input (index of first character in string, relative | |
| 57 * to *string_base) | |
| 58 * - void** string_base (location of a handle containing the string) | |
| 59 * - return address | |
| 60 * - backup of esi | |
| 61 * - backup of edi | |
| 62 * ebp-> - old ebp | |
| 63 * - register 0 ebp[-4] | |
| 64 * - register 1 ebp[-8] | |
| 65 * - ... | |
| 66 * | |
| 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)(String** string_base, | |
| 70 * int start_offset, | |
| 71 * int end_offset, | |
| 72 * int* capture_output_array) | |
| 73 */ | |
| 74 | |
| 75 #define __ masm_-> | |
| 76 | |
| 77 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( | |
| 78 Mode mode, | |
| 79 int registers_to_save, | |
| 80 bool ignore_case) | |
| 81 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), | |
|
Mads Ager (chromium)
2008/11/25 21:09:41
Guess what? :-)
| |
| 82 constants_(kRegExpConstantsSize), | |
| 83 mode_(mode), | |
| 84 num_registers_(registers_to_save), | |
| 85 num_saved_registers_(registers_to_save), | |
| 86 ignore_case_(ignore_case), | |
| 87 entry_label_(), | |
| 88 start_label_(), | |
| 89 success_label_(), | |
| 90 exit_label_(), | |
| 91 self_(Heap::undefined_value()) { | |
| 92 __ jmp(&entry_label_); // We'll write the entry code later. | |
| 93 __ bind(&start_label_); // And then continue from here. | |
| 94 } | |
| 95 | |
| 96 | |
| 97 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { | |
| 98 delete masm_; | |
| 99 // Unuse labels in case we throw away the assembler without calling GetCode. | |
| 100 entry_label_.Unuse(); | |
| 101 start_label_.Unuse(); | |
| 102 success_label_.Unuse(); | |
| 103 exit_label_.Unuse(); | |
| 104 } | |
| 105 | |
| 106 | |
| 107 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { | |
| 108 ASSERT(by > 0); | |
| 109 Label inside_string; | |
| 110 __ add(Operand(edi), Immediate(by * char_size())); | |
| 111 __ j(below, &inside_string); | |
| 112 Backtrack(); | |
| 113 | |
| 114 __ bind(&inside_string); | |
| 115 } | |
| 116 | |
| 117 | |
| 118 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { | |
| 119 ASSERT(reg >= 0); | |
| 120 ASSERT(reg < num_registers_); | |
| 121 __ add(register_location(reg), Immediate(by)); | |
| 122 } | |
| 123 | |
| 124 | |
| 125 void RegExpMacroAssemblerIA32::Backtrack() { | |
| 126 __ pop(ecx); | |
| 127 __ add(Operand(ecx), Immediate(self_)); | |
| 128 __ jmp(Operand(ecx)); | |
| 129 } | |
| 130 | |
| 131 | |
| 132 void RegExpMacroAssemblerIA32::Bind(Label* label) { | |
| 133 __ bind(label); | |
| 134 } | |
| 135 | |
| 136 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, | |
| 137 Label* bitmap, | |
| 138 Label* on_zero) { | |
| 139 ReadCurrentChar(eax); | |
| 140 __ sub(Operand(eax), Immediate(start)); | |
| 141 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. | |
| 142 BranchOrBacktrack(greater_equal, on_zero); | |
| 143 __ mov(ebx, eax); | |
| 144 __ shr(ebx, 3); | |
| 145 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead. | |
| 146 // __ mov(ecx, position_of_bitmap); | |
| 147 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0)); | |
| 148 __ and_(eax, (1<<3)-1); | |
| 149 __ bt(Operand(ebx), eax); | |
| 150 __ j(carry, on_zero); | |
| 151 } | |
| 152 | |
| 153 | |
| 154 void RegExpMacroAssemblerIA32::CheckCharacter(uc16 c, Label* on_equal) { | |
| 155 __ cmp(edx, c); | |
| 156 BranchOrBacktrack(equal, on_equal); | |
| 157 } | |
| 158 | |
| 159 | |
| 160 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { | |
| 161 __ cmp(edx, limit); | |
| 162 BranchOrBacktrack(greater, on_greater); | |
| 163 } | |
| 164 | |
| 165 | |
| 166 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { | |
| 167 __ cmp(edx, limit); | |
| 168 BranchOrBacktrack(less, on_less); | |
| 169 } | |
| 170 | |
| 171 | |
| 172 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, | |
| 173 int cp_offset, | |
| 174 Label* on_failure) { | |
| 175 int byte_length = str.length() * char_size(); | |
| 176 int start_offset = cp_offset * char_size(); | |
| 177 __ mov(ebx, edi); | |
| 178 __ add(Operand(ebx), Immediate(start_offset + byte_length)); | |
| 179 BranchOrBacktrack(greater_equal, on_failure); | |
| 180 | |
| 181 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); | |
| 182 for (int i = 0; i < str.length(); i++) { | |
| 183 if (mode_ == ASCII) { | |
| 184 constant_buffer.at<char>(i) = static_cast<char>(str[i]); | |
| 185 } else { | |
| 186 memcpy(constant_buffer.location<void>(), | |
| 187 str.start(), | |
| 188 str.length() * sizeof(uc16)); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 __ mov(eax, edi); | |
| 193 __ mov(ebx, esi); | |
| 194 __ lea(edi, Operand(esi, edi, times_1, start_offset)); | |
| 195 LoadConstantBufferAddress(esi, &constant_buffer); | |
| 196 __ mov(ecx, str.length()); | |
| 197 if (mode_ == ASCII) { | |
| 198 __ rep_cmpsb(); | |
| 199 } else { | |
| 200 ASSERT(mode_ == UC16); | |
| 201 __ rep_cmpsw(); | |
| 202 } | |
| 203 __ mov(esi, ebx); | |
| 204 __ mov(edi, eax); | |
| 205 BranchOrBacktrack(not_equal, on_failure); | |
| 206 } | |
| 207 | |
| 208 | |
| 209 void RegExpMacroAssemblerIA32::CheckCurrentPosition(int register_index, | |
| 210 Label* on_equal) { | |
| 211 __ cmp(edi, register_location(register_index)); | |
| 212 BranchOrBacktrack(equal, on_equal); | |
| 213 } | |
| 214 | |
| 215 | |
| 216 void RegExpMacroAssemblerIA32::CheckNotBackReference( | |
| 217 int start_reg, Label* on_no_match) { | |
| 218 if (ignore_case_) { | |
| 219 UNIMPLEMENTED(); | |
| 220 } | |
| 221 Label fallthrough; | |
| 222 __ mov(eax, register_location(start_reg)); | |
| 223 __ mov(ecx, register_location(start_reg + 1)); | |
| 224 __ sub(ecx, Operand(eax)); // Length to check. | |
| 225 __ j(equal, &fallthrough); // Covers the case where it's not bound (-1,-1). | |
| 226 __ mov(ebx, Operand(edi)); | |
| 227 __ push(esi); | |
| 228 __ add(edi, Operand(esi)); | |
| 229 __ add(esi, Operand(eax)); | |
| 230 if (mode_ == ASCII) { | |
| 231 __ rep_cmpsb(); | |
| 232 } else { | |
| 233 __ rep_cmpsw(); | |
| 234 } | |
| 235 __ pop(esi); | |
| 236 __ mov(edi, Operand(ebx)); | |
| 237 BranchOrBacktrack(not_equal, on_no_match); | |
| 238 __ bind(&fallthrough); | |
| 239 } | |
| 240 | |
| 241 | |
| 242 void RegExpMacroAssemblerIA32::CheckNotCharacter(uc16 c, Label* on_not_equal) { | |
| 243 __ cmp(edx, c); | |
| 244 BranchOrBacktrack(not_equal, on_not_equal); | |
| 245 } | |
| 246 | |
| 247 | |
| 248 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterOr(uc16 c, | |
| 249 uc16 mask, | |
| 250 Label* on_not_equal) { | |
| 251 __ mov(eax, Operand(edx)); | |
| 252 __ or_(eax, mask); | |
| 253 __ cmp(eax, c); | |
| 254 BranchOrBacktrack(not_equal, on_not_equal); | |
| 255 } | |
| 256 | |
| 257 | |
| 258 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusOr( | |
| 259 uc16 c, | |
| 260 uc16 mask, | |
| 261 Label* on_not_equal) { | |
| 262 __ lea(eax, Operand(edx, -mask)); | |
| 263 __ or_(eax, mask); | |
| 264 __ cmp(eax, c); | |
| 265 BranchOrBacktrack(not_equal, on_not_equal); | |
| 266 } | |
| 267 | |
| 268 | |
| 269 void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap( | |
| 270 uc16 start, | |
| 271 Label* half_nibble_map, | |
| 272 const Vector<Label*>& destinations) { | |
| 273 ReadCurrentChar(eax); | |
| 274 __ sub(Operand(eax), Immediate(start)); | |
| 275 | |
| 276 __ mov(ecx, eax); | |
| 277 __ shr(eax, 2); | |
| 278 // FIXME: ecx must hold address of map | |
| 279 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | |
| 280 __ and_(ecx, 0x03); | |
| 281 __ add(ecx, Operand(ecx)); | |
| 282 __ shr(eax); // Shift right cl times | |
| 283 | |
| 284 Label second_bit_set, case_3, case_1; | |
| 285 __ test(eax, Immediate(0x02)); | |
| 286 __ j(not_zero, &second_bit_set); | |
| 287 __ test(eax, Immediate(0x01)); | |
| 288 __ j(not_zero, &case_1); | |
| 289 // Case 0: | |
| 290 __ jmp(destinations[0]); | |
| 291 __ bind(&case_1); | |
| 292 // Case 1: | |
| 293 __ jmp(destinations[1]); | |
| 294 __ bind(&second_bit_set); | |
| 295 __ test(eax, Immediate(0x01)); | |
| 296 __ j(not_zero, &case_3); | |
| 297 // Case 2 | |
| 298 __ jmp(destinations[2]); | |
| 299 __ bind(&case_3); | |
| 300 // Case 3: | |
| 301 __ jmp(destinations[3]); | |
| 302 } | |
| 303 | |
| 304 | |
| 305 void RegExpMacroAssemblerIA32::DispatchByteMap( | |
| 306 uc16 start, | |
| 307 Label* byte_map, | |
| 308 const Vector<Label*>& destinations) { | |
| 309 Label fallthrough; | |
| 310 ReadCurrentChar(eax); | |
| 311 __ sub(Operand(eax), Immediate(start)); | |
| 312 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? | |
| 313 __ j(greater_equal, &fallthrough); | |
| 314 // FIXME: ecx must hold address of map | |
| 315 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | |
| 316 // jump table: jump to destinations[eax]; | |
| 317 | |
| 318 __ bind(&fallthrough); | |
| 319 } | |
| 320 | |
| 321 | |
| 322 | |
| 323 void RegExpMacroAssemblerIA32::DispatchHighByteMap( | |
| 324 byte start, | |
| 325 Label* byte_map, | |
| 326 const Vector<Label*>& destinations) { | |
| 327 Label fallthrough; | |
| 328 ReadCurrentChar(eax); | |
| 329 __ shr(eax, 8); | |
| 330 __ sub(Operand(eax), Immediate(start)); | |
| 331 __ cmp(eax, destinations.length() - start); | |
| 332 __ j(greater_equal, &fallthrough); | |
| 333 | |
| 334 // TODO(lrn) jumptable: jump to destinations[eax] | |
| 335 __ bind(&fallthrough); | |
| 336 } | |
| 337 | |
| 338 | |
| 339 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { | |
| 340 UNREACHABLE(); // Has no use. | |
| 341 } | |
| 342 | |
| 343 | |
| 344 void RegExpMacroAssemblerIA32::Fail() { | |
| 345 __ mov(eax, 0); | |
| 346 __ jmp(&exit_label_); | |
| 347 } | |
| 348 | |
| 349 | |
| 350 Handle<Object> RegExpMacroAssemblerIA32::GetCode() { | |
| 351 // Finalize code - write the entry point code now we know how many | |
| 352 // registers we need. | |
| 353 | |
| 354 // Entry code: | |
| 355 __ bind(&entry_label_); | |
| 356 __ push(esi); | |
| 357 __ push(edi); | |
| 358 __ enter(Immediate(num_registers_ * sizeof(uint32_t))); | |
| 359 __ mov(esi, Operand(ebp, kInputEndOffset)); | |
| 360 __ mov(edi, Operand(ebp, kInputStartOffset)); | |
| 361 __ sub(edi, Operand(esi)); | |
| 362 __ mov(edx, Operand(ebp, kInputBuffer)); | |
| 363 __ mov(edx, Operand(edx, 0)); | |
| 364 __ add(esi, Operand(edx)); | |
| 365 __ jmp(&start_label_); | |
| 366 | |
| 367 // Exit code: | |
| 368 __ bind(&success_label_); | |
| 369 __ mov(ebx, Operand(ebp, kRegisterOutput)); | |
| 370 __ mov(ecx, Operand(ebp, kInputEndOffset)); | |
| 371 __ sub(ecx, Operand(ebp, kInputStartOffset)); | |
| 372 for (int i = 0; i < num_saved_registers_; i++) { | |
| 373 __ mov(eax, register_location(i)); | |
| 374 __ sub(eax, Operand(ecx)); // Convert to index from start, not end. | |
| 375 __ mov(Operand(ebx, i * sizeof(int32_t)), eax); | |
| 376 } | |
| 377 // copy captures to output | |
| 378 __ mov(eax, Immediate(1)); | |
| 379 | |
| 380 __ bind(&exit_label_); | |
| 381 __ leave(); | |
| 382 __ pop(edi); | |
| 383 __ pop(esi); | |
| 384 __ ret(0); | |
| 385 | |
| 386 CodeDesc code_desc; | |
| 387 masm_->GetCode(&code_desc); | |
| 388 Handle<Code> code = Factory::NewCode(code_desc, | |
| 389 NULL, | |
| 390 Code::ComputeFlags(Code::REGEXP), | |
| 391 self_); | |
| 392 LOG(CodeCreateEvent("RegExp", *code, "(Compiled RegExp)")); | |
| 393 return Handle<Object>::cast(code); | |
| 394 } | |
| 395 | |
| 396 | |
| 397 void RegExpMacroAssemblerIA32::GoTo(Label* to) { | |
| 398 __ jmp(to); | |
| 399 } | |
| 400 | |
| 401 | |
| 402 | |
| 403 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg, | |
| 404 int comparand, | |
| 405 Label* if_ge) { | |
| 406 __ cmp(register_location(reg), Immediate(comparand)); | |
| 407 BranchOrBacktrack(greater_equal, if_ge); | |
| 408 } | |
| 409 | |
| 410 | |
| 411 | |
| 412 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg, | |
| 413 int comparand, | |
| 414 Label* if_lt) { | |
| 415 __ cmp(register_location(reg), Immediate(comparand)); | |
| 416 BranchOrBacktrack(less, if_lt); | |
| 417 } | |
| 418 | |
| 419 | |
| 420 | |
| 421 RegExpMacroAssembler::IrregexpImplementation | |
| 422 RegExpMacroAssemblerIA32::Implementation() { | |
| 423 return kIA32Implementation; | |
| 424 } | |
| 425 | |
| 426 | |
| 427 | |
| 428 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, | |
| 429 Label* on_end_of_input) { | |
| 430 ASSERT(cp_offset >= 0); | |
| 431 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | |
| 432 __ cmp(edi, -cp_offset); | |
| 433 BranchOrBacktrack(less_equal, on_end_of_input); | |
| 434 ReadChar(edx, cp_offset); | |
| 435 } | |
| 436 | |
| 437 | |
| 438 void RegExpMacroAssemblerIA32::PopCurrentPosition() { | |
| 439 __ pop(edi); | |
| 440 } | |
| 441 | |
| 442 | |
| 443 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { | |
| 444 RecordRegister(register_index); | |
| 445 __ pop(register_location(register_index)); | |
| 446 } | |
| 447 | |
| 448 | |
| 449 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { | |
| 450 // Check for preemption first. | |
| 451 Label no_preempt; | |
| 452 Label retry_preempt; | |
| 453 // Check for preemption. | |
| 454 ExternalReference stack_limit = | |
| 455 ExternalReference::address_of_stack_guard_limit(); | |
| 456 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 457 __ j(above, &no_preempt); | |
| 458 | |
| 459 __ push(edi); // Current position. | |
| 460 __ push(edx); // Current character. | |
| 461 // Restore original edi, esi. | |
| 462 __ mov(edi, Operand(ebp, kBackup_edi)); | |
| 463 __ mov(esi, Operand(ebp, kBackup_esi)); | |
| 464 | |
| 465 __ bind(&retry_preempt); | |
| 466 // simulate stack for Runtime call. | |
| 467 __ push(Immediate(0)); // Dummy receiver | |
| 468 __ CallRuntime(Runtime::kStackGuard, 0); | |
| 469 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 470 __ j(below_equal, &retry_preempt); | |
| 471 | |
| 472 __ pop(edx); | |
| 473 __ pop(edi); | |
| 474 __ mov(esi, Operand(ebp, kInputBuffer)); | |
| 475 __ mov(esi, Operand(esi, 0)); | |
| 476 __ add(esi, Operand(ebp, kInputEndOffset)); | |
| 477 | |
| 478 __ bind(&no_preempt); | |
| 479 | |
| 480 Label cont; | |
| 481 __ push(label, RelocInfo::NONE); | |
| 482 } | |
| 483 | |
| 484 | |
| 485 void RegExpMacroAssemblerIA32::PushCurrentPosition() { | |
| 486 __ push(edi); | |
| 487 } | |
| 488 | |
| 489 | |
| 490 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { | |
| 491 __ push(register_location(register_index)); | |
| 492 } | |
| 493 | |
| 494 | |
| 495 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { | |
| 496 __ mov(edi, register_location(reg)); | |
| 497 } | |
| 498 | |
| 499 | |
| 500 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { | |
| 501 __ mov(esp, register_location(reg)); | |
| 502 } | |
| 503 | |
| 504 | |
| 505 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { | |
| 506 RecordRegister(register_index); | |
| 507 __ mov(register_location(register_index), Immediate(to)); | |
| 508 } | |
| 509 | |
| 510 | |
| 511 void RegExpMacroAssemblerIA32::Succeed() { | |
| 512 __ jmp(&success_label_); | |
| 513 } | |
| 514 | |
| 515 | |
| 516 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( | |
| 517 int register_index) { | |
| 518 __ mov(register_location(register_index), edi); | |
| 519 } | |
| 520 | |
| 521 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { | |
| 522 __ mov(register_location(reg), esp); | |
| 523 } | |
| 524 | |
| 525 | |
| 526 // Private methods: | |
| 527 | |
| 528 Operand RegExpMacroAssemblerIA32::register_location( | |
| 529 int register_index) { | |
| 530 ASSERT(register_index < (1<<30)); | |
| 531 return Operand(ebp, -((register_index + 1) * sizeof(uint32_t))); | |
| 532 } | |
| 533 | |
| 534 | |
| 535 size_t RegExpMacroAssemblerIA32::char_size() { | |
| 536 return static_cast<size_t>(mode_); | |
| 537 } | |
| 538 | |
| 539 | |
| 540 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, | |
| 541 Label* to) { | |
| 542 if (condition < 0) { // No condition | |
| 543 if (to == NULL) { | |
| 544 Backtrack(); | |
| 545 return; | |
| 546 } | |
| 547 __ jmp(to); | |
| 548 return; | |
| 549 } else if (to == NULL) { | |
| 550 Label skip; | |
| 551 __ j(NegateCondition(condition), &skip); | |
| 552 Backtrack(); | |
| 553 __ bind(&skip); | |
| 554 return; | |
| 555 } | |
| 556 __ j(condition, to); | |
| 557 } | |
| 558 | |
| 559 | |
| 560 void RegExpMacroAssemblerIA32::Canonicalize(Register reg) { | |
| 561 if (mode_ == ASCII) { | |
| 562 Label end; | |
| 563 __ cmp(Operand(reg), Immediate('a')); | |
| 564 __ j(below, &end); | |
| 565 __ cmp(Operand(reg), Immediate('z')); | |
| 566 __ j(above, &end); | |
| 567 __ sub(Operand(reg), Immediate('a' - 'A')); | |
| 568 __ bind(&end); | |
| 569 return; | |
| 570 } | |
| 571 ASSERT(mode_ == UC16); | |
| 572 // TODO(lrn): Use some tables. | |
| 573 } | |
| 574 | |
| 575 | |
| 576 void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { | |
| 577 if (register_index >= num_registers_) { | |
| 578 num_registers_ = register_index + 1; | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 | |
| 583 void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { | |
| 584 if (mode_ == ASCII) { | |
| 585 __ movzx_b(destination, Operand(esi, edi, times_1, offset)); | |
| 586 return; | |
| 587 } | |
| 588 ASSERT(mode_ == UC16); | |
| 589 __ movzx_w(destination, Operand(esi, edi, times_1, offset * 2)); | |
| 590 } | |
| 591 | |
| 592 | |
| 593 void RegExpMacroAssemblerIA32::ReadCurrentChar(Register destination) { | |
| 594 __ mov(destination, edx); | |
| 595 } | |
| 596 | |
| 597 | |
| 598 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, | |
| 599 ArraySlice* buffer) { | |
| 600 __ mov(reg, buffer->array()); | |
| 601 __ add(Operand(reg), Immediate(buffer->base_offset())); | |
| 602 } | |
| 603 | |
| 604 #undef __ | |
| 605 }} | |
| OLD | NEW |