 Chromium Code Reviews
 Chromium Code Reviews Issue 13940014:
  Simplify some code related to x64 calling convention.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 13940014:
  Simplify some code related to x64 calling convention.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| OLD | NEW | 
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 | 518 | 
| 519 __ bind(&patch); | 519 __ bind(&patch); | 
| 520 GenerateTypeTransition(masm); | 520 GenerateTypeTransition(masm); | 
| 521 } | 521 } | 
| 522 | 522 | 
| 523 | 523 | 
| 524 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 524 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { | 
| 525 __ PushCallerSaved(save_doubles_); | 525 __ PushCallerSaved(save_doubles_); | 
| 526 const int argument_count = 1; | 526 const int argument_count = 1; | 
| 527 __ PrepareCallCFunction(argument_count); | 527 __ PrepareCallCFunction(argument_count); | 
| 528 #ifdef _WIN64 | 528 __ LoadAddress(arg_reg_1, | 
| 529 __ LoadAddress(rcx, ExternalReference::isolate_address(masm->isolate())); | 529 ExternalReference::isolate_address(masm->isolate())); | 
| 530 #else | |
| 531 __ LoadAddress(rdi, ExternalReference::isolate_address(masm->isolate())); | |
| 532 #endif | |
| 533 | 530 | 
| 534 AllowExternalCallThatCantCauseGC scope(masm); | 531 AllowExternalCallThatCantCauseGC scope(masm); | 
| 535 __ CallCFunction( | 532 __ CallCFunction( | 
| 536 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 533 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 
| 537 argument_count); | 534 argument_count); | 
| 538 __ PopCallerSaved(save_doubles_); | 535 __ PopCallerSaved(save_doubles_); | 
| 539 __ ret(0); | 536 __ ret(0); | 
| 540 } | 537 } | 
| 541 | 538 | 
| 542 | 539 | 
| (...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1992 if (on_success != NULL) { | 1989 if (on_success != NULL) { | 
| 1993 __ jmp(on_success); | 1990 __ jmp(on_success); | 
| 1994 } | 1991 } | 
| 1995 // Else: fall through. | 1992 // Else: fall through. | 
| 1996 | 1993 | 
| 1997 __ bind(&done); | 1994 __ bind(&done); | 
| 1998 } | 1995 } | 
| 1999 | 1996 | 
| 2000 | 1997 | 
| 2001 void MathPowStub::Generate(MacroAssembler* masm) { | 1998 void MathPowStub::Generate(MacroAssembler* masm) { | 
| 2002 // Choose register conforming to calling convention (when bailing out). | |
| 2003 #ifdef _WIN64 | |
| 2004 const Register exponent = rdx; | 1999 const Register exponent = rdx; | 
| 2005 #else | |
| 2006 const Register exponent = rdi; | |
| 2007 #endif | |
| 2008 const Register base = rax; | 2000 const Register base = rax; | 
| 2009 const Register scratch = rcx; | 2001 const Register scratch = rcx; | 
| 2010 const XMMRegister double_result = xmm3; | 2002 const XMMRegister double_result = xmm3; | 
| 2011 const XMMRegister double_base = xmm2; | 2003 const XMMRegister double_base = xmm2; | 
| 2012 const XMMRegister double_exponent = xmm1; | 2004 const XMMRegister double_exponent = xmm1; | 
| 2013 const XMMRegister double_scratch = xmm4; | 2005 const XMMRegister double_scratch = xmm4; | 
| 2014 | 2006 | 
| 2015 Label call_runtime, done, exponent_not_smi, int_exponent; | 2007 Label call_runtime, done, exponent_not_smi, int_exponent; | 
| 2016 | 2008 | 
| 2017 // Save 1 in double_result - we need this several times later on. | 2009 // Save 1 in double_result - we need this several times later on. | 
| (...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3006 #endif | 2998 #endif | 
| 3007 | 2999 | 
| 3008 // Argument 5: static offsets vector buffer. | 3000 // Argument 5: static offsets vector buffer. | 
| 3009 __ LoadAddress(r8, | 3001 __ LoadAddress(r8, | 
| 3010 ExternalReference::address_of_static_offsets_vector(isolate)); | 3002 ExternalReference::address_of_static_offsets_vector(isolate)); | 
| 3011 // Argument 5 passed in r8 on Linux and on the stack on Windows. | 3003 // Argument 5 passed in r8 on Linux and on the stack on Windows. | 
| 3012 #ifdef _WIN64 | 3004 #ifdef _WIN64 | 
| 3013 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kPointerSize), r8); | 3005 __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kPointerSize), r8); | 
| 3014 #endif | 3006 #endif | 
| 3015 | 3007 | 
| 3016 // First four arguments are passed in registers on both Linux and Windows. | |
| 3017 #ifdef _WIN64 | |
| 3018 Register arg4 = r9; | |
| 3019 Register arg3 = r8; | |
| 3020 Register arg2 = rdx; | |
| 3021 Register arg1 = rcx; | |
| 3022 #else | |
| 3023 Register arg4 = rcx; | |
| 3024 Register arg3 = rdx; | |
| 3025 Register arg2 = rsi; | |
| 3026 Register arg1 = rdi; | |
| 3027 #endif | |
| 3028 | |
| 3029 // Keep track on aliasing between argX defined above and the registers used. | 3008 // Keep track on aliasing between argX defined above and the registers used. | 
| 3030 // rdi: subject string | 3009 // rdi: subject string | 
| 3031 // rbx: previous index | 3010 // rbx: previous index | 
| 
mvstanton
2013/04/24 10:54:54
These comments should be updated to refer to arg_r
 | |
| 3032 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 3011 // rcx: encoding of subject string (1 if ASCII 0 if two_byte); | 
| 3033 // r11: code | 3012 // r11: code | 
| 3034 // r14: slice offset | 3013 // r14: slice offset | 
| 3035 // r15: original subject string | 3014 // r15: original subject string | 
| 3036 | 3015 | 
| 3037 // Argument 2: Previous index. | 3016 // Argument 2: Previous index. | 
| 3038 __ movq(arg2, rbx); | 3017 __ movq(arg_reg_2, rbx); | 
| 3039 | 3018 | 
| 3040 // Argument 4: End of string data | 3019 // Argument 4: End of string data | 
| 3041 // Argument 3: Start of string data | 3020 // Argument 3: Start of string data | 
| 3042 Label setup_two_byte, setup_rest, got_length, length_not_from_slice; | 3021 Label setup_two_byte, setup_rest, got_length, length_not_from_slice; | 
| 3043 // Prepare start and end index of the input. | 3022 // Prepare start and end index of the input. | 
| 3044 // Load the length from the original sliced string if that is the case. | 3023 // Load the length from the original sliced string if that is the case. | 
| 3045 __ addq(rbx, r14); | 3024 __ addq(rbx, r14); | 
| 3046 __ SmiToInteger32(arg3, FieldOperand(r15, String::kLengthOffset)); | 3025 __ SmiToInteger32(arg_reg_3, FieldOperand(r15, String::kLengthOffset)); | 
| 3047 __ addq(r14, arg3); // Using arg3 as scratch. | 3026 __ addq(r14, arg_reg_3); // Using arg3 as scratch. | 
| 3048 | 3027 | 
| 3049 // rbx: start index of the input | 3028 // rbx: start index of the input | 
| 3050 // r14: end index of the input | 3029 // r14: end index of the input | 
| 3051 // r15: original subject string | 3030 // r15: original subject string | 
| 3052 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. | 3031 __ testb(rcx, rcx); // Last use of rcx as encoding of subject string. | 
| 3053 __ j(zero, &setup_two_byte, Label::kNear); | 3032 __ j(zero, &setup_two_byte, Label::kNear); | 
| 3054 __ lea(arg4, FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize)); | 3033 __ lea(arg_reg_4, | 
| 3055 __ lea(arg3, FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize)); | 3034 FieldOperand(rdi, r14, times_1, SeqOneByteString::kHeaderSize)); | 
| 3035 __ lea(arg_reg_3, | |
| 3036 FieldOperand(rdi, rbx, times_1, SeqOneByteString::kHeaderSize)); | |
| 3056 __ jmp(&setup_rest, Label::kNear); | 3037 __ jmp(&setup_rest, Label::kNear); | 
| 3057 __ bind(&setup_two_byte); | 3038 __ bind(&setup_two_byte); | 
| 3058 __ lea(arg4, FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); | 3039 __ lea(arg_reg_4, | 
| 3059 __ lea(arg3, FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); | 3040 FieldOperand(rdi, r14, times_2, SeqTwoByteString::kHeaderSize)); | 
| 3041 __ lea(arg_reg_3, | |
| 3042 FieldOperand(rdi, rbx, times_2, SeqTwoByteString::kHeaderSize)); | |
| 3060 __ bind(&setup_rest); | 3043 __ bind(&setup_rest); | 
| 3061 | 3044 | 
| 3062 // Argument 1: Original subject string. | 3045 // Argument 1: Original subject string. | 
| 3063 // The original subject is in the previous stack frame. Therefore we have to | 3046 // The original subject is in the previous stack frame. Therefore we have to | 
| 3064 // use rbp, which points exactly to one pointer size below the previous rsp. | 3047 // use rbp, which points exactly to one pointer size below the previous rsp. | 
| 3065 // (Because creating a new stack frame pushes the previous rbp onto the stack | 3048 // (Because creating a new stack frame pushes the previous rbp onto the stack | 
| 3066 // and thereby moves up rsp by one kPointerSize.) | 3049 // and thereby moves up rsp by one kPointerSize.) | 
| 3067 __ movq(arg1, r15); | 3050 __ movq(arg_reg_1, r15); | 
| 3068 | 3051 | 
| 3069 // Locate the code entry and call it. | 3052 // Locate the code entry and call it. | 
| 3070 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 3053 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 
| 3071 __ call(r11); | 3054 __ call(r11); | 
| 3072 | 3055 | 
| 3073 __ LeaveApiExitFrame(); | 3056 __ LeaveApiExitFrame(); | 
| 3074 | 3057 | 
| 3075 // Check the result. | 3058 // Check the result. | 
| 3076 Label success; | 3059 Label success; | 
| 3077 Label exception; | 3060 Label exception; | 
| (...skipping 1004 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4082 // Check stack alignment. | 4065 // Check stack alignment. | 
| 4083 if (FLAG_debug_code) { | 4066 if (FLAG_debug_code) { | 
| 4084 __ CheckStackAlignment(); | 4067 __ CheckStackAlignment(); | 
| 4085 } | 4068 } | 
| 4086 | 4069 | 
| 4087 if (do_gc) { | 4070 if (do_gc) { | 
| 4088 // Pass failure code returned from last attempt as first argument to | 4071 // Pass failure code returned from last attempt as first argument to | 
| 4089 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | 4072 // PerformGC. No need to use PrepareCallCFunction/CallCFunction here as the | 
| 4090 // stack is known to be aligned. This function takes one argument which is | 4073 // stack is known to be aligned. This function takes one argument which is | 
| 4091 // passed in register. | 4074 // passed in register. | 
| 4092 #ifdef _WIN64 | 4075 __ movq(arg_reg_1, rax); | 
| 4093 __ movq(rcx, rax); | |
| 4094 #else // _WIN64 | |
| 4095 __ movq(rdi, rax); | |
| 4096 #endif | |
| 4097 __ movq(kScratchRegister, | 4076 __ movq(kScratchRegister, | 
| 4098 ExternalReference::perform_gc_function(masm->isolate())); | 4077 ExternalReference::perform_gc_function(masm->isolate())); | 
| 4099 __ call(kScratchRegister); | 4078 __ call(kScratchRegister); | 
| 4100 } | 4079 } | 
| 4101 | 4080 | 
| 4102 ExternalReference scope_depth = | 4081 ExternalReference scope_depth = | 
| 4103 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); | 4082 ExternalReference::heap_always_allocate_scope_depth(masm->isolate()); | 
| 4104 if (always_allocate_scope) { | 4083 if (always_allocate_scope) { | 
| 4105 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); | 4084 Operand scope_depth_operand = masm->ExternalOperand(scope_depth); | 
| 4106 __ incl(scope_depth_operand); | 4085 __ incl(scope_depth_operand); | 
| (...skipping 2367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6474 CheckNeedsToInformIncrementalMarker( | 6453 CheckNeedsToInformIncrementalMarker( | 
| 6475 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); | 6454 masm, kReturnOnNoNeedToInformIncrementalMarker, mode); | 
| 6476 InformIncrementalMarker(masm, mode); | 6455 InformIncrementalMarker(masm, mode); | 
| 6477 regs_.Restore(masm); | 6456 regs_.Restore(masm); | 
| 6478 __ ret(0); | 6457 __ ret(0); | 
| 6479 } | 6458 } | 
| 6480 | 6459 | 
| 6481 | 6460 | 
| 6482 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { | 6461 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) { | 
| 6483 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 6462 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_); | 
| 6484 #ifdef _WIN64 | |
| 6485 Register arg3 = r8; | |
| 6486 Register arg2 = rdx; | |
| 6487 Register arg1 = rcx; | |
| 6488 #else | |
| 6489 Register arg3 = rdx; | |
| 6490 Register arg2 = rsi; | |
| 6491 Register arg1 = rdi; | |
| 6492 #endif | |
| 6493 Register address = | 6463 Register address = | 
| 6494 arg1.is(regs_.address()) ? kScratchRegister : regs_.address(); | 6464 arg_reg_1.is(regs_.address()) ? kScratchRegister : regs_.address(); | 
| 6495 ASSERT(!address.is(regs_.object())); | 6465 ASSERT(!address.is(regs_.object())); | 
| 6496 ASSERT(!address.is(arg1)); | 6466 ASSERT(!address.is(arg_reg_1)); | 
| 6497 __ Move(address, regs_.address()); | 6467 __ Move(address, regs_.address()); | 
| 6498 __ Move(arg1, regs_.object()); | 6468 __ Move(arg_reg_1, regs_.object()); | 
| 6499 // TODO(gc) Can we just set address arg2 in the beginning? | 6469 // TODO(gc) Can we just set address arg2 in the beginning? | 
| 6500 __ Move(arg2, address); | 6470 __ Move(arg_reg_2, address); | 
| 6501 __ LoadAddress(arg3, ExternalReference::isolate_address(masm->isolate())); | 6471 __ LoadAddress(arg_reg_3, | 
| 6472 ExternalReference::isolate_address(masm->isolate())); | |
| 6502 int argument_count = 3; | 6473 int argument_count = 3; | 
| 6503 | 6474 | 
| 6504 AllowExternalCallThatCantCauseGC scope(masm); | 6475 AllowExternalCallThatCantCauseGC scope(masm); | 
| 6505 __ PrepareCallCFunction(argument_count); | 6476 __ PrepareCallCFunction(argument_count); | 
| 6506 if (mode == INCREMENTAL_COMPACTION) { | 6477 if (mode == INCREMENTAL_COMPACTION) { | 
| 6507 __ CallCFunction( | 6478 __ CallCFunction( | 
| 6508 ExternalReference::incremental_evacuation_record_write_function( | 6479 ExternalReference::incremental_evacuation_record_write_function( | 
| 6509 masm->isolate()), | 6480 masm->isolate()), | 
| 6510 argument_count); | 6481 argument_count); | 
| 6511 } else { | 6482 } else { | 
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6767 #endif | 6738 #endif | 
| 6768 | 6739 | 
| 6769 __ Ret(); | 6740 __ Ret(); | 
| 6770 } | 6741 } | 
| 6771 | 6742 | 
| 6772 #undef __ | 6743 #undef __ | 
| 6773 | 6744 | 
| 6774 } } // namespace v8::internal | 6745 } } // namespace v8::internal | 
| 6775 | 6746 | 
| 6776 #endif // V8_TARGET_ARCH_X64 | 6747 #endif // V8_TARGET_ARCH_X64 | 
| OLD | NEW |