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 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #include <string.h> | 28 #include <string.h> |
| 29 #include "v8.h" | 29 #include "v8.h" |
| 30 #include "log.h" | 30 #include "log.h" |
| 31 #include "ast.h" | 31 #include "ast.h" |
| 32 #include "macro-assembler.h" | 32 #include "macro-assembler.h" |
| 33 #include "regexp-macro-assembler-ia32.h" | 33 #include "regexp-macro-assembler-ia32.h" |
| 34 | 34 |
| 35 namespace v8 { namespace internal { | 35 namespace v8 { namespace internal { |
| 36 /* | 36 /* |
| 37 * This assembler uses the following register assignment convention | 37 * This assembler uses the following register assignment convention |
| 38 * - edx : current character, or kEndOfInput if current position is not | 38 * - edx : current character. Must be loaded using LoadCurrentCharacter |
| 39 * inside string. The kEndOfInput value is greater than 0xffff, | 39 * before using any of the dispatch methods. |
| 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. | 40 * - edi : current position in input, as negative offset from end of string. |
| 41 * NOTICE: This is the byte offset, not the character offset! | |
|
Erik Corry
2008/11/25 12:39:11
No shouting :-)
| |
| 45 * - esi : end of input (points to byte after last character in input). | 42 * - esi : end of input (points to byte after last character in input). |
| 46 * - ebp : points to the location above the registers on the stack, | 43 * - ebp : points to the location above the registers on the stack, |
| 47 * as if by the "enter <register_count>" opcode. | 44 * as if by the "enter <register_count>" opcode. |
| 48 * - esp : points to tip of backtracking stack. | 45 * - esp : points to tip of backtracking stack. |
| 49 * | 46 * |
| 50 * The registers eax, ebx and ecx are free to use for computations. | 47 * The registers eax, ebx and ecx are free to use for computations. |
| 51 * | 48 * |
| 52 * Each call to a public method should retain this convention. | 49 * Each call to a public method should retain this convention. |
| 53 * The stack will have the following structure: | 50 * The stack will have the following structure: |
| 54 * - int* capture_array (int[num_saved_registers_], for output). | 51 * - int* capture_array (int[num_saved_registers_], for output). |
| 55 * - end of input (index of end of string, relative to *string_base) | 52 * - end of input (index of end of string, relative to *string_base) |
| 56 * - start of input (index of first character in string, relative | 53 * - start of input (index of first character in string, relative |
| 57 * to *string_base) | 54 * to *string_base) |
| 58 * - void** string_base (location of a handle containing the string) | 55 * - void** string_base (location of a handle containing the string) |
| 59 * - return address | 56 * - return address |
| 60 * - backup of esi | 57 * - backup of esi |
| 61 * - backup of edi | 58 * - backup of edi |
| 62 * ebp-> - old ebp | 59 * ebp-> - old ebp |
| 63 * - register 0 ebp[-4] | 60 * - register 0 ebp[-4] (Only positions must be stored in the first |
| 64 * - register 1 ebp[-8] | 61 * - register 1 ebp[-8] num_saved_registers_ registers) |
| 65 * - ... | 62 * - ... |
| 66 * | 63 * |
| 67 * The data before ebp must be placed there by the calling code, e.g., | 64 * The first num_saved_registers_ registers are initialized to point to |
| 68 * by calling the code as cast to: | 65 * "character -1" in the string (i.e., char_size() bytes before the first |
| 66 * character of the string). The remaining registers are starts out as garbage. | |
|
Erik Corry
2008/11/25 12:39:11
this sentence are not parse
| |
| 67 * | |
| 68 * The data up to the return address must be placed there by the calling | |
| 69 * code, e.g., by calling the code as cast to: | |
| 69 * bool (*match)(String** string_base, | 70 * bool (*match)(String** string_base, |
| 70 * int start_offset, | 71 * int start_offset, |
| 71 * int end_offset, | 72 * int end_offset, |
| 72 * int* capture_output_array) | 73 * int* capture_output_array) |
| 73 */ | 74 */ |
| 74 | 75 |
| 75 #define __ masm_-> | 76 #define __ masm_-> |
| 76 | 77 |
| 77 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( | 78 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( |
| 78 Mode mode, | 79 Mode mode, |
| 79 int registers_to_save, | 80 int registers_to_save, |
| 80 bool ignore_case) | 81 bool ignore_case) |
|
Erik Corry
2008/11/25 12:39:11
ignore_case is unused and likely to remain so.
Lasse Reichstein
2008/11/25 13:05:47
I see that the CheckNotBackReferenceCaseIndependen
| |
| 81 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), | 82 : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), |
| 82 constants_(kRegExpConstantsSize), | 83 constants_(kRegExpConstantsSize), |
| 83 mode_(mode), | 84 mode_(mode), |
| 84 num_registers_(registers_to_save), | 85 num_registers_(registers_to_save), |
| 85 num_saved_registers_(registers_to_save), | 86 num_saved_registers_(registers_to_save), |
| 86 ignore_case_(ignore_case), | 87 ignore_case_(ignore_case), |
| 87 entry_label_(), | 88 entry_label_(), |
| 88 start_label_(), | 89 start_label_(), |
| 89 success_label_(), | 90 success_label_(), |
| 90 exit_label_(), | 91 exit_label_(), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 101 start_label_.Unuse(); | 102 start_label_.Unuse(); |
| 102 success_label_.Unuse(); | 103 success_label_.Unuse(); |
| 103 exit_label_.Unuse(); | 104 exit_label_.Unuse(); |
| 104 } | 105 } |
| 105 | 106 |
| 106 | 107 |
| 107 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { | 108 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { |
| 108 ASSERT(by > 0); | 109 ASSERT(by > 0); |
| 109 Label inside_string; | 110 Label inside_string; |
| 110 __ add(Operand(edi), Immediate(by * char_size())); | 111 __ add(Operand(edi), Immediate(by * char_size())); |
| 111 __ j(below, &inside_string); | |
| 112 Backtrack(); | |
| 113 | |
| 114 __ bind(&inside_string); | |
| 115 } | 112 } |
| 116 | 113 |
| 117 | 114 |
| 118 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { | 115 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { |
| 119 ASSERT(reg >= 0); | 116 ASSERT(reg >= 0); |
| 120 ASSERT(reg < num_registers_); | 117 ASSERT(reg < num_registers_); |
| 121 __ add(register_location(reg), Immediate(by)); | 118 __ add(register_location(reg), Immediate(by)); |
| 122 } | 119 } |
| 123 | 120 |
| 124 | 121 |
| 125 void RegExpMacroAssemblerIA32::Backtrack() { | 122 void RegExpMacroAssemblerIA32::Backtrack() { |
| 126 __ pop(ecx); | 123 __ pop(ecx); |
| 127 __ add(Operand(ecx), Immediate(self_)); | 124 __ add(Operand(ecx), Immediate(self_)); |
| 128 __ jmp(Operand(ecx)); | 125 __ jmp(Operand(ecx)); |
| 129 } | 126 } |
| 130 | 127 |
| 131 | 128 |
| 132 void RegExpMacroAssemblerIA32::Bind(Label* label) { | 129 void RegExpMacroAssemblerIA32::Bind(Label* label) { |
| 133 __ bind(label); | 130 __ bind(label); |
| 134 } | 131 } |
| 135 | 132 |
| 136 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, | 133 void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start, |
| 137 Label* bitmap, | 134 Label* bitmap, |
| 138 Label* on_zero) { | 135 Label* on_zero) { |
| 136 UNREACHABLE(); | |
| 139 ReadCurrentChar(eax); | 137 ReadCurrentChar(eax); |
| 140 __ sub(Operand(eax), Immediate(start)); | 138 __ sub(Operand(eax), Immediate(start)); |
| 141 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. | 139 __ cmp(eax, 64); // FIXME: 64 = length_of_bitmap_in_bits. |
| 142 BranchOrBacktrack(greater_equal, on_zero); | 140 BranchOrBacktrack(greater_equal, on_zero); |
| 143 __ mov(ebx, eax); | 141 __ mov(ebx, eax); |
| 144 __ shr(ebx, 3); | 142 __ shr(ebx, 3); |
| 145 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead. | 143 // TODO(lrn): Where is the bitmap stored? Pass the bitmap as argument instead. |
| 146 // __ mov(ecx, position_of_bitmap); | 144 // __ mov(ecx, position_of_bitmap); |
| 147 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0)); | 145 __ movzx_b(ebx, Operand(ecx, ebx, times_1, 0)); |
| 148 __ and_(eax, (1<<3)-1); | 146 __ and_(eax, (1<<3)-1); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 166 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { | 164 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { |
| 167 __ cmp(edx, limit); | 165 __ cmp(edx, limit); |
| 168 BranchOrBacktrack(less, on_less); | 166 BranchOrBacktrack(less, on_less); |
| 169 } | 167 } |
| 170 | 168 |
| 171 | 169 |
| 172 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, | 170 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, |
| 173 int cp_offset, | 171 int cp_offset, |
| 174 Label* on_failure) { | 172 Label* on_failure) { |
| 175 int byte_length = str.length() * char_size(); | 173 int byte_length = str.length() * char_size(); |
| 176 int start_offset = cp_offset * char_size(); | 174 int byte_offset = cp_offset * char_size(); |
| 177 __ mov(ebx, edi); | 175 __ mov(ebx, edi); |
| 178 __ add(Operand(ebx), Immediate(start_offset + byte_length)); | 176 __ add(Operand(ebx), Immediate(byte_offset + byte_length)); |
| 179 BranchOrBacktrack(greater_equal, on_failure); | 177 BranchOrBacktrack(greater_equal, on_failure); |
| 180 | 178 |
| 181 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); | 179 ArraySlice constant_buffer = constants_.GetBuffer(str.length(), char_size()); |
| 182 for (int i = 0; i < str.length(); i++) { | 180 if (mode_ == ASCII) { |
| 183 if (mode_ == ASCII) { | 181 for (int i = 0; i < str.length(); i++) { |
| 184 constant_buffer.at<char>(i) = static_cast<char>(str[i]); | 182 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 } | 183 } |
| 184 } else { | |
| 185 memcpy(constant_buffer.location<void>(), | |
| 186 str.start(), | |
| 187 str.length() * sizeof(uc16)); | |
| 190 } | 188 } |
| 191 | 189 |
| 192 __ mov(eax, edi); | 190 __ mov(eax, edi); |
| 193 __ mov(ebx, esi); | 191 __ mov(ebx, esi); |
| 194 __ lea(edi, Operand(esi, edi, times_1, start_offset)); | 192 __ lea(edi, Operand(esi, edi, times_1, byte_offset)); |
| 195 LoadConstantBufferAddress(esi, &constant_buffer); | 193 LoadConstantBufferAddress(esi, &constant_buffer); |
| 196 __ mov(ecx, str.length()); | 194 __ mov(ecx, str.length()); |
| 197 if (mode_ == ASCII) { | 195 if (mode_ == ASCII) { |
| 198 __ rep_cmpsb(); | 196 __ rep_cmpsb(); |
| 199 } else { | 197 } else { |
| 200 ASSERT(mode_ == UC16); | 198 ASSERT(mode_ == UC16); |
| 201 __ rep_cmpsw(); | 199 __ rep_cmpsw(); |
| 202 } | 200 } |
| 203 __ mov(esi, ebx); | 201 __ mov(esi, ebx); |
| 204 __ mov(edi, eax); | 202 __ mov(edi, eax); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 307 | 305 |
| 308 void RegExpMacroAssemblerIA32::DispatchByteMap( | 306 void RegExpMacroAssemblerIA32::DispatchByteMap( |
| 309 uc16 start, | 307 uc16 start, |
| 310 Label* byte_map, | 308 Label* byte_map, |
| 311 const Vector<Label*>& destinations) { | 309 const Vector<Label*>& destinations) { |
| 312 Label fallthrough; | 310 Label fallthrough; |
| 313 ReadCurrentChar(eax); | 311 ReadCurrentChar(eax); |
| 314 __ sub(Operand(eax), Immediate(start)); | 312 __ sub(Operand(eax), Immediate(start)); |
| 315 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? | 313 __ cmp(eax, 64); // FIXME: 64 = size of map. Found somehow?? |
| 316 __ j(greater_equal, &fallthrough); | 314 __ j(greater_equal, &fallthrough); |
| 317 // FIXME: ecx must hold address of map | 315 // TODO(lrn): ecx must hold address of map |
| 318 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); | 316 __ movzx_b(eax, Operand(ecx, eax, times_1, 0)); |
| 319 // jump table: jump to destinations[eax]; | 317 // jump table: jump to destinations[eax]; |
| 320 | 318 |
| 321 __ bind(&fallthrough); | 319 __ bind(&fallthrough); |
| 322 } | 320 } |
| 323 | 321 |
| 324 | 322 |
| 325 | 323 |
| 326 void RegExpMacroAssemblerIA32::DispatchHighByteMap( | 324 void RegExpMacroAssemblerIA32::DispatchHighByteMap( |
| 327 byte start, | 325 byte start, |
| 328 Label* byte_map, | 326 Label* byte_map, |
| 329 const Vector<Label*>& destinations) { | 327 const Vector<Label*>& destinations) { |
| 328 UNREACHABLE(); | |
| 329 | |
| 330 Label fallthrough; | 330 Label fallthrough; |
| 331 ReadCurrentChar(eax); | 331 ReadCurrentChar(eax); |
| 332 __ shr(eax, 8); | 332 __ shr(eax, 8); |
| 333 __ sub(Operand(eax), Immediate(start)); | 333 __ sub(Operand(eax), Immediate(start)); |
| 334 __ cmp(eax, destinations.length() - start); | 334 __ cmp(eax, destinations.length() - start); |
| 335 __ j(greater_equal, &fallthrough); | 335 __ j(greater_equal, &fallthrough); |
| 336 | 336 |
| 337 // TODO(lrn) jumptable: jump to destinations[eax] | 337 // TODO(lrn) jumptable: jump to destinations[eax] |
| 338 __ bind(&fallthrough); | 338 __ bind(&fallthrough); |
| 339 } | 339 } |
| 340 | 340 |
| 341 | 341 |
| 342 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { | 342 void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) { |
| 343 UNREACHABLE(); // Has no use. | 343 UNREACHABLE(); // Has no use. |
| 344 } | 344 } |
| 345 | 345 |
| 346 | 346 |
| 347 void RegExpMacroAssemblerIA32::Fail() { | 347 void RegExpMacroAssemblerIA32::Fail() { |
| 348 __ mov(eax, 0); | 348 __ xor_(eax, Operand(eax)); // zero eax. |
| 349 __ jmp(&exit_label_); | 349 __ jmp(&exit_label_); |
| 350 } | 350 } |
| 351 | 351 |
| 352 | 352 |
| 353 Handle<Object> RegExpMacroAssemblerIA32::GetCode() { | 353 Handle<Object> RegExpMacroAssemblerIA32::GetCode() { |
| 354 // Finalize code - write the entry point code now we know how many | 354 // Finalize code - write the entry point code now we know how many |
| 355 // registers we need. | 355 // registers we need. |
| 356 | 356 |
| 357 // Entry code: | 357 // Entry code: |
| 358 __ bind(&entry_label_); | 358 __ bind(&entry_label_); |
| 359 __ push(esi); | 359 __ push(esi); |
| 360 __ push(edi); | 360 __ push(edi); |
| 361 __ enter(Immediate(num_registers_ * sizeof(uint32_t))); | 361 __ enter(Immediate(num_registers_ * sizeof(uint32_t))); |
| 362 __ mov(esi, Operand(ebp, kInputEndOffset)); | 362 __ mov(esi, Operand(ebp, kInputEndOffset)); |
| 363 __ mov(edi, Operand(ebp, kInputStartOffset)); | 363 __ mov(edi, Operand(ebp, kInputStartOffset)); |
| 364 __ sub(edi, Operand(esi)); | 364 __ sub(edi, Operand(esi)); |
| 365 __ mov(edx, Operand(ebp, kInputBuffer)); | 365 __ mov(edx, Operand(ebp, kInputBuffer)); |
| 366 __ mov(edx, Operand(edx, 0)); | 366 __ mov(edx, Operand(edx, 0)); |
| 367 __ add(esi, Operand(edx)); | 367 __ add(esi, Operand(edx)); |
| 368 if (num_saved_registers_ > 0) { | |
| 369 // Fill saved registers with initial value = start offset - 1 | |
| 370 __ mov(ecx, -num_saved_registers_); | |
| 371 __ mov(eax, Operand(edi)); | |
| 372 if (char_size() == 1) { | |
| 373 __ dec(eax); | |
|
Erik Corry
2008/11/25 12:39:11
I think dec is deprecated for performance reasons
| |
| 374 } else { | |
| 375 __ sub(Operand(eax), Immediate(2)); | |
| 376 } | |
| 377 Label init_loop; | |
| 378 __ bind(&init_loop); | |
| 379 __ mov(Operand(ebp, ecx, times_4, +0), eax); | |
| 380 __ inc(ecx); | |
| 381 __ j(not_equal, &init_loop); | |
| 382 } | |
| 368 __ jmp(&start_label_); | 383 __ jmp(&start_label_); |
| 369 | 384 |
| 370 // Exit code: | 385 // Exit code: |
| 371 __ bind(&success_label_); | 386 __ bind(&success_label_); |
| 372 __ mov(ebx, Operand(ebp, kRegisterOutput)); | 387 if (num_saved_registers_ > 0) { |
| 373 __ mov(ecx, Operand(ebp, kInputEndOffset)); | 388 // copy captures to output |
| 374 __ sub(ecx, Operand(ebp, kInputStartOffset)); | 389 __ mov(ebx, Operand(ebp, kRegisterOutput)); |
| 375 for (int i = 0; i < num_saved_registers_; i++) { | 390 __ mov(ecx, Operand(ebp, kInputEndOffset)); |
| 376 __ mov(eax, register_location(i)); | 391 __ sub(ecx, Operand(ebp, kInputStartOffset)); |
| 377 __ sub(eax, Operand(ecx)); // Convert to index from start, not end. | 392 for (int i = 0; i < num_saved_registers_; i++) { |
| 378 __ mov(Operand(ebx, i * sizeof(int32_t)), eax); | 393 __ mov(eax, register_location(i)); |
| 394 __ add(eax, Operand(ecx)); // Convert to index from start, not end. | |
| 395 if (char_size() == 2) { | |
| 396 __ shr(eax); | |
| 397 } | |
| 398 __ mov(Operand(ebx, i * sizeof(int32_t)), eax); | |
| 399 } | |
| 379 } | 400 } |
| 380 // copy captures to output | |
| 381 __ mov(eax, Immediate(1)); | 401 __ mov(eax, Immediate(1)); |
| 382 | 402 |
| 383 __ bind(&exit_label_); | 403 __ bind(&exit_label_); |
| 384 __ leave(); | 404 __ leave(); |
| 385 __ pop(edi); | 405 __ pop(edi); |
| 386 __ pop(esi); | 406 __ pop(esi); |
| 387 __ ret(0); | 407 __ ret(0); |
| 388 | 408 |
| 389 CodeDesc code_desc; | 409 CodeDesc code_desc; |
| 390 masm_->GetCode(&code_desc); | 410 masm_->GetCode(&code_desc); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 RegExpMacroAssemblerIA32::Implementation() { | 445 RegExpMacroAssemblerIA32::Implementation() { |
| 426 return kIA32Implementation; | 446 return kIA32Implementation; |
| 427 } | 447 } |
| 428 | 448 |
| 429 | 449 |
| 430 | 450 |
| 431 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, | 451 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, |
| 432 Label* on_end_of_input) { | 452 Label* on_end_of_input) { |
| 433 ASSERT(cp_offset >= 0); | 453 ASSERT(cp_offset >= 0); |
| 434 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 454 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
| 435 __ cmp(edi, -cp_offset); | 455 __ cmp(edi, -cp_offset * char_size()); |
| 436 BranchOrBacktrack(less_equal, on_end_of_input); | 456 BranchOrBacktrack(greater_equal, on_end_of_input); |
| 437 ReadChar(edx, cp_offset); | 457 ReadChar(edx, cp_offset); |
| 438 } | 458 } |
| 439 | 459 |
| 440 | 460 |
| 441 void RegExpMacroAssemblerIA32::PopCurrentPosition() { | 461 void RegExpMacroAssemblerIA32::PopCurrentPosition() { |
| 442 __ pop(edi); | 462 __ pop(edi); |
| 443 } | 463 } |
| 444 | 464 |
| 445 | 465 |
| 446 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { | 466 void RegExpMacroAssemblerIA32::PopRegister(int register_index) { |
| 447 RecordRegister(register_index); | 467 RecordRegister(register_index); |
| 448 __ pop(register_location(register_index)); | 468 __ pop(register_location(register_index)); |
| 449 } | 469 } |
| 450 | 470 |
| 451 | 471 |
| 452 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { | 472 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { |
| 453 // Check for preemption first. | 473 // CheckStackLimit(); // Not ready yet. |
| 454 Label no_preempt; | |
| 455 Label retry_preempt; | |
| 456 // Check for preemption. | |
| 457 ExternalReference stack_limit = | |
| 458 ExternalReference::address_of_stack_guard_limit(); | |
| 459 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 460 __ j(above, &no_preempt); | |
| 461 | |
| 462 __ push(edi); // Current position. | |
| 463 __ push(edx); // Current character. | |
| 464 // Restore original edi, esi. | |
| 465 __ mov(edi, Operand(ebp, kBackup_edi)); | |
| 466 __ mov(esi, Operand(ebp, kBackup_esi)); | |
| 467 | |
| 468 __ bind(&retry_preempt); | |
| 469 // simulate stack for Runtime call. | |
| 470 __ push(Immediate(0)); // Dummy receiver | |
| 471 __ CallRuntime(Runtime::kStackGuard, 0); | |
| 472 __ cmp(esp, Operand::StaticVariable(stack_limit)); | |
| 473 __ j(below_equal, &retry_preempt); | |
| 474 | |
| 475 __ pop(edx); | |
| 476 __ pop(edi); | |
| 477 __ mov(esi, Operand(ebp, kInputBuffer)); | |
| 478 __ mov(esi, Operand(esi, 0)); | |
| 479 __ add(esi, Operand(ebp, kInputEndOffset)); | |
| 480 | |
| 481 __ bind(&no_preempt); | |
| 482 | |
| 483 Label cont; | |
| 484 __ push(label, RelocInfo::NONE); | 474 __ push(label, RelocInfo::NONE); |
| 485 } | 475 } |
| 486 | 476 |
| 487 | 477 |
| 488 void RegExpMacroAssemblerIA32::PushCurrentPosition() { | 478 void RegExpMacroAssemblerIA32::PushCurrentPosition() { |
| 489 __ push(edi); | 479 __ push(edi); |
| 490 } | 480 } |
| 491 | 481 |
| 492 | 482 |
| 493 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { | 483 void RegExpMacroAssemblerIA32::PushRegister(int register_index) { |
| 494 __ push(register_location(register_index)); | 484 __ push(register_location(register_index)); |
| 495 } | 485 } |
| 496 | 486 |
| 497 | 487 |
| 498 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { | 488 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { |
| 499 __ mov(edi, register_location(reg)); | 489 __ mov(edi, register_location(reg)); |
| 500 } | 490 } |
| 501 | 491 |
| 502 | 492 |
| 503 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { | 493 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { |
| 504 __ mov(esp, register_location(reg)); | 494 __ mov(esp, register_location(reg)); |
| 505 } | 495 } |
| 506 | 496 |
| 507 | 497 |
| 508 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { | 498 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { |
| 499 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | |
|
Erik Corry
2008/11/25 12:39:11
We might want to use this instruction on capture p
Lasse Reichstein
2008/11/25 13:05:47
It won't work for positions, as currently implemen
| |
| 509 RecordRegister(register_index); | 500 RecordRegister(register_index); |
| 510 __ mov(register_location(register_index), Immediate(to)); | 501 __ mov(register_location(register_index), Immediate(to)); |
| 511 } | 502 } |
| 512 | 503 |
| 513 | 504 |
| 514 void RegExpMacroAssemblerIA32::Succeed() { | 505 void RegExpMacroAssemblerIA32::Succeed() { |
| 515 __ jmp(&success_label_); | 506 __ jmp(&success_label_); |
| 516 } | 507 } |
| 517 | 508 |
| 518 | 509 |
| 519 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( | 510 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister( |
| 520 int register_index) { | 511 int register_index) { |
| 512 RecordRegister(register_index); | |
| 521 __ mov(register_location(register_index), edi); | 513 __ mov(register_location(register_index), edi); |
| 522 } | 514 } |
| 523 | 515 |
| 524 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { | 516 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { |
| 525 __ mov(register_location(reg), esp); | 517 __ mov(register_location(reg), esp); |
| 526 } | 518 } |
| 527 | 519 |
| 528 | 520 |
| 529 // Private methods: | 521 // Private methods: |
| 530 | 522 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 542 | 534 |
| 543 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, | 535 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, |
| 544 Label* to) { | 536 Label* to) { |
| 545 if (condition < 0) { // No condition | 537 if (condition < 0) { // No condition |
| 546 if (to == NULL) { | 538 if (to == NULL) { |
| 547 Backtrack(); | 539 Backtrack(); |
| 548 return; | 540 return; |
| 549 } | 541 } |
| 550 __ jmp(to); | 542 __ jmp(to); |
| 551 return; | 543 return; |
| 552 } else if (to == NULL) { | 544 } |
| 545 if (to == NULL) { | |
| 553 Label skip; | 546 Label skip; |
| 554 __ j(NegateCondition(condition), &skip); | 547 __ j(NegateCondition(condition), &skip); |
| 555 Backtrack(); | 548 Backtrack(); |
| 556 __ bind(&skip); | 549 __ bind(&skip); |
| 557 return; | 550 return; |
| 558 } | 551 } |
| 559 __ j(condition, to); | 552 __ j(condition, to); |
| 560 } | 553 } |
| 561 | 554 |
| 562 | 555 |
| 563 void RegExpMacroAssemblerIA32::Canonicalize(Register reg) { | 556 void RegExpMacroAssemblerIA32::Canonicalize(Register reg) { |
| 564 if (mode_ == ASCII) { | 557 if (mode_ == ASCII) { |
| 565 Label end; | 558 Label end; |
| 566 __ cmp(Operand(reg), Immediate('a')); | 559 __ cmp(Operand(reg), Immediate('a')); |
| 567 __ j(below, &end); | 560 __ j(below, &end); |
| 568 __ cmp(Operand(reg), Immediate('z')); | 561 __ cmp(Operand(reg), Immediate('z')); |
| 569 __ j(above, &end); | 562 __ j(above, &end); |
| 570 __ sub(Operand(reg), Immediate('a' - 'A')); | 563 __ sub(Operand(reg), Immediate('a' - 'A')); |
| 571 __ bind(&end); | 564 __ bind(&end); |
| 572 return; | 565 return; |
| 573 } | 566 } |
| 574 ASSERT(mode_ == UC16); | 567 ASSERT(mode_ == UC16); |
| 575 // TODO(lrn): Use some tables. | 568 // TODO(lrn): Use some tables. |
| 576 } | 569 } |
| 577 | 570 |
| 578 | 571 |
| 572 void RegExpMacroAssemblerIA32::CheckStackLimit() { | |
| 573 if (FLAG_check_stack) { | |
| 574 // Check for preemption first. | |
| 575 Label no_preempt; | |
| 576 Label retry_preempt; | |
| 577 // Check for preemption. | |
| 578 ExternalReference stack_guard_limit = | |
| 579 ExternalReference::address_of_stack_guard_limit(); | |
| 580 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | |
| 581 __ j(above, &no_preempt, taken); | |
|
Erik Corry
2008/11/25 12:39:11
This needs to be moved out of line at some point (
| |
| 582 | |
| 583 __ push(edi); // Current position. | |
| 584 __ push(edx); // Current character. | |
| 585 // Restore original edi, esi. | |
| 586 __ mov(edi, Operand(ebp, kBackup_edi)); | |
| 587 __ mov(esi, Operand(ebp, kBackup_esi)); | |
| 588 | |
| 589 __ bind(&retry_preempt); | |
| 590 // simulate stack for Runtime call. | |
| 591 __ push(eax); | |
| 592 __ push(Immediate(Smi::FromInt(0))); // Dummy receiver | |
| 593 __ CallRuntime(Runtime::kStackGuard, 1); | |
| 594 __ pop(eax); | |
| 595 | |
| 596 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); | |
| 597 __ j(below_equal, &retry_preempt); | |
| 598 | |
| 599 __ pop(edx); | |
| 600 __ pop(edi); | |
| 601 __ mov(esi, Operand(ebp, kInputBuffer)); | |
| 602 __ mov(esi, Operand(esi, 0)); | |
| 603 __ add(esi, Operand(ebp, kInputEndOffset)); | |
| 604 | |
| 605 __ bind(&no_preempt); | |
| 606 } | |
| 607 } | |
| 608 | |
| 609 | |
| 579 void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { | 610 void RegExpMacroAssemblerIA32::RecordRegister(int register_index) { |
| 580 if (register_index >= num_registers_) { | 611 if (register_index >= num_registers_) { |
| 581 num_registers_ = register_index + 1; | 612 num_registers_ = register_index + 1; |
| 582 } | 613 } |
| 583 } | 614 } |
| 584 | 615 |
| 585 | 616 |
| 586 void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { | 617 void RegExpMacroAssemblerIA32::ReadChar(Register destination, int offset) { |
| 587 if (mode_ == ASCII) { | 618 if (mode_ == ASCII) { |
| 588 __ movzx_b(destination, Operand(esi, edi, times_1, offset)); | 619 __ movzx_b(destination, Operand(esi, edi, times_1, offset)); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 599 | 630 |
| 600 | 631 |
| 601 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, | 632 void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg, |
| 602 ArraySlice* buffer) { | 633 ArraySlice* buffer) { |
| 603 __ mov(reg, buffer->array()); | 634 __ mov(reg, buffer->array()); |
| 604 __ add(Operand(reg), Immediate(buffer->base_offset())); | 635 __ add(Operand(reg), Immediate(buffer->base_offset())); |
| 605 } | 636 } |
| 606 | 637 |
| 607 #undef __ | 638 #undef __ |
| 608 }} | 639 }} |
| OLD | NEW |