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

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

Issue 845002: Porting binary op ICs to x64. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 8318 matching lines...) Expand 10 before | Expand all | Expand 10 after
8329 const char* op_name = Token::Name(op_); 8329 const char* op_name = Token::Name(op_);
8330 const char* overwrite_name; 8330 const char* overwrite_name;
8331 switch (mode_) { 8331 switch (mode_) {
8332 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 8332 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
8333 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 8333 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
8334 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 8334 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
8335 default: overwrite_name = "UnknownOverwrite"; break; 8335 default: overwrite_name = "UnknownOverwrite"; break;
8336 } 8336 }
8337 8337
8338 OS::SNPrintF(Vector<char>(name_, len), 8338 OS::SNPrintF(Vector<char>(name_, len),
8339 "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s", 8339 "GenericBinaryOpStub_%s_%s%s_%s%s_%s%s_%s",
8340 op_name, 8340 op_name,
8341 overwrite_name, 8341 overwrite_name,
8342 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 8342 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
8343 args_in_registers_ ? "RegArgs" : "StackArgs", 8343 args_in_registers_ ? "RegArgs" : "StackArgs",
8344 args_reversed_ ? "_R" : "", 8344 args_reversed_ ? "_R" : "",
8345 use_sse3_ ? "SSE3" : "SSE2", 8345 use_sse3_ ? "SSE3" : "SSE2",
8346 operands_type_.ToString()); 8346 static_operands_type_.ToString(),
8347 BinaryOpIC::GetName(runtime_operands_type_));
8347 return name_; 8348 return name_;
8348 } 8349 }
8349 8350
8350 8351
8351 void GenericBinaryOpStub::GenerateCall( 8352 void GenericBinaryOpStub::GenerateCall(
8352 MacroAssembler* masm, 8353 MacroAssembler* masm,
8353 Register left, 8354 Register left,
8354 Register right) { 8355 Register right) {
8355 if (!ArgsInRegistersSupported()) { 8356 if (!ArgsInRegistersSupported()) {
8356 // Pass arguments on the stack. 8357 // Pass arguments on the stack.
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
8647 break; 8648 break;
8648 8649
8649 default: 8650 default:
8650 break; 8651 break;
8651 } 8652 }
8652 } 8653 }
8653 8654
8654 8655
8655 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 8656 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
8656 Label call_runtime; 8657 Label call_runtime;
8657 if (HasSmiCodeInStub()) { 8658
8659 if (ShouldGenerateSmiCode()) {
8658 GenerateSmiCode(masm, &call_runtime); 8660 GenerateSmiCode(masm, &call_runtime);
8659 } else if (op_ != Token::MOD) { 8661 } else if (op_ != Token::MOD) {
8660 GenerateLoadArguments(masm); 8662 if (!HasArgsInRegisters()) {
8663 GenerateLoadArguments(masm);
8664 }
8661 } 8665 }
8662 // Floating point case. 8666 // Floating point case.
8663 switch (op_) { 8667 if (ShouldGenerateFPCode()) {
8664 case Token::ADD: 8668 switch (op_) {
8665 case Token::SUB: 8669 case Token::ADD:
8666 case Token::MUL: 8670 case Token::SUB:
8667 case Token::DIV: { 8671 case Token::MUL:
8668 // rax: y 8672 case Token::DIV: {
8669 // rdx: x 8673 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
8670 if (operands_type_.IsNumber()) { 8674 HasSmiCodeInStub()) {
8675 // Execution reaches this point when the first non-smi argument occurs
8676 // (and only if smi code is generated). This is the right moment to
8677 // patch to HEAP_NUMBERS state. The transition is attempted only for
8678 // the four basic operations. The stub stays in the DEFAULT state
8679 // forever for all other operations (also if smi code is skipped).
8680 GenerateTypeTransition(masm);
8681 }
8682
8683 Label not_floats;
8684 // rax: y
8685 // rdx: x
8686 if (static_operands_type_.IsNumber()) {
8671 if (FLAG_debug_code) { 8687 if (FLAG_debug_code) {
8672 // Assert at runtime that inputs are only numbers. 8688 // Assert at runtime that inputs are only numbers.
8673 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); 8689 __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number.");
8674 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number."); 8690 __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number.");
8675 } 8691 }
8676 } else { 8692 } else {
8677 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); 8693 FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
8678 } 8694 }
8679 // Fast-case: Both operands are numbers. 8695 // Fast-case: Both operands are numbers.
8680 // xmm4 and xmm5 are volatile XMM registers. 8696 // xmm4 and xmm5 are volatile XMM registers.
8681 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5); 8697 FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
8682 8698
8683 switch (op_) { 8699 switch (op_) {
8684 case Token::ADD: __ addsd(xmm4, xmm5); break; 8700 case Token::ADD: __ addsd(xmm4, xmm5); break;
8685 case Token::SUB: __ subsd(xmm4, xmm5); break; 8701 case Token::SUB: __ subsd(xmm4, xmm5); break;
8686 case Token::MUL: __ mulsd(xmm4, xmm5); break; 8702 case Token::MUL: __ mulsd(xmm4, xmm5); break;
8687 case Token::DIV: __ divsd(xmm4, xmm5); break; 8703 case Token::DIV: __ divsd(xmm4, xmm5); break;
8688 default: UNREACHABLE(); 8704 default: UNREACHABLE();
8689 }
8690 // Allocate a heap number, if needed.
8691 Label skip_allocation;
8692 OverwriteMode mode = mode_;
8693 if (HasArgsReversed()) {
8694 if (mode == OVERWRITE_RIGHT) {
8695 mode = OVERWRITE_LEFT;
8696 } else if (mode == OVERWRITE_LEFT) {
8697 mode = OVERWRITE_RIGHT;
8698 } 8705 }
8699 } 8706 // Allocate a heap number, if needed.
8700 switch (mode) { 8707 Label skip_allocation;
8701 case OVERWRITE_LEFT: 8708 OverwriteMode mode = mode_;
8702 __ JumpIfNotSmi(rdx, &skip_allocation); 8709 if (HasArgsReversed()) {
8703 __ AllocateHeapNumber(rbx, rcx, &call_runtime); 8710 if (mode == OVERWRITE_RIGHT) {
8704 __ movq(rdx, rbx); 8711 mode = OVERWRITE_LEFT;
8705 __ bind(&skip_allocation); 8712 } else if (mode == OVERWRITE_LEFT) {
8706 __ movq(rax, rdx); 8713 mode = OVERWRITE_RIGHT;
8707 break; 8714 }
8708 case OVERWRITE_RIGHT: 8715 }
8709 // If the argument in rax is already an object, we skip the 8716 switch (mode) {
8710 // allocation of a heap number.
8711 __ JumpIfNotSmi(rax, &skip_allocation);
8712 // Fall through!
8713 case NO_OVERWRITE:
8714 // Allocate a heap number for the result. Keep rax and rdx intact
8715 // for the possible runtime call.
8716 __ AllocateHeapNumber(rbx, rcx, &call_runtime);
8717 __ movq(rax, rbx);
8718 __ bind(&skip_allocation);
8719 break;
8720 default: UNREACHABLE();
8721 }
8722 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
8723 GenerateReturn(masm);
8724 }
8725 case Token::MOD: {
8726 // For MOD we go directly to runtime in the non-smi case.
8727 break;
8728 }
8729 case Token::BIT_OR:
8730 case Token::BIT_AND:
8731 case Token::BIT_XOR:
8732 case Token::SAR:
8733 case Token::SHL:
8734 case Token::SHR: {
8735 Label skip_allocation, non_smi_result;
8736 FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
8737 switch (op_) {
8738 case Token::BIT_OR: __ orl(rax, rcx); break;
8739 case Token::BIT_AND: __ andl(rax, rcx); break;
8740 case Token::BIT_XOR: __ xorl(rax, rcx); break;
8741 case Token::SAR: __ sarl_cl(rax); break;
8742 case Token::SHL: __ shll_cl(rax); break;
8743 case Token::SHR: __ shrl_cl(rax); break;
8744 default: UNREACHABLE();
8745 }
8746 if (op_ == Token::SHR) {
8747 // Check if result is non-negative. This can only happen for a shift
8748 // by zero, which also doesn't update the sign flag.
8749 __ testl(rax, rax);
8750 __ j(negative, &non_smi_result);
8751 }
8752 __ JumpIfNotValidSmiValue(rax, &non_smi_result);
8753 // Tag smi result, if possible, and return.
8754 __ Integer32ToSmi(rax, rax);
8755 GenerateReturn(masm);
8756
8757 // All ops except SHR return a signed int32 that we load in a HeapNumber.
8758 if (op_ != Token::SHR && non_smi_result.is_linked()) {
8759 __ bind(&non_smi_result);
8760 // Allocate a heap number if needed.
8761 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result
8762 switch (mode_) {
8763 case OVERWRITE_LEFT: 8717 case OVERWRITE_LEFT:
8718 __ JumpIfNotSmi(rdx, &skip_allocation);
8719 __ AllocateHeapNumber(rbx, rcx, &call_runtime);
8720 __ movq(rdx, rbx);
8721 __ bind(&skip_allocation);
8722 __ movq(rax, rdx);
8723 break;
8764 case OVERWRITE_RIGHT: 8724 case OVERWRITE_RIGHT:
8765 // If the operand was an object, we skip the 8725 // If the argument in rax is already an object, we skip the
8766 // allocation of a heap number. 8726 // allocation of a heap number.
8767 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
8768 1 * kPointerSize : 2 * kPointerSize));
8769 __ JumpIfNotSmi(rax, &skip_allocation); 8727 __ JumpIfNotSmi(rax, &skip_allocation);
8770 // Fall through! 8728 // Fall through!
8771 case NO_OVERWRITE: 8729 case NO_OVERWRITE:
8772 __ AllocateHeapNumber(rax, rcx, &call_runtime); 8730 // Allocate a heap number for the result. Keep rax and rdx intact
8731 // for the possible runtime call.
8732 __ AllocateHeapNumber(rbx, rcx, &call_runtime);
8733 __ movq(rax, rbx);
8773 __ bind(&skip_allocation); 8734 __ bind(&skip_allocation);
8774 break; 8735 break;
8775 default: UNREACHABLE(); 8736 default: UNREACHABLE();
8776 } 8737 }
8777 // Store the result in the HeapNumber and return. 8738 __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
8778 __ movq(Operand(rsp, 1 * kPointerSize), rbx);
8779 __ fild_s(Operand(rsp, 1 * kPointerSize));
8780 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
8781 GenerateReturn(masm); 8739 GenerateReturn(masm);
8740 __ bind(&not_floats);
8741 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
8742 !HasSmiCodeInStub()) {
8743 // Execution reaches this point when the first non-number argument
8744 // occurs (and only if smi code is skipped from the stub, otherwise
8745 // the patching has already been done earlier in this case branch).
8746 // A perfect moment to try patching to STRINGS for ADD operation.
8747 if (op_ == Token::ADD) {
Mads Ager (chromium) 2010/03/17 10:10:59 Indentation is off here.
Vladislav Kaznacheev 2010/03/18 11:14:23 Done.
8748 GenerateTypeTransition(masm);
8749 }
8750 }
8751 break;
8782 } 8752 }
8753 case Token::MOD: {
8754 // For MOD we go directly to runtime in the non-smi case.
8755 break;
8756 }
8757 case Token::BIT_OR:
8758 case Token::BIT_AND:
8759 case Token::BIT_XOR:
8760 case Token::SAR:
8761 case Token::SHL:
8762 case Token::SHR: {
8763 Label skip_allocation, non_smi_result;
8764 FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
8765 switch (op_) {
8766 case Token::BIT_OR: __ orl(rax, rcx); break;
8767 case Token::BIT_AND: __ andl(rax, rcx); break;
8768 case Token::BIT_XOR: __ xorl(rax, rcx); break;
8769 case Token::SAR: __ sarl_cl(rax); break;
8770 case Token::SHL: __ shll_cl(rax); break;
8771 case Token::SHR: __ shrl_cl(rax); break;
8772 default: UNREACHABLE();
8773 }
8774 if (op_ == Token::SHR) {
8775 // Check if result is non-negative. This can only happen for a shift
8776 // by zero, which also doesn't update the sign flag.
8777 __ testl(rax, rax);
8778 __ j(negative, &non_smi_result);
8779 }
8780 __ JumpIfNotValidSmiValue(rax, &non_smi_result);
8781 // Tag smi result, if possible, and return.
8782 __ Integer32ToSmi(rax, rax);
8783 GenerateReturn(masm);
8783 8784
8784 // SHR should return uint32 - go to runtime for non-smi/negative result. 8785 // All ops except SHR return a signed int32 that we load in
8785 if (op_ == Token::SHR) { 8786 // a HeapNumber.
8786 __ bind(&non_smi_result); 8787 if (op_ != Token::SHR && non_smi_result.is_linked()) {
8788 __ bind(&non_smi_result);
8789 // Allocate a heap number if needed.
8790 __ movsxlq(rbx, rax); // rbx: sign extended 32-bit result
8791 switch (mode_) {
8792 case OVERWRITE_LEFT:
8793 case OVERWRITE_RIGHT:
8794 // If the operand was an object, we skip the
8795 // allocation of a heap number.
8796 __ movq(rax, Operand(rsp, mode_ == OVERWRITE_RIGHT ?
8797 1 * kPointerSize : 2 * kPointerSize));
8798 __ JumpIfNotSmi(rax, &skip_allocation);
8799 // Fall through!
8800 case NO_OVERWRITE:
8801 __ AllocateHeapNumber(rax, rcx, &call_runtime);
8802 __ bind(&skip_allocation);
8803 break;
8804 default: UNREACHABLE();
8805 }
8806 // Store the result in the HeapNumber and return.
8807 __ movq(Operand(rsp, 1 * kPointerSize), rbx);
8808 __ fild_s(Operand(rsp, 1 * kPointerSize));
8809 __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
8810 GenerateReturn(masm);
8811 }
8812
8813 // SHR should return uint32 - go to runtime for non-smi/negative result.
8814 if (op_ == Token::SHR) {
8815 __ bind(&non_smi_result);
8816 }
8817 break;
8787 } 8818 }
8788 break; 8819 default: UNREACHABLE(); break;
8789 } 8820 }
8790 default: UNREACHABLE(); break;
8791 } 8821 }
8792 8822
8793 // If all else fails, use the runtime system to get the correct 8823 // If all else fails, use the runtime system to get the correct
8794 // result. If arguments was passed in registers now place them on the 8824 // result. If arguments was passed in registers now place them on the
8795 // stack in the correct order below the return address. 8825 // stack in the correct order below the return address.
8796 __ bind(&call_runtime); 8826 __ bind(&call_runtime);
8797 if (HasArgsInRegisters()) { 8827 if (HasArgsInRegisters()) {
8798 __ pop(rcx); 8828 GenerateRegisterArgsPush(masm);
8799 if (HasArgsReversed()) {
8800 __ push(rax);
8801 __ push(rdx);
8802 } else {
8803 __ push(rdx);
8804 __ push(rax);
8805 }
8806 __ push(rcx);
8807 } 8829 }
8830
8808 switch (op_) { 8831 switch (op_) {
8809 case Token::ADD: { 8832 case Token::ADD: {
8810 // Test for string arguments before calling runtime. 8833 // Test for string arguments before calling runtime.
8811 Label not_strings, both_strings, not_string1, string1; 8834 Label not_strings, both_strings, not_string1, string1;
8835
8836 // If this stub has already generated FP-specific code then the arguments
8837 // are already in rdx, rax
8838 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) {
8839 GenerateLoadArguments(masm);
8840 }
8841
8812 Condition is_smi; 8842 Condition is_smi;
8813 Result answer;
8814 is_smi = masm->CheckSmi(rdx); 8843 is_smi = masm->CheckSmi(rdx);
8815 __ j(is_smi, &not_string1); 8844 __ j(is_smi, &not_string1);
8816 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx); 8845 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rdx);
8817 __ j(above_equal, &not_string1); 8846 __ j(above_equal, &not_string1);
8818 8847
8819 // First argument is a a string, test second. 8848 // First argument is a a string, test second.
8820 is_smi = masm->CheckSmi(rax); 8849 is_smi = masm->CheckSmi(rax);
8821 __ j(is_smi, &string1); 8850 __ j(is_smi, &string1);
8822 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax); 8851 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rax);
8823 __ j(above_equal, &string1); 8852 __ j(above_equal, &string1);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
8879 break; 8908 break;
8880 case Token::SHL: 8909 case Token::SHL:
8881 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); 8910 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
8882 break; 8911 break;
8883 case Token::SHR: 8912 case Token::SHR:
8884 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); 8913 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
8885 break; 8914 break;
8886 default: 8915 default:
8887 UNREACHABLE(); 8916 UNREACHABLE();
8888 } 8917 }
8918
8919 // Generate an unreachable reference to the DEFAULT stub so that it can be
Mads Ager (chromium) 2010/03/17 10:10:59 This still feels like a nasty hack to me. Does th
Vladislav Kaznacheev 2010/03/18 11:14:23 Added a TODO to experiment and remove. On 2010/03/
8920 // found at the end of this stub when clearing ICs at GC.
8921 if (runtime_operands_type_ != BinaryOpIC::DEFAULT) {
8922 GenericBinaryOpStub uninit(MinorKey(), BinaryOpIC::DEFAULT);
8923 __ TailCallStub(&uninit);
8924 }
8889 } 8925 }
8890 8926
8891 8927
8892 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) { 8928 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) {
8893 // If arguments are not passed in registers read them from the stack. 8929 ASSERT(!HasArgsInRegisters());
8894 if (!HasArgsInRegisters()) { 8930 __ movq(rax, Operand(rsp, 1 * kPointerSize));
8895 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 8931 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
8896 __ movq(rdx, Operand(rsp, 2 * kPointerSize));
8897 }
8898 } 8932 }
8899 8933
8900 8934
8901 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) { 8935 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) {
8902 // If arguments are not passed in registers remove them from the stack before 8936 // If arguments are not passed in registers remove them from the stack before
8903 // returning. 8937 // returning.
8904 if (!HasArgsInRegisters()) { 8938 if (!HasArgsInRegisters()) {
8905 __ ret(2 * kPointerSize); // Remove both operands 8939 __ ret(2 * kPointerSize); // Remove both operands
8906 } else { 8940 } else {
8907 __ ret(0); 8941 __ ret(0);
8908 } 8942 }
8909 } 8943 }
8910 8944
8911 8945
8946 void GenericBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
8947 ASSERT(HasArgsInRegisters());
8948 __ pop(rcx);
8949 if (HasArgsReversed()) {
8950 __ push(rax);
8951 __ push(rdx);
8952 } else {
8953 __ push(rdx);
8954 __ push(rax);
8955 }
8956 __ push(rcx);
8957 }
8958
8959
8960 void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
8961 Label get_result;
8962
8963 // Keep a copy of operands on the stack and make sure they are also in
8964 // edx, eax.
Mads Ager (chromium) 2010/03/17 10:10:59 ia32 register names.
Vladislav Kaznacheev 2010/03/18 11:14:23 Done.
8965 if (HasArgsInRegisters()) {
8966 GenerateRegisterArgsPush(masm);
8967 } else {
8968 GenerateLoadArguments(masm);
8969 }
8970
8971 // Internal frame is necessary to handle exceptions properly.
8972 __ EnterInternalFrame();
8973
8974 // Push arguments on stack if the stub expects them there.
8975 if (!HasArgsInRegisters()) {
8976 __ push(rdx);
8977 __ push(rax);
8978 }
8979 // Call the stub proper to get the result in rax.
8980 __ call(&get_result);
8981 __ LeaveInternalFrame();
8982
8983 // Left and right arguments are already on stack.
8984 __ pop(rcx);
8985 // Push the operation result. The tail call to BinaryOp_Patch will
8986 // return it to the original caller..
8987 __ push(rax);
8988
8989 // Push this stub's key.
8990 __ movq(rax, Immediate(MinorKey()));
8991 __ Integer32ToSmi(rax, rax);
8992 __ push(rax);
8993
8994 // Although the operation and the type info are encoded into the key,
8995 // the encoding is opaque, so push them too.
8996 __ movq(rax, Immediate(op_));
8997 __ Integer32ToSmi(rax, rax);
8998 __ push(rax);
8999
9000 __ movq(rax, Immediate(runtime_operands_type_));
9001 __ Integer32ToSmi(rax, rax);
9002 __ push(rax);
9003
9004 __ push(rcx);
9005
9006 // Perform patching to an appropriate fast case and return the result.
9007 __ TailCallExternalReference(
9008 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
9009 6,
9010 1);
9011
9012 // The entry point for the result calculation is assumed to be immediately
9013 // after this sequence.
9014 __ bind(&get_result);
9015 }
9016
9017
8912 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { 9018 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
8913 return Handle<Code>::null(); 9019 GenericBinaryOpStub stub(key, type_info);
9020 HandleScope scope;
Mads Ager (chromium) 2010/03/17 10:10:59 This returns a handle from a destroyed handle scop
Vladislav Kaznacheev 2010/03/18 11:14:23 Done.
9021 return stub.GetCode();
8914 } 9022 }
8915 9023
8916 9024
8917 int CompareStub::MinorKey() { 9025 int CompareStub::MinorKey() {
8918 // Encode the three parameters in a unique 16 bit value. 9026 // Encode the three parameters in a unique 16 bit value.
8919 ASSERT(static_cast<unsigned>(cc_) < (1 << 14)); 9027 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
8920 int nnn_value = (never_nan_nan_ ? 2 : 0); 9028 int nnn_value = (never_nan_nan_ ? 2 : 0);
8921 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs. 9029 if (cc_ != equal) nnn_value = 0; // Avoid duplicate stubs.
8922 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0); 9030 return (static_cast<unsigned>(cc_) << 2) | nnn_value | (strict_ ? 1 : 0);
8923 } 9031 }
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after
9798 // Call the function from C++. 9906 // Call the function from C++.
9799 return FUNCTION_CAST<ModuloFunction>(buffer); 9907 return FUNCTION_CAST<ModuloFunction>(buffer);
9800 } 9908 }
9801 9909
9802 #endif 9910 #endif
9803 9911
9804 9912
9805 #undef __ 9913 #undef __
9806 9914
9807 } } // namespace v8::internal 9915 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698