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

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

Issue 555147: Use registers to pass arguments to GenericBinaryOpStub (x64).... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 10 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
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/full-codegen-x64.cc » ('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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 // Code pattern for loading a floating point value. Input value must 200 // Code pattern for loading a floating point value. Input value must
201 // be either a smi or a heap number object (fp value). Requirements: 201 // be either a smi or a heap number object (fp value). Requirements:
202 // operand in src register. Returns operand as floating point number 202 // operand in src register. Returns operand as floating point number
203 // in XMM register 203 // in XMM register
204 static void LoadFloatOperand(MacroAssembler* masm, 204 static void LoadFloatOperand(MacroAssembler* masm,
205 Register src, 205 Register src,
206 XMMRegister dst); 206 XMMRegister dst);
207 207
208 // Code pattern for loading floating point values. Input values must 208 // Code pattern for loading floating point values. Input values must
209 // be either smi or heap number objects (fp values). Requirements: 209 // be either smi or heap number objects (fp values). Requirements:
210 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as 210 // operand_1 in rdx, operand_2 in rax; Returns operands as
211 // floating point numbers in XMM registers. 211 // floating point numbers in XMM registers.
212 static void LoadFloatOperands(MacroAssembler* masm, 212 static void LoadFloatOperands(MacroAssembler* masm,
213 XMMRegister dst1, 213 XMMRegister dst1,
214 XMMRegister dst2); 214 XMMRegister dst2);
215 215
216 // Similar to LoadFloatOperands, assumes that the operands are smis.
217 static void LoadFloatOperandsFromSmis(MacroAssembler* masm,
218 XMMRegister dst1,
219 XMMRegister dst2);
220
216 // Code pattern for loading floating point values onto the fp stack. 221 // Code pattern for loading floating point values onto the fp stack.
217 // Input values must be either smi or heap number objects (fp values). 222 // Input values must be either smi or heap number objects (fp values).
218 // Requirements: 223 // Requirements:
219 // Register version: operands in registers lhs and rhs. 224 // Register version: operands in registers lhs and rhs.
220 // Stack version: operands on TOS+1 and TOS+2. 225 // Stack version: operands on TOS+1 and TOS+2.
221 // Returns operands as floating point numbers on fp stack. 226 // Returns operands as floating point numbers on fp stack.
222 static void LoadFloatOperands(MacroAssembler* masm);
223 static void LoadFloatOperands(MacroAssembler* masm, 227 static void LoadFloatOperands(MacroAssembler* masm,
224 Register lhs, 228 Register lhs,
225 Register rhs); 229 Register rhs);
226 230
227 // Test if operands are smi or number objects (fp). Requirements: 231 // Test if operands are smi or number objects (fp). Requirements:
228 // operand_1 in rax, operand_2 in rdx; falls through on float or smi 232 // operand_1 in rax, operand_2 in rdx; falls through on float or smi
229 // operands, jumps to the non_float label otherwise. 233 // operands, jumps to the non_float label otherwise.
230 static void CheckNumberOperands(MacroAssembler* masm, 234 static void CheckNumberOperands(MacroAssembler* masm,
231 Label* non_float); 235 Label* non_float);
232 236
(...skipping 4877 matching lines...) Expand 10 before | Expand all | Expand 10 after
5110 5114
5111 if (left_is_smi && right_is_smi) { 5115 if (left_is_smi && right_is_smi) {
5112 // Compute the constant result at compile time, and leave it on the frame. 5116 // Compute the constant result at compile time, and leave it on the frame.
5113 int left_int = Smi::cast(*left.handle())->value(); 5117 int left_int = Smi::cast(*left.handle())->value();
5114 int right_int = Smi::cast(*right.handle())->value(); 5118 int right_int = Smi::cast(*right.handle())->value();
5115 if (FoldConstantSmis(op, left_int, right_int)) return; 5119 if (FoldConstantSmis(op, left_int, right_int)) return;
5116 } 5120 }
5117 5121
5118 Result answer; 5122 Result answer;
5119 if (left_is_non_smi || right_is_non_smi) { 5123 if (left_is_non_smi || right_is_non_smi) {
5120 // Go straight to the slow case, with no smi code
5121 frame_->Push(&left);
5122 frame_->Push(&right);
5123 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB); 5124 GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
5124 answer = frame_->CallStub(&stub, 2); 5125 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5125 } else if (right_is_smi) { 5126 } else if (right_is_smi) {
5126 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 5127 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
5127 type, false, overwrite_mode); 5128 type, false, overwrite_mode);
5128 } else if (left_is_smi) { 5129 } else if (left_is_smi) {
5129 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 5130 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
5130 type, true, overwrite_mode); 5131 type, true, overwrite_mode);
5131 } else { 5132 } else {
5132 // Set the flags based on the operation, type and loop nesting level. 5133 // Set the flags based on the operation, type and loop nesting level.
5133 // Bit operations always assume they likely operate on Smis. Still only 5134 // Bit operations always assume they likely operate on Smis. Still only
5134 // generate the inline Smi check code if this operation is part of a loop. 5135 // generate the inline Smi check code if this operation is part of a loop.
5135 // For all other operations only inline the Smi check code for likely smis 5136 // For all other operations only inline the Smi check code for likely smis
5136 // if the operation is part of a loop. 5137 // if the operation is part of a loop.
5137 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { 5138 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
5138 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 5139 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
5139 } else { 5140 } else {
5140 frame_->Push(&left);
5141 frame_->Push(&right);
5142 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS); 5141 GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS);
5143 answer = frame_->CallStub(&stub, 2); 5142 answer = stub.GenerateCall(masm_, frame_, &left, &right);
5144 } 5143 }
5145 } 5144 }
5146 frame_->Push(&answer); 5145 frame_->Push(&answer);
5147 } 5146 }
5148 5147
5149 5148
5150 // Emit a LoadIC call to get the value from receiver and leave it in 5149 // Emit a LoadIC call to get the value from receiver and leave it in
5151 // dst. The receiver register is restored after the call. 5150 // dst. The receiver register is restored after the call.
5152 class DeferredReferenceGetNamedValue: public DeferredCode { 5151 class DeferredReferenceGetNamedValue: public DeferredCode {
5153 public: 5152 public:
(...skipping 2340 matching lines...) Expand 10 before | Expand all | Expand 10 after
7494 __ SmiToInteger32(src, src); 7493 __ SmiToInteger32(src, src);
7495 __ cvtlsi2sd(dst, src); 7494 __ cvtlsi2sd(dst, src);
7496 7495
7497 __ bind(&done); 7496 __ bind(&done);
7498 } 7497 }
7499 7498
7500 7499
7501 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 7500 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
7502 XMMRegister dst1, 7501 XMMRegister dst1,
7503 XMMRegister dst2) { 7502 XMMRegister dst2) {
7504 __ movq(kScratchRegister, Operand(rsp, 2 * kPointerSize)); 7503 Register left = rdx;
Mads Ager (chromium) 2010/01/28 12:32:09 Does it add much to rename to left and right here.
Vladislav Kaznacheev 2010/01/28 12:38:20 Done.
7504 Register right = rax;
7505 __ movq(kScratchRegister, left);
7505 LoadFloatOperand(masm, kScratchRegister, dst1); 7506 LoadFloatOperand(masm, kScratchRegister, dst1);
7506 __ movq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); 7507 __ movq(kScratchRegister, right);
7507 LoadFloatOperand(masm, kScratchRegister, dst2); 7508 LoadFloatOperand(masm, kScratchRegister, dst2);
7508 } 7509 }
7509 7510
7510 7511
7511 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm) { 7512 void FloatingPointHelper::LoadFloatOperandsFromSmis(MacroAssembler* masm,
7512 Label load_smi_1, load_smi_2, done_load_1, done; 7513 XMMRegister dst1,
7513 __ movq(kScratchRegister, Operand(rsp, 2 * kPointerSize)); 7514 XMMRegister dst2) {
7514 __ JumpIfSmi(kScratchRegister, &load_smi_1); 7515 Register left = rdx;
Mads Ager (chromium) 2010/01/28 12:32:09 Same here.
Vladislav Kaznacheev 2010/01/28 12:38:20 Done.
7515 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset)); 7516 Register right = rax;
7516 __ bind(&done_load_1); 7517 __ SmiToInteger32(kScratchRegister, left);
7517 7518 __ cvtlsi2sd(dst1, kScratchRegister);
7518 __ movq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); 7519 __ SmiToInteger32(kScratchRegister, right);
7519 __ JumpIfSmi(kScratchRegister, &load_smi_2); 7520 __ cvtlsi2sd(dst2, kScratchRegister);
7520 __ fld_d(FieldOperand(kScratchRegister, HeapNumber::kValueOffset));
7521 __ jmp(&done);
7522
7523 __ bind(&load_smi_1);
7524 __ SmiToInteger32(kScratchRegister, kScratchRegister);
7525 __ push(kScratchRegister);
7526 __ fild_s(Operand(rsp, 0));
7527 __ pop(kScratchRegister);
7528 __ jmp(&done_load_1);
7529
7530 __ bind(&load_smi_2);
7531 __ SmiToInteger32(kScratchRegister, kScratchRegister);
7532 __ push(kScratchRegister);
7533 __ fild_s(Operand(rsp, 0));
7534 __ pop(kScratchRegister);
7535
7536 __ bind(&done);
7537 } 7521 }
7538 7522
7539 7523
7540 // Input: rdx, rax are the left and right objects of a bit op. 7524 // Input: rdx, rax are the left and right objects of a bit op.
7541 // Output: rax, rcx are left and right integers for a bit op. 7525 // Output: rax, rcx are left and right integers for a bit op.
7542 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, 7526 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
7543 bool use_sse3, 7527 bool use_sse3,
7544 Label* conversion_failure) { 7528 Label* conversion_failure) {
7545 // Check float operands. 7529 // Check float operands.
7546 Label arg1_is_object, check_undefined_arg1; 7530 Label arg1_is_object, check_undefined_arg1;
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
7780 // Update flags to indicate that arguments are in registers. 7764 // Update flags to indicate that arguments are in registers.
7781 SetArgsInRegisters(); 7765 SetArgsInRegisters();
7782 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 7766 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1);
7783 } 7767 }
7784 7768
7785 // Call the stub. 7769 // Call the stub.
7786 __ CallStub(this); 7770 __ CallStub(this);
7787 } 7771 }
7788 7772
7789 7773
7774 Result GenericBinaryOpStub::GenerateCall(MacroAssembler* masm,
7775 VirtualFrame* frame,
7776 Result* left,
7777 Result* right) {
7778 if (ArgsInRegistersSupported()) {
7779 SetArgsInRegisters();
7780 return frame->CallStub(this, left, right);
7781 } else {
7782 frame->Push(left);
7783 frame->Push(right);
7784 return frame->CallStub(this, 2);
7785 }
7786 }
7787
7788
7790 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 7789 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
7791 // Perform fast-case smi code for the operation (rax <op> rbx) and 7790 // 1. Move arguments into edx, eax except for DIV and MOD, which need the
7792 // leave result in register rax. 7791 // dividend in eax and edx free for the division. Use eax, ebx for those.
7792 Comment load_comment(masm, "-- Load arguments");
7793 Register left = rdx;
7794 Register right = rax;
7795 if (op_ == Token::DIV || op_ == Token::MOD) {
7796 left = rax;
7797 right = rbx;
7798 if (HasArgsInRegisters()) {
7799 __ movq(rbx, rax);
7800 __ movq(rax, rdx);
7801 }
7802 }
7803 if (!HasArgsInRegisters()) {
7804 __ movq(right, Operand(rsp, 1 * kPointerSize));
7805 __ movq(left, Operand(rsp, 2 * kPointerSize));
7806 }
7793 7807
7794 // Smi check both operands. 7808 // 2. Smi check both operands. Skip the check for OR as it is better combined
7795 __ JumpIfNotBothSmi(rax, rbx, slow); 7809 // with the actual operation.
7810 Label not_smis;
7811 if (op_ != Token::BIT_OR) {
7812 Comment smi_check_comment(masm, "-- Smi check arguments");
7813 __ JumpIfNotBothSmi(left, right, &not_smis);
7814 }
7796 7815
7816 // 3. Operands are both smis (except for OR), perform the operation leaving
7817 // the result in rax and check the result if necessary.
7818 Comment perform_smi(masm, "-- Perform smi operation");
7819 Label use_fp_on_smis;
7797 switch (op_) { 7820 switch (op_) {
7798 case Token::ADD: { 7821 case Token::ADD: {
7799 __ SmiAdd(rax, rax, rbx, slow); 7822 ASSERT(right.is(rax));
7823 __ SmiAdd(right, right, left, &use_fp_on_smis); // ADD is commutative.
7800 break; 7824 break;
7801 } 7825 }
7802 7826
7803 case Token::SUB: { 7827 case Token::SUB: {
7804 __ SmiSub(rax, rax, rbx, slow); 7828 __ SmiSub(left, left, right, &use_fp_on_smis);
7829 __ movq(rax, left);
7805 break; 7830 break;
7806 } 7831 }
7807 7832
7808 case Token::MUL: 7833 case Token::MUL:
7809 __ SmiMul(rax, rax, rbx, slow); 7834 ASSERT(right.is(rax));
7835 __ SmiMul(right, right, left, &use_fp_on_smis); // MUL is commutative.
7810 break; 7836 break;
7811 7837
7812 case Token::DIV: 7838 case Token::DIV:
7813 __ SmiDiv(rax, rax, rbx, slow); 7839 ASSERT(left.is(rax));
7840 __ SmiDiv(left, left, right, &use_fp_on_smis);
7814 break; 7841 break;
7815 7842
7816 case Token::MOD: 7843 case Token::MOD:
7817 __ SmiMod(rax, rax, rbx, slow); 7844 ASSERT(left.is(rax));
7845 __ SmiMod(left, left, right, slow);
7818 break; 7846 break;
7819 7847
7820 case Token::BIT_OR: 7848 case Token::BIT_OR:
7821 __ SmiOr(rax, rax, rbx); 7849 ASSERT(right.is(rax));
7850 __ movq(rcx, right); // Save the right operand.
7851 __ SmiOr(right, right, left); // BIT_OR is commutative.
7852 __ testb(right, Immediate(kSmiTagMask));
7853 __ j(not_zero, &not_smis);
7822 break; 7854 break;
7823 7855
7824 case Token::BIT_AND: 7856 case Token::BIT_AND:
7825 __ SmiAnd(rax, rax, rbx); 7857 ASSERT(right.is(rax));
7858 __ SmiAnd(right, right, left); // BIT_AND is commutative.
7826 break; 7859 break;
7827 7860
7828 case Token::BIT_XOR: 7861 case Token::BIT_XOR:
7829 __ SmiXor(rax, rax, rbx); 7862 ASSERT(right.is(rax));
7863 __ SmiXor(right, right, left); // BIT_XOR is commutative.
7830 break; 7864 break;
7831 7865
7832 case Token::SHL: 7866 case Token::SHL:
7833 case Token::SHR: 7867 case Token::SHR:
7834 case Token::SAR: 7868 case Token::SAR:
7835 // Move the second operand into register rcx.
7836 __ movq(rcx, rbx);
7837 // Perform the operation.
7838 switch (op_) { 7869 switch (op_) {
7839 case Token::SAR: 7870 case Token::SAR:
7840 __ SmiShiftArithmeticRight(rax, rax, rcx); 7871 __ SmiShiftArithmeticRight(left, left, right);
7841 break; 7872 break;
7842 case Token::SHR: 7873 case Token::SHR:
7843 __ SmiShiftLogicalRight(rax, rax, rcx, slow); 7874 __ SmiShiftLogicalRight(left, left, right, slow);
7844 break; 7875 break;
7845 case Token::SHL: 7876 case Token::SHL:
7846 __ SmiShiftLeft(rax, rax, rcx, slow); 7877 __ SmiShiftLeft(left, left, right, slow);
7847 break; 7878 break;
7848 default: 7879 default:
7849 UNREACHABLE(); 7880 UNREACHABLE();
7850 } 7881 }
7882 __ movq(rax, left);
7851 break; 7883 break;
7852 7884
7853 default: 7885 default:
7854 UNREACHABLE(); 7886 UNREACHABLE();
7855 break; 7887 break;
7856 } 7888 }
7889
7890 // 4. Emit return of result in eax.
7891 GenerateReturn(masm);
7892
7893 // 5. For some operations emit inline code to perform floating point
7894 // operations on known smis (e.g., if the result of the operation
7895 // overflowed the smi range).
7896 switch (op_) {
7897 case Token::ADD:
7898 case Token::SUB:
7899 case Token::MUL:
7900 case Token::DIV: {
7901 __ bind(&use_fp_on_smis);
7902 if (op_ == Token::DIV) {
7903 __ movq(rdx, rax);
7904 __ movq(rax, rbx);
7905 }
7906 // left is rdx, right is rax.
7907 __ AllocateHeapNumber(rbx, rcx, slow);
7908 FloatingPointHelper::LoadFloatOperandsFromSmis(masm, xmm4, xmm5);
7909 switch (op_) {
7910 case Token::ADD: __ addsd(xmm4, xmm5); break;
7911 case Token::SUB: __ subsd(xmm4, xmm5); break;
7912 case Token::MUL: __ mulsd(xmm4, xmm5); break;
7913 case Token::DIV: __ divsd(xmm4, xmm5); break;
7914 default: UNREACHABLE();
7915 }
7916 __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm4);
7917 __ movq(rax, rbx);
7918 GenerateReturn(masm);
7919 }
7920 default:
7921 break;
7922 }
7923
7924 // 6. Non-smi operands, fall out to the non-smi code with the operands in
7925 // edx and eax.
Mads Ager (chromium) 2010/01/28 12:32:09 edx -> rdx eax -> rax
Vladislav Kaznacheev 2010/01/28 12:38:20 Done.
7926 Comment done_comment(masm, "-- Enter non-smi code");
7927 __ bind(&not_smis);
7928
7929 switch (op_) {
7930 case Token::DIV:
7931 case Token::MOD:
7932 // Operands are in rax, rbx at this point.
7933 __ movq(rdx, rax);
7934 __ movq(rax, rbx);
7935 break;
7936
7937 case Token::BIT_OR:
7938 // Right operand is saved in rcx and rax was destroyed by the smi
7939 // operation.
7940 __ movq(rax, rcx);
7941 break;
7942
7943 default:
7944 break;
7945 }
7857 } 7946 }
7858 7947
7859 7948
7860 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 7949 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
7861 Label call_runtime; 7950 Label call_runtime;
7862 if (HasSmiCodeInStub()) { 7951 if (HasSmiCodeInStub()) {
7863 // The fast case smi code wasn't inlined in the stub caller 7952 GenerateSmiCode(masm, &call_runtime);
7864 // code. Generate it here to speed up common operations. 7953 } else if (op_ != Token::MOD) {
7865 Label slow; 7954 GenerateLoadArguments(masm);
7866 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // get y
7867 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // get x
7868 GenerateSmiCode(masm, &slow);
7869 GenerateReturn(masm);
7870
7871 // Too bad. The fast case smi code didn't succeed.
7872 __ bind(&slow);
7873 } 7955 }
7874
7875 // Make sure the arguments are in rdx and rax.
7876 GenerateLoadArguments(masm);
7877
7878 // Floating point case. 7956 // Floating point case.
7879 switch (op_) { 7957 switch (op_) {
7880 case Token::ADD: 7958 case Token::ADD:
7881 case Token::SUB: 7959 case Token::SUB:
7882 case Token::MUL: 7960 case Token::MUL:
7883 case Token::DIV: { 7961 case Token::DIV: {
7884 // rax: y 7962 // rax: y
7885 // rdx: x 7963 // rdx: x
7886 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 7964 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
7887 // Fast-case: Both operands are numbers. 7965 // Fast-case: Both operands are numbers.
7966 // xmm4 and xmm5 are volatile XMM registers.
7967 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
7968
7969 switch (op_) {
7970 case Token::ADD: __ addsd(xmm4, xmm5); break;
7971 case Token::SUB: __ subsd(xmm4, xmm5); break;
7972 case Token::MUL: __ mulsd(xmm4, xmm5); break;
7973 case Token::DIV: __ divsd(xmm4, xmm5); break;
7974 default: UNREACHABLE();
7975 }
7888 // Allocate a heap number, if needed. 7976 // Allocate a heap number, if needed.
7889 Label skip_allocation; 7977 Label skip_allocation;
7890 switch (mode_) { 7978 OverwriteMode mode = mode_;
7979 if (HasArgsReversed()) {
7980 if (mode == OVERWRITE_RIGHT) {
7981 mode = OVERWRITE_LEFT;
7982 } else if (mode == OVERWRITE_LEFT) {
7983 mode = OVERWRITE_RIGHT;
7984 }
7985 }
7986 switch (mode) {
7891 case OVERWRITE_LEFT: 7987 case OVERWRITE_LEFT:
7988 __ JumpIfNotSmi(rdx, &skip_allocation);
7989 __ AllocateHeapNumber(rbx, rcx, &call_runtime);
7990 __ movq(rdx, rbx);
7991 __ bind(&skip_allocation);
7892 __ movq(rax, rdx); 7992 __ movq(rax, rdx);
7893 // Fall through! 7993 break;
7894 case OVERWRITE_RIGHT: 7994 case OVERWRITE_RIGHT:
7895 // If the argument in rax is already an object, we skip the 7995 // If the argument in rax is already an object, we skip the
7896 // allocation of a heap number. 7996 // allocation of a heap number.
7897 __ JumpIfNotSmi(rax, &skip_allocation); 7997 __ JumpIfNotSmi(rax, &skip_allocation);
7898 // Fall through! 7998 // Fall through!
7899 case NO_OVERWRITE: 7999 case NO_OVERWRITE:
7900 // Allocate a heap number for the result. Keep rax and rdx intact 8000 // Allocate a heap number for the result. Keep rax and rdx intact
7901 // for the possible runtime call. 8001 // for the possible runtime call.
7902 __ AllocateHeapNumber(rbx, rcx, &call_runtime); 8002 __ AllocateHeapNumber(rbx, rcx, &call_runtime);
7903 __ movq(rax, rbx); 8003 __ movq(rax, rbx);
7904 __ bind(&skip_allocation); 8004 __ bind(&skip_allocation);
7905 break; 8005 break;
7906 default: UNREACHABLE(); 8006 default: UNREACHABLE();
7907 } 8007 }
7908 // xmm4 and xmm5 are volatile XMM registers.
7909 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
7910
7911 switch (op_) {
7912 case Token::ADD: __ addsd(xmm4, xmm5); break;
7913 case Token::SUB: __ subsd(xmm4, xmm5); break;
7914 case Token::MUL: __ mulsd(xmm4, xmm5); break;
7915 case Token::DIV: __ divsd(xmm4, xmm5); break;
7916 default: UNREACHABLE();
7917 }
7918 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4); 8008 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
7919 GenerateReturn(masm); 8009 GenerateReturn(masm);
7920 } 8010 }
7921 case Token::MOD: { 8011 case Token::MOD: {
7922 // For MOD we go directly to runtime in the non-smi case. 8012 // For MOD we go directly to runtime in the non-smi case.
7923 break; 8013 break;
7924 } 8014 }
7925 case Token::BIT_OR: 8015 case Token::BIT_OR:
7926 case Token::BIT_AND: 8016 case Token::BIT_AND:
7927 case Token::BIT_XOR: 8017 case Token::BIT_XOR:
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
7974 __ movq(Operand(rsp, 1 * kPointerSize), rbx); 8064 __ movq(Operand(rsp, 1 * kPointerSize), rbx);
7975 __ fild_s(Operand(rsp, 1 * kPointerSize)); 8065 __ fild_s(Operand(rsp, 1 * kPointerSize));
7976 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset)); 8066 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
7977 GenerateReturn(masm); 8067 GenerateReturn(masm);
7978 } 8068 }
7979 8069
7980 // SHR should return uint32 - go to runtime for non-smi/negative result. 8070 // SHR should return uint32 - go to runtime for non-smi/negative result.
7981 if (op_ == Token::SHR) { 8071 if (op_ == Token::SHR) {
7982 __ bind(&non_smi_result); 8072 __ bind(&non_smi_result);
7983 } 8073 }
7984 __ movq(rax, Operand(rsp, 1 * kPointerSize));
7985 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
7986 break; 8074 break;
7987 } 8075 }
7988 default: UNREACHABLE(); break; 8076 default: UNREACHABLE(); break;
7989 } 8077 }
7990 8078
7991 // If all else fails, use the runtime system to get the correct 8079 // If all else fails, use the runtime system to get the correct
7992 // result. If arguments was passed in registers now place them on the 8080 // result. If arguments was passed in registers now place them on the
7993 // stack in the correct order below the return address. 8081 // stack in the correct order below the return address.
7994 __ bind(&call_runtime); 8082 __ bind(&call_runtime);
7995 if (HasArgumentsInRegisters()) { 8083 if (HasArgsInRegisters()) {
7996 __ pop(rcx); 8084 __ pop(rcx);
7997 if (HasArgumentsReversed()) { 8085 if (HasArgsReversed()) {
7998 __ push(rax); 8086 __ push(rax);
7999 __ push(rdx); 8087 __ push(rdx);
8000 } else { 8088 } else {
8001 __ push(rdx); 8089 __ push(rdx);
8002 __ push(rax); 8090 __ push(rax);
8003 } 8091 }
8004 __ push(rcx); 8092 __ push(rcx);
8005 } 8093 }
8006 switch (op_) { 8094 switch (op_) {
8007 case Token::ADD: { 8095 case Token::ADD: {
8008 // Test for string arguments before calling runtime. 8096 // Test for string arguments before calling runtime.
8009 Label not_strings, both_strings, not_string1, string1; 8097 Label not_strings, both_strings, not_string1, string1;
8010 Condition is_smi; 8098 Condition is_smi;
8011 Result answer; 8099 Result answer;
8012 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // First argument.
8013 __ movq(rax, Operand(rsp, 1 * kPointerSize)); // Second argument.
8014 is_smi = masm->CheckSmi(rdx); 8100 is_smi = masm->CheckSmi(rdx);
8015 __ j(is_smi, &not_string1); 8101 __ j(is_smi, &not_string1);
8016 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx); 8102 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx);
8017 __ j(above_equal, &not_string1); 8103 __ j(above_equal, &not_string1);
8018 8104
8019 // First argument is a a string, test second. 8105 // First argument is a a string, test second.
8020 is_smi = masm->CheckSmi(rax); 8106 is_smi = masm->CheckSmi(rax);
8021 __ j(is_smi, &string1); 8107 __ j(is_smi, &string1);
8022 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); 8108 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax);
8023 __ j(above_equal, &string1); 8109 __ j(above_equal, &string1);
8024 8110
8025 // First and second argument are strings. 8111 // First and second argument are strings.
8026 StringAddStub stub(NO_STRING_CHECK_IN_STUB); 8112 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
8027 __ TailCallStub(&stub); 8113 __ TailCallStub(&stub);
8028 8114
8029 // Only first argument is a string. 8115 // Only first argument is a string.
8030 __ bind(&string1); 8116 __ bind(&string1);
8031 __ InvokeBuiltin(Builtins::STRING_ADD_LEFT, JUMP_FUNCTION); 8117 __ InvokeBuiltin(
8118 HasArgsReversed() ?
8119 Builtins::STRING_ADD_RIGHT :
8120 Builtins::STRING_ADD_LEFT,
8121 JUMP_FUNCTION);
8032 8122
8033 // First argument was not a string, test second. 8123 // First argument was not a string, test second.
8034 __ bind(&not_string1); 8124 __ bind(&not_string1);
8035 is_smi = masm->CheckSmi(rax); 8125 is_smi = masm->CheckSmi(rax);
8036 __ j(is_smi, &not_strings); 8126 __ j(is_smi, &not_strings);
8037 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); 8127 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax);
8038 __ j(above_equal, &not_strings); 8128 __ j(above_equal, &not_strings);
8039 8129
8040 // Only second argument is a string. 8130 // Only second argument is a string.
8041 __ InvokeBuiltin(Builtins::STRING_ADD_RIGHT, JUMP_FUNCTION); 8131 __ InvokeBuiltin(
8132 HasArgsReversed() ?
8133 Builtins::STRING_ADD_LEFT :
8134 Builtins::STRING_ADD_RIGHT,
8135 JUMP_FUNCTION);
8042 8136
8043 __ bind(&not_strings); 8137 __ bind(&not_strings);
8044 // Neither argument is a string. 8138 // Neither argument is a string.
8045 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION); 8139 __ InvokeBuiltin(Builtins::ADD, JUMP_FUNCTION);
8046 break; 8140 break;
8047 } 8141 }
8048 case Token::SUB: 8142 case Token::SUB:
8049 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION); 8143 __ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
8050 break; 8144 break;
8051 case Token::MUL: 8145 case Token::MUL:
8052 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION); 8146 __ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
8053 break; 8147 break;
8054 case Token::DIV: 8148 case Token::DIV:
8055 __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION); 8149 __ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
8056 break; 8150 break;
8057 case Token::MOD: 8151 case Token::MOD:
8058 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); 8152 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION);
8059 break; 8153 break;
8060 case Token::BIT_OR: 8154 case Token::BIT_OR:
8061 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION); 8155 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_FUNCTION);
8062 break; 8156 break;
8063 case Token::BIT_AND: 8157 case Token::BIT_AND:
(...skipping 12 matching lines...) Expand all
8076 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); 8170 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
8077 break; 8171 break;
8078 default: 8172 default:
8079 UNREACHABLE(); 8173 UNREACHABLE();
8080 } 8174 }
8081 } 8175 }
8082 8176
8083 8177
8084 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) { 8178 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) {
8085 // If arguments are not passed in registers read them from the stack. 8179 // If arguments are not passed in registers read them from the stack.
8086 if (!HasArgumentsInRegisters()) { 8180 if (!HasArgsInRegisters()) {
8087 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 8181 __ movq(rax, Operand(rsp, 1 * kPointerSize));
8088 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 8182 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
8089 } 8183 }
8090 } 8184 }
8091 8185
8092 8186
8093 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) { 8187 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) {
8094 // If arguments are not passed in registers remove them from the stack before 8188 // If arguments are not passed in registers remove them from the stack before
8095 // returning. 8189 // returning.
8096 if (!HasArgumentsInRegisters()) { 8190 if (!HasArgsInRegisters()) {
8097 __ ret(2 * kPointerSize); // Remove both operands 8191 __ ret(2 * kPointerSize); // Remove both operands
8098 } else { 8192 } else {
8099 __ ret(0); 8193 __ ret(0);
8100 } 8194 }
8101 } 8195 }
8102 8196
8103 8197
8104 int CompareStub::MinorKey() { 8198 int CompareStub::MinorKey() {
8105 // Encode the three parameters in a unique 16 bit value. 8199 // Encode the three parameters in a unique 16 bit value.
8106 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); 8200 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
8756 // Call the function from C++. 8850 // Call the function from C++.
8757 return FUNCTION_CAST<ModuloFunction>(buffer); 8851 return FUNCTION_CAST<ModuloFunction>(buffer);
8758 } 8852 }
8759 8853
8760 #endif 8854 #endif
8761 8855
8762 8856
8763 #undef __ 8857 #undef __
8764 8858
8765 } } // namespace v8::internal 8859 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698