OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_outermost_js); | 9984 __ j(not_zero, ¬_outermost_js); |
9973 __ movq(rax, rbp); | 9985 __ movq(rax, rbp); |
9974 __ store_rax(js_entry_sp); | 9986 __ store_rax(js_entry_sp); |
9975 __ bind(¬_outermost_js); | 9987 __ bind(¬_outermost_js); |
9976 #endif | 9988 #endif |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10027 __ bind(¬_outermost_js_2); | 10039 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |