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

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

Issue 668151: Make more use of the NumberInfo data.... (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
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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and 726 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and
727 // convert it to a boolean in the condition code register or jump to 727 // convert it to a boolean in the condition code register or jump to
728 // 'false_target'/'true_target' as appropriate. 728 // 'false_target'/'true_target' as appropriate.
729 void CodeGenerator::ToBoolean(ControlDestination* dest) { 729 void CodeGenerator::ToBoolean(ControlDestination* dest) {
730 Comment cmnt(masm_, "[ ToBoolean"); 730 Comment cmnt(masm_, "[ ToBoolean");
731 731
732 // The value to convert should be popped from the frame. 732 // The value to convert should be popped from the frame.
733 Result value = frame_->Pop(); 733 Result value = frame_->Pop();
734 value.ToRegister(); 734 value.ToRegister();
735 735
736 if (value.is_number()) { 736 if (value.is_integer32()) { // Also takes Smi case.
737 Comment cmnt(masm_, "ONLY_INTEGER_32");
738 if (FLAG_debug_code) {
739 Label ok;
740 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
741 __ test(value.reg(), Immediate(kSmiTagMask));
742 __ j(zero, &ok);
743 __ fldz();
744 __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
745 __ FCmp();
746 __ j(not_zero, &ok);
747 __ Abort("Smi was wrapped in HeapNumber in output from bitop");
748 __ bind(&ok);
749 }
750 // In the integer32 case there are no Smis hidden in heap numbers, so we
751 // need only test for Smi zero.
752 __ test(value.reg(), Operand(value.reg()));
753 dest->false_target()->Branch(zero);
754 value.Unuse();
755 dest->Split(not_zero);
756 } else if (value.is_number()) {
737 Comment cmnt(masm_, "ONLY_NUMBER"); 757 Comment cmnt(masm_, "ONLY_NUMBER");
738 // Fast case if NumberInfo indicates only numbers. 758 // Fast case if NumberInfo indicates only numbers.
739 if (FLAG_debug_code) { 759 if (FLAG_debug_code) {
740 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); 760 __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
741 } 761 }
742 // Smi => false iff zero. 762 // Smi => false iff zero.
743 ASSERT(kSmiTag == 0); 763 ASSERT(kSmiTag == 0);
744 __ test(value.reg(), Operand(value.reg())); 764 __ test(value.reg(), Operand(value.reg()));
745 dest->false_target()->Branch(zero); 765 dest->false_target()->Branch(zero);
746 __ test(value.reg(), Immediate(kSmiTagMask)); 766 __ test(value.reg(), Immediate(kSmiTagMask));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 830
811 // Test if operands are smi or number objects (fp). Requirements: 831 // Test if operands are smi or number objects (fp). Requirements:
812 // operand_1 in eax, operand_2 in edx; falls through on float 832 // operand_1 in eax, operand_2 in edx; falls through on float
813 // operands, jumps to the non_float label otherwise. 833 // operands, jumps to the non_float label otherwise.
814 static void CheckFloatOperands(MacroAssembler* masm, 834 static void CheckFloatOperands(MacroAssembler* masm,
815 Label* non_float, 835 Label* non_float,
816 Register scratch); 836 Register scratch);
817 // Takes the operands in edx and eax and loads them as integers in eax 837 // Takes the operands in edx and eax and loads them as integers in eax
818 // and ecx. 838 // and ecx.
819 static void LoadAsIntegers(MacroAssembler* masm, 839 static void LoadAsIntegers(MacroAssembler* masm,
840 NumberInfo number_info,
820 bool use_sse3, 841 bool use_sse3,
821 Label* operand_conversion_failure); 842 Label* operand_conversion_failure);
822 // Test if operands are smis or heap numbers and load them 843 // Test if operands are smis or heap numbers and load them
823 // into xmm0 and xmm1 if they are. Operands are in edx and eax. 844 // into xmm0 and xmm1 if they are. Operands are in edx and eax.
824 // Leaves operands unchanged. 845 // Leaves operands unchanged.
825 static void LoadSSE2Operands(MacroAssembler* masm); 846 static void LoadSSE2Operands(MacroAssembler* masm);
826 // Test if operands are numbers (smi or HeapNumber objects), and load 847 // Test if operands are numbers (smi or HeapNumber objects), and load
827 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if 848 // them into xmm0 and xmm1 if they are. Jump to label not_numbers if
828 // either operand is not a number. Operands are in edx and eax. 849 // either operand is not a number. Operands are in edx and eax.
829 // Leaves operands unchanged. 850 // Leaves operands unchanged.
(...skipping 19 matching lines...) Expand all
849 default: overwrite_name = "UnknownOverwrite"; break; 870 default: overwrite_name = "UnknownOverwrite"; break;
850 } 871 }
851 872
852 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 873 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
853 "GenericBinaryOpStub_%s_%s%s_%s%s_%s_%s", 874 "GenericBinaryOpStub_%s_%s%s_%s%s_%s_%s",
854 op_name, 875 op_name,
855 overwrite_name, 876 overwrite_name,
856 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 877 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
857 args_in_registers_ ? "RegArgs" : "StackArgs", 878 args_in_registers_ ? "RegArgs" : "StackArgs",
858 args_reversed_ ? "_R" : "", 879 args_reversed_ ? "_R" : "",
859 NumberInfo::ToString(static_operands_type_), 880 static_operands_type_.ToString(),
860 BinaryOpIC::GetName(runtime_operands_type_)); 881 BinaryOpIC::GetName(runtime_operands_type_));
861 return name_; 882 return name_;
862 } 883 }
863 884
864 885
865 // Call the specialized stub for a binary operation. 886 // Call the specialized stub for a binary operation.
866 class DeferredInlineBinaryOperation: public DeferredCode { 887 class DeferredInlineBinaryOperation: public DeferredCode {
867 public: 888 public:
868 DeferredInlineBinaryOperation(Token::Value op, 889 DeferredInlineBinaryOperation(Token::Value op,
869 Register dst, 890 Register dst,
870 Register left, 891 Register left,
871 Register right, 892 Register right,
893 NumberInfo left_info,
894 NumberInfo right_info,
872 OverwriteMode mode) 895 OverwriteMode mode)
873 : op_(op), dst_(dst), left_(left), right_(right), mode_(mode) { 896 : op_(op), dst_(dst), left_(left), right_(right),
897 left_info_(left_info), right_info_(right_info), mode_(mode) {
874 set_comment("[ DeferredInlineBinaryOperation"); 898 set_comment("[ DeferredInlineBinaryOperation");
875 } 899 }
876 900
877 virtual void Generate(); 901 virtual void Generate();
878 902
879 private: 903 private:
880 Token::Value op_; 904 Token::Value op_;
881 Register dst_; 905 Register dst_;
882 Register left_; 906 Register left_;
883 Register right_; 907 Register right_;
908 NumberInfo left_info_;
909 NumberInfo right_info_;
884 OverwriteMode mode_; 910 OverwriteMode mode_;
885 }; 911 };
886 912
887 913
888 void DeferredInlineBinaryOperation::Generate() { 914 void DeferredInlineBinaryOperation::Generate() {
889 Label done; 915 Label done;
890 if (CpuFeatures::IsSupported(SSE2) && ((op_ == Token::ADD) || 916 if (CpuFeatures::IsSupported(SSE2) && ((op_ == Token::ADD) ||
891 (op_ ==Token::SUB) || 917 (op_ ==Token::SUB) ||
892 (op_ == Token::MUL) || 918 (op_ == Token::MUL) ||
893 (op_ == Token::DIV))) { 919 (op_ == Token::DIV))) {
894 CpuFeatures::Scope use_sse2(SSE2); 920 CpuFeatures::Scope use_sse2(SSE2);
895 Label call_runtime, after_alloc_failure; 921 Label call_runtime, after_alloc_failure;
896 Label left_smi, right_smi, load_right, do_op; 922 Label left_smi, right_smi, load_right, do_op;
897 __ test(left_, Immediate(kSmiTagMask)); 923 if (!left_info_.IsSmi()) {
898 __ j(zero, &left_smi); 924 __ test(left_, Immediate(kSmiTagMask));
899 __ cmp(FieldOperand(left_, HeapObject::kMapOffset), 925 __ j(zero, &left_smi);
900 Factory::heap_number_map()); 926 if (!left_info_.IsNumber()) {
901 __ j(not_equal, &call_runtime); 927 __ cmp(FieldOperand(left_, HeapObject::kMapOffset),
902 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); 928 Factory::heap_number_map());
903 if (mode_ == OVERWRITE_LEFT) { 929 __ j(not_equal, &call_runtime);
904 __ mov(dst_, left_); 930 }
931 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset));
932 if (mode_ == OVERWRITE_LEFT) {
933 __ mov(dst_, left_);
934 }
935 __ jmp(&load_right);
936
937 __ bind(&left_smi);
905 } 938 }
906 __ jmp(&load_right);
907
908 __ bind(&left_smi);
909 __ SmiUntag(left_); 939 __ SmiUntag(left_);
910 __ cvtsi2sd(xmm0, Operand(left_)); 940 __ cvtsi2sd(xmm0, Operand(left_));
911 __ SmiTag(left_); 941 __ SmiTag(left_);
912 if (mode_ == OVERWRITE_LEFT) { 942 if (mode_ == OVERWRITE_LEFT) {
913 Label alloc_failure; 943 Label alloc_failure;
914 __ push(left_); 944 __ push(left_);
915 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 945 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
916 __ pop(left_); 946 __ pop(left_);
917 } 947 }
918 948
919 __ bind(&load_right); 949 __ bind(&load_right);
920 __ test(right_, Immediate(kSmiTagMask)); 950 if (!right_info_.IsSmi()) {
921 __ j(zero, &right_smi); 951 __ test(right_, Immediate(kSmiTagMask));
922 __ cmp(FieldOperand(right_, HeapObject::kMapOffset), 952 __ j(zero, &right_smi);
923 Factory::heap_number_map()); 953 if (!right_info_.IsNumber()) {
924 __ j(not_equal, &call_runtime); 954 __ cmp(FieldOperand(right_, HeapObject::kMapOffset),
925 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); 955 Factory::heap_number_map());
926 if (mode_ == OVERWRITE_RIGHT) { 956 __ j(not_equal, &call_runtime);
927 __ mov(dst_, right_); 957 }
928 } else if (mode_ == NO_OVERWRITE) { 958 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset));
929 Label alloc_failure; 959 if (mode_ == OVERWRITE_RIGHT) {
930 __ push(left_); 960 __ mov(dst_, right_);
931 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 961 } else if (mode_ == NO_OVERWRITE) {
932 __ pop(left_); 962 Label alloc_failure;
963 __ push(left_);
964 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
965 __ pop(left_);
966 }
967 __ jmp(&do_op);
968
969 __ bind(&right_smi);
933 } 970 }
934 __ jmp(&do_op);
935
936 __ bind(&right_smi);
937 __ SmiUntag(right_); 971 __ SmiUntag(right_);
938 __ cvtsi2sd(xmm1, Operand(right_)); 972 __ cvtsi2sd(xmm1, Operand(right_));
939 __ SmiTag(right_); 973 __ SmiTag(right_);
940 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) { 974 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) {
941 Label alloc_failure; 975 Label alloc_failure;
942 __ push(left_); 976 __ push(left_);
943 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); 977 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure);
944 __ pop(left_); 978 __ pop(left_);
945 } 979 }
946 980
947 __ bind(&do_op); 981 __ bind(&do_op);
948 switch (op_) { 982 switch (op_) {
949 case Token::ADD: __ addsd(xmm0, xmm1); break; 983 case Token::ADD: __ addsd(xmm0, xmm1); break;
950 case Token::SUB: __ subsd(xmm0, xmm1); break; 984 case Token::SUB: __ subsd(xmm0, xmm1); break;
951 case Token::MUL: __ mulsd(xmm0, xmm1); break; 985 case Token::MUL: __ mulsd(xmm0, xmm1); break;
952 case Token::DIV: __ divsd(xmm0, xmm1); break; 986 case Token::DIV: __ divsd(xmm0, xmm1); break;
953 default: UNREACHABLE(); 987 default: UNREACHABLE();
954 } 988 }
955 __ movdbl(FieldOperand(dst_, HeapNumber::kValueOffset), xmm0); 989 __ movdbl(FieldOperand(dst_, HeapNumber::kValueOffset), xmm0);
956 __ jmp(&done); 990 __ jmp(&done);
957 991
958 __ bind(&after_alloc_failure); 992 __ bind(&after_alloc_failure);
959 __ pop(left_); 993 __ pop(left_);
960 __ bind(&call_runtime); 994 __ bind(&call_runtime);
961 } 995 }
962 GenericBinaryOpStub stub(op_, mode_, NO_SMI_CODE_IN_STUB); 996 GenericBinaryOpStub stub(op_,
997 mode_,
998 NO_SMI_CODE_IN_STUB,
999 NumberInfo::Combine(left_info_, right_info_));
963 stub.GenerateCall(masm_, left_, right_); 1000 stub.GenerateCall(masm_, left_, right_);
964 if (!dst_.is(eax)) __ mov(dst_, eax); 1001 if (!dst_.is(eax)) __ mov(dst_, eax);
965 __ bind(&done); 1002 __ bind(&done);
966 } 1003 }
967 1004
968 1005
1006 static NumberInfo CalculateNumberInfo(NumberInfo operands_type,
1007 Token::Value op,
1008 const Result& right,
1009 const Result& left) {
1010 // Set NumberInfo of result according to the operation performed.
1011 // Rely on the fact that smis have a 31 bit payload on ia32.
1012 ASSERT(kSmiValueSize == 31);
1013 switch (op) {
1014 case Token::COMMA:
1015 return right.number_info();
1016 case Token::OR:
1017 case Token::AND:
1018 // Result type can be either of the two input types.
1019 return operands_type;
1020 case Token::BIT_AND: {
1021 // Anding with positive Smis will give you a Smi.
1022 if (right.is_constant() && right.handle()->IsSmi() &&
1023 Smi::cast(*right.handle())->value() >= 0) {
1024 return NumberInfo::Smi();
1025 } else if (left.is_constant() && left.handle()->IsSmi() &&
1026 Smi::cast(*left.handle())->value() >= 0) {
1027 return NumberInfo::Smi();
1028 }
1029 return (operands_type.IsSmi())
1030 ? NumberInfo::Smi()
1031 : NumberInfo::Integer32();
1032 }
1033 case Token::BIT_OR: {
1034 // Oring with negative Smis will give you a Smi.
1035 if (right.is_constant() && right.handle()->IsSmi() &&
1036 Smi::cast(*right.handle())->value() < 0) {
1037 return NumberInfo::Smi();
1038 } else if (left.is_constant() && left.handle()->IsSmi() &&
1039 Smi::cast(*left.handle())->value() < 0) {
1040 return NumberInfo::Smi();
1041 }
1042 return (operands_type.IsSmi())
1043 ? NumberInfo::Smi()
1044 : NumberInfo::Integer32();
1045 }
1046 case Token::BIT_XOR:
1047 // Result is always a number. Smi property of inputs is preserved.
fschneider 2010/03/05 15:01:07 // Result is always a integer32.
1048 return (operands_type.IsSmi())
1049 ? NumberInfo::Smi()
1050 : NumberInfo::Integer32();
1051 case Token::SAR:
1052 if (left.is_smi()) return NumberInfo::Smi();
1053 // Result is a smi if we shift by a constant >= 1, otherwise a number.
fschneider 2010/03/05 15:01:07 number --> integer32
1054 return (right.is_constant() && right.handle()->IsSmi()
1055 && Smi::cast(*right.handle())->value() >= 1)
1056 ? NumberInfo::Smi()
1057 : NumberInfo::Integer32();
1058 case Token::SHR:
1059 // Result is a smi if we shift by a constant >= 2, otherwise a number.
fschneider 2010/03/05 15:01:07 number --> integer32
1060 return (right.is_constant() && right.handle()->IsSmi()
1061 && Smi::cast(*right.handle())->value() >= 2)
1062 ? NumberInfo::Smi()
1063 : NumberInfo::Integer32();
1064 case Token::ADD:
1065 if (operands_type.IsSmi()) {
1066 // The Integer32 range is big enough to take the sum of any two Smis.
1067 return NumberInfo::Integer32();
1068 } else {
1069 // Result could be a string or a number. Check types of inputs.
1070 return operands_type.IsNumber()
1071 ? NumberInfo::Number()
1072 : NumberInfo::Unknown();
1073 }
1074 case Token::SHL:
1075 return NumberInfo::Integer32();
1076 case Token::SUB:
1077 // The Integer32 range is big enough to take the difference of any two Smi s.
fschneider 2010/03/05 15:01:07 long line
1078 return (operands_type.IsSmi()) ?
1079 NumberInfo::Integer32() :
1080 NumberInfo::Number();
1081 case Token::MUL:
1082 case Token::DIV:
1083 case Token::MOD:
1084 // Result is always a number.
1085 return NumberInfo::Number();
1086 default:
1087 UNREACHABLE();
1088 }
1089 UNREACHABLE();
1090 return NumberInfo::Unknown();
1091 }
1092
1093
969 void CodeGenerator::GenericBinaryOperation(Token::Value op, 1094 void CodeGenerator::GenericBinaryOperation(Token::Value op,
970 StaticType* type, 1095 StaticType* type,
971 OverwriteMode overwrite_mode) { 1096 OverwriteMode overwrite_mode) {
972 Comment cmnt(masm_, "[ BinaryOperation"); 1097 Comment cmnt(masm_, "[ BinaryOperation");
973 Comment cmnt_token(masm_, Token::String(op)); 1098 Comment cmnt_token(masm_, Token::String(op));
974 1099
975 if (op == Token::COMMA) { 1100 if (op == Token::COMMA) {
976 // Simply discard left value. 1101 // Simply discard left value.
977 frame_->Nip(1); 1102 frame_->Nip(1);
978 return; 1103 return;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 right.is_constant() && !right.handle()->IsSmi(); 1139 right.is_constant() && !right.handle()->IsSmi();
1015 1140
1016 if (left_is_smi_constant && right_is_smi_constant) { 1141 if (left_is_smi_constant && right_is_smi_constant) {
1017 // Compute the constant result at compile time, and leave it on the frame. 1142 // Compute the constant result at compile time, and leave it on the frame.
1018 int left_int = Smi::cast(*left.handle())->value(); 1143 int left_int = Smi::cast(*left.handle())->value();
1019 int right_int = Smi::cast(*right.handle())->value(); 1144 int right_int = Smi::cast(*right.handle())->value();
1020 if (FoldConstantSmis(op, left_int, right_int)) return; 1145 if (FoldConstantSmis(op, left_int, right_int)) return;
1021 } 1146 }
1022 1147
1023 // Get number type of left and right sub-expressions. 1148 // Get number type of left and right sub-expressions.
1024 NumberInfo::Type operands_type = 1149 NumberInfo operands_type =
1025 NumberInfo::Combine(left.number_info(), right.number_info()); 1150 NumberInfo::Combine(left.number_info(), right.number_info());
1026 1151
1152 NumberInfo result_type = CalculateNumberInfo(operands_type, op, right, left);
1153
1027 Result answer; 1154 Result answer;
1028 if (left_is_non_smi_constant || right_is_non_smi_constant) { 1155 if (left_is_non_smi_constant || right_is_non_smi_constant) {
1029 // Go straight to the slow case, with no smi code. 1156 // Go straight to the slow case, with no smi code.
1030 GenericBinaryOpStub stub(op, 1157 GenericBinaryOpStub stub(op,
1031 overwrite_mode, 1158 overwrite_mode,
1032 NO_SMI_CODE_IN_STUB, 1159 NO_SMI_CODE_IN_STUB,
1033 operands_type); 1160 operands_type);
1034 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1161 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1035 } else if (right_is_smi_constant) { 1162 } else if (right_is_smi_constant) {
1036 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 1163 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
1037 type, false, overwrite_mode); 1164 type, false, overwrite_mode);
1038 } else if (left_is_smi_constant) { 1165 } else if (left_is_smi_constant) {
1039 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 1166 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
1040 type, true, overwrite_mode); 1167 type, true, overwrite_mode);
1041 } else { 1168 } else {
1042 // Set the flags based on the operation, type and loop nesting level. 1169 // Set the flags based on the operation, type and loop nesting level.
1043 // Bit operations always assume they likely operate on Smis. Still only 1170 // Bit operations always assume they likely operate on Smis. Still only
1044 // generate the inline Smi check code if this operation is part of a loop. 1171 // generate the inline Smi check code if this operation is part of a loop.
1045 // For all other operations only inline the Smi check code for likely smis 1172 // For all other operations only inline the Smi check code for likely smis
1046 // if the operation is part of a loop. 1173 // if the operation is part of a loop.
1047 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { 1174 if (loop_nesting() > 0 &&
1175 (Token::IsBitOp(op) ||
1176 operands_type.IsInteger32() ||
1177 type->IsLikelySmi())) {
1048 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 1178 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
1049 } else { 1179 } else {
1050 GenericBinaryOpStub stub(op, 1180 GenericBinaryOpStub stub(op,
1051 overwrite_mode, 1181 overwrite_mode,
1052 NO_GENERIC_BINARY_FLAGS, 1182 NO_GENERIC_BINARY_FLAGS,
1053 operands_type); 1183 operands_type);
1054 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1184 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1055 } 1185 }
1056 } 1186 }
1057 1187
1058 // Set NumberInfo of result according to the operation performed.
1059 // Rely on the fact that smis have a 31 bit payload on ia32.
1060 ASSERT(kSmiValueSize == 31);
1061 NumberInfo::Type result_type = NumberInfo::kUnknown;
1062 switch (op) {
1063 case Token::COMMA:
1064 result_type = right.number_info();
1065 break;
1066 case Token::OR:
1067 case Token::AND:
1068 // Result type can be either of the two input types.
1069 result_type = operands_type;
1070 break;
1071 case Token::BIT_OR:
1072 case Token::BIT_XOR:
1073 case Token::BIT_AND:
1074 // Result is always a number. Smi property of inputs is preserved.
1075 result_type = (operands_type == NumberInfo::kSmi)
1076 ? NumberInfo::kSmi
1077 : NumberInfo::kNumber;
1078 break;
1079 case Token::SAR:
1080 // Result is a smi if we shift by a constant >= 1, otherwise a number.
1081 result_type = (right.is_constant() && right.handle()->IsSmi()
1082 && Smi::cast(*right.handle())->value() >= 1)
1083 ? NumberInfo::kSmi
1084 : NumberInfo::kNumber;
1085 break;
1086 case Token::SHR:
1087 // Result is a smi if we shift by a constant >= 2, otherwise a number.
1088 result_type = (right.is_constant() && right.handle()->IsSmi()
1089 && Smi::cast(*right.handle())->value() >= 2)
1090 ? NumberInfo::kSmi
1091 : NumberInfo::kNumber;
1092 break;
1093 case Token::ADD:
1094 // Result could be a string or a number. Check types of inputs.
1095 result_type = NumberInfo::IsNumber(operands_type)
1096 ? NumberInfo::kNumber
1097 : NumberInfo::kUnknown;
1098 break;
1099 case Token::SHL:
1100 case Token::SUB:
1101 case Token::MUL:
1102 case Token::DIV:
1103 case Token::MOD:
1104 // Result is always a number.
1105 result_type = NumberInfo::kNumber;
1106 break;
1107 default:
1108 UNREACHABLE();
1109 }
1110 answer.set_number_info(result_type); 1188 answer.set_number_info(result_type);
1111 frame_->Push(&answer); 1189 frame_->Push(&answer);
1112 } 1190 }
1113 1191
1114 1192
1115 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { 1193 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
1116 Object* answer_object = Heap::undefined_value(); 1194 Object* answer_object = Heap::undefined_value();
1117 switch (op) { 1195 switch (op) {
1118 case Token::ADD: 1196 case Token::ADD:
1119 if (Smi::IsValid(left + right)) { 1197 if (Smi::IsValid(left + right)) {
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 break; 1264 break;
1187 } 1265 }
1188 if (answer_object == Heap::undefined_value()) { 1266 if (answer_object == Heap::undefined_value()) {
1189 return false; 1267 return false;
1190 } 1268 }
1191 frame_->Push(Handle<Object>(answer_object)); 1269 frame_->Push(Handle<Object>(answer_object));
1192 return true; 1270 return true;
1193 } 1271 }
1194 1272
1195 1273
1274 static void CheckTwoForSminess(MacroAssembler* masm,
1275 Register left, Register right, Register scratch,
1276 NumberInfo left_info, NumberInfo right_info,
1277 DeferredInlineBinaryOperation* deferred);
1278
1279
1196 // Implements a binary operation using a deferred code object and some 1280 // Implements a binary operation using a deferred code object and some
1197 // inline code to operate on smis quickly. 1281 // inline code to operate on smis quickly.
1198 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, 1282 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
1199 Result* left, 1283 Result* left,
1200 Result* right, 1284 Result* right,
1201 OverwriteMode overwrite_mode) { 1285 OverwriteMode overwrite_mode) {
1202 Result answer; 1286 Result answer;
1203 // Special handling of div and mod because they use fixed registers. 1287 // Special handling of div and mod because they use fixed registers.
1204 if (op == Token::DIV || op == Token::MOD) { 1288 if (op == Token::DIV || op == Token::MOD) {
1205 // We need eax as the quotient register, edx as the remainder 1289 // We need eax as the quotient register, edx as the remainder
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 right->ToRegister(); 1350 right->ToRegister();
1267 frame_->Spill(eax); 1351 frame_->Spill(eax);
1268 frame_->Spill(edx); 1352 frame_->Spill(edx);
1269 1353
1270 // Check that left and right are smi tagged. 1354 // Check that left and right are smi tagged.
1271 DeferredInlineBinaryOperation* deferred = 1355 DeferredInlineBinaryOperation* deferred =
1272 new DeferredInlineBinaryOperation(op, 1356 new DeferredInlineBinaryOperation(op,
1273 (op == Token::DIV) ? eax : edx, 1357 (op == Token::DIV) ? eax : edx,
1274 left->reg(), 1358 left->reg(),
1275 right->reg(), 1359 right->reg(),
1360 left->number_info(),
1361 right->number_info(),
1276 overwrite_mode); 1362 overwrite_mode);
1277 if (left->reg().is(right->reg())) { 1363 if (left->reg().is(right->reg())) {
1278 __ test(left->reg(), Immediate(kSmiTagMask)); 1364 __ test(left->reg(), Immediate(kSmiTagMask));
1279 } else { 1365 } else {
1280 // Use the quotient register as a scratch for the tag check. 1366 // Use the quotient register as a scratch for the tag check.
1281 if (!left_is_in_eax) __ mov(eax, left->reg()); 1367 if (!left_is_in_eax) __ mov(eax, left->reg());
1282 left_is_in_eax = false; // About to destroy the value in eax. 1368 left_is_in_eax = false; // About to destroy the value in eax.
1283 __ or_(eax, Operand(right->reg())); 1369 __ or_(eax, Operand(right->reg()));
1284 ASSERT(kSmiTag == 0); // Adjust test if not the case. 1370 ASSERT(kSmiTag == 0); // Adjust test if not the case.
1285 __ test(eax, Immediate(kSmiTagMask)); 1371 __ test(eax, Immediate(kSmiTagMask));
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 // Use a fresh answer register to avoid spilling the left operand. 1449 // Use a fresh answer register to avoid spilling the left operand.
1364 answer = allocator_->Allocate(); 1450 answer = allocator_->Allocate();
1365 ASSERT(answer.is_valid()); 1451 ASSERT(answer.is_valid());
1366 // Check that both operands are smis using the answer register as a 1452 // Check that both operands are smis using the answer register as a
1367 // temporary. 1453 // temporary.
1368 DeferredInlineBinaryOperation* deferred = 1454 DeferredInlineBinaryOperation* deferred =
1369 new DeferredInlineBinaryOperation(op, 1455 new DeferredInlineBinaryOperation(op,
1370 answer.reg(), 1456 answer.reg(),
1371 left->reg(), 1457 left->reg(),
1372 ecx, 1458 ecx,
1459 left->number_info(),
1460 right->number_info(),
1373 overwrite_mode); 1461 overwrite_mode);
1374 __ mov(answer.reg(), left->reg()); 1462 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
1375 __ or_(answer.reg(), Operand(ecx)); 1463 left->number_info(), right->number_info(), deferred);
1376 __ test(answer.reg(), Immediate(kSmiTagMask));
1377 deferred->Branch(not_zero);
1378 1464
1379 // Untag both operands. 1465 // Untag both operands.
1380 __ mov(answer.reg(), left->reg()); 1466 __ mov(answer.reg(), left->reg());
1381 __ SmiUntag(answer.reg()); 1467 __ SmiUntag(answer.reg());
1382 __ SmiUntag(ecx); 1468 __ SmiUntag(ecx);
1383 // Perform the operation. 1469 // Perform the operation.
1384 switch (op) { 1470 switch (op) {
1385 case Token::SAR: 1471 case Token::SAR:
1386 __ sar_cl(answer.reg()); 1472 __ sar_cl(answer.reg());
1387 // No checks of result necessary 1473 // No checks of result necessary
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 // need to be spilled in the fast case. 1523 // need to be spilled in the fast case.
1438 answer = allocator_->Allocate(); 1524 answer = allocator_->Allocate();
1439 ASSERT(answer.is_valid()); 1525 ASSERT(answer.is_valid());
1440 1526
1441 // Perform the smi tag check. 1527 // Perform the smi tag check.
1442 DeferredInlineBinaryOperation* deferred = 1528 DeferredInlineBinaryOperation* deferred =
1443 new DeferredInlineBinaryOperation(op, 1529 new DeferredInlineBinaryOperation(op,
1444 answer.reg(), 1530 answer.reg(),
1445 left->reg(), 1531 left->reg(),
1446 right->reg(), 1532 right->reg(),
1533 left->number_info(),
1534 right->number_info(),
1447 overwrite_mode); 1535 overwrite_mode);
1448 if (left->reg().is(right->reg())) { 1536 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(),
1449 __ test(left->reg(), Immediate(kSmiTagMask)); 1537 left->number_info(), right->number_info(), deferred);
1450 } else { 1538
1451 __ mov(answer.reg(), left->reg());
1452 __ or_(answer.reg(), Operand(right->reg()));
1453 ASSERT(kSmiTag == 0); // Adjust test if not the case.
1454 __ test(answer.reg(), Immediate(kSmiTagMask));
1455 }
1456 deferred->Branch(not_zero);
1457 __ mov(answer.reg(), left->reg()); 1539 __ mov(answer.reg(), left->reg());
1458 switch (op) { 1540 switch (op) {
1459 case Token::ADD: 1541 case Token::ADD:
1460 __ add(answer.reg(), Operand(right->reg())); 1542 __ add(answer.reg(), Operand(right->reg()));
1461 deferred->Branch(overflow); 1543 deferred->Branch(overflow);
1462 break; 1544 break;
1463 1545
1464 case Token::SUB: 1546 case Token::SUB:
1465 __ sub(answer.reg(), Operand(right->reg())); 1547 __ sub(answer.reg(), Operand(right->reg()));
1466 deferred->Branch(overflow); 1548 deferred->Branch(overflow);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 } 1597 }
1516 1598
1517 1599
1518 // Call the appropriate binary operation stub to compute src op value 1600 // Call the appropriate binary operation stub to compute src op value
1519 // and leave the result in dst. 1601 // and leave the result in dst.
1520 class DeferredInlineSmiOperation: public DeferredCode { 1602 class DeferredInlineSmiOperation: public DeferredCode {
1521 public: 1603 public:
1522 DeferredInlineSmiOperation(Token::Value op, 1604 DeferredInlineSmiOperation(Token::Value op,
1523 Register dst, 1605 Register dst,
1524 Register src, 1606 Register src,
1607 NumberInfo number_info,
1525 Smi* value, 1608 Smi* value,
1526 OverwriteMode overwrite_mode) 1609 OverwriteMode overwrite_mode)
1527 : op_(op), 1610 : op_(op),
1528 dst_(dst), 1611 dst_(dst),
1529 src_(src), 1612 src_(src),
1613 number_info_(number_info),
1530 value_(value), 1614 value_(value),
1531 overwrite_mode_(overwrite_mode) { 1615 overwrite_mode_(overwrite_mode) {
1616 if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
1532 set_comment("[ DeferredInlineSmiOperation"); 1617 set_comment("[ DeferredInlineSmiOperation");
1533 } 1618 }
1534 1619
1535 virtual void Generate(); 1620 virtual void Generate();
1536 1621
1537 private: 1622 private:
1538 Token::Value op_; 1623 Token::Value op_;
1539 Register dst_; 1624 Register dst_;
1540 Register src_; 1625 Register src_;
1626 NumberInfo number_info_;
1541 Smi* value_; 1627 Smi* value_;
1542 OverwriteMode overwrite_mode_; 1628 OverwriteMode overwrite_mode_;
1543 }; 1629 };
1544 1630
1545 1631
1546 void DeferredInlineSmiOperation::Generate() { 1632 void DeferredInlineSmiOperation::Generate() {
1547 // For mod we don't generate all the Smi code inline. 1633 // For mod we don't generate all the Smi code inline.
1548 GenericBinaryOpStub stub( 1634 GenericBinaryOpStub stub(
1549 op_, 1635 op_,
1550 overwrite_mode_, 1636 overwrite_mode_,
1551 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB); 1637 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB,
1638 NumberInfo::Combine(NumberInfo::Smi(), number_info_));
1552 stub.GenerateCall(masm_, src_, value_); 1639 stub.GenerateCall(masm_, src_, value_);
1553 if (!dst_.is(eax)) __ mov(dst_, eax); 1640 if (!dst_.is(eax)) __ mov(dst_, eax);
1554 } 1641 }
1555 1642
1556 1643
1557 // Call the appropriate binary operation stub to compute value op src 1644 // Call the appropriate binary operation stub to compute value op src
1558 // and leave the result in dst. 1645 // and leave the result in dst.
1559 class DeferredInlineSmiOperationReversed: public DeferredCode { 1646 class DeferredInlineSmiOperationReversed: public DeferredCode {
1560 public: 1647 public:
1561 DeferredInlineSmiOperationReversed(Token::Value op, 1648 DeferredInlineSmiOperationReversed(Token::Value op,
1562 Register dst, 1649 Register dst,
1563 Smi* value, 1650 Smi* value,
1564 Register src, 1651 Register src,
1652 NumberInfo number_info,
1565 OverwriteMode overwrite_mode) 1653 OverwriteMode overwrite_mode)
1566 : op_(op), 1654 : op_(op),
1567 dst_(dst), 1655 dst_(dst),
1656 number_info_(number_info),
1568 value_(value), 1657 value_(value),
1569 src_(src), 1658 src_(src),
1570 overwrite_mode_(overwrite_mode) { 1659 overwrite_mode_(overwrite_mode) {
1571 set_comment("[ DeferredInlineSmiOperationReversed"); 1660 set_comment("[ DeferredInlineSmiOperationReversed");
1572 } 1661 }
1573 1662
1574 virtual void Generate(); 1663 virtual void Generate();
1575 1664
1576 private: 1665 private:
1577 Token::Value op_; 1666 Token::Value op_;
1578 Register dst_; 1667 Register dst_;
1668 NumberInfo number_info_;
1579 Smi* value_; 1669 Smi* value_;
1580 Register src_; 1670 Register src_;
1581 OverwriteMode overwrite_mode_; 1671 OverwriteMode overwrite_mode_;
1582 }; 1672 };
1583 1673
1584 1674
1585 void DeferredInlineSmiOperationReversed::Generate() { 1675 void DeferredInlineSmiOperationReversed::Generate() {
1586 GenericBinaryOpStub igostub(op_, overwrite_mode_, NO_SMI_CODE_IN_STUB); 1676 GenericBinaryOpStub igostub(
1677 op_,
1678 overwrite_mode_,
1679 NO_SMI_CODE_IN_STUB,
1680 NumberInfo::Combine(NumberInfo::Smi(), number_info_));
1587 igostub.GenerateCall(masm_, value_, src_); 1681 igostub.GenerateCall(masm_, value_, src_);
1588 if (!dst_.is(eax)) __ mov(dst_, eax); 1682 if (!dst_.is(eax)) __ mov(dst_, eax);
1589 } 1683 }
1590 1684
1591 1685
1592 // The result of src + value is in dst. It either overflowed or was not 1686 // The result of src + value is in dst. It either overflowed or was not
1593 // smi tagged. Undo the speculative addition and call the appropriate 1687 // smi tagged. Undo the speculative addition and call the appropriate
1594 // specialized stub for add. The result is left in dst. 1688 // specialized stub for add. The result is left in dst.
1595 class DeferredInlineSmiAdd: public DeferredCode { 1689 class DeferredInlineSmiAdd: public DeferredCode {
1596 public: 1690 public:
1597 DeferredInlineSmiAdd(Register dst, 1691 DeferredInlineSmiAdd(Register dst,
1692 NumberInfo number_info,
1598 Smi* value, 1693 Smi* value,
1599 OverwriteMode overwrite_mode) 1694 OverwriteMode overwrite_mode)
1600 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { 1695 : dst_(dst),
1696 number_info_(number_info),
1697 value_(value),
1698 overwrite_mode_(overwrite_mode) {
1699 if (number_info_.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
1601 set_comment("[ DeferredInlineSmiAdd"); 1700 set_comment("[ DeferredInlineSmiAdd");
1602 } 1701 }
1603 1702
1604 virtual void Generate(); 1703 virtual void Generate();
1605 1704
1606 private: 1705 private:
1607 Register dst_; 1706 Register dst_;
1707 NumberInfo number_info_;
1608 Smi* value_; 1708 Smi* value_;
1609 OverwriteMode overwrite_mode_; 1709 OverwriteMode overwrite_mode_;
1610 }; 1710 };
1611 1711
1612 1712
1613 void DeferredInlineSmiAdd::Generate() { 1713 void DeferredInlineSmiAdd::Generate() {
1614 // Undo the optimistic add operation and call the shared stub. 1714 // Undo the optimistic add operation and call the shared stub.
1615 __ sub(Operand(dst_), Immediate(value_)); 1715 __ sub(Operand(dst_), Immediate(value_));
1616 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); 1716 GenericBinaryOpStub igostub(
1717 Token::ADD,
1718 overwrite_mode_,
1719 NO_SMI_CODE_IN_STUB,
1720 NumberInfo::Combine(NumberInfo::Smi(), number_info_));
1617 igostub.GenerateCall(masm_, dst_, value_); 1721 igostub.GenerateCall(masm_, dst_, value_);
1618 if (!dst_.is(eax)) __ mov(dst_, eax); 1722 if (!dst_.is(eax)) __ mov(dst_, eax);
1619 } 1723 }
1620 1724
1621 1725
1622 // The result of value + src is in dst. It either overflowed or was not 1726 // The result of value + src is in dst. It either overflowed or was not
1623 // smi tagged. Undo the speculative addition and call the appropriate 1727 // smi tagged. Undo the speculative addition and call the appropriate
1624 // specialized stub for add. The result is left in dst. 1728 // specialized stub for add. The result is left in dst.
1625 class DeferredInlineSmiAddReversed: public DeferredCode { 1729 class DeferredInlineSmiAddReversed: public DeferredCode {
1626 public: 1730 public:
1627 DeferredInlineSmiAddReversed(Register dst, 1731 DeferredInlineSmiAddReversed(Register dst,
1732 NumberInfo number_info,
1628 Smi* value, 1733 Smi* value,
1629 OverwriteMode overwrite_mode) 1734 OverwriteMode overwrite_mode)
1630 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { 1735 : dst_(dst),
1736 number_info_(number_info),
1737 value_(value),
1738 overwrite_mode_(overwrite_mode) {
1631 set_comment("[ DeferredInlineSmiAddReversed"); 1739 set_comment("[ DeferredInlineSmiAddReversed");
1632 } 1740 }
1633 1741
1634 virtual void Generate(); 1742 virtual void Generate();
1635 1743
1636 private: 1744 private:
1637 Register dst_; 1745 Register dst_;
1746 NumberInfo number_info_;
1638 Smi* value_; 1747 Smi* value_;
1639 OverwriteMode overwrite_mode_; 1748 OverwriteMode overwrite_mode_;
1640 }; 1749 };
1641 1750
1642 1751
1643 void DeferredInlineSmiAddReversed::Generate() { 1752 void DeferredInlineSmiAddReversed::Generate() {
1644 // Undo the optimistic add operation and call the shared stub. 1753 // Undo the optimistic add operation and call the shared stub.
1645 __ sub(Operand(dst_), Immediate(value_)); 1754 __ sub(Operand(dst_), Immediate(value_));
1646 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, NO_SMI_CODE_IN_STUB); 1755 GenericBinaryOpStub igostub(Token::ADD,
1756 overwrite_mode_,
1757 NO_SMI_CODE_IN_STUB,
1758 NumberInfo::Combine(NumberInfo::Smi(), number_info _));
1647 igostub.GenerateCall(masm_, value_, dst_); 1759 igostub.GenerateCall(masm_, value_, dst_);
1648 if (!dst_.is(eax)) __ mov(dst_, eax); 1760 if (!dst_.is(eax)) __ mov(dst_, eax);
1649 } 1761 }
1650 1762
1651 1763
1652 // The result of src - value is in dst. It either overflowed or was not 1764 // The result of src - value is in dst. It either overflowed or was not
1653 // smi tagged. Undo the speculative subtraction and call the 1765 // smi tagged. Undo the speculative subtraction and call the
1654 // appropriate specialized stub for subtract. The result is left in 1766 // appropriate specialized stub for subtract. The result is left in
1655 // dst. 1767 // dst.
1656 class DeferredInlineSmiSub: public DeferredCode { 1768 class DeferredInlineSmiSub: public DeferredCode {
1657 public: 1769 public:
1658 DeferredInlineSmiSub(Register dst, 1770 DeferredInlineSmiSub(Register dst,
1771 NumberInfo number_info,
1659 Smi* value, 1772 Smi* value,
1660 OverwriteMode overwrite_mode) 1773 OverwriteMode overwrite_mode)
1661 : dst_(dst), value_(value), overwrite_mode_(overwrite_mode) { 1774 : dst_(dst),
1775 number_info_(number_info),
1776 value_(value),
1777 overwrite_mode_(overwrite_mode) {
1778 if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE;
1662 set_comment("[ DeferredInlineSmiSub"); 1779 set_comment("[ DeferredInlineSmiSub");
1663 } 1780 }
1664 1781
1665 virtual void Generate(); 1782 virtual void Generate();
1666 1783
1667 private: 1784 private:
1668 Register dst_; 1785 Register dst_;
1786 NumberInfo number_info_;
1669 Smi* value_; 1787 Smi* value_;
1670 OverwriteMode overwrite_mode_; 1788 OverwriteMode overwrite_mode_;
1671 }; 1789 };
1672 1790
1673 1791
1674 void DeferredInlineSmiSub::Generate() { 1792 void DeferredInlineSmiSub::Generate() {
1675 // Undo the optimistic sub operation and call the shared stub. 1793 // Undo the optimistic sub operation and call the shared stub.
1676 __ add(Operand(dst_), Immediate(value_)); 1794 __ add(Operand(dst_), Immediate(value_));
1677 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, NO_SMI_CODE_IN_STUB); 1795 GenericBinaryOpStub igostub(Token::SUB,
1796 overwrite_mode_,
1797 NO_SMI_CODE_IN_STUB,
1798 NumberInfo::Combine(NumberInfo::Smi(), number_info _));
1678 igostub.GenerateCall(masm_, dst_, value_); 1799 igostub.GenerateCall(masm_, dst_, value_);
1679 if (!dst_.is(eax)) __ mov(dst_, eax); 1800 if (!dst_.is(eax)) __ mov(dst_, eax);
1680 } 1801 }
1681 1802
1682 1803
1683 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, 1804 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
1684 Result* operand, 1805 Result* operand,
1685 Handle<Object> value, 1806 Handle<Object> value,
1686 StaticType* type, 1807 StaticType* type,
1687 bool reversed, 1808 bool reversed,
(...skipping 23 matching lines...) Expand all
1711 switch (op) { 1832 switch (op) {
1712 case Token::ADD: { 1833 case Token::ADD: {
1713 operand->ToRegister(); 1834 operand->ToRegister();
1714 frame_->Spill(operand->reg()); 1835 frame_->Spill(operand->reg());
1715 1836
1716 // Optimistically add. Call the specialized add stub if the 1837 // Optimistically add. Call the specialized add stub if the
1717 // result is not a smi or overflows. 1838 // result is not a smi or overflows.
1718 DeferredCode* deferred = NULL; 1839 DeferredCode* deferred = NULL;
1719 if (reversed) { 1840 if (reversed) {
1720 deferred = new DeferredInlineSmiAddReversed(operand->reg(), 1841 deferred = new DeferredInlineSmiAddReversed(operand->reg(),
1842 operand->number_info(),
1721 smi_value, 1843 smi_value,
1722 overwrite_mode); 1844 overwrite_mode);
1723 } else { 1845 } else {
1724 deferred = new DeferredInlineSmiAdd(operand->reg(), 1846 deferred = new DeferredInlineSmiAdd(operand->reg(),
1847 operand->number_info(),
1725 smi_value, 1848 smi_value,
1726 overwrite_mode); 1849 overwrite_mode);
1727 } 1850 }
1728 __ add(Operand(operand->reg()), Immediate(value)); 1851 __ add(Operand(operand->reg()), Immediate(value));
1729 deferred->Branch(overflow); 1852 deferred->Branch(overflow);
1730 __ test(operand->reg(), Immediate(kSmiTagMask)); 1853 if (!operand->number_info().IsSmi()) {
1731 deferred->Branch(not_zero); 1854 __ test(operand->reg(), Immediate(kSmiTagMask));
1855 deferred->Branch(not_zero);
1856 }
1732 deferred->BindExit(); 1857 deferred->BindExit();
1733 answer = *operand; 1858 answer = *operand;
1734 break; 1859 break;
1735 } 1860 }
1736 1861
1737 case Token::SUB: { 1862 case Token::SUB: {
1738 DeferredCode* deferred = NULL; 1863 DeferredCode* deferred = NULL;
1739 if (reversed) { 1864 if (reversed) {
1740 // The reversed case is only hit when the right operand is not a 1865 // The reversed case is only hit when the right operand is not a
1741 // constant. 1866 // constant.
1742 ASSERT(operand->is_register()); 1867 ASSERT(operand->is_register());
1743 answer = allocator()->Allocate(); 1868 answer = allocator()->Allocate();
1744 ASSERT(answer.is_valid()); 1869 ASSERT(answer.is_valid());
1745 __ Set(answer.reg(), Immediate(value)); 1870 __ Set(answer.reg(), Immediate(value));
1746 deferred = new DeferredInlineSmiOperationReversed(op, 1871 deferred = new DeferredInlineSmiOperationReversed(op,
1747 answer.reg(), 1872 answer.reg(),
1748 smi_value, 1873 smi_value,
1749 operand->reg(), 1874 operand->reg(),
1875 operand->number_info() ,
fschneider 2010/03/05 15:01:07 long line?
1750 overwrite_mode); 1876 overwrite_mode);
1751 __ sub(answer.reg(), Operand(operand->reg())); 1877 __ sub(answer.reg(), Operand(operand->reg()));
1752 } else { 1878 } else {
1753 operand->ToRegister(); 1879 operand->ToRegister();
1754 frame_->Spill(operand->reg()); 1880 frame_->Spill(operand->reg());
1755 answer = *operand; 1881 answer = *operand;
1756 deferred = new DeferredInlineSmiSub(operand->reg(), 1882 deferred = new DeferredInlineSmiSub(operand->reg(),
1883 operand->number_info(),
1757 smi_value, 1884 smi_value,
1758 overwrite_mode); 1885 overwrite_mode);
1759 __ sub(Operand(operand->reg()), Immediate(value)); 1886 __ sub(Operand(operand->reg()), Immediate(value));
1760 } 1887 }
1761 deferred->Branch(overflow); 1888 deferred->Branch(overflow);
1762 __ test(answer.reg(), Immediate(kSmiTagMask)); 1889 if (!operand->number_info().IsSmi()) {
1763 deferred->Branch(not_zero); 1890 __ test(answer.reg(), Immediate(kSmiTagMask));
1891 deferred->Branch(not_zero);
1892 }
1764 deferred->BindExit(); 1893 deferred->BindExit();
1765 operand->Unuse(); 1894 operand->Unuse();
1766 break; 1895 break;
1767 } 1896 }
1768 1897
1769 case Token::SAR: 1898 case Token::SAR:
1770 if (reversed) { 1899 if (reversed) {
1771 Result constant_operand(value); 1900 Result constant_operand(value);
1772 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 1901 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1773 overwrite_mode); 1902 overwrite_mode);
1774 } else { 1903 } else {
1775 // Only the least significant 5 bits of the shift value are used. 1904 // Only the least significant 5 bits of the shift value are used.
1776 // In the slow case, this masking is done inside the runtime call. 1905 // In the slow case, this masking is done inside the runtime call.
1777 int shift_value = int_value & 0x1f; 1906 int shift_value = int_value & 0x1f;
1778 operand->ToRegister(); 1907 operand->ToRegister();
1779 frame_->Spill(operand->reg()); 1908 frame_->Spill(operand->reg());
1780 DeferredInlineSmiOperation* deferred = 1909 DeferredInlineSmiOperation* deferred =
1781 new DeferredInlineSmiOperation(op, 1910 new DeferredInlineSmiOperation(op,
1782 operand->reg(), 1911 operand->reg(),
1783 operand->reg(), 1912 operand->reg(),
1913 operand->number_info(),
fschneider 2010/03/05 15:01:07 You could avoid creating the DeferredInlineSmiOper
1784 smi_value, 1914 smi_value,
1785 overwrite_mode); 1915 overwrite_mode);
1786 __ test(operand->reg(), Immediate(kSmiTagMask)); 1916 if (!operand->number_info().IsSmi()) {
1787 deferred->Branch(not_zero); 1917 __ test(operand->reg(), Immediate(kSmiTagMask));
1918 deferred->Branch(not_zero);
1919 }
1788 if (shift_value > 0) { 1920 if (shift_value > 0) {
1789 __ sar(operand->reg(), shift_value); 1921 __ sar(operand->reg(), shift_value);
1790 __ and_(operand->reg(), ~kSmiTagMask); 1922 __ and_(operand->reg(), ~kSmiTagMask);
1791 } 1923 }
1792 deferred->BindExit(); 1924 deferred->BindExit();
1793 answer = *operand; 1925 answer = *operand;
1794 } 1926 }
1795 break; 1927 break;
1796 1928
1797 case Token::SHR: 1929 case Token::SHR:
1798 if (reversed) { 1930 if (reversed) {
1799 Result constant_operand(value); 1931 Result constant_operand(value);
1800 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, 1932 answer = LikelySmiBinaryOperation(op, &constant_operand, operand,
1801 overwrite_mode); 1933 overwrite_mode);
1802 } else { 1934 } else {
1803 // Only the least significant 5 bits of the shift value are used. 1935 // Only the least significant 5 bits of the shift value are used.
1804 // In the slow case, this masking is done inside the runtime call. 1936 // In the slow case, this masking is done inside the runtime call.
1805 int shift_value = int_value & 0x1f; 1937 int shift_value = int_value & 0x1f;
1806 operand->ToRegister(); 1938 operand->ToRegister();
1807 answer = allocator()->Allocate(); 1939 answer = allocator()->Allocate();
1808 ASSERT(answer.is_valid()); 1940 ASSERT(answer.is_valid());
1809 DeferredInlineSmiOperation* deferred = 1941 DeferredInlineSmiOperation* deferred =
1810 new DeferredInlineSmiOperation(op, 1942 new DeferredInlineSmiOperation(op,
1811 answer.reg(), 1943 answer.reg(),
1812 operand->reg(), 1944 operand->reg(),
1945 operand->number_info(),
1813 smi_value, 1946 smi_value,
1814 overwrite_mode); 1947 overwrite_mode);
1815 __ test(operand->reg(), Immediate(kSmiTagMask)); 1948 if (!operand->number_info().IsSmi()) {
1816 deferred->Branch(not_zero); 1949 __ test(operand->reg(), Immediate(kSmiTagMask));
1950 deferred->Branch(not_zero);
1951 }
1817 __ mov(answer.reg(), operand->reg()); 1952 __ mov(answer.reg(), operand->reg());
1818 __ SmiUntag(answer.reg()); 1953 __ SmiUntag(answer.reg());
1819 __ shr(answer.reg(), shift_value); 1954 __ shr(answer.reg(), shift_value);
1820 // A negative Smi shifted right two is in the positive Smi range. 1955 // A negative Smi shifted right two is in the positive Smi range.
1821 if (shift_value < 2) { 1956 if (shift_value < 2) {
1822 __ test(answer.reg(), Immediate(0xc0000000)); 1957 __ test(answer.reg(), Immediate(0xc0000000));
1823 deferred->Branch(not_zero); 1958 deferred->Branch(not_zero);
1824 } 1959 }
1825 operand->Unuse(); 1960 operand->Unuse();
1826 __ SmiTag(answer.reg()); 1961 __ SmiTag(answer.reg());
(...skipping 21 matching lines...) Expand all
1848 right = *operand; 1983 right = *operand;
1849 } 1984 }
1850 operand->Unuse(); 1985 operand->Unuse();
1851 1986
1852 answer = allocator()->Allocate(); 1987 answer = allocator()->Allocate();
1853 DeferredInlineSmiOperationReversed* deferred = 1988 DeferredInlineSmiOperationReversed* deferred =
1854 new DeferredInlineSmiOperationReversed(op, 1989 new DeferredInlineSmiOperationReversed(op,
1855 answer.reg(), 1990 answer.reg(),
1856 smi_value, 1991 smi_value,
1857 right.reg(), 1992 right.reg(),
1993 right.number_info(),
1858 overwrite_mode); 1994 overwrite_mode);
1859 __ mov(answer.reg(), Immediate(int_value)); 1995 __ mov(answer.reg(), Immediate(int_value));
1860 __ sar(ecx, kSmiTagSize); 1996 __ sar(ecx, kSmiTagSize);
1861 deferred->Branch(carry); 1997 if (!right.number_info().IsSmi()) {
1998 deferred->Branch(carry);
1999 }
1862 __ shl_cl(answer.reg()); 2000 __ shl_cl(answer.reg());
1863 __ cmp(answer.reg(), 0xc0000000); 2001 __ cmp(answer.reg(), 0xc0000000);
1864 deferred->Branch(sign); 2002 deferred->Branch(sign);
1865 __ SmiTag(answer.reg()); 2003 __ SmiTag(answer.reg());
1866 2004
1867 deferred->BindExit(); 2005 deferred->BindExit();
1868 } else { 2006 } else {
1869 // Only the least significant 5 bits of the shift value are used. 2007 // Only the least significant 5 bits of the shift value are used.
1870 // In the slow case, this masking is done inside the runtime call. 2008 // In the slow case, this masking is done inside the runtime call.
1871 int shift_value = int_value & 0x1f; 2009 int shift_value = int_value & 0x1f;
1872 operand->ToRegister(); 2010 operand->ToRegister();
1873 if (shift_value == 0) { 2011 if (shift_value == 0) {
1874 // Spill operand so it can be overwritten in the slow case. 2012 // Spill operand so it can be overwritten in the slow case.
1875 frame_->Spill(operand->reg()); 2013 frame_->Spill(operand->reg());
1876 DeferredInlineSmiOperation* deferred = 2014 DeferredInlineSmiOperation* deferred =
1877 new DeferredInlineSmiOperation(op, 2015 new DeferredInlineSmiOperation(op,
1878 operand->reg(), 2016 operand->reg(),
1879 operand->reg(), 2017 operand->reg(),
2018 operand->number_info(),
1880 smi_value, 2019 smi_value,
1881 overwrite_mode); 2020 overwrite_mode);
1882 __ test(operand->reg(), Immediate(kSmiTagMask)); 2021 if (!operand->number_info().IsSmi()) {
fschneider 2010/03/05 15:01:07 Also here only instantiate DeferredInlineSmiOperat
1883 deferred->Branch(not_zero); 2022 __ test(operand->reg(), Immediate(kSmiTagMask));
2023 deferred->Branch(not_zero);
2024 }
1884 deferred->BindExit(); 2025 deferred->BindExit();
1885 answer = *operand; 2026 answer = *operand;
1886 } else { 2027 } else {
1887 // Use a fresh temporary for nonzero shift values. 2028 // Use a fresh temporary for nonzero shift values.
1888 answer = allocator()->Allocate(); 2029 answer = allocator()->Allocate();
1889 ASSERT(answer.is_valid()); 2030 ASSERT(answer.is_valid());
1890 DeferredInlineSmiOperation* deferred = 2031 DeferredInlineSmiOperation* deferred =
1891 new DeferredInlineSmiOperation(op, 2032 new DeferredInlineSmiOperation(op,
1892 answer.reg(), 2033 answer.reg(),
1893 operand->reg(), 2034 operand->reg(),
2035 operand->number_info(),
1894 smi_value, 2036 smi_value,
1895 overwrite_mode); 2037 overwrite_mode);
1896 __ test(operand->reg(), Immediate(kSmiTagMask)); 2038 if (!operand->number_info().IsSmi()) {
1897 deferred->Branch(not_zero); 2039 __ test(operand->reg(), Immediate(kSmiTagMask));
2040 deferred->Branch(not_zero);
2041 }
1898 __ mov(answer.reg(), operand->reg()); 2042 __ mov(answer.reg(), operand->reg());
1899 ASSERT(kSmiTag == 0); // adjust code if not the case 2043 ASSERT(kSmiTag == 0); // adjust code if not the case
1900 // We do no shifts, only the Smi conversion, if shift_value is 1. 2044 // We do no shifts, only the Smi conversion, if shift_value is 1.
1901 if (shift_value > 1) { 2045 if (shift_value > 1) {
1902 __ shl(answer.reg(), shift_value - 1); 2046 __ shl(answer.reg(), shift_value - 1);
1903 } 2047 }
1904 // Convert int result to Smi, checking that it is in int range. 2048 // Convert int result to Smi, checking that it is in int range.
1905 ASSERT(kSmiTagSize == 1); // adjust code if not the case 2049 ASSERT(kSmiTagSize == 1); // adjust code if not the case
1906 __ add(answer.reg(), Operand(answer.reg())); 2050 __ add(answer.reg(), Operand(answer.reg()));
1907 deferred->Branch(overflow); 2051 deferred->Branch(overflow);
1908 deferred->BindExit(); 2052 deferred->BindExit();
1909 operand->Unuse(); 2053 operand->Unuse();
1910 } 2054 }
1911 } 2055 }
1912 break; 2056 break;
1913 2057
1914 case Token::BIT_OR: 2058 case Token::BIT_OR:
1915 case Token::BIT_XOR: 2059 case Token::BIT_XOR:
1916 case Token::BIT_AND: { 2060 case Token::BIT_AND: {
1917 operand->ToRegister(); 2061 operand->ToRegister();
1918 frame_->Spill(operand->reg()); 2062 frame_->Spill(operand->reg());
1919 DeferredCode* deferred = NULL; 2063 DeferredCode* deferred = NULL;
1920 if (reversed) { 2064 if (reversed) {
1921 deferred = new DeferredInlineSmiOperationReversed(op, 2065 deferred = new DeferredInlineSmiOperationReversed(op,
1922 operand->reg(), 2066 operand->reg(),
1923 smi_value, 2067 smi_value,
1924 operand->reg(), 2068 operand->reg(),
2069 operand->number_info() ,
fschneider 2010/03/05 15:01:07 long line.
1925 overwrite_mode); 2070 overwrite_mode);
1926 } else { 2071 } else {
1927 deferred = new DeferredInlineSmiOperation(op, 2072 deferred = new DeferredInlineSmiOperation(op,
1928 operand->reg(), 2073 operand->reg(),
1929 operand->reg(), 2074 operand->reg(),
2075 operand->number_info(),
1930 smi_value, 2076 smi_value,
1931 overwrite_mode); 2077 overwrite_mode);
1932 } 2078 }
1933 __ test(operand->reg(), Immediate(kSmiTagMask)); 2079 if (!operand->number_info().IsSmi()) {
fschneider 2010/03/05 15:01:07 Also here only instantiate DeferredInlineSmiOperat
Erik Corry 2010/03/05 20:20:15 Actually instead I will remove the 'if' since shif
1934 deferred->Branch(not_zero); 2080 __ test(operand->reg(), Immediate(kSmiTagMask));
2081 deferred->Branch(not_zero);
2082 }
1935 if (op == Token::BIT_AND) { 2083 if (op == Token::BIT_AND) {
1936 __ and_(Operand(operand->reg()), Immediate(value)); 2084 __ and_(Operand(operand->reg()), Immediate(value));
1937 } else if (op == Token::BIT_XOR) { 2085 } else if (op == Token::BIT_XOR) {
1938 if (int_value != 0) { 2086 if (int_value != 0) {
1939 __ xor_(Operand(operand->reg()), Immediate(value)); 2087 __ xor_(Operand(operand->reg()), Immediate(value));
1940 } 2088 }
1941 } else { 2089 } else {
1942 ASSERT(op == Token::BIT_OR); 2090 ASSERT(op == Token::BIT_OR);
1943 if (int_value != 0) { 2091 if (int_value != 0) {
1944 __ or_(Operand(operand->reg()), Immediate(value)); 2092 __ or_(Operand(operand->reg()), Immediate(value));
1945 } 2093 }
1946 } 2094 }
1947 deferred->BindExit(); 2095 deferred->BindExit();
1948 answer = *operand; 2096 answer = *operand;
1949 break; 2097 break;
1950 } 2098 }
1951 2099
1952 case Token::DIV: 2100 case Token::DIV:
1953 if (!reversed && int_value == 2) { 2101 if (!reversed && int_value == 2) {
1954 operand->ToRegister(); 2102 operand->ToRegister();
1955 frame_->Spill(operand->reg()); 2103 frame_->Spill(operand->reg());
1956 2104
1957 DeferredInlineSmiOperation* deferred = 2105 DeferredInlineSmiOperation* deferred =
1958 new DeferredInlineSmiOperation(op, 2106 new DeferredInlineSmiOperation(op,
1959 operand->reg(), 2107 operand->reg(),
1960 operand->reg(), 2108 operand->reg(),
2109 operand->number_info(),
1961 smi_value, 2110 smi_value,
1962 overwrite_mode); 2111 overwrite_mode);
1963 // Check that lowest log2(value) bits of operand are zero, and test 2112 // Check that lowest log2(value) bits of operand are zero, and test
1964 // smi tag at the same time. 2113 // smi tag at the same time.
1965 ASSERT_EQ(0, kSmiTag); 2114 ASSERT_EQ(0, kSmiTag);
1966 ASSERT_EQ(1, kSmiTagSize); 2115 ASSERT_EQ(1, kSmiTagSize);
1967 __ test(operand->reg(), Immediate(3)); 2116 __ test(operand->reg(), Immediate(3));
1968 deferred->Branch(not_zero); // Branch if non-smi or odd smi. 2117 deferred->Branch(not_zero); // Branch if non-smi or odd smi.
1969 __ sar(operand->reg(), 1); 2118 __ sar(operand->reg(), 1);
1970 deferred->BindExit(); 2119 deferred->BindExit();
(...skipping 14 matching lines...) Expand all
1985 // Generate inline code for mod of powers of 2 and negative powers of 2. 2134 // Generate inline code for mod of powers of 2 and negative powers of 2.
1986 case Token::MOD: 2135 case Token::MOD:
1987 if (!reversed && 2136 if (!reversed &&
1988 int_value != 0 && 2137 int_value != 0 &&
1989 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { 2138 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) {
1990 operand->ToRegister(); 2139 operand->ToRegister();
1991 frame_->Spill(operand->reg()); 2140 frame_->Spill(operand->reg());
1992 DeferredCode* deferred = new DeferredInlineSmiOperation(op, 2141 DeferredCode* deferred = new DeferredInlineSmiOperation(op,
1993 operand->reg(), 2142 operand->reg(),
1994 operand->reg(), 2143 operand->reg(),
2144 operand->number_ info(),
fschneider 2010/03/05 15:01:07 Long line.
1995 smi_value, 2145 smi_value,
1996 overwrite_mode); 2146 overwrite_mode);
1997 // Check for negative or non-Smi left hand side. 2147 // Check for negative or non-Smi left hand side.
1998 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); 2148 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000));
1999 deferred->Branch(not_zero); 2149 deferred->Branch(not_zero);
2000 if (int_value < 0) int_value = -int_value; 2150 if (int_value < 0) int_value = -int_value;
2001 if (int_value == 1) { 2151 if (int_value == 1) {
2002 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); 2152 __ mov(operand->reg(), Immediate(Smi::FromInt(0)));
2003 } else { 2153 } else {
2004 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); 2154 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1);
(...skipping 15 matching lines...) Expand all
2020 } 2170 }
2021 break; 2171 break;
2022 } 2172 }
2023 } 2173 }
2024 ASSERT(answer.is_valid()); 2174 ASSERT(answer.is_valid());
2025 return answer; 2175 return answer;
2026 } 2176 }
2027 2177
2028 2178
2029 static bool CouldBeNaN(const Result& result) { 2179 static bool CouldBeNaN(const Result& result) {
2180 if (result.number_info().IsSmi()) return false;
2181 if (result.number_info().IsInteger32()) return false;
2030 if (!result.is_constant()) return true; 2182 if (!result.is_constant()) return true;
2031 if (!result.handle()->IsHeapNumber()) return false; 2183 if (!result.handle()->IsHeapNumber()) return false;
2032 return isnan(HeapNumber::cast(*result.handle())->value()); 2184 return isnan(HeapNumber::cast(*result.handle())->value());
2033 } 2185 }
2034 2186
2035 2187
2036 void CodeGenerator::Comparison(AstNode* node, 2188 void CodeGenerator::Comparison(AstNode* node,
2037 Condition cc, 2189 Condition cc,
2038 bool strict, 2190 bool strict,
2039 ControlDestination* dest) { 2191 ControlDestination* dest) {
(...skipping 5083 matching lines...) Expand 10 before | Expand all | Expand 10 after
7123 // Initially, use an invalid map. The map is patched in the IC 7275 // Initially, use an invalid map. The map is patched in the IC
7124 // initialization code. 7276 // initialization code.
7125 __ bind(deferred->patch_site()); 7277 __ bind(deferred->patch_site());
7126 // Use masm-> here instead of the double underscore macro since extra 7278 // Use masm-> here instead of the double underscore macro since extra
7127 // coverage code can interfere with the patching. 7279 // coverage code can interfere with the patching.
7128 masm_->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 7280 masm_->cmp(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
7129 Immediate(Factory::null_value())); 7281 Immediate(Factory::null_value()));
7130 deferred->Branch(not_equal); 7282 deferred->Branch(not_equal);
7131 7283
7132 // Check that the key is a smi. 7284 // Check that the key is a smi.
7133 __ test(key.reg(), Immediate(kSmiTagMask)); 7285 if (!key.is_smi()) {
7134 deferred->Branch(not_zero); 7286 __ test(key.reg(), Immediate(kSmiTagMask));
7287 deferred->Branch(not_zero);
7288 }
7135 7289
7136 // Get the elements array from the receiver and check that it 7290 // Get the elements array from the receiver and check that it
7137 // is not a dictionary. 7291 // is not a dictionary.
7138 __ mov(elements.reg(), 7292 __ mov(elements.reg(),
7139 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); 7293 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
7140 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), 7294 __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
7141 Immediate(Factory::fixed_array_map())); 7295 Immediate(Factory::fixed_array_map()));
7142 deferred->Branch(not_equal); 7296 deferred->Branch(not_equal);
7143 7297
7144 // Shift the key to get the actual index value and check that 7298 // Shift the key to get the actual index value and check that
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
7269 } 7423 }
7270 ASSERT(frame()->height() == original_height - 3); 7424 ASSERT(frame()->height() == original_height - 3);
7271 return result; 7425 return result;
7272 } 7426 }
7273 7427
7274 7428
7275 #undef __ 7429 #undef __
7276 #define __ ACCESS_MASM(masm) 7430 #define __ ACCESS_MASM(masm)
7277 7431
7278 7432
7433 static void CheckTwoForSminess(MacroAssembler* masm,
7434 Register left, Register right, Register scratch,
7435 NumberInfo left_info, NumberInfo right_info,
7436 DeferredInlineBinaryOperation* deferred) {
7437 if (left.is(right)) {
7438 if (!left_info.IsSmi()) {
7439 __ test(left, Immediate(kSmiTagMask));
7440 deferred->Branch(not_zero);
7441 }
7442 } else if (!left_info.IsSmi()) {
7443 if (!right_info.IsSmi()) {
7444 __ mov(scratch, left);
7445 __ or_(scratch, Operand(right));
7446 __ test(scratch, Immediate(kSmiTagMask));
7447 deferred->Branch(not_zero);
7448 } else {
7449 __ test (left, Immediate(kSmiTagMask));
7450 deferred->Branch(not_zero);
7451 }
7452 } else {
7453 if (!right_info.IsSmi()) {
7454 __ test(right, Immediate(kSmiTagMask));
7455 deferred->Branch(not_zero);
7456 }
7457 }
7458 }
7459
7460
7279 Handle<String> Reference::GetName() { 7461 Handle<String> Reference::GetName() {
7280 ASSERT(type_ == NAMED); 7462 ASSERT(type_ == NAMED);
7281 Property* property = expression_->AsProperty(); 7463 Property* property = expression_->AsProperty();
7282 if (property == NULL) { 7464 if (property == NULL) {
7283 // Global variable reference treated as a named property reference. 7465 // Global variable reference treated as a named property reference.
7284 VariableProxy* proxy = expression_->AsVariableProxy(); 7466 VariableProxy* proxy = expression_->AsVariableProxy();
7285 ASSERT(proxy->AsVariable() != NULL); 7467 ASSERT(proxy->AsVariable() != NULL);
7286 ASSERT(proxy->AsVariable()->is_global()); 7468 ASSERT(proxy->AsVariable()->is_global());
7287 return proxy->name(); 7469 return proxy->name();
7288 } else { 7470 } else {
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
7769 if (HasArgsInRegisters()) { 7951 if (HasArgsInRegisters()) {
7770 __ mov(ebx, eax); 7952 __ mov(ebx, eax);
7771 __ mov(eax, edx); 7953 __ mov(eax, edx);
7772 } 7954 }
7773 } 7955 }
7774 if (!HasArgsInRegisters()) { 7956 if (!HasArgsInRegisters()) {
7775 __ mov(right, Operand(esp, 1 * kPointerSize)); 7957 __ mov(right, Operand(esp, 1 * kPointerSize));
7776 __ mov(left, Operand(esp, 2 * kPointerSize)); 7958 __ mov(left, Operand(esp, 2 * kPointerSize));
7777 } 7959 }
7778 7960
7961 if (static_operands_type_.IsSmi()) {
7962 if (op_ == Token::BIT_OR) {
7963 __ or_(right, Operand(left));
7964 GenerateReturn(masm);
7965 return;
7966 } else if (op_ == Token::BIT_AND) {
7967 __ and_(right, Operand(left));
7968 GenerateReturn(masm);
7969 return;
7970 } else if (op_ == Token::BIT_XOR) {
7971 __ xor_(right, Operand(left));
7972 GenerateReturn(masm);
7973 return;
7974 }
7975 }
7976
7779 // 2. Prepare the smi check of both operands by oring them together. 7977 // 2. Prepare the smi check of both operands by oring them together.
7780 Comment smi_check_comment(masm, "-- Smi check arguments"); 7978 Comment smi_check_comment(masm, "-- Smi check arguments");
7781 Label not_smis; 7979 Label not_smis;
7782 Register combined = ecx; 7980 Register combined = ecx;
7783 ASSERT(!left.is(combined) && !right.is(combined)); 7981 ASSERT(!left.is(combined) && !right.is(combined));
7784 switch (op_) { 7982 switch (op_) {
7785 case Token::BIT_OR: 7983 case Token::BIT_OR:
7786 // Perform the operation into eax and smi check the result. Preserve 7984 // Perform the operation into eax and smi check the result. Preserve
7787 // eax in case the result is not a smi. 7985 // eax in case the result is not a smi.
7788 ASSERT(!left.is(ecx) && !right.is(ecx)); 7986 ASSERT(!left.is(ecx) && !right.is(ecx));
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
8105 // (and only if smi code is generated). This is the right moment to 8303 // (and only if smi code is generated). This is the right moment to
8106 // patch to HEAP_NUMBERS state. The transition is attempted only for 8304 // patch to HEAP_NUMBERS state. The transition is attempted only for
8107 // the four basic operations. The stub stays in the DEFAULT state 8305 // the four basic operations. The stub stays in the DEFAULT state
8108 // forever for all other operations (also if smi code is skipped). 8306 // forever for all other operations (also if smi code is skipped).
8109 GenerateTypeTransition(masm); 8307 GenerateTypeTransition(masm);
8110 } 8308 }
8111 8309
8112 Label not_floats; 8310 Label not_floats;
8113 if (CpuFeatures::IsSupported(SSE2)) { 8311 if (CpuFeatures::IsSupported(SSE2)) {
8114 CpuFeatures::Scope use_sse2(SSE2); 8312 CpuFeatures::Scope use_sse2(SSE2);
8115 if (NumberInfo::IsNumber(static_operands_type_)) { 8313 if (static_operands_type_.IsNumber()) {
8116 if (FLAG_debug_code) { 8314 if (FLAG_debug_code) {
8117 // Assert at runtime that inputs are only numbers. 8315 // Assert at runtime that inputs are only numbers.
8118 __ AbortIfNotNumber(edx, 8316 __ AbortIfNotNumber(edx,
8119 "GenericBinaryOpStub operand not a number."); 8317 "GenericBinaryOpStub operand not a number.");
8120 __ AbortIfNotNumber(eax, 8318 __ AbortIfNotNumber(eax,
8121 "GenericBinaryOpStub operand not a number."); 8319 "GenericBinaryOpStub operand not a number.");
8122 } 8320 }
8123 FloatingPointHelper::LoadSSE2Operands(masm); 8321 if (static_operands_type_.IsSmi()) {
8322 FloatingPointHelper::LoadSSE2Smis(masm, ecx);
8323 } else {
8324 FloatingPointHelper::LoadSSE2Operands(masm);
8325 }
8124 } else { 8326 } else {
8125 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime); 8327 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
8126 } 8328 }
8127 8329
8128 switch (op_) { 8330 switch (op_) {
8129 case Token::ADD: __ addsd(xmm0, xmm1); break; 8331 case Token::ADD: __ addsd(xmm0, xmm1); break;
8130 case Token::SUB: __ subsd(xmm0, xmm1); break; 8332 case Token::SUB: __ subsd(xmm0, xmm1); break;
8131 case Token::MUL: __ mulsd(xmm0, xmm1); break; 8333 case Token::MUL: __ mulsd(xmm0, xmm1); break;
8132 case Token::DIV: __ divsd(xmm0, xmm1); break; 8334 case Token::DIV: __ divsd(xmm0, xmm1); break;
8133 default: UNREACHABLE(); 8335 default: UNREACHABLE();
8134 } 8336 }
8135 GenerateHeapResultAllocation(masm, &call_runtime); 8337 GenerateHeapResultAllocation(masm, &call_runtime);
8136 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 8338 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
8137 GenerateReturn(masm); 8339 GenerateReturn(masm);
8138 } else { // SSE2 not available, use FPU. 8340 } else { // SSE2 not available, use FPU.
8139 if (NumberInfo::IsNumber(static_operands_type_)) { 8341 if (static_operands_type_.IsNumber()) {
8140 if (FLAG_debug_code) { 8342 if (FLAG_debug_code) {
8141 // Assert at runtime that inputs are only numbers. 8343 // Assert at runtime that inputs are only numbers.
8142 __ AbortIfNotNumber(edx, 8344 __ AbortIfNotNumber(edx,
8143 "GenericBinaryOpStub operand not a number."); 8345 "GenericBinaryOpStub operand not a number.");
8144 __ AbortIfNotNumber(eax, 8346 __ AbortIfNotNumber(eax,
8145 "GenericBinaryOpStub operand not a number."); 8347 "GenericBinaryOpStub operand not a number.");
8146 } 8348 }
8147 } else { 8349 } else {
8148 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 8350 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
8149 } 8351 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
8183 // For MOD we go directly to runtime in the non-smi case. 8385 // For MOD we go directly to runtime in the non-smi case.
8184 break; 8386 break;
8185 } 8387 }
8186 case Token::BIT_OR: 8388 case Token::BIT_OR:
8187 case Token::BIT_AND: 8389 case Token::BIT_AND:
8188 case Token::BIT_XOR: 8390 case Token::BIT_XOR:
8189 case Token::SAR: 8391 case Token::SAR:
8190 case Token::SHL: 8392 case Token::SHL:
8191 case Token::SHR: { 8393 case Token::SHR: {
8192 Label non_smi_result; 8394 Label non_smi_result;
8193 FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime); 8395 FloatingPointHelper::LoadAsIntegers(masm,
8396 static_operands_type_,
8397 use_sse3_,
8398 &call_runtime);
8194 switch (op_) { 8399 switch (op_) {
8195 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break; 8400 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
8196 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break; 8401 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
8197 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break; 8402 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break;
8198 case Token::SAR: __ sar_cl(eax); break; 8403 case Token::SAR: __ sar_cl(eax); break;
8199 case Token::SHL: __ shl_cl(eax); break; 8404 case Token::SHL: __ shl_cl(eax); break;
8200 case Token::SHR: __ shr_cl(eax); break; 8405 case Token::SHR: __ shr_cl(eax); break;
8201 default: UNREACHABLE(); 8406 default: UNREACHABLE();
8202 } 8407 }
8203 if (op_ == Token::SHR) { 8408 if (op_ == Token::SHR) {
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
8712 __ bind(&done); 8917 __ bind(&done);
8713 } 8918 }
8714 8919
8715 8920
8716 // Get the integer part of a heap number. Surprisingly, all this bit twiddling 8921 // Get the integer part of a heap number. Surprisingly, all this bit twiddling
8717 // is faster than using the built-in instructions on floating point registers. 8922 // is faster than using the built-in instructions on floating point registers.
8718 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the 8923 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the
8719 // trashed registers. 8924 // trashed registers.
8720 void IntegerConvert(MacroAssembler* masm, 8925 void IntegerConvert(MacroAssembler* masm,
8721 Register source, 8926 Register source,
8927 NumberInfo number_info,
8722 bool use_sse3, 8928 bool use_sse3,
8723 Label* conversion_failure) { 8929 Label* conversion_failure) {
8724 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); 8930 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx));
8725 Label done, right_exponent, normal_exponent; 8931 Label done, right_exponent, normal_exponent;
8726 Register scratch = ebx; 8932 Register scratch = ebx;
8727 Register scratch2 = edi; 8933 Register scratch2 = edi;
8728 // Get exponent word. 8934 if (!number_info.IsInteger32() || !use_sse3) {
8729 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); 8935 // Get exponent word.
8730 // Get exponent alone in scratch2. 8936 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset));
8731 __ mov(scratch2, scratch); 8937 // Get exponent alone in scratch2.
8732 __ and_(scratch2, HeapNumber::kExponentMask); 8938 __ mov(scratch2, scratch);
8939 __ and_(scratch2, HeapNumber::kExponentMask);
8940 }
8733 if (use_sse3) { 8941 if (use_sse3) {
8734 CpuFeatures::Scope scope(SSE3); 8942 CpuFeatures::Scope scope(SSE3);
8735 // Check whether the exponent is too big for a 64 bit signed integer. 8943 if (!number_info.IsInteger32()) {
8736 static const uint32_t kTooBigExponent = 8944 // Check whether the exponent is too big for a 64 bit signed integer.
8737 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 8945 static const uint32_t kTooBigExponent =
8738 __ cmp(Operand(scratch2), Immediate(kTooBigExponent)); 8946 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
8739 __ j(greater_equal, conversion_failure); 8947 __ cmp(Operand(scratch2), Immediate(kTooBigExponent));
8948 __ j(greater_equal, conversion_failure);
8949 }
8740 // Load x87 register with heap number. 8950 // Load x87 register with heap number.
8741 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); 8951 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset));
8742 // Reserve space for 64 bit answer. 8952 // Reserve space for 64 bit answer.
8743 __ sub(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint. 8953 __ sub(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint.
8744 // Do conversion, which cannot fail because we checked the exponent. 8954 // Do conversion, which cannot fail because we checked the exponent.
8745 __ fisttp_d(Operand(esp, 0)); 8955 __ fisttp_d(Operand(esp, 0));
8746 __ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx. 8956 __ mov(ecx, Operand(esp, 0)); // Load low word of answer into ecx.
8747 __ add(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint. 8957 __ add(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint.
8748 } else { 8958 } else {
8749 // Load ecx with zero. We use this either for the final shift or 8959 // Load ecx with zero. We use this either for the final shift or
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
8844 __ bind(&negative); 9054 __ bind(&negative);
8845 __ sub(ecx, Operand(scratch2)); 9055 __ sub(ecx, Operand(scratch2));
8846 __ bind(&done); 9056 __ bind(&done);
8847 } 9057 }
8848 } 9058 }
8849 9059
8850 9060
8851 // Input: edx, eax are the left and right objects of a bit op. 9061 // Input: edx, eax are the left and right objects of a bit op.
8852 // Output: eax, ecx are left and right integers for a bit op. 9062 // Output: eax, ecx are left and right integers for a bit op.
8853 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, 9063 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
9064 NumberInfo number_info,
8854 bool use_sse3, 9065 bool use_sse3,
8855 Label* conversion_failure) { 9066 Label* conversion_failure) {
8856 // Check float operands. 9067 // Check float operands.
8857 Label arg1_is_object, check_undefined_arg1; 9068 Label arg1_is_object, check_undefined_arg1;
8858 Label arg2_is_object, check_undefined_arg2; 9069 Label arg2_is_object, check_undefined_arg2;
8859 Label load_arg2, done; 9070 Label load_arg2, done;
8860 9071
8861 __ test(edx, Immediate(kSmiTagMask)); 9072 if (number_info.IsHeapNumber()) {
fschneider 2010/03/05 15:01:07 This function is getting quite messy with all the
8862 __ j(not_zero, &arg1_is_object); 9073 __ jmp (&arg1_is_object);
fschneider 2010/03/05 15:01:07 Remove extra space.
8863 __ SmiUntag(edx); 9074 } else {
8864 __ jmp(&load_arg2); 9075 if (!number_info.IsSmi()) {
9076 __ test(edx, Immediate(kSmiTagMask));
9077 __ j(not_zero, &arg1_is_object);
9078 }
9079 __ SmiUntag(edx);
9080 __ jmp(&load_arg2);
9081 }
8865 9082
8866 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 9083 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
8867 __ bind(&check_undefined_arg1); 9084 if (!number_info.IsNumber()) {
8868 __ cmp(edx, Factory::undefined_value()); 9085 __ bind(&check_undefined_arg1);
8869 __ j(not_equal, conversion_failure); 9086 __ cmp(edx, Factory::undefined_value());
8870 __ mov(edx, Immediate(0)); 9087 __ j(not_equal, conversion_failure);
8871 __ jmp(&load_arg2); 9088 __ mov(edx, Immediate(0));
9089 __ jmp(&load_arg2);
9090 }
8872 9091
8873 __ bind(&arg1_is_object); 9092 __ bind(&arg1_is_object);
8874 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 9093 if (!number_info.IsNumber()) {
8875 __ cmp(ebx, Factory::heap_number_map()); 9094 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
8876 __ j(not_equal, &check_undefined_arg1); 9095 __ cmp(ebx, Factory::heap_number_map());
9096 __ j(not_equal, &check_undefined_arg1);
9097 }
8877 // Get the untagged integer version of the edx heap number in ecx. 9098 // Get the untagged integer version of the edx heap number in ecx.
8878 IntegerConvert(masm, edx, use_sse3, conversion_failure); 9099 IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure);
8879 __ mov(edx, ecx); 9100 __ mov(edx, ecx);
8880 9101
8881 // Here edx has the untagged integer, eax has a Smi or a heap number. 9102 // Here edx has the untagged integer, eax has a Smi or a heap number.
8882 __ bind(&load_arg2); 9103 __ bind(&load_arg2);
8883 // Test if arg2 is a Smi. 9104 if (number_info.IsHeapNumber()) {
8884 __ test(eax, Immediate(kSmiTagMask)); 9105 __ jmp(&arg2_is_object);
8885 __ j(not_zero, &arg2_is_object); 9106 } else {
8886 __ SmiUntag(eax); 9107 // Test if arg2 is a Smi.
8887 __ mov(ecx, eax); 9108 if (!number_info.IsSmi()) {
8888 __ jmp(&done); 9109 __ test(eax, Immediate(kSmiTagMask));
9110 __ j(not_zero, &arg2_is_object);
9111 }
9112 __ SmiUntag(eax);
9113 __ mov(ecx, eax);
9114 __ jmp(&done);
9115 }
8889 9116
8890 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 9117 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
8891 __ bind(&check_undefined_arg2); 9118 if (!number_info.IsNumber()) {
8892 __ cmp(eax, Factory::undefined_value()); 9119 __ bind(&check_undefined_arg2);
8893 __ j(not_equal, conversion_failure); 9120 __ cmp(eax, Factory::undefined_value());
8894 __ mov(ecx, Immediate(0)); 9121 __ j(not_equal, conversion_failure);
8895 __ jmp(&done); 9122 __ mov(ecx, Immediate(0));
9123 __ jmp(&done);
9124 }
8896 9125
8897 __ bind(&arg2_is_object); 9126 __ bind(&arg2_is_object);
8898 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); 9127 if (!number_info.IsNumber()) {
8899 __ cmp(ebx, Factory::heap_number_map()); 9128 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
8900 __ j(not_equal, &check_undefined_arg2); 9129 __ cmp(ebx, Factory::heap_number_map());
9130 __ j(not_equal, &check_undefined_arg2);
9131 }
8901 // Get the untagged integer version of the eax heap number in ecx. 9132 // Get the untagged integer version of the eax heap number in ecx.
8902 IntegerConvert(masm, eax, use_sse3, conversion_failure); 9133 IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure);
8903 __ bind(&done); 9134 __ bind(&done);
8904 __ mov(eax, edx); 9135 __ mov(eax, edx);
8905 } 9136 }
8906 9137
8907 9138
8908 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 9139 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
8909 Register number) { 9140 Register number) {
8910 Label load_smi, done; 9141 Label load_smi, done;
8911 9142
8912 __ test(number, Immediate(kSmiTagMask)); 9143 __ test(number, Immediate(kSmiTagMask));
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
9134 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); 9365 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset));
9135 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 9366 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
9136 } 9367 }
9137 } else if (op_ == Token::BIT_NOT) { 9368 } else if (op_ == Token::BIT_NOT) {
9138 // Check if the operand is a heap number. 9369 // Check if the operand is a heap number.
9139 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 9370 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
9140 __ cmp(edx, Factory::heap_number_map()); 9371 __ cmp(edx, Factory::heap_number_map());
9141 __ j(not_equal, &slow, not_taken); 9372 __ j(not_equal, &slow, not_taken);
9142 9373
9143 // Convert the heap number in eax to an untagged integer in ecx. 9374 // Convert the heap number in eax to an untagged integer in ecx.
9144 IntegerConvert(masm, eax, CpuFeatures::IsSupported(SSE3), &slow); 9375 IntegerConvert(masm,
9376 eax,
9377 NumberInfo::Unknown(),
9378 CpuFeatures::IsSupported(SSE3),
9379 &slow);
9145 9380
9146 // Do the bitwise operation and check if the result fits in a smi. 9381 // Do the bitwise operation and check if the result fits in a smi.
9147 Label try_float; 9382 Label try_float;
9148 __ not_(ecx); 9383 __ not_(ecx);
9149 __ cmp(ecx, 0xc0000000); 9384 __ cmp(ecx, 0xc0000000);
9150 __ j(sign, &try_float, not_taken); 9385 __ j(sign, &try_float, not_taken);
9151 9386
9152 // Tag the result as a smi and we're done. 9387 // Tag the result as a smi and we're done.
9153 ASSERT(kSmiTagSize == 1); 9388 ASSERT(kSmiTagSize == 1);
9154 __ lea(eax, Operand(ecx, times_2, kSmiTag)); 9389 __ lea(eax, Operand(ecx, times_2, kSmiTag));
(...skipping 2229 matching lines...) Expand 10 before | Expand all | Expand 10 after
11384 11619
11385 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 11620 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
11386 // tagged as a small integer. 11621 // tagged as a small integer.
11387 __ bind(&runtime); 11622 __ bind(&runtime);
11388 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 11623 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
11389 } 11624 }
11390 11625
11391 #undef __ 11626 #undef __
11392 11627
11393 } } // namespace v8::internal 11628 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | src/number-info.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698