OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 } | 944 } |
945 | 945 |
946 | 946 |
947 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 947 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
948 // Nothing to do. | 948 // Nothing to do. |
949 } | 949 } |
950 | 950 |
951 | 951 |
952 void LCodeGen::DoModI(LModI* instr) { | 952 void LCodeGen::DoModI(LModI* instr) { |
953 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 953 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
954 Register dividend = ToRegister(instr->InputAt(0)); | 954 Register dividend = ToRegister(instr->left()); |
955 Register result = ToRegister(instr->result()); | 955 Register result = ToRegister(instr->result()); |
956 | 956 |
957 int32_t divisor = | 957 int32_t divisor = |
958 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); | 958 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
959 | 959 |
960 if (divisor < 0) divisor = -divisor; | 960 if (divisor < 0) divisor = -divisor; |
961 | 961 |
962 Label positive_dividend, done; | 962 Label positive_dividend, done; |
963 __ cmp(dividend, Operand(0)); | 963 __ cmp(dividend, Operand(0)); |
964 __ b(pl, &positive_dividend); | 964 __ b(pl, &positive_dividend); |
965 __ rsb(result, dividend, Operand(0)); | 965 __ rsb(result, dividend, Operand(0)); |
966 __ and_(result, result, Operand(divisor - 1), SetCC); | 966 __ and_(result, result, Operand(divisor - 1), SetCC); |
967 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 967 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
968 DeoptimizeIf(eq, instr->environment()); | 968 DeoptimizeIf(eq, instr->environment()); |
969 } | 969 } |
970 __ rsb(result, result, Operand(0)); | 970 __ rsb(result, result, Operand(0)); |
971 __ b(&done); | 971 __ b(&done); |
972 __ bind(&positive_dividend); | 972 __ bind(&positive_dividend); |
973 __ and_(result, dividend, Operand(divisor - 1)); | 973 __ and_(result, dividend, Operand(divisor - 1)); |
974 __ bind(&done); | 974 __ bind(&done); |
975 return; | 975 return; |
976 } | 976 } |
977 | 977 |
978 // These registers hold untagged 32 bit values. | 978 // These registers hold untagged 32 bit values. |
979 Register left = ToRegister(instr->InputAt(0)); | 979 Register left = ToRegister(instr->left()); |
980 Register right = ToRegister(instr->InputAt(1)); | 980 Register right = ToRegister(instr->right()); |
981 Register result = ToRegister(instr->result()); | 981 Register result = ToRegister(instr->result()); |
982 | 982 |
983 Register scratch = scratch0(); | 983 Register scratch = scratch0(); |
984 Register scratch2 = ToRegister(instr->TempAt(0)); | 984 Register scratch2 = ToRegister(instr->temp()); |
985 DwVfpRegister dividend = ToDoubleRegister(instr->TempAt(1)); | 985 DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); |
986 DwVfpRegister divisor = ToDoubleRegister(instr->TempAt(2)); | 986 DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); |
987 DwVfpRegister quotient = double_scratch0(); | 987 DwVfpRegister quotient = double_scratch0(); |
988 | 988 |
989 ASSERT(!dividend.is(divisor)); | 989 ASSERT(!dividend.is(divisor)); |
990 ASSERT(!dividend.is(quotient)); | 990 ASSERT(!dividend.is(quotient)); |
991 ASSERT(!divisor.is(quotient)); | 991 ASSERT(!divisor.is(quotient)); |
992 ASSERT(!scratch.is(left)); | 992 ASSERT(!scratch.is(left)); |
993 ASSERT(!scratch.is(right)); | 993 ASSERT(!scratch.is(right)); |
994 ASSERT(!scratch.is(result)); | 994 ASSERT(!scratch.is(result)); |
995 | 995 |
996 Label done, vfp_modulo, both_positive, right_negative; | 996 Label done, vfp_modulo, both_positive, right_negative; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 } | 1179 } |
1180 } | 1180 } |
1181 | 1181 |
1182 | 1182 |
1183 void LCodeGen::DoDivI(LDivI* instr) { | 1183 void LCodeGen::DoDivI(LDivI* instr) { |
1184 class DeferredDivI: public LDeferredCode { | 1184 class DeferredDivI: public LDeferredCode { |
1185 public: | 1185 public: |
1186 DeferredDivI(LCodeGen* codegen, LDivI* instr) | 1186 DeferredDivI(LCodeGen* codegen, LDivI* instr) |
1187 : LDeferredCode(codegen), instr_(instr) { } | 1187 : LDeferredCode(codegen), instr_(instr) { } |
1188 virtual void Generate() { | 1188 virtual void Generate() { |
1189 codegen()->DoDeferredBinaryOpStub(instr_, Token::DIV); | 1189 codegen()->DoDeferredBinaryOpStub(instr_->pointer_map(), |
| 1190 instr_->left(), |
| 1191 instr_->right(), |
| 1192 Token::DIV); |
1190 } | 1193 } |
1191 virtual LInstruction* instr() { return instr_; } | 1194 virtual LInstruction* instr() { return instr_; } |
1192 private: | 1195 private: |
1193 LDivI* instr_; | 1196 LDivI* instr_; |
1194 }; | 1197 }; |
1195 | 1198 |
1196 const Register left = ToRegister(instr->InputAt(0)); | 1199 const Register left = ToRegister(instr->left()); |
1197 const Register right = ToRegister(instr->InputAt(1)); | 1200 const Register right = ToRegister(instr->right()); |
1198 const Register scratch = scratch0(); | 1201 const Register scratch = scratch0(); |
1199 const Register result = ToRegister(instr->result()); | 1202 const Register result = ToRegister(instr->result()); |
1200 | 1203 |
1201 // Check for x / 0. | 1204 // Check for x / 0. |
1202 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1205 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
1203 __ cmp(right, Operand(0)); | 1206 __ cmp(right, Operand(0)); |
1204 DeoptimizeIf(eq, instr->environment()); | 1207 DeoptimizeIf(eq, instr->environment()); |
1205 } | 1208 } |
1206 | 1209 |
1207 // Check for (0 / -x) that will produce negative zero. | 1210 // Check for (0 / -x) that will produce negative zero. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1256 __ b(&done); | 1259 __ b(&done); |
1257 | 1260 |
1258 __ bind(&deoptimize); | 1261 __ bind(&deoptimize); |
1259 DeoptimizeIf(al, instr->environment()); | 1262 DeoptimizeIf(al, instr->environment()); |
1260 __ bind(&done); | 1263 __ bind(&done); |
1261 } | 1264 } |
1262 | 1265 |
1263 | 1266 |
1264 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { | 1267 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
1265 const Register result = ToRegister(instr->result()); | 1268 const Register result = ToRegister(instr->result()); |
1266 const Register left = ToRegister(instr->InputAt(0)); | 1269 const Register left = ToRegister(instr->left()); |
1267 const Register remainder = ToRegister(instr->TempAt(0)); | 1270 const Register remainder = ToRegister(instr->temp()); |
1268 const Register scratch = scratch0(); | 1271 const Register scratch = scratch0(); |
1269 | 1272 |
1270 // We only optimize this for division by constants, because the standard | 1273 // We only optimize this for division by constants, because the standard |
1271 // integer division routine is usually slower than transitionning to VFP. | 1274 // integer division routine is usually slower than transitionning to VFP. |
1272 // This could be optimized on processors with SDIV available. | 1275 // This could be optimized on processors with SDIV available. |
1273 ASSERT(instr->InputAt(1)->IsConstantOperand()); | 1276 ASSERT(instr->right()->IsConstantOperand()); |
1274 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->InputAt(1))); | 1277 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
1275 if (divisor < 0) { | 1278 if (divisor < 0) { |
1276 __ cmp(left, Operand(0)); | 1279 __ cmp(left, Operand(0)); |
1277 DeoptimizeIf(eq, instr->environment()); | 1280 DeoptimizeIf(eq, instr->environment()); |
1278 } | 1281 } |
1279 EmitSignedIntegerDivisionByConstant(result, | 1282 EmitSignedIntegerDivisionByConstant(result, |
1280 left, | 1283 left, |
1281 divisor, | 1284 divisor, |
1282 remainder, | 1285 remainder, |
1283 scratch, | 1286 scratch, |
1284 instr->environment()); | 1287 instr->environment()); |
1285 // We operated a truncating division. Correct the result if necessary. | 1288 // We operated a truncating division. Correct the result if necessary. |
1286 __ cmp(remainder, Operand(0)); | 1289 __ cmp(remainder, Operand(0)); |
1287 __ teq(remainder, Operand(divisor), ne); | 1290 __ teq(remainder, Operand(divisor), ne); |
1288 __ sub(result, result, Operand(1), LeaveCC, mi); | 1291 __ sub(result, result, Operand(1), LeaveCC, mi); |
1289 } | 1292 } |
1290 | 1293 |
1291 | 1294 |
1292 template<int T> | 1295 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, |
1293 void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr, | 1296 LOperand* left_argument, |
| 1297 LOperand* right_argument, |
1294 Token::Value op) { | 1298 Token::Value op) { |
1295 Register left = ToRegister(instr->InputAt(0)); | 1299 Register left = ToRegister(left_argument); |
1296 Register right = ToRegister(instr->InputAt(1)); | 1300 Register right = ToRegister(right_argument); |
1297 | 1301 |
1298 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); | 1302 PushSafepointRegistersScope scope(this, Safepoint::kWithRegistersAndDoubles); |
1299 // Move left to r1 and right to r0 for the stub call. | 1303 // Move left to r1 and right to r0 for the stub call. |
1300 if (left.is(r1)) { | 1304 if (left.is(r1)) { |
1301 __ Move(r0, right); | 1305 __ Move(r0, right); |
1302 } else if (left.is(r0) && right.is(r1)) { | 1306 } else if (left.is(r0) && right.is(r1)) { |
1303 __ Swap(r0, r1, r2); | 1307 __ Swap(r0, r1, r2); |
1304 } else if (left.is(r0)) { | 1308 } else if (left.is(r0)) { |
1305 ASSERT(!right.is(r1)); | 1309 ASSERT(!right.is(r1)); |
1306 __ mov(r1, r0); | 1310 __ mov(r1, r0); |
1307 __ mov(r0, right); | 1311 __ mov(r0, right); |
1308 } else { | 1312 } else { |
1309 ASSERT(!left.is(r0) && !right.is(r0)); | 1313 ASSERT(!left.is(r0) && !right.is(r0)); |
1310 __ mov(r0, right); | 1314 __ mov(r0, right); |
1311 __ mov(r1, left); | 1315 __ mov(r1, left); |
1312 } | 1316 } |
1313 BinaryOpStub stub(op, OVERWRITE_LEFT); | 1317 BinaryOpStub stub(op, OVERWRITE_LEFT); |
1314 __ CallStub(&stub); | 1318 __ CallStub(&stub); |
1315 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1319 RecordSafepointWithRegistersAndDoubles(pointer_map, |
1316 0, | 1320 0, |
1317 Safepoint::kNoLazyDeopt); | 1321 Safepoint::kNoLazyDeopt); |
1318 // Overwrite the stored value of r0 with the result of the stub. | 1322 // Overwrite the stored value of r0 with the result of the stub. |
1319 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1323 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1320 } | 1324 } |
1321 | 1325 |
1322 | 1326 |
1323 void LCodeGen::DoMulI(LMulI* instr) { | 1327 void LCodeGen::DoMulI(LMulI* instr) { |
1324 Register scratch = scratch0(); | 1328 Register scratch = scratch0(); |
1325 Register result = ToRegister(instr->result()); | 1329 Register result = ToRegister(instr->result()); |
1326 // Note that result may alias left. | 1330 // Note that result may alias left. |
1327 Register left = ToRegister(instr->InputAt(0)); | 1331 Register left = ToRegister(instr->left()); |
1328 LOperand* right_op = instr->InputAt(1); | 1332 LOperand* right_op = instr->right(); |
1329 | 1333 |
1330 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1334 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1331 bool bailout_on_minus_zero = | 1335 bool bailout_on_minus_zero = |
1332 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1336 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1333 | 1337 |
1334 if (right_op->IsConstantOperand() && !can_overflow) { | 1338 if (right_op->IsConstantOperand() && !can_overflow) { |
1335 // Use optimized code for specific constants. | 1339 // Use optimized code for specific constants. |
1336 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1340 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1337 | 1341 |
1338 if (bailout_on_minus_zero && (constant < 0)) { | 1342 if (bailout_on_minus_zero && (constant < 0)) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 } else { | 1389 } else { |
1386 // Generate standard code. | 1390 // Generate standard code. |
1387 __ mov(ip, Operand(constant)); | 1391 __ mov(ip, Operand(constant)); |
1388 __ mul(result, left, ip); | 1392 __ mul(result, left, ip); |
1389 } | 1393 } |
1390 } | 1394 } |
1391 | 1395 |
1392 } else { | 1396 } else { |
1393 Register right = EmitLoadRegister(right_op, scratch); | 1397 Register right = EmitLoadRegister(right_op, scratch); |
1394 if (bailout_on_minus_zero) { | 1398 if (bailout_on_minus_zero) { |
1395 __ orr(ToRegister(instr->TempAt(0)), left, right); | 1399 __ orr(ToRegister(instr->temp()), left, right); |
1396 } | 1400 } |
1397 | 1401 |
1398 if (can_overflow) { | 1402 if (can_overflow) { |
1399 // scratch:result = left * right. | 1403 // scratch:result = left * right. |
1400 __ smull(result, scratch, left, right); | 1404 __ smull(result, scratch, left, right); |
1401 __ cmp(scratch, Operand(result, ASR, 31)); | 1405 __ cmp(scratch, Operand(result, ASR, 31)); |
1402 DeoptimizeIf(ne, instr->environment()); | 1406 DeoptimizeIf(ne, instr->environment()); |
1403 } else { | 1407 } else { |
1404 __ mul(result, left, right); | 1408 __ mul(result, left, right); |
1405 } | 1409 } |
1406 | 1410 |
1407 if (bailout_on_minus_zero) { | 1411 if (bailout_on_minus_zero) { |
1408 // Bail out if the result is supposed to be negative zero. | 1412 // Bail out if the result is supposed to be negative zero. |
1409 Label done; | 1413 Label done; |
1410 __ cmp(result, Operand(0)); | 1414 __ cmp(result, Operand(0)); |
1411 __ b(ne, &done); | 1415 __ b(ne, &done); |
1412 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1416 __ cmp(ToRegister(instr->temp()), Operand(0)); |
1413 DeoptimizeIf(mi, instr->environment()); | 1417 DeoptimizeIf(mi, instr->environment()); |
1414 __ bind(&done); | 1418 __ bind(&done); |
1415 } | 1419 } |
1416 } | 1420 } |
1417 } | 1421 } |
1418 | 1422 |
1419 | 1423 |
1420 void LCodeGen::DoBitI(LBitI* instr) { | 1424 void LCodeGen::DoBitI(LBitI* instr) { |
1421 LOperand* left_op = instr->InputAt(0); | 1425 LOperand* left_op = instr->left(); |
1422 LOperand* right_op = instr->InputAt(1); | 1426 LOperand* right_op = instr->right(); |
1423 ASSERT(left_op->IsRegister()); | 1427 ASSERT(left_op->IsRegister()); |
1424 Register left = ToRegister(left_op); | 1428 Register left = ToRegister(left_op); |
1425 Register result = ToRegister(instr->result()); | 1429 Register result = ToRegister(instr->result()); |
1426 Operand right(no_reg); | 1430 Operand right(no_reg); |
1427 | 1431 |
1428 if (right_op->IsStackSlot() || right_op->IsArgument()) { | 1432 if (right_op->IsStackSlot() || right_op->IsArgument()) { |
1429 right = Operand(EmitLoadRegister(right_op, ip)); | 1433 right = Operand(EmitLoadRegister(right_op, ip)); |
1430 } else { | 1434 } else { |
1431 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); | 1435 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); |
1432 right = ToOperand(right_op); | 1436 right = ToOperand(right_op); |
(...skipping 12 matching lines...) Expand all Loading... |
1445 default: | 1449 default: |
1446 UNREACHABLE(); | 1450 UNREACHABLE(); |
1447 break; | 1451 break; |
1448 } | 1452 } |
1449 } | 1453 } |
1450 | 1454 |
1451 | 1455 |
1452 void LCodeGen::DoShiftI(LShiftI* instr) { | 1456 void LCodeGen::DoShiftI(LShiftI* instr) { |
1453 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so | 1457 // Both 'left' and 'right' are "used at start" (see LCodeGen::DoShift), so |
1454 // result may alias either of them. | 1458 // result may alias either of them. |
1455 LOperand* right_op = instr->InputAt(1); | 1459 LOperand* right_op = instr->right(); |
1456 Register left = ToRegister(instr->InputAt(0)); | 1460 Register left = ToRegister(instr->left()); |
1457 Register result = ToRegister(instr->result()); | 1461 Register result = ToRegister(instr->result()); |
1458 Register scratch = scratch0(); | 1462 Register scratch = scratch0(); |
1459 if (right_op->IsRegister()) { | 1463 if (right_op->IsRegister()) { |
1460 // Mask the right_op operand. | 1464 // Mask the right_op operand. |
1461 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); | 1465 __ and_(scratch, ToRegister(right_op), Operand(0x1F)); |
1462 switch (instr->op()) { | 1466 switch (instr->op()) { |
1463 case Token::SAR: | 1467 case Token::SAR: |
1464 __ mov(result, Operand(left, ASR, scratch)); | 1468 __ mov(result, Operand(left, ASR, scratch)); |
1465 break; | 1469 break; |
1466 case Token::SHR: | 1470 case Token::SHR: |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 break; | 1514 break; |
1511 default: | 1515 default: |
1512 UNREACHABLE(); | 1516 UNREACHABLE(); |
1513 break; | 1517 break; |
1514 } | 1518 } |
1515 } | 1519 } |
1516 } | 1520 } |
1517 | 1521 |
1518 | 1522 |
1519 void LCodeGen::DoSubI(LSubI* instr) { | 1523 void LCodeGen::DoSubI(LSubI* instr) { |
1520 LOperand* left = instr->InputAt(0); | 1524 LOperand* left = instr->left(); |
1521 LOperand* right = instr->InputAt(1); | 1525 LOperand* right = instr->right(); |
1522 LOperand* result = instr->result(); | 1526 LOperand* result = instr->result(); |
1523 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1527 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1524 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1528 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1525 | 1529 |
1526 if (right->IsStackSlot() || right->IsArgument()) { | 1530 if (right->IsStackSlot() || right->IsArgument()) { |
1527 Register right_reg = EmitLoadRegister(right, ip); | 1531 Register right_reg = EmitLoadRegister(right, ip); |
1528 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1532 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1529 } else { | 1533 } else { |
1530 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1534 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1531 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1535 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
(...skipping 25 matching lines...) Expand all Loading... |
1557 __ mov(ToRegister(instr->result()), Operand(value)); | 1561 __ mov(ToRegister(instr->result()), Operand(value)); |
1558 } else { | 1562 } else { |
1559 __ LoadHeapObject(ToRegister(instr->result()), | 1563 __ LoadHeapObject(ToRegister(instr->result()), |
1560 Handle<HeapObject>::cast(value)); | 1564 Handle<HeapObject>::cast(value)); |
1561 } | 1565 } |
1562 } | 1566 } |
1563 | 1567 |
1564 | 1568 |
1565 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1569 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
1566 Register result = ToRegister(instr->result()); | 1570 Register result = ToRegister(instr->result()); |
1567 Register array = ToRegister(instr->InputAt(0)); | 1571 Register array = ToRegister(instr->value()); |
1568 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); | 1572 __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
1569 } | 1573 } |
1570 | 1574 |
1571 | 1575 |
1572 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { | 1576 void LCodeGen::DoFixedArrayBaseLength(LFixedArrayBaseLength* instr) { |
1573 Register result = ToRegister(instr->result()); | 1577 Register result = ToRegister(instr->result()); |
1574 Register array = ToRegister(instr->InputAt(0)); | 1578 Register array = ToRegister(instr->value()); |
1575 __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); | 1579 __ ldr(result, FieldMemOperand(array, FixedArrayBase::kLengthOffset)); |
1576 } | 1580 } |
1577 | 1581 |
1578 | 1582 |
1579 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1583 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1580 Register result = ToRegister(instr->result()); | 1584 Register result = ToRegister(instr->result()); |
1581 Register map = ToRegister(instr->InputAt(0)); | 1585 Register map = ToRegister(instr->value()); |
1582 __ EnumLength(result, map); | 1586 __ EnumLength(result, map); |
1583 } | 1587 } |
1584 | 1588 |
1585 | 1589 |
1586 void LCodeGen::DoElementsKind(LElementsKind* instr) { | 1590 void LCodeGen::DoElementsKind(LElementsKind* instr) { |
1587 Register result = ToRegister(instr->result()); | 1591 Register result = ToRegister(instr->result()); |
1588 Register input = ToRegister(instr->InputAt(0)); | 1592 Register input = ToRegister(instr->value()); |
1589 | 1593 |
1590 // Load map into |result|. | 1594 // Load map into |result|. |
1591 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | 1595 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); |
1592 // Load the map's "bit field 2" into |result|. We only need the first byte, | 1596 // Load the map's "bit field 2" into |result|. We only need the first byte, |
1593 // but the following bit field extraction takes care of that anyway. | 1597 // but the following bit field extraction takes care of that anyway. |
1594 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | 1598 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); |
1595 // Retrieve elements_kind from bit field 2. | 1599 // Retrieve elements_kind from bit field 2. |
1596 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | 1600 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); |
1597 } | 1601 } |
1598 | 1602 |
1599 | 1603 |
1600 void LCodeGen::DoValueOf(LValueOf* instr) { | 1604 void LCodeGen::DoValueOf(LValueOf* instr) { |
1601 Register input = ToRegister(instr->InputAt(0)); | 1605 Register input = ToRegister(instr->value()); |
1602 Register result = ToRegister(instr->result()); | 1606 Register result = ToRegister(instr->result()); |
1603 Register map = ToRegister(instr->TempAt(0)); | 1607 Register map = ToRegister(instr->temp()); |
1604 Label done; | 1608 Label done; |
1605 | 1609 |
1606 // If the object is a smi return the object. | 1610 // If the object is a smi return the object. |
1607 __ tst(input, Operand(kSmiTagMask)); | 1611 __ tst(input, Operand(kSmiTagMask)); |
1608 __ Move(result, input, eq); | 1612 __ Move(result, input, eq); |
1609 __ b(eq, &done); | 1613 __ b(eq, &done); |
1610 | 1614 |
1611 // If the object is not a value type, return the object. | 1615 // If the object is not a value type, return the object. |
1612 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1616 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
1613 __ Move(result, input, ne); | 1617 __ Move(result, input, ne); |
1614 __ b(ne, &done); | 1618 __ b(ne, &done); |
1615 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | 1619 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); |
1616 | 1620 |
1617 __ bind(&done); | 1621 __ bind(&done); |
1618 } | 1622 } |
1619 | 1623 |
1620 | 1624 |
1621 void LCodeGen::DoDateField(LDateField* instr) { | 1625 void LCodeGen::DoDateField(LDateField* instr) { |
1622 Register object = ToRegister(instr->InputAt(0)); | 1626 Register object = ToRegister(instr->date()); |
1623 Register result = ToRegister(instr->result()); | 1627 Register result = ToRegister(instr->result()); |
1624 Register scratch = ToRegister(instr->TempAt(0)); | 1628 Register scratch = ToRegister(instr->temp()); |
1625 Smi* index = instr->index(); | 1629 Smi* index = instr->index(); |
1626 Label runtime, done; | 1630 Label runtime, done; |
1627 ASSERT(object.is(result)); | 1631 ASSERT(object.is(result)); |
1628 ASSERT(object.is(r0)); | 1632 ASSERT(object.is(r0)); |
1629 ASSERT(!scratch.is(scratch0())); | 1633 ASSERT(!scratch.is(scratch0())); |
1630 ASSERT(!scratch.is(object)); | 1634 ASSERT(!scratch.is(object)); |
1631 | 1635 |
1632 __ tst(object, Operand(kSmiTagMask)); | 1636 __ tst(object, Operand(kSmiTagMask)); |
1633 DeoptimizeIf(eq, instr->environment()); | 1637 DeoptimizeIf(eq, instr->environment()); |
1634 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); | 1638 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); |
(...skipping 16 matching lines...) Expand all Loading... |
1651 __ bind(&runtime); | 1655 __ bind(&runtime); |
1652 __ PrepareCallCFunction(2, scratch); | 1656 __ PrepareCallCFunction(2, scratch); |
1653 __ mov(r1, Operand(index)); | 1657 __ mov(r1, Operand(index)); |
1654 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1658 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
1655 __ bind(&done); | 1659 __ bind(&done); |
1656 } | 1660 } |
1657 } | 1661 } |
1658 | 1662 |
1659 | 1663 |
1660 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1664 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1661 Register input = ToRegister(instr->InputAt(0)); | 1665 Register input = ToRegister(instr->value()); |
1662 Register result = ToRegister(instr->result()); | 1666 Register result = ToRegister(instr->result()); |
1663 __ mvn(result, Operand(input)); | 1667 __ mvn(result, Operand(input)); |
1664 } | 1668 } |
1665 | 1669 |
1666 | 1670 |
1667 void LCodeGen::DoThrow(LThrow* instr) { | 1671 void LCodeGen::DoThrow(LThrow* instr) { |
1668 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 1672 Register input_reg = EmitLoadRegister(instr->value(), ip); |
1669 __ push(input_reg); | 1673 __ push(input_reg); |
1670 CallRuntime(Runtime::kThrow, 1, instr); | 1674 CallRuntime(Runtime::kThrow, 1, instr); |
1671 | 1675 |
1672 if (FLAG_debug_code) { | 1676 if (FLAG_debug_code) { |
1673 __ stop("Unreachable code."); | 1677 __ stop("Unreachable code."); |
1674 } | 1678 } |
1675 } | 1679 } |
1676 | 1680 |
1677 | 1681 |
1678 void LCodeGen::DoAddI(LAddI* instr) { | 1682 void LCodeGen::DoAddI(LAddI* instr) { |
1679 LOperand* left = instr->InputAt(0); | 1683 LOperand* left = instr->left(); |
1680 LOperand* right = instr->InputAt(1); | 1684 LOperand* right = instr->right(); |
1681 LOperand* result = instr->result(); | 1685 LOperand* result = instr->result(); |
1682 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1686 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1683 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1687 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1684 | 1688 |
1685 if (right->IsStackSlot() || right->IsArgument()) { | 1689 if (right->IsStackSlot() || right->IsArgument()) { |
1686 Register right_reg = EmitLoadRegister(right, ip); | 1690 Register right_reg = EmitLoadRegister(right, ip); |
1687 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1691 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1688 } else { | 1692 } else { |
1689 ASSERT(right->IsRegister() || right->IsConstantOperand()); | 1693 ASSERT(right->IsRegister() || right->IsConstantOperand()); |
1690 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1694 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1691 } | 1695 } |
1692 | 1696 |
1693 if (can_overflow) { | 1697 if (can_overflow) { |
1694 DeoptimizeIf(vs, instr->environment()); | 1698 DeoptimizeIf(vs, instr->environment()); |
1695 } | 1699 } |
1696 } | 1700 } |
1697 | 1701 |
1698 | 1702 |
1699 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1703 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1700 LOperand* left = instr->InputAt(0); | 1704 LOperand* left = instr->left(); |
1701 LOperand* right = instr->InputAt(1); | 1705 LOperand* right = instr->right(); |
1702 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1706 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
1703 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1707 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
1704 if (instr->hydrogen()->representation().IsInteger32()) { | 1708 if (instr->hydrogen()->representation().IsInteger32()) { |
1705 Register left_reg = ToRegister(left); | 1709 Register left_reg = ToRegister(left); |
1706 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 1710 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
1707 ? ToOperand(right) | 1711 ? ToOperand(right) |
1708 : Operand(EmitLoadRegister(right, ip)); | 1712 : Operand(EmitLoadRegister(right, ip)); |
1709 Register result_reg = ToRegister(instr->result()); | 1713 Register result_reg = ToRegister(instr->result()); |
1710 __ cmp(left_reg, right_op); | 1714 __ cmp(left_reg, right_op); |
1711 if (!result_reg.is(left_reg)) { | 1715 if (!result_reg.is(left_reg)) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 __ bind(&return_left); | 1756 __ bind(&return_left); |
1753 if (!left_reg.is(result_reg)) { | 1757 if (!left_reg.is(result_reg)) { |
1754 __ vmov(result_reg, left_reg); | 1758 __ vmov(result_reg, left_reg); |
1755 } | 1759 } |
1756 __ bind(&done); | 1760 __ bind(&done); |
1757 } | 1761 } |
1758 } | 1762 } |
1759 | 1763 |
1760 | 1764 |
1761 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1765 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
1762 DoubleRegister left = ToDoubleRegister(instr->InputAt(0)); | 1766 DoubleRegister left = ToDoubleRegister(instr->left()); |
1763 DoubleRegister right = ToDoubleRegister(instr->InputAt(1)); | 1767 DoubleRegister right = ToDoubleRegister(instr->right()); |
1764 DoubleRegister result = ToDoubleRegister(instr->result()); | 1768 DoubleRegister result = ToDoubleRegister(instr->result()); |
1765 switch (instr->op()) { | 1769 switch (instr->op()) { |
1766 case Token::ADD: | 1770 case Token::ADD: |
1767 __ vadd(result, left, right); | 1771 __ vadd(result, left, right); |
1768 break; | 1772 break; |
1769 case Token::SUB: | 1773 case Token::SUB: |
1770 __ vsub(result, left, right); | 1774 __ vsub(result, left, right); |
1771 break; | 1775 break; |
1772 case Token::MUL: | 1776 case Token::MUL: |
1773 __ vmul(result, left, right); | 1777 __ vmul(result, left, right); |
(...skipping 18 matching lines...) Expand all Loading... |
1792 break; | 1796 break; |
1793 } | 1797 } |
1794 default: | 1798 default: |
1795 UNREACHABLE(); | 1799 UNREACHABLE(); |
1796 break; | 1800 break; |
1797 } | 1801 } |
1798 } | 1802 } |
1799 | 1803 |
1800 | 1804 |
1801 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1805 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
1802 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); | 1806 ASSERT(ToRegister(instr->left()).is(r1)); |
1803 ASSERT(ToRegister(instr->InputAt(1)).is(r0)); | 1807 ASSERT(ToRegister(instr->right()).is(r0)); |
1804 ASSERT(ToRegister(instr->result()).is(r0)); | 1808 ASSERT(ToRegister(instr->result()).is(r0)); |
1805 | 1809 |
1806 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1810 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
1807 // Block literal pool emission to ensure nop indicating no inlined smi code | 1811 // Block literal pool emission to ensure nop indicating no inlined smi code |
1808 // is in the correct position. | 1812 // is in the correct position. |
1809 Assembler::BlockConstPoolScope block_const_pool(masm()); | 1813 Assembler::BlockConstPoolScope block_const_pool(masm()); |
1810 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1814 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
1811 __ nop(); // Signals no inlined code. | 1815 __ nop(); // Signals no inlined code. |
1812 } | 1816 } |
1813 | 1817 |
(...skipping 24 matching lines...) Expand all Loading... |
1838 } | 1842 } |
1839 } | 1843 } |
1840 | 1844 |
1841 | 1845 |
1842 void LCodeGen::DoBranch(LBranch* instr) { | 1846 void LCodeGen::DoBranch(LBranch* instr) { |
1843 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1847 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
1844 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1848 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
1845 | 1849 |
1846 Representation r = instr->hydrogen()->value()->representation(); | 1850 Representation r = instr->hydrogen()->value()->representation(); |
1847 if (r.IsInteger32()) { | 1851 if (r.IsInteger32()) { |
1848 Register reg = ToRegister(instr->InputAt(0)); | 1852 Register reg = ToRegister(instr->value()); |
1849 __ cmp(reg, Operand(0)); | 1853 __ cmp(reg, Operand(0)); |
1850 EmitBranch(true_block, false_block, ne); | 1854 EmitBranch(true_block, false_block, ne); |
1851 } else if (r.IsDouble()) { | 1855 } else if (r.IsDouble()) { |
1852 DoubleRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1856 DoubleRegister reg = ToDoubleRegister(instr->value()); |
1853 Register scratch = scratch0(); | 1857 Register scratch = scratch0(); |
1854 | 1858 |
1855 // Test the double value. Zero and NaN are false. | 1859 // Test the double value. Zero and NaN are false. |
1856 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 1860 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); |
1857 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 1861 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); |
1858 EmitBranch(true_block, false_block, eq); | 1862 EmitBranch(true_block, false_block, eq); |
1859 } else { | 1863 } else { |
1860 ASSERT(r.IsTagged()); | 1864 ASSERT(r.IsTagged()); |
1861 Register reg = ToRegister(instr->InputAt(0)); | 1865 Register reg = ToRegister(instr->value()); |
1862 HType type = instr->hydrogen()->value()->type(); | 1866 HType type = instr->hydrogen()->value()->type(); |
1863 if (type.IsBoolean()) { | 1867 if (type.IsBoolean()) { |
1864 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1868 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
1865 EmitBranch(true_block, false_block, eq); | 1869 EmitBranch(true_block, false_block, eq); |
1866 } else if (type.IsSmi()) { | 1870 } else if (type.IsSmi()) { |
1867 __ cmp(reg, Operand(0)); | 1871 __ cmp(reg, Operand(0)); |
1868 EmitBranch(true_block, false_block, ne); | 1872 EmitBranch(true_block, false_block, ne); |
1869 } else { | 1873 } else { |
1870 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1874 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
1871 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1875 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1990 case Token::IN: | 1994 case Token::IN: |
1991 case Token::INSTANCEOF: | 1995 case Token::INSTANCEOF: |
1992 default: | 1996 default: |
1993 UNREACHABLE(); | 1997 UNREACHABLE(); |
1994 } | 1998 } |
1995 return cond; | 1999 return cond; |
1996 } | 2000 } |
1997 | 2001 |
1998 | 2002 |
1999 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2003 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
2000 LOperand* left = instr->InputAt(0); | 2004 LOperand* left = instr->left(); |
2001 LOperand* right = instr->InputAt(1); | 2005 LOperand* right = instr->right(); |
2002 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2006 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2003 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2007 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2004 Condition cond = TokenToCondition(instr->op(), false); | 2008 Condition cond = TokenToCondition(instr->op(), false); |
2005 | 2009 |
2006 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2010 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2007 // We can statically evaluate the comparison. | 2011 // We can statically evaluate the comparison. |
2008 double left_val = ToDouble(LConstantOperand::cast(left)); | 2012 double left_val = ToDouble(LConstantOperand::cast(left)); |
2009 double right_val = ToDouble(LConstantOperand::cast(right)); | 2013 double right_val = ToDouble(LConstantOperand::cast(right)); |
2010 int next_block = | 2014 int next_block = |
2011 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2015 EvalComparison(instr->op(), left_val, right_val) ? true_block |
(...skipping 19 matching lines...) Expand all Loading... |
2031 } else { | 2035 } else { |
2032 __ cmp(ToRegister(left), ToRegister(right)); | 2036 __ cmp(ToRegister(left), ToRegister(right)); |
2033 } | 2037 } |
2034 } | 2038 } |
2035 EmitBranch(true_block, false_block, cond); | 2039 EmitBranch(true_block, false_block, cond); |
2036 } | 2040 } |
2037 } | 2041 } |
2038 | 2042 |
2039 | 2043 |
2040 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2044 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2041 Register left = ToRegister(instr->InputAt(0)); | 2045 Register left = ToRegister(instr->left()); |
2042 Register right = ToRegister(instr->InputAt(1)); | 2046 Register right = ToRegister(instr->right()); |
2043 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2047 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2044 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2048 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2045 | 2049 |
2046 __ cmp(left, Operand(right)); | 2050 __ cmp(left, Operand(right)); |
2047 EmitBranch(true_block, false_block, eq); | 2051 EmitBranch(true_block, false_block, eq); |
2048 } | 2052 } |
2049 | 2053 |
2050 | 2054 |
2051 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2055 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
2052 Register left = ToRegister(instr->InputAt(0)); | 2056 Register left = ToRegister(instr->left()); |
2053 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2057 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2054 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2058 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2055 | 2059 |
2056 __ cmp(left, Operand(instr->hydrogen()->right())); | 2060 __ cmp(left, Operand(instr->hydrogen()->right())); |
2057 EmitBranch(true_block, false_block, eq); | 2061 EmitBranch(true_block, false_block, eq); |
2058 } | 2062 } |
2059 | 2063 |
2060 | 2064 |
2061 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { | 2065 void LCodeGen::DoIsNilAndBranch(LIsNilAndBranch* instr) { |
2062 Register scratch = scratch0(); | 2066 Register scratch = scratch0(); |
2063 Register reg = ToRegister(instr->InputAt(0)); | 2067 Register reg = ToRegister(instr->value()); |
2064 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2068 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2065 | 2069 |
2066 // If the expression is known to be untagged or a smi, then it's definitely | 2070 // If the expression is known to be untagged or a smi, then it's definitely |
2067 // not null, and it can't be a an undetectable object. | 2071 // not null, and it can't be a an undetectable object. |
2068 if (instr->hydrogen()->representation().IsSpecialization() || | 2072 if (instr->hydrogen()->representation().IsSpecialization() || |
2069 instr->hydrogen()->type().IsSmi()) { | 2073 instr->hydrogen()->type().IsSmi()) { |
2070 EmitGoto(false_block); | 2074 EmitGoto(false_block); |
2071 return; | 2075 return; |
2072 } | 2076 } |
2073 | 2077 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2121 // Load instance type and check that it is in object type range. | 2125 // Load instance type and check that it is in object type range. |
2122 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); | 2126 __ ldrb(temp2, FieldMemOperand(temp1, Map::kInstanceTypeOffset)); |
2123 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2127 __ cmp(temp2, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2124 __ b(lt, is_not_object); | 2128 __ b(lt, is_not_object); |
2125 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 2129 __ cmp(temp2, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
2126 return le; | 2130 return le; |
2127 } | 2131 } |
2128 | 2132 |
2129 | 2133 |
2130 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2134 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
2131 Register reg = ToRegister(instr->InputAt(0)); | 2135 Register reg = ToRegister(instr->value()); |
2132 Register temp1 = ToRegister(instr->TempAt(0)); | 2136 Register temp1 = ToRegister(instr->temp()); |
2133 | 2137 |
2134 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2138 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2135 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2139 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2136 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2140 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2137 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2141 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2138 | 2142 |
2139 Condition true_cond = | 2143 Condition true_cond = |
2140 EmitIsObject(reg, temp1, false_label, true_label); | 2144 EmitIsObject(reg, temp1, false_label, true_label); |
2141 | 2145 |
2142 EmitBranch(true_block, false_block, true_cond); | 2146 EmitBranch(true_block, false_block, true_cond); |
2143 } | 2147 } |
2144 | 2148 |
2145 | 2149 |
2146 Condition LCodeGen::EmitIsString(Register input, | 2150 Condition LCodeGen::EmitIsString(Register input, |
2147 Register temp1, | 2151 Register temp1, |
2148 Label* is_not_string) { | 2152 Label* is_not_string) { |
2149 __ JumpIfSmi(input, is_not_string); | 2153 __ JumpIfSmi(input, is_not_string); |
2150 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); | 2154 __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); |
2151 | 2155 |
2152 return lt; | 2156 return lt; |
2153 } | 2157 } |
2154 | 2158 |
2155 | 2159 |
2156 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2160 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
2157 Register reg = ToRegister(instr->InputAt(0)); | 2161 Register reg = ToRegister(instr->value()); |
2158 Register temp1 = ToRegister(instr->TempAt(0)); | 2162 Register temp1 = ToRegister(instr->temp()); |
2159 | 2163 |
2160 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2164 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2161 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2165 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2162 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2166 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2163 | 2167 |
2164 Condition true_cond = | 2168 Condition true_cond = |
2165 EmitIsString(reg, temp1, false_label); | 2169 EmitIsString(reg, temp1, false_label); |
2166 | 2170 |
2167 EmitBranch(true_block, false_block, true_cond); | 2171 EmitBranch(true_block, false_block, true_cond); |
2168 } | 2172 } |
2169 | 2173 |
2170 | 2174 |
2171 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2175 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2172 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2176 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2173 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2177 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2174 | 2178 |
2175 Register input_reg = EmitLoadRegister(instr->InputAt(0), ip); | 2179 Register input_reg = EmitLoadRegister(instr->value(), ip); |
2176 __ tst(input_reg, Operand(kSmiTagMask)); | 2180 __ tst(input_reg, Operand(kSmiTagMask)); |
2177 EmitBranch(true_block, false_block, eq); | 2181 EmitBranch(true_block, false_block, eq); |
2178 } | 2182 } |
2179 | 2183 |
2180 | 2184 |
2181 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2185 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2182 Register input = ToRegister(instr->InputAt(0)); | 2186 Register input = ToRegister(instr->value()); |
2183 Register temp = ToRegister(instr->TempAt(0)); | 2187 Register temp = ToRegister(instr->temp()); |
2184 | 2188 |
2185 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2189 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2186 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2190 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2187 | 2191 |
2188 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 2192 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); |
2189 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); | 2193 __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); |
2190 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); | 2194 __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); |
2191 __ tst(temp, Operand(1 << Map::kIsUndetectable)); | 2195 __ tst(temp, Operand(1 << Map::kIsUndetectable)); |
2192 EmitBranch(true_block, false_block, ne); | 2196 EmitBranch(true_block, false_block, ne); |
2193 } | 2197 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2243 if (from == to) return eq; | 2247 if (from == to) return eq; |
2244 if (to == LAST_TYPE) return hs; | 2248 if (to == LAST_TYPE) return hs; |
2245 if (from == FIRST_TYPE) return ls; | 2249 if (from == FIRST_TYPE) return ls; |
2246 UNREACHABLE(); | 2250 UNREACHABLE(); |
2247 return eq; | 2251 return eq; |
2248 } | 2252 } |
2249 | 2253 |
2250 | 2254 |
2251 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2255 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2252 Register scratch = scratch0(); | 2256 Register scratch = scratch0(); |
2253 Register input = ToRegister(instr->InputAt(0)); | 2257 Register input = ToRegister(instr->value()); |
2254 | 2258 |
2255 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2259 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2256 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2260 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2257 | 2261 |
2258 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2262 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2259 | 2263 |
2260 __ JumpIfSmi(input, false_label); | 2264 __ JumpIfSmi(input, false_label); |
2261 | 2265 |
2262 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); | 2266 __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); |
2263 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2267 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
2264 } | 2268 } |
2265 | 2269 |
2266 | 2270 |
2267 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2271 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2268 Register input = ToRegister(instr->InputAt(0)); | 2272 Register input = ToRegister(instr->value()); |
2269 Register result = ToRegister(instr->result()); | 2273 Register result = ToRegister(instr->result()); |
2270 | 2274 |
2271 __ AbortIfNotString(input); | 2275 __ AbortIfNotString(input); |
2272 | 2276 |
2273 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); | 2277 __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset)); |
2274 __ IndexFromHash(result, result); | 2278 __ IndexFromHash(result, result); |
2275 } | 2279 } |
2276 | 2280 |
2277 | 2281 |
2278 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2282 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2279 LHasCachedArrayIndexAndBranch* instr) { | 2283 LHasCachedArrayIndexAndBranch* instr) { |
2280 Register input = ToRegister(instr->InputAt(0)); | 2284 Register input = ToRegister(instr->value()); |
2281 Register scratch = scratch0(); | 2285 Register scratch = scratch0(); |
2282 | 2286 |
2283 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2287 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2284 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2288 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2285 | 2289 |
2286 __ ldr(scratch, | 2290 __ ldr(scratch, |
2287 FieldMemOperand(input, String::kHashFieldOffset)); | 2291 FieldMemOperand(input, String::kHashFieldOffset)); |
2288 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); | 2292 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); |
2289 EmitBranch(true_block, false_block, eq); | 2293 EmitBranch(true_block, false_block, eq); |
2290 } | 2294 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2351 // booted. This routine isn't expected to work for random API-created | 2355 // booted. This routine isn't expected to work for random API-created |
2352 // classes and it doesn't have to because you can't access it with natives | 2356 // classes and it doesn't have to because you can't access it with natives |
2353 // syntax. Since both sides are symbols it is sufficient to use an identity | 2357 // syntax. Since both sides are symbols it is sufficient to use an identity |
2354 // comparison. | 2358 // comparison. |
2355 __ cmp(temp, Operand(class_name)); | 2359 __ cmp(temp, Operand(class_name)); |
2356 // End with the answer in flags. | 2360 // End with the answer in flags. |
2357 } | 2361 } |
2358 | 2362 |
2359 | 2363 |
2360 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2364 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2361 Register input = ToRegister(instr->InputAt(0)); | 2365 Register input = ToRegister(instr->value()); |
2362 Register temp = scratch0(); | 2366 Register temp = scratch0(); |
2363 Register temp2 = ToRegister(instr->TempAt(0)); | 2367 Register temp2 = ToRegister(instr->temp()); |
2364 Handle<String> class_name = instr->hydrogen()->class_name(); | 2368 Handle<String> class_name = instr->hydrogen()->class_name(); |
2365 | 2369 |
2366 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2370 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
2367 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2371 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
2368 | 2372 |
2369 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2373 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
2370 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 2374 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
2371 | 2375 |
2372 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 2376 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
2373 | 2377 |
2374 EmitBranch(true_block, false_block, eq); | 2378 EmitBranch(true_block, false_block, eq); |
2375 } | 2379 } |
2376 | 2380 |
2377 | 2381 |
2378 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2382 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2379 Register reg = ToRegister(instr->InputAt(0)); | 2383 Register reg = ToRegister(instr->value()); |
2380 Register temp = ToRegister(instr->TempAt(0)); | 2384 Register temp = ToRegister(instr->temp()); |
2381 int true_block = instr->true_block_id(); | 2385 int true_block = instr->true_block_id(); |
2382 int false_block = instr->false_block_id(); | 2386 int false_block = instr->false_block_id(); |
2383 | 2387 |
2384 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2388 __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2385 __ cmp(temp, Operand(instr->map())); | 2389 __ cmp(temp, Operand(instr->map())); |
2386 EmitBranch(true_block, false_block, eq); | 2390 EmitBranch(true_block, false_block, eq); |
2387 } | 2391 } |
2388 | 2392 |
2389 | 2393 |
2390 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2394 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2391 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); // Object is in r0. | 2395 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
2392 ASSERT(ToRegister(instr->InputAt(1)).is(r1)); // Function is in r1. | 2396 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
2393 | 2397 |
2394 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2398 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2395 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2399 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2396 | 2400 |
2397 __ cmp(r0, Operand(0)); | 2401 __ cmp(r0, Operand(0)); |
2398 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2402 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
2399 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2403 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
2400 } | 2404 } |
2401 | 2405 |
2402 | 2406 |
(...skipping 10 matching lines...) Expand all Loading... |
2413 Label* map_check() { return &map_check_; } | 2417 Label* map_check() { return &map_check_; } |
2414 private: | 2418 private: |
2415 LInstanceOfKnownGlobal* instr_; | 2419 LInstanceOfKnownGlobal* instr_; |
2416 Label map_check_; | 2420 Label map_check_; |
2417 }; | 2421 }; |
2418 | 2422 |
2419 DeferredInstanceOfKnownGlobal* deferred; | 2423 DeferredInstanceOfKnownGlobal* deferred; |
2420 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2424 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
2421 | 2425 |
2422 Label done, false_result; | 2426 Label done, false_result; |
2423 Register object = ToRegister(instr->InputAt(0)); | 2427 Register object = ToRegister(instr->value()); |
2424 Register temp = ToRegister(instr->TempAt(0)); | 2428 Register temp = ToRegister(instr->temp()); |
2425 Register result = ToRegister(instr->result()); | 2429 Register result = ToRegister(instr->result()); |
2426 | 2430 |
2427 ASSERT(object.is(r0)); | 2431 ASSERT(object.is(r0)); |
2428 ASSERT(result.is(r0)); | 2432 ASSERT(result.is(r0)); |
2429 | 2433 |
2430 // A Smi is not instance of anything. | 2434 // A Smi is not instance of anything. |
2431 __ JumpIfSmi(object, &false_result); | 2435 __ JumpIfSmi(object, &false_result); |
2432 | 2436 |
2433 // This is the inlined call site instanceof cache. The two occurences of the | 2437 // This is the inlined call site instanceof cache. The two occurences of the |
2434 // hole value will be patched to the last map/result pair generated by the | 2438 // hole value will be patched to the last map/result pair generated by the |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2494 flags | InstanceofStub::kCallSiteInlineCheck); | 2498 flags | InstanceofStub::kCallSiteInlineCheck); |
2495 flags = static_cast<InstanceofStub::Flags>( | 2499 flags = static_cast<InstanceofStub::Flags>( |
2496 flags | InstanceofStub::kReturnTrueFalseObject); | 2500 flags | InstanceofStub::kReturnTrueFalseObject); |
2497 InstanceofStub stub(flags); | 2501 InstanceofStub stub(flags); |
2498 | 2502 |
2499 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 2503 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
2500 | 2504 |
2501 // Get the temp register reserved by the instruction. This needs to be r4 as | 2505 // Get the temp register reserved by the instruction. This needs to be r4 as |
2502 // its slot of the pushing of safepoint registers is used to communicate the | 2506 // its slot of the pushing of safepoint registers is used to communicate the |
2503 // offset to the location of the map check. | 2507 // offset to the location of the map check. |
2504 Register temp = ToRegister(instr->TempAt(0)); | 2508 Register temp = ToRegister(instr->temp()); |
2505 ASSERT(temp.is(r4)); | 2509 ASSERT(temp.is(r4)); |
2506 __ LoadHeapObject(InstanceofStub::right(), instr->function()); | 2510 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
2507 static const int kAdditionalDelta = 5; | 2511 static const int kAdditionalDelta = 5; |
2508 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2512 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
2509 Label before_push_delta; | 2513 Label before_push_delta; |
2510 __ bind(&before_push_delta); | 2514 __ bind(&before_push_delta); |
2511 __ BlockConstPoolFor(kAdditionalDelta); | 2515 __ BlockConstPoolFor(kAdditionalDelta); |
2512 __ mov(temp, Operand(delta * kPointerSize)); | 2516 __ mov(temp, Operand(delta * kPointerSize)); |
2513 // The mov above can generate one or two instructions. The delta was computed | 2517 // The mov above can generate one or two instructions. The delta was computed |
2514 // for two instructions, so we need to pad here in case of one instruction. | 2518 // for two instructions, so we need to pad here in case of one instruction. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2591 | 2595 |
2592 // Load the cell. | 2596 // Load the cell. |
2593 __ mov(cell, Operand(instr->hydrogen()->cell())); | 2597 __ mov(cell, Operand(instr->hydrogen()->cell())); |
2594 | 2598 |
2595 // If the cell we are storing to contains the hole it could have | 2599 // If the cell we are storing to contains the hole it could have |
2596 // been deleted from the property dictionary. In that case, we need | 2600 // been deleted from the property dictionary. In that case, we need |
2597 // to update the property details in the property dictionary to mark | 2601 // to update the property details in the property dictionary to mark |
2598 // it as no longer deleted. | 2602 // it as no longer deleted. |
2599 if (instr->hydrogen()->RequiresHoleCheck()) { | 2603 if (instr->hydrogen()->RequiresHoleCheck()) { |
2600 // We use a temp to check the payload (CompareRoot might clobber ip). | 2604 // We use a temp to check the payload (CompareRoot might clobber ip). |
2601 Register payload = ToRegister(instr->TempAt(0)); | 2605 Register payload = ToRegister(instr->temp()); |
2602 __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2606 __ ldr(payload, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
2603 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); | 2607 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); |
2604 DeoptimizeIf(eq, instr->environment()); | 2608 DeoptimizeIf(eq, instr->environment()); |
2605 } | 2609 } |
2606 | 2610 |
2607 // Store the value. | 2611 // Store the value. |
2608 __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); | 2612 __ str(value, FieldMemOperand(cell, JSGlobalPropertyCell::kValueOffset)); |
2609 // Cells are always rescanned, so no write barrier here. | 2613 // Cells are always rescanned, so no write barrier here. |
2610 } | 2614 } |
2611 | 2615 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2670 kSaveFPRegs, | 2674 kSaveFPRegs, |
2671 EMIT_REMEMBERED_SET, | 2675 EMIT_REMEMBERED_SET, |
2672 check_needed); | 2676 check_needed); |
2673 } | 2677 } |
2674 | 2678 |
2675 __ bind(&skip_assignment); | 2679 __ bind(&skip_assignment); |
2676 } | 2680 } |
2677 | 2681 |
2678 | 2682 |
2679 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2683 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2680 Register object = ToRegister(instr->InputAt(0)); | 2684 Register object = ToRegister(instr->object()); |
2681 Register result = ToRegister(instr->result()); | 2685 Register result = ToRegister(instr->result()); |
2682 if (instr->hydrogen()->is_in_object()) { | 2686 if (instr->hydrogen()->is_in_object()) { |
2683 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2687 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
2684 } else { | 2688 } else { |
2685 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 2689 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
2686 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); | 2690 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
2687 } | 2691 } |
2688 } | 2692 } |
2689 | 2693 |
2690 | 2694 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2824 __ bind(&non_instance); | 2828 __ bind(&non_instance); |
2825 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); | 2829 __ ldr(result, FieldMemOperand(result, Map::kConstructorOffset)); |
2826 | 2830 |
2827 // All done. | 2831 // All done. |
2828 __ bind(&done); | 2832 __ bind(&done); |
2829 } | 2833 } |
2830 | 2834 |
2831 | 2835 |
2832 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2836 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
2833 Register result = ToRegister(instr->result()); | 2837 Register result = ToRegister(instr->result()); |
2834 Register input = ToRegister(instr->InputAt(0)); | 2838 Register input = ToRegister(instr->object()); |
2835 Register scratch = scratch0(); | 2839 Register scratch = scratch0(); |
2836 | 2840 |
2837 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); | 2841 __ ldr(result, FieldMemOperand(input, JSObject::kElementsOffset)); |
2838 if (FLAG_debug_code) { | 2842 if (FLAG_debug_code) { |
2839 Label done, fail; | 2843 Label done, fail; |
2840 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); | 2844 __ ldr(scratch, FieldMemOperand(result, HeapObject::kMapOffset)); |
2841 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); | 2845 __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex); |
2842 __ cmp(scratch, ip); | 2846 __ cmp(scratch, ip); |
2843 __ b(eq, &done); | 2847 __ b(eq, &done); |
2844 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); | 2848 __ LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex); |
(...skipping 14 matching lines...) Expand all Loading... |
2859 __ bind(&fail); | 2863 __ bind(&fail); |
2860 __ Abort("Check for fast or external elements failed."); | 2864 __ Abort("Check for fast or external elements failed."); |
2861 __ bind(&done); | 2865 __ bind(&done); |
2862 } | 2866 } |
2863 } | 2867 } |
2864 | 2868 |
2865 | 2869 |
2866 void LCodeGen::DoLoadExternalArrayPointer( | 2870 void LCodeGen::DoLoadExternalArrayPointer( |
2867 LLoadExternalArrayPointer* instr) { | 2871 LLoadExternalArrayPointer* instr) { |
2868 Register to_reg = ToRegister(instr->result()); | 2872 Register to_reg = ToRegister(instr->result()); |
2869 Register from_reg = ToRegister(instr->InputAt(0)); | 2873 Register from_reg = ToRegister(instr->object()); |
2870 __ ldr(to_reg, FieldMemOperand(from_reg, | 2874 __ ldr(to_reg, FieldMemOperand(from_reg, |
2871 ExternalArray::kExternalPointerOffset)); | 2875 ExternalArray::kExternalPointerOffset)); |
2872 } | 2876 } |
2873 | 2877 |
2874 | 2878 |
2875 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2879 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2876 Register arguments = ToRegister(instr->arguments()); | 2880 Register arguments = ToRegister(instr->arguments()); |
2877 Register length = ToRegister(instr->length()); | 2881 Register length = ToRegister(instr->length()); |
2878 Register index = ToRegister(instr->index()); | 2882 Register index = ToRegister(instr->index()); |
2879 Register result = ToRegister(instr->result()); | 2883 Register result = ToRegister(instr->result()); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3116 | 3120 |
3117 // Result is the frame pointer for the frame if not adapted and for the real | 3121 // Result is the frame pointer for the frame if not adapted and for the real |
3118 // frame below the adaptor frame if adapted. | 3122 // frame below the adaptor frame if adapted. |
3119 __ mov(result, fp, LeaveCC, ne); | 3123 __ mov(result, fp, LeaveCC, ne); |
3120 __ mov(result, scratch, LeaveCC, eq); | 3124 __ mov(result, scratch, LeaveCC, eq); |
3121 } | 3125 } |
3122 } | 3126 } |
3123 | 3127 |
3124 | 3128 |
3125 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3129 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
3126 Register elem = ToRegister(instr->InputAt(0)); | 3130 Register elem = ToRegister(instr->elements()); |
3127 Register result = ToRegister(instr->result()); | 3131 Register result = ToRegister(instr->result()); |
3128 | 3132 |
3129 Label done; | 3133 Label done; |
3130 | 3134 |
3131 // If no arguments adaptor frame the number of arguments is fixed. | 3135 // If no arguments adaptor frame the number of arguments is fixed. |
3132 __ cmp(fp, elem); | 3136 __ cmp(fp, elem); |
3133 __ mov(result, Operand(scope()->num_parameters())); | 3137 __ mov(result, Operand(scope()->num_parameters())); |
3134 __ b(eq, &done); | 3138 __ b(eq, &done); |
3135 | 3139 |
3136 // Arguments adaptor frame present. Get argument length from there. | 3140 // Arguments adaptor frame present. Get argument length from there. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3235 // The number of arguments is stored in receiver which is r0, as expected | 3239 // The number of arguments is stored in receiver which is r0, as expected |
3236 // by InvokeFunction. | 3240 // by InvokeFunction. |
3237 ParameterCount actual(receiver); | 3241 ParameterCount actual(receiver); |
3238 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3242 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3239 safepoint_generator, CALL_AS_METHOD); | 3243 safepoint_generator, CALL_AS_METHOD); |
3240 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3244 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3241 } | 3245 } |
3242 | 3246 |
3243 | 3247 |
3244 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3248 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3245 LOperand* argument = instr->InputAt(0); | 3249 LOperand* argument = instr->value(); |
3246 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3250 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3247 Abort("DoPushArgument not implemented for double type."); | 3251 Abort("DoPushArgument not implemented for double type."); |
3248 } else { | 3252 } else { |
3249 Register argument_reg = EmitLoadRegister(argument, ip); | 3253 Register argument_reg = EmitLoadRegister(argument, ip); |
3250 __ push(argument_reg); | 3254 __ push(argument_reg); |
3251 } | 3255 } |
3252 } | 3256 } |
3253 | 3257 |
3254 | 3258 |
3255 void LCodeGen::DoDrop(LDrop* instr) { | 3259 void LCodeGen::DoDrop(LDrop* instr) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3287 } | 3291 } |
3288 | 3292 |
3289 | 3293 |
3290 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3294 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
3291 Register result = ToRegister(instr->result()); | 3295 Register result = ToRegister(instr->result()); |
3292 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3296 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
3293 } | 3297 } |
3294 | 3298 |
3295 | 3299 |
3296 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3300 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
3297 Register global = ToRegister(instr->global()); | 3301 Register global = ToRegister(instr->global_object()); |
3298 Register result = ToRegister(instr->result()); | 3302 Register result = ToRegister(instr->result()); |
3299 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3303 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); |
3300 } | 3304 } |
3301 | 3305 |
3302 | 3306 |
3303 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3307 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
3304 int arity, | 3308 int arity, |
3305 LInstruction* instr, | 3309 LInstruction* instr, |
3306 CallKind call_kind, | 3310 CallKind call_kind, |
3307 R1State r1_state) { | 3311 R1State r1_state) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3347 ASSERT(ToRegister(instr->result()).is(r0)); | 3351 ASSERT(ToRegister(instr->result()).is(r0)); |
3348 CallKnownFunction(instr->function(), | 3352 CallKnownFunction(instr->function(), |
3349 instr->arity(), | 3353 instr->arity(), |
3350 instr, | 3354 instr, |
3351 CALL_AS_METHOD, | 3355 CALL_AS_METHOD, |
3352 R1_UNINITIALIZED); | 3356 R1_UNINITIALIZED); |
3353 } | 3357 } |
3354 | 3358 |
3355 | 3359 |
3356 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 3360 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
3357 Register input = ToRegister(instr->InputAt(0)); | 3361 Register input = ToRegister(instr->value()); |
3358 Register result = ToRegister(instr->result()); | 3362 Register result = ToRegister(instr->result()); |
3359 Register scratch = scratch0(); | 3363 Register scratch = scratch0(); |
3360 | 3364 |
3361 // Deoptimize if not a heap number. | 3365 // Deoptimize if not a heap number. |
3362 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3366 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
3363 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3367 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3364 __ cmp(scratch, Operand(ip)); | 3368 __ cmp(scratch, Operand(ip)); |
3365 DeoptimizeIf(ne, instr->environment()); | 3369 DeoptimizeIf(ne, instr->environment()); |
3366 | 3370 |
3367 Label done; | 3371 Label done; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3413 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); | 3417 __ str(tmp2, FieldMemOperand(tmp1, HeapNumber::kMantissaOffset)); |
3414 | 3418 |
3415 __ StoreToSafepointRegisterSlot(tmp1, result); | 3419 __ StoreToSafepointRegisterSlot(tmp1, result); |
3416 } | 3420 } |
3417 | 3421 |
3418 __ bind(&done); | 3422 __ bind(&done); |
3419 } | 3423 } |
3420 | 3424 |
3421 | 3425 |
3422 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { | 3426 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
3423 Register input = ToRegister(instr->InputAt(0)); | 3427 Register input = ToRegister(instr->value()); |
3424 Register result = ToRegister(instr->result()); | 3428 Register result = ToRegister(instr->result()); |
3425 __ cmp(input, Operand(0)); | 3429 __ cmp(input, Operand(0)); |
3426 __ Move(result, input, pl); | 3430 __ Move(result, input, pl); |
3427 // We can make rsb conditional because the previous cmp instruction | 3431 // We can make rsb conditional because the previous cmp instruction |
3428 // will clear the V (overflow) flag and rsb won't set this flag | 3432 // will clear the V (overflow) flag and rsb won't set this flag |
3429 // if input is positive. | 3433 // if input is positive. |
3430 __ rsb(result, input, Operand(0), SetCC, mi); | 3434 __ rsb(result, input, Operand(0), SetCC, mi); |
3431 // Deoptimize on overflow. | 3435 // Deoptimize on overflow. |
3432 DeoptimizeIf(vs, instr->environment()); | 3436 DeoptimizeIf(vs, instr->environment()); |
3433 } | 3437 } |
3434 | 3438 |
3435 | 3439 |
3436 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 3440 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
3437 // Class for deferred case. | 3441 // Class for deferred case. |
3438 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 3442 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
3439 public: | 3443 public: |
3440 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3444 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3441 LUnaryMathOperation* instr) | 3445 LUnaryMathOperation* instr) |
3442 : LDeferredCode(codegen), instr_(instr) { } | 3446 : LDeferredCode(codegen), instr_(instr) { } |
3443 virtual void Generate() { | 3447 virtual void Generate() { |
3444 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3448 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
3445 } | 3449 } |
3446 virtual LInstruction* instr() { return instr_; } | 3450 virtual LInstruction* instr() { return instr_; } |
3447 private: | 3451 private: |
3448 LUnaryMathOperation* instr_; | 3452 LUnaryMathOperation* instr_; |
3449 }; | 3453 }; |
3450 | 3454 |
3451 Representation r = instr->hydrogen()->value()->representation(); | 3455 Representation r = instr->hydrogen()->value()->representation(); |
3452 if (r.IsDouble()) { | 3456 if (r.IsDouble()) { |
3453 DwVfpRegister input = ToDoubleRegister(instr->InputAt(0)); | 3457 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3454 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3458 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3455 __ vabs(result, input); | 3459 __ vabs(result, input); |
3456 } else if (r.IsInteger32()) { | 3460 } else if (r.IsInteger32()) { |
3457 EmitIntegerMathAbs(instr); | 3461 EmitIntegerMathAbs(instr); |
3458 } else { | 3462 } else { |
3459 // Representation is tagged. | 3463 // Representation is tagged. |
3460 DeferredMathAbsTaggedHeapNumber* deferred = | 3464 DeferredMathAbsTaggedHeapNumber* deferred = |
3461 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); | 3465 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
3462 Register input = ToRegister(instr->InputAt(0)); | 3466 Register input = ToRegister(instr->value()); |
3463 // Smi check. | 3467 // Smi check. |
3464 __ JumpIfNotSmi(input, deferred->entry()); | 3468 __ JumpIfNotSmi(input, deferred->entry()); |
3465 // If smi, handle it directly. | 3469 // If smi, handle it directly. |
3466 EmitIntegerMathAbs(instr); | 3470 EmitIntegerMathAbs(instr); |
3467 __ bind(deferred->exit()); | 3471 __ bind(deferred->exit()); |
3468 } | 3472 } |
3469 } | 3473 } |
3470 | 3474 |
3471 | 3475 |
3472 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 3476 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
3473 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3477 DoubleRegister input = ToDoubleRegister(instr->value()); |
3474 Register result = ToRegister(instr->result()); | 3478 Register result = ToRegister(instr->result()); |
3475 SwVfpRegister single_scratch = double_scratch0().low(); | 3479 SwVfpRegister single_scratch = double_scratch0().low(); |
3476 Register scratch1 = scratch0(); | 3480 Register scratch1 = scratch0(); |
3477 Register scratch2 = ToRegister(instr->TempAt(0)); | 3481 Register scratch2 = ToRegister(instr->temp()); |
3478 | 3482 |
3479 __ EmitVFPTruncate(kRoundToMinusInf, | 3483 __ EmitVFPTruncate(kRoundToMinusInf, |
3480 single_scratch, | 3484 single_scratch, |
3481 input, | 3485 input, |
3482 scratch1, | 3486 scratch1, |
3483 scratch2); | 3487 scratch2); |
3484 DeoptimizeIf(ne, instr->environment()); | 3488 DeoptimizeIf(ne, instr->environment()); |
3485 | 3489 |
3486 // Move the result back to general purpose register r0. | 3490 // Move the result back to general purpose register r0. |
3487 __ vmov(result, single_scratch); | 3491 __ vmov(result, single_scratch); |
3488 | 3492 |
3489 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3493 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3490 // Test for -0. | 3494 // Test for -0. |
3491 Label done; | 3495 Label done; |
3492 __ cmp(result, Operand(0)); | 3496 __ cmp(result, Operand(0)); |
3493 __ b(ne, &done); | 3497 __ b(ne, &done); |
3494 __ vmov(scratch1, input.high()); | 3498 __ vmov(scratch1, input.high()); |
3495 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 3499 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
3496 DeoptimizeIf(ne, instr->environment()); | 3500 DeoptimizeIf(ne, instr->environment()); |
3497 __ bind(&done); | 3501 __ bind(&done); |
3498 } | 3502 } |
3499 } | 3503 } |
3500 | 3504 |
3501 | 3505 |
3502 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 3506 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
3503 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3507 DoubleRegister input = ToDoubleRegister(instr->value()); |
3504 Register result = ToRegister(instr->result()); | 3508 Register result = ToRegister(instr->result()); |
3505 Register scratch = scratch0(); | 3509 Register scratch = scratch0(); |
3506 Label done, check_sign_on_zero; | 3510 Label done, check_sign_on_zero; |
3507 | 3511 |
3508 // Extract exponent bits. | 3512 // Extract exponent bits. |
3509 __ vmov(result, input.high()); | 3513 __ vmov(result, input.high()); |
3510 __ ubfx(scratch, | 3514 __ ubfx(scratch, |
3511 result, | 3515 result, |
3512 HeapNumber::kExponentShift, | 3516 HeapNumber::kExponentShift, |
3513 HeapNumber::kExponentBits); | 3517 HeapNumber::kExponentBits); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3558 __ bind(&check_sign_on_zero); | 3562 __ bind(&check_sign_on_zero); |
3559 __ vmov(scratch, input.high()); | 3563 __ vmov(scratch, input.high()); |
3560 __ tst(scratch, Operand(HeapNumber::kSignMask)); | 3564 __ tst(scratch, Operand(HeapNumber::kSignMask)); |
3561 DeoptimizeIf(ne, instr->environment()); | 3565 DeoptimizeIf(ne, instr->environment()); |
3562 } | 3566 } |
3563 __ bind(&done); | 3567 __ bind(&done); |
3564 } | 3568 } |
3565 | 3569 |
3566 | 3570 |
3567 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 3571 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
3568 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3572 DoubleRegister input = ToDoubleRegister(instr->value()); |
3569 DoubleRegister result = ToDoubleRegister(instr->result()); | 3573 DoubleRegister result = ToDoubleRegister(instr->result()); |
3570 __ vsqrt(result, input); | 3574 __ vsqrt(result, input); |
3571 } | 3575 } |
3572 | 3576 |
3573 | 3577 |
3574 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 3578 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
3575 DoubleRegister input = ToDoubleRegister(instr->InputAt(0)); | 3579 DoubleRegister input = ToDoubleRegister(instr->value()); |
3576 DoubleRegister result = ToDoubleRegister(instr->result()); | 3580 DoubleRegister result = ToDoubleRegister(instr->result()); |
3577 DoubleRegister temp = ToDoubleRegister(instr->TempAt(0)); | 3581 DoubleRegister temp = ToDoubleRegister(instr->temp()); |
3578 | 3582 |
3579 // Note that according to ECMA-262 15.8.2.13: | 3583 // Note that according to ECMA-262 15.8.2.13: |
3580 // Math.pow(-Infinity, 0.5) == Infinity | 3584 // Math.pow(-Infinity, 0.5) == Infinity |
3581 // Math.sqrt(-Infinity) == NaN | 3585 // Math.sqrt(-Infinity) == NaN |
3582 Label done; | 3586 Label done; |
3583 __ vmov(temp, -V8_INFINITY); | 3587 __ vmov(temp, -V8_INFINITY); |
3584 __ VFPCompareAndSetFlags(input, temp); | 3588 __ VFPCompareAndSetFlags(input, temp); |
3585 __ vneg(result, temp, eq); | 3589 __ vneg(result, temp, eq); |
3586 __ b(&done, eq); | 3590 __ b(&done, eq); |
3587 | 3591 |
3588 // Add +0 to convert -0 to +0. | 3592 // Add +0 to convert -0 to +0. |
3589 __ vadd(result, input, kDoubleRegZero); | 3593 __ vadd(result, input, kDoubleRegZero); |
3590 __ vsqrt(result, result); | 3594 __ vsqrt(result, result); |
3591 __ bind(&done); | 3595 __ bind(&done); |
3592 } | 3596 } |
3593 | 3597 |
3594 | 3598 |
3595 void LCodeGen::DoPower(LPower* instr) { | 3599 void LCodeGen::DoPower(LPower* instr) { |
3596 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3600 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3597 // Having marked this as a call, we can use any registers. | 3601 // Having marked this as a call, we can use any registers. |
3598 // Just make sure that the input/output registers are the expected ones. | 3602 // Just make sure that the input/output registers are the expected ones. |
3599 ASSERT(!instr->InputAt(1)->IsDoubleRegister() || | 3603 ASSERT(!instr->right()->IsDoubleRegister() || |
3600 ToDoubleRegister(instr->InputAt(1)).is(d2)); | 3604 ToDoubleRegister(instr->right()).is(d2)); |
3601 ASSERT(!instr->InputAt(1)->IsRegister() || | 3605 ASSERT(!instr->right()->IsRegister() || |
3602 ToRegister(instr->InputAt(1)).is(r2)); | 3606 ToRegister(instr->right()).is(r2)); |
3603 ASSERT(ToDoubleRegister(instr->InputAt(0)).is(d1)); | 3607 ASSERT(ToDoubleRegister(instr->left()).is(d1)); |
3604 ASSERT(ToDoubleRegister(instr->result()).is(d3)); | 3608 ASSERT(ToDoubleRegister(instr->result()).is(d3)); |
3605 | 3609 |
3606 if (exponent_type.IsTagged()) { | 3610 if (exponent_type.IsTagged()) { |
3607 Label no_deopt; | 3611 Label no_deopt; |
3608 __ JumpIfSmi(r2, &no_deopt); | 3612 __ JumpIfSmi(r2, &no_deopt); |
3609 __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset)); | 3613 __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset)); |
3610 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3614 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3611 __ cmp(r7, Operand(ip)); | 3615 __ cmp(r7, Operand(ip)); |
3612 DeoptimizeIf(ne, instr->environment()); | 3616 DeoptimizeIf(ne, instr->environment()); |
3613 __ bind(&no_deopt); | 3617 __ bind(&no_deopt); |
(...skipping 19 matching lines...) Expand all Loading... |
3633 virtual LInstruction* instr() { return instr_; } | 3637 virtual LInstruction* instr() { return instr_; } |
3634 private: | 3638 private: |
3635 LRandom* instr_; | 3639 LRandom* instr_; |
3636 }; | 3640 }; |
3637 | 3641 |
3638 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); | 3642 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); |
3639 | 3643 |
3640 // Having marked this instruction as a call we can use any | 3644 // Having marked this instruction as a call we can use any |
3641 // registers. | 3645 // registers. |
3642 ASSERT(ToDoubleRegister(instr->result()).is(d7)); | 3646 ASSERT(ToDoubleRegister(instr->result()).is(d7)); |
3643 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); | 3647 ASSERT(ToRegister(instr->global_object()).is(r0)); |
3644 | 3648 |
3645 static const int kSeedSize = sizeof(uint32_t); | 3649 static const int kSeedSize = sizeof(uint32_t); |
3646 STATIC_ASSERT(kPointerSize == kSeedSize); | 3650 STATIC_ASSERT(kPointerSize == kSeedSize); |
3647 | 3651 |
3648 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); | 3652 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); |
3649 static const int kRandomSeedOffset = | 3653 static const int kRandomSeedOffset = |
3650 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; | 3654 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; |
3651 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); | 3655 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); |
3652 // r2: FixedArray of the native context's random seeds | 3656 // r2: FixedArray of the native context's random seeds |
3653 | 3657 |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3844 ASSERT(ToRegister(instr->result()).is(r0)); | 3848 ASSERT(ToRegister(instr->result()).is(r0)); |
3845 CallKnownFunction(instr->target(), | 3849 CallKnownFunction(instr->target(), |
3846 instr->arity(), | 3850 instr->arity(), |
3847 instr, | 3851 instr, |
3848 CALL_AS_FUNCTION, | 3852 CALL_AS_FUNCTION, |
3849 R1_UNINITIALIZED); | 3853 R1_UNINITIALIZED); |
3850 } | 3854 } |
3851 | 3855 |
3852 | 3856 |
3853 void LCodeGen::DoCallNew(LCallNew* instr) { | 3857 void LCodeGen::DoCallNew(LCallNew* instr) { |
3854 ASSERT(ToRegister(instr->InputAt(0)).is(r1)); | 3858 ASSERT(ToRegister(instr->constructor()).is(r1)); |
3855 ASSERT(ToRegister(instr->result()).is(r0)); | 3859 ASSERT(ToRegister(instr->result()).is(r0)); |
3856 | 3860 |
3857 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3861 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
3858 __ mov(r0, Operand(instr->arity())); | 3862 __ mov(r0, Operand(instr->arity())); |
3859 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); | 3863 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); |
3860 } | 3864 } |
3861 | 3865 |
3862 | 3866 |
3863 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3867 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
3864 CallRuntime(instr->function(), instr->arity(), instr); | 3868 CallRuntime(instr->function(), instr->arity(), instr); |
3865 } | 3869 } |
3866 | 3870 |
3867 | 3871 |
3868 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3872 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3869 Register object = ToRegister(instr->object()); | 3873 Register object = ToRegister(instr->object()); |
3870 Register value = ToRegister(instr->value()); | 3874 Register value = ToRegister(instr->value()); |
3871 Register scratch = scratch0(); | 3875 Register scratch = scratch0(); |
3872 int offset = instr->offset(); | 3876 int offset = instr->offset(); |
3873 | 3877 |
3874 ASSERT(!object.is(value)); | 3878 ASSERT(!object.is(value)); |
3875 | 3879 |
3876 if (!instr->transition().is_null()) { | 3880 if (!instr->transition().is_null()) { |
3877 __ mov(scratch, Operand(instr->transition())); | 3881 __ mov(scratch, Operand(instr->transition())); |
3878 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3882 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
3879 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3883 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3880 Register temp = ToRegister(instr->TempAt(0)); | 3884 Register temp = ToRegister(instr->temp()); |
3881 // Update the write barrier for the map field. | 3885 // Update the write barrier for the map field. |
3882 __ RecordWriteField(object, | 3886 __ RecordWriteField(object, |
3883 HeapObject::kMapOffset, | 3887 HeapObject::kMapOffset, |
3884 scratch, | 3888 scratch, |
3885 temp, | 3889 temp, |
3886 kLRHasBeenSaved, | 3890 kLRHasBeenSaved, |
3887 kSaveFPRegs, | 3891 kSaveFPRegs, |
3888 OMIT_REMEMBERED_SET, | 3892 OMIT_REMEMBERED_SET, |
3889 OMIT_SMI_CHECK); | 3893 OMIT_SMI_CHECK); |
3890 } | 3894 } |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4148 | 4152 |
4149 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4153 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4150 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4154 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
4151 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4155 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4152 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4156 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4153 } | 4157 } |
4154 | 4158 |
4155 | 4159 |
4156 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4160 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
4157 Register object_reg = ToRegister(instr->object()); | 4161 Register object_reg = ToRegister(instr->object()); |
4158 Register new_map_reg = ToRegister(instr->new_map_reg()); | 4162 Register new_map_reg = ToRegister(instr->new_map_temp()); |
4159 Register scratch = scratch0(); | 4163 Register scratch = scratch0(); |
4160 | 4164 |
4161 Handle<Map> from_map = instr->original_map(); | 4165 Handle<Map> from_map = instr->original_map(); |
4162 Handle<Map> to_map = instr->transitioned_map(); | 4166 Handle<Map> to_map = instr->transitioned_map(); |
4163 ElementsKind from_kind = from_map->elements_kind(); | 4167 ElementsKind from_kind = from_map->elements_kind(); |
4164 ElementsKind to_kind = to_map->elements_kind(); | 4168 ElementsKind to_kind = to_map->elements_kind(); |
4165 | 4169 |
4166 Label not_applicable; | 4170 Label not_applicable; |
4167 __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4171 __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
4168 __ cmp(scratch, Operand(from_map)); | 4172 __ cmp(scratch, Operand(from_map)); |
4169 __ b(ne, ¬_applicable); | 4173 __ b(ne, ¬_applicable); |
4170 __ mov(new_map_reg, Operand(to_map)); | 4174 __ mov(new_map_reg, Operand(to_map)); |
4171 | 4175 |
4172 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4176 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
4173 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); | 4177 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); |
4174 // Write barrier. | 4178 // Write barrier. |
4175 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4179 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
4176 scratch, kLRHasBeenSaved, kDontSaveFPRegs); | 4180 scratch, kLRHasBeenSaved, kDontSaveFPRegs); |
4177 } else if (IsFastSmiElementsKind(from_kind) && | 4181 } else if (IsFastSmiElementsKind(from_kind) && |
4178 IsFastDoubleElementsKind(to_kind)) { | 4182 IsFastDoubleElementsKind(to_kind)) { |
4179 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 4183 Register fixed_object_reg = ToRegister(instr->temp()); |
4180 ASSERT(fixed_object_reg.is(r2)); | 4184 ASSERT(fixed_object_reg.is(r2)); |
4181 ASSERT(new_map_reg.is(r3)); | 4185 ASSERT(new_map_reg.is(r3)); |
4182 __ mov(fixed_object_reg, object_reg); | 4186 __ mov(fixed_object_reg, object_reg); |
4183 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 4187 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
4184 RelocInfo::CODE_TARGET, instr); | 4188 RelocInfo::CODE_TARGET, instr); |
4185 } else if (IsFastDoubleElementsKind(from_kind) && | 4189 } else if (IsFastDoubleElementsKind(from_kind) && |
4186 IsFastObjectElementsKind(to_kind)) { | 4190 IsFastObjectElementsKind(to_kind)) { |
4187 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 4191 Register fixed_object_reg = ToRegister(instr->temp()); |
4188 ASSERT(fixed_object_reg.is(r2)); | 4192 ASSERT(fixed_object_reg.is(r2)); |
4189 ASSERT(new_map_reg.is(r3)); | 4193 ASSERT(new_map_reg.is(r3)); |
4190 __ mov(fixed_object_reg, object_reg); | 4194 __ mov(fixed_object_reg, object_reg); |
4191 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 4195 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
4192 RelocInfo::CODE_TARGET, instr); | 4196 RelocInfo::CODE_TARGET, instr); |
4193 } else { | 4197 } else { |
4194 UNREACHABLE(); | 4198 UNREACHABLE(); |
4195 } | 4199 } |
4196 __ bind(¬_applicable); | 4200 __ bind(¬_applicable); |
4197 } | 4201 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4302 | 4306 |
4303 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4307 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4304 __ SmiTag(char_code); | 4308 __ SmiTag(char_code); |
4305 __ push(char_code); | 4309 __ push(char_code); |
4306 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4310 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
4307 __ StoreToSafepointRegisterSlot(r0, result); | 4311 __ StoreToSafepointRegisterSlot(r0, result); |
4308 } | 4312 } |
4309 | 4313 |
4310 | 4314 |
4311 void LCodeGen::DoStringLength(LStringLength* instr) { | 4315 void LCodeGen::DoStringLength(LStringLength* instr) { |
4312 Register string = ToRegister(instr->InputAt(0)); | 4316 Register string = ToRegister(instr->string()); |
4313 Register result = ToRegister(instr->result()); | 4317 Register result = ToRegister(instr->result()); |
4314 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 4318 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
4315 } | 4319 } |
4316 | 4320 |
4317 | 4321 |
4318 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4322 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4319 LOperand* input = instr->InputAt(0); | 4323 LOperand* input = instr->value(); |
4320 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4324 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4321 LOperand* output = instr->result(); | 4325 LOperand* output = instr->result(); |
4322 ASSERT(output->IsDoubleRegister()); | 4326 ASSERT(output->IsDoubleRegister()); |
4323 SwVfpRegister single_scratch = double_scratch0().low(); | 4327 SwVfpRegister single_scratch = double_scratch0().low(); |
4324 if (input->IsStackSlot()) { | 4328 if (input->IsStackSlot()) { |
4325 Register scratch = scratch0(); | 4329 Register scratch = scratch0(); |
4326 __ ldr(scratch, ToMemOperand(input)); | 4330 __ ldr(scratch, ToMemOperand(input)); |
4327 __ vmov(single_scratch, scratch); | 4331 __ vmov(single_scratch, scratch); |
4328 } else { | 4332 } else { |
4329 __ vmov(single_scratch, ToRegister(input)); | 4333 __ vmov(single_scratch, ToRegister(input)); |
4330 } | 4334 } |
4331 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); | 4335 __ vcvt_f64_s32(ToDoubleRegister(output), single_scratch); |
4332 } | 4336 } |
4333 | 4337 |
4334 | 4338 |
4335 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4339 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
4336 LOperand* input = instr->InputAt(0); | 4340 LOperand* input = instr->value(); |
4337 LOperand* output = instr->result(); | 4341 LOperand* output = instr->result(); |
4338 | 4342 |
4339 SwVfpRegister flt_scratch = double_scratch0().low(); | 4343 SwVfpRegister flt_scratch = double_scratch0().low(); |
4340 __ vmov(flt_scratch, ToRegister(input)); | 4344 __ vmov(flt_scratch, ToRegister(input)); |
4341 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); | 4345 __ vcvt_f64_u32(ToDoubleRegister(output), flt_scratch); |
4342 } | 4346 } |
4343 | 4347 |
4344 | 4348 |
4345 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4349 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4346 class DeferredNumberTagI: public LDeferredCode { | 4350 class DeferredNumberTagI: public LDeferredCode { |
4347 public: | 4351 public: |
4348 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4352 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
4349 : LDeferredCode(codegen), instr_(instr) { } | 4353 : LDeferredCode(codegen), instr_(instr) { } |
4350 virtual void Generate() { | 4354 virtual void Generate() { |
4351 codegen()->DoDeferredNumberTagI(instr_, | 4355 codegen()->DoDeferredNumberTagI(instr_, |
4352 instr_->InputAt(0), | 4356 instr_->value(), |
4353 SIGNED_INT32); | 4357 SIGNED_INT32); |
4354 } | 4358 } |
4355 virtual LInstruction* instr() { return instr_; } | 4359 virtual LInstruction* instr() { return instr_; } |
4356 private: | 4360 private: |
4357 LNumberTagI* instr_; | 4361 LNumberTagI* instr_; |
4358 }; | 4362 }; |
4359 | 4363 |
4360 Register src = ToRegister(instr->InputAt(0)); | 4364 Register src = ToRegister(instr->value()); |
4361 Register dst = ToRegister(instr->result()); | 4365 Register dst = ToRegister(instr->result()); |
4362 | 4366 |
4363 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4367 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
4364 __ SmiTag(dst, src, SetCC); | 4368 __ SmiTag(dst, src, SetCC); |
4365 __ b(vs, deferred->entry()); | 4369 __ b(vs, deferred->entry()); |
4366 __ bind(deferred->exit()); | 4370 __ bind(deferred->exit()); |
4367 } | 4371 } |
4368 | 4372 |
4369 | 4373 |
4370 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4374 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
4371 class DeferredNumberTagU: public LDeferredCode { | 4375 class DeferredNumberTagU: public LDeferredCode { |
4372 public: | 4376 public: |
4373 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) | 4377 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
4374 : LDeferredCode(codegen), instr_(instr) { } | 4378 : LDeferredCode(codegen), instr_(instr) { } |
4375 virtual void Generate() { | 4379 virtual void Generate() { |
4376 codegen()->DoDeferredNumberTagI(instr_, | 4380 codegen()->DoDeferredNumberTagI(instr_, |
4377 instr_->InputAt(0), | 4381 instr_->value(), |
4378 UNSIGNED_INT32); | 4382 UNSIGNED_INT32); |
4379 } | 4383 } |
4380 virtual LInstruction* instr() { return instr_; } | 4384 virtual LInstruction* instr() { return instr_; } |
4381 private: | 4385 private: |
4382 LNumberTagU* instr_; | 4386 LNumberTagU* instr_; |
4383 }; | 4387 }; |
4384 | 4388 |
4385 LOperand* input = instr->InputAt(0); | 4389 LOperand* input = instr->value(); |
4386 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4390 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4387 Register reg = ToRegister(input); | 4391 Register reg = ToRegister(input); |
4388 | 4392 |
4389 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); | 4393 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
4390 __ cmp(reg, Operand(Smi::kMaxValue)); | 4394 __ cmp(reg, Operand(Smi::kMaxValue)); |
4391 __ b(hi, deferred->entry()); | 4395 __ b(hi, deferred->entry()); |
4392 __ SmiTag(reg, reg); | 4396 __ SmiTag(reg, reg); |
4393 __ bind(deferred->exit()); | 4397 __ bind(deferred->exit()); |
4394 } | 4398 } |
4395 | 4399 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4453 class DeferredNumberTagD: public LDeferredCode { | 4457 class DeferredNumberTagD: public LDeferredCode { |
4454 public: | 4458 public: |
4455 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 4459 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
4456 : LDeferredCode(codegen), instr_(instr) { } | 4460 : LDeferredCode(codegen), instr_(instr) { } |
4457 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 4461 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
4458 virtual LInstruction* instr() { return instr_; } | 4462 virtual LInstruction* instr() { return instr_; } |
4459 private: | 4463 private: |
4460 LNumberTagD* instr_; | 4464 LNumberTagD* instr_; |
4461 }; | 4465 }; |
4462 | 4466 |
4463 DoubleRegister input_reg = ToDoubleRegister(instr->InputAt(0)); | 4467 DoubleRegister input_reg = ToDoubleRegister(instr->value()); |
4464 Register scratch = scratch0(); | 4468 Register scratch = scratch0(); |
4465 Register reg = ToRegister(instr->result()); | 4469 Register reg = ToRegister(instr->result()); |
4466 Register temp1 = ToRegister(instr->TempAt(0)); | 4470 Register temp1 = ToRegister(instr->temp()); |
4467 Register temp2 = ToRegister(instr->TempAt(1)); | 4471 Register temp2 = ToRegister(instr->temp2()); |
4468 | 4472 |
4469 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); | 4473 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); |
4470 if (FLAG_inline_new) { | 4474 if (FLAG_inline_new) { |
4471 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); | 4475 __ LoadRoot(scratch, Heap::kHeapNumberMapRootIndex); |
4472 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); | 4476 __ AllocateHeapNumber(reg, temp1, temp2, scratch, deferred->entry()); |
4473 } else { | 4477 } else { |
4474 __ jmp(deferred->entry()); | 4478 __ jmp(deferred->entry()); |
4475 } | 4479 } |
4476 __ bind(deferred->exit()); | 4480 __ bind(deferred->exit()); |
4477 __ sub(ip, reg, Operand(kHeapObjectTag)); | 4481 __ sub(ip, reg, Operand(kHeapObjectTag)); |
4478 __ vstr(input_reg, ip, HeapNumber::kValueOffset); | 4482 __ vstr(input_reg, ip, HeapNumber::kValueOffset); |
4479 } | 4483 } |
4480 | 4484 |
4481 | 4485 |
4482 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4486 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
4483 // TODO(3095996): Get rid of this. For now, we need to make the | 4487 // TODO(3095996): Get rid of this. For now, we need to make the |
4484 // result register contain a valid pointer because it is already | 4488 // result register contain a valid pointer because it is already |
4485 // contained in the register pointer map. | 4489 // contained in the register pointer map. |
4486 Register reg = ToRegister(instr->result()); | 4490 Register reg = ToRegister(instr->result()); |
4487 __ mov(reg, Operand(0)); | 4491 __ mov(reg, Operand(0)); |
4488 | 4492 |
4489 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4493 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4490 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4494 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4491 __ StoreToSafepointRegisterSlot(r0, reg); | 4495 __ StoreToSafepointRegisterSlot(r0, reg); |
4492 } | 4496 } |
4493 | 4497 |
4494 | 4498 |
4495 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4499 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4496 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4500 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4497 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->InputAt(0))); | 4501 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); |
4498 } | 4502 } |
4499 | 4503 |
4500 | 4504 |
4501 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4505 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4502 Register input = ToRegister(instr->InputAt(0)); | 4506 Register input = ToRegister(instr->value()); |
4503 Register result = ToRegister(instr->result()); | 4507 Register result = ToRegister(instr->result()); |
4504 if (instr->needs_check()) { | 4508 if (instr->needs_check()) { |
4505 STATIC_ASSERT(kHeapObjectTag == 1); | 4509 STATIC_ASSERT(kHeapObjectTag == 1); |
4506 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4510 // If the input is a HeapObject, SmiUntag will set the carry flag. |
4507 __ SmiUntag(result, input, SetCC); | 4511 __ SmiUntag(result, input, SetCC); |
4508 DeoptimizeIf(cs, instr->environment()); | 4512 DeoptimizeIf(cs, instr->environment()); |
4509 } else { | 4513 } else { |
4510 __ SmiUntag(result, input); | 4514 __ SmiUntag(result, input); |
4511 } | 4515 } |
4512 } | 4516 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4564 // Smi to double register conversion | 4568 // Smi to double register conversion |
4565 __ bind(&load_smi); | 4569 __ bind(&load_smi); |
4566 // scratch: untagged value of input_reg | 4570 // scratch: untagged value of input_reg |
4567 __ vmov(flt_scratch, scratch); | 4571 __ vmov(flt_scratch, scratch); |
4568 __ vcvt_f64_s32(result_reg, flt_scratch); | 4572 __ vcvt_f64_s32(result_reg, flt_scratch); |
4569 __ bind(&done); | 4573 __ bind(&done); |
4570 } | 4574 } |
4571 | 4575 |
4572 | 4576 |
4573 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 4577 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
4574 Register input_reg = ToRegister(instr->InputAt(0)); | 4578 Register input_reg = ToRegister(instr->value()); |
4575 Register scratch1 = scratch0(); | 4579 Register scratch1 = scratch0(); |
4576 Register scratch2 = ToRegister(instr->TempAt(0)); | 4580 Register scratch2 = ToRegister(instr->temp()); |
4577 DwVfpRegister double_scratch = double_scratch0(); | 4581 DwVfpRegister double_scratch = double_scratch0(); |
4578 SwVfpRegister single_scratch = double_scratch.low(); | 4582 SwVfpRegister single_scratch = double_scratch.low(); |
4579 | 4583 |
4580 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); | 4584 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
4581 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); | 4585 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
4582 | 4586 |
4583 Label done; | 4587 Label done; |
4584 | 4588 |
4585 // The input was optimistically untagged; revert it. | 4589 // The input was optimistically untagged; revert it. |
4586 // The carry flag is set when we reach this deferred code as we just executed | 4590 // The carry flag is set when we reach this deferred code as we just executed |
4587 // SmiUntag(heap_object, SetCC) | 4591 // SmiUntag(heap_object, SetCC) |
4588 STATIC_ASSERT(kHeapObjectTag == 1); | 4592 STATIC_ASSERT(kHeapObjectTag == 1); |
4589 __ adc(input_reg, input_reg, Operand(input_reg)); | 4593 __ adc(input_reg, input_reg, Operand(input_reg)); |
4590 | 4594 |
4591 // Heap number map check. | 4595 // Heap number map check. |
4592 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4596 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4593 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4597 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
4594 __ cmp(scratch1, Operand(ip)); | 4598 __ cmp(scratch1, Operand(ip)); |
4595 | 4599 |
4596 if (instr->truncating()) { | 4600 if (instr->truncating()) { |
4597 Register scratch3 = ToRegister(instr->TempAt(1)); | 4601 Register scratch3 = ToRegister(instr->temp2()); |
4598 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2)); | 4602 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3()); |
4599 ASSERT(!scratch3.is(input_reg) && | 4603 ASSERT(!scratch3.is(input_reg) && |
4600 !scratch3.is(scratch1) && | 4604 !scratch3.is(scratch1) && |
4601 !scratch3.is(scratch2)); | 4605 !scratch3.is(scratch2)); |
4602 // Performs a truncating conversion of a floating point number as used by | 4606 // Performs a truncating conversion of a floating point number as used by |
4603 // the JS bitwise operations. | 4607 // the JS bitwise operations. |
4604 Label heap_number; | 4608 Label heap_number; |
4605 __ b(eq, &heap_number); | 4609 __ b(eq, &heap_number); |
4606 // Check for undefined. Undefined is converted to zero for truncating | 4610 // Check for undefined. Undefined is converted to zero for truncating |
4607 // conversions. | 4611 // conversions. |
4608 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4612 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4655 class DeferredTaggedToI: public LDeferredCode { | 4659 class DeferredTaggedToI: public LDeferredCode { |
4656 public: | 4660 public: |
4657 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4661 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
4658 : LDeferredCode(codegen), instr_(instr) { } | 4662 : LDeferredCode(codegen), instr_(instr) { } |
4659 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 4663 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
4660 virtual LInstruction* instr() { return instr_; } | 4664 virtual LInstruction* instr() { return instr_; } |
4661 private: | 4665 private: |
4662 LTaggedToI* instr_; | 4666 LTaggedToI* instr_; |
4663 }; | 4667 }; |
4664 | 4668 |
4665 LOperand* input = instr->InputAt(0); | 4669 LOperand* input = instr->value(); |
4666 ASSERT(input->IsRegister()); | 4670 ASSERT(input->IsRegister()); |
4667 ASSERT(input->Equals(instr->result())); | 4671 ASSERT(input->Equals(instr->result())); |
4668 | 4672 |
4669 Register input_reg = ToRegister(input); | 4673 Register input_reg = ToRegister(input); |
4670 | 4674 |
4671 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); | 4675 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); |
4672 | 4676 |
4673 // Optimistically untag the input. | 4677 // Optimistically untag the input. |
4674 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4678 // If the input is a HeapObject, SmiUntag will set the carry flag. |
4675 __ SmiUntag(input_reg, SetCC); | 4679 __ SmiUntag(input_reg, SetCC); |
4676 // Branch to deferred code if the input was tagged. | 4680 // Branch to deferred code if the input was tagged. |
4677 // The deferred code will take care of restoring the tag. | 4681 // The deferred code will take care of restoring the tag. |
4678 __ b(cs, deferred->entry()); | 4682 __ b(cs, deferred->entry()); |
4679 __ bind(deferred->exit()); | 4683 __ bind(deferred->exit()); |
4680 } | 4684 } |
4681 | 4685 |
4682 | 4686 |
4683 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4687 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4684 LOperand* input = instr->InputAt(0); | 4688 LOperand* input = instr->value(); |
4685 ASSERT(input->IsRegister()); | 4689 ASSERT(input->IsRegister()); |
4686 LOperand* result = instr->result(); | 4690 LOperand* result = instr->result(); |
4687 ASSERT(result->IsDoubleRegister()); | 4691 ASSERT(result->IsDoubleRegister()); |
4688 | 4692 |
4689 Register input_reg = ToRegister(input); | 4693 Register input_reg = ToRegister(input); |
4690 DoubleRegister result_reg = ToDoubleRegister(result); | 4694 DoubleRegister result_reg = ToDoubleRegister(result); |
4691 | 4695 |
4692 EmitNumberUntagD(input_reg, result_reg, | 4696 EmitNumberUntagD(input_reg, result_reg, |
4693 instr->hydrogen()->deoptimize_on_undefined(), | 4697 instr->hydrogen()->deoptimize_on_undefined(), |
4694 instr->hydrogen()->deoptimize_on_minus_zero(), | 4698 instr->hydrogen()->deoptimize_on_minus_zero(), |
4695 instr->environment()); | 4699 instr->environment()); |
4696 } | 4700 } |
4697 | 4701 |
4698 | 4702 |
4699 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4703 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4700 Register result_reg = ToRegister(instr->result()); | 4704 Register result_reg = ToRegister(instr->result()); |
4701 Register scratch1 = scratch0(); | 4705 Register scratch1 = scratch0(); |
4702 Register scratch2 = ToRegister(instr->TempAt(0)); | 4706 Register scratch2 = ToRegister(instr->temp()); |
4703 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); | 4707 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
4704 SwVfpRegister single_scratch = double_scratch0().low(); | 4708 SwVfpRegister single_scratch = double_scratch0().low(); |
4705 | 4709 |
4706 Label done; | 4710 Label done; |
4707 | 4711 |
4708 if (instr->truncating()) { | 4712 if (instr->truncating()) { |
4709 Register scratch3 = ToRegister(instr->TempAt(1)); | 4713 Register scratch3 = ToRegister(instr->temp2()); |
4710 __ EmitECMATruncate(result_reg, | 4714 __ EmitECMATruncate(result_reg, |
4711 double_input, | 4715 double_input, |
4712 single_scratch, | 4716 single_scratch, |
4713 scratch1, | 4717 scratch1, |
4714 scratch2, | 4718 scratch2, |
4715 scratch3); | 4719 scratch3); |
4716 } else { | 4720 } else { |
4717 VFPRoundingMode rounding_mode = kRoundToMinusInf; | 4721 VFPRoundingMode rounding_mode = kRoundToMinusInf; |
4718 __ EmitVFPTruncate(rounding_mode, | 4722 __ EmitVFPTruncate(rounding_mode, |
4719 single_scratch, | 4723 single_scratch, |
4720 double_input, | 4724 double_input, |
4721 scratch1, | 4725 scratch1, |
4722 scratch2, | 4726 scratch2, |
4723 kCheckForInexactConversion); | 4727 kCheckForInexactConversion); |
4724 // Deoptimize if we had a vfp invalid exception, | 4728 // Deoptimize if we had a vfp invalid exception, |
4725 // including inexact operation. | 4729 // including inexact operation. |
4726 DeoptimizeIf(ne, instr->environment()); | 4730 DeoptimizeIf(ne, instr->environment()); |
4727 // Retrieve the result. | 4731 // Retrieve the result. |
4728 __ vmov(result_reg, single_scratch); | 4732 __ vmov(result_reg, single_scratch); |
4729 } | 4733 } |
4730 __ bind(&done); | 4734 __ bind(&done); |
4731 } | 4735 } |
4732 | 4736 |
4733 | 4737 |
4734 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4738 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
4735 LOperand* input = instr->InputAt(0); | 4739 LOperand* input = instr->value(); |
4736 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 4740 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
4737 DeoptimizeIf(ne, instr->environment()); | 4741 DeoptimizeIf(ne, instr->environment()); |
4738 } | 4742 } |
4739 | 4743 |
4740 | 4744 |
4741 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4745 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
4742 LOperand* input = instr->InputAt(0); | 4746 LOperand* input = instr->value(); |
4743 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 4747 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
4744 DeoptimizeIf(eq, instr->environment()); | 4748 DeoptimizeIf(eq, instr->environment()); |
4745 } | 4749 } |
4746 | 4750 |
4747 | 4751 |
4748 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4752 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
4749 Register input = ToRegister(instr->InputAt(0)); | 4753 Register input = ToRegister(instr->value()); |
4750 Register scratch = scratch0(); | 4754 Register scratch = scratch0(); |
4751 | 4755 |
4752 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 4756 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
4753 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 4757 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
4754 | 4758 |
4755 if (instr->hydrogen()->is_interval_check()) { | 4759 if (instr->hydrogen()->is_interval_check()) { |
4756 InstanceType first; | 4760 InstanceType first; |
4757 InstanceType last; | 4761 InstanceType last; |
4758 instr->hydrogen()->GetCheckInterval(&first, &last); | 4762 instr->hydrogen()->GetCheckInterval(&first, &last); |
4759 | 4763 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4812 LEnvironment* env) { | 4816 LEnvironment* env) { |
4813 Label success; | 4817 Label success; |
4814 __ CompareMap(reg, scratch, map, &success, mode); | 4818 __ CompareMap(reg, scratch, map, &success, mode); |
4815 DeoptimizeIf(ne, env); | 4819 DeoptimizeIf(ne, env); |
4816 __ bind(&success); | 4820 __ bind(&success); |
4817 } | 4821 } |
4818 | 4822 |
4819 | 4823 |
4820 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4824 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4821 Register scratch = scratch0(); | 4825 Register scratch = scratch0(); |
4822 LOperand* input = instr->InputAt(0); | 4826 LOperand* input = instr->value(); |
4823 ASSERT(input->IsRegister()); | 4827 ASSERT(input->IsRegister()); |
4824 Register reg = ToRegister(input); | 4828 Register reg = ToRegister(input); |
4825 | 4829 |
4826 Label success; | 4830 Label success; |
4827 SmallMapList* map_set = instr->hydrogen()->map_set(); | 4831 SmallMapList* map_set = instr->hydrogen()->map_set(); |
4828 for (int i = 0; i < map_set->length() - 1; i++) { | 4832 for (int i = 0; i < map_set->length() - 1; i++) { |
4829 Handle<Map> map = map_set->at(i); | 4833 Handle<Map> map = map_set->at(i); |
4830 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); | 4834 __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP); |
4831 __ b(eq, &success); | 4835 __ b(eq, &success); |
4832 } | 4836 } |
4833 Handle<Map> map = map_set->last(); | 4837 Handle<Map> map = map_set->last(); |
4834 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); | 4838 DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment()); |
4835 __ bind(&success); | 4839 __ bind(&success); |
4836 } | 4840 } |
4837 | 4841 |
4838 | 4842 |
4839 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4843 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
4840 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4844 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
4841 Register result_reg = ToRegister(instr->result()); | 4845 Register result_reg = ToRegister(instr->result()); |
4842 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); | 4846 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
4843 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); | 4847 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); |
4844 } | 4848 } |
4845 | 4849 |
4846 | 4850 |
4847 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 4851 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
4848 Register unclamped_reg = ToRegister(instr->unclamped()); | 4852 Register unclamped_reg = ToRegister(instr->unclamped()); |
4849 Register result_reg = ToRegister(instr->result()); | 4853 Register result_reg = ToRegister(instr->result()); |
4850 __ ClampUint8(result_reg, unclamped_reg); | 4854 __ ClampUint8(result_reg, unclamped_reg); |
4851 } | 4855 } |
4852 | 4856 |
4853 | 4857 |
4854 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 4858 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
4855 Register scratch = scratch0(); | 4859 Register scratch = scratch0(); |
4856 Register input_reg = ToRegister(instr->unclamped()); | 4860 Register input_reg = ToRegister(instr->unclamped()); |
4857 Register result_reg = ToRegister(instr->result()); | 4861 Register result_reg = ToRegister(instr->result()); |
4858 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); | 4862 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
4859 Label is_smi, done, heap_number; | 4863 Label is_smi, done, heap_number; |
4860 | 4864 |
4861 // Both smi and heap number cases are handled. | 4865 // Both smi and heap number cases are handled. |
4862 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 4866 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
4863 | 4867 |
4864 // Check for heap number | 4868 // Check for heap number |
4865 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4869 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4866 __ cmp(scratch, Operand(factory()->heap_number_map())); | 4870 __ cmp(scratch, Operand(factory()->heap_number_map())); |
4867 __ b(eq, &heap_number); | 4871 __ b(eq, &heap_number); |
4868 | 4872 |
(...skipping 13 matching lines...) Expand all Loading... |
4882 | 4886 |
4883 // smi | 4887 // smi |
4884 __ bind(&is_smi); | 4888 __ bind(&is_smi); |
4885 __ ClampUint8(result_reg, result_reg); | 4889 __ ClampUint8(result_reg, result_reg); |
4886 | 4890 |
4887 __ bind(&done); | 4891 __ bind(&done); |
4888 } | 4892 } |
4889 | 4893 |
4890 | 4894 |
4891 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4895 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
4892 Register temp1 = ToRegister(instr->TempAt(0)); | 4896 Register temp1 = ToRegister(instr->temp()); |
4893 Register temp2 = ToRegister(instr->TempAt(1)); | 4897 Register temp2 = ToRegister(instr->temp2()); |
4894 | 4898 |
4895 Handle<JSObject> holder = instr->holder(); | 4899 Handle<JSObject> holder = instr->holder(); |
4896 Handle<JSObject> current_prototype = instr->prototype(); | 4900 Handle<JSObject> current_prototype = instr->prototype(); |
4897 | 4901 |
4898 // Load prototype object. | 4902 // Load prototype object. |
4899 __ LoadHeapObject(temp1, current_prototype); | 4903 __ LoadHeapObject(temp1, current_prototype); |
4900 | 4904 |
4901 // Check prototype maps up to the holder. | 4905 // Check prototype maps up to the holder. |
4902 while (!current_prototype.is_identical_to(holder)) { | 4906 while (!current_prototype.is_identical_to(holder)) { |
4903 DoCheckMapCommon(temp1, temp2, | 4907 DoCheckMapCommon(temp1, temp2, |
(...skipping 21 matching lines...) Expand all Loading... |
4925 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } | 4929 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); } |
4926 virtual LInstruction* instr() { return instr_; } | 4930 virtual LInstruction* instr() { return instr_; } |
4927 private: | 4931 private: |
4928 LAllocateObject* instr_; | 4932 LAllocateObject* instr_; |
4929 }; | 4933 }; |
4930 | 4934 |
4931 DeferredAllocateObject* deferred = | 4935 DeferredAllocateObject* deferred = |
4932 new(zone()) DeferredAllocateObject(this, instr); | 4936 new(zone()) DeferredAllocateObject(this, instr); |
4933 | 4937 |
4934 Register result = ToRegister(instr->result()); | 4938 Register result = ToRegister(instr->result()); |
4935 Register scratch = ToRegister(instr->TempAt(0)); | 4939 Register scratch = ToRegister(instr->temp()); |
4936 Register scratch2 = ToRegister(instr->TempAt(1)); | 4940 Register scratch2 = ToRegister(instr->temp2()); |
4937 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); | 4941 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); |
4938 Handle<Map> initial_map(constructor->initial_map()); | 4942 Handle<Map> initial_map(constructor->initial_map()); |
4939 int instance_size = initial_map->instance_size(); | 4943 int instance_size = initial_map->instance_size(); |
4940 ASSERT(initial_map->pre_allocated_property_fields() + | 4944 ASSERT(initial_map->pre_allocated_property_fields() + |
4941 initial_map->unused_property_fields() - | 4945 initial_map->unused_property_fields() - |
4942 initial_map->inobject_properties() == 0); | 4946 initial_map->inobject_properties() == 0); |
4943 | 4947 |
4944 // Allocate memory for the object. The initial map might change when | 4948 // Allocate memory for the object. The initial map might change when |
4945 // the constructor's prototype changes, but instance size and property | 4949 // the constructor's prototype changes, but instance size and property |
4946 // counts remain unchanged (if slack tracking finished). | 4950 // counts remain unchanged (if slack tracking finished). |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5218 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 5222 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
5219 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); | 5223 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); |
5220 } else { | 5224 } else { |
5221 FastCloneShallowObjectStub stub(properties_count); | 5225 FastCloneShallowObjectStub stub(properties_count); |
5222 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5226 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
5223 } | 5227 } |
5224 } | 5228 } |
5225 | 5229 |
5226 | 5230 |
5227 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5231 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5228 ASSERT(ToRegister(instr->InputAt(0)).is(r0)); | 5232 ASSERT(ToRegister(instr->value()).is(r0)); |
5229 __ push(r0); | 5233 __ push(r0); |
5230 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5234 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5231 } | 5235 } |
5232 | 5236 |
5233 | 5237 |
5234 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5238 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5235 Label materialized; | 5239 Label materialized; |
5236 // Registers will be used as follows: | 5240 // Registers will be used as follows: |
5237 // r7 = literals array. | 5241 // r7 = literals array. |
5238 // r1 = regexp literal. | 5242 // r1 = regexp literal. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5299 __ mov(r1, Operand(pretenure | 5303 __ mov(r1, Operand(pretenure |
5300 ? factory()->true_value() | 5304 ? factory()->true_value() |
5301 : factory()->false_value())); | 5305 : factory()->false_value())); |
5302 __ Push(cp, r2, r1); | 5306 __ Push(cp, r2, r1); |
5303 CallRuntime(Runtime::kNewClosure, 3, instr); | 5307 CallRuntime(Runtime::kNewClosure, 3, instr); |
5304 } | 5308 } |
5305 } | 5309 } |
5306 | 5310 |
5307 | 5311 |
5308 void LCodeGen::DoTypeof(LTypeof* instr) { | 5312 void LCodeGen::DoTypeof(LTypeof* instr) { |
5309 Register input = ToRegister(instr->InputAt(0)); | 5313 Register input = ToRegister(instr->value()); |
5310 __ push(input); | 5314 __ push(input); |
5311 CallRuntime(Runtime::kTypeof, 1, instr); | 5315 CallRuntime(Runtime::kTypeof, 1, instr); |
5312 } | 5316 } |
5313 | 5317 |
5314 | 5318 |
5315 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5319 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5316 Register input = ToRegister(instr->InputAt(0)); | 5320 Register input = ToRegister(instr->value()); |
5317 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5321 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5318 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5322 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5319 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 5323 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
5320 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 5324 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
5321 | 5325 |
5322 Condition final_branch_condition = EmitTypeofIs(true_label, | 5326 Condition final_branch_condition = EmitTypeofIs(true_label, |
5323 false_label, | 5327 false_label, |
5324 input, | 5328 input, |
5325 instr->type_literal()); | 5329 instr->type_literal()); |
5326 if (final_branch_condition != kNoCondition) { | 5330 if (final_branch_condition != kNoCondition) { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5396 | 5400 |
5397 } else { | 5401 } else { |
5398 __ b(false_label); | 5402 __ b(false_label); |
5399 } | 5403 } |
5400 | 5404 |
5401 return final_branch_condition; | 5405 return final_branch_condition; |
5402 } | 5406 } |
5403 | 5407 |
5404 | 5408 |
5405 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 5409 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
5406 Register temp1 = ToRegister(instr->TempAt(0)); | 5410 Register temp1 = ToRegister(instr->temp()); |
5407 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 5411 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
5408 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 5412 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
5409 | 5413 |
5410 EmitIsConstructCall(temp1, scratch0()); | 5414 EmitIsConstructCall(temp1, scratch0()); |
5411 EmitBranch(true_block, false_block, eq); | 5415 EmitBranch(true_block, false_block, eq); |
5412 } | 5416 } |
5413 | 5417 |
5414 | 5418 |
5415 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { | 5419 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
5416 ASSERT(!temp1.is(temp2)); | 5420 ASSERT(!temp1.is(temp2)); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5656 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 5660 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5657 __ ldr(result, FieldMemOperand(scratch, | 5661 __ ldr(result, FieldMemOperand(scratch, |
5658 FixedArray::kHeaderSize - kPointerSize)); | 5662 FixedArray::kHeaderSize - kPointerSize)); |
5659 __ bind(&done); | 5663 __ bind(&done); |
5660 } | 5664 } |
5661 | 5665 |
5662 | 5666 |
5663 #undef __ | 5667 #undef __ |
5664 | 5668 |
5665 } } // namespace v8::internal | 5669 } } // namespace v8::internal |
OLD | NEW |