| 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 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); | 862 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); |
| 863 frame_->SpillAll(); | 863 frame_->SpillAll(); |
| 864 frame_->CallStub(&stub, 0); | 864 frame_->CallStub(&stub, 0); |
| 865 done.Bind(); | 865 done.Bind(); |
| 866 } | 866 } |
| 867 frame_->EmitPush(r0); | 867 frame_->EmitPush(r0); |
| 868 break; | 868 break; |
| 869 } else { | 869 } else { |
| 870 // Fall through! | 870 // Fall through! |
| 871 } | 871 } |
| 872 case Token::MUL: | |
| 873 case Token::DIV: | 872 case Token::DIV: |
| 874 case Token::MOD: | 873 case Token::MOD: |
| 875 case Token::SHL: | 874 case Token::SHL: |
| 876 case Token::SHR: | 875 case Token::SHR: |
| 877 case Token::SAR: { | 876 case Token::SAR: { |
| 878 Register rhs = frame_->PopToRegister(); | 877 Register rhs = frame_->PopToRegister(); |
| 879 Register lhs = frame_->PopToRegister(rhs); // Don't pop to rhs register. | 878 Register lhs = frame_->PopToRegister(rhs); // Don't pop to rhs register. |
| 880 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); | 879 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); |
| 881 frame_->SpillAll(); | 880 frame_->SpillAll(); |
| 882 frame_->CallStub(&stub, 0); | 881 frame_->CallStub(&stub, 0); |
| 883 frame_->EmitPush(r0); | 882 frame_->EmitPush(r0); |
| 884 break; | 883 break; |
| 885 } | 884 } |
| 886 | 885 |
| 886 case Token::MUL: { |
| 887 Register rhs = frame_->PopToRegister(); |
| 888 Register lhs = frame_->PopToRegister(rhs); |
| 889 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs); |
| 890 if (inline_smi) { |
| 891 JumpTarget slow, done; |
| 892 Register smi_test_reg = VirtualFrame::scratch0(); |
| 893 Register low = VirtualFrame::scratch1(); |
| 894 Register high = smi_test_reg; |
| 895 // We need to know whether we are dealing with two positive Smis. Set |
| 896 // up smi_test_reg to tell us that. |
| 897 __ orr(smi_test_reg, lhs, Operand(rhs)); |
| 898 __ tst(smi_test_reg, Operand(0x80000000 | kSmiTagMask)); |
| 899 smi_test_reg = no_reg; |
| 900 slow.Branch(ne); |
| 901 // Do multiplication |
| 902 __ smull(low, high, lhs, rhs); |
| 903 __ cmp(high, Operand(0)); |
| 904 // Remove double tag from answer. |
| 905 __ mov(r0, Operand(low, LSR, kSmiTagSize), LeaveCC, eq); |
| 906 done.Branch(eq); |
| 907 slow.Bind(); |
| 908 frame_->SpillAll(); |
| 909 frame_->CallStub(&stub, 0); |
| 910 done.Bind(); |
| 911 } else { |
| 912 frame_->SpillAll(); |
| 913 frame_->CallStub(&stub, 0); |
| 914 } |
| 915 frame_->EmitPush(r0); |
| 916 break; |
| 917 } |
| 918 |
| 887 case Token::COMMA: { | 919 case Token::COMMA: { |
| 888 Register scratch = frame_->PopToRegister(); | 920 Register scratch = frame_->PopToRegister(); |
| 889 // Simply discard left value. | 921 // Simply discard left value. |
| 890 frame_->Drop(); | 922 frame_->Drop(); |
| 891 frame_->EmitPush(scratch); | 923 frame_->EmitPush(scratch); |
| 892 break; | 924 break; |
| 893 } | 925 } |
| 894 | 926 |
| 895 default: | 927 default: |
| 896 // Other cases should have been handled before this point. | 928 // Other cases should have been handled before this point. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 | 1061 |
| 1030 | 1062 |
| 1031 void CodeGenerator::SmiOperation(Token::Value op, | 1063 void CodeGenerator::SmiOperation(Token::Value op, |
| 1032 Handle<Object> value, | 1064 Handle<Object> value, |
| 1033 bool reversed, | 1065 bool reversed, |
| 1034 OverwriteMode mode) { | 1066 OverwriteMode mode) { |
| 1035 int int_value = Smi::cast(*value)->value(); | 1067 int int_value = Smi::cast(*value)->value(); |
| 1036 | 1068 |
| 1037 bool both_sides_are_smi = frame_->KnownSmiAt(0); | 1069 bool both_sides_are_smi = frame_->KnownSmiAt(0); |
| 1038 | 1070 |
| 1039 bool something_to_inline; | 1071 bool inline_op_with_constant_smi; |
| 1072 GenerateInlineSmi inline_generic_smi_code = GENERATE_INLINE_SMI; |
| 1040 switch (op) { | 1073 switch (op) { |
| 1041 case Token::ADD: | 1074 case Token::ADD: |
| 1042 case Token::SUB: | 1075 case Token::SUB: |
| 1043 case Token::BIT_AND: | 1076 case Token::BIT_AND: |
| 1044 case Token::BIT_OR: | 1077 case Token::BIT_OR: |
| 1045 case Token::BIT_XOR: { | 1078 case Token::BIT_XOR: { |
| 1046 something_to_inline = true; | 1079 inline_op_with_constant_smi = true; |
| 1047 break; | 1080 break; |
| 1048 } | 1081 } |
| 1049 case Token::SHL: { | 1082 case Token::SHL: { |
| 1050 something_to_inline = (both_sides_are_smi || !reversed); | 1083 inline_op_with_constant_smi = (both_sides_are_smi || !reversed); |
| 1051 break; | 1084 break; |
| 1052 } | 1085 } |
| 1053 case Token::SHR: | 1086 case Token::SHR: |
| 1054 case Token::SAR: { | 1087 case Token::SAR: { |
| 1055 if (reversed) { | 1088 if (reversed) { |
| 1056 something_to_inline = false; | 1089 inline_op_with_constant_smi = false; |
| 1057 } else { | 1090 } else { |
| 1058 something_to_inline = true; | 1091 inline_op_with_constant_smi = true; |
| 1059 } | 1092 } |
| 1060 break; | 1093 break; |
| 1061 } | 1094 } |
| 1095 case Token::MUL: { |
| 1096 // Multiplying by negative small constants is too annoying because of the |
| 1097 // -0 issues. |
| 1098 inline_op_with_constant_smi = (int_value >= 2); |
| 1099 inline_generic_smi_code = inline_op_with_constant_smi ? |
| 1100 GENERATE_INLINE_SMI : |
| 1101 DONT_GENERATE_INLINE_SMI; |
| 1102 break; |
| 1103 } |
| 1062 case Token::MOD: { | 1104 case Token::MOD: { |
| 1063 if (reversed || int_value < 2 || !IsPowerOf2(int_value)) { | 1105 if (reversed || int_value < 2 || !IsPowerOf2(int_value)) { |
| 1064 something_to_inline = false; | 1106 inline_op_with_constant_smi = false; |
| 1065 } else { | 1107 } else { |
| 1066 something_to_inline = true; | 1108 inline_op_with_constant_smi = true; |
| 1067 } | |
| 1068 break; | |
| 1069 } | |
| 1070 case Token::MUL: { | |
| 1071 if (!IsEasyToMultiplyBy(int_value)) { | |
| 1072 something_to_inline = false; | |
| 1073 } else { | |
| 1074 something_to_inline = true; | |
| 1075 } | 1109 } |
| 1076 break; | 1110 break; |
| 1077 } | 1111 } |
| 1078 default: { | 1112 default: { |
| 1079 something_to_inline = false; | 1113 inline_op_with_constant_smi = false; |
| 1080 break; | 1114 break; |
| 1081 } | 1115 } |
| 1082 } | 1116 } |
| 1083 | 1117 |
| 1084 if (!something_to_inline) { | 1118 if (!inline_op_with_constant_smi) { |
| 1085 if (!reversed) { | 1119 if (!reversed) { |
| 1086 // Push the rhs onto the virtual frame by putting it in a TOS register. | 1120 // Push the rhs onto the virtual frame by putting it in a TOS register. |
| 1087 Register rhs = frame_->GetTOSRegister(); | 1121 Register rhs = frame_->GetTOSRegister(); |
| 1088 __ mov(rhs, Operand(value)); | 1122 __ mov(rhs, Operand(value)); |
| 1089 frame_->EmitPush(rhs, TypeInfo::Smi()); | 1123 frame_->EmitPush(rhs, TypeInfo::Smi()); |
| 1090 GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, int_value); | 1124 GenericBinaryOperation(op, mode, inline_generic_smi_code, int_value); |
| 1091 } else { | 1125 } else { |
| 1092 // Pop the rhs, then push lhs and rhs in the right order. Only performs | 1126 // Pop the rhs, then push lhs and rhs in the right order. Only performs |
| 1093 // at most one pop, the rest takes place in TOS registers. | 1127 // at most one pop, the rest takes place in TOS registers. |
| 1094 Register lhs = frame_->GetTOSRegister(); // Get reg for pushing. | 1128 Register lhs = frame_->GetTOSRegister(); // Get reg for pushing. |
| 1095 Register rhs = frame_->PopToRegister(lhs); // Don't use lhs for this. | 1129 Register rhs = frame_->PopToRegister(lhs); // Don't use lhs for this. |
| 1096 __ mov(lhs, Operand(value)); | 1130 __ mov(lhs, Operand(value)); |
| 1097 frame_->EmitPush(lhs, TypeInfo::Smi()); | 1131 frame_->EmitPush(lhs, TypeInfo::Smi()); |
| 1098 TypeInfo t = both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Unknown(); | 1132 TypeInfo t = both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Unknown(); |
| 1099 frame_->EmitPush(rhs, t); | 1133 frame_->EmitPush(rhs, t); |
| 1100 GenericBinaryOperation(op, mode, GENERATE_INLINE_SMI, kUnknownIntValue); | 1134 GenericBinaryOperation(op, mode, inline_generic_smi_code, kUnknownIntValue
); |
| 1101 } | 1135 } |
| 1102 return; | 1136 return; |
| 1103 } | 1137 } |
| 1104 | 1138 |
| 1105 // We move the top of stack to a register (normally no move is invoved). | 1139 // We move the top of stack to a register (normally no move is invoved). |
| 1106 Register tos = frame_->PopToRegister(); | 1140 Register tos = frame_->PopToRegister(); |
| 1107 switch (op) { | 1141 switch (op) { |
| 1108 case Token::ADD: { | 1142 case Token::ADD: { |
| 1109 DeferredCode* deferred = | 1143 DeferredCode* deferred = |
| 1110 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos); | 1144 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 __ and_(tos, tos, Operand(mask)); | 1330 __ and_(tos, tos, Operand(mask)); |
| 1297 deferred->BindExit(); | 1331 deferred->BindExit(); |
| 1298 // Mod of positive power of 2 Smi gives a Smi if the lhs is an integer. | 1332 // Mod of positive power of 2 Smi gives a Smi if the lhs is an integer. |
| 1299 frame_->EmitPush( | 1333 frame_->EmitPush( |
| 1300 tos, | 1334 tos, |
| 1301 both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Number()); | 1335 both_sides_are_smi ? TypeInfo::Smi() : TypeInfo::Number()); |
| 1302 break; | 1336 break; |
| 1303 } | 1337 } |
| 1304 | 1338 |
| 1305 case Token::MUL: { | 1339 case Token::MUL: { |
| 1306 ASSERT(IsEasyToMultiplyBy(int_value)); | 1340 ASSERT(int_value > 0); |
| 1341 |
| 1307 DeferredCode* deferred = | 1342 DeferredCode* deferred = |
| 1308 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos); | 1343 new DeferredInlineSmiOperation(op, int_value, reversed, mode, tos); |
| 1309 unsigned max_smi_that_wont_overflow = Smi::kMaxValue / int_value; | 1344 unsigned max_smi_that_wont_overflow = Smi::kMaxValue / int_value; |
| 1310 max_smi_that_wont_overflow <<= kSmiTagSize; | 1345 max_smi_that_wont_overflow <<= kSmiTagSize; |
| 1311 unsigned mask = 0x80000000u; | 1346 unsigned mask = 0x80000000u; |
| 1312 while ((mask & max_smi_that_wont_overflow) == 0) { | 1347 while ((mask & max_smi_that_wont_overflow) == 0) { |
| 1313 mask |= mask >> 1; | 1348 mask |= mask >> 1; |
| 1314 } | 1349 } |
| 1315 mask |= kSmiTagMask; | 1350 if (!both_sides_are_smi) mask |= kSmiTagMask; |
| 1316 // This does a single mask that checks for a too high value in a | 1351 // This does a single mask that checks for a too high value in a |
| 1317 // conservative way and for a non-Smi. It also filters out negative | 1352 // conservative way and for a non-Smi. It also filters out negative |
| 1318 // numbers, unfortunately, but since this code is inline we prefer | 1353 // numbers, unfortunately, but since this code is inline we prefer |
| 1319 // brevity to comprehensiveness. | 1354 // brevity to comprehensiveness. |
| 1320 __ tst(tos, Operand(mask)); | 1355 __ tst(tos, Operand(mask)); |
| 1321 deferred->Branch(ne); | 1356 deferred->Branch(ne); |
| 1322 MultiplyByKnownInt(masm_, tos, tos, int_value); | 1357 |
| 1358 if (IsEasyToMultiplyBy(int_value)) { |
| 1359 MultiplyByKnownInt(masm_, tos, tos, int_value); |
| 1360 } else { |
| 1361 Register high = VirtualFrame::scratch0(); |
| 1362 Register low = VirtualFrame::scratch1(); |
| 1363 __ mov(ip, Operand(int_value)); |
| 1364 // Multiplying a tagged with an untagged value gives a tagged |
| 1365 // result. |
| 1366 __ smull(tos, high, tos, ip); |
| 1367 // Remove double tag from answer and make its sign bit 0. |
| 1368 } |
| 1323 deferred->BindExit(); | 1369 deferred->BindExit(); |
| 1324 frame_->EmitPush(tos); | 1370 frame_->EmitPush(tos); |
| 1325 break; | 1371 break; |
| 1326 } | 1372 } |
| 1327 | 1373 |
| 1328 default: | 1374 default: |
| 1329 UNREACHABLE(); | 1375 UNREACHABLE(); |
| 1330 break; | 1376 break; |
| 1331 } | 1377 } |
| 1332 } | 1378 } |
| (...skipping 9584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10917 __ bind(&string_add_runtime); | 10963 __ bind(&string_add_runtime); |
| 10918 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10964 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 10919 } | 10965 } |
| 10920 | 10966 |
| 10921 | 10967 |
| 10922 #undef __ | 10968 #undef __ |
| 10923 | 10969 |
| 10924 } } // namespace v8::internal | 10970 } } // namespace v8::internal |
| 10925 | 10971 |
| 10926 #endif // V8_TARGET_ARCH_ARM | 10972 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |