Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(830)

Side by Side Diff: src/x64/regexp-macro-assembler-x64.cc

Issue 548179: Port direct call from JavaScript to native RegExp to x64... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/x64/codegen-x64.cc ('K') | « src/x64/regexp-macro-assembler-x64.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« src/x64/codegen-x64.cc ('K') | « src/x64/regexp-macro-assembler-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698