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 |