| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 __ cmpq(r9, rbx); | 322 __ cmpq(r9, rbx); |
| 323 __ j(below, &loop); | 323 __ j(below, &loop); |
| 324 | 324 |
| 325 // Compute new value of character position after the matched part. | 325 // Compute new value of character position after the matched part. |
| 326 __ movq(rdi, r11); | 326 __ movq(rdi, r11); |
| 327 __ subq(rdi, rsi); | 327 __ subq(rdi, rsi); |
| 328 } else { | 328 } else { |
| 329 ASSERT(mode_ == UC16); | 329 ASSERT(mode_ == UC16); |
| 330 // Save important/volatile registers before calling C function. | 330 // Save important/volatile registers before calling C function. |
| 331 #ifndef _WIN64 | 331 #ifndef _WIN64 |
| 332 // Callee save on Win64 | 332 // Caller save on Linux and callee save in Windows. |
| 333 __ push(rsi); | 333 __ push(rsi); |
| 334 __ push(rdi); | 334 __ push(rdi); |
| 335 #endif | 335 #endif |
| 336 __ push(backtrack_stackpointer()); | 336 __ push(backtrack_stackpointer()); |
| 337 | 337 |
| 338 int num_arguments = 3; | 338 int num_arguments = 3; |
| 339 FrameAlign(num_arguments); | 339 __ PrepareCallCFunction(num_arguments); |
| 340 | 340 |
| 341 // Put arguments into parameter registers. Parameters are | 341 // Put arguments into parameter registers. Parameters are |
| 342 // Address byte_offset1 - Address captured substring's start. | 342 // Address byte_offset1 - Address captured substring's start. |
| 343 // Address byte_offset2 - Address of current character position. | 343 // Address byte_offset2 - Address of current character position. |
| 344 // size_t byte_length - length of capture in bytes(!) | 344 // size_t byte_length - length of capture in bytes(!) |
| 345 #ifdef _WIN64 | 345 #ifdef _WIN64 |
| 346 // Compute and set byte_offset1 (start of capture). | 346 // Compute and set byte_offset1 (start of capture). |
| 347 __ lea(rcx, Operand(rsi, rdx, times_1, 0)); | 347 __ lea(rcx, Operand(rsi, rdx, times_1, 0)); |
| 348 // Set byte_offset2. | 348 // Set byte_offset2. |
| 349 __ lea(rdx, Operand(rsi, rdi, times_1, 0)); | 349 __ lea(rdx, Operand(rsi, rdi, times_1, 0)); |
| 350 // Set byte_length. | 350 // Set byte_length. |
| 351 __ movq(r8, rbx); | 351 __ movq(r8, rbx); |
| 352 #else // AMD64 calling convention | 352 #else // AMD64 calling convention |
| 353 // Compute byte_offset2 (current position = rsi+rdi). | 353 // Compute byte_offset2 (current position = rsi+rdi). |
| 354 __ lea(rax, Operand(rsi, rdi, times_1, 0)); | 354 __ lea(rax, Operand(rsi, rdi, times_1, 0)); |
| 355 // Compute and set byte_offset1 (start of capture). | 355 // Compute and set byte_offset1 (start of capture). |
| 356 __ lea(rdi, Operand(rsi, rdx, times_1, 0)); | 356 __ lea(rdi, Operand(rsi, rdx, times_1, 0)); |
| 357 // Set byte_offset2. | 357 // Set byte_offset2. |
| 358 __ movq(rsi, rax); | 358 __ movq(rsi, rax); |
| 359 // Set byte_length. | 359 // Set byte_length. |
| 360 __ movq(rdx, rbx); | 360 __ movq(rdx, rbx); |
| 361 #endif | 361 #endif |
| 362 ExternalReference compare = | 362 ExternalReference compare = |
| 363 ExternalReference::re_case_insensitive_compare_uc16(); | 363 ExternalReference::re_case_insensitive_compare_uc16(); |
| 364 CallCFunction(compare, num_arguments); | 364 __ CallCFunction(compare, num_arguments); |
| 365 | 365 |
| 366 // Restore original values before reacting on result value. | 366 // Restore original values before reacting on result value. |
| 367 __ Move(code_object_pointer(), masm_->CodeObject()); | 367 __ Move(code_object_pointer(), masm_->CodeObject()); |
| 368 __ pop(backtrack_stackpointer()); | 368 __ pop(backtrack_stackpointer()); |
| 369 #ifndef _WIN64 | 369 #ifndef _WIN64 |
| 370 __ pop(rdi); | 370 __ pop(rdi); |
| 371 __ pop(rsi); | 371 __ pop(rsi); |
| 372 #endif | 372 #endif |
| 373 | 373 |
| 374 // Check if function returned non-zero for success or zero for failure. | 374 // Check if function returned non-zero for success or zero for failure. |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 void RegExpMacroAssemblerX64::Fail() { | 627 void RegExpMacroAssemblerX64::Fail() { |
| 628 ASSERT(FAILURE == 0); // Return value for failure is zero. | 628 ASSERT(FAILURE == 0); // Return value for failure is zero. |
| 629 __ xor_(rax, rax); // zero rax. | 629 __ xor_(rax, rax); // zero rax. |
| 630 __ jmp(&exit_label_); | 630 __ jmp(&exit_label_); |
| 631 } | 631 } |
| 632 | 632 |
| 633 | 633 |
| 634 Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { | 634 Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { |
| 635 // Finalize code - write the entry point code now we know how many | 635 // Finalize code - write the entry point code now we know how many |
| 636 // registers we need. | 636 // registers we need. |
| 637 | |
| 638 // Entry code: | 637 // Entry code: |
| 639 __ bind(&entry_label_); | 638 __ bind(&entry_label_); |
| 640 // Start new stack frame. | 639 // Start new stack frame. |
| 641 __ push(rbp); | 640 __ push(rbp); |
| 642 __ movq(rbp, rsp); | 641 __ movq(rbp, rsp); |
| 643 // Save parameters and callee-save registers. Order here should correspond | 642 // Save parameters and callee-save registers. Order here should correspond |
| 644 // to order of kBackup_ebx etc. | 643 // to order of kBackup_ebx etc. |
| 645 #ifdef _WIN64 | 644 #ifdef _WIN64 |
| 646 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. | 645 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. |
| 647 // Store register parameters in pre-allocated stack slots, | 646 // Store register parameters in pre-allocated stack slots, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 664 ASSERT_EQ(kStackHighEnd, -6 * kPointerSize); | 663 ASSERT_EQ(kStackHighEnd, -6 * kPointerSize); |
| 665 __ push(rdi); | 664 __ push(rdi); |
| 666 __ push(rsi); | 665 __ push(rsi); |
| 667 __ push(rdx); | 666 __ push(rdx); |
| 668 __ push(rcx); | 667 __ push(rcx); |
| 669 __ push(r8); | 668 __ push(r8); |
| 670 __ push(r9); | 669 __ push(r9); |
| 671 | 670 |
| 672 __ push(rbx); // Callee-save | 671 __ push(rbx); // Callee-save |
| 673 #endif | 672 #endif |
| 673 |
| 674 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 674 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
| 675 __ push(Immediate(0)); // Make room for "at start" constant. | 675 __ push(Immediate(0)); // Make room for "at start" constant. |
| 676 | 676 |
| 677 // Check if we have space on the stack for registers. | 677 // Check if we have space on the stack for registers. |
| 678 Label stack_limit_hit; | 678 Label stack_limit_hit; |
| 679 Label stack_ok; | 679 Label stack_ok; |
| 680 | 680 |
| 681 ExternalReference stack_limit = | 681 ExternalReference stack_limit = |
| 682 ExternalReference::address_of_stack_limit(); | 682 ExternalReference::address_of_stack_limit(); |
| 683 __ movq(rcx, rsp); | 683 __ movq(rcx, rsp); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 Label grow_failed; | 843 Label grow_failed; |
| 844 // Save registers before calling C function | 844 // Save registers before calling C function |
| 845 #ifndef _WIN64 | 845 #ifndef _WIN64 |
| 846 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. | 846 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. |
| 847 __ push(rsi); | 847 __ push(rsi); |
| 848 __ push(rdi); | 848 __ push(rdi); |
| 849 #endif | 849 #endif |
| 850 | 850 |
| 851 // Call GrowStack(backtrack_stackpointer()) | 851 // Call GrowStack(backtrack_stackpointer()) |
| 852 int num_arguments = 2; | 852 int num_arguments = 2; |
| 853 FrameAlign(num_arguments); | 853 __ PrepareCallCFunction(num_arguments); |
| 854 #ifdef _WIN64 | 854 #ifdef _WIN64 |
| 855 // Microsoft passes parameters in rcx, rdx. | 855 // Microsoft passes parameters in rcx, rdx. |
| 856 // First argument, backtrack stackpointer, is already in rcx. | 856 // First argument, backtrack stackpointer, is already in rcx. |
| 857 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument | 857 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument |
| 858 #else | 858 #else |
| 859 // AMD64 ABI passes parameters in rdi, rsi. | 859 // AMD64 ABI passes parameters in rdi, rsi. |
| 860 __ movq(rdi, backtrack_stackpointer()); // First argument. | 860 __ movq(rdi, backtrack_stackpointer()); // First argument. |
| 861 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. | 861 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. |
| 862 #endif | 862 #endif |
| 863 ExternalReference grow_stack = ExternalReference::re_grow_stack(); | 863 ExternalReference grow_stack = ExternalReference::re_grow_stack(); |
| 864 CallCFunction(grow_stack, num_arguments); | 864 __ CallCFunction(grow_stack, num_arguments); |
| 865 // If return NULL, we have failed to grow the stack, and | 865 // If return NULL, we have failed to grow the stack, and |
| 866 // must exit with a stack-overflow exception. | 866 // must exit with a stack-overflow exception. |
| 867 __ testq(rax, rax); | 867 __ testq(rax, rax); |
| 868 __ j(equal, &exit_with_exception); | 868 __ j(equal, &exit_with_exception); |
| 869 // Otherwise use return value as new stack pointer. | 869 // Otherwise use return value as new stack pointer. |
| 870 __ movq(backtrack_stackpointer(), rax); | 870 __ movq(backtrack_stackpointer(), rax); |
| 871 // Restore saved registers and continue. | 871 // Restore saved registers and continue. |
| 872 __ Move(code_object_pointer(), masm_->CodeObject()); | 872 __ Move(code_object_pointer(), masm_->CodeObject()); |
| 873 #ifndef _WIN64 | 873 #ifndef _WIN64 |
| 874 __ pop(rdi); | 874 __ pop(rdi); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 __ movq(register_location(reg), rax); | 1023 __ movq(register_location(reg), rax); |
| 1024 } | 1024 } |
| 1025 | 1025 |
| 1026 | 1026 |
| 1027 // Private methods: | 1027 // Private methods: |
| 1028 | 1028 |
| 1029 void RegExpMacroAssemblerX64::CallCheckStackGuardState() { | 1029 void RegExpMacroAssemblerX64::CallCheckStackGuardState() { |
| 1030 // This function call preserves no register values. Caller should | 1030 // This function call preserves no register values. Caller should |
| 1031 // store anything volatile in a C call or overwritten by this function. | 1031 // store anything volatile in a C call or overwritten by this function. |
| 1032 int num_arguments = 3; | 1032 int num_arguments = 3; |
| 1033 FrameAlign(num_arguments); | 1033 __ PrepareCallCFunction(num_arguments); |
| 1034 #ifdef _WIN64 | 1034 #ifdef _WIN64 |
| 1035 // Second argument: Code* of self. (Do this before overwriting r8). | 1035 // Second argument: Code* of self. (Do this before overwriting r8). |
| 1036 __ movq(rdx, code_object_pointer()); | 1036 __ movq(rdx, code_object_pointer()); |
| 1037 // Third argument: RegExp code frame pointer. | 1037 // Third argument: RegExp code frame pointer. |
| 1038 __ movq(r8, rbp); | 1038 __ movq(r8, rbp); |
| 1039 // First argument: Next address on the stack (will be address of | 1039 // First argument: Next address on the stack (will be address of |
| 1040 // return address). | 1040 // return address). |
| 1041 __ lea(rcx, Operand(rsp, -kPointerSize)); | 1041 __ lea(rcx, Operand(rsp, -kPointerSize)); |
| 1042 #else | 1042 #else |
| 1043 // Third argument: RegExp code frame pointer. | 1043 // Third argument: RegExp code frame pointer. |
| 1044 __ movq(rdx, rbp); | 1044 __ movq(rdx, rbp); |
| 1045 // Second argument: Code* of self. | 1045 // Second argument: Code* of self. |
| 1046 __ movq(rsi, code_object_pointer()); | 1046 __ movq(rsi, code_object_pointer()); |
| 1047 // First argument: Next address on the stack (will be address of | 1047 // First argument: Next address on the stack (will be address of |
| 1048 // return address). | 1048 // return address). |
| 1049 __ lea(rdi, Operand(rsp, -kPointerSize)); | 1049 __ lea(rdi, Operand(rsp, -kPointerSize)); |
| 1050 #endif | 1050 #endif |
| 1051 ExternalReference stack_check = | 1051 ExternalReference stack_check = |
| 1052 ExternalReference::re_check_stack_guard_state(); | 1052 ExternalReference::re_check_stack_guard_state(); |
| 1053 CallCFunction(stack_check, num_arguments); | 1053 __ CallCFunction(stack_check, num_arguments); |
| 1054 } | 1054 } |
| 1055 | 1055 |
| 1056 | 1056 |
| 1057 // Helper function for reading a value out of a stack frame. | 1057 // Helper function for reading a value out of a stack frame. |
| 1058 template <typename T> | 1058 template <typename T> |
| 1059 static T& frame_entry(Address re_frame, int frame_offset) { | 1059 static T& frame_entry(Address re_frame, int frame_offset) { |
| 1060 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); | 1060 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); |
| 1061 } | 1061 } |
| 1062 | 1062 |
| 1063 | 1063 |
| 1064 int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, | 1064 int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, |
| 1065 Code* re_code, | 1065 Code* re_code, |
| 1066 Address re_frame) { | 1066 Address re_frame) { |
| 1067 if (StackGuard::IsStackOverflow()) { | 1067 if (StackGuard::IsStackOverflow()) { |
| 1068 Top::StackOverflow(); | 1068 Top::StackOverflow(); |
| 1069 return EXCEPTION; | 1069 return EXCEPTION; |
| 1070 } | 1070 } |
| 1071 | 1071 |
| 1072 // If not real stack overflow the stack guard was used to interrupt | 1072 // If not real stack overflow the stack guard was used to interrupt |
| 1073 // execution for another purpose. | 1073 // execution for another purpose. |
| 1074 | 1074 |
| 1075 // If this is a direct call from JavaScript retry the RegExp forcing the call |
| 1076 // through the runtime system. Currently the direct call cannot handle a GC. |
| 1077 if (frame_entry<int>(re_frame, kDirectCall) == 1) { |
| 1078 return RETRY; |
| 1079 } |
| 1080 |
| 1075 // Prepare for possible GC. | 1081 // Prepare for possible GC. |
| 1076 HandleScope handles; | 1082 HandleScope handles; |
| 1077 Handle<Code> code_handle(re_code); | 1083 Handle<Code> code_handle(re_code); |
| 1078 | 1084 |
| 1079 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); | 1085 Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); |
| 1080 // Current string. | 1086 // Current string. |
| 1081 bool is_ascii = subject->IsAsciiRepresentation(); | 1087 bool is_ascii = subject->IsAsciiRepresentation(); |
| 1082 | 1088 |
| 1083 ASSERT(re_code->instruction_start() <= *return_address); | 1089 ASSERT(re_code->instruction_start() <= *return_address); |
| 1084 ASSERT(*return_address <= | 1090 ASSERT(*return_address <= |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 __ load_rax(stack_limit); | 1265 __ load_rax(stack_limit); |
| 1260 __ cmpq(backtrack_stackpointer(), rax); | 1266 __ cmpq(backtrack_stackpointer(), rax); |
| 1261 __ j(above, &no_stack_overflow); | 1267 __ j(above, &no_stack_overflow); |
| 1262 | 1268 |
| 1263 SafeCall(&stack_overflow_label_); | 1269 SafeCall(&stack_overflow_label_); |
| 1264 | 1270 |
| 1265 __ bind(&no_stack_overflow); | 1271 __ bind(&no_stack_overflow); |
| 1266 } | 1272 } |
| 1267 | 1273 |
| 1268 | 1274 |
| 1269 void RegExpMacroAssemblerX64::FrameAlign(int num_arguments) { | |
| 1270 // TODO(lrn): Since we no longer use the system stack arbitrarily (but we do | |
| 1271 // use it, e.g., for SafeCall), we know the number of elements on the stack | |
| 1272 // since the last frame alignment. We might be able to do this simpler then. | |
| 1273 int frameAlignment = OS::ActivationFrameAlignment(); | |
| 1274 ASSERT(frameAlignment != 0); | |
| 1275 // Make stack end at alignment and make room for num_arguments pointers | |
| 1276 // (on Win64 only) and the original value of rsp. | |
| 1277 __ movq(kScratchRegister, rsp); | |
| 1278 ASSERT(IsPowerOf2(frameAlignment)); | |
| 1279 #ifdef _WIN64 | |
| 1280 // Allocate space for parameters and old rsp. | |
| 1281 __ subq(rsp, Immediate((num_arguments + 1) * kPointerSize)); | |
| 1282 __ and_(rsp, Immediate(-frameAlignment)); | |
| 1283 __ movq(Operand(rsp, num_arguments * kPointerSize), kScratchRegister); | |
| 1284 #else | |
| 1285 // Allocate space for old rsp. | |
| 1286 __ subq(rsp, Immediate(kPointerSize)); | |
| 1287 __ and_(rsp, Immediate(-frameAlignment)); | |
| 1288 __ movq(Operand(rsp, 0), kScratchRegister); | |
| 1289 #endif | |
| 1290 } | |
| 1291 | |
| 1292 | |
| 1293 void RegExpMacroAssemblerX64::CallCFunction(ExternalReference function, | |
| 1294 int num_arguments) { | |
| 1295 __ movq(rax, function); | |
| 1296 __ call(rax); | |
| 1297 ASSERT(OS::ActivationFrameAlignment() != 0); | |
| 1298 #ifdef _WIN64 | |
| 1299 __ movq(rsp, Operand(rsp, num_arguments * kPointerSize)); | |
| 1300 #else | |
| 1301 // All arguments passed in registers. | |
| 1302 ASSERT(num_arguments <= 6); | |
| 1303 __ pop(rsp); | |
| 1304 #endif | |
| 1305 } | |
| 1306 | |
| 1307 | |
| 1308 void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, | 1275 void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, |
| 1309 int characters) { | 1276 int characters) { |
| 1310 if (mode_ == ASCII) { | 1277 if (mode_ == ASCII) { |
| 1311 if (characters == 4) { | 1278 if (characters == 4) { |
| 1312 __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); | 1279 __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); |
| 1313 } else if (characters == 2) { | 1280 } else if (characters == 2) { |
| 1314 __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); | 1281 __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); |
| 1315 } else { | 1282 } else { |
| 1316 ASSERT(characters == 1); | 1283 ASSERT(characters == 1); |
| 1317 __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); | 1284 __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); |
| 1318 } | 1285 } |
| 1319 } else { | 1286 } else { |
| 1320 ASSERT(mode_ == UC16); | 1287 ASSERT(mode_ == UC16); |
| 1321 if (characters == 2) { | 1288 if (characters == 2) { |
| 1322 __ movl(current_character(), | 1289 __ movl(current_character(), |
| 1323 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1290 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
| 1324 } else { | 1291 } else { |
| 1325 ASSERT(characters == 1); | 1292 ASSERT(characters == 1); |
| 1326 __ movzxwl(current_character(), | 1293 __ movzxwl(current_character(), |
| 1327 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1294 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
| 1328 } | 1295 } |
| 1329 } | 1296 } |
| 1330 } | 1297 } |
| 1331 | 1298 |
| 1332 #undef __ | 1299 #undef __ |
| 1333 | 1300 |
| 1334 #endif // V8_NATIVE_REGEXP | 1301 #endif // V8_NATIVE_REGEXP |
| 1335 | 1302 |
| 1336 }} // namespace v8::internal | 1303 }} // namespace v8::internal |
| OLD | NEW |