OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 __ bind(&ok); | 843 __ bind(&ok); |
844 } | 844 } |
845 // In the integer32 case there are no Smis hidden in heap numbers, so we | 845 // In the integer32 case there are no Smis hidden in heap numbers, so we |
846 // need only test for Smi zero. | 846 // need only test for Smi zero. |
847 __ test(value.reg(), Operand(value.reg())); | 847 __ test(value.reg(), Operand(value.reg())); |
848 dest->false_target()->Branch(zero); | 848 dest->false_target()->Branch(zero); |
849 value.Unuse(); | 849 value.Unuse(); |
850 dest->Split(not_zero); | 850 dest->Split(not_zero); |
851 } else if (value.is_number()) { | 851 } else if (value.is_number()) { |
852 Comment cmnt(masm_, "ONLY_NUMBER"); | 852 Comment cmnt(masm_, "ONLY_NUMBER"); |
853 // Fast case if NumberInfo indicates only numbers. | 853 // Fast case if TypeInfo indicates only numbers. |
854 if (FLAG_debug_code) { | 854 if (FLAG_debug_code) { |
855 __ AbortIfNotNumber(value.reg()); | 855 __ AbortIfNotNumber(value.reg()); |
856 } | 856 } |
857 // Smi => false iff zero. | 857 // Smi => false iff zero. |
858 ASSERT(kSmiTag == 0); | 858 ASSERT(kSmiTag == 0); |
859 __ test(value.reg(), Operand(value.reg())); | 859 __ test(value.reg(), Operand(value.reg())); |
860 dest->false_target()->Branch(zero); | 860 dest->false_target()->Branch(zero); |
861 __ test(value.reg(), Immediate(kSmiTagMask)); | 861 __ test(value.reg(), Immediate(kSmiTagMask)); |
862 dest->true_target()->Branch(zero); | 862 dest->true_target()->Branch(zero); |
863 __ fldz(); | 863 __ fldz(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
925 | 925 |
926 // Test if operands are smi or number objects (fp). Requirements: | 926 // Test if operands are smi or number objects (fp). Requirements: |
927 // operand_1 in eax, operand_2 in edx; falls through on float | 927 // operand_1 in eax, operand_2 in edx; falls through on float |
928 // operands, jumps to the non_float label otherwise. | 928 // operands, jumps to the non_float label otherwise. |
929 static void CheckFloatOperands(MacroAssembler* masm, | 929 static void CheckFloatOperands(MacroAssembler* masm, |
930 Label* non_float, | 930 Label* non_float, |
931 Register scratch); | 931 Register scratch); |
932 // Takes the operands in edx and eax and loads them as integers in eax | 932 // Takes the operands in edx and eax and loads them as integers in eax |
933 // and ecx. | 933 // and ecx. |
934 static void LoadAsIntegers(MacroAssembler* masm, | 934 static void LoadAsIntegers(MacroAssembler* masm, |
935 NumberInfo number_info, | 935 TypeInfo type_info, |
936 bool use_sse3, | 936 bool use_sse3, |
937 Label* operand_conversion_failure); | 937 Label* operand_conversion_failure); |
938 static void LoadNumbersAsIntegers(MacroAssembler* masm, | 938 static void LoadNumbersAsIntegers(MacroAssembler* masm, |
939 NumberInfo number_info, | 939 TypeInfo type_info, |
940 bool use_sse3, | 940 bool use_sse3, |
941 Label* operand_conversion_failure); | 941 Label* operand_conversion_failure); |
942 static void LoadUnknownsAsIntegers(MacroAssembler* masm, | 942 static void LoadUnknownsAsIntegers(MacroAssembler* masm, |
943 bool use_sse3, | 943 bool use_sse3, |
944 Label* operand_conversion_failure); | 944 Label* operand_conversion_failure); |
945 | 945 |
946 // Test if operands are smis or heap numbers and load them | 946 // Test if operands are smis or heap numbers and load them |
947 // into xmm0 and xmm1 if they are. Operands are in edx and eax. | 947 // into xmm0 and xmm1 if they are. Operands are in edx and eax. |
948 // Leaves operands unchanged. | 948 // Leaves operands unchanged. |
949 static void LoadSSE2Operands(MacroAssembler* masm); | 949 static void LoadSSE2Operands(MacroAssembler* masm); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 } | 986 } |
987 | 987 |
988 | 988 |
989 // Call the specialized stub for a binary operation. | 989 // Call the specialized stub for a binary operation. |
990 class DeferredInlineBinaryOperation: public DeferredCode { | 990 class DeferredInlineBinaryOperation: public DeferredCode { |
991 public: | 991 public: |
992 DeferredInlineBinaryOperation(Token::Value op, | 992 DeferredInlineBinaryOperation(Token::Value op, |
993 Register dst, | 993 Register dst, |
994 Register left, | 994 Register left, |
995 Register right, | 995 Register right, |
996 NumberInfo left_info, | 996 TypeInfo left_info, |
997 NumberInfo right_info, | 997 TypeInfo right_info, |
998 OverwriteMode mode) | 998 OverwriteMode mode) |
999 : op_(op), dst_(dst), left_(left), right_(right), | 999 : op_(op), dst_(dst), left_(left), right_(right), |
1000 left_info_(left_info), right_info_(right_info), mode_(mode) { | 1000 left_info_(left_info), right_info_(right_info), mode_(mode) { |
1001 set_comment("[ DeferredInlineBinaryOperation"); | 1001 set_comment("[ DeferredInlineBinaryOperation"); |
1002 } | 1002 } |
1003 | 1003 |
1004 virtual void Generate(); | 1004 virtual void Generate(); |
1005 | 1005 |
1006 private: | 1006 private: |
1007 Token::Value op_; | 1007 Token::Value op_; |
1008 Register dst_; | 1008 Register dst_; |
1009 Register left_; | 1009 Register left_; |
1010 Register right_; | 1010 Register right_; |
1011 NumberInfo left_info_; | 1011 TypeInfo left_info_; |
1012 NumberInfo right_info_; | 1012 TypeInfo right_info_; |
1013 OverwriteMode mode_; | 1013 OverwriteMode mode_; |
1014 }; | 1014 }; |
1015 | 1015 |
1016 | 1016 |
1017 void DeferredInlineBinaryOperation::Generate() { | 1017 void DeferredInlineBinaryOperation::Generate() { |
1018 Label done; | 1018 Label done; |
1019 if (CpuFeatures::IsSupported(SSE2) && ((op_ == Token::ADD) || | 1019 if (CpuFeatures::IsSupported(SSE2) && ((op_ == Token::ADD) || |
1020 (op_ ==Token::SUB) || | 1020 (op_ ==Token::SUB) || |
1021 (op_ == Token::MUL) || | 1021 (op_ == Token::MUL) || |
1022 (op_ == Token::DIV))) { | 1022 (op_ == Token::DIV))) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 __ movdbl(FieldOperand(dst_, HeapNumber::kValueOffset), xmm0); | 1096 __ movdbl(FieldOperand(dst_, HeapNumber::kValueOffset), xmm0); |
1097 __ jmp(&done); | 1097 __ jmp(&done); |
1098 | 1098 |
1099 __ bind(&after_alloc_failure); | 1099 __ bind(&after_alloc_failure); |
1100 __ pop(left_); | 1100 __ pop(left_); |
1101 __ bind(&call_runtime); | 1101 __ bind(&call_runtime); |
1102 } | 1102 } |
1103 GenericBinaryOpStub stub(op_, | 1103 GenericBinaryOpStub stub(op_, |
1104 mode_, | 1104 mode_, |
1105 NO_SMI_CODE_IN_STUB, | 1105 NO_SMI_CODE_IN_STUB, |
1106 NumberInfo::Combine(left_info_, right_info_)); | 1106 TypeInfo::Combine(left_info_, right_info_)); |
1107 stub.GenerateCall(masm_, left_, right_); | 1107 stub.GenerateCall(masm_, left_, right_); |
1108 if (!dst_.is(eax)) __ mov(dst_, eax); | 1108 if (!dst_.is(eax)) __ mov(dst_, eax); |
1109 __ bind(&done); | 1109 __ bind(&done); |
1110 } | 1110 } |
1111 | 1111 |
1112 | 1112 |
1113 static NumberInfo CalculateNumberInfo(NumberInfo operands_type, | 1113 static TypeInfo CalculateTypeInfo(TypeInfo operands_type, |
1114 Token::Value op, | 1114 Token::Value op, |
1115 const Result& right, | 1115 const Result& right, |
1116 const Result& left) { | 1116 const Result& left) { |
1117 // Set NumberInfo of result according to the operation performed. | 1117 // Set TypeInfo of result according to the operation performed. |
1118 // Rely on the fact that smis have a 31 bit payload on ia32. | 1118 // Rely on the fact that smis have a 31 bit payload on ia32. |
1119 ASSERT(kSmiValueSize == 31); | 1119 ASSERT(kSmiValueSize == 31); |
1120 switch (op) { | 1120 switch (op) { |
1121 case Token::COMMA: | 1121 case Token::COMMA: |
1122 return right.number_info(); | 1122 return right.type_info(); |
1123 case Token::OR: | 1123 case Token::OR: |
1124 case Token::AND: | 1124 case Token::AND: |
1125 // Result type can be either of the two input types. | 1125 // Result type can be either of the two input types. |
1126 return operands_type; | 1126 return operands_type; |
1127 case Token::BIT_AND: { | 1127 case Token::BIT_AND: { |
1128 // Anding with positive Smis will give you a Smi. | 1128 // Anding with positive Smis will give you a Smi. |
1129 if (right.is_constant() && right.handle()->IsSmi() && | 1129 if (right.is_constant() && right.handle()->IsSmi() && |
1130 Smi::cast(*right.handle())->value() >= 0) { | 1130 Smi::cast(*right.handle())->value() >= 0) { |
1131 return NumberInfo::Smi(); | 1131 return TypeInfo::Smi(); |
1132 } else if (left.is_constant() && left.handle()->IsSmi() && | 1132 } else if (left.is_constant() && left.handle()->IsSmi() && |
1133 Smi::cast(*left.handle())->value() >= 0) { | 1133 Smi::cast(*left.handle())->value() >= 0) { |
1134 return NumberInfo::Smi(); | 1134 return TypeInfo::Smi(); |
1135 } | 1135 } |
1136 return (operands_type.IsSmi()) | 1136 return (operands_type.IsSmi()) |
1137 ? NumberInfo::Smi() | 1137 ? TypeInfo::Smi() |
1138 : NumberInfo::Integer32(); | 1138 : TypeInfo::Integer32(); |
1139 } | 1139 } |
1140 case Token::BIT_OR: { | 1140 case Token::BIT_OR: { |
1141 // Oring with negative Smis will give you a Smi. | 1141 // Oring with negative Smis will give you a Smi. |
1142 if (right.is_constant() && right.handle()->IsSmi() && | 1142 if (right.is_constant() && right.handle()->IsSmi() && |
1143 Smi::cast(*right.handle())->value() < 0) { | 1143 Smi::cast(*right.handle())->value() < 0) { |
1144 return NumberInfo::Smi(); | 1144 return TypeInfo::Smi(); |
1145 } else if (left.is_constant() && left.handle()->IsSmi() && | 1145 } else if (left.is_constant() && left.handle()->IsSmi() && |
1146 Smi::cast(*left.handle())->value() < 0) { | 1146 Smi::cast(*left.handle())->value() < 0) { |
1147 return NumberInfo::Smi(); | 1147 return TypeInfo::Smi(); |
1148 } | 1148 } |
1149 return (operands_type.IsSmi()) | 1149 return (operands_type.IsSmi()) |
1150 ? NumberInfo::Smi() | 1150 ? TypeInfo::Smi() |
1151 : NumberInfo::Integer32(); | 1151 : TypeInfo::Integer32(); |
1152 } | 1152 } |
1153 case Token::BIT_XOR: | 1153 case Token::BIT_XOR: |
1154 // Result is always a 32 bit integer. Smi property of inputs is preserved. | 1154 // Result is always a 32 bit integer. Smi property of inputs is preserved. |
1155 return (operands_type.IsSmi()) | 1155 return (operands_type.IsSmi()) |
1156 ? NumberInfo::Smi() | 1156 ? TypeInfo::Smi() |
1157 : NumberInfo::Integer32(); | 1157 : TypeInfo::Integer32(); |
1158 case Token::SAR: | 1158 case Token::SAR: |
1159 if (left.is_smi()) return NumberInfo::Smi(); | 1159 if (left.is_smi()) return TypeInfo::Smi(); |
1160 // Result is a smi if we shift by a constant >= 1, otherwise an integer32. | 1160 // Result is a smi if we shift by a constant >= 1, otherwise an integer32. |
1161 return (right.is_constant() && right.handle()->IsSmi() | 1161 return (right.is_constant() && right.handle()->IsSmi() |
1162 && Smi::cast(*right.handle())->value() >= 1) | 1162 && Smi::cast(*right.handle())->value() >= 1) |
1163 ? NumberInfo::Smi() | 1163 ? TypeInfo::Smi() |
1164 : NumberInfo::Integer32(); | 1164 : TypeInfo::Integer32(); |
1165 case Token::SHR: | 1165 case Token::SHR: |
1166 // Result is a smi if we shift by a constant >= 2, otherwise an integer32. | 1166 // Result is a smi if we shift by a constant >= 2, otherwise an integer32. |
1167 return (right.is_constant() && right.handle()->IsSmi() | 1167 return (right.is_constant() && right.handle()->IsSmi() |
1168 && Smi::cast(*right.handle())->value() >= 2) | 1168 && Smi::cast(*right.handle())->value() >= 2) |
1169 ? NumberInfo::Smi() | 1169 ? TypeInfo::Smi() |
1170 : NumberInfo::Integer32(); | 1170 : TypeInfo::Integer32(); |
1171 case Token::ADD: | 1171 case Token::ADD: |
1172 if (operands_type.IsSmi()) { | 1172 if (operands_type.IsSmi()) { |
1173 // The Integer32 range is big enough to take the sum of any two Smis. | 1173 // The Integer32 range is big enough to take the sum of any two Smis. |
1174 return NumberInfo::Integer32(); | 1174 return TypeInfo::Integer32(); |
1175 } else { | 1175 } else { |
1176 // Result could be a string or a number. Check types of inputs. | 1176 // Result could be a string or a number. Check types of inputs. |
1177 return operands_type.IsNumber() | 1177 return operands_type.IsNumber() |
1178 ? NumberInfo::Number() | 1178 ? TypeInfo::Number() |
1179 : NumberInfo::Unknown(); | 1179 : TypeInfo::Unknown(); |
1180 } | 1180 } |
1181 case Token::SHL: | 1181 case Token::SHL: |
1182 return NumberInfo::Integer32(); | 1182 return TypeInfo::Integer32(); |
1183 case Token::SUB: | 1183 case Token::SUB: |
1184 // The Integer32 range is big enough to take the difference of any two | 1184 // The Integer32 range is big enough to take the difference of any two |
1185 // Smis. | 1185 // Smis. |
1186 return (operands_type.IsSmi()) ? | 1186 return (operands_type.IsSmi()) ? |
1187 NumberInfo::Integer32() : | 1187 TypeInfo::Integer32() : |
1188 NumberInfo::Number(); | 1188 TypeInfo::Number(); |
1189 case Token::MUL: | 1189 case Token::MUL: |
1190 case Token::DIV: | 1190 case Token::DIV: |
1191 case Token::MOD: | 1191 case Token::MOD: |
1192 // Result is always a number. | 1192 // Result is always a number. |
1193 return NumberInfo::Number(); | 1193 return TypeInfo::Number(); |
1194 default: | 1194 default: |
1195 UNREACHABLE(); | 1195 UNREACHABLE(); |
1196 } | 1196 } |
1197 UNREACHABLE(); | 1197 UNREACHABLE(); |
1198 return NumberInfo::Unknown(); | 1198 return TypeInfo::Unknown(); |
1199 } | 1199 } |
1200 | 1200 |
1201 | 1201 |
1202 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 1202 void CodeGenerator::GenericBinaryOperation(Token::Value op, |
1203 StaticType* type, | 1203 StaticType* type, |
1204 OverwriteMode overwrite_mode, | 1204 OverwriteMode overwrite_mode, |
1205 bool no_negative_zero) { | 1205 bool no_negative_zero) { |
1206 Comment cmnt(masm_, "[ BinaryOperation"); | 1206 Comment cmnt(masm_, "[ BinaryOperation"); |
1207 Comment cmnt_token(masm_, Token::String(op)); | 1207 Comment cmnt_token(masm_, Token::String(op)); |
1208 | 1208 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1248 right.is_constant() && !right.handle()->IsSmi(); | 1248 right.is_constant() && !right.handle()->IsSmi(); |
1249 | 1249 |
1250 if (left_is_smi_constant && right_is_smi_constant) { | 1250 if (left_is_smi_constant && right_is_smi_constant) { |
1251 // Compute the constant result at compile time, and leave it on the frame. | 1251 // Compute the constant result at compile time, and leave it on the frame. |
1252 int left_int = Smi::cast(*left.handle())->value(); | 1252 int left_int = Smi::cast(*left.handle())->value(); |
1253 int right_int = Smi::cast(*right.handle())->value(); | 1253 int right_int = Smi::cast(*right.handle())->value(); |
1254 if (FoldConstantSmis(op, left_int, right_int)) return; | 1254 if (FoldConstantSmis(op, left_int, right_int)) return; |
1255 } | 1255 } |
1256 | 1256 |
1257 // Get number type of left and right sub-expressions. | 1257 // Get number type of left and right sub-expressions. |
1258 NumberInfo operands_type = | 1258 TypeInfo operands_type = |
1259 NumberInfo::Combine(left.number_info(), right.number_info()); | 1259 TypeInfo::Combine(left.type_info(), right.type_info()); |
1260 | 1260 |
1261 NumberInfo result_type = CalculateNumberInfo(operands_type, op, right, left); | 1261 TypeInfo result_type = CalculateTypeInfo(operands_type, op, right, left); |
1262 | 1262 |
1263 Result answer; | 1263 Result answer; |
1264 if (left_is_non_smi_constant || right_is_non_smi_constant) { | 1264 if (left_is_non_smi_constant || right_is_non_smi_constant) { |
1265 // Go straight to the slow case, with no smi code. | 1265 // Go straight to the slow case, with no smi code. |
1266 GenericBinaryOpStub stub(op, | 1266 GenericBinaryOpStub stub(op, |
1267 overwrite_mode, | 1267 overwrite_mode, |
1268 NO_SMI_CODE_IN_STUB, | 1268 NO_SMI_CODE_IN_STUB, |
1269 operands_type); | 1269 operands_type); |
1270 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1270 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
1271 } else if (right_is_smi_constant) { | 1271 } else if (right_is_smi_constant) { |
(...skipping 18 matching lines...) Expand all Loading... |
1290 overwrite_mode, no_negative_zero); | 1290 overwrite_mode, no_negative_zero); |
1291 } else { | 1291 } else { |
1292 GenericBinaryOpStub stub(op, | 1292 GenericBinaryOpStub stub(op, |
1293 overwrite_mode, | 1293 overwrite_mode, |
1294 NO_GENERIC_BINARY_FLAGS, | 1294 NO_GENERIC_BINARY_FLAGS, |
1295 operands_type); | 1295 operands_type); |
1296 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1296 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
1297 } | 1297 } |
1298 } | 1298 } |
1299 | 1299 |
1300 answer.set_number_info(result_type); | 1300 answer.set_type_info(result_type); |
1301 frame_->Push(&answer); | 1301 frame_->Push(&answer); |
1302 } | 1302 } |
1303 | 1303 |
1304 | 1304 |
1305 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { | 1305 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { |
1306 Object* answer_object = Heap::undefined_value(); | 1306 Object* answer_object = Heap::undefined_value(); |
1307 switch (op) { | 1307 switch (op) { |
1308 case Token::ADD: | 1308 case Token::ADD: |
1309 if (Smi::IsValid(left + right)) { | 1309 if (Smi::IsValid(left + right)) { |
1310 answer_object = Smi::FromInt(left + right); | 1310 answer_object = Smi::FromInt(left + right); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1378 if (answer_object == Heap::undefined_value()) { | 1378 if (answer_object == Heap::undefined_value()) { |
1379 return false; | 1379 return false; |
1380 } | 1380 } |
1381 frame_->Push(Handle<Object>(answer_object)); | 1381 frame_->Push(Handle<Object>(answer_object)); |
1382 return true; | 1382 return true; |
1383 } | 1383 } |
1384 | 1384 |
1385 | 1385 |
1386 static void CheckTwoForSminess(MacroAssembler* masm, | 1386 static void CheckTwoForSminess(MacroAssembler* masm, |
1387 Register left, Register right, Register scratch, | 1387 Register left, Register right, Register scratch, |
1388 NumberInfo left_info, NumberInfo right_info, | 1388 TypeInfo left_info, TypeInfo right_info, |
1389 DeferredInlineBinaryOperation* deferred); | 1389 DeferredInlineBinaryOperation* deferred); |
1390 | 1390 |
1391 | 1391 |
1392 // Implements a binary operation using a deferred code object and some | 1392 // Implements a binary operation using a deferred code object and some |
1393 // inline code to operate on smis quickly. | 1393 // inline code to operate on smis quickly. |
1394 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, | 1394 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, |
1395 Result* left, | 1395 Result* left, |
1396 Result* right, | 1396 Result* right, |
1397 OverwriteMode overwrite_mode, | 1397 OverwriteMode overwrite_mode, |
1398 bool no_negative_zero) { | 1398 bool no_negative_zero) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 right->ToRegister(); | 1463 right->ToRegister(); |
1464 frame_->Spill(eax); | 1464 frame_->Spill(eax); |
1465 frame_->Spill(edx); | 1465 frame_->Spill(edx); |
1466 | 1466 |
1467 // Check that left and right are smi tagged. | 1467 // Check that left and right are smi tagged. |
1468 DeferredInlineBinaryOperation* deferred = | 1468 DeferredInlineBinaryOperation* deferred = |
1469 new DeferredInlineBinaryOperation(op, | 1469 new DeferredInlineBinaryOperation(op, |
1470 (op == Token::DIV) ? eax : edx, | 1470 (op == Token::DIV) ? eax : edx, |
1471 left->reg(), | 1471 left->reg(), |
1472 right->reg(), | 1472 right->reg(), |
1473 left->number_info(), | 1473 left->type_info(), |
1474 right->number_info(), | 1474 right->type_info(), |
1475 overwrite_mode); | 1475 overwrite_mode); |
1476 if (left->reg().is(right->reg())) { | 1476 if (left->reg().is(right->reg())) { |
1477 __ test(left->reg(), Immediate(kSmiTagMask)); | 1477 __ test(left->reg(), Immediate(kSmiTagMask)); |
1478 } else { | 1478 } else { |
1479 // Use the quotient register as a scratch for the tag check. | 1479 // Use the quotient register as a scratch for the tag check. |
1480 if (!left_is_in_eax) __ mov(eax, left->reg()); | 1480 if (!left_is_in_eax) __ mov(eax, left->reg()); |
1481 left_is_in_eax = false; // About to destroy the value in eax. | 1481 left_is_in_eax = false; // About to destroy the value in eax. |
1482 __ or_(eax, Operand(right->reg())); | 1482 __ or_(eax, Operand(right->reg())); |
1483 ASSERT(kSmiTag == 0); // Adjust test if not the case. | 1483 ASSERT(kSmiTag == 0); // Adjust test if not the case. |
1484 __ test(eax, Immediate(kSmiTagMask)); | 1484 __ test(eax, Immediate(kSmiTagMask)); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1567 // Use a fresh answer register to avoid spilling the left operand. | 1567 // Use a fresh answer register to avoid spilling the left operand. |
1568 answer = allocator_->Allocate(); | 1568 answer = allocator_->Allocate(); |
1569 ASSERT(answer.is_valid()); | 1569 ASSERT(answer.is_valid()); |
1570 // Check that both operands are smis using the answer register as a | 1570 // Check that both operands are smis using the answer register as a |
1571 // temporary. | 1571 // temporary. |
1572 DeferredInlineBinaryOperation* deferred = | 1572 DeferredInlineBinaryOperation* deferred = |
1573 new DeferredInlineBinaryOperation(op, | 1573 new DeferredInlineBinaryOperation(op, |
1574 answer.reg(), | 1574 answer.reg(), |
1575 left->reg(), | 1575 left->reg(), |
1576 ecx, | 1576 ecx, |
1577 left->number_info(), | 1577 left->type_info(), |
1578 right->number_info(), | 1578 right->type_info(), |
1579 overwrite_mode); | 1579 overwrite_mode); |
1580 | 1580 |
1581 Label do_op, left_nonsmi; | 1581 Label do_op, left_nonsmi; |
1582 // If right is a smi we make a fast case if left is either a smi | 1582 // If right is a smi we make a fast case if left is either a smi |
1583 // or a heapnumber. | 1583 // or a heapnumber. |
1584 if (CpuFeatures::IsSupported(SSE2) && right->number_info().IsSmi()) { | 1584 if (CpuFeatures::IsSupported(SSE2) && right->type_info().IsSmi()) { |
1585 CpuFeatures::Scope use_sse2(SSE2); | 1585 CpuFeatures::Scope use_sse2(SSE2); |
1586 __ mov(answer.reg(), left->reg()); | 1586 __ mov(answer.reg(), left->reg()); |
1587 // Fast case - both are actually smis. | 1587 // Fast case - both are actually smis. |
1588 if (!left->number_info().IsSmi()) { | 1588 if (!left->type_info().IsSmi()) { |
1589 __ test(answer.reg(), Immediate(kSmiTagMask)); | 1589 __ test(answer.reg(), Immediate(kSmiTagMask)); |
1590 __ j(not_zero, &left_nonsmi); | 1590 __ j(not_zero, &left_nonsmi); |
1591 } else { | 1591 } else { |
1592 if (FLAG_debug_code) __ AbortIfNotSmi(left->reg()); | 1592 if (FLAG_debug_code) __ AbortIfNotSmi(left->reg()); |
1593 } | 1593 } |
1594 if (FLAG_debug_code) __ AbortIfNotSmi(right->reg()); | 1594 if (FLAG_debug_code) __ AbortIfNotSmi(right->reg()); |
1595 __ SmiUntag(answer.reg()); | 1595 __ SmiUntag(answer.reg()); |
1596 __ jmp(&do_op); | 1596 __ jmp(&do_op); |
1597 | 1597 |
1598 __ bind(&left_nonsmi); | 1598 __ bind(&left_nonsmi); |
1599 // Branch if not a heapnumber. | 1599 // Branch if not a heapnumber. |
1600 __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), | 1600 __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), |
1601 Factory::heap_number_map()); | 1601 Factory::heap_number_map()); |
1602 deferred->Branch(not_equal); | 1602 deferred->Branch(not_equal); |
1603 | 1603 |
1604 // Load integer value into answer register using truncation. | 1604 // Load integer value into answer register using truncation. |
1605 __ cvttsd2si(answer.reg(), | 1605 __ cvttsd2si(answer.reg(), |
1606 FieldOperand(answer.reg(), HeapNumber::kValueOffset)); | 1606 FieldOperand(answer.reg(), HeapNumber::kValueOffset)); |
1607 // Branch if we do not fit in a smi. | 1607 // Branch if we do not fit in a smi. |
1608 __ cmp(answer.reg(), 0xc0000000); | 1608 __ cmp(answer.reg(), 0xc0000000); |
1609 deferred->Branch(negative); | 1609 deferred->Branch(negative); |
1610 } else { | 1610 } else { |
1611 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), | 1611 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
1612 left->number_info(), right->number_info(), deferred); | 1612 left->type_info(), right->type_info(), deferred); |
1613 | 1613 |
1614 // Untag both operands. | 1614 // Untag both operands. |
1615 __ mov(answer.reg(), left->reg()); | 1615 __ mov(answer.reg(), left->reg()); |
1616 __ SmiUntag(answer.reg()); | 1616 __ SmiUntag(answer.reg()); |
1617 } | 1617 } |
1618 | 1618 |
1619 __ bind(&do_op); | 1619 __ bind(&do_op); |
1620 __ SmiUntag(ecx); | 1620 __ SmiUntag(ecx); |
1621 // Perform the operation. | 1621 // Perform the operation. |
1622 switch (op) { | 1622 switch (op) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 // need to be spilled in the fast case. | 1675 // need to be spilled in the fast case. |
1676 answer = allocator_->Allocate(); | 1676 answer = allocator_->Allocate(); |
1677 ASSERT(answer.is_valid()); | 1677 ASSERT(answer.is_valid()); |
1678 | 1678 |
1679 // Perform the smi tag check. | 1679 // Perform the smi tag check. |
1680 DeferredInlineBinaryOperation* deferred = | 1680 DeferredInlineBinaryOperation* deferred = |
1681 new DeferredInlineBinaryOperation(op, | 1681 new DeferredInlineBinaryOperation(op, |
1682 answer.reg(), | 1682 answer.reg(), |
1683 left->reg(), | 1683 left->reg(), |
1684 right->reg(), | 1684 right->reg(), |
1685 left->number_info(), | 1685 left->type_info(), |
1686 right->number_info(), | 1686 right->type_info(), |
1687 overwrite_mode); | 1687 overwrite_mode); |
1688 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), | 1688 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
1689 left->number_info(), right->number_info(), deferred); | 1689 left->type_info(), right->type_info(), deferred); |
1690 | 1690 |
1691 __ mov(answer.reg(), left->reg()); | 1691 __ mov(answer.reg(), left->reg()); |
1692 switch (op) { | 1692 switch (op) { |
1693 case Token::ADD: | 1693 case Token::ADD: |
1694 __ add(answer.reg(), Operand(right->reg())); | 1694 __ add(answer.reg(), Operand(right->reg())); |
1695 deferred->Branch(overflow); | 1695 deferred->Branch(overflow); |
1696 break; | 1696 break; |
1697 | 1697 |
1698 case Token::SUB: | 1698 case Token::SUB: |
1699 __ sub(answer.reg(), Operand(right->reg())); | 1699 __ sub(answer.reg(), Operand(right->reg())); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1751 } | 1751 } |
1752 | 1752 |
1753 | 1753 |
1754 // Call the appropriate binary operation stub to compute src op value | 1754 // Call the appropriate binary operation stub to compute src op value |
1755 // and leave the result in dst. | 1755 // and leave the result in dst. |
1756 class DeferredInlineSmiOperation: public DeferredCode { | 1756 class DeferredInlineSmiOperation: public DeferredCode { |
1757 public: | 1757 public: |
1758 DeferredInlineSmiOperation(Token::Value op, | 1758 DeferredInlineSmiOperation(Token::Value op, |
1759 Register dst, | 1759 Register dst, |
1760 Register src, | 1760 Register src, |
1761 NumberInfo number_info, | 1761 TypeInfo type_info, |
1762 Smi* value, | 1762 Smi* value, |
1763 OverwriteMode overwrite_mode) | 1763 OverwriteMode overwrite_mode) |
1764 : op_(op), | 1764 : op_(op), |
1765 dst_(dst), | 1765 dst_(dst), |
1766 src_(src), | 1766 src_(src), |
1767 number_info_(number_info), | 1767 type_info_(type_info), |
1768 value_(value), | 1768 value_(value), |
1769 overwrite_mode_(overwrite_mode) { | 1769 overwrite_mode_(overwrite_mode) { |
1770 if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; | 1770 if (type_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
1771 set_comment("[ DeferredInlineSmiOperation"); | 1771 set_comment("[ DeferredInlineSmiOperation"); |
1772 } | 1772 } |
1773 | 1773 |
1774 virtual void Generate(); | 1774 virtual void Generate(); |
1775 | 1775 |
1776 private: | 1776 private: |
1777 Token::Value op_; | 1777 Token::Value op_; |
1778 Register dst_; | 1778 Register dst_; |
1779 Register src_; | 1779 Register src_; |
1780 NumberInfo number_info_; | 1780 TypeInfo type_info_; |
1781 Smi* value_; | 1781 Smi* value_; |
1782 OverwriteMode overwrite_mode_; | 1782 OverwriteMode overwrite_mode_; |
1783 }; | 1783 }; |
1784 | 1784 |
1785 | 1785 |
1786 void DeferredInlineSmiOperation::Generate() { | 1786 void DeferredInlineSmiOperation::Generate() { |
1787 // For mod we don't generate all the Smi code inline. | 1787 // For mod we don't generate all the Smi code inline. |
1788 GenericBinaryOpStub stub( | 1788 GenericBinaryOpStub stub( |
1789 op_, | 1789 op_, |
1790 overwrite_mode_, | 1790 overwrite_mode_, |
1791 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB, | 1791 (op_ == Token::MOD) ? NO_GENERIC_BINARY_FLAGS : NO_SMI_CODE_IN_STUB, |
1792 NumberInfo::Combine(NumberInfo::Smi(), number_info_)); | 1792 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1793 stub.GenerateCall(masm_, src_, value_); | 1793 stub.GenerateCall(masm_, src_, value_); |
1794 if (!dst_.is(eax)) __ mov(dst_, eax); | 1794 if (!dst_.is(eax)) __ mov(dst_, eax); |
1795 } | 1795 } |
1796 | 1796 |
1797 | 1797 |
1798 // Call the appropriate binary operation stub to compute value op src | 1798 // Call the appropriate binary operation stub to compute value op src |
1799 // and leave the result in dst. | 1799 // and leave the result in dst. |
1800 class DeferredInlineSmiOperationReversed: public DeferredCode { | 1800 class DeferredInlineSmiOperationReversed: public DeferredCode { |
1801 public: | 1801 public: |
1802 DeferredInlineSmiOperationReversed(Token::Value op, | 1802 DeferredInlineSmiOperationReversed(Token::Value op, |
1803 Register dst, | 1803 Register dst, |
1804 Smi* value, | 1804 Smi* value, |
1805 Register src, | 1805 Register src, |
1806 NumberInfo number_info, | 1806 TypeInfo type_info, |
1807 OverwriteMode overwrite_mode) | 1807 OverwriteMode overwrite_mode) |
1808 : op_(op), | 1808 : op_(op), |
1809 dst_(dst), | 1809 dst_(dst), |
1810 number_info_(number_info), | 1810 type_info_(type_info), |
1811 value_(value), | 1811 value_(value), |
1812 src_(src), | 1812 src_(src), |
1813 overwrite_mode_(overwrite_mode) { | 1813 overwrite_mode_(overwrite_mode) { |
1814 set_comment("[ DeferredInlineSmiOperationReversed"); | 1814 set_comment("[ DeferredInlineSmiOperationReversed"); |
1815 } | 1815 } |
1816 | 1816 |
1817 virtual void Generate(); | 1817 virtual void Generate(); |
1818 | 1818 |
1819 private: | 1819 private: |
1820 Token::Value op_; | 1820 Token::Value op_; |
1821 Register dst_; | 1821 Register dst_; |
1822 NumberInfo number_info_; | 1822 TypeInfo type_info_; |
1823 Smi* value_; | 1823 Smi* value_; |
1824 Register src_; | 1824 Register src_; |
1825 OverwriteMode overwrite_mode_; | 1825 OverwriteMode overwrite_mode_; |
1826 }; | 1826 }; |
1827 | 1827 |
1828 | 1828 |
1829 void DeferredInlineSmiOperationReversed::Generate() { | 1829 void DeferredInlineSmiOperationReversed::Generate() { |
1830 GenericBinaryOpStub igostub( | 1830 GenericBinaryOpStub igostub( |
1831 op_, | 1831 op_, |
1832 overwrite_mode_, | 1832 overwrite_mode_, |
1833 NO_SMI_CODE_IN_STUB, | 1833 NO_SMI_CODE_IN_STUB, |
1834 NumberInfo::Combine(NumberInfo::Smi(), number_info_)); | 1834 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1835 igostub.GenerateCall(masm_, value_, src_); | 1835 igostub.GenerateCall(masm_, value_, src_); |
1836 if (!dst_.is(eax)) __ mov(dst_, eax); | 1836 if (!dst_.is(eax)) __ mov(dst_, eax); |
1837 } | 1837 } |
1838 | 1838 |
1839 | 1839 |
1840 // The result of src + value is in dst. It either overflowed or was not | 1840 // The result of src + value is in dst. It either overflowed or was not |
1841 // smi tagged. Undo the speculative addition and call the appropriate | 1841 // smi tagged. Undo the speculative addition and call the appropriate |
1842 // specialized stub for add. The result is left in dst. | 1842 // specialized stub for add. The result is left in dst. |
1843 class DeferredInlineSmiAdd: public DeferredCode { | 1843 class DeferredInlineSmiAdd: public DeferredCode { |
1844 public: | 1844 public: |
1845 DeferredInlineSmiAdd(Register dst, | 1845 DeferredInlineSmiAdd(Register dst, |
1846 NumberInfo number_info, | 1846 TypeInfo type_info, |
1847 Smi* value, | 1847 Smi* value, |
1848 OverwriteMode overwrite_mode) | 1848 OverwriteMode overwrite_mode) |
1849 : dst_(dst), | 1849 : dst_(dst), |
1850 number_info_(number_info), | 1850 type_info_(type_info), |
1851 value_(value), | 1851 value_(value), |
1852 overwrite_mode_(overwrite_mode) { | 1852 overwrite_mode_(overwrite_mode) { |
1853 if (number_info_.IsSmi()) overwrite_mode_ = NO_OVERWRITE; | 1853 if (type_info_.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
1854 set_comment("[ DeferredInlineSmiAdd"); | 1854 set_comment("[ DeferredInlineSmiAdd"); |
1855 } | 1855 } |
1856 | 1856 |
1857 virtual void Generate(); | 1857 virtual void Generate(); |
1858 | 1858 |
1859 private: | 1859 private: |
1860 Register dst_; | 1860 Register dst_; |
1861 NumberInfo number_info_; | 1861 TypeInfo type_info_; |
1862 Smi* value_; | 1862 Smi* value_; |
1863 OverwriteMode overwrite_mode_; | 1863 OverwriteMode overwrite_mode_; |
1864 }; | 1864 }; |
1865 | 1865 |
1866 | 1866 |
1867 void DeferredInlineSmiAdd::Generate() { | 1867 void DeferredInlineSmiAdd::Generate() { |
1868 // Undo the optimistic add operation and call the shared stub. | 1868 // Undo the optimistic add operation and call the shared stub. |
1869 __ sub(Operand(dst_), Immediate(value_)); | 1869 __ sub(Operand(dst_), Immediate(value_)); |
1870 GenericBinaryOpStub igostub( | 1870 GenericBinaryOpStub igostub( |
1871 Token::ADD, | 1871 Token::ADD, |
1872 overwrite_mode_, | 1872 overwrite_mode_, |
1873 NO_SMI_CODE_IN_STUB, | 1873 NO_SMI_CODE_IN_STUB, |
1874 NumberInfo::Combine(NumberInfo::Smi(), number_info_)); | 1874 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1875 igostub.GenerateCall(masm_, dst_, value_); | 1875 igostub.GenerateCall(masm_, dst_, value_); |
1876 if (!dst_.is(eax)) __ mov(dst_, eax); | 1876 if (!dst_.is(eax)) __ mov(dst_, eax); |
1877 } | 1877 } |
1878 | 1878 |
1879 | 1879 |
1880 // The result of value + src is in dst. It either overflowed or was not | 1880 // The result of value + src is in dst. It either overflowed or was not |
1881 // smi tagged. Undo the speculative addition and call the appropriate | 1881 // smi tagged. Undo the speculative addition and call the appropriate |
1882 // specialized stub for add. The result is left in dst. | 1882 // specialized stub for add. The result is left in dst. |
1883 class DeferredInlineSmiAddReversed: public DeferredCode { | 1883 class DeferredInlineSmiAddReversed: public DeferredCode { |
1884 public: | 1884 public: |
1885 DeferredInlineSmiAddReversed(Register dst, | 1885 DeferredInlineSmiAddReversed(Register dst, |
1886 NumberInfo number_info, | 1886 TypeInfo type_info, |
1887 Smi* value, | 1887 Smi* value, |
1888 OverwriteMode overwrite_mode) | 1888 OverwriteMode overwrite_mode) |
1889 : dst_(dst), | 1889 : dst_(dst), |
1890 number_info_(number_info), | 1890 type_info_(type_info), |
1891 value_(value), | 1891 value_(value), |
1892 overwrite_mode_(overwrite_mode) { | 1892 overwrite_mode_(overwrite_mode) { |
1893 set_comment("[ DeferredInlineSmiAddReversed"); | 1893 set_comment("[ DeferredInlineSmiAddReversed"); |
1894 } | 1894 } |
1895 | 1895 |
1896 virtual void Generate(); | 1896 virtual void Generate(); |
1897 | 1897 |
1898 private: | 1898 private: |
1899 Register dst_; | 1899 Register dst_; |
1900 NumberInfo number_info_; | 1900 TypeInfo type_info_; |
1901 Smi* value_; | 1901 Smi* value_; |
1902 OverwriteMode overwrite_mode_; | 1902 OverwriteMode overwrite_mode_; |
1903 }; | 1903 }; |
1904 | 1904 |
1905 | 1905 |
1906 void DeferredInlineSmiAddReversed::Generate() { | 1906 void DeferredInlineSmiAddReversed::Generate() { |
1907 // Undo the optimistic add operation and call the shared stub. | 1907 // Undo the optimistic add operation and call the shared stub. |
1908 __ sub(Operand(dst_), Immediate(value_)); | 1908 __ sub(Operand(dst_), Immediate(value_)); |
1909 GenericBinaryOpStub igostub( | 1909 GenericBinaryOpStub igostub( |
1910 Token::ADD, | 1910 Token::ADD, |
1911 overwrite_mode_, | 1911 overwrite_mode_, |
1912 NO_SMI_CODE_IN_STUB, | 1912 NO_SMI_CODE_IN_STUB, |
1913 NumberInfo::Combine(NumberInfo::Smi(), number_info_)); | 1913 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1914 igostub.GenerateCall(masm_, value_, dst_); | 1914 igostub.GenerateCall(masm_, value_, dst_); |
1915 if (!dst_.is(eax)) __ mov(dst_, eax); | 1915 if (!dst_.is(eax)) __ mov(dst_, eax); |
1916 } | 1916 } |
1917 | 1917 |
1918 | 1918 |
1919 // The result of src - value is in dst. It either overflowed or was not | 1919 // The result of src - value is in dst. It either overflowed or was not |
1920 // smi tagged. Undo the speculative subtraction and call the | 1920 // smi tagged. Undo the speculative subtraction and call the |
1921 // appropriate specialized stub for subtract. The result is left in | 1921 // appropriate specialized stub for subtract. The result is left in |
1922 // dst. | 1922 // dst. |
1923 class DeferredInlineSmiSub: public DeferredCode { | 1923 class DeferredInlineSmiSub: public DeferredCode { |
1924 public: | 1924 public: |
1925 DeferredInlineSmiSub(Register dst, | 1925 DeferredInlineSmiSub(Register dst, |
1926 NumberInfo number_info, | 1926 TypeInfo type_info, |
1927 Smi* value, | 1927 Smi* value, |
1928 OverwriteMode overwrite_mode) | 1928 OverwriteMode overwrite_mode) |
1929 : dst_(dst), | 1929 : dst_(dst), |
1930 number_info_(number_info), | 1930 type_info_(type_info), |
1931 value_(value), | 1931 value_(value), |
1932 overwrite_mode_(overwrite_mode) { | 1932 overwrite_mode_(overwrite_mode) { |
1933 if (number_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; | 1933 if (type_info.IsSmi()) overwrite_mode_ = NO_OVERWRITE; |
1934 set_comment("[ DeferredInlineSmiSub"); | 1934 set_comment("[ DeferredInlineSmiSub"); |
1935 } | 1935 } |
1936 | 1936 |
1937 virtual void Generate(); | 1937 virtual void Generate(); |
1938 | 1938 |
1939 private: | 1939 private: |
1940 Register dst_; | 1940 Register dst_; |
1941 NumberInfo number_info_; | 1941 TypeInfo type_info_; |
1942 Smi* value_; | 1942 Smi* value_; |
1943 OverwriteMode overwrite_mode_; | 1943 OverwriteMode overwrite_mode_; |
1944 }; | 1944 }; |
1945 | 1945 |
1946 | 1946 |
1947 void DeferredInlineSmiSub::Generate() { | 1947 void DeferredInlineSmiSub::Generate() { |
1948 // Undo the optimistic sub operation and call the shared stub. | 1948 // Undo the optimistic sub operation and call the shared stub. |
1949 __ add(Operand(dst_), Immediate(value_)); | 1949 __ add(Operand(dst_), Immediate(value_)); |
1950 GenericBinaryOpStub igostub( | 1950 GenericBinaryOpStub igostub( |
1951 Token::SUB, | 1951 Token::SUB, |
1952 overwrite_mode_, | 1952 overwrite_mode_, |
1953 NO_SMI_CODE_IN_STUB, | 1953 NO_SMI_CODE_IN_STUB, |
1954 NumberInfo::Combine(NumberInfo::Smi(), number_info_)); | 1954 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1955 igostub.GenerateCall(masm_, dst_, value_); | 1955 igostub.GenerateCall(masm_, dst_, value_); |
1956 if (!dst_.is(eax)) __ mov(dst_, eax); | 1956 if (!dst_.is(eax)) __ mov(dst_, eax); |
1957 } | 1957 } |
1958 | 1958 |
1959 | 1959 |
1960 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, | 1960 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, |
1961 Result* operand, | 1961 Result* operand, |
1962 Handle<Object> value, | 1962 Handle<Object> value, |
1963 StaticType* type, | 1963 StaticType* type, |
1964 bool reversed, | 1964 bool reversed, |
(...skipping 24 matching lines...) Expand all Loading... |
1989 switch (op) { | 1989 switch (op) { |
1990 case Token::ADD: { | 1990 case Token::ADD: { |
1991 operand->ToRegister(); | 1991 operand->ToRegister(); |
1992 frame_->Spill(operand->reg()); | 1992 frame_->Spill(operand->reg()); |
1993 | 1993 |
1994 // Optimistically add. Call the specialized add stub if the | 1994 // Optimistically add. Call the specialized add stub if the |
1995 // result is not a smi or overflows. | 1995 // result is not a smi or overflows. |
1996 DeferredCode* deferred = NULL; | 1996 DeferredCode* deferred = NULL; |
1997 if (reversed) { | 1997 if (reversed) { |
1998 deferred = new DeferredInlineSmiAddReversed(operand->reg(), | 1998 deferred = new DeferredInlineSmiAddReversed(operand->reg(), |
1999 operand->number_info(), | 1999 operand->type_info(), |
2000 smi_value, | 2000 smi_value, |
2001 overwrite_mode); | 2001 overwrite_mode); |
2002 } else { | 2002 } else { |
2003 deferred = new DeferredInlineSmiAdd(operand->reg(), | 2003 deferred = new DeferredInlineSmiAdd(operand->reg(), |
2004 operand->number_info(), | 2004 operand->type_info(), |
2005 smi_value, | 2005 smi_value, |
2006 overwrite_mode); | 2006 overwrite_mode); |
2007 } | 2007 } |
2008 __ add(Operand(operand->reg()), Immediate(value)); | 2008 __ add(Operand(operand->reg()), Immediate(value)); |
2009 deferred->Branch(overflow); | 2009 deferred->Branch(overflow); |
2010 if (!operand->number_info().IsSmi()) { | 2010 if (!operand->type_info().IsSmi()) { |
2011 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2011 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2012 deferred->Branch(not_zero); | 2012 deferred->Branch(not_zero); |
2013 } else { | 2013 } else { |
2014 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2014 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2015 } | 2015 } |
2016 deferred->BindExit(); | 2016 deferred->BindExit(); |
2017 answer = *operand; | 2017 answer = *operand; |
2018 break; | 2018 break; |
2019 } | 2019 } |
2020 | 2020 |
2021 case Token::SUB: { | 2021 case Token::SUB: { |
2022 DeferredCode* deferred = NULL; | 2022 DeferredCode* deferred = NULL; |
2023 if (reversed) { | 2023 if (reversed) { |
2024 // The reversed case is only hit when the right operand is not a | 2024 // The reversed case is only hit when the right operand is not a |
2025 // constant. | 2025 // constant. |
2026 ASSERT(operand->is_register()); | 2026 ASSERT(operand->is_register()); |
2027 answer = allocator()->Allocate(); | 2027 answer = allocator()->Allocate(); |
2028 ASSERT(answer.is_valid()); | 2028 ASSERT(answer.is_valid()); |
2029 __ Set(answer.reg(), Immediate(value)); | 2029 __ Set(answer.reg(), Immediate(value)); |
2030 deferred = | 2030 deferred = |
2031 new DeferredInlineSmiOperationReversed(op, | 2031 new DeferredInlineSmiOperationReversed(op, |
2032 answer.reg(), | 2032 answer.reg(), |
2033 smi_value, | 2033 smi_value, |
2034 operand->reg(), | 2034 operand->reg(), |
2035 operand->number_info(), | 2035 operand->type_info(), |
2036 overwrite_mode); | 2036 overwrite_mode); |
2037 __ sub(answer.reg(), Operand(operand->reg())); | 2037 __ sub(answer.reg(), Operand(operand->reg())); |
2038 } else { | 2038 } else { |
2039 operand->ToRegister(); | 2039 operand->ToRegister(); |
2040 frame_->Spill(operand->reg()); | 2040 frame_->Spill(operand->reg()); |
2041 answer = *operand; | 2041 answer = *operand; |
2042 deferred = new DeferredInlineSmiSub(operand->reg(), | 2042 deferred = new DeferredInlineSmiSub(operand->reg(), |
2043 operand->number_info(), | 2043 operand->type_info(), |
2044 smi_value, | 2044 smi_value, |
2045 overwrite_mode); | 2045 overwrite_mode); |
2046 __ sub(Operand(operand->reg()), Immediate(value)); | 2046 __ sub(Operand(operand->reg()), Immediate(value)); |
2047 } | 2047 } |
2048 deferred->Branch(overflow); | 2048 deferred->Branch(overflow); |
2049 if (!operand->number_info().IsSmi()) { | 2049 if (!operand->type_info().IsSmi()) { |
2050 __ test(answer.reg(), Immediate(kSmiTagMask)); | 2050 __ test(answer.reg(), Immediate(kSmiTagMask)); |
2051 deferred->Branch(not_zero); | 2051 deferred->Branch(not_zero); |
2052 } else { | 2052 } else { |
2053 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2053 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2054 } | 2054 } |
2055 deferred->BindExit(); | 2055 deferred->BindExit(); |
2056 operand->Unuse(); | 2056 operand->Unuse(); |
2057 break; | 2057 break; |
2058 } | 2058 } |
2059 | 2059 |
2060 case Token::SAR: | 2060 case Token::SAR: |
2061 if (reversed) { | 2061 if (reversed) { |
2062 Result constant_operand(value); | 2062 Result constant_operand(value); |
2063 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2063 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
2064 overwrite_mode, no_negative_zero); | 2064 overwrite_mode, no_negative_zero); |
2065 } else { | 2065 } else { |
2066 // Only the least significant 5 bits of the shift value are used. | 2066 // Only the least significant 5 bits of the shift value are used. |
2067 // In the slow case, this masking is done inside the runtime call. | 2067 // In the slow case, this masking is done inside the runtime call. |
2068 int shift_value = int_value & 0x1f; | 2068 int shift_value = int_value & 0x1f; |
2069 operand->ToRegister(); | 2069 operand->ToRegister(); |
2070 frame_->Spill(operand->reg()); | 2070 frame_->Spill(operand->reg()); |
2071 if (!operand->number_info().IsSmi()) { | 2071 if (!operand->type_info().IsSmi()) { |
2072 DeferredInlineSmiOperation* deferred = | 2072 DeferredInlineSmiOperation* deferred = |
2073 new DeferredInlineSmiOperation(op, | 2073 new DeferredInlineSmiOperation(op, |
2074 operand->reg(), | 2074 operand->reg(), |
2075 operand->reg(), | 2075 operand->reg(), |
2076 operand->number_info(), | 2076 operand->type_info(), |
2077 smi_value, | 2077 smi_value, |
2078 overwrite_mode); | 2078 overwrite_mode); |
2079 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2079 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2080 deferred->Branch(not_zero); | 2080 deferred->Branch(not_zero); |
2081 if (shift_value > 0) { | 2081 if (shift_value > 0) { |
2082 __ sar(operand->reg(), shift_value); | 2082 __ sar(operand->reg(), shift_value); |
2083 __ and_(operand->reg(), ~kSmiTagMask); | 2083 __ and_(operand->reg(), ~kSmiTagMask); |
2084 } | 2084 } |
2085 deferred->BindExit(); | 2085 deferred->BindExit(); |
2086 } else { | 2086 } else { |
(...skipping 16 matching lines...) Expand all Loading... |
2103 // Only the least significant 5 bits of the shift value are used. | 2103 // Only the least significant 5 bits of the shift value are used. |
2104 // In the slow case, this masking is done inside the runtime call. | 2104 // In the slow case, this masking is done inside the runtime call. |
2105 int shift_value = int_value & 0x1f; | 2105 int shift_value = int_value & 0x1f; |
2106 operand->ToRegister(); | 2106 operand->ToRegister(); |
2107 answer = allocator()->Allocate(); | 2107 answer = allocator()->Allocate(); |
2108 ASSERT(answer.is_valid()); | 2108 ASSERT(answer.is_valid()); |
2109 DeferredInlineSmiOperation* deferred = | 2109 DeferredInlineSmiOperation* deferred = |
2110 new DeferredInlineSmiOperation(op, | 2110 new DeferredInlineSmiOperation(op, |
2111 answer.reg(), | 2111 answer.reg(), |
2112 operand->reg(), | 2112 operand->reg(), |
2113 operand->number_info(), | 2113 operand->type_info(), |
2114 smi_value, | 2114 smi_value, |
2115 overwrite_mode); | 2115 overwrite_mode); |
2116 if (!operand->number_info().IsSmi()) { | 2116 if (!operand->type_info().IsSmi()) { |
2117 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2117 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2118 deferred->Branch(not_zero); | 2118 deferred->Branch(not_zero); |
2119 } else { | 2119 } else { |
2120 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2120 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2121 } | 2121 } |
2122 __ mov(answer.reg(), operand->reg()); | 2122 __ mov(answer.reg(), operand->reg()); |
2123 __ SmiUntag(answer.reg()); | 2123 __ SmiUntag(answer.reg()); |
2124 __ shr(answer.reg(), shift_value); | 2124 __ shr(answer.reg(), shift_value); |
2125 // A negative Smi shifted right two is in the positive Smi range. | 2125 // A negative Smi shifted right two is in the positive Smi range. |
2126 if (shift_value < 2) { | 2126 if (shift_value < 2) { |
(...skipping 26 matching lines...) Expand all Loading... |
2153 right = *operand; | 2153 right = *operand; |
2154 } | 2154 } |
2155 operand->Unuse(); | 2155 operand->Unuse(); |
2156 | 2156 |
2157 answer = allocator()->Allocate(); | 2157 answer = allocator()->Allocate(); |
2158 DeferredInlineSmiOperationReversed* deferred = | 2158 DeferredInlineSmiOperationReversed* deferred = |
2159 new DeferredInlineSmiOperationReversed(op, | 2159 new DeferredInlineSmiOperationReversed(op, |
2160 answer.reg(), | 2160 answer.reg(), |
2161 smi_value, | 2161 smi_value, |
2162 right.reg(), | 2162 right.reg(), |
2163 right.number_info(), | 2163 right.type_info(), |
2164 overwrite_mode); | 2164 overwrite_mode); |
2165 __ mov(answer.reg(), Immediate(int_value)); | 2165 __ mov(answer.reg(), Immediate(int_value)); |
2166 __ sar(ecx, kSmiTagSize); | 2166 __ sar(ecx, kSmiTagSize); |
2167 if (!right.number_info().IsSmi()) { | 2167 if (!right.type_info().IsSmi()) { |
2168 deferred->Branch(carry); | 2168 deferred->Branch(carry); |
2169 } else { | 2169 } else { |
2170 if (FLAG_debug_code) __ AbortIfNotSmi(right.reg()); | 2170 if (FLAG_debug_code) __ AbortIfNotSmi(right.reg()); |
2171 } | 2171 } |
2172 __ shl_cl(answer.reg()); | 2172 __ shl_cl(answer.reg()); |
2173 __ cmp(answer.reg(), 0xc0000000); | 2173 __ cmp(answer.reg(), 0xc0000000); |
2174 deferred->Branch(sign); | 2174 deferred->Branch(sign); |
2175 __ SmiTag(answer.reg()); | 2175 __ SmiTag(answer.reg()); |
2176 | 2176 |
2177 deferred->BindExit(); | 2177 deferred->BindExit(); |
2178 } else { | 2178 } else { |
2179 // Only the least significant 5 bits of the shift value are used. | 2179 // Only the least significant 5 bits of the shift value are used. |
2180 // In the slow case, this masking is done inside the runtime call. | 2180 // In the slow case, this masking is done inside the runtime call. |
2181 int shift_value = int_value & 0x1f; | 2181 int shift_value = int_value & 0x1f; |
2182 operand->ToRegister(); | 2182 operand->ToRegister(); |
2183 if (shift_value == 0) { | 2183 if (shift_value == 0) { |
2184 // Spill operand so it can be overwritten in the slow case. | 2184 // Spill operand so it can be overwritten in the slow case. |
2185 frame_->Spill(operand->reg()); | 2185 frame_->Spill(operand->reg()); |
2186 DeferredInlineSmiOperation* deferred = | 2186 DeferredInlineSmiOperation* deferred = |
2187 new DeferredInlineSmiOperation(op, | 2187 new DeferredInlineSmiOperation(op, |
2188 operand->reg(), | 2188 operand->reg(), |
2189 operand->reg(), | 2189 operand->reg(), |
2190 operand->number_info(), | 2190 operand->type_info(), |
2191 smi_value, | 2191 smi_value, |
2192 overwrite_mode); | 2192 overwrite_mode); |
2193 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2193 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2194 deferred->Branch(not_zero); | 2194 deferred->Branch(not_zero); |
2195 deferred->BindExit(); | 2195 deferred->BindExit(); |
2196 answer = *operand; | 2196 answer = *operand; |
2197 } else { | 2197 } else { |
2198 // Use a fresh temporary for nonzero shift values. | 2198 // Use a fresh temporary for nonzero shift values. |
2199 answer = allocator()->Allocate(); | 2199 answer = allocator()->Allocate(); |
2200 ASSERT(answer.is_valid()); | 2200 ASSERT(answer.is_valid()); |
2201 DeferredInlineSmiOperation* deferred = | 2201 DeferredInlineSmiOperation* deferred = |
2202 new DeferredInlineSmiOperation(op, | 2202 new DeferredInlineSmiOperation(op, |
2203 answer.reg(), | 2203 answer.reg(), |
2204 operand->reg(), | 2204 operand->reg(), |
2205 operand->number_info(), | 2205 operand->type_info(), |
2206 smi_value, | 2206 smi_value, |
2207 overwrite_mode); | 2207 overwrite_mode); |
2208 if (!operand->number_info().IsSmi()) { | 2208 if (!operand->type_info().IsSmi()) { |
2209 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2209 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2210 deferred->Branch(not_zero); | 2210 deferred->Branch(not_zero); |
2211 } else { | 2211 } else { |
2212 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2212 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2213 } | 2213 } |
2214 __ mov(answer.reg(), operand->reg()); | 2214 __ mov(answer.reg(), operand->reg()); |
2215 ASSERT(kSmiTag == 0); // adjust code if not the case | 2215 ASSERT(kSmiTag == 0); // adjust code if not the case |
2216 // We do no shifts, only the Smi conversion, if shift_value is 1. | 2216 // We do no shifts, only the Smi conversion, if shift_value is 1. |
2217 if (shift_value > 1) { | 2217 if (shift_value > 1) { |
2218 __ shl(answer.reg(), shift_value - 1); | 2218 __ shl(answer.reg(), shift_value - 1); |
(...skipping 13 matching lines...) Expand all Loading... |
2232 case Token::BIT_AND: { | 2232 case Token::BIT_AND: { |
2233 operand->ToRegister(); | 2233 operand->ToRegister(); |
2234 frame_->Spill(operand->reg()); | 2234 frame_->Spill(operand->reg()); |
2235 DeferredCode* deferred = NULL; | 2235 DeferredCode* deferred = NULL; |
2236 if (reversed) { | 2236 if (reversed) { |
2237 deferred = | 2237 deferred = |
2238 new DeferredInlineSmiOperationReversed(op, | 2238 new DeferredInlineSmiOperationReversed(op, |
2239 operand->reg(), | 2239 operand->reg(), |
2240 smi_value, | 2240 smi_value, |
2241 operand->reg(), | 2241 operand->reg(), |
2242 operand->number_info(), | 2242 operand->type_info(), |
2243 overwrite_mode); | 2243 overwrite_mode); |
2244 } else { | 2244 } else { |
2245 deferred = new DeferredInlineSmiOperation(op, | 2245 deferred = new DeferredInlineSmiOperation(op, |
2246 operand->reg(), | 2246 operand->reg(), |
2247 operand->reg(), | 2247 operand->reg(), |
2248 operand->number_info(), | 2248 operand->type_info(), |
2249 smi_value, | 2249 smi_value, |
2250 overwrite_mode); | 2250 overwrite_mode); |
2251 } | 2251 } |
2252 if (!operand->number_info().IsSmi()) { | 2252 if (!operand->type_info().IsSmi()) { |
2253 __ test(operand->reg(), Immediate(kSmiTagMask)); | 2253 __ test(operand->reg(), Immediate(kSmiTagMask)); |
2254 deferred->Branch(not_zero); | 2254 deferred->Branch(not_zero); |
2255 } else { | 2255 } else { |
2256 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2256 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2257 } | 2257 } |
2258 if (op == Token::BIT_AND) { | 2258 if (op == Token::BIT_AND) { |
2259 __ and_(Operand(operand->reg()), Immediate(value)); | 2259 __ and_(Operand(operand->reg()), Immediate(value)); |
2260 } else if (op == Token::BIT_XOR) { | 2260 } else if (op == Token::BIT_XOR) { |
2261 if (int_value != 0) { | 2261 if (int_value != 0) { |
2262 __ xor_(Operand(operand->reg()), Immediate(value)); | 2262 __ xor_(Operand(operand->reg()), Immediate(value)); |
(...skipping 11 matching lines...) Expand all Loading... |
2274 | 2274 |
2275 case Token::DIV: | 2275 case Token::DIV: |
2276 if (!reversed && int_value == 2) { | 2276 if (!reversed && int_value == 2) { |
2277 operand->ToRegister(); | 2277 operand->ToRegister(); |
2278 frame_->Spill(operand->reg()); | 2278 frame_->Spill(operand->reg()); |
2279 | 2279 |
2280 DeferredInlineSmiOperation* deferred = | 2280 DeferredInlineSmiOperation* deferred = |
2281 new DeferredInlineSmiOperation(op, | 2281 new DeferredInlineSmiOperation(op, |
2282 operand->reg(), | 2282 operand->reg(), |
2283 operand->reg(), | 2283 operand->reg(), |
2284 operand->number_info(), | 2284 operand->type_info(), |
2285 smi_value, | 2285 smi_value, |
2286 overwrite_mode); | 2286 overwrite_mode); |
2287 // Check that lowest log2(value) bits of operand are zero, and test | 2287 // Check that lowest log2(value) bits of operand are zero, and test |
2288 // smi tag at the same time. | 2288 // smi tag at the same time. |
2289 ASSERT_EQ(0, kSmiTag); | 2289 ASSERT_EQ(0, kSmiTag); |
2290 ASSERT_EQ(1, kSmiTagSize); | 2290 ASSERT_EQ(1, kSmiTagSize); |
2291 __ test(operand->reg(), Immediate(3)); | 2291 __ test(operand->reg(), Immediate(3)); |
2292 deferred->Branch(not_zero); // Branch if non-smi or odd smi. | 2292 deferred->Branch(not_zero); // Branch if non-smi or odd smi. |
2293 __ sar(operand->reg(), 1); | 2293 __ sar(operand->reg(), 1); |
2294 deferred->BindExit(); | 2294 deferred->BindExit(); |
(...skipping 15 matching lines...) Expand all Loading... |
2310 case Token::MOD: | 2310 case Token::MOD: |
2311 if (!reversed && | 2311 if (!reversed && |
2312 int_value != 0 && | 2312 int_value != 0 && |
2313 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 2313 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
2314 operand->ToRegister(); | 2314 operand->ToRegister(); |
2315 frame_->Spill(operand->reg()); | 2315 frame_->Spill(operand->reg()); |
2316 DeferredCode* deferred = | 2316 DeferredCode* deferred = |
2317 new DeferredInlineSmiOperation(op, | 2317 new DeferredInlineSmiOperation(op, |
2318 operand->reg(), | 2318 operand->reg(), |
2319 operand->reg(), | 2319 operand->reg(), |
2320 operand->number_info(), | 2320 operand->type_info(), |
2321 smi_value, | 2321 smi_value, |
2322 overwrite_mode); | 2322 overwrite_mode); |
2323 // Check for negative or non-Smi left hand side. | 2323 // Check for negative or non-Smi left hand side. |
2324 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); | 2324 __ test(operand->reg(), Immediate(kSmiTagMask | 0x80000000)); |
2325 deferred->Branch(not_zero); | 2325 deferred->Branch(not_zero); |
2326 if (int_value < 0) int_value = -int_value; | 2326 if (int_value < 0) int_value = -int_value; |
2327 if (int_value == 1) { | 2327 if (int_value == 1) { |
2328 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); | 2328 __ mov(operand->reg(), Immediate(Smi::FromInt(0))); |
2329 } else { | 2329 } else { |
2330 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); | 2330 __ and_(operand->reg(), (int_value << kSmiTagSize) - 1); |
(...skipping 15 matching lines...) Expand all Loading... |
2346 } | 2346 } |
2347 break; | 2347 break; |
2348 } | 2348 } |
2349 } | 2349 } |
2350 ASSERT(answer.is_valid()); | 2350 ASSERT(answer.is_valid()); |
2351 return answer; | 2351 return answer; |
2352 } | 2352 } |
2353 | 2353 |
2354 | 2354 |
2355 static bool CouldBeNaN(const Result& result) { | 2355 static bool CouldBeNaN(const Result& result) { |
2356 if (result.number_info().IsSmi()) return false; | 2356 if (result.type_info().IsSmi()) return false; |
2357 if (result.number_info().IsInteger32()) return false; | 2357 if (result.type_info().IsInteger32()) return false; |
2358 if (!result.is_constant()) return true; | 2358 if (!result.is_constant()) return true; |
2359 if (!result.handle()->IsHeapNumber()) return false; | 2359 if (!result.handle()->IsHeapNumber()) return false; |
2360 return isnan(HeapNumber::cast(*result.handle())->value()); | 2360 return isnan(HeapNumber::cast(*result.handle())->value()); |
2361 } | 2361 } |
2362 | 2362 |
2363 | 2363 |
2364 void CodeGenerator::Comparison(AstNode* node, | 2364 void CodeGenerator::Comparison(AstNode* node, |
2365 Condition cc, | 2365 Condition cc, |
2366 bool strict, | 2366 bool strict, |
2367 ControlDestination* dest) { | 2367 ControlDestination* dest) { |
(...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3645 | 3645 |
3646 // The break target may be already bound (by the condition), or there | 3646 // The break target may be already bound (by the condition), or there |
3647 // may not be a valid frame. Bind it only if needed. | 3647 // may not be a valid frame. Bind it only if needed. |
3648 if (node->break_target()->is_linked()) { | 3648 if (node->break_target()->is_linked()) { |
3649 node->break_target()->Bind(); | 3649 node->break_target()->Bind(); |
3650 } | 3650 } |
3651 DecrementLoopNesting(); | 3651 DecrementLoopNesting(); |
3652 } | 3652 } |
3653 | 3653 |
3654 | 3654 |
3655 void CodeGenerator::SetTypeForStackSlot(Slot* slot, NumberInfo info) { | 3655 void CodeGenerator::SetTypeForStackSlot(Slot* slot, TypeInfo info) { |
3656 ASSERT(slot->type() == Slot::LOCAL || slot->type() == Slot::PARAMETER); | 3656 ASSERT(slot->type() == Slot::LOCAL || slot->type() == Slot::PARAMETER); |
3657 if (slot->type() == Slot::LOCAL) { | 3657 if (slot->type() == Slot::LOCAL) { |
3658 frame_->SetTypeForLocalAt(slot->index(), info); | 3658 frame_->SetTypeForLocalAt(slot->index(), info); |
3659 } else { | 3659 } else { |
3660 frame_->SetTypeForParamAt(slot->index(), info); | 3660 frame_->SetTypeForParamAt(slot->index(), info); |
3661 } | 3661 } |
3662 if (FLAG_debug_code && info.IsSmi()) { | 3662 if (FLAG_debug_code && info.IsSmi()) { |
3663 if (slot->type() == Slot::LOCAL) { | 3663 if (slot->type() == Slot::LOCAL) { |
3664 frame_->PushLocalAt(slot->index()); | 3664 frame_->PushLocalAt(slot->index()); |
3665 } else { | 3665 } else { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3765 | 3765 |
3766 CheckStack(); // TODO(1222600): ignore if body contains calls. | 3766 CheckStack(); // TODO(1222600): ignore if body contains calls. |
3767 | 3767 |
3768 // We know that the loop index is a smi if it is not modified in the | 3768 // We know that the loop index is a smi if it is not modified in the |
3769 // loop body and it is checked against a constant limit in the loop | 3769 // loop body and it is checked against a constant limit in the loop |
3770 // condition. In this case, we reset the static type information of the | 3770 // condition. In this case, we reset the static type information of the |
3771 // loop index to smi before compiling the body, the update expression, and | 3771 // loop index to smi before compiling the body, the update expression, and |
3772 // the bottom check of the loop condition. | 3772 // the bottom check of the loop condition. |
3773 if (node->is_fast_smi_loop()) { | 3773 if (node->is_fast_smi_loop()) { |
3774 // Set number type of the loop variable to smi. | 3774 // Set number type of the loop variable to smi. |
3775 SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi()); | 3775 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); |
3776 } | 3776 } |
3777 | 3777 |
3778 Visit(node->body()); | 3778 Visit(node->body()); |
3779 | 3779 |
3780 // If there is an update expression, compile it if necessary. | 3780 // If there is an update expression, compile it if necessary. |
3781 if (node->next() != NULL) { | 3781 if (node->next() != NULL) { |
3782 if (node->continue_target()->is_linked()) { | 3782 if (node->continue_target()->is_linked()) { |
3783 node->continue_target()->Bind(); | 3783 node->continue_target()->Bind(); |
3784 } | 3784 } |
3785 | 3785 |
3786 // Control can reach the update by falling out of the body or by a | 3786 // Control can reach the update by falling out of the body or by a |
3787 // continue. | 3787 // continue. |
3788 if (has_valid_frame()) { | 3788 if (has_valid_frame()) { |
3789 // Record the source position of the statement as this code which | 3789 // Record the source position of the statement as this code which |
3790 // is after the code for the body actually belongs to the loop | 3790 // is after the code for the body actually belongs to the loop |
3791 // statement and not the body. | 3791 // statement and not the body. |
3792 CodeForStatementPosition(node); | 3792 CodeForStatementPosition(node); |
3793 Visit(node->next()); | 3793 Visit(node->next()); |
3794 } | 3794 } |
3795 } | 3795 } |
3796 | 3796 |
3797 // Set the type of the loop variable to smi before compiling the test | 3797 // Set the type of the loop variable to smi before compiling the test |
3798 // expression if we are in a fast smi loop condition. | 3798 // expression if we are in a fast smi loop condition. |
3799 if (node->is_fast_smi_loop() && has_valid_frame()) { | 3799 if (node->is_fast_smi_loop() && has_valid_frame()) { |
3800 // Set number type of the loop variable to smi. | 3800 // Set number type of the loop variable to smi. |
3801 SetTypeForStackSlot(node->loop_variable()->slot(), NumberInfo::Smi()); | 3801 SetTypeForStackSlot(node->loop_variable()->slot(), TypeInfo::Smi()); |
3802 } | 3802 } |
3803 | 3803 |
3804 // Based on the condition analysis, compile the backward jump as | 3804 // Based on the condition analysis, compile the backward jump as |
3805 // necessary. | 3805 // necessary. |
3806 switch (info) { | 3806 switch (info) { |
3807 case ALWAYS_TRUE: | 3807 case ALWAYS_TRUE: |
3808 if (has_valid_frame()) { | 3808 if (has_valid_frame()) { |
3809 if (node->next() == NULL) { | 3809 if (node->next() == NULL) { |
3810 node->continue_target()->Jump(); | 3810 node->continue_target()->Jump(); |
3811 } else { | 3811 } else { |
(...skipping 2882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6694 } else { | 6694 } else { |
6695 Load(node->expression()); | 6695 Load(node->expression()); |
6696 bool overwrite = | 6696 bool overwrite = |
6697 (node->expression()->AsBinaryOperation() != NULL && | 6697 (node->expression()->AsBinaryOperation() != NULL && |
6698 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | 6698 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
6699 switch (op) { | 6699 switch (op) { |
6700 case Token::SUB: { | 6700 case Token::SUB: { |
6701 GenericUnaryOpStub stub(Token::SUB, overwrite); | 6701 GenericUnaryOpStub stub(Token::SUB, overwrite); |
6702 Result operand = frame_->Pop(); | 6702 Result operand = frame_->Pop(); |
6703 Result answer = frame_->CallStub(&stub, &operand); | 6703 Result answer = frame_->CallStub(&stub, &operand); |
6704 answer.set_number_info(NumberInfo::Number()); | 6704 answer.set_type_info(TypeInfo::Number()); |
6705 frame_->Push(&answer); | 6705 frame_->Push(&answer); |
6706 break; | 6706 break; |
6707 } | 6707 } |
6708 case Token::BIT_NOT: { | 6708 case Token::BIT_NOT: { |
6709 // Smi check. | 6709 // Smi check. |
6710 JumpTarget smi_label; | 6710 JumpTarget smi_label; |
6711 JumpTarget continue_label; | 6711 JumpTarget continue_label; |
6712 Result operand = frame_->Pop(); | 6712 Result operand = frame_->Pop(); |
6713 NumberInfo operand_info = operand.number_info(); | 6713 TypeInfo operand_info = operand.type_info(); |
6714 operand.ToRegister(); | 6714 operand.ToRegister(); |
6715 if (operand_info.IsSmi()) { | 6715 if (operand_info.IsSmi()) { |
6716 if (FLAG_debug_code) __ AbortIfNotSmi(operand.reg()); | 6716 if (FLAG_debug_code) __ AbortIfNotSmi(operand.reg()); |
6717 frame_->Spill(operand.reg()); | 6717 frame_->Spill(operand.reg()); |
6718 // Set smi tag bit. It will be reset by the not operation. | 6718 // Set smi tag bit. It will be reset by the not operation. |
6719 __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask)); | 6719 __ lea(operand.reg(), Operand(operand.reg(), kSmiTagMask)); |
6720 __ not_(operand.reg()); | 6720 __ not_(operand.reg()); |
6721 Result answer = operand; | 6721 Result answer = operand; |
6722 answer.set_number_info(NumberInfo::Smi()); | 6722 answer.set_type_info(TypeInfo::Smi()); |
6723 frame_->Push(&answer); | 6723 frame_->Push(&answer); |
6724 } else { | 6724 } else { |
6725 __ test(operand.reg(), Immediate(kSmiTagMask)); | 6725 __ test(operand.reg(), Immediate(kSmiTagMask)); |
6726 smi_label.Branch(zero, &operand, taken); | 6726 smi_label.Branch(zero, &operand, taken); |
6727 | 6727 |
6728 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 6728 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
6729 Result answer = frame_->CallStub(&stub, &operand); | 6729 Result answer = frame_->CallStub(&stub, &operand); |
6730 continue_label.Jump(&answer); | 6730 continue_label.Jump(&answer); |
6731 | 6731 |
6732 smi_label.Bind(&answer); | 6732 smi_label.Bind(&answer); |
6733 answer.ToRegister(); | 6733 answer.ToRegister(); |
6734 frame_->Spill(answer.reg()); | 6734 frame_->Spill(answer.reg()); |
6735 // Set smi tag bit. It will be reset by the not operation. | 6735 // Set smi tag bit. It will be reset by the not operation. |
6736 __ lea(answer.reg(), Operand(answer.reg(), kSmiTagMask)); | 6736 __ lea(answer.reg(), Operand(answer.reg(), kSmiTagMask)); |
6737 __ not_(answer.reg()); | 6737 __ not_(answer.reg()); |
6738 | 6738 |
6739 continue_label.Bind(&answer); | 6739 continue_label.Bind(&answer); |
6740 if (operand_info.IsInteger32()) { | 6740 if (operand_info.IsInteger32()) { |
6741 answer.set_number_info(NumberInfo::Integer32()); | 6741 answer.set_type_info(TypeInfo::Integer32()); |
6742 } else { | 6742 } else { |
6743 answer.set_number_info(NumberInfo::Number()); | 6743 answer.set_type_info(TypeInfo::Number()); |
6744 } | 6744 } |
6745 frame_->Push(&answer); | 6745 frame_->Push(&answer); |
6746 } | 6746 } |
6747 break; | 6747 break; |
6748 } | 6748 } |
6749 case Token::ADD: { | 6749 case Token::ADD: { |
6750 // Smi check. | 6750 // Smi check. |
6751 JumpTarget continue_label; | 6751 JumpTarget continue_label; |
6752 Result operand = frame_->Pop(); | 6752 Result operand = frame_->Pop(); |
6753 NumberInfo operand_info = operand.number_info(); | 6753 TypeInfo operand_info = operand.type_info(); |
6754 operand.ToRegister(); | 6754 operand.ToRegister(); |
6755 __ test(operand.reg(), Immediate(kSmiTagMask)); | 6755 __ test(operand.reg(), Immediate(kSmiTagMask)); |
6756 continue_label.Branch(zero, &operand, taken); | 6756 continue_label.Branch(zero, &operand, taken); |
6757 | 6757 |
6758 frame_->Push(&operand); | 6758 frame_->Push(&operand); |
6759 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, | 6759 Result answer = frame_->InvokeBuiltin(Builtins::TO_NUMBER, |
6760 CALL_FUNCTION, 1); | 6760 CALL_FUNCTION, 1); |
6761 | 6761 |
6762 continue_label.Bind(&answer); | 6762 continue_label.Bind(&answer); |
6763 if (operand_info.IsSmi()) { | 6763 if (operand_info.IsSmi()) { |
6764 answer.set_number_info(NumberInfo::Smi()); | 6764 answer.set_type_info(TypeInfo::Smi()); |
6765 } else if (operand_info.IsInteger32()) { | 6765 } else if (operand_info.IsInteger32()) { |
6766 answer.set_number_info(NumberInfo::Integer32()); | 6766 answer.set_type_info(TypeInfo::Integer32()); |
6767 } else { | 6767 } else { |
6768 answer.set_number_info(NumberInfo::Number()); | 6768 answer.set_type_info(TypeInfo::Number()); |
6769 } | 6769 } |
6770 frame_->Push(&answer); | 6770 frame_->Push(&answer); |
6771 break; | 6771 break; |
6772 } | 6772 } |
6773 default: | 6773 default: |
6774 // NOT, DELETE, TYPEOF, and VOID are handled outside the | 6774 // NOT, DELETE, TYPEOF, and VOID are handled outside the |
6775 // switch. | 6775 // switch. |
6776 UNREACHABLE(); | 6776 UNREACHABLE(); |
6777 } | 6777 } |
6778 } | 6778 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6898 | 6898 |
6899 Result old_value; // Only allocated in the postfix case. | 6899 Result old_value; // Only allocated in the postfix case. |
6900 if (is_postfix) { | 6900 if (is_postfix) { |
6901 // Allocate a temporary to preserve the old value. | 6901 // Allocate a temporary to preserve the old value. |
6902 old_value = allocator_->Allocate(); | 6902 old_value = allocator_->Allocate(); |
6903 ASSERT(old_value.is_valid()); | 6903 ASSERT(old_value.is_valid()); |
6904 __ mov(old_value.reg(), new_value.reg()); | 6904 __ mov(old_value.reg(), new_value.reg()); |
6905 | 6905 |
6906 // The return value for postfix operations is the | 6906 // The return value for postfix operations is the |
6907 // same as the input, and has the same number info. | 6907 // same as the input, and has the same number info. |
6908 old_value.set_number_info(new_value.number_info()); | 6908 old_value.set_type_info(new_value.type_info()); |
6909 } | 6909 } |
6910 | 6910 |
6911 // Ensure the new value is writable. | 6911 // Ensure the new value is writable. |
6912 frame_->Spill(new_value.reg()); | 6912 frame_->Spill(new_value.reg()); |
6913 | 6913 |
6914 Result tmp; | 6914 Result tmp; |
6915 if (new_value.is_smi()) { | 6915 if (new_value.is_smi()) { |
6916 if (FLAG_debug_code) __ AbortIfNotSmi(new_value.reg()); | 6916 if (FLAG_debug_code) __ AbortIfNotSmi(new_value.reg()); |
6917 } else { | 6917 } else { |
6918 // We don't know statically if the input is a smi. | 6918 // We don't know statically if the input is a smi. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6965 deferred->Branch(overflow); | 6965 deferred->Branch(overflow); |
6966 __ test(new_value.reg(), Immediate(kSmiTagMask)); | 6966 __ test(new_value.reg(), Immediate(kSmiTagMask)); |
6967 deferred->Branch(not_zero); | 6967 deferred->Branch(not_zero); |
6968 } | 6968 } |
6969 } | 6969 } |
6970 deferred->BindExit(); | 6970 deferred->BindExit(); |
6971 | 6971 |
6972 // The result of ++ or -- is an Integer32 if the | 6972 // The result of ++ or -- is an Integer32 if the |
6973 // input is a smi. Otherwise it is a number. | 6973 // input is a smi. Otherwise it is a number. |
6974 if (new_value.is_smi()) { | 6974 if (new_value.is_smi()) { |
6975 new_value.set_number_info(NumberInfo::Integer32()); | 6975 new_value.set_type_info(TypeInfo::Integer32()); |
6976 } else { | 6976 } else { |
6977 new_value.set_number_info(NumberInfo::Number()); | 6977 new_value.set_type_info(TypeInfo::Number()); |
6978 } | 6978 } |
6979 | 6979 |
6980 // Postfix: store the old value in the allocated slot under the | 6980 // Postfix: store the old value in the allocated slot under the |
6981 // reference. | 6981 // reference. |
6982 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); | 6982 if (is_postfix) frame_->SetElementAt(target.size(), &old_value); |
6983 | 6983 |
6984 frame_->Push(&new_value); | 6984 frame_->Push(&new_value); |
6985 // Non-constant: update the reference. | 6985 // Non-constant: update the reference. |
6986 if (!is_const) target.SetValue(NOT_CONST_INIT); | 6986 if (!is_const) target.SetValue(NOT_CONST_INIT); |
6987 } | 6987 } |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7181 if (op == Token::MOD) { | 7181 if (op == Token::MOD) { |
7182 // Negative zero can arise as a negative divident with a zero result. | 7182 // Negative zero can arise as a negative divident with a zero result. |
7183 if (!node->no_negative_zero()) { | 7183 if (!node->no_negative_zero()) { |
7184 Label not_negative_zero; | 7184 Label not_negative_zero; |
7185 __ test(edx, Operand(edx)); | 7185 __ test(edx, Operand(edx)); |
7186 __ j(not_zero, ¬_negative_zero); | 7186 __ j(not_zero, ¬_negative_zero); |
7187 __ test(eax, Operand(eax)); | 7187 __ test(eax, Operand(eax)); |
7188 unsafe_bailout_->Branch(negative); | 7188 unsafe_bailout_->Branch(negative); |
7189 __ bind(¬_negative_zero); | 7189 __ bind(¬_negative_zero); |
7190 } | 7190 } |
7191 Result edx_result(edx, NumberInfo::Integer32()); | 7191 Result edx_result(edx, TypeInfo::Integer32()); |
7192 edx_result.set_untagged_int32(true); | 7192 edx_result.set_untagged_int32(true); |
7193 frame_->Push(&edx_result); | 7193 frame_->Push(&edx_result); |
7194 } else { | 7194 } else { |
7195 ASSERT(op == Token::DIV); | 7195 ASSERT(op == Token::DIV); |
7196 __ test(edx, Operand(edx)); | 7196 __ test(edx, Operand(edx)); |
7197 unsafe_bailout_->Branch(not_equal); | 7197 unsafe_bailout_->Branch(not_equal); |
7198 Result eax_result(eax, NumberInfo::Integer32()); | 7198 Result eax_result(eax, TypeInfo::Integer32()); |
7199 eax_result.set_untagged_int32(true); | 7199 eax_result.set_untagged_int32(true); |
7200 frame_->Push(&eax_result); | 7200 frame_->Push(&eax_result); |
7201 } | 7201 } |
7202 break; | 7202 break; |
7203 } | 7203 } |
7204 default: | 7204 default: |
7205 UNREACHABLE(); | 7205 UNREACHABLE(); |
7206 break; | 7206 break; |
7207 } | 7207 } |
7208 } | 7208 } |
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8075 return result; | 8075 return result; |
8076 } | 8076 } |
8077 | 8077 |
8078 | 8078 |
8079 #undef __ | 8079 #undef __ |
8080 #define __ ACCESS_MASM(masm) | 8080 #define __ ACCESS_MASM(masm) |
8081 | 8081 |
8082 | 8082 |
8083 static void CheckTwoForSminess(MacroAssembler* masm, | 8083 static void CheckTwoForSminess(MacroAssembler* masm, |
8084 Register left, Register right, Register scratch, | 8084 Register left, Register right, Register scratch, |
8085 NumberInfo left_info, NumberInfo right_info, | 8085 TypeInfo left_info, TypeInfo right_info, |
8086 DeferredInlineBinaryOperation* deferred) { | 8086 DeferredInlineBinaryOperation* deferred) { |
8087 if (left.is(right)) { | 8087 if (left.is(right)) { |
8088 if (!left_info.IsSmi()) { | 8088 if (!left_info.IsSmi()) { |
8089 __ test(left, Immediate(kSmiTagMask)); | 8089 __ test(left, Immediate(kSmiTagMask)); |
8090 deferred->Branch(not_zero); | 8090 deferred->Branch(not_zero); |
8091 } else { | 8091 } else { |
8092 if (FLAG_debug_code) __ AbortIfNotSmi(left); | 8092 if (FLAG_debug_code) __ AbortIfNotSmi(left); |
8093 } | 8093 } |
8094 } else if (!left_info.IsSmi()) { | 8094 } else if (!left_info.IsSmi()) { |
8095 if (!right_info.IsSmi()) { | 8095 if (!right_info.IsSmi()) { |
(...skipping 1480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9576 __ bind(&done); | 9576 __ bind(&done); |
9577 } | 9577 } |
9578 | 9578 |
9579 | 9579 |
9580 // Get the integer part of a heap number. Surprisingly, all this bit twiddling | 9580 // Get the integer part of a heap number. Surprisingly, all this bit twiddling |
9581 // is faster than using the built-in instructions on floating point registers. | 9581 // is faster than using the built-in instructions on floating point registers. |
9582 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the | 9582 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the |
9583 // trashed registers. | 9583 // trashed registers. |
9584 void IntegerConvert(MacroAssembler* masm, | 9584 void IntegerConvert(MacroAssembler* masm, |
9585 Register source, | 9585 Register source, |
9586 NumberInfo number_info, | 9586 TypeInfo type_info, |
9587 bool use_sse3, | 9587 bool use_sse3, |
9588 Label* conversion_failure) { | 9588 Label* conversion_failure) { |
9589 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); | 9589 ASSERT(!source.is(ecx) && !source.is(edi) && !source.is(ebx)); |
9590 Label done, right_exponent, normal_exponent; | 9590 Label done, right_exponent, normal_exponent; |
9591 Register scratch = ebx; | 9591 Register scratch = ebx; |
9592 Register scratch2 = edi; | 9592 Register scratch2 = edi; |
9593 if (!number_info.IsInteger32() || !use_sse3) { | 9593 if (!type_info.IsInteger32() || !use_sse3) { |
9594 // Get exponent word. | 9594 // Get exponent word. |
9595 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); | 9595 __ mov(scratch, FieldOperand(source, HeapNumber::kExponentOffset)); |
9596 // Get exponent alone in scratch2. | 9596 // Get exponent alone in scratch2. |
9597 __ mov(scratch2, scratch); | 9597 __ mov(scratch2, scratch); |
9598 __ and_(scratch2, HeapNumber::kExponentMask); | 9598 __ and_(scratch2, HeapNumber::kExponentMask); |
9599 } | 9599 } |
9600 if (use_sse3) { | 9600 if (use_sse3) { |
9601 CpuFeatures::Scope scope(SSE3); | 9601 CpuFeatures::Scope scope(SSE3); |
9602 if (!number_info.IsInteger32()) { | 9602 if (!type_info.IsInteger32()) { |
9603 // Check whether the exponent is too big for a 64 bit signed integer. | 9603 // Check whether the exponent is too big for a 64 bit signed integer. |
9604 static const uint32_t kTooBigExponent = | 9604 static const uint32_t kTooBigExponent = |
9605 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 9605 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
9606 __ cmp(Operand(scratch2), Immediate(kTooBigExponent)); | 9606 __ cmp(Operand(scratch2), Immediate(kTooBigExponent)); |
9607 __ j(greater_equal, conversion_failure); | 9607 __ j(greater_equal, conversion_failure); |
9608 } | 9608 } |
9609 // Load x87 register with heap number. | 9609 // Load x87 register with heap number. |
9610 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); | 9610 __ fld_d(FieldOperand(source, HeapNumber::kValueOffset)); |
9611 // Reserve space for 64 bit answer. | 9611 // Reserve space for 64 bit answer. |
9612 __ sub(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint. | 9612 __ sub(Operand(esp), Immediate(sizeof(uint64_t))); // Nolint. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9713 __ bind(&negative); | 9713 __ bind(&negative); |
9714 __ sub(ecx, Operand(scratch2)); | 9714 __ sub(ecx, Operand(scratch2)); |
9715 __ bind(&done); | 9715 __ bind(&done); |
9716 } | 9716 } |
9717 } | 9717 } |
9718 | 9718 |
9719 | 9719 |
9720 // Input: edx, eax are the left and right objects of a bit op. | 9720 // Input: edx, eax are the left and right objects of a bit op. |
9721 // Output: eax, ecx are left and right integers for a bit op. | 9721 // Output: eax, ecx are left and right integers for a bit op. |
9722 void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm, | 9722 void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm, |
9723 NumberInfo number_info, | 9723 TypeInfo type_info, |
9724 bool use_sse3, | 9724 bool use_sse3, |
9725 Label* conversion_failure) { | 9725 Label* conversion_failure) { |
9726 // Check float operands. | 9726 // Check float operands. |
9727 Label arg1_is_object, check_undefined_arg1; | 9727 Label arg1_is_object, check_undefined_arg1; |
9728 Label arg2_is_object, check_undefined_arg2; | 9728 Label arg2_is_object, check_undefined_arg2; |
9729 Label load_arg2, done; | 9729 Label load_arg2, done; |
9730 | 9730 |
9731 if (!number_info.IsDouble()) { | 9731 if (!type_info.IsDouble()) { |
9732 if (!number_info.IsSmi()) { | 9732 if (!type_info.IsSmi()) { |
9733 __ test(edx, Immediate(kSmiTagMask)); | 9733 __ test(edx, Immediate(kSmiTagMask)); |
9734 __ j(not_zero, &arg1_is_object); | 9734 __ j(not_zero, &arg1_is_object); |
9735 } else { | 9735 } else { |
9736 if (FLAG_debug_code) __ AbortIfNotSmi(edx); | 9736 if (FLAG_debug_code) __ AbortIfNotSmi(edx); |
9737 } | 9737 } |
9738 __ SmiUntag(edx); | 9738 __ SmiUntag(edx); |
9739 __ jmp(&load_arg2); | 9739 __ jmp(&load_arg2); |
9740 } | 9740 } |
9741 | 9741 |
9742 __ bind(&arg1_is_object); | 9742 __ bind(&arg1_is_object); |
9743 | 9743 |
9744 // Get the untagged integer version of the edx heap number in ecx. | 9744 // Get the untagged integer version of the edx heap number in ecx. |
9745 IntegerConvert(masm, edx, number_info, use_sse3, conversion_failure); | 9745 IntegerConvert(masm, edx, type_info, use_sse3, conversion_failure); |
9746 __ mov(edx, ecx); | 9746 __ mov(edx, ecx); |
9747 | 9747 |
9748 // Here edx has the untagged integer, eax has a Smi or a heap number. | 9748 // Here edx has the untagged integer, eax has a Smi or a heap number. |
9749 __ bind(&load_arg2); | 9749 __ bind(&load_arg2); |
9750 if (!number_info.IsDouble()) { | 9750 if (!type_info.IsDouble()) { |
9751 // Test if arg2 is a Smi. | 9751 // Test if arg2 is a Smi. |
9752 if (!number_info.IsSmi()) { | 9752 if (!type_info.IsSmi()) { |
9753 __ test(eax, Immediate(kSmiTagMask)); | 9753 __ test(eax, Immediate(kSmiTagMask)); |
9754 __ j(not_zero, &arg2_is_object); | 9754 __ j(not_zero, &arg2_is_object); |
9755 } else { | 9755 } else { |
9756 if (FLAG_debug_code) __ AbortIfNotSmi(eax); | 9756 if (FLAG_debug_code) __ AbortIfNotSmi(eax); |
9757 } | 9757 } |
9758 __ SmiUntag(eax); | 9758 __ SmiUntag(eax); |
9759 __ mov(ecx, eax); | 9759 __ mov(ecx, eax); |
9760 __ jmp(&done); | 9760 __ jmp(&done); |
9761 } | 9761 } |
9762 | 9762 |
9763 __ bind(&arg2_is_object); | 9763 __ bind(&arg2_is_object); |
9764 | 9764 |
9765 // Get the untagged integer version of the eax heap number in ecx. | 9765 // Get the untagged integer version of the eax heap number in ecx. |
9766 IntegerConvert(masm, eax, number_info, use_sse3, conversion_failure); | 9766 IntegerConvert(masm, eax, type_info, use_sse3, conversion_failure); |
9767 __ bind(&done); | 9767 __ bind(&done); |
9768 __ mov(eax, edx); | 9768 __ mov(eax, edx); |
9769 } | 9769 } |
9770 | 9770 |
9771 | 9771 |
9772 // Input: edx, eax are the left and right objects of a bit op. | 9772 // Input: edx, eax are the left and right objects of a bit op. |
9773 // Output: eax, ecx are left and right integers for a bit op. | 9773 // Output: eax, ecx are left and right integers for a bit op. |
9774 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, | 9774 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm, |
9775 bool use_sse3, | 9775 bool use_sse3, |
9776 Label* conversion_failure) { | 9776 Label* conversion_failure) { |
(...skipping 17 matching lines...) Expand all Loading... |
9794 __ jmp(&load_arg2); | 9794 __ jmp(&load_arg2); |
9795 | 9795 |
9796 __ bind(&arg1_is_object); | 9796 __ bind(&arg1_is_object); |
9797 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 9797 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
9798 __ cmp(ebx, Factory::heap_number_map()); | 9798 __ cmp(ebx, Factory::heap_number_map()); |
9799 __ j(not_equal, &check_undefined_arg1); | 9799 __ j(not_equal, &check_undefined_arg1); |
9800 | 9800 |
9801 // Get the untagged integer version of the edx heap number in ecx. | 9801 // Get the untagged integer version of the edx heap number in ecx. |
9802 IntegerConvert(masm, | 9802 IntegerConvert(masm, |
9803 edx, | 9803 edx, |
9804 NumberInfo::Unknown(), | 9804 TypeInfo::Unknown(), |
9805 use_sse3, | 9805 use_sse3, |
9806 conversion_failure); | 9806 conversion_failure); |
9807 __ mov(edx, ecx); | 9807 __ mov(edx, ecx); |
9808 | 9808 |
9809 // Here edx has the untagged integer, eax has a Smi or a heap number. | 9809 // Here edx has the untagged integer, eax has a Smi or a heap number. |
9810 __ bind(&load_arg2); | 9810 __ bind(&load_arg2); |
9811 | 9811 |
9812 // Test if arg2 is a Smi. | 9812 // Test if arg2 is a Smi. |
9813 __ test(eax, Immediate(kSmiTagMask)); | 9813 __ test(eax, Immediate(kSmiTagMask)); |
9814 __ j(not_zero, &arg2_is_object); | 9814 __ j(not_zero, &arg2_is_object); |
(...skipping 10 matching lines...) Expand all Loading... |
9825 __ jmp(&done); | 9825 __ jmp(&done); |
9826 | 9826 |
9827 __ bind(&arg2_is_object); | 9827 __ bind(&arg2_is_object); |
9828 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 9828 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
9829 __ cmp(ebx, Factory::heap_number_map()); | 9829 __ cmp(ebx, Factory::heap_number_map()); |
9830 __ j(not_equal, &check_undefined_arg2); | 9830 __ j(not_equal, &check_undefined_arg2); |
9831 | 9831 |
9832 // Get the untagged integer version of the eax heap number in ecx. | 9832 // Get the untagged integer version of the eax heap number in ecx. |
9833 IntegerConvert(masm, | 9833 IntegerConvert(masm, |
9834 eax, | 9834 eax, |
9835 NumberInfo::Unknown(), | 9835 TypeInfo::Unknown(), |
9836 use_sse3, | 9836 use_sse3, |
9837 conversion_failure); | 9837 conversion_failure); |
9838 __ bind(&done); | 9838 __ bind(&done); |
9839 __ mov(eax, edx); | 9839 __ mov(eax, edx); |
9840 } | 9840 } |
9841 | 9841 |
9842 | 9842 |
9843 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, | 9843 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm, |
9844 NumberInfo number_info, | 9844 TypeInfo type_info, |
9845 bool use_sse3, | 9845 bool use_sse3, |
9846 Label* conversion_failure) { | 9846 Label* conversion_failure) { |
9847 if (number_info.IsNumber()) { | 9847 if (type_info.IsNumber()) { |
9848 LoadNumbersAsIntegers(masm, number_info, use_sse3, conversion_failure); | 9848 LoadNumbersAsIntegers(masm, type_info, use_sse3, conversion_failure); |
9849 } else { | 9849 } else { |
9850 LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure); | 9850 LoadUnknownsAsIntegers(masm, use_sse3, conversion_failure); |
9851 } | 9851 } |
9852 } | 9852 } |
9853 | 9853 |
9854 | 9854 |
9855 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, | 9855 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, |
9856 Register number) { | 9856 Register number) { |
9857 Label load_smi, done; | 9857 Label load_smi, done; |
9858 | 9858 |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10083 } | 10083 } |
10084 } else if (op_ == Token::BIT_NOT) { | 10084 } else if (op_ == Token::BIT_NOT) { |
10085 // Check if the operand is a heap number. | 10085 // Check if the operand is a heap number. |
10086 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 10086 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
10087 __ cmp(edx, Factory::heap_number_map()); | 10087 __ cmp(edx, Factory::heap_number_map()); |
10088 __ j(not_equal, &slow, not_taken); | 10088 __ j(not_equal, &slow, not_taken); |
10089 | 10089 |
10090 // Convert the heap number in eax to an untagged integer in ecx. | 10090 // Convert the heap number in eax to an untagged integer in ecx. |
10091 IntegerConvert(masm, | 10091 IntegerConvert(masm, |
10092 eax, | 10092 eax, |
10093 NumberInfo::Unknown(), | 10093 TypeInfo::Unknown(), |
10094 CpuFeatures::IsSupported(SSE3), | 10094 CpuFeatures::IsSupported(SSE3), |
10095 &slow); | 10095 &slow); |
10096 | 10096 |
10097 // Do the bitwise operation and check if the result fits in a smi. | 10097 // Do the bitwise operation and check if the result fits in a smi. |
10098 Label try_float; | 10098 Label try_float; |
10099 __ not_(ecx); | 10099 __ not_(ecx); |
10100 __ cmp(ecx, 0xc0000000); | 10100 __ cmp(ecx, 0xc0000000); |
10101 __ j(sign, &try_float, not_taken); | 10101 __ j(sign, &try_float, not_taken); |
10102 | 10102 |
10103 // Tag the result as a smi and we're done. | 10103 // Tag the result as a smi and we're done. |
(...skipping 2225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12329 | 12329 |
12330 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 12330 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
12331 // tagged as a small integer. | 12331 // tagged as a small integer. |
12332 __ bind(&runtime); | 12332 __ bind(&runtime); |
12333 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 12333 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
12334 } | 12334 } |
12335 | 12335 |
12336 #undef __ | 12336 #undef __ |
12337 | 12337 |
12338 } } // namespace v8::internal | 12338 } } // namespace v8::internal |
OLD | NEW |