| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 | 866 |
| 867 | 867 |
| 868 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 868 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 869 // Nothing to do. | 869 // Nothing to do. |
| 870 } | 870 } |
| 871 | 871 |
| 872 | 872 |
| 873 void LCodeGen::DoModI(LModI* instr) { | 873 void LCodeGen::DoModI(LModI* instr) { |
| 874 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 874 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 875 Register dividend = ToRegister(instr->InputAt(0)); | 875 Register dividend = ToRegister(instr->InputAt(0)); |
| 876 Register result = ToRegister(instr->result()); | |
| 877 | 876 |
| 878 int32_t divisor = | 877 int32_t divisor = |
| 879 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 878 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| 880 | 879 |
| 881 if (divisor < 0) divisor = -divisor; | 880 if (divisor < 0) divisor = -divisor; |
| 882 | 881 |
| 883 Label positive_dividend, done; | 882 Label positive_dividend, done; |
| 884 __ cmp(dividend, Operand(0)); | 883 __ cmp(dividend, Operand(0)); |
| 885 __ b(pl, &positive_dividend); | 884 __ b(pl, &positive_dividend); |
| 886 __ rsb(result, dividend, Operand(0)); | 885 __ rsb(dividend, dividend, Operand(0)); |
| 887 __ and_(dividend, result, Operand(divisor - 1), SetCC); | 886 __ and_(dividend, dividend, Operand(divisor - 1)); |
| 887 __ rsb(dividend, dividend, Operand(0), SetCC); |
| 888 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 888 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 889 DeoptimizeIf(eq, instr->environment()); | 889 __ b(ne, &done); |
| 890 DeoptimizeIf(al, instr->environment()); |
| 891 } else { |
| 892 __ b(&done); |
| 890 } | 893 } |
| 891 __ rsb(result, dividend, Operand(0)); | |
| 892 __ b(&done); | |
| 893 __ bind(&positive_dividend); | 894 __ bind(&positive_dividend); |
| 894 __ and_(result, dividend, Operand(divisor - 1)); | 895 __ and_(dividend, dividend, Operand(divisor - 1)); |
| 895 __ bind(&done); | 896 __ bind(&done); |
| 896 return; | 897 return; |
| 897 } | 898 } |
| 898 | 899 |
| 899 // These registers hold untagged 32 bit values. | 900 // These registers hold untagged 32 bit values. |
| 900 Register left = ToRegister(instr->InputAt(0)); | 901 Register left = ToRegister(instr->InputAt(0)); |
| 901 Register right = ToRegister(instr->InputAt(1)); | 902 Register right = ToRegister(instr->InputAt(1)); |
| 902 Register result = ToRegister(instr->result()); | 903 Register result = ToRegister(instr->result()); |
| 903 | 904 |
| 904 Register scratch = scratch0(); | 905 Register scratch = scratch0(); |
| 905 Register scratch2 = ToRegister(instr->TempAt(0)); | 906 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 906 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); | 907 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); |
| 907 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); | 908 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); |
| 908 DwVfpRegister quotient = double_scratch0(); | 909 DwVfpRegister quotient = double_scratch0(); |
| 909 | 910 |
| 911 ASSERT(result.is(left)); |
| 912 |
| 910 ASSERT(!dividend.is(divisor)); | 913 ASSERT(!dividend.is(divisor)); |
| 911 ASSERT(!dividend.is(quotient)); | 914 ASSERT(!dividend.is(quotient)); |
| 912 ASSERT(!divisor.is(quotient)); | 915 ASSERT(!divisor.is(quotient)); |
| 913 ASSERT(!scratch.is(left)); | 916 ASSERT(!scratch.is(left)); |
| 914 ASSERT(!scratch.is(right)); | 917 ASSERT(!scratch.is(right)); |
| 915 ASSERT(!scratch.is(result)); | 918 ASSERT(!scratch.is(result)); |
| 916 | 919 |
| 917 Label done, vfp_modulo, both_positive, right_negative; | 920 Label done, vfp_modulo, both_positive, right_negative; |
| 918 | 921 |
| 919 // Check for x % 0. | 922 // Check for x % 0. |
| 920 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 923 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 921 __ cmp(right, Operand(0)); | 924 __ cmp(right, Operand(0)); |
| 922 DeoptimizeIf(eq, instr->environment()); | 925 DeoptimizeIf(eq, instr->environment()); |
| 923 } | 926 } |
| 924 | 927 |
| 925 __ Move(result, left); | |
| 926 | |
| 927 // (0 % x) must yield 0 (if x is finite, which is the case here). | 928 // (0 % x) must yield 0 (if x is finite, which is the case here). |
| 928 __ cmp(left, Operand(0)); | 929 __ cmp(left, Operand(0)); |
| 929 __ b(eq, &done); | 930 __ b(eq, &done); |
| 930 // Preload right in a vfp register. | 931 // Preload right in a vfp register. |
| 931 __ vmov(divisor.low(), right); | 932 __ vmov(divisor.low(), right); |
| 932 __ b(lt, &vfp_modulo); | 933 __ b(lt, &vfp_modulo); |
| 933 | 934 |
| 934 __ cmp(left, Operand(right)); | 935 __ cmp(left, Operand(right)); |
| 935 __ b(lt, &done); | 936 __ b(lt, &done); |
| 936 | 937 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 __ CallStub(&stub); | 1113 __ CallStub(&stub); |
| 1113 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1114 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 1114 0, | 1115 0, |
| 1115 Safepoint::kNoDeoptimizationIndex); | 1116 Safepoint::kNoDeoptimizationIndex); |
| 1116 // Overwrite the stored value of r0 with the result of the stub. | 1117 // Overwrite the stored value of r0 with the result of the stub. |
| 1117 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1118 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
| 1118 } | 1119 } |
| 1119 | 1120 |
| 1120 | 1121 |
| 1121 void LCodeGen::DoMulI(LMulI* instr) { | 1122 void LCodeGen::DoMulI(LMulI* instr) { |
| 1123 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
| 1122 Register scratch = scratch0(); | 1124 Register scratch = scratch0(); |
| 1123 Register result = ToRegister(instr->result()); | 1125 Register result = ToRegister(instr->result()); |
| 1124 // Note that result may alias left. | |
| 1125 Register left = ToRegister(instr->InputAt(0)); | 1126 Register left = ToRegister(instr->InputAt(0)); |
| 1126 LOperand* right_op = instr->InputAt(1); | 1127 LOperand* right_op = instr->InputAt(1); |
| 1127 | 1128 |
| 1128 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1129 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1129 bool bailout_on_minus_zero = | 1130 bool bailout_on_minus_zero = |
| 1130 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1131 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1131 | 1132 |
| 1132 if (right_op->IsConstantOperand() && !can_overflow) { | 1133 if (right_op->IsConstantOperand() && !can_overflow) { |
| 1133 // Use optimized code for specific constants. | 1134 // Use optimized code for specific constants. |
| 1134 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1135 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1147 case 0: | 1148 case 0: |
| 1148 if (bailout_on_minus_zero) { | 1149 if (bailout_on_minus_zero) { |
| 1149 // If left is strictly negative and the constant is null, the | 1150 // If left is strictly negative and the constant is null, the |
| 1150 // result is -0. Deoptimize if required, otherwise return 0. | 1151 // result is -0. Deoptimize if required, otherwise return 0. |
| 1151 __ cmp(left, Operand(0)); | 1152 __ cmp(left, Operand(0)); |
| 1152 DeoptimizeIf(mi, instr->environment()); | 1153 DeoptimizeIf(mi, instr->environment()); |
| 1153 } | 1154 } |
| 1154 __ mov(result, Operand(0)); | 1155 __ mov(result, Operand(0)); |
| 1155 break; | 1156 break; |
| 1156 case 1: | 1157 case 1: |
| 1157 __ Move(result, left); | 1158 // Nothing to do. |
| 1158 break; | 1159 break; |
| 1159 default: | 1160 default: |
| 1160 // Multiplying by powers of two and powers of two plus or minus | 1161 // Multiplying by powers of two and powers of two plus or minus |
| 1161 // one can be done faster with shifted operands. | 1162 // one can be done faster with shifted operands. |
| 1162 // For other constants we emit standard code. | 1163 // For other constants we emit standard code. |
| 1163 int32_t mask = constant >> 31; | 1164 int32_t mask = constant >> 31; |
| 1164 uint32_t constant_abs = (constant + mask) ^ mask; | 1165 uint32_t constant_abs = (constant + mask) ^ mask; |
| 1165 | 1166 |
| 1166 if (IsPowerOf2(constant_abs) || | 1167 if (IsPowerOf2(constant_abs) || |
| 1167 IsPowerOf2(constant_abs - 1) || | 1168 IsPowerOf2(constant_abs - 1) || |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 __ b(ne, &done); | 1210 __ b(ne, &done); |
| 1210 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1211 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
| 1211 DeoptimizeIf(mi, instr->environment()); | 1212 DeoptimizeIf(mi, instr->environment()); |
| 1212 __ bind(&done); | 1213 __ bind(&done); |
| 1213 } | 1214 } |
| 1214 } | 1215 } |
| 1215 } | 1216 } |
| 1216 | 1217 |
| 1217 | 1218 |
| 1218 void LCodeGen::DoBitI(LBitI* instr) { | 1219 void LCodeGen::DoBitI(LBitI* instr) { |
| 1219 LOperand* left_op = instr->InputAt(0); | 1220 LOperand* left = instr->InputAt(0); |
| 1220 LOperand* right_op = instr->InputAt(1); | 1221 LOperand* right = instr->InputAt(1); |
| 1221 ASSERT(left_op->IsRegister()); | 1222 ASSERT(left->Equals(instr->result())); |
| 1222 Register left = ToRegister(left_op); | 1223 ASSERT(left->IsRegister()); |
| 1223 Register result = ToRegister(instr->result()); | 1224 Register result = ToRegister(left); |
| 1224 Operand right(no_reg); | 1225 Operand right_operand(no_reg); |
| 1225 | 1226 |
| 1226 if (right_op->IsStackSlot() || right_op->IsArgument()) { | 1227 if (right->IsStackSlot() || right->IsArgument()) { |
| 1227 right = Operand(EmitLoadRegister(right_op, ip)); | 1228 Register right_reg = EmitLoadRegister(right, ip); |
| 1229 right_operand = Operand(right_reg); |
| 1228 } else { | 1230 } else { |
| 1229 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); | 1231 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1230 right = ToOperand(right_op); | 1232 right_operand = ToOperand(right); |
| 1231 } | 1233 } |
| 1232 | 1234 |
| 1233 switch (instr->op()) { | 1235 switch (instr->op()) { |
| 1234 case Token::BIT_AND: | 1236 case Token::BIT_AND: |
| 1235 __ and_(result, left, right); | 1237 __ and_(result, ToRegister(left), right_operand); |
| 1236 break; | 1238 break; |
| 1237 case Token::BIT_OR: | 1239 case Token::BIT_OR: |
| 1238 __ orr(result, left, right); | 1240 __ orr(result, ToRegister(left), right_operand); |
| 1239 break; | 1241 break; |
| 1240 case Token::BIT_XOR: | 1242 case Token::BIT_XOR: |
| 1241 __ eor(result, left, right); | 1243 __ eor(result, ToRegister(left), right_operand); |
| 1242 break; | 1244 break; |
| 1243 default: | 1245 default: |
| 1244 UNREACHABLE(); | 1246 UNREACHABLE(); |
| 1245 break; | 1247 break; |
| 1246 } | 1248 } |
| 1247 } | 1249 } |
| 1248 | 1250 |
| 1249 | 1251 |
| 1250 void LCodeGen::DoShiftI(LShiftI* instr) { | 1252 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 1251 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so | |
| 1252 // result may alias either of them. | |
| 1253 LOperand* right_op = instr->InputAt(1); | |
| 1254 Register left = ToRegister(instr->InputAt(0)); | |
| 1255 Register result = ToRegister(instr->result()); | |
| 1256 Register scratch = scratch0(); | 1253 Register scratch = scratch0(); |
| 1257 if (right_op->IsRegister()) { | 1254 LOperand* left = instr->InputAt(0); |
| 1258 // Mask the right_op operand. | 1255 LOperand* right = instr->InputAt(1); |
| 1259 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); | 1256 ASSERT(left->Equals(instr->result())); |
| 1257 ASSERT(left->IsRegister()); |
| 1258 Register result = ToRegister(left); |
| 1259 if (right->IsRegister()) { |
| 1260 // Mask the right operand. |
| 1261 __ and_(scratch, ToRegister(right), Operand(0x1F)); |
| 1260 switch (instr->op()) { | 1262 switch (instr->op()) { |
| 1261 case Token::SAR: | 1263 case Token::SAR: |
| 1262 __ mov(result, Operand(left, ASR, scratch)); | 1264 __ mov(result, Operand(result, ASR, scratch)); |
| 1263 break; | 1265 break; |
| 1264 case Token::SHR: | 1266 case Token::SHR: |
| 1265 if (instr->can_deopt()) { | 1267 if (instr->can_deopt()) { |
| 1266 __ mov(result, Operand(left, LSR, scratch), SetCC); | 1268 __ mov(result, Operand(result, LSR, scratch), SetCC); |
| 1267 DeoptimizeIf(mi, instr->environment()); | 1269 DeoptimizeIf(mi, instr->environment()); |
| 1268 } else { | 1270 } else { |
| 1269 __ mov(result, Operand(left, LSR, scratch)); | 1271 __ mov(result, Operand(result, LSR, scratch)); |
| 1270 } | 1272 } |
| 1271 break; | 1273 break; |
| 1272 case Token::SHL: | 1274 case Token::SHL: |
| 1273 __ mov(result, Operand(left, LSL, scratch)); | 1275 __ mov(result, Operand(result, LSL, scratch)); |
| 1274 break; | 1276 break; |
| 1275 default: | 1277 default: |
| 1276 UNREACHABLE(); | 1278 UNREACHABLE(); |
| 1277 break; | 1279 break; |
| 1278 } | 1280 } |
| 1279 } else { | 1281 } else { |
| 1280 // Mask the right_op operand. | 1282 int value = ToInteger32(LConstantOperand::cast(right)); |
| 1281 int value = ToInteger32(LConstantOperand::cast(right_op)); | |
| 1282 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1283 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
| 1283 switch (instr->op()) { | 1284 switch (instr->op()) { |
| 1284 case Token::SAR: | 1285 case Token::SAR: |
| 1285 if (shift_count != 0) { | 1286 if (shift_count != 0) { |
| 1286 __ mov(result, Operand(left, ASR, shift_count)); | 1287 __ mov(result, Operand(result, ASR, shift_count)); |
| 1287 } else { | |
| 1288 __ Move(result, left); | |
| 1289 } | 1288 } |
| 1290 break; | 1289 break; |
| 1291 case Token::SHR: | 1290 case Token::SHR: |
| 1292 if (shift_count != 0) { | 1291 if (shift_count == 0 && instr->can_deopt()) { |
| 1293 __ mov(result, Operand(left, LSR, shift_count)); | 1292 __ tst(result, Operand(0x80000000)); |
| 1293 DeoptimizeIf(ne, instr->environment()); |
| 1294 } else { | 1294 } else { |
| 1295 if (instr->can_deopt()) { | 1295 __ mov(result, Operand(result, LSR, shift_count)); |
| 1296 __ tst(left, Operand(0x80000000)); | |
| 1297 DeoptimizeIf(ne, instr->environment()); | |
| 1298 } | |
| 1299 __ Move(result, left); | |
| 1300 } | 1296 } |
| 1301 break; | 1297 break; |
| 1302 case Token::SHL: | 1298 case Token::SHL: |
| 1303 if (shift_count != 0) { | 1299 if (shift_count != 0) { |
| 1304 __ mov(result, Operand(left, LSL, shift_count)); | 1300 __ mov(result, Operand(result, LSL, shift_count)); |
| 1305 } else { | |
| 1306 __ Move(result, left); | |
| 1307 } | 1301 } |
| 1308 break; | 1302 break; |
| 1309 default: | 1303 default: |
| 1310 UNREACHABLE(); | 1304 UNREACHABLE(); |
| 1311 break; | 1305 break; |
| 1312 } | 1306 } |
| 1313 } | 1307 } |
| 1314 } | 1308 } |
| 1315 | 1309 |
| 1316 | 1310 |
| 1317 void LCodeGen::DoSubI(LSubI* instr) { | 1311 void LCodeGen::DoSubI(LSubI* instr) { |
| 1318 LOperand* left = instr->InputAt(0); | 1312 LOperand* left = instr->InputAt(0); |
| 1319 LOperand* right = instr->InputAt(1); | 1313 LOperand* right = instr->InputAt(1); |
| 1320 LOperand* result = instr->result(); | 1314 ASSERT(left->Equals(instr->result())); |
| 1321 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1315 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1322 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1316 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
| 1323 | 1317 |
| 1324 if (right->IsStackSlot() || right->IsArgument()) { | 1318 if (right->IsStackSlot() || right->IsArgument()) { |
| 1325 Register right_reg = EmitLoadRegister(right, ip); | 1319 Register right_reg = EmitLoadRegister(right, ip); |
| 1326 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1320 __ sub(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); |
| 1327 } else { | 1321 } else { |
| 1328 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1322 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1329 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1323 __ sub(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); |
| 1330 } | 1324 } |
| 1331 | 1325 |
| 1332 if (can_overflow) { | 1326 if (can_overflow) { |
| 1333 DeoptimizeIf(vs, instr->environment()); | 1327 DeoptimizeIf(vs, instr->environment()); |
| 1334 } | 1328 } |
| 1335 } | 1329 } |
| 1336 | 1330 |
| 1337 | 1331 |
| 1338 void LCodeGen::DoConstantI(LConstantI* instr) { | 1332 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1339 ASSERT(instr->result()->IsRegister()); | 1333 ASSERT(instr->result()->IsRegister()); |
| 1340 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1334 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1341 } | 1335 } |
| 1342 | 1336 |
| 1343 | 1337 |
| 1344 void LCodeGen::DoConstantD(LConstantD* instr) { | 1338 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1345 ASSERT(instr->result()->IsDoubleRegister()); | 1339 ASSERT(instr->result()->IsDoubleRegister()); |
| 1346 DwVfpRegister result = ToDoubleRegister(instr->result()); | 1340 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 1347 double v = instr->value(); | 1341 double v = instr->value(); |
| 1348 __ Vmov(result, v); | 1342 __ vmov(result, v); |
| 1349 } | 1343 } |
| 1350 | 1344 |
| 1351 | 1345 |
| 1352 void LCodeGen::DoConstantT(LConstantT* instr) { | 1346 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1353 ASSERT(instr->result()->IsRegister()); | 1347 ASSERT(instr->result()->IsRegister()); |
| 1354 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1348 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1355 } | 1349 } |
| 1356 | 1350 |
| 1357 | 1351 |
| 1358 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1352 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1387 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | 1381 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); |
| 1388 // Retrieve elements_kind from bit field 2. | 1382 // Retrieve elements_kind from bit field 2. |
| 1389 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | 1383 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); |
| 1390 } | 1384 } |
| 1391 | 1385 |
| 1392 | 1386 |
| 1393 void LCodeGen::DoValueOf(LValueOf* instr) { | 1387 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1394 Register input = ToRegister(instr->InputAt(0)); | 1388 Register input = ToRegister(instr->InputAt(0)); |
| 1395 Register result = ToRegister(instr->result()); | 1389 Register result = ToRegister(instr->result()); |
| 1396 Register map = ToRegister(instr->TempAt(0)); | 1390 Register map = ToRegister(instr->TempAt(0)); |
| 1391 ASSERT(input.is(result)); |
| 1397 Label done; | 1392 Label done; |
| 1398 | 1393 |
| 1399 // If the object is a smi return the object. | 1394 // If the object is a smi return the object. |
| 1400 __ tst(input, Operand(kSmiTagMask)); | 1395 __ JumpIfSmi(input, &done); |
| 1401 __ Move(result, input, eq); | |
| 1402 __ b(eq, &done); | |
| 1403 | 1396 |
| 1404 // If the object is not a value type, return the object. | 1397 // If the object is not a value type, return the object. |
| 1405 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1398 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
| 1406 __ Move(result, input, ne); | |
| 1407 __ b(ne, &done); | 1399 __ b(ne, &done); |
| 1408 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1400 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
| 1409 | 1401 |
| 1410 __ bind(&done); | 1402 __ bind(&done); |
| 1411 } | 1403 } |
| 1412 | 1404 |
| 1413 | 1405 |
| 1414 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1406 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1415 Register input = ToRegister(instr->InputAt(0)); | 1407 LOperand* input = instr->InputAt(0); |
| 1416 Register result = ToRegister(instr->result()); | 1408 ASSERT(input->Equals(instr->result())); |
| 1417 __ mvn(result, Operand(input)); | 1409 __ mvn(ToRegister(input), Operand(ToRegister(input))); |
| 1418 } | 1410 } |
| 1419 | 1411 |
| 1420 | 1412 |
| 1421 void LCodeGen::DoThrow(LThrow* instr) { | 1413 void LCodeGen::DoThrow(LThrow* instr) { |
| 1422 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 1414 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); |
| 1423 __ push(input_reg); | 1415 __ push(input_reg); |
| 1424 CallRuntime(Runtime::kThrow, 1, instr); | 1416 CallRuntime(Runtime::kThrow, 1, instr); |
| 1425 | 1417 |
| 1426 if (FLAG_debug_code) { | 1418 if (FLAG_debug_code) { |
| 1427 __ stop("Unreachable code."); | 1419 __ stop("Unreachable code."); |
| 1428 } | 1420 } |
| 1429 } | 1421 } |
| 1430 | 1422 |
| 1431 | 1423 |
| 1432 void LCodeGen::DoAddI(LAddI* instr) { | 1424 void LCodeGen::DoAddI(LAddI* instr) { |
| 1433 LOperand* left = instr->InputAt(0); | 1425 LOperand* left = instr->InputAt(0); |
| 1434 LOperand* right = instr->InputAt(1); | 1426 LOperand* right = instr->InputAt(1); |
| 1435 LOperand* result = instr->result(); | 1427 ASSERT(left->Equals(instr->result())); |
| 1436 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1428 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1437 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1429 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
| 1438 | 1430 |
| 1439 if (right->IsStackSlot() || right->IsArgument()) { | 1431 if (right->IsStackSlot() || right->IsArgument()) { |
| 1440 Register right_reg = EmitLoadRegister(right, ip); | 1432 Register right_reg = EmitLoadRegister(right, ip); |
| 1441 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1433 __ add(ToRegister(left), ToRegister(left), Operand(right_reg), set_cond); |
| 1442 } else { | 1434 } else { |
| 1443 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1435 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
| 1444 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1436 __ add(ToRegister(left), ToRegister(left), ToOperand(right), set_cond); |
| 1445 } | 1437 } |
| 1446 | 1438 |
| 1447 if (can_overflow) { | 1439 if (can_overflow) { |
| 1448 DeoptimizeIf(vs, instr->environment()); | 1440 DeoptimizeIf(vs, instr->environment()); |
| 1449 } | 1441 } |
| 1450 } | 1442 } |
| 1451 | 1443 |
| 1452 | 1444 |
| 1453 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1445 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1454 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); | 1446 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); |
| 1455 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); | 1447 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); |
| 1456 DoubleRegister result = ToDoubleRegister(instr->result()); | |
| 1457 switch (instr->op()) { | 1448 switch (instr->op()) { |
| 1458 case Token::ADD: | 1449 case Token::ADD: |
| 1459 __ vadd(result, left, right); | 1450 __ vadd(left, left, right); |
| 1460 break; | 1451 break; |
| 1461 case Token::SUB: | 1452 case Token::SUB: |
| 1462 __ vsub(result, left, right); | 1453 __ vsub(left, left, right); |
| 1463 break; | 1454 break; |
| 1464 case Token::MUL: | 1455 case Token::MUL: |
| 1465 __ vmul(result, left, right); | 1456 __ vmul(left, left, right); |
| 1466 break; | 1457 break; |
| 1467 case Token::DIV: | 1458 case Token::DIV: |
| 1468 __ vdiv(result, left, right); | 1459 __ vdiv(left, left, right); |
| 1469 break; | 1460 break; |
| 1470 case Token::MOD: { | 1461 case Token::MOD: { |
| 1471 // Save r0-r3 on the stack. | 1462 // Save r0-r3 on the stack. |
| 1472 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1463 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
| 1473 | 1464 |
| 1474 __ PrepareCallCFunction(0, 2, scratch0()); | 1465 __ PrepareCallCFunction(0, 2, scratch0()); |
| 1475 __ SetCallCDoubleArguments(left, right); | 1466 __ SetCallCDoubleArguments(left, right); |
| 1476 __ CallCFunction( | 1467 __ CallCFunction( |
| 1477 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 1468 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
| 1478 0, 2); | 1469 0, 2); |
| 1479 // Move the result in the double result register. | 1470 // Move the result in the double result register. |
| 1480 __ GetCFunctionDoubleResult(result); | 1471 __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result())); |
| 1481 | 1472 |
| 1482 // Restore r0-r3. | 1473 // Restore r0-r3. |
| 1483 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 1474 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
| 1484 break; | 1475 break; |
| 1485 } | 1476 } |
| 1486 default: | 1477 default: |
| 1487 UNREACHABLE(); | 1478 UNREACHABLE(); |
| 1488 break; | 1479 break; |
| 1489 } | 1480 } |
| 1490 } | 1481 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1563 __ b(eq, true_label); | 1554 __ b(eq, true_label); |
| 1564 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 1555 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 1565 __ cmp(reg, ip); | 1556 __ cmp(reg, ip); |
| 1566 __ b(eq, false_label); | 1557 __ b(eq, false_label); |
| 1567 __ cmp(reg, Operand(0)); | 1558 __ cmp(reg, Operand(0)); |
| 1568 __ b(eq, false_label); | 1559 __ b(eq, false_label); |
| 1569 __ JumpIfSmi(reg, true_label); | 1560 __ JumpIfSmi(reg, true_label); |
| 1570 | 1561 |
| 1571 // Test double values. Zero and NaN are false. | 1562 // Test double values. Zero and NaN are false. |
| 1572 Label call_stub; | 1563 Label call_stub; |
| 1573 DoubleRegister dbl_scratch = double_scratch0(); | 1564 DoubleRegister dbl_scratch = d0; |
| 1574 Register scratch = scratch0(); | 1565 Register scratch = scratch0(); |
| 1575 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); | 1566 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 1576 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 1567 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 1577 __ cmp(scratch, Operand(ip)); | 1568 __ cmp(scratch, Operand(ip)); |
| 1578 __ b(ne, &call_stub); | 1569 __ b(ne, &call_stub); |
| 1579 __ sub(ip, reg, Operand(kHeapObjectTag)); | 1570 __ sub(ip, reg, Operand(kHeapObjectTag)); |
| 1580 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); | 1571 __ vldr(dbl_scratch, ip, HeapNumber::kValueOffset); |
| 1581 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); | 1572 __ VFPCompareAndLoadFlags(dbl_scratch, 0.0, scratch); |
| 1582 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1573 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
| 1583 __ b(ne, false_label); | 1574 __ b(ne, false_label); |
| (...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2609 __ add(length, length, Operand(1)); | 2600 __ add(length, length, Operand(1)); |
| 2610 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | 2601 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
| 2611 } | 2602 } |
| 2612 | 2603 |
| 2613 | 2604 |
| 2614 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2605 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
| 2615 Register elements = ToRegister(instr->elements()); | 2606 Register elements = ToRegister(instr->elements()); |
| 2616 Register key = EmitLoadRegister(instr->key(), scratch0()); | 2607 Register key = EmitLoadRegister(instr->key(), scratch0()); |
| 2617 Register result = ToRegister(instr->result()); | 2608 Register result = ToRegister(instr->result()); |
| 2618 Register scratch = scratch0(); | 2609 Register scratch = scratch0(); |
| 2610 ASSERT(result.is(elements)); |
| 2619 | 2611 |
| 2620 // Load the result. | 2612 // Load the result. |
| 2621 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 2613 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
| 2622 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 2614 __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
| 2623 | 2615 |
| 2624 // Check for the hole value. | 2616 // Check for the hole value. |
| 2625 if (instr->hydrogen()->RequiresHoleCheck()) { | 2617 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2626 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2618 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 2627 __ cmp(result, scratch); | 2619 __ cmp(result, scratch); |
| 2628 DeoptimizeIf(eq, instr->environment()); | 2620 DeoptimizeIf(eq, instr->environment()); |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2928 ASSERT(ToRegister(instr->result()).is(r0)); | 2920 ASSERT(ToRegister(instr->result()).is(r0)); |
| 2929 __ mov(r1, Operand(instr->function())); | 2921 __ mov(r1, Operand(instr->function())); |
| 2930 CallKnownFunction(instr->function(), | 2922 CallKnownFunction(instr->function(), |
| 2931 instr->arity(), | 2923 instr->arity(), |
| 2932 instr, | 2924 instr, |
| 2933 CALL_AS_METHOD); | 2925 CALL_AS_METHOD); |
| 2934 } | 2926 } |
| 2935 | 2927 |
| 2936 | 2928 |
| 2937 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2929 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2930 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2938 Register input = ToRegister(instr->InputAt(0)); | 2931 Register input = ToRegister(instr->InputAt(0)); |
| 2939 Register result = ToRegister(instr->result()); | |
| 2940 Register scratch = scratch0(); | 2932 Register scratch = scratch0(); |
| 2941 | 2933 |
| 2942 // Deoptimize if not a heap number. | 2934 // Deoptimize if not a heap number. |
| 2943 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 2935 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 2944 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 2936 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 2945 __ cmp(scratch, Operand(ip)); | 2937 __ cmp(scratch, Operand(ip)); |
| 2946 DeoptimizeIf(ne, instr->environment()); | 2938 DeoptimizeIf(ne, instr->environment()); |
| 2947 | 2939 |
| 2948 Label done; | 2940 Label done; |
| 2949 Register exponent = scratch0(); | 2941 Register exponent = scratch0(); |
| 2950 scratch = no_reg; | 2942 scratch = no_reg; |
| 2951 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2943 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2952 // Check the sign of the argument. If the argument is positive, just | 2944 // Check the sign of the argument. If the argument is positive, just |
| 2953 // return it. | 2945 // return it. We do not need to patch the stack since |input| and |
| 2946 // |result| are the same register and |input| would be restored |
| 2947 // unchanged by popping safepoint registers. |
| 2954 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 2948 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
| 2955 // Move the input to the result if necessary. | |
| 2956 __ Move(result, input); | |
| 2957 __ b(eq, &done); | 2949 __ b(eq, &done); |
| 2958 | 2950 |
| 2959 // Input is negative. Reverse its sign. | 2951 // Input is negative. Reverse its sign. |
| 2960 // Preserve the value of all registers. | 2952 // Preserve the value of all registers. |
| 2961 { | 2953 { |
| 2962 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2954 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 2963 | 2955 |
| 2964 // Registers were saved at the safepoint, so we can use | 2956 // Registers were saved at the safepoint, so we can use |
| 2965 // many scratch registers. | 2957 // many scratch registers. |
| 2966 Register tmp1 = input.is(r1) ? r0 : r1; | 2958 Register tmp1 = input.is(r1) ? r0 : r1; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2986 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 2978 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 2987 | 2979 |
| 2988 __ bind(&allocated); | 2980 __ bind(&allocated); |
| 2989 // exponent: floating point exponent value. | 2981 // exponent: floating point exponent value. |
| 2990 // tmp1: allocated heap number. | 2982 // tmp1: allocated heap number. |
| 2991 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); | 2983 __ bic(exponent, exponent, Operand(HeapNumber::kSignMask)); |
| 2992 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); | 2984 __ str(exponent, FieldMemOperand(tmp1, HeapNumber::kExponentOffset)); |
| 2993 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); | 2985 __ ldr(tmp2, FieldMemOperand(input, HeapNumber::kMantissaOffset)); |
| 2994 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 2986 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
| 2995 | 2987 |
| 2996 __ StoreToSafepointRegisterSlot(tmp1, result); | 2988 __ StoreToSafepointRegisterSlot(tmp1, input); |
| 2997 } | 2989 } |
| 2998 | 2990 |
| 2999 __ bind(&done); | 2991 __ bind(&done); |
| 3000 } | 2992 } |
| 3001 | 2993 |
| 3002 | 2994 |
| 3003 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 2995 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 3004 Register input = ToRegister(instr->InputAt(0)); | 2996 Register input = ToRegister(instr->InputAt(0)); |
| 3005 Register result = ToRegister(instr->result()); | |
| 3006 __ cmp(input, Operand(0)); | 2997 __ cmp(input, Operand(0)); |
| 3007 __ Move(result, input, pl); | |
| 3008 // We can make rsb conditional because the previous cmp instruction | 2998 // We can make rsb conditional because the previous cmp instruction |
| 3009 // will clear the V (overflow) flag and rsb won't set this flag | 2999 // will clear the V (overflow) flag and rsb won't set this flag |
| 3010 // if input is positive. | 3000 // if input is positive. |
| 3011 __ rsb(result, input, Operand(0), SetCC, mi); | 3001 __ rsb(input, input, Operand(0), SetCC, mi); |
| 3012 // Deoptimize on overflow. | 3002 // Deoptimize on overflow. |
| 3013 DeoptimizeIf(vs, instr->environment()); | 3003 DeoptimizeIf(vs, instr->environment()); |
| 3014 } | 3004 } |
| 3015 | 3005 |
| 3016 | 3006 |
| 3017 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3007 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 3018 // Class for deferred case. | 3008 // Class for deferred case. |
| 3019 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3009 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 3020 public: | 3010 public: |
| 3021 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3011 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 3022 LUnaryMathOperation* instr) | 3012 LUnaryMathOperation* instr) |
| 3023 : LDeferredCode(codegen), instr_(instr) { } | 3013 : LDeferredCode(codegen), instr_(instr) { } |
| 3024 virtual void Generate() { | 3014 virtual void Generate() { |
| 3025 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3015 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3026 } | 3016 } |
| 3027 private: | 3017 private: |
| 3028 LUnaryMathOperation* instr_; | 3018 LUnaryMathOperation* instr_; |
| 3029 }; | 3019 }; |
| 3030 | 3020 |
| 3021 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 3031 Representation r = instr->hydrogen()->value()->representation(); | 3022 Representation r = instr->hydrogen()->value()->representation(); |
| 3032 if (r.IsDouble()) { | 3023 if (r.IsDouble()) { |
| 3033 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); | 3024 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3034 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3025 __ vabs(input, input); |
| 3035 __ vabs(result, input); | |
| 3036 } else if (r.IsInteger32()) { | 3026 } else if (r.IsInteger32()) { |
| 3037 EmitIntegerMathAbs(instr); | 3027 EmitIntegerMathAbs(instr); |
| 3038 } else { | 3028 } else { |
| 3039 // Representation is tagged. | 3029 // Representation is tagged. |
| 3040 DeferredMathAbsTaggedHeapNumber* deferred = | 3030 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3041 new DeferredMathAbsTaggedHeapNumber(this, instr); | 3031 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3042 Register input = ToRegister(instr->InputAt(0)); | 3032 Register input = ToRegister(instr->InputAt(0)); |
| 3043 // Smi check. | 3033 // Smi check. |
| 3044 __ JumpIfNotSmi(input, deferred->entry()); | 3034 __ JumpIfNotSmi(input, deferred->entry()); |
| 3045 // If smi, handle it directly. | 3035 // If smi, handle it directly. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3103 } | 3093 } |
| 3104 | 3094 |
| 3105 // The following conversion will not work with numbers | 3095 // The following conversion will not work with numbers |
| 3106 // outside of ]-2^32, 2^32[. | 3096 // outside of ]-2^32, 2^32[. |
| 3107 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); | 3097 __ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32)); |
| 3108 DeoptimizeIf(ge, instr->environment()); | 3098 DeoptimizeIf(ge, instr->environment()); |
| 3109 | 3099 |
| 3110 // Save the original sign for later comparison. | 3100 // Save the original sign for later comparison. |
| 3111 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); | 3101 __ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask)); |
| 3112 | 3102 |
| 3113 __ Vmov(double_scratch0(), 0.5); | 3103 __ vmov(double_scratch0(), 0.5); |
| 3114 __ vadd(input, input, double_scratch0()); | 3104 __ vadd(input, input, double_scratch0()); |
| 3115 | 3105 |
| 3116 // Check sign of the result: if the sign changed, the input | 3106 // Check sign of the result: if the sign changed, the input |
| 3117 // value was in ]0.5, 0[ and the result should be -0. | 3107 // value was in ]0.5, 0[ and the result should be -0. |
| 3118 __ vmov(scratch1, input.high()); | 3108 __ vmov(scratch1, input.high()); |
| 3119 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); | 3109 __ eor(scratch1, scratch1, Operand(scratch2), SetCC); |
| 3120 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3110 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3121 DeoptimizeIf(mi, instr->environment()); | 3111 DeoptimizeIf(mi, instr->environment()); |
| 3122 } else { | 3112 } else { |
| 3123 __ mov(result, Operand(0), LeaveCC, mi); | 3113 __ mov(result, Operand(0), LeaveCC, mi); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3140 __ vmov(scratch1, input.high()); | 3130 __ vmov(scratch1, input.high()); |
| 3141 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3131 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| 3142 DeoptimizeIf(ne, instr->environment()); | 3132 DeoptimizeIf(ne, instr->environment()); |
| 3143 } | 3133 } |
| 3144 __ bind(&done); | 3134 __ bind(&done); |
| 3145 } | 3135 } |
| 3146 | 3136 |
| 3147 | 3137 |
| 3148 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3138 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 3149 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3139 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3150 DoubleRegister result = ToDoubleRegister(instr->result()); | 3140 ASSERT(ToDoubleRegister(instr->result()).is(input)); |
| 3151 __ vsqrt(result, input); | 3141 __ vsqrt(input, input); |
| 3152 } | 3142 } |
| 3153 | 3143 |
| 3154 | 3144 |
| 3155 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3145 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 3156 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3146 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); |
| 3157 DoubleRegister result = ToDoubleRegister(instr->result()); | 3147 Register scratch = scratch0(); |
| 3148 SwVfpRegister single_scratch = double_scratch0().low(); |
| 3149 DoubleRegister double_scratch = double_scratch0(); |
| 3150 ASSERT(ToDoubleRegister(instr->result()).is(input)); |
| 3151 |
| 3158 // Add +0 to convert -0 to +0. | 3152 // Add +0 to convert -0 to +0. |
| 3159 __ vadd(result, input, kDoubleRegZero); | 3153 __ mov(scratch, Operand(0)); |
| 3160 __ vsqrt(result, result); | 3154 __ vmov(single_scratch, scratch); |
| 3155 __ vcvt_f64_s32(double_scratch, single_scratch); |
| 3156 __ vadd(input, input, double_scratch); |
| 3157 __ vsqrt(input, input); |
| 3161 } | 3158 } |
| 3162 | 3159 |
| 3163 | 3160 |
| 3164 void LCodeGen::DoPower(LPower* instr) { | 3161 void LCodeGen::DoPower(LPower* instr) { |
| 3165 LOperand* left = instr->InputAt(0); | 3162 LOperand* left = instr->InputAt(0); |
| 3166 LOperand* right = instr->InputAt(1); | 3163 LOperand* right = instr->InputAt(1); |
| 3167 Register scratch = scratch0(); | 3164 Register scratch = scratch0(); |
| 3168 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 3165 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
| 3169 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3166 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 3170 if (exponent_type.IsDouble()) { | 3167 if (exponent_type.IsDouble()) { |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3749 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 3746 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
| 3750 __ SmiTag(reg, SetCC); | 3747 __ SmiTag(reg, SetCC); |
| 3751 __ b(vs, deferred->entry()); | 3748 __ b(vs, deferred->entry()); |
| 3752 __ bind(deferred->exit()); | 3749 __ bind(deferred->exit()); |
| 3753 } | 3750 } |
| 3754 | 3751 |
| 3755 | 3752 |
| 3756 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 3753 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 3757 Label slow; | 3754 Label slow; |
| 3758 Register reg = ToRegister(instr->InputAt(0)); | 3755 Register reg = ToRegister(instr->InputAt(0)); |
| 3759 DoubleRegister dbl_scratch = double_scratch0(); | 3756 DoubleRegister dbl_scratch = d0; |
| 3760 SwVfpRegister flt_scratch = dbl_scratch.low(); | 3757 SwVfpRegister flt_scratch = s0; |
| 3761 | 3758 |
| 3762 // Preserve the value of all registers. | 3759 // Preserve the value of all registers. |
| 3763 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 3760 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
| 3764 | 3761 |
| 3765 // There was overflow, so bits 30 and 31 of the original integer | 3762 // There was overflow, so bits 30 and 31 of the original integer |
| 3766 // disagree. Try to allocate a heap number in new space and store | 3763 // disagree. Try to allocate a heap number in new space and store |
| 3767 // the value in there. If that fails, call the runtime system. | 3764 // the value in there. If that fails, call the runtime system. |
| 3768 Label done; | 3765 Label done; |
| 3769 __ SmiUntag(reg); | 3766 __ SmiUntag(reg); |
| 3770 __ eor(reg, reg, Operand(0x80000000)); | 3767 __ eor(reg, reg, Operand(0x80000000)); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3859 __ SmiUntag(ToRegister(input)); | 3856 __ SmiUntag(ToRegister(input)); |
| 3860 } | 3857 } |
| 3861 } | 3858 } |
| 3862 | 3859 |
| 3863 | 3860 |
| 3864 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3861 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 3865 DoubleRegister result_reg, | 3862 DoubleRegister result_reg, |
| 3866 bool deoptimize_on_undefined, | 3863 bool deoptimize_on_undefined, |
| 3867 LEnvironment* env) { | 3864 LEnvironment* env) { |
| 3868 Register scratch = scratch0(); | 3865 Register scratch = scratch0(); |
| 3869 SwVfpRegister flt_scratch = double_scratch0().low(); | 3866 SwVfpRegister flt_scratch = s0; |
| 3870 ASSERT(!result_reg.is(double_scratch0())); | 3867 ASSERT(!result_reg.is(d0)); |
| 3871 | 3868 |
| 3872 Label load_smi, heap_number, done; | 3869 Label load_smi, heap_number, done; |
| 3873 | 3870 |
| 3874 // Smi check. | 3871 // Smi check. |
| 3875 __ JumpIfSmi(input_reg, &load_smi); | 3872 __ JumpIfSmi(input_reg, &load_smi); |
| 3876 | 3873 |
| 3877 // Heap number map check. | 3874 // Heap number map check. |
| 3878 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3875 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 3879 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3876 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3880 __ cmp(scratch, Operand(ip)); | 3877 __ cmp(scratch, Operand(ip)); |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4605 ASSERT(osr_pc_offset_ == -1); | 4602 ASSERT(osr_pc_offset_ == -1); |
| 4606 osr_pc_offset_ = masm()->pc_offset(); | 4603 osr_pc_offset_ = masm()->pc_offset(); |
| 4607 } | 4604 } |
| 4608 | 4605 |
| 4609 | 4606 |
| 4610 | 4607 |
| 4611 | 4608 |
| 4612 #undef __ | 4609 #undef __ |
| 4613 | 4610 |
| 4614 } } // namespace v8::internal | 4611 } } // namespace v8::internal |
| OLD | NEW |