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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 2885018: X64: Added register holding Smi::FromInt(1). (Closed)
Patch Set: Addressed review comments Created 10 years, 5 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
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/frames-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 bool CodeGenerator::HasValidEntryRegisters() { 585 bool CodeGenerator::HasValidEntryRegisters() {
586 return (allocator()->count(rax) == (frame()->is_used(rax) ? 1 : 0)) 586 return (allocator()->count(rax) == (frame()->is_used(rax) ? 1 : 0))
587 && (allocator()->count(rbx) == (frame()->is_used(rbx) ? 1 : 0)) 587 && (allocator()->count(rbx) == (frame()->is_used(rbx) ? 1 : 0))
588 && (allocator()->count(rcx) == (frame()->is_used(rcx) ? 1 : 0)) 588 && (allocator()->count(rcx) == (frame()->is_used(rcx) ? 1 : 0))
589 && (allocator()->count(rdx) == (frame()->is_used(rdx) ? 1 : 0)) 589 && (allocator()->count(rdx) == (frame()->is_used(rdx) ? 1 : 0))
590 && (allocator()->count(rdi) == (frame()->is_used(rdi) ? 1 : 0)) 590 && (allocator()->count(rdi) == (frame()->is_used(rdi) ? 1 : 0))
591 && (allocator()->count(r8) == (frame()->is_used(r8) ? 1 : 0)) 591 && (allocator()->count(r8) == (frame()->is_used(r8) ? 1 : 0))
592 && (allocator()->count(r9) == (frame()->is_used(r9) ? 1 : 0)) 592 && (allocator()->count(r9) == (frame()->is_used(r9) ? 1 : 0))
593 && (allocator()->count(r11) == (frame()->is_used(r11) ? 1 : 0)) 593 && (allocator()->count(r11) == (frame()->is_used(r11) ? 1 : 0))
594 && (allocator()->count(r14) == (frame()->is_used(r14) ? 1 : 0)) 594 && (allocator()->count(r14) == (frame()->is_used(r14) ? 1 : 0))
595 && (allocator()->count(r15) == (frame()->is_used(r15) ? 1 : 0))
596 && (allocator()->count(r12) == (frame()->is_used(r12) ? 1 : 0)); 595 && (allocator()->count(r12) == (frame()->is_used(r12) ? 1 : 0));
597 } 596 }
598 #endif 597 #endif
599 598
600 599
601 class DeferredReferenceGetKeyedValue: public DeferredCode { 600 class DeferredReferenceGetKeyedValue: public DeferredCode {
602 public: 601 public:
603 explicit DeferredReferenceGetKeyedValue(Register dst, 602 explicit DeferredReferenceGetKeyedValue(Register dst,
604 Register receiver, 603 Register receiver,
605 Register key) 604 Register key)
(...skipping 2993 matching lines...) Expand 10 before | Expand all | Expand 10 after
3599 is_increment, 3598 is_increment,
3600 new_value.type_info()); 3599 new_value.type_info());
3601 } 3600 }
3602 3601
3603 if (new_value.is_smi()) { 3602 if (new_value.is_smi()) {
3604 if (FLAG_debug_code) { __ AbortIfNotSmi(new_value.reg()); } 3603 if (FLAG_debug_code) { __ AbortIfNotSmi(new_value.reg()); }
3605 } else { 3604 } else {
3606 __ JumpIfNotSmi(new_value.reg(), deferred->entry_label()); 3605 __ JumpIfNotSmi(new_value.reg(), deferred->entry_label());
3607 } 3606 }
3608 if (is_increment) { 3607 if (is_increment) {
3609 __ SmiAddConstant(kScratchRegister, 3608 __ SmiAddConstant(new_value.reg(),
3610 new_value.reg(), 3609 new_value.reg(),
3611 Smi::FromInt(1), 3610 Smi::FromInt(1),
3612 deferred->entry_label()); 3611 deferred->entry_label());
3613 } else { 3612 } else {
3614 __ SmiSubConstant(kScratchRegister, 3613 __ SmiSubConstant(new_value.reg(),
3615 new_value.reg(), 3614 new_value.reg(),
3616 Smi::FromInt(1), 3615 Smi::FromInt(1),
3617 deferred->entry_label()); 3616 deferred->entry_label());
3618 } 3617 }
3619 __ movq(new_value.reg(), kScratchRegister);
3620 deferred->BindExit(); 3618 deferred->BindExit();
3621 3619
3622 // Postfix count operations return their input converted to 3620 // Postfix count operations return their input converted to
3623 // number. The case when the input is already a number is covered 3621 // number. The case when the input is already a number is covered
3624 // above in the allocation code for old_value. 3622 // above in the allocation code for old_value.
3625 if (is_postfix && !new_value.type_info().IsNumber()) { 3623 if (is_postfix && !new_value.type_info().IsNumber()) {
3626 old_value.set_type_info(TypeInfo::Number()); 3624 old_value.set_type_info(TypeInfo::Number());
3627 } 3625 }
3628 3626
3629 new_value.set_type_info(TypeInfo::Number()); 3627 new_value.set_type_info(TypeInfo::Number());
(...skipping 5090 matching lines...) Expand 10 before | Expand all | Expand 10 after
8720 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag); 8718 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag);
8721 __ j(zero, &seq_two_byte_string); 8719 __ j(zero, &seq_two_byte_string);
8722 // Any other flat string must be ascii. 8720 // Any other flat string must be ascii.
8723 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 8721 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
8724 Immediate(kStringRepresentationMask)); 8722 Immediate(kStringRepresentationMask));
8725 __ j(not_zero, &runtime); 8723 __ j(not_zero, &runtime);
8726 8724
8727 __ bind(&seq_ascii_string); 8725 __ bind(&seq_ascii_string);
8728 // rax: subject string (sequential ascii) 8726 // rax: subject string (sequential ascii)
8729 // rcx: RegExp data (FixedArray) 8727 // rcx: RegExp data (FixedArray)
8730 __ movq(r12, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset)); 8728 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset));
8731 __ Set(rdi, 1); // Type is ascii. 8729 __ Set(rdi, 1); // Type is ascii.
8732 __ jmp(&check_code); 8730 __ jmp(&check_code);
8733 8731
8734 __ bind(&seq_two_byte_string); 8732 __ bind(&seq_two_byte_string);
8735 // rax: subject string (flat two-byte) 8733 // rax: subject string (flat two-byte)
8736 // rcx: RegExp data (FixedArray) 8734 // rcx: RegExp data (FixedArray)
8737 __ movq(r12, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset)); 8735 __ movq(r11, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset));
8738 __ Set(rdi, 0); // Type is two byte. 8736 __ Set(rdi, 0); // Type is two byte.
8739 8737
8740 __ bind(&check_code); 8738 __ bind(&check_code);
8741 // Check that the irregexp code has been generated for the actual string 8739 // Check that the irregexp code has been generated for the actual string
8742 // encoding. If it has, the field contains a code object otherwise it contains 8740 // encoding. If it has, the field contains a code object otherwise it contains
8743 // the hole. 8741 // the hole.
8744 __ CmpObjectType(r12, CODE_TYPE, kScratchRegister); 8742 __ CmpObjectType(r11, CODE_TYPE, kScratchRegister);
8745 __ j(not_equal, &runtime); 8743 __ j(not_equal, &runtime);
8746 8744
8747 // rax: subject string 8745 // rax: subject string
8748 // rdi: encoding of subject string (1 if ascii, 0 if two_byte); 8746 // rdi: encoding of subject string (1 if ascii, 0 if two_byte);
8749 // r12: code 8747 // r11: code
8750 // Load used arguments before starting to push arguments for call to native 8748 // Load used arguments before starting to push arguments for call to native
8751 // RegExp code to avoid handling changing stack height. 8749 // RegExp code to avoid handling changing stack height.
8752 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset)); 8750 __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset));
8753 8751
8754 // rax: subject string 8752 // rax: subject string
8755 // rbx: previous index 8753 // rbx: previous index
8756 // rdi: encoding of subject string (1 if ascii 0 if two_byte); 8754 // rdi: encoding of subject string (1 if ascii 0 if two_byte);
8757 // r12: code 8755 // r11: code
8758 // All checks done. Now push arguments for native regexp code. 8756 // All checks done. Now push arguments for native regexp code.
8759 __ IncrementCounter(&Counters::regexp_entry_native, 1); 8757 __ IncrementCounter(&Counters::regexp_entry_native, 1);
8760 8758
8761 // rsi is caller save on Windows and used to pass parameter on Linux. 8759 // rsi is caller save on Windows and used to pass parameter on Linux.
8762 __ push(rsi); 8760 __ push(rsi);
8763 8761
8764 static const int kRegExpExecuteArguments = 7; 8762 static const int kRegExpExecuteArguments = 7;
8765 __ PrepareCallCFunction(kRegExpExecuteArguments); 8763 __ PrepareCallCFunction(kRegExpExecuteArguments);
8766 int argument_slots_on_stack = 8764 int argument_slots_on_stack =
8767 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments); 8765 masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
(...skipping 29 matching lines...) Expand all
8797 Register arg4 = rcx; 8795 Register arg4 = rcx;
8798 Register arg3 = rdx; 8796 Register arg3 = rdx;
8799 Register arg2 = rsi; 8797 Register arg2 = rsi;
8800 Register arg1 = rdi; 8798 Register arg1 = rdi;
8801 #endif 8799 #endif
8802 8800
8803 // Keep track on aliasing between argX defined above and the registers used. 8801 // Keep track on aliasing between argX defined above and the registers used.
8804 // rax: subject string 8802 // rax: subject string
8805 // rbx: previous index 8803 // rbx: previous index
8806 // rdi: encoding of subject string (1 if ascii 0 if two_byte); 8804 // rdi: encoding of subject string (1 if ascii 0 if two_byte);
8807 // r12: code 8805 // r11: code
8808 8806
8809 // Argument 4: End of string data 8807 // Argument 4: End of string data
8810 // Argument 3: Start of string data 8808 // Argument 3: Start of string data
8811 Label setup_two_byte, setup_rest; 8809 Label setup_two_byte, setup_rest;
8812 __ testb(rdi, rdi); 8810 __ testb(rdi, rdi);
8813 __ j(zero, &setup_two_byte); 8811 __ j(zero, &setup_two_byte);
8814 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 8812 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
8815 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize)); 8813 __ lea(arg4, FieldOperand(rax, rdi, times_1, SeqAsciiString::kHeaderSize));
8816 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize)); 8814 __ lea(arg3, FieldOperand(rax, rbx, times_1, SeqAsciiString::kHeaderSize));
8817 __ jmp(&setup_rest); 8815 __ jmp(&setup_rest);
8818 __ bind(&setup_two_byte); 8816 __ bind(&setup_two_byte);
8819 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 8817 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
8820 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize)); 8818 __ lea(arg4, FieldOperand(rax, rdi, times_2, SeqTwoByteString::kHeaderSize));
8821 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize)); 8819 __ lea(arg3, FieldOperand(rax, rbx, times_2, SeqTwoByteString::kHeaderSize));
8822 8820
8823 __ bind(&setup_rest); 8821 __ bind(&setup_rest);
8824 // Argument 2: Previous index. 8822 // Argument 2: Previous index.
8825 __ movq(arg2, rbx); 8823 __ movq(arg2, rbx);
8826 8824
8827 // Argument 1: Subject string. 8825 // Argument 1: Subject string.
8828 __ movq(arg1, rax); 8826 __ movq(arg1, rax);
8829 8827
8830 // Locate the code entry and call it. 8828 // Locate the code entry and call it.
8831 __ addq(r12, Immediate(Code::kHeaderSize - kHeapObjectTag)); 8829 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
8832 __ CallCFunction(r12, kRegExpExecuteArguments); 8830 __ CallCFunction(r11, kRegExpExecuteArguments);
8833 8831
8834 // rsi is caller save, as it is used to pass parameter. 8832 // rsi is caller save, as it is used to pass parameter.
8835 __ pop(rsi); 8833 __ pop(rsi);
8836 8834
8837 // Check the result. 8835 // Check the result.
8838 Label success; 8836 Label success;
8839 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS)); 8837 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::SUCCESS));
8840 __ j(equal, &success); 8838 __ j(equal, &success);
8841 Label failure; 8839 Label failure;
8842 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE)); 8840 __ cmpl(rax, Immediate(NativeRegExpMacroAssembler::FAILURE));
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after
9620 Label* throw_termination_exception, 9618 Label* throw_termination_exception,
9621 Label* throw_out_of_memory_exception, 9619 Label* throw_out_of_memory_exception,
9622 bool do_gc, 9620 bool do_gc,
9623 bool always_allocate_scope, 9621 bool always_allocate_scope,
9624 int /* alignment_skew */) { 9622 int /* alignment_skew */) {
9625 // rax: result parameter for PerformGC, if any. 9623 // rax: result parameter for PerformGC, if any.
9626 // rbx: pointer to C function (C callee-saved). 9624 // rbx: pointer to C function (C callee-saved).
9627 // rbp: frame pointer (restored after C call). 9625 // rbp: frame pointer (restored after C call).
9628 // rsp: stack pointer (restored after C call). 9626 // rsp: stack pointer (restored after C call).
9629 // r14: number of arguments including receiver (C callee-saved). 9627 // r14: number of arguments including receiver (C callee-saved).
9630 // r15: pointer to the first argument (C callee-saved). 9628 // r12: pointer to the first argument (C callee-saved).
9631 // This pointer is reused in LeaveExitFrame(), so it is stored in a 9629 // This pointer is reused in LeaveExitFrame(), so it is stored in a
9632 // callee-saved register. 9630 // callee-saved register.
9633 9631
9634 // Simple results returned in rax (both AMD64 and Win64 calling conventions). 9632 // Simple results returned in rax (both AMD64 and Win64 calling conventions).
9635 // Complex results must be written to address passed as first argument. 9633 // Complex results must be written to address passed as first argument.
9636 // AMD64 calling convention: a struct of two pointers in rax+rdx 9634 // AMD64 calling convention: a struct of two pointers in rax+rdx
9637 9635
9638 // Check stack alignment. 9636 // Check stack alignment.
9639 if (FLAG_debug_code) { 9637 if (FLAG_debug_code) {
9640 __ CheckStackAlignment(); 9638 __ CheckStackAlignment();
(...skipping 20 matching lines...) Expand all
9661 if (always_allocate_scope) { 9659 if (always_allocate_scope) {
9662 __ movq(kScratchRegister, scope_depth); 9660 __ movq(kScratchRegister, scope_depth);
9663 __ incl(Operand(kScratchRegister, 0)); 9661 __ incl(Operand(kScratchRegister, 0));
9664 } 9662 }
9665 9663
9666 // Call C function. 9664 // Call C function.
9667 #ifdef _WIN64 9665 #ifdef _WIN64
9668 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 9666 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
9669 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. 9667 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
9670 __ movq(Operand(rsp, 4 * kPointerSize), r14); // argc. 9668 __ movq(Operand(rsp, 4 * kPointerSize), r14); // argc.
9671 __ movq(Operand(rsp, 5 * kPointerSize), r15); // argv. 9669 __ movq(Operand(rsp, 5 * kPointerSize), r12); // argv.
9672 if (result_size_ < 2) { 9670 if (result_size_ < 2) {
9673 // Pass a pointer to the Arguments object as the first argument. 9671 // Pass a pointer to the Arguments object as the first argument.
9674 // Return result in single register (rax). 9672 // Return result in single register (rax).
9675 __ lea(rcx, Operand(rsp, 4 * kPointerSize)); 9673 __ lea(rcx, Operand(rsp, 4 * kPointerSize));
9676 } else { 9674 } else {
9677 ASSERT_EQ(2, result_size_); 9675 ASSERT_EQ(2, result_size_);
9678 // Pass a pointer to the result location as the first argument. 9676 // Pass a pointer to the result location as the first argument.
9679 __ lea(rcx, Operand(rsp, 6 * kPointerSize)); 9677 __ lea(rcx, Operand(rsp, 6 * kPointerSize));
9680 // Pass a pointer to the Arguments object as the second argument. 9678 // Pass a pointer to the Arguments object as the second argument.
9681 __ lea(rdx, Operand(rsp, 4 * kPointerSize)); 9679 __ lea(rdx, Operand(rsp, 4 * kPointerSize));
9682 } 9680 }
9683 9681
9684 #else // _WIN64 9682 #else // _WIN64
9685 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. 9683 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
9686 __ movq(rdi, r14); // argc. 9684 __ movq(rdi, r14); // argc.
9687 __ movq(rsi, r15); // argv. 9685 __ movq(rsi, r12); // argv.
9688 #endif 9686 #endif
9689 __ call(rbx); 9687 __ call(rbx);
9690 // Result is in rax - do not destroy this register! 9688 // Result is in rax - do not destroy this register!
9691 9689
9692 if (always_allocate_scope) { 9690 if (always_allocate_scope) {
9693 __ movq(kScratchRegister, scope_depth); 9691 __ movq(kScratchRegister, scope_depth);
9694 __ decl(Operand(kScratchRegister, 0)); 9692 __ decl(Operand(kScratchRegister, 0));
9695 } 9693 }
9696 9694
9697 // Check for failure result. 9695 // Check for failure result.
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
9879 // rax: Holds the context at this point, but should not be used. 9877 // rax: Holds the context at this point, but should not be used.
9880 // On entry to code generated by GenerateCore, it must hold 9878 // On entry to code generated by GenerateCore, it must hold
9881 // a failure result if the collect_garbage argument to GenerateCore 9879 // a failure result if the collect_garbage argument to GenerateCore
9882 // is true. This failure result can be the result of code 9880 // is true. This failure result can be the result of code
9883 // generated by a previous call to GenerateCore. The value 9881 // generated by a previous call to GenerateCore. The value
9884 // of rax is then passed to Runtime::PerformGC. 9882 // of rax is then passed to Runtime::PerformGC.
9885 // rbx: pointer to builtin function (C callee-saved). 9883 // rbx: pointer to builtin function (C callee-saved).
9886 // rbp: frame pointer of exit frame (restored after C call). 9884 // rbp: frame pointer of exit frame (restored after C call).
9887 // rsp: stack pointer (restored after C call). 9885 // rsp: stack pointer (restored after C call).
9888 // r14: number of arguments including receiver (C callee-saved). 9886 // r14: number of arguments including receiver (C callee-saved).
9889 // r15: argv pointer (C callee-saved). 9887 // r12: argv pointer (C callee-saved).
9890 9888
9891 Label throw_normal_exception; 9889 Label throw_normal_exception;
9892 Label throw_termination_exception; 9890 Label throw_termination_exception;
9893 Label throw_out_of_memory_exception; 9891 Label throw_out_of_memory_exception;
9894 9892
9895 // Call into the runtime system. 9893 // Call into the runtime system.
9896 GenerateCore(masm, 9894 GenerateCore(masm,
9897 &throw_normal_exception, 9895 &throw_normal_exception,
9898 &throw_termination_exception, 9896 &throw_termination_exception,
9899 &throw_out_of_memory_exception, 9897 &throw_out_of_memory_exception,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
9939 #ifdef ENABLE_LOGGING_AND_PROFILING 9937 #ifdef ENABLE_LOGGING_AND_PROFILING
9940 Label not_outermost_js, not_outermost_js_2; 9938 Label not_outermost_js, not_outermost_js_2;
9941 #endif 9939 #endif
9942 9940
9943 // Setup frame. 9941 // Setup frame.
9944 __ push(rbp); 9942 __ push(rbp);
9945 __ movq(rbp, rsp); 9943 __ movq(rbp, rsp);
9946 9944
9947 // Push the stack frame type marker twice. 9945 // Push the stack frame type marker twice.
9948 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 9946 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
9949 __ Push(Smi::FromInt(marker)); // context slot 9947 // Scratch register is neither callee-save, nor an argument register on any
9950 __ Push(Smi::FromInt(marker)); // function slot 9948 // platform. It's free to use at this point.
9951 // Save callee-saved registers (X64 calling conventions). 9949 // Cannot use smi-register for loading yet.
9950 __ movq(kScratchRegister,
9951 reinterpret_cast<uint64_t>(Smi::FromInt(marker)),
9952 RelocInfo::NONE);
9953 __ push(kScratchRegister); // context slot
9954 __ push(kScratchRegister); // function slot
9955 // Save callee-saved registers (X64/Win64 calling conventions).
9952 __ push(r12); 9956 __ push(r12);
9953 __ push(r13); 9957 __ push(r13);
9954 __ push(r14); 9958 __ push(r14);
9955 __ push(r15); 9959 __ push(r15);
9956 __ push(rdi); 9960 #ifdef _WIN64
9957 __ push(rsi); 9961 __ push(rdi); // Only callee save in Win64 ABI, argument in AMD64 ABI.
9962 __ push(rsi); // Only callee save in Win64 ABI, argument in AMD64 ABI.
9963 #endif
9958 __ push(rbx); 9964 __ push(rbx);
9959 // TODO(X64): Push XMM6-XMM15 (low 64 bits) as well, or make them 9965 // TODO(X64): On Win64, if we ever use XMM6-XMM15, the low low 64 bits are
9960 // callee-save in JS code as well. 9966 // callee save as well.
9961 9967
9962 // Save copies of the top frame descriptor on the stack. 9968 // Save copies of the top frame descriptor on the stack.
9963 ExternalReference c_entry_fp(Top::k_c_entry_fp_address); 9969 ExternalReference c_entry_fp(Top::k_c_entry_fp_address);
9964 __ load_rax(c_entry_fp); 9970 __ load_rax(c_entry_fp);
9965 __ push(rax); 9971 __ push(rax);
9966 9972
9973 // Set up the roots and smi constant registers.
9974 // Needs to be done before any further smi loads.
9975 ExternalReference roots_address = ExternalReference::roots_address();
9976 __ movq(kRootRegister, roots_address);
9977 __ InitializeSmiConstantRegister();
9978
9967 #ifdef ENABLE_LOGGING_AND_PROFILING 9979 #ifdef ENABLE_LOGGING_AND_PROFILING
9968 // If this is the outermost JS call, set js_entry_sp value. 9980 // If this is the outermost JS call, set js_entry_sp value.
9969 ExternalReference js_entry_sp(Top::k_js_entry_sp_address); 9981 ExternalReference js_entry_sp(Top::k_js_entry_sp_address);
9970 __ load_rax(js_entry_sp); 9982 __ load_rax(js_entry_sp);
9971 __ testq(rax, rax); 9983 __ testq(rax, rax);
9972 __ j(not_zero, &not_outermost_js); 9984 __ j(not_zero, &not_outermost_js);
9973 __ movq(rax, rbp); 9985 __ movq(rax, rbp);
9974 __ store_rax(js_entry_sp); 9986 __ store_rax(js_entry_sp);
9975 __ bind(&not_outermost_js); 9987 __ bind(&not_outermost_js);
9976 #endif 9988 #endif
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
10027 __ bind(&not_outermost_js_2); 10039 __ bind(&not_outermost_js_2);
10028 #endif 10040 #endif
10029 10041
10030 // Restore the top frame descriptor from the stack. 10042 // Restore the top frame descriptor from the stack.
10031 __ bind(&exit); 10043 __ bind(&exit);
10032 __ movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address)); 10044 __ movq(kScratchRegister, ExternalReference(Top::k_c_entry_fp_address));
10033 __ pop(Operand(kScratchRegister, 0)); 10045 __ pop(Operand(kScratchRegister, 0));
10034 10046
10035 // Restore callee-saved registers (X64 conventions). 10047 // Restore callee-saved registers (X64 conventions).
10036 __ pop(rbx); 10048 __ pop(rbx);
10049 #ifdef _WIN64
10050 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
10037 __ pop(rsi); 10051 __ pop(rsi);
10038 __ pop(rdi); 10052 __ pop(rdi);
10053 #endif
10039 __ pop(r15); 10054 __ pop(r15);
10040 __ pop(r14); 10055 __ pop(r14);
10041 __ pop(r13); 10056 __ pop(r13);
10042 __ pop(r12); 10057 __ pop(r12);
10043 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers 10058 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers
10044 10059
10045 // Restore frame pointer and return. 10060 // Restore frame pointer and return.
10046 __ pop(rbp); 10061 __ pop(rbp);
10047 __ ret(0); 10062 __ ret(0);
10048 } 10063 }
(...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after
11262 // Look at the length of the result of adding the two strings. 11277 // Look at the length of the result of adding the two strings.
11263 ASSERT(String::kMaxLength <= Smi::kMaxValue / 2); 11278 ASSERT(String::kMaxLength <= Smi::kMaxValue / 2);
11264 __ SmiAdd(rbx, rbx, rcx, NULL); 11279 __ SmiAdd(rbx, rbx, rcx, NULL);
11265 // Use the runtime system when adding two one character strings, as it 11280 // Use the runtime system when adding two one character strings, as it
11266 // contains optimizations for this specific case using the symbol table. 11281 // contains optimizations for this specific case using the symbol table.
11267 __ SmiCompare(rbx, Smi::FromInt(2)); 11282 __ SmiCompare(rbx, Smi::FromInt(2));
11268 __ j(not_equal, &longer_than_two); 11283 __ j(not_equal, &longer_than_two);
11269 11284
11270 // Check that both strings are non-external ascii strings. 11285 // Check that both strings are non-external ascii strings.
11271 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx, 11286 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r8, r9, rbx, rcx,
11272 &string_add_runtime); 11287 &string_add_runtime);
11273 11288
11274 // Get the two characters forming the sub string. 11289 // Get the two characters forming the sub string.
11275 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize)); 11290 __ movzxbq(rbx, FieldOperand(rax, SeqAsciiString::kHeaderSize));
11276 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize)); 11291 __ movzxbq(rcx, FieldOperand(rdx, SeqAsciiString::kHeaderSize));
11277 11292
11278 // Try to lookup two character string in symbol table. If it is not found 11293 // Try to lookup two character string in symbol table. If it is not found
11279 // just allocate a new one. 11294 // just allocate a new one.
11280 Label make_two_character_string, make_flat_ascii_string; 11295 Label make_two_character_string, make_flat_ascii_string;
11281 StringHelper::GenerateTwoCharacterSymbolTableProbe( 11296 StringHelper::GenerateTwoCharacterSymbolTableProbe(
11282 masm, rbx, rcx, r14, r12, rdi, r15, &make_two_character_string); 11297 masm, rbx, rcx, r14, r11, rdi, r12, &make_two_character_string);
11283 __ IncrementCounter(&Counters::string_add_native, 1); 11298 __ IncrementCounter(&Counters::string_add_native, 1);
11284 __ ret(2 * kPointerSize); 11299 __ ret(2 * kPointerSize);
11285 11300
11286 __ bind(&make_two_character_string); 11301 __ bind(&make_two_character_string);
11287 __ Set(rbx, 2); 11302 __ Set(rbx, 2);
11288 __ jmp(&make_flat_ascii_string); 11303 __ jmp(&make_flat_ascii_string);
11289 11304
11290 __ bind(&longer_than_two); 11305 __ bind(&longer_than_two);
11291 // Check if resulting string will be flat. 11306 // Check if resulting string will be flat.
11292 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength)); 11307 __ SmiCompare(rbx, Smi::FromInt(String::kMinNonFlatLength));
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
11364 // r9: instance type of second string 11379 // r9: instance type of second string
11365 Label non_ascii_string_add_flat_result; 11380 Label non_ascii_string_add_flat_result;
11366 ASSERT(kStringEncodingMask == kAsciiStringTag); 11381 ASSERT(kStringEncodingMask == kAsciiStringTag);
11367 __ testl(r8, Immediate(kAsciiStringTag)); 11382 __ testl(r8, Immediate(kAsciiStringTag));
11368 __ j(zero, &non_ascii_string_add_flat_result); 11383 __ j(zero, &non_ascii_string_add_flat_result);
11369 __ testl(r9, Immediate(kAsciiStringTag)); 11384 __ testl(r9, Immediate(kAsciiStringTag));
11370 __ j(zero, &string_add_runtime); 11385 __ j(zero, &string_add_runtime);
11371 11386
11372 __ bind(&make_flat_ascii_string); 11387 __ bind(&make_flat_ascii_string);
11373 // Both strings are ascii strings. As they are short they are both flat. 11388 // Both strings are ascii strings. As they are short they are both flat.
11374 __ AllocateAsciiString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 11389 __ AllocateAsciiString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
11375 // rcx: result string 11390 // rcx: result string
11376 __ movq(rbx, rcx); 11391 __ movq(rbx, rcx);
11377 // Locate first character of result. 11392 // Locate first character of result.
11378 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 11393 __ addq(rcx, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
11379 // Locate first character of first argument 11394 // Locate first character of first argument
11380 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 11395 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
11381 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 11396 __ addq(rax, Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
11382 // rax: first char of first argument 11397 // rax: first char of first argument
11383 // rbx: result string 11398 // rbx: result string
11384 // rcx: first character of result 11399 // rcx: first character of result
(...skipping 16 matching lines...) Expand all
11401 // rax: first string - known to be two byte 11416 // rax: first string - known to be two byte
11402 // rbx: length of resulting flat string 11417 // rbx: length of resulting flat string
11403 // rdx: second string 11418 // rdx: second string
11404 // r8: instance type of first string 11419 // r8: instance type of first string
11405 // r9: instance type of first string 11420 // r9: instance type of first string
11406 __ bind(&non_ascii_string_add_flat_result); 11421 __ bind(&non_ascii_string_add_flat_result);
11407 __ and_(r9, Immediate(kAsciiStringTag)); 11422 __ and_(r9, Immediate(kAsciiStringTag));
11408 __ j(not_zero, &string_add_runtime); 11423 __ j(not_zero, &string_add_runtime);
11409 // Both strings are two byte strings. As they are short they are both 11424 // Both strings are two byte strings. As they are short they are both
11410 // flat. 11425 // flat.
11411 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r15, &string_add_runtime); 11426 __ AllocateTwoByteString(rcx, rbx, rdi, r14, r11, &string_add_runtime);
11412 // rcx: result string 11427 // rcx: result string
11413 __ movq(rbx, rcx); 11428 __ movq(rbx, rcx);
11414 // Locate first character of result. 11429 // Locate first character of result.
11415 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 11430 __ addq(rcx, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
11416 // Locate first character of first argument. 11431 // Locate first character of first argument.
11417 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset)); 11432 __ SmiToInteger32(rdi, FieldOperand(rax, String::kLengthOffset));
11418 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 11433 __ addq(rax, Immediate(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
11419 // rax: first char of first argument 11434 // rax: first char of first argument
11420 // rbx: result string 11435 // rbx: result string
11421 // rcx: first character of result 11436 // rcx: first character of result
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
12054 } 12069 }
12055 12070
12056 #endif 12071 #endif
12057 12072
12058 12073
12059 #undef __ 12074 #undef __
12060 12075
12061 } } // namespace v8::internal 12076 } } // namespace v8::internal
12062 12077
12063 #endif // V8_TARGET_ARCH_X64 12078 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/frames-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698